From f5db16b10a0f850b588198e007e5cb5d38ff58d4 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 14 Aug 2020 12:44:03 -0400 Subject: [PATCH 001/852] Added the phen_model_day timer to work with all restart conditions --- biogeochem/EDPhysiologyMod.F90 | 11 +++++- main/EDInitMod.F90 | 66 ++++++++++++++++--------------- main/EDTypesMod.F90 | 5 +++ main/FatesRestartInterfaceMod.F90 | 48 ++++++++++++---------- 4 files changed, 76 insertions(+), 54 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 0c23795f9a..3d35319b42 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -744,8 +744,9 @@ subroutine phenology( currentSite, bc_in ) ! This is the integer model day. The first day of the simulation is 1, and it ! continues monotonically, indefinitely - model_day_int = nint(hlm_model_day) + + model_day_int = currentSite%phen_model_date ! Use the following layer index to calculate drought conditions ilayer_swater = minloc(abs(bc_in%z_sisl(:)-dphen_soil_depth),dim=1) @@ -1061,6 +1062,12 @@ subroutine phenology( currentSite, bc_in ) call phenology_leafonoff(currentSite) + ! Advance the model day (this should be a global, no reason + ! for site level, but we don't have global scalars in the + ! restart file) + + currentSite%phen_model_date = currentSite%phen_model_date + 1 + end subroutine phenology ! ============================================================================ @@ -1349,7 +1356,7 @@ subroutine SeedIn( currentSite, bc_in ) ! !USES: use EDTypesMod, only : area use EDTypesMod, only : homogenize_seed_pfts - !use FatesInterfaceTypesMod, only : hlm_use_fixed_biogeog ! For future reduced complexity? + ! ! !ARGUMENTS type(ed_site_type), intent(inout), target :: currentSite diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 646084ef1b..a9f2ee4c69 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -25,32 +25,33 @@ module EDInitMod use EDTypesMod , only : AREA use EDTypesMod , only : init_spread_near_bare_ground use EDTypesMod , only : init_spread_inventory - use EDTypesMod , only : leaves_on - use EDTypesMod , only : leaves_off - use EDTypesMod , only : num_elements - use EDTypesMod , only : element_list - use EDTypesMod , only : phen_cstat_nevercold - use EDTypesMod , only : phen_cstat_iscold - use EDTypesMod , only : phen_dstat_timeoff - use EDTypesMod , only : phen_dstat_moistoff - use EDTypesMod , only : phen_cstat_notcold - use EDTypesMod , only : phen_dstat_moiston - use FatesInterfaceTypesMod , only : bc_in_type - use FatesInterfaceTypesMod , only : hlm_use_planthydro - use FatesInterfaceTypesMod , only : hlm_use_inventory_init - use FatesInterfaceTypesMod , only : hlm_use_fixed_biogeog - use FatesInterfaceTypesMod , only : numpft - use FatesInterfaceTypesMod , only : nleafage - use FatesInterfaceTypesMod , only : nlevsclass - use FatesInterfaceTypesMod , only : nlevcoage - use FatesAllometryMod , only : h2d_allom - use FatesAllometryMod , only : bagw_allom - use FatesAllometryMod , only : bbgw_allom - use FatesAllometryMod , only : bleaf - use FatesAllometryMod , only : bfineroot - use FatesAllometryMod , only : bsap_allom - use FatesAllometryMod , only : bdead_allom - use FatesAllometryMod , only : bstore_allom + use EDTypesMod , only : leaves_on + use EDTypesMod , only : leaves_off + use EDTypesMod , only : num_elements + use EDTypesMod , only : element_list + use EDTypesMod , only : phen_cstat_nevercold + use EDTypesMod , only : phen_cstat_iscold + use EDTypesMod , only : phen_dstat_timeoff + use EDTypesMod , only : phen_dstat_moistoff + use EDTypesMod , only : phen_cstat_notcold + use EDTypesMod , only : phen_dstat_moiston + use FatesInterfaceTypesMod , only : hlm_day_of_year + use FatesInterfaceTypesMod , only : bc_in_type + use FatesInterfaceTypesMod , only : hlm_use_planthydro + use FatesInterfaceTypesMod , only : hlm_use_inventory_init + use FatesInterfaceTypesMod , only : hlm_use_fixed_biogeog + use FatesInterfaceTypesMod , only : numpft + use FatesInterfaceTypesMod , only : nleafage + use FatesInterfaceTypesMod , only : nlevsclass + use FatesInterfaceTypesMod , only : nlevcoage + use FatesAllometryMod , only : h2d_allom + use FatesAllometryMod , only : bagw_allom + use FatesAllometryMod , only : bbgw_allom + use FatesAllometryMod , only : bleaf + use FatesAllometryMod , only : bfineroot + use FatesAllometryMod , only : bsap_allom + use FatesAllometryMod , only : bdead_allom + use FatesAllometryMod , only : bstore_allom use FatesInterfaceTypesMod, only : hlm_parteh_mode use PRTGenericMod, only : prt_carbon_allom_hyp @@ -167,16 +168,16 @@ subroutine zero_site( site_in ) site_in%cstatus = fates_unset_int ! are leaves in this pixel on or off? site_in%dstatus = fates_unset_int - site_in%grow_deg_days = nan ! growing degree days + site_in%grow_deg_days = nan ! growing degree days site_in%nchilldays = fates_unset_int site_in%ncolddays = fates_unset_int - site_in%cleafondate = fates_unset_int ! doy of leaf on - site_in%cleafoffdate = fates_unset_int ! doy of leaf off - site_in%dleafondate = fates_unset_int ! doy of leaf on drought - site_in%dleafoffdate = fates_unset_int ! doy of leaf on drought + site_in%cleafondate = fates_unset_int + site_in%cleafoffdate = fates_unset_int + site_in%dleafondate = fates_unset_int + site_in%dleafoffdate = fates_unset_int site_in%water_memory(:) = nan site_in%vegtemp_memory(:) = nan ! record of last 10 days temperature for senescence model. - + site_in%phen_model_date = fates_unset_int ! FIRE site_in%acc_ni = 0.0_r8 ! daily nesterov index accumulating over time. time unlimited theoretically. @@ -277,6 +278,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) ! is memory-less, but needed ! for first value in history file + sites(s)%phen_model_date = hlm_day_of_year sites(s)%cleafondate = cleafon sites(s)%cleafoffdate = cleafoff sites(s)%dleafoffdate = dleafoff diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 0e843df123..e3f0555722 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -690,7 +690,12 @@ module EDTypesMod integer :: cleafoffdate ! model date (day integer) of leaf off (cold):- integer :: dleafondate ! model date (day integer) of leaf on drought:- integer :: dleafoffdate ! model date (day integer) of leaf off drought:- + integer :: phen_model_date ! current model date (day integer) + ! this date stays continuous when + ! in runs that are restarted, regardless of + ! the conditions of restart + real(r8) :: water_memory(numWaterMem) ! last 10 days of soil moisture memory... diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 6f32df2382..3b315183ec 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -80,10 +80,11 @@ module FatesRestartInterfaceMod integer :: ir_dd_status_si integer :: ir_nchill_days_si integer :: ir_ncold_days_si - integer :: ir_leafondate_si - integer :: ir_leafoffdate_si + integer :: ir_cleafondate_si + integer :: ir_cleafoffdate_si integer :: ir_dleafondate_si integer :: ir_dleafoffdate_si + integer :: ir_phenmodeldate_si integer :: ir_acc_ni_si integer :: ir_gdd_si integer :: ir_trunk_product_si @@ -577,22 +578,26 @@ subroutine define_restart_vars(this, initialize_variables) long_name='cold day counter', units='unitless', flushval = flushinvalid, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_ncold_days_si ) - call this%set_restart_var(vname='fates_leafondate', vtype=site_int, & - long_name='the day of year for leaf on', units='day of year', flushval = flushinvalid, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_leafondate_si ) + call this%set_restart_var(vname='fates_cold_leafondate', vtype=site_int, & + long_name='the model day of last cold leaf on', units='absolute integer day', flushval = flushinvalid, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_cleafondate_si ) - call this%set_restart_var(vname='fates_leafoffdate', vtype=site_int, & - long_name='the day of year for leaf off', units='day of year', flushval = flushinvalid, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_leafoffdate_si ) + call this%set_restart_var(vname='fates_cold_leafoffdate', vtype=site_int, & + long_name='the model day last cold leaf off', units='absolute integer day', flushval = flushinvalid, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_cleafoffdate_si ) call this%set_restart_var(vname='fates_drought_leafondate', vtype=site_int, & - long_name='the day of year for drought based leaf-on', units='day of year', flushval = flushinvalid, & + long_name='the model day of last drought based leaf-on', units='absolute integer day', flushval = flushinvalid, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_dleafondate_si ) call this%set_restart_var(vname='fates_drought_leafoffdate', vtype=site_int, & - long_name='the day of year for drought based leaf-off', units='day of year', flushval = flushinvalid, & + long_name='the model day of last drought based leaf-off', units='absolute integer day', flushval = flushinvalid, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_dleafoffdate_si ) + call this%set_restart_var(vname='fates_phen_model_date', vtype=site_int, & + long_name='integer model day used for phen timing', units='absolute integer day', flushval = flushinvalid, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_phenmodeldate_si ) + call this%set_restart_var(vname='fates_acc_nesterov_id', vtype=site_r8, & long_name='a nesterov index accumulator', units='unitless', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_acc_ni_si ) @@ -1491,10 +1496,11 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_dd_status_si => this%rvars(ir_dd_status_si)%int1d, & rio_nchill_days_si => this%rvars(ir_nchill_days_si)%int1d, & rio_ncold_days_si => this%rvars(ir_ncold_days_si)%int1d, & - rio_leafondate_si => this%rvars(ir_leafondate_si)%int1d, & - rio_leafoffdate_si => this%rvars(ir_leafoffdate_si)%int1d, & + rio_cleafondate_si => this%rvars(ir_cleafondate_si)%int1d, & + rio_cleafoffdate_si => this%rvars(ir_cleafoffdate_si)%int1d, & rio_dleafondate_si => this%rvars(ir_dleafondate_si)%int1d, & rio_dleafoffdate_si => this%rvars(ir_dleafoffdate_si)%int1d, & + rio_phenmodeldate_si => this%rvars(ir_phenmodeldate_si)%int1d, & rio_acc_ni_si => this%rvars(ir_acc_ni_si)%r81d, & rio_gdd_si => this%rvars(ir_gdd_si)%r81d, & rio_trunk_product_si => this%rvars(ir_trunk_product_si)%r81d, & @@ -1902,9 +1908,9 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_dd_status_si(io_idx_si) = sites(s)%dstatus rio_nchill_days_si(io_idx_si) = sites(s)%nchilldays rio_ncold_days_si(io_idx_si) = sites(s)%ncolddays - rio_leafondate_si(io_idx_si) = sites(s)%cleafondate - rio_leafoffdate_si(io_idx_si) = sites(s)%cleafoffdate - + rio_cleafondate_si(io_idx_si) = sites(s)%cleafondate + rio_cleafoffdate_si(io_idx_si) = sites(s)%cleafoffdate + rio_phenmodeldate_si(io_idx_si)= sites(s)%phen_model_date rio_dleafondate_si(io_idx_si) = sites(s)%dleafondate rio_dleafoffdate_si(io_idx_si) = sites(s)%dleafoffdate rio_acc_ni_si(io_idx_si) = sites(s)%acc_NI @@ -2238,10 +2244,11 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_dd_status_si => this%rvars(ir_dd_status_si)%int1d, & rio_nchill_days_si => this%rvars(ir_nchill_days_si)%int1d, & rio_ncold_days_si => this%rvars(ir_ncold_days_si)%int1d, & - rio_leafondate_si => this%rvars(ir_leafondate_si)%int1d, & - rio_leafoffdate_si => this%rvars(ir_leafoffdate_si)%int1d, & + rio_cleafondate_si => this%rvars(ir_cleafondate_si)%int1d, & + rio_cleafoffdate_si => this%rvars(ir_cleafoffdate_si)%int1d, & rio_dleafondate_si => this%rvars(ir_dleafondate_si)%int1d, & rio_dleafoffdate_si => this%rvars(ir_dleafoffdate_si)%int1d, & + rio_phenmodeldate_si => this%rvars(ir_phenmodeldate_si)%int1d, & rio_acc_ni_si => this%rvars(ir_acc_ni_si)%r81d, & rio_gdd_si => this%rvars(ir_gdd_si)%r81d, & rio_trunk_product_si => this%rvars(ir_trunk_product_si)%r81d, & @@ -2678,13 +2685,14 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%dstatus = rio_dd_status_si(io_idx_si) sites(s)%nchilldays = rio_nchill_days_si(io_idx_si) sites(s)%ncolddays = rio_ncold_days_si(io_idx_si) - sites(s)%cleafondate = rio_leafondate_si(io_idx_si) - sites(s)%cleafoffdate = rio_leafoffdate_si(io_idx_si) + sites(s)%cleafondate = rio_cleafondate_si(io_idx_si) + sites(s)%cleafoffdate = rio_cleafoffdate_si(io_idx_si) sites(s)%dleafondate = rio_dleafondate_si(io_idx_si) sites(s)%dleafoffdate = rio_dleafoffdate_si(io_idx_si) sites(s)%acc_NI = rio_acc_ni_si(io_idx_si) sites(s)%grow_deg_days = rio_gdd_si(io_idx_si) - + sites(s)%phen_model_date= rio_phenmodeldate_si(io_idx_si) + sites(s)%resources_management%trunk_product_site = rio_trunk_product_si(io_idx_si) end do From 325245ae826d3af4290536eaa04430924e993ece Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 14 Aug 2020 19:42:03 -0400 Subject: [PATCH 002/852] fixed dleafon_date in history writes. Slightly shifted the phenology model day counter to start at 0, and +1 at start of phenology routine, which is simpler for restarts. --- biogeochem/EDPhysiologyMod.F90 | 6 +- main/EDInitMod.F90 | 189 +----------------------------- main/FatesHistoryInterfaceMod.F90 | 17 ++- 3 files changed, 17 insertions(+), 195 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 3d35319b42..d689411953 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -745,7 +745,7 @@ subroutine phenology( currentSite, bc_in ) ! This is the integer model day. The first day of the simulation is 1, and it ! continues monotonically, indefinitely - + currentSite%phen_model_date = currentSite%phen_model_date + 1 model_day_int = currentSite%phen_model_date ! Use the following layer index to calculate drought conditions @@ -850,7 +850,7 @@ subroutine phenology( currentSite, bc_in ) end if if (model_day_int < currentSite%cleafondate) then - dayssincecleafon = model_day_int - (currentSite%cleafondate-365) + dayssincecleafon = model_day_int - (currentSite%cleafondate - 365) else dayssincecleafon = model_day_int - currentSite%cleafondate end if @@ -1066,7 +1066,7 @@ subroutine phenology( currentSite, bc_in ) ! for site level, but we don't have global scalars in the ! restart file) - currentSite%phen_model_date = currentSite%phen_model_date + 1 + end subroutine phenology diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index a9f2ee4c69..074f645cb4 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -1,181 +1,4 @@ -module EDInitMod - ! ============================================================================ - ! Contains all modules to set up the ED structure. - ! ============================================================================ - - use FatesConstantsMod , only : r8 => fates_r8 - use FatesConstantsMod , only : ifalse - use FatesConstantsMod , only : itrue - use FatesConstantsMod , only : fates_unset_int - use FatesConstantsMod , only : primaryforest - use FatesGlobals , only : endrun => fates_endrun - use EDTypesMod , only : nclmax - use FatesGlobals , only : fates_log - use FatesInterfaceTypesMod , only : hlm_is_restart - use EDPftvarcon , only : EDPftvarcon_inst - use EDCohortDynamicsMod , only : create_cohort, fuse_cohorts, sort_cohorts - use EDCohortDynamicsMod , only : InitPRTObject - use EDPatchDynamicsMod , only : create_patch - use ChecksBalancesMod , only : SiteMassStock - use EDTypesMod , only : ed_site_type, ed_patch_type, ed_cohort_type - use EDTypesMod , only : numWaterMem - use EDTypesMod , only : num_vegtemp_mem - use EDTypesMod , only : maxpft - use EDTypesMod , only : AREA - use EDTypesMod , only : init_spread_near_bare_ground - use EDTypesMod , only : init_spread_inventory - use EDTypesMod , only : leaves_on - use EDTypesMod , only : leaves_off - use EDTypesMod , only : num_elements - use EDTypesMod , only : element_list - use EDTypesMod , only : phen_cstat_nevercold - use EDTypesMod , only : phen_cstat_iscold - use EDTypesMod , only : phen_dstat_timeoff - use EDTypesMod , only : phen_dstat_moistoff - use EDTypesMod , only : phen_cstat_notcold - use EDTypesMod , only : phen_dstat_moiston - use FatesInterfaceTypesMod , only : hlm_day_of_year - use FatesInterfaceTypesMod , only : bc_in_type - use FatesInterfaceTypesMod , only : hlm_use_planthydro - use FatesInterfaceTypesMod , only : hlm_use_inventory_init - use FatesInterfaceTypesMod , only : hlm_use_fixed_biogeog - use FatesInterfaceTypesMod , only : numpft - use FatesInterfaceTypesMod , only : nleafage - use FatesInterfaceTypesMod , only : nlevsclass - use FatesInterfaceTypesMod , only : nlevcoage - use FatesAllometryMod , only : h2d_allom - use FatesAllometryMod , only : bagw_allom - use FatesAllometryMod , only : bbgw_allom - use FatesAllometryMod , only : bleaf - use FatesAllometryMod , only : bfineroot - use FatesAllometryMod , only : bsap_allom - use FatesAllometryMod , only : bdead_allom - use FatesAllometryMod , only : bstore_allom - - use FatesInterfaceTypesMod, only : hlm_parteh_mode - use PRTGenericMod, only : prt_carbon_allom_hyp - use PRTGenericMod, only : prt_cnp_flex_allom_hyp - use PRTGenericMod, only : prt_vartypes - use PRTGenericMod, only : leaf_organ - use PRTGenericMod, only : fnrt_organ - use PRTGenericMod, only : sapw_organ - use PRTGenericMod, only : store_organ - use PRTGenericMod, only : struct_organ - use PRTGenericMod, only : repro_organ - use PRTGenericMod, only : carbon12_element - use PRTGenericMod, only : nitrogen_element - use PRTGenericMod, only : phosphorus_element - use PRTGenericMod, only : SetState - - ! CIME GLOBALS - use shr_log_mod , only : errMsg => shr_log_errMsg - - implicit none - private - - logical :: debug = .false. - - character(len=*), parameter, private :: sourcefile = & - __FILE__ - - public :: zero_site - public :: init_site_vars - public :: init_patches - public :: set_site_properties - private :: init_cohorts - - - ! ============================================================================ - -contains - - ! ============================================================================ - - subroutine init_site_vars( site_in, bc_in ) - ! - ! !DESCRIPTION: - ! - ! - ! !ARGUMENTS - type(ed_site_type), intent(inout) :: site_in - type(bc_in_type),intent(in) :: bc_in - ! - ! !LOCAL VARIABLES: - !---------------------------------------------------------------------- - integer :: el - - ! - allocate(site_in%term_nindivs_canopy(1:nlevsclass,1:numpft)) - allocate(site_in%term_nindivs_ustory(1:nlevsclass,1:numpft)) - allocate(site_in%demotion_rate(1:nlevsclass)) - allocate(site_in%promotion_rate(1:nlevsclass)) - allocate(site_in%imort_rate(1:nlevsclass,1:numpft)) - allocate(site_in%fmort_rate_canopy(1:nlevsclass,1:numpft)) - allocate(site_in%fmort_rate_ustory(1:nlevsclass,1:numpft)) - allocate(site_in%fmort_rate_cambial(1:nlevsclass,1:numpft)) - allocate(site_in%fmort_rate_crown(1:nlevsclass,1:numpft)) - allocate(site_in%growthflux_fusion(1:nlevsclass,1:numpft)) - allocate(site_in%mass_balance(1:num_elements)) - allocate(site_in%flux_diags(1:num_elements)) - - site_in%nlevsoil = bc_in%nlevsoil - allocate(site_in%rootfrac_scr(site_in%nlevsoil)) - allocate(site_in%zi_soil(0:site_in%nlevsoil)) - allocate(site_in%dz_soil(site_in%nlevsoil)) - allocate(site_in%z_soil(site_in%nlevsoil)) - - allocate(site_in%area_pft(1:numpft)) - allocate(site_in%use_this_pft(1:numpft)) - - do el=1,num_elements - allocate(site_in%flux_diags(el)%leaf_litter_input(1:numpft)) - allocate(site_in%flux_diags(el)%root_litter_input(1:numpft)) - end do - - ! Initialize the static soil - ! arrays from the boundary (initial) condition - - - site_in%zi_soil(:) = bc_in%zi_sisl(:) - site_in%dz_soil(:) = bc_in%dz_sisl(:) - site_in%z_soil(:) = bc_in%z_sisl(:) - - - ! - end subroutine init_site_vars - - ! ============================================================================ - subroutine zero_site( site_in ) - ! - ! !DESCRIPTION: - ! - ! !USES: - use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) - ! - ! !ARGUMENTS - type(ed_site_type), intent(inout) :: site_in - ! - ! !LOCAL VARIABLES: - integer :: el - !---------------------------------------------------------------------- - - site_in%oldest_patch => null() ! pointer to oldest patch at the site - site_in%youngest_patch => null() ! pointer to yngest patch at the site - - - ! PHENOLOGY - - site_in%cstatus = fates_unset_int ! are leaves in this pixel on or off? - site_in%dstatus = fates_unset_int - site_in%grow_deg_days = nan ! growing degree days - site_in%nchilldays = fates_unset_int - site_in%ncolddays = fates_unset_int - site_in%cleafondate = fates_unset_int - site_in%cleafoffdate = fates_unset_int - site_in%dleafondate = fates_unset_int - site_in%dleafoffdate = fates_unset_int - site_in%water_memory(:) = nan site_in%vegtemp_memory(:) = nan ! record of last 10 days temperature for senescence model. site_in%phen_model_date = fates_unset_int @@ -278,12 +101,12 @@ subroutine set_site_properties( nsites, sites,bc_in ) ! is memory-less, but needed ! for first value in history file - sites(s)%phen_model_date = hlm_day_of_year - sites(s)%cleafondate = cleafon - sites(s)%cleafoffdate = cleafoff - sites(s)%dleafoffdate = dleafoff - sites(s)%dleafondate = dleafon - sites(s)%grow_deg_days = GDD + sites(s)%phen_model_date = 0 + sites(s)%cleafondate = cleafon - hlm_day_of_year + sites(s)%cleafoffdate = cleafoff - hlm_day_of_year + sites(s)%dleafoffdate = dleafoff - hlm_day_of_year + sites(s)%dleafondate = dleafon - hlm_day_of_year + sites(s)%grow_deg_days = GDD sites(s)%water_memory(1:numWaterMem) = watermem sites(s)%vegtemp_memory(1:num_vegtemp_mem) = 0._r8 diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index a022e64624..6b408e713f 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -1695,7 +1695,6 @@ subroutine update_history_dyn(this,nc,nsites,sites) integer :: height_bin_max, height_bin_min ! which height bin a given cohort's canopy is in integer :: i_heightbin ! iterator for height bins integer :: el ! Loop index for elements - integer :: model_day_int ! integer model day from reference integer :: ageclass_since_anthrodist ! what is the equivalent age class for ! time-since-anthropogenic-disturbance of secondary forest @@ -1973,7 +1972,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_cleafoff_si => this%hvars(ih_cleafoff_si)%r81d, & hio_cleafon_si => this%hvars(ih_cleafon_si)%r81d, & hio_dleafoff_si => this%hvars(ih_dleafoff_si)%r81d, & - hio_dleafon_si => this%hvars(ih_dleafoff_si)%r81d, & + hio_dleafon_si => this%hvars(ih_dleafon_si)%r81d, & hio_meanliqvol_si => this%hvars(ih_meanliqvol_si)%r81d, & hio_cbal_err_fates_si => this%hvars(ih_cbal_err_fates_si)%r81d, & hio_err_fates_si => this%hvars(ih_err_fates_si)%r82d ) @@ -1989,7 +1988,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! If we don't have dynamics turned on, we just abort these diagnostics if (hlm_use_ed_st3.eq.itrue) return - model_day_int = nint(hlm_model_day) + ! --------------------------------------------------------------------------------- ! Loop through the FATES scale hierarchy and fill the history IO arrays @@ -2034,12 +2033,12 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_gdd_si(io_si) = sites(s)%grow_deg_days - hio_cleafoff_si(io_si) = real(model_day_int - sites(s)%cleafoffdate,r8) - hio_cleafon_si(io_si) = real(model_day_int - sites(s)%cleafondate,r8) - hio_dleafoff_si(io_si) = real(model_day_int - sites(s)%dleafoffdate,r8) - hio_dleafon_si(io_si) = real(model_day_int - sites(s)%dleafondate,r8) - - if(model_day_int>numWaterMem)then + hio_cleafoff_si(io_si) = real(sites(s)%phen_model_date - sites(s)%cleafoffdate,r8) + hio_cleafon_si(io_si) = real(sites(s)%phen_model_date - sites(s)%cleafondate,r8) + hio_dleafoff_si(io_si) = real(sites(s)%phen_model_date - sites(s)%dleafoffdate,r8) + hio_dleafon_si(io_si) = real(sites(s)%phen_model_date - sites(s)%dleafondate,r8) + + if(sites(s)%phen_model_date>numWaterMem)then hio_meanliqvol_si(io_si) = & sum(sites(s)%water_memory(1:numWaterMem))/real(numWaterMem,r8) end if From 4f102243ea247633d9d5bb07fee27dc21d24b633 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 14 Aug 2020 19:57:48 -0400 Subject: [PATCH 003/852] Somehow some really strange changes got into last commit (bumped keyboard), this reverts and fixes EDInitMod.F90 --- main/EDInitMod.F90 | 178 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 177 insertions(+), 1 deletion(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 074f645cb4..02630b0092 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -1,4 +1,181 @@ +module EDInitMod + ! ============================================================================ + ! Contains all modules to set up the ED structure. + ! ============================================================================ + + use FatesConstantsMod , only : r8 => fates_r8 + use FatesConstantsMod , only : ifalse + use FatesConstantsMod , only : itrue + use FatesConstantsMod , only : fates_unset_int + use FatesConstantsMod , only : primaryforest + use FatesGlobals , only : endrun => fates_endrun + use EDTypesMod , only : nclmax + use FatesGlobals , only : fates_log + use FatesInterfaceTypesMod , only : hlm_is_restart + use EDPftvarcon , only : EDPftvarcon_inst + use EDCohortDynamicsMod , only : create_cohort, fuse_cohorts, sort_cohorts + use EDCohortDynamicsMod , only : InitPRTObject + use EDPatchDynamicsMod , only : create_patch + use ChecksBalancesMod , only : SiteMassStock + use EDTypesMod , only : ed_site_type, ed_patch_type, ed_cohort_type + use EDTypesMod , only : numWaterMem + use EDTypesMod , only : num_vegtemp_mem + use EDTypesMod , only : maxpft + use EDTypesMod , only : AREA + use EDTypesMod , only : init_spread_near_bare_ground + use EDTypesMod , only : init_spread_inventory + use EDTypesMod , only : leaves_on + use EDTypesMod , only : leaves_off + use EDTypesMod , only : num_elements + use EDTypesMod , only : element_list + use EDTypesMod , only : phen_cstat_nevercold + use EDTypesMod , only : phen_cstat_iscold + use EDTypesMod , only : phen_dstat_timeoff + use EDTypesMod , only : phen_dstat_moistoff + use EDTypesMod , only : phen_cstat_notcold + use EDTypesMod , only : phen_dstat_moiston + use FatesInterfaceTypesMod , only : hlm_day_of_year + use FatesInterfaceTypesMod , only : bc_in_type + use FatesInterfaceTypesMod , only : hlm_use_planthydro + use FatesInterfaceTypesMod , only : hlm_use_inventory_init + use FatesInterfaceTypesMod , only : hlm_use_fixed_biogeog + use FatesInterfaceTypesMod , only : numpft + use FatesInterfaceTypesMod , only : nleafage + use FatesInterfaceTypesMod , only : nlevsclass + use FatesInterfaceTypesMod , only : nlevcoage + use FatesAllometryMod , only : h2d_allom + use FatesAllometryMod , only : bagw_allom + use FatesAllometryMod , only : bbgw_allom + use FatesAllometryMod , only : bleaf + use FatesAllometryMod , only : bfineroot + use FatesAllometryMod , only : bsap_allom + use FatesAllometryMod , only : bdead_allom + use FatesAllometryMod , only : bstore_allom + + use FatesInterfaceTypesMod, only : hlm_parteh_mode + use PRTGenericMod, only : prt_carbon_allom_hyp + use PRTGenericMod, only : prt_cnp_flex_allom_hyp + use PRTGenericMod, only : prt_vartypes + use PRTGenericMod, only : leaf_organ + use PRTGenericMod, only : fnrt_organ + use PRTGenericMod, only : sapw_organ + use PRTGenericMod, only : store_organ + use PRTGenericMod, only : struct_organ + use PRTGenericMod, only : repro_organ + use PRTGenericMod, only : carbon12_element + use PRTGenericMod, only : nitrogen_element + use PRTGenericMod, only : phosphorus_element + use PRTGenericMod, only : SetState + + ! CIME GLOBALS + use shr_log_mod , only : errMsg => shr_log_errMsg + + implicit none + private + + logical :: debug = .false. + + character(len=*), parameter, private :: sourcefile = & + __FILE__ + + public :: zero_site + public :: init_site_vars + public :: init_patches + public :: set_site_properties + private :: init_cohorts + + + ! ============================================================================ + +contains + + ! ============================================================================ + + subroutine init_site_vars( site_in, bc_in ) + ! + ! !DESCRIPTION: + ! + ! + ! !ARGUMENTS + type(ed_site_type), intent(inout) :: site_in + type(bc_in_type),intent(in) :: bc_in + ! + ! !LOCAL VARIABLES: + !---------------------------------------------------------------------- + integer :: el + + ! + allocate(site_in%term_nindivs_canopy(1:nlevsclass,1:numpft)) + allocate(site_in%term_nindivs_ustory(1:nlevsclass,1:numpft)) + allocate(site_in%demotion_rate(1:nlevsclass)) + allocate(site_in%promotion_rate(1:nlevsclass)) + allocate(site_in%imort_rate(1:nlevsclass,1:numpft)) + allocate(site_in%fmort_rate_canopy(1:nlevsclass,1:numpft)) + allocate(site_in%fmort_rate_ustory(1:nlevsclass,1:numpft)) + allocate(site_in%fmort_rate_cambial(1:nlevsclass,1:numpft)) + allocate(site_in%fmort_rate_crown(1:nlevsclass,1:numpft)) + allocate(site_in%growthflux_fusion(1:nlevsclass,1:numpft)) + allocate(site_in%mass_balance(1:num_elements)) + allocate(site_in%flux_diags(1:num_elements)) + + site_in%nlevsoil = bc_in%nlevsoil + allocate(site_in%rootfrac_scr(site_in%nlevsoil)) + allocate(site_in%zi_soil(0:site_in%nlevsoil)) + allocate(site_in%dz_soil(site_in%nlevsoil)) + allocate(site_in%z_soil(site_in%nlevsoil)) + + allocate(site_in%area_pft(1:numpft)) + allocate(site_in%use_this_pft(1:numpft)) + + do el=1,num_elements + allocate(site_in%flux_diags(el)%leaf_litter_input(1:numpft)) + allocate(site_in%flux_diags(el)%root_litter_input(1:numpft)) + end do + + ! Initialize the static soil + ! arrays from the boundary (initial) condition + + + site_in%zi_soil(:) = bc_in%zi_sisl(:) + site_in%dz_soil(:) = bc_in%dz_sisl(:) + site_in%z_soil(:) = bc_in%z_sisl(:) + + + ! + end subroutine init_site_vars + + ! ============================================================================ + subroutine zero_site( site_in ) + ! + ! !DESCRIPTION: + ! + ! !USES: + use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) + ! + ! !ARGUMENTS + type(ed_site_type), intent(inout) :: site_in + ! + ! !LOCAL VARIABLES: + integer :: el + !---------------------------------------------------------------------- + + site_in%oldest_patch => null() ! pointer to oldest patch at the site + site_in%youngest_patch => null() ! pointer to yngest patch at the site + + + ! PHENOLOGY + + site_in%cstatus = fates_unset_int ! are leaves in this pixel on or off? + site_in%dstatus = fates_unset_int + site_in%grow_deg_days = nan ! growing degree days + site_in%nchilldays = fates_unset_int + site_in%ncolddays = fates_unset_int + site_in%cleafondate = fates_unset_int + site_in%cleafoffdate = fates_unset_int + site_in%dleafondate = fates_unset_int + site_in%dleafoffdate = fates_unset_int + site_in%water_memory(:) = nan site_in%vegtemp_memory(:) = nan ! record of last 10 days temperature for senescence model. site_in%phen_model_date = fates_unset_int @@ -100,7 +277,6 @@ subroutine set_site_properties( nsites, sites,bc_in ) ! immediately, so yes this ! is memory-less, but needed ! for first value in history file - sites(s)%phen_model_date = 0 sites(s)%cleafondate = cleafon - hlm_day_of_year sites(s)%cleafoffdate = cleafoff - hlm_day_of_year From f7d864b9c71982405aade80780bdcaf6ed39abc3 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 23 Oct 2020 10:26:13 -0600 Subject: [PATCH 004/852] Moved comment on phen model day counter to correct position --- biogeochem/EDPhysiologyMod.F90 | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 39bea9ea14..ad3497c56f 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -745,6 +745,9 @@ subroutine phenology( currentSite, bc_in ) ! This is the integer model day. The first day of the simulation is 1, and it ! continues monotonically, indefinitely + ! Advance it. (this should be a global, no reason + ! for site level, but we don't have global scalars in the + ! restart file) currentSite%phen_model_date = currentSite%phen_model_date + 1 model_day_int = currentSite%phen_model_date @@ -1063,12 +1066,7 @@ subroutine phenology( currentSite, bc_in ) call phenology_leafonoff(currentSite) - ! Advance the model day (this should be a global, no reason - ! for site level, but we don't have global scalars in the - ! restart file) - - - + return end subroutine phenology ! ============================================================================ From ba0b01ac09baeb86c856779bf67ea07f5efb25d1 Mon Sep 17 00:00:00 2001 From: czarakas Date: Wed, 3 Mar 2021 18:05:22 -0700 Subject: [PATCH 005/852] Preliminary implementation of Kumarathunge et al. temperature acclimation --- biogeochem/EDPatchDynamicsMod.F90 | 5 +- biogeophys/FatesPlantRespPhotosynthMod.F90 | 137 ++++++++++++++++++--- main/EDParamsMod.F90 | 15 ++- main/EDTypesMod.F90 | 7 ++ main/FatesHistoryInterfaceMod.F90 | 85 ++++++++++++- 5 files changed, 229 insertions(+), 20 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index ea0b2918db..9c129061fb 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -2087,7 +2087,10 @@ subroutine zero_patch(cp_p) currentPatch%ed_laisha_z(:,:,:) = nan currentPatch%ed_parsun_z(:,:,:) = nan currentPatch%ed_parsha_z(:,:,:) = nan - currentPatch%psn_z(:,:,:) = 0._r8 + currentPatch%psn_z(:,:,:) = 0._r8 + currentPatch%aj_z(:,:,:) = 0._r8 + currentPatch%ac_z(:,:,:) = 0._r8 + currentPatch%ap_z(:,:,:) = 0._r8 currentPatch%f_sun(:,:,:) = nan currentPatch%tr_soil_dir(:) = nan ! fraction of incoming direct radiation that is transmitted to the soil as direct diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index bfe01d25be..dea90e7a41 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -46,9 +46,11 @@ module FATESPlantRespPhotosynthMod use PRTGenericMod, only : store_organ use PRTGenericMod, only : repro_organ use PRTGenericMod, only : struct_organ - use EDParamsMod, only : ED_val_base_mr_20, stomatal_model + use EDParamsMod, only : ED_val_base_mr_20, stomatal_model, temp_acclim use PRTParametersMod, only : prt_params + use TemperatureType, only : temperature_type + ! CIME Globals use shr_log_mod , only : errMsg => shr_log_errMsg @@ -77,7 +79,7 @@ module FATESPlantRespPhotosynthMod !-------------------------------------------------------------------------------------- - subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) + subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime, temperature_inst) ! ----------------------------------------------------------------------------------- ! !DESCRIPTION: @@ -119,6 +121,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) type(bc_in_type),intent(in) :: bc_in(nsites) type(bc_out_type),intent(inout) :: bc_out(nsites) real(r8),intent(in) :: dtime + type(temperature_type) , intent(in) :: temperature_inst ! LOCAL VARIABLES: @@ -498,6 +501,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) call LeafLayerBiophysicalRates(currentPatch%ed_parsun_z(cl,ft,iv), & ! in + temperature_inst, & !in ft, & ! in currentCohort%vcmax25top, & ! in currentCohort%jmax25top, & ! in @@ -540,6 +544,9 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) co2_cpoint, & ! in lmr_z(iv,ft,cl), & ! in currentPatch%psn_z(cl,ft,iv), & ! out + currentPatch%aj_z(cl,ft,iv), & ! out + currentPatch%ac_z(cl,ft,iv), & ! out + currentPatch%ap_z(cl,ft,iv), & ! out rs_z(iv,ft,cl), & ! out anet_av_z(iv,ft,cl), & ! out c13disc_z(cl,ft,iv)) ! out @@ -552,6 +559,9 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) currentCohort%npp_tstep = 0.0_r8 currentCohort%resp_tstep = 0.0_r8 currentCohort%gpp_tstep = 0.0_r8 + currentCohort%aj_sum_tstep = 0.0_r8 + currentCohort%ac_sum_tstep = 0.0_r8 + currentCohort%ap_sum_tstep = 0.0_r8 currentCohort%rdark = 0.0_r8 currentCohort%resp_m = 0.0_r8 currentCohort%ts_net_uptake = 0.0_r8 @@ -567,6 +577,9 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) nv = currentCohort%nv call ScaleLeafLayerFluxToCohort(nv, & !in currentPatch%psn_z(cl,ft,1:nv), & !in + currentPatch%aj_z(cl,ft,1:nv), & !in + currentPatch%ac_z(cl,ft,1:nv), & !in + currentPatch%ap_z(cl,ft,1:nv), & !in lmr_z(1:nv,ft,cl), & !in rs_z(1:nv,ft,cl), & !in currentPatch%elai_profile(cl,ft,1:nv), & !in @@ -577,6 +590,9 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) maintresp_reduction_factor, & !in currentCohort%g_sb_laweight, & !out currentCohort%gpp_tstep, & !out + currentCohort%aj_sum_tstep, & !out + currentCohort%ac_sum_tstep, & !out + currentCohort%ap_sum_tstep, & !out currentCohort%rdark, & !out currentCohort%c13disc_clm, & !out cohort_eleaf_area) !out @@ -591,6 +607,9 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! or dark respiration cohort_eleaf_area = 0.0_r8 currentCohort%gpp_tstep = 0.0_r8 + currentCohort%aj_sum_tstep = 0.0_r8 + currentCohort%ac_sum_tstep = 0.0_r8 + currentCohort%ap_sum_tstep = 0.0_r8 currentCohort%rdark = 0.0_r8 currentCohort%g_sb_laweight = 0.0_r8 currentCohort%ts_net_uptake(:) = 0.0_r8 @@ -721,6 +740,9 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! convert from kgC/indiv/s to kgC/indiv/timestep currentCohort%resp_m = currentCohort%resp_m * dtime currentCohort%gpp_tstep = currentCohort%gpp_tstep * dtime + currentCohort%aj_sum_tstep = currentCohort%aj_sum_tstep * dtime + currentCohort%ac_sum_tstep = currentCohort%ac_sum_tstep * dtime + currentCohort%ap_sum_tstep = currentCohort%ap_sum_tstep * dtime currentCohort%ts_net_uptake = currentCohort%ts_net_uptake * dtime if ( debug ) write(fates_log(),*) 'EDPhoto 911 ', currentCohort%gpp_tstep @@ -856,6 +878,9 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in co2_cpoint, & ! in lmr, & ! in psn_out, & ! out + aj_out, & ! out + ac_out, & ! out + ap_out, & ! out rstoma_out, & ! out anet_av_out, & ! out c13disc_z) ! out @@ -912,6 +937,9 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in real(r8), intent(in) :: lmr ! Leaf Maintenance Respiration (umol CO2/m**2/s) real(r8), intent(out) :: psn_out ! carbon assimilated in this leaf layer umolC/m2/s + real(r8), intent(out) :: aj_out ! RuBP-limited gross photosynthesis (umol CO2/m2/s) + real(r8), intent(out) :: ac_out ! Rubisco-limited gross photosynthesis (umol CO2/m2/s) + real(r8), intent(out) :: ap_out ! Product-limited gross photosynthesis (umol CO2/m2/s) real(r8), intent(out) :: rstoma_out ! stomatal resistance (1/gs_lsl) (s/m) real(r8), intent(out) :: anet_av_out ! net leaf photosynthesis (umol CO2/m**2/s) ! averaged over sun and shade leaves. @@ -996,6 +1024,9 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in anet_av_out = -lmr psn_out = 0._r8 + aj_out = 0._r8 + ac_out = 0._r8 + ap_out = 0._r8 ! The cuticular conductance already factored in maximum resistance as a bound ! no need to re-bound it @@ -1011,6 +1042,9 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in !Loop aroun shaded and unshaded leaves psn_out = 0._r8 ! psn is accumulated across sun and shaded leaves. + aj_out = 0._r8 + ac_out = 0._r8 + ap_out = 0._r8 rstoma_out = 0._r8 ! 1/rs is accumulated across sun and shaded leaves. anet_av_out = 0._r8 gstoma = 0._r8 @@ -1190,10 +1224,16 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in ! weight per unit sun and sha leaves. if(sunsha == 1)then !sunlit psn_out = psn_out + agross * f_sun_lsl + aj_out = aj_out + aj * f_sun_lsl + ac_out = ac_out + ac * f_sun_lsl + ap_out = ap_out + ap * f_sun_lsl anet_av_out = anet_av_out + anet * f_sun_lsl gstoma = gstoma + 1._r8/(min(1._r8/gs, rsmax0)) * f_sun_lsl else - psn_out = psn_out + agross * (1.0_r8-f_sun_lsl) + psn_out = psn_out + agross * (1.0_r8-f_sun_lsl) + aj_out = aj_out + aj * (1.0_r8-f_sun_lsl) + ac_out = ac_out + ac * (1.0_r8-f_sun_lsl) + ap_out = ap_out + ap * (1.0_r8-f_sun_lsl) anet_av_out = anet_av_out + anet * (1.0_r8-f_sun_lsl) gstoma = gstoma + & 1._r8/(min(1._r8/gs, rsmax0)) * (1.0_r8-f_sun_lsl) @@ -1233,6 +1273,9 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in ! (leaves are off, or have reduced to 0) psn_out = 0._r8 + aj_out = 0._r8 + ac_out = 0._r8 + ap_out = 0._r8 anet_av_out = 0._r8 rstoma_out = min(rsmax0,cf/(stem_cuticle_loss_frac*stomatal_intercept(ft))) @@ -1252,6 +1295,9 @@ end subroutine LeafLayerPhotosynthesis subroutine ScaleLeafLayerFluxToCohort(nv, & ! in currentCohort%nv psn_llz, & ! in %psn_z(1:currentCohort%nv,ft,cl) + aj_llz, & ! in %aj_z(1:currentCohort%nv,ft,cl) + ac_llz, & ! in %ac_z(1:currentCohort%nv,ft,cl) + ap_llz, & ! in %ap_z(1:currentCohort%nv,ft,cl) lmr_llz, & ! in lmr_z(1:currentCohort%nv,ft,cl) rs_llz, & ! in rs_z(1:currentCohort%nv,ft,cl) elai_llz, & ! in %elai_profile(cl,ft,1:currentCohort%nv) @@ -1262,6 +1308,9 @@ subroutine ScaleLeafLayerFluxToCohort(nv, & ! in currentCohort%nv maintresp_reduction_factor, & ! in g_sb_laweight, & ! out currentCohort%g_sb_laweight [m/s] [m2-leaf] gpp, & ! out currentCohort%gpp_tstep + aj_sum, & ! out currentCohort%aj_sum_tstep + ac_sum, & ! out currentCohort%ac_sum_tstep + ap_sum, & ! out currentCohort%ap_sum_tstep rdark, & ! out currentCohort%rdark c13disc_clm, & ! out currentCohort%c13disc_clm cohort_eleaf_area ) ! out [m2] @@ -1279,6 +1328,9 @@ subroutine ScaleLeafLayerFluxToCohort(nv, & ! in currentCohort%nv ! Arguments integer, intent(in) :: nv ! number of active leaf layers real(r8), intent(in) :: psn_llz(nv) ! layer photosynthesis rate (GPP) [umolC/m2leaf/s] + real(r8), intent(in) :: aj_llz(nv) ! layer RuBP-limited photosynthesis rate [umolC/m2leaf/s] + real(r8), intent(in) :: ac_llz(nv) ! layer Rubisco-limited photosynthesis rate [umolC/m2leaf/s] + real(r8), intent(in) :: ap_llz(nv) ! layer Product-limited photosynthesis rate [umolC/m2leaf/s] real(r8), intent(in) :: lmr_llz(nv) ! layer dark respiration rate [umolC/m2leaf/s] real(r8), intent(in) :: rs_llz(nv) ! leaf layer stomatal resistance [s/m] real(r8), intent(in) :: elai_llz(nv) ! exposed LAI per layer [m2 leaf/ m2 pft footprint] @@ -1290,6 +1342,9 @@ subroutine ScaleLeafLayerFluxToCohort(nv, & ! in currentCohort%nv real(r8), intent(out) :: g_sb_laweight ! Combined conductance (stomatal + boundary layer) for the cohort ! weighted by leaf area [m/s]*[m2] real(r8), intent(out) :: gpp ! GPP (kgC/indiv/s) + real(r8), intent(out) :: aj_sum ! RuBP-limited GPP (kgC/indiv/s) + real(r8), intent(out) :: ac_sum ! Rubisco-limited GPP (kgC/indiv/s) + real(r8), intent(out) :: ap_sum ! Product-limited GPP (kgC/indiv/s) real(r8), intent(out) :: rdark ! Dark Leaf Respiration (kgC/indiv/s) real(r8), intent(out) :: cohort_eleaf_area ! Effective leaf area of the cohort [m2] real(r8), intent(out) :: c13disc_clm ! unpacked Cohort level c13 discrimination @@ -1306,6 +1361,9 @@ subroutine ScaleLeafLayerFluxToCohort(nv, & ! in currentCohort%nv cohort_eleaf_area = 0.0_r8 g_sb_laweight = 0.0_r8 gpp = 0.0_r8 + aj_sum = 0.0_r8 + ac_sum = 0.0_r8 + ap_sum = 0.0_r8 rdark = 0.0_r8 do il = 1, nv ! Loop over the leaf layers this cohort participates in @@ -1331,6 +1389,11 @@ subroutine ScaleLeafLayerFluxToCohort(nv, & ! in currentCohort%nv ! GPP [umolC/m2leaf/s] * [m2 leaf ] -> [umolC/s] (This is cohort group sum) gpp = gpp + psn_llz(il) * cohort_layer_eleaf_area + !RuBP-, rubisco-, and product-limited GPP + aj_sum = aj_sum + aj_llz(il) * cohort_layer_eleaf_area + ac_sum = ac_sum + ac_llz(il) * cohort_layer_eleaf_area + ap_sum = ap_sum + ap_llz(il) * cohort_layer_eleaf_area + ! Dark respiration ! [umolC/m2leaf/s] * [m2 leaf] (This is the cohort group sum) rdark = rdark + lmr_llz(il) * cohort_layer_eleaf_area @@ -1365,6 +1428,9 @@ subroutine ScaleLeafLayerFluxToCohort(nv, & ! in currentCohort%nv rdark = rdark * umolC_to_kgC * maintresp_reduction_factor / nplant gpp = gpp * umolC_to_kgC / nplant + aj_sum = aj_sum * umolC_to_kgC / nplant + ac_sum = ac_sum * umolC_to_kgC / nplant + ap_sum = ap_sum * umolC_to_kgC / nplant if ( debug ) then write(fates_log(),*) 'EDPhoto 816 ', gpp @@ -1811,6 +1877,7 @@ end subroutine LeafLayerMaintenanceRespiration ! ==================================================================================== subroutine LeafLayerBiophysicalRates( parsun_lsl, & + temperature_inst, & ft, & vcmax25top_ft, & jmax25top_ft, & @@ -1843,8 +1910,9 @@ subroutine LeafLayerBiophysicalRates( parsun_lsl, & ! Arguments ! ------------------------------------------------------------------------------ - + real(r8), intent(in) :: parsun_lsl ! PAR absorbed in sunlit leaves for this layer + type(temperature_type) , intent(in) :: temperature_inst integer, intent(in) :: ft ! (plant) Functional Type Index real(r8), intent(in) :: nscaler ! Scale for leaf nitrogen profile real(r8), intent(in) :: vcmax25top_ft ! canopy top maximum rate of carboxylation at 25C @@ -1864,7 +1932,7 @@ subroutine LeafLayerBiophysicalRates( parsun_lsl, & real(r8), intent(out) :: tpu ! triose phosphate utilization rate ! (umol CO2/m**2/s) real(r8), intent(out) :: co2_rcurve_islope ! initial slope of CO2 response curve (C4 plants) - + ! Locals ! ------------------------------------------------------------------------------- real(r8) :: vcmax25 ! leaf layer: maximum rate of carboxylation at 25C @@ -1888,26 +1956,55 @@ subroutine LeafLayerBiophysicalRates( parsun_lsl, & real(r8) :: vcmaxse ! entropy term for vcmax (J/mol/K) real(r8) :: jmaxse ! entropy term for jmax (J/mol/K) real(r8) :: tpuse ! entropy term for tpu (J/mol/K) + + real(r8) :: tgrowth ! average growing temperature + real(r8) :: thome ! average home temperature + real(r8) :: jvr ! ratio of Jmax25 / Vcmax25 + real(r8) :: vcmaxc ! scaling factor for high temperature inhibition (25 C = 1.0) real(r8) :: jmaxc ! scaling factor for high temperature inhibition (25 C = 1.0) real(r8) :: tpuc ! scaling factor for high temperature inhibition (25 C = 1.0) - vcmaxha = EDPftvarcon_inst%vcmaxha(FT) - jmaxha = EDPftvarcon_inst%jmaxha(FT) + associate( t10 => temperature_inst%t_a10_patch, & ! Input: [real(r8) (:) ] 10-day running mean of the 2 m temperature (K) + t30 => temperature_inst%t_a30_patch) ! Input: [real(r8) (:) ] 30-day running mean of the 2 m temperature (K) + + if (temp_acclim == 0) then !No temperature acclimation + vcmaxha = EDPftvarcon_inst%vcmaxha(FT) + jmaxha = EDPftvarcon_inst%jmaxha(FT) + vcmaxhd = EDPftvarcon_inst%vcmaxhd(FT) + jmaxhd = EDPftvarcon_inst%jmaxhd(FT) + vcmaxse = EDPftvarcon_inst%vcmaxse(FT) + jmaxse = EDPftvarcon_inst%jmaxse(FT) + else if (temp_acclim == 1) then !Kumarathunge et al. temperature acclimation, Thome=Tgrowth + tgrowth = t30(1)-tfrz + thome = t30(1)-tfrz + vcmaxha = (42.6 + (1.14*tgrowth))*1000 !J/mol + jmaxha = 40.71*1000 !J/mol + vcmaxhd = 200*1000 !J/mol + jmaxhd = 200*1000 !J/mol + vcmaxse = (645.13 - (0.38*tgrowth)) + jmaxse = 658.77 - (0.84*thome) - 0.52*(tgrowth-thome) + jvr = 2.56 - (0.0375*thome)-(0.0202*(tgrowth-thome)) + else if (temp_acclim == 2) then !Kumarathunge et al. temperature acclimation, Thome=25C + tgrowth = t30(1)-tfrz + thome = 25 !degrees C + vcmaxha = (42.6 + (1.14*tgrowth))*1000 !J/mol + jmaxha = 40.71*1000 !J/mol + vcmaxhd = 200*1000 !J/mol + jmaxhd = 200*1000 !J/mol + vcmaxse = (645.13 - (0.38*tgrowth)) + jmaxse = 658.77 - (0.84*thome) - 0.52*(tgrowth-thome) + jvr = 2.56 - (0.0375*thome)-(0.0202*(tgrowth-thome)) + end if + tpuha = EDPftvarcon_inst%tpuha(FT) - - vcmaxhd = EDPftvarcon_inst%vcmaxhd(FT) - jmaxhd = EDPftvarcon_inst%jmaxhd(FT) tpuhd = EDPftvarcon_inst%tpuhd(FT) - - vcmaxse = EDPftvarcon_inst%vcmaxse(FT) - jmaxse = EDPftvarcon_inst%jmaxse(FT) tpuse = EDPftvarcon_inst%tpuse(FT) - + vcmaxc = fth25_f(vcmaxhd, vcmaxse) jmaxc = fth25_f(jmaxhd, jmaxse) tpuc = fth25_f(tpuhd, tpuse) - + if ( parsun_lsl <= 0._r8) then ! night time vcmax = 0._r8 jmax = 0._r8 @@ -1917,7 +2014,13 @@ subroutine LeafLayerBiophysicalRates( parsun_lsl, & ! Vcmax25top was already calculated to derive the nscaler function vcmax25 = vcmax25top_ft * nscaler - jmax25 = jmax25top_ft * nscaler + if (temp_acclim == 0) then + jmax25 = jmax25top_ft * nscaler + else if (temp_acclim == 1) then + jmax25 = vcmax25*jvr + else if (temp_acclim == 2) then + jmax25 = vcmax25*jvr + end if tpu25 = tpu25top_ft * nscaler co2_rcurve_islope25 = co2_rcurve_islope25top_ft * nscaler @@ -1939,6 +2042,8 @@ subroutine LeafLayerBiophysicalRates( parsun_lsl, & vcmax = vcmax * btran return + end associate + end subroutine LeafLayerBiophysicalRates subroutine lowstorage_maintresp_reduction(frac, pft, maintresp_reduction_factor) diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 8162939bc3..a4987d593f 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -43,7 +43,8 @@ module EDParamsMod real(r8),protected, public :: ED_val_patch_fusion_tol 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 :: temp_acclim !switch for turning on and off temperature acclimation, 0 for off, 1 for Kumarathunge et al. temperature acclimation + logical,protected, public :: active_crown_fire ! flag, 1=active crown fire 0=no active crown fire character(len=param_string_length),parameter :: fates_name_active_crown_fire = "fates_fire_active_crown_fire" @@ -82,6 +83,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_temp_acclim= "fates_leaf_temp_acclim" ! Resistance to active crown fire @@ -195,6 +197,7 @@ subroutine FatesParamsInit() ED_val_patch_fusion_tol = nan ED_val_canopy_closure_thresh = nan stomatal_model = -9 + temp_acclim = 0 hydr_kmax_rsurf1 = nan hydr_kmax_rsurf2 = nan hydr_psi0 = nan @@ -305,6 +308,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_temp_acclim, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) call fates_params%RegisterParameter(name=hydr_name_kmax_rsurf1, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -458,6 +464,10 @@ subroutine FatesReceiveParams(fates_params) data=tmpreal) stomatal_model = nint(tmpreal) + call fates_params%RetreiveParameter(name=ED_name_temp_acclim, & + data=tmpreal) + temp_acclim = nint(tmpreal) + call fates_params%RetreiveParameter(name=hydr_name_kmax_rsurf1, & data=hydr_kmax_rsurf1) @@ -565,7 +575,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) 'stomatal_model = ',stomatal_model + write(fates_log(),fmt0) 'stomatal_model = ',stomatal_model + write(fates_log(),fmt0) 'temp_acclim = ',temp_acclim write(fates_log(),fmt0) 'hydr_kmax_rsurf1 = ',hydr_kmax_rsurf1 write(fates_log(),fmt0) 'hydr_kmax_rsurf2 = ',hydr_kmax_rsurf2 write(fates_log(),fmt0) 'hydr_psi0 = ',hydr_psi0 diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 7288a4ef99..c63e2e9503 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -268,6 +268,10 @@ module EDTypesMod real(r8) :: gpp_acc real(r8) :: gpp_acc_hold + real(r8) :: aj_sum_tstep ! RuBP-limited gross Primary Production (see above *) + real(r8) :: ac_sum_tstep ! Rubisco-limited gross Primary Production (see above *) + real(r8) :: ap_sum_tstep ! Product-limited gross Primary Production (see above *) + real(r8) :: npp_tstep ! Net Primary Production (see above *) real(r8) :: npp_acc real(r8) :: npp_acc_hold @@ -506,6 +510,9 @@ module EDTypesMod ! PHOTOSYNTHESIS real(r8) :: psn_z(nclmax,maxpft,nlevleaf) ! carbon assimilation in each canopy layer, pft, and leaf layer. umolC/m2/s + real(r8) :: aj_z(nclmax,maxpft,nlevleaf) ! RuBP-limited carbon assimilation in each canopy layer, pft, and leaf layer. umolC/m2/s + real(r8) :: ac_z(nclmax,maxpft,nlevleaf) ! Rubisco-limited carbon assimilation in each canopy layer, pft, and leaf layer. umolC/m2/s + real(r8) :: ap_z(nclmax,maxpft,nlevleaf) ! Product-limited carbon assimilation in each canopy layer, pft, and leaf layer. umolC/m2/s ! ROOTS real(r8) :: btran_ft(maxpft) ! btran calculated seperately for each PFT:- diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index aa5e7db161..a01d701efc 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -255,13 +255,22 @@ module FatesHistoryInterfaceMod integer :: ih_agb_si integer :: ih_npp_si integer :: ih_gpp_si + integer :: ih_aj_si + integer :: ih_ac_si + integer :: ih_ap_si integer :: ih_aresp_si integer :: ih_maint_resp_si integer :: ih_growth_resp_si integer :: ih_ar_canopy_si integer :: ih_gpp_canopy_si + integer :: ih_aj_canopy_si + integer :: ih_ac_canopy_si + integer :: ih_ap_canopy_si integer :: ih_ar_understory_si integer :: ih_gpp_understory_si + integer :: ih_aj_understory_si + integer :: ih_ac_understory_si + integer :: ih_ap_understory_si integer :: ih_canopy_biomass_si integer :: ih_understory_biomass_si @@ -3373,6 +3382,9 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) real(r8) :: per_dt_tstep ! Time step in frequency units (/s) associate( hio_gpp_si => this%hvars(ih_gpp_si)%r81d, & + hio_aj_si => this%hvars(ih_aj_si)%r81d, & + hio_ac_si => this%hvars(ih_ac_si)%r81d, & + hio_ap_si => this%hvars(ih_ap_si)%r81d, & hio_npp_si => this%hvars(ih_npp_si)%r81d, & hio_aresp_si => this%hvars(ih_aresp_si)%r81d, & hio_maint_resp_si => this%hvars(ih_maint_resp_si)%r81d, & @@ -3388,8 +3400,14 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) hio_ar_crootm_si_scpf => this%hvars(ih_ar_crootm_si_scpf)%r82d, & hio_ar_frootm_si_scpf => this%hvars(ih_ar_frootm_si_scpf)%r82d, & hio_gpp_canopy_si => this%hvars(ih_gpp_canopy_si)%r81d, & + hio_aj_canopy_si => this%hvars(ih_aj_canopy_si)%r81d, & + hio_ac_canopy_si => this%hvars(ih_ac_canopy_si)%r81d, & + hio_ap_canopy_si => this%hvars(ih_ap_canopy_si)%r81d, & hio_ar_canopy_si => this%hvars(ih_ar_canopy_si)%r81d, & hio_gpp_understory_si => this%hvars(ih_gpp_understory_si)%r81d, & + hio_aj_understory_si => this%hvars(ih_aj_understory_si)%r81d, & + hio_ac_understory_si => this%hvars(ih_ac_understory_si)%r81d, & + hio_ap_understory_si => this%hvars(ih_ap_understory_si)%r81d, & hio_ar_understory_si => this%hvars(ih_ar_understory_si)%r81d, & hio_rdark_canopy_si_scls => this%hvars(ih_rdark_canopy_si_scls)%r82d, & hio_livestem_mr_canopy_si_scls => this%hvars(ih_livestem_mr_canopy_si_scls)%r82d, & @@ -3508,6 +3526,14 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) hio_gpp_si(io_si) = hio_gpp_si(io_si) + & ccohort%gpp_tstep * g_per_kg * n_perm2 * per_dt_tstep + + hio_aj_si(io_si) = hio_aj_si(io_si) + & + ccohort%aj_sum_tstep * g_per_kg * n_perm2 * per_dt_tstep + hio_ac_si(io_si) = hio_ac_si(io_si) + & + ccohort%ac_sum_tstep * g_per_kg * n_perm2 * per_dt_tstep + hio_ap_si(io_si) = hio_ap_si(io_si) + & + ccohort%ap_sum_tstep * g_per_kg * n_perm2 * per_dt_tstep + hio_aresp_si(io_si) = hio_aresp_si(io_si) + & aresp * g_per_kg * n_perm2 * per_dt_tstep hio_growth_resp_si(io_si) = hio_growth_resp_si(io_si) + & @@ -3572,6 +3598,12 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) ! bulk fluxes are in gC / m2 / s hio_gpp_canopy_si(io_si) = hio_gpp_canopy_si(io_si) + & ccohort%gpp_tstep * g_per_kg * n_perm2 * per_dt_tstep + hio_aj_canopy_si(io_si) = hio_aj_canopy_si(io_si) + & + ccohort%aj_sum_tstep * g_per_kg * n_perm2 * per_dt_tstep + hio_ac_canopy_si(io_si) = hio_ac_canopy_si(io_si) + & + ccohort%ac_sum_tstep * g_per_kg * n_perm2 * per_dt_tstep + hio_ap_canopy_si(io_si) = hio_ap_canopy_si(io_si) + & + ccohort%ap_sum_tstep * g_per_kg * n_perm2 * per_dt_tstep hio_ar_canopy_si(io_si) = hio_ar_canopy_si(io_si) + & aresp * g_per_kg * n_perm2 * per_dt_tstep @@ -3593,7 +3625,13 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) ! ! bulk fluxes are in gC / m2 / s hio_gpp_understory_si(io_si) = hio_gpp_understory_si(io_si) + & - ccohort%gpp_tstep * g_per_kg * n_perm2 * per_dt_tstep + ccohort%gpp_tstep * g_per_kg * n_perm2 * per_dt_tstep + hio_aj_understory_si(io_si) = hio_aj_understory_si(io_si) + & + ccohort%aj_sum_tstep * g_per_kg * n_perm2 * per_dt_tstep + hio_ac_understory_si(io_si) = hio_ac_understory_si(io_si) + & + ccohort%ac_sum_tstep * g_per_kg * n_perm2 * per_dt_tstep + hio_ap_understory_si(io_si) = hio_ap_understory_si(io_si) + & + ccohort%ap_sum_tstep * g_per_kg * n_perm2 * per_dt_tstep hio_ar_understory_si(io_si) = hio_ar_understory_si(io_si) + & aresp * g_per_kg * n_perm2 * per_dt_tstep @@ -4858,6 +4896,21 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=2, & ivar=ivar, initialize=initialize_variables, index = ih_gpp_si ) + call this%set_history_var(vname='AJ', units='gC/m^2/s', & + long='RuBP-limited gross primary production', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=2, & + ivar=ivar, initialize=initialize_variables, index = ih_aj_si ) + + call this%set_history_var(vname='AC', units='gC/m^2/s', & + long='Rubisco-limited gross primary production', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=2, & + ivar=ivar, initialize=initialize_variables, index = ih_ac_si ) + + call this%set_history_var(vname='AP', units='gC/m^2/s', & + long='Product-limited gross primary production', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=2, & + ivar=ivar, initialize=initialize_variables, index = ih_ap_si ) + call this%set_history_var(vname='AR', units='gC/m^2/s', & long='autotrophic respiration', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=2, & @@ -4902,6 +4955,21 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=2, & ivar=ivar, initialize=initialize_variables, index = ih_gpp_canopy_si ) + call this%set_history_var(vname='AJ_CANOPY', units='gC/m^2/s', & + long='RuBP-limited gross primary production of canopy plants', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=2, & + ivar=ivar, initialize=initialize_variables, index = ih_aj_canopy_si ) + + call this%set_history_var(vname='AC_CANOPY', units='gC/m^2/s', & + long='Rubisco-limited gross primary production of canopy plants', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=2, & + ivar=ivar, initialize=initialize_variables, index = ih_ac_canopy_si ) + + call this%set_history_var(vname='AP_CANOPY', units='gC/m^2/s', & + long='Product-limited gross primary production of canopy plants', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=2, & + ivar=ivar, initialize=initialize_variables, index = ih_ap_canopy_si ) + call this%set_history_var(vname='AR_CANOPY', units='gC/m^2/s', & long='autotrophic respiration of canopy plants', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=2, & @@ -4912,6 +4980,21 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=2, & ivar=ivar, initialize=initialize_variables, index = ih_gpp_understory_si ) + call this%set_history_var(vname='AJ_UNDERSTORY', units='gC/m^2/s', & + long='RuBP-limited gross primary production of understory plants', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=2, & + ivar=ivar, initialize=initialize_variables, index = ih_aj_understory_si ) + + call this%set_history_var(vname='AC_UNDERSTORY', units='gC/m^2/s', & + long='Rubisco-limited gross primary production of understory plants', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=2, & + ivar=ivar, initialize=initialize_variables, index = ih_ac_understory_si ) + + call this%set_history_var(vname='AP_UNDERSTORY', units='gC/m^2/s', & + long='Product-limited gross primary production of understory plants', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=2, & + ivar=ivar, initialize=initialize_variables, index = ih_ap_understory_si ) + call this%set_history_var(vname='AR_UNDERSTORY', units='gC/m^2/s', & long='autotrophic respiration of understory plants', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=2, & From 33c2f5b239a771df5fe01e8da37ed13acf436131 Mon Sep 17 00:00:00 2001 From: YanlanLiu Date: Tue, 25 May 2021 11:20:08 -0700 Subject: [PATCH 006/852] calculating seed_out and track mass balance --- biogeochem/EDPhysiologyMod.F90 | 35 ++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 26073ecd35..a8a518e46b 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1371,12 +1371,23 @@ subroutine SeedIn( currentSite, bc_in ) integer :: n_litt_types ! number of litter element types (c,n,p, etc) integer :: el ! loop counter for litter element types integer :: element_id ! element id consistent with parteh/PRTGenericMod.F90 - !------------------------------------------------------------------------------------ + + + !YL--------- + real(r8) :: site_seed_out(maxpft) ! The sum of seed-rain leaving the site [kg/site/day] + real(r8) :: disp_frac(maxpft) ! fraction of seed-rain among the site_seed_rain that's leaving the site [unitless] + real(r8) :: seed_in_supply ! + !----------- do el = 1, num_elements site_seed_rain(:) = 0._r8 + !YL------- + site_seed_out(:) = 0._r8 ! seed-rain leaving the site, 05/21 + disp_frac(:) = 0.4 ! to be specified in the parameter file or calculated using dispersal kernel + !--------- + element_id = element_list(el) site_mass => currentSite%mass_balance(el) @@ -1412,9 +1423,21 @@ subroutine SeedIn( currentSite, bc_in ) currentcohort%seed_prod = seed_prod end if + !YL---------- + + !site_seed_rain(pft) = site_seed_rain(pft) + & + ! (seed_prod * currentCohort%n + store_m_to_repro) + site_seed_rain(pft) = site_seed_rain(pft) + & - (seed_prod * currentCohort%n + store_m_to_repro) + (seed_prod * currentCohort%n + store_m_to_repro)*(1-disp_frac(pft)) + site_seed_out(pft) = site_seed_out(pft) + & + (seed_prod * currentCohort%n + store_m_to_repro)*disp_frac(pft) + write(fates_log(),*) 'pft, site_seed_rain(pft), site_seed_out(pft):', pft, site_seed_rain(pft), site_seed_out(pft) + print *, pft, site_seed_rain(pft), site_seed_out(pft) + + !----------- + currentCohort => currentCohort%shorter enddo !cohort loop @@ -1465,6 +1488,11 @@ subroutine SeedIn( currentSite, bc_in ) ! Seeds entering externally [kg/site/day] site_mass%seed_in = site_mass%seed_in + seed_in_external*currentPatch%area + + !YL------- + site_mass%seed_out = site_mass%seed_out + site_seed_out(pft) + !---------- + end if !use this pft enddo @@ -1550,6 +1578,9 @@ subroutine SeedGermination( litt, cold_stat, drought_stat ) if ((prt_params%season_decid(pft) == itrue ) .and. & (any(cold_stat == [phen_cstat_nevercold,phen_cstat_iscold]))) then + + ! no germination for all PFTs when cold. YL 03/22/2018 +! if (any(cold_stat == [phen_cstat_nevercold,phen_cstat_iscold])) then litt%seed_germ_in(pft) = 0.0_r8 endif if ((prt_params%stress_decid(pft) == itrue ) .and. & From a58b3c46c493090f1fa99afe9bea26a025c6ff40 Mon Sep 17 00:00:00 2001 From: YanlanLiu Date: Tue, 15 Jun 2021 10:45:59 -0700 Subject: [PATCH 007/852] calculate seed out in EDphysiology --- biogeochem/EDPhysiologyMod.F90 | 12 +- biogeochem/EDPhysiologyMod_0.F90 | 2400 ++++++++++++++++++++++++++++++ 2 files changed, 2403 insertions(+), 9 deletions(-) create mode 100644 biogeochem/EDPhysiologyMod_0.F90 diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index a8a518e46b..c2e83f8c15 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1375,8 +1375,7 @@ subroutine SeedIn( currentSite, bc_in ) !YL--------- real(r8) :: site_seed_out(maxpft) ! The sum of seed-rain leaving the site [kg/site/day] - real(r8) :: disp_frac(maxpft) ! fraction of seed-rain among the site_seed_rain that's leaving the site [unitless] - real(r8) :: seed_in_supply ! + real(r8) :: disp_frac(maxpft) ! fraction of seed-rain among the site_seed_rain that's leaving the site [unitless] !----------- do el = 1, num_elements @@ -1434,7 +1433,6 @@ subroutine SeedIn( currentSite, bc_in ) (seed_prod * currentCohort%n + store_m_to_repro)*disp_frac(pft) write(fates_log(),*) 'pft, site_seed_rain(pft), site_seed_out(pft):', pft, site_seed_rain(pft), site_seed_out(pft) - print *, pft, site_seed_rain(pft), site_seed_out(pft) !----------- @@ -1488,12 +1486,8 @@ subroutine SeedIn( currentSite, bc_in ) ! Seeds entering externally [kg/site/day] site_mass%seed_in = site_mass%seed_in + seed_in_external*currentPatch%area - - !YL------- - site_mass%seed_out = site_mass%seed_out + site_seed_out(pft) - !---------- - - end if !use this pft + write(fates_log(),*) 'pft, equivalent seed_suppl: ', pft, site_mass%seed_in/currentPatch%area/seed_stoich/years_per_day + end if !use this pft enddo diff --git a/biogeochem/EDPhysiologyMod_0.F90 b/biogeochem/EDPhysiologyMod_0.F90 new file mode 100644 index 0000000000..a8a518e46b --- /dev/null +++ b/biogeochem/EDPhysiologyMod_0.F90 @@ -0,0 +1,2400 @@ +module EDPhysiologyMod + +#include "shr_assert.h" + + ! ============================================================================ + ! Miscellaneous physiology routines from ED. + ! ============================================================================ + + use FatesGlobals, only : fates_log + use FatesInterfaceTypesMod, only : hlm_days_per_year + use FatesInterfaceTypesMod, only : hlm_model_day + use FatesInterfaceTypesMod, only : hlm_freq_day + use FatesInterfaceTypesMod, only : hlm_day_of_year + use FatesInterfaceTypesMod, only : numpft + use FatesInterfaceTypesMod, only : nleafage + use FatesInterfaceTypesMod, only : hlm_use_planthydro + use FatesInterfaceTypesMod, only : hlm_parteh_mode + use FatesInterfaceTypesMod, only : hlm_nitrogen_spec + use FatesInterfaceTypesMod, only : hlm_phosphorus_spec + use FatesConstantsMod, only : r8 => fates_r8 + use FatesConstantsMod, only : nearzero + use EDPftvarcon , only : EDPftvarcon_inst + use PRTParametersMod , only : prt_params + use EDPftvarcon , only : GetDecompyFrac + use FatesInterfaceTypesMod, only : bc_in_type + use FatesInterfaceTypesMod, only : bc_out_type + use EDCohortDynamicsMod , only : zero_cohort + use EDCohortDynamicsMod , only : create_cohort, sort_cohorts + use EDCohortDynamicsMod , only : InitPRTObject + use FatesAllometryMod , only : tree_lai + use FatesAllometryMod , only : tree_sai + use FatesAllometryMod , only : decay_coeff_kn + use FatesLitterMod , only : litter_type + use EDTypesMod , only : site_massbal_type + use EDTypesMod , only : numlevsoil_max + use EDTypesMod , only : numWaterMem + use EDTypesMod , only : dl_sf, dinc_ed, area_inv + use FatesLitterMod , only : ncwd + use FatesLitterMod , only : ndcmpy + use FatesLitterMod , only : ilabile + use FatesLitterMod , only : ilignin + use FatesLitterMod , only : icellulose + use EDTypesMod , only : AREA,AREA_INV + use EDTypesMod , only : nlevleaf + use EDTypesMod , only : num_vegtemp_mem + use EDTypesMod , only : maxpft + use EDTypesMod , only : ed_site_type, ed_patch_type, ed_cohort_type + use EDTypesMod , only : leaves_on + use EDTypesMod , only : leaves_off + use EDTypesMod , only : min_n_safemath + use PRTGenericMod , only : num_elements + use PRTGenericMod , only : element_list + use PRTGenericMod , only : element_pos + use EDTypesMod , only : site_fluxdiags_type + use EDTypesMod , only : phen_cstat_nevercold + use EDTypesMod , only : phen_cstat_iscold + use EDTypesMod , only : phen_cstat_notcold + use EDTypesMod , only : phen_dstat_timeoff + use EDTypesMod , only : phen_dstat_moistoff + use EDTypesMod , only : phen_dstat_moiston + use EDTypesMod , only : phen_dstat_timeon + use shr_log_mod , only : errMsg => shr_log_errMsg + use FatesGlobals , only : fates_log + use FatesGlobals , only : endrun => fates_endrun + use EDParamsMod , only : fates_mortality_disturbance_fraction + use EDParamsMod , only : q10_mr + use EDParamsMod , only : q10_froz + use EDParamsMod , only : logging_export_frac + use FatesPlantHydraulicsMod , only : AccumulateMortalityWaterStorage + use FatesConstantsMod , only : itrue,ifalse + use FatesConstantsMod , only : calloc_abs_error + use FatesConstantsMod , only : years_per_day + use FatesAllometryMod , only : h_allom + use FatesAllometryMod , only : h2d_allom + use FatesAllometryMod , only : bagw_allom + use FatesAllometryMod , only : bsap_allom + use FatesAllometryMod , only : bleaf + use FatesAllometryMod , only : bfineroot + use FatesAllometryMod , only : bdead_allom + use FatesAllometryMod , only : bstore_allom + use FatesAllometryMod , only : bbgw_allom + use FatesAllometryMod , only : carea_allom + use FatesAllometryMod , only : CheckIntegratedAllometries + use FatesAllometryMod, only : set_root_fraction + use PRTGenericMod, only : prt_carbon_allom_hyp + use PRTGenericMod, only : prt_cnp_flex_allom_hyp + use PRTGenericMod, only : prt_vartypes + use PRTGenericMod, only : leaf_organ + use PRTGenericMod, only : sapw_organ, struct_organ + use PRTGenericMod, only : all_carbon_elements + use PRTGenericMod, only : carbon12_element + use PRTGenericMod, only : nitrogen_element + use PRTGenericMod, only : phosphorus_element + use PRTGenericMod, only : leaf_organ + use PRTGenericMod, only : fnrt_organ + use PRTGenericMod, only : sapw_organ + use PRTGenericMod, only : store_organ + use PRTGenericMod, only : repro_organ + use PRTGenericMod, only : struct_organ + use PRTGenericMod, only : SetState + use PRTLossFluxesMod, only : PRTPhenologyFlush + use PRTLossFluxesMod, only : PRTDeciduousTurnover + use PRTLossFluxesMod, only : PRTReproRelease + + + + public :: trim_canopy + public :: phenology + public :: recruitment + public :: ZeroLitterFluxes + + public :: ZeroAllocationRates + public :: PreDisturbanceLitterFluxes + public :: PreDisturbanceIntegrateLitter + public :: SeedIn + + logical, parameter :: debug = .false. ! local debug flag + character(len=*), parameter, private :: sourcefile = & + __FILE__ + + integer, parameter :: dleafon_drycheck = 100 ! Drought deciduous leaves max days on check parameter + + + + + ! ============================================================================ + +contains + + subroutine ZeroLitterFluxes( currentSite ) + + ! This routine loops through all patches in a site + ! and zero's the flux terms for the litter pools. + ! This is typically called at the beginning of the dynamics + ! call sequence. + + + ! !ARGUMENTS + type(ed_site_type), intent(inout), target :: currentSite + type(ed_patch_type), pointer :: currentPatch + + integer :: el + + currentPatch => currentSite%youngest_patch + do while(associated(currentPatch)) + do el=1,num_elements + call currentPatch%litter(el)%ZeroFlux() + end do + currentPatch => currentPatch%older + end do + + + return + end subroutine ZeroLitterFluxes + + ! ===================================================================================== + + subroutine ZeroAllocationRates( currentSite ) + + ! !ARGUMENTS + type(ed_site_type), intent(inout), target :: currentSite + type(ed_patch_type), pointer :: currentPatch + type(ed_cohort_type), pointer :: currentCohort + + currentPatch => currentSite%youngest_patch + do while(associated(currentPatch)) + + currentCohort => currentPatch%tallest + do while (associated(currentCohort)) + + ! This sets turnover and growth rates to zero + call currentCohort%prt%ZeroRates() + + currentCohort => currentCohort%shorter + enddo + currentPatch => currentPatch%older + end do + + return + end subroutine ZeroAllocationRates + + + ! ============================================================================ + + subroutine PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in ) + + ! ----------------------------------------------------------------------------------- + ! + ! This subroutine calculates all of the different litter input and output fluxes + ! associated with seed turnover, seed influx, litterfall from live and + ! dead plants, germination, and fragmentation. + ! + ! At this time we do not have explicit herbivory, and burning losses to litter + ! are handled elsewhere. + ! + ! Note: The processes conducted here DO NOT handle litter fluxes associated + ! with disturbance. Those fluxes are handled elsewhere (EDPatchDynamcisMod) + ! because the fluxes are potentially cross patch, and also dealing + ! patch areas that are changing. + ! + ! ----------------------------------------------------------------------------------- + + + ! !ARGUMENTS + type(ed_site_type), intent(inout) :: currentSite + type(ed_patch_type), intent(inout) :: currentPatch + type(bc_in_type), intent(in) :: bc_in + + ! + ! !LOCAL VARIABLES: + type(site_massbal_type), pointer :: site_mass + type(litter_type), pointer :: litt ! Points to the litter object for + ! the different element types + integer :: el ! Litter element loop index + integer :: nlev_eff_decomp ! Number of active layers over which + ! fragmentation fluxes are transfered + !------------------------------------------------------------------------------------ + + ! Calculate the fragmentation rates + call fragmentation_scaler(currentPatch, bc_in) + + + do el = 1, num_elements + + litt => currentPatch%litter(el) + + ! Calculate loss rate of viable seeds to litter + call SeedDecay(litt) + + ! Send those decaying seeds in the previous call + ! to the litter input flux + call SeedDecayToFines(litt) + + ! Calculate seed germination rate, the status flags prevent + ! germination from occuring when the site is in a drought + ! (for drought deciduous) or too cold (for cold deciduous) + call SeedGermination(litt, currentSite%cstatus, currentSite%dstatus) + + ! Send fluxes from newly created litter into the litter pools + ! This litter flux is from non-disturbance inducing mortality, as well + ! as litter fluxes from live trees + call CWDInput(currentSite, currentPatch, litt) + + + ! Only calculate fragmentation flux over layers that are active + ! (RGK-Mar2019) SHOULD WE MAX THIS AT 1? DONT HAVE TO + + nlev_eff_decomp = max(bc_in%max_rooting_depth_index_col, 1) + call CWDOut(litt,currentPatch%fragmentation_scaler,nlev_eff_decomp) + + + site_mass => currentSite%mass_balance(el) + + ! Fragmentation flux to soil decomposition model [kg/site/day] + site_mass%frag_out = site_mass%frag_out + currentPatch%area * & + ( sum(litt%ag_cwd_frag) + sum(litt%bg_cwd_frag) + & + sum(litt%leaf_fines_frag) + sum(litt%root_fines_frag)) + + end do + + + return + end subroutine PreDisturbanceLitterFluxes + + ! ===================================================================================== + + subroutine PreDisturbanceIntegrateLitter(currentPatch) + + ! ----------------------------------------------------------------------------------- + ! + ! This step applies the litter fluxes to the prognostic state variables. + ! This procedure is called in response to fluxes generated from: + ! 1) seed rain, + ! 2) non-disturbance generating turnover + ! 3) litter fall from living plants + ! 4) fragmentation + ! + ! This routine does NOT accomodate the litter fluxes associated with + ! disturbance generation. That will happen after this call. + ! Fluxes associated with FIRE also happen after this step. + ! + ! All states are in units kg/m2 + ! All fluxes are in units kg/m2/day + ! The integration step is 1 day, thus time is implied + ! + ! ----------------------------------------------------------------------------------- + + ! Arguments + type(ed_patch_type),intent(inout),target :: currentPatch + + + ! Locals + type(litter_type), pointer :: litt + integer :: el ! Loop counter for litter element type + integer :: pft ! pft loop counter + integer :: c ! CWD loop counter + integer :: nlevsoil ! number of soil layers + integer :: ilyr ! soil layer loop counter + integer :: dcmpy ! decomposability index + + do el = 1, num_elements + + litt => currentPatch%litter(el) + + ! Update the bank of viable seeds + ! ----------------------------------------------------------------------------------- + + do pft = 1,numpft + litt%seed(pft) = litt%seed(pft) + & + litt%seed_in_local(pft) + & + litt%seed_in_extern(pft) - & + litt%seed_decay(pft) - & + litt%seed_germ_in(pft) + + ! Note that the recruitment scheme will use seed_germ + ! for its construction costs. + litt%seed_germ(pft) = litt%seed_germ(pft) + & + litt%seed_germ_in(pft) - & + litt%seed_germ_decay(pft) + + + enddo + + ! Update the Coarse Woody Debris pools (above and below) + ! ----------------------------------------------------------------------------------- + nlevsoil = size(litt%bg_cwd,dim=2) + do c = 1,ncwd + litt%ag_cwd(c) = litt%ag_cwd(c) + litt%ag_cwd_in(c) - litt%ag_cwd_frag(c) + do ilyr=1,nlevsoil + litt%bg_cwd(c,ilyr) = litt%bg_cwd(c,ilyr) & + + litt%bg_cwd_in(c,ilyr) & + - litt%bg_cwd_frag(c,ilyr) + enddo + end do + + ! Update the fine litter pools from leaves and fine-roots + ! ----------------------------------------------------------------------------------- + + do dcmpy = 1,ndcmpy + + litt%leaf_fines(dcmpy) = litt%leaf_fines(dcmpy) & + + litt%leaf_fines_in(dcmpy) & + - litt%leaf_fines_frag(dcmpy) + do ilyr=1,nlevsoil + litt%root_fines(dcmpy,ilyr) = litt%root_fines(dcmpy,ilyr) & + + litt%root_fines_in(dcmpy,ilyr) & + - litt%root_fines_frag(dcmpy,ilyr) + enddo + + end do + + end do ! litter element loop + + return + end subroutine PreDisturbanceIntegrateLitter + + + + ! ============================================================================ + + subroutine trim_canopy( currentSite ) + ! + ! !DESCRIPTION: + ! Canopy trimming / leaf optimisation. Removes leaves in negative annual carbon balance. + ! + ! !USES: + + ! !ARGUMENTS + type (ed_site_type),intent(inout), target :: currentSite + ! + ! !LOCAL VARIABLES: + type (ed_cohort_type) , pointer :: currentCohort + type (ed_patch_type) , pointer :: currentPatch + + integer :: z ! leaf layer + integer :: ipft ! pft index + logical :: trimmed ! was this layer trimmed in this year? If not expand the canopy. + real(r8) :: tar_bl ! target leaf biomass (leaves flushed, trimmed) + real(r8) :: tar_bfr ! target fine-root biomass (leaves flushed, trimmed) + real(r8) :: bfr_per_bleaf ! ratio of fine root per leaf biomass + real(r8) :: sla_levleaf ! sla at leaf level z + real(r8) :: nscaler_levleaf ! nscaler value at leaf level z + integer :: cl ! canopy layer index + real(r8) :: kn ! nitrogen decay coefficient + real(r8) :: sla_max ! Observational constraint on how large sla (m2/gC) can become + real(r8) :: leaf_c ! leaf carbon [kg] + real(r8) :: sapw_c ! sapwood carbon [kg] + real(r8) :: store_c ! storage carbon [kg] + real(r8) :: struct_c ! structure carbon [kg] + real(r8) :: leaf_inc ! LAI-only portion of the vegetation increment of dinc_ed + real(r8) :: lai_canopy_above ! the LAI in the canopy layers above the layer of interest + real(r8) :: lai_layers_above ! the LAI in the leaf layers, within the current canopy, + ! above the leaf layer of interest + real(r8) :: lai_current ! the LAI in the current leaf layer + real(r8) :: cumulative_lai ! whole canopy cumulative LAI, top down, to the leaf layer of interest + real(r8) :: cumulative_lai_cohort ! cumulative LAI within the current cohort only + + ! Temporary diagnostic ouptut + integer :: ipatch + integer :: icohort + + ! LAPACK linear least squares fit variables + ! The standard equation for a linear fit, y = mx + b, is converted to a linear system, AX=B and has + ! the form: [n sum(x); sum(x) sum(x^2)] * [b; m] = [sum(y); sum(x*y)] where + ! n is the number of leaf layers + ! x is yearly_net_uptake minus the leaf cost aka the net-net uptake + ! y is the cumulative lai for the current cohort + ! b is the y-intercept i.e. the cumulative lai that has zero net-net uptake + ! m is the slope of the linear fit + integer :: nll = 3 ! Number of leaf layers to fit a regression to for calculating the optimum lai + character(1) :: trans = 'N' ! Input matrix is not transposed + + integer, parameter :: m = 2, n = 2 ! Number of rows and columns, respectively, in matrix A + integer, parameter :: nrhs = 1 ! Number of columns in matrix B and X + integer, parameter :: workmax = 100 ! Maximum iterations to minimize work + + integer :: lda = m, ldb = n ! Leading dimension of A and B, respectively + integer :: lwork ! Dimension of work array + integer :: info ! Procedure diagnostic ouput + + real(r8) :: nnu_clai_a(m,n) ! LHS of linear least squares fit, A matrix + real(r8) :: nnu_clai_b(m,nrhs) ! RHS of linear least squares fit, B matrix + real(r8) :: work(workmax) ! work array + + real(r8) :: initial_trim ! Initial trim + real(r8) :: optimum_trim ! Optimum trim value + real(r8) :: initial_laimem ! Initial laimemory + real(r8) :: optimum_laimem ! Optimum laimemory + + !---------------------------------------------------------------------- + + ipatch = 1 ! Start counting patches + + currentPatch => currentSite%youngest_patch + do while(associated(currentPatch)) + + ! Add debug diagnstic output to determine which patch + if (debug) then + write(fates_log(),*) 'Current patch:', ipatch + write(fates_log(),*) 'Current patch cohorts:', currentPatch%countcohorts + endif + + icohort = 1 + + currentCohort => currentPatch%tallest + do while (associated(currentCohort)) + + ! Save off the incoming trim and laimemory + initial_trim = currentCohort%canopy_trim + initial_laimem = currentCohort%laimemory + + ! Add debug diagnstic output to determine which cohort + if (debug) then + write(fates_log(),*) 'Current cohort:', icohort + write(fates_log(),*) 'Starting canopy trim:', initial_trim + write(fates_log(),*) 'Starting laimemory:', currentCohort%laimemory + endif + + trimmed = .false. + ipft = currentCohort%pft + call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread,currentCohort%pft,currentCohort%c_area) + + leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) + + currentCohort%treelai = tree_lai(leaf_c, currentCohort%pft, currentCohort%c_area, & + currentCohort%n, currentCohort%canopy_layer, & + currentPatch%canopy_layer_tlai,currentCohort%vcmax25top ) + + currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_trim, & + currentCohort%c_area, currentCohort%n, currentCohort%canopy_layer, & + currentPatch%canopy_layer_tlai, currentCohort%treelai, & + currentCohort%vcmax25top,0 ) + + currentCohort%nv = ceiling((currentCohort%treelai+currentCohort%treesai)/dinc_ed) + + if (currentCohort%nv > nlevleaf)then + write(fates_log(),*) 'nv > nlevleaf',currentCohort%nv, & + currentCohort%treelai,currentCohort%treesai, & + currentCohort%c_area,currentCohort%n,leaf_c + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + + call bleaf(currentcohort%dbh,ipft,currentcohort%canopy_trim,tar_bl) + + if ( int(prt_params%allom_fmode(ipft)) .eq. 1 ) then + ! only query fine root biomass if using a fine root allometric model that takes leaf trim into account + call bfineroot(currentcohort%dbh,ipft,currentcohort%canopy_trim,tar_bfr) + bfr_per_bleaf = tar_bfr/tar_bl + endif + + ! Identify current canopy layer (cl) + cl = currentCohort%canopy_layer + + ! PFT-level maximum SLA value, even if under a thick canopy (same units as slatop) + sla_max = prt_params%slamax(ipft) + + ! Initialize nnu_clai_a + nnu_clai_a(:,:) = 0._r8 + nnu_clai_b(:,:) = 0._r8 + + !Leaf cost vs netuptake for each leaf layer. + do z = 1, currentCohort%nv + + ! Calculate the cumulative total vegetation area index (no snow occlusion, stems and leaves) + + leaf_inc = dinc_ed * & + currentCohort%treelai/(currentCohort%treelai+currentCohort%treesai) + + ! Now calculate the cumulative top-down lai of the current layer's midpoint within the current cohort + lai_layers_above = leaf_inc * (z-1) + lai_current = min(leaf_inc, currentCohort%treelai - lai_layers_above) + cumulative_lai_cohort = lai_layers_above + 0.5*lai_current + + ! Now add in the lai above the current cohort for calculating the sla leaf level + lai_canopy_above = sum(currentPatch%canopy_layer_tlai(1:cl-1)) + cumulative_lai = lai_canopy_above + cumulative_lai_cohort + + ! There was activity this year in this leaf layer. This should only occur for bottom most leaf layer + if (currentCohort%year_net_uptake(z) /= 999._r8)then + + ! Calculate sla_levleaf following the sla profile with overlying leaf area + ! Scale for leaf nitrogen profile + kn = decay_coeff_kn(ipft,currentCohort%vcmax25top) + ! Nscaler value at leaf level z + nscaler_levleaf = exp(-kn * cumulative_lai) + ! Sla value at leaf level z after nitrogen profile scaling (m2/gC) + sla_levleaf = prt_params%slatop(ipft)/nscaler_levleaf + + if(sla_levleaf > sla_max)then + sla_levleaf = sla_max + end if + + !Leaf Cost kgC/m2/year-1 + !decidous costs. + if (prt_params%season_decid(ipft) == itrue .or. & + prt_params%stress_decid(ipft) == itrue )then + + ! Leaf cost at leaf level z accounting for sla profile (kgC/m2) + currentCohort%leaf_cost = 1._r8/(sla_levleaf*1000.0_r8) + + if ( int(prt_params%allom_fmode(ipft)) .eq. 1 ) then + ! if using trimmed leaf for fine root biomass allometry, add the cost of the root increment + ! to the leaf increment; otherwise do not. + currentCohort%leaf_cost = currentCohort%leaf_cost + & + 1.0_r8/(sla_levleaf*1000.0_r8) * & + bfr_per_bleaf / prt_params%root_long(ipft) + endif + + currentCohort%leaf_cost = currentCohort%leaf_cost * & + (prt_params%grperc(ipft) + 1._r8) + else !evergreen costs + + ! Leaf cost at leaf level z accounting for sla profile + currentCohort%leaf_cost = 1.0_r8/(sla_levleaf* & + sum(prt_params%leaf_long(ipft,:))*1000.0_r8) !convert from sla in m2g-1 to m2kg-1 + + + if ( int(prt_params%allom_fmode(ipft)) .eq. 1 ) then + ! if using trimmed leaf for fine root biomass allometry, add the cost of the root increment + ! to the leaf increment; otherwise do not. + currentCohort%leaf_cost = currentCohort%leaf_cost + & + 1.0_r8/(sla_levleaf*1000.0_r8) * & + bfr_per_bleaf / prt_params%root_long(ipft) + endif + currentCohort%leaf_cost = currentCohort%leaf_cost * & + (prt_params%grperc(ipft) + 1._r8) + endif + + ! Construct the arrays for a least square fit of the net_net_uptake versus the cumulative lai + ! if at least nll leaf layers are present in the current cohort and only for the bottom nll + ! leaf layers. + if (currentCohort%nv > nll .and. currentCohort%nv - z < nll) then + + ! Build the A matrix for the LHS of the linear system. A = [n sum(x); sum(x) sum(x^2)] + ! where n = nll and x = yearly_net_uptake-leafcost + nnu_clai_a(1,1) = nnu_clai_a(1,1) + 1 ! Increment for each layer used + nnu_clai_a(1,2) = nnu_clai_a(1,2) + currentCohort%year_net_uptake(z) - currentCohort%leaf_cost + nnu_clai_a(2,1) = nnu_clai_a(1,2) + nnu_clai_a(2,2) = nnu_clai_a(2,2) + (currentCohort%year_net_uptake(z) - currentCohort%leaf_cost)**2 + + ! Build the B matrix for the RHS of the linear system. B = [sum(y); sum(x*y)] + ! where x = yearly_net_uptake-leafcost and y = cumulative_lai_cohort + nnu_clai_b(1,1) = nnu_clai_b(1,1) + cumulative_lai_cohort + nnu_clai_b(2,1) = nnu_clai_b(2,1) + (cumulative_lai_cohort * & + (currentCohort%year_net_uptake(z) - currentCohort%leaf_cost)) + end if + + ! Check leaf cost against the yearly net uptake for that cohort leaf layer + if (currentCohort%year_net_uptake(z) < currentCohort%leaf_cost) then + ! Make sure the cohort trim fraction is great than the pft trim limit + if (currentCohort%canopy_trim > EDPftvarcon_inst%trim_limit(ipft)) then + + ! if ( debug ) then + ! write(fates_log(),*) 'trimming leaves', & + ! currentCohort%canopy_trim,currentCohort%leaf_cost + ! endif + + ! keep trimming until none of the canopy is in negative carbon balance. + if (currentCohort%hite > EDPftvarcon_inst%hgt_min(ipft)) then + currentCohort%canopy_trim = currentCohort%canopy_trim - & + EDPftvarcon_inst%trim_inc(ipft) + if (prt_params%evergreen(ipft) /= 1)then + currentCohort%laimemory = currentCohort%laimemory * & + (1.0_r8 - EDPftvarcon_inst%trim_inc(ipft)) + endif + + trimmed = .true. + + endif ! hite check + endif ! trim limit check + endif ! net uptake check + endif ! leaf activity check + enddo ! z, leaf layer loop + + ! Compute the optimal cumulative lai based on the cohort net-net uptake profile if at least 2 leaf layers + if (nnu_clai_a(1,1) > 1) then + + ! Compute the optimum size of the work array + lwork = -1 ! Ask sgels to compute optimal number of entries for work + call dgels(trans, m, n, nrhs, nnu_clai_a, lda, nnu_clai_b, ldb, work, lwork, info) + lwork = int(work(1)) ! Pick the optimum. TBD, can work(1) come back with greater than work size? + + ! if (debug) then + ! write(fates_log(),*) 'LLSF lwork output (info, lwork):', info, lwork + ! endif + + ! Compute the minimum of 2-norm of of the least squares fit to solve for X + ! Note that dgels returns the solution by overwriting the nnu_clai_b array. + ! The result has the form: X = [b; m] + ! where b = y-intercept (i.e. the cohort lai that has zero yearly net-net uptake) + ! and m is the slope of the linear fit + call dgels(trans, m, n, nrhs, nnu_clai_a, lda, nnu_clai_b, ldb, work, lwork, info) + + if (info < 0) then + write(fates_log(),*) 'LLSF optimium LAI calculation returned illegal value' + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + + if (debug) then + write(fates_log(),*) 'LLSF optimium LAI (intercept,slope):', nnu_clai_b + write(fates_log(),*) 'LLSF optimium LAI:', nnu_clai_b(1,1) + write(fates_log(),*) 'LLSF optimium LAI info:', info + write(fates_log(),*) 'LAI fraction (optimum_lai/cumulative_lai):', nnu_clai_b(1,1) / cumulative_lai_cohort + endif + + ! Calculate the optimum trim based on the initial canopy trim value + if (cumulative_lai_cohort > 0._r8) then ! Sometime cumulative_lai comes in at 0.0? + + ! + optimum_trim = (nnu_clai_b(1,1) / cumulative_lai_cohort) * initial_trim + optimum_laimem = (nnu_clai_b(1,1) / cumulative_lai_cohort) * initial_laimem + + ! Determine if the optimum trim value makes sense. The smallest cohorts tend to have unrealistic fits. + if (optimum_trim > 0. .and. optimum_trim < 1.) then + currentCohort%canopy_trim = optimum_trim + + ! If the cohort pft is not evergreen we reduce the laimemory as well + if (prt_params%evergreen(ipft) /= 1) then + currentCohort%laimemory = optimum_laimem + endif + + trimmed = .true. + + endif + endif + endif + + ! Reset activity for the cohort for the start of the next year + currentCohort%year_net_uptake(:) = 999.0_r8 + + ! Add to trim fraction if cohort not trimmed at all + if ( (.not.trimmed) .and.currentCohort%canopy_trim < 1.0_r8)then + currentCohort%canopy_trim = currentCohort%canopy_trim + EDPftvarcon_inst%trim_inc(ipft) + endif + + if ( debug ) then + write(fates_log(),*) 'trimming:',currentCohort%canopy_trim + endif + + ! currentCohort%canopy_trim = 1.0_r8 !FIX(RF,032414) this turns off ctrim for now. + currentCohort => currentCohort%shorter + icohort = icohort + 1 + enddo + currentPatch => currentPatch%older + ipatch = ipatch + 1 + enddo + + end subroutine trim_canopy + + ! ============================================================================ + subroutine phenology( currentSite, bc_in ) + ! + ! !DESCRIPTION: + ! Phenology. + ! + ! !USES: + use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm + use EDParamsMod, only : ED_val_phen_drought_threshold, ED_val_phen_doff_time + use EDParamsMod, only : ED_val_phen_a, ED_val_phen_b, ED_val_phen_c, ED_val_phen_chiltemp + use EDParamsMod, only : ED_val_phen_mindayson, ED_val_phen_ncolddayslim, ED_val_phen_coldtemp + + + ! + ! !ARGUMENTS: + type(ed_site_type), intent(inout), target :: currentSite + type(bc_in_type), intent(in) :: bc_in + + ! + ! !LOCAL VARIABLES: + + type(ed_patch_type),pointer :: cpatch + integer :: model_day_int ! integer model day 1 - inf + integer :: ncolddays ! no days underneath the threshold for leaf drop + integer :: i_wmem ! Loop counter for water mem days + integer :: i_tmem ! Loop counter for veg temp mem days + integer :: dayssincedleafon ! Days since drought-decid leaf-on started + integer :: dayssincedleafoff ! Days since drought-decid leaf-off started + integer :: dayssincecleafon ! Days since cold-decid leaf-on started + integer :: dayssincecleafoff ! Days since cold-decid leaf-off started + real(r8) :: mean_10day_liqvol ! mean liquid volume (m3/m3) over last 10 days + real(r8) :: leaf_c ! leaf carbon [kg] + real(r8) :: fnrt_c ! fineroot carbon [kg] + real(r8) :: sapw_c ! sapwood carbon [kg] + real(r8) :: store_c ! storage carbon [kg] + real(r8) :: struct_c ! structure carbon [kg] + real(r8) :: gdd_threshold ! GDD accumulation function, + integer :: ilayer_swater ! Layer index for soil water + ! which also depends on chilling days. + integer :: ncdstart ! beginning of counting period for chilling degree days. + integer :: gddstart ! beginning of counting period for growing degree days. + real(r8) :: temp_in_C ! daily averaged temperature in celcius + + integer, parameter :: canopy_leaf_lifespan = 365 ! Maximum lifespan of drought decid leaves + + integer, parameter :: min_daysoff_dforcedflush = 30 ! THis is the number of days that must had elapsed + ! since leaves had dropped, in order to forcably + ! flush leaves again. This does not impact flushing + ! due to real moisture constraints, and will prevent + ! drought deciduous in perennially wet environments + ! that have been forced to drop their leaves, from + ! flushing them back immediately. + + real(r8),parameter :: dphen_soil_depth = 0.1 ! Use liquid soil water that is + ! closest to this depth [m] + + ! This is the integer model day. The first day of the simulation is 1, and it + ! continues monotonically, indefinitely + model_day_int = nint(hlm_model_day) + + + ! Use the following layer index to calculate drought conditions + ilayer_swater = minloc(abs(bc_in%z_sisl(:)-dphen_soil_depth),dim=1) + + + ! Parameter of drought decid leaf loss in mm in top layer...FIX(RF,032414) + ! - this is arbitrary and poorly understood. Needs work. ED_ + !Parameters: defaults from Botta et al. 2000 GCB,6 709-725 + !Parameters, default from from SDGVM model of senesence + + temp_in_C = 0._r8 + cpatch => CurrentSite%oldest_patch + do while(associated(cpatch)) + temp_in_C = temp_in_C + bc_in%t_veg24_pa(cpatch%patchno)*cpatch%area + cpatch => cpatch%younger + end do + temp_in_C = temp_in_C * area_inv - tfrz + + + !-----------------Cold Phenology--------------------! + + !Zero growing degree and chilling day counters + if (currentSite%lat > 0)then + ncdstart = 270 !Northern Hemisphere begining November + gddstart = 1 !Northern Hemisphere begining January + else + ncdstart = 120 !Southern Hemisphere beginning May + gddstart = 181 !Northern Hemisphere begining July + endif + + ! Count the number of chilling days over a seasonal window. + ! For comparing against GDD, we start calculating chilling + ! in the late autumn. + ! This value is used to determine the GDD exceedance threshold + if (hlm_day_of_year == ncdstart)then + currentSite%nchilldays = 0 + endif + + !Accumulate growing/chilling days after start of counting period + if (temp_in_C < ED_val_phen_chiltemp)then + currentSite%nchilldays = currentSite%nchilldays + 1 + endif + + !GDD accumulation function, which also depends on chilling days. + ! -68 + 638 * (-0.001 * ncd) + gdd_threshold = ED_val_phen_a + ED_val_phen_b*exp(ED_val_phen_c*real(currentSite%nchilldays,r8)) + + !Accumulate temperature of last 10 days. + currentSite%vegtemp_memory(2:num_vegtemp_mem) = currentSite%vegtemp_memory(1:num_vegtemp_mem-1) + currentSite%vegtemp_memory(1) = temp_in_C + + !count number of days for leaves off + ncolddays = 0 + do i_tmem = 1,num_vegtemp_mem + if (currentSite%vegtemp_memory(i_tmem) < ED_val_phen_coldtemp)then + ncolddays = ncolddays + 1 + endif + enddo + + ! Here is where we do the GDD accumulation calculation + ! + ! reset GDD on set dates + if (hlm_day_of_year == gddstart)then + currentSite%grow_deg_days = 0._r8 + endif + ! + ! accumulate the GDD using daily mean temperatures + ! Don't accumulate GDD during the growing season (that wouldn't make sense) + if (temp_in_C .gt. 0._r8 .and. currentSite%cstatus == phen_cstat_iscold) then + currentSite%grow_deg_days = currentSite%grow_deg_days + temp_in_C + endif + + !this logic is to prevent GDD accumulating after the leaves have fallen and before the + ! beginnning of the accumulation period, to prevend erroneous autumn leaf flushing. + if(model_day_int>365)then !only do this after the first year to prevent odd behaviour + + if(currentSite%lat .gt. 0.0_r8)then !Northern Hemisphere + ! In the north, don't accumulate when we are past the leaf fall date. + ! Accumulation starts on day 1 of year in NH. + ! The 180 is to prevent going into an 'always off' state after initialization + if( model_day_int .gt. currentSite%cleafoffdate.and.hlm_day_of_year.gt.180)then ! + currentSite%grow_deg_days = 0._r8 + endif + else !Southern Hemisphere + ! In the South, don't accumulate after the leaf off date, and before the start of + ! the accumulation phase (day 181). + if(model_day_int .gt. currentSite%cleafoffdate.and.hlm_day_of_year.lt.gddstart) then! + currentSite%grow_deg_days = 0._r8 + endif + endif + endif !year1 + + ! Calculate the number of days since the leaves last came on + ! and off. If this is the beginning of the simulation, that day might + ! not had occured yet, so set it to last year to get things rolling + + if (model_day_int < currentSite%cleafoffdate) then + dayssincecleafoff = model_day_int - (currentSite%cleafoffdate - 365) + else + dayssincecleafoff = model_day_int - currentSite%cleafoffdate + end if + + if (model_day_int < currentSite%cleafondate) then + dayssincecleafon = model_day_int - (currentSite%cleafondate-365) + else + dayssincecleafon = model_day_int - currentSite%cleafondate + end if + + + + !LEAF ON: COLD DECIDUOUS. Needs to + !1) have exceeded the growing degree day threshold + !2) The leaves should not be on already + !3) There should have been at least one chilling day in the counting period. + ! this prevents tropical or warm climate plants that are "cold-deciduous" + ! from ever re-flushing after they have reached their maximum age (thus + ! preventing them from competing + + if ( (currentSite%cstatus == phen_cstat_iscold .or. & + currentSite%cstatus == phen_cstat_nevercold) .and. & + (currentSite%grow_deg_days > gdd_threshold) .and. & + (dayssincecleafoff > ED_val_phen_mindayson) .and. & + (currentSite%nchilldays >= 1)) then + currentSite%cstatus = phen_cstat_notcold ! Set to not-cold status (leaves can come on) + currentSite%cleafondate = model_day_int + dayssincecleafon = 0 + currentSite%grow_deg_days = 0._r8 ! zero GDD for the rest of the year until counting season begins. + if ( debug ) write(fates_log(),*) 'leaves on' + endif !GDD + + + + + !LEAF OFF: COLD THRESHOLD + !Needs to: + !1) have exceeded the number of cold days threshold + !2) have exceeded the minimum leafon time. + !3) The leaves should not be off already + !4) The day of simulation should be larger than the counting period. + + + if ( (currentSite%cstatus == phen_cstat_notcold) .and. & + (model_day_int > num_vegtemp_mem) .and. & + (ncolddays > ED_val_phen_ncolddayslim) .and. & + (dayssincecleafon > ED_val_phen_mindayson) )then + + currentSite%grow_deg_days = 0._r8 ! The equations for Botta et al + ! are for calculations of + ! first flush, but if we dont + ! clear this value, it will cause + ! leaves to flush later in the year + currentSite%cstatus = phen_cstat_iscold ! alter status of site to 'leaves off' + currentSite%cleafoffdate = model_day_int ! record leaf off date + + if ( debug ) write(fates_log(),*) 'leaves off' + endif + + ! LEAF OFF: COLD LIFESPAN THRESHOLD + ! NOTE: Some areas of the planet will never generate a cold day + ! and thus %nchilldays will never go from zero to 1. The following logic + ! when coupled with this fact will essentially prevent cold-deciduous + ! plants from re-emerging in areas without at least some cold days + + if( (currentSite%cstatus == phen_cstat_notcold) .and. & + (dayssincecleafoff > 400)) then ! remove leaves after a whole year + ! when there is no 'off' period. + currentSite%grow_deg_days = 0._r8 + + currentSite%cstatus = phen_cstat_nevercold ! alter status of site to imply that this + ! site is never really cold enough + ! for cold deciduous + currentSite%cleafoffdate = model_day_int ! record leaf off date + + if ( debug ) write(fates_log(),*) 'leaves off' + endif + + !-----------------Drought Phenology--------------------! + ! Principles of drought-deciduos phenology model... + ! The 'is_drought' flag is false when leaves are on, and true when leaves area off. + ! The following sets those site-level flags, which are acted on in phenology_deciduos. + ! A* The leaves live for either the length of time the soil moisture is over the threshold + ! or the lifetime of the leaves, whichever is shorter. + ! B*: If the soil is only wet for a very short time, then the leaves stay on for 100 days + ! C*: The leaves are only permitted to come ON for a 60 day window around when they last came on, + ! to prevent 'flickering' on in response to wet season storms + ! D*: We don't allow anything to happen in the first ten days to allow the water memory window + ! to come into equlibirium. + ! E*: If the soil is always wet, the leaves come on at the beginning of the window, and then + ! last for their lifespan. + ! ISSUES + ! 1. It's not clear what water content we should track. Here we are tracking the top layer, + ! but we probably should track something like BTRAN, but BTRAN is defined for each PFT, + ! and there could potentially be more than one stress-dec PFT.... ? + ! 2. In the beginning, the window is set at an arbitrary time of the year, so the leaves + ! might come on in the dry season, using up stored reserves + ! for the stress-dec plants, and potentially killing them. To get around this, + ! we need to read in the 'leaf on' date from some kind of start-up file + ! but we would need that to happen for every resolution, etc. + ! 3. Will this methodology properly kill off the stress-dec trees where there is no + ! water stress? What about where the wet period coincides with the warm period? + ! We would just get them overlapping with the cold-dec trees, even though that isn't appropriate + ! Why don't the drought deciduous trees grow in the North? + ! Is cold decidousness maybe even the same as drought deciduosness there (and so does this + ! distinction actually matter??).... + + ! Accumulate surface water memory of last 10 days. + ! Liquid volume in ground layer (m3/m3) + do i_wmem = 1,numWaterMem-1 !shift memory along one + currentSite%water_memory(numWaterMem+1-i_wmem) = currentSite%water_memory(numWaterMem-i_wmem) + enddo + currentSite%water_memory(1) = bc_in%h2o_liqvol_sl(ilayer_swater) + + ! Calculate the mean water content over the last 10 days (m3/m3) + mean_10day_liqvol = sum(currentSite%water_memory(1:numWaterMem))/real(numWaterMem,r8) + + ! In drought phenology, we often need to force the leaves to stay + ! on or off as moisture fluctuates... + + ! Calculate days since leaves have come off, but make a provision + ! for the first year of simulation, we have to assume a leaf drop + ! date to start, so if that is in the future, set it to last year + + if (model_day_int < currentSite%dleafoffdate) then + dayssincedleafoff = model_day_int - (currentSite%dleafoffdate-365) + else + dayssincedleafoff = model_day_int - currentSite%dleafoffdate + endif + + ! the leaves are on. How long have they been on? + if (model_day_int < currentSite%dleafondate) then + dayssincedleafon = model_day_int - (currentSite%dleafondate-365) + else + dayssincedleafon = model_day_int - currentSite%dleafondate + endif + + ! LEAF ON: DROUGHT DECIDUOUS WETNESS + ! Here, we used a window of oppurtunity to determine if we are + ! close to the time when then leaves came on last year + + ! Has it been ... + ! a) a year, plus or minus 1 month since we last had leaf-on? + ! b) Has there also been at least a nominaly short amount of "leaf-off" + ! c) is the model day at least > 10 (let soil water spin-up) + ! Note that cold-starts begin in the "leaf-on" + ! status + if ( (currentSite%dstatus == phen_dstat_timeoff .or. & + currentSite%dstatus == phen_dstat_moistoff) .and. & + (model_day_int > numWaterMem) .and. & + (dayssincedleafon >= 365-30 .and. dayssincedleafon <= 365+30 ) .and. & + (dayssincedleafoff > ED_val_phen_doff_time) ) then + + ! If leaves are off, and have been off for at least a few days + ! and the time is consistent with the correct + ! time window... test if the moisture conditions allow for leaf-on + + if ( mean_10day_liqvol >= ED_val_phen_drought_threshold ) then + currentSite%dstatus = phen_dstat_moiston ! set status to leaf-on + currentSite%dleafondate = model_day_int ! save the model day we start flushing + dayssincedleafon = 0 + endif + endif + + ! LEAF ON: DROUGHT DECIDUOUS TIME EXCEEDANCE + ! If we still haven't done budburst by end of window, then force it + + ! If the status is "phen_dstat_moistoff", it means this site currently has + ! leaves off due to actual moisture limitations. + ! So we trigger bud-burst at the end of the month since + ! last year's bud-burst. If this is imposed, then we set the new + ! status to indicate bud-burst was forced by timing + + if( currentSite%dstatus == phen_dstat_moistoff ) then + if ( dayssincedleafon > 365+30 ) then + currentSite%dstatus = phen_dstat_timeon ! force budburst! + currentSite%dleafondate = model_day_int ! record leaf on date + dayssincedleafon = 0 + end if + end if + + ! But if leaves are off due to time, then we enforce + ! a longer cool-down (because this is a perrenially wet system) + + if(currentSite%dstatus == phen_dstat_timeoff ) then + if (dayssincedleafoff > min_daysoff_dforcedflush) then + currentSite%dstatus = phen_dstat_timeon ! force budburst! + currentSite%dleafondate = model_day_int ! record leaf on date + dayssincedleafon = 0 + end if + end if + + ! LEAF OFF: DROUGHT DECIDUOUS LIFESPAN - if the leaf gets to + ! the end of its useful life. A*, E* + ! i.e. Are the leaves rouhgly at the end of their lives? + + if ( (currentSite%dstatus == phen_dstat_moiston .or. & + currentSite%dstatus == phen_dstat_timeon ) .and. & + (dayssincedleafon > canopy_leaf_lifespan) )then + currentSite%dstatus = phen_dstat_timeoff !alter status of site to 'leaves off' + currentSite%dleafoffdate = model_day_int !record leaf on date + endif + + ! LEAF OFF: DROUGHT DECIDUOUS DRYNESS - if the soil gets too dry, + ! and the leaves have already been on a while... + + if ( (currentSite%dstatus == phen_dstat_moiston .or. & + currentSite%dstatus == phen_dstat_timeon ) .and. & + (model_day_int > numWaterMem) .and. & + (mean_10day_liqvol <= ED_val_phen_drought_threshold) .and. & + (dayssincedleafon > dleafon_drycheck ) ) then + currentSite%dstatus = phen_dstat_moistoff ! alter status of site to 'leaves off' + currentSite%dleafoffdate = model_day_int ! record leaf on date + endif + + call phenology_leafonoff(currentSite) + + end subroutine phenology + + ! ============================================================================ + subroutine phenology_leafonoff(currentSite) + ! + ! !DESCRIPTION: + ! Controls the leaf on and off economics + ! + ! !USES: + ! + ! !ARGUMENTS: + type(ed_site_type), intent(inout), target :: currentSite + ! + ! !LOCAL VARIABLES: + type(ed_patch_type) , pointer :: currentPatch + type(ed_cohort_type), pointer :: currentCohort + + real(r8) :: leaf_c ! leaf carbon [kg] + real(r8) :: sapw_c ! sapwood carbon [kg] + real(r8) :: struct_c ! structural wood carbon [kg] + real(r8) :: store_c ! storage carbon [kg] + real(r8) :: store_c_transfer_frac ! Fraction of storage carbon used to flush leaves + real(r8) :: totalmemory ! total memory of carbon [kg] + integer :: ipft + real(r8), parameter :: leaf_drop_fraction = 1.0_r8 + real(r8), parameter :: carbon_store_buffer = 0.10_r8 + real(r8) :: stem_drop_fraction + !------------------------------------------------------------------------ + + currentPatch => CurrentSite%oldest_patch + + do while(associated(currentPatch)) + currentCohort => currentPatch%tallest + do while(associated(currentCohort)) + + ipft = currentCohort%pft + + ! Retrieve existing leaf and storage carbon + + if(debug) call currentCohort%prt%CheckMassConservation(ipft,0) + + store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) + leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) + sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) + struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) + + stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(ipft) + + ! COLD LEAF ON + ! The site level flags signify that it is no-longer too cold + ! for leaves. Time to signal flushing + + if (prt_params%season_decid(ipft) == itrue)then + if ( currentSite%cstatus == phen_cstat_notcold )then ! we have just moved to leaves being on . + if (currentCohort%status_coh == leaves_off)then ! Are the leaves currently off? + currentCohort%status_coh = leaves_on ! Leaves are on, so change status to + ! stop flow of carbon out of bstore. + + if(store_c>nearzero) then + ! flush either the amount required from the laimemory, or -most- of the storage pool + ! RF: added a criterion to stop the entire store pool emptying and triggering termination mortality + ! n.b. this might not be necessary if we adopted a more gradual approach to leaf flushing... + store_c_transfer_frac = min((EDPftvarcon_inst%phenflush_fraction(ipft)* & + currentCohort%laimemory)/store_c,(1.0_r8-carbon_store_buffer)) + + if(prt_params%woody(ipft).ne.itrue)then + totalmemory=currentCohort%laimemory+currentCohort%sapwmemory+currentCohort%structmemory + store_c_transfer_frac = min((EDPftvarcon_inst%phenflush_fraction(ipft)* & + totalmemory)/store_c, (1.0_r8-carbon_store_buffer)) + endif + + else + store_c_transfer_frac = 0.0_r8 + end if + + ! This call will request that storage carbon will be transferred to + ! leaf tissues. It is specified as a fraction of the available storage + if(prt_params%woody(ipft) == itrue) then + + call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, store_c_transfer_frac) + currentCohort%laimemory = 0.0_r8 + + else + + ! Check that the stem drop fraction is set to non-zero amount otherwise flush all carbon store to leaves + if (stem_drop_fraction .gt. 0.0_r8) then + + call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & + store_c_transfer_frac*currentCohort%laimemory/totalmemory) + + call PRTPhenologyFlush(currentCohort%prt, ipft, sapw_organ, & + store_c_transfer_frac*currentCohort%sapwmemory/totalmemory) + + call PRTPhenologyFlush(currentCohort%prt, ipft, struct_organ, & + store_c_transfer_frac*currentCohort%structmemory/totalmemory) + + else + + call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & + store_c_transfer_frac) + + end if + + currentCohort%laimemory = 0.0_r8 + currentCohort%structmemory = 0.0_r8 + currentCohort%sapwmemory = 0.0_r8 + + endif + endif !pft phenology + endif ! growing season + + !COLD LEAF OFF + if (currentSite%cstatus == phen_cstat_nevercold .or. & + currentSite%cstatus == phen_cstat_iscold) then ! past leaf drop day? Leaves still on tree? + + if (currentCohort%status_coh == leaves_on) then ! leaves have not dropped + + ! leaf off occur on individuals bigger than specific size for grass + if (currentCohort%dbh > EDPftvarcon_inst%phen_cold_size_threshold(ipft) & + .or. prt_params%woody(ipft)==itrue) then + + ! This sets the cohort to the "leaves off" flag + currentCohort%status_coh = leaves_off + + ! Remember what the lai was (leaf mass actually) was for next year + ! the same amount back on in the spring... + + currentCohort%laimemory = leaf_c + + ! Drop Leaves (this routine will update the leaf state variables, + ! for carbon and any other element that are prognostic. It will + ! also track the turnover masses that will be sent to litter later on) + + call PRTDeciduousTurnover(currentCohort%prt,ipft, & + leaf_organ, leaf_drop_fraction) + + if(prt_params%woody(ipft).ne.itrue)then + + currentCohort%sapwmemory = sapw_c * stem_drop_fraction + + currentCohort%structmemory = struct_c * stem_drop_fraction + + call PRTDeciduousTurnover(currentCohort%prt,ipft, & + sapw_organ, stem_drop_fraction) + + call PRTDeciduousTurnover(currentCohort%prt,ipft, & + struct_organ, stem_drop_fraction) + + endif ! woody plant check + endif ! individual dbh size check + endif !leaf status + endif !currentSite status + endif !season_decid + + ! DROUGHT LEAF ON + ! Site level flag indicates it is no longer in drought condition + ! deciduous plants can flush + + if (prt_params%stress_decid(ipft) == itrue )then + + if (currentSite%dstatus == phen_dstat_moiston .or. & + currentSite%dstatus == phen_dstat_timeon )then + + ! we have just moved to leaves being on . + if (currentCohort%status_coh == leaves_off)then + + !is it the leaf-on day? Are the leaves currently off? + + currentCohort%status_coh = leaves_on ! Leaves are on, so change status to + ! stop flow of carbon out of bstore. + + if(store_c>nearzero) then + + store_c_transfer_frac = & + min((EDPftvarcon_inst%phenflush_fraction(ipft)*currentCohort%laimemory)/store_c, & + (1.0_r8-carbon_store_buffer)) + + if(prt_params%woody(ipft).ne.itrue)then + + totalmemory=currentCohort%laimemory+currentCohort%sapwmemory+currentCohort%structmemory + store_c_transfer_frac = min(EDPftvarcon_inst%phenflush_fraction(ipft)*totalmemory/store_c, & + (1.0_r8-carbon_store_buffer)) + + endif + + else + store_c_transfer_frac = 0.0_r8 + endif + + ! This call will request that storage carbon will be transferred to + ! leaf tissues. It is specified as a fraction of the available storage + if(prt_params%woody(ipft) == itrue) then + + call PRTPhenologyFlush(currentCohort%prt, ipft, & + leaf_organ, store_c_transfer_frac) + + currentCohort%laimemory = 0.0_r8 + + else + + ! Check that the stem drop fraction is set to non-zero amount otherwise flush all carbon store to leaves + if (stem_drop_fraction .gt. 0.0_r8) then + + call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & + store_c_transfer_frac*currentCohort%laimemory/totalmemory) + + call PRTPhenologyFlush(currentCohort%prt, ipft, sapw_organ, & + store_c_transfer_frac*currentCohort%sapwmemory/totalmemory) + + call PRTPhenologyFlush(currentCohort%prt, ipft, struct_organ, & + store_c_transfer_frac*currentCohort%structmemory/totalmemory) + + else + + call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & + store_c_transfer_frac) + + end if + + currentCohort%laimemory = 0.0_r8 + currentCohort%structmemory = 0.0_r8 + currentCohort%sapwmemory = 0.0_r8 + + endif ! woody plant check + endif !currentCohort status again? + endif !currentSite status + + !DROUGHT LEAF OFF + if (currentSite%dstatus == phen_dstat_moistoff .or. & + currentSite%dstatus == phen_dstat_timeoff) then + + if (currentCohort%status_coh == leaves_on) then ! leaves have not dropped + + ! This sets the cohort to the "leaves off" flag + currentCohort%status_coh = leaves_off + + ! Remember what the lai (leaf mass actually) was for next year + currentCohort%laimemory = leaf_c + + call PRTDeciduousTurnover(currentCohort%prt,ipft, & + leaf_organ, leaf_drop_fraction) + + if(prt_params%woody(ipft).ne.itrue)then + + currentCohort%sapwmemory = sapw_c * stem_drop_fraction + currentCohort%structmemory = struct_c * stem_drop_fraction + + call PRTDeciduousTurnover(currentCohort%prt,ipft, & + sapw_organ, stem_drop_fraction) + + call PRTDeciduousTurnover(currentCohort%prt,ipft, & + struct_organ, stem_drop_fraction) + endif + + endif + endif !status + endif !drought dec. + + if(debug) call currentCohort%prt%CheckMassConservation(ipft,1) + + currentCohort => currentCohort%shorter + enddo !currentCohort + + currentPatch => currentPatch%younger + + enddo !currentPatch + + end subroutine phenology_leafonoff + + + ! ===================================================================================== + + subroutine SeedIn( currentSite, bc_in ) + + ! ----------------------------------------------------------------------------------- + ! Flux from plants into the seed pool. + ! It is assumed that allocation to seed on living pools has already been calculated + ! at the daily time step. + ! Note: Some seed generation can occur during disturbance. It is assumed that + ! some plants use their storage upon death to create seeds, but this in only + ! triggered during non-fire and non-logging events. See + ! subroutine mortality_litter_fluxes() and DistributeSeeds(), look for + ! parameter allom_frbstor_repro + ! ----------------------------------------------------------------------------------- + + + ! !USES: + use EDTypesMod, only : area + use EDTypesMod, only : homogenize_seed_pfts + !use FatesInterfaceTypesMod, only : hlm_use_fixed_biogeog ! For future reduced complexity? + ! + ! !ARGUMENTS + type(ed_site_type), intent(inout), target :: currentSite + type(bc_in_type), intent(in) :: bc_in + + type(ed_patch_type), pointer :: currentPatch + type(litter_type), pointer :: litt + type(ed_cohort_type), pointer :: currentCohort + type(site_massbal_type), pointer :: site_mass + + integer :: pft + real(r8) :: store_m_to_repro ! mass sent from storage to reproduction upon death [kg/plant] + real(r8) :: site_seed_rain(maxpft) ! This is the sum of seed-rain for the site [kg/site/day] + real(r8) :: seed_in_external ! Mass of externally generated seeds [kg/m2/day] + real(r8) :: seed_stoich ! Mass ratio of nutrient per C12 in seeds [kg/kg] + real(r8) :: seed_prod ! Seed produced in this dynamics step [kg/day] + integer :: n_litt_types ! number of litter element types (c,n,p, etc) + integer :: el ! loop counter for litter element types + integer :: element_id ! element id consistent with parteh/PRTGenericMod.F90 + + + !YL--------- + real(r8) :: site_seed_out(maxpft) ! The sum of seed-rain leaving the site [kg/site/day] + real(r8) :: disp_frac(maxpft) ! fraction of seed-rain among the site_seed_rain that's leaving the site [unitless] + real(r8) :: seed_in_supply ! + !----------- + + do el = 1, num_elements + + site_seed_rain(:) = 0._r8 + + !YL------- + site_seed_out(:) = 0._r8 ! seed-rain leaving the site, 05/21 + disp_frac(:) = 0.4 ! to be specified in the parameter file or calculated using dispersal kernel + !--------- + + element_id = element_list(el) + + site_mass => currentSite%mass_balance(el) + + ! Loop over all patches and sum up the seed input for each PFT + currentPatch => currentSite%oldest_patch + do while (associated(currentPatch)) + + currentCohort => currentPatch%tallest + do while (associated(currentCohort)) + + pft = currentCohort%pft + + ! a certain fraction of bstore might go to clonal reproduction when plants die + ! (since this is only applied to the dying portion of the cohort + ! we do not actually pair down the storage via PARTEH, instead + ! we just make sure that we don't send a portion of the storage + ! to the litter in CWDInput) + ! units = [kg/ha/day] = [kg] * [fraction] * [plants/ha/year] * [year/day] + store_m_to_repro = -currentCohort%prt%GetState(store_organ,element_id) * & + EDPftvarcon_inst%allom_frbstor_repro(pft)*currentCohort%dndt*years_per_day + + ! Transfer all reproductive tissues into seed production + ! The following call to PRTReproRelease, will return the mass + ! of seeds [kg] released by the plant, per the mass_fraction + ! specified as input. This routine will also remove the mass + ! from the parteh state-variable. + + call PRTReproRelease(currentCohort%prt,repro_organ,element_id, & + 1.0_r8, seed_prod) + + if(element_id==carbon12_element)then + currentcohort%seed_prod = seed_prod + end if + + !YL---------- + + !site_seed_rain(pft) = site_seed_rain(pft) + & + ! (seed_prod * currentCohort%n + store_m_to_repro) + + site_seed_rain(pft) = site_seed_rain(pft) + & + (seed_prod * currentCohort%n + store_m_to_repro)*(1-disp_frac(pft)) + site_seed_out(pft) = site_seed_out(pft) + & + (seed_prod * currentCohort%n + store_m_to_repro)*disp_frac(pft) + + write(fates_log(),*) 'pft, site_seed_rain(pft), site_seed_out(pft):', pft, site_seed_rain(pft), site_seed_out(pft) + print *, pft, site_seed_rain(pft), site_seed_out(pft) + + !----------- + + currentCohort => currentCohort%shorter + enddo !cohort loop + + currentPatch => currentPatch%younger + enddo + + ! We can choose to homogenize seeds. This is simple, we just + ! add up all the seed from each pft at the site level, and then + ! equally distribute to the PFT pools + if ( homogenize_seed_pfts ) then + site_seed_rain(1:numpft) = sum(site_seed_rain(:))/real(numpft,r8) + end if + + + ! Loop over all patches again and disperse the mixed seeds into the input flux + ! arrays + + ! Loop over all patches and sum up the seed input for each PFT + currentPatch => currentSite%oldest_patch + do while (associated(currentPatch)) + + litt => currentPatch%litter(el) + do pft = 1,numpft + + if(currentSite%use_this_pft(pft).eq.itrue)then + ! Seed input from local sources (within site) + litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)/area + + ! If there is forced external seed rain, we calculate the input mass flux + ! from the different elements, usung the seed optimal stoichiometry + ! for non-carbon + select case(element_id) + case(carbon12_element) + seed_stoich = 1._r8 + case(nitrogen_element) + seed_stoich = prt_params%nitr_stoich_p2(pft,repro_organ) + case(phosphorus_element) + seed_stoich = prt_params%phos_stoich_p2(pft,repro_organ) + case default + write(fates_log(), *) 'undefined element specified' + write(fates_log(), *) 'while defining forced external seed mass flux' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select + + ! Seed input from external sources (user param seed rain, or dispersal model) + seed_in_external = seed_stoich*EDPftvarcon_inst%seed_suppl(pft)*years_per_day + litt%seed_in_extern(pft) = litt%seed_in_extern(pft) + seed_in_external + + ! Seeds entering externally [kg/site/day] + site_mass%seed_in = site_mass%seed_in + seed_in_external*currentPatch%area + + !YL------- + site_mass%seed_out = site_mass%seed_out + site_seed_out(pft) + !---------- + + end if !use this pft + enddo + + + currentPatch => currentPatch%younger + enddo + + end do + + return + end subroutine SeedIn + + ! ============================================================================ + + subroutine SeedDecay( litt ) + ! + ! !DESCRIPTION: + ! Flux from seed pool into leaf litter pool + ! + ! !ARGUMENTS + type(litter_type) :: litt + ! + ! !LOCAL VARIABLES: + integer :: pft + !---------------------------------------------------------------------- + + ! default value from Liscke and Loffler 2006 ; making this a PFT-specific parameter + ! decays the seed pool according to exponential model + ! seed_decay_rate is in yr-1 + ! seed_decay is kg/day + ! Assume that decay rates are same for all chemical species + + do pft = 1,numpft + litt%seed_decay(pft) = litt%seed(pft) * & + EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day + + litt%seed_germ_decay(pft) = litt%seed_germ(pft) * & + EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day + + enddo + + return + end subroutine SeedDecay + + ! ============================================================================ + subroutine SeedGermination( litt, cold_stat, drought_stat ) + ! + ! !DESCRIPTION: + ! Flux from seed pool into sapling pool + ! + ! !USES: + + ! + ! !ARGUMENTS + type(litter_type) :: litt + integer, intent(in) :: cold_stat ! Is the site in cold leaf-off status? + integer, intent(in) :: drought_stat ! Is the site in drought leaf-off status? + ! + ! !LOCAL VARIABLES: + integer :: pft + + + real(r8), parameter :: max_germination = 1.0_r8 ! Cap on germination rates. + ! KgC/m2/yr Lishcke et al. 2009 + + ! Turning of this cap? because the cap will impose changes on proportionality + ! of nutrients. (RGK 02-2019) + !real(r8), parameter :: max_germination = 1.e6_r8 ! Force to very high number + + !---------------------------------------------------------------------- + + ! germination_rate is being pulled to PFT parameter; units are 1/yr + ! thus the mortality rate of seed -> recruit (in units of carbon) + ! is seed_decay_rate(p)/germination_rate(p) + ! and thus the mortality rate (in units of individuals) is the product of + ! that times the ratio of (hypothetical) seed mass to recruit biomass + + do pft = 1,numpft + litt%seed_germ_in(pft) = min(litt%seed(pft) * EDPftvarcon_inst%germination_rate(pft), & + max_germination)*years_per_day + + !set the germination only under the growing season...c.xu + + if ((prt_params%season_decid(pft) == itrue ) .and. & + (any(cold_stat == [phen_cstat_nevercold,phen_cstat_iscold]))) then + + ! no germination for all PFTs when cold. YL 03/22/2018 +! if (any(cold_stat == [phen_cstat_nevercold,phen_cstat_iscold])) then + litt%seed_germ_in(pft) = 0.0_r8 + endif + if ((prt_params%stress_decid(pft) == itrue ) .and. & + (any(drought_stat == [phen_dstat_timeoff,phen_dstat_moistoff]))) then + litt%seed_germ_in(pft) = 0.0_r8 + end if + + + enddo + + end subroutine SeedGermination + + ! ===================================================================================== + + + + + + ! ===================================================================================== + + subroutine recruitment( currentSite, currentPatch, bc_in ) + ! + ! !DESCRIPTION: + ! spawn new cohorts of juveniles of each PFT + ! + ! !USES: + use FatesInterfaceTypesMod, only : hlm_use_ed_prescribed_phys + ! + ! !ARGUMENTS + type(ed_site_type), intent(inout), target :: currentSite + type(ed_patch_type), intent(inout), pointer :: currentPatch + type(bc_in_type), intent(in) :: bc_in + ! + ! !LOCAL VARIABLES: + class(prt_vartypes), pointer :: prt + integer :: ft + type (ed_cohort_type) , pointer :: temp_cohort + type (litter_type), pointer :: litt ! The litter object (carbon right now) + type(site_massbal_type), pointer :: site_mass ! For accounting total in-out mass fluxes + integer :: cohortstatus + integer :: el ! loop counter for element + integer :: element_id ! element index consistent with definitions in PRTGenericMod + integer :: iage ! age loop counter for leaf age bins + integer,parameter :: recruitstatus = 1 !weather it the new created cohorts is recruited or initialized + real(r8) :: c_leaf ! target leaf biomass [kgC] + real(r8) :: c_fnrt ! target fine root biomass [kgC] + real(r8) :: c_sapw ! target sapwood biomass [kgC] + real(r8) :: a_sapw ! target sapwood cross section are [m2] (dummy) + real(r8) :: c_agw ! target Above ground biomass [kgC] + real(r8) :: c_bgw ! target Below ground biomass [kgC] + real(r8) :: c_struct ! target Structural biomass [kgc] + real(r8) :: c_store ! target Storage biomass [kgC] + real(r8) :: m_leaf ! leaf mass (element agnostic) [kg] + real(r8) :: m_fnrt ! fine-root mass (element agnostic) [kg] + real(r8) :: m_sapw ! sapwood mass (element agnostic) [kg] + real(r8) :: m_agw ! AG wood mass (element agnostic) [kg] + real(r8) :: m_bgw ! BG wood mass (element agnostic) [kg] + real(r8) :: m_struct ! structural mass (element agnostic) [kg] + real(r8) :: m_store ! storage mass (element agnostic) [kg] + real(r8) :: m_repro ! reproductive mass (element agnostic) [kg] + real(r8) :: mass_avail ! The mass of each nutrient/carbon available in the seed_germination pool [kg] + real(r8) :: mass_demand ! Total mass demanded by the plant to achieve the stoichiometric targets + ! of all the organs in the recruits. Used for both [kg per plant] and [kg per cohort] + real(r8) :: stem_drop_fraction + + !---------------------------------------------------------------------- + + allocate(temp_cohort) ! create temporary cohort + call zero_cohort(temp_cohort) + + + do ft = 1,numpft + if(currentSite%use_this_pft(ft).eq.itrue)then + temp_cohort%canopy_trim = 0.8_r8 !starting with the canopy not fully expanded + temp_cohort%pft = ft + temp_cohort%hite = EDPftvarcon_inst%hgt_min(ft) + temp_cohort%coage = 0.0_r8 + stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(ft) + + call h2d_allom(temp_cohort%hite,ft,temp_cohort%dbh) + + ! Initialize live pools + call bleaf(temp_cohort%dbh,ft,temp_cohort%canopy_trim,c_leaf) + call bfineroot(temp_cohort%dbh,ft,temp_cohort%canopy_trim,c_fnrt) + call bsap_allom(temp_cohort%dbh,ft,temp_cohort%canopy_trim,a_sapw, c_sapw) + call bagw_allom(temp_cohort%dbh,ft,c_agw) + call bbgw_allom(temp_cohort%dbh,ft,c_bgw) + call bdead_allom(c_agw,c_bgw,c_sapw,ft,c_struct) + call bstore_allom(temp_cohort%dbh,ft,temp_cohort%canopy_trim,c_store) + + ! Default assumption is that leaves are on + cohortstatus = leaves_on + temp_cohort%laimemory = 0.0_r8 + temp_cohort%sapwmemory = 0.0_r8 + temp_cohort%structmemory = 0.0_r8 + + + ! But if the plant is seasonally (cold) deciduous, and the site status is flagged + ! as "cold", then set the cohort's status to leaves_off, and remember the leaf biomass + if ((prt_params%season_decid(ft) == itrue) .and. & + (any(currentSite%cstatus == [phen_cstat_nevercold,phen_cstat_iscold]))) then + temp_cohort%laimemory = c_leaf + c_leaf = 0.0_r8 + + ! If plant is not woody then set sapwood and structural biomass as well + if (prt_params%woody(ft).ne.itrue) then + temp_cohort%sapwmemory = c_sapw * stem_drop_fraction + temp_cohort%structmemory = c_struct * stem_drop_fraction + c_sapw = (1.0_r8 - stem_drop_fraction) * c_sapw + c_struct = (1.0_r8 - stem_drop_fraction) * c_struct + endif + cohortstatus = leaves_off + endif + + ! Or.. if the plant is drought deciduous, and the site status is flagged as + ! "in a drought", then likewise, set the cohort's status to leaves_off, and remember leaf + ! biomass + if ((prt_params%stress_decid(ft) == itrue) .and. & + (any(currentSite%dstatus == [phen_dstat_timeoff,phen_dstat_moistoff]))) then + temp_cohort%laimemory = c_leaf + c_leaf = 0.0_r8 + + ! If plant is not woody then set sapwood and structural biomass as well + if(prt_params%woody(ft).ne.itrue)then + temp_cohort%sapwmemory = c_sapw * stem_drop_fraction + temp_cohort%structmemory = c_struct * stem_drop_fraction + c_sapw = (1.0_r8 - stem_drop_fraction) * c_sapw + c_struct = (1.0_r8 - stem_drop_fraction) * c_struct + endif + cohortstatus = leaves_off + endif + + + ! Cycle through available carbon and nutrients, find the limiting element + ! to dictate the total number of plants that can be generated + + if ( (hlm_use_ed_prescribed_phys .eq. ifalse) .or. & + (EDPftvarcon_inst%prescribed_recruitment(ft) .lt. 0._r8) ) then + + temp_cohort%n = 1.e10_r8 + + do el = 1,num_elements + + element_id = element_list(el) + select case(element_id) + case(carbon12_element) + + mass_demand = (c_struct+c_leaf+c_fnrt+c_sapw+c_store) + + case(nitrogen_element) + + mass_demand = c_struct*prt_params%nitr_stoich_p1(ft,struct_organ) + & + c_leaf*prt_params%nitr_stoich_p1(ft,leaf_organ) + & + c_fnrt*prt_params%nitr_stoich_p1(ft,fnrt_organ) + & + c_sapw*prt_params%nitr_stoich_p1(ft,sapw_organ) + & + c_store*prt_params%nitr_stoich_p1(ft,store_organ) + + case(phosphorus_element) + + mass_demand = c_struct*prt_params%phos_stoich_p1(ft,struct_organ) + & + c_leaf*prt_params%phos_stoich_p1(ft,leaf_organ) + & + c_fnrt*prt_params%phos_stoich_p1(ft,fnrt_organ) + & + c_sapw*prt_params%phos_stoich_p1(ft,sapw_organ) + & + c_store*prt_params%phos_stoich_p1(ft,store_organ) + + case default + write(fates_log(),*) 'Undefined element type in recruitment' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select + + mass_avail = currentPatch%area * currentPatch%litter(el)%seed_germ(ft) + + ! ------------------------------------------------------------------------ + ! Update number density if this is the limiting mass + ! ------------------------------------------------------------------------ + + temp_cohort%n = min(temp_cohort%n, mass_avail/mass_demand) + + end do + + + else + ! prescribed recruitment rates. number per sq. meter per year + temp_cohort%n = currentPatch%area * & + EDPftvarcon_inst%prescribed_recruitment(ft) * & + hlm_freq_day + endif + + ! Only bother allocating a new cohort if there is a reasonable amount of it + if (temp_cohort%n > min_n_safemath )then + + ! ----------------------------------------------------------------------------- + ! PART II. + ! Initialize the PARTEH object, and determine the initial masses of all + ! organs and elements. + ! ----------------------------------------------------------------------------- + prt => null() + call InitPRTObject(prt) + + do el = 1,num_elements + + element_id = element_list(el) + + ! If this is carbon12, then the initialization is straight forward + ! otherwise, we use stoichiometric ratios + select case(element_id) + case(carbon12_element) + + m_struct = c_struct + m_leaf = c_leaf + m_fnrt = c_fnrt + m_sapw = c_sapw + m_store = c_store + m_repro = 0._r8 + + case(nitrogen_element) + + m_struct = c_struct*prt_params%nitr_stoich_p1(ft,struct_organ) + m_leaf = c_leaf*prt_params%nitr_stoich_p1(ft,leaf_organ) + m_fnrt = c_fnrt*prt_params%nitr_stoich_p1(ft,fnrt_organ) + m_sapw = c_sapw*prt_params%nitr_stoich_p1(ft,sapw_organ) + m_store = c_store*prt_params%nitr_stoich_p1(ft,store_organ) + m_repro = 0._r8 + + case(phosphorus_element) + + m_struct = c_struct*prt_params%phos_stoich_p1(ft,struct_organ) + m_leaf = c_leaf*prt_params%phos_stoich_p1(ft,leaf_organ) + m_fnrt = c_fnrt*prt_params%phos_stoich_p1(ft,fnrt_organ) + m_sapw = c_sapw*prt_params%phos_stoich_p1(ft,sapw_organ) + m_store = c_store*prt_params%phos_stoich_p1(ft,store_organ) + m_repro = 0._r8 + + end select + + select case(hlm_parteh_mode) + case (prt_carbon_allom_hyp,prt_cnp_flex_allom_hyp ) + + ! Put all of the leaf mass into the first bin + call SetState(prt,leaf_organ, element_id,m_leaf,1) + do iage = 2,nleafage + call SetState(prt,leaf_organ, element_id,0._r8,iage) + end do + + call SetState(prt,fnrt_organ, element_id, m_fnrt) + call SetState(prt,sapw_organ, element_id, m_sapw) + call SetState(prt,store_organ, element_id, m_store) + call SetState(prt,struct_organ, element_id, m_struct) + call SetState(prt,repro_organ, element_id, m_repro) + + case default + write(fates_log(),*) 'Unspecified PARTEH module during create_cohort' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select + + site_mass => currentSite%mass_balance(el) + + ! Remove mass from the germination pool. However, if we are use prescribed physiology, + ! AND the forced recruitment model, then we are not realling using the prognostic + ! seed_germination model, so we have to short circuit things. We send all of the + ! seed germination mass to an outflux pool, and use an arbitrary generic input flux + ! to balance out the new recruits. + + if ( (hlm_use_ed_prescribed_phys .eq. itrue ) .and. & + (EDPftvarcon_inst%prescribed_recruitment(ft) .ge. 0._r8 )) then + + site_mass%flux_generic_in = site_mass%flux_generic_in + & + temp_cohort%n*(m_struct + m_leaf + m_fnrt + m_sapw + m_store + m_repro) + + site_mass%flux_generic_out = site_mass%flux_generic_out + & + currentPatch%area * currentPatch%litter(el)%seed_germ(ft) + + currentPatch%litter(el)%seed_germ(ft) = 0._r8 + + + else + + currentPatch%litter(el)%seed_germ(ft) = currentPatch%litter(el)%seed_germ(ft) - & + temp_cohort%n / currentPatch%area * & + (m_struct + m_leaf + m_fnrt + m_sapw + m_store + m_repro) + + end if + + + + end do + + ! This call cycles through the initial conditions, and makes sure that they + ! are all initialized. + ! ----------------------------------------------------------------------------------- + + call prt%CheckInitialConditions() + + ! This initializes the cohort + call create_cohort(currentSite,currentPatch, temp_cohort%pft, temp_cohort%n, & + temp_cohort%hite, temp_cohort%coage, temp_cohort%dbh, prt, & + temp_cohort%laimemory, temp_cohort%sapwmemory, temp_cohort%structmemory, & + cohortstatus, recruitstatus, & + temp_cohort%canopy_trim, currentPatch%NCL_p, currentSite%spread, bc_in) + + ! Note that if hydraulics is on, the number of cohorts may had + ! changed due to hydraulic constraints. + ! This constaint is applied during "create_cohort" subroutine. + + ! keep track of how many individuals were recruited for passing to history + currentSite%recruitment_rate(ft) = currentSite%recruitment_rate(ft) + temp_cohort%n + + + endif + endif !use_this_pft + enddo !pft loop + + deallocate(temp_cohort) ! delete temporary cohort + + end subroutine recruitment + + ! ============================================================================ + + subroutine CWDInput( currentSite, currentPatch, litt) + + ! + ! !DESCRIPTION: + ! Generate litter fields from turnover. + ! Note, that the when this is called, the number density of the plants + ! has not been reduced from non-mortal turnover yet. + ! Thus, we need to avoid double counting losses from dying trees + ! and turnover in dying trees. + ! + ! !USES: + use SFParamsMod , only : SF_val_CWD_frac + + ! + ! !ARGUMENTS + type(ed_site_type), intent(inout), target :: currentSite + type(ed_patch_type),intent(inout), target :: currentPatch + type(litter_type),intent(inout),target :: litt + + + ! + ! !LOCAL VARIABLES: + type(ed_cohort_type), pointer :: currentCohort + type(site_fluxdiags_type), pointer :: flux_diags + type(site_massbal_type), pointer :: site_mass + integer :: c + real(r8) :: dead_n ! total understorey dead tree density + real(r8) :: dead_n_dlogging ! direct logging understory dead-tree density + real(r8) :: dead_n_ilogging ! indirect understory dead-tree density (logging) + real(r8) :: dead_n_natural ! understory dead density not associated + ! with direct logging + real(r8) :: leaf_m ! mass of the element of interest in the + ! leaf [kg] + real(r8) :: fnrt_m ! fine-root [kg] + real(r8) :: sapw_m ! sapwood [kg] + real(r8) :: struct_m ! structural [kg] + real(r8) :: store_m ! storage [kg] + real(r8) :: repro_m ! reproductive [kg] + real(r8) :: leaf_m_turnover ! leaf turnover [kg] + real(r8) :: fnrt_m_turnover + real(r8) :: sapw_m_turnover + real(r8) :: struct_m_turnover + real(r8) :: store_m_turnover + real(r8) :: repro_m_turnover + real(r8) :: dcmpy_frac ! Fraction of mass sent to decomposability pool + real(r8) :: plant_dens ! Number of plants per m2 + real(r8) :: bg_cwd_tot ! Total below-ground coarse woody debris + ! input flux + real(r8) :: root_fines_tot ! Total below-ground fine root coarse + ! woody debris + integer :: element_id ! element id consistent with parteh/PRTGenericMod.F90 + + real(r8) :: trunk_wood ! carbon flux into trunk products kgC/day/site + integer :: ilyr + integer :: pft + integer :: dcmpy ! decomposability pool index + integer :: numlevsoil ! Actual number of soil layers + !---------------------------------------------------------------------- + + ! ----------------------------------------------------------------------------------- + ! Other direct litter fluxes happen in phenology and in spawn_patches. + ! ----------------------------------------------------------------------------------- + + numlevsoil = currentSite%nlevsoil + + element_id = litt%element_id + + ! Object tracking flux diagnostics for each element + flux_diags => currentSite%flux_diags(element_pos(element_id)) + + ! Object tracking site level mass balance for each element + site_mass => currentSite%mass_balance(element_pos(element_id)) + + currentCohort => currentPatch%shortest + do while(associated(currentCohort)) + pft = currentCohort%pft + + call set_root_fraction(currentSite%rootfrac_scr, pft, currentSite%zi_soil) + + leaf_m_turnover = currentCohort%prt%GetTurnover(leaf_organ,element_id) + store_m_turnover = currentCohort%prt%GetTurnover(store_organ,element_id) + fnrt_m_turnover = currentCohort%prt%GetTurnover(fnrt_organ,element_id) + sapw_m_turnover = currentCohort%prt%GetTurnover(sapw_organ,element_id) + struct_m_turnover = currentCohort%prt%GetTurnover(struct_organ,element_id) + repro_m_turnover = currentCohort%prt%GetTurnover(repro_organ,element_id) + + leaf_m = currentCohort%prt%GetState(leaf_organ,element_id) + store_m = currentCohort%prt%GetState(store_organ,element_id) + fnrt_m = currentCohort%prt%GetState(fnrt_organ,element_id) + sapw_m = currentCohort%prt%GetState(sapw_organ,element_id) + struct_m = currentCohort%prt%GetState(struct_organ,element_id) + repro_m = currentCohort%prt%GetState(repro_organ,element_id) + + plant_dens = currentCohort%n/currentPatch%area + + ! --------------------------------------------------------------------------------- + ! PART 1 Litter fluxes from non-mortal tissue turnovers Kg/m2/day + ! Important note: Turnover has already been removed from the cohorts. + ! So, in the next part of this algorithm, when we send the biomass + ! from dying trees to the litter pools, we don't have to worry + ! about double counting. + ! --------------------------------------------------------------------------------- + + flux_diags%leaf_litter_input(pft) = & + flux_diags%leaf_litter_input(pft) + & + leaf_m_turnover * currentCohort%n + + root_fines_tot = (fnrt_m_turnover + store_m_turnover ) * & + plant_dens + + 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 + + dcmpy_frac = GetDecompyFrac(pft,fnrt_organ,dcmpy) + do ilyr = 1, numlevsoil + litt%root_fines_in(dcmpy,ilyr) = litt%root_fines_in(dcmpy,ilyr) + & + currentSite%rootfrac_scr(ilyr) * root_fines_tot * dcmpy_frac + end do + end do + + flux_diags%root_litter_input(pft) = & + flux_diags%root_litter_input(pft) + & + (fnrt_m_turnover + store_m_turnover ) * currentCohort%n + + + ! Assumption: turnover from deadwood and sapwood are lumped together in CWD pool + + do c = 1,ncwd + litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + & + (sapw_m_turnover + struct_m_turnover) * & + SF_val_CWD_frac(c) * plant_dens * & + prt_params%allom_agb_frac(pft) + + flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & + (struct_m_turnover + sapw_m_turnover) * SF_val_CWD_frac(c) * & + prt_params%allom_agb_frac(pft) * currentCohort%n + + bg_cwd_tot = (sapw_m_turnover + struct_m_turnover) * & + SF_val_CWD_frac(c) * plant_dens * & + (1.0_r8-prt_params%allom_agb_frac(pft)) + + do ilyr = 1, numlevsoil + litt%bg_cwd_in(c,ilyr) = litt%bg_cwd_in(c,ilyr) + & + bg_cwd_tot * currentSite%rootfrac_scr(ilyr) + end do + + flux_diags%cwd_bg_input(c) = flux_diags%cwd_bg_input(c) + & + bg_cwd_tot*currentPatch%area + + enddo + + + ! --------------------------------------------------------------------------------- + ! PART 2 Litter fluxes from non-disturbance inducing mortality. Kg/m2/day + ! --------------------------------------------------------------------------------- + + ! Total number of dead (n/m2/day) + dead_n = -1.0_r8 * currentCohort%dndt/currentPatch%area*years_per_day + + if(currentCohort%canopy_layer > 1)then + + ! Total number of dead understory from direct logging + ! (it is possible that large harvestable trees are in the understory) + dead_n_dlogging = currentCohort%lmort_direct * & + currentCohort%n/currentPatch%area + + ! Total number of dead understory from indirect logging + dead_n_ilogging = (currentCohort%lmort_collateral + currentCohort%lmort_infra) * & + currentCohort%n/currentPatch%area + + else + + ! All mortality from logging in the canopy is + ! is disturbance generating + + dead_n_dlogging = 0._r8 + dead_n_ilogging = 0._r8 + + end if + + dead_n_natural = dead_n - dead_n_dlogging - dead_n_ilogging + + + flux_diags%leaf_litter_input(pft) = & + flux_diags%leaf_litter_input(pft) + & + leaf_m * dead_n*currentPatch%area + + + ! %n has not been updated due to mortality yet, thus + ! the litter flux has already been counted since it captured + ! the losses of live trees and those flagged for death + + root_fines_tot = dead_n * (fnrt_m + & + store_m*(1._r8-EDPftvarcon_inst%allom_frbstor_repro(pft)) ) + + do dcmpy=1,ndcmpy + + dcmpy_frac = GetDecompyFrac(pft,leaf_organ,dcmpy) + litt%leaf_fines_in(dcmpy) = litt%leaf_fines_in(dcmpy) + & + (leaf_m+repro_m) * dead_n * dcmpy_frac + + dcmpy_frac = GetDecompyFrac(pft,fnrt_organ,dcmpy) + do ilyr = 1, numlevsoil + litt%root_fines_in(dcmpy,ilyr) = litt%root_fines_in(dcmpy,ilyr) + & + root_fines_tot * currentSite%rootfrac_scr(ilyr) * dcmpy_frac + end do + end do + + flux_diags%root_litter_input(pft) = & + flux_diags%root_litter_input(pft) + & + root_fines_tot*currentPatch%area + + ! Track CWD inputs from dead plants + + do c = 1,ncwd + + ! Below-ground + + bg_cwd_tot = (struct_m + sapw_m) * & + SF_val_CWD_frac(c) * dead_n * & + (1.0_r8-prt_params%allom_agb_frac(pft)) + + do ilyr = 1, numlevsoil + litt%bg_cwd_in(c,ilyr) = litt%bg_cwd_in(c,ilyr) + & + currentSite%rootfrac_scr(ilyr) * bg_cwd_tot + end do + + flux_diags%cwd_bg_input(c) = flux_diags%cwd_bg_input(c) + & + bg_cwd_tot * currentPatch%area + + ! Send AGB component of boles from logging activities into the litter. + ! This includes fluxes from indirect modes of death, as well as the + ! non-exported boles due to direct harvesting. + + if (c==ncwd) then + + + trunk_wood = (struct_m + sapw_m) * & + SF_val_CWD_frac(c) * dead_n_dlogging * & + prt_params%allom_agb_frac(pft) + + site_mass%wood_product = site_mass%wood_product + & + trunk_wood * currentPatch%area * logging_export_frac + + ! Add AG wood to litter from the non-exported fraction of wood + ! from direct anthro sources + + litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + & + trunk_wood * (1._r8-logging_export_frac) + + flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & + trunk_wood * (1._r8-logging_export_frac) * currentPatch%area + + ! Add AG wood to litter from indirect anthro sources + + litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + (struct_m + sapw_m) * & + SF_val_CWD_frac(c) * (dead_n_natural+dead_n_ilogging) * & + prt_params%allom_agb_frac(pft) + + flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & + SF_val_CWD_frac(c) * (dead_n_natural+dead_n_ilogging) * & + currentPatch%area * prt_params%allom_agb_frac(pft) + + else + + litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + (struct_m + sapw_m) * & + SF_val_CWD_frac(c) * dead_n * & + prt_params%allom_agb_frac(pft) + + flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & + SF_val_CWD_frac(c) * dead_n * (struct_m + sapw_m) * & + currentPatch%area * prt_params%allom_agb_frac(pft) + + end if + + end do + + + ! Update diagnostics that track resource management + + if( element_id .eq. carbon12_element ) then + + currentSite%resources_management%delta_litter_stock = & + currentSite%resources_management%delta_litter_stock + & + (leaf_m + fnrt_m + store_m ) * & + (dead_n_ilogging+dead_n_dlogging) * currentPatch%area + + currentSite%resources_management%delta_biomass_stock = & + currentSite%resources_management%delta_biomass_stock + & + (leaf_m + fnrt_m + store_m ) * & + (dead_n_ilogging+dead_n_dlogging) *currentPatch%area + + currentSite%resources_management%trunk_product_site = & + currentSite%resources_management%trunk_product_site + & + trunk_wood * logging_export_frac * currentPatch%area + + do c = 1,ncwd + currentSite%resources_management%delta_litter_stock = & + currentSite%resources_management%delta_litter_stock + & + (struct_m + sapw_m) * & + SF_val_CWD_frac(c) * (dead_n_natural+dead_n_ilogging) * & + currentPatch%area + + currentSite%resources_management%delta_biomass_stock = & + currentSite%resources_management%delta_biomass_stock + & + (struct_m + sapw_m) * & + SF_val_CWD_frac(c) * dead_n * currentPatch%area + end do + + ! Update diagnostics that track resource management + currentSite%resources_management%delta_individual = & + currentSite%resources_management%delta_individual + & + (dead_n_dlogging+dead_n_ilogging) * hlm_freq_day * currentPatch%area + end if + + + currentCohort => currentCohort%taller + enddo ! end loop over cohorts + + + return + end subroutine CWDInput + + ! ===================================================================================== + + subroutine SeedDecayToFines(litt) + + type(litter_type) :: litt + ! + ! !LOCAL VARIABLES: + integer :: pft + + ! Add decaying seeds to the leaf litter + ! ----------------------------------------------------------------------------------- + + do pft = 1,numpft + + litt%leaf_fines_in(ilabile) = litt%leaf_fines_in(ilabile) + & + (litt%seed_decay(pft) + litt%seed_germ_decay(pft)) * EDPftvarcon_inst%lf_flab(pft) + + litt%leaf_fines_in(icellulose) = litt%leaf_fines_in(icellulose) + & + (litt%seed_decay(pft) + litt%seed_germ_decay(pft)) * EDPftvarcon_inst%lf_fcel(pft) + + litt%leaf_fines_in(ilignin) = litt%leaf_fines_in(ilignin) + & + (litt%seed_decay(pft) + litt%seed_germ_decay(pft)) * EDPftvarcon_inst%lf_flig(pft) + + enddo + + + return + end subroutine SeedDecayToFines + + + + + + ! ===================================================================================== + + subroutine fragmentation_scaler( currentPatch, bc_in) + ! + ! !DESCRIPTION: + ! Simple CWD fragmentation Model + ! FIX(SPM, 091914) this should be a function as it returns a value in + ! currentPatch%fragmentation_scaler + ! + ! !USES: + + use FatesSynchronizedParamsMod , only : FatesSynchronizedParamsInst + use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm + use FatesConstantsMod, only : pi => pi_const + ! + ! !ARGUMENTS + type(ed_patch_type), intent(inout) :: currentPatch + type(bc_in_type), intent(in) :: bc_in + + ! + ! !LOCAL VARIABLES: + logical :: use_century_tfunc = .false. + logical :: use_hlm_soil_scalar = .true. ! Use hlm input decomp fraction scalars + integer :: j + integer :: ifp ! Index of a FATES Patch "ifp" + real(r8) :: t_scalar ! temperature scalar + real(r8) :: w_scalar ! moisture scalar + real(r8) :: catanf ! hyperbolic temperature function from CENTURY + real(r8) :: catanf_30 ! hyperbolic temperature function from CENTURY + real(r8) :: t1 ! temperature argument + !---------------------------------------------------------------------- + + catanf(t1) = 11.75_r8 +(29.7_r8 / pi) * atan( pi * 0.031_r8 * ( t1 - 15.4_r8 )) + catanf_30 = catanf(30._r8) + + ifp = currentPatch%patchno + + ! Use the hlm temp and moisture decomp fractions by default + if ( use_hlm_soil_scalar ) then + + ! Calculate the fragmentation_scaler + currentPatch%fragmentation_scaler = min(1.0_r8,max(0.0_r8,bc_in%t_scalar_sisl * bc_in%w_scalar_sisl)) + + else + + if ( .not. use_century_tfunc ) then + !calculate rate constant scalar for soil temperature,assuming that the base rate constants + !are assigned for non-moisture limiting conditions at 25C. + if (bc_in%t_veg24_pa(ifp) >= tfrz) then + t_scalar = q10_mr**((bc_in%t_veg24_pa(ifp)-(tfrz+25._r8))/10._r8) + ! Q10**((t_soisno(c,j)-(tfrz+25._r8))/10._r8) + else + t_scalar = (q10_mr**(-25._r8/10._r8))*(q10_froz**((bc_in%t_veg24_pa(ifp)-tfrz)/10._r8)) + !Q10**(-25._r8/10._r8))*(froz_q10**((t_soisno(c,j)-tfrz)/10._r8) + endif + else + ! original century uses an arctangent function to calculate the + ! temperature dependence of decomposition + t_scalar = max(catanf(bc_in%t_veg24_pa(ifp)-tfrz)/catanf_30,0.01_r8) + endif + + !Moisture Limitations + !BTRAN APPROACH - is quite simple, but max's out decomp at all unstressed + !soil moisture values, which is not realistic. + !litter decomp is proportional to water limitation on average... + w_scalar = sum(currentPatch%btran_ft(1:numpft))/real(numpft,r8) + + ! Calculate the fragmentation_scaler + currentPatch%fragmentation_scaler(:) = min(1.0_r8,max(0.0_r8,t_scalar * w_scalar)) + + endif + + + end subroutine fragmentation_scaler + + ! ============================================================================ + + subroutine CWDOut( litt, fragmentation_scaler, nlev_eff_decomp ) + ! + ! !DESCRIPTION: + ! Simple CWD fragmentation Model + ! spawn new cohorts of juveniles of each PFT + ! + ! !USES: + use SFParamsMod, only : SF_val_max_decomp + + ! + ! !ARGUMENTS + type(litter_type),intent(inout),target :: litt + real(r8),intent(in) :: fragmentation_scaler(:) + + ! This is not necessarily every soil layer, this is the number + ! of effective layers that are active and can be sent + ! to the soil decomposition model + integer,intent(in) :: nlev_eff_decomp + + ! + ! !LOCAL VARIABLES: + integer :: c ! Fuel size class index + integer :: ilyr ! Soil layer index + integer :: dcmpy ! Decomposibility pool indexer + integer :: soil_layer_index = 1 ! Soil layer index associated with above ground litter + !---------------------------------------------------------------------- + + + ! Above ground litters are associated with the top soil layer temperature and + ! moisture scalars and fragmentation scalar associated with specified index value + ! is used for ag_cwd_frag and root_fines_frag calculations. + + do c = 1,ncwd + + litt%ag_cwd_frag(c) = litt%ag_cwd(c) * SF_val_max_decomp(c) * & + years_per_day * fragmentation_scaler(soil_layer_index) + + do ilyr = 1,nlev_eff_decomp + + litt%bg_cwd_frag(c,ilyr) = litt%bg_cwd(c,ilyr) * SF_val_max_decomp(c) * & + years_per_day * fragmentation_scaler(ilyr) + + enddo + end do + + ! this is the rate at which dropped leaves stop being part of the burnable pool + ! and begin to be part of the decomposing pool. This should probably be highly + ! sensitive to moisture, but also to the type of leaf thick leaves can dry out + ! before they are decomposed, for example. This section needs further scientific input. + + do dcmpy = 1,ndcmpy + + litt%leaf_fines_frag(dcmpy) = litt%leaf_fines(dcmpy) * & + years_per_day * SF_val_max_decomp(dl_sf) * fragmentation_scaler(soil_layer_index) + + do ilyr = 1,nlev_eff_decomp + litt%root_fines_frag(dcmpy,ilyr) = litt%root_fines(dcmpy,ilyr) * & + years_per_day * SF_val_max_decomp(dl_sf) * fragmentation_scaler(ilyr) + end do + enddo + + end subroutine CWDOut + +end module EDPhysiologyMod From 8ced31c89c6bf0571439a600d30c567a2ccd47a9 Mon Sep 17 00:00:00 2001 From: YanlanLiu Date: Tue, 15 Jun 2021 11:03:57 -0700 Subject: [PATCH 008/852] track seed_out in the recruitment submodule --- biogeochem/EDPhysiologyMod.F90 | 7 +++++-- ...DPhysiologyMod_0.F90 => EDphysiologyMod.F90} | 17 +++++++---------- main/EDMainMod.F90 | 5 +++-- 3 files changed, 15 insertions(+), 14 deletions(-) rename biogeochem/{EDPhysiologyMod_0.F90 => EDphysiologyMod.F90} (99%) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index c2e83f8c15..abaecd0315 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1594,8 +1594,10 @@ end subroutine SeedGermination ! ===================================================================================== - - subroutine recruitment( currentSite, currentPatch, bc_in ) + + ! subroutine recruitment( currentSite, currentPatch, bc_in ) + !YL------- pass in bc_out ------ + subroutine recruitment( currentSite, currentPatch, bc_in, bc_out ) ! ! !DESCRIPTION: ! spawn new cohorts of juveniles of each PFT @@ -1607,6 +1609,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) type(ed_site_type), intent(inout), target :: currentSite type(ed_patch_type), intent(inout), pointer :: currentPatch type(bc_in_type), intent(in) :: bc_in + type(bc_out_type), intent(inout) :: bc_out ! ! !LOCAL VARIABLES: class(prt_vartypes), pointer :: prt diff --git a/biogeochem/EDPhysiologyMod_0.F90 b/biogeochem/EDphysiologyMod.F90 similarity index 99% rename from biogeochem/EDPhysiologyMod_0.F90 rename to biogeochem/EDphysiologyMod.F90 index a8a518e46b..71d8b01d03 100644 --- a/biogeochem/EDPhysiologyMod_0.F90 +++ b/biogeochem/EDphysiologyMod.F90 @@ -1375,8 +1375,7 @@ subroutine SeedIn( currentSite, bc_in ) !YL--------- real(r8) :: site_seed_out(maxpft) ! The sum of seed-rain leaving the site [kg/site/day] - real(r8) :: disp_frac(maxpft) ! fraction of seed-rain among the site_seed_rain that's leaving the site [unitless] - real(r8) :: seed_in_supply ! + real(r8) :: disp_frac(maxpft) ! fraction of seed-rain among the site_seed_rain that's leaving the site [unitless] !----------- do el = 1, num_elements @@ -1434,7 +1433,6 @@ subroutine SeedIn( currentSite, bc_in ) (seed_prod * currentCohort%n + store_m_to_repro)*disp_frac(pft) write(fates_log(),*) 'pft, site_seed_rain(pft), site_seed_out(pft):', pft, site_seed_rain(pft), site_seed_out(pft) - print *, pft, site_seed_rain(pft), site_seed_out(pft) !----------- @@ -1488,12 +1486,8 @@ subroutine SeedIn( currentSite, bc_in ) ! Seeds entering externally [kg/site/day] site_mass%seed_in = site_mass%seed_in + seed_in_external*currentPatch%area - - !YL------- - site_mass%seed_out = site_mass%seed_out + site_seed_out(pft) - !---------- - - end if !use this pft + write(fates_log(),*) 'pft, equivalent seed_suppl: ', pft, site_mass%seed_in/currentPatch%area/seed_stoich/years_per_day + end if !use this pft enddo @@ -1601,7 +1595,9 @@ end subroutine SeedGermination ! ===================================================================================== - subroutine recruitment( currentSite, currentPatch, bc_in ) + ! subroutine recruitment( currentSite, currentPatch, bc_in ) + ! YL------- pass in bc_out + subroutine recruitment( currentSite, currentPatch, bc_in , bc_out ) ! ! !DESCRIPTION: ! spawn new cohorts of juveniles of each PFT @@ -1613,6 +1609,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) type(ed_site_type), intent(inout), target :: currentSite type(ed_patch_type), intent(inout), pointer :: currentPatch type(bc_in_type), intent(in) :: bc_in + type(bc_out_type), intent(inout) :: bc_out ! ! !LOCAL VARIABLES: class(prt_vartypes), pointer :: prt diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 1188802e03..3bf4b35018 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -219,8 +219,9 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) do while (associated(currentPatch)) ! adds small cohort of each PFT - call recruitment(currentSite, currentPatch, bc_in) - + ! call recruitment(currentSite, currentPatch, bc_in) + !YL -------------- + call recruitment(currentSite, currentPatch, bc_in, bc_out) currentPatch => currentPatch%younger enddo end if From fa0f43b59c991a526209646a3ff0c6c200659fd8 Mon Sep 17 00:00:00 2001 From: YanlanLiu Date: Mon, 21 Jun 2021 00:17:48 -0700 Subject: [PATCH 009/852] cleaned repetitive EDphysiologyMod --- biogeochem/EDPhysiologyMod.F90 | 6 +- biogeochem/EDphysiologyMod.F90 | 2397 -------------------------------- 2 files changed, 3 insertions(+), 2400 deletions(-) delete mode 100644 biogeochem/EDphysiologyMod.F90 diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index abaecd0315..48bf9a5c0c 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1431,9 +1431,8 @@ subroutine SeedIn( currentSite, bc_in ) (seed_prod * currentCohort%n + store_m_to_repro)*(1-disp_frac(pft)) site_seed_out(pft) = site_seed_out(pft) + & (seed_prod * currentCohort%n + store_m_to_repro)*disp_frac(pft) - write(fates_log(),*) 'pft, site_seed_rain(pft), site_seed_out(pft):', pft, site_seed_rain(pft), site_seed_out(pft) - + print *, 'pft, site_seed_rain(pft), site_seed_out(pft):', pft, site_seed_rain(pft), site_seed_out(pft) !----------- currentCohort => currentCohort%shorter @@ -1486,7 +1485,8 @@ subroutine SeedIn( currentSite, bc_in ) ! Seeds entering externally [kg/site/day] site_mass%seed_in = site_mass%seed_in + seed_in_external*currentPatch%area - write(fates_log(),*) 'pft, equivalent seed_suppl: ', pft, site_mass%seed_in/currentPatch%area/seed_stoich/years_per_day + write(fates_log(),*) 'pft, site_mass%seed_in, site_seed_rain, site_seed_out: ', pft, site_mass%seed_in, site_seed_rain(pft), site_seed_out(pft) +! write(fates_log(),*) 'pft, equivalent seed_suppl: ', pft, site_mass%seed_in/currentPatch%area/seed_stoich/years_per_day end if !use this pft enddo diff --git a/biogeochem/EDphysiologyMod.F90 b/biogeochem/EDphysiologyMod.F90 deleted file mode 100644 index 71d8b01d03..0000000000 --- a/biogeochem/EDphysiologyMod.F90 +++ /dev/null @@ -1,2397 +0,0 @@ -module EDPhysiologyMod - -#include "shr_assert.h" - - ! ============================================================================ - ! Miscellaneous physiology routines from ED. - ! ============================================================================ - - use FatesGlobals, only : fates_log - use FatesInterfaceTypesMod, only : hlm_days_per_year - use FatesInterfaceTypesMod, only : hlm_model_day - use FatesInterfaceTypesMod, only : hlm_freq_day - use FatesInterfaceTypesMod, only : hlm_day_of_year - use FatesInterfaceTypesMod, only : numpft - use FatesInterfaceTypesMod, only : nleafage - use FatesInterfaceTypesMod, only : hlm_use_planthydro - use FatesInterfaceTypesMod, only : hlm_parteh_mode - use FatesInterfaceTypesMod, only : hlm_nitrogen_spec - use FatesInterfaceTypesMod, only : hlm_phosphorus_spec - use FatesConstantsMod, only : r8 => fates_r8 - use FatesConstantsMod, only : nearzero - use EDPftvarcon , only : EDPftvarcon_inst - use PRTParametersMod , only : prt_params - use EDPftvarcon , only : GetDecompyFrac - use FatesInterfaceTypesMod, only : bc_in_type - use FatesInterfaceTypesMod, only : bc_out_type - use EDCohortDynamicsMod , only : zero_cohort - use EDCohortDynamicsMod , only : create_cohort, sort_cohorts - use EDCohortDynamicsMod , only : InitPRTObject - use FatesAllometryMod , only : tree_lai - use FatesAllometryMod , only : tree_sai - use FatesAllometryMod , only : decay_coeff_kn - use FatesLitterMod , only : litter_type - use EDTypesMod , only : site_massbal_type - use EDTypesMod , only : numlevsoil_max - use EDTypesMod , only : numWaterMem - use EDTypesMod , only : dl_sf, dinc_ed, area_inv - use FatesLitterMod , only : ncwd - use FatesLitterMod , only : ndcmpy - use FatesLitterMod , only : ilabile - use FatesLitterMod , only : ilignin - use FatesLitterMod , only : icellulose - use EDTypesMod , only : AREA,AREA_INV - use EDTypesMod , only : nlevleaf - use EDTypesMod , only : num_vegtemp_mem - use EDTypesMod , only : maxpft - use EDTypesMod , only : ed_site_type, ed_patch_type, ed_cohort_type - use EDTypesMod , only : leaves_on - use EDTypesMod , only : leaves_off - use EDTypesMod , only : min_n_safemath - use PRTGenericMod , only : num_elements - use PRTGenericMod , only : element_list - use PRTGenericMod , only : element_pos - use EDTypesMod , only : site_fluxdiags_type - use EDTypesMod , only : phen_cstat_nevercold - use EDTypesMod , only : phen_cstat_iscold - use EDTypesMod , only : phen_cstat_notcold - use EDTypesMod , only : phen_dstat_timeoff - use EDTypesMod , only : phen_dstat_moistoff - use EDTypesMod , only : phen_dstat_moiston - use EDTypesMod , only : phen_dstat_timeon - use shr_log_mod , only : errMsg => shr_log_errMsg - use FatesGlobals , only : fates_log - use FatesGlobals , only : endrun => fates_endrun - use EDParamsMod , only : fates_mortality_disturbance_fraction - use EDParamsMod , only : q10_mr - use EDParamsMod , only : q10_froz - use EDParamsMod , only : logging_export_frac - use FatesPlantHydraulicsMod , only : AccumulateMortalityWaterStorage - use FatesConstantsMod , only : itrue,ifalse - use FatesConstantsMod , only : calloc_abs_error - use FatesConstantsMod , only : years_per_day - use FatesAllometryMod , only : h_allom - use FatesAllometryMod , only : h2d_allom - use FatesAllometryMod , only : bagw_allom - use FatesAllometryMod , only : bsap_allom - use FatesAllometryMod , only : bleaf - use FatesAllometryMod , only : bfineroot - use FatesAllometryMod , only : bdead_allom - use FatesAllometryMod , only : bstore_allom - use FatesAllometryMod , only : bbgw_allom - use FatesAllometryMod , only : carea_allom - use FatesAllometryMod , only : CheckIntegratedAllometries - use FatesAllometryMod, only : set_root_fraction - use PRTGenericMod, only : prt_carbon_allom_hyp - use PRTGenericMod, only : prt_cnp_flex_allom_hyp - use PRTGenericMod, only : prt_vartypes - use PRTGenericMod, only : leaf_organ - use PRTGenericMod, only : sapw_organ, struct_organ - use PRTGenericMod, only : all_carbon_elements - use PRTGenericMod, only : carbon12_element - use PRTGenericMod, only : nitrogen_element - use PRTGenericMod, only : phosphorus_element - use PRTGenericMod, only : leaf_organ - use PRTGenericMod, only : fnrt_organ - use PRTGenericMod, only : sapw_organ - use PRTGenericMod, only : store_organ - use PRTGenericMod, only : repro_organ - use PRTGenericMod, only : struct_organ - use PRTGenericMod, only : SetState - use PRTLossFluxesMod, only : PRTPhenologyFlush - use PRTLossFluxesMod, only : PRTDeciduousTurnover - use PRTLossFluxesMod, only : PRTReproRelease - - - - public :: trim_canopy - public :: phenology - public :: recruitment - public :: ZeroLitterFluxes - - public :: ZeroAllocationRates - public :: PreDisturbanceLitterFluxes - public :: PreDisturbanceIntegrateLitter - public :: SeedIn - - logical, parameter :: debug = .false. ! local debug flag - character(len=*), parameter, private :: sourcefile = & - __FILE__ - - integer, parameter :: dleafon_drycheck = 100 ! Drought deciduous leaves max days on check parameter - - - - - ! ============================================================================ - -contains - - subroutine ZeroLitterFluxes( currentSite ) - - ! This routine loops through all patches in a site - ! and zero's the flux terms for the litter pools. - ! This is typically called at the beginning of the dynamics - ! call sequence. - - - ! !ARGUMENTS - type(ed_site_type), intent(inout), target :: currentSite - type(ed_patch_type), pointer :: currentPatch - - integer :: el - - currentPatch => currentSite%youngest_patch - do while(associated(currentPatch)) - do el=1,num_elements - call currentPatch%litter(el)%ZeroFlux() - end do - currentPatch => currentPatch%older - end do - - - return - end subroutine ZeroLitterFluxes - - ! ===================================================================================== - - subroutine ZeroAllocationRates( currentSite ) - - ! !ARGUMENTS - type(ed_site_type), intent(inout), target :: currentSite - type(ed_patch_type), pointer :: currentPatch - type(ed_cohort_type), pointer :: currentCohort - - currentPatch => currentSite%youngest_patch - do while(associated(currentPatch)) - - currentCohort => currentPatch%tallest - do while (associated(currentCohort)) - - ! This sets turnover and growth rates to zero - call currentCohort%prt%ZeroRates() - - currentCohort => currentCohort%shorter - enddo - currentPatch => currentPatch%older - end do - - return - end subroutine ZeroAllocationRates - - - ! ============================================================================ - - subroutine PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in ) - - ! ----------------------------------------------------------------------------------- - ! - ! This subroutine calculates all of the different litter input and output fluxes - ! associated with seed turnover, seed influx, litterfall from live and - ! dead plants, germination, and fragmentation. - ! - ! At this time we do not have explicit herbivory, and burning losses to litter - ! are handled elsewhere. - ! - ! Note: The processes conducted here DO NOT handle litter fluxes associated - ! with disturbance. Those fluxes are handled elsewhere (EDPatchDynamcisMod) - ! because the fluxes are potentially cross patch, and also dealing - ! patch areas that are changing. - ! - ! ----------------------------------------------------------------------------------- - - - ! !ARGUMENTS - type(ed_site_type), intent(inout) :: currentSite - type(ed_patch_type), intent(inout) :: currentPatch - type(bc_in_type), intent(in) :: bc_in - - ! - ! !LOCAL VARIABLES: - type(site_massbal_type), pointer :: site_mass - type(litter_type), pointer :: litt ! Points to the litter object for - ! the different element types - integer :: el ! Litter element loop index - integer :: nlev_eff_decomp ! Number of active layers over which - ! fragmentation fluxes are transfered - !------------------------------------------------------------------------------------ - - ! Calculate the fragmentation rates - call fragmentation_scaler(currentPatch, bc_in) - - - do el = 1, num_elements - - litt => currentPatch%litter(el) - - ! Calculate loss rate of viable seeds to litter - call SeedDecay(litt) - - ! Send those decaying seeds in the previous call - ! to the litter input flux - call SeedDecayToFines(litt) - - ! Calculate seed germination rate, the status flags prevent - ! germination from occuring when the site is in a drought - ! (for drought deciduous) or too cold (for cold deciduous) - call SeedGermination(litt, currentSite%cstatus, currentSite%dstatus) - - ! Send fluxes from newly created litter into the litter pools - ! This litter flux is from non-disturbance inducing mortality, as well - ! as litter fluxes from live trees - call CWDInput(currentSite, currentPatch, litt) - - - ! Only calculate fragmentation flux over layers that are active - ! (RGK-Mar2019) SHOULD WE MAX THIS AT 1? DONT HAVE TO - - nlev_eff_decomp = max(bc_in%max_rooting_depth_index_col, 1) - call CWDOut(litt,currentPatch%fragmentation_scaler,nlev_eff_decomp) - - - site_mass => currentSite%mass_balance(el) - - ! Fragmentation flux to soil decomposition model [kg/site/day] - site_mass%frag_out = site_mass%frag_out + currentPatch%area * & - ( sum(litt%ag_cwd_frag) + sum(litt%bg_cwd_frag) + & - sum(litt%leaf_fines_frag) + sum(litt%root_fines_frag)) - - end do - - - return - end subroutine PreDisturbanceLitterFluxes - - ! ===================================================================================== - - subroutine PreDisturbanceIntegrateLitter(currentPatch) - - ! ----------------------------------------------------------------------------------- - ! - ! This step applies the litter fluxes to the prognostic state variables. - ! This procedure is called in response to fluxes generated from: - ! 1) seed rain, - ! 2) non-disturbance generating turnover - ! 3) litter fall from living plants - ! 4) fragmentation - ! - ! This routine does NOT accomodate the litter fluxes associated with - ! disturbance generation. That will happen after this call. - ! Fluxes associated with FIRE also happen after this step. - ! - ! All states are in units kg/m2 - ! All fluxes are in units kg/m2/day - ! The integration step is 1 day, thus time is implied - ! - ! ----------------------------------------------------------------------------------- - - ! Arguments - type(ed_patch_type),intent(inout),target :: currentPatch - - - ! Locals - type(litter_type), pointer :: litt - integer :: el ! Loop counter for litter element type - integer :: pft ! pft loop counter - integer :: c ! CWD loop counter - integer :: nlevsoil ! number of soil layers - integer :: ilyr ! soil layer loop counter - integer :: dcmpy ! decomposability index - - do el = 1, num_elements - - litt => currentPatch%litter(el) - - ! Update the bank of viable seeds - ! ----------------------------------------------------------------------------------- - - do pft = 1,numpft - litt%seed(pft) = litt%seed(pft) + & - litt%seed_in_local(pft) + & - litt%seed_in_extern(pft) - & - litt%seed_decay(pft) - & - litt%seed_germ_in(pft) - - ! Note that the recruitment scheme will use seed_germ - ! for its construction costs. - litt%seed_germ(pft) = litt%seed_germ(pft) + & - litt%seed_germ_in(pft) - & - litt%seed_germ_decay(pft) - - - enddo - - ! Update the Coarse Woody Debris pools (above and below) - ! ----------------------------------------------------------------------------------- - nlevsoil = size(litt%bg_cwd,dim=2) - do c = 1,ncwd - litt%ag_cwd(c) = litt%ag_cwd(c) + litt%ag_cwd_in(c) - litt%ag_cwd_frag(c) - do ilyr=1,nlevsoil - litt%bg_cwd(c,ilyr) = litt%bg_cwd(c,ilyr) & - + litt%bg_cwd_in(c,ilyr) & - - litt%bg_cwd_frag(c,ilyr) - enddo - end do - - ! Update the fine litter pools from leaves and fine-roots - ! ----------------------------------------------------------------------------------- - - do dcmpy = 1,ndcmpy - - litt%leaf_fines(dcmpy) = litt%leaf_fines(dcmpy) & - + litt%leaf_fines_in(dcmpy) & - - litt%leaf_fines_frag(dcmpy) - do ilyr=1,nlevsoil - litt%root_fines(dcmpy,ilyr) = litt%root_fines(dcmpy,ilyr) & - + litt%root_fines_in(dcmpy,ilyr) & - - litt%root_fines_frag(dcmpy,ilyr) - enddo - - end do - - end do ! litter element loop - - return - end subroutine PreDisturbanceIntegrateLitter - - - - ! ============================================================================ - - subroutine trim_canopy( currentSite ) - ! - ! !DESCRIPTION: - ! Canopy trimming / leaf optimisation. Removes leaves in negative annual carbon balance. - ! - ! !USES: - - ! !ARGUMENTS - type (ed_site_type),intent(inout), target :: currentSite - ! - ! !LOCAL VARIABLES: - type (ed_cohort_type) , pointer :: currentCohort - type (ed_patch_type) , pointer :: currentPatch - - integer :: z ! leaf layer - integer :: ipft ! pft index - logical :: trimmed ! was this layer trimmed in this year? If not expand the canopy. - real(r8) :: tar_bl ! target leaf biomass (leaves flushed, trimmed) - real(r8) :: tar_bfr ! target fine-root biomass (leaves flushed, trimmed) - real(r8) :: bfr_per_bleaf ! ratio of fine root per leaf biomass - real(r8) :: sla_levleaf ! sla at leaf level z - real(r8) :: nscaler_levleaf ! nscaler value at leaf level z - integer :: cl ! canopy layer index - real(r8) :: kn ! nitrogen decay coefficient - real(r8) :: sla_max ! Observational constraint on how large sla (m2/gC) can become - real(r8) :: leaf_c ! leaf carbon [kg] - real(r8) :: sapw_c ! sapwood carbon [kg] - real(r8) :: store_c ! storage carbon [kg] - real(r8) :: struct_c ! structure carbon [kg] - real(r8) :: leaf_inc ! LAI-only portion of the vegetation increment of dinc_ed - real(r8) :: lai_canopy_above ! the LAI in the canopy layers above the layer of interest - real(r8) :: lai_layers_above ! the LAI in the leaf layers, within the current canopy, - ! above the leaf layer of interest - real(r8) :: lai_current ! the LAI in the current leaf layer - real(r8) :: cumulative_lai ! whole canopy cumulative LAI, top down, to the leaf layer of interest - real(r8) :: cumulative_lai_cohort ! cumulative LAI within the current cohort only - - ! Temporary diagnostic ouptut - integer :: ipatch - integer :: icohort - - ! LAPACK linear least squares fit variables - ! The standard equation for a linear fit, y = mx + b, is converted to a linear system, AX=B and has - ! the form: [n sum(x); sum(x) sum(x^2)] * [b; m] = [sum(y); sum(x*y)] where - ! n is the number of leaf layers - ! x is yearly_net_uptake minus the leaf cost aka the net-net uptake - ! y is the cumulative lai for the current cohort - ! b is the y-intercept i.e. the cumulative lai that has zero net-net uptake - ! m is the slope of the linear fit - integer :: nll = 3 ! Number of leaf layers to fit a regression to for calculating the optimum lai - character(1) :: trans = 'N' ! Input matrix is not transposed - - integer, parameter :: m = 2, n = 2 ! Number of rows and columns, respectively, in matrix A - integer, parameter :: nrhs = 1 ! Number of columns in matrix B and X - integer, parameter :: workmax = 100 ! Maximum iterations to minimize work - - integer :: lda = m, ldb = n ! Leading dimension of A and B, respectively - integer :: lwork ! Dimension of work array - integer :: info ! Procedure diagnostic ouput - - real(r8) :: nnu_clai_a(m,n) ! LHS of linear least squares fit, A matrix - real(r8) :: nnu_clai_b(m,nrhs) ! RHS of linear least squares fit, B matrix - real(r8) :: work(workmax) ! work array - - real(r8) :: initial_trim ! Initial trim - real(r8) :: optimum_trim ! Optimum trim value - real(r8) :: initial_laimem ! Initial laimemory - real(r8) :: optimum_laimem ! Optimum laimemory - - !---------------------------------------------------------------------- - - ipatch = 1 ! Start counting patches - - currentPatch => currentSite%youngest_patch - do while(associated(currentPatch)) - - ! Add debug diagnstic output to determine which patch - if (debug) then - write(fates_log(),*) 'Current patch:', ipatch - write(fates_log(),*) 'Current patch cohorts:', currentPatch%countcohorts - endif - - icohort = 1 - - currentCohort => currentPatch%tallest - do while (associated(currentCohort)) - - ! Save off the incoming trim and laimemory - initial_trim = currentCohort%canopy_trim - initial_laimem = currentCohort%laimemory - - ! Add debug diagnstic output to determine which cohort - if (debug) then - write(fates_log(),*) 'Current cohort:', icohort - write(fates_log(),*) 'Starting canopy trim:', initial_trim - write(fates_log(),*) 'Starting laimemory:', currentCohort%laimemory - endif - - trimmed = .false. - ipft = currentCohort%pft - call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread,currentCohort%pft,currentCohort%c_area) - - leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) - - currentCohort%treelai = tree_lai(leaf_c, currentCohort%pft, currentCohort%c_area, & - currentCohort%n, currentCohort%canopy_layer, & - currentPatch%canopy_layer_tlai,currentCohort%vcmax25top ) - - currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_trim, & - currentCohort%c_area, currentCohort%n, currentCohort%canopy_layer, & - currentPatch%canopy_layer_tlai, currentCohort%treelai, & - currentCohort%vcmax25top,0 ) - - currentCohort%nv = ceiling((currentCohort%treelai+currentCohort%treesai)/dinc_ed) - - if (currentCohort%nv > nlevleaf)then - write(fates_log(),*) 'nv > nlevleaf',currentCohort%nv, & - currentCohort%treelai,currentCohort%treesai, & - currentCohort%c_area,currentCohort%n,leaf_c - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - - call bleaf(currentcohort%dbh,ipft,currentcohort%canopy_trim,tar_bl) - - if ( int(prt_params%allom_fmode(ipft)) .eq. 1 ) then - ! only query fine root biomass if using a fine root allometric model that takes leaf trim into account - call bfineroot(currentcohort%dbh,ipft,currentcohort%canopy_trim,tar_bfr) - bfr_per_bleaf = tar_bfr/tar_bl - endif - - ! Identify current canopy layer (cl) - cl = currentCohort%canopy_layer - - ! PFT-level maximum SLA value, even if under a thick canopy (same units as slatop) - sla_max = prt_params%slamax(ipft) - - ! Initialize nnu_clai_a - nnu_clai_a(:,:) = 0._r8 - nnu_clai_b(:,:) = 0._r8 - - !Leaf cost vs netuptake for each leaf layer. - do z = 1, currentCohort%nv - - ! Calculate the cumulative total vegetation area index (no snow occlusion, stems and leaves) - - leaf_inc = dinc_ed * & - currentCohort%treelai/(currentCohort%treelai+currentCohort%treesai) - - ! Now calculate the cumulative top-down lai of the current layer's midpoint within the current cohort - lai_layers_above = leaf_inc * (z-1) - lai_current = min(leaf_inc, currentCohort%treelai - lai_layers_above) - cumulative_lai_cohort = lai_layers_above + 0.5*lai_current - - ! Now add in the lai above the current cohort for calculating the sla leaf level - lai_canopy_above = sum(currentPatch%canopy_layer_tlai(1:cl-1)) - cumulative_lai = lai_canopy_above + cumulative_lai_cohort - - ! There was activity this year in this leaf layer. This should only occur for bottom most leaf layer - if (currentCohort%year_net_uptake(z) /= 999._r8)then - - ! Calculate sla_levleaf following the sla profile with overlying leaf area - ! Scale for leaf nitrogen profile - kn = decay_coeff_kn(ipft,currentCohort%vcmax25top) - ! Nscaler value at leaf level z - nscaler_levleaf = exp(-kn * cumulative_lai) - ! Sla value at leaf level z after nitrogen profile scaling (m2/gC) - sla_levleaf = prt_params%slatop(ipft)/nscaler_levleaf - - if(sla_levleaf > sla_max)then - sla_levleaf = sla_max - end if - - !Leaf Cost kgC/m2/year-1 - !decidous costs. - if (prt_params%season_decid(ipft) == itrue .or. & - prt_params%stress_decid(ipft) == itrue )then - - ! Leaf cost at leaf level z accounting for sla profile (kgC/m2) - currentCohort%leaf_cost = 1._r8/(sla_levleaf*1000.0_r8) - - if ( int(prt_params%allom_fmode(ipft)) .eq. 1 ) then - ! if using trimmed leaf for fine root biomass allometry, add the cost of the root increment - ! to the leaf increment; otherwise do not. - currentCohort%leaf_cost = currentCohort%leaf_cost + & - 1.0_r8/(sla_levleaf*1000.0_r8) * & - bfr_per_bleaf / prt_params%root_long(ipft) - endif - - currentCohort%leaf_cost = currentCohort%leaf_cost * & - (prt_params%grperc(ipft) + 1._r8) - else !evergreen costs - - ! Leaf cost at leaf level z accounting for sla profile - currentCohort%leaf_cost = 1.0_r8/(sla_levleaf* & - sum(prt_params%leaf_long(ipft,:))*1000.0_r8) !convert from sla in m2g-1 to m2kg-1 - - - if ( int(prt_params%allom_fmode(ipft)) .eq. 1 ) then - ! if using trimmed leaf for fine root biomass allometry, add the cost of the root increment - ! to the leaf increment; otherwise do not. - currentCohort%leaf_cost = currentCohort%leaf_cost + & - 1.0_r8/(sla_levleaf*1000.0_r8) * & - bfr_per_bleaf / prt_params%root_long(ipft) - endif - currentCohort%leaf_cost = currentCohort%leaf_cost * & - (prt_params%grperc(ipft) + 1._r8) - endif - - ! Construct the arrays for a least square fit of the net_net_uptake versus the cumulative lai - ! if at least nll leaf layers are present in the current cohort and only for the bottom nll - ! leaf layers. - if (currentCohort%nv > nll .and. currentCohort%nv - z < nll) then - - ! Build the A matrix for the LHS of the linear system. A = [n sum(x); sum(x) sum(x^2)] - ! where n = nll and x = yearly_net_uptake-leafcost - nnu_clai_a(1,1) = nnu_clai_a(1,1) + 1 ! Increment for each layer used - nnu_clai_a(1,2) = nnu_clai_a(1,2) + currentCohort%year_net_uptake(z) - currentCohort%leaf_cost - nnu_clai_a(2,1) = nnu_clai_a(1,2) - nnu_clai_a(2,2) = nnu_clai_a(2,2) + (currentCohort%year_net_uptake(z) - currentCohort%leaf_cost)**2 - - ! Build the B matrix for the RHS of the linear system. B = [sum(y); sum(x*y)] - ! where x = yearly_net_uptake-leafcost and y = cumulative_lai_cohort - nnu_clai_b(1,1) = nnu_clai_b(1,1) + cumulative_lai_cohort - nnu_clai_b(2,1) = nnu_clai_b(2,1) + (cumulative_lai_cohort * & - (currentCohort%year_net_uptake(z) - currentCohort%leaf_cost)) - end if - - ! Check leaf cost against the yearly net uptake for that cohort leaf layer - if (currentCohort%year_net_uptake(z) < currentCohort%leaf_cost) then - ! Make sure the cohort trim fraction is great than the pft trim limit - if (currentCohort%canopy_trim > EDPftvarcon_inst%trim_limit(ipft)) then - - ! if ( debug ) then - ! write(fates_log(),*) 'trimming leaves', & - ! currentCohort%canopy_trim,currentCohort%leaf_cost - ! endif - - ! keep trimming until none of the canopy is in negative carbon balance. - if (currentCohort%hite > EDPftvarcon_inst%hgt_min(ipft)) then - currentCohort%canopy_trim = currentCohort%canopy_trim - & - EDPftvarcon_inst%trim_inc(ipft) - if (prt_params%evergreen(ipft) /= 1)then - currentCohort%laimemory = currentCohort%laimemory * & - (1.0_r8 - EDPftvarcon_inst%trim_inc(ipft)) - endif - - trimmed = .true. - - endif ! hite check - endif ! trim limit check - endif ! net uptake check - endif ! leaf activity check - enddo ! z, leaf layer loop - - ! Compute the optimal cumulative lai based on the cohort net-net uptake profile if at least 2 leaf layers - if (nnu_clai_a(1,1) > 1) then - - ! Compute the optimum size of the work array - lwork = -1 ! Ask sgels to compute optimal number of entries for work - call dgels(trans, m, n, nrhs, nnu_clai_a, lda, nnu_clai_b, ldb, work, lwork, info) - lwork = int(work(1)) ! Pick the optimum. TBD, can work(1) come back with greater than work size? - - ! if (debug) then - ! write(fates_log(),*) 'LLSF lwork output (info, lwork):', info, lwork - ! endif - - ! Compute the minimum of 2-norm of of the least squares fit to solve for X - ! Note that dgels returns the solution by overwriting the nnu_clai_b array. - ! The result has the form: X = [b; m] - ! where b = y-intercept (i.e. the cohort lai that has zero yearly net-net uptake) - ! and m is the slope of the linear fit - call dgels(trans, m, n, nrhs, nnu_clai_a, lda, nnu_clai_b, ldb, work, lwork, info) - - if (info < 0) then - write(fates_log(),*) 'LLSF optimium LAI calculation returned illegal value' - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - - if (debug) then - write(fates_log(),*) 'LLSF optimium LAI (intercept,slope):', nnu_clai_b - write(fates_log(),*) 'LLSF optimium LAI:', nnu_clai_b(1,1) - write(fates_log(),*) 'LLSF optimium LAI info:', info - write(fates_log(),*) 'LAI fraction (optimum_lai/cumulative_lai):', nnu_clai_b(1,1) / cumulative_lai_cohort - endif - - ! Calculate the optimum trim based on the initial canopy trim value - if (cumulative_lai_cohort > 0._r8) then ! Sometime cumulative_lai comes in at 0.0? - - ! - optimum_trim = (nnu_clai_b(1,1) / cumulative_lai_cohort) * initial_trim - optimum_laimem = (nnu_clai_b(1,1) / cumulative_lai_cohort) * initial_laimem - - ! Determine if the optimum trim value makes sense. The smallest cohorts tend to have unrealistic fits. - if (optimum_trim > 0. .and. optimum_trim < 1.) then - currentCohort%canopy_trim = optimum_trim - - ! If the cohort pft is not evergreen we reduce the laimemory as well - if (prt_params%evergreen(ipft) /= 1) then - currentCohort%laimemory = optimum_laimem - endif - - trimmed = .true. - - endif - endif - endif - - ! Reset activity for the cohort for the start of the next year - currentCohort%year_net_uptake(:) = 999.0_r8 - - ! Add to trim fraction if cohort not trimmed at all - if ( (.not.trimmed) .and.currentCohort%canopy_trim < 1.0_r8)then - currentCohort%canopy_trim = currentCohort%canopy_trim + EDPftvarcon_inst%trim_inc(ipft) - endif - - if ( debug ) then - write(fates_log(),*) 'trimming:',currentCohort%canopy_trim - endif - - ! currentCohort%canopy_trim = 1.0_r8 !FIX(RF,032414) this turns off ctrim for now. - currentCohort => currentCohort%shorter - icohort = icohort + 1 - enddo - currentPatch => currentPatch%older - ipatch = ipatch + 1 - enddo - - end subroutine trim_canopy - - ! ============================================================================ - subroutine phenology( currentSite, bc_in ) - ! - ! !DESCRIPTION: - ! Phenology. - ! - ! !USES: - use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm - use EDParamsMod, only : ED_val_phen_drought_threshold, ED_val_phen_doff_time - use EDParamsMod, only : ED_val_phen_a, ED_val_phen_b, ED_val_phen_c, ED_val_phen_chiltemp - use EDParamsMod, only : ED_val_phen_mindayson, ED_val_phen_ncolddayslim, ED_val_phen_coldtemp - - - ! - ! !ARGUMENTS: - type(ed_site_type), intent(inout), target :: currentSite - type(bc_in_type), intent(in) :: bc_in - - ! - ! !LOCAL VARIABLES: - - type(ed_patch_type),pointer :: cpatch - integer :: model_day_int ! integer model day 1 - inf - integer :: ncolddays ! no days underneath the threshold for leaf drop - integer :: i_wmem ! Loop counter for water mem days - integer :: i_tmem ! Loop counter for veg temp mem days - integer :: dayssincedleafon ! Days since drought-decid leaf-on started - integer :: dayssincedleafoff ! Days since drought-decid leaf-off started - integer :: dayssincecleafon ! Days since cold-decid leaf-on started - integer :: dayssincecleafoff ! Days since cold-decid leaf-off started - real(r8) :: mean_10day_liqvol ! mean liquid volume (m3/m3) over last 10 days - real(r8) :: leaf_c ! leaf carbon [kg] - real(r8) :: fnrt_c ! fineroot carbon [kg] - real(r8) :: sapw_c ! sapwood carbon [kg] - real(r8) :: store_c ! storage carbon [kg] - real(r8) :: struct_c ! structure carbon [kg] - real(r8) :: gdd_threshold ! GDD accumulation function, - integer :: ilayer_swater ! Layer index for soil water - ! which also depends on chilling days. - integer :: ncdstart ! beginning of counting period for chilling degree days. - integer :: gddstart ! beginning of counting period for growing degree days. - real(r8) :: temp_in_C ! daily averaged temperature in celcius - - integer, parameter :: canopy_leaf_lifespan = 365 ! Maximum lifespan of drought decid leaves - - integer, parameter :: min_daysoff_dforcedflush = 30 ! THis is the number of days that must had elapsed - ! since leaves had dropped, in order to forcably - ! flush leaves again. This does not impact flushing - ! due to real moisture constraints, and will prevent - ! drought deciduous in perennially wet environments - ! that have been forced to drop their leaves, from - ! flushing them back immediately. - - real(r8),parameter :: dphen_soil_depth = 0.1 ! Use liquid soil water that is - ! closest to this depth [m] - - ! This is the integer model day. The first day of the simulation is 1, and it - ! continues monotonically, indefinitely - model_day_int = nint(hlm_model_day) - - - ! Use the following layer index to calculate drought conditions - ilayer_swater = minloc(abs(bc_in%z_sisl(:)-dphen_soil_depth),dim=1) - - - ! Parameter of drought decid leaf loss in mm in top layer...FIX(RF,032414) - ! - this is arbitrary and poorly understood. Needs work. ED_ - !Parameters: defaults from Botta et al. 2000 GCB,6 709-725 - !Parameters, default from from SDGVM model of senesence - - temp_in_C = 0._r8 - cpatch => CurrentSite%oldest_patch - do while(associated(cpatch)) - temp_in_C = temp_in_C + bc_in%t_veg24_pa(cpatch%patchno)*cpatch%area - cpatch => cpatch%younger - end do - temp_in_C = temp_in_C * area_inv - tfrz - - - !-----------------Cold Phenology--------------------! - - !Zero growing degree and chilling day counters - if (currentSite%lat > 0)then - ncdstart = 270 !Northern Hemisphere begining November - gddstart = 1 !Northern Hemisphere begining January - else - ncdstart = 120 !Southern Hemisphere beginning May - gddstart = 181 !Northern Hemisphere begining July - endif - - ! Count the number of chilling days over a seasonal window. - ! For comparing against GDD, we start calculating chilling - ! in the late autumn. - ! This value is used to determine the GDD exceedance threshold - if (hlm_day_of_year == ncdstart)then - currentSite%nchilldays = 0 - endif - - !Accumulate growing/chilling days after start of counting period - if (temp_in_C < ED_val_phen_chiltemp)then - currentSite%nchilldays = currentSite%nchilldays + 1 - endif - - !GDD accumulation function, which also depends on chilling days. - ! -68 + 638 * (-0.001 * ncd) - gdd_threshold = ED_val_phen_a + ED_val_phen_b*exp(ED_val_phen_c*real(currentSite%nchilldays,r8)) - - !Accumulate temperature of last 10 days. - currentSite%vegtemp_memory(2:num_vegtemp_mem) = currentSite%vegtemp_memory(1:num_vegtemp_mem-1) - currentSite%vegtemp_memory(1) = temp_in_C - - !count number of days for leaves off - ncolddays = 0 - do i_tmem = 1,num_vegtemp_mem - if (currentSite%vegtemp_memory(i_tmem) < ED_val_phen_coldtemp)then - ncolddays = ncolddays + 1 - endif - enddo - - ! Here is where we do the GDD accumulation calculation - ! - ! reset GDD on set dates - if (hlm_day_of_year == gddstart)then - currentSite%grow_deg_days = 0._r8 - endif - ! - ! accumulate the GDD using daily mean temperatures - ! Don't accumulate GDD during the growing season (that wouldn't make sense) - if (temp_in_C .gt. 0._r8 .and. currentSite%cstatus == phen_cstat_iscold) then - currentSite%grow_deg_days = currentSite%grow_deg_days + temp_in_C - endif - - !this logic is to prevent GDD accumulating after the leaves have fallen and before the - ! beginnning of the accumulation period, to prevend erroneous autumn leaf flushing. - if(model_day_int>365)then !only do this after the first year to prevent odd behaviour - - if(currentSite%lat .gt. 0.0_r8)then !Northern Hemisphere - ! In the north, don't accumulate when we are past the leaf fall date. - ! Accumulation starts on day 1 of year in NH. - ! The 180 is to prevent going into an 'always off' state after initialization - if( model_day_int .gt. currentSite%cleafoffdate.and.hlm_day_of_year.gt.180)then ! - currentSite%grow_deg_days = 0._r8 - endif - else !Southern Hemisphere - ! In the South, don't accumulate after the leaf off date, and before the start of - ! the accumulation phase (day 181). - if(model_day_int .gt. currentSite%cleafoffdate.and.hlm_day_of_year.lt.gddstart) then! - currentSite%grow_deg_days = 0._r8 - endif - endif - endif !year1 - - ! Calculate the number of days since the leaves last came on - ! and off. If this is the beginning of the simulation, that day might - ! not had occured yet, so set it to last year to get things rolling - - if (model_day_int < currentSite%cleafoffdate) then - dayssincecleafoff = model_day_int - (currentSite%cleafoffdate - 365) - else - dayssincecleafoff = model_day_int - currentSite%cleafoffdate - end if - - if (model_day_int < currentSite%cleafondate) then - dayssincecleafon = model_day_int - (currentSite%cleafondate-365) - else - dayssincecleafon = model_day_int - currentSite%cleafondate - end if - - - - !LEAF ON: COLD DECIDUOUS. Needs to - !1) have exceeded the growing degree day threshold - !2) The leaves should not be on already - !3) There should have been at least one chilling day in the counting period. - ! this prevents tropical or warm climate plants that are "cold-deciduous" - ! from ever re-flushing after they have reached their maximum age (thus - ! preventing them from competing - - if ( (currentSite%cstatus == phen_cstat_iscold .or. & - currentSite%cstatus == phen_cstat_nevercold) .and. & - (currentSite%grow_deg_days > gdd_threshold) .and. & - (dayssincecleafoff > ED_val_phen_mindayson) .and. & - (currentSite%nchilldays >= 1)) then - currentSite%cstatus = phen_cstat_notcold ! Set to not-cold status (leaves can come on) - currentSite%cleafondate = model_day_int - dayssincecleafon = 0 - currentSite%grow_deg_days = 0._r8 ! zero GDD for the rest of the year until counting season begins. - if ( debug ) write(fates_log(),*) 'leaves on' - endif !GDD - - - - - !LEAF OFF: COLD THRESHOLD - !Needs to: - !1) have exceeded the number of cold days threshold - !2) have exceeded the minimum leafon time. - !3) The leaves should not be off already - !4) The day of simulation should be larger than the counting period. - - - if ( (currentSite%cstatus == phen_cstat_notcold) .and. & - (model_day_int > num_vegtemp_mem) .and. & - (ncolddays > ED_val_phen_ncolddayslim) .and. & - (dayssincecleafon > ED_val_phen_mindayson) )then - - currentSite%grow_deg_days = 0._r8 ! The equations for Botta et al - ! are for calculations of - ! first flush, but if we dont - ! clear this value, it will cause - ! leaves to flush later in the year - currentSite%cstatus = phen_cstat_iscold ! alter status of site to 'leaves off' - currentSite%cleafoffdate = model_day_int ! record leaf off date - - if ( debug ) write(fates_log(),*) 'leaves off' - endif - - ! LEAF OFF: COLD LIFESPAN THRESHOLD - ! NOTE: Some areas of the planet will never generate a cold day - ! and thus %nchilldays will never go from zero to 1. The following logic - ! when coupled with this fact will essentially prevent cold-deciduous - ! plants from re-emerging in areas without at least some cold days - - if( (currentSite%cstatus == phen_cstat_notcold) .and. & - (dayssincecleafoff > 400)) then ! remove leaves after a whole year - ! when there is no 'off' period. - currentSite%grow_deg_days = 0._r8 - - currentSite%cstatus = phen_cstat_nevercold ! alter status of site to imply that this - ! site is never really cold enough - ! for cold deciduous - currentSite%cleafoffdate = model_day_int ! record leaf off date - - if ( debug ) write(fates_log(),*) 'leaves off' - endif - - !-----------------Drought Phenology--------------------! - ! Principles of drought-deciduos phenology model... - ! The 'is_drought' flag is false when leaves are on, and true when leaves area off. - ! The following sets those site-level flags, which are acted on in phenology_deciduos. - ! A* The leaves live for either the length of time the soil moisture is over the threshold - ! or the lifetime of the leaves, whichever is shorter. - ! B*: If the soil is only wet for a very short time, then the leaves stay on for 100 days - ! C*: The leaves are only permitted to come ON for a 60 day window around when they last came on, - ! to prevent 'flickering' on in response to wet season storms - ! D*: We don't allow anything to happen in the first ten days to allow the water memory window - ! to come into equlibirium. - ! E*: If the soil is always wet, the leaves come on at the beginning of the window, and then - ! last for their lifespan. - ! ISSUES - ! 1. It's not clear what water content we should track. Here we are tracking the top layer, - ! but we probably should track something like BTRAN, but BTRAN is defined for each PFT, - ! and there could potentially be more than one stress-dec PFT.... ? - ! 2. In the beginning, the window is set at an arbitrary time of the year, so the leaves - ! might come on in the dry season, using up stored reserves - ! for the stress-dec plants, and potentially killing them. To get around this, - ! we need to read in the 'leaf on' date from some kind of start-up file - ! but we would need that to happen for every resolution, etc. - ! 3. Will this methodology properly kill off the stress-dec trees where there is no - ! water stress? What about where the wet period coincides with the warm period? - ! We would just get them overlapping with the cold-dec trees, even though that isn't appropriate - ! Why don't the drought deciduous trees grow in the North? - ! Is cold decidousness maybe even the same as drought deciduosness there (and so does this - ! distinction actually matter??).... - - ! Accumulate surface water memory of last 10 days. - ! Liquid volume in ground layer (m3/m3) - do i_wmem = 1,numWaterMem-1 !shift memory along one - currentSite%water_memory(numWaterMem+1-i_wmem) = currentSite%water_memory(numWaterMem-i_wmem) - enddo - currentSite%water_memory(1) = bc_in%h2o_liqvol_sl(ilayer_swater) - - ! Calculate the mean water content over the last 10 days (m3/m3) - mean_10day_liqvol = sum(currentSite%water_memory(1:numWaterMem))/real(numWaterMem,r8) - - ! In drought phenology, we often need to force the leaves to stay - ! on or off as moisture fluctuates... - - ! Calculate days since leaves have come off, but make a provision - ! for the first year of simulation, we have to assume a leaf drop - ! date to start, so if that is in the future, set it to last year - - if (model_day_int < currentSite%dleafoffdate) then - dayssincedleafoff = model_day_int - (currentSite%dleafoffdate-365) - else - dayssincedleafoff = model_day_int - currentSite%dleafoffdate - endif - - ! the leaves are on. How long have they been on? - if (model_day_int < currentSite%dleafondate) then - dayssincedleafon = model_day_int - (currentSite%dleafondate-365) - else - dayssincedleafon = model_day_int - currentSite%dleafondate - endif - - ! LEAF ON: DROUGHT DECIDUOUS WETNESS - ! Here, we used a window of oppurtunity to determine if we are - ! close to the time when then leaves came on last year - - ! Has it been ... - ! a) a year, plus or minus 1 month since we last had leaf-on? - ! b) Has there also been at least a nominaly short amount of "leaf-off" - ! c) is the model day at least > 10 (let soil water spin-up) - ! Note that cold-starts begin in the "leaf-on" - ! status - if ( (currentSite%dstatus == phen_dstat_timeoff .or. & - currentSite%dstatus == phen_dstat_moistoff) .and. & - (model_day_int > numWaterMem) .and. & - (dayssincedleafon >= 365-30 .and. dayssincedleafon <= 365+30 ) .and. & - (dayssincedleafoff > ED_val_phen_doff_time) ) then - - ! If leaves are off, and have been off for at least a few days - ! and the time is consistent with the correct - ! time window... test if the moisture conditions allow for leaf-on - - if ( mean_10day_liqvol >= ED_val_phen_drought_threshold ) then - currentSite%dstatus = phen_dstat_moiston ! set status to leaf-on - currentSite%dleafondate = model_day_int ! save the model day we start flushing - dayssincedleafon = 0 - endif - endif - - ! LEAF ON: DROUGHT DECIDUOUS TIME EXCEEDANCE - ! If we still haven't done budburst by end of window, then force it - - ! If the status is "phen_dstat_moistoff", it means this site currently has - ! leaves off due to actual moisture limitations. - ! So we trigger bud-burst at the end of the month since - ! last year's bud-burst. If this is imposed, then we set the new - ! status to indicate bud-burst was forced by timing - - if( currentSite%dstatus == phen_dstat_moistoff ) then - if ( dayssincedleafon > 365+30 ) then - currentSite%dstatus = phen_dstat_timeon ! force budburst! - currentSite%dleafondate = model_day_int ! record leaf on date - dayssincedleafon = 0 - end if - end if - - ! But if leaves are off due to time, then we enforce - ! a longer cool-down (because this is a perrenially wet system) - - if(currentSite%dstatus == phen_dstat_timeoff ) then - if (dayssincedleafoff > min_daysoff_dforcedflush) then - currentSite%dstatus = phen_dstat_timeon ! force budburst! - currentSite%dleafondate = model_day_int ! record leaf on date - dayssincedleafon = 0 - end if - end if - - ! LEAF OFF: DROUGHT DECIDUOUS LIFESPAN - if the leaf gets to - ! the end of its useful life. A*, E* - ! i.e. Are the leaves rouhgly at the end of their lives? - - if ( (currentSite%dstatus == phen_dstat_moiston .or. & - currentSite%dstatus == phen_dstat_timeon ) .and. & - (dayssincedleafon > canopy_leaf_lifespan) )then - currentSite%dstatus = phen_dstat_timeoff !alter status of site to 'leaves off' - currentSite%dleafoffdate = model_day_int !record leaf on date - endif - - ! LEAF OFF: DROUGHT DECIDUOUS DRYNESS - if the soil gets too dry, - ! and the leaves have already been on a while... - - if ( (currentSite%dstatus == phen_dstat_moiston .or. & - currentSite%dstatus == phen_dstat_timeon ) .and. & - (model_day_int > numWaterMem) .and. & - (mean_10day_liqvol <= ED_val_phen_drought_threshold) .and. & - (dayssincedleafon > dleafon_drycheck ) ) then - currentSite%dstatus = phen_dstat_moistoff ! alter status of site to 'leaves off' - currentSite%dleafoffdate = model_day_int ! record leaf on date - endif - - call phenology_leafonoff(currentSite) - - end subroutine phenology - - ! ============================================================================ - subroutine phenology_leafonoff(currentSite) - ! - ! !DESCRIPTION: - ! Controls the leaf on and off economics - ! - ! !USES: - ! - ! !ARGUMENTS: - type(ed_site_type), intent(inout), target :: currentSite - ! - ! !LOCAL VARIABLES: - type(ed_patch_type) , pointer :: currentPatch - type(ed_cohort_type), pointer :: currentCohort - - real(r8) :: leaf_c ! leaf carbon [kg] - real(r8) :: sapw_c ! sapwood carbon [kg] - real(r8) :: struct_c ! structural wood carbon [kg] - real(r8) :: store_c ! storage carbon [kg] - real(r8) :: store_c_transfer_frac ! Fraction of storage carbon used to flush leaves - real(r8) :: totalmemory ! total memory of carbon [kg] - integer :: ipft - real(r8), parameter :: leaf_drop_fraction = 1.0_r8 - real(r8), parameter :: carbon_store_buffer = 0.10_r8 - real(r8) :: stem_drop_fraction - !------------------------------------------------------------------------ - - currentPatch => CurrentSite%oldest_patch - - do while(associated(currentPatch)) - currentCohort => currentPatch%tallest - do while(associated(currentCohort)) - - ipft = currentCohort%pft - - ! Retrieve existing leaf and storage carbon - - if(debug) call currentCohort%prt%CheckMassConservation(ipft,0) - - store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) - leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) - sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) - struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) - - stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(ipft) - - ! COLD LEAF ON - ! The site level flags signify that it is no-longer too cold - ! for leaves. Time to signal flushing - - if (prt_params%season_decid(ipft) == itrue)then - if ( currentSite%cstatus == phen_cstat_notcold )then ! we have just moved to leaves being on . - if (currentCohort%status_coh == leaves_off)then ! Are the leaves currently off? - currentCohort%status_coh = leaves_on ! Leaves are on, so change status to - ! stop flow of carbon out of bstore. - - if(store_c>nearzero) then - ! flush either the amount required from the laimemory, or -most- of the storage pool - ! RF: added a criterion to stop the entire store pool emptying and triggering termination mortality - ! n.b. this might not be necessary if we adopted a more gradual approach to leaf flushing... - store_c_transfer_frac = min((EDPftvarcon_inst%phenflush_fraction(ipft)* & - currentCohort%laimemory)/store_c,(1.0_r8-carbon_store_buffer)) - - if(prt_params%woody(ipft).ne.itrue)then - totalmemory=currentCohort%laimemory+currentCohort%sapwmemory+currentCohort%structmemory - store_c_transfer_frac = min((EDPftvarcon_inst%phenflush_fraction(ipft)* & - totalmemory)/store_c, (1.0_r8-carbon_store_buffer)) - endif - - else - store_c_transfer_frac = 0.0_r8 - end if - - ! This call will request that storage carbon will be transferred to - ! leaf tissues. It is specified as a fraction of the available storage - if(prt_params%woody(ipft) == itrue) then - - call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, store_c_transfer_frac) - currentCohort%laimemory = 0.0_r8 - - else - - ! Check that the stem drop fraction is set to non-zero amount otherwise flush all carbon store to leaves - if (stem_drop_fraction .gt. 0.0_r8) then - - call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & - store_c_transfer_frac*currentCohort%laimemory/totalmemory) - - call PRTPhenologyFlush(currentCohort%prt, ipft, sapw_organ, & - store_c_transfer_frac*currentCohort%sapwmemory/totalmemory) - - call PRTPhenologyFlush(currentCohort%prt, ipft, struct_organ, & - store_c_transfer_frac*currentCohort%structmemory/totalmemory) - - else - - call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & - store_c_transfer_frac) - - end if - - currentCohort%laimemory = 0.0_r8 - currentCohort%structmemory = 0.0_r8 - currentCohort%sapwmemory = 0.0_r8 - - endif - endif !pft phenology - endif ! growing season - - !COLD LEAF OFF - if (currentSite%cstatus == phen_cstat_nevercold .or. & - currentSite%cstatus == phen_cstat_iscold) then ! past leaf drop day? Leaves still on tree? - - if (currentCohort%status_coh == leaves_on) then ! leaves have not dropped - - ! leaf off occur on individuals bigger than specific size for grass - if (currentCohort%dbh > EDPftvarcon_inst%phen_cold_size_threshold(ipft) & - .or. prt_params%woody(ipft)==itrue) then - - ! This sets the cohort to the "leaves off" flag - currentCohort%status_coh = leaves_off - - ! Remember what the lai was (leaf mass actually) was for next year - ! the same amount back on in the spring... - - currentCohort%laimemory = leaf_c - - ! Drop Leaves (this routine will update the leaf state variables, - ! for carbon and any other element that are prognostic. It will - ! also track the turnover masses that will be sent to litter later on) - - call PRTDeciduousTurnover(currentCohort%prt,ipft, & - leaf_organ, leaf_drop_fraction) - - if(prt_params%woody(ipft).ne.itrue)then - - currentCohort%sapwmemory = sapw_c * stem_drop_fraction - - currentCohort%structmemory = struct_c * stem_drop_fraction - - call PRTDeciduousTurnover(currentCohort%prt,ipft, & - sapw_organ, stem_drop_fraction) - - call PRTDeciduousTurnover(currentCohort%prt,ipft, & - struct_organ, stem_drop_fraction) - - endif ! woody plant check - endif ! individual dbh size check - endif !leaf status - endif !currentSite status - endif !season_decid - - ! DROUGHT LEAF ON - ! Site level flag indicates it is no longer in drought condition - ! deciduous plants can flush - - if (prt_params%stress_decid(ipft) == itrue )then - - if (currentSite%dstatus == phen_dstat_moiston .or. & - currentSite%dstatus == phen_dstat_timeon )then - - ! we have just moved to leaves being on . - if (currentCohort%status_coh == leaves_off)then - - !is it the leaf-on day? Are the leaves currently off? - - currentCohort%status_coh = leaves_on ! Leaves are on, so change status to - ! stop flow of carbon out of bstore. - - if(store_c>nearzero) then - - store_c_transfer_frac = & - min((EDPftvarcon_inst%phenflush_fraction(ipft)*currentCohort%laimemory)/store_c, & - (1.0_r8-carbon_store_buffer)) - - if(prt_params%woody(ipft).ne.itrue)then - - totalmemory=currentCohort%laimemory+currentCohort%sapwmemory+currentCohort%structmemory - store_c_transfer_frac = min(EDPftvarcon_inst%phenflush_fraction(ipft)*totalmemory/store_c, & - (1.0_r8-carbon_store_buffer)) - - endif - - else - store_c_transfer_frac = 0.0_r8 - endif - - ! This call will request that storage carbon will be transferred to - ! leaf tissues. It is specified as a fraction of the available storage - if(prt_params%woody(ipft) == itrue) then - - call PRTPhenologyFlush(currentCohort%prt, ipft, & - leaf_organ, store_c_transfer_frac) - - currentCohort%laimemory = 0.0_r8 - - else - - ! Check that the stem drop fraction is set to non-zero amount otherwise flush all carbon store to leaves - if (stem_drop_fraction .gt. 0.0_r8) then - - call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & - store_c_transfer_frac*currentCohort%laimemory/totalmemory) - - call PRTPhenologyFlush(currentCohort%prt, ipft, sapw_organ, & - store_c_transfer_frac*currentCohort%sapwmemory/totalmemory) - - call PRTPhenologyFlush(currentCohort%prt, ipft, struct_organ, & - store_c_transfer_frac*currentCohort%structmemory/totalmemory) - - else - - call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & - store_c_transfer_frac) - - end if - - currentCohort%laimemory = 0.0_r8 - currentCohort%structmemory = 0.0_r8 - currentCohort%sapwmemory = 0.0_r8 - - endif ! woody plant check - endif !currentCohort status again? - endif !currentSite status - - !DROUGHT LEAF OFF - if (currentSite%dstatus == phen_dstat_moistoff .or. & - currentSite%dstatus == phen_dstat_timeoff) then - - if (currentCohort%status_coh == leaves_on) then ! leaves have not dropped - - ! This sets the cohort to the "leaves off" flag - currentCohort%status_coh = leaves_off - - ! Remember what the lai (leaf mass actually) was for next year - currentCohort%laimemory = leaf_c - - call PRTDeciduousTurnover(currentCohort%prt,ipft, & - leaf_organ, leaf_drop_fraction) - - if(prt_params%woody(ipft).ne.itrue)then - - currentCohort%sapwmemory = sapw_c * stem_drop_fraction - currentCohort%structmemory = struct_c * stem_drop_fraction - - call PRTDeciduousTurnover(currentCohort%prt,ipft, & - sapw_organ, stem_drop_fraction) - - call PRTDeciduousTurnover(currentCohort%prt,ipft, & - struct_organ, stem_drop_fraction) - endif - - endif - endif !status - endif !drought dec. - - if(debug) call currentCohort%prt%CheckMassConservation(ipft,1) - - currentCohort => currentCohort%shorter - enddo !currentCohort - - currentPatch => currentPatch%younger - - enddo !currentPatch - - end subroutine phenology_leafonoff - - - ! ===================================================================================== - - subroutine SeedIn( currentSite, bc_in ) - - ! ----------------------------------------------------------------------------------- - ! Flux from plants into the seed pool. - ! It is assumed that allocation to seed on living pools has already been calculated - ! at the daily time step. - ! Note: Some seed generation can occur during disturbance. It is assumed that - ! some plants use their storage upon death to create seeds, but this in only - ! triggered during non-fire and non-logging events. See - ! subroutine mortality_litter_fluxes() and DistributeSeeds(), look for - ! parameter allom_frbstor_repro - ! ----------------------------------------------------------------------------------- - - - ! !USES: - use EDTypesMod, only : area - use EDTypesMod, only : homogenize_seed_pfts - !use FatesInterfaceTypesMod, only : hlm_use_fixed_biogeog ! For future reduced complexity? - ! - ! !ARGUMENTS - type(ed_site_type), intent(inout), target :: currentSite - type(bc_in_type), intent(in) :: bc_in - - type(ed_patch_type), pointer :: currentPatch - type(litter_type), pointer :: litt - type(ed_cohort_type), pointer :: currentCohort - type(site_massbal_type), pointer :: site_mass - - integer :: pft - real(r8) :: store_m_to_repro ! mass sent from storage to reproduction upon death [kg/plant] - real(r8) :: site_seed_rain(maxpft) ! This is the sum of seed-rain for the site [kg/site/day] - real(r8) :: seed_in_external ! Mass of externally generated seeds [kg/m2/day] - real(r8) :: seed_stoich ! Mass ratio of nutrient per C12 in seeds [kg/kg] - real(r8) :: seed_prod ! Seed produced in this dynamics step [kg/day] - integer :: n_litt_types ! number of litter element types (c,n,p, etc) - integer :: el ! loop counter for litter element types - integer :: element_id ! element id consistent with parteh/PRTGenericMod.F90 - - - !YL--------- - real(r8) :: site_seed_out(maxpft) ! The sum of seed-rain leaving the site [kg/site/day] - real(r8) :: disp_frac(maxpft) ! fraction of seed-rain among the site_seed_rain that's leaving the site [unitless] - !----------- - - do el = 1, num_elements - - site_seed_rain(:) = 0._r8 - - !YL------- - site_seed_out(:) = 0._r8 ! seed-rain leaving the site, 05/21 - disp_frac(:) = 0.4 ! to be specified in the parameter file or calculated using dispersal kernel - !--------- - - element_id = element_list(el) - - site_mass => currentSite%mass_balance(el) - - ! Loop over all patches and sum up the seed input for each PFT - currentPatch => currentSite%oldest_patch - do while (associated(currentPatch)) - - currentCohort => currentPatch%tallest - do while (associated(currentCohort)) - - pft = currentCohort%pft - - ! a certain fraction of bstore might go to clonal reproduction when plants die - ! (since this is only applied to the dying portion of the cohort - ! we do not actually pair down the storage via PARTEH, instead - ! we just make sure that we don't send a portion of the storage - ! to the litter in CWDInput) - ! units = [kg/ha/day] = [kg] * [fraction] * [plants/ha/year] * [year/day] - store_m_to_repro = -currentCohort%prt%GetState(store_organ,element_id) * & - EDPftvarcon_inst%allom_frbstor_repro(pft)*currentCohort%dndt*years_per_day - - ! Transfer all reproductive tissues into seed production - ! The following call to PRTReproRelease, will return the mass - ! of seeds [kg] released by the plant, per the mass_fraction - ! specified as input. This routine will also remove the mass - ! from the parteh state-variable. - - call PRTReproRelease(currentCohort%prt,repro_organ,element_id, & - 1.0_r8, seed_prod) - - if(element_id==carbon12_element)then - currentcohort%seed_prod = seed_prod - end if - - !YL---------- - - !site_seed_rain(pft) = site_seed_rain(pft) + & - ! (seed_prod * currentCohort%n + store_m_to_repro) - - site_seed_rain(pft) = site_seed_rain(pft) + & - (seed_prod * currentCohort%n + store_m_to_repro)*(1-disp_frac(pft)) - site_seed_out(pft) = site_seed_out(pft) + & - (seed_prod * currentCohort%n + store_m_to_repro)*disp_frac(pft) - - write(fates_log(),*) 'pft, site_seed_rain(pft), site_seed_out(pft):', pft, site_seed_rain(pft), site_seed_out(pft) - - !----------- - - currentCohort => currentCohort%shorter - enddo !cohort loop - - currentPatch => currentPatch%younger - enddo - - ! We can choose to homogenize seeds. This is simple, we just - ! add up all the seed from each pft at the site level, and then - ! equally distribute to the PFT pools - if ( homogenize_seed_pfts ) then - site_seed_rain(1:numpft) = sum(site_seed_rain(:))/real(numpft,r8) - end if - - - ! Loop over all patches again and disperse the mixed seeds into the input flux - ! arrays - - ! Loop over all patches and sum up the seed input for each PFT - currentPatch => currentSite%oldest_patch - do while (associated(currentPatch)) - - litt => currentPatch%litter(el) - do pft = 1,numpft - - if(currentSite%use_this_pft(pft).eq.itrue)then - ! Seed input from local sources (within site) - litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)/area - - ! If there is forced external seed rain, we calculate the input mass flux - ! from the different elements, usung the seed optimal stoichiometry - ! for non-carbon - select case(element_id) - case(carbon12_element) - seed_stoich = 1._r8 - case(nitrogen_element) - seed_stoich = prt_params%nitr_stoich_p2(pft,repro_organ) - case(phosphorus_element) - seed_stoich = prt_params%phos_stoich_p2(pft,repro_organ) - case default - write(fates_log(), *) 'undefined element specified' - write(fates_log(), *) 'while defining forced external seed mass flux' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end select - - ! Seed input from external sources (user param seed rain, or dispersal model) - seed_in_external = seed_stoich*EDPftvarcon_inst%seed_suppl(pft)*years_per_day - litt%seed_in_extern(pft) = litt%seed_in_extern(pft) + seed_in_external - - ! Seeds entering externally [kg/site/day] - site_mass%seed_in = site_mass%seed_in + seed_in_external*currentPatch%area - write(fates_log(),*) 'pft, equivalent seed_suppl: ', pft, site_mass%seed_in/currentPatch%area/seed_stoich/years_per_day - end if !use this pft - enddo - - - currentPatch => currentPatch%younger - enddo - - end do - - return - end subroutine SeedIn - - ! ============================================================================ - - subroutine SeedDecay( litt ) - ! - ! !DESCRIPTION: - ! Flux from seed pool into leaf litter pool - ! - ! !ARGUMENTS - type(litter_type) :: litt - ! - ! !LOCAL VARIABLES: - integer :: pft - !---------------------------------------------------------------------- - - ! default value from Liscke and Loffler 2006 ; making this a PFT-specific parameter - ! decays the seed pool according to exponential model - ! seed_decay_rate is in yr-1 - ! seed_decay is kg/day - ! Assume that decay rates are same for all chemical species - - do pft = 1,numpft - litt%seed_decay(pft) = litt%seed(pft) * & - EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day - - litt%seed_germ_decay(pft) = litt%seed_germ(pft) * & - EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day - - enddo - - return - end subroutine SeedDecay - - ! ============================================================================ - subroutine SeedGermination( litt, cold_stat, drought_stat ) - ! - ! !DESCRIPTION: - ! Flux from seed pool into sapling pool - ! - ! !USES: - - ! - ! !ARGUMENTS - type(litter_type) :: litt - integer, intent(in) :: cold_stat ! Is the site in cold leaf-off status? - integer, intent(in) :: drought_stat ! Is the site in drought leaf-off status? - ! - ! !LOCAL VARIABLES: - integer :: pft - - - real(r8), parameter :: max_germination = 1.0_r8 ! Cap on germination rates. - ! KgC/m2/yr Lishcke et al. 2009 - - ! Turning of this cap? because the cap will impose changes on proportionality - ! of nutrients. (RGK 02-2019) - !real(r8), parameter :: max_germination = 1.e6_r8 ! Force to very high number - - !---------------------------------------------------------------------- - - ! germination_rate is being pulled to PFT parameter; units are 1/yr - ! thus the mortality rate of seed -> recruit (in units of carbon) - ! is seed_decay_rate(p)/germination_rate(p) - ! and thus the mortality rate (in units of individuals) is the product of - ! that times the ratio of (hypothetical) seed mass to recruit biomass - - do pft = 1,numpft - litt%seed_germ_in(pft) = min(litt%seed(pft) * EDPftvarcon_inst%germination_rate(pft), & - max_germination)*years_per_day - - !set the germination only under the growing season...c.xu - - if ((prt_params%season_decid(pft) == itrue ) .and. & - (any(cold_stat == [phen_cstat_nevercold,phen_cstat_iscold]))) then - - ! no germination for all PFTs when cold. YL 03/22/2018 -! if (any(cold_stat == [phen_cstat_nevercold,phen_cstat_iscold])) then - litt%seed_germ_in(pft) = 0.0_r8 - endif - if ((prt_params%stress_decid(pft) == itrue ) .and. & - (any(drought_stat == [phen_dstat_timeoff,phen_dstat_moistoff]))) then - litt%seed_germ_in(pft) = 0.0_r8 - end if - - - enddo - - end subroutine SeedGermination - - ! ===================================================================================== - - - - - - ! ===================================================================================== - - ! subroutine recruitment( currentSite, currentPatch, bc_in ) - ! YL------- pass in bc_out - subroutine recruitment( currentSite, currentPatch, bc_in , bc_out ) - ! - ! !DESCRIPTION: - ! spawn new cohorts of juveniles of each PFT - ! - ! !USES: - use FatesInterfaceTypesMod, only : hlm_use_ed_prescribed_phys - ! - ! !ARGUMENTS - type(ed_site_type), intent(inout), target :: currentSite - type(ed_patch_type), intent(inout), pointer :: currentPatch - type(bc_in_type), intent(in) :: bc_in - type(bc_out_type), intent(inout) :: bc_out - ! - ! !LOCAL VARIABLES: - class(prt_vartypes), pointer :: prt - integer :: ft - type (ed_cohort_type) , pointer :: temp_cohort - type (litter_type), pointer :: litt ! The litter object (carbon right now) - type(site_massbal_type), pointer :: site_mass ! For accounting total in-out mass fluxes - integer :: cohortstatus - integer :: el ! loop counter for element - integer :: element_id ! element index consistent with definitions in PRTGenericMod - integer :: iage ! age loop counter for leaf age bins - integer,parameter :: recruitstatus = 1 !weather it the new created cohorts is recruited or initialized - real(r8) :: c_leaf ! target leaf biomass [kgC] - real(r8) :: c_fnrt ! target fine root biomass [kgC] - real(r8) :: c_sapw ! target sapwood biomass [kgC] - real(r8) :: a_sapw ! target sapwood cross section are [m2] (dummy) - real(r8) :: c_agw ! target Above ground biomass [kgC] - real(r8) :: c_bgw ! target Below ground biomass [kgC] - real(r8) :: c_struct ! target Structural biomass [kgc] - real(r8) :: c_store ! target Storage biomass [kgC] - real(r8) :: m_leaf ! leaf mass (element agnostic) [kg] - real(r8) :: m_fnrt ! fine-root mass (element agnostic) [kg] - real(r8) :: m_sapw ! sapwood mass (element agnostic) [kg] - real(r8) :: m_agw ! AG wood mass (element agnostic) [kg] - real(r8) :: m_bgw ! BG wood mass (element agnostic) [kg] - real(r8) :: m_struct ! structural mass (element agnostic) [kg] - real(r8) :: m_store ! storage mass (element agnostic) [kg] - real(r8) :: m_repro ! reproductive mass (element agnostic) [kg] - real(r8) :: mass_avail ! The mass of each nutrient/carbon available in the seed_germination pool [kg] - real(r8) :: mass_demand ! Total mass demanded by the plant to achieve the stoichiometric targets - ! of all the organs in the recruits. Used for both [kg per plant] and [kg per cohort] - real(r8) :: stem_drop_fraction - - !---------------------------------------------------------------------- - - allocate(temp_cohort) ! create temporary cohort - call zero_cohort(temp_cohort) - - - do ft = 1,numpft - if(currentSite%use_this_pft(ft).eq.itrue)then - temp_cohort%canopy_trim = 0.8_r8 !starting with the canopy not fully expanded - temp_cohort%pft = ft - temp_cohort%hite = EDPftvarcon_inst%hgt_min(ft) - temp_cohort%coage = 0.0_r8 - stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(ft) - - call h2d_allom(temp_cohort%hite,ft,temp_cohort%dbh) - - ! Initialize live pools - call bleaf(temp_cohort%dbh,ft,temp_cohort%canopy_trim,c_leaf) - call bfineroot(temp_cohort%dbh,ft,temp_cohort%canopy_trim,c_fnrt) - call bsap_allom(temp_cohort%dbh,ft,temp_cohort%canopy_trim,a_sapw, c_sapw) - call bagw_allom(temp_cohort%dbh,ft,c_agw) - call bbgw_allom(temp_cohort%dbh,ft,c_bgw) - call bdead_allom(c_agw,c_bgw,c_sapw,ft,c_struct) - call bstore_allom(temp_cohort%dbh,ft,temp_cohort%canopy_trim,c_store) - - ! Default assumption is that leaves are on - cohortstatus = leaves_on - temp_cohort%laimemory = 0.0_r8 - temp_cohort%sapwmemory = 0.0_r8 - temp_cohort%structmemory = 0.0_r8 - - - ! But if the plant is seasonally (cold) deciduous, and the site status is flagged - ! as "cold", then set the cohort's status to leaves_off, and remember the leaf biomass - if ((prt_params%season_decid(ft) == itrue) .and. & - (any(currentSite%cstatus == [phen_cstat_nevercold,phen_cstat_iscold]))) then - temp_cohort%laimemory = c_leaf - c_leaf = 0.0_r8 - - ! If plant is not woody then set sapwood and structural biomass as well - if (prt_params%woody(ft).ne.itrue) then - temp_cohort%sapwmemory = c_sapw * stem_drop_fraction - temp_cohort%structmemory = c_struct * stem_drop_fraction - c_sapw = (1.0_r8 - stem_drop_fraction) * c_sapw - c_struct = (1.0_r8 - stem_drop_fraction) * c_struct - endif - cohortstatus = leaves_off - endif - - ! Or.. if the plant is drought deciduous, and the site status is flagged as - ! "in a drought", then likewise, set the cohort's status to leaves_off, and remember leaf - ! biomass - if ((prt_params%stress_decid(ft) == itrue) .and. & - (any(currentSite%dstatus == [phen_dstat_timeoff,phen_dstat_moistoff]))) then - temp_cohort%laimemory = c_leaf - c_leaf = 0.0_r8 - - ! If plant is not woody then set sapwood and structural biomass as well - if(prt_params%woody(ft).ne.itrue)then - temp_cohort%sapwmemory = c_sapw * stem_drop_fraction - temp_cohort%structmemory = c_struct * stem_drop_fraction - c_sapw = (1.0_r8 - stem_drop_fraction) * c_sapw - c_struct = (1.0_r8 - stem_drop_fraction) * c_struct - endif - cohortstatus = leaves_off - endif - - - ! Cycle through available carbon and nutrients, find the limiting element - ! to dictate the total number of plants that can be generated - - if ( (hlm_use_ed_prescribed_phys .eq. ifalse) .or. & - (EDPftvarcon_inst%prescribed_recruitment(ft) .lt. 0._r8) ) then - - temp_cohort%n = 1.e10_r8 - - do el = 1,num_elements - - element_id = element_list(el) - select case(element_id) - case(carbon12_element) - - mass_demand = (c_struct+c_leaf+c_fnrt+c_sapw+c_store) - - case(nitrogen_element) - - mass_demand = c_struct*prt_params%nitr_stoich_p1(ft,struct_organ) + & - c_leaf*prt_params%nitr_stoich_p1(ft,leaf_organ) + & - c_fnrt*prt_params%nitr_stoich_p1(ft,fnrt_organ) + & - c_sapw*prt_params%nitr_stoich_p1(ft,sapw_organ) + & - c_store*prt_params%nitr_stoich_p1(ft,store_organ) - - case(phosphorus_element) - - mass_demand = c_struct*prt_params%phos_stoich_p1(ft,struct_organ) + & - c_leaf*prt_params%phos_stoich_p1(ft,leaf_organ) + & - c_fnrt*prt_params%phos_stoich_p1(ft,fnrt_organ) + & - c_sapw*prt_params%phos_stoich_p1(ft,sapw_organ) + & - c_store*prt_params%phos_stoich_p1(ft,store_organ) - - case default - write(fates_log(),*) 'Undefined element type in recruitment' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end select - - mass_avail = currentPatch%area * currentPatch%litter(el)%seed_germ(ft) - - ! ------------------------------------------------------------------------ - ! Update number density if this is the limiting mass - ! ------------------------------------------------------------------------ - - temp_cohort%n = min(temp_cohort%n, mass_avail/mass_demand) - - end do - - - else - ! prescribed recruitment rates. number per sq. meter per year - temp_cohort%n = currentPatch%area * & - EDPftvarcon_inst%prescribed_recruitment(ft) * & - hlm_freq_day - endif - - ! Only bother allocating a new cohort if there is a reasonable amount of it - if (temp_cohort%n > min_n_safemath )then - - ! ----------------------------------------------------------------------------- - ! PART II. - ! Initialize the PARTEH object, and determine the initial masses of all - ! organs and elements. - ! ----------------------------------------------------------------------------- - prt => null() - call InitPRTObject(prt) - - do el = 1,num_elements - - element_id = element_list(el) - - ! If this is carbon12, then the initialization is straight forward - ! otherwise, we use stoichiometric ratios - select case(element_id) - case(carbon12_element) - - m_struct = c_struct - m_leaf = c_leaf - m_fnrt = c_fnrt - m_sapw = c_sapw - m_store = c_store - m_repro = 0._r8 - - case(nitrogen_element) - - m_struct = c_struct*prt_params%nitr_stoich_p1(ft,struct_organ) - m_leaf = c_leaf*prt_params%nitr_stoich_p1(ft,leaf_organ) - m_fnrt = c_fnrt*prt_params%nitr_stoich_p1(ft,fnrt_organ) - m_sapw = c_sapw*prt_params%nitr_stoich_p1(ft,sapw_organ) - m_store = c_store*prt_params%nitr_stoich_p1(ft,store_organ) - m_repro = 0._r8 - - case(phosphorus_element) - - m_struct = c_struct*prt_params%phos_stoich_p1(ft,struct_organ) - m_leaf = c_leaf*prt_params%phos_stoich_p1(ft,leaf_organ) - m_fnrt = c_fnrt*prt_params%phos_stoich_p1(ft,fnrt_organ) - m_sapw = c_sapw*prt_params%phos_stoich_p1(ft,sapw_organ) - m_store = c_store*prt_params%phos_stoich_p1(ft,store_organ) - m_repro = 0._r8 - - end select - - select case(hlm_parteh_mode) - case (prt_carbon_allom_hyp,prt_cnp_flex_allom_hyp ) - - ! Put all of the leaf mass into the first bin - call SetState(prt,leaf_organ, element_id,m_leaf,1) - do iage = 2,nleafage - call SetState(prt,leaf_organ, element_id,0._r8,iage) - end do - - call SetState(prt,fnrt_organ, element_id, m_fnrt) - call SetState(prt,sapw_organ, element_id, m_sapw) - call SetState(prt,store_organ, element_id, m_store) - call SetState(prt,struct_organ, element_id, m_struct) - call SetState(prt,repro_organ, element_id, m_repro) - - case default - write(fates_log(),*) 'Unspecified PARTEH module during create_cohort' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end select - - site_mass => currentSite%mass_balance(el) - - ! Remove mass from the germination pool. However, if we are use prescribed physiology, - ! AND the forced recruitment model, then we are not realling using the prognostic - ! seed_germination model, so we have to short circuit things. We send all of the - ! seed germination mass to an outflux pool, and use an arbitrary generic input flux - ! to balance out the new recruits. - - if ( (hlm_use_ed_prescribed_phys .eq. itrue ) .and. & - (EDPftvarcon_inst%prescribed_recruitment(ft) .ge. 0._r8 )) then - - site_mass%flux_generic_in = site_mass%flux_generic_in + & - temp_cohort%n*(m_struct + m_leaf + m_fnrt + m_sapw + m_store + m_repro) - - site_mass%flux_generic_out = site_mass%flux_generic_out + & - currentPatch%area * currentPatch%litter(el)%seed_germ(ft) - - currentPatch%litter(el)%seed_germ(ft) = 0._r8 - - - else - - currentPatch%litter(el)%seed_germ(ft) = currentPatch%litter(el)%seed_germ(ft) - & - temp_cohort%n / currentPatch%area * & - (m_struct + m_leaf + m_fnrt + m_sapw + m_store + m_repro) - - end if - - - - end do - - ! This call cycles through the initial conditions, and makes sure that they - ! are all initialized. - ! ----------------------------------------------------------------------------------- - - call prt%CheckInitialConditions() - - ! This initializes the cohort - call create_cohort(currentSite,currentPatch, temp_cohort%pft, temp_cohort%n, & - temp_cohort%hite, temp_cohort%coage, temp_cohort%dbh, prt, & - temp_cohort%laimemory, temp_cohort%sapwmemory, temp_cohort%structmemory, & - cohortstatus, recruitstatus, & - temp_cohort%canopy_trim, currentPatch%NCL_p, currentSite%spread, bc_in) - - ! Note that if hydraulics is on, the number of cohorts may had - ! changed due to hydraulic constraints. - ! This constaint is applied during "create_cohort" subroutine. - - ! keep track of how many individuals were recruited for passing to history - currentSite%recruitment_rate(ft) = currentSite%recruitment_rate(ft) + temp_cohort%n - - - endif - endif !use_this_pft - enddo !pft loop - - deallocate(temp_cohort) ! delete temporary cohort - - end subroutine recruitment - - ! ============================================================================ - - subroutine CWDInput( currentSite, currentPatch, litt) - - ! - ! !DESCRIPTION: - ! Generate litter fields from turnover. - ! Note, that the when this is called, the number density of the plants - ! has not been reduced from non-mortal turnover yet. - ! Thus, we need to avoid double counting losses from dying trees - ! and turnover in dying trees. - ! - ! !USES: - use SFParamsMod , only : SF_val_CWD_frac - - ! - ! !ARGUMENTS - type(ed_site_type), intent(inout), target :: currentSite - type(ed_patch_type),intent(inout), target :: currentPatch - type(litter_type),intent(inout),target :: litt - - - ! - ! !LOCAL VARIABLES: - type(ed_cohort_type), pointer :: currentCohort - type(site_fluxdiags_type), pointer :: flux_diags - type(site_massbal_type), pointer :: site_mass - integer :: c - real(r8) :: dead_n ! total understorey dead tree density - real(r8) :: dead_n_dlogging ! direct logging understory dead-tree density - real(r8) :: dead_n_ilogging ! indirect understory dead-tree density (logging) - real(r8) :: dead_n_natural ! understory dead density not associated - ! with direct logging - real(r8) :: leaf_m ! mass of the element of interest in the - ! leaf [kg] - real(r8) :: fnrt_m ! fine-root [kg] - real(r8) :: sapw_m ! sapwood [kg] - real(r8) :: struct_m ! structural [kg] - real(r8) :: store_m ! storage [kg] - real(r8) :: repro_m ! reproductive [kg] - real(r8) :: leaf_m_turnover ! leaf turnover [kg] - real(r8) :: fnrt_m_turnover - real(r8) :: sapw_m_turnover - real(r8) :: struct_m_turnover - real(r8) :: store_m_turnover - real(r8) :: repro_m_turnover - real(r8) :: dcmpy_frac ! Fraction of mass sent to decomposability pool - real(r8) :: plant_dens ! Number of plants per m2 - real(r8) :: bg_cwd_tot ! Total below-ground coarse woody debris - ! input flux - real(r8) :: root_fines_tot ! Total below-ground fine root coarse - ! woody debris - integer :: element_id ! element id consistent with parteh/PRTGenericMod.F90 - - real(r8) :: trunk_wood ! carbon flux into trunk products kgC/day/site - integer :: ilyr - integer :: pft - integer :: dcmpy ! decomposability pool index - integer :: numlevsoil ! Actual number of soil layers - !---------------------------------------------------------------------- - - ! ----------------------------------------------------------------------------------- - ! Other direct litter fluxes happen in phenology and in spawn_patches. - ! ----------------------------------------------------------------------------------- - - numlevsoil = currentSite%nlevsoil - - element_id = litt%element_id - - ! Object tracking flux diagnostics for each element - flux_diags => currentSite%flux_diags(element_pos(element_id)) - - ! Object tracking site level mass balance for each element - site_mass => currentSite%mass_balance(element_pos(element_id)) - - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - pft = currentCohort%pft - - call set_root_fraction(currentSite%rootfrac_scr, pft, currentSite%zi_soil) - - leaf_m_turnover = currentCohort%prt%GetTurnover(leaf_organ,element_id) - store_m_turnover = currentCohort%prt%GetTurnover(store_organ,element_id) - fnrt_m_turnover = currentCohort%prt%GetTurnover(fnrt_organ,element_id) - sapw_m_turnover = currentCohort%prt%GetTurnover(sapw_organ,element_id) - struct_m_turnover = currentCohort%prt%GetTurnover(struct_organ,element_id) - repro_m_turnover = currentCohort%prt%GetTurnover(repro_organ,element_id) - - leaf_m = currentCohort%prt%GetState(leaf_organ,element_id) - store_m = currentCohort%prt%GetState(store_organ,element_id) - fnrt_m = currentCohort%prt%GetState(fnrt_organ,element_id) - sapw_m = currentCohort%prt%GetState(sapw_organ,element_id) - struct_m = currentCohort%prt%GetState(struct_organ,element_id) - repro_m = currentCohort%prt%GetState(repro_organ,element_id) - - plant_dens = currentCohort%n/currentPatch%area - - ! --------------------------------------------------------------------------------- - ! PART 1 Litter fluxes from non-mortal tissue turnovers Kg/m2/day - ! Important note: Turnover has already been removed from the cohorts. - ! So, in the next part of this algorithm, when we send the biomass - ! from dying trees to the litter pools, we don't have to worry - ! about double counting. - ! --------------------------------------------------------------------------------- - - flux_diags%leaf_litter_input(pft) = & - flux_diags%leaf_litter_input(pft) + & - leaf_m_turnover * currentCohort%n - - root_fines_tot = (fnrt_m_turnover + store_m_turnover ) * & - plant_dens - - 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 - - dcmpy_frac = GetDecompyFrac(pft,fnrt_organ,dcmpy) - do ilyr = 1, numlevsoil - litt%root_fines_in(dcmpy,ilyr) = litt%root_fines_in(dcmpy,ilyr) + & - currentSite%rootfrac_scr(ilyr) * root_fines_tot * dcmpy_frac - end do - end do - - flux_diags%root_litter_input(pft) = & - flux_diags%root_litter_input(pft) + & - (fnrt_m_turnover + store_m_turnover ) * currentCohort%n - - - ! Assumption: turnover from deadwood and sapwood are lumped together in CWD pool - - do c = 1,ncwd - litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + & - (sapw_m_turnover + struct_m_turnover) * & - SF_val_CWD_frac(c) * plant_dens * & - prt_params%allom_agb_frac(pft) - - flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & - (struct_m_turnover + sapw_m_turnover) * SF_val_CWD_frac(c) * & - prt_params%allom_agb_frac(pft) * currentCohort%n - - bg_cwd_tot = (sapw_m_turnover + struct_m_turnover) * & - SF_val_CWD_frac(c) * plant_dens * & - (1.0_r8-prt_params%allom_agb_frac(pft)) - - do ilyr = 1, numlevsoil - litt%bg_cwd_in(c,ilyr) = litt%bg_cwd_in(c,ilyr) + & - bg_cwd_tot * currentSite%rootfrac_scr(ilyr) - end do - - flux_diags%cwd_bg_input(c) = flux_diags%cwd_bg_input(c) + & - bg_cwd_tot*currentPatch%area - - enddo - - - ! --------------------------------------------------------------------------------- - ! PART 2 Litter fluxes from non-disturbance inducing mortality. Kg/m2/day - ! --------------------------------------------------------------------------------- - - ! Total number of dead (n/m2/day) - dead_n = -1.0_r8 * currentCohort%dndt/currentPatch%area*years_per_day - - if(currentCohort%canopy_layer > 1)then - - ! Total number of dead understory from direct logging - ! (it is possible that large harvestable trees are in the understory) - dead_n_dlogging = currentCohort%lmort_direct * & - currentCohort%n/currentPatch%area - - ! Total number of dead understory from indirect logging - dead_n_ilogging = (currentCohort%lmort_collateral + currentCohort%lmort_infra) * & - currentCohort%n/currentPatch%area - - else - - ! All mortality from logging in the canopy is - ! is disturbance generating - - dead_n_dlogging = 0._r8 - dead_n_ilogging = 0._r8 - - end if - - dead_n_natural = dead_n - dead_n_dlogging - dead_n_ilogging - - - flux_diags%leaf_litter_input(pft) = & - flux_diags%leaf_litter_input(pft) + & - leaf_m * dead_n*currentPatch%area - - - ! %n has not been updated due to mortality yet, thus - ! the litter flux has already been counted since it captured - ! the losses of live trees and those flagged for death - - root_fines_tot = dead_n * (fnrt_m + & - store_m*(1._r8-EDPftvarcon_inst%allom_frbstor_repro(pft)) ) - - do dcmpy=1,ndcmpy - - dcmpy_frac = GetDecompyFrac(pft,leaf_organ,dcmpy) - litt%leaf_fines_in(dcmpy) = litt%leaf_fines_in(dcmpy) + & - (leaf_m+repro_m) * dead_n * dcmpy_frac - - dcmpy_frac = GetDecompyFrac(pft,fnrt_organ,dcmpy) - do ilyr = 1, numlevsoil - litt%root_fines_in(dcmpy,ilyr) = litt%root_fines_in(dcmpy,ilyr) + & - root_fines_tot * currentSite%rootfrac_scr(ilyr) * dcmpy_frac - end do - end do - - flux_diags%root_litter_input(pft) = & - flux_diags%root_litter_input(pft) + & - root_fines_tot*currentPatch%area - - ! Track CWD inputs from dead plants - - do c = 1,ncwd - - ! Below-ground - - bg_cwd_tot = (struct_m + sapw_m) * & - SF_val_CWD_frac(c) * dead_n * & - (1.0_r8-prt_params%allom_agb_frac(pft)) - - do ilyr = 1, numlevsoil - litt%bg_cwd_in(c,ilyr) = litt%bg_cwd_in(c,ilyr) + & - currentSite%rootfrac_scr(ilyr) * bg_cwd_tot - end do - - flux_diags%cwd_bg_input(c) = flux_diags%cwd_bg_input(c) + & - bg_cwd_tot * currentPatch%area - - ! Send AGB component of boles from logging activities into the litter. - ! This includes fluxes from indirect modes of death, as well as the - ! non-exported boles due to direct harvesting. - - if (c==ncwd) then - - - trunk_wood = (struct_m + sapw_m) * & - SF_val_CWD_frac(c) * dead_n_dlogging * & - prt_params%allom_agb_frac(pft) - - site_mass%wood_product = site_mass%wood_product + & - trunk_wood * currentPatch%area * logging_export_frac - - ! Add AG wood to litter from the non-exported fraction of wood - ! from direct anthro sources - - litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + & - trunk_wood * (1._r8-logging_export_frac) - - flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & - trunk_wood * (1._r8-logging_export_frac) * currentPatch%area - - ! Add AG wood to litter from indirect anthro sources - - litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + (struct_m + sapw_m) * & - SF_val_CWD_frac(c) * (dead_n_natural+dead_n_ilogging) * & - prt_params%allom_agb_frac(pft) - - flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & - SF_val_CWD_frac(c) * (dead_n_natural+dead_n_ilogging) * & - currentPatch%area * prt_params%allom_agb_frac(pft) - - else - - litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + (struct_m + sapw_m) * & - SF_val_CWD_frac(c) * dead_n * & - prt_params%allom_agb_frac(pft) - - flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & - SF_val_CWD_frac(c) * dead_n * (struct_m + sapw_m) * & - currentPatch%area * prt_params%allom_agb_frac(pft) - - end if - - end do - - - ! Update diagnostics that track resource management - - if( element_id .eq. carbon12_element ) then - - currentSite%resources_management%delta_litter_stock = & - currentSite%resources_management%delta_litter_stock + & - (leaf_m + fnrt_m + store_m ) * & - (dead_n_ilogging+dead_n_dlogging) * currentPatch%area - - currentSite%resources_management%delta_biomass_stock = & - currentSite%resources_management%delta_biomass_stock + & - (leaf_m + fnrt_m + store_m ) * & - (dead_n_ilogging+dead_n_dlogging) *currentPatch%area - - currentSite%resources_management%trunk_product_site = & - currentSite%resources_management%trunk_product_site + & - trunk_wood * logging_export_frac * currentPatch%area - - do c = 1,ncwd - currentSite%resources_management%delta_litter_stock = & - currentSite%resources_management%delta_litter_stock + & - (struct_m + sapw_m) * & - SF_val_CWD_frac(c) * (dead_n_natural+dead_n_ilogging) * & - currentPatch%area - - currentSite%resources_management%delta_biomass_stock = & - currentSite%resources_management%delta_biomass_stock + & - (struct_m + sapw_m) * & - SF_val_CWD_frac(c) * dead_n * currentPatch%area - end do - - ! Update diagnostics that track resource management - currentSite%resources_management%delta_individual = & - currentSite%resources_management%delta_individual + & - (dead_n_dlogging+dead_n_ilogging) * hlm_freq_day * currentPatch%area - end if - - - currentCohort => currentCohort%taller - enddo ! end loop over cohorts - - - return - end subroutine CWDInput - - ! ===================================================================================== - - subroutine SeedDecayToFines(litt) - - type(litter_type) :: litt - ! - ! !LOCAL VARIABLES: - integer :: pft - - ! Add decaying seeds to the leaf litter - ! ----------------------------------------------------------------------------------- - - do pft = 1,numpft - - litt%leaf_fines_in(ilabile) = litt%leaf_fines_in(ilabile) + & - (litt%seed_decay(pft) + litt%seed_germ_decay(pft)) * EDPftvarcon_inst%lf_flab(pft) - - litt%leaf_fines_in(icellulose) = litt%leaf_fines_in(icellulose) + & - (litt%seed_decay(pft) + litt%seed_germ_decay(pft)) * EDPftvarcon_inst%lf_fcel(pft) - - litt%leaf_fines_in(ilignin) = litt%leaf_fines_in(ilignin) + & - (litt%seed_decay(pft) + litt%seed_germ_decay(pft)) * EDPftvarcon_inst%lf_flig(pft) - - enddo - - - return - end subroutine SeedDecayToFines - - - - - - ! ===================================================================================== - - subroutine fragmentation_scaler( currentPatch, bc_in) - ! - ! !DESCRIPTION: - ! Simple CWD fragmentation Model - ! FIX(SPM, 091914) this should be a function as it returns a value in - ! currentPatch%fragmentation_scaler - ! - ! !USES: - - use FatesSynchronizedParamsMod , only : FatesSynchronizedParamsInst - use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm - use FatesConstantsMod, only : pi => pi_const - ! - ! !ARGUMENTS - type(ed_patch_type), intent(inout) :: currentPatch - type(bc_in_type), intent(in) :: bc_in - - ! - ! !LOCAL VARIABLES: - logical :: use_century_tfunc = .false. - logical :: use_hlm_soil_scalar = .true. ! Use hlm input decomp fraction scalars - integer :: j - integer :: ifp ! Index of a FATES Patch "ifp" - real(r8) :: t_scalar ! temperature scalar - real(r8) :: w_scalar ! moisture scalar - real(r8) :: catanf ! hyperbolic temperature function from CENTURY - real(r8) :: catanf_30 ! hyperbolic temperature function from CENTURY - real(r8) :: t1 ! temperature argument - !---------------------------------------------------------------------- - - catanf(t1) = 11.75_r8 +(29.7_r8 / pi) * atan( pi * 0.031_r8 * ( t1 - 15.4_r8 )) - catanf_30 = catanf(30._r8) - - ifp = currentPatch%patchno - - ! Use the hlm temp and moisture decomp fractions by default - if ( use_hlm_soil_scalar ) then - - ! Calculate the fragmentation_scaler - currentPatch%fragmentation_scaler = min(1.0_r8,max(0.0_r8,bc_in%t_scalar_sisl * bc_in%w_scalar_sisl)) - - else - - if ( .not. use_century_tfunc ) then - !calculate rate constant scalar for soil temperature,assuming that the base rate constants - !are assigned for non-moisture limiting conditions at 25C. - if (bc_in%t_veg24_pa(ifp) >= tfrz) then - t_scalar = q10_mr**((bc_in%t_veg24_pa(ifp)-(tfrz+25._r8))/10._r8) - ! Q10**((t_soisno(c,j)-(tfrz+25._r8))/10._r8) - else - t_scalar = (q10_mr**(-25._r8/10._r8))*(q10_froz**((bc_in%t_veg24_pa(ifp)-tfrz)/10._r8)) - !Q10**(-25._r8/10._r8))*(froz_q10**((t_soisno(c,j)-tfrz)/10._r8) - endif - else - ! original century uses an arctangent function to calculate the - ! temperature dependence of decomposition - t_scalar = max(catanf(bc_in%t_veg24_pa(ifp)-tfrz)/catanf_30,0.01_r8) - endif - - !Moisture Limitations - !BTRAN APPROACH - is quite simple, but max's out decomp at all unstressed - !soil moisture values, which is not realistic. - !litter decomp is proportional to water limitation on average... - w_scalar = sum(currentPatch%btran_ft(1:numpft))/real(numpft,r8) - - ! Calculate the fragmentation_scaler - currentPatch%fragmentation_scaler(:) = min(1.0_r8,max(0.0_r8,t_scalar * w_scalar)) - - endif - - - end subroutine fragmentation_scaler - - ! ============================================================================ - - subroutine CWDOut( litt, fragmentation_scaler, nlev_eff_decomp ) - ! - ! !DESCRIPTION: - ! Simple CWD fragmentation Model - ! spawn new cohorts of juveniles of each PFT - ! - ! !USES: - use SFParamsMod, only : SF_val_max_decomp - - ! - ! !ARGUMENTS - type(litter_type),intent(inout),target :: litt - real(r8),intent(in) :: fragmentation_scaler(:) - - ! This is not necessarily every soil layer, this is the number - ! of effective layers that are active and can be sent - ! to the soil decomposition model - integer,intent(in) :: nlev_eff_decomp - - ! - ! !LOCAL VARIABLES: - integer :: c ! Fuel size class index - integer :: ilyr ! Soil layer index - integer :: dcmpy ! Decomposibility pool indexer - integer :: soil_layer_index = 1 ! Soil layer index associated with above ground litter - !---------------------------------------------------------------------- - - - ! Above ground litters are associated with the top soil layer temperature and - ! moisture scalars and fragmentation scalar associated with specified index value - ! is used for ag_cwd_frag and root_fines_frag calculations. - - do c = 1,ncwd - - litt%ag_cwd_frag(c) = litt%ag_cwd(c) * SF_val_max_decomp(c) * & - years_per_day * fragmentation_scaler(soil_layer_index) - - do ilyr = 1,nlev_eff_decomp - - litt%bg_cwd_frag(c,ilyr) = litt%bg_cwd(c,ilyr) * SF_val_max_decomp(c) * & - years_per_day * fragmentation_scaler(ilyr) - - enddo - end do - - ! this is the rate at which dropped leaves stop being part of the burnable pool - ! and begin to be part of the decomposing pool. This should probably be highly - ! sensitive to moisture, but also to the type of leaf thick leaves can dry out - ! before they are decomposed, for example. This section needs further scientific input. - - do dcmpy = 1,ndcmpy - - litt%leaf_fines_frag(dcmpy) = litt%leaf_fines(dcmpy) * & - years_per_day * SF_val_max_decomp(dl_sf) * fragmentation_scaler(soil_layer_index) - - do ilyr = 1,nlev_eff_decomp - litt%root_fines_frag(dcmpy,ilyr) = litt%root_fines(dcmpy,ilyr) * & - years_per_day * SF_val_max_decomp(dl_sf) * fragmentation_scaler(ilyr) - end do - enddo - - end subroutine CWDOut - -end module EDPhysiologyMod From 2d11c713121bdb5effe43a50f84f61255ebb2dd8 Mon Sep 17 00:00:00 2001 From: YanlanLiu Date: Mon, 21 Jun 2021 15:55:37 -0700 Subject: [PATCH 010/852] Benchmark: correctly print out seed production --- biogeochem/EDPhysiologyMod.F90 | 22 +++++++++++++++------- main/EDMainMod.F90 | 4 ++-- main/FatesHistoryInterfaceMod.F90 | 6 +++--- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 48bf9a5c0c..94c18c26db 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1428,11 +1428,11 @@ subroutine SeedIn( currentSite, bc_in ) ! (seed_prod * currentCohort%n + store_m_to_repro) site_seed_rain(pft) = site_seed_rain(pft) + & - (seed_prod * currentCohort%n + store_m_to_repro)*(1-disp_frac(pft)) + (seed_prod * currentCohort%n + store_m_to_repro) !*(1-disp_frac(pft)) site_seed_out(pft) = site_seed_out(pft) + & (seed_prod * currentCohort%n + store_m_to_repro)*disp_frac(pft) - write(fates_log(),*) 'pft, site_seed_rain(pft), site_seed_out(pft):', pft, site_seed_rain(pft), site_seed_out(pft) - print *, 'pft, site_seed_rain(pft), site_seed_out(pft):', pft, site_seed_rain(pft), site_seed_out(pft) + write(fates_log(),*) 'pft, site_seed_rain(pft), site_seed_out(pft):', pft, site_seed_rain(pft)*10000.0, site_seed_out(pft)*10000.0 +! print *, 'pft, site_seed_rain(pft), site_seed_out(pft):', pft, site_seed_rain(pft), site_seed_out(pft) !----------- currentCohort => currentCohort%shorter @@ -1454,6 +1454,11 @@ subroutine SeedIn( currentSite, bc_in ) ! Loop over all patches and sum up the seed input for each PFT currentPatch => currentSite%oldest_patch + + !YL---- + !write(fates_log(),*) 'area:', area + !------ + do while (associated(currentPatch)) litt => currentPatch%litter(el) @@ -1463,6 +1468,9 @@ subroutine SeedIn( currentSite, bc_in ) ! Seed input from local sources (within site) litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)/area + !YL-------- + ! write(fates_log(),*) 'pft, litt%seed_in_local(pft), site_seed_rain(pft): ', litt%seed_in_local(pft), site_seed_rain(pft) + ! If there is forced external seed rain, we calculate the input mass flux ! from the different elements, usung the seed optimal stoichiometry ! for non-carbon @@ -1485,7 +1493,7 @@ subroutine SeedIn( currentSite, bc_in ) ! Seeds entering externally [kg/site/day] site_mass%seed_in = site_mass%seed_in + seed_in_external*currentPatch%area - write(fates_log(),*) 'pft, site_mass%seed_in, site_seed_rain, site_seed_out: ', pft, site_mass%seed_in, site_seed_rain(pft), site_seed_out(pft) +! write(fates_log(),*) 'pft, site_mass%seed_in, site_seed_rain, site_seed_out: ', pft, site_mass%seed_in, site_seed_rain(pft), site_seed_out(pft) ! write(fates_log(),*) 'pft, equivalent seed_suppl: ', pft, site_mass%seed_in/currentPatch%area/seed_stoich/years_per_day end if !use this pft enddo @@ -1595,9 +1603,9 @@ end subroutine SeedGermination ! ===================================================================================== - ! subroutine recruitment( currentSite, currentPatch, bc_in ) + subroutine recruitment( currentSite, currentPatch, bc_in ) !YL------- pass in bc_out ------ - subroutine recruitment( currentSite, currentPatch, bc_in, bc_out ) + ! subroutine recruitment( currentSite, currentPatch, bc_in, bc_out ) ! ! !DESCRIPTION: ! spawn new cohorts of juveniles of each PFT @@ -1609,7 +1617,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in, bc_out ) type(ed_site_type), intent(inout), target :: currentSite type(ed_patch_type), intent(inout), pointer :: currentPatch type(bc_in_type), intent(in) :: bc_in - type(bc_out_type), intent(inout) :: bc_out + ! type(bc_out_type), intent(inout) :: bc_out ! ! !LOCAL VARIABLES: class(prt_vartypes), pointer :: prt diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 3bf4b35018..7a9c1e5436 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -219,9 +219,9 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) do while (associated(currentPatch)) ! adds small cohort of each PFT - ! call recruitment(currentSite, currentPatch, bc_in) + call recruitment(currentSite, currentPatch, bc_in) !YL -------------- - call recruitment(currentSite, currentPatch, bc_in, bc_out) + ! call recruitment(currentSite, currentPatch, bc_in, bc_out) currentPatch => currentPatch%younger enddo end if diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index aa5e7db161..2bc40e141a 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -5217,7 +5217,7 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ar_understory_si_scpf ) call this%set_history_var(vname='NPP_SCPF', units='kgC/m2/yr', & - long='total net primary production by pft/size', use_default='inactive', & + long='total net primary production by pft/size', use_default='active', & avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', flushval=0.0_r8, & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_npp_totl_si_scpf ) @@ -5227,7 +5227,7 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_npp_leaf_si_scpf ) call this%set_history_var(vname='NPP_SEED_SCPF', units='kgC/m2/yr', & - long='NPP flux into seeds by pft/size', use_default='inactive', & + long='NPP flux into seeds by pft/size', use_default='active', & avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', flushval=0.0_r8, & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_npp_seed_si_scpf ) @@ -5691,7 +5691,7 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_bsw_md_canopy_si_scls ) call this%set_history_var(vname='SEED_PROD_CANOPY_SCLS', units = 'kg C / ha / yr', & - long='SEED_PROD for canopy plants by size class', use_default='inactive', & + long='SEED_PROD for canopy plants by size class', use_default='active', & avgflag='A', vtype=site_size_r8, hlms='CLM:ALM', flushval=0.0_r8, & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_seed_prod_canopy_si_scls ) From b903ffa57d1370d3fab2bab04f99b3a6b18d67d3 Mon Sep 17 00:00:00 2001 From: YanlanLiu Date: Mon, 21 Jun 2021 16:47:30 -0700 Subject: [PATCH 011/852] track seed_out in site_mass --- biogeochem/EDPhysiologyMod.F90 | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 94c18c26db..6619a1694c 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1334,7 +1334,7 @@ end subroutine phenology_leafonoff ! ===================================================================================== - subroutine SeedIn( currentSite, bc_in ) + subroutine SeedIn( currentSite, bc_in) ! ----------------------------------------------------------------------------------- ! Flux from plants into the seed pool. @@ -1428,7 +1428,7 @@ subroutine SeedIn( currentSite, bc_in ) ! (seed_prod * currentCohort%n + store_m_to_repro) site_seed_rain(pft) = site_seed_rain(pft) + & - (seed_prod * currentCohort%n + store_m_to_repro) !*(1-disp_frac(pft)) + (seed_prod * currentCohort%n + store_m_to_repro)*(1-disp_frac(pft)) site_seed_out(pft) = site_seed_out(pft) + & (seed_prod * currentCohort%n + store_m_to_repro)*disp_frac(pft) write(fates_log(),*) 'pft, site_seed_rain(pft), site_seed_out(pft):', pft, site_seed_rain(pft)*10000.0, site_seed_out(pft)*10000.0 @@ -1493,11 +1493,14 @@ subroutine SeedIn( currentSite, bc_in ) ! Seeds entering externally [kg/site/day] site_mass%seed_in = site_mass%seed_in + seed_in_external*currentPatch%area -! write(fates_log(),*) 'pft, site_mass%seed_in, site_seed_rain, site_seed_out: ', pft, site_mass%seed_in, site_seed_rain(pft), site_seed_out(pft) -! write(fates_log(),*) 'pft, equivalent seed_suppl: ', pft, site_mass%seed_in/currentPatch%area/seed_stoich/years_per_day + + !YL--------- + site_mass%seed_out = site_mass%seed_out + site_seed_out(pft) + ! write(fates_log(),*) 'pft, equivalent seed_suppl: ', pft, site_mass%seed_in/currentPatch%area/seed_stoich/years_per_day end if !use this pft enddo + write(fates_log(),*) 'pft, site_mass%seed_in, site_mass%seed_out: ', pft, site_mass%seed_in*10000.0, site_mass%seed_in*10000.0 currentPatch => currentPatch%younger enddo From 5973c485f89ce4c92153f846f21085d0652fb1d1 Mon Sep 17 00:00:00 2001 From: YanlanLiu Date: Mon, 21 Jun 2021 20:19:59 -0700 Subject: [PATCH 012/852] updated seed_out --- biogeochem/EDPhysiologyMod.F90 | 41 ++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 6619a1694c..be165371bb 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1384,7 +1384,7 @@ subroutine SeedIn( currentSite, bc_in) !YL------- site_seed_out(:) = 0._r8 ! seed-rain leaving the site, 05/21 - disp_frac(:) = 0.4 ! to be specified in the parameter file or calculated using dispersal kernel + disp_frac(:) = 0.2 ! to be specified in the parameter file or calculated using dispersal kernel !--------- element_id = element_list(el) @@ -1424,14 +1424,14 @@ subroutine SeedIn( currentSite, bc_in) !YL---------- - !site_seed_rain(pft) = site_seed_rain(pft) + & - ! (seed_prod * currentCohort%n + store_m_to_repro) - site_seed_rain(pft) = site_seed_rain(pft) + & - (seed_prod * currentCohort%n + store_m_to_repro)*(1-disp_frac(pft)) - site_seed_out(pft) = site_seed_out(pft) + & - (seed_prod * currentCohort%n + store_m_to_repro)*disp_frac(pft) - write(fates_log(),*) 'pft, site_seed_rain(pft), site_seed_out(pft):', pft, site_seed_rain(pft)*10000.0, site_seed_out(pft)*10000.0 + (seed_prod * currentCohort%n + store_m_to_repro) ![kg/site/day, kg/ha/day] + + !site_seed_rain(pft) = site_seed_rain(pft) + & + ! (seed_prod * currentCohort%n + store_m_to_repro)*(1-disp_frac(pft)) + !site_seed_out(pft) = site_seed_out(pft) + & + ! (seed_prod * currentCohort%n + store_m_to_repro)*disp_frac(pft) + !write(fates_log(),*) 'pft, site_seed_rain(pft), site_seed_out(pft):', pft, site_seed_rain(pft)*10000.0, site_seed_out(pft)*10000.0 ! print *, 'pft, site_seed_rain(pft), site_seed_out(pft):', pft, site_seed_rain(pft), site_seed_out(pft) !----------- @@ -1466,11 +1466,13 @@ subroutine SeedIn( currentSite, bc_in) if(currentSite%use_this_pft(pft).eq.itrue)then ! Seed input from local sources (within site) - litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)/area - !YL-------- + !YL----- + !litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)/area + litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)*(1-disp_frac(pft))/area ![kg/m2/day] ! write(fates_log(),*) 'pft, litt%seed_in_local(pft), site_seed_rain(pft): ', litt%seed_in_local(pft), site_seed_rain(pft) - + !------- + ! If there is forced external seed rain, we calculate the input mass flux ! from the different elements, usung the seed optimal stoichiometry ! for non-carbon @@ -1488,20 +1490,25 @@ subroutine SeedIn( currentSite, bc_in) end select ! Seed input from external sources (user param seed rain, or dispersal model) - seed_in_external = seed_stoich*EDPftvarcon_inst%seed_suppl(pft)*years_per_day + + !YL-------- + seed_in_external = seed_stoich*EDPftvarcon_inst%seed_suppl(pft)*years_per_day ![kg/m2/day] + !seed_in_external = seed_stoich*EDPftvarcon_inst%seed_suppl(pft)*years_per_day + 5.0E-7 ![kg/m2/day] # to test seed_in in comparison with seed_out + !---------- + litt%seed_in_extern(pft) = litt%seed_in_extern(pft) + seed_in_external ! Seeds entering externally [kg/site/day] - site_mass%seed_in = site_mass%seed_in + seed_in_external*currentPatch%area + site_mass%seed_in = site_mass%seed_in + seed_in_external*currentPatch%area ![kg/site/day] !YL--------- - site_mass%seed_out = site_mass%seed_out + site_seed_out(pft) - ! write(fates_log(),*) 'pft, equivalent seed_suppl: ', pft, site_mass%seed_in/currentPatch%area/seed_stoich/years_per_day + site_mass%seed_out = site_mass%seed_out + site_seed_rain(pft)*disp_frac(pft) ![kg/site/day] + write(fates_log(),*) 'pft, site_seed_rain(pft), site_mass%seed_in, site_mass%seed_out', pft, site_seed_rain(pft), site_mass%seed_in, site_mass%seed_out + !----------- + end if !use this pft enddo - write(fates_log(),*) 'pft, site_mass%seed_in, site_mass%seed_out: ', pft, site_mass%seed_in*10000.0, site_mass%seed_in*10000.0 - currentPatch => currentPatch%younger enddo From 3ddc3416ee5674d95c484ee89b65c091a87df392 Mon Sep 17 00:00:00 2001 From: YanlanLiu Date: Tue, 22 Jun 2021 00:22:29 -0700 Subject: [PATCH 013/852] bench mark, compare with master --- biogeochem/EDPhysiologyMod.F90 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index be165371bb..1ac6b8fce2 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1470,6 +1470,8 @@ subroutine SeedIn( currentSite, bc_in) !YL----- !litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)/area litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)*(1-disp_frac(pft))/area ![kg/m2/day] + !litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)/area*0.8 ![kg/m2/day] + write(fates_log(),*) 'pft, disp_frac(pft): ', pft, disp_frac(pft) ! write(fates_log(),*) 'pft, litt%seed_in_local(pft), site_seed_rain(pft): ', litt%seed_in_local(pft), site_seed_rain(pft) !------- @@ -1503,6 +1505,7 @@ subroutine SeedIn( currentSite, bc_in) !YL--------- site_mass%seed_out = site_mass%seed_out + site_seed_rain(pft)*disp_frac(pft) ![kg/site/day] + !site_mass%seed_out = site_mass%seed_out + site_seed_rain(pft)*0.2 write(fates_log(),*) 'pft, site_seed_rain(pft), site_mass%seed_in, site_mass%seed_out', pft, site_seed_rain(pft), site_mass%seed_in, site_mass%seed_out !----------- From d011b2a4744b5c8bd6e637cda25ec533ff6462a1 Mon Sep 17 00:00:00 2001 From: adamhb Date: Wed, 23 Jun 2021 13:01:11 -0700 Subject: [PATCH 014/852] testing git workflow; made a comment in PRTAllometricCarbonMod.F90 --- parteh/PRTAllometricCarbonMod.F90 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 5bdf624502..f0e3e87589 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -940,6 +940,8 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) call bstore_allom(dbh,ipft,canopy_trim,ct_store,ct_dstoredd) ! fraction of carbon going towards reproduction + ! Adam will make changes to this section of code + if (dbh <= prt_params%dbh_repro_threshold(ipft)) then ! cap on leaf biomass repro_fraction = prt_params%seed_alloc(ipft) else From 2cf0588a9cf6bfaf3cdf03dbbac5ea19436a643c Mon Sep 17 00:00:00 2001 From: YanlanLiu Date: Wed, 23 Jun 2021 13:34:00 -0700 Subject: [PATCH 015/852] corrected sitemass%seed_out --- biogeochem/EDPhysiologyMod.F90 | 17 +++++++++++++---- main/ChecksBalancesMod.F90 | 9 +++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 1ac6b8fce2..b730047a9e 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -318,6 +318,9 @@ subroutine PreDisturbanceIntegrateLitter(currentPatch) litt%seed_germ_in(pft) - & litt%seed_germ_decay(pft) + !YL------ + write(fates_log(),*) 'el, pft, litt%seed_germ(pft), litt%seed(pft), litt%seed_in_local(pft): ', el, pft, litt%seed_germ(pft), litt%seed(pft), litt%seed_in_local(pft) + !------- enddo @@ -1471,8 +1474,8 @@ subroutine SeedIn( currentSite, bc_in) !litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)/area litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)*(1-disp_frac(pft))/area ![kg/m2/day] !litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)/area*0.8 ![kg/m2/day] - write(fates_log(),*) 'pft, disp_frac(pft): ', pft, disp_frac(pft) - ! write(fates_log(),*) 'pft, litt%seed_in_local(pft), site_seed_rain(pft): ', litt%seed_in_local(pft), site_seed_rain(pft) + !write(fates_log(),*) 'pft, ', pft, disp_frac(pft) + !write(fates_log(),*) 'pft, litt%seed_in_local(pft), site_seed_rain(pft): ', pft, litt%seed_in_local(pft), site_seed_rain(pft) !------- ! If there is forced external seed rain, we calculate the input mass flux @@ -1504,9 +1507,9 @@ subroutine SeedIn( currentSite, bc_in) site_mass%seed_in = site_mass%seed_in + seed_in_external*currentPatch%area ![kg/site/day] !YL--------- - site_mass%seed_out = site_mass%seed_out + site_seed_rain(pft)*disp_frac(pft) ![kg/site/day] + !site_mass%seed_out = site_mass%seed_out + site_seed_rain(pft)*disp_frac(pft) ![kg/site/day] !site_mass%seed_out = site_mass%seed_out + site_seed_rain(pft)*0.2 - write(fates_log(),*) 'pft, site_seed_rain(pft), site_mass%seed_in, site_mass%seed_out', pft, site_seed_rain(pft), site_mass%seed_in, site_mass%seed_out + !write(fates_log(),*) 'pft, site_seed_rain(pft), litt%seed_in_local(pft), site_mass%seed_out: ', pft, site_seed_rain(pft), litt%seed_in_local(pft), site_mass%seed_out !----------- end if !use this pft @@ -1517,6 +1520,12 @@ subroutine SeedIn( currentSite, bc_in) end do + do pft = 1,numpft + site_mass%seed_out = site_mass%seed_out + site_seed_rain(pft)*disp_frac(pft) ![kg/site/day] + write(fates_log(),*) 'pft, site_seed_rain(pft), site_mass%seed_out: ', pft, site_mass%seed_out + end do + + return end subroutine SeedIn diff --git a/main/ChecksBalancesMod.F90 b/main/ChecksBalancesMod.F90 index 9a17fbfc33..d86d80712d 100644 --- a/main/ChecksBalancesMod.F90 +++ b/main/ChecksBalancesMod.F90 @@ -72,6 +72,9 @@ subroutine SiteMassStock(currentSite,el,total_stock,biomass_stock,litter_stock,s total_stock = biomass_stock + seed_stock + litter_stock + !YL----- + write(fates_log(),*) 'seed_stock, litter_stock: ', seed_stock, litter_stock + !------- return end subroutine SiteMassStock @@ -106,6 +109,12 @@ subroutine PatchMassStock(currentPatch,el,live_stock,seed_stock,litter_stock) seed_stock = currentPatch%area * & (sum(litt%seed) + sum(litt%seed_germ)) + !YL----- + write(fates_log(),*) 'litt%seed: ', litt%seed + write(fates_log(),*) 'litt%seed_germ: ', litt%seed_germ + write(fates_log(),*) 'seed_stock (current patch):', seed_stock + !------- + ! Total mass on living plants live_stock = 0._r8 currentCohort => currentPatch%tallest From 43f24e6fe14fb5e91720c49386634ee0216845dd Mon Sep 17 00:00:00 2001 From: YanlanLiu Date: Wed, 23 Jun 2021 13:37:01 -0700 Subject: [PATCH 016/852] corrected site_mass%seed_out, cleaned --- biogeochem/EDPhysiologyMod.F90 | 24 ------------------------ main/ChecksBalancesMod.F90 | 7 +------ 2 files changed, 1 insertion(+), 30 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index b730047a9e..0142a09a4e 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1377,7 +1377,6 @@ subroutine SeedIn( currentSite, bc_in) !YL--------- - real(r8) :: site_seed_out(maxpft) ! The sum of seed-rain leaving the site [kg/site/day] real(r8) :: disp_frac(maxpft) ! fraction of seed-rain among the site_seed_rain that's leaving the site [unitless] !----------- @@ -1386,7 +1385,6 @@ subroutine SeedIn( currentSite, bc_in) site_seed_rain(:) = 0._r8 !YL------- - site_seed_out(:) = 0._r8 ! seed-rain leaving the site, 05/21 disp_frac(:) = 0.2 ! to be specified in the parameter file or calculated using dispersal kernel !--------- @@ -1425,19 +1423,10 @@ subroutine SeedIn( currentSite, bc_in) currentcohort%seed_prod = seed_prod end if - !YL---------- site_seed_rain(pft) = site_seed_rain(pft) + & (seed_prod * currentCohort%n + store_m_to_repro) ![kg/site/day, kg/ha/day] - !site_seed_rain(pft) = site_seed_rain(pft) + & - ! (seed_prod * currentCohort%n + store_m_to_repro)*(1-disp_frac(pft)) - !site_seed_out(pft) = site_seed_out(pft) + & - ! (seed_prod * currentCohort%n + store_m_to_repro)*disp_frac(pft) - !write(fates_log(),*) 'pft, site_seed_rain(pft), site_seed_out(pft):', pft, site_seed_rain(pft)*10000.0, site_seed_out(pft)*10000.0 -! print *, 'pft, site_seed_rain(pft), site_seed_out(pft):', pft, site_seed_rain(pft), site_seed_out(pft) - !----------- - currentCohort => currentCohort%shorter enddo !cohort loop @@ -1458,9 +1447,6 @@ subroutine SeedIn( currentSite, bc_in) ! Loop over all patches and sum up the seed input for each PFT currentPatch => currentSite%oldest_patch - !YL---- - !write(fates_log(),*) 'area:', area - !------ do while (associated(currentPatch)) @@ -1473,8 +1459,6 @@ subroutine SeedIn( currentSite, bc_in) !YL----- !litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)/area litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)*(1-disp_frac(pft))/area ![kg/m2/day] - !litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)/area*0.8 ![kg/m2/day] - !write(fates_log(),*) 'pft, ', pft, disp_frac(pft) !write(fates_log(),*) 'pft, litt%seed_in_local(pft), site_seed_rain(pft): ', pft, litt%seed_in_local(pft), site_seed_rain(pft) !------- @@ -1496,21 +1480,13 @@ subroutine SeedIn( currentSite, bc_in) ! Seed input from external sources (user param seed rain, or dispersal model) - !YL-------- seed_in_external = seed_stoich*EDPftvarcon_inst%seed_suppl(pft)*years_per_day ![kg/m2/day] - !seed_in_external = seed_stoich*EDPftvarcon_inst%seed_suppl(pft)*years_per_day + 5.0E-7 ![kg/m2/day] # to test seed_in in comparison with seed_out - !---------- litt%seed_in_extern(pft) = litt%seed_in_extern(pft) + seed_in_external ! Seeds entering externally [kg/site/day] site_mass%seed_in = site_mass%seed_in + seed_in_external*currentPatch%area ![kg/site/day] - !YL--------- - !site_mass%seed_out = site_mass%seed_out + site_seed_rain(pft)*disp_frac(pft) ![kg/site/day] - !site_mass%seed_out = site_mass%seed_out + site_seed_rain(pft)*0.2 - !write(fates_log(),*) 'pft, site_seed_rain(pft), litt%seed_in_local(pft), site_mass%seed_out: ', pft, site_seed_rain(pft), litt%seed_in_local(pft), site_mass%seed_out - !----------- end if !use this pft enddo diff --git a/main/ChecksBalancesMod.F90 b/main/ChecksBalancesMod.F90 index d86d80712d..d2aead36d0 100644 --- a/main/ChecksBalancesMod.F90 +++ b/main/ChecksBalancesMod.F90 @@ -73,7 +73,7 @@ subroutine SiteMassStock(currentSite,el,total_stock,biomass_stock,litter_stock,s total_stock = biomass_stock + seed_stock + litter_stock !YL----- - write(fates_log(),*) 'seed_stock, litter_stock: ', seed_stock, litter_stock + !write(fates_log(),*) 'seed_stock, litter_stock: ', seed_stock, litter_stock !------- return end subroutine SiteMassStock @@ -109,11 +109,6 @@ subroutine PatchMassStock(currentPatch,el,live_stock,seed_stock,litter_stock) seed_stock = currentPatch%area * & (sum(litt%seed) + sum(litt%seed_germ)) - !YL----- - write(fates_log(),*) 'litt%seed: ', litt%seed - write(fates_log(),*) 'litt%seed_germ: ', litt%seed_germ - write(fates_log(),*) 'seed_stock (current patch):', seed_stock - !------- ! Total mass on living plants live_stock = 0._r8 From 386dade84ec094cbd09ad59a8c85e3e621192fee Mon Sep 17 00:00:00 2001 From: YanlanLiu Date: Wed, 23 Jun 2021 13:43:20 -0700 Subject: [PATCH 017/852] notation --- biogeochem/EDPhysiologyMod.F90 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 0142a09a4e..4a2a0fb082 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1496,10 +1496,12 @@ subroutine SeedIn( currentSite, bc_in) end do + !YL, 06/23/2021, track seed mass living the site ----------- do pft = 1,numpft site_mass%seed_out = site_mass%seed_out + site_seed_rain(pft)*disp_frac(pft) ![kg/site/day] write(fates_log(),*) 'pft, site_seed_rain(pft), site_mass%seed_out: ', pft, site_mass%seed_out end do + !----------------------------------------------------------- return From d02791c0763294444d45f14c1a2105bfa31b5dce Mon Sep 17 00:00:00 2001 From: YanlanLiu Date: Fri, 25 Jun 2021 21:39:17 -0700 Subject: [PATCH 018/852] corrected position for seed_out --- biogeochem/EDPhysiologyMod.F90 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 4a2a0fb082..dddf4fa4aa 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1493,15 +1493,15 @@ subroutine SeedIn( currentSite, bc_in) currentPatch => currentPatch%younger enddo - - end do - !YL, 06/23/2021, track seed mass living the site ----------- - do pft = 1,numpft - site_mass%seed_out = site_mass%seed_out + site_seed_rain(pft)*disp_frac(pft) ![kg/site/day] - write(fates_log(),*) 'pft, site_seed_rain(pft), site_mass%seed_out: ', pft, site_mass%seed_out + !YL, 06/23/2021, track seed mass living the site ----------- + do pft = 1,numpft + site_mass%seed_out = site_mass%seed_out + site_seed_rain(pft)*disp_frac(pft) ![kg/site/day] + write(fates_log(),*) 'pft, site_seed_rain(pft), site_mass%seed_out: ', pft, site_mass%seed_out + end do + !----------------------------------------------------------- + end do - !----------------------------------------------------------- return From 2d494d2e5d4576b503a63f782ee2713f66780d01 Mon Sep 17 00:00:00 2001 From: YanlanLiu Date: Fri, 25 Jun 2021 22:51:24 -0700 Subject: [PATCH 019/852] added bc_out in SeedIn() --- biogeochem/EDPhysiologyMod.F90 | 13 ++++++++++--- main/EDMainMod.F90 | 7 +++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index dddf4fa4aa..6082665030 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -319,7 +319,7 @@ subroutine PreDisturbanceIntegrateLitter(currentPatch) litt%seed_germ_decay(pft) !YL------ - write(fates_log(),*) 'el, pft, litt%seed_germ(pft), litt%seed(pft), litt%seed_in_local(pft): ', el, pft, litt%seed_germ(pft), litt%seed(pft), litt%seed_in_local(pft) + !write(fates_log(),*) 'el, pft, litt%seed_germ(pft), litt%seed(pft), litt%seed_in_local(pft): ', el, pft, litt%seed_germ(pft), litt%seed(pft), litt%seed_in_local(pft) !------- enddo @@ -1336,8 +1336,11 @@ end subroutine phenology_leafonoff ! ===================================================================================== - - subroutine SeedIn( currentSite, bc_in) + + !YL-------------- + !subroutine SeedIn( currentSite, bc_in) + subroutine SeedIn( currentSite, bc_in, bc_out) + !---------------- ! ----------------------------------------------------------------------------------- ! Flux from plants into the seed pool. @@ -1360,6 +1363,10 @@ subroutine SeedIn( currentSite, bc_in) type(ed_site_type), intent(inout), target :: currentSite type(bc_in_type), intent(in) :: bc_in + !YL--------- + type(bc_out_type), intent(inout) :: bc_out + !----------- + type(ed_patch_type), pointer :: currentPatch type(litter_type), pointer :: litt type(ed_cohort_type), pointer :: currentCohort diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 7a9c1e5436..edf9a031c4 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -574,9 +574,12 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! With growth and mortality rates now calculated we can determine the seed rain ! fluxes. However, because this is potentially a cross-patch mixing model ! we will calculate this as a group - - call SeedIn(currentSite,bc_in) + !YL------- + !call SeedIn(currentSite,bc_in) + call SeedIn(currentSite,bc_in,bc_out) + !--------- + ! Calculate all other litter fluxes ! ----------------------------------------------------------------------------------- From c7b5ea792bd2a78a7edf98d08249e80b2db08af1 Mon Sep 17 00:00:00 2001 From: YanlanLiu Date: Fri, 25 Jun 2021 23:25:39 -0700 Subject: [PATCH 020/852] added seed_out(numpft) in bc_out --- main/FatesInterfaceMod.F90 | 9 +++++++++ main/FatesInterfaceTypesMod.F90 | 6 +++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 48aef9deed..3c0bde3094 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -306,6 +306,10 @@ subroutine zero_bcs(fates,s) fates%bc_out(s)%qflx_ro_sisl(:) = 0.0_r8 end if fates%bc_out(s)%plant_stored_h2o_si = 0.0_r8 + + !YL------- + fates%bc_out(s)%seed_out(:) = 0.0_r8 + !--------- return end subroutine zero_bcs @@ -591,6 +595,11 @@ subroutine allocate_bcout(bc_out, nlevsoil_in, nlevdecomp_in) allocate(bc_out%qflx_ro_sisl(nlevsoil_in)) end if + !YL--------- + ! Seed dispersal + allocate(bc_out%seed_out(1:numpft)) + !----------- + return end subroutine allocate_bcout diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 5b069709cc..bb8e51f3d8 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -673,7 +673,11 @@ module FatesInterfaceTypesMod ! small fluxes for various reasons ! [mm H2O/s] - + !YL------------- + ! Seed dispersal + real(r8),allocatable :: seed_out(:) ! amount of seed leaving the site [kg/site/day] + !--------------- + end type bc_out_type From 903b7f81c39bbda814412115dc78fc344d9de731 Mon Sep 17 00:00:00 2001 From: YanlanLiu Date: Sat, 26 Jun 2021 11:36:30 -0700 Subject: [PATCH 021/852] benchmark edits within FATES --- biogeochem/EDPhysiologyMod.F90 | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 6082665030..86bfbcdcca 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1501,15 +1501,21 @@ subroutine SeedIn( currentSite, bc_in, bc_out) currentPatch => currentPatch%younger enddo - !YL, 06/23/2021, track seed mass living the site ----------- + !YL, 06/23/2021, track seed mass (of each element) leaving the site ----------- do pft = 1,numpft site_mass%seed_out = site_mass%seed_out + site_seed_rain(pft)*disp_frac(pft) ![kg/site/day] write(fates_log(),*) 'pft, site_seed_rain(pft), site_mass%seed_out: ', pft, site_mass%seed_out end do - !----------------------------------------------------------- + !----------------------------------------------------------------------------- end do + !YL--------- + do pft = 1,numpft + bc_out%seed_out(pft) = bc_out%seed_out(pft) + site_seed_rain(pft)*disp_frac(pft) ![kg/site/day] + write(fates_log(),*) 'pft, site_seed_rain(pft), bc_out%seed_out(pft): ', pft, site_seed_rain(pft), bc_out%seed_out(pft) + end do + !----------- return end subroutine SeedIn From f0d60163412c74850ac56f7e81e283739b646e19 Mon Sep 17 00:00:00 2001 From: YanlanLiu Date: Sat, 26 Jun 2021 14:04:32 -0700 Subject: [PATCH 022/852] added seed_in in bc_in --- main/FatesInterfaceMod.F90 | 8 ++++++++ main/FatesInterfaceTypesMod.F90 | 6 +++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 3c0bde3094..cdca06a77e 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -308,6 +308,7 @@ subroutine zero_bcs(fates,s) fates%bc_out(s)%plant_stored_h2o_si = 0.0_r8 !YL------- + fates%bc_in(s)%seed_in(:) = 0.0_r8 fates%bc_out(s)%seed_out(:) = 0.0_r8 !--------- @@ -466,6 +467,13 @@ subroutine allocate_bcin(bc_in, nlevsoil_in, nlevdecomp_in, num_lu_harvest_cats) allocate(bc_in%h2o_liq_sisl(nlevsoil_in)); bc_in%h2o_liq_sisl = nan end if + + !YL--------- + ! Seed dispersal + allocate(bc_in%seed_in(1:numpft)) + !----------- + + ! Land use ! harvest flag denote data from hlm, diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index bb8e51f3d8..06d54a63f6 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -499,7 +499,11 @@ module FatesInterfaceTypesMod real(r8),allocatable :: hksat_sisl(:) ! hydraulic conductivity at saturation (mm H2O /s) real(r8),allocatable :: h2o_liq_sisl(:) ! Liquid water mass in each layer (kg/m2) real(r8) :: smpmin_si ! restriction for min of soil potential (mm) - + + !YL------------ + real(r8), allocatable :: seed_in(:) ! amount of seed dispersed into the site from neighbouring cells [kg/site/day] + !-------------- + ! Land use ! --------------------------------------------------------------------------------- real(r8),allocatable :: hlm_harvest_rates(:) ! annual harvest rate per cat from hlm for a site From 91d945cdc3766bef5a8a8e3e99b77fb5a990c293 Mon Sep 17 00:00:00 2001 From: YanlanLiu Date: Sat, 26 Jun 2021 14:25:17 -0700 Subject: [PATCH 023/852] added seed_in in bc_in --- biogeochem/EDPhysiologyMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 86bfbcdcca..c287076354 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1504,7 +1504,7 @@ subroutine SeedIn( currentSite, bc_in, bc_out) !YL, 06/23/2021, track seed mass (of each element) leaving the site ----------- do pft = 1,numpft site_mass%seed_out = site_mass%seed_out + site_seed_rain(pft)*disp_frac(pft) ![kg/site/day] - write(fates_log(),*) 'pft, site_seed_rain(pft), site_mass%seed_out: ', pft, site_mass%seed_out + !write(fates_log(),*) 'pft, site_seed_rain(pft), site_mass%seed_out: ', pft, site_mass%seed_out end do !----------------------------------------------------------------------------- @@ -1513,7 +1513,7 @@ subroutine SeedIn( currentSite, bc_in, bc_out) !YL--------- do pft = 1,numpft bc_out%seed_out(pft) = bc_out%seed_out(pft) + site_seed_rain(pft)*disp_frac(pft) ![kg/site/day] - write(fates_log(),*) 'pft, site_seed_rain(pft), bc_out%seed_out(pft): ', pft, site_seed_rain(pft), bc_out%seed_out(pft) + !write(fates_log(),*) 'pft, site_seed_rain(pft), bc_out%seed_out(pft): ', pft, site_seed_rain(pft), bc_out%seed_out(pft) end do !----------- From 474e5e505a4ef7e7a14829c2424e71aaf042e226 Mon Sep 17 00:00:00 2001 From: adamhb Date: Wed, 30 Jun 2021 12:31:49 -0700 Subject: [PATCH 024/852] made small change as a test, code is working --- parteh/PRTAllometricCarbonMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index f0e3e87589..a4f3e495a2 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -940,10 +940,10 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) call bstore_allom(dbh,ipft,canopy_trim,ct_store,ct_dstoredd) ! fraction of carbon going towards reproduction - ! Adam will make changes to this section of code + ! Adam has changed this section if (dbh <= prt_params%dbh_repro_threshold(ipft)) then ! cap on leaf biomass - repro_fraction = prt_params%seed_alloc(ipft) + repro_fraction = prt_params%seed_alloc(ipft) / 4.0_r8 ! ahb added / 4.0_r8 else repro_fraction = prt_params%seed_alloc(ipft) + prt_params%seed_alloc_mature(ipft) end if From 13d1e4b0b189efa953016895a29527bf24a742f5 Mon Sep 17 00:00:00 2001 From: adamhb Date: Wed, 30 Jun 2021 13:27:46 -0700 Subject: [PATCH 025/852] reproductive allocation working, no changes to param file yet --- parteh/PRTAllometricCarbonMod.F90 | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index a4f3e495a2..a0cc4e6796 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -908,7 +908,7 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) real(r8) :: ct_ddeaddd ! target structural biomass derivative wrt diameter, (kgC/cm) real(r8) :: ct_dtotaldd ! target total (not reproductive) biomass derivative wrt diameter, (kgC/cm) real(r8) :: repro_fraction ! fraction of carbon balance directed towards reproduction (kgC/kgC) - + real(r8), parameter :: repro_alloc_a = 0.0058, repro_alloc_b = -3.1380 !ahb added this 6/30/2021 associate( dbh => c_pools(dbh_id), & cleaf => c_pools(leaf_c_id), & @@ -942,11 +942,20 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) ! fraction of carbon going towards reproduction ! Adam has changed this section - if (dbh <= prt_params%dbh_repro_threshold(ipft)) then ! cap on leaf biomass - repro_fraction = prt_params%seed_alloc(ipft) / 4.0_r8 ! ahb added / 4.0_r8 - else - repro_fraction = prt_params%seed_alloc(ipft) + prt_params%seed_alloc_mature(ipft) - end if + !original code + !-------------------------------------------------------------------------------------! + !if (dbh <= prt_params%dbh_repro_threshold(ipft)) then ! cap on leaf biomass + ! repro_fraction = prt_params%seed_alloc(ipft) + !else + ! repro_fraction = prt_params%seed_alloc(ipft) + prt_params%seed_alloc_mature(ipft) + !end if + !-------------------------------------------------------------------------------------! + + !new code + !-------------------------------------------------------------------------------------! + repro_fraction = prt_params%seed_alloc(ipft) * & + (exp(repro_alloc_b+repro_alloc_a*dbh*10.0_r8) / (1 + exp(repro_alloc_b+repro_alloc_a*dbh*10.0_r8))) + !-------------------------------------------------------------------------------------! dCdx = 0.0_r8 From be9180cc43606a74b0786ae4b88ed56d3c7888ba Mon Sep 17 00:00:00 2001 From: adamhb Date: Thu, 1 Jul 2021 12:26:50 -0700 Subject: [PATCH 026/852] added reproductive allocation function with new reproductive allocation parameters, passed ahb's tests successfully --- parteh/PRTAllometricCarbonMod.F90 | 9 +++++---- parteh/PRTParametersMod.F90 | 3 ++- parteh/PRTParamsFATESMod.F90 | 23 +++++++++++++++++++++++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index a0cc4e6796..22f9bad601 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -908,7 +908,7 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) real(r8) :: ct_ddeaddd ! target structural biomass derivative wrt diameter, (kgC/cm) real(r8) :: ct_dtotaldd ! target total (not reproductive) biomass derivative wrt diameter, (kgC/cm) real(r8) :: repro_fraction ! fraction of carbon balance directed towards reproduction (kgC/kgC) - real(r8), parameter :: repro_alloc_a = 0.0058, repro_alloc_b = -3.1380 !ahb added this 6/30/2021 + !real(r8), parameter :: repro_alloc_a = 0.0058, repro_alloc_b = -3.1380 !ahb added this 6/30/2021 associate( dbh => c_pools(dbh_id), & cleaf => c_pools(leaf_c_id), & @@ -940,7 +940,7 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) call bstore_allom(dbh,ipft,canopy_trim,ct_store,ct_dstoredd) ! fraction of carbon going towards reproduction - ! Adam has changed this section + ! ahb changed this section !original code !-------------------------------------------------------------------------------------! @@ -951,10 +951,11 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) !end if !-------------------------------------------------------------------------------------! - !new code + !new regeneration code (ahb) !-------------------------------------------------------------------------------------! repro_fraction = prt_params%seed_alloc(ipft) * & - (exp(repro_alloc_b+repro_alloc_a*dbh*10.0_r8) / (1 + exp(repro_alloc_b+repro_alloc_a*dbh*10.0_r8))) + (exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*10.0_r8) / & + (1 + exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_b(ipft)*dbh*10.0_r8))) !-------------------------------------------------------------------------------------! dCdx = 0.0_r8 diff --git a/parteh/PRTParametersMod.F90 b/parteh/PRTParametersMod.F90 index 6e2c17ac66..200da09613 100644 --- a/parteh/PRTParametersMod.F90 +++ b/parteh/PRTParametersMod.F90 @@ -73,7 +73,8 @@ module PRTParametersMod real(r8), allocatable :: seed_alloc_mature(:) ! fraction of carbon balance allocated to ! clonal reproduction. real(r8), allocatable :: seed_alloc(:) ! fraction of carbon balance allocated to seeds. - + real(r8), allocatable :: repro_alloc_a(:) ! ahb added this; sigmoidal shape param relating dbh to seed allocation fraction + real(r8), allocatable :: repro_alloc_b(:) ! ahb added this; intercept param relating dbh to seed allocation fraction ! Derived parameters diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index 4442c090e8..1774900b85 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -223,6 +223,16 @@ subroutine PRTRegisterPFT(fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + !ahb added the params below + !------------------------------------------------------------------------------------- + name = 'fates_repro_alloc_a' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_repro_alloc_b' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + !-------------------------------------------------------------------------------------- name = 'fates_c2b' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -447,6 +457,17 @@ subroutine PRTReceivePFT(fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%seed_alloc) + !ahb added the code below + !-------------------------------------------------------- + name = 'fates_repro_alloc_a' + call fates_params%RetreiveParameterAllocate(name=name, & + data=prt_params%repro_alloc_a) + + name = 'fates_repro_alloc_b' + call fates_params%RetreiveParameterAllocate(name=name, & + data=prt_params%repro_alloc_b) + !--------------------------------------------------------- + name = 'fates_c2b' call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%c2b) @@ -820,6 +841,8 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'senleaf_long_fdrought = ',prt_params%senleaf_long_fdrought write(fates_log(),fmt0) 'seed_alloc_mature = ',prt_params%seed_alloc_mature write(fates_log(),fmt0) 'seed_alloc = ',prt_params%seed_alloc + write(fates_log(),fmt0) 'repro_alloc_a = ',prt_params%repro_alloc_a !ahb added this + write(fates_log(),fmt0) 'repro_alloc_b = ',prt_params%repro_alloc_b !ahb added this write(fates_log(),fmt0) 'slamax = ',prt_params%slamax write(fates_log(),fmt0) 'slatop = ',prt_params%slatop write(fates_log(),fmt0) 'allom_sai_scaler = ',prt_params%allom_sai_scaler From a35dfb2398821b82966b7246c096c0e9f8c78375 Mon Sep 17 00:00:00 2001 From: adamhb Date: Tue, 6 Jul 2021 12:56:16 -0700 Subject: [PATCH 027/852] made a hard coded test change to the germination function; this does affect the recruitment rates --- biogeochem/EDPhysiologyMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index fe184dd343..5a3c37a902 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1541,7 +1541,7 @@ subroutine SeedGermination( litt, cold_stat, drought_stat ) ! that times the ratio of (hypothetical) seed mass to recruit biomass do pft = 1,numpft - litt%seed_germ_in(pft) = min(litt%seed(pft) * EDPftvarcon_inst%germination_rate(pft), & + litt%seed_germ_in(pft) = min(litt%seed(pft) * EDPftvarcon_inst%germination_rate(pft) / 4.0_r8, & !ahb added / 4.0_r8 as a test max_germination)*years_per_day !set the germination only under the growing season...c.xu From bdda7251a367dd7333ab4253f225876d33b3851d Mon Sep 17 00:00:00 2001 From: adamhb Date: Wed, 7 Jul 2021 16:24:06 -0700 Subject: [PATCH 028/852] pre changing reproductive release parameter in Physiology mod; reproductive allocation is working --- main/FatesConstantsMod.F90 | 3 +++ parteh/PRTAllometricCarbonMod.F90 | 14 +++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index 7e19856aa2..2688f91fd1 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -141,6 +141,9 @@ module FatesConstantsMod ! Conversion factor: milimeters per meter real(fates_r8), parameter, public :: mm_per_m = 1.0E3_fates_r8 + ! Conversion factor: milimeters per centimeter ahb added this 7/7/2021 + ! read(fates_r8), parameter, public :: mm_per_cm = 1.0E1_fates_r8 + ! Conversion factor: m2 per ha real(fates_r8), parameter, public :: m2_per_ha = 1.0e4_fates_r8 diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 22f9bad601..3d39a207cb 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -42,6 +42,7 @@ module PRTAllometricCarbonMod use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : i4 => fates_int use FatesConstantsMod , only : sec_per_day + !use FatesConstantsMod , only : mm_per_cm !ahb added this 7/7/2021 use FatesIntegratorsMod , only : RKF45 use FatesIntegratorsMod , only : Euler use FatesConstantsMod , only : calloc_abs_error @@ -908,7 +909,7 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) real(r8) :: ct_ddeaddd ! target structural biomass derivative wrt diameter, (kgC/cm) real(r8) :: ct_dtotaldd ! target total (not reproductive) biomass derivative wrt diameter, (kgC/cm) real(r8) :: repro_fraction ! fraction of carbon balance directed towards reproduction (kgC/kgC) - !real(r8), parameter :: repro_alloc_a = 0.0058, repro_alloc_b = -3.1380 !ahb added this 6/30/2021 + real(r8), parameter :: mm_per_cm = 10.0_r8 !ahb added this; this is temporary. Need to add this to the FATES constants file associate( dbh => c_pools(dbh_id), & cleaf => c_pools(leaf_c_id), & @@ -940,7 +941,8 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) call bstore_allom(dbh,ipft,canopy_trim,ct_store,ct_dstoredd) ! fraction of carbon going towards reproduction - ! ahb changed this section + + !START ahb's changes !original code !-------------------------------------------------------------------------------------! @@ -951,13 +953,15 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) !end if !-------------------------------------------------------------------------------------! - !new regeneration code (ahb) + !new regeneration code (ahb, July 2021) !-------------------------------------------------------------------------------------! repro_fraction = prt_params%seed_alloc(ipft) * & - (exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*10.0_r8) / & - (1 + exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_b(ipft)*dbh*10.0_r8))) + (exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm) / & + (1 + exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_b(ipft)*dbh*mm_per_cm))) !-------------------------------------------------------------------------------------! + !END ahb's changes + dCdx = 0.0_r8 ct_dtotaldd = ct_ddeaddd From a993ccccfb406107a811dac8d6dafc21cec09fa9 Mon Sep 17 00:00:00 2001 From: adamhb Date: Thu, 8 Jul 2021 18:26:54 -0700 Subject: [PATCH 029/852] all changes to non-seed reproductive allocation commented out; model working. added new litter pool for non-seed reproductive allocation, but I don't use them. I have to delete code that creates this new litter pool if I don't end up using it --- biogeochem/EDPatchDynamicsMod.F90 | 3 ++ biogeochem/EDPhysiologyMod.F90 | 36 +++++++++++++++++++++--- biogeochem/FatesLitterMod.F90 | 8 ++++++ biogeochem/FatesSoilBGCFluxMod.F90 | 44 +++++++++++++++++++++--------- main/FatesConstantsMod.F90 | 4 +-- parteh/PRTAllometricCarbonMod.F90 | 3 +- 6 files changed, 77 insertions(+), 21 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 60716b23dd..34a38555b4 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1392,6 +1392,9 @@ subroutine TransLitterNewPatch(currentSite, & new_litt%seed_decay(pft) = new_litt%seed_decay(pft) + & curr_litt%seed_decay(pft)*patch_site_areadis/newPatch%area + new_litt%non_seed_repro_mass_decay(pft) = new_litt%non_seed_repro_mass_decay(pft) + & !ahb added this + curr_litt%non_seed_repro_mass_decay(pft)*patch_site_areadis/newPatch%area !ahb added this + new_litt%seed_germ_decay(pft) = new_litt%seed_germ_decay(pft) + & curr_litt%seed_germ_decay(pft)*patch_site_areadis/newPatch%area diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 5a3c37a902..794a44fd20 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -252,6 +252,7 @@ subroutine PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in ) site_mass%frag_out = site_mass%frag_out + currentPatch%area * & ( sum(litt%ag_cwd_frag) + sum(litt%bg_cwd_frag) + & sum(litt%leaf_fines_frag) + sum(litt%root_fines_frag) + & + !sum(litt%non_seed_repro_mass_decay) + & !ahb added this line on 7/8/2021 sum(litt%seed_decay) + sum(litt%seed_germ_decay)) end do @@ -1365,6 +1366,7 @@ subroutine SeedIn( currentSite, bc_in ) real(r8) :: site_seed_rain(maxpft) ! This is the sum of seed-rain for the site [kg/site/day] real(r8) :: seed_in_external ! Mass of externally generated seeds [kg/m2/day] real(r8) :: seed_stoich ! Mass ratio of nutrient per C12 in seeds [kg/kg] + real(r8) :: repro_mass_prod ! Mass of reproductive material produced [kg/day] ; added by ahb 7/8/2021 real(r8) :: seed_prod ! Seed produced in this dynamics step [kg/day] integer :: n_litt_types ! number of litter element types (c,n,p, etc) integer :: el ! loop counter for litter element types @@ -1403,9 +1405,35 @@ subroutine SeedIn( currentSite, bc_in ) ! specified as input. This routine will also remove the mass ! from the parteh state-variable. - call PRTReproRelease(currentCohort%prt,repro_organ,element_id, & - 1.0_r8, seed_prod) + !START ahb changes + !-------------------------------------------------------------------------- + !original code + !call PRTReproRelease(currentCohort%prt,repro_organ,element_id, & + ! 1.0_r8, seed_prod) + !-------------------------------------------------------------------------- + + !-------------------------------------------------------------------------- + !ahb's new code + !the original code sends all reproductive tissue to seed + !This new code, added by ahb, is designed to send some reproductive biomass + !straight to the leaf litter pool to account for non-seed reproductive + !biomass. For now, ahb does this after the call to the + !PRTReproRelease function, but a better solution would probably be to do + !this within the PRTReproRelease module in parteh/PRTLossFluxesMod.F90::L342 + !by adding new live reproductive organs (ahb needs help with this). + + call PRTReproRelease(currentCohort%prt,repro_organ,element_id, & + 1.0_r8, repro_mass_prod) !ahb changed from seed_prod to repro_mass_prod + + seed_prod = repro_mass_prod ! * 0.5_r8 ! only a fraction of reproductive carbon is seed (ahb) + + ! the remainder goes to non-seed reproductive litter + !litt%non_seed_repro_mass_decay(pft) = repro_mass_prod * (1.0_r8 - 0.5_r8) ! ahb + !--------------------------------------------------------------------------- + + !END ahb changes + if(element_id==carbon12_element)then currentcohort%seed_prod = seed_prod end if @@ -1496,7 +1524,7 @@ subroutine SeedDecay( litt ) ! Assume that decay rates are same for all chemical species do pft = 1,numpft - litt%seed_decay(pft) = litt%seed(pft) * & + litt%seed_decay(pft) = litt%seed(pft) * & EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day litt%seed_germ_decay(pft) = litt%seed_germ(pft) * & @@ -1541,7 +1569,7 @@ subroutine SeedGermination( litt, cold_stat, drought_stat ) ! that times the ratio of (hypothetical) seed mass to recruit biomass do pft = 1,numpft - litt%seed_germ_in(pft) = min(litt%seed(pft) * EDPftvarcon_inst%germination_rate(pft) / 4.0_r8, & !ahb added / 4.0_r8 as a test + litt%seed_germ_in(pft) = min(litt%seed(pft) * EDPftvarcon_inst%germination_rate(pft), & max_germination)*years_per_day !set the germination only under the growing season...c.xu diff --git a/biogeochem/FatesLitterMod.F90 b/biogeochem/FatesLitterMod.F90 index be5ec48aa9..dbcf05a9d4 100644 --- a/biogeochem/FatesLitterMod.F90 +++ b/biogeochem/FatesLitterMod.F90 @@ -105,6 +105,7 @@ module FatesLitterMod real(r8),allocatable :: root_fines_frag(:,:) ! kg/m2/day real(r8), allocatable :: seed_decay(:) ! decay of viable seeds to litter [kg/m2/day] + real(r8), allocatable :: non_seed_repro_mass_decay(:) ! ahb, decay of non-seed reproductive mass [kg/m2/day] real(r8), allocatable :: seed_germ_decay(:) ! decay of germinated seeds to litter [kg/m2/day] real(r8), allocatable :: seed_germ_in(:) ! flux from viable to germinated seed [kg/m2/day] @@ -193,6 +194,8 @@ subroutine FuseLitter(this,self_area,donor_area,donor_litt) this%seed_decay(pft) = this%seed_decay(pft) * self_weight + & donor_litt%seed_decay(pft) * donor_weight + this%non_seed_repro_mass_decay(pft) = this%non_seed_repro_mass_decay(pft) * self_weight + & !ahb + donor_litt%non_seed_repro_mass_decay(pft) * donor_weight !ahb this%seed_germ_decay(pft) = this%seed_germ_decay(pft) * self_weight + & donor_litt%seed_germ_decay(pft) * donor_weight this%seed_germ_in(pft) = this%seed_germ_in(pft) * self_weight + & @@ -252,6 +255,7 @@ subroutine CopyLitter(this,donor_litt) this%leaf_fines_frag(:) = donor_litt%leaf_fines_frag(:) this%seed_decay(:) = donor_litt%seed_decay(:) + this%non_seed_repro_mass_decay(:) = donor_litt%non_seed_repro_mass_decay(:) !ahb this%seed_germ_decay(:) = donor_litt%seed_germ_decay(:) this%seed_germ_in(:) = donor_litt%seed_germ_in(:) this%root_fines(:,:) = donor_litt%root_fines(:,:) @@ -289,6 +293,7 @@ subroutine InitAllocate(this,numpft,numlevsoil,element_id) allocate(this%seed_germ(numpft)) allocate(this%seed_germ_in(numpft)) allocate(this%seed_germ_decay(numpft)) + allocate(this%non_seed_repro_mass_decay(numpft)) !ahb allocate(this%seed_decay(numpft)) ! Initialize everything to a nonsense flag @@ -312,6 +317,7 @@ subroutine InitAllocate(this,numpft,numlevsoil,element_id) this%root_fines_frag(:,:) = fates_unset_r8 this%seed_decay(:) = fates_unset_r8 + this%non_seed_repro_mass_decay(:) = fates_unset_r8 !ahb this%seed_germ_decay(:) = fates_unset_r8 this%seed_germ_in(:) = fates_unset_r8 @@ -376,6 +382,7 @@ subroutine DeallocateLitt(this) deallocate(this%root_fines_frag) deallocate(this%seed_decay) + deallocate(this%non_seed_repro_mass_decay) deallocate(this%seed_germ_decay) deallocate(this%seed_germ_in) @@ -402,6 +409,7 @@ subroutine ZeroFlux(this) this%seed_germ_in(:) = 0._r8 this%seed_decay(:) = 0._r8 + this%non_seed_repro_mass_decay = 0._r8 this%seed_germ_decay(:) = 0._r8 diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index a8d535e114..50e379aa45 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -1099,21 +1099,39 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) ! decaying seeds from the litter pool do ipft = 1,numpft do id = 1,nlev_eff_decomp - - flux_lab_si(id) = flux_lab_si(id) + & - (litt%seed_decay(ipft) + litt%seed_germ_decay(ipft)) * & - EDPftvarcon_inst%lf_flab(ipft) * area_frac* surface_prof(id) - - flux_cel_si(id) = flux_cel_si(id) + & - (litt%seed_decay(ipft) + litt%seed_germ_decay(ipft)) * & - EDPftvarcon_inst%lf_fcel(ipft) * area_frac* surface_prof(id) - - flux_lig_si(id) = flux_lig_si(id) + & - (litt%seed_decay(ipft) + litt%seed_germ_decay(ipft)) * & - EDPftvarcon_inst%lf_flig(ipft) * area_frac* surface_prof(id) + !ahb START + !original code + !------------------------------------------------------------------------ + ! flux_lab_si(id) = flux_lab_si(id) + & + ! (litt%seed_decay(ipft) + litt%seed_germ_decay(ipft)) * & + ! EDPftvarcon_inst%lf_flab(ipft) * area_frac* surface_prof(id) + + ! flux_cel_si(id) = flux_cel_si(id) + & + ! (litt%seed_decay(ipft) + litt%seed_germ_decay(ipft)) * & + ! EDPftvarcon_inst%lf_fcel(ipft) * area_frac* surface_prof(id) + + ! flux_lig_si(id) = flux_lig_si(id) + & + ! (litt%seed_decay(ipft) + litt%seed_germ_decay(ipft)) * & + ! EDPftvarcon_inst%lf_flig(ipft) * area_frac* surface_prof(id) + !------------------------------------------------------------------------- + + !new code + !------------------------------------------------------------------------- + flux_lab_si(id) = flux_lab_si(id) + & + (litt%seed_decay(ipft) + litt%seed_germ_decay(ipft) + litt%non_seed_repro_mass_decay(ipft)) * & + EDPftvarcon_inst%lf_flab(ipft) * area_frac* surface_prof(id) + + flux_cel_si(id) = flux_cel_si(id) + & + (litt%seed_decay(ipft) + litt%seed_germ_decay(ipft) + litt%non_seed_repro_mass_decay(ipft)) * & + EDPftvarcon_inst%lf_fcel(ipft) * area_frac* surface_prof(id) + + flux_lig_si(id) = flux_lig_si(id) + & + (litt%seed_decay(ipft) + litt%seed_germ_decay(ipft) + litt%non_seed_repro_mass_decay(ipft)) * & + EDPftvarcon_inst%lf_flig(ipft) * area_frac* surface_prof(id) + !------------------------------------------------------------------------- end do end do - + !END ahb mods do j = 1, nlev_eff_soil diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index 2688f91fd1..06eafc3d5c 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -141,8 +141,8 @@ module FatesConstantsMod ! Conversion factor: milimeters per meter real(fates_r8), parameter, public :: mm_per_m = 1.0E3_fates_r8 - ! Conversion factor: milimeters per centimeter ahb added this 7/7/2021 - ! read(fates_r8), parameter, public :: mm_per_cm = 1.0E1_fates_r8 + ! Conversion factor: millimeters per centimeter (ahb added this 7/7/2021) + real(fates_r8), parameter, public :: mm_per_cm = 10.0_fates_r8 ! Conversion factor: m2 per ha real(fates_r8), parameter, public :: m2_per_ha = 1.0e4_fates_r8 diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 3d39a207cb..7ade02af5c 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -42,7 +42,7 @@ module PRTAllometricCarbonMod use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : i4 => fates_int use FatesConstantsMod , only : sec_per_day - !use FatesConstantsMod , only : mm_per_cm !ahb added this 7/7/2021 + use FatesConstantsMod , only : mm_per_cm !ahb added this 7/7/2021 use FatesIntegratorsMod , only : RKF45 use FatesIntegratorsMod , only : Euler use FatesConstantsMod , only : calloc_abs_error @@ -909,7 +909,6 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) real(r8) :: ct_ddeaddd ! target structural biomass derivative wrt diameter, (kgC/cm) real(r8) :: ct_dtotaldd ! target total (not reproductive) biomass derivative wrt diameter, (kgC/cm) real(r8) :: repro_fraction ! fraction of carbon balance directed towards reproduction (kgC/kgC) - real(r8), parameter :: mm_per_cm = 10.0_r8 !ahb added this; this is temporary. Need to add this to the FATES constants file associate( dbh => c_pools(dbh_id), & cleaf => c_pools(leaf_c_id), & From 2e287ce9543284bd46ea183c2991037dd1af354d Mon Sep 17 00:00:00 2001 From: adamhb Date: Fri, 9 Jul 2021 09:44:09 -0700 Subject: [PATCH 030/852] model working well, before changes to non-seed reproductive carbon --- biogeochem/EDPhysiologyMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 794a44fd20..a06ac4a25a 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1426,7 +1426,7 @@ subroutine SeedIn( currentSite, bc_in ) call PRTReproRelease(currentCohort%prt,repro_organ,element_id, & 1.0_r8, repro_mass_prod) !ahb changed from seed_prod to repro_mass_prod - seed_prod = repro_mass_prod ! * 0.5_r8 ! only a fraction of reproductive carbon is seed (ahb) + seed_prod = repro_mass_prod ! only a fraction of reproductive carbon is seed (ahb) ! the remainder goes to non-seed reproductive litter !litt%non_seed_repro_mass_decay(pft) = repro_mass_prod * (1.0_r8 - 0.5_r8) ! ahb From cb85933af7578490038d8a83cc700f556968ae2d Mon Sep 17 00:00:00 2001 From: adamhb Date: Fri, 9 Jul 2021 10:04:06 -0700 Subject: [PATCH 031/852] added the reference to the reproductive allocation function --- parteh/PRTAllometricCarbonMod.F90 | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 7ade02af5c..87ec4769c7 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -944,15 +944,23 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) !START ahb's changes !original code - !-------------------------------------------------------------------------------------! + !------------------------------------------------------------------------------------- !if (dbh <= prt_params%dbh_repro_threshold(ipft)) then ! cap on leaf biomass ! repro_fraction = prt_params%seed_alloc(ipft) !else ! repro_fraction = prt_params%seed_alloc(ipft) + prt_params%seed_alloc_mature(ipft) !end if - !-------------------------------------------------------------------------------------! - - !new regeneration code (ahb, July 2021) + !------------------------------------------------------------------------------------- + + !new code + !------------------------------------------------------------------------------------- + !This reproductive allocation function calculates the fraction of available carbon + !allocated to reproductive tissue based on a cohort's size. This function is based on + !empirical data and analysis at BCI (Visser et al., 2016). + + !Visser MD, Bruijning M, Wright SJ, Muller-Landau HC, Jongejans E, Comita LS, + !de Kroon H. 2016. Functional traits as predictors of vital rates across the life cycle + !of tropical trees. Functional Ecology 30: 168–180. !-------------------------------------------------------------------------------------! repro_fraction = prt_params%seed_alloc(ipft) * & (exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm) / & From e53f03b82c470a28d117acd0beffcb372d619638 Mon Sep 17 00:00:00 2001 From: adamhb Date: Fri, 9 Jul 2021 14:11:33 -0700 Subject: [PATCH 032/852] removed my changes to the biogeochem/FatesSoilBGCFluxMod.F90 module --- biogeochem/FatesSoilBGCFluxMod.F90 | 42 ++++++++---------------------- 1 file changed, 11 insertions(+), 31 deletions(-) diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index 50e379aa45..d37cce013e 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -1099,39 +1099,19 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) ! decaying seeds from the litter pool do ipft = 1,numpft do id = 1,nlev_eff_decomp - !ahb START - !original code - !------------------------------------------------------------------------ - ! flux_lab_si(id) = flux_lab_si(id) + & - ! (litt%seed_decay(ipft) + litt%seed_germ_decay(ipft)) * & - ! EDPftvarcon_inst%lf_flab(ipft) * area_frac* surface_prof(id) - - ! flux_cel_si(id) = flux_cel_si(id) + & - ! (litt%seed_decay(ipft) + litt%seed_germ_decay(ipft)) * & - ! EDPftvarcon_inst%lf_fcel(ipft) * area_frac* surface_prof(id) - - ! flux_lig_si(id) = flux_lig_si(id) + & - ! (litt%seed_decay(ipft) + litt%seed_germ_decay(ipft)) * & - ! EDPftvarcon_inst%lf_flig(ipft) * area_frac* surface_prof(id) - !------------------------------------------------------------------------- - - !new code - !------------------------------------------------------------------------- - flux_lab_si(id) = flux_lab_si(id) + & - (litt%seed_decay(ipft) + litt%seed_germ_decay(ipft) + litt%non_seed_repro_mass_decay(ipft)) * & - EDPftvarcon_inst%lf_flab(ipft) * area_frac* surface_prof(id) - - flux_cel_si(id) = flux_cel_si(id) + & - (litt%seed_decay(ipft) + litt%seed_germ_decay(ipft) + litt%non_seed_repro_mass_decay(ipft)) * & - EDPftvarcon_inst%lf_fcel(ipft) * area_frac* surface_prof(id) - - flux_lig_si(id) = flux_lig_si(id) + & - (litt%seed_decay(ipft) + litt%seed_germ_decay(ipft) + litt%non_seed_repro_mass_decay(ipft)) * & - EDPftvarcon_inst%lf_flig(ipft) * area_frac* surface_prof(id) - !------------------------------------------------------------------------- + flux_lab_si(id) = flux_lab_si(id) + & + (litt%seed_decay(ipft) + litt%seed_germ_decay(ipft)) * & + EDPftvarcon_inst%lf_flab(ipft) * area_frac* surface_prof(id) + + flux_cel_si(id) = flux_cel_si(id) + & + (litt%seed_decay(ipft) + litt%seed_germ_decay(ipft)) * & + EDPftvarcon_inst%lf_fcel(ipft) * area_frac* surface_prof(id) + + flux_lig_si(id) = flux_lig_si(id) + & + (litt%seed_decay(ipft) + litt%seed_germ_decay(ipft)) * & + EDPftvarcon_inst%lf_flig(ipft) * area_frac* surface_prof(id) end do end do - !END ahb mods do j = 1, nlev_eff_soil From 8e5373248e34bd24e375fc513465a44297226a45 Mon Sep 17 00:00:00 2001 From: adamhb Date: Tue, 13 Jul 2021 13:36:22 -0700 Subject: [PATCH 033/852] model working --- biogeochem/EDPhysiologyMod.F90 | 38 ++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index a06ac4a25a..ed7c98ddc6 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1367,7 +1367,9 @@ subroutine SeedIn( currentSite, bc_in ) real(r8) :: seed_in_external ! Mass of externally generated seeds [kg/m2/day] real(r8) :: seed_stoich ! Mass ratio of nutrient per C12 in seeds [kg/kg] real(r8) :: repro_mass_prod ! Mass of reproductive material produced [kg/day] ; added by ahb 7/8/2021 + !real(r8), parameter :: repro_frac_seed = 0.5 !added by ahb 7/12/2021 real(r8) :: seed_prod ! Seed produced in this dynamics step [kg/day] + real(r8) :: non_seed_repro_prod ! Mass of non-seed reproductive material produced [kg/day] ; added by ahb 7/10/2021 integer :: n_litt_types ! number of litter element types (c,n,p, etc) integer :: el ! loop counter for litter element types integer :: element_id ! element id consistent with parteh/PRTGenericMod.F90 @@ -1386,6 +1388,7 @@ subroutine SeedIn( currentSite, bc_in ) do while (associated(currentPatch)) currentCohort => currentPatch%tallest + !litt => currentPatch%litter(el) !added by ahb do while (associated(currentCohort)) pft = currentCohort%pft @@ -1405,12 +1408,16 @@ subroutine SeedIn( currentSite, bc_in ) ! specified as input. This routine will also remove the mass ! from the parteh state-variable. + + + + !START ahb changes !-------------------------------------------------------------------------- !original code - !call PRTReproRelease(currentCohort%prt,repro_organ,element_id, & - ! 1.0_r8, seed_prod) + call PRTReproRelease(currentCohort%prt,repro_organ,element_id, & + 1.0_r8, seed_prod) !-------------------------------------------------------------------------- !-------------------------------------------------------------------------- @@ -1423,23 +1430,31 @@ subroutine SeedIn( currentSite, bc_in ) !this within the PRTReproRelease module in parteh/PRTLossFluxesMod.F90::L342 !by adding new live reproductive organs (ahb needs help with this). - call PRTReproRelease(currentCohort%prt,repro_organ,element_id, & - 1.0_r8, repro_mass_prod) !ahb changed from seed_prod to repro_mass_prod + !call PRTReproRelease(currentCohort%prt,repro_organ,element_id, & + ! 1.0_r8, repro_mass_prod) !ahb changed from seed_prod to repro_mass_prod - seed_prod = repro_mass_prod ! only a fraction of reproductive carbon is seed (ahb) + !seed_prod = repro_mass_prod * repro_frac_seed ! seed production per ind. (ahb) + ! only a fraction of reproductive (ahb) + ! mass is seed (ahb) + + !non_seed_repro_prod = repro_mass_prod * (1.0_r8 - repro_frac_seed) !non-seed repro (ahb) + !mass per ind. (ahb) - ! the remainder goes to non-seed reproductive litter - !litt%non_seed_repro_mass_decay(pft) = repro_mass_prod * (1.0_r8 - 0.5_r8) ! ahb + !litt%seed_decay(pft) = non_seed_repro_prod * currentCohort%n / area !send non-seed repro mass to seed decay pool !--------------------------------------------------------------------------- !END ahb changes + + + + if(element_id==carbon12_element)then - currentcohort%seed_prod = seed_prod + currentcohort%seed_prod = seed_prod end if site_seed_rain(pft) = site_seed_rain(pft) + & - (seed_prod * currentCohort%n + store_m_to_repro) + (seed_prod * currentCohort%n + store_m_to_repro) currentCohort => currentCohort%shorter enddo !cohort loop @@ -1525,7 +1540,8 @@ subroutine SeedDecay( litt ) do pft = 1,numpft litt%seed_decay(pft) = litt%seed(pft) * & - EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day + EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day ! + & ! "+ &" added by ahb (7/10/2021) + ! litt%seed_decay(pft) ! whole line added by ahb (7/10/2021) litt%seed_germ_decay(pft) = litt%seed_germ(pft) * & EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day @@ -1569,7 +1585,7 @@ subroutine SeedGermination( litt, cold_stat, drought_stat ) ! that times the ratio of (hypothetical) seed mass to recruit biomass do pft = 1,numpft - litt%seed_germ_in(pft) = min(litt%seed(pft) * EDPftvarcon_inst%germination_rate(pft), & + litt%seed_germ_in(pft) = min(litt%seed(pft) * EDPftvarcon_inst%germination_rate(pft), & max_germination)*years_per_day !set the germination only under the growing season...c.xu From 3c488956c0ba77135300051cbc56b668296a9247 Mon Sep 17 00:00:00 2001 From: adamhb Date: Wed, 14 Jul 2021 14:35:16 -0700 Subject: [PATCH 034/852] added seedling emergence notes --- biogeochem/EDPhysiologyMod.F90 | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index ed7c98ddc6..1baa11dabb 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1584,11 +1584,32 @@ subroutine SeedGermination( litt, cold_stat, drought_stat ) ! and thus the mortality rate (in units of individuals) is the product of ! that times the ratio of (hypothetical) seed mass to recruit biomass + !ORIGINAL CODE + !------------------------------------------------------------------------------------------- do pft = 1,numpft litt%seed_germ_in(pft) = min(litt%seed(pft) * EDPftvarcon_inst%germination_rate(pft), & max_germination)*years_per_day - - !set the germination only under the growing season...c.xu + !------------------------------------------------------------------------------------------- + + !ahb NEW CODE + !------------------------------------------------------------------------------------------- + !Step 1. Define a variable that is the mean SMP in the top 6 cm over the prior 14 days + + !real(r8),parameter :: demerg_soil_depth = 0.06_r8 + !ilayer_swater_emerg = minloc(abs(bc_in%z_sisl(:)-demerg_soil_depth),dim=1) + !smp_emerg_today = bc_in%smp_sl(ilayer_swater_emerg) + !currentSite%water_memory_emerg(1) = smp_emerg_today + !NEED TO BUILD OUT THIS WATER MEMORY MORE + + !do pft = 1,numpft + ! litt%seed_germ_in(pft) = min(litt%seed(pft) * EDPftvarcon_inst%germination_rate(pft), & + ! max_germination)*years_per_day + !------------------------------------------------------------------------------------------- + + + + + !set the germination only under the growing season...c.xu if ((prt_params%season_decid(pft) == itrue ) .and. & (any(cold_stat == [phen_cstat_nevercold,phen_cstat_iscold]))) then From 26a8bfb06da829ad0ed9420382626f01482f3fa3 Mon Sep 17 00:00:00 2001 From: adamhb Date: Thu, 15 Jul 2021 12:37:08 -0700 Subject: [PATCH 035/852] model working with moving a fraction of the seed rain to decay immediately --- biogeochem/EDPhysiologyMod.F90 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index ed7c98ddc6..523cfe8ba4 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1484,6 +1484,11 @@ subroutine SeedIn( currentSite, bc_in ) ! Seed input from local sources (within site) litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)/area + !new code 7/14/2021 ahb + !-------------------------------- + litt%seed_decay(pft) = litt%seed_in_local(pft) * 0.5_r8 + !-------------------------------- + ! If there is forced external seed rain, we calculate the input mass flux ! from the different elements, usung the seed optimal stoichiometry ! for non-carbon From ab9625aae316043213514c5f9122f99cddf73d9f Mon Sep 17 00:00:00 2001 From: adamhb Date: Thu, 15 Jul 2021 19:59:42 -0700 Subject: [PATCH 036/852] Adam Hanbury-Brown added a reproductive allocation scheme to fates. Reproductive allocation is a function of size in this new scheme. Changes are made in AllomCGrowthDeriv function in parteh. The SeedIn subroutine is alos modified so that only a fraction of reproductive carbon goes to the seed bank, while the remainder goes to the litter pool (via the "seed_decay" flux). These changes also required a change to the SeedDecay subroutine so that the non-seed reproductive mass flux from the SeedIn subroutine is added to the decay_decay flux from actual decaying seeds. Three new parameters were added to the fates parameter file for these updates: fates_repro_alloc_a, fates_repro_alloc_b, fates_repro_frac_seed. Fixes: None User interface changes?: No Code review: Adam Hanbury-Brown Test suite: COMPILER=gnu, MACHINE=lobata Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary: COMPILER=gnu, MACHINE=lobata. No formal tests were done. This version of the model is working for a run at BCI. --- biogeochem/EDPhysiologyMod.F90 | 9 +++++---- main/EDPftvarcon.F90 | 10 ++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 523cfe8ba4..cebae23862 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1367,7 +1367,7 @@ subroutine SeedIn( currentSite, bc_in ) real(r8) :: seed_in_external ! Mass of externally generated seeds [kg/m2/day] real(r8) :: seed_stoich ! Mass ratio of nutrient per C12 in seeds [kg/kg] real(r8) :: repro_mass_prod ! Mass of reproductive material produced [kg/day] ; added by ahb 7/8/2021 - !real(r8), parameter :: repro_frac_seed = 0.5 !added by ahb 7/12/2021 + real(r8), parameter :: repro_frac_seed = 0.5 !added by ahb 7/12/2021; move this to param file real(r8) :: seed_prod ! Seed produced in this dynamics step [kg/day] real(r8) :: non_seed_repro_prod ! Mass of non-seed reproductive material produced [kg/day] ; added by ahb 7/10/2021 integer :: n_litt_types ! number of litter element types (c,n,p, etc) @@ -1486,7 +1486,7 @@ subroutine SeedIn( currentSite, bc_in ) !new code 7/14/2021 ahb !-------------------------------- - litt%seed_decay(pft) = litt%seed_in_local(pft) * 0.5_r8 + litt%seed_decay(pft) = litt%seed_in_local(pft) * (1.0_r8 - EDPftvarcon_inst%repro_frac_seed(pft)) !ahb !-------------------------------- ! If there is forced external seed rain, we calculate the input mass flux @@ -1545,8 +1545,9 @@ subroutine SeedDecay( litt ) do pft = 1,numpft litt%seed_decay(pft) = litt%seed(pft) * & - EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day ! + & ! "+ &" added by ahb (7/10/2021) - ! litt%seed_decay(pft) ! whole line added by ahb (7/10/2021) + EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day + & ! "+ &" added by ahb (7/10/2021) + litt%seed_decay(pft) ! line added by ahb so that the flux from non-seed reproductive + ! biomass (from SeedIn subroutine) is not lost (7/10/2021) litt%seed_germ_decay(pft) = litt%seed_germ(pft) * & EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 61f095a758..4934f3920a 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -103,6 +103,7 @@ module EDPftvarcon real(r8), allocatable :: seed_decay_rate(:) ! Fraction of seed mass (both germinated and ! ungerminated), decaying per year (yr-1) + real(r8), allocatable :: repro_frac_seed(:) ! added by ahb 7/15/2021 real(r8), allocatable :: trim_limit(:) ! Limit to reductions in leaf area w stress (m2/m2) real(r8), allocatable :: trim_inc(:) ! Incremental change in trimming function (m2/m2) real(r8), allocatable :: rhol(:, :) @@ -513,6 +514,10 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_repro_frac_seed' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_seed_decay_rate' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -844,6 +849,10 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=this%germination_rate) + name = 'fates_repro_frac_seed' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%repro_frac_seed) + name = 'fates_seed_decay_rate' call fates_params%RetreiveParameterAllocate(name=name, & data=this%seed_decay_rate) @@ -1330,6 +1339,7 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'jmaxse = ',EDPftvarcon_inst%jmaxse write(fates_log(),fmt0) 'germination_timescale = ',EDPftvarcon_inst%germination_rate write(fates_log(),fmt0) 'seed_decay_turnover = ',EDPftvarcon_inst%seed_decay_rate + write(fates_log(),fmt0) 'repro_frac_seed = ',EDPftvarcon_inst%repro_frac_seed write(fates_log(),fmt0) 'trim_limit = ',EDPftvarcon_inst%trim_limit write(fates_log(),fmt0) 'trim_inc = ',EDPftvarcon_inst%trim_inc write(fates_log(),fmt0) 'rhol = ',EDPftvarcon_inst%rhol From b2e0a1f8d9d79f019f802504dd651636fae0a2ba Mon Sep 17 00:00:00 2001 From: adamhb Date: Thu, 15 Jul 2021 20:25:48 -0700 Subject: [PATCH 037/852] AHB cleaned up code and updated the comments of the reproductive allocation scheme. Fixes: None User interface changes?: No Code review: Adam Hanbury-Brown Test summary: None --- parteh/PRTAllometricCarbonMod.F90 | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 87ec4769c7..c988bb9a30 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -942,7 +942,6 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) ! fraction of carbon going towards reproduction !START ahb's changes - !original code !------------------------------------------------------------------------------------- !if (dbh <= prt_params%dbh_repro_threshold(ipft)) then ! cap on leaf biomass @@ -952,7 +951,7 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) !end if !------------------------------------------------------------------------------------- - !new code + !new regeneration code !------------------------------------------------------------------------------------- !This reproductive allocation function calculates the fraction of available carbon !allocated to reproductive tissue based on a cohort's size. This function is based on @@ -961,7 +960,7 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) !Visser MD, Bruijning M, Wright SJ, Muller-Landau HC, Jongejans E, Comita LS, !de Kroon H. 2016. Functional traits as predictors of vital rates across the life cycle !of tropical trees. Functional Ecology 30: 168–180. - !-------------------------------------------------------------------------------------! + !------------------------------------------------------------------------------------- repro_fraction = prt_params%seed_alloc(ipft) * & (exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm) / & (1 + exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_b(ipft)*dbh*mm_per_cm))) From 32c6146f744d40e0b6c80cc61ec06b779f6f8aee Mon Sep 17 00:00:00 2001 From: adamhb Date: Thu, 15 Jul 2021 20:29:30 -0700 Subject: [PATCH 038/852] Cleaned up comments to the reproductive allocation scheme and the SeedIn subroutine. Fixes: none User interface changes?: No Code review: Adam Hanbury-Brown Tests: none --- biogeochem/EDPhysiologyMod.F90 | 45 +++++----------------------------- 1 file changed, 6 insertions(+), 39 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index cebae23862..b5f24bffb2 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1407,47 +1407,9 @@ subroutine SeedIn( currentSite, bc_in ) ! of seeds [kg] released by the plant, per the mass_fraction ! specified as input. This routine will also remove the mass ! from the parteh state-variable. - - - - - - !START ahb changes - !-------------------------------------------------------------------------- - !original code call PRTReproRelease(currentCohort%prt,repro_organ,element_id, & 1.0_r8, seed_prod) - !-------------------------------------------------------------------------- - - !-------------------------------------------------------------------------- - !ahb's new code - !the original code sends all reproductive tissue to seed - !This new code, added by ahb, is designed to send some reproductive biomass - !straight to the leaf litter pool to account for non-seed reproductive - !biomass. For now, ahb does this after the call to the - !PRTReproRelease function, but a better solution would probably be to do - !this within the PRTReproRelease module in parteh/PRTLossFluxesMod.F90::L342 - !by adding new live reproductive organs (ahb needs help with this). - - !call PRTReproRelease(currentCohort%prt,repro_organ,element_id, & - ! 1.0_r8, repro_mass_prod) !ahb changed from seed_prod to repro_mass_prod - - !seed_prod = repro_mass_prod * repro_frac_seed ! seed production per ind. (ahb) - ! only a fraction of reproductive (ahb) - ! mass is seed (ahb) - - !non_seed_repro_prod = repro_mass_prod * (1.0_r8 - repro_frac_seed) !non-seed repro (ahb) - !mass per ind. (ahb) - - !litt%seed_decay(pft) = non_seed_repro_prod * currentCohort%n / area !send non-seed repro mass to seed decay pool - !--------------------------------------------------------------------------- - - !END ahb changes - - - - if(element_id==carbon12_element)then currentcohort%seed_prod = seed_prod @@ -1484,7 +1446,12 @@ subroutine SeedIn( currentSite, bc_in ) ! Seed input from local sources (within site) litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)/area - !new code 7/14/2021 ahb + !New regeneration code added by ahb on 7/15/2021 + !The original code sends all reproductive tissue to seed + !This new code is designed to send some reproductive biomass + !straight to the leaf litter pool to account for non-seed reproductive + !biomass. Also see small change to SeedDecay subroutine. + !This can be turned off by commenting out line 1456. !-------------------------------- litt%seed_decay(pft) = litt%seed_in_local(pft) * (1.0_r8 - EDPftvarcon_inst%repro_frac_seed(pft)) !ahb !-------------------------------- From 0e476131b78df1f3eec612f84d44df77021e9853 Mon Sep 17 00:00:00 2001 From: adamhb Date: Fri, 16 Jul 2021 10:54:00 -0700 Subject: [PATCH 039/852] commit prior to the creation of a seedling pool --- biogeochem/EDPhysiologyMod.F90.save | 2396 +++++++++++++++++++++++++++ 1 file changed, 2396 insertions(+) create mode 100644 biogeochem/EDPhysiologyMod.F90.save diff --git a/biogeochem/EDPhysiologyMod.F90.save b/biogeochem/EDPhysiologyMod.F90.save new file mode 100644 index 0000000000..9a068eb85c --- /dev/null +++ b/biogeochem/EDPhysiologyMod.F90.save @@ -0,0 +1,2396 @@ +module EDPhysiologyMod + +#include "shr_assert.h" + + ! ============================================================================ + ! Miscellaneous physiology routines from ED. + ! ============================================================================ + + use FatesGlobals, only : fates_log + use FatesInterfaceTypesMod, only : hlm_days_per_year + use FatesInterfaceTypesMod, only : hlm_model_day + use FatesInterfaceTypesMod, only : hlm_freq_day + use FatesInterfaceTypesMod, only : hlm_day_of_year + use FatesInterfaceTypesMod, only : numpft + use FatesInterfaceTypesMod, only : nleafage + use FatesInterfaceTypesMod, only : hlm_use_planthydro + use FatesInterfaceTypesMod, only : hlm_parteh_mode + use FatesInterfaceTypesMod, only : hlm_nitrogen_spec + use FatesInterfaceTypesMod, only : hlm_phosphorus_spec + use FatesConstantsMod, only : r8 => fates_r8 + use FatesConstantsMod, only : nearzero + use EDPftvarcon , only : EDPftvarcon_inst + use PRTParametersMod , only : prt_params + use EDPftvarcon , only : GetDecompyFrac + use FatesInterfaceTypesMod, only : bc_in_type + use FatesInterfaceTypesMod, only : bc_out_type + use EDCohortDynamicsMod , only : zero_cohort + use EDCohortDynamicsMod , only : create_cohort, sort_cohorts + use EDCohortDynamicsMod , only : InitPRTObject + use FatesAllometryMod , only : tree_lai + use FatesAllometryMod , only : tree_sai + use FatesAllometryMod , only : decay_coeff_kn + use FatesLitterMod , only : litter_type + use EDTypesMod , only : site_massbal_type + use EDTypesMod , only : numlevsoil_max + use EDTypesMod , only : numWaterMem + use EDTypesMod , only : dl_sf, dinc_ed, area_inv + use FatesLitterMod , only : ncwd + use FatesLitterMod , only : ndcmpy + use FatesLitterMod , only : ilabile + use FatesLitterMod , only : ilignin + use FatesLitterMod , only : icellulose + use EDTypesMod , only : AREA,AREA_INV + use EDTypesMod , only : nlevleaf + use EDTypesMod , only : num_vegtemp_mem + use EDTypesMod , only : maxpft + use EDTypesMod , only : ed_site_type, ed_patch_type, ed_cohort_type + use EDTypesMod , only : leaves_on + use EDTypesMod , only : leaves_off + use EDTypesMod , only : min_n_safemath + use PRTGenericMod , only : num_elements + use PRTGenericMod , only : element_list + use PRTGenericMod , only : element_pos + use EDTypesMod , only : site_fluxdiags_type + use EDTypesMod , only : phen_cstat_nevercold + use EDTypesMod , only : phen_cstat_iscold + use EDTypesMod , only : phen_cstat_notcold + use EDTypesMod , only : phen_dstat_timeoff + use EDTypesMod , only : phen_dstat_moistoff + use EDTypesMod , only : phen_dstat_moiston + use EDTypesMod , only : phen_dstat_timeon + use EDTypesMod , only : init_recruit_trim + use shr_log_mod , only : errMsg => shr_log_errMsg + use FatesGlobals , only : fates_log + use FatesGlobals , only : endrun => fates_endrun + use EDParamsMod , only : fates_mortality_disturbance_fraction + use EDParamsMod , only : q10_mr + use EDParamsMod , only : q10_froz + use EDParamsMod , only : logging_export_frac + use FatesPlantHydraulicsMod , only : AccumulateMortalityWaterStorage + use FatesConstantsMod , only : itrue,ifalse + use FatesConstantsMod , only : calloc_abs_error + use FatesConstantsMod , only : years_per_day + use FatesAllometryMod , only : h_allom + use FatesAllometryMod , only : h2d_allom + use FatesAllometryMod , only : bagw_allom + use FatesAllometryMod , only : bsap_allom + use FatesAllometryMod , only : bleaf + use FatesAllometryMod , only : bfineroot + use FatesAllometryMod , only : bdead_allom + use FatesAllometryMod , only : bstore_allom + use FatesAllometryMod , only : bbgw_allom + use FatesAllometryMod , only : carea_allom + use FatesAllometryMod , only : CheckIntegratedAllometries + use FatesAllometryMod, only : set_root_fraction + use PRTGenericMod, only : prt_carbon_allom_hyp + use PRTGenericMod, only : prt_cnp_flex_allom_hyp + use PRTGenericMod, only : prt_vartypes + use PRTGenericMod, only : leaf_organ + use PRTGenericMod, only : sapw_organ, struct_organ + use PRTGenericMod, only : all_carbon_elements + use PRTGenericMod, only : carbon12_element + use PRTGenericMod, only : nitrogen_element + use PRTGenericMod, only : phosphorus_element + use PRTGenericMod, only : leaf_organ + use PRTGenericMod, only : fnrt_organ + use PRTGenericMod, only : sapw_organ + use PRTGenericMod, only : store_organ + use PRTGenericMod, only : repro_organ + use PRTGenericMod, only : struct_organ + use PRTGenericMod, only : SetState + use PRTLossFluxesMod, only : PRTPhenologyFlush + use PRTLossFluxesMod, only : PRTDeciduousTurnover + use PRTLossFluxesMod, only : PRTReproRelease + use PRTGenericMod, only : StorageNutrientTarget + + implicit none + private + + public :: trim_canopy + public :: phenology + public :: recruitment + public :: ZeroLitterFluxes + + public :: ZeroAllocationRates + public :: PreDisturbanceLitterFluxes + public :: PreDisturbanceIntegrateLitter + public :: SeedIn + + logical, parameter :: debug = .false. ! local debug flag + character(len=*), parameter, private :: sourcefile = & + __FILE__ + + integer, parameter :: dleafon_drycheck = 100 ! Drought deciduous leaves max days on check parameter + + + ! ============================================================================ + +contains + + subroutine ZeroLitterFluxes( currentSite ) + + ! This routine loops through all patches in a site + ! and zero's the flux terms for the litter pools. + ! This is typically called at the beginning of the dynamics + ! call sequence. + + + ! !ARGUMENTS + type(ed_site_type), intent(inout), target :: currentSite + type(ed_patch_type), pointer :: currentPatch + + integer :: el + + currentPatch => currentSite%youngest_patch + do while(associated(currentPatch)) + do el=1,num_elements + call currentPatch%litter(el)%ZeroFlux() + end do + currentPatch => currentPatch%older + end do + + + return + end subroutine ZeroLitterFluxes + + ! ===================================================================================== + + subroutine ZeroAllocationRates( currentSite ) + + ! !ARGUMENTS + type(ed_site_type), intent(inout), target :: currentSite + type(ed_patch_type), pointer :: currentPatch + type(ed_cohort_type), pointer :: currentCohort + + currentPatch => currentSite%youngest_patch + do while(associated(currentPatch)) + + currentCohort => currentPatch%tallest + do while (associated(currentCohort)) + + ! This sets turnover and growth rates to zero + call currentCohort%prt%ZeroRates() + + currentCohort => currentCohort%shorter + enddo + currentPatch => currentPatch%older + end do + + return + end subroutine ZeroAllocationRates + + + ! ============================================================================ + + subroutine PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in ) + + ! ----------------------------------------------------------------------------------- + ! + ! This subroutine calculates all of the different litter input and output fluxes + ! associated with seed turnover, seed influx, litterfall from live and + ! dead plants, germination, and fragmentation. + ! + ! At this time we do not have explicit herbivory, and burning losses to litter + ! are handled elsewhere. + ! + ! Note: The processes conducted here DO NOT handle litter fluxes associated + ! with disturbance. Those fluxes are handled elsewhere (EDPatchDynamcisMod) + ! because the fluxes are potentially cross patch, and also dealing + ! patch areas that are changing. + ! + ! ----------------------------------------------------------------------------------- + + + ! !ARGUMENTS + type(ed_site_type), intent(inout) :: currentSite + type(ed_patch_type), intent(inout) :: currentPatch + type(bc_in_type), intent(in) :: bc_in + + ! + ! !LOCAL VARIABLES: + type(site_massbal_type), pointer :: site_mass + type(litter_type), pointer :: litt ! Points to the litter object for + ! the different element types + integer :: el ! Litter element loop index + integer :: nlev_eff_decomp ! Number of active layers over which + ! fragmentation fluxes are transfered + !------------------------------------------------------------------------------------ + + ! Calculate the fragmentation rates + call fragmentation_scaler(currentPatch, bc_in) + + + do el = 1, num_elements + + litt => currentPatch%litter(el) + + ! Calculate loss rate of viable seeds to litter + call SeedDecay(litt) + + ! Calculate seed germination rate, the status flags prevent + ! germination from occuring when the site is in a drought + ! (for drought deciduous) or too cold (for cold deciduous) + call SeedGermination(litt, currentSite%cstatus, currentSite%dstatus) + + ! Send fluxes from newly created litter into the litter pools + ! This litter flux is from non-disturbance inducing mortality, as well + ! as litter fluxes from live trees + call CWDInput(currentSite, currentPatch, litt,bc_in) + + + ! Only calculate fragmentation flux over layers that are active + ! (RGK-Mar2019) SHOULD WE MAX THIS AT 1? DONT HAVE TO + + nlev_eff_decomp = max(bc_in%max_rooting_depth_index_col, 1) + call CWDOut(litt,currentPatch%fragmentation_scaler,nlev_eff_decomp) + + + site_mass => currentSite%mass_balance(el) + + ! Fragmentation flux to soil decomposition model [kg/site/day] + site_mass%frag_out = site_mass%frag_out + currentPatch%area * & + ( sum(litt%ag_cwd_frag) + sum(litt%bg_cwd_frag) + & + sum(litt%leaf_fines_frag) + sum(litt%root_fines_frag) + & + !sum(litt%non_seed_repro_mass_decay) + & !ahb added this line on 7/8/2021 + sum(litt%seed_decay) + sum(litt%seed_germ_decay)) + + end do + + + return + end subroutine PreDisturbanceLitterFluxes + + ! ===================================================================================== + + subroutine PreDisturbanceIntegrateLitter(currentPatch) + + ! ----------------------------------------------------------------------------------- + ! + ! This step applies the litter fluxes to the prognostic state variables. + ! This procedure is called in response to fluxes generated from: + ! 1) seed rain, + ! 2) non-disturbance generating turnover + ! 3) litter fall from living plants + ! 4) fragmentation + ! + ! This routine does NOT accomodate the litter fluxes associated with + ! disturbance generation. That will happen after this call. + ! Fluxes associated with FIRE also happen after this step. + ! + ! All states are in units kg/m2 + ! All fluxes are in units kg/m2/day + ! The integration step is 1 day, thus time is implied + ! + ! ----------------------------------------------------------------------------------- + + ! Arguments + type(ed_patch_type),intent(inout),target :: currentPatch + + + ! Locals + type(litter_type), pointer :: litt + integer :: el ! Loop counter for litter element type + integer :: pft ! pft loop counter + integer :: c ! CWD loop counter + integer :: nlevsoil ! number of soil layers + integer :: ilyr ! soil layer loop counter + integer :: dcmpy ! decomposability index + + do el = 1, num_elements + + litt => currentPatch%litter(el) + + ! Update the bank of viable seeds + ! ----------------------------------------------------------------------------------- + + do pft = 1,numpft + litt%seed(pft) = litt%seed(pft) + & + litt%seed_in_local(pft) + & + litt%seed_in_extern(pft) - & + litt%seed_decay(pft) - & + litt%seed_germ_in(pft) + + ! Note that the recruitment scheme will use seed_germ + ! for its construction costs. + litt%seed_germ(pft) = litt%seed_germ(pft) + & + litt%seed_germ_in(pft) - & + litt%seed_germ_decay(pft) + + + enddo + + ! Update the Coarse Woody Debris pools (above and below) + ! ----------------------------------------------------------------------------------- + nlevsoil = size(litt%bg_cwd,dim=2) + do c = 1,ncwd + litt%ag_cwd(c) = litt%ag_cwd(c) + litt%ag_cwd_in(c) - litt%ag_cwd_frag(c) + do ilyr=1,nlevsoil + litt%bg_cwd(c,ilyr) = litt%bg_cwd(c,ilyr) & + + litt%bg_cwd_in(c,ilyr) & + - litt%bg_cwd_frag(c,ilyr) + enddo + end do + + ! Update the fine litter pools from leaves and fine-roots + ! ----------------------------------------------------------------------------------- + + do dcmpy = 1,ndcmpy + + litt%leaf_fines(dcmpy) = litt%leaf_fines(dcmpy) & + + litt%leaf_fines_in(dcmpy) & + - litt%leaf_fines_frag(dcmpy) + do ilyr=1,nlevsoil + litt%root_fines(dcmpy,ilyr) = litt%root_fines(dcmpy,ilyr) & + + litt%root_fines_in(dcmpy,ilyr) & + - litt%root_fines_frag(dcmpy,ilyr) + enddo + + end do + + end do ! litter element loop + + return + end subroutine PreDisturbanceIntegrateLitter + + + + ! ============================================================================ + + subroutine trim_canopy( currentSite ) + ! + ! !DESCRIPTION: + ! Canopy trimming / leaf optimisation. Removes leaves in negative annual carbon balance. + ! + ! !USES: + + ! !ARGUMENTS + type (ed_site_type),intent(inout), target :: currentSite + ! + ! !LOCAL VARIABLES: + type (ed_cohort_type) , pointer :: currentCohort + type (ed_patch_type) , pointer :: currentPatch + + integer :: z ! leaf layer + integer :: ipft ! pft index + logical :: trimmed ! was this layer trimmed in this year? If not expand the canopy. + real(r8) :: tar_bl ! target leaf biomass (leaves flushed, trimmed) + real(r8) :: tar_bfr ! target fine-root biomass (leaves flushed, trimmed) + real(r8) :: bfr_per_bleaf ! ratio of fine root per leaf biomass + real(r8) :: sla_levleaf ! sla at leaf level z + real(r8) :: nscaler_levleaf ! nscaler value at leaf level z + integer :: cl ! canopy layer index + real(r8) :: kn ! nitrogen decay coefficient + real(r8) :: sla_max ! Observational constraint on how large sla (m2/gC) can become + real(r8) :: leaf_c ! leaf carbon [kg] + real(r8) :: sapw_c ! sapwood carbon [kg] + real(r8) :: store_c ! storage carbon [kg] + real(r8) :: struct_c ! structure carbon [kg] + real(r8) :: leaf_inc ! LAI-only portion of the vegetation increment of dinc_ed + real(r8) :: lai_canopy_above ! the LAI in the canopy layers above the layer of interest + real(r8) :: lai_layers_above ! the LAI in the leaf layers, within the current canopy, + ! above the leaf layer of interest + real(r8) :: lai_current ! the LAI in the current leaf layer + real(r8) :: cumulative_lai ! whole canopy cumulative LAI, top down, to the leaf layer of interest + real(r8) :: cumulative_lai_cohort ! cumulative LAI within the current cohort only + + ! Temporary diagnostic ouptut + integer :: ipatch + integer :: icohort + + ! LAPACK linear least squares fit variables + ! The standard equation for a linear fit, y = mx + b, is converted to a linear system, AX=B and has + ! the form: [n sum(x); sum(x) sum(x^2)] * [b; m] = [sum(y); sum(x*y)] where + ! n is the number of leaf layers + ! x is yearly_net_uptake minus the leaf cost aka the net-net uptake + ! y is the cumulative lai for the current cohort + ! b is the y-intercept i.e. the cumulative lai that has zero net-net uptake + ! m is the slope of the linear fit + integer :: nll = 3 ! Number of leaf layers to fit a regression to for calculating the optimum lai + character(1) :: trans = 'N' ! Input matrix is not transposed + + integer, parameter :: m = 2, n = 2 ! Number of rows and columns, respectively, in matrix A + integer, parameter :: nrhs = 1 ! Number of columns in matrix B and X + integer, parameter :: workmax = 100 ! Maximum iterations to minimize work + + integer :: lda = m, ldb = n ! Leading dimension of A and B, respectively + integer :: lwork ! Dimension of work array + integer :: info ! Procedure diagnostic ouput + + real(r8) :: nnu_clai_a(m,n) ! LHS of linear least squares fit, A matrix + real(r8) :: nnu_clai_b(m,nrhs) ! RHS of linear least squares fit, B matrix + real(r8) :: work(workmax) ! work array + + real(r8) :: initial_trim ! Initial trim + real(r8) :: optimum_trim ! Optimum trim value + real(r8) :: initial_laimem ! Initial laimemory + real(r8) :: optimum_laimem ! Optimum laimemory + + !---------------------------------------------------------------------- + + ipatch = 1 ! Start counting patches + + currentPatch => currentSite%youngest_patch + do while(associated(currentPatch)) + + ! Add debug diagnstic output to determine which patch + if (debug) then + write(fates_log(),*) 'Current patch:', ipatch + write(fates_log(),*) 'Current patch cohorts:', currentPatch%countcohorts + endif + + icohort = 1 + + currentCohort => currentPatch%tallest + do while (associated(currentCohort)) + + ! Save off the incoming trim and laimemory + initial_trim = currentCohort%canopy_trim + initial_laimem = currentCohort%laimemory + + ! Add debug diagnstic output to determine which cohort + if (debug) then + write(fates_log(),*) 'Current cohort:', icohort + write(fates_log(),*) 'Starting canopy trim:', initial_trim + write(fates_log(),*) 'Starting laimemory:', currentCohort%laimemory + endif + + trimmed = .false. + ipft = currentCohort%pft + call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread,currentCohort%pft,currentCohort%c_area) + + leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) + + currentCohort%treelai = tree_lai(leaf_c, currentCohort%pft, currentCohort%c_area, & + currentCohort%n, currentCohort%canopy_layer, & + currentPatch%canopy_layer_tlai,currentCohort%vcmax25top ) + + currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_trim, & + currentCohort%c_area, currentCohort%n, currentCohort%canopy_layer, & + currentPatch%canopy_layer_tlai, currentCohort%treelai, & + currentCohort%vcmax25top,0 ) + + currentCohort%nv = ceiling((currentCohort%treelai+currentCohort%treesai)/dinc_ed) + + if (currentCohort%nv > nlevleaf)then + write(fates_log(),*) 'nv > nlevleaf',currentCohort%nv, & + currentCohort%treelai,currentCohort%treesai, & + currentCohort%c_area,currentCohort%n,leaf_c + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + + call bleaf(currentcohort%dbh,ipft,currentcohort%canopy_trim,tar_bl) + + if ( int(prt_params%allom_fmode(ipft)) .eq. 1 ) then + ! only query fine root biomass if using a fine root allometric model that takes leaf trim into account + call bfineroot(currentcohort%dbh,ipft,currentcohort%canopy_trim,tar_bfr) + bfr_per_bleaf = tar_bfr/tar_bl + endif + + ! Identify current canopy layer (cl) + cl = currentCohort%canopy_layer + + ! PFT-level maximum SLA value, even if under a thick canopy (same units as slatop) + sla_max = prt_params%slamax(ipft) + + ! Initialize nnu_clai_a + nnu_clai_a(:,:) = 0._r8 + nnu_clai_b(:,:) = 0._r8 + + !Leaf cost vs netuptake for each leaf layer. + do z = 1, currentCohort%nv + + ! Calculate the cumulative total vegetation area index (no snow occlusion, stems and leaves) + + leaf_inc = dinc_ed * & + currentCohort%treelai/(currentCohort%treelai+currentCohort%treesai) + + ! Now calculate the cumulative top-down lai of the current layer's midpoint within the current cohort + lai_layers_above = leaf_inc * (z-1) + lai_current = min(leaf_inc, currentCohort%treelai - lai_layers_above) + cumulative_lai_cohort = lai_layers_above + 0.5*lai_current + + ! Now add in the lai above the current cohort for calculating the sla leaf level + lai_canopy_above = sum(currentPatch%canopy_layer_tlai(1:cl-1)) + cumulative_lai = lai_canopy_above + cumulative_lai_cohort + + ! There was activity this year in this leaf layer. This should only occur for bottom most leaf layer + if (currentCohort%year_net_uptake(z) /= 999._r8)then + + ! Calculate sla_levleaf following the sla profile with overlying leaf area + ! Scale for leaf nitrogen profile + kn = decay_coeff_kn(ipft,currentCohort%vcmax25top) + ! Nscaler value at leaf level z + nscaler_levleaf = exp(-kn * cumulative_lai) + ! Sla value at leaf level z after nitrogen profile scaling (m2/gC) + sla_levleaf = prt_params%slatop(ipft)/nscaler_levleaf + + if(sla_levleaf > sla_max)then + sla_levleaf = sla_max + end if + + !Leaf Cost kgC/m2/year-1 + !decidous costs. + if (prt_params%season_decid(ipft) == itrue .or. & + prt_params%stress_decid(ipft) == itrue )then + + ! Leaf cost at leaf level z accounting for sla profile (kgC/m2) + currentCohort%leaf_cost = 1._r8/(sla_levleaf*1000.0_r8) + + if ( int(prt_params%allom_fmode(ipft)) .eq. 1 ) then + ! if using trimmed leaf for fine root biomass allometry, add the cost of the root increment + ! to the leaf increment; otherwise do not. + currentCohort%leaf_cost = currentCohort%leaf_cost + & + 1.0_r8/(sla_levleaf*1000.0_r8) * & + bfr_per_bleaf / prt_params%root_long(ipft) + endif + + currentCohort%leaf_cost = currentCohort%leaf_cost * & + (prt_params%grperc(ipft) + 1._r8) + else !evergreen costs + + ! Leaf cost at leaf level z accounting for sla profile + currentCohort%leaf_cost = 1.0_r8/(sla_levleaf* & + sum(prt_params%leaf_long(ipft,:))*1000.0_r8) !convert from sla in m2g-1 to m2kg-1 + + + if ( int(prt_params%allom_fmode(ipft)) .eq. 1 ) then + ! if using trimmed leaf for fine root biomass allometry, add the cost of the root increment + ! to the leaf increment; otherwise do not. + currentCohort%leaf_cost = currentCohort%leaf_cost + & + 1.0_r8/(sla_levleaf*1000.0_r8) * & + bfr_per_bleaf / prt_params%root_long(ipft) + endif + currentCohort%leaf_cost = currentCohort%leaf_cost * & + (prt_params%grperc(ipft) + 1._r8) + endif + + ! Construct the arrays for a least square fit of the net_net_uptake versus the cumulative lai + ! if at least nll leaf layers are present in the current cohort and only for the bottom nll + ! leaf layers. + if (currentCohort%nv > nll .and. currentCohort%nv - z < nll) then + + ! Build the A matrix for the LHS of the linear system. A = [n sum(x); sum(x) sum(x^2)] + ! where n = nll and x = yearly_net_uptake-leafcost + nnu_clai_a(1,1) = nnu_clai_a(1,1) + 1 ! Increment for each layer used + nnu_clai_a(1,2) = nnu_clai_a(1,2) + currentCohort%year_net_uptake(z) - currentCohort%leaf_cost + nnu_clai_a(2,1) = nnu_clai_a(1,2) + nnu_clai_a(2,2) = nnu_clai_a(2,2) + (currentCohort%year_net_uptake(z) - currentCohort%leaf_cost)**2 + + ! Build the B matrix for the RHS of the linear system. B = [sum(y); sum(x*y)] + ! where x = yearly_net_uptake-leafcost and y = cumulative_lai_cohort + nnu_clai_b(1,1) = nnu_clai_b(1,1) + cumulative_lai_cohort + nnu_clai_b(2,1) = nnu_clai_b(2,1) + (cumulative_lai_cohort * & + (currentCohort%year_net_uptake(z) - currentCohort%leaf_cost)) + end if + + ! Check leaf cost against the yearly net uptake for that cohort leaf layer + if (currentCohort%year_net_uptake(z) < currentCohort%leaf_cost) then + ! Make sure the cohort trim fraction is great than the pft trim limit + if (currentCohort%canopy_trim > EDPftvarcon_inst%trim_limit(ipft)) then + + ! if ( debug ) then + ! write(fates_log(),*) 'trimming leaves', & + ! currentCohort%canopy_trim,currentCohort%leaf_cost + ! endif + + ! keep trimming until none of the canopy is in negative carbon balance. + if (currentCohort%hite > EDPftvarcon_inst%hgt_min(ipft)) then + currentCohort%canopy_trim = currentCohort%canopy_trim - & + EDPftvarcon_inst%trim_inc(ipft) + if (prt_params%evergreen(ipft) /= 1)then + currentCohort%laimemory = currentCohort%laimemory * & + (1.0_r8 - EDPftvarcon_inst%trim_inc(ipft)) + endif + + trimmed = .true. + + endif ! hite check + endif ! trim limit check + endif ! net uptake check + endif ! leaf activity check + enddo ! z, leaf layer loop + + ! Compute the optimal cumulative lai based on the cohort net-net uptake profile if at least 2 leaf layers + if (nnu_clai_a(1,1) > 1) then + + ! Compute the optimum size of the work array + lwork = -1 ! Ask sgels to compute optimal number of entries for work + call dgels(trans, m, n, nrhs, nnu_clai_a, lda, nnu_clai_b, ldb, work, lwork, info) + lwork = int(work(1)) ! Pick the optimum. TBD, can work(1) come back with greater than work size? + + ! if (debug) then + ! write(fates_log(),*) 'LLSF lwork output (info, lwork):', info, lwork + ! endif + + ! Compute the minimum of 2-norm of of the least squares fit to solve for X + ! Note that dgels returns the solution by overwriting the nnu_clai_b array. + ! The result has the form: X = [b; m] + ! where b = y-intercept (i.e. the cohort lai that has zero yearly net-net uptake) + ! and m is the slope of the linear fit + call dgels(trans, m, n, nrhs, nnu_clai_a, lda, nnu_clai_b, ldb, work, lwork, info) + + if (info < 0) then + write(fates_log(),*) 'LLSF optimium LAI calculation returned illegal value' + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + + if (debug) then + write(fates_log(),*) 'LLSF optimium LAI (intercept,slope):', nnu_clai_b + write(fates_log(),*) 'LLSF optimium LAI:', nnu_clai_b(1,1) + write(fates_log(),*) 'LLSF optimium LAI info:', info + write(fates_log(),*) 'LAI fraction (optimum_lai/cumulative_lai):', nnu_clai_b(1,1) / cumulative_lai_cohort + endif + + ! Calculate the optimum trim based on the initial canopy trim value + if (cumulative_lai_cohort > 0._r8) then ! Sometime cumulative_lai comes in at 0.0? + + ! + optimum_trim = (nnu_clai_b(1,1) / cumulative_lai_cohort) * initial_trim + optimum_laimem = (nnu_clai_b(1,1) / cumulative_lai_cohort) * initial_laimem + + ! Determine if the optimum trim value makes sense. The smallest cohorts tend to have unrealistic fits. + if (optimum_trim > 0. .and. optimum_trim < 1.) then + currentCohort%canopy_trim = optimum_trim + + ! If the cohort pft is not evergreen we reduce the laimemory as well + if (prt_params%evergreen(ipft) /= 1) then + currentCohort%laimemory = optimum_laimem + endif + + trimmed = .true. + + endif + endif + endif + + ! Reset activity for the cohort for the start of the next year + currentCohort%year_net_uptake(:) = 999.0_r8 + + ! Add to trim fraction if cohort not trimmed at all + if ( (.not.trimmed) .and.currentCohort%canopy_trim < 1.0_r8)then + currentCohort%canopy_trim = currentCohort%canopy_trim + EDPftvarcon_inst%trim_inc(ipft) + endif + + if ( debug ) then + write(fates_log(),*) 'trimming:',currentCohort%canopy_trim + endif + + ! currentCohort%canopy_trim = 1.0_r8 !FIX(RF,032414) this turns off ctrim for now. + currentCohort => currentCohort%shorter + icohort = icohort + 1 + enddo + currentPatch => currentPatch%older + ipatch = ipatch + 1 + enddo + + end subroutine trim_canopy + + ! ============================================================================ + subroutine phenology( currentSite, bc_in ) + ! + ! !DESCRIPTION: + ! Phenology. + ! + ! !USES: + use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm + use EDParamsMod, only : ED_val_phen_drought_threshold, ED_val_phen_doff_time + use EDParamsMod, only : ED_val_phen_a, ED_val_phen_b, ED_val_phen_c, ED_val_phen_chiltemp + use EDParamsMod, only : ED_val_phen_mindayson, ED_val_phen_ncolddayslim, ED_val_phen_coldtemp + + + ! + ! !ARGUMENTS: + type(ed_site_type), intent(inout), target :: currentSite + type(bc_in_type), intent(in) :: bc_in + + ! + ! !LOCAL VARIABLES: + + type(ed_patch_type),pointer :: cpatch + integer :: model_day_int ! integer model day 1 - inf + integer :: ncolddays ! no days underneath the threshold for leaf drop + integer :: i_wmem ! Loop counter for water mem days + integer :: i_tmem ! Loop counter for veg temp mem days + integer :: dayssincedleafon ! Days since drought-decid leaf-on started + integer :: dayssincedleafoff ! Days since drought-decid leaf-off started + integer :: dayssincecleafon ! Days since cold-decid leaf-on started + integer :: dayssincecleafoff ! Days since cold-decid leaf-off started + real(r8) :: mean_10day_liqvol ! mean liquid volume (m3/m3) over last 10 days + real(r8) :: leaf_c ! leaf carbon [kg] + real(r8) :: fnrt_c ! fineroot carbon [kg] + real(r8) :: sapw_c ! sapwood carbon [kg] + real(r8) :: store_c ! storage carbon [kg] + real(r8) :: struct_c ! structure carbon [kg] + real(r8) :: gdd_threshold ! GDD accumulation function, + integer :: ilayer_swater ! Layer index for soil water + ! which also depends on chilling days. + integer :: ncdstart ! beginning of counting period for chilling degree days. + integer :: gddstart ! beginning of counting period for growing degree days. + real(r8) :: temp_in_C ! daily averaged temperature in celcius + + integer, parameter :: canopy_leaf_lifespan = 365 ! Maximum lifespan of drought decid leaves + + integer, parameter :: min_daysoff_dforcedflush = 30 ! THis is the number of days that must had elapsed + ! since leaves had dropped, in order to forcably + ! flush leaves again. This does not impact flushing + ! due to real moisture constraints, and will prevent + ! drought deciduous in perennially wet environments + ! that have been forced to drop their leaves, from + ! flushing them back immediately. + + real(r8),parameter :: dphen_soil_depth = 0.1 ! Use liquid soil water that is + ! closest to this depth [m] + + ! This is the integer model day. The first day of the simulation is 1, and it + ! continues monotonically, indefinitely + model_day_int = nint(hlm_model_day) + + + ! Use the following layer index to calculate drought conditions + ilayer_swater = minloc(abs(bc_in%z_sisl(:)-dphen_soil_depth),dim=1) + + + ! Parameter of drought decid leaf loss in mm in top layer...FIX(RF,032414) + ! - this is arbitrary and poorly understood. Needs work. ED_ + !Parameters: defaults from Botta et al. 2000 GCB,6 709-725 + !Parameters, default from from SDGVM model of senesence + + temp_in_C = 0._r8 + cpatch => CurrentSite%oldest_patch + do while(associated(cpatch)) + temp_in_C = temp_in_C + bc_in%t_veg24_pa(cpatch%patchno)*cpatch%area + cpatch => cpatch%younger + end do + temp_in_C = temp_in_C * area_inv - tfrz + + + !-----------------Cold Phenology--------------------! + + !Zero growing degree and chilling day counters + if (currentSite%lat > 0)then + ncdstart = 270 !Northern Hemisphere begining November + gddstart = 1 !Northern Hemisphere begining January + else + ncdstart = 120 !Southern Hemisphere beginning May + gddstart = 181 !Northern Hemisphere begining July + endif + + ! Count the number of chilling days over a seasonal window. + ! For comparing against GDD, we start calculating chilling + ! in the late autumn. + ! This value is used to determine the GDD exceedance threshold + if (hlm_day_of_year == ncdstart)then + currentSite%nchilldays = 0 + endif + + !Accumulate growing/chilling days after start of counting period + if (temp_in_C < ED_val_phen_chiltemp)then + currentSite%nchilldays = currentSite%nchilldays + 1 + endif + + !GDD accumulation function, which also depends on chilling days. + ! -68 + 638 * (-0.001 * ncd) + gdd_threshold = ED_val_phen_a + ED_val_phen_b*exp(ED_val_phen_c*real(currentSite%nchilldays,r8)) + + !Accumulate temperature of last 10 days. + currentSite%vegtemp_memory(2:num_vegtemp_mem) = currentSite%vegtemp_memory(1:num_vegtemp_mem-1) + currentSite%vegtemp_memory(1) = temp_in_C + + !count number of days for leaves off + ncolddays = 0 + do i_tmem = 1,num_vegtemp_mem + if (currentSite%vegtemp_memory(i_tmem) < ED_val_phen_coldtemp)then + ncolddays = ncolddays + 1 + endif + enddo + + ! Here is where we do the GDD accumulation calculation + ! + ! reset GDD on set dates + if (hlm_day_of_year == gddstart)then + currentSite%grow_deg_days = 0._r8 + endif + ! + ! accumulate the GDD using daily mean temperatures + ! Don't accumulate GDD during the growing season (that wouldn't make sense) + if (temp_in_C .gt. 0._r8 .and. currentSite%cstatus == phen_cstat_iscold) then + currentSite%grow_deg_days = currentSite%grow_deg_days + temp_in_C + endif + + !this logic is to prevent GDD accumulating after the leaves have fallen and before the + ! beginnning of the accumulation period, to prevend erroneous autumn leaf flushing. + if(model_day_int>365)then !only do this after the first year to prevent odd behaviour + + if(currentSite%lat .gt. 0.0_r8)then !Northern Hemisphere + ! In the north, don't accumulate when we are past the leaf fall date. + ! Accumulation starts on day 1 of year in NH. + ! The 180 is to prevent going into an 'always off' state after initialization + if( model_day_int .gt. currentSite%cleafoffdate.and.hlm_day_of_year.gt.180)then ! + currentSite%grow_deg_days = 0._r8 + endif + else !Southern Hemisphere + ! In the South, don't accumulate after the leaf off date, and before the start of + ! the accumulation phase (day 181). + if(model_day_int .gt. currentSite%cleafoffdate.and.hlm_day_of_year.lt.gddstart) then! + currentSite%grow_deg_days = 0._r8 + endif + endif + endif !year1 + + ! Calculate the number of days since the leaves last came on + ! and off. If this is the beginning of the simulation, that day might + ! not had occured yet, so set it to last year to get things rolling + + if (model_day_int < currentSite%cleafoffdate) then + dayssincecleafoff = model_day_int - (currentSite%cleafoffdate - 365) + else + dayssincecleafoff = model_day_int - currentSite%cleafoffdate + end if + + if (model_day_int < currentSite%cleafondate) then + dayssincecleafon = model_day_int - (currentSite%cleafondate-365) + else + dayssincecleafon = model_day_int - currentSite%cleafondate + end if + + + + !LEAF ON: COLD DECIDUOUS. Needs to + !1) have exceeded the growing degree day threshold + !2) The leaves should not be on already + !3) There should have been at least one chilling day in the counting period. + ! this prevents tropical or warm climate plants that are "cold-deciduous" + ! from ever re-flushing after they have reached their maximum age (thus + ! preventing them from competing + + if ( (currentSite%cstatus == phen_cstat_iscold .or. & + currentSite%cstatus == phen_cstat_nevercold) .and. & + (currentSite%grow_deg_days > gdd_threshold) .and. & + (dayssincecleafoff > ED_val_phen_mindayson) .and. & + (currentSite%nchilldays >= 1)) then + currentSite%cstatus = phen_cstat_notcold ! Set to not-cold status (leaves can come on) + currentSite%cleafondate = model_day_int + dayssincecleafon = 0 + currentSite%grow_deg_days = 0._r8 ! zero GDD for the rest of the year until counting season begins. + if ( debug ) write(fates_log(),*) 'leaves on' + endif !GDD + + + + + !LEAF OFF: COLD THRESHOLD + !Needs to: + !1) have exceeded the number of cold days threshold + !2) have exceeded the minimum leafon time. + !3) The leaves should not be off already + !4) The day of simulation should be larger than the counting period. + + + if ( (currentSite%cstatus == phen_cstat_notcold) .and. & + (model_day_int > num_vegtemp_mem) .and. & + (ncolddays > ED_val_phen_ncolddayslim) .and. & + (dayssincecleafon > ED_val_phen_mindayson) )then + + currentSite%grow_deg_days = 0._r8 ! The equations for Botta et al + ! are for calculations of + ! first flush, but if we dont + ! clear this value, it will cause + ! leaves to flush later in the year + currentSite%cstatus = phen_cstat_iscold ! alter status of site to 'leaves off' + currentSite%cleafoffdate = model_day_int ! record leaf off date + + if ( debug ) write(fates_log(),*) 'leaves off' + endif + + ! LEAF OFF: COLD LIFESPAN THRESHOLD + ! NOTE: Some areas of the planet will never generate a cold day + ! and thus %nchilldays will never go from zero to 1. The following logic + ! when coupled with this fact will essentially prevent cold-deciduous + ! plants from re-emerging in areas without at least some cold days + + if( (currentSite%cstatus == phen_cstat_notcold) .and. & + (dayssincecleafoff > 400)) then ! remove leaves after a whole year + ! when there is no 'off' period. + currentSite%grow_deg_days = 0._r8 + + currentSite%cstatus = phen_cstat_nevercold ! alter status of site to imply that this + ! site is never really cold enough + ! for cold deciduous + currentSite%cleafoffdate = model_day_int ! record leaf off date + + if ( debug ) write(fates_log(),*) 'leaves off' + endif + + !-----------------Drought Phenology--------------------! + ! Principles of drought-deciduos phenology model... + ! The 'is_drought' flag is false when leaves are on, and true when leaves area off. + ! The following sets those site-level flags, which are acted on in phenology_deciduos. + ! A* The leaves live for either the length of time the soil moisture is over the threshold + ! or the lifetime of the leaves, whichever is shorter. + ! B*: If the soil is only wet for a very short time, then the leaves stay on for 100 days + ! C*: The leaves are only permitted to come ON for a 60 day window around when they last came on, + ! to prevent 'flickering' on in response to wet season storms + ! D*: We don't allow anything to happen in the first ten days to allow the water memory window + ! to come into equlibirium. + ! E*: If the soil is always wet, the leaves come on at the beginning of the window, and then + ! last for their lifespan. + ! ISSUES + ! 1. It's not clear what water content we should track. Here we are tracking the top layer, + ! but we probably should track something like BTRAN, but BTRAN is defined for each PFT, + ! and there could potentially be more than one stress-dec PFT.... ? + ! 2. In the beginning, the window is set at an arbitrary time of the year, so the leaves + ! might come on in the dry season, using up stored reserves + ! for the stress-dec plants, and potentially killing them. To get around this, + ! we need to read in the 'leaf on' date from some kind of start-up file + ! but we would need that to happen for every resolution, etc. + ! 3. Will this methodology properly kill off the stress-dec trees where there is no + ! water stress? What about where the wet period coincides with the warm period? + ! We would just get them overlapping with the cold-dec trees, even though that isn't appropriate + ! Why don't the drought deciduous trees grow in the North? + ! Is cold decidousness maybe even the same as drought deciduosness there (and so does this + ! distinction actually matter??).... + + ! Accumulate surface water memory of last 10 days. + ! Liquid volume in ground layer (m3/m3) + do i_wmem = 1,numWaterMem-1 !shift memory along one + currentSite%water_memory(numWaterMem+1-i_wmem) = currentSite%water_memory(numWaterMem-i_wmem) + enddo + currentSite%water_memory(1) = bc_in%h2o_liqvol_sl(ilayer_swater) + + ! Calculate the mean water content over the last 10 days (m3/m3) + mean_10day_liqvol = sum(currentSite%water_memory(1:numWaterMem))/real(numWaterMem,r8) + + ! In drought phenology, we often need to force the leaves to stay + ! on or off as moisture fluctuates... + + ! Calculate days since leaves have come off, but make a provision + ! for the first year of simulation, we have to assume a leaf drop + ! date to start, so if that is in the future, set it to last year + + if (model_day_int < currentSite%dleafoffdate) then + dayssincedleafoff = model_day_int - (currentSite%dleafoffdate-365) + else + dayssincedleafoff = model_day_int - currentSite%dleafoffdate + endif + + ! the leaves are on. How long have they been on? + if (model_day_int < currentSite%dleafondate) then + dayssincedleafon = model_day_int - (currentSite%dleafondate-365) + else + dayssincedleafon = model_day_int - currentSite%dleafondate + endif + + ! LEAF ON: DROUGHT DECIDUOUS WETNESS + ! Here, we used a window of oppurtunity to determine if we are + ! close to the time when then leaves came on last year + + ! Has it been ... + ! a) a year, plus or minus 1 month since we last had leaf-on? + ! b) Has there also been at least a nominaly short amount of "leaf-off" + ! c) is the model day at least > 10 (let soil water spin-up) + ! Note that cold-starts begin in the "leaf-on" + ! status + if ( (currentSite%dstatus == phen_dstat_timeoff .or. & + currentSite%dstatus == phen_dstat_moistoff) .and. & + (model_day_int > numWaterMem) .and. & + (dayssincedleafon >= 365-30 .and. dayssincedleafon <= 365+30 ) .and. & + (dayssincedleafoff > ED_val_phen_doff_time) ) then + + ! If leaves are off, and have been off for at least a few days + ! and the time is consistent with the correct + ! time window... test if the moisture conditions allow for leaf-on + + if ( mean_10day_liqvol >= ED_val_phen_drought_threshold ) then + currentSite%dstatus = phen_dstat_moiston ! set status to leaf-on + currentSite%dleafondate = model_day_int ! save the model day we start flushing + dayssincedleafon = 0 + endif + endif + + ! LEAF ON: DROUGHT DECIDUOUS TIME EXCEEDANCE + ! If we still haven't done budburst by end of window, then force it + + ! If the status is "phen_dstat_moistoff", it means this site currently has + ! leaves off due to actual moisture limitations. + ! So we trigger bud-burst at the end of the month since + ! last year's bud-burst. If this is imposed, then we set the new + ! status to indicate bud-burst was forced by timing + + if( currentSite%dstatus == phen_dstat_moistoff ) then + if ( dayssincedleafon > 365+30 ) then + currentSite%dstatus = phen_dstat_timeon ! force budburst! + currentSite%dleafondate = model_day_int ! record leaf on date + dayssincedleafon = 0 + end if + end if + + ! But if leaves are off due to time, then we enforce + ! a longer cool-down (because this is a perrenially wet system) + + if(currentSite%dstatus == phen_dstat_timeoff ) then + if (dayssincedleafoff > min_daysoff_dforcedflush) then + currentSite%dstatus = phen_dstat_timeon ! force budburst! + currentSite%dleafondate = model_day_int ! record leaf on date + dayssincedleafon = 0 + end if + end if + + ! LEAF OFF: DROUGHT DECIDUOUS LIFESPAN - if the leaf gets to + ! the end of its useful life. A*, E* + ! i.e. Are the leaves rouhgly at the end of their lives? + + if ( (currentSite%dstatus == phen_dstat_moiston .or. & + currentSite%dstatus == phen_dstat_timeon ) .and. & + (dayssincedleafon > canopy_leaf_lifespan) )then + currentSite%dstatus = phen_dstat_timeoff !alter status of site to 'leaves off' + currentSite%dleafoffdate = model_day_int !record leaf on date + endif + + ! LEAF OFF: DROUGHT DECIDUOUS DRYNESS - if the soil gets too dry, + ! and the leaves have already been on a while... + + if ( (currentSite%dstatus == phen_dstat_moiston .or. & + currentSite%dstatus == phen_dstat_timeon ) .and. & + (model_day_int > numWaterMem) .and. & + (mean_10day_liqvol <= ED_val_phen_drought_threshold) .and. & + (dayssincedleafon > dleafon_drycheck ) ) then + currentSite%dstatus = phen_dstat_moistoff ! alter status of site to 'leaves off' + currentSite%dleafoffdate = model_day_int ! record leaf on date + endif + + call phenology_leafonoff(currentSite) + + end subroutine phenology + + ! ============================================================================ + subroutine phenology_leafonoff(currentSite) + ! + ! !DESCRIPTION: + ! Controls the leaf on and off economics + ! + ! !USES: + ! + ! !ARGUMENTS: + type(ed_site_type), intent(inout), target :: currentSite + ! + ! !LOCAL VARIABLES: + type(ed_patch_type) , pointer :: currentPatch + type(ed_cohort_type), pointer :: currentCohort + + real(r8) :: leaf_c ! leaf carbon [kg] + real(r8) :: sapw_c ! sapwood carbon [kg] + real(r8) :: struct_c ! structural wood carbon [kg] + real(r8) :: store_c ! storage carbon [kg] + real(r8) :: store_c_transfer_frac ! Fraction of storage carbon used to flush leaves + real(r8) :: totalmemory ! total memory of carbon [kg] + integer :: ipft + real(r8), parameter :: leaf_drop_fraction = 1.0_r8 + real(r8), parameter :: carbon_store_buffer = 0.10_r8 + real(r8) :: stem_drop_fraction + !------------------------------------------------------------------------ + + currentPatch => CurrentSite%oldest_patch + + do while(associated(currentPatch)) + currentCohort => currentPatch%tallest + do while(associated(currentCohort)) + + ipft = currentCohort%pft + + ! Retrieve existing leaf and storage carbon + + if(debug) call currentCohort%prt%CheckMassConservation(ipft,0) + + store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) + leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) + sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) + struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) + + stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(ipft) + + ! COLD LEAF ON + ! The site level flags signify that it is no-longer too cold + ! for leaves. Time to signal flushing + + if (prt_params%season_decid(ipft) == itrue)then + if ( currentSite%cstatus == phen_cstat_notcold )then ! we have just moved to leaves being on . + if (currentCohort%status_coh == leaves_off)then ! Are the leaves currently off? + currentCohort%status_coh = leaves_on ! Leaves are on, so change status to + ! stop flow of carbon out of bstore. + + if(store_c>nearzero) then + ! flush either the amount required from the laimemory, or -most- of the storage pool + ! RF: added a criterion to stop the entire store pool emptying and triggering termination mortality + ! n.b. this might not be necessary if we adopted a more gradual approach to leaf flushing... + store_c_transfer_frac = min((EDPftvarcon_inst%phenflush_fraction(ipft)* & + currentCohort%laimemory)/store_c,(1.0_r8-carbon_store_buffer)) + + if(prt_params%woody(ipft).ne.itrue)then + totalmemory=currentCohort%laimemory+currentCohort%sapwmemory+currentCohort%structmemory + store_c_transfer_frac = min((EDPftvarcon_inst%phenflush_fraction(ipft)* & + totalmemory)/store_c, (1.0_r8-carbon_store_buffer)) + endif + + else + store_c_transfer_frac = 0.0_r8 + end if + + ! This call will request that storage carbon will be transferred to + ! leaf tissues. It is specified as a fraction of the available storage + if(prt_params%woody(ipft) == itrue) then + + call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, store_c_transfer_frac) + currentCohort%laimemory = 0.0_r8 + + else + + ! Check that the stem drop fraction is set to non-zero amount otherwise flush all carbon store to leaves + if (stem_drop_fraction .gt. 0.0_r8) then + + call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & + store_c_transfer_frac*currentCohort%laimemory/totalmemory) + + call PRTPhenologyFlush(currentCohort%prt, ipft, sapw_organ, & + store_c_transfer_frac*currentCohort%sapwmemory/totalmemory) + + call PRTPhenologyFlush(currentCohort%prt, ipft, struct_organ, & + store_c_transfer_frac*currentCohort%structmemory/totalmemory) + + else + + call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & + store_c_transfer_frac) + + end if + + currentCohort%laimemory = 0.0_r8 + currentCohort%structmemory = 0.0_r8 + currentCohort%sapwmemory = 0.0_r8 + + endif + endif !pft phenology + endif ! growing season + + !COLD LEAF OFF + if (currentSite%cstatus == phen_cstat_nevercold .or. & + currentSite%cstatus == phen_cstat_iscold) then ! past leaf drop day? Leaves still on tree? + + if (currentCohort%status_coh == leaves_on) then ! leaves have not dropped + + ! leaf off occur on individuals bigger than specific size for grass + if (currentCohort%dbh > EDPftvarcon_inst%phen_cold_size_threshold(ipft) & + .or. prt_params%woody(ipft)==itrue) then + + ! This sets the cohort to the "leaves off" flag + currentCohort%status_coh = leaves_off + + ! Remember what the lai was (leaf mass actually) was for next year + ! the same amount back on in the spring... + + currentCohort%laimemory = leaf_c + + ! Drop Leaves (this routine will update the leaf state variables, + ! for carbon and any other element that are prognostic. It will + ! also track the turnover masses that will be sent to litter later on) + + call PRTDeciduousTurnover(currentCohort%prt,ipft, & + leaf_organ, leaf_drop_fraction) + + if(prt_params%woody(ipft).ne.itrue)then + + currentCohort%sapwmemory = sapw_c * stem_drop_fraction + + currentCohort%structmemory = struct_c * stem_drop_fraction + + call PRTDeciduousTurnover(currentCohort%prt,ipft, & + sapw_organ, stem_drop_fraction) + + call PRTDeciduousTurnover(currentCohort%prt,ipft, & + struct_organ, stem_drop_fraction) + + endif ! woody plant check + endif ! individual dbh size check + endif !leaf status + endif !currentSite status + endif !season_decid + + ! DROUGHT LEAF ON + ! Site level flag indicates it is no longer in drought condition + ! deciduous plants can flush + + if (prt_params%stress_decid(ipft) == itrue )then + + if (currentSite%dstatus == phen_dstat_moiston .or. & + currentSite%dstatus == phen_dstat_timeon )then + + ! we have just moved to leaves being on . + if (currentCohort%status_coh == leaves_off)then + + !is it the leaf-on day? Are the leaves currently off? + + currentCohort%status_coh = leaves_on ! Leaves are on, so change status to + ! stop flow of carbon out of bstore. + + if(store_c>nearzero) then + + store_c_transfer_frac = & + min((EDPftvarcon_inst%phenflush_fraction(ipft)*currentCohort%laimemory)/store_c, & + (1.0_r8-carbon_store_buffer)) + + if(prt_params%woody(ipft).ne.itrue)then + + totalmemory=currentCohort%laimemory+currentCohort%sapwmemory+currentCohort%structmemory + store_c_transfer_frac = min(EDPftvarcon_inst%phenflush_fraction(ipft)*totalmemory/store_c, & + (1.0_r8-carbon_store_buffer)) + + endif + + else + store_c_transfer_frac = 0.0_r8 + endif + + ! This call will request that storage carbon will be transferred to + ! leaf tissues. It is specified as a fraction of the available storage + if(prt_params%woody(ipft) == itrue) then + + call PRTPhenologyFlush(currentCohort%prt, ipft, & + leaf_organ, store_c_transfer_frac) + + currentCohort%laimemory = 0.0_r8 + + else + + ! Check that the stem drop fraction is set to non-zero amount otherwise flush all carbon store to leaves + if (stem_drop_fraction .gt. 0.0_r8) then + + call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & + store_c_transfer_frac*currentCohort%laimemory/totalmemory) + + call PRTPhenologyFlush(currentCohort%prt, ipft, sapw_organ, & + store_c_transfer_frac*currentCohort%sapwmemory/totalmemory) + + call PRTPhenologyFlush(currentCohort%prt, ipft, struct_organ, & + store_c_transfer_frac*currentCohort%structmemory/totalmemory) + + else + + call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & + store_c_transfer_frac) + + end if + + currentCohort%laimemory = 0.0_r8 + currentCohort%structmemory = 0.0_r8 + currentCohort%sapwmemory = 0.0_r8 + + endif ! woody plant check + endif !currentCohort status again? + endif !currentSite status + + !DROUGHT LEAF OFF + if (currentSite%dstatus == phen_dstat_moistoff .or. & + currentSite%dstatus == phen_dstat_timeoff) then + + if (currentCohort%status_coh == leaves_on) then ! leaves have not dropped + + ! This sets the cohort to the "leaves off" flag + currentCohort%status_coh = leaves_off + + ! Remember what the lai (leaf mass actually) was for next year + currentCohort%laimemory = leaf_c + + call PRTDeciduousTurnover(currentCohort%prt,ipft, & + leaf_organ, leaf_drop_fraction) + + if(prt_params%woody(ipft).ne.itrue)then + + currentCohort%sapwmemory = sapw_c * stem_drop_fraction + currentCohort%structmemory = struct_c * stem_drop_fraction + + call PRTDeciduousTurnover(currentCohort%prt,ipft, & + sapw_organ, stem_drop_fraction) + + call PRTDeciduousTurnover(currentCohort%prt,ipft, & + struct_organ, stem_drop_fraction) + endif + + endif + endif !status + endif !drought dec. + + if(debug) call currentCohort%prt%CheckMassConservation(ipft,1) + + currentCohort => currentCohort%shorter + enddo !currentCohort + + currentPatch => currentPatch%younger + + enddo !currentPatch + + end subroutine phenology_leafonoff + + + ! ===================================================================================== + + subroutine SeedIn( currentSite, bc_in ) + + ! ----------------------------------------------------------------------------------- + ! Flux from plants into the seed pool. + ! It is assumed that allocation to seed on living pools has already been calculated + ! at the daily time step. + ! Note: Some seed generation can occur during disturbance. It is assumed that + ! some plants use their storage upon death to create seeds, but this in only + ! triggered during non-fire and non-logging events. See + ! subroutine mortality_litter_fluxes() and DistributeSeeds(), look for + ! parameter allom_frbstor_repro + ! ----------------------------------------------------------------------------------- + + + ! !USES: + use EDTypesMod, only : area + use EDTypesMod, only : homogenize_seed_pfts + !use FatesInterfaceTypesMod, only : hlm_use_fixed_biogeog ! For future reduced complexity? + ! + ! !ARGUMENTS + type(ed_site_type), intent(inout), target :: currentSite + type(bc_in_type), intent(in) :: bc_in + + type(ed_patch_type), pointer :: currentPatch + type(litter_type), pointer :: litt + type(ed_cohort_type), pointer :: currentCohort + type(site_massbal_type), pointer :: site_mass + + integer :: pft + real(r8) :: store_m_to_repro ! mass sent from storage to reproduction upon death [kg/plant] + real(r8) :: site_seed_rain(maxpft) ! This is the sum of seed-rain for the site [kg/site/day] + real(r8) :: seed_in_external ! Mass of externally generated seeds [kg/m2/day] + real(r8) :: seed_stoich ! Mass ratio of nutrient per C12 in seeds [kg/kg] + real(r8) :: repro_mass_prod ! Mass of reproductive material produced [kg/day] ; added by ahb 7/8/2021 + real(r8), parameter :: repro_frac_seed = 0.5 !added by ahb 7/12/2021; move this to param file + real(r8) :: seed_prod ! Seed produced in this dynamics step [kg/day] + real(r8) :: non_seed_repro_prod ! Mass of non-seed reproductive material produced [kg/day] ; added by ahb 7/10/2021 + integer :: n_litt_types ! number of litter element types (c,n,p, etc) + integer :: el ! loop counter for litter element types + integer :: element_id ! element id consistent with parteh/PRTGenericMod.F90 + !------------------------------------------------------------------------------------ + + do el = 1, num_elements + + site_seed_rain(:) = 0._r8 + + element_id = element_list(el) + + site_mass => currentSite%mass_balance(el) + + ! Loop over all patches and sum up the seed input for each PFT + currentPatch => currentSite%oldest_patch + do while (associated(currentPatch)) + + currentCohort => currentPatch%tallest + !litt => currentPatch%litter(el) !added by ahb + do while (associated(currentCohort)) + + pft = currentCohort%pft + + ! a certain fraction of bstore might go to clonal reproduction when plants die + ! (since this is only applied to the dying portion of the cohort + ! we do not actually pair down the storage via PARTEH, instead + ! we just make sure that we don't send a portion of the storage + ! to the litter in CWDInput) + ! units = [kg/ha/day] = [kg] * [fraction] * [plants/ha/year] * [year/day] + store_m_to_repro = -currentCohort%prt%GetState(store_organ,element_id) * & + EDPftvarcon_inst%allom_frbstor_repro(pft)*currentCohort%dndt*years_per_day + + ! Transfer all reproductive tissues into seed production + ! The following call to PRTReproRelease, will return the mass + ! of seeds [kg] released by the plant, per the mass_fraction + ! specified as input. This routine will also remove the mass + ! from the parteh state-variable. + + + + + + !START ahb changes + + !-------------------------------------------------------------------------- + !original code + call PRTReproRelease(currentCohort%prt,repro_organ,element_id, & + 1.0_r8, seed_prod) + !-------------------------------------------------------------------------- + + !-------------------------------------------------------------------------- + !ahb's new code + !the original code sends all reproductive tissue to seed + !This new code, added by ahb, is designed to send some reproductive biomass + !straight to the leaf litter pool to account for non-seed reproductive + !biomass. For now, ahb does this after the call to the + !PRTReproRelease function, but a better solution would probably be to do + !this within the PRTReproRelease module in parteh/PRTLossFluxesMod.F90::L342 + !by adding new live reproductive organs (ahb needs help with this). + + !call PRTReproRelease(currentCohort%prt,repro_organ,element_id, & + ! 1.0_r8, repro_mass_prod) !ahb changed from seed_prod to repro_mass_prod + + !seed_prod = repro_mass_prod * repro_frac_seed ! seed production per ind. (ahb) + ! only a fraction of reproductive (ahb) + ! mass is seed (ahb) + + !non_seed_repro_prod = repro_mass_prod * (1.0_r8 - repro_frac_seed) !non-seed repro (ahb) + !mass per ind. (ahb) + + !litt%seed_decay(pft) = non_seed_repro_prod * currentCohort%n / area !send non-seed repro mass to seed decay pool + !--------------------------------------------------------------------------- + + !END ahb changes + + + + + + if(element_id==carbon12_element)then + currentcohort%seed_prod = seed_prod + end if + + site_seed_rain(pft) = site_seed_rain(pft) + & + (seed_prod * currentCohort%n + store_m_to_repro) + + currentCohort => currentCohort%shorter + enddo !cohort loop + + currentPatch => currentPatch%younger + enddo + + ! We can choose to homogenize seeds. This is simple, we just + ! add up all the seed from each pft at the site level, and then + ! equally distribute to the PFT pools + if ( homogenize_seed_pfts ) then + site_seed_rain(1:numpft) = sum(site_seed_rain(:))/real(numpft,r8) + end if + + + ! Loop over all patches again and disperse the mixed seeds into the input flux + ! arrays + + ! Loop over all patches and sum up the seed input for each PFT + currentPatch => currentSite%oldest_patch + do while (associated(currentPatch)) + + litt => currentPatch%litter(el) + do pft = 1,numpft + + if(currentSite%use_this_pft(pft).eq.itrue)then + ! Seed input from local sources (within site) + litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)/area + + !new code 7/14/2021 ahb + !-------------------------------- + litt%seed_decay(pft) = litt%seed_in_local(pft) * (1.0_r8 - repro_frac_seed) !ahb + !-------------------------------- + + ! If there is forced external seed rain, we calculate the input mass flux + ! from the different elements, usung the seed optimal stoichiometry + ! for non-carbon + select case(element_id) + case(carbon12_element) + seed_stoich = 1._r8 + case(nitrogen_element) + seed_stoich = prt_params%nitr_recr_stoich(pft) + case(phosphorus_element) + seed_stoich = prt_params%phos_recr_stoich(pft) + case default + write(fates_log(), *) 'undefined element specified' + write(fates_log(), *) 'while defining forced external seed mass flux' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select + + ! Seed input from external sources (user param seed rain, or dispersal model) + seed_in_external = seed_stoich*EDPftvarcon_inst%seed_suppl(pft)*years_per_day + litt%seed_in_extern(pft) = litt%seed_in_extern(pft) + seed_in_external + + ! Seeds entering externally [kg/site/day] + site_mass%seed_in = site_mass%seed_in + seed_in_external*currentPatch%area + end if !use this pft + enddo + + + currentPatch => currentPatch%younger + enddo + + end do + + return + end subroutine SeedIn + + ! ============================================================================ + + subroutine SeedDecay( litt ) + ! + ! !DESCRIPTION: + ! Flux from seed pool into leaf litter pool + ! + ! !ARGUMENTS + type(litter_type) :: litt + ! + ! !LOCAL VARIABLES: + integer :: pft + !---------------------------------------------------------------------- + + ! default value from Liscke and Loffler 2006 ; making this a PFT-specific parameter + ! decays the seed pool according to exponential model + ! seed_decay_rate is in yr-1 + ! seed_decay is kg/day + ! Assume that decay rates are same for all chemical species + + do pft = 1,numpft + litt%seed_decay(pft) = litt%seed(pft) * & + EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day + & ! "+ &" added by ahb (7/10/2021) + litt%seed_decay(pft) ! line added by ahb so that the flux from non-seed reproductive + ! biomass (from SeedIn subroutine) is not lost (7/10/2021) + + litt%seed_germ_decay(pft) = litt%seed_germ(pft) * & + EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day + + enddo + + return + end subroutine SeedDecay + + ! ============================================================================ + subroutine SeedGermination( litt, cold_stat, drought_stat ) + ! + ! !DESCRIPTION: + ! Flux from seed pool into sapling pool + ! + ! !USES: + + ! + ! !ARGUMENTS + type(litter_type) :: litt + integer, intent(in) :: cold_stat ! Is the site in cold leaf-off status? + integer, intent(in) :: drought_stat ! Is the site in drought leaf-off status? + ! + ! !LOCAL VARIABLES: + integer :: pft + + + real(r8), parameter :: max_germination = 1.0_r8 ! Cap on germination rates. + ! KgC/m2/yr Lishcke et al. 2009 + + ! Turning of this cap? because the cap will impose changes on proportionality + ! of nutrients. (RGK 02-2019) + !real(r8), parameter :: max_germination = 1.e6_r8 ! Force to very high number + + !---------------------------------------------------------------------- + + ! germination_rate is being pulled to PFT parameter; units are 1/yr + ! thus the mortality rate of seed -> recruit (in units of carbon) + ! is seed_decay_rate(p)/germination_rate(p) + ! and thus the mortality rate (in units of individuals) is the product of + ! that times the ratio of (hypothetical) seed mass to recruit biomass + + do pft = 1,numpft + litt%seed_germ_in(pft) = min(litt%seed(pft) * EDPftvarcon_inst%germination_rate(pft), & + max_germination)*years_per_day + + !set the germination only under the growing season...c.xu + + if ((prt_params%season_decid(pft) == itrue ) .and. & + (any(cold_stat == [phen_cstat_nevercold,phen_cstat_iscold]))) then + litt%seed_germ_in(pft) = 0.0_r8 + endif + if ((prt_params%stress_decid(pft) == itrue ) .and. & + (any(drought_stat == [phen_dstat_timeoff,phen_dstat_moistoff]))) then + litt%seed_germ_in(pft) = 0.0_r8 + end if + + + enddo + + end subroutine SeedGermination + + ! ===================================================================================== + + + + + + ! ===================================================================================== + + subroutine recruitment( currentSite, currentPatch, bc_in ) + ! + ! !DESCRIPTION: + ! spawn new cohorts of juveniles of each PFT + ! + ! !USES: + use FatesInterfaceTypesMod, only : hlm_use_ed_prescribed_phys + ! + ! !ARGUMENTS + type(ed_site_type), intent(inout), target :: currentSite + type(ed_patch_type), intent(inout), pointer :: currentPatch + type(bc_in_type), intent(in) :: bc_in + ! + ! !LOCAL VARIABLES: + class(prt_vartypes), pointer :: prt + integer :: ft + type (ed_cohort_type) , pointer :: temp_cohort + type (litter_type), pointer :: litt ! The litter object (carbon right now) + type(site_massbal_type), pointer :: site_mass ! For accounting total in-out mass fluxes + integer :: cohortstatus + integer :: el ! loop counter for element + integer :: element_id ! element index consistent with definitions in PRTGenericMod + integer :: iage ! age loop counter for leaf age bins + integer,parameter :: recruitstatus = 1 !weather it the new created cohorts is recruited or initialized + real(r8) :: c_leaf ! target leaf biomass [kgC] + real(r8) :: c_fnrt ! target fine root biomass [kgC] + real(r8) :: c_sapw ! target sapwood biomass [kgC] + real(r8) :: a_sapw ! target sapwood cross section are [m2] (dummy) + real(r8) :: c_agw ! target Above ground biomass [kgC] + real(r8) :: c_bgw ! target Below ground biomass [kgC] + real(r8) :: c_struct ! target Structural biomass [kgc] + real(r8) :: c_store ! target Storage biomass [kgC] + real(r8) :: m_leaf ! leaf mass (element agnostic) [kg] + real(r8) :: m_fnrt ! fine-root mass (element agnostic) [kg] + real(r8) :: m_sapw ! sapwood mass (element agnostic) [kg] + real(r8) :: m_agw ! AG wood mass (element agnostic) [kg] + real(r8) :: m_bgw ! BG wood mass (element agnostic) [kg] + real(r8) :: m_struct ! structural mass (element agnostic) [kg] + real(r8) :: m_store ! storage mass (element agnostic) [kg] + real(r8) :: m_repro ! reproductive mass (element agnostic) [kg] + real(r8) :: mass_avail ! The mass of each nutrient/carbon available in the seed_germination pool [kg] + real(r8) :: mass_demand ! Total mass demanded by the plant to achieve the stoichiometric targets + ! of all the organs in the recruits. Used for both [kg per plant] and [kg per cohort] + real(r8) :: stem_drop_fraction + + !---------------------------------------------------------------------- + + allocate(temp_cohort) ! create temporary cohort + call zero_cohort(temp_cohort) + + + do ft = 1,numpft + if(currentSite%use_this_pft(ft).eq.itrue)then + temp_cohort%canopy_trim = init_recruit_trim + temp_cohort%pft = ft + temp_cohort%hite = EDPftvarcon_inst%hgt_min(ft) + temp_cohort%coage = 0.0_r8 + stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(ft) + + call h2d_allom(temp_cohort%hite,ft,temp_cohort%dbh) + + ! Initialize live pools + call bleaf(temp_cohort%dbh,ft,temp_cohort%canopy_trim,c_leaf) + call bfineroot(temp_cohort%dbh,ft,temp_cohort%canopy_trim,c_fnrt) + call bsap_allom(temp_cohort%dbh,ft,temp_cohort%canopy_trim,a_sapw, c_sapw) + call bagw_allom(temp_cohort%dbh,ft,c_agw) + call bbgw_allom(temp_cohort%dbh,ft,c_bgw) + call bdead_allom(c_agw,c_bgw,c_sapw,ft,c_struct) + call bstore_allom(temp_cohort%dbh,ft,temp_cohort%canopy_trim,c_store) + + ! Default assumption is that leaves are on + cohortstatus = leaves_on + temp_cohort%laimemory = 0.0_r8 + temp_cohort%sapwmemory = 0.0_r8 + temp_cohort%structmemory = 0.0_r8 + + + ! But if the plant is seasonally (cold) deciduous, and the site status is flagged + ! as "cold", then set the cohort's status to leaves_off, and remember the leaf biomass + if ((prt_params%season_decid(ft) == itrue) .and. & + (any(currentSite%cstatus == [phen_cstat_nevercold,phen_cstat_iscold]))) then + temp_cohort%laimemory = c_leaf + c_leaf = 0.0_r8 + + ! If plant is not woody then set sapwood and structural biomass as well + if (prt_params%woody(ft).ne.itrue) then + temp_cohort%sapwmemory = c_sapw * stem_drop_fraction + temp_cohort%structmemory = c_struct * stem_drop_fraction + c_sapw = (1.0_r8 - stem_drop_fraction) * c_sapw + c_struct = (1.0_r8 - stem_drop_fraction) * c_struct + endif + cohortstatus = leaves_off + endif + + ! Or.. if the plant is drought deciduous, and the site status is flagged as + ! "in a drought", then likewise, set the cohort's status to leaves_off, and remember leaf + ! biomass + if ((prt_params%stress_decid(ft) == itrue) .and. & + (any(currentSite%dstatus == [phen_dstat_timeoff,phen_dstat_moistoff]))) then + temp_cohort%laimemory = c_leaf + c_leaf = 0.0_r8 + + ! If plant is not woody then set sapwood and structural biomass as well + if(prt_params%woody(ft).ne.itrue)then + temp_cohort%sapwmemory = c_sapw * stem_drop_fraction + temp_cohort%structmemory = c_struct * stem_drop_fraction + c_sapw = (1.0_r8 - stem_drop_fraction) * c_sapw + c_struct = (1.0_r8 - stem_drop_fraction) * c_struct + endif + cohortstatus = leaves_off + endif + + + ! Cycle through available carbon and nutrients, find the limiting element + ! to dictate the total number of plants that can be generated + + if ( (hlm_use_ed_prescribed_phys .eq. ifalse) .or. & + (EDPftvarcon_inst%prescribed_recruitment(ft) .lt. 0._r8) ) then + + temp_cohort%n = 1.e20_r8 + + do el = 1,num_elements + + element_id = element_list(el) + select case(element_id) + case(carbon12_element) + + mass_demand = c_struct+c_leaf+c_fnrt+c_sapw+c_store + + case(nitrogen_element) + + mass_demand = & + c_struct*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(struct_organ)) + & + c_leaf*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)) + & + c_fnrt*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)) + & + c_sapw*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)) + & + StorageNutrientTarget(ft, element_id, & + c_leaf*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)), & + c_fnrt*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)), & + c_sapw*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)), & + c_struct*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(struct_organ))) + + case(phosphorus_element) + + mass_demand = & + c_struct*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(struct_organ)) + & + c_leaf*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)) + & + c_fnrt*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)) + & + c_sapw*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)) + & + StorageNutrientTarget(ft, element_id, & + c_leaf*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)), & + c_fnrt*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)), & + c_sapw*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)), & + c_struct*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(struct_organ))) + + case default + write(fates_log(),*) 'Undefined element type in recruitment' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select + + mass_avail = currentPatch%area * currentPatch%litter(el)%seed_germ(ft) + + ! ------------------------------------------------------------------------ + ! Update number density if this is the limiting mass + ! ------------------------------------------------------------------------ + + temp_cohort%n = min(temp_cohort%n, mass_avail/mass_demand) + + end do + + + else + ! prescribed recruitment rates. number per sq. meter per year + temp_cohort%n = currentPatch%area * & + EDPftvarcon_inst%prescribed_recruitment(ft) * & + hlm_freq_day + endif + + ! Only bother allocating a new cohort if there is a reasonable amount of it + any_recruits: if (temp_cohort%n > min_n_safemath )then + + ! ----------------------------------------------------------------------------- + ! PART II. + ! Initialize the PARTEH object, and determine the initial masses of all + ! organs and elements. + ! ----------------------------------------------------------------------------- + prt => null() + call InitPRTObject(prt) + + do el = 1,num_elements + + element_id = element_list(el) + + ! If this is carbon12, then the initialization is straight forward + ! otherwise, we use stoichiometric ratios + select case(element_id) + case(carbon12_element) + + m_struct = c_struct + m_leaf = c_leaf + m_fnrt = c_fnrt + m_sapw = c_sapw + m_store = c_store + m_repro = 0._r8 + + case(nitrogen_element) + + m_struct = c_struct*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(struct_organ)) + m_leaf = c_leaf*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)) + m_fnrt = c_fnrt*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)) + m_sapw = c_sapw*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)) + m_store = StorageNutrientTarget(ft, element_id, m_leaf, m_fnrt, m_sapw, m_struct ) + m_repro = 0._r8 + + case(phosphorus_element) + + m_struct = c_struct*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(struct_organ)) + m_leaf = c_leaf*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)) + m_fnrt = c_fnrt*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)) + m_sapw = c_sapw*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)) + m_store = StorageNutrientTarget(ft, element_id, m_leaf, m_fnrt, m_sapw, m_struct ) + m_repro = 0._r8 + + end select + + select case(hlm_parteh_mode) + case (prt_carbon_allom_hyp,prt_cnp_flex_allom_hyp ) + + ! Put all of the leaf mass into the first bin + call SetState(prt,leaf_organ, element_id,m_leaf,1) + do iage = 2,nleafage + call SetState(prt,leaf_organ, element_id,0._r8,iage) + end do + + call SetState(prt,fnrt_organ, element_id, m_fnrt) + call SetState(prt,sapw_organ, element_id, m_sapw) + call SetState(prt,store_organ, element_id, m_store) + call SetState(prt,struct_organ, element_id, m_struct) + call SetState(prt,repro_organ, element_id, m_repro) + + case default + write(fates_log(),*) 'Unspecified PARTEH module during create_cohort' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select + + site_mass => currentSite%mass_balance(el) + + ! Remove mass from the germination pool. However, if we are use prescribed physiology, + ! AND the forced recruitment model, then we are not realling using the prognostic + ! seed_germination model, so we have to short circuit things. We send all of the + ! seed germination mass to an outflux pool, and use an arbitrary generic input flux + ! to balance out the new recruits. + + if ( (hlm_use_ed_prescribed_phys .eq. itrue ) .and. & + (EDPftvarcon_inst%prescribed_recruitment(ft) .ge. 0._r8 )) then + + site_mass%flux_generic_in = site_mass%flux_generic_in + & + temp_cohort%n*(m_struct + m_leaf + m_fnrt + m_sapw + m_store + m_repro) + + site_mass%flux_generic_out = site_mass%flux_generic_out + & + currentPatch%area * currentPatch%litter(el)%seed_germ(ft) + + currentPatch%litter(el)%seed_germ(ft) = 0._r8 + + + else + + currentPatch%litter(el)%seed_germ(ft) = currentPatch%litter(el)%seed_germ(ft) - & + temp_cohort%n / currentPatch%area * & + (m_struct + m_leaf + m_fnrt + m_sapw + m_store + m_repro) + + end if + + + + end do + + ! This call cycles through the initial conditions, and makes sure that they + ! are all initialized. + ! ----------------------------------------------------------------------------------- + + call prt%CheckInitialConditions() + + ! This initializes the cohort + call create_cohort(currentSite,currentPatch, temp_cohort%pft, temp_cohort%n, & + temp_cohort%hite, temp_cohort%coage, temp_cohort%dbh, prt, & + temp_cohort%laimemory, temp_cohort%sapwmemory, temp_cohort%structmemory, & + cohortstatus, recruitstatus, & + temp_cohort%canopy_trim, currentPatch%NCL_p, currentSite%spread, bc_in) + + ! Note that if hydraulics is on, the number of cohorts may had + ! changed due to hydraulic constraints. + ! This constaint is applied during "create_cohort" subroutine. + + ! keep track of how many individuals were recruited for passing to history + currentSite%recruitment_rate(ft) = currentSite%recruitment_rate(ft) + temp_cohort%n + + + endif any_recruits + endif !use_this_pft + enddo !pft loop + + deallocate(temp_cohort) ! delete temporary cohort + + end subroutine recruitment + + ! ============================================================================ + + subroutine CWDInput( currentSite, currentPatch, litt, bc_in) + + ! + ! !DESCRIPTION: + ! Generate litter fields from turnover. + ! Note, that the when this is called, the number density of the plants + ! has not been reduced from non-mortal turnover yet. + ! Thus, we need to avoid double counting losses from dying trees + ! and turnover in dying trees. + ! + ! !USES: + use SFParamsMod , only : SF_val_CWD_frac + + ! + ! !ARGUMENTS + type(ed_site_type), intent(inout), target :: currentSite + type(ed_patch_type),intent(inout), target :: currentPatch + type(litter_type),intent(inout),target :: litt + type(bc_in_type),intent(in) :: bc_in + + ! + ! !LOCAL VARIABLES: + type(ed_cohort_type), pointer :: currentCohort + type(site_fluxdiags_type), pointer :: flux_diags + type(site_massbal_type), pointer :: site_mass + integer :: c + real(r8) :: dead_n ! total understorey dead tree density + real(r8) :: dead_n_dlogging ! direct logging understory dead-tree density + real(r8) :: dead_n_ilogging ! indirect understory dead-tree density (logging) + real(r8) :: dead_n_natural ! understory dead density not associated + ! with direct logging + real(r8) :: leaf_m ! mass of the element of interest in the + ! leaf [kg] + real(r8) :: fnrt_m ! fine-root [kg] + real(r8) :: sapw_m ! sapwood [kg] + real(r8) :: struct_m ! structural [kg] + real(r8) :: store_m ! storage [kg] + real(r8) :: repro_m ! reproductive [kg] + real(r8) :: leaf_m_turnover ! leaf turnover [kg] + real(r8) :: fnrt_m_turnover + real(r8) :: sapw_m_turnover + real(r8) :: struct_m_turnover + real(r8) :: store_m_turnover + real(r8) :: repro_m_turnover + real(r8) :: dcmpy_frac ! Fraction of mass sent to decomposability pool + real(r8) :: plant_dens ! Number of plants per m2 + real(r8) :: bg_cwd_tot ! Total below-ground coarse woody debris + ! input flux + real(r8) :: root_fines_tot ! Total below-ground fine root coarse + ! woody debris + integer :: element_id ! element id consistent with parteh/PRTGenericMod.F90 + + real(r8) :: trunk_wood ! carbon flux into trunk products kgC/day/site + integer :: ilyr + integer :: pft + integer :: dcmpy ! decomposability pool index + integer :: numlevsoil ! Actual number of soil layers + !---------------------------------------------------------------------- + + ! ----------------------------------------------------------------------------------- + ! Other direct litter fluxes happen in phenology and in spawn_patches. + ! ----------------------------------------------------------------------------------- + + numlevsoil = currentSite%nlevsoil + + element_id = litt%element_id + + ! Object tracking flux diagnostics for each element + flux_diags => currentSite%flux_diags(element_pos(element_id)) + + ! Object tracking site level mass balance for each element + site_mass => currentSite%mass_balance(element_pos(element_id)) + + currentCohort => currentPatch%shortest + do while(associated(currentCohort)) + pft = currentCohort%pft + + call set_root_fraction(currentSite%rootfrac_scr, pft, currentSite%zi_soil, & + bc_in%max_rooting_depth_index_col) + + leaf_m_turnover = currentCohort%prt%GetTurnover(leaf_organ,element_id) + store_m_turnover = currentCohort%prt%GetTurnover(store_organ,element_id) + fnrt_m_turnover = currentCohort%prt%GetTurnover(fnrt_organ,element_id) + sapw_m_turnover = currentCohort%prt%GetTurnover(sapw_organ,element_id) + struct_m_turnover = currentCohort%prt%GetTurnover(struct_organ,element_id) + repro_m_turnover = currentCohort%prt%GetTurnover(repro_organ,element_id) + + leaf_m = currentCohort%prt%GetState(leaf_organ,element_id) + store_m = currentCohort%prt%GetState(store_organ,element_id) + fnrt_m = currentCohort%prt%GetState(fnrt_organ,element_id) + sapw_m = currentCohort%prt%GetState(sapw_organ,element_id) + struct_m = currentCohort%prt%GetState(struct_organ,element_id) + repro_m = currentCohort%prt%GetState(repro_organ,element_id) + + plant_dens = currentCohort%n/currentPatch%area + + ! --------------------------------------------------------------------------------- + ! PART 1 Litter fluxes from non-mortal tissue turnovers Kg/m2/day + ! Important note: Turnover has already been removed from the cohorts. + ! So, in the next part of this algorithm, when we send the biomass + ! from dying trees to the litter pools, we don't have to worry + ! about double counting. + ! --------------------------------------------------------------------------------- + + flux_diags%leaf_litter_input(pft) = & + flux_diags%leaf_litter_input(pft) + & + leaf_m_turnover * currentCohort%n + + root_fines_tot = (fnrt_m_turnover + store_m_turnover ) * & + plant_dens + + 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 + + dcmpy_frac = GetDecompyFrac(pft,fnrt_organ,dcmpy) + do ilyr = 1, numlevsoil + litt%root_fines_in(dcmpy,ilyr) = litt%root_fines_in(dcmpy,ilyr) + & + currentSite%rootfrac_scr(ilyr) * root_fines_tot * dcmpy_frac + end do + end do + + flux_diags%root_litter_input(pft) = & + flux_diags%root_litter_input(pft) + & + (fnrt_m_turnover + store_m_turnover ) * currentCohort%n + + + ! Assumption: turnover from deadwood and sapwood are lumped together in CWD pool + + do c = 1,ncwd + litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + & + (sapw_m_turnover + struct_m_turnover) * & + SF_val_CWD_frac(c) * plant_dens * & + prt_params%allom_agb_frac(pft) + + flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & + (struct_m_turnover + sapw_m_turnover) * SF_val_CWD_frac(c) * & + prt_params%allom_agb_frac(pft) * currentCohort%n + + bg_cwd_tot = (sapw_m_turnover + struct_m_turnover) * & + SF_val_CWD_frac(c) * plant_dens * & + (1.0_r8-prt_params%allom_agb_frac(pft)) + + do ilyr = 1, numlevsoil + litt%bg_cwd_in(c,ilyr) = litt%bg_cwd_in(c,ilyr) + & + bg_cwd_tot * currentSite%rootfrac_scr(ilyr) + end do + + flux_diags%cwd_bg_input(c) = flux_diags%cwd_bg_input(c) + & + bg_cwd_tot*currentPatch%area + + enddo + + + ! --------------------------------------------------------------------------------- + ! PART 2 Litter fluxes from non-disturbance inducing mortality. Kg/m2/day + ! --------------------------------------------------------------------------------- + + ! Total number of dead (n/m2/day) + dead_n = -1.0_r8 * currentCohort%dndt/currentPatch%area*years_per_day + + if(currentCohort%canopy_layer > 1)then + + ! Total number of dead understory from direct logging + ! (it is possible that large harvestable trees are in the understory) + dead_n_dlogging = currentCohort%lmort_direct * & + currentCohort%n/currentPatch%area + + ! Total number of dead understory from indirect logging + dead_n_ilogging = (currentCohort%lmort_collateral + currentCohort%lmort_infra) * & + currentCohort%n/currentPatch%area + + else + + ! All mortality from logging in the canopy is + ! is disturbance generating + + dead_n_dlogging = 0._r8 + dead_n_ilogging = 0._r8 + + end if + + dead_n_natural = dead_n - dead_n_dlogging - dead_n_ilogging + + + flux_diags%leaf_litter_input(pft) = & + flux_diags%leaf_litter_input(pft) + & + leaf_m * dead_n*currentPatch%area + + + ! %n has not been updated due to mortality yet, thus + ! the litter flux has already been counted since it captured + ! the losses of live trees and those flagged for death + + root_fines_tot = dead_n * (fnrt_m + & + store_m*(1._r8-EDPftvarcon_inst%allom_frbstor_repro(pft)) ) + + do dcmpy=1,ndcmpy + + dcmpy_frac = GetDecompyFrac(pft,leaf_organ,dcmpy) + litt%leaf_fines_in(dcmpy) = litt%leaf_fines_in(dcmpy) + & + (leaf_m+repro_m) * dead_n * dcmpy_frac + + dcmpy_frac = GetDecompyFrac(pft,fnrt_organ,dcmpy) + do ilyr = 1, numlevsoil + litt%root_fines_in(dcmpy,ilyr) = litt%root_fines_in(dcmpy,ilyr) + & + root_fines_tot * currentSite%rootfrac_scr(ilyr) * dcmpy_frac + end do + end do + + flux_diags%root_litter_input(pft) = & + flux_diags%root_litter_input(pft) + & + root_fines_tot*currentPatch%area + + ! Track CWD inputs from dead plants + + do c = 1,ncwd + + ! Below-ground + + bg_cwd_tot = (struct_m + sapw_m) * & + SF_val_CWD_frac(c) * dead_n * & + (1.0_r8-prt_params%allom_agb_frac(pft)) + + do ilyr = 1, numlevsoil + litt%bg_cwd_in(c,ilyr) = litt%bg_cwd_in(c,ilyr) + & + currentSite%rootfrac_scr(ilyr) * bg_cwd_tot + end do + + flux_diags%cwd_bg_input(c) = flux_diags%cwd_bg_input(c) + & + bg_cwd_tot * currentPatch%area + + ! Send AGB component of boles from logging activities into the litter. + ! This includes fluxes from indirect modes of death, as well as the + ! non-exported boles due to direct harvesting. + + if (c==ncwd) then + + + trunk_wood = (struct_m + sapw_m) * & + SF_val_CWD_frac(c) * dead_n_dlogging * & + prt_params%allom_agb_frac(pft) + + site_mass%wood_product = site_mass%wood_product + & + trunk_wood * currentPatch%area * logging_export_frac + + ! Add AG wood to litter from the non-exported fraction of wood + ! from direct anthro sources + + litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + & + trunk_wood * (1._r8-logging_export_frac) + + flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & + trunk_wood * (1._r8-logging_export_frac) * currentPatch%area + + ! Add AG wood to litter from indirect anthro sources + + litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + (struct_m + sapw_m) * & + SF_val_CWD_frac(c) * (dead_n_natural+dead_n_ilogging) * & + prt_params%allom_agb_frac(pft) + + flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & + SF_val_CWD_frac(c) * (dead_n_natural+dead_n_ilogging) * & + currentPatch%area * prt_params%allom_agb_frac(pft) + + else + + litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + (struct_m + sapw_m) * & + SF_val_CWD_frac(c) * dead_n * & + prt_params%allom_agb_frac(pft) + + flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & + SF_val_CWD_frac(c) * dead_n * (struct_m + sapw_m) * & + currentPatch%area * prt_params%allom_agb_frac(pft) + + end if + + end do + + + ! Update diagnostics that track resource management + + if( element_id .eq. carbon12_element ) then + + currentSite%resources_management%delta_litter_stock = & + currentSite%resources_management%delta_litter_stock + & + (leaf_m + fnrt_m + store_m ) * & + (dead_n_ilogging+dead_n_dlogging) * currentPatch%area + + currentSite%resources_management%delta_biomass_stock = & + currentSite%resources_management%delta_biomass_stock + & + (leaf_m + fnrt_m + store_m ) * & + (dead_n_ilogging+dead_n_dlogging) *currentPatch%area + + currentSite%resources_management%trunk_product_site = & + currentSite%resources_management%trunk_product_site + & + trunk_wood * logging_export_frac * currentPatch%area + + do c = 1,ncwd + currentSite%resources_management%delta_litter_stock = & + currentSite%resources_management%delta_litter_stock + & + (struct_m + sapw_m) * & + SF_val_CWD_frac(c) * (dead_n_natural+dead_n_ilogging) * & + currentPatch%area + + currentSite%resources_management%delta_biomass_stock = & + currentSite%resources_management%delta_biomass_stock + & + (struct_m + sapw_m) * & + SF_val_CWD_frac(c) * dead_n * currentPatch%area + end do + + ! Update diagnostics that track resource management + currentSite%resources_management%delta_individual = & + currentSite%resources_management%delta_individual + & + (dead_n_dlogging+dead_n_ilogging) * hlm_freq_day * currentPatch%area + end if + + + currentCohort => currentCohort%taller + enddo ! end loop over cohorts + + + return + end subroutine CWDInput + + ! ===================================================================================== + + + subroutine fragmentation_scaler( currentPatch, bc_in) + ! + ! !DESCRIPTION: + ! Simple CWD fragmentation Model + ! FIX(SPM, 091914) this should be a function as it returns a value in + ! currentPatch%fragmentation_scaler + ! + ! !USES: + + use FatesSynchronizedParamsMod , only : FatesSynchronizedParamsInst + use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm + use FatesConstantsMod, only : pi => pi_const + ! + ! !ARGUMENTS + type(ed_patch_type), intent(inout) :: currentPatch + type(bc_in_type), intent(in) :: bc_in + + ! + ! !LOCAL VARIABLES: + logical :: use_century_tfunc = .false. + logical :: use_hlm_soil_scalar = .true. ! Use hlm input decomp fraction scalars + integer :: j + integer :: ifp ! Index of a FATES Patch "ifp" + real(r8) :: t_scalar ! temperature scalar + real(r8) :: w_scalar ! moisture scalar + real(r8) :: catanf ! hyperbolic temperature function from CENTURY + real(r8) :: catanf_30 ! hyperbolic temperature function from CENTURY + real(r8) :: t1 ! temperature argument + !---------------------------------------------------------------------- + + catanf(t1) = 11.75_r8 +(29.7_r8 / pi) * atan( pi * 0.031_r8 * ( t1 - 15.4_r8 )) + catanf_30 = catanf(30._r8) + + ifp = currentPatch%patchno + + ! Use the hlm temp and moisture decomp fractions by default + if ( use_hlm_soil_scalar ) then + + ! Calculate the fragmentation_scaler + currentPatch%fragmentation_scaler = min(1.0_r8,max(0.0_r8,bc_in%t_scalar_sisl * bc_in%w_scalar_sisl)) + + else + + if ( .not. use_century_tfunc ) then + !calculate rate constant scalar for soil temperature,assuming that the base rate constants + !are assigned for non-moisture limiting conditions at 25C. + if (bc_in%t_veg24_pa(ifp) >= tfrz) then + t_scalar = q10_mr**((bc_in%t_veg24_pa(ifp)-(tfrz+25._r8))/10._r8) + ! Q10**((t_soisno(c,j)-(tfrz+25._r8))/10._r8) + else + t_scalar = (q10_mr**(-25._r8/10._r8))*(q10_froz**((bc_in%t_veg24_pa(ifp)-tfrz)/10._r8)) + !Q10**(-25._r8/10._r8))*(froz_q10**((t_soisno(c,j)-tfrz)/10._r8) + endif + else + ! original century uses an arctangent function to calculate the + ! temperature dependence of decomposition + t_scalar = max(catanf(bc_in%t_veg24_pa(ifp)-tfrz)/catanf_30,0.01_r8) + endif + + !Moisture Limitations + !BTRAN APPROACH - is quite simple, but max's out decomp at all unstressed + !soil moisture values, which is not realistic. + !litter decomp is proportional to water limitation on average... + w_scalar = sum(currentPatch%btran_ft(1:numpft))/real(numpft,r8) + + ! Calculate the fragmentation_scaler + currentPatch%fragmentation_scaler(:) = min(1.0_r8,max(0.0_r8,t_scalar * w_scalar)) + + endif + + + end subroutine fragmentation_scaler + + ! ============================================================================ + + subroutine CWDOut( litt, fragmentation_scaler, nlev_eff_decomp ) + ! + ! !DESCRIPTION: + ! Simple CWD fragmentation Model + ! spawn new cohorts of juveniles of each PFT + ! + ! !USES: + use SFParamsMod, only : SF_val_max_decomp + + ! + ! !ARGUMENTS + type(litter_type),intent(inout),target :: litt + real(r8),intent(in) :: fragmentation_scaler(:) + + ! This is not necessarily every soil layer, this is the number + ! of effective layers that are active and can be sent + ! to the soil decomposition model + integer,intent(in) :: nlev_eff_decomp + + ! + ! !LOCAL VARIABLES: + integer :: c ! Fuel size class index + integer :: ilyr ! Soil layer index + integer :: dcmpy ! Decomposibility pool indexer + integer :: soil_layer_index = 1 ! Soil layer index associated with above ground litter + !---------------------------------------------------------------------- + + + ! Above ground litters are associated with the top soil layer temperature and + ! moisture scalars and fragmentation scalar associated with specified index value + ! is used for ag_cwd_frag and root_fines_frag calculations. + + do c = 1,ncwd + + litt%ag_cwd_frag(c) = litt%ag_cwd(c) * SF_val_max_decomp(c) * & + years_per_day * fragmentation_scaler(soil_layer_index) + + do ilyr = 1,nlev_eff_decomp + + litt%bg_cwd_frag(c,ilyr) = litt%bg_cwd(c,ilyr) * SF_val_max_decomp(c) * & + years_per_day * fragmentation_scaler(ilyr) + + enddo + end do + + ! this is the rate at which dropped leaves stop being part of the burnable pool + ! and begin to be part of the decomposing pool. This should probably be highly + ! sensitive to moisture, but also to the type of leaf thick leaves can dry out + ! before they are decomposed, for example. This section needs further scientific input. + + do dcmpy = 1,ndcmpy + + litt%leaf_fines_frag(dcmpy) = litt%leaf_fines(dcmpy) * & + years_per_day * SF_val_max_decomp(dl_sf) * fragmentation_scaler(soil_layer_index) + + do ilyr = 1,nlev_eff_decomp + litt%root_fines_frag(dcmpy,ilyr) = litt%root_fines(dcmpy,ilyr) * & + years_per_day * SF_val_max_decomp(dl_sf) * fragmentation_scaler(ilyr) + end do + enddo + + end subroutine CWDOut + +end module EDPhysiologyMod From b096c8d662ac0cec73c025110c9cbbe6356d6803 Mon Sep 17 00:00:00 2001 From: adamhb Date: Mon, 19 Jul 2021 14:26:53 -0700 Subject: [PATCH 040/852] The new emergence function is working well. Added light and moisture sensitive seedling emergence. The current implementation does not use time averages at this time (instantaneous values). Fixes: none User interface changes?: No Code review: Adam Hanbury-Brown Test summary: no testing --- biogeochem/EDPhysiologyMod.F90 | 67 +++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index c748dfdb8b..7523d32d45 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -231,7 +231,8 @@ subroutine PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in ) ! Calculate seed germination rate, the status flags prevent ! germination from occuring when the site is in a drought ! (for drought deciduous) or too cold (for cold deciduous) - call SeedGermination(litt, currentSite%cstatus, currentSite%dstatus) + call SeedGermination(litt, currentSite%cstatus, currentSite%dstatus, bc_in, currentPatch) !ahb added currentPatch + ! Send fluxes from newly created litter into the litter pools ! This litter flux is from non-disturbance inducing mortality, as well @@ -1525,18 +1526,20 @@ subroutine SeedDecay( litt ) end subroutine SeedDecay ! ============================================================================ - subroutine SeedGermination( litt, cold_stat, drought_stat ) + subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) !ahb added currentPatch ! ! !DESCRIPTION: - ! Flux from seed pool into sapling pool + ! Flux from seed bank into the seedling pool ! ! !USES: ! ! !ARGUMENTS type(litter_type) :: litt - integer, intent(in) :: cold_stat ! Is the site in cold leaf-off status? - integer, intent(in) :: drought_stat ! Is the site in drought leaf-off status? + integer, intent(in) :: cold_stat ! Is the site in cold leaf-off status? + integer, intent(in) :: drought_stat ! Is the site in drought leaf-off status? + type(bc_in_type), intent(in) :: bc_in ! ahb added this + type(ed_patch_type), intent(in) :: currentPatch ! ! !LOCAL VARIABLES: integer :: pft @@ -1545,6 +1548,23 @@ subroutine SeedGermination( litt, cold_stat, drought_stat ) real(r8), parameter :: max_germination = 1.0_r8 ! Cap on germination rates. ! KgC/m2/yr Lishcke et al. 2009 + + !New seedling emergence parameters (ahb) + + real(r8), parameter :: emerg_soil_depth = 0.06 !soil depth (m) for emergence + real(r8), parameter :: mpa_per_mm_suction = 1.e-5 + real(r8), parameter :: a_emerg = 0.0006 + real(r8), parameter :: b_emerg = 1.6 + integer :: ilayer_swater_emerg + real(r8) :: f_PAR + real(r8), parameter :: PAR_crit = 70 + real(r8) :: wetness_index + real(r8) :: f_emerg + real(r8) :: SMP_seed !SMP at emerg_soil_depth + real(r8) :: PAR_seed !PAR at seedling layer + + + ! Turning of this cap? because the cap will impose changes on proportionality ! of nutrients. (RGK 02-2019) !real(r8), parameter :: max_germination = 1.e6_r8 ! Force to very high number @@ -1559,29 +1579,34 @@ subroutine SeedGermination( litt, cold_stat, drought_stat ) !ORIGINAL CODE !------------------------------------------------------------------------------------------- - do pft = 1,numpft - litt%seed_germ_in(pft) = min(litt%seed(pft) * EDPftvarcon_inst%germination_rate(pft), & - max_germination)*years_per_day + !do pft = 1,numpft + ! litt%seed_germ_in(pft) = min(litt%seed(pft) * EDPftvarcon_inst%germination_rate(pft), & + ! max_germination)*years_per_day !------------------------------------------------------------------------------------------- !ahb NEW CODE !------------------------------------------------------------------------------------------- - !Step 1. Define a variable that is the mean SMP in the top 6 cm over the prior 14 days - - !real(r8),parameter :: demerg_soil_depth = 0.06_r8 - !ilayer_swater_emerg = minloc(abs(bc_in%z_sisl(:)-demerg_soil_depth),dim=1) - !smp_emerg_today = bc_in%smp_sl(ilayer_swater_emerg) - !currentSite%water_memory_emerg(1) = smp_emerg_today - !NEED TO BUILD OUT THIS WATER MEMORY MORE - - !do pft = 1,numpft - ! litt%seed_germ_in(pft) = min(litt%seed(pft) * EDPftvarcon_inst%germination_rate(pft), & - ! max_germination)*years_per_day + !Step 1. calculate the photoblastic germination rate modifier + PAR_seed = currentPatch%parprof_pft_dir_z(1,1,1) !(ican, pft, ileaf) !PAR at lowest layer? + !W-M2... (mean over 24 hrs?) + PAR_seed = PAR_seed * 4.6 !covert to umol s-1 of PAR + f_PAR = PAR_seed / (PAR_seed + PAR_crit) !calculate photoblastic germ rate + !modifier + !Step 2. calculate the soil matric potential at 'emerg_soil_depth' (m) + ilayer_swater_emerg = minloc(abs(bc_in%z_sisl(:)-emerg_soil_depth),dim=1) !define soil layer + SMP_seed = bc_in%smp_sl(ilayer_swater_emerg) !calculate smp (mm H20 suction?) + wetness_index = 1.0_r8 / (SMP_seed * -1.0_r8 * mpa_per_mm_suction) !calculate wetness + + !Step 3. calculate the seedling emergence rate based on SMP_seed and f_PAR + f_emerg = f_PAR * a_emerg * wetness_index**b_emerg + + !Step 4. calculate the 'seed_germ_in' flux !put all code inside loop + !when params become pft-specific + do pft = 1,numpft + litt%seed_germ_in(pft) = min(litt%seed(pft) * f_emerg, max_germination) !------------------------------------------------------------------------------------------- - - !set the germination only under the growing season...c.xu if ((prt_params%season_decid(pft) == itrue ) .and. & From 4fca97f812f258f6da916d048ab1ef0d0f898331 Mon Sep 17 00:00:00 2001 From: adamhb Date: Mon, 19 Jul 2021 15:26:59 -0700 Subject: [PATCH 041/852] moved pft-specific parameters into (instantaneous) emergence function --- biogeochem/EDPhysiologyMod.F90 | 22 ++++++++++++---------- main/EDPftvarcon.F90 | 30 ++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 7523d32d45..2c9afe0b1e 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1552,12 +1552,12 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) !New seedling emergence parameters (ahb) real(r8), parameter :: emerg_soil_depth = 0.06 !soil depth (m) for emergence - real(r8), parameter :: mpa_per_mm_suction = 1.e-5 - real(r8), parameter :: a_emerg = 0.0006 - real(r8), parameter :: b_emerg = 1.6 + real(r8), parameter :: mpa_per_mm_suction = 1.e-5 ! move this to FATES globals once sure of smp units + !real(r8), parameter :: a_emerg = 0.0006 + !real(r8), parameter :: b_emerg = 1.6 integer :: ilayer_swater_emerg real(r8) :: f_PAR - real(r8), parameter :: PAR_crit = 70 + !real(r8), parameter :: PAR_crit = 70 real(r8) :: wetness_index real(r8) :: f_emerg real(r8) :: SMP_seed !SMP at emerg_soil_depth @@ -1579,18 +1579,20 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) !ORIGINAL CODE !------------------------------------------------------------------------------------------- - !do pft = 1,numpft + do pft = 1,numpft ! litt%seed_germ_in(pft) = min(litt%seed(pft) * EDPftvarcon_inst%germination_rate(pft), & ! max_germination)*years_per_day !------------------------------------------------------------------------------------------- !ahb NEW CODE + !This new code adds light and moisture-sensitive seedling emergence functions. It replaces + !the old prescribed seed germination rate parameter. !------------------------------------------------------------------------------------------- !Step 1. calculate the photoblastic germination rate modifier - PAR_seed = currentPatch%parprof_pft_dir_z(1,1,1) !(ican, pft, ileaf) !PAR at lowest layer? - !W-M2... (mean over 24 hrs?) + PAR_seed = currentPatch%parprof_pft_dir_z(1,1,1) + & !(ican, pft, ileaf) !PAR at lowest layer? + currentPatch%parprof_pft_dif_z(1,1,1) !W-M2... (mean over 24 hrs?) PAR_seed = PAR_seed * 4.6 !covert to umol s-1 of PAR - f_PAR = PAR_seed / (PAR_seed + PAR_crit) !calculate photoblastic germ rate + f_PAR = PAR_seed / (PAR_seed + EDPftvarcon_inst%par_crit_germ(pft)) !calculate photoblastic germ rate !modifier !Step 2. calculate the soil matric potential at 'emerg_soil_depth' (m) ilayer_swater_emerg = minloc(abs(bc_in%z_sisl(:)-emerg_soil_depth),dim=1) !define soil layer @@ -1598,11 +1600,11 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) wetness_index = 1.0_r8 / (SMP_seed * -1.0_r8 * mpa_per_mm_suction) !calculate wetness !Step 3. calculate the seedling emergence rate based on SMP_seed and f_PAR - f_emerg = f_PAR * a_emerg * wetness_index**b_emerg + f_emerg = f_PAR * EDPftvarcon_inst%a_emerg(pft) * wetness_index**EDPftvarcon_inst%b_emerg(pft) !Step 4. calculate the 'seed_germ_in' flux !put all code inside loop !when params become pft-specific - do pft = 1,numpft + !do pft = 1,numpft litt%seed_germ_in(pft) = min(litt%seed(pft) * f_emerg, max_germination) !------------------------------------------------------------------------------------------- diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 4934f3920a..bd0317163d 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -104,6 +104,9 @@ module EDPftvarcon ! ungerminated), decaying per year (yr-1) real(r8), allocatable :: repro_frac_seed(:) ! added by ahb 7/15/2021 + real(r8), allocatable :: a_emerg(:) ! added by ahb 7/19/2021 + real(r8), allocatable :: b_emerg(:) ! added by ahb 7/19/2021 + real(r8), allocatable :: par_crit_germ(:) ! added by ahb 7/19/2021 real(r8), allocatable :: trim_limit(:) ! Limit to reductions in leaf area w stress (m2/m2) real(r8), allocatable :: trim_inc(:) ! Incremental change in trimming function (m2/m2) real(r8), allocatable :: rhol(:, :) @@ -518,6 +521,18 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_a_emerg' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_b_emerg' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_par_crit_germ' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_seed_decay_rate' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -853,6 +868,18 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=this%repro_frac_seed) + name = 'fates_a_emerg' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%a_emerg) + + name = 'fates_b_emerg' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%b_emerg) + + name = 'fates_par_crit_germ' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%par_crit_germ) + name = 'fates_seed_decay_rate' call fates_params%RetreiveParameterAllocate(name=name, & data=this%seed_decay_rate) @@ -1340,6 +1367,9 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'germination_timescale = ',EDPftvarcon_inst%germination_rate write(fates_log(),fmt0) 'seed_decay_turnover = ',EDPftvarcon_inst%seed_decay_rate write(fates_log(),fmt0) 'repro_frac_seed = ',EDPftvarcon_inst%repro_frac_seed + write(fates_log(),fmt0) 'a_emerg = ',EDPftvarcon_inst%a_emerg + write(fates_log(),fmt0) 'b_emerg = ',EDPftvarcon_inst%b_emerg + write(fates_log(),fmt0) 'par_crit_germ = ',EDPftvarcon_inst%par_crit_germ write(fates_log(),fmt0) 'trim_limit = ',EDPftvarcon_inst%trim_limit write(fates_log(),fmt0) 'trim_inc = ',EDPftvarcon_inst%trim_inc write(fates_log(),fmt0) 'rhol = ',EDPftvarcon_inst%rhol From 12863bf952449862f1cbc00057196c7a1248c198 Mon Sep 17 00:00:00 2001 From: adamhb Date: Mon, 19 Jul 2021 18:25:56 -0700 Subject: [PATCH 042/852] changed which par profile variable was being used by the seedling emergence subroutine --- biogeochem/EDPhysiologyMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 2c9afe0b1e..4955a208aa 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1589,8 +1589,8 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) !the old prescribed seed germination rate parameter. !------------------------------------------------------------------------------------------- !Step 1. calculate the photoblastic germination rate modifier - PAR_seed = currentPatch%parprof_pft_dir_z(1,1,1) + & !(ican, pft, ileaf) !PAR at lowest layer? - currentPatch%parprof_pft_dif_z(1,1,1) !W-M2... (mean over 24 hrs?) + PAR_seed = currentPatch%parprof_dir_z(1,1) + & !(ican, ileaf) !is 1,1 PAR at lowest layer? + currentPatch%parprof_dif_z(1,1) !W-M2... (mean over 24 hrs?) PAR_seed = PAR_seed * 4.6 !covert to umol s-1 of PAR f_PAR = PAR_seed / (PAR_seed + EDPftvarcon_inst%par_crit_germ(pft)) !calculate photoblastic germ rate !modifier From 99321aa28a890093a82bac8276023310e6ef1019 Mon Sep 17 00:00:00 2001 From: adamhb Date: Mon, 26 Jul 2021 12:52:12 -0700 Subject: [PATCH 043/852] deleted old comments --- biogeochem/EDPhysiologyMod.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 4955a208aa..2d5d8ed273 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1591,7 +1591,7 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) !Step 1. calculate the photoblastic germination rate modifier PAR_seed = currentPatch%parprof_dir_z(1,1) + & !(ican, ileaf) !is 1,1 PAR at lowest layer? currentPatch%parprof_dif_z(1,1) !W-M2... (mean over 24 hrs?) - PAR_seed = PAR_seed * 4.6 !covert to umol s-1 of PAR + PAR_seed = PAR_seed * 4.6_r8 !covert to umol s-1 of PAR f_PAR = PAR_seed / (PAR_seed + EDPftvarcon_inst%par_crit_germ(pft)) !calculate photoblastic germ rate !modifier !Step 2. calculate the soil matric potential at 'emerg_soil_depth' (m) @@ -1602,8 +1602,8 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) !Step 3. calculate the seedling emergence rate based on SMP_seed and f_PAR f_emerg = f_PAR * EDPftvarcon_inst%a_emerg(pft) * wetness_index**EDPftvarcon_inst%b_emerg(pft) - !Step 4. calculate the 'seed_germ_in' flux !put all code inside loop - !when params become pft-specific + !Step 4. calculate the 'seed_germ_in' flux + !do pft = 1,numpft litt%seed_germ_in(pft) = min(litt%seed(pft) * f_emerg, max_germination) !------------------------------------------------------------------------------------------- From 1c29442f52a17648543864953e0710c638f2f786 Mon Sep 17 00:00:00 2001 From: adamhb Date: Tue, 27 Jul 2021 14:49:44 -0700 Subject: [PATCH 044/852] added light-based seedling mortality the seed_germ pool is now treated as a seedling pool which can lose carbon from seedling mortality. this commit includes new code for light-based seedling mortality. This is important to capture the affect of understory light on recruitment rates. Fixes: none User interface changes?: No Code review: Adam Hanbury-Brown Test suite: ahb's account on Lobata Test summary: just did a simple test to see if the model would run at bci. it does. --- biogeochem/EDPhysiologyMod.F90 | 42 +++++++++++++++++++++++++++++----- main/EDPftvarcon.F90 | 33 +++++++++++++++++++++++--- main/FatesConstantsMod.F90 | 3 +++ 3 files changed, 69 insertions(+), 9 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 2d5d8ed273..7b81109f9b 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -19,6 +19,8 @@ module EDPhysiologyMod use FatesInterfaceTypesMod, only : hlm_phosphorus_spec use FatesConstantsMod, only : r8 => fates_r8 use FatesConstantsMod, only : nearzero + use FatesConstantsMod, only : sec_per_day + use FatesConstantsMod, only : megajoules_per_joule use EDPftvarcon , only : EDPftvarcon_inst use PRTParametersMod , only : prt_params use EDPftvarcon , only : GetDecompyFrac @@ -226,7 +228,7 @@ subroutine PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in ) litt => currentPatch%litter(el) ! Calculate loss rate of viable seeds to litter - call SeedDecay(litt) + call SeedDecay(litt, currentPatch, bc_in) ! Calculate seed germination rate, the status flags prevent ! germination from occuring when the site is in a drought @@ -1452,7 +1454,6 @@ subroutine SeedIn( currentSite, bc_in ) !This new code is designed to send some reproductive biomass !straight to the leaf litter pool to account for non-seed reproductive !biomass. Also see small change to SeedDecay subroutine. - !This can be turned off by commenting out line 1456. !-------------------------------- litt%seed_decay(pft) = litt%seed_in_local(pft) * (1.0_r8 - EDPftvarcon_inst%repro_frac_seed(pft)) !ahb !-------------------------------- @@ -1493,16 +1494,22 @@ end subroutine SeedIn ! ============================================================================ - subroutine SeedDecay( litt ) + subroutine SeedDecay( litt , currentPatch, bc_in ) ! ! !DESCRIPTION: ! Flux from seed pool into leaf litter pool ! ! !ARGUMENTS type(litter_type) :: litt + type(ed_patch_type), intent(in) :: currentPatch ! ahb added this + type(bc_in_type), intent(in) :: bc_in ! ahb added this ! ! !LOCAL VARIABLES: integer :: pft + real(r8) :: cumulative_light_seedling !cumulative light at the seedling layer (MJ) over prior 64 days + !this 64 day window is hard-coded for now because param values + !would need to change if the window changes + real(r8) :: seedling_light_mort_rate !the daily seedling mortality rate from light stress !---------------------------------------------------------------------- ! default value from Liscke and Loffler 2006 ; making this a PFT-specific parameter @@ -1516,9 +1523,32 @@ subroutine SeedDecay( litt ) EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day + & ! "+ &" added by ahb (7/10/2021) litt%seed_decay(pft) ! line added by ahb so that the flux from non-seed reproductive ! biomass (from SeedIn subroutine) is not lost (7/10/2021) + !START ahb's changes + !ORIGINAL CODE + !---------------------------------------------------------------------- + ! litt%seed_germ_decay(pft) = litt%seed_germ(pft) * & + ! EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day + !---------------------------------------------------------------------- + + !---------------------------------------------------------------------- + !NEW CODE FOR ENVIRONMENTALLY SENSITIVE SEEDLING MORTALITY + !Step 1. Calculate the daily seedling mortality rate from light stress + cumulative_light_seedling = ( currentPatch%parprof_dir_z(1,1) + & !indices: (ican, ileaf); is 1,1 PAR at lowest layer? + currentPatch%parprof_dif_z(1,1) ) * & + megajoules_per_joule * sec_per_day * 64.0_r8 !this is a placeholder until I get + !cumulative sum over prior 64 days working - litt%seed_germ_decay(pft) = litt%seed_germ(pft) * & - EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day + seedling_light_mort_rate = exp(EDPftvarcon_inst%seedling_light_mort_a(pft) * & + cumulative_light_seedling + EDPftvarcon_inst%seedling_light_mort_b(pft)) + + + litt%seed_germ_decay(pft) = (litt%seed_germ(pft) * seedling_light_mort_rate) !+ & + !(litt%seed_germ(pft) * seedling_h2o_mort_rate) + & + !(litt%seed_germ(pft) * EDPftvarcon_inst%background_seedling_mort(pft) & + !*years_per_day) + + !----------------------------------------------------------------------- + !END ahb's changes enddo @@ -1526,7 +1556,7 @@ subroutine SeedDecay( litt ) end subroutine SeedDecay ! ============================================================================ - subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) !ahb added currentPatch + subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) !ahb added currentPatch and bc_in ! ! !DESCRIPTION: ! Flux from seed bank into the seedling pool diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 29daf9534c..1d8f0e1834 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -103,9 +103,12 @@ module EDPftvarcon ! ungerminated), decaying per year (yr-1) real(r8), allocatable :: repro_frac_seed(:) ! added by ahb 7/15/2021 - real(r8), allocatable :: a_emerg(:) ! added by ahb 7/19/2021 - real(r8), allocatable :: b_emerg(:) ! added by ahb 7/19/2021 - real(r8), allocatable :: par_crit_germ(:) ! added by ahb 7/19/2021 + real(r8), allocatable :: a_emerg(:) !added by ahb 7/19/2021 + real(r8), allocatable :: b_emerg(:) !added by ahb 7/19/2021 + real(r8), allocatable :: par_crit_germ(:) !added by ahb 7/19/2021 + real(r8), allocatable :: seedling_light_mort_a(:) !added by ahb on 7/27/2021 + real(r8), allocatable :: seedling_light_mort_b(:) !added by ahb on 7/27/2021 + real(r8), allocatable :: background_seedling_mort(:)!added by ahb on 7/27/2021 real(r8), allocatable :: trim_limit(:) ! Limit to reductions in leaf area w stress (m2/m2) real(r8), allocatable :: trim_inc(:) ! Incremental change in trimming function (m2/m2) real(r8), allocatable :: rhol(:, :) @@ -561,7 +564,19 @@ subroutine Register_PFT(this, fates_params) name = 'fates_par_crit_germ' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_seedling_light_mort_a' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_seedling_light_mort_b' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_background_seedling_mort' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_seed_decay_rate' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -924,6 +939,18 @@ subroutine Receive_PFT(this, fates_params) name = 'fates_par_crit_germ' call fates_params%RetreiveParameterAllocate(name=name, & data=this%par_crit_germ) + + name = 'fates_seedling_light_mort_a' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%seedling_light_mort_a) + + name = 'fates_seedling_light_mort_b' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%seedling_light_mort_b) + + name = 'fates_background_seedling_mort' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%background_seedling_mort) name = 'fates_seed_decay_rate' call fates_params%RetreiveParameterAllocate(name=name, & diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index 06eafc3d5c..ce6bb4f212 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -167,6 +167,9 @@ module FatesConstantsMod ! Conversion: seconds per day real(fates_r8), parameter, public :: sec_per_day = 86400.0_fates_r8 + ! Conversion: megajoules per joule + real(fates_r8), parameter, public :: megajoules_per_joule = 1.0E-6_fates_r8 + ! Conversion: days per second real(fates_r8), parameter, public :: days_per_sec = 1.0_fates_r8/86400.0_fates_r8 From 7338ec2c885e895e412c4bf55df1e457224c6493 Mon Sep 17 00:00:00 2001 From: adamhb Date: Tue, 27 Jul 2021 18:33:22 -0700 Subject: [PATCH 045/852] started to add code for moisture deficit days --- biogeochem/EDPhysiologyMod.F90 | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 7b81109f9b..a104426c34 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1533,6 +1533,8 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) !---------------------------------------------------------------------- !NEW CODE FOR ENVIRONMENTALLY SENSITIVE SEEDLING MORTALITY !Step 1. Calculate the daily seedling mortality rate from light stress + + !ADD CODE FOR CUMULATIVE LIGHT cumulative_light_seedling = ( currentPatch%parprof_dir_z(1,1) + & !indices: (ican, ileaf); is 1,1 PAR at lowest layer? currentPatch%parprof_dif_z(1,1) ) * & megajoules_per_joule * sec_per_day * 64.0_r8 !this is a placeholder until I get @@ -1541,7 +1543,27 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) seedling_light_mort_rate = exp(EDPftvarcon_inst%seedling_light_mort_a(pft) * & cumulative_light_seedling + EDPftvarcon_inst%seedling_light_mort_b(pft)) + !Step 2. Calculate the moisture deficit days !this code is a placeholder for now + + !ilayer_swater_emerg = minloc(abs(bc_in%z_sisl(:)-emerg_soil_depth),dim=1) !define soil layer + + !moisture_def_days = abs(bc_in%smp_sl(ilayer_swater_emerg) * mpa_per_mm_suction) - & !calculate smp (mm H20 suction?) + ! abs(EDPftvarcon_inst%seedling_smp_crit(pft)) + + + !Step 3. Calculate the daily seedling mortality rate from moisture stress + + !seedling_h2o_mort_rate = EDPftvarcon_inst%seedling_h2o_mort_a(pft) * moisture_def_days**2 + & + ! EDPftvarcon_inst%seedling_h2o_mort_b(pft) * moisture_def_days + & + ! EDPftvarcon_inst%seedling_h2o_mort_c(pft) + + !if (moisture_def_days < EDPftvarcon_inst%moisture_dd_crit(pft) ) then + ! seedling_h2o_mort_rate = 0.0_r8 + !end if + + + !Step 4. Add background mortality and send seedling carbon to litter flux (i.e. to 'seed_germ_decay' flux) litt%seed_germ_decay(pft) = (litt%seed_germ(pft) * seedling_light_mort_rate) !+ & !(litt%seed_germ(pft) * seedling_h2o_mort_rate) + & !(litt%seed_germ(pft) * EDPftvarcon_inst%background_seedling_mort(pft) & From 19413273a3fbf0a28e50439ff66224dc48ab4fe1 Mon Sep 17 00:00:00 2001 From: adamhb Date: Tue, 27 Jul 2021 19:31:19 -0700 Subject: [PATCH 046/852] germination not working --- biogeochem/EDPhysiologyMod.F90 | 45 +++++++++++++++------------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index a104426c34..978c01faab 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1595,26 +1595,21 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) ! ! !LOCAL VARIABLES: integer :: pft - - real(r8), parameter :: max_germination = 1.0_r8 ! Cap on germination rates. ! KgC/m2/yr Lishcke et al. 2009 - - !New seedling emergence parameters (ahb) - - real(r8), parameter :: emerg_soil_depth = 0.06 !soil depth (m) for emergence - real(r8), parameter :: mpa_per_mm_suction = 1.e-5 ! move this to FATES globals once sure of smp units - !real(r8), parameter :: a_emerg = 0.0006 - !real(r8), parameter :: b_emerg = 1.6 - integer :: ilayer_swater_emerg - real(r8) :: f_PAR - !real(r8), parameter :: PAR_crit = 70 - real(r8) :: wetness_index - real(r8) :: f_emerg - real(r8) :: SMP_seed !SMP at emerg_soil_depth - real(r8) :: PAR_seed !PAR at seedling layer - + !Light and moisture-sensitive seedling emergence variables (ahb) + !------------------------------------------------------------------------------------------------------------ + real(r8), parameter :: root_depth = 0.06 + real(r8), parameter :: mpa_per_mm_suction = 1.e-5 ! move this to FATES globals once sure of smp units + integer :: ilayer_swater_emerg ! the soil layer used for seedling moisture functions + real(r8) :: f_PAR ! emergence rate modifier for light-sensitive germination + real(r8) :: wetness_index ! a soil 'wetness index' calculated from smp + ! used in the moisture-sensitive emergence function + real(r8) :: f_emerg ! the fraction of the seed bank emerging in the current time step + real(r8) :: SMP_seed ! soil matric potential at seedling rooting depth + real(r8) :: PAR_seed ! photosynthetically active radiation at the seedling layer + !------------------------------------------------------------------------------------------------------------- ! Turning of this cap? because the cap will impose changes on proportionality @@ -1641,15 +1636,15 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) !the old prescribed seed germination rate parameter. !------------------------------------------------------------------------------------------- !Step 1. calculate the photoblastic germination rate modifier - PAR_seed = currentPatch%parprof_dir_z(1,1) + & !(ican, ileaf) !is 1,1 PAR at lowest layer? - currentPatch%parprof_dif_z(1,1) !W-M2... (mean over 24 hrs?) + PAR_seed = currentPatch%parprof_dir_z(1,1) + & !(ican, ileaf) !is 1,1 PAR at lowest layer? + currentPatch%parprof_dif_z(1,1) !W-M2... (mean over 24 hrs?) PAR_seed = PAR_seed * 4.6_r8 !covert to umol s-1 of PAR - f_PAR = PAR_seed / (PAR_seed + EDPftvarcon_inst%par_crit_germ(pft)) !calculate photoblastic germ rate - !modifier - !Step 2. calculate the soil matric potential at 'emerg_soil_depth' (m) - ilayer_swater_emerg = minloc(abs(bc_in%z_sisl(:)-emerg_soil_depth),dim=1) !define soil layer - SMP_seed = bc_in%smp_sl(ilayer_swater_emerg) !calculate smp (mm H20 suction?) - wetness_index = 1.0_r8 / (SMP_seed * -1.0_r8 * mpa_per_mm_suction) !calculate wetness + f_PAR = PAR_seed / (PAR_seed + EDPftvarcon_inst%par_crit_germ(pft)) !calculate photoblastic germ rate + !modifier + !Step 2. calculate the soil matric potential at the seedling root depth + ilayer_swater_emerg = minloc(abs(bc_in%z_sisl(:)-root_depth),dim=1) !define soil layer + SMP_seed = bc_in%smp_sl(ilayer_swater_emerg) !calculate smp (mm H20 suction?) + wetness_index = 1.0_r8 / (SMP_seed * (-1.0_r8) * mpa_per_mm_suction) !calculate wetness !Step 3. calculate the seedling emergence rate based on SMP_seed and f_PAR f_emerg = f_PAR * EDPftvarcon_inst%a_emerg(pft) * wetness_index**EDPftvarcon_inst%b_emerg(pft) From 316467d3e5ed78bfd4d051f02265b009ca0d68e6 Mon Sep 17 00:00:00 2001 From: adamhb Date: Tue, 27 Jul 2021 19:33:36 -0700 Subject: [PATCH 047/852] germination not working --- main/EDPftvarcon.F90 | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 1d8f0e1834..42f193772e 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -106,6 +106,7 @@ module EDPftvarcon real(r8), allocatable :: a_emerg(:) !added by ahb 7/19/2021 real(r8), allocatable :: b_emerg(:) !added by ahb 7/19/2021 real(r8), allocatable :: par_crit_germ(:) !added by ahb 7/19/2021 + real(r8), allocatable :: seedling_root_depth(:) !added by ahb 7/27/2021 real(r8), allocatable :: seedling_light_mort_a(:) !added by ahb on 7/27/2021 real(r8), allocatable :: seedling_light_mort_b(:) !added by ahb on 7/27/2021 real(r8), allocatable :: background_seedling_mort(:)!added by ahb on 7/27/2021 @@ -564,7 +565,11 @@ subroutine Register_PFT(this, fates_params) name = 'fates_par_crit_germ' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - + + name = 'fates_seedling_root_depth' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_seedling_light_mort_a' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -939,7 +944,11 @@ subroutine Receive_PFT(this, fates_params) name = 'fates_par_crit_germ' call fates_params%RetreiveParameterAllocate(name=name, & data=this%par_crit_germ) - + + name = 'fates_seedling_root_depth' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%seedling_root_depth) + name = 'fates_seedling_light_mort_a' call fates_params%RetreiveParameterAllocate(name=name, & data=this%seedling_light_mort_a) @@ -1498,6 +1507,7 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'a_emerg = ',EDPftvarcon_inst%a_emerg write(fates_log(),fmt0) 'b_emerg = ',EDPftvarcon_inst%b_emerg write(fates_log(),fmt0) 'par_crit_germ = ',EDPftvarcon_inst%par_crit_germ + write(fates_log(),fmt0) 'seedling_root_depth = ',EDPftvarcon_inst%seedling_root_depth write(fates_log(),fmt0) 'trim_limit = ',EDPftvarcon_inst%trim_limit write(fates_log(),fmt0) 'trim_inc = ',EDPftvarcon_inst%trim_inc write(fates_log(),fmt0) 'rhol = ',EDPftvarcon_inst%rhol From 36c331cb23b9fb9d10804b7734e94c3904866e5c Mon Sep 17 00:00:00 2001 From: adamhb Date: Tue, 27 Jul 2021 19:40:21 -0700 Subject: [PATCH 048/852] mass balance issue --- biogeochem/EDPhysiologyMod.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 978c01faab..e026a02878 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1643,11 +1643,11 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) !modifier !Step 2. calculate the soil matric potential at the seedling root depth ilayer_swater_emerg = minloc(abs(bc_in%z_sisl(:)-root_depth),dim=1) !define soil layer - SMP_seed = bc_in%smp_sl(ilayer_swater_emerg) !calculate smp (mm H20 suction?) - wetness_index = 1.0_r8 / (SMP_seed * (-1.0_r8) * mpa_per_mm_suction) !calculate wetness + SMP_seed = bc_in%smp_sl(ilayer_swater_emerg) !calculate smp (mm H20 suction?) + wetness_index = 1.0_r8 / (SMP_seed * (-1.0_r8) * mpa_per_mm_suction) !calculate wetness !Step 3. calculate the seedling emergence rate based on SMP_seed and f_PAR - f_emerg = f_PAR * EDPftvarcon_inst%a_emerg(pft) * wetness_index**EDPftvarcon_inst%b_emerg(pft) + f_emerg = f_PAR * EDPftvarcon_inst%a_emerg(pft) * wetness_index**EDPftvarcon_inst%b_emerg(pft) !Step 4. calculate the 'seed_germ_in' flux From d7ea5b6129779ca76b0b3754d0fdbc4113d9b881 Mon Sep 17 00:00:00 2001 From: adamhb Date: Tue, 27 Jul 2021 19:50:09 -0700 Subject: [PATCH 049/852] fixed mass balance issue --- biogeochem/EDPhysiologyMod.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index e026a02878..ebbd354463 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1526,8 +1526,8 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) !START ahb's changes !ORIGINAL CODE !---------------------------------------------------------------------- - ! litt%seed_germ_decay(pft) = litt%seed_germ(pft) * & - ! EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day + litt%seed_germ_decay(pft) = litt%seed_germ(pft) * & + EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day !---------------------------------------------------------------------- !---------------------------------------------------------------------- @@ -1564,7 +1564,7 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) !Step 4. Add background mortality and send seedling carbon to litter flux (i.e. to 'seed_germ_decay' flux) - litt%seed_germ_decay(pft) = (litt%seed_germ(pft) * seedling_light_mort_rate) !+ & + !litt%seed_germ_decay(pft) = (litt%seed_germ(pft) * seedling_light_mort_rate) !+ & !(litt%seed_germ(pft) * seedling_h2o_mort_rate) + & !(litt%seed_germ(pft) * EDPftvarcon_inst%background_seedling_mort(pft) & !*years_per_day) From 3c78d6bb63edb480d5ca12d9cd17031e0ee9db3b Mon Sep 17 00:00:00 2001 From: adamhb Date: Wed, 28 Jul 2021 12:13:37 -0700 Subject: [PATCH 050/852] testing --- biogeochem/EDPhysiologyMod.F90 | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index ebbd354463..ccaca53170 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1506,10 +1506,11 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) ! ! !LOCAL VARIABLES: integer :: pft - real(r8) :: cumulative_light_seedling !cumulative light at the seedling layer (MJ) over prior 64 days - !this 64 day window is hard-coded for now because param values - !would need to change if the window changes - real(r8) :: seedling_light_mort_rate !the daily seedling mortality rate from light stress + real(r8) :: cumulative_light_seedling !cumulative light at the seedling layer (MJ) over prior 64 days + !this 64 day window is hard-coded for now because param values + !would need to change if the window changes + real(r8) :: seedling_light_mort_rate !the daily seedling mortality rate from light stress + real(r8), parameter :: mpa_per_mm_suction = 1.0e5_r8 !---------------------------------------------------------------------- ! default value from Liscke and Loffler 2006 ; making this a PFT-specific parameter @@ -1588,10 +1589,10 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) ! ! !ARGUMENTS type(litter_type) :: litt - integer, intent(in) :: cold_stat ! Is the site in cold leaf-off status? - integer, intent(in) :: drought_stat ! Is the site in drought leaf-off status? - type(bc_in_type), intent(in) :: bc_in ! ahb added this - type(ed_patch_type), intent(in) :: currentPatch + integer, intent(in) :: cold_stat ! Is the site in cold leaf-off status? + integer, intent(in) :: drought_stat ! Is the site in drought leaf-off status? + type(bc_in_type), intent(in) :: bc_in ! ahb added this July 2021 + type(ed_patch_type), intent(in) :: currentPatch ! ahb added this July 2021 ! ! !LOCAL VARIABLES: integer :: pft @@ -1642,7 +1643,7 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) f_PAR = PAR_seed / (PAR_seed + EDPftvarcon_inst%par_crit_germ(pft)) !calculate photoblastic germ rate !modifier !Step 2. calculate the soil matric potential at the seedling root depth - ilayer_swater_emerg = minloc(abs(bc_in%z_sisl(:)-root_depth),dim=1) !define soil layer + ilayer_swater_emerg = minloc(abs(bc_in%z_sisl(:)-EDPftvarcon_inst%seedling_root_depth(pft)),dim=1) !define soil layer SMP_seed = bc_in%smp_sl(ilayer_swater_emerg) !calculate smp (mm H20 suction?) wetness_index = 1.0_r8 / (SMP_seed * (-1.0_r8) * mpa_per_mm_suction) !calculate wetness From 16f148d3b7d7d04c6adba6a83ab8737d4ea1e5cd Mon Sep 17 00:00:00 2001 From: adamhb Date: Thu, 29 Jul 2021 10:50:32 -0700 Subject: [PATCH 051/852] added comments to end of germination code chunk --- biogeochem/EDPhysiologyMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 2d5d8ed273..dccccab29f 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1607,7 +1607,7 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) !do pft = 1,numpft litt%seed_germ_in(pft) = min(litt%seed(pft) * f_emerg, max_germination) !------------------------------------------------------------------------------------------- - + !END ahb's new code !set the germination only under the growing season...c.xu From b9e3ed969ed416b5fe2a9353825508cc3160172f Mon Sep 17 00:00:00 2001 From: adamhb Date: Fri, 30 Jul 2021 18:08:56 -0700 Subject: [PATCH 052/852] working, but parprof arrays are all zeroes --- biogeochem/EDPhysiologyMod.F90 | 112 +++++++++++++++++++++------------ main/EDMainMod.F90 | 5 +- main/EDTypesMod.F90 | 2 + main/FatesConstantsMod.F90 | 5 +- main/FatesRunningMeanMod.F90 | 7 ++- 5 files changed, 85 insertions(+), 46 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index e6b7f86bbe..f7a760ca32 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -21,6 +21,7 @@ module EDPhysiologyMod use FatesConstantsMod, only : nearzero use FatesConstantsMod, only : sec_per_day use FatesConstantsMod, only : megajoules_per_joule + use FatesConstantsMod, only : mpa_per_mm_suction use EDPftvarcon , only : EDPftvarcon_inst use PRTParametersMod , only : prt_params use EDPftvarcon , only : GetDecompyFrac @@ -1498,7 +1499,8 @@ end subroutine SeedIn subroutine SeedDecay( litt , currentPatch, bc_in ) ! ! !DESCRIPTION: - ! Flux from seed pool into leaf litter pool + ! 1. Flux from seed pool into leaf litter pool + ! 2. Flux from seedling pool into leaf litter pool ! ! !ARGUMENTS type(litter_type) :: litt @@ -1507,26 +1509,31 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) ! ! !LOCAL VARIABLES: integer :: pft - real(r8) :: cumulative_light_seedling !cumulative light at the seedling layer (MJ) over prior 64 days - !this 64 day window is hard-coded for now because param values - !would need to change if the window changes + real(r8) :: seedling_layer_par !cumulative light at the seedling layer (MJ) over prior window of days + !(defined by 'light_mort_window' param) + real(r8), parameter :: seedling_light_mort_window = 64.0 !days; move to pft-level parameter real(r8) :: seedling_light_mort_rate !the daily seedling mortality rate from light stress - real(r8), parameter :: mpa_per_mm_suction = 1.0e5_r8 !---------------------------------------------------------------------- + + ! 1. Flux from seed pool into leaf litter pool + ! default value from Liscke and Loffler 2006 ; making this a PFT-specific parameter ! decays the seed pool according to exponential model ! seed_decay_rate is in yr-1 ! seed_decay is kg/day ! Assume that decay rates are same for all chemical species + ! START ahb's changes do pft = 1,numpft litt%seed_decay(pft) = litt%seed(pft) * & EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day + & ! "+ &" added by ahb (7/10/2021) litt%seed_decay(pft) ! line added by ahb so that the flux from non-seed reproductive ! biomass (from SeedIn subroutine) is not lost (7/10/2021) - !START ahb's changes - !ORIGINAL CODE + + ! 2. Flux from seedling pool into leaf litter pool + + ! ORIGINAL CODE !---------------------------------------------------------------------- litt%seed_germ_decay(pft) = litt%seed_germ(pft) * & EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day @@ -1537,13 +1544,17 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) !Step 1. Calculate the daily seedling mortality rate from light stress !ADD CODE FOR CUMULATIVE LIGHT - cumulative_light_seedling = ( currentPatch%parprof_dir_z(1,1) + & !indices: (ican, ileaf); is 1,1 PAR at lowest layer? - currentPatch%parprof_dif_z(1,1) ) * & - megajoules_per_joule * sec_per_day * 64.0_r8 !this is a placeholder until I get - !cumulative sum over prior 64 days working + ! seedling_layer_par = ( currentPatch%parprof_dir_z(currentPatch%ncl_p,max(currentPatch%ncan(currentPatch%ncl_p,:))) ) ! + & + ! currentPatch%parprof_dif_z(currentPatch%ncl_p,max(currentPatch%ncan(currentPatch%ncl_p,:))) ) + ! * & + ! megajoules_per_joule * sec_per_day * seedling_light_mort_window + + ! seedling_light_mort_rate = exp(EDPftvarcon_inst%seedling_light_mort_a(pft) * & + ! seedling_layer_par + EDPftvarcon_inst%seedling_light_mort_b(pft)) + - seedling_light_mort_rate = exp(EDPftvarcon_inst%seedling_light_mort_a(pft) * & - cumulative_light_seedling + EDPftvarcon_inst%seedling_light_mort_b(pft)) + ! write(fates_log(),*) 'seedling layer par ', seedling_layer_par + ! write(fates_log(),*) 'seedling light mort rate ', seedling_light_mort_rate !Step 2. Calculate the moisture deficit days !this code is a placeholder for now @@ -1602,15 +1613,14 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) !Light and moisture-sensitive seedling emergence variables (ahb) !------------------------------------------------------------------------------------------------------------ - real(r8), parameter :: root_depth = 0.06 - real(r8), parameter :: mpa_per_mm_suction = 1.e-5 ! move this to FATES globals once sure of smp units - integer :: ilayer_swater_emerg ! the soil layer used for seedling moisture functions - real(r8) :: f_PAR ! emergence rate modifier for light-sensitive germination - real(r8) :: wetness_index ! a soil 'wetness index' calculated from smp - ! used in the moisture-sensitive emergence function - real(r8) :: f_emerg ! the fraction of the seed bank emerging in the current time step - real(r8) :: SMP_seed ! soil matric potential at seedling rooting depth - real(r8) :: PAR_seed ! photosynthetically active radiation at the seedling layer + integer :: ilayer_seedling_root ! the soil layer at seedling rooting depth + real(r8) :: seedling_layer_smp ! soil matric potential at seedling rooting depth + real(r8) :: wetness_index ! a soil 'wetness index' calculated from soil matric potential + + real(r8) :: seedling_layer_par ! photosynthetically active radiation at the seedling layer + real(r8) :: photoblastic_germ_modifier ! seedling emergence rate modifier for light-sensitive germination + ! used in the moisture-sensitive emergence function + real(r8) :: seedling_emerg_rate ! the fraction of the seed bank emerging in the current time step !------------------------------------------------------------------------------------------------------------- @@ -1625,7 +1635,8 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) ! is seed_decay_rate(p)/germination_rate(p) ! and thus the mortality rate (in units of individuals) is the product of ! that times the ratio of (hypothetical) seed mass to recruit biomass - + + !START ahb's CHANGES !ORIGINAL CODE !------------------------------------------------------------------------------------------- do pft = 1,numpft @@ -1633,30 +1644,51 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) ! max_germination)*years_per_day !------------------------------------------------------------------------------------------- - !ahb NEW CODE - !This new code adds light and moisture-sensitive seedling emergence functions. It replaces - !the old prescribed seed germination rate parameter. + !This code adds light and moisture-sensitive seedling emergence from the seed bank. + !It replaces the old prescribed seed germination rate parameter. !------------------------------------------------------------------------------------------- !Step 1. calculate the photoblastic germination rate modifier - PAR_seed = currentPatch%parprof_dir_z(1,1) + & !(ican, ileaf) !is 1,1 PAR at lowest layer? - currentPatch%parprof_dif_z(1,1) !W-M2... (mean over 24 hrs?) - PAR_seed = PAR_seed * 4.6_r8 !covert to umol s-1 of PAR - f_PAR = PAR_seed / (PAR_seed + EDPftvarcon_inst%par_crit_germ(pft)) !calculate photoblastic germ rate - !modifier - !Step 2. calculate the soil matric potential at the seedling root depth - ilayer_swater_emerg = minloc(abs(bc_in%z_sisl(:)-EDPftvarcon_inst%seedling_root_depth(pft)),dim=1) !define soil layer - SMP_seed = bc_in%smp_sl(ilayer_swater_emerg) !calculate smp (mm H20 suction?) - wetness_index = 1.0_r8 / (SMP_seed * (-1.0_r8) * mpa_per_mm_suction) !calculate wetness - - !Step 3. calculate the seedling emergence rate based on SMP_seed and f_PAR - f_emerg = f_PAR * EDPftvarcon_inst%a_emerg(pft) * wetness_index**EDPftvarcon_inst%b_emerg(pft) + + seedling_layer_par = & + ( currentPatch%parprof_dir_z(currentPatch%ncl_p,maxval(currentPatch%ncan(currentPatch%ncl_p,:))) + & + currentPatch%parprof_dif_z(currentPatch%ncl_p,maxval(currentPatch%ncan(currentPatch%ncl_p,:))) + & + currentPatch%parprof_dif_z(1,1) & + ) + + + write(fates_log(),*) 'nrm parprof', currentPatch%nrmlzd_parprof_dir_z(:,:,:) + !write(fates_log(),*) 'parprof', currentPatch%parprof_dif_z(1,:) + !write(fates_log(),*) 'number_leaf_layers_in_second_canopy_layer', maxval(currentPatch%ncan(currentPatch%ncl_p,:)) + + !write(fates_log(),*) 'seedling_layer_par_raw', seedling_layer_par + + seedling_layer_par = seedling_layer_par * 4.6_r8 !covert to umol s-1 of PAR + !1 W/m2 ≈ 4.6 μmole.m2/s + + photoblastic_germ_modifier = seedling_layer_par / & + (seedling_layer_par + EDPftvarcon_inst%par_crit_germ(pft)) + + !Step 2. calculate the soil matric potential at the seedling root depth + + !define soil layer + ilayer_seedling_root = minloc(abs(bc_in%z_sisl(:)-EDPftvarcon_inst%seedling_root_depth(pft)),dim=1) + + !get soil matric potential (mm of H2O suction) at the seedling rooting depth + seedling_layer_smp = bc_in%smp_sl(ilayer_seedling_root) + + !calculate a soil wetness index, which is used by the moisture-based seedling mortality function + wetness_index = 1.0_r8 / (seedling_layer_smp * (-1.0_r8) * mpa_per_mm_suction) + + !Step 3. calculate the seedling emergence rate based on soil moisture and par + seedling_emerg_rate = photoblastic_germ_modifier * EDPftvarcon_inst%a_emerg(pft) * & + wetness_index**EDPftvarcon_inst%b_emerg(pft) !Step 4. calculate the 'seed_germ_in' flux !do pft = 1,numpft - litt%seed_germ_in(pft) = min(litt%seed(pft) * f_emerg, max_germination) + litt%seed_germ_in(pft) = min(litt%seed(pft) * seedling_emerg_rate, max_germination) !------------------------------------------------------------------------------------------- - + !END ahb changes !set the germination only under the growing season...c.xu diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 0518c1b34e..6d6d742de1 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -95,7 +95,7 @@ module EDMainMod use FatesHistoryInterfaceMod, only : ih_nh4uptake_si, ih_no3uptake_si, ih_puptake_si use FatesHistoryInterfaceMod, only : ih_nh4uptake_scpf, ih_no3uptake_scpf, ih_puptake_scpf use FatesHistoryInterfaceMod, only : fates_hist - + ! CIME Globals use shr_log_mod , only : errMsg => shr_log_errMsg use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) @@ -584,7 +584,8 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! we will calculate this as a group call SeedIn(currentSite,bc_in) - + + ! Calculate all other litter fluxes ! ----------------------------------------------------------------------------------- diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 05a4178da9..6c0f21626a 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -426,6 +426,8 @@ module EDTypesMod class(rmean_type), pointer :: tveg_lpa ! Running mean of vegetation temperature at the ! leaf photosynthesis acclimation timescale [K] + class(rmean_type), pointer :: seedling_layer_par ! photosynthetically active radiation at the seedling layer (w-m2) + ! LEAF ORGANIZATION real(r8) :: pft_agb_profile(maxpft,n_dbh_bins) ! binned above ground biomass, for patch fusion: KgC/m2 real(r8) :: canopy_layer_tlai(nclmax) ! total leaf area index of each canopy layer diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index ce6bb4f212..c1363fe98d 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -169,7 +169,10 @@ module FatesConstantsMod ! Conversion: megajoules per joule real(fates_r8), parameter, public :: megajoules_per_joule = 1.0E-6_fates_r8 - + + ! Conversion: megapascals per mm H2O suction + real(fates_r8), parameter, public :: mpa_per_mm_suction = 1.0E-5_fates_r8 + ! Conversion: days per second real(fates_r8), parameter, public :: days_per_sec = 1.0_fates_r8/86400.0_fates_r8 diff --git a/main/FatesRunningMeanMod.F90 b/main/FatesRunningMeanMod.F90 index df1c12c7be..28d39c6995 100644 --- a/main/FatesRunningMeanMod.F90 +++ b/main/FatesRunningMeanMod.F90 @@ -88,9 +88,10 @@ module FatesRunningMeanMod ! Define the time methods that we want to have available to us - class(rmean_def_type), public, pointer :: ema_24hr ! Exponential moving average - 24hr window - class(rmean_def_type), public, pointer :: fixed_24hr ! Fixed, 24-hour window - class(rmean_def_type), public, pointer :: ema_lpa ! Exponential moving average - leaf photo acclimation + class(rmean_def_type), public, pointer :: ema_24hr ! Exponential moving average - 24hr window + class(rmean_def_type), public, pointer :: fixed_24hr ! Fixed, 24-hour window + class(rmean_def_type), public, pointer :: ema_lpa ! Exponential moving average - leaf photo acclimation + class(rmean_def_type), public, pointer :: moving_64day ! Moving, 64-day window; added by ahb contains From 7842661c940653a887379ac2194c7bc8e5198174 Mon Sep 17 00:00:00 2001 From: adamhb Date: Tue, 3 Aug 2021 10:42:15 -0700 Subject: [PATCH 053/852] indexed par at the seedling layer --- biogeochem/EDPhysiologyMod.F90 | 6 ++---- main/FatesInterfaceMod.F90 | 13 +++++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index f7a760ca32..ddbc4b2c15 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1651,12 +1651,10 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) seedling_layer_par = & ( currentPatch%parprof_dir_z(currentPatch%ncl_p,maxval(currentPatch%ncan(currentPatch%ncl_p,:))) + & - currentPatch%parprof_dif_z(currentPatch%ncl_p,maxval(currentPatch%ncan(currentPatch%ncl_p,:))) + & - currentPatch%parprof_dif_z(1,1) & - ) + currentPatch%parprof_dif_z(currentPatch%ncl_p,maxval(currentPatch%ncan(currentPatch%ncl_p,:))) ) - write(fates_log(),*) 'nrm parprof', currentPatch%nrmlzd_parprof_dir_z(:,:,:) + !write(fates_log(),*) 'nrm parprof', currentPatch%nrmlzd_parprof_dir_z(:,:,:) !write(fates_log(),*) 'parprof', currentPatch%parprof_dif_z(1,:) !write(fates_log(),*) 'number_leaf_layers_in_second_canopy_layer', maxval(currentPatch%ncan(currentPatch%ncl_p,:)) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index d5273a9ca7..7f6630e571 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1846,6 +1846,8 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) type(ed_patch_type), pointer :: cpatch type(ed_cohort_type), pointer :: ccohort integer :: s, ifp, io_si + real(r8) :: seedling_layer_par + do s = 1,size(sites,dim=1) @@ -1856,11 +1858,22 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) call cpatch%tveg24%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) call cpatch%tveg_lpa%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) + !ahb wrote these lines here + seedling_layer_par = ( cpatch%parprof_dir_z(cpatch%ncl_p,maxval(cpatch%ncan(cpatch%ncl_p,:)) -1.0_r8 ) ) ! + & + ! cpatch%parprof_dif_z(cpatch%ncl_p,maxval(cpatch%ncan(cpatch%ncl_p,:))) ) + write(fates_log(),*) 'patch number', cpatch%patchno + write(fates_log(),*) 'canopy layers', cpatch%ncl_p + write(fates_log(),*) 'leaf layers', maxval(cpatch%ncan(cpatch%ncl_p,:)) + write(fates_log(),*) 'cat parprof', seedling_layer_par + + ccohort => cpatch%tallest + do while (associated(ccohort)) call ccohort%tveg_lpa%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) ccohort => ccohort%shorter end do + cpatch => cpatch%younger enddo From 5f152f7242ebd07ed766da96041527d3102ccda8 Mon Sep 17 00:00:00 2001 From: adamhb Date: Thu, 5 Aug 2021 16:54:10 -0700 Subject: [PATCH 054/852] added moving fixed window (24 hr) average of par at the seedling layer as a patch-level variable --- biogeochem/EDPatchDynamicsMod.F90 | 18 ++++++++++++---- biogeochem/EDPhysiologyMod.F90 | 18 +++++++--------- main/EDTypesMod.F90 | 3 ++- main/FatesInterfaceMod.F90 | 36 +++++++++++++++++++++++-------- main/FatesRestartInterfaceMod.F90 | 12 ++++++++--- main/FatesRunningMeanMod.F90 | 3 ++- 6 files changed, 62 insertions(+), 28 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index beeedab46b..f53d978ff2 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -678,7 +678,7 @@ subroutine spawn_patches( currentSite, bc_in) ! -------------------------------------------------------------------------- call new_patch%tveg24%CopyFromDonor(currentPatch%tveg24) call new_patch%tveg_lpa%CopyFromDonor(currentPatch%tveg_lpa) - + call new_patch%seedling_layer_par24%CopyFromDonor(currentPatch%seedling_layer_par24) ! -------------------------------------------------------------------------- ! The newly formed patch from disturbance (new_patch), has now been given @@ -2002,6 +2002,8 @@ subroutine create_patch(currentSite, new_patch, age, areap, label) ! Until bc's are pointed to by sites give veg temp a default temp [K] real(r8), parameter :: temp_init_veg = 15._r8+t_water_freeze_k_1atm + real(r8), parameter :: init_seedling_par = 5.0_r8 !arbtrary initialization, ahb + ! !LOCAL VARIABLES: !--------------------------------------------------------------------- integer :: el ! element loop index @@ -2021,7 +2023,13 @@ subroutine create_patch(currentSite, new_patch, age, areap, label) call new_patch%tveg24%InitRMean(fixed_24hr,init_value=temp_init_veg,init_offset=real(hlm_current_tod,r8) ) allocate(new_patch%tveg_lpa) call new_patch%tveg_lpa%InitRmean(ema_lpa,init_value=temp_init_veg) - + + + allocate(new_patch%seedling_layer_par24) + call new_patch%seedling_layer_par24%InitRMean(fixed_24hr,init_value=init_seedling_par,init_offset=real(hlm_current_tod,r8) ) + + + ! Litter ! Allocate, Zero Fluxes, and Initialize to "unset" values @@ -2526,7 +2534,8 @@ subroutine fuse_2_patches(csite, dp, rp) ! Weighted mean of the running means call rp%tveg24%FuseRMean(dp%tveg24,rp%area*inv_sum_area) call rp%tveg_lpa%FuseRMean(dp%tveg_lpa,rp%area*inv_sum_area) - + call rp%seedling_layer_par24%FuseRMean(dp%seedling_layer_par24,rp%area*inv_sum_area) !ahb + rp%fuel_eff_moist = (dp%fuel_eff_moist*dp%area + rp%fuel_eff_moist*rp%area) * inv_sum_area rp%livegrass = (dp%livegrass*dp%area + rp%livegrass*rp%area) * inv_sum_area rp%sum_fuel = (dp%sum_fuel*dp%area + rp%sum_fuel*rp%area) * inv_sum_area @@ -2868,7 +2877,8 @@ subroutine dealloc_patch(cpatch) ! Deallocate any running means deallocate(cpatch%tveg24) deallocate(cpatch%tveg_lpa) - + deallocate(cpatch%seedling_layer_par24) + return end subroutine dealloc_patch diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index ddbc4b2c15..c9038c8a14 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1617,7 +1617,7 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) real(r8) :: seedling_layer_smp ! soil matric potential at seedling rooting depth real(r8) :: wetness_index ! a soil 'wetness index' calculated from soil matric potential - real(r8) :: seedling_layer_par ! photosynthetically active radiation at the seedling layer + real(r8) :: seedling_layer_par ! photosynthetically active radiation at the seedling layer real(r8) :: photoblastic_germ_modifier ! seedling emergence rate modifier for light-sensitive germination ! used in the moisture-sensitive emergence function real(r8) :: seedling_emerg_rate ! the fraction of the seed bank emerging in the current time step @@ -1649,16 +1649,14 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) !------------------------------------------------------------------------------------------- !Step 1. calculate the photoblastic germination rate modifier - seedling_layer_par = & - ( currentPatch%parprof_dir_z(currentPatch%ncl_p,maxval(currentPatch%ncan(currentPatch%ncl_p,:))) + & - currentPatch%parprof_dif_z(currentPatch%ncl_p,maxval(currentPatch%ncan(currentPatch%ncl_p,:))) ) - - - !write(fates_log(),*) 'nrm parprof', currentPatch%nrmlzd_parprof_dir_z(:,:,:) - !write(fates_log(),*) 'parprof', currentPatch%parprof_dif_z(1,:) - !write(fates_log(),*) 'number_leaf_layers_in_second_canopy_layer', maxval(currentPatch%ncan(currentPatch%ncl_p,:)) + seedling_layer_par = currentPatch%seedling_layer_par24%GetMean() + + ! write(fates_log(),*) 'nrm parprof', currentPatch%nrmlzd_parprof_dir_z(:,:,:) + ! write(fates_log(),*) 'parprof', currentPatch%parprof_dif_z(1,:) + ! write(fates_log(),*) 'number_leaf_layers_in_second_canopy_layer', maxval(currentPatch%ncan(currentPatch%ncl_p,:)) - !write(fates_log(),*) 'seedling_layer_par_raw', seedling_layer_par + write(fates_log(),*) 'patchno', currentPatch%patchno + write(fates_log(),*) 'seedling_layer_par', seedling_layer_par seedling_layer_par = seedling_layer_par * 4.6_r8 !covert to umol s-1 of PAR !1 W/m2 ≈ 4.6 μmole.m2/s diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 6c0f21626a..3783bc4084 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -426,7 +426,8 @@ module EDTypesMod class(rmean_type), pointer :: tveg_lpa ! Running mean of vegetation temperature at the ! leaf photosynthesis acclimation timescale [K] - class(rmean_type), pointer :: seedling_layer_par ! photosynthetically active radiation at the seedling layer (w-m2) + class(rmean_type), pointer :: seedling_layer_par24 ! 24-hour mean of photosynthetically active radiation + ! at the seedling layer (w-m2) ! LEAF ORGANIZATION real(r8) :: pft_agb_profile(maxpft,n_dbh_bins) ! binned above ground biomass, for patch fusion: KgC/m2 diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 7f6630e571..7230ae606b 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1846,8 +1846,10 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) type(ed_patch_type), pointer :: cpatch type(ed_cohort_type), pointer :: ccohort integer :: s, ifp, io_si - real(r8) :: seedling_layer_par - + real(r8) :: new_seedling_layer_par !seedling layer par in the current timestep + integer :: n_leaf !number of leaf layers per canopy layer in patch + real(r8) :: lai_sun_frac + real(r8) :: lai_shade_frac do s = 1,size(sites,dim=1) @@ -1857,14 +1859,30 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) ifp=ifp+1 call cpatch%tveg24%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) call cpatch%tveg_lpa%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) + + !updating seedling layer par; ahb, August 2021 + !--------------------------------------------------------------------------------------- - !ahb wrote these lines here - seedling_layer_par = ( cpatch%parprof_dir_z(cpatch%ncl_p,maxval(cpatch%ncan(cpatch%ncl_p,:)) -1.0_r8 ) ) ! + & - ! cpatch%parprof_dif_z(cpatch%ncl_p,maxval(cpatch%ncan(cpatch%ncl_p,:))) ) - write(fates_log(),*) 'patch number', cpatch%patchno - write(fates_log(),*) 'canopy layers', cpatch%ncl_p - write(fates_log(),*) 'leaf layers', maxval(cpatch%ncan(cpatch%ncl_p,:)) - write(fates_log(),*) 'cat parprof', seedling_layer_par + n_leaf = maxval(cpatch%ncan(cpatch%ncl_p,:)) !calculating the number of leaf layers + !in the lowest canopy layer + + !calculating the fraction of total lai (summed across pfts) in sun vs. shade + !at the lowest leaf level of the lowest canopy level + lai_sun_frac = sum(cpatch%ed_laisun_z(cpatch%ncl_p,:,n_leaf)) & + / ( sum(cpatch%ed_laisun_z(cpatch%ncl_p,:,n_leaf)) + & !summed across pfts + sum(cpatch%ed_laisha_z(cpatch%ncl_p,:,n_leaf)) ) !summed across pfts + + lai_shade_frac = 1.0_r8 - lai_sun_frac + + !calculating seedling layer par for the current time step + !using the weighted average of direct and diffuse par profiles + + new_seedling_layer_par = & + (cpatch%parprof_dir_z(cpatch%ncl_p,n_leaf) * lai_sun_frac) + & + (cpatch%parprof_dif_z(cpatch%ncl_p,n_leaf) * (1.0_r8 - lai_sun_frac)) + + call cpatch%seedling_layer_par24%UpdateRMean(new_seedling_layer_par) + !--------------------------------------------------------------------------------------- ccohort => cpatch%tallest diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 04a17e1a1c..55f46fb5d5 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -142,6 +142,7 @@ module FatesRestartInterfaceMod integer :: ir_tveg24_pa integer :: ir_tveglpa_pa integer :: ir_tveglpa_co + integer :: ir_seedling_layer_par24_pa !ahb integer :: ir_ddbhdt_co integer :: ir_resp_tstep_co @@ -1215,13 +1216,16 @@ subroutine define_restart_vars(this, initialize_variables) call this%set_restart_var(vname='fates_promcflux', vtype=site_r8, & long_name='fates diagnostic promotion carbon flux ', & units='', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_promcflux_si ) - + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_promcflux_si ) call this%DefineRMeanRestartVar(vname='fates_tveg24patch',vtype=cohort_r8, & long_name='24-hour patch veg temp', & units='K', initialize=initialize_variables,ivar=ivar, index = ir_tveg24_pa) + call this%DefineRMeanRestartVar(vname='fates_seedling_layer_par24',vtype=cohort_r8, & + long_name='24-hour seedling layer PAR', & + units='K', initialize=initialize_variables,ivar=ivar, index = ir_seedling_layer_par24_pa) + call this%DefineRMeanRestartVar(vname='fates_tveglpapatch',vtype=cohort_r8, & long_name='running average (EMA) of patch veg temp for photo acclim', & units='K', initialize=initialize_variables,ivar=ivar, index = ir_tveglpa_pa) @@ -2030,6 +2034,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) ! Patch level running means call this%SetRMeanRestartVar(cpatch%tveg24, ir_tveg24_pa, io_idx_co_1st) call this%SetRMeanRestartVar(cpatch%tveg_lpa, ir_tveglpa_pa, io_idx_co_1st) + call this%SetRMeanRestartVar(cpatch%seedling_layer_par24, ir_seedling_layer_par24_pa, io_idx_co_1st) ! set cohorts per patch for IO rio_ncohort_pa( io_idx_co_1st ) = cohortsperpatch @@ -2816,7 +2821,8 @@ subroutine get_restart_vectors(this, nc, nsites, sites) call this%GetRMeanRestartVar(cpatch%tveg24, ir_tveg24_pa, io_idx_co_1st) call this%GetRMeanRestartVar(cpatch%tveg_lpa, ir_tveglpa_pa, io_idx_co_1st) - + call this%GetRMeanRestartVar(cpatch%seedling_layer_par24, ir_seedling_layer_par24_pa, io_idx_co_1st) + ! set cohorts per patch for IO if ( debug ) then diff --git a/main/FatesRunningMeanMod.F90 b/main/FatesRunningMeanMod.F90 index 28d39c6995..600703954a 100644 --- a/main/FatesRunningMeanMod.F90 +++ b/main/FatesRunningMeanMod.F90 @@ -91,7 +91,8 @@ module FatesRunningMeanMod class(rmean_def_type), public, pointer :: ema_24hr ! Exponential moving average - 24hr window class(rmean_def_type), public, pointer :: fixed_24hr ! Fixed, 24-hour window class(rmean_def_type), public, pointer :: ema_lpa ! Exponential moving average - leaf photo acclimation - class(rmean_def_type), public, pointer :: moving_64day ! Moving, 64-day window; added by ahb + class(rmean_def_type), public, pointer :: ema_seedling_mort ! Exponential moving average + ! seedling mort from light contains From 61756c8f4c844e4ec8491de5873daba1b904d4f3 Mon Sep 17 00:00:00 2001 From: adamhb Date: Tue, 10 Aug 2021 14:39:41 -0700 Subject: [PATCH 055/852] added running means for par and smp; model crashing --- biogeochem/EDPatchDynamicsMod.F90 | 34 ++++++++++++++++++++- biogeochem/EDPhysiologyMod.F90 | 5 +++- main/EDParamsMod.F90 | 47 +++++++++++++++++++++++++++++ main/EDTypesMod.F90 | 16 ++++++++++ main/FatesInterfaceMod.F90 | 49 +++++++++++++++++++++++++++++-- main/FatesRestartInterfaceMod.F90 | 27 ++++++++++++++++- main/FatesRunningMeanMod.F90 | 11 ++++--- 7 files changed, 180 insertions(+), 9 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index f53d978ff2..a5d79c41c0 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -87,6 +87,7 @@ module EDPatchDynamicsMod use EDParamsMod, only : logging_event_code use EDParamsMod, only : logging_export_frac use FatesRunningMeanMod, only : ema_24hr, fixed_24hr, ema_lpa + use FatesRunningMeanMod, only : ema_sdlng_emerg_h2o, ema_sdlng_mort_par, ema_sdlng2sap_par ! CIME globals use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) @@ -679,6 +680,9 @@ subroutine spawn_patches( currentSite, bc_in) call new_patch%tveg24%CopyFromDonor(currentPatch%tveg24) call new_patch%tveg_lpa%CopyFromDonor(currentPatch%tveg_lpa) call new_patch%seedling_layer_par24%CopyFromDonor(currentPatch%seedling_layer_par24) + call new_patch%sdlng_emerg_smp%CopyFromDonor(currentPatch%sdlng_emerg_smp) + call new_patch%sdlng_mort_par%CopyFromDonor(currentPatch%sdlng_mort_par) + call new_patch%sdlng2sap_par%CopyFromDonor(currentPatch%sdlng2sap_par) ! -------------------------------------------------------------------------- ! The newly formed patch from disturbance (new_patch), has now been given @@ -2002,7 +2006,11 @@ subroutine create_patch(currentSite, new_patch, age, areap, label) ! Until bc's are pointed to by sites give veg temp a default temp [K] real(r8), parameter :: temp_init_veg = 15._r8+t_water_freeze_k_1atm - real(r8), parameter :: init_seedling_par = 5.0_r8 !arbtrary initialization, ahb + real(r8), parameter :: init_seedling_par = 5.0_r8 !arbtrary initialization, ahb + + real(r8), parameter :: init_seedling_smp = -26652.0_r8 !mean smp (mm) from prior ED2 + !simulation at BCI (arbitrary) + ! !LOCAL VARIABLES: !--------------------------------------------------------------------- @@ -2028,6 +2036,22 @@ subroutine create_patch(currentSite, new_patch, age, areap, label) allocate(new_patch%seedling_layer_par24) call new_patch%seedling_layer_par24%InitRMean(fixed_24hr,init_value=init_seedling_par,init_offset=real(hlm_current_tod,r8) ) + allocate(new_patch%sdlng_emerg_smp) + call new_patch%sdlng_emerg_smp%InitRMean(ema_sdlng_emerg_h2o, & + init_value=init_seedling_smp,init_offset=real(hlm_current_tod,r8) ) + + allocate(new_patch%sdlng_mort_par) + call new_patch%sdlng_mort_par%InitRMean(ema_sdlng_mort_par, & + init_value=init_seedling_par,init_offset=real(hlm_current_tod,r8) ) + + !allocate(new_patch%sdlng_mdd) + !call new_patch%sdlng_mdd%InitRMean(ema_sdlng_mdd, & + ! init_value=0.0_r8,init_offset=real(hlm_current_tod,r8) ) + + allocate(new_patch%sdlng2sap_par) + call new_patch%sdlng2sap_par%InitRMean(ema_sdlng2sap_par, & + init_value=init_seedling_par,init_offset=real(hlm_current_tod,r8) ) + ! Litter @@ -2535,6 +2559,9 @@ subroutine fuse_2_patches(csite, dp, rp) call rp%tveg24%FuseRMean(dp%tveg24,rp%area*inv_sum_area) call rp%tveg_lpa%FuseRMean(dp%tveg_lpa,rp%area*inv_sum_area) call rp%seedling_layer_par24%FuseRMean(dp%seedling_layer_par24,rp%area*inv_sum_area) !ahb + call rp%sdlng_emerg_smp%FuseRMean(dp%sdlng_emerg_smp,rp%area*inv_sum_area) !ahb + call rp%sdlng_mort_par%FuseRMean(dp%sdlng_mort_par,rp%area*inv_sum_area) !ahb + call rp%sdlng2sap_par%FuseRMean(dp%sdlng2sap_par,rp%area*inv_sum_area) !ahb rp%fuel_eff_moist = (dp%fuel_eff_moist*dp%area + rp%fuel_eff_moist*rp%area) * inv_sum_area rp%livegrass = (dp%livegrass*dp%area + rp%livegrass*rp%area) * inv_sum_area @@ -2878,6 +2905,11 @@ subroutine dealloc_patch(cpatch) deallocate(cpatch%tveg24) deallocate(cpatch%tveg_lpa) deallocate(cpatch%seedling_layer_par24) + deallocate(cpatch%sdlng_emerg_smp) + deallocate(cpatch%sdlng_mort_par) + deallocate(cpatch%sdlng_mdd) + deallocate(cpatch%sdlng2sap_par) + return end subroutine dealloc_patch diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index c9038c8a14..11184a9878 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1657,7 +1657,10 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) write(fates_log(),*) 'patchno', currentPatch%patchno write(fates_log(),*) 'seedling_layer_par', seedling_layer_par - + write(fates_log(),*) 'seedling_emerg_smp', currentPatch%sdlng_emerg_smp%GetMean() + write(fates_log(),*) 'seedling_mort_par', currentPatch%sdlng_mort_par%GetMean() + write(fates_log(),*) 'seedling2sap_trans_par', currentPatch%sdlng2sap_par%GetMean() + seedling_layer_par = seedling_layer_par * 4.6_r8 !covert to umol s-1 of PAR !1 W/m2 ≈ 4.6 μmole.m2/s diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 1f10aa2c7f..ea12daabe3 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -31,6 +31,17 @@ module EDParamsMod ! of vegetation temperature used in photosynthesis ! temperature acclimation (NOT YET IMPLEMENTED) + real(r8),protected, public :: sdlng_emerg_h2o_timescale !Length of the window for the exponential moving + !average of smp used to calculate seedling emergence + real(r8),protected, public :: sdlng_mort_par_timescale !Length of the window for the exponential moving average + !of par at the seedling layer used to calculate + !seedling mortality + real(r8),protected, public :: sdlng_mdd_timescale !Length of the window for the exponential moving average + ! of moisture deficit days used to calculate seedling mortality + real(r8),protected, public :: sdlng2sap_par_timescale !Length of the window for the exponential + !moving average of par at the seedling layer used to + !calculate seedling to sapling transition rates + integer,protected, public :: maintresp_model ! switch for choosing between leaf maintenance ! respiration model. 1=Ryan (1991) (NOT YET IMPLEMENTED) integer,protected, public :: photo_tempsens_model ! switch for choosing the model that defines the temperature @@ -94,6 +105,10 @@ module EDParamsMod character(len=param_string_length),parameter,public :: ED_name_vai_top_bin_width = "fates_vai_top_bin_width" character(len=param_string_length),parameter,public :: ED_name_vai_width_increase_factor = "fates_vai_width_increase_factor" character(len=param_string_length),parameter,public :: ED_name_photo_temp_acclim_timescale = "fates_photo_temp_acclim_timescale" + character(len=param_string_length),parameter,public :: ED_name_sdlng_emerg_h2o_timescale = "fates_sdlng_emerg_h2o_timescale" + character(len=param_string_length),parameter,public :: ED_name_sdlng_mort_par_timescale = "fates_sdlng_mort_par_timescale" + character(len=param_string_length),parameter,public :: ED_name_sdlng_mdd_timescale = "fates_sdlng_mdd_timescale" + character(len=param_string_length),parameter,public :: ED_name_sdlng2sap_par_timescale = "fates_sdlng2sap_par_timescale" character(len=param_string_length),parameter,public :: name_photo_tempsens_model = "fates_photo_tempsens_model" character(len=param_string_length),parameter,public :: name_maintresp_model = "fates_maintresp_model" character(len=param_string_length),parameter,public :: ED_name_hydr_htftype_node = "fates_hydr_htftype_node" @@ -212,6 +227,10 @@ subroutine FatesParamsInit() vai_top_bin_width = nan vai_width_increase_factor = nan photo_temp_acclim_timescale = nan + sdlng_emerg_h2o_timescale = nan + sdlng_mort_par_timescale = nan + sdlng_mdd_timescale = nan + sdlng2sap_par_timescale = nan photo_tempsens_model = -9 maintresp_model = -9 fates_mortality_disturbance_fraction = nan @@ -292,6 +311,18 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=ED_name_photo_temp_acclim_timescale, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=ED_name_sdlng_emerg_h2o_timescale, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + + call fates_params%RegisterParameter(name=ED_name_sdlng_mort_par_timescale, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + + call fates_params%RegisterParameter(name=ED_name_sdlng_mdd_timescale, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + + call fates_params%RegisterParameter(name=ED_name_sdlng2sap_par_timescale, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=name_photo_tempsens_model,dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -472,6 +503,18 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetreiveParameter(name=ED_name_photo_temp_acclim_timescale, & data=photo_temp_acclim_timescale) + call fates_params%RetreiveParameter(name=ED_name_sdlng_emerg_h2o_timescale, & + data=sdlng_emerg_h2o_timescale) + + call fates_params%RetreiveParameter(name=ED_name_sdlng_mort_par_timescale, & + data=sdlng_mort_par_timescale) + + call fates_params%RetreiveParameter(name=ED_name_sdlng_mdd_timescale, & + data=sdlng_mdd_timescale) + + call fates_params%RetreiveParameter(name=ED_name_sdlng2sap_par_timescale, & + data=sdlng2sap_par_timescale) + call fates_params%RetreiveParameter(name=name_photo_tempsens_model, & data=tmpreal) photo_tempsens_model = nint(tmpreal) @@ -651,6 +694,10 @@ subroutine FatesReportParams(is_master) write(fates_log(),fmt0) 'vai_top_bin_width = ',vai_top_bin_width write(fates_log(),fmt0) 'vai_width_increase_factor = ',vai_width_increase_factor write(fates_log(),fmt0) 'photo_temp_acclim_timescale = ',photo_temp_acclim_timescale + write(fates_log(),fmt0) 'sdlng_emerg_h2o_timescale = ', sdlng_emerg_h2o_timescale + write(fates_log(),fmt0) 'sdlng_mort_par_timescale = ', sdlng_mort_par_timescale + write(fates_log(),fmt0) 'sdlng_mdd_timescale = ', sdlng_mdd_timescale + write(fates_log(),fmt0) 'sdlng2sap_par_timescale = ', sdlng2sap_par_timescale write(fates_log(),fmti) 'hydr_htftype_node = ',hydr_htftype_node write(fates_log(),fmt0) 'fates_mortality_disturbance_fraction = ',fates_mortality_disturbance_fraction write(fates_log(),fmt0) 'ED_val_comp_excln = ',ED_val_comp_excln diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 3783bc4084..18549d27bb 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -429,6 +429,22 @@ module EDTypesMod class(rmean_type), pointer :: seedling_layer_par24 ! 24-hour mean of photosynthetically active radiation ! at the seedling layer (w-m2) + class(rmean_type), pointer :: sdlng_emerg_smp ! Running mean of soil matric potential at the seedling + ! rooting depth at the h2o seedling emergence + ! timescale (see sdlng_emerg_h2o_timescale parameter) + class(rmean_type), pointer :: sdlng_mort_par ! Running mean of photosythetically active radiation + ! at the seedling layer and at the par-based seedling + ! mortality timescale (sdlng_mort_par_timescale) + class(rmean_type), pointer :: sdlng_mdd ! Running mean of moisture deficit days + ! at the seedling layer and at the mdd-based seedling + ! mortality timescale (sdlng_mdd_timescale) + ! (sdlng2sap_par_timescale) + class(rmean_type), pointer :: sdlng2sap_par ! Running mean of photosythetically active radiation + ! at the seedling layer and at the par-based seedling + ! to sapling transition timescale + ! (sdlng2sap_par_timescale) + + ! LEAF ORGANIZATION real(r8) :: pft_agb_profile(maxpft,n_dbh_bins) ! binned above ground biomass, for patch fusion: KgC/m2 real(r8) :: canopy_layer_tlai(nclmax) ! total leaf area index of each canopy layer diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 7230ae606b..c2a6e1375f 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -42,6 +42,9 @@ module FatesInterfaceMod use EDParamsMod , only : bgc_soil_salinity use FatesPlantHydraulicsMod , only : InitHydroGlobals use EDParamsMod , only : photo_temp_acclim_timescale + use EDParamsMod , only : sdlng_emerg_h2o_timescale + use EDParamsMod , only : sdlng_mort_par_timescale + use EDParamsMod , only : sdlng2sap_par_timescale use EDParamsMod , only : ED_val_history_sizeclass_bin_edges use EDParamsMod , only : ED_val_history_ageclass_bin_edges use EDParamsMod , only : ED_val_history_height_bin_edges @@ -74,6 +77,8 @@ module FatesInterfaceMod use PRTAllometricCarbonMod , only : InitPRTGlobalAllometricCarbon use PRTAllometricCNPMod , only : InitPRTGlobalAllometricCNP use FatesRunningMeanMod , only : ema_24hr + use FatesRunningMeanMod , only : ema_sdlng_emerg_h2o, ema_sdlng_mort_par + use FatesRunningMeanMod , only : ema_sdlng_mdd, ema_sdlng2sap_par use FatesRunningMeanMod , only : fixed_24hr use FatesRunningMeanMod , only : ema_lpa use FatesRunningMeanMod , only : moving_ema_window @@ -872,6 +877,20 @@ subroutine SetFatesGlobalElements(use_fates) allocate(ema_lpa) call ema_lpa%define(photo_temp_acclim_timescale*sec_per_day, & hlm_stepsize,moving_ema_window) + allocate(ema_sdlng_emerg_h2o) + call ema_sdlng_emerg_h2o%define(sdlng_emerg_h2o_timescale*sec_per_day, & + hlm_stepsize,moving_ema_window) + allocate(ema_sdlng_mort_par) + call ema_sdlng_mort_par%define(sdlng_mort_par_timescale*sec_per_day, & + hlm_stepsize,moving_ema_window) + !allocate(ema_sdlng_mdd) + !call ema_sdlng_mdd%define(sdlng_mdd_timescale*sec_per_day, & + ! hlm_stepsize,moving_ema_window) + allocate(ema_sdlng2sap_par) + call ema_sdlng2sap_par%define(sdlng2sap_par_timescale*sec_per_day, & + hlm_stepsize,moving_ema_window) + + else ! If we are not using FATES, the cohort dimension is still @@ -1847,6 +1866,14 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) type(ed_cohort_type), pointer :: ccohort integer :: s, ifp, io_si real(r8) :: new_seedling_layer_par !seedling layer par in the current timestep + real(r8) :: new_seedling_layer_smp !seedling layer smp in the current timestep + !real(r8) :: new_seedling_mdd !seedling layer moisture deficit days in the current timestep + + !real(r8), parameter :: seedling_smp_crit = -175912.9_r8 !seedling soil moisture stress + !threshold at which point + !the seedling layer starts accumulating moisture + !deficit days; move to pft-specific param if works + integer :: ilayer_seedling_root !the soil layer at seedling rooting depth integer :: n_leaf !number of leaf layers per canopy layer in patch real(r8) :: lai_sun_frac real(r8) :: lai_shade_frac @@ -1860,7 +1887,8 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) call cpatch%tveg24%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) call cpatch%tveg_lpa%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) - !updating seedling layer par; ahb, August 2021 + !updating seedling layer par, soil matric potential and + !moisture deficit days (mdd) in the seedling layer; ahb, August 2021 !--------------------------------------------------------------------------------------- n_leaf = maxval(cpatch%ncan(cpatch%ncl_p,:)) !calculating the number of leaf layers @@ -1880,8 +1908,25 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) new_seedling_layer_par = & (cpatch%parprof_dir_z(cpatch%ncl_p,n_leaf) * lai_sun_frac) + & (cpatch%parprof_dif_z(cpatch%ncl_p,n_leaf) * (1.0_r8 - lai_sun_frac)) - + call cpatch%seedling_layer_par24%UpdateRMean(new_seedling_layer_par) + call cpatch%sdlng_mort_par%UpdateRMean(new_seedling_layer_par) + call cpatch%sdlng2sap_par%UpdateRMean(new_seedling_layer_par) + + !calculating seedling layer soil matric potential for the current time step + !note: need to make this a pft-specific running mean... + ilayer_seedling_root = minloc(abs(bc_in(s)%z_sisl(:)-EDPftvarcon_inst%seedling_root_depth(1)),dim=1) + new_seedling_layer_smp = bc_in(s)%smp_sl(ilayer_seedling_root) + + !updating the soil matric potential moving averages + call cpatch%sdlng_emerg_smp%UpdateRMean(new_seedling_layer_smp) + + !calculating moisture deficit days in the seedling layer + !new_seedling_mdd = 0.0_r8 + + ! new_seedling_mdd = (abs(seedling_smp_crit) - abs(new_seedling_layer_smp)) * -1.0_r8 + + !--------------------------------------------------------------------------------------- diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 55f46fb5d5..8da2a096cc 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -143,7 +143,13 @@ module FatesRestartInterfaceMod integer :: ir_tveglpa_pa integer :: ir_tveglpa_co integer :: ir_seedling_layer_par24_pa !ahb + integer :: ir_sdlng_emerg_smp_pa !ahb + integer :: ir_sdlng_mort_par_pa ! ahb + integer :: ir_sdlng2sap_par_pa ! ahb + + + integer :: ir_ddbhdt_co integer :: ir_resp_tstep_co integer :: ir_pft_co @@ -1224,7 +1230,19 @@ subroutine define_restart_vars(this, initialize_variables) call this%DefineRMeanRestartVar(vname='fates_seedling_layer_par24',vtype=cohort_r8, & long_name='24-hour seedling layer PAR', & - units='K', initialize=initialize_variables,ivar=ivar, index = ir_seedling_layer_par24_pa) + units='W m2-1', initialize=initialize_variables,ivar=ivar, index = ir_seedling_layer_par24_pa) + + call this%DefineRMeanRestartVar(vname='fates_sdlng_emerg_smp',vtype=cohort_r8, & + long_name='seedling layer PAR on the seedling emergence timescale', & + units='mm suction', initialize=initialize_variables,ivar=ivar, index = ir_sdlng_emerg_smp_pa) + + call this%DefineRMeanRestartVar(vname='fates_sdlng_mort_par',vtype=cohort_r8, & + long_name='seedling layer PAR on the seedling mortality timescale', & + units='W m2-1', initialize=initialize_variables,ivar=ivar, index = ir_sdlng_mort_par_pa) + + call this%DefineRMeanRestartVar(vname='fates_sdlng2sap_par',vtype=cohort_r8, & + long_name='seedling layer PAR on the seedling to sapling transition timescale', & + units='W m2-1', initialize=initialize_variables,ivar=ivar, index = ir_sdlng2sap_par_pa) call this%DefineRMeanRestartVar(vname='fates_tveglpapatch',vtype=cohort_r8, & long_name='running average (EMA) of patch veg temp for photo acclim', & @@ -2035,6 +2053,9 @@ subroutine set_restart_vectors(this,nc,nsites,sites) call this%SetRMeanRestartVar(cpatch%tveg24, ir_tveg24_pa, io_idx_co_1st) call this%SetRMeanRestartVar(cpatch%tveg_lpa, ir_tveglpa_pa, io_idx_co_1st) call this%SetRMeanRestartVar(cpatch%seedling_layer_par24, ir_seedling_layer_par24_pa, io_idx_co_1st) + call this%SetRMeanRestartVar(cpatch%sdlng_emerg_smp, ir_sdlng_emerg_smp_pa,io_idx_co_1st) + call this%SetRMeanRestartVar(cpatch%sdlng_mort_par, ir_sdlng_mort_par_pa,io_idx_co_1st) + call this%SetRMeanRestartVar(cpatch%sdlng2sap_par, ir_sdlng2sap_par_pa,io_idx_co_1st) ! set cohorts per patch for IO rio_ncohort_pa( io_idx_co_1st ) = cohortsperpatch @@ -2822,6 +2843,10 @@ subroutine get_restart_vectors(this, nc, nsites, sites) call this%GetRMeanRestartVar(cpatch%tveg24, ir_tveg24_pa, io_idx_co_1st) call this%GetRMeanRestartVar(cpatch%tveg_lpa, ir_tveglpa_pa, io_idx_co_1st) call this%GetRMeanRestartVar(cpatch%seedling_layer_par24, ir_seedling_layer_par24_pa, io_idx_co_1st) + call this%GetRMeanRestartVar(cpatch%sdlng_emerg_smp, ir_sdlng_emerg_smp_pa,io_idx_co_1st) + call this%GetRMeanRestartVar(cpatch%sdlng_mort_par, ir_sdlng_mort_par_pa,io_idx_co_1st) + call this%GetRMeanRestartVar(cpatch%sdlng2sap_par, ir_sdlng2sap_par_pa,io_idx_co_1st) + ! set cohorts per patch for IO diff --git a/main/FatesRunningMeanMod.F90 b/main/FatesRunningMeanMod.F90 index 600703954a..cd54e3ca25 100644 --- a/main/FatesRunningMeanMod.F90 +++ b/main/FatesRunningMeanMod.F90 @@ -90,10 +90,13 @@ module FatesRunningMeanMod class(rmean_def_type), public, pointer :: ema_24hr ! Exponential moving average - 24hr window class(rmean_def_type), public, pointer :: fixed_24hr ! Fixed, 24-hour window - class(rmean_def_type), public, pointer :: ema_lpa ! Exponential moving average - leaf photo acclimation - class(rmean_def_type), public, pointer :: ema_seedling_mort ! Exponential moving average - ! seedling mort from light - + class(rmean_def_type), public, pointer :: ema_lpa ! Exponential moving average (EMA) - leaf photo acclimation + class(rmean_def_type), public, pointer :: ema_sdlng_emerg_h2o ! EMA for moisture-based seedling emergence + class(rmean_def_type), public, pointer :: ema_sdlng_mort_par ! EMA for seedling mort from light stress + class(rmean_def_type), public, pointer :: ema_sdlng_mdd ! EMA for seedling moisture deficit days + class(rmean_def_type), public, pointer :: ema_sdlng2sap_par ! EMA for seedling to sapling transition rates + ! based in par + contains From 989da81f8dbeb5bd8199a499b78682843d3026f9 Mon Sep 17 00:00:00 2001 From: adamhb Date: Thu, 12 Aug 2021 17:38:03 -0700 Subject: [PATCH 056/852] the running means are working --- biogeochem/EDPatchDynamicsMod.F90 | 65 +++++++++++++--------- biogeochem/EDPhysiologyMod.F90 | 20 ++++--- main/EDTypesMod.F90 | 7 +-- main/FatesInterfaceMod.F90 | 89 ++++++++++++++++++++++--------- main/FatesRestartInterfaceMod.F90 | 24 +++++++-- main/FatesRunningMeanMod.F90 | 5 ++ 6 files changed, 145 insertions(+), 65 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index a5d79c41c0..92cb737bf4 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -86,7 +86,7 @@ module EDPatchDynamicsMod use SFParamsMod, only : SF_VAL_CWD_FRAC use EDParamsMod, only : logging_event_code use EDParamsMod, only : logging_export_frac - use FatesRunningMeanMod, only : ema_24hr, fixed_24hr, ema_lpa + use FatesRunningMeanMod, only : ema_24hr, fixed_24hr, ema_lpa, ema_sdlng_mdd use FatesRunningMeanMod, only : ema_sdlng_emerg_h2o, ema_sdlng_mort_par, ema_sdlng2sap_par ! CIME globals @@ -473,6 +473,7 @@ subroutine spawn_patches( currentSite, bc_in) real(r8) :: patch_site_areadis ! total area disturbed in m2 per patch per day real(r8) :: age ! notional age of this patch in years integer :: el ! element loop index + integer :: pft ! pft loop index integer :: tnull ! is there a tallest cohort? integer :: snull ! is there a shortest cohort? integer :: levcan ! canopy level @@ -680,10 +681,16 @@ subroutine spawn_patches( currentSite, bc_in) call new_patch%tveg24%CopyFromDonor(currentPatch%tveg24) call new_patch%tveg_lpa%CopyFromDonor(currentPatch%tveg_lpa) call new_patch%seedling_layer_par24%CopyFromDonor(currentPatch%seedling_layer_par24) - call new_patch%sdlng_emerg_smp%CopyFromDonor(currentPatch%sdlng_emerg_smp) call new_patch%sdlng_mort_par%CopyFromDonor(currentPatch%sdlng_mort_par) call new_patch%sdlng2sap_par%CopyFromDonor(currentPatch%sdlng2sap_par) + + do pft = 1,maxpft + call new_patch%sdlng_emerg_smp(pft)%p%CopyFromDonor(currentPatch%sdlng_emerg_smp(pft)%p) !ahb + call new_patch%sdlng_mdd(pft)%p%CopyFromDonor(currentPatch%sdlng_mdd(pft)%p) !ahb + enddo + + ! -------------------------------------------------------------------------- ! The newly formed patch from disturbance (new_patch), has now been given ! some litter from dead plants and pre-existing litter from the donor patches. @@ -2010,7 +2017,7 @@ subroutine create_patch(currentSite, new_patch, age, areap, label) real(r8), parameter :: init_seedling_smp = -26652.0_r8 !mean smp (mm) from prior ED2 !simulation at BCI (arbitrary) - + integer :: pft !pft index ! !LOCAL VARIABLES: !--------------------------------------------------------------------- @@ -2031,28 +2038,24 @@ subroutine create_patch(currentSite, new_patch, age, areap, label) call new_patch%tveg24%InitRMean(fixed_24hr,init_value=temp_init_veg,init_offset=real(hlm_current_tod,r8) ) allocate(new_patch%tveg_lpa) call new_patch%tveg_lpa%InitRmean(ema_lpa,init_value=temp_init_veg) - - allocate(new_patch%seedling_layer_par24) - call new_patch%seedling_layer_par24%InitRMean(fixed_24hr,init_value=init_seedling_par,init_offset=real(hlm_current_tod,r8) ) - - allocate(new_patch%sdlng_emerg_smp) - call new_patch%sdlng_emerg_smp%InitRMean(ema_sdlng_emerg_h2o, & - init_value=init_seedling_smp,init_offset=real(hlm_current_tod,r8) ) - + call new_patch%seedling_layer_par24%InitRMean(fixed_24hr,init_value=init_seedling_par, init_offset=real(hlm_current_tod,r8)) allocate(new_patch%sdlng_mort_par) - call new_patch%sdlng_mort_par%InitRMean(ema_sdlng_mort_par, & - init_value=init_seedling_par,init_offset=real(hlm_current_tod,r8) ) - - !allocate(new_patch%sdlng_mdd) - !call new_patch%sdlng_mdd%InitRMean(ema_sdlng_mdd, & - ! init_value=0.0_r8,init_offset=real(hlm_current_tod,r8) ) - + call new_patch%sdlng_mort_par%InitRMean(ema_sdlng_mort_par,init_value=temp_init_veg) allocate(new_patch%sdlng2sap_par) - call new_patch%sdlng2sap_par%InitRMean(ema_sdlng2sap_par, & - init_value=init_seedling_par,init_offset=real(hlm_current_tod,r8) ) - + call new_patch%sdlng2sap_par%InitRMean(ema_sdlng2sap_par,init_value=init_seedling_par) + + allocate(new_patch%sdlng_mdd(maxpft)) + allocate(new_patch%sdlng_emerg_smp(maxpft)) + + do pft = 1,maxpft + allocate(new_patch%sdlng_mdd(pft)%p) + call new_patch%sdlng_mdd(pft)%p%InitRMean(ema_sdlng_mdd, init_value=0.0_r8) + allocate(new_patch%sdlng_emerg_smp(pft)%p) + call new_patch%sdlng_emerg_smp(pft)%p%InitRMean(ema_sdlng_emerg_h2o,init_value=init_seedling_smp) + enddo + ! Litter ! Allocate, Zero Fluxes, and Initialize to "unset" values @@ -2528,7 +2531,7 @@ subroutine fuse_2_patches(csite, dp, rp) type (ed_cohort_type), pointer :: nextc ! Remembers next cohort in list type (ed_cohort_type), pointer :: storesmallcohort type (ed_cohort_type), pointer :: storebigcohort - integer :: c,p !counters for pft and litter size class. + integer :: c,p,pft !counters for pft and litter size class. ahb added pft here. integer :: tnull,snull ! are the tallest and shortest cohorts associated? integer :: el ! loop counting index for elements type(ed_patch_type), pointer :: youngerp ! pointer to the patch younger than donor @@ -2559,7 +2562,12 @@ subroutine fuse_2_patches(csite, dp, rp) call rp%tveg24%FuseRMean(dp%tveg24,rp%area*inv_sum_area) call rp%tveg_lpa%FuseRMean(dp%tveg_lpa,rp%area*inv_sum_area) call rp%seedling_layer_par24%FuseRMean(dp%seedling_layer_par24,rp%area*inv_sum_area) !ahb - call rp%sdlng_emerg_smp%FuseRMean(dp%sdlng_emerg_smp,rp%area*inv_sum_area) !ahb + + do pft = 1,maxpft + call rp%sdlng_emerg_smp(pft)%p%FuseRMean(dp%sdlng_emerg_smp(pft)%p,rp%area*inv_sum_area) !ahb + call rp%sdlng_mdd(pft)%p%FuseRMean(dp%sdlng_mdd(pft)%p,rp%area*inv_sum_area) !ahb + enddo + call rp%sdlng_mort_par%FuseRMean(dp%sdlng_mort_par,rp%area*inv_sum_area) !ahb call rp%sdlng2sap_par%FuseRMean(dp%sdlng2sap_par,rp%area*inv_sum_area) !ahb @@ -2866,7 +2874,7 @@ subroutine dealloc_patch(cpatch) type(ed_cohort_type), pointer :: ccohort ! current type(ed_cohort_type), pointer :: ncohort ! next - integer :: el ! loop counter for elements + integer :: el,pft ! loop counter for elements and pfts ! First Deallocate the cohort space ! ----------------------------------------------------------------------------------- @@ -2905,11 +2913,16 @@ subroutine dealloc_patch(cpatch) deallocate(cpatch%tveg24) deallocate(cpatch%tveg_lpa) deallocate(cpatch%seedling_layer_par24) - deallocate(cpatch%sdlng_emerg_smp) deallocate(cpatch%sdlng_mort_par) - deallocate(cpatch%sdlng_mdd) deallocate(cpatch%sdlng2sap_par) + do pft = 1, maxpft + deallocate(cpatch%sdlng_mdd(pft)%p) + deallocate(cpatch%sdlng_emerg_smp(pft)%p) + enddo + + deallocate(cpatch%sdlng_mdd) + deallocate(cpatch%sdlng_emerg_smp) return end subroutine dealloc_patch diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 11184a9878..50b4da3413 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1618,6 +1618,10 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) real(r8) :: wetness_index ! a soil 'wetness index' calculated from soil matric potential real(r8) :: seedling_layer_par ! photosynthetically active radiation at the seedling layer + real(r8) :: slsmp_emerg + real(r8) :: slparmort + real(r8) :: slpartrans + real(r8) :: photoblastic_germ_modifier ! seedling emergence rate modifier for light-sensitive germination ! used in the moisture-sensitive emergence function real(r8) :: seedling_emerg_rate ! the fraction of the seed bank emerging in the current time step @@ -1650,16 +1654,20 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) !Step 1. calculate the photoblastic germination rate modifier seedling_layer_par = currentPatch%seedling_layer_par24%GetMean() - + !slsmp_emerg = currentPatch%sdlng_emerg_smp%GetMean() + !slparmort = currentPatch%sdlng_mort_par%GetMean() + !slpartrans = currentPatch%sdlng2sap_par%GetMean() + ! write(fates_log(),*) 'nrm parprof', currentPatch%nrmlzd_parprof_dir_z(:,:,:) ! write(fates_log(),*) 'parprof', currentPatch%parprof_dif_z(1,:) ! write(fates_log(),*) 'number_leaf_layers_in_second_canopy_layer', maxval(currentPatch%ncan(currentPatch%ncl_p,:)) - write(fates_log(),*) 'patchno', currentPatch%patchno - write(fates_log(),*) 'seedling_layer_par', seedling_layer_par - write(fates_log(),*) 'seedling_emerg_smp', currentPatch%sdlng_emerg_smp%GetMean() - write(fates_log(),*) 'seedling_mort_par', currentPatch%sdlng_mort_par%GetMean() - write(fates_log(),*) 'seedling2sap_trans_par', currentPatch%sdlng2sap_par%GetMean() + ! write(fates_log(),*) 'patchno', currentPatch%patchno + ! write(fates_log(),*) 'seedling_layer_par', seedling_layer_par + ! write(fates_log(),*) 'seedling_emerg_smp', slsmp_emerg + ! write(fates_log(),*) 'seedling_mort_par', slparmort + ! write(fates_log(),*) 'seedling2sap_trans_par', slpartrans + ! write(fates_log(),*) 'tveg_lpa', currentPatch%tveg_lpa%GetMean() seedling_layer_par = seedling_layer_par * 4.6_r8 !covert to umol s-1 of PAR !1 W/m2 ≈ 4.6 μmole.m2/s diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 18549d27bb..3e426d30fb 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -18,7 +18,7 @@ module EDTypesMod use FatesLitterMod, only : ncwd use FatesConstantsMod, only : n_anthro_disturbance_categories use FatesConstantsMod, only : days_per_year - use FatesRunningMeanMod, only : rmean_type + use FatesRunningMeanMod, only : rmean_type,rmean_arr_type use FatesInterfaceTypesMod,only : bc_in_type use FatesInterfaceTypesMod,only : bc_out_type @@ -429,13 +429,14 @@ module EDTypesMod class(rmean_type), pointer :: seedling_layer_par24 ! 24-hour mean of photosynthetically active radiation ! at the seedling layer (w-m2) - class(rmean_type), pointer :: sdlng_emerg_smp ! Running mean of soil matric potential at the seedling + class(rmean_arr_type), pointer :: sdlng_emerg_smp(:) + ! Running mean of soil matric potential at the seedling ! rooting depth at the h2o seedling emergence ! timescale (see sdlng_emerg_h2o_timescale parameter) class(rmean_type), pointer :: sdlng_mort_par ! Running mean of photosythetically active radiation ! at the seedling layer and at the par-based seedling ! mortality timescale (sdlng_mort_par_timescale) - class(rmean_type), pointer :: sdlng_mdd ! Running mean of moisture deficit days + class(rmean_arr_type), pointer :: sdlng_mdd(:) ! Running mean of moisture deficit days ! at the seedling layer and at the mdd-based seedling ! mortality timescale (sdlng_mdd_timescale) ! (sdlng2sap_par_timescale) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index c2a6e1375f..09dea6fa87 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -45,6 +45,7 @@ module FatesInterfaceMod use EDParamsMod , only : sdlng_emerg_h2o_timescale use EDParamsMod , only : sdlng_mort_par_timescale use EDParamsMod , only : sdlng2sap_par_timescale + use EDParamsMod , only : sdlng_mdd_timescale use EDParamsMod , only : ED_val_history_sizeclass_bin_edges use EDParamsMod , only : ED_val_history_ageclass_bin_edges use EDParamsMod , only : ED_val_history_height_bin_edges @@ -883,12 +884,12 @@ subroutine SetFatesGlobalElements(use_fates) allocate(ema_sdlng_mort_par) call ema_sdlng_mort_par%define(sdlng_mort_par_timescale*sec_per_day, & hlm_stepsize,moving_ema_window) - !allocate(ema_sdlng_mdd) - !call ema_sdlng_mdd%define(sdlng_mdd_timescale*sec_per_day, & - ! hlm_stepsize,moving_ema_window) allocate(ema_sdlng2sap_par) call ema_sdlng2sap_par%define(sdlng2sap_par_timescale*sec_per_day, & hlm_stepsize,moving_ema_window) + allocate(ema_sdlng_mdd) + call ema_sdlng_mdd%define(sdlng_mdd_timescale*sec_per_day, & + hlm_stepsize,moving_ema_window) @@ -1864,19 +1865,20 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) type(ed_patch_type), pointer :: cpatch type(ed_cohort_type), pointer :: ccohort - integer :: s, ifp, io_si - real(r8) :: new_seedling_layer_par !seedling layer par in the current timestep - real(r8) :: new_seedling_layer_smp !seedling layer smp in the current timestep - !real(r8) :: new_seedling_mdd !seedling layer moisture deficit days in the current timestep + integer :: s, ifp, io_si, pft + real(r8) :: new_seedling_layer_par !seedling layer par in the current timestep + real(r8) :: new_seedling_layer_smp(maxpft) !seedling layer smp in the current timestep + real(r8) :: new_seedling_mdd(maxpft) !seedling layer moisture deficit days in the current timestep - !real(r8), parameter :: seedling_smp_crit = -175912.9_r8 !seedling soil moisture stress - !threshold at which point - !the seedling layer starts accumulating moisture - !deficit days; move to pft-specific param if works - integer :: ilayer_seedling_root !the soil layer at seedling rooting depth + real(r8), parameter :: seedling_smp_crit = -175912.9_r8 !seedling soil moisture stress + !threshold at which point + !the seedling layer starts accumulating moisture + !deficit days; move to pft-specific param if works + integer :: ilayer_seedling_root(maxpft) !the soil layer at seedling rooting depth integer :: n_leaf !number of leaf layers per canopy layer in patch real(r8) :: lai_sun_frac real(r8) :: lai_shade_frac + integer,parameter :: ipar = 1 !solar radiation in the shortwave band (i.e. par) do s = 1,size(sites,dim=1) @@ -1899,7 +1901,7 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) lai_sun_frac = sum(cpatch%ed_laisun_z(cpatch%ncl_p,:,n_leaf)) & / ( sum(cpatch%ed_laisun_z(cpatch%ncl_p,:,n_leaf)) + & !summed across pfts sum(cpatch%ed_laisha_z(cpatch%ncl_p,:,n_leaf)) ) !summed across pfts - + lai_shade_frac = 1.0_r8 - lai_sun_frac !calculating seedling layer par for the current time step @@ -1908,25 +1910,62 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) new_seedling_layer_par = & (cpatch%parprof_dir_z(cpatch%ncl_p,n_leaf) * lai_sun_frac) + & (cpatch%parprof_dif_z(cpatch%ncl_p,n_leaf) * (1.0_r8 - lai_sun_frac)) + + ! if there is no lai in the patch (i.e. no vegetation) then the lai_sun_frac + ! and lai_shade frac vars become nan, causing seedling layer par to be nan. + ! which messes up the running means. This say's that if there is no lai, the + ! par at the seedling layer is taken from the ctsm boundary conditions + if (new_seedling_layer_par /= new_seedling_layer_par) then + new_seedling_layer_par = bc_in(s)%solad_parb(ifp,ipar) + bc_in(s)%solai_parb(ifp,ipar) + end if + ! update the par running means call cpatch%seedling_layer_par24%UpdateRMean(new_seedling_layer_par) call cpatch%sdlng_mort_par%UpdateRMean(new_seedling_layer_par) call cpatch%sdlng2sap_par%UpdateRMean(new_seedling_layer_par) - !calculating seedling layer soil matric potential for the current time step - !note: need to make this a pft-specific running mean... - ilayer_seedling_root = minloc(abs(bc_in(s)%z_sisl(:)-EDPftvarcon_inst%seedling_root_depth(1)),dim=1) - new_seedling_layer_smp = bc_in(s)%smp_sl(ilayer_seedling_root) + !write(fates_log(),*) 'patchno', cpatch%patchno + !write(fates_log(),*) 'patcharea', cpatch%area + !write(fates_log(),*) 'laiSun',sum(cpatch%ed_laisun_z(cpatch%ncl_p,:,n_leaf)) + !write(fates_log(),*) 'laiShade',sum(cpatch%ed_laisha_z(cpatch%ncl_p,:,n_leaf)) + !write(fates_log(),*) 'patchlaiSunFrac', lai_sun_frac + !write(fates_log(),*) 'patchlaiShadeFrac', lai_shade_frac + !write(fates_log(),*) 'parprof_dir', cpatch%parprof_dir_z(cpatch%ncl_p,n_leaf) + !write(fates_log(),*) 'parprof_dif', cpatch%parprof_dif_z(cpatch%ncl_p,n_leaf) + !write(fates_log(),*) 'bc_in par d', bc_in(s)%solad_parb(ifp,ipar) + !write(fates_log(),*) 'bc_in par i', bc_in(s)%solad_parb(ifp,ipar) + !write(fates_log(),*) 'new_seedling_layer_par', new_seedling_layer_par + !write(fates_log(),*) 'par24', cpatch%seedling_layer_par24%GetMean() + !write(fates_log(),*) 'parMort', cpatch%sdlng_mort_par%GetMean() + + + do pft = 1,numpft + !calculate the soil moisture at the seedling rooting depth for each pft + + ilayer_seedling_root(pft) = minloc(abs(bc_in(s)%z_sisl(:)-EDPftvarcon_inst%seedling_root_depth(pft)),dim=1) + new_seedling_layer_smp(pft) = bc_in(s)%smp_sl(ilayer_seedling_root(pft)) + + !calculate the new moisture deficit day (mdd) value for each pft + new_seedling_mdd(pft) = (abs(seedling_smp_crit) - abs(new_seedling_layer_smp(pft))) * (-1.0_r8) - !updating the soil matric potential moving averages - call cpatch%sdlng_emerg_smp%UpdateRMean(new_seedling_layer_smp) - - !calculating moisture deficit days in the seedling layer - !new_seedling_mdd = 0.0_r8 + ! if mdds are negative then it means that soil is wetter than smp_crit and the moisture + ! deficit is 0 + if (new_seedling_mdd(pft) < 0.0_r8) then + new_seedling_mdd(pft) = 0.0_r8 + endif + + !update the smp and mdd running means + call cpatch%sdlng_emerg_smp(pft)%p%UpdateRMean(new_seedling_layer_smp(pft)) + call cpatch%sdlng_mdd(pft)%p%UpdateRMean(new_seedling_mdd(pft)) - ! new_seedling_mdd = (abs(seedling_smp_crit) - abs(new_seedling_layer_smp)) * -1.0_r8 - - + + !write(fates_log(),*) 'new_seedling_layer_smp', new_seedling_layer_smp(pft) + !write(fates_log(),*) 'smpEmerg', cpatch%sdlng_emerg_smp(pft)%p%GetMean() + !write(fates_log(),*) 'new_sdling_mdd', new_seedling_mdd(pft) + !write(fates_log(),*) 'sdling_mdd', cpatch%sdlng_mdd(pft)%p%GetMean() + + enddo + !END ahb's changes !--------------------------------------------------------------------------------------- diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 8da2a096cc..b3875e8cc1 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -146,6 +146,7 @@ module FatesRestartInterfaceMod integer :: ir_sdlng_emerg_smp_pa !ahb integer :: ir_sdlng_mort_par_pa ! ahb integer :: ir_sdlng2sap_par_pa ! ahb + integer :: ir_sdlng_mdd_pa ! ahb @@ -1244,6 +1245,10 @@ subroutine define_restart_vars(this, initialize_variables) long_name='seedling layer PAR on the seedling to sapling transition timescale', & units='W m2-1', initialize=initialize_variables,ivar=ivar, index = ir_sdlng2sap_par_pa) + call this%DefineRMeanRestartVar(vname='fates_sdlng_mdd',vtype=cohort_r8, & + long_name='seedling moisture deficit days', & + units='mm days', initialize=initialize_variables,ivar=ivar, index = ir_sdlng_mdd_pa) + call this%DefineRMeanRestartVar(vname='fates_tveglpapatch',vtype=cohort_r8, & long_name='running average (EMA) of patch veg temp for photo acclim', & units='K', initialize=initialize_variables,ivar=ivar, index = ir_tveglpa_pa) @@ -1661,6 +1666,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) use EDTypesMod, only : maxSWb use EDTypesMod, only : numWaterMem use EDTypesMod, only : num_vegtemp_mem + use EDTypesMod, only : maxpft ! Arguments class(fates_restart_interface_type) :: this @@ -2053,10 +2059,14 @@ subroutine set_restart_vectors(this,nc,nsites,sites) call this%SetRMeanRestartVar(cpatch%tveg24, ir_tveg24_pa, io_idx_co_1st) call this%SetRMeanRestartVar(cpatch%tveg_lpa, ir_tveglpa_pa, io_idx_co_1st) call this%SetRMeanRestartVar(cpatch%seedling_layer_par24, ir_seedling_layer_par24_pa, io_idx_co_1st) - call this%SetRMeanRestartVar(cpatch%sdlng_emerg_smp, ir_sdlng_emerg_smp_pa,io_idx_co_1st) call this%SetRMeanRestartVar(cpatch%sdlng_mort_par, ir_sdlng_mort_par_pa,io_idx_co_1st) call this%SetRMeanRestartVar(cpatch%sdlng2sap_par, ir_sdlng2sap_par_pa,io_idx_co_1st) - + + do i_pft = 1, maxpft + call this%SetRMeanRestartVar(cpatch%sdlng_mdd(i_pft)%p, ir_sdlng_mdd_pa,io_idx_co_1st) + call this%SetRMeanRestartVar(cpatch%sdlng_emerg_smp(i_pft)%p, ir_sdlng_emerg_smp_pa,io_idx_co_1st) + enddo + ! set cohorts per patch for IO rio_ncohort_pa( io_idx_co_1st ) = cohortsperpatch @@ -2461,6 +2471,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) use FatesInterfaceTypesMod, only : numpft use FatesInterfaceTypesMod, only : fates_maxElementsPerPatch use EDTypesMod, only : numWaterMem + use EDTypesMod, only : maxpft use EDTypesMod, only : num_vegtemp_mem use FatesSizeAgeTypeIndicesMod, only : get_age_class_index @@ -2478,7 +2489,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) type(ed_cohort_type),pointer :: ccohort ! current cohort type(litter_type), pointer :: litt ! litter object on the current patch ! loop indices - integer :: s, i, j, k + integer :: s, i, j, k, pft ! ---------------------------------------------------------------------------------- ! The following group of integers indicate the positional index (idx) @@ -2843,10 +2854,13 @@ subroutine get_restart_vectors(this, nc, nsites, sites) call this%GetRMeanRestartVar(cpatch%tveg24, ir_tveg24_pa, io_idx_co_1st) call this%GetRMeanRestartVar(cpatch%tveg_lpa, ir_tveglpa_pa, io_idx_co_1st) call this%GetRMeanRestartVar(cpatch%seedling_layer_par24, ir_seedling_layer_par24_pa, io_idx_co_1st) - call this%GetRMeanRestartVar(cpatch%sdlng_emerg_smp, ir_sdlng_emerg_smp_pa,io_idx_co_1st) call this%GetRMeanRestartVar(cpatch%sdlng_mort_par, ir_sdlng_mort_par_pa,io_idx_co_1st) call this%GetRMeanRestartVar(cpatch%sdlng2sap_par, ir_sdlng2sap_par_pa,io_idx_co_1st) - + + do pft = 1, maxpft + call this%GetRMeanRestartVar(cpatch%sdlng_mdd(pft)%p, ir_sdlng_mdd_pa,io_idx_co_1st) + call this%GetRMeanRestartVar(cpatch%sdlng_emerg_smp(pft)%p, ir_sdlng_emerg_smp_pa,io_idx_co_1st) + enddo ! set cohorts per patch for IO diff --git a/main/FatesRunningMeanMod.F90 b/main/FatesRunningMeanMod.F90 index cd54e3ca25..8a7b7a21ea 100644 --- a/main/FatesRunningMeanMod.F90 +++ b/main/FatesRunningMeanMod.F90 @@ -80,6 +80,11 @@ module FatesRunningMeanMod end type rmean_type + type, public :: rmean_arr_type + class(rmean_type), pointer :: p + end type rmean_arr_type + + logical, parameter :: debug = .true. character(len=*), parameter, private :: sourcefile = & From 49b41a0484760d93bedec653f42c363a63b725e9 Mon Sep 17 00:00:00 2001 From: JessicaNeedham Date: Wed, 29 Sep 2021 16:27:04 -0700 Subject: [PATCH 057/852] [ cancel endrun for buggy error check ] [one of the checks in EDPftvarcon is breaking runs with 1 pft. Cancel out the endrun message as a quick fix. ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary:no testing --- main/EDPftvarcon.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index c89e63df98..030f15738f 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1759,7 +1759,7 @@ subroutine FatesCheckParams(is_master) write(fates_log(),*) 'Error is:',sumarea-1.0_r8 write(fates_log(),*) 'and the hlm_pft_map is:', EDPftvarcon_inst%hlm_pft_map(1:npft,hlm_pft) write(fates_log(),*) 'Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) +! call endrun(msg=errMsg(sourcefile, __LINE__)) end if end do !hlm_pft end do !ipft From e68c22ca544518dd921d93ac9fecf6cd75f0bbf0 Mon Sep 17 00:00:00 2001 From: JessicaNeedham Date: Thu, 30 Sep 2021 14:11:27 -0700 Subject: [PATCH 058/852] Squashed commit of all crown damage work --- biogeochem/EDCanopyStructureMod.F90 | 58 +- biogeochem/EDCohortDynamicsMod.F90 | 149 ++- biogeochem/EDLoggingMortalityMod.F90 | 2 +- biogeochem/EDMortalityFunctionsMod.F90 | 148 +-- biogeochem/EDPatchDynamicsMod.F90 | 908 +++++++++++++--- biogeochem/EDPhysiologyMod.F90 | 57 +- biogeochem/FatesAllometryMod.F90 | 169 ++- biogeochem/FatesSoilBGCFluxMod.F90 | 3 +- biogeophys/FatesPlantHydraulicsMod.F90 | 9 +- biogeophys/FatesPlantRespPhotosynthMod.F90 | 35 +- .../parteh/f90src/FatesCohortWrapMod.F90 | 14 +- main/DamageMainMod.F90 | 161 +++ main/EDInitMod.F90 | 95 +- main/EDMainMod.F90 | 215 +++- main/EDParamsMod.F90 | 24 +- main/EDPftvarcon.F90 | 39 +- main/EDTypesMod.F90 | 51 +- main/FatesHistoryInterfaceMod.F90 | 966 +++++++++++++++++- main/FatesHistoryVariableType.F90 | 26 + main/FatesIODimensionsMod.F90 | 21 +- main/FatesIOVariableKindMod.F90 | 4 + main/FatesInterfaceMod.F90 | 89 +- main/FatesInterfaceTypesMod.F90 | 20 +- main/FatesInventoryInitMod.F90 | 27 +- main/FatesParameterDerivedMod.F90 | 94 +- main/FatesParametersInterface.F90 | 1 + main/FatesRestartInterfaceMod.F90 | 338 +++++- main/FatesSizeAgeTypeIndicesMod.F90 | 46 +- parameter_files/fates_params_default.cdl | 32 +- parteh/PRTAllometricCNPMod.F90 | 66 +- parteh/PRTAllometricCarbonMod.F90 | 250 ++++- parteh/PRTGenericMod.F90 | 43 +- parteh/PRTLossFluxesMod.F90 | 84 +- parteh/PRTParametersMod.F90 | 1 + parteh/PRTParamsFATESMod.F90 | 30 +- 35 files changed, 3693 insertions(+), 582 deletions(-) create mode 100644 main/DamageMainMod.F90 diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 08e6c0513f..a7d9f6c8c5 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -381,7 +381,8 @@ subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr,bc_in) currentCohort => currentPatch%shortest do while (associated(currentCohort)) call carea_allom(currentCohort%dbh,currentCohort%n, & - currentSite%spread,currentCohort%pft,currentCohort%c_area) + currentSite%spread,currentCohort%pft,& + currentCohort%crowndamage, currentCohort%c_area) if(debug) then if(currentCohort%c_area<0._r8)then @@ -686,9 +687,10 @@ subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr,bc_in) currentSite%demotion_carbonflux = currentSite%demotion_carbonflux + & (leaf_c + store_c + fnrt_c + sapw_c + struct_c) * currentCohort%n - call carea_allom(copyc%dbh,copyc%n,currentSite%spread,copyc%pft,copyc%c_area) + call carea_allom(copyc%dbh,copyc%n,currentSite%spread,copyc%pft, & + copyc%crowndamage, copyc%c_area) call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread, & - currentCohort%pft,currentCohort%c_area) + currentCohort%pft,currentCohort%crowndamage, currentCohort%c_area) !----------- Insert copy into linked list ------------------------! copyc%shorter => currentCohort @@ -727,7 +729,8 @@ subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr,bc_in) end if call carea_allom(currentCohort%dbh,currentCohort%n, & - currentSite%spread,currentCohort%pft,currentCohort%c_area) + currentSite%spread,currentCohort%pft,& + currentCohort%crowndamage, currentCohort%c_area) endif !canopy layer = i_ly @@ -833,7 +836,7 @@ subroutine PromoteIntoLayer(currentSite,currentPatch,i_lyr) currentCohort%canopy_layer = i_lyr call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread, & - currentCohort%pft,currentCohort%c_area) + currentCohort%pft,currentCohort%crowndamage, currentCohort%c_area) ! keep track of number and biomass of promoted cohort currentSite%promotion_rate(currentCohort%size_class) = & currentSite%promotion_rate(currentCohort%size_class) + currentCohort%n @@ -859,7 +862,7 @@ subroutine PromoteIntoLayer(currentSite,currentPatch,i_lyr) currentCohort => currentPatch%tallest do while (associated(currentCohort)) call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread, & - currentCohort%pft,currentCohort%c_area) + currentCohort%pft,currentCohort%crowndamage, currentCohort%c_area) if(currentCohort%canopy_layer == i_lyr+1)then !look at the cohorts in the canopy layer below... if (ED_val_comp_excln .ge. 0.0_r8 ) then @@ -1126,7 +1129,7 @@ subroutine PromoteIntoLayer(currentSite,currentPatch,i_lyr) newarea = currentCohort%c_area - cc_gain !new area of existing cohort call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread, & - currentCohort%pft,currentCohort%c_area) + currentCohort%pft,currentCohort%crowndamage, currentCohort%c_area) ! number of individuals in promoted cohort. copyc%n = currentCohort%n*cc_gain/currentCohort%c_area @@ -1145,8 +1148,9 @@ subroutine PromoteIntoLayer(currentSite,currentPatch,i_lyr) (leaf_c + fnrt_c + store_c + sapw_c + struct_c) * copyc%n call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread, & - currentCohort%pft,currentCohort%c_area) - call carea_allom(copyc%dbh,copyc%n,currentSite%spread,copyc%pft,copyc%c_area) + currentCohort%pft,currentCohort%crowndamage, currentCohort%c_area) + call carea_allom(copyc%dbh,copyc%n,currentSite%spread,copyc%pft,& + copyc%crowndamage, copyc%c_area) !----------- Insert copy into linked list ------------------------! copyc%shorter => currentCohort @@ -1223,7 +1227,9 @@ subroutine canopy_spread( currentSite ) currentCohort => currentPatch%tallest do while (associated(currentCohort)) call carea_allom(currentCohort%dbh,currentCohort%n, & - currentSite%spread,currentCohort%pft,currentCohort%c_area) + currentSite%spread,currentCohort%pft, & + currentCohort%crowndamage, currentCohort%c_area) + if( ( int(prt_params%woody(currentCohort%pft)) .eq. itrue ) .and. & (currentCohort%canopy_layer .eq. 1 ) ) then sitelevel_canopyarea = sitelevel_canopyarea + currentCohort%c_area @@ -1323,7 +1329,7 @@ subroutine canopy_summarization( nsites, sites, bc_in ) ! Update the cohort's index within the size bin classes ! Update the cohort's index within the SCPF classification system call sizetype_class_index(currentCohort%dbh,currentCohort%pft, & - currentCohort%size_class,currentCohort%size_by_pft_class) + currentCohort%size_class,currentCohort%size_by_pft_class) if (hlm_use_cohort_age_tracking .eq. itrue) then call coagetype_class_index(currentCohort%coage,currentCohort%pft, & @@ -1332,7 +1338,7 @@ subroutine canopy_summarization( nsites, sites, bc_in ) if(hlm_use_sp.eq.ifalse)then call carea_allom(currentCohort%dbh,currentCohort%n,sites(s)%spread,& - currentCohort%pft,currentCohort%c_area) + currentCohort%pft,currentCohort%crowndamage,currentCohort%c_area) endif currentCohort%treelai = tree_lai(leaf_c, & currentCohort%pft, currentCohort%c_area, currentCohort%n, & @@ -1445,7 +1451,7 @@ subroutine leaf_area_profile( currentSite ) ! currentCohort%treesai ! SAI per unit crown area (m2/m2) ! currentCohort%lai ! LAI per unit canopy area (m2/m2) ! currentCohort%sai ! SAI per unit canopy area (m2/m2) - ! currentCohort%NV ! The number of discrete vegetation + ! currentCohort%nv ! The number of discrete vegetation ! ! layers needed to describe this crown ! ! The following patch level diagnostics are updated here: @@ -1471,7 +1477,6 @@ subroutine leaf_area_profile( currentSite ) ! !USES: use EDtypesMod , only : area, dinc_ed, hitemax, n_hite_bins - ! ! !ARGUMENTS type(ed_site_type) , intent(inout) :: currentSite @@ -1498,8 +1503,9 @@ subroutine leaf_area_profile( currentSite ) real(r8) :: min_chite ! bottom of cohort canopy (m) real(r8) :: max_chite ! top of cohort canopy (m) real(r8) :: lai ! summed lai for checking m2 m-2 - real(r8) :: leaf_c ! leaf carbon [kg] - + real(r8) :: snow_depth_avg ! avg snow over whole site + real(r8) :: leaf_c ! leaf carbon [kgC] + real(r8) :: target_c_area ! crown area of undamaged cohort given dbh !---------------------------------------------------------------------- @@ -1554,13 +1560,14 @@ subroutine leaf_area_profile( currentSite ) currentCohort%treelai = tree_lai(leaf_c, currentCohort%pft, currentCohort%c_area, & currentCohort%n, currentCohort%canopy_layer, & currentPatch%canopy_layer_tlai,currentCohort%vcmax25top ) - - if (hlm_use_sp .eq. ifalse) then - currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_trim, & - currentCohort%c_area, currentCohort%n, currentCohort%canopy_layer, & - currentPatch%canopy_layer_tlai, currentCohort%treelai , & - currentCohort%vcmax25top,4) - end if + + if (hlm_use_sp .eq. ifalse) then + currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh,& + currentSite%spread, currentCohort%canopy_trim, & + currentCohort%c_area, currentCohort%n, currentCohort%canopy_layer, & + currentPatch%canopy_layer_tlai, currentCohort%treelai , & + currentCohort%vcmax25top,4) + end if currentCohort%lai = currentCohort%treelai *currentCohort%c_area/currentPatch%total_canopy_area currentCohort%sai = currentCohort%treesai *currentCohort%c_area/currentPatch%total_canopy_area @@ -2164,7 +2171,7 @@ subroutine CanopyLayerArea(currentPatch,site_spread,layer_index,layer_area) currentCohort => currentPatch%tallest do while (associated(currentCohort)) call carea_allom(currentCohort%dbh,currentCohort%n,site_spread, & - currentCohort%pft,currentCohort%c_area) + currentCohort%pft,currentCohort%crowndamage, currentCohort%c_area) if (currentCohort%canopy_layer .eq. layer_index) then layer_area = layer_area + currentCohort%c_area end if @@ -2208,7 +2215,8 @@ function NumPotentialCanopyLayers(currentPatch,site_spread,include_substory) res currentCohort => currentPatch%tallest do while (associated(currentCohort)) if(currentCohort%canopy_layer == z) then - call carea_allom(currentCohort%dbh,currentCohort%n,site_spread,currentCohort%pft,c_area) + call carea_allom(currentCohort%dbh,currentCohort%n,site_spread,& + currentCohort%pft,currentCohort%crowndamage, c_area) arealayer = arealayer + c_area end if currentCohort => currentCohort%shorter diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 2fa98aa59f..10fbf5e879 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -1,4 +1,4 @@ -module EDCohortDynamicsMod +Module EDCohortDynamicsMod ! ! !DESCRIPTION: ! Cohort stuctures in ED. @@ -85,6 +85,9 @@ module EDCohortDynamicsMod use PRTAllometricCarbonMod, only : callom_prt_vartypes use PRTAllometricCarbonMod, only : ac_bc_inout_id_netdc use PRTAllometricCarbonMod, only : ac_bc_in_id_pft + use PRTAllometricCarbonMod, only : ac_bc_inout_id_cdamage + use PRTAllometricCarbonMod, only : ac_bc_in_id_branch_frac + use PRTAllometricCarbonMod, only : ac_bc_inout_id_n use PRTAllometricCarbonMod, only : ac_bc_in_id_ctrim use PRTAllometricCarbonMod, only : ac_bc_inout_id_dbh use PRTAllometricCarbonMod, only : ac_bc_in_id_lstat @@ -122,7 +125,7 @@ module EDCohortDynamicsMod public :: UpdateCohortBioPhysRates public :: DeallocateCohort public :: EvaluateAndCorrectDBH - + logical, parameter :: debug = .false. ! local debug flag character(len=*), parameter, private :: sourcefile = & @@ -140,12 +143,11 @@ module EDCohortDynamicsMod contains !-------------------------------------------------------------------------------------! - - - subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & - prt, laimemory, sapwmemory, structmemory, & - status, recruitstatus,ctrim, carea, clayer, spread, bc_in) + prt, laimemory, sapwmemory, structmemory, & + status, recruitstatus,ctrim,carea, & + clayer, crowndamage,branch_frac, spread, bc_in) + ! ! !DESCRIPTION: ! create new cohort @@ -165,7 +167,9 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & type(ed_patch_type), intent(inout), pointer :: patchptr integer, intent(in) :: pft ! Cohort Plant Functional Type - integer, intent(in) :: clayer ! canopy status of cohort + integer, intent(in) :: crowndamage ! Cohort damage class + real(r8), intent(in) :: branch_frac ! Fraction of biomass in branches + integer, intent(in) :: clayer ! canopy status of cohort ! (1 = canopy, 2 = understorey, etc.) integer, intent(in) :: status ! growth status of plant ! (2 = leaves on , 1 = leaves off) @@ -200,7 +204,7 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & real(r8) :: leaf_c ! total leaf carbon integer :: tnull,snull ! are the tallest and shortest cohorts allocate integer :: nlevrhiz ! number of rhizosphere layers - + !---------------------------------------------------------------------- allocate(new_cohort) @@ -226,6 +230,8 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & new_cohort%patchptr => patchptr new_cohort%pft = pft + new_cohort%crowndamage = crowndamage + new_cohort%branch_frac = branch_frac new_cohort%status_coh = status new_cohort%n = nn new_cohort%hite = hite @@ -266,27 +272,27 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & ! Assign canopy extent and depth if(hlm_use_sp.eq.ifalse)then - call carea_allom(new_cohort%dbh,new_cohort%n,spread,new_cohort%pft,new_cohort%c_area) + call carea_allom(new_cohort%dbh,new_cohort%n,spread,new_cohort%pft, & + new_cohort%crowndamage,new_cohort%c_area) else new_cohort%c_area = carea ! set this from previously precision-controlled value in SP mode endif ! Query PARTEH for the leaf carbon [kg] leaf_c = new_cohort%prt%GetState(leaf_organ,carbon12_element) - new_cohort%treelai = tree_lai(leaf_c, new_cohort%pft, new_cohort%c_area, & new_cohort%n, new_cohort%canopy_layer, & patchptr%canopy_layer_tlai,new_cohort%vcmax25top ) if(hlm_use_sp.eq.ifalse)then - new_cohort%treesai = tree_sai(new_cohort%pft, new_cohort%dbh, new_cohort%canopy_trim, & - new_cohort%c_area, new_cohort%n, new_cohort%canopy_layer, & - patchptr%canopy_layer_tlai, new_cohort%treelai,new_cohort%vcmax25top,2 ) + new_cohort%treesai = tree_sai(new_cohort%pft, new_cohort%dbh, currentSite%spread, & + new_cohort%canopy_trim, & + new_cohort%c_area, new_cohort%n, new_cohort%canopy_layer, & + patchptr%canopy_layer_tlai, new_cohort%treelai,new_cohort%vcmax25top,2 ) end if new_cohort%lai = new_cohort%treelai * new_cohort%c_area/patchptr%area - ! Put cohort at the right place in the linked list storebigcohort => patchptr%tallest storesmallcohort => patchptr%shortest @@ -397,10 +403,13 @@ subroutine InitPRTBoundaryConditions(new_cohort) call new_cohort%prt%RegisterBCInOut(ac_bc_inout_id_dbh,bc_rval = new_cohort%dbh) call new_cohort%prt%RegisterBCInOut(ac_bc_inout_id_netdc,bc_rval = new_cohort%npp_acc) + call new_cohort%prt%RegisterBCInOut(ac_bc_inout_id_n,bc_rval = new_cohort%n) + call new_cohort%prt%RegisterBCInOut(ac_bc_inout_id_cdamage,bc_ival = new_cohort%crowndamage) call new_cohort%prt%RegisterBCIn(ac_bc_in_id_pft,bc_ival = new_cohort%pft) call new_cohort%prt%RegisterBCIn(ac_bc_in_id_ctrim,bc_rval = new_cohort%canopy_trim) call new_cohort%prt%RegisterBCIn(ac_bc_in_id_lstat,bc_ival = new_cohort%status_coh) - + call new_cohort%prt%RegisterBCIn(ac_bc_in_id_branch_frac,bc_rval = new_cohort%branch_frac) + case (prt_cnp_flex_allom_hyp) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_pft,bc_ival = new_cohort%pft) @@ -517,6 +526,7 @@ subroutine nan_cohort(cc_p) ! VEGETATION STRUCTURE currentCohort%pft = fates_unset_int ! pft number + currentCohort%crowndamage = fates_unset_int ! Crown damage class currentCohort%indexnumber = fates_unset_int ! unique number for each cohort. (within clump?) currentCohort%canopy_layer = fates_unset_int ! canopy status of cohort (1 = canopy, 2 = understorey, etc.) currentCohort%canopy_layer_yesterday = nan ! recent canopy status of cohort (1 = canopy, 2 = understorey, etc.) @@ -708,7 +718,9 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_ ! terminates cohorts when they get too small ! ! !USES: - + use FatesInterfaceTypesMod , only : hlm_use_canopy_damage + use FatesInterfaceTypesMod , only : hlm_use_understory_damage + ! ! !ARGUMENTS type (ed_site_type) , intent(inout), target :: currentSite @@ -816,15 +828,41 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_ if(levcan==ican_upper) then currentSite%term_nindivs_canopy(currentCohort%size_class,currentCohort%pft) = & currentSite%term_nindivs_canopy(currentCohort%size_class,currentCohort%pft) + currentCohort%n - currentSite%term_carbonflux_canopy = currentSite%term_carbonflux_canopy + & currentCohort%n * (struct_c+sapw_c+leaf_c+fnrt_c+store_c+repro_c) + + currentSite%term_crownarea_canopy = currentSite%term_crownarea_canopy + & + currentCohort%c_area + else currentSite%term_nindivs_ustory(currentCohort%size_class,currentCohort%pft) = & currentSite%term_nindivs_ustory(currentCohort%size_class,currentCohort%pft) + currentCohort%n - currentSite%term_carbonflux_ustory = currentSite%term_carbonflux_ustory + & currentCohort%n * (struct_c+sapw_c+leaf_c+fnrt_c+store_c+repro_c) + + currentSite%term_crownarea_ustory = currentSite%term_crownarea_ustory + & + currentCohort%c_area + + end if + + if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + if( levcan==ican_upper) then + currentSite%term_nindivs_canopy_damage(currentCohort%crowndamage, & + currentCohort%size_class, currentCohort%pft) = & + currentSite%term_nindivs_canopy_damage(currentCohort%crowndamage,& + currentCohort%size_class, currentCohort%pft) + currentCohort%n + currentSite%term_cflux_canopy_damage(currentCohort%crowndamage, currentCohort%size_class) = & + currentSite%term_cflux_canopy_damage(currentCohort%crowndamage, currentCohort%size_class) + & + currentCohort%n * (struct_c+sapw_c+leaf_c+fnrt_c+store_c+repro_c) + else + currentSite%term_nindivs_ustory_damage(currentCohort%crowndamage,& + currentCohort%size_class, currentCohort%pft) = & + currentSite%term_nindivs_ustory_damage(currentCohort%crowndamage,& + currentCohort%size_class, currentCohort%pft) + currentCohort%n + currentSite%term_cflux_ustory_damage(currentCohort%crowndamage, currentCohort%size_class) = & + currentSite%term_cflux_ustory_damage(currentCohort%crowndamage, currentCohort%size_class) + & + currentCohort%n * (struct_c+sapw_c+leaf_c+fnrt_c+store_c+repro_c) + end if end if ! put the litter from the terminated cohorts @@ -861,7 +899,7 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_ endif currentCohort => tallerCohort enddo - + end subroutine terminate_cohorts ! ===================================================================================== @@ -906,6 +944,7 @@ subroutine SendCohortToLitter(csite,cpatch,ccohort,nplant,bc_in) integer :: el ! loop index for elements integer :: c ! loop index for CWD integer :: pft ! pft index of the cohort + integer :: crowndamage ! the crown damage class of the cohort integer :: sl ! loop index for soil layers integer :: dcmpy ! loop index for decomposability @@ -1011,7 +1050,6 @@ subroutine DeallocateCohort(currentCohort) return end subroutine DeallocateCohort - subroutine fuse_cohorts(currentSite, currentPatch, bc_in) ! @@ -1025,7 +1063,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) use FatesConstantsMod , only : itrue use FatesConstantsMod, only : days_per_year use EDTypesMod , only : maxCohortsPerPatch - + use DamageMainMod, only : get_crown_reduction ! ! !ARGUMENTS type (ed_site_type), intent(inout), target :: currentSite @@ -1055,11 +1093,13 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) real(r8) :: dynamic_age_fusion_tolerance real(r8) :: dbh real(r8) :: leaf_c ! leaf carbon [kg] + real(r8) :: target_c_area integer :: largersc, smallersc, sc_i ! indices for tracking the growth flux caused by fusion real(r8) :: larger_n, smaller_n integer :: oldercacls, youngercacls, cacls_i ! indices for tracking the age flux caused by fusion real(r8) :: older_n, younger_n + real(r8) :: crown_reduction logical, parameter :: fuse_debug = .false. ! This debug is over-verbose ! and gets its own flag @@ -1085,7 +1125,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) !---------------------------------------------------------------------! ! Keep doing this until nocohorts <= maxcohorts ! !---------------------------------------------------------------------! - + if (associated(currentPatch%shortest)) then do while(iterate == 1) @@ -1126,6 +1166,9 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) if (currentCohort%pft == nextc%pft) then + ! check cohorts have same damage class before fusing + if (currentCohort%crowndamage == nextc%crowndamage) then + ! check cohorts in same c. layer. before fusing if (currentCohort%canopy_layer == nextc%canopy_layer) then @@ -1153,6 +1196,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) write(fates_log(),*) 'coage:',currentCohort%coage,nextc%coage write(fates_log(),*) 'dbh:',currentCohort%dbh,nextc%dbh write(fates_log(),*) 'pft:',currentCohort%pft,nextc%pft + write(fates_log(),*) 'crowndamage:',currentCohort%crowndamage,nextc%crowndamage write(fates_log(),*) 'canopy_trim:',currentCohort%canopy_trim,nextc%canopy_trim write(fates_log(),*) 'canopy_layer_yesterday:', & currentCohort%canopy_layer_yesterday,nextc%canopy_layer_yesterday @@ -1230,10 +1274,12 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) call carea_allom(currentCohort%dbh,currentCohort%n, & currentSite%spread,currentCohort%pft,& + currentCohort%crowndamage, & currentCohort%c_area,inverse=.false.) call carea_allom(nextc%dbh,nextc%n, & currentSite%spread,nextc%pft,& + nextc%crowndamage, & nextc%c_area,inverse=.false.) currentCohort%c_area = currentCohort%c_area + nextc%c_area @@ -1241,7 +1287,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) ! dbh = currentCohort%dbh call carea_allom(dbh,newn,currentSite%spread,currentCohort%pft,& - currentCohort%c_area,inverse=.true.) + currentCohort%crowndamage,currentCohort%c_area,inverse=.true.) ! if (abs(dbh-fates_unset_r8) calloc_abs_error ) then - call ForceDBH( ipft, canopy_trim, dbh, hite_out, bdead=struct_c ) - delta_dbh = dbh - currentCohort%dbh + + call ForceDBH( ipft,canopy_trim, dbh, hite_out, bdead=struct_c, & + crowndamage = icrowndamage, branch_frac = branch_frac) + + delta_dbh = dbh - currentCohort%dbh delta_hite = hite_out - currentCohort%hite currentCohort%dbh = dbh currentCohort%hite = hite_out @@ -2077,7 +2142,7 @@ subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) ! Target leaf biomass according to allometry and trimming - call bleaf(dbh,ipft,canopy_trim,target_leaf_c) + call bleaf(dbh,ipft,icrowndamage, canopy_trim,target_leaf_c) if( ( leaf_c - target_leaf_c ) > calloc_abs_error ) then call ForceDBH( ipft, canopy_trim, dbh, hite_out, bl=leaf_c ) @@ -2091,5 +2156,7 @@ subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) return end subroutine EvaluateAndCorrectDBH + !------------------------------------------------------------------------------------ + end module EDCohortDynamicsMod diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index f1f23d9f33..40b9909474 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -789,7 +789,7 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site currentCohort => newPatch%shortest do while(associated(currentCohort)) call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread, & - currentCohort%pft,currentCohort%c_area) + currentCohort%pft,currentCohort%crowndamage,currentCohort%c_area) currentCohort => currentCohort%taller enddo diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index 6eb5ec3097..f930a7a2dd 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -17,6 +17,8 @@ module EDMortalityFunctionsMod use FatesInterfaceTypesMod , only : hlm_use_ed_prescribed_phys use FatesInterfaceTypesMod , only : hlm_freq_day use FatesInterfaceTypesMod , only : hlm_use_planthydro + use FatesInterfaceTypesMod , only : hlm_use_canopy_damage + use FatesInterfaceTypesMod , only : hlm_use_understory_damage use EDLoggingMortalityMod , only : LoggingMortality_frac use EDParamsMod , only : fates_mortality_disturbance_fraction @@ -41,7 +43,7 @@ module EDMortalityFunctionsMod - subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmort ) + subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmort,dgmort ) ! ============================================================================ ! Calculate mortality rates from carbon storage, hydraulic cavitation, @@ -51,6 +53,7 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmor use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm use FatesInterfaceTypesMod , only : hlm_hio_ignore_val use FatesConstantsMod, only : fates_check_param_set + use DamageMainMod, only : get_damage_mortality type (ed_cohort_type), intent(in) :: cohort_in type (bc_in_type), intent(in) :: bc_in @@ -59,11 +62,12 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmor real(r8),intent(out) :: hmort ! hydraulic failure mortality real(r8),intent(out) :: frmort ! freezing stress mortality real(r8),intent(out) :: smort ! size dependent senescence term - real(r8),intent(out) :: asmort ! age dependent senescence term + real(r8),intent(out) :: asmort ! age dependent senescence term + real(r8),intent(out) :: dgmort ! damage dependent mortality integer :: ifp real(r8) :: frac ! relativised stored carbohydrate - real(r8) :: leaf_c_target ! target leaf biomass kgC + real(r8) :: leaf_c ! leaf biomass kgC real(r8) :: store_c real(r8) :: hf_sm_threshold ! hydraulic failure soil moisture threshold real(r8) :: hf_flc_threshold ! hydraulic failure fractional loss of conductivity threshold @@ -82,7 +86,9 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmor logical, parameter :: test_zero_mortality = .false. ! Developer test which ! may help to debug carbon imbalances ! and the like - + + + ! Size Dependent Senescence ! rate (r) and inflection point (ip) define the increase in mortality rate with dbh mort_r_size_senescence = EDPftvarcon_inst%mort_r_size_senescence(cohort_in%pft) @@ -97,9 +103,6 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmor end if ! if param values have been set then calculate asmort - - - mort_r_age_senescence = EDPftvarcon_inst%mort_r_age_senescence(cohort_in%pft) mort_ip_age_senescence = EDPftvarcon_inst%mort_ip_age_senescence(cohort_in%pft) @@ -113,76 +116,82 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmor asmort = 0.0_r8 end if + ! Damage dependent mortality + if (hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + call get_damage_mortality(cohort_in%crowndamage, cohort_in%pft, dgmort) + else + dgmort = 0.0_r8 + end if -if (hlm_use_ed_prescribed_phys .eq. ifalse) then + if (hlm_use_ed_prescribed_phys .eq. ifalse) then + + ! 'Background' mortality (can vary as a function of + ! density as in ED1.0 and ED2.0, but doesn't here for tractability) - ! 'Background' mortality (can vary as a function of - ! density as in ED1.0 and ED2.0, but doesn't here for tractability) - bmort = EDPftvarcon_inst%bmort(cohort_in%pft) - ! Proxy for hydraulic failure induced mortality. - hf_sm_threshold = EDPftvarcon_inst%hf_sm_threshold(cohort_in%pft) - hf_flc_threshold = EDPftvarcon_inst%hf_flc_threshold(cohort_in%pft) - if(hlm_use_planthydro.eq.itrue)then - !note the flc is set as the fraction of max conductivity in hydro - min_fmc_ag = minval(cohort_in%co_hydr%ftc_ag(:)) - min_fmc_tr = cohort_in%co_hydr%ftc_troot - min_fmc_ar = minval(cohort_in%co_hydr%ftc_aroot(:)) - min_fmc = min(min_fmc_ag, min_fmc_tr) - min_fmc = min(min_fmc, min_fmc_ar) - flc = 1.0_r8-min_fmc - if(flc >= hf_flc_threshold .and. hf_flc_threshold < 1.0_r8 )then - hmort = (flc-hf_flc_threshold)/(1.0_r8-hf_flc_threshold) * & - EDPftvarcon_inst%mort_scalar_hydrfailure(cohort_in%pft) - else - hmort = 0.0_r8 - endif - else - if(cohort_in%patchptr%btran_ft(cohort_in%pft) <= hf_sm_threshold)then - hmort = EDPftvarcon_inst%mort_scalar_hydrfailure(cohort_in%pft) - else - hmort = 0.0_r8 - endif - endif - - ! Carbon Starvation induced mortality. - if ( cohort_in%dbh > 0._r8 ) then + ! Proxy for hydraulic failure induced mortality. + hf_sm_threshold = EDPftvarcon_inst%hf_sm_threshold(cohort_in%pft) + hf_flc_threshold = EDPftvarcon_inst%hf_flc_threshold(cohort_in%pft) + if(hlm_use_planthydro.eq.itrue)then + !note the flc is set as the fraction of max conductivity in hydro + min_fmc_ag = minval(cohort_in%co_hydr%ftc_ag(:)) + min_fmc_tr = cohort_in%co_hydr%ftc_troot + min_fmc_ar = minval(cohort_in%co_hydr%ftc_aroot(:)) + min_fmc = min(min_fmc_ag, min_fmc_tr) + min_fmc = min(min_fmc, min_fmc_ar) + flc = 1.0_r8-min_fmc + if(flc >= hf_flc_threshold .and. hf_flc_threshold < 1.0_r8 )then + hmort = (flc-hf_flc_threshold)/(1.0_r8-hf_flc_threshold) * & + EDPftvarcon_inst%mort_scalar_hydrfailure(cohort_in%pft) + else + hmort = 0.0_r8 + endif + else + if(cohort_in%patchptr%btran_ft(cohort_in%pft) <= hf_sm_threshold)then + hmort = EDPftvarcon_inst%mort_scalar_hydrfailure(cohort_in%pft) + else + hmort = 0.0_r8 + endif + endif + + ! Carbon Starvation induced mortality. + if ( cohort_in%dbh > 0._r8 ) then + + call bleaf(cohort_in%dbh,cohort_in%pft,cohort_in%crowndamage,cohort_in%canopy_trim,leaf_c) + store_c = cohort_in%prt%GetState(store_organ,all_carbon_elements) - call bleaf(cohort_in%dbh,cohort_in%pft,cohort_in%canopy_trim,leaf_c_target) - store_c = cohort_in%prt%GetState(store_organ,all_carbon_elements) + call storage_fraction_of_target(leaf_c, store_c, frac) + if( frac .lt. 1._r8) then + cmort = max(0.0_r8,EDPftvarcon_inst%mort_scalar_cstarvation(cohort_in%pft) * & + (1.0_r8 - frac)) + else + cmort = 0.0_r8 + endif - call storage_fraction_of_target(leaf_c_target, store_c, frac) - if( frac .lt. 1._r8) then - cmort = max(0.0_r8,EDPftvarcon_inst%mort_scalar_cstarvation(cohort_in%pft) * & - (1.0_r8 - frac)) else - cmort = 0.0_r8 + write(fates_log(),*) 'dbh problem in mortality_rates', & + cohort_in%dbh,cohort_in%pft,cohort_in%n,cohort_in%canopy_layer endif + !-------------------------------------------------------------------------------- + ! Mortality due to cold and freezing stress (frmort), based on ED2 and: + ! Albani, M.; D. Medvigy; G. C. Hurtt; P. R. Moorcroft, 2006: The contributions + ! of land-use change, CO2 fertilization, and climate variability to the + ! Eastern US carbon sink. Glob. Change Biol., 12, 2370-2390, + ! doi: 10.1111/j.1365-2486.2006.01254.x - else - write(fates_log(),*) 'dbh problem in mortality_rates', & - cohort_in%dbh,cohort_in%pft,cohort_in%n,cohort_in%canopy_layer - endif - !-------------------------------------------------------------------------------- - ! Mortality due to cold and freezing stress (frmort), based on ED2 and: - ! Albani, M.; D. Medvigy; G. C. Hurtt; P. R. Moorcroft, 2006: The contributions - ! of land-use change, CO2 fertilization, and climate variability to the - ! Eastern US carbon sink. Glob. Change Biol., 12, 2370-2390, - ! doi: 10.1111/j.1365-2486.2006.01254.x + ifp = cohort_in%patchptr%patchno + temp_in_C = bc_in%t_veg24_pa(ifp) - tfrz + temp_dep_fraction = max(0.0_r8, min(1.0_r8, 1.0_r8 - (temp_in_C - & + EDPftvarcon_inst%freezetol(cohort_in%pft))/frost_mort_buffer) ) + frmort = EDPftvarcon_inst%mort_scalar_coldstress(cohort_in%pft) * temp_dep_fraction - ifp = cohort_in%patchptr%patchno - temp_in_C = bc_in%t_veg24_pa(ifp) - tfrz - temp_dep_fraction = max(0.0_r8, min(1.0_r8, 1.0_r8 - (temp_in_C - & - EDPftvarcon_inst%freezetol(cohort_in%pft))/frost_mort_buffer) ) - frmort = EDPftvarcon_inst%mort_scalar_coldstress(cohort_in%pft) * temp_dep_fraction + !mortality_rates = bmort + hmort + cmort - !mortality_rates = bmort + hmort + cmort + else ! i.e. hlm_use_ed_prescribed_phys is true - else ! i.e. hlm_use_ed_prescribed_phys is true - if ( cohort_in%canopy_layer .eq. 1) then bmort = EDPftvarcon_inst%prescribed_mortality_canopy(cohort_in%pft) else @@ -200,8 +209,9 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmor bmort = 0.0_r8 smort = 0.0_r8 asmort = 0.0_r8 + dgmort = 0.0_r8 end if - + return end subroutine mortality_rates @@ -232,15 +242,17 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_pr real(r8) :: frmort ! freezing mortality rate (fraction per year) real(r8) :: smort ! size dependent senescence mortality rate (fraction per year) real(r8) :: asmort ! age dependent senescence mortality rate (fraction per year) + real(r8) :: dgmort ! damage mortality (fraction per year) real(r8) :: dndt_logging ! Mortality rate (per day) associated with the a logging event integer :: ipft ! local copy of the pft index - !---------------------------------------------------------------------- + + !---------------------------------------------------------------------- ipft = currentCohort%pft ! Mortality for trees in the understorey. !if trees are in the canopy, then their death is 'disturbance'. This probably needs a different terminology - call mortality_rates(currentCohort,bc_in,cmort,hmort,bmort,frmort,smort, asmort) + call mortality_rates(currentCohort,bc_in,cmort,hmort,bmort,frmort,smort, asmort, dgmort) call LoggingMortality_frac(ipft, currentCohort%dbh, currentCohort%canopy_layer, & currentCohort%lmort_direct, & currentCohort%lmort_collateral, & @@ -264,7 +276,7 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_pr currentCohort%dndt = -1.0_r8 * & - (cmort+hmort+bmort+frmort+smort+asmort + dndt_logging) & + (cmort+hmort+bmort+frmort+smort+asmort+dgmort + dndt_logging) & * currentCohort%n else @@ -273,7 +285,7 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_pr ! Mortality from logging in the canopy is ONLY disturbance generating, don't ! update number densities via non-disturbance inducing death currentCohort%dndt= -(1.0_r8-fates_mortality_disturbance_fraction) & - * (cmort+hmort+bmort+frmort+smort+asmort) * & + * (cmort+hmort+bmort+frmort+smort+asmort+dgmort) * & currentCohort%n endif diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index c08e93565e..0652559ad8 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -5,6 +5,7 @@ module EDPatchDynamicsMod ! ============================================================================ use FatesGlobals , only : fates_log use FatesInterfaceTypesMod , only : hlm_freq_day + use FatesInterfaceTypesMod , only : hlm_days_per_year use EDPftvarcon , only : EDPftvarcon_inst use EDPftvarcon , only : GetDecompyFrac use PRTParametersMod , only : prt_params @@ -58,6 +59,7 @@ module EDPatchDynamicsMod use EDLoggingMortalityMod, only : logging_time use EDLoggingMortalityMod, only : get_harvest_rate_area use EDParamsMod , only : fates_mortality_disturbance_fraction + use DamageMainMod , only : damage_time use FatesAllometryMod , only : carea_allom use FatesAllometryMod , only : set_root_fraction use FatesConstantsMod , only : g_per_kg @@ -131,7 +133,7 @@ module EDPatchDynamicsMod real(r8), parameter :: existing_litt_localization = 1.0_r8 real(r8), parameter :: treefall_localization = 0.0_r8 real(r8), parameter :: burn_localization = 0.0_r8 - + real(r8), parameter :: damage_localization = 0.0_r8 ! 10/30/09: Created by Rosie Fisher ! ============================================================================ @@ -170,7 +172,8 @@ subroutine disturbance_rates( site_in, bc_in) real(r8) :: frmort real(r8) :: smort real(r8) :: asmort - + real(r8) :: dgmort + real(r8) :: lmort_direct real(r8) :: lmort_collateral real(r8) :: lmort_infra @@ -201,11 +204,13 @@ subroutine disturbance_rates( site_in, bc_in) ! Mortality for trees in the understorey. currentCohort%patchptr => currentPatch - call mortality_rates(currentCohort,bc_in,cmort,hmort,bmort,frmort,smort,asmort) - currentCohort%dmort = cmort+hmort+bmort+frmort+smort+asmort + call mortality_rates(currentCohort,bc_in,cmort,hmort,bmort,frmort,smort,asmort,dgmort) + currentCohort%dmort = cmort+hmort+bmort+frmort+smort+asmort+dgmort + call carea_allom(currentCohort%dbh,currentCohort%n,site_in%spread,currentCohort%pft, & - currentCohort%c_area) + currentCohort%crowndamage,currentCohort%c_area) + ! Initialize diagnostic mortality rates currentCohort%cmort = cmort currentCohort%bmort = bmort @@ -213,6 +218,7 @@ subroutine disturbance_rates( site_in, bc_in) currentCohort%frmort = frmort currentCohort%smort = smort currentCohort%asmort = asmort + currentCohort%dgmort = dgmort call LoggingMortality_frac(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_layer, & lmort_direct,lmort_collateral,lmort_infra,l_degrad,& @@ -297,6 +303,8 @@ subroutine disturbance_rates( site_in, bc_in) currentCohort%c_area/currentPatch%area endif + + currentCohort => currentCohort%taller enddo !currentCohort @@ -367,6 +375,7 @@ subroutine disturbance_rates( site_in, bc_in) currentCohort%frmort = currentCohort%frmort*(1.0_r8 - fates_mortality_disturbance_fraction) currentCohort%smort = currentCohort%smort*(1.0_r8 - fates_mortality_disturbance_fraction) currentCohort%asmort = currentCohort%asmort*(1.0_r8 - fates_mortality_disturbance_fraction) + currentCohort%dgmort = currentCohort%dgmort*(1.0_r8 - fates_mortality_disturbance_fraction) end if currentCohort => currentCohort%taller enddo !currentCohort @@ -389,6 +398,7 @@ subroutine disturbance_rates( site_in, bc_in) currentCohort%frmort = currentCohort%frmort*(1.0_r8 - fates_mortality_disturbance_fraction) currentCohort%smort = currentCohort%smort*(1.0_r8 - fates_mortality_disturbance_fraction) currentCohort%asmort = currentCohort%asmort*(1.0_r8 - fates_mortality_disturbance_fraction) + currentCohort%dgmort = currentCohort%dgmort*(1.0_r8 - fates_mortality_disturbance_fraction) currentCohort%lmort_direct = 0.0_r8 currentCohort%lmort_collateral = 0.0_r8 currentCohort%lmort_infra = 0.0_r8 @@ -445,6 +455,7 @@ subroutine spawn_patches( currentSite, bc_in) ! 6) For mortality, Plants in new and existing understorey are killed ! 7) For fire, burned plants are killed, and unburned plants are added to new patch. ! 8) New cohorts are added to new patch and sorted. + ! This includes splitting cohorts within the new patch into different damage classes ! 9) New patch is added into linked list ! 10) Area checked, and patchno recalculated. ! @@ -452,20 +463,32 @@ subroutine spawn_patches( currentSite, bc_in) use EDParamsMod , only : ED_val_understorey_death, logging_coll_under_frac use EDCohortDynamicsMod , only : zero_cohort, copy_cohort, terminate_cohorts + use DamageMainMod , only : get_crown_reduction + use DamageMainMod , only : get_damage_frac + use PRTLossFluxesMod , only : PRTDamageLosses + use PRTGenericMod , only : leaf_organ + use ChecksBalancesMod , only : SiteMassStock + use FatesInterfaceTypesMod, only : hlm_use_canopy_damage + use FatesInterfaceTypesMod, only : hlm_use_understory_damage + use FatesInterfaceTypesMod, only : ncrowndamage + use EDCohortDynamicsMod , only : zero_cohort, copy_cohort, terminate_cohorts use FatesConstantsMod , only : rsnbl_math_prec - ! ! !ARGUMENTS: type (ed_site_type), intent(inout), target :: currentSite type (bc_in_type), intent(in) :: bc_in ! ! !LOCAL VARIABLES: + type(litter_type), pointer :: litt + type(litter_type), pointer :: litt_new + type (ed_patch_type) , pointer :: new_patch type (ed_patch_type) , pointer :: new_patch_primary type (ed_patch_type) , pointer :: new_patch_secondary type (ed_patch_type) , pointer :: currentPatch type (ed_cohort_type), pointer :: currentCohort type (ed_cohort_type), pointer :: nc + type (ed_cohort_type), pointer :: nc_d type (ed_cohort_type), pointer :: storesmallcohort type (ed_cohort_type), pointer :: storebigcohort real(r8) :: site_areadis_primary ! total area disturbed (to primary forest) in m2 per site per day @@ -481,13 +504,41 @@ subroutine spawn_patches( currentSite, bc_in) real(r8) :: sapw_c ! sapwood carbon [kg] real(r8) :: store_c ! storage carbon [kg] real(r8) :: struct_c ! structure carbon [kg] + real(r8) :: repro_c ! reproductive carbon [kg] real(r8) :: total_c ! total carbon of plant [kg] real(r8) :: leaf_burn_frac ! fraction of leaves burned in fire ! for both woody and grass species real(r8) :: leaf_m ! leaf mass during partial burn calculations + + real(r8) :: total_litter_d ! total litter from damage + real(r8) :: patch_damage_litter ! patch level litter from damage + real(r8) :: mass_frac ! mass to remove from damaged cohorts + real(r8) :: leaf_m_pre ! leaf mass pre damage + real(r8) :: leaf_m_post ! leaf mass post damage + real(r8) :: leaf_loss_prt ! leaf mass lost + real(r8) :: sapw_m_pre ! sapw mass pre damage + real(r8) :: sapw_m_post ! sapw mass post damage + real(r8) :: sapw_loss_prt ! sapw mass lost + real(r8) :: struct_m_pre ! struct mass pre damage + real(r8) :: struct_m_post ! struct mass post damage + real(r8) :: struct_loss_prt ! struct mass lost + real(r8) :: store_m_pre ! storage mass pre damage + real(r8) :: store_m_post ! storage mass post damage + real(r8) :: store_loss_prt ! storage mass lost + real(r8) :: cd_n ! number in new damaged cohort + real(r8) :: cd_n_total ! total number damaged + integer :: cd ! crowndamage counter + real(r8) :: cd_frac ! fraction of cohort going to new damage class + real(r8) :: agb_frac ! agoveground biomass fraction of cohort + logical :: found_youngest_primary ! logical for finding the first primary forest patch - !--------------------------------------------------------------------- + real(r8), parameter :: damage_error_fail = 1.0e-6_r8 + + !--------------------------------------------------------------------- + + total_litter_d = 0.0_r8 + storesmallcohort => null() ! storage of the smallest cohort for insertion routine storebigcohort => null() ! storage of the largest cohort for insertion routine @@ -495,8 +546,14 @@ subroutine spawn_patches( currentSite, bc_in) currentPatch => currentSite%youngest_patch site_areadis_primary = 0.0_r8 - site_areadis_secondary = 0.0_r8 + site_areadis_secondary = 0.0_r8 + leaf_loss_prt = 0.0_r8 + sapw_loss_prt = 0.0_r8 + struct_loss_prt = 0.0_r8 + store_loss_prt = 0.0_r8 + patch_damage_litter = 0.0_r8 + ! zero the diagnostic disturbance rate fields currentSite%disturbance_rates_primary_to_primary(1:N_DIST_TYPES) = 0._r8 currentSite%disturbance_rates_primary_to_secondary(1:N_DIST_TYPES) = 0._r8 @@ -556,7 +613,7 @@ subroutine spawn_patches( currentSite, bc_in) ! It is possible that no disturbance area was generated if ( (site_areadis_primary + site_areadis_secondary) > nearzero) then - + age = 0.0_r8 ! create two empty patches, to absorb newly disturbed primary and secondary forest area @@ -571,12 +628,12 @@ subroutine spawn_patches( currentSite, bc_in) ! pools will be populated by looping over the existing patches ! and transfering in mass do el=1,num_elements - call new_patch_primary%litter(el)%InitConditions(init_leaf_fines=0._r8, & - init_root_fines=0._r8, & - init_ag_cwd=0._r8, & - init_bg_cwd=0._r8, & - init_seed=0._r8, & - init_seed_germ=0._r8) + call new_patch_primary%litter(el)%InitConditions(init_leaf_fines=0._r8, & + init_root_fines=0._r8, & + init_ag_cwd=0._r8, & + init_bg_cwd=0._r8, & + init_seed=0._r8, & + init_seed_germ=0._r8) end do new_patch_primary%tallest => null() new_patch_primary%shortest => null() @@ -610,53 +667,52 @@ subroutine spawn_patches( currentSite, bc_in) ! pools to the new patch. We only loop the pre-existing patches, so ! quit the loop if the current patch is either null, or matches the ! two new pointers. - + currentPatch => currentSite%oldest_patch do while(associated(currentPatch)) ! This is the amount of patch area that is disturbed, and donated by the donor patch_site_areadis = currentPatch%area * currentPatch%disturbance_rate - if ( patch_site_areadis > nearzero ) then - ! figure out whether the receiver patch for disturbance from this patch - ! will be primary or secondary land receiver patch is primary forest - ! only if both the donor patch is primary forest and the dominant - ! disturbance type is not logging - if (currentPatch%anthro_disturbance_label .eq. primaryforest .and. & - (currentPatch%disturbance_mode .ne. dtype_ilog)) then - new_patch => new_patch_primary - else - new_patch => new_patch_secondary - endif - - if(.not.associated(new_patch))then - write(fates_log(),*) 'Patch spawning has attempted to point to' - write(fates_log(),*) 'an un-allocated patch' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + ! figure out whether the receiver patch for disturbance from this patch + ! will be primary or secondary land receiver patch is primary forest + ! only if both the donor patch is primary forest and the dominant + ! disturbance type is not logging + if (currentPatch%anthro_disturbance_label .eq. primaryforest .and. & + (currentPatch%disturbance_mode .ne. dtype_ilog)) then + new_patch => new_patch_primary + else + new_patch => new_patch_secondary + endif + + if(.not.associated(new_patch))then + write(fates_log(),*) 'Patch spawning has attempted to point to' + write(fates_log(),*) 'an un-allocated patch' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if ! for the case where the donating patch is secondary forest, if ! the dominant disturbance from this patch is non-anthropogenic, ! we need to average in the time-since-anthropogenic-disturbance ! from the donor patch into that of the receiver patch if ( currentPatch%anthro_disturbance_label .eq. secondaryforest .and. & - (currentPatch%disturbance_mode .ne. dtype_ilog) ) then + (currentPatch%disturbance_mode .ne. dtype_ilog) ) then new_patch%age_since_anthro_disturbance = new_patch%age_since_anthro_disturbance + & currentPatch%age_since_anthro_disturbance * (patch_site_areadis / site_areadis_secondary) endif - - + + ! Transfer the litter existing already in the donor patch to the new patch ! This call will only transfer non-burned litter to new patch ! and burned litter to atmosphere. Thus it is important to zero burnt_frac_litter when ! fire is not the dominant disturbance regime. if(currentPatch%disturbance_mode .ne. dtype_ifire) then - currentPatch%burnt_frac_litter(:) = 0._r8 + currentPatch%burnt_frac_litter(:) = 0._r8 end if call TransLitterNewPatch( currentSite, currentPatch, new_patch, patch_site_areadis) @@ -670,9 +726,23 @@ subroutine spawn_patches( currentSite, bc_in) call fire_litter_fluxes(currentSite, currentPatch, & new_patch, patch_site_areadis,bc_in) else - call mortality_litter_fluxes(currentSite, currentPatch, & + call mortality_litter_fluxes(currentSite, currentPatch,& new_patch, patch_site_areadis,bc_in) - endif + end if + + + + ! and the damaged trees + if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + if( damage_time ) then + + call damage_litter_fluxes(currentSite, currentPatch, & + new_patch, patch_site_areadis, patch_damage_litter) + end if + end if + + ! in kg - for mass conservation checking + total_litter_d = total_litter_d + patch_damage_litter ! -------------------------------------------------------------------------- ! The newly formed patch from disturbance (new_patch), has now been given @@ -680,70 +750,82 @@ subroutine spawn_patches( currentSite, bc_in) ! ! Next, we loop through the cohorts in the donor patch, copy them with ! area modified number density into the new-patch, and apply survivorship. + ! Cohorts in the new patch have to be split into damage and undamaged. ! ------------------------------------------------------------------------- currentCohort => currentPatch%shortest do while(associated(currentCohort)) - - allocate(nc) - if(hlm_use_planthydro.eq.itrue) call InitHydrCohort(CurrentSite,nc) - - ! Initialize the PARTEH object and point to the - ! correct boundary condition fields - nc%prt => null() - call InitPRTObject(nc%prt) - call InitPRTBoundaryConditions(nc) - - call zero_cohort(nc) - ! nc is the new cohort that goes in the disturbed patch (new_patch)... currentCohort - ! is the curent cohort that stays in the donor patch (currentPatch) - call copy_cohort(currentCohort, nc) - !this is the case as the new patch probably doesn't have a closed canopy, and - ! even if it does, that will be sorted out in canopy_structure. - nc%canopy_layer = 1 - nc%canopy_layer_yesterday = 1._r8 - - sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) - struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) - leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) - fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) - store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) - total_c = sapw_c + struct_c + leaf_c + fnrt_c + store_c - - ! treefall mortality is the dominant disturbance - if(currentPatch%disturbance_mode .eq. dtype_ifall) then - - if(currentCohort%canopy_layer == 1)then + agb_frac = prt_params%allom_agb_frac(currentCohort%pft) + + allocate(nc) ! new cohort surviving + if(hlm_use_planthydro.eq.itrue) call InitHydrCohort(CurrentSite,nc) + + ! Initialize the PARTEH object and point to the + ! correct boundary condition fields + nc%prt => null() + + call InitPRTObject(nc%prt) + call InitPRTBoundaryConditions(nc) + call zero_cohort(nc) + + + ! nc is the new cohort that goes in the disturbed patch (new_patch)... currentCohort + ! is the curent cohort that stays in the donor patch (currentPatch) + ! nc_d is the new cohort that goes in the disturbed (new) patch and gets damaged + call copy_cohort(currentCohort, nc) + + !this is the case as the new patch probably doesn't have a closed canopy, and + ! even if it does, that will be sorted out in canopy_structure. + nc%canopy_layer = 1 + nc%canopy_layer_yesterday = 1._r8 + + sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) + struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) + leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) + fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) + store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) + total_c = sapw_c + struct_c + leaf_c + fnrt_c + store_c + + + ! As we loop through disturbances we just focus on nc - surviving trees in new patch + ! After this loop we can alter number densities in nc and nc_d and apply damage + + ! if treefall mortality is the dominant disturbance + if(currentPatch%disturbance_mode .eq. dtype_ifall) then + + ! if canopy + if(currentCohort%canopy_layer == 1)then ! In the donor patch we are left with fewer trees because the area has decreased ! the plant density for large trees does not actually decrease in the donor patch ! because this is the part of the original patch where no trees have actually fallen ! The diagnostic cmort,bmort,hmort, and frmort rates have already been saved - + currentCohort%n = currentCohort%n * (1.0_r8 - fates_mortality_disturbance_fraction * & - min(1.0_r8,currentCohort%dmort * hlm_freq_day)) - + min(1.0_r8,currentCohort%dmort * hlm_freq_day)) + nc%n = 0.0_r8 ! kill all of the trees who caused the disturbance. - + nc%cmort = nan ! The mortality diagnostics are set to nan - ! because the cohort should dissappear + ! because the cohort should dissappear nc%hmort = nan nc%bmort = nan nc%frmort = nan nc%smort = nan nc%asmort = nan + nc%dgmort = nan nc%lmort_direct = nan nc%lmort_collateral = nan nc%lmort_infra = nan nc%l_degrad = nan - + else ! small trees if( int(prt_params%woody(currentCohort%pft)) == itrue)then - - + + ! Survivorship of undestory woody plants. Two step process. ! Step 1: Reduce current number of plants to reflect the ! change in area. @@ -752,7 +834,7 @@ subroutine spawn_patches( currentSite, bc_in) ! are absolute, reduce this number. nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - + ! because the mortality rate due to impact for the cohorts which ! had been in the understory and are now in the newly- ! disturbed patch is very high, passing the imort directly to history @@ -763,17 +845,36 @@ subroutine spawn_patches( currentSite, bc_in) currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) = & currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) + & nc%n * ED_val_understorey_death / hlm_freq_day - - + + currentSite%imort_crownarea = currentSite%imort_crownarea + & + currentCohort%c_area * ED_val_understorey_death / hlm_freq_day + currentSite%imort_carbonflux = currentSite%imort_carbonflux + & (nc%n * ED_val_understorey_death / hlm_freq_day ) * & total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 - + + + if (hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + + currentSite%imort_rate_damage(currentCohort%crowndamage, & + currentCohort%size_class, currentCohort%pft) = & + currentSite%imort_rate_damage(currentCohort%crowndamage,& + currentCohort%size_class, currentCohort%pft) + & + nc%n * ED_val_understorey_death / hlm_freq_day + + currentSite%imort_cflux_damage(currentCohort%crowndamage, currentCohort%size_class) = & + currentSite%imort_cflux_damage(currentCohort%crowndamage, currentCohort%size_class) + & + (nc%n * ED_val_understorey_death / hlm_freq_day ) * & + total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 + + end if + + ! Step 2: Apply survivor ship function based on the understory death fraction ! remaining of understory plants of those that are knocked over ! by the overstorey trees dying... nc%n = nc%n * (1.0_r8 - ED_val_understorey_death) - + ! since the donor patch split and sent a fraction of its members ! to the new patch and a fraction to be preserved in itself, ! when reporting diagnostic rates, we must carry over the mortality rates from @@ -781,96 +882,131 @@ subroutine spawn_patches( currentSite, bc_in) ! for diagnostics. But think of it this way, the rates are weighted by ! number density in EDCLMLink, and the number density of this new patch is donated ! so with the number density must come the effective mortality rates. - + nc%cmort = currentCohort%cmort nc%hmort = currentCohort%hmort nc%bmort = currentCohort%bmort nc%frmort = currentCohort%frmort nc%smort = currentCohort%smort nc%asmort = currentCohort%asmort + nc%dgmort = currentCohort%dgmort nc%dmort = currentCohort%dmort nc%lmort_direct = currentCohort%lmort_direct nc%lmort_collateral = currentCohort%lmort_collateral nc%lmort_infra = currentCohort%lmort_infra - + ! understory trees that might potentially be knocked over in the disturbance. ! The existing (donor) patch should not have any impact mortality, it should ! only lose cohorts due to the decrease in area. This is not mortality. ! Besides, the current and newly created patch sum to unity - + currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - - else + + else ! if not woody ! grass is not killed by mortality disturbance events. Just move it into the new patch area. ! Just split the grass into the existing and new patch structures nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - + ! Those remaining in the existing currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - + nc%cmort = currentCohort%cmort nc%hmort = currentCohort%hmort nc%bmort = currentCohort%bmort nc%frmort = currentCohort%frmort nc%smort = currentCohort%smort nc%asmort = currentCohort%asmort + nc%dgmort = currentCohort%dgmort nc%dmort = currentCohort%dmort nc%lmort_direct = currentCohort%lmort_direct nc%lmort_collateral = currentCohort%lmort_collateral nc%lmort_infra = currentCohort%lmort_infra - + endif - endif - + end if + ! Fire is the dominant disturbance elseif (currentPatch%disturbance_mode .eq. dtype_ifire ) then - + ! Number of members in the new patch, before we impose fire survivorship nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - + ! loss of individuals from source patch due to area shrinking currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - + levcan = currentCohort%canopy_layer - + if(levcan==ican_upper) then - + ! before changing number densities, track total rate of trees that died ! due to fire, as well as from each fire mortality term currentSite%fmort_rate_canopy(currentCohort%size_class, currentCohort%pft) = & currentSite%fmort_rate_canopy(currentCohort%size_class, currentCohort%pft) + & nc%n * currentCohort%fire_mort / hlm_freq_day - + currentSite%fmort_carbonflux_canopy = currentSite%fmort_carbonflux_canopy + & (nc%n * currentCohort%fire_mort) * & total_c * g_per_kg * days_per_sec * ha_per_m2 - + + currentSite%fmort_crownarea_canopy = currentSite%fmort_crownarea_canopy + & + currentCohort%c_area * currentCohort%fire_mort / hlm_freq_day + else currentSite%fmort_rate_ustory(currentCohort%size_class, currentCohort%pft) = & currentSite%fmort_rate_ustory(currentCohort%size_class, currentCohort%pft) + & nc%n * currentCohort%fire_mort / hlm_freq_day - + currentSite%fmort_carbonflux_ustory = currentSite%fmort_carbonflux_ustory + & (nc%n * currentCohort%fire_mort) * & total_c * g_per_kg * days_per_sec * ha_per_m2 + + currentSite%fmort_crownarea_ustory = currentSite%fmort_crownarea_ustory + & + currentCohort%c_area * currentCohort%fire_mort / hlm_freq_day + end if + ! also track fire damage mortality and cflux along size x damage axis + if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + if(levcan==ican_upper) then + currentSite%fmort_rate_canopy_damage(currentCohort%crowndamage, currentCohort%size_class, & + currentCohort%pft) = & + currentSite%fmort_rate_canopy_damage(currentCohort%crowndamage, currentCohort%size_class,& + currentCohort%pft) + nc%n * currentCohort%fire_mort / hlm_freq_day + + currentSite%fmort_cflux_canopy_damage(currentCohort%crowndamage, currentCohort%size_class) = & + currentSite%fmort_cflux_canopy_damage(currentCohort%crowndamage, currentCohort%size_class) + & + (nc%n * currentCohort%fire_mort) * & + total_c * g_per_kg * days_per_sec * ha_per_m2 + else + currentSite%fmort_rate_ustory_damage(currentCohort%crowndamage, currentCohort%size_class, & + currentCohort%pft) = & + currentSite%fmort_rate_ustory_damage(currentCohort%crowndamage, currentCohort%size_class, & + currentCohort%pft) + nc%n * currentCohort%fire_mort / hlm_freq_day + + currentSite%fmort_cflux_ustory_damage(currentCohort%crowndamage, currentCohort%size_class) = & + currentSite%fmort_cflux_ustory_damage(currentCohort%crowndamage, currentCohort%size_class) + & + (nc%n * currentCohort%fire_mort) * & + total_c * g_per_kg * days_per_sec * ha_per_m2 + end if + end if + currentSite%fmort_rate_cambial(currentCohort%size_class, currentCohort%pft) = & currentSite%fmort_rate_cambial(currentCohort%size_class, currentCohort%pft) + & nc%n * currentCohort%cambial_mort / hlm_freq_day currentSite%fmort_rate_crown(currentCohort%size_class, currentCohort%pft) = & currentSite%fmort_rate_crown(currentCohort%size_class, currentCohort%pft) + & nc%n * currentCohort%crownfire_mort / hlm_freq_day - + ! loss of individual from fire in new patch. nc%n = nc%n * (1.0_r8 - currentCohort%fire_mort) - + nc%cmort = currentCohort%cmort nc%hmort = currentCohort%hmort nc%bmort = currentCohort%bmort nc%frmort = currentCohort%frmort nc%smort = currentCohort%smort nc%asmort = currentCohort%asmort + nc%dgmort = currentCohort%dgmort nc%dmort = currentCohort%dmort nc%lmort_direct = currentCohort%lmort_direct nc%lmort_collateral = currentCohort%lmort_collateral @@ -880,37 +1016,37 @@ subroutine spawn_patches( currentSite, bc_in) ! Some of of the leaf mass from living plants has been ! burned off. Here, we remove that mass, and ! tally it in the flux we sent to the atmosphere - + if(int(prt_params%woody(currentCohort%pft)) == itrue)then - leaf_burn_frac = currentCohort%fraction_crown_burned + leaf_burn_frac = currentCohort%fraction_crown_burned else - ! Grasses determine their fraction of leaves burned here + ! Grasses determine their fraction of leaves burned here - leaf_burn_frac = currentPatch%burnt_frac_litter(lg_sf) + leaf_burn_frac = currentPatch%burnt_frac_litter(lg_sf) endif - + ! Perform a check to make sure that spitfire gave ! us reasonable mortality and burn fraction rates - + if( (leaf_burn_frac < 0._r8) .or. & - (leaf_burn_frac > 1._r8) .or. & - (currentCohort%fire_mort < 0._r8) .or. & - (currentCohort%fire_mort > 1._r8)) then - write(fates_log(),*) 'unexpected fire fractions' - write(fates_log(),*) prt_params%woody(currentCohort%pft) - write(fates_log(),*) leaf_burn_frac - write(fates_log(),*) currentCohort%fire_mort - call endrun(msg=errMsg(sourcefile, __LINE__)) + (leaf_burn_frac > 1._r8) .or. & + (currentCohort%fire_mort < 0._r8) .or. & + (currentCohort%fire_mort > 1._r8)) then + write(fates_log(),*) 'unexpected fire fractions' + write(fates_log(),*) prt_params%woody(currentCohort%pft) + write(fates_log(),*) leaf_burn_frac + write(fates_log(),*) currentCohort%fire_mort + call endrun(msg=errMsg(sourcefile, __LINE__)) end if do el = 1,num_elements - leaf_m = nc%prt%GetState(leaf_organ, element_list(el)) + leaf_m = nc%prt%GetState(leaf_organ, element_list(el)) - currentSite%mass_balance(el)%burn_flux_to_atm = & - currentSite%mass_balance(el)%burn_flux_to_atm + & - leaf_burn_frac * leaf_m * nc%n + currentSite%mass_balance(el)%burn_flux_to_atm = & + currentSite%mass_balance(el)%burn_flux_to_atm + & + leaf_burn_frac * leaf_m * nc%n end do ! Here the mass is removed from the plant @@ -919,26 +1055,24 @@ subroutine spawn_patches( currentSite, bc_in) currentCohort%fraction_crown_burned = 0.0_r8 nc%fraction_crown_burned = 0.0_r8 + ! Logging is the dominant disturbance + elseif (currentPatch%disturbance_mode .eq. dtype_ilog ) then - - ! Logging is the dominant disturbance - elseif (currentPatch%disturbance_mode .eq. dtype_ilog ) then - ! If this cohort is in the upper canopy. It generated if(currentCohort%canopy_layer == 1)then - + ! calculate the survivorship of disturbed trees because non-harvested nc%n = currentCohort%n * currentCohort%l_degrad ! nc%n = (currentCohort%l_degrad / (currentCohort%l_degrad + & ! currentCohort%lmort_direct + currentCohort%lmort_collateral + ! currentCohort%lmort_infra) ) * & ! currentCohort%n * patch_site_areadis/currentPatch%area - + ! Reduce counts in the existing/donor patch according to the logging rate currentCohort%n = currentCohort%n * & - (1.0_r8 - min(1.0_r8,(currentCohort%lmort_direct + & - currentCohort%lmort_collateral + & - currentCohort%lmort_infra + currentCohort%l_degrad))) + (1.0_r8 - min(1.0_r8,(currentCohort%lmort_direct + & + currentCohort%lmort_collateral + & + currentCohort%lmort_infra + currentCohort%l_degrad))) nc%cmort = currentCohort%cmort nc%hmort = currentCohort%hmort @@ -946,6 +1080,7 @@ subroutine spawn_patches( currentSite, bc_in) nc%frmort = currentCohort%frmort nc%smort = currentCohort%smort nc%asmort = currentCohort%asmort + nc%dgmort = currentCohort%dgmort nc%dmort = currentCohort%dmort ! since these are the ones that weren't logged, @@ -953,15 +1088,15 @@ subroutine spawn_patches( currentSite, bc_in) nc%lmort_direct = 0._r8 nc%lmort_collateral = 0._r8 nc%lmort_infra = 0._r8 - + else - + ! WHat to do with cohorts in the understory of a logging generated ! disturbance patch? - + if(int(prt_params%woody(currentCohort%pft)) == itrue)then - - + + ! Survivorship of undestory woody plants. Two step process. ! Step 1: Reduce current number of plants to reflect the ! change in area. @@ -969,7 +1104,8 @@ subroutine spawn_patches( currentSite, bc_in) ! but since the patch is smaller ! and cohort counts are absolute, reduce this number. nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - + + ! because the mortality rate due to impact for the cohorts which had ! been in the understory and are now in the newly- ! disturbed patch is very high, passing the imort directly to @@ -981,47 +1117,66 @@ subroutine spawn_patches( currentSite, bc_in) currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) + & nc%n * currentPatch%fract_ldist_not_harvested * & logging_coll_under_frac / hlm_freq_day + + currentSite%imort_crownarea = currentSite%imort_crownarea + & + nc%c_area * currentPatch%fract_ldist_not_harvested * & + logging_coll_under_frac / hlm_freq_day currentSite%imort_carbonflux = currentSite%imort_carbonflux + & (nc%n * currentPatch%fract_ldist_not_harvested * & logging_coll_under_frac/ hlm_freq_day ) * & total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 - - + + if (hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + currentSite%imort_rate_damage(currentCohort%crowndamage,& + currentCohort%size_class, currentCohort%pft) = & + currentSite%imort_rate_damage(currentCohort%crowndamage,& + currentCohort%size_class, currentCohort%pft) + & + nc%n * currentPatch%fract_ldist_not_harvested * & + logging_coll_under_frac / hlm_freq_day + + currentSite%imort_cflux_damage(nc%crowndamage, nc%size_class) = & + currentSite%imort_cflux_damage(nc%crowndamage, nc%size_class) + & + (nc%n * currentPatch%fract_ldist_not_harvested * & + logging_coll_under_frac/ hlm_freq_day ) * & + total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 + end if + ! Step 2: Apply survivor ship function based on the understory death fraction - + ! remaining of understory plants of those that are knocked ! over by the overstorey trees dying... ! LOGGING SURVIVORSHIP OF UNDERSTORY PLANTS IS SET AS A NEW PARAMETER ! in the fatesparameter files nc%n = nc%n * (1.0_r8 - & (1.0_r8-currentPatch%fract_ldist_not_harvested) * logging_coll_under_frac) - + ! Step 3: Reduce the number count of cohorts in the ! original/donor/non-disturbed patch to reflect the area change currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - + nc%cmort = currentCohort%cmort nc%hmort = currentCohort%hmort nc%bmort = currentCohort%bmort nc%frmort = currentCohort%frmort nc%smort = currentCohort%smort nc%asmort = currentCohort%asmort + nc%dgmort = currentCohort%dgmort nc%dmort = currentCohort%dmort nc%lmort_direct = currentCohort%lmort_direct nc%lmort_collateral = currentCohort%lmort_collateral nc%lmort_infra = currentCohort%lmort_infra - - else - + + else ! if not woody + ! grass is not killed by mortality disturbance events. ! Just move it into the new patch area. ! Just split the grass into the existing and new patch structures nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - + ! Those remaining in the existing currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - + ! No grass impact mortality imposed on the newly created patch nc%cmort = currentCohort%cmort nc%hmort = currentCohort%hmort @@ -1029,21 +1184,196 @@ subroutine spawn_patches( currentSite, bc_in) nc%frmort = currentCohort%frmort nc%smort = currentCohort%smort nc%asmort = currentCohort%asmort + nc%dgmort = currentCohort%dgmort nc%dmort = currentCohort%dmort nc%lmort_direct = currentCohort%lmort_direct nc%lmort_collateral = currentCohort%lmort_collateral nc%lmort_infra = currentCohort%lmort_infra - + endif ! is/is-not woody - - endif ! Select canopy layer - - else - write(fates_log(),*) 'unknown disturbance mode?' - write(fates_log(),*) 'disturbance_mode: ',currentPatch%disturbance_mode - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if ! Select disturbance mode + + end if + + else + write(fates_log(),*) 'unknown disturbance mode?' + write(fates_log(),*) 'disturbance_mode: ',currentPatch%disturbance_mode + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if ! Select disturbance mode + + ! Regardless of disturbance type, reduce mass of damaged trees + if(hlm_use_canopy_damage .eq.itrue .or. hlm_use_understory_damage .eq. itrue) then + if(damage_time) then + + ! if woody + if (prt_params%woody(currentCohort%pft)==1 ) then + + if(.not. currentCohort%isnew ) then + + ! to keep track of how much canopy n needs to be reduced by after the loop + cd_n_total = 0.0_r8 + + ! for each damage class find the number density and if big enough allocate a new cohort + do cd = currentCohort%crowndamage+1, ncrowndamage + + call get_damage_frac(currentCohort%crowndamage, cd, currentCohort%pft, cd_frac) + + if(hlm_use_canopy_damage .eq. itrue .and. currentCohort%canopy_layer == 1) then + cd_n = currentCohort%n * cd_frac + else if(hlm_use_understory_damage .eq. itrue .and. currentCohort%canopy_layer > 1) then + cd_n = nc%n * cd_frac + else + cd_n = 0._r8 + end if + + + if(cd_n > nearzero) then + + cd_n_total = cd_n_total + cd_n + + allocate(nc_d) ! new cohort surviving but damaged + if(hlm_use_planthydro.eq.itrue) call InitHydrCohort(CurrentSite,nc_d) + + ! Initialize the PARTEH object and point to the + ! correct boundary condition fields + nc_d%prt => null() + + call InitPRTObject(nc_d%prt) + call InitPRTBoundaryConditions(nc_d) + call zero_cohort(nc_d) + + ! nc_canopy_d is the new cohort that gets damaged + call copy_cohort(currentCohort, nc_d) + + nc_d%canopy_layer = currentCohort%canopy_layer + nc_d%canopy_layer_yesterday = 1._r8 + + ! new number densities - we just do damaged cohort here - + ! undamaged at the end of the cohort loop once we know how many damaged to + ! subtract + + nc_d%n = cd_n + nc_d%crowndamage = cd + + ! update crown area here - for cohort fusion and canopy organisation below + call carea_allom(nc_d%dbh, nc_d%n, currentSite%spread,& + nc_d%pft, nc_d%crowndamage, nc_d%c_area) + + call get_crown_reduction(nc_d%crowndamage, mass_frac) + + + leaf_m_pre = nc_d%prt%GetState(leaf_organ, all_carbon_elements) + & + nc_d%prt%GetState(repro_organ, all_carbon_elements) + call PRTDamageLosses(nc_d%prt, leaf_organ, mass_frac) + call PRTDamageLosses(nc_d%prt, repro_organ, mass_frac) + leaf_m_post = nc_d%prt%GetState(leaf_organ, all_carbon_elements) + & + nc_d%prt%GetState(repro_organ, all_carbon_elements) + + leaf_loss_prt = leaf_loss_prt + (leaf_m_pre - leaf_m_post)* & + nc_d%n + + sapw_m_pre = nc_d%prt%GetState(sapw_organ, all_carbon_elements) + call PRTDamageLosses(nc_d%prt, sapw_organ, mass_frac * & + nc_d%branch_frac * agb_frac) + sapw_m_post = nc_d%prt%GetState(sapw_organ, all_carbon_elements) + sapw_loss_prt = sapw_loss_prt + (sapw_m_pre - sapw_m_post)*nc_d%n + + struct_m_pre = nc_d%prt%GetState(struct_organ, all_carbon_elements) + call PRTDamageLosses(nc_d%prt, struct_organ, mass_frac * & + nc_d%branch_frac * agb_frac) + struct_m_post = nc_d%prt%GetState(struct_organ, all_carbon_elements) + struct_loss_prt = struct_loss_prt + (struct_m_pre - struct_m_post)* & + nc_d%n + + store_m_pre = nc_d%prt%GetState(store_organ, all_carbon_elements) + call PRTDamageLosses(nc_d%prt, store_organ, mass_frac * & + nc_d%branch_frac * agb_frac) + store_m_post = nc_d%prt%GetState(store_organ, all_carbon_elements) + store_loss_prt = store_loss_prt + (store_m_pre - store_m_post)* & + nc_d%n + + fnrt_c = nc_d%prt%GetState(fnrt_organ, all_carbon_elements) + + currentSite%damage_cflux(currentCohort%crowndamage, cd) = & + currentSite%damage_cflux(currentCohort%crowndamage, cd) + & + (leaf_m_post + sapw_m_post + struct_m_post + store_m_post + fnrt_c) * cd_n * & + hlm_days_per_year + + currentSite%damage_rate(currentCohort%crowndamage, cd) = & + currentSite%damage_rate(currentCohort%crowndamage, cd) + cd_n * hlm_days_per_year + + if(hlm_use_canopy_damage .eq. itrue) then + currentSite%crownarea_canopy_damage = currentSite%crownarea_canopy_damage + & + (currentCohort%c_area/currentCohort%n - nc_d%c_area/nc_d%n) * nc_d%n + end if + + if(hlm_use_understory_damage .eq. itrue) then + currentSite%crownarea_ustory_damage = currentSite%crownarea_ustory_damage + & + (currentCohort%c_area/currentCohort%n - nc_d%c_area/nc_d%n) * nc_d%n + end if + + + storebigcohort => currentPatch%tallest + storesmallcohort => currentPatch%shortest + if(associated(currentPatch%tallest))then + tnull = 0 + else + tnull = 1 + currentPatch%tallest => nc_d + nc_d%taller => null() + endif + + if(associated(currentPatch%shortest))then + snull = 0 + else + snull = 1 + currentPatch%shortest => nc_d + nc_d%shorter => null() + endif + + call insert_cohort(nc_d, currentPatch%tallest, currentPatch%shortest, & + tnull, snull, storebigcohort, storesmallcohort) + + currentPatch%tallest => storebigcohort + currentPatch%shortest => storesmallcohort + + end if ! end if new n is large enough + + end do ! end crowndamage loop + + ! Reduce currentCohort%n now based on sum of all new damage classes + currentCohort%n = currentCohort%n - cd_n_total + + end if ! end if not new + end if ! end if canopy and woody + end if ! end if damage time + end if ! end if damage is on + + + if(hlm_use_canopy_damage .eq. itrue .and. currentCohort%canopy_layer == 1 .or.& + hlm_use_understory_damage .eq. itrue .and. currentCohort%canopy_layer > 1) then + + if(.not. currentCohort%isnew) then + + ! Keep track of number and carbon that stayed in the same damage class + sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) + struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) + leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) + fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) + store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) + repro_c = currentCohort%prt%GetState(repro_organ, all_carbon_elements) + + currentSite%damage_cflux(currentCohort%crowndamage, currentCohort%crowndamage) = & + currentSite%damage_cflux(currentCohort%crowndamage, currentCohort%crowndamage) + & + (sapw_c + struct_c + leaf_c + fnrt_c + store_c + repro_c) * currentCohort%n + + currentSite%damage_rate(currentCohort%crowndamage, currentCohort%crowndamage) = & + currentSite%damage_rate(currentCohort%crowndamage, currentCohort%crowndamage) + currentCohort%n + + end if + end if ! end if damage is on + + ! Put new undamaged cohorts in the correct place in the linked list if (nc%n > 0.0_r8) then storebigcohort => new_patch%tallest storesmallcohort => new_patch%shortest @@ -1054,7 +1384,7 @@ subroutine spawn_patches( currentSite, bc_in) new_patch%tallest => nc nc%taller => null() endif - + if(associated(new_patch%shortest))then snull = 0 else @@ -1064,22 +1394,24 @@ subroutine spawn_patches( currentSite, bc_in) endif nc%patchptr => new_patch call insert_cohort(nc, new_patch%tallest, new_patch%shortest, & - tnull, snull, storebigcohort, storesmallcohort) - + tnull, snull, storebigcohort, storesmallcohort) + new_patch%tallest => storebigcohort new_patch%shortest => storesmallcohort else - + ! Get rid of the new temporary cohort call DeallocateCohort(nc) deallocate(nc) - + endif - + currentCohort => currentCohort%taller enddo ! currentCohort - call sort_cohorts(currentPatch) + + call sort_cohorts(currentPatch) + !update area of donor patch currentPatch%area = currentPatch%area - patch_site_areadis @@ -1092,18 +1424,21 @@ subroutine spawn_patches( currentSite, bc_in) call terminate_cohorts(currentSite, currentPatch, 2,16,bc_in) call sort_cohorts(currentPatch) + end if ! if ( new_patch%area > nearzero ) then - + !zero disturbance rate trackers currentPatch%disturbance_rate = 0._r8 currentPatch%disturbance_rates = 0._r8 currentPatch%fract_ldist_not_harvested = 0._r8 - + currentPatch => currentPatch%younger - - enddo ! currentPatch patch loop. - !*************************/ + + enddo ! currentPatch patch loop. + + + !*************************/ !** INSERT NEW PATCH(ES) INTO LINKED LIST !*************************/ @@ -1179,6 +1514,24 @@ subroutine spawn_patches( currentSite, bc_in) call check_patch_area(currentSite) call set_patchno(currentSite) + + ! Stop run if the amount of litter from damage does not match the biomass lost from damaged cohorts + if ( abs(total_litter_d - (leaf_loss_prt + sapw_loss_prt + & + struct_loss_prt + store_loss_prt)) > damage_error_fail ) then + write(fates_log(),*) 'Damage to litter does not match biomass loss' + write(fates_log(),*) 'Damage to litter: ',total_litter_d, & + 'biomass loss: ', (leaf_loss_prt + sapw_loss_prt + struct_loss_prt + store_loss_prt), & + 'error: ',total_litter_d - (leaf_loss_prt + sapw_loss_prt + struct_loss_prt + store_loss_prt) + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + if (damage_time) then + + + write(fates_log(),*) 'Damage to litter: ',total_litter_d + write(fates_log(),*) 'Damage from trees:',leaf_loss_prt+ & + sapw_loss_prt + struct_loss_prt + store_loss_prt + end if return end subroutine spawn_patches @@ -1205,6 +1558,8 @@ subroutine check_patch_area( currentSite ) real(r8) :: seed_stock real(r8) :: litter_stock real(r8) :: mass_gain + real(r8) :: litter_leaf + real(r8) :: live_leaf real(r8), parameter :: area_error_fail = 1.0e-6_r8 !--------------------------------------------------------------------- @@ -1238,8 +1593,7 @@ subroutine check_patch_area( currentSite ) do el = 1,num_elements ! This returns the total mass on the patch for the current area [kg] - call PatchMassStock(largestPatch,el,live_stock,seed_stock,litter_stock) - + call PatchMassStock(largestPatch,el,live_stock,seed_stock,litter_stock) ! Then we scale the total mass by the added area mass_gain = (seed_stock+litter_stock) * & (area_site-areatot)/largestPatch%area @@ -1381,6 +1735,7 @@ subroutine TransLitterNewPatch(currentSite, & curr_litt => currentPatch%litter(el) new_litt => newPatch%litter(el) + ! Distribute the fragmentation litter flux rates. This is only used for diagnostics ! at this point. Litter fragmentation has already been passed to the output ! boundary flux arrays. @@ -1504,6 +1859,7 @@ subroutine TransLitterNewPatch(currentSite, & end do end do + do pft = 1,numpft @@ -1969,7 +2325,6 @@ subroutine mortality_litter_fluxes(currentSite, currentPatch, & flux_diags%leaf_litter_input(pft) = flux_diags%leaf_litter_input(pft) + & num_dead*(leaf_m + repro_m) - flux_diags%root_litter_input(pft) = flux_diags%root_litter_input(pft) + & num_dead * (fnrt_m + store_m*(1.0_r8-EDPftvarcon_inst%allom_frbstor_repro(pft))) @@ -1984,6 +2339,221 @@ subroutine mortality_litter_fluxes(currentSite, currentPatch, & return end subroutine mortality_litter_fluxes + ! ============================================================================ + + subroutine damage_litter_fluxes(currentSite, currentPatch, newPatch,patch_site_areadis, & + total_damage_litter) + ! + ! !DESCRIPTION: + ! + ! !USES: + use DamageMainMod, only : get_crown_reduction + use DamageMainMod , only : get_damage_frac + use SFParamsMod , only : SF_val_cwd_frac + use FatesInterfaceTypesMod , only : ncrowndamage + use EDParamsMod , only : ED_val_understorey_death + use FatesInterfaceTypesMod, only : hlm_use_canopy_damage + use FatesInterfaceTypesMod, only : hlm_use_understory_damage + use FatesConstantsMod, only : itrue + + ! + + ! !ARGUMENTS: + type(ed_site_type) , intent(inout), target :: currentSite + type(ed_patch_type) , intent(inout), target :: currentPatch + type(ed_patch_type) , intent(inout), target :: newPatch + real(r8) , intent(in) :: patch_site_areadis + real(r8), intent(out) :: total_damage_litter + + + ! !LOCAL VARIABLES: + type(ed_cohort_type), pointer :: currentCohort + type(litter_type), pointer :: new_litt + type(litter_type), pointer :: curr_litt + type(site_massbal_type), pointer :: site_mass + type(site_fluxdiags_type), pointer :: flux_diags + + real(r8) :: leaf_donatable_mass ! mass of donatable litter [kg] + real(r8) :: branch_donatable_mass! mass of donatable cwd [kg] + real(r8) :: leaf_m ! leaf mass [kg] + real(r8) :: sapw_m ! sapwood mass [kg] + real(r8) :: struct_m ! structure mass [kg] + real(r8) :: repro_m ! reproductive mass [kg] + real(r8) :: store_m ! storage mass [kg] + real(r8) :: remainder_area ! current patch area after donation [m2] + real(r8) :: retain_frac ! Fraction of mass to be retained + real(r8) :: retain_m2 ! area normalization for litter mass destined to old patch [m-2] + real(r8) :: donate_frac ! Fraction of mass to be donated + real(r8) :: donate_m2 ! area normalization for litter mass destined to new patch [m-2] + integer :: pft ! plant functional type index + integer :: crowndamage ! new increased crown damage class + real(r8) :: crown_reduction ! amount that crown is reduced by (must be same as leaf biomass) + real(r8) :: leaf_loss ! amount of leaf biomass that has been lost + real(r8) :: branch_loss ! amount of branch biomass that has been lost + integer :: dcmpy ! decomposability index + real(r8) :: seed_mass ! Total seed mass generated from storage death [kg] + integer :: c ! coarse woody debris pool index + integer :: el ! element loop index + integer :: sl ! soil layer index + integer :: element_id ! parteh compatible global element index + real(r8) :: dcmpy_frac ! decomposability fraction + real(r8) :: num_trees ! number of trees that were damaged + real(r8) :: num_trees_cd + integer :: cd + real(r8) :: cd_frac + real(r8) :: agb_frac + integer :: ncwd_no_trunk + real(r8), allocatable :: SF_val_CWD_frac_canopy(:) + real(r8) :: cd_n_tot + !--------------------------------------------------------------------- + total_damage_litter = 0.0_r8 + cd_n_tot = 0.0_r8 + ncwd_no_trunk = ncwd - 1 + allocate(SF_val_CWD_frac_canopy(ncwd_no_trunk)) + + ! crown damage is currently not trunks - but we want 100% of + ! damage above to go to litter. We therefore have to + ! renormalise just the first three litter bins + SF_val_CWD_frac_canopy = SF_val_CWD_frac(1:ncwd_no_trunk)/sum(SF_val_CWD_frac(1:ncwd_no_trunk)) + + + ! m2 + remainder_area = currentPatch%area - patch_site_areadis + ! fraction of litter to retain (remain area frac * how much + ! dispersal of litter there is) + retain_frac = (1.0_r8-damage_localization) * & + remainder_area/(newPatch%area+remainder_area) + donate_frac = 1.0_r8-retain_frac + + if(remainder_area > rsnbl_math_prec) then + retain_m2 = retain_frac/remainder_area + donate_m2 = (1.0_r8-retain_frac)/newPatch%area + else + retain_m2 = 0._r8 + donate_m2 = 1._r8/newPatch%area + end if + + + ! loop through elements and spread between retain and donate litter + do el = 1,num_elements + + element_id = element_list(el) + site_mass => currentSite%mass_balance(el) + flux_diags => currentSite%flux_diags(el) + curr_litt => currentPatch%litter(el) ! Litter pool of "current" patch + new_litt => newPatch%litter(el) + + + + currentCohort => currentPatch%shortest + + do while(associated(currentCohort)) + + + agb_frac = prt_params%allom_agb_frac(currentCohort%pft) + pft = currentCohort%pft + ! Get mass in Kg of the element in the specified organ + sapw_m = currentCohort%prt%GetState(sapw_organ, element_id) + struct_m = currentCohort%prt%GetState(struct_organ, element_id) + leaf_m = currentCohort%prt%GetState(leaf_organ, element_id) !kg + repro_m = currentCohort%prt%GetState(repro_organ, element_id) + store_m = currentCohort%prt%GetState(store_organ, element_id) + + if(prt_params%woody(currentCohort%pft)==1) then + + if( hlm_use_canopy_damage .eq.itrue .and. & + currentCohort%canopy_layer ==1 .and. .not. currentCohort%isnew) then + + ! litter is called before damage - so we need to account for mortality here too + num_trees = currentCohort%n * (1.0_r8 - fates_mortality_disturbance_fraction * & + min(1.0_r8, currentCohort%dmort* hlm_freq_day)) + + else if( hlm_use_understory_damage .eq.itrue .and. & + currentCohort%canopy_layer > 1 .and. .not. currentCohort%isnew) then + + ! for trees in new patch to be damaged + num_trees = currentCohort%n * (patch_site_areadis/currentPatch%area) * & + (1.0_r8 - ED_val_understorey_death) + + else + num_trees = 0._r8 + end if + + + + do cd = currentCohort%crowndamage+1, ncrowndamage + + call get_damage_frac(currentCohort%crowndamage, cd, currentCohort%pft, cd_frac) + + ! now to get the number of damaged trees we multiply by damage frac + num_trees_cd = num_trees * cd_frac + + cd_n_tot = cd_n_tot + num_trees_cd + + ! if non negligable get litter + if (num_trees_cd > nearzero ) then + + call get_crown_reduction(cd, crown_reduction) + + + ! leaf loss in kg + leaf_loss = (leaf_m + repro_m) * crown_reduction + leaf_donatable_mass = num_trees_cd * leaf_loss + + do dcmpy=1,ndcmpy + dcmpy_frac = GetDecompyFrac(pft,leaf_organ,dcmpy) + + new_litt%leaf_fines(dcmpy) = new_litt%leaf_fines(dcmpy) + & + leaf_donatable_mass*donate_m2*dcmpy_frac ! kg per m2 + curr_litt%leaf_fines(dcmpy) = curr_litt%leaf_fines(dcmpy) + & + leaf_donatable_mass*retain_m2*dcmpy_frac ! kg per m2 + end do + + flux_diags%leaf_litter_input(pft) = flux_diags%leaf_litter_input(pft) + & + leaf_donatable_mass + + ! branch loss + branch_loss = (sapw_m + struct_m + store_m) * crown_reduction * & + currentCohort%branch_frac * agb_frac * num_trees_cd + + do c=1,(ncwd_no_trunk) + + branch_donatable_mass = branch_loss * SF_val_CWD_frac_canopy(c) + + ! Transfer wood of dying trees to AG CWD pools + new_litt%ag_cwd(c) = new_litt%ag_cwd(c) + branch_donatable_mass * donate_m2 + + curr_litt%ag_cwd(c) = curr_litt%ag_cwd(c) + branch_donatable_mass * retain_m2 + + flux_diags%cwd_ag_input(c) = & + flux_diags%cwd_ag_input(c) + branch_donatable_mass + + end do + + ! should match leaf damage that is printed after PRTDamageLosses is called + total_damage_litter = total_damage_litter + leaf_donatable_mass + & + branch_loss + + end if ! end if non-negligable + end do ! end crown damage loop + + end if ! end if woody + + + + currentCohort => currentCohort%taller + + + enddo !currentCohort + + enddo ! end element + + return + end subroutine damage_litter_fluxes + + + + ! ============================================================================ subroutine create_patch(currentSite, new_patch, age, areap, label,nocomp_pft) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 859f6e3534..218b55e3f1 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -427,6 +427,7 @@ subroutine trim_canopy( currentSite ) real(r8) :: initial_laimem ! Initial laimemory real(r8) :: optimum_laimem ! Optimum laimemory + real(r8) :: target_c_area !---------------------------------------------------------------------- ipatch = 1 ! Start counting patches @@ -458,18 +459,25 @@ subroutine trim_canopy( currentSite ) trimmed = .false. ipft = currentCohort%pft - call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread,currentCohort%pft,currentCohort%c_area) + call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread,currentCohort%pft,& + currentCohort%crowndamage, currentCohort%c_area) + leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) currentCohort%treelai = tree_lai(leaf_c, currentCohort%pft, currentCohort%c_area, & currentCohort%n, currentCohort%canopy_layer, & currentPatch%canopy_layer_tlai,currentCohort%vcmax25top ) - currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_trim, & - currentCohort%c_area, currentCohort%n, currentCohort%canopy_layer, & + call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread,currentCohort%pft,& + 1, target_c_area) + + currentCohort%treesai = tree_sai(currentCohort%pft, & + currentCohort%dbh, & + currentSite%spread, currentCohort%canopy_trim, & + target_c_area, currentCohort%n,currentCohort%canopy_layer,& currentPatch%canopy_layer_tlai, currentCohort%treelai, & - currentCohort%vcmax25top,0 ) + currentCohort%vcmax25top,0 ) currentCohort%nv = ceiling((currentCohort%treelai+currentCohort%treesai)/dinc_ed) @@ -480,7 +488,8 @@ subroutine trim_canopy( currentSite ) call endrun(msg=errMsg(sourcefile, __LINE__)) endif - call bleaf(currentcohort%dbh,ipft,currentcohort%canopy_trim,tar_bl) + call bleaf(currentcohort%dbh,ipft,& + currentCohort%crowndamage, currentcohort%canopy_trim,tar_bl) if ( int(prt_params%allom_fmode(ipft)) .eq. 1 ) then ! only query fine root biomass if using a fine root allometric model that takes leaf trim into account @@ -1504,7 +1513,8 @@ subroutine assign_cohort_SP_properties(currentCohort,htop,tlai,tsai,parea,init,l spread = 1.0_r8 ! fix this to 0 to remove dynamics of canopy closure, assuming a closed canopy. ! n.b. the value of this will only affect 'n', which isn't/shouldn't be a diagnostic in ! SP mode. - call carea_allom(currentCohort%dbh,dummy_n,spread,currentCohort%pft,currentCohort%c_area) + call carea_allom(currentCohort%dbh,dummy_n,spread,currentCohort%pft,& + currentCohort%crowndamage,currentCohort%c_area) !------------------------------------------ ! Calculate canopy N assuming patch area is full @@ -1512,7 +1522,8 @@ subroutine assign_cohort_SP_properties(currentCohort,htop,tlai,tsai,parea,init,l currentCohort%n = parea / currentCohort%c_area ! correct c_area for the new nplant - call carea_allom(currentCohort%dbh,currentCohort%n,spread,currentCohort%pft,currentCohort%c_area) + call carea_allom(currentCohort%dbh,currentCohort%n,spread,currentCohort%pft,& + currentCohort%crowndamage,currentCohort%c_area) ! ------------------------------------------ ! Calculate leaf carbon from target treelai @@ -1808,6 +1819,8 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) ! ! !USES: use FatesInterfaceTypesMod, only : hlm_use_ed_prescribed_phys + use FatesLitterMod , only : ncwd + use SFParamsMod , only : SF_val_CWD_frac ! ! !ARGUMENTS type(ed_site_type), intent(inout), target :: currentSite @@ -1817,6 +1830,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) ! !LOCAL VARIABLES: class(prt_vartypes), pointer :: prt integer :: ft + integer :: c type (ed_cohort_type) , pointer :: temp_cohort type (litter_type), pointer :: litt ! The litter object (carbon right now) type(site_massbal_type), pointer :: site_mass ! For accounting total in-out mass fluxes @@ -1824,6 +1838,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) integer :: el ! loop counter for element integer :: element_id ! element index consistent with definitions in PRTGenericMod integer :: iage ! age loop counter for leaf age bins + integer :: crowndamage integer,parameter :: recruitstatus = 1 !weather it the new created cohorts is recruited or initialized real(r8) :: c_leaf ! target leaf biomass [kgC] real(r8) :: c_fnrt ! target fine root biomass [kgC] @@ -1854,7 +1869,8 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) do ft = 1,numpft if(currentSite%use_this_pft(ft).eq.itrue)then - temp_cohort%canopy_trim = init_recruit_trim + temp_cohort%canopy_trim = init_recruit_trim + temp_cohort%crowndamage = 1 ! new recruits are undamaged temp_cohort%pft = ft temp_cohort%hite = EDPftvarcon_inst%hgt_min(ft) temp_cohort%coage = 0.0_r8 @@ -1862,14 +1878,23 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) call h2d_allom(temp_cohort%hite,ft,temp_cohort%dbh) + temp_cohort%branch_frac = 0.0_r8 + do c = 1, (ncwd-1) + temp_cohort%branch_frac = temp_cohort%branch_frac + & + SF_val_CWD_frac(c) + end do + ! Initialize live pools - call bleaf(temp_cohort%dbh,ft,temp_cohort%canopy_trim,c_leaf) + call bleaf(temp_cohort%dbh,ft,temp_cohort%crowndamage,& + temp_cohort%canopy_trim,c_leaf) call bfineroot(temp_cohort%dbh,ft,temp_cohort%canopy_trim,c_fnrt) - call bsap_allom(temp_cohort%dbh,ft,temp_cohort%canopy_trim,a_sapw, c_sapw) - call bagw_allom(temp_cohort%dbh,ft,c_agw) + call bsap_allom(temp_cohort%dbh,ft,temp_cohort%crowndamage, temp_cohort%branch_frac, & + temp_cohort%canopy_trim,a_sapw, c_sapw) + call bagw_allom(temp_cohort%dbh,ft,temp_cohort%crowndamage, temp_cohort%branch_frac, c_agw) call bbgw_allom(temp_cohort%dbh,ft,c_bgw) call bdead_allom(c_agw,c_bgw,c_sapw,ft,c_struct) - call bstore_allom(temp_cohort%dbh,ft,temp_cohort%canopy_trim,c_store) + call bstore_allom(temp_cohort%dbh,ft, temp_cohort%crowndamage, & + temp_cohort%canopy_trim,c_store) ! Default assumption is that leaves are on cohortstatus = leaves_on @@ -2084,12 +2109,14 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) call prt%CheckInitialConditions() ! This initializes the cohort - call create_cohort(currentSite,currentPatch, temp_cohort%pft, temp_cohort%n, & - temp_cohort%hite, temp_cohort%coage, temp_cohort%dbh, prt, & + call create_cohort(currentSite,currentPatch, temp_cohort%pft, temp_cohort%n, & + temp_cohort%hite,temp_cohort%coage, temp_cohort%dbh, prt, & temp_cohort%laimemory, temp_cohort%sapwmemory, temp_cohort%structmemory, & cohortstatus, recruitstatus, & temp_cohort%canopy_trim,temp_cohort%c_area, & - currentPatch%NCL_p, currentSite%spread, bc_in) + currentPatch%NCL_p, & + temp_cohort%crowndamage, temp_cohort%branch_frac, & + currentSite%spread, bc_in) ! Note that if hydraulics is on, the number of cohorts may had ! changed due to hydraulic constraints. diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index e47934715d..d94b5d4adb 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -97,7 +97,7 @@ module FatesAllometryMod use FatesGlobals , only : endrun => fates_endrun use EDTypesMod , only : nlevleaf, dinc_ed use EDTypesMod , only : nclmax - + use DamageMainMod , only : get_crown_reduction implicit none @@ -157,8 +157,8 @@ module FatesAllometryMod ! ============================================================================ - subroutine CheckIntegratedAllometries(dbh,ipft,canopy_trim, & - bl,bfr,bsap,bstore,bdead, & + subroutine CheckIntegratedAllometries(dbh,ipft,crowndamage, branch_frac, & + canopy_trim, bl,bfr,bsap,bstore,bdead, & grow_leaf, grow_fr, grow_sap, grow_store, grow_dead, & max_err, l_pass) @@ -172,6 +172,8 @@ subroutine CheckIntegratedAllometries(dbh,ipft,canopy_trim, & real(r8),intent(in) :: dbh ! diameter of plant [cm] integer,intent(in) :: ipft ! plant functional type index + integer,intent(in) :: crowndamage + real(r8),intent(in) :: branch_frac real(r8),intent(in) :: canopy_trim ! trimming function real(r8),intent(in) :: bl ! integrated leaf biomass [kgC] real(r8),intent(in) :: bfr ! integrated fine root biomass [kgC] @@ -202,7 +204,7 @@ subroutine CheckIntegratedAllometries(dbh,ipft,canopy_trim, & l_pass = .true. ! Default assumption is that step passed if (grow_leaf) then - call bleaf(dbh,ipft,canopy_trim,bl_diag) + call bleaf(dbh,ipft,crowndamage, canopy_trim,bl_diag) if( abs(bl_diag-bl) > max_err ) then if(verbose_logging) then write(fates_log(),*) 'disparity in integrated/diagnosed leaf carbon' @@ -230,7 +232,7 @@ subroutine CheckIntegratedAllometries(dbh,ipft,canopy_trim, & end if if (grow_sap) then - call bsap_allom(dbh,ipft,canopy_trim,asap_diag,bsap_diag) + call bsap_allom(dbh,ipft,crowndamage, branch_frac, canopy_trim,asap_diag,bsap_diag) if( abs(bsap_diag-bsap) > max_err ) then if(verbose_logging) then write(fates_log(),*) 'disparity in integrated/diagnosed sapwood carbon' @@ -244,7 +246,7 @@ subroutine CheckIntegratedAllometries(dbh,ipft,canopy_trim, & end if if (grow_store) then - call bstore_allom(dbh,ipft,canopy_trim,bstore_diag) + call bstore_allom(dbh,ipft,crowndamage, canopy_trim,bstore_diag) if( abs(bstore_diag-bstore) > max_err ) then if(verbose_logging) then write(fates_log(),*) 'disparity in integrated/diagnosed storage carbon' @@ -258,8 +260,8 @@ subroutine CheckIntegratedAllometries(dbh,ipft,canopy_trim, & end if if (grow_dead) then - call bsap_allom(dbh,ipft,canopy_trim,asap_diag,bsap_diag) - call bagw_allom(dbh,ipft,bagw_diag) + call bsap_allom(dbh,ipft,crowndamage, branch_frac, canopy_trim,asap_diag,bsap_diag) + call bagw_allom(dbh,ipft,crowndamage, branch_frac, bagw_diag) call bbgw_allom(dbh,ipft,bbgw_diag) call bdead_allom( bagw_diag, bbgw_diag, bsap_diag, ipft, bdead_diag ) if( abs(bdead_diag-bdead) > max_err ) then @@ -359,16 +361,20 @@ end subroutine h_allom ! Generic AGB interface ! ============================================================================ - subroutine bagw_allom(d,ipft,bagw,dbagwdd) + subroutine bagw_allom(d,ipft,crowndamage, branch_frac, bagw,dbagwdd) + use DamageMainMod, only : get_crown_reduction real(r8),intent(in) :: d ! plant diameter [cm] integer(i4),intent(in) :: ipft ! PFT index + integer(i4),intent(in) :: crowndamage + real(r8),intent(in) :: branch_frac real(r8),intent(out) :: bagw ! biomass above ground woody tissues real(r8),intent(out),optional :: dbagwdd ! change in agbw per diameter [kgC/cm] real(r8) :: h ! height real(r8) :: dhdd ! change in height wrt d + real(r8) :: crown_reduction associate( p1 => prt_params%allom_agb1(ipft), & p2 => prt_params%allom_agb2(ipft), & @@ -395,6 +401,15 @@ subroutine bagw_allom(d,ipft,bagw,dbagwdd) call endrun(msg=errMsg(sourcefile, __LINE__)) end select + if(crowndamage > 1) then + call get_crown_reduction(crowndamage, crown_reduction) + bagw = bagw - (bagw * branch_frac * crown_reduction) + if(present(dbagwdd))then + dbagwdd = dbagwdd - (dbagwdd * branch_frac * crown_reduction) + end if + end if + + end associate return end subroutine bagw_allom @@ -439,12 +454,13 @@ end subroutine blmax_allom ! Generic crown area allometry wrapper ! ============================================================================ - subroutine carea_allom(dbh,nplant,site_spread,ipft,c_area,inverse) + subroutine carea_allom(dbh,nplant,site_spread,ipft,crowndamage,c_area,inverse) real(r8),intent(inout) :: dbh ! plant diameter at breast (reference) height [cm] real(r8),intent(in) :: site_spread ! site level spread factor (crowdedness) real(r8),intent(in) :: nplant ! number of plants [1/ha] integer(i4),intent(in) :: ipft ! PFT index + integer(i4),intent(in) :: crowndamage ! crown damage class of the cohort real(r8),intent(inout) :: c_area ! crown area per cohort (m2) logical,optional,intent(in) :: inverse ! if true, calculate dbh from crown area ! instead of crown area from dbh @@ -475,14 +491,17 @@ subroutine carea_allom(dbh,nplant,site_spread,ipft,c_area,inverse) select case(int(allom_lmode)) case(1) dbh_eff = min(dbh,dbh_maxh) - call carea_2pwr(dbh_eff,site_spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max,c_area,do_inverse) + call carea_2pwr(dbh_eff,site_spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max, & + c_area,do_inverse, crowndamage) capped_allom = .true. case(2) ! "2par_pwr") - call carea_2pwr(dbh,site_spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max,c_area,do_inverse) + call carea_2pwr(dbh,site_spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max,c_area, & + do_inverse, crowndamage) capped_allom = .false. case(3) dbh_eff = min(dbh,dbh_maxh) - call carea_2pwr(dbh_eff,site_spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max,c_area,do_inverse) + call carea_2pwr(dbh_eff,site_spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max, & + c_area,do_inverse, crowndamage) capped_allom = .true. case DEFAULT write(fates_log(),*) 'An undefined leaf allometry was specified: ', & @@ -513,7 +532,7 @@ end subroutine carea_allom ! ===================================================================================== - subroutine bleaf(d,ipft,canopy_trim,bl,dbldd) + subroutine bleaf(d,ipft,crowndamage,canopy_trim,bl,dbldd) ! ------------------------------------------------------------------------- ! This subroutine calculates the actual target bleaf @@ -521,15 +540,19 @@ subroutine bleaf(d,ipft,canopy_trim,bl,dbldd) ! is not allometry and rather an emergent property, ! this routine is not name-spaced with allom_ ! ------------------------------------------------------------------------- + + use DamageMainMod , only : get_crown_reduction real(r8),intent(in) :: d ! plant diameter [cm] integer(i4),intent(in) :: ipft ! PFT index + integer(i4),intent(in) :: crowndamage ! crown damage class real(r8),intent(in) :: canopy_trim ! trimming function real(r8),intent(out) :: bl ! plant leaf biomass [kg] real(r8),intent(out),optional :: dbldd ! change leaf bio per diameter [kgC/cm] real(r8) :: blmax real(r8) :: dblmaxdd + real(r8) :: crown_reduction call blmax_allom(d,ipft,blmax,dblmaxdd) @@ -541,10 +564,20 @@ subroutine bleaf(d,ipft,canopy_trim,bl,dbldd) ! ------------------------------------------------------------------------- bl = blmax * canopy_trim - + if(present(dbldd))then dbldd = dblmaxdd * canopy_trim end if + + + if ( crowndamage > 1 ) then + + call get_crown_reduction(crowndamage, crown_reduction) + bl = bl * (1.0_r8 - crown_reduction) + if(present(dbldd))then + dbldd = dblmaxdd * canopy_trim * (1.0_r8 - crown_reduction) + end if + end if return end subroutine bleaf @@ -702,17 +735,18 @@ end function tree_lai ! ============================================================================ - real(r8) function tree_sai( pft, dbh, canopy_trim, c_area, nplant, cl, & + real(r8) function tree_sai(pft, dbh, site_spread, canopy_trim, target_c_area, nplant, cl, & canopy_lai, treelai, vcmax25top, call_id ) ! ============================================================================ ! SAI of individual trees is a function of the LAI of individual trees ! ============================================================================ - integer, intent(in) :: pft - real(r8), intent(in) :: dbh + integer, intent(in) :: pft + real(r8), intent(inout) :: dbh + real(r8), intent(in) :: site_spread + real(r8), intent(inout) :: target_c_area real(r8), intent(in) :: canopy_trim ! trimming function (0-1) - real(r8), intent(in) :: c_area ! crown area (m2) real(r8), intent(in) :: nplant ! number of plants integer, intent(in) :: cl ! canopy layer index real(r8), intent(in) :: canopy_lai(nclmax) ! total leaf area index of @@ -722,12 +756,16 @@ real(r8) function tree_sai( pft, dbh, canopy_trim, c_area, nplant, cl, & integer,intent(in) :: call_id ! flag specifying where this is called ! from real(r8) :: h - real(r8) :: target_bleaf real(r8) :: target_lai + real(r8) :: target_bleaf - call bleaf(dbh,pft,canopy_trim,target_bleaf) + ! target undamaged bleaf + call bleaf(dbh, pft, 1, canopy_trim, target_bleaf) - target_lai = tree_lai( target_bleaf, pft, c_area, nplant, cl, canopy_lai, vcmax25top) + call carea_allom(dbh, nplant, site_spread, pft, 1, target_c_area, inverse = .false.) + + target_lai = tree_lai(target_bleaf, pft, target_c_area, nplant, cl,& + canopy_lai, vcmax25top) tree_sai = prt_params%allom_sai_scaler(pft) * target_lai @@ -738,17 +776,17 @@ real(r8) function tree_sai( pft, dbh, canopy_trim, c_area, nplant, cl, & write(fates_log(),*) 'The leaf and stem are predicted for a cohort, maxed out the array size' write(fates_log(),*) 'lai: ',treelai write(fates_log(),*) 'sai: ',tree_sai - write(fates_log(),*) 'target_lai: ',target_lai write(fates_log(),*) 'lai+sai: ',treelai+tree_sai + write(fates_log(),*) 'target_bleaf: ', target_bleaf + write(fates_log(),*) 'target_c_area: ', target_c_area + write(fates_log(),*) 'target_lai: ',target_lai write(fates_log(),*) 'nlevleaf,dinc_ed,nlevleaf*dinc_ed :',nlevleaf,dinc_ed,nlevleaf*dinc_ed write(fates_log(),*) 'pft: ',pft write(fates_log(),*) 'call id: ',call_id write(fates_log(),*) 'n: ',nplant - write(fates_log(),*) 'c_area: ',c_area write(fates_log(),*) 'dbh: ',dbh,' dbh_max: ',prt_params%allom_dbh_maxheight(pft) write(fates_log(),*) 'h: ',h write(fates_log(),*) 'canopy_trim: ',canopy_trim - write(fates_log(),*) 'target_bleaf: ',target_bleaf write(fates_log(),*) 'canopy layer: ',cl write(fates_log(),*) 'canopy_tlai: ',canopy_lai(:) write(fates_log(),*) 'vcmax25top: ',vcmax25top @@ -853,10 +891,14 @@ end function leafc_from_treelai ! Generic sapwood biomass interface ! ============================================================================ - subroutine bsap_allom(d,ipft,canopy_trim,sapw_area,bsap,dbsapdd) + subroutine bsap_allom(d,ipft,crowndamage, branch_frac, canopy_trim,sapw_area,bsap,dbsapdd) + + use DamageMainMod , only : get_crown_reduction real(r8),intent(in) :: d ! plant diameter [cm] integer(i4),intent(in) :: ipft ! PFT index + integer(i4),intent(in) :: crowndamage + real(r8),intent(in) :: branch_frac real(r8),intent(in) :: canopy_trim real(r8),intent(out) :: sapw_area ! cross section area of ! plant sapwood at reference [m2] @@ -876,10 +918,16 @@ subroutine bsap_allom(d,ipft,canopy_trim,sapw_area,bsap,dbsapdd) ! than some specified proportion of woody biomass ! should not trip, and only in small plants + real(r8) :: crown_reduction + real(r8) :: agb_frac + ! Constrain sapwood so that its above ground portion be no larger than ! X% of total woody/fibrous (ie non leaf/fineroot) tissues real(r8),parameter :: max_frac = 0.95_r8 + agb_frac = prt_params%allom_agb_frac(ipft) + + select case(int(prt_params%allom_smode(ipft))) ! --------------------------------------------------------------------- ! Currently only one sapwood allometry model. the slope @@ -889,11 +937,23 @@ subroutine bsap_allom(d,ipft,canopy_trim,sapw_area,bsap,dbsapdd) ! and slatop (no provisions for slamax) call h_allom(d,ipft,h,dhdd) - call bleaf(d,ipft,canopy_trim,bl,dbldd) + call bleaf(d,ipft,1,canopy_trim,bl,dbldd) call bsap_ltarg_slatop(d,h,dhdd,bl,dbldd,ipft,sapw_area,bsap,dbsapdd) + ! if trees are damaged reduce bsap by percent crown loss * + ! fraction of biomass that would be in branches (pft specific) + if(crowndamage > 1)then + + call get_crown_reduction(crowndamage, crown_reduction) + bsap = bsap - (bsap * agb_frac * branch_frac * crown_reduction) + if(present(dbsapdd))then + dbsapdd = dbsapdd - (dbsapdd * agb_frac * branch_frac * crown_reduction) + end if + end if + + ! Perform a capping/check on total woody biomass - call bagw_allom(d,ipft,bagw,dbagwdd) + call bagw_allom(d,ipft,crowndamage, branch_frac, bagw,dbagwdd) call bbgw_allom(d,ipft,bbgw,dbbgwdd) ! Force sapwood to be less than a maximum fraction of total biomass @@ -935,7 +995,8 @@ subroutine bbgw_allom(d,ipft,bbgw,dbbgwdd) select case(int(prt_params%allom_cmode(ipft))) case(1) !"constant") - call bagw_allom(d,ipft,bagw,dbagwdd) + ! bbgw not affected by damage so use target allometry no damage + call bagw_allom(d,ipft,1, 1.0_r8, bagw,dbagwdd) call bbgw_const(d,bagw,dbagwdd,ipft,bbgw,dbbgwdd) case DEFAULT write(fates_log(),*) 'An undefined coarse root allometry was specified: ', & @@ -1002,10 +1063,11 @@ end subroutine bfineroot ! Storage biomass interface ! ============================================================================ - subroutine bstore_allom(d,ipft,canopy_trim,bstore,dbstoredd) + subroutine bstore_allom(d,ipft,crowndamage, canopy_trim,bstore,dbstoredd) real(r8),intent(in) :: d ! plant diameter [cm] integer(i4),intent(in) :: ipft ! PFT index + integer(i4),intent(in) :: crowndamage ! Crowndamage class real(r8),intent(in) :: canopy_trim ! Crown trimming function [0-1] real(r8),intent(out) :: bstore ! allometric target storage [kgC] real(r8),intent(out),optional :: dbstoredd ! change storage per cm [kgC/cm] @@ -1023,7 +1085,7 @@ subroutine bstore_allom(d,ipft,canopy_trim,bstore,dbstoredd) case(1) ! Storage is constant proportionality of trimmed maximum leaf ! biomass (ie cushion * bleaf) - call bleaf(d,ipft,canopy_trim,bl,dbldd) + call bleaf(d,ipft, crowndamage, canopy_trim, bl, dbldd) call bstore_blcushion(d,bl,dbldd,cushion,ipft,bstore,dbstoredd) case DEFAULT @@ -2012,7 +2074,7 @@ end subroutine CrownDepth ! ============================================================================= - subroutine carea_2pwr(dbh,spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max,c_area,inverse) + subroutine carea_2pwr(dbh,spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max,c_area,inverse,crowndamage) ! ============================================================================ ! Calculate area of ground covered by entire cohort. (m2) @@ -2027,9 +2089,11 @@ subroutine carea_2pwr(dbh,spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max,c_area,inv real(r8),intent(in) :: d2ca_max ! maximum diameter to crown area scaling factor real(r8),intent(inout) :: c_area ! crown area for one plant [m2] logical,intent(in) :: inverse ! if true, calculate dbh from crown area rather than its reverse + integer,intent(in) :: crowndamage real(r8) :: crown_area_to_dbh_exponent real(r8) :: spreadterm ! Effective 2bh to crown area scaling factor + real(r8) :: crown_reduction ! default is to use the same exponent as the dbh to bleaf exponent so that per-plant ! canopy depth remains invariant during growth, but allowed to vary via the @@ -2052,7 +2116,17 @@ subroutine carea_2pwr(dbh,spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max,c_area,inv if ( .not. inverse) then c_area = spreadterm * dbh ** crown_area_to_dbh_exponent + + if(crowndamage > 1) then + call get_crown_reduction(crowndamage, crown_reduction) + c_area = c_area * (1.0_r8 - crown_reduction) + end if + else + if(crowndamage > 1) then + call get_crown_reduction(crowndamage, crown_reduction) + c_area = c_area/(1.0_r8 - crown_reduction) + end if dbh = (c_area / spreadterm) ** (1./crown_area_to_dbh_exponent) endif @@ -2320,9 +2394,7 @@ real(r8) function decay_coeff_kn(pft,vcmax25top) end function decay_coeff_kn ! ===================================================================================== - - - subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl ) +subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl, crowndamage, branch_frac ) ! ========================================================================= ! This subroutine estimates the diameter based on either the structural biomass @@ -2332,17 +2404,18 @@ subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl ) ! Here, we keep searching until the difference between actual structure and ! the predicted structure based on the searched diameter is within a tolerance. ! ============================================================================ - - use FatesConstantsMod , only : calloc_abs_error + use FatesConstantsMod , only : calloc_abs_error ! Arguments integer(i4),intent(in) :: ipft ! PFT index + integer(i4),intent(in),optional :: crowndamage ! crowndamage real(r8),intent(in) :: canopy_trim real(r8),intent(inout) :: d ! plant diameter [cm] real(r8),intent(out) :: h ! plant height real(r8),intent(in),optional :: bdead ! Structural biomass real(r8),intent(in),optional :: bl ! Leaf biomass + real(r8),intent(in),optional :: branch_frac ! Locals @@ -2362,6 +2435,7 @@ subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl ) integer :: counter real(r8), parameter :: step_frac0 = 0.9_r8 integer, parameter :: max_counter = 200 + ! Do reduce "if" calls, we break this call into two parts if ( int(prt_params%woody(ipft)) == itrue ) then @@ -2371,9 +2445,10 @@ subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl ) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - call bsap_allom(d,ipft,canopy_trim,at_sap,bt_sap,dbt_sap_dd) - call bagw_allom(d,ipft,bt_agw,dbt_agw_dd) + call bsap_allom(d,ipft,crowndamage, branch_frac, canopy_trim,at_sap,bt_sap,dbt_sap_dd) + call bagw_allom(d,ipft,crowndamage, branch_frac, bt_agw,dbt_agw_dd) call bbgw_allom(d,ipft,bt_bgw,dbt_bgw_dd) + call bdead_allom(bt_agw,bt_bgw, bt_sap, ipft, bt_dead, dbt_agw_dd, & dbt_bgw_dd, dbt_sap_dd, dbt_dead_dd) @@ -2388,13 +2463,15 @@ subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl ) dd = step_frac*(bdead-bt_dead)/dbt_dead_dd d_try = d + dd - call bsap_allom(d_try,ipft,canopy_trim,at_sap,bt_sap,dbt_sap_dd) - call bagw_allom(d_try,ipft,bt_agw,dbt_agw_dd) - call bbgw_allom(d_try,ipft,bt_bgw,dbt_bgw_dd) + call bsap_allom(d_try,ipft,crowndamage, branch_frac, canopy_trim,at_sap,bt_sap,dbt_sap_dd) + call bagw_allom(d_try,ipft,crowndamage, branch_frac, bt_agw,dbt_agw_dd) + call bbgw_allom(d_try,ipft, bt_bgw,dbt_bgw_dd) + + call bdead_allom(bt_agw,bt_bgw, bt_sap, ipft, bt_dead_try, dbt_agw_dd, & dbt_bgw_dd, dbt_sap_dd, dbt_dead_dd_try) - ! Prevent overshooting + ! Prevent overshooting if(bt_dead_try > (bdead+calloc_abs_error)) then step_frac = step_frac*0.5_r8 else @@ -2418,7 +2495,7 @@ subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl ) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - call bleaf(d,ipft,canopy_trim,bt_leaf,dbt_leaf_dd) + call bleaf(d,ipft,1,canopy_trim,bt_leaf,dbt_leaf_dd) counter = 0 step_frac = step_frac0 @@ -2427,7 +2504,7 @@ subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl ) dd = step_frac*(bl-bt_leaf)/dbt_leaf_dd d_try = d + dd - call bleaf(d_try,ipft,canopy_trim,bt_leaf_try,dbt_leaf_dd_try) + call bleaf(d_try,ipft,1,canopy_trim,bt_leaf_try,dbt_leaf_dd_try) ! Prevent overshooting if(bt_leaf_try > (bl+calloc_abs_error)) then @@ -2498,4 +2575,6 @@ subroutine cspline(x1,x2,y1,y2,dydx1,dydx2,x,y,dydx) return end subroutine cspline + + end module FatesAllometryMod diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index 9f210e8404..24cd1c2baf 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -1183,7 +1183,6 @@ function ECACScalar(ccohort, element_id) result(c_scalar) integer, parameter :: downreg_CN_logi = 3 integer, parameter :: downreg_type = downreg_linear - real(r8), parameter :: logi_k = 25.0_r8 ! logistic function k real(r8), parameter :: store_x0 = 1.0_r8 ! storage fraction inflection point @@ -1226,7 +1225,7 @@ function ECACScalar(ccohort, element_id) result(c_scalar) else store_c = ccohort%prt%GetState(store_organ, carbon12_element) - call bstore_allom(ccohort%dbh,ccohort%pft,ccohort%canopy_trim,store_c_max) + call bstore_allom(ccohort%dbh,ccohort%pft,ccohort%crowndamage, ccohort%canopy_trim,store_c_max) ! Fraction of N per fraction of C ! If this is greater than 1, then we have more N in storage than diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 98aaad6488..c4c1dff76a 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -880,7 +880,8 @@ subroutine UpdatePlantHydrLenVol(ccohort,site_hydr) ! Get the target, or rather, maximum leaf carrying capacity of plant ! Lets also avoid super-low targets that have very low trimming functions - call bleaf(ccohort%dbh,ccohort%pft,max(ccohort%canopy_trim,min_trim),leaf_c_target) + call bleaf(ccohort%dbh,ccohort%pft,ccohort%crowndamage, & + max(ccohort%canopy_trim,min_trim),leaf_c_target) if( (ccohort%status_coh == leaves_on) .or. ccohort_hydr%is_newly_recruited ) then ccohort_hydr%v_ag(1:n_hypool_leaf) = max(leaf_c,min_leaf_frac*leaf_c_target) * & @@ -895,7 +896,8 @@ subroutine UpdatePlantHydrLenVol(ccohort,site_hydr) ! v_stem = c_stem_biom / (prt_params%wood_density(ft) * kg_per_g * cm3_per_m3 ) ! calculate the sapwood cross-sectional area - call bsap_allom(ccohort%dbh,ccohort%pft,ccohort%canopy_trim,a_sapwood_target,sapw_c_target) + call bsap_allom(ccohort%dbh,ccohort%pft,ccohort%crowndamage, ccohort%branch_frac, & + ccohort%canopy_trim,a_sapwood_target,sapw_c_target) ! uncomment this if you want to use ! the actual sapwood, which may be lower than target due to branchfall. @@ -2770,7 +2772,8 @@ subroutine UpdatePlantKmax(ccohort_hydr,ccohort,csite_hydr) pft = ccohort%pft ! Get the cross-section of the plant's sapwood area [m2] - call bsap_allom(ccohort%dbh,pft,ccohort%canopy_trim,a_sapwood,c_sap_dummy) + call bsap_allom(ccohort%dbh,pft,ccohort%crowndamage,ccohort%branch_frac, & + ccohort%canopy_trim,a_sapwood,c_sap_dummy) ! Leaf Maximum Hydraulic Conductance ! The starting hypothesis is that there is no resistance inside the diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 4ff827443b..c5d96585f9 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -111,6 +111,11 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) use FatesAllometryMod, only : set_root_fraction use FatesAllometryMod, only : decay_coeff_kn + use DamageMainMod, only : get_crown_reduction + + use FatesInterfaceTypesMod, only : hlm_use_canopy_damage + use FatesInterfaceTypesMod, only : hlm_use_understory_damage + ! ARGUMENTS: ! ----------------------------------------------------------------------------------- integer,intent(in) :: nsites @@ -216,6 +221,13 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) real(r8), allocatable :: rootfr_ft(:,:) ! Root fractions per depth and PFT + real(r8) :: branch_frac + real(r8) :: agb_frac + real(r8) :: crown_reduction + real(r8) :: sapw_c_predamage + real(r8) :: sapw_n + real(r8) :: sapw_n_predamage + ! ----------------------------------------------------------------------------------- ! Keeping these two definitions in case they need to be added later ! @@ -362,7 +374,8 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ft = currentCohort%pft cl = currentCohort%canopy_layer - call bleaf(currentCohort%dbh,currentCohort%pft,currentCohort%canopy_trim,store_c_target) + call bleaf(currentCohort%dbh,currentCohort%pft,& + currentCohort%crowndamage,currentCohort%canopy_trim,store_c_target) ! call bstore_allom(currentCohort%dbh,currentCohort%pft, & ! currentCohort%canopy_trim,store_c_target) @@ -607,7 +620,19 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) + + if (hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + + agb_frac = prt_params%allom_agb_frac(currentCohort%pft) + branch_frac = currentCohort%branch_frac + call get_crown_reduction(currentCohort%crowndamage, crown_reduction) + ! need the undamaged version if using ratios with roots + sapw_c = sapw_c / & + (1.0_r8 - (agb_frac * branch_frac * (1.0_r8-crown_reduction))) + end if + + select case(hlm_parteh_mode) case (prt_carbon_allom_hyp) @@ -617,7 +642,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) live_croot_n = (1.0_r8-prt_params%allom_agb_frac(currentCohort%pft)) * & sapw_c * prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) - fnrt_n = fnrt_c * prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)) + fnrt_n = fnrt_c * prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)) case(prt_cnp_flex_allom_hyp) @@ -633,10 +658,10 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! use the stoichiometry parameter ! ! live_stem_n = prt_params%allom_agb_frac(currentCohort%pft) * & - ! sapw_c * prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) + ! sapw_c * prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) ! live_croot_n = (1.0_r8-prt_params%allom_agb_frac(currentCohort%pft)) * & - ! sapw_c * prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) - ! fnrt_n = fnrt_c * prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)) + ! sapw_c * prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) + ! fnrt_n = fnrt_c * prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)) case default diff --git a/functional_unit_testing/parteh/f90src/FatesCohortWrapMod.F90 b/functional_unit_testing/parteh/f90src/FatesCohortWrapMod.F90 index 75575d3df9..6238111e30 100644 --- a/functional_unit_testing/parteh/f90src/FatesCohortWrapMod.F90 +++ b/functional_unit_testing/parteh/f90src/FatesCohortWrapMod.F90 @@ -230,7 +230,7 @@ subroutine CohortPySet(ipft,hgt_min,canopy_trim) ! Use allometry to compute initial values ! Leaf biomass (carbon) - call bleaf(ccohort%dbh, ipft, canopy_trim, leaf_c) + call bleaf(ccohort%dbh, ipft,canopy_trim, leaf_c) ! Fine-root biomass (carbon) call bfineroot(ccohort%dbh, ipft, canopy_trim, fnrt_c) @@ -431,7 +431,7 @@ end subroutine WrapDailyPRT ! ===================================================================================== - subroutine WrapQueryVars(ipft,leaf_area,crown_area,agb,store_c,target_leaf_c) + subroutine WrapQueryVars(ipft,crowndamage, leaf_area,crown_area,agb,store_c,target_leaf_c) implicit none ! Arguments @@ -444,12 +444,13 @@ subroutine WrapQueryVars(ipft,leaf_area,crown_area,agb,store_c,target_leaf_c) real(r8) :: leaf_c type(ed_cohort_type), pointer :: ccohort - + real(r8),parameter :: nplant = 1.0_r8 real(r8),parameter :: site_spread = 1.0_r8 real(r8), dimension(nclmax) :: canopy_lai integer, parameter :: cl1 = 1 + ccohort => cohort_array(ipft) @@ -466,18 +467,19 @@ subroutine WrapQueryVars(ipft,leaf_area,crown_area,agb,store_c,target_leaf_c) leaf_c = ccohort%prt%GetState(leaf_organ, carbon12_element ) store_c = ccohort%prt%GetState(store_organ, carbon12_element ) - call carea_allom(ccohort%dbh,nplant,site_spread,ipft,crown_area) + call carea_allom(ccohort%dbh,nplant,site_spread,ipft,ccohort%crowndamage,crown_area) leaf_area = crown_area*tree_lai(leaf_c, ipft, crown_area, nplant, cl1, canopy_lai,ccohort%vcmax25top) - call bagw_allom(ccohort%dbh,ipft,agb) + call bagw_allom(ccohort%dbh,ipft, agb) call bleaf(ccohort%dbh,ipft, ccohort%canopy_trim, target_leaf_c) return end subroutine WrapQueryVars - + + ! ========================================================================================== subroutine WrapQueryDiagnostics(ipft, dbh, & leaf_c, fnrt_c, sapw_c, store_c, struct_c, repro_c, & diff --git a/main/DamageMainMod.F90 b/main/DamageMainMod.F90 new file mode 100644 index 0000000000..7dbe385cbf --- /dev/null +++ b/main/DamageMainMod.F90 @@ -0,0 +1,161 @@ +module DamageMainMod + + use FatesConstantsMod , only : r8 => fates_r8 + use FatesConstantsMod , only : i4 => fates_int + use FatesConstantsMod , only : itrue, ifalse + use FatesConstantsMod , only : years_per_day + use FatesGlobals , only : fates_log + + use EDPftvarcon , only : EDPftvarcon_inst + + use EDtypesMod , only : ed_site_type + use EDtypesMod , only : ed_patch_type + use EDtypesMod , only : ed_cohort_type + use EDtypesMod , only : AREA + + use PRTGenericMod, only : leaf_organ + use PRTGenericMod, only : carbon12_element + use PRTGenericMod, only : all_carbon_elements + use PRTGenericMod, only : leaf_organ + use PRTGenericMod, only : fnrt_organ + use PRTGenericMod, only : sapw_organ + use PRTGenericMod, only : store_organ + use PRTGenericMod, only : repro_organ + use PRTGenericMod, only : struct_organ + use PRTGenericMod, only : SetState + + implicit none + private + + logical, protected :: damage_time ! if true then damage occurs during current time step + + public :: get_crown_reduction + public :: get_damage_frac + public :: is_it_damage_time + public :: damage_time + public :: get_damage_mortality + + logical :: debug = .false. ! for debugging + + ! ============================================================================ + ! ============================================================================ + +contains + + + subroutine is_it_damage_time(is_master, currentSite) + + !---------------------------------------------------------------------------- + ! This subroutine determines whether damage should occur (it is called daily) + !----------------------------------------------------------------------------- + + use FatesInterfaceTypesMod , only : hlm_day_of_year + + integer, intent(in) :: is_master + type(ed_site_type), intent(inout), target :: currentSite + + + damage_time = .false. + + if (hlm_day_of_year .eq. 1) then + damage_time = .true. + end if + + end subroutine is_it_damage_time + + !---------------------------------------------------------------------------- + + subroutine get_damage_frac(cc_cd, nc_cd, pft, dist_frac) + + + ! given current cohort damage class find the fraction of individuals + ! going to the new damage class. + ! Consults a look up table of transitions from param derived. + + ! USES + use FatesInterfaceTypesMod, only : ncrowndamage + use FatesConstantsMod, only : years_per_day + use FatesParameterDerivedMod, only : param_derived + + + ! ARGUMENTS + integer, intent(in) :: cc_cd ! current cohort crown damage + integer, intent(in) :: nc_cd ! new cohort crown damage + integer, intent(in) :: pft + real(r8), intent(out) :: dist_frac ! probability of current cohort moving to new damage level + + dist_frac = param_derived%damage_transitions(cc_cd, nc_cd, pft) !* years_per_day (if damage is occuring annually don't do this) + + + end subroutine get_damage_frac + + !------------------------------------------------------- + + subroutine get_crown_reduction(crowndamage, crown_reduction) + + !------------------------------------------------------------------ + ! This function takes the crown damage class of a cohort (integer) + ! and returns the fraction of the crown that is lost + ! Since crowndamage class = 1 means no damage, we subtract one + ! before multiplying by 0.2 + ! Therefore, first damage class is 20% loss of crown, second 40% etc. + !------------------------------------------------------------------- + use FatesInterfaceTypesMod , only : ncrowndamage + + integer(i4), intent(in) :: crowndamage + real(r8), intent(out) :: crown_reduction + + ! local variables + real(r8) :: class_width + + class_width = 1.0_r8/ncrowndamage + crown_reduction = min(1.0_r8, (real(crowndamage) - 1.0_r8) * class_width) + + return + end subroutine get_crown_reduction + + + !---------------------------------------------------------------------------------------- + + + subroutine get_damage_mortality(crowndamage,pft, dgmort) + + use FatesInterfaceTypesMod , only : ncrowndamage + use EDPftvarcon , only : EDPftvarcon_inst + + integer(i4), intent(in) :: crowndamage + integer(i4), intent(in) :: pft + real(r8), intent(out) :: dgmort + + ! local variables + real(r8) :: damage_mort_p1 + real(r8) :: damage_mort_p2 + real(r8) :: class_width + real(r8) :: crown_loss + + class_width = 1.0_r8/real(ncrowndamage) + + ! parameter to determine slope of exponential + damage_mort_p1 = EDPftvarcon_inst%damage_mort_p1(pft) + damage_mort_p2 = EDPftvarcon_inst%damage_mort_p2(pft) + + ! make damage mortality a function of crownloss and not crowndamage + ! class so that it doesn't need to be re-parameterised if the number + ! of damage classes change. + crown_loss = min(1.0_r8, (real(crowndamage) - 1.0_r8) * class_width) + + if (crowndamage .eq. 1 ) then + dgmort = 0.0_r8 + else + dgmort = 1.0_r8 / (1.0_r8 + exp(-1.0_r8 * damage_mort_p2 * & + (crown_loss - damage_mort_p1) ) ) + + end if + + return + end subroutine get_damage_mortality + !---------------------------------------------------------------------------------------- + + +end module DamageMainMod + diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index c3b503a729..22b7a6e0c3 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -43,11 +43,14 @@ module EDInitMod use FatesInterfaceTypesMod , only : hlm_use_planthydro use FatesInterfaceTypesMod , only : hlm_use_inventory_init use FatesInterfaceTypesMod , only : hlm_use_fixed_biogeog + use FatesInterfaceTypesMod , only : hlm_use_canopy_damage + use FatesInterfaceTypesMod , only : hlm_use_understory_damage use FatesInterfaceTypesMod , only : hlm_use_sp use FatesInterfaceTypesMod , only : numpft use FatesInterfaceTypesMod , only : nleafage use FatesInterfaceTypesMod , only : nlevsclass use FatesInterfaceTypesMod , only : nlevcoage + use FatesInterfaceTypesMod , only : ncrowndamage use FatesInterfaceTypesMod , only : hlm_use_nocomp use FatesInterfaceTypesMod , only : nlevage @@ -127,6 +130,39 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) allocate(site_in%mass_balance(1:num_elements)) allocate(site_in%flux_diags(1:num_elements)) + if (hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + allocate(site_in%damage_cflux(1:ncrowndamage, 1:ncrowndamage+1)) + allocate(site_in%damage_rate(1:ncrowndamage, 1:ncrowndamage+1)) + allocate(site_in%recovery_cflux(1:ncrowndamage, 1:ncrowndamage+1)) + allocate(site_in%recovery_rate(1:ncrowndamage, 1:ncrowndamage+1)) + allocate(site_in%term_nindivs_canopy_damage(1:ncrowndamage, 1:nlevsclass, 1:numpft)) + allocate(site_in%term_nindivs_ustory_damage(1:ncrowndamage, 1:nlevsclass, 1:numpft)) + allocate(site_in%imort_rate_damage(1:ncrowndamage, 1:nlevsclass, 1:numpft)) + allocate(site_in%imort_cflux_damage(1:ncrowndamage, 1:nlevsclass)) + allocate(site_in%term_cflux_canopy_damage(1:ncrowndamage, 1:nlevsclass)) + allocate(site_in%term_cflux_ustory_damage(1:ncrowndamage, 1:nlevsclass)) + allocate(site_in%fmort_rate_canopy_damage(1:ncrowndamage, 1:nlevsclass, 1:numpft)) + allocate(site_in%fmort_rate_ustory_damage(1:ncrowndamage, 1:nlevsclass, 1:numpft)) + allocate(site_in%fmort_cflux_canopy_damage(1:ncrowndamage, 1:nlevsclass)) + allocate(site_in%fmort_cflux_ustory_damage(1:ncrowndamage, 1:nlevsclass)) + else + allocate(site_in%damage_cflux(1, 1)) + allocate(site_in%damage_rate(1, 1)) + allocate(site_in%recovery_cflux(1, 1)) + allocate(site_in%recovery_rate(1, 1)) + allocate(site_in%term_nindivs_canopy_damage(1,1,1)) + allocate(site_in%term_nindivs_ustory_damage(1,1,1)) + allocate(site_in%imort_rate_damage(1,1,1)) + allocate(site_in%imort_cflux_damage(1,1)) + allocate(site_in%term_cflux_canopy_damage(1,1)) + allocate(site_in%term_cflux_ustory_damage(1,1)) + allocate(site_in%fmort_rate_canopy_damage(1,1,1)) + allocate(site_in%fmort_rate_ustory_damage(1,1,1)) + allocate(site_in%fmort_cflux_canopy_damage(1,1)) + allocate(site_in%fmort_cflux_ustory_damage(1,1)) + end if + + site_in%nlevsoil = bc_in%nlevsoil allocate(site_in%rootfrac_scr(site_in%nlevsoil)) allocate(site_in%zi_soil(0:site_in%nlevsoil)) @@ -198,8 +234,8 @@ subroutine zero_site( site_in ) site_in%water_memory(:) = nan site_in%vegtemp_memory(:) = nan ! record of last 10 days temperature for senescence model. - - ! FIRE + + ! FIRE site_in%acc_ni = 0.0_r8 ! daily nesterov index accumulating over time. time unlimited theoretically. site_in%NF = 0.0_r8 ! daily lightning strikes per km2 site_in%NF_successful = 0.0_r8 ! daily successful iginitions per km2 @@ -217,13 +253,18 @@ subroutine zero_site( site_in ) site_in%term_nindivs_ustory(:,:) = 0._r8 site_in%term_carbonflux_canopy = 0._r8 site_in%term_carbonflux_ustory = 0._r8 + site_in%term_crownarea_canopy = 0._r8 + site_in%term_crownarea_ustory = 0._r8 site_in%recruitment_rate(:) = 0._r8 site_in%imort_rate(:,:) = 0._r8 site_in%imort_carbonflux = 0._r8 + site_in%imort_crownarea = 0._r8 site_in%fmort_rate_canopy(:,:) = 0._r8 site_in%fmort_rate_ustory(:,:) = 0._r8 site_in%fmort_carbonflux_canopy = 0._r8 site_in%fmort_carbonflux_ustory = 0._r8 + site_in%fmort_crownarea_canopy = 0._r8 + site_in%fmort_crownarea_ustory = 0._r8 site_in%fmort_rate_cambial(:,:) = 0._r8 site_in%fmort_rate_crown(:,:) = 0._r8 @@ -236,6 +277,24 @@ subroutine zero_site( site_in ) site_in%promotion_rate(:) = 0._r8 site_in%promotion_carbonflux = 0._r8 + ! damage transition info + site_in%damage_cflux(:,:) = 0._r8 + site_in%damage_rate(:,:) = 0._r8 + site_in%recovery_cflux(:,:) = 0._r8 + site_in%recovery_rate(:,:) = 0._r8 + site_in%imort_rate_damage(:,:,:) = 0._r8 + site_in%term_nindivs_canopy_damage(:,:,:) = 0._r8 + site_in%term_nindivs_ustory_damage(:,:,:) = 0._r8 + site_in%imort_cflux_damage(:,:) = 0._r8 + site_in%term_cflux_canopy_damage(:,:) = 0._r8 + site_in%term_cflux_ustory_damage(:,:) = 0._r8 + site_in%crownarea_canopy_damage = 0._r8 + site_in%crownarea_ustory_damage = 0._r8 + site_in%fmort_rate_canopy_damage(:,:,:) = 0._r8 + site_in%fmort_rate_ustory_damage(:,:,:) = 0._r8 + site_in%fmort_cflux_canopy_damage(:,:) = 0._r8 + site_in%fmort_cflux_ustory_damage(:,:) = 0._r8 + ! Resources management (logging/harvesting, etc) site_in%resources_management%trunk_product_site = 0.0_r8 @@ -645,7 +704,7 @@ subroutine init_patches( nsites, sites, bc_in) return end subroutine init_patches - + ! ============================================================================ subroutine init_cohorts( site_in, patch_in, bc_in) ! @@ -653,6 +712,8 @@ subroutine init_cohorts( site_in, patch_in, bc_in) ! initialize new cohorts on bare ground ! ! !USES: + use FatesParameterDerivedMod , only : param_derived + ! ! !ARGUMENTS type(ed_site_type), intent(inout), pointer :: site_in @@ -664,6 +725,8 @@ subroutine init_cohorts( site_in, patch_in, bc_in) class(prt_vartypes),pointer :: prt_obj integer :: cstatus integer :: pft + integer :: crowndamage ! which crown damage class + real :: branch_frac ! fraction of biomass in branches integer :: iage ! index for leaf age loop integer :: el ! index for element loop integer :: element_id ! element index consistent with defs in PRTGeneric @@ -747,17 +810,24 @@ subroutine init_cohorts( site_in, patch_in, bc_in) else temp_cohort%hite = EDPftvarcon_inst%hgt_min(pft) + temp_cohort%branch_frac = param_derived%branch_frac(pft) + + ! Assume no damage to begin with - since we assume no damage + ! we do not need to initialise branch frac just yet. + temp_cohort%crowndamage = 1 ! Calculate the plant diameter from height call h2d_allom(temp_cohort%hite,pft,temp_cohort%dbh) ! Calculate the leaf biomass from allometry ! (calculates a maximum first, then applies canopy trim) - call bleaf(temp_cohort%dbh,pft,temp_cohort%canopy_trim,c_leaf) + call bleaf(temp_cohort%dbh,pft,temp_cohort%crowndamage, & + temp_cohort%canopy_trim,c_leaf) end if ! sp mode ! Calculate total above-ground biomass from allometry - call bagw_allom(temp_cohort%dbh,pft,c_agw) + call bagw_allom(temp_cohort%dbh,pft,temp_cohort%crowndamage, & + 1.0_r8, c_agw) ! Calculate coarse root biomass from allometry call bbgw_allom(temp_cohort%dbh,pft,c_bgw) @@ -767,11 +837,13 @@ subroutine init_cohorts( site_in, patch_in, bc_in) call bfineroot(temp_cohort%dbh,pft,temp_cohort%canopy_trim,c_fnrt) ! Calculate sapwood biomass - call bsap_allom(temp_cohort%dbh,pft,temp_cohort%canopy_trim,a_sapw,c_sapw) + call bsap_allom(temp_cohort%dbh,pft,temp_cohort%crowndamage, 1.0_r8, & + temp_cohort%canopy_trim,a_sapw,c_sapw) call bdead_allom( c_agw, c_bgw, c_sapw, pft, c_struct ) - call bstore_allom(temp_cohort%dbh, pft, temp_cohort%canopy_trim, c_store) + call bstore_allom(temp_cohort%dbh, pft, temp_cohort%crowndamage, & + temp_cohort%canopy_trim, c_store) temp_cohort%laimemory = 0._r8 temp_cohort%sapwmemory = 0._r8 @@ -878,10 +950,11 @@ subroutine init_cohorts( site_in, patch_in, bc_in) call prt_obj%CheckInitialConditions() - call create_cohort(site_in, patch_in, pft, temp_cohort%n, temp_cohort%hite, & - temp_cohort%coage, temp_cohort%dbh, prt_obj, temp_cohort%laimemory, & - temp_cohort%sapwmemory, temp_cohort%structmemory, cstatus, rstatus, & - temp_cohort%canopy_trim, temp_cohort%c_area,1, site_in%spread, bc_in) + call create_cohort(site_in, patch_in, pft, temp_cohort%n, temp_cohort%hite, & + temp_cohort%coage, temp_cohort%dbh, prt_obj, temp_cohort%laimemory,& + temp_cohort%sapwmemory, temp_cohort%structmemory, cstatus, rstatus, & + temp_cohort%canopy_trim, temp_cohort%c_area, 1, temp_cohort%crowndamage,& + temp_cohort%branch_frac, site_in%spread, bc_in) deallocate(temp_cohort) ! get rid of temporary cohort diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 48820e5ad6..83c1cf7e58 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -19,6 +19,8 @@ module EDMainMod use FatesInterfaceTypesMod , only : hlm_use_cohort_age_tracking use FatesInterfaceTypesMod , only : hlm_reference_date use FatesInterfaceTypesMod , only : hlm_use_ed_prescribed_phys + use FatesInterfaceTypesMod , only : hlm_use_canopy_damage + use FatesInterfaceTypesMod , only : hlm_use_understory_damage use FatesInterfaceTypesMod , only : hlm_use_ed_st3 use FatesInterfaceTypesMod , only : hlm_use_sp use FatesInterfaceTypesMod , only : bc_in_type @@ -79,6 +81,7 @@ module EDMainMod use FatesAllometryMod , only : h_allom,tree_sai,tree_lai use FatesPlantHydraulicsMod , only : UpdateSizeDepRhizHydStates use EDLoggingMortalityMod , only : IsItLoggingTime + use DamageMainMod , only : is_it_damage_time use EDPatchDynamicsMod , only : get_frac_site_primary use FatesGlobals , only : endrun => fates_endrun use ChecksBalancesMod , only : SiteMassStock @@ -143,11 +146,12 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) ! ! !LOCAL VARIABLES: type(ed_patch_type), pointer :: currentPatch - integer :: el ! Loop counter for elements + integer :: el ! Loop counter for variables integer :: do_patch_dynamics ! for some modes, we turn off patch dynamics - + !----------------------------------------------------------------------- + if ( hlm_masterproc==itrue ) write(fates_log(),'(A,I4,A,I2.2,A,I2.2)') 'FATES Dynamics: ',& hlm_current_year,'-',hlm_current_month,'-',hlm_current_day @@ -163,6 +167,11 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) ! This is limited to a global event until more structured event handling is enabled call IsItLoggingTime(hlm_masterproc,currentSite) + ! Call a routine that identifies if damage should occur + if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + call is_it_damage_time(hlm_masterproc, currentSite) + end if + !************************************************************************** ! Fire, growth, biogeochemistry. !************************************************************************** @@ -292,7 +301,7 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) end if call TotalBalanceCheck(currentSite,5) - + end subroutine ed_ecosystem_dynamics !-------------------------------------------------------------------------------! @@ -303,8 +312,30 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! FIX(SPM,032414) refactor so everything goes through interface ! ! !USES: + use FatesInterfaceTypesMod, only : ncrowndamage + use FatesAllometryMod , only : bleaf + use FatesAllometryMod , only : carea_allom + use PRTGenericMod , only : leaf_organ + use PRTGenericMod , only : repro_organ + use PRTGenericMod , only : sapw_organ + use PRTGenericMod , only : struct_organ + use PRTGenericMod , only : store_organ + use PRTGenericMod , only : fnrt_organ use FatesInterfaceTypesMod, only : hlm_use_cohort_age_tracking use FatesConstantsMod, only : itrue + use PRTGenericMod , only : all_carbon_elements + use DamageMainMod , only : damage_time + use EDCohortDynamicsMod , only : zero_cohort, copy_cohort, insert_cohort + use EDCohortDynamicsMod , only : DeallocateCohort + use FatesPlantHydraulicsMod, only : InitHydrCohort + use EDCohortDynamicsMod , only : InitPRTObject + use EDCohortDynamicsMod , only : InitPRTBoundaryConditions + use FatesConstantsMod , only : nearzero + use EDCanopyStructureMod , only : canopy_structure + use PRTLossFluxesMod , only : PRTDamageRecoveryFluxes + use PRTGenericMod , only : max_nleafage + use PRTGenericMod , only : prt_global + ! !ARGUMENTS: type(ed_site_type) , intent(inout) :: currentSite @@ -316,6 +347,12 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) type(site_massbal_type), pointer :: site_cmass type(ed_patch_type) , pointer :: currentPatch type(ed_cohort_type) , pointer :: currentCohort + type(ed_cohort_type) , pointer :: nc + type(ed_cohort_type) , pointer :: storesmallcohort + type(ed_cohort_type) , pointer :: storebigcohort + + integer :: snull + integer :: tnull integer :: c ! Counter for litter size class integer :: ft ! Counter for PFT @@ -328,12 +365,45 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) logical :: is_drought ! logical for if the plant (site) is in a drought state real(r8) :: delta_dbh ! correction for dbh real(r8) :: delta_hite ! correction for hite - real(r8) :: current_npp ! place holder for calculating npp each year in prescribed physiology mode - !----------------------------------------------------------------------- + + real(r8) :: target_leaf_c real(r8) :: frac_site_primary + real(r8) :: n_old + real(r8) :: n_recover + integer :: nleafage + real(r8) :: sapw_c + real(r8) :: leaf_c + real(r8) :: fnrt_c + real(r8) :: struct_c + real(r8) :: repro_c + real(r8) :: total_c + real(r8) :: store_c + + real(r8) :: cc_leaf_c + real(r8) :: cc_fnrt_c + real(r8) :: cc_struct_c + real(r8) :: cc_repro_c + real(r8) :: cc_store_c + real(r8) :: cc_sapw_c + + real(r8) :: sapw_c0 + real(r8) :: leaf_c0 + real(r8) :: fnrt_c0 + real(r8) :: struct_c0 + real(r8) :: repro_c0 + real(r8) :: store_c0 + real(r8) :: total_c0 + real(r8) :: nc_carbon + real(r8) :: cc_carbon + + integer,parameter :: leaf_c_id = 1 + + !----------------------------------------------------------------------- + nleafage = prt_global%state_descriptor(leaf_c_id)%num_pos + call get_frac_site_primary(currentSite, frac_site_primary) ! Set a pointer to this sites carbon12 mass balance @@ -360,13 +430,13 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! check to see if the patch has moved to the next age class currentPatch%age_class = get_age_class_index(currentPatch%age) + ! Update Canopy Biomass Pools currentCohort => currentPatch%shortest do while(associated(currentCohort)) - ft = currentCohort%pft - + ! Calculate the mortality derivatives call Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_primary ) @@ -420,6 +490,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) else is_drought = .true. end if + call PRTMaintTurnover(currentCohort%prt,ft,is_drought) ! If the current diameter of a plant is somehow less than what is consistent @@ -435,9 +506,124 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! Growth and Allocation (PARTEH) ! ----------------------------------------------------------------------------- + ! cohorts will be split during this phase to allow some fraction to recover + ! keep track of starting population + n_old = currentCohort%n + + ! track initial carbon pools + + leaf_c0 = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) + fnrt_c0 = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) + sapw_c0 = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) + struct_c0 = currentCohort%prt%GetState(struct_organ, all_carbon_elements) + store_c0 = currentCohort%prt%GetState(store_organ, all_carbon_elements) + repro_c0 = currentCohort%prt%GetState(repro_organ, all_carbon_elements) + + total_c0 = sapw_c0 + struct_c0 + leaf_c0 + fnrt_c0 + store_c0 + repro_c0 + cc_carbon = 0.0_r8 ! need to set it here to avoid nan errors if conditions aren't met below + call currentCohort%prt%DailyPRT() - + + if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + + if(currentCohort%crowndamage > 1) then + + ! N is inout boundary condition so has now been updated. The difference must + ! go to a new cohort + n_recover = n_old - currentCohort%n + + if(n_recover > nearzero) then + + allocate(nc) + if(hlm_use_planthydro .eq. itrue) call InitHydrCohort(CurrentSite,nc) + ! Initialize the PARTEH object and point to the + ! correct boundary condition fields + nc%prt => null() + call InitPRTObject(nc%prt) + call InitPRTBoundaryConditions(nc) + ! call zero_cohort(nc) + call copy_cohort(currentCohort, nc) + + nc%n = n_recover + nc%crowndamage = currentCohort%crowndamage - 1 + + ! Need to adjust the crown area which is NOT on a per individual basis + nc%c_area = nc%n/n_old * currentCohort%c_area + currentCohort%c_area = currentCohort%c_area - nc%c_area + + ! This new cohort spends carbon balance on growing out pools + ! (but not dbh) to reach new allometric targets + ! This was already calculated within parteh - this cohort should just + ! be able to hit allometric targets of one damage class down + call nc%prt%DamageRecovery() + + ! at this point we need to update fluxes or this cohort will + ! fail its mass conservation checks + + sapw_c = nc%prt%GetState(sapw_organ, all_carbon_elements) + struct_c = nc%prt%GetState(struct_organ, all_carbon_elements) + leaf_c = nc%prt%GetState(leaf_organ, all_carbon_elements) + fnrt_c = nc%prt%GetState(fnrt_organ, all_carbon_elements) + store_c = nc%prt%GetState(store_organ, all_carbon_elements) + repro_c = nc%prt%GetState(repro_organ, all_carbon_elements) + nc_carbon = sapw_c + struct_c + leaf_c + fnrt_c + store_c + repro_c + + cc_sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) + cc_struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) + cc_leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) + cc_fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) + cc_store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) + cc_repro_c = currentCohort%prt%GetState(repro_organ, all_carbon_elements) + cc_carbon = cc_sapw_c + cc_struct_c + cc_leaf_c + cc_fnrt_c + cc_store_c + cc_repro_c + + + call PRTDamageRecoveryFluxes(nc%prt, leaf_organ, leaf_c0, leaf_c, cc_leaf_c) + call PRTDamageRecoveryFluxes(nc%prt, repro_organ, repro_c0, repro_c, cc_repro_c) + call PRTDamageRecoveryFluxes(nc%prt, sapw_organ, sapw_c0, sapw_c, cc_sapw_c) + call PRTDamageRecoveryFluxes(nc%prt, struct_organ, struct_c0, struct_c, cc_struct_c) + call PRTDamageRecoveryFluxes(nc%prt, store_organ, store_c0, store_c, cc_store_c) + call PRTDamageRecoveryFluxes(nc%prt, fnrt_organ, fnrt_c0, fnrt_c, cc_fnrt_c) + + ! update crown area + call carea_allom(nc%dbh, nc%n, currentSite%spread, nc%pft, nc%crowndamage, nc%c_area) + call carea_allom(currentCohort%dbh, currentCohort%n, currentSite%spread, & + currentCohort%pft, currentCohort%crowndamage, currentCohort%c_area) + + + currentSite%recovery_rate(currentCohort%crowndamage, nc%crowndamage) = & + currentSite%recovery_rate(currentCohort%crowndamage, nc%crowndamage) + nc%n + currentSite%recovery_cflux(currentCohort%crowndamage, nc%crowndamage) = & + currentSite%recovery_cflux(currentCohort%crowndamage, nc%crowndamage) + & + nc%n * nc_carbon + + !----------- Insert copy into linked list ----------------------! + nc%shorter => currentCohort + if(associated(currentCohort%taller))then + nc%taller => currentCohort%taller + currentCohort%taller%shorter => nc + else + currentPatch%tallest => nc + nc%taller => null() + endif + currentCohort%taller => nc + + end if ! end if greater than nearzero + + end if ! end if crowndamage > 1 + + + ! fill in the diagonals - i.e. those that did not recover + currentSite%recovery_rate(currentCohort%crowndamage, currentCohort%crowndamage) = & + currentSite%recovery_rate(currentCohort%crowndamage, currentCohort%crowndamage) +& + currentCohort%n + currentSite%recovery_cflux(currentCohort%crowndamage, currentCohort%crowndamage) = & + currentSite%recovery_cflux(currentCohort%crowndamage, currentCohort%crowndamage) + & + currentCohort%n * cc_carbon + + end if ! end if crowndamage is on + + ! Update the mass balance tracking for the daily nutrient uptake flux ! Then zero out the daily uptakes, they have been used ! ----------------------------------------------------------------------------- @@ -567,15 +753,16 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentCohort%coage_class,currentCohort%coage_by_pft_class) end if - + currentCohort => currentCohort%taller - end do + + + end do currentPatch => currentPatch%older end do - - ! When plants die, the water goes with them. This effects + ! When plants die, the water goes with them. This effects ! the water balance. if( hlm_use_planthydro == itrue ) then @@ -682,9 +869,8 @@ subroutine ed_update_site( currentSite, bc_in, bc_out ) ! This cohort count is used in the photosynthesis loop call count_cohorts(currentPatch) - currentPatch => currentPatch%younger - enddo + enddo ! The HLMs need to know about nutrient demand, and/or ! root mass and affinities @@ -931,6 +1117,7 @@ subroutine bypass_dynamics(currentSite) currentCohort%frmort = 0.0_r8 currentCohort%smort = 0.0_r8 currentCohort%asmort = 0.0_r8 + currentCohort%dgmort = 0.0_r8 currentCohort%dndt = 0.0_r8 currentCohort%dhdt = 0.0_r8 diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 1f10aa2c7f..e37190c921 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -42,6 +42,7 @@ module EDParamsMod real(r8),protected, public :: ED_val_init_litter real(r8),protected, public :: ED_val_nignitions real(r8),protected, public :: ED_val_understorey_death + real(r8),protected, public :: ED_val_ncrowndamage real(r8),protected, public :: ED_val_cwd_fcel real(r8),protected, public :: ED_val_cwd_flig real(r8),protected, public :: ED_val_base_mr_20 @@ -102,6 +103,7 @@ module EDParamsMod character(len=param_string_length),parameter,public :: ED_name_init_litter = "fates_init_litter" character(len=param_string_length),parameter,public :: ED_name_nignitions = "fates_fire_nignitions" character(len=param_string_length),parameter,public :: ED_name_understorey_death = "fates_mort_understorey_death" + character(len=param_string_length),parameter,public :: ED_name_ncrowndamage = 'fates_ncrowndamage' character(len=param_string_length),parameter,public :: ED_name_cwd_fcel= "fates_cwd_fcel" character(len=param_string_length),parameter,public :: ED_name_cwd_flig= "fates_cwd_flig" character(len=param_string_length),parameter,public :: ED_name_base_mr_20= "fates_base_mr_20" @@ -130,8 +132,10 @@ module EDParamsMod character(len=param_string_length),parameter,public :: ED_name_history_sizeclass_bin_edges= "fates_history_sizeclass_bin_edges" character(len=param_string_length),parameter,public :: ED_name_history_ageclass_bin_edges= "fates_history_ageclass_bin_edges" character(len=param_string_length),parameter,public :: ED_name_history_height_bin_edges= "fates_history_height_bin_edges" + character(len=param_string_length),parameter,public :: ED_name_history_coageclass_bin_edges = "fates_history_coageclass_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 @@ -152,7 +156,8 @@ module EDParamsMod ! ---------------------------------------------------------------------------------------------- real(r8),protected,public :: bgc_soil_salinity ! site-level soil salinity for FATES when not coupled to dynamic soil BGC of salinity character(len=param_string_length),parameter,public :: bgc_name_soil_salinity= "fates_soil_salinity" - + + ! Logging Control Parameters (ONLY RELEVANT WHEN USE_FATES_LOGGING = TRUE) ! ---------------------------------------------------------------------------------------------- @@ -219,6 +224,7 @@ subroutine FatesParamsInit() ED_val_init_litter = nan ED_val_nignitions = nan ED_val_understorey_death = nan + ED_val_ncrowndamage = nan ED_val_cwd_fcel = nan ED_val_cwd_flig = nan ED_val_base_mr_20 = nan @@ -269,7 +275,6 @@ subroutine FatesRegisterParams(fates_params) use FatesParametersInterface, only : dimension_name_history_coage_bins use FatesParametersInterface, only : dimension_shape_scalar - implicit none class(fates_parameters_type), intent(inout) :: fates_params @@ -319,6 +324,9 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=ED_name_understorey_death, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=ED_name_ncrowndamage, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=ED_name_cwd_fcel, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -384,7 +392,7 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=bgc_name_soil_salinity, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) - + call fates_params%RegisterParameter(name=logging_name_dbhmin, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -462,7 +470,7 @@ subroutine FatesReceiveParams(fates_params) real(r8) :: tmpreal ! local real variable for changing type on read real(r8), allocatable :: hydr_htftype_real(:) - + call fates_params%RetreiveParameter(name=ED_name_vai_top_bin_width, & data=vai_top_bin_width) @@ -495,6 +503,9 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetreiveParameter(name=ED_name_understorey_death, & data=ED_val_understorey_death) + call fates_params%RetreiveParameter(name=ED_name_ncrowndamage, & + data=ED_val_ncrowndamage) + call fates_params%RetreiveParameter(name=ED_name_cwd_fcel, & data=ED_val_cwd_fcel) @@ -560,7 +571,7 @@ subroutine FatesReceiveParams(fates_params) data=hydr_psicap) call fates_params%RetreiveParameter(name=bgc_name_soil_salinity, & - data=bgc_soil_salinity) + data=bgc_soil_salinity) call fates_params%RetreiveParameter(name=logging_name_dbhmin, & data=logging_dbhmin) @@ -623,7 +634,7 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetreiveParameterAllocate(name=ED_name_history_height_bin_edges, & data=ED_val_history_height_bin_edges) - + call fates_params%RetreiveParameterAllocate(name=ED_name_history_coageclass_bin_edges, & data=ED_val_history_coageclass_bin_edges) @@ -657,6 +668,7 @@ subroutine FatesReportParams(is_master) write(fates_log(),fmt0) 'ED_val_init_litter = ',ED_val_init_litter write(fates_log(),fmt0) 'ED_val_nignitions = ',ED_val_nignitions write(fates_log(),fmt0) 'ED_val_understorey_death = ',ED_val_understorey_death + write(fates_log(),fmt0) 'ED_val_ncrowndamage = ', ED_val_ncrowndamage write(fates_log(),fmt0) 'ED_val_cwd_fcel = ',ED_val_cwd_fcel write(fates_log(),fmt0) 'ED_val_cwd_flig = ',ED_val_cwd_flig write(fates_log(),fmt0) 'ED_val_base_mr_20 = ', ED_val_base_mr_20 diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 030f15738f..3e932a51ed 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -109,6 +109,12 @@ module EDPftvarcon real(r8), allocatable :: taul(:, :) real(r8), allocatable :: taus(:, :) + + ! Damage parameters + real(r8), allocatable :: damage_frac(:) ! Fraction of each cohort damaged per year + real(r8), allocatable :: damage_mort_p1(:) ! Inflection point for damage mortality function + real(r8), allocatable :: damage_mort_p2(:) ! Rate parameter for damage mortality function + ! Fire Parameters (No PFT vector capabilities in their own routines) ! See fire/SFParamsMod.F90 for bulk of fire parameters ! ------------------------------------------------------------------------------------------- @@ -118,7 +124,6 @@ module EDPftvarcon ! Non-PARTEH Allometry Parameters ! -------------------------------------------------------------------------------------------- - real(r8), allocatable :: allom_frbstor_repro(:) ! fraction of bstrore for reproduction after mortality ! Prescribed Physiology Mode Parameters @@ -296,8 +301,7 @@ subroutine Receive(this, fates_params) call this%Receive_PFT_numrad(fates_params) call this%Receive_PFT_hydr_organs(fates_params) call this%Receive_PFT_leafage(fates_params) - - end subroutine Receive + end subroutine Receive !----------------------------------------------------------------------- subroutine Register_PFT(this, fates_params) @@ -544,6 +548,18 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_damage_frac' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_damage_mort_p1' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_damage_mort_p2' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_trim_limit' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -891,6 +907,18 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=this%seed_decay_rate) + name = 'fates_damage_frac' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%damage_frac) + + name = 'fates_damage_mort_p1' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%damage_mort_p1) + + name = 'fates_damage_mort_p2' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%damage_mort_p2) + name = 'fates_trim_limit' call fates_params%RetreiveParameterAllocate(name=name, & data=this%trim_limit) @@ -1430,6 +1458,9 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'jmaxhd = ',EDPftvarcon_inst%jmaxhd write(fates_log(),fmt0) 'vcmaxse = ',EDPftvarcon_inst%vcmaxse write(fates_log(),fmt0) 'jmaxse = ',EDPftvarcon_inst%jmaxse + write(fates_log(),fmt0) 'damage_frac = ',EDPftvarcon_inst%damage_frac + write(fates_log(),fmt0) 'damage_mort_p1 = ',EDPftvarcon_inst%damage_mort_p1 + write(fates_log(),fmt0) 'damage_mort_p2 = ',EDPftvarcon_inst%damage_mort_p2 write(fates_log(),fmt0) 'germination_timescale = ',EDPftvarcon_inst%germination_rate write(fates_log(),fmt0) 'seed_decay_turnover = ',EDPftvarcon_inst%seed_decay_rate write(fates_log(),fmt0) 'trim_limit = ',EDPftvarcon_inst%trim_limit @@ -1507,7 +1538,6 @@ subroutine FatesCheckParams(is_master) if(.not.is_master) return - if (hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) then ! Check to see if either RD/ECA/MIC is turned on @@ -1733,6 +1763,7 @@ subroutine FatesCheckParams(is_master) end if + ! Check if photosynthetic pathway is neither C3/C4 ! ---------------------------------------------------------------------------------- diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index b7d3eedb96..5fde9eef56 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -28,21 +28,21 @@ module EDTypesMod integer, parameter, public :: maxPatchesPerSite = 14 ! maximum number of patches to live on a site integer, parameter, public :: maxPatchesPerSite_by_disttype(n_anthro_disturbance_categories) = & (/ 10, 4 /) !!! MUST SUM TO maxPatchesPerSite !!! - integer, public :: maxCohortsPerPatch = 100 ! maximum number of cohorts per patch + integer, public :: maxCohortsPerPatch = 300 ! maximum number of cohorts per patch - integer, parameter, public :: nclmax = 2 ! Maximum number of canopy layers + integer, parameter, public :: nclmax = 3 ! Maximum number of canopy layers integer, parameter, public :: ican_upper = 1 ! Nominal index for the upper canopy integer, parameter, public :: ican_ustory = 2 ! Nominal index for diagnostics that refer ! to understory layers (all layers that ! are not the top canopy layer) + integer, parameter, public :: nlevleaf = 30 ! number of leaf layers in canopy layer integer, parameter, public :: maxpft = 16 ! maximum number of PFTs allowed ! the parameter file may determine that fewer ! are used, but this helps allocate scratch ! space and output arrays. - real(r8), parameter, public :: init_recruit_trim = 0.8_r8 ! This is the initial trimming value that ! new recruits start with @@ -166,7 +166,7 @@ module EDTypesMod ! COHORT TERMINATION - real(r8), parameter, public :: min_npm2 = 1.0E-7_r8 ! minimum cohort number density per m2 before termination + real(r8), parameter, public :: min_npm2 = 1.0E-12_r8 ! minimum cohort number density per m2 before termination real(r8), parameter, public :: min_patch_area = 0.01_r8 ! smallest allowable patch area before termination real(r8), parameter, public :: min_patch_area_forced = 0.0001_r8 ! patch termination will not fuse the youngest patch ! if the area is less than min_patch_area. @@ -174,7 +174,7 @@ module EDTypesMod ! if the fusion area is less than min_patch_area_forced real(r8), parameter, public :: min_nppatch = min_npm2*min_patch_area ! minimum number of cohorts per patch (min_npm2*min_patch_area) - real(r8), parameter, public :: min_n_safemath = 1.0E-12_r8 ! in some cases, we want to immediately remove super small + real(r8), parameter, public :: min_n_safemath = 1.0E-15_r8 ! in some cases, we want to immediately remove super small ! number densities of cohorts to prevent FPEs character*4 yearchar @@ -220,6 +220,7 @@ module EDTypesMod real(r8) :: sapwmemory ! target sapwood biomass- set from previous year: kGC per indiv real(r8) :: structmemory ! target structural biomass- set from previous year: kGC per indiv integer :: canopy_layer ! canopy status of cohort (1 = canopy, 2 = understorey, etc.) + integer :: crowndamage ! crown damage class of the cohort real(r8) :: canopy_layer_yesterday ! recent canopy status of cohort ! (1 = canopy, 2 = understorey, etc.) ! real to be conservative during fusion @@ -325,6 +326,7 @@ module EDTypesMod real(r8) :: ts_net_uptake(nlevleaf) ! Net uptake of leaf layers: kgC/m2/timestep real(r8) :: year_net_uptake(nlevleaf) ! Net uptake of leaf layers: kgC/m2/year + ! RESPIRATION COMPONENTS real(r8) :: rdark ! Dark respiration: kgC/indiv/s @@ -340,6 +342,9 @@ module EDTypesMod ! (below ground) real(r8) :: froot_mr ! Live fine root maintenance respiration: kgC/indiv/s + !DAMAGE + real(r8) :: branch_frac ! Fraction of aboveground biomass in branches + !MORTALITY real(r8) :: dmort ! proportional mortality rate. (year-1) @@ -350,6 +355,7 @@ module EDTypesMod real(r8) :: frmort ! freezing mortality n/year real(r8) :: smort ! senesence mortality n/year real(r8) :: asmort ! age senescence mortality n/year + real(r8) :: dgmort ! damage mortality n/year ! Logging Mortality Rate ! Yi Xu & M. Huang @@ -782,11 +788,19 @@ module EDTypesMod ! with termination mortality, per canopy level real(r8) :: term_carbonflux_ustory ! carbon flux from live to dead pools associated ! with termination mortality, per canopy level + + real(r8) :: term_crownarea_canopy ! crownarea from termination mortality, per canopy level + real(r8) :: term_crownarea_ustory ! crownarea from termination mortality, per canopy level + real(r8) :: demotion_carbonflux ! biomass of demoted individuals from canopy to understory [kgC/ha/day] real(r8) :: promotion_carbonflux ! biomass of promoted individuals from understory to canopy [kgC/ha/day] real(r8) :: imort_carbonflux ! biomass of individuals killed due to impact mortality per year. [kgC/ha/day] + real(r8) :: imort_crownarea ! crownarea of individuals killed due to impact mortality per year. [m2 day] + real(r8) :: fmort_carbonflux_canopy ! biomass of canopy indivs killed due to fire per year. [gC/m2/sec] real(r8) :: fmort_carbonflux_ustory ! biomass of understory indivs killed due to fire per year [gC/m2/sec] + real(r8) :: fmort_crownarea_canopy ! crownarea of canopy indivs killed due to fire per year. [m2/sec] + real(r8) :: fmort_crownarea_ustory ! crownarea of understory indivs killed due to fire per year [m2/sec] real(r8) :: recruitment_rate(1:maxpft) ! number of individuals that were recruited into new cohorts real(r8), allocatable :: demotion_rate(:) ! rate of individuals demoted from canopy to understory per FATES timestep @@ -809,8 +823,26 @@ module EDTypesMod real(r8), allocatable :: growthflux_fusion(:,:) ! rate of individuals moving into a given size class bin ! due to fusion in a given day. on size x pft array - - + ! Damage fluxes + real(r8), allocatable :: damage_cflux(:,:) ! carbon flux into each damage class each timestep + real(r8), allocatable :: damage_rate(:,:) ! number of individuals moving into a damage class + real(r8), allocatable :: recovery_cflux(:,:) ! carbon flux from recovery each timestep + real(r8), allocatable :: recovery_rate(:,:) ! number of individuals recovering each timesept + + real(r8), allocatable :: imort_rate_damage(:,:,:) ! number of individuals per damage class that die from impact mortality + real(r8), allocatable :: term_nindivs_canopy_damage(:,:,:) ! number of individuals per damage class that die from termination mortality - canopy + real(r8), allocatable :: term_nindivs_ustory_damage(:,:,:) ! number of individuals per damage class that die from termination mortality - canopy + real(r8), allocatable :: fmort_rate_canopy_damage(:,:,:) ! number of individuals per damage class that die from fire - canopy + real(r8), allocatable :: fmort_rate_ustory_damage(:,:,:) ! number of individuals per damage class that die from fire - ustory + real(r8), allocatable :: fmort_cflux_canopy_damage(:,:) ! cflux per damage class that die from fire - canopy + real(r8), allocatable :: fmort_cflux_ustory_damage(:,:) ! cflux per damage class that die from fire - ustory + real(r8), allocatable :: imort_cflux_damage(:,:) ! carbon flux from impact mortality by damage class + real(r8), allocatable :: term_cflux_canopy_damage(:,:) ! carbon flux from termination mortality by damage class + real(r8), allocatable :: term_cflux_ustory_damage(:,:) ! carbon flux from termination mortality by damage class + + real(r8) :: crownarea_canopy_damage ! crown area of canopy that is damaged annually + real(r8) :: crownarea_ustory_damage ! crown area of understory that is damaged annually + ! Canopy Spread real(r8) :: spread ! dynamic canopy allometric term [unitless] @@ -1029,6 +1061,7 @@ subroutine dump_cohort(ccohort) write(fates_log(),*) 'co%n = ', ccohort%n write(fates_log(),*) 'co%dbh = ', ccohort%dbh write(fates_log(),*) 'co%hite = ', ccohort%hite + write(fates_log(),*) 'co%crowndamage = ', ccohort%crowndamage write(fates_log(),*) 'co%coage = ', ccohort%coage write(fates_log(),*) 'co%laimemory = ', ccohort%laimemory write(fates_log(),*) 'co%sapwmemory = ', ccohort%sapwmemory @@ -1072,7 +1105,7 @@ subroutine dump_cohort(ccohort) write(fates_log(),*) 'co%livestem_mr = ', ccohort%livestem_mr write(fates_log(),*) 'co%livecroot_mr = ', ccohort%livecroot_mr write(fates_log(),*) 'co%froot_mr = ', ccohort%froot_mr - write(fates_log(),*) 'co%dmort = ', ccohort%dmort + write(fates_log(),*) 'co%dgmort = ', ccohort%dgmort write(fates_log(),*) 'co%treelai = ', ccohort%treelai write(fates_log(),*) 'co%treesai = ', ccohort%treesai write(fates_log(),*) 'co%c_area = ', ccohort%c_area @@ -1080,9 +1113,9 @@ subroutine dump_cohort(ccohort) write(fates_log(),*) 'co%bmort = ', ccohort%bmort write(fates_log(),*) 'co%smort = ', ccohort%smort write(fates_log(),*) 'co%asmort = ', ccohort%asmort + write(fates_log(),*) 'co%dgmort = ', ccohort%dgmort write(fates_log(),*) 'co%hmort = ', ccohort%hmort write(fates_log(),*) 'co%frmort = ', ccohort%frmort - write(fates_log(),*) 'co%asmort = ', ccohort%asmort write(fates_log(),*) 'co%isnew = ', ccohort%isnew write(fates_log(),*) 'co%dndt = ', ccohort%dndt write(fates_log(),*) 'co%dhdt = ', ccohort%dhdt diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 97f3342b43..7232bc84f7 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -1,4 +1,4 @@ -module FatesHistoryInterfaceMod +Module FatesHistoryInterfaceMod use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : fates_avg_flag_length @@ -36,6 +36,8 @@ module FatesHistoryInterfaceMod use FatesInterfaceTypesMod , only : hlm_use_planthydro use FatesInterfaceTypesMod , only : hlm_use_ed_st3 use FatesInterfaceTypesMod , only : hlm_use_cohort_age_tracking + use FatesInterfaceTypesMod , only : hlm_use_canopy_damage + use FatesInterfaceTypesMod , only : hlm_use_understory_damage use FatesInterfaceTypesMod , only : numpft use FatesInterfaceTypesMod , only : hlm_freq_day use FatesInterfaceTypesMod , only : hlm_parteh_mode @@ -46,6 +48,7 @@ module FatesHistoryInterfaceMod use FatesInterfaceTypesMod , only : bc_in_type use FatesInterfaceTypesMod , only : hlm_model_day use FatesInterfaceTypesMod , only : nlevcoage + use FatesInterfaceTypesMod , only : ncrowndamage ! FIXME(bja, 2016-10) need to remove CLM dependancy use EDPftvarcon , only : EDPftvarcon_inst @@ -55,6 +58,8 @@ module FatesHistoryInterfaceMod use shr_log_mod , only : errMsg => shr_log_errMsg use shr_infnan_mod , only : isnan => shr_infnan_isnan use FatesConstantsMod , only : g_per_kg + use FatesConstantsMod , only : kg_per_g + use FatesConstantsMod , only : m2_per_ha use FatesConstantsMod , only : ha_per_m2 use FatesConstantsMod , only : days_per_sec use FatesConstantsMod , only : sec_per_day @@ -317,6 +322,8 @@ module FatesHistoryInterfaceMod integer :: ih_promotion_carbonflux_si integer :: ih_canopy_mortality_carbonflux_si integer :: ih_understory_mortality_carbonflux_si + integer :: ih_canopy_mortality_crownarea_si + integer :: ih_understory_mortality_crownarea_si integer :: ih_canopy_spread_si integer :: ih_npp_leaf_si integer :: ih_npp_seed_si @@ -381,6 +388,8 @@ module FatesHistoryInterfaceMod integer :: ih_mortality_canopy_si_scpf integer :: ih_mortality_understory_si_scpf + integer :: ih_m3_mortality_canopy_si_scpf + integer :: ih_m3_mortality_understory_si_scpf integer :: ih_nplant_canopy_si_scpf integer :: ih_nplant_understory_si_scpf integer :: ih_ddbh_canopy_si_scpf @@ -405,12 +414,11 @@ module FatesHistoryInterfaceMod integer :: ih_m8_si_scpf integer :: ih_m9_si_scpf integer :: ih_m10_si_scpf + integer :: ih_m11_si_scpf integer :: ih_crownfiremort_si_scpf integer :: ih_cambialfiremort_si_scpf - integer :: ih_m10_si_capf integer :: ih_nplant_si_capf - integer :: ih_ar_si_scpf integer :: ih_ar_grow_si_scpf integer :: ih_ar_maint_si_scpf @@ -432,6 +440,8 @@ module FatesHistoryInterfaceMod integer :: ih_sai_understory_si_scls integer :: ih_mortality_canopy_si_scls integer :: ih_mortality_understory_si_scls + integer :: ih_m3_mortality_canopy_si_scls + integer :: ih_m3_mortality_understory_si_scls integer :: ih_demotion_rate_si_scls integer :: ih_promotion_rate_si_scls integer :: ih_trimming_canopy_si_scls @@ -442,8 +452,8 @@ module FatesHistoryInterfaceMod integer :: ih_ddbh_understory_si_scls integer :: ih_agb_si_scls integer :: ih_biomass_si_scls - - ! mortality vars + + ! mortality var integer :: ih_m1_si_scls integer :: ih_m2_si_scls integer :: ih_m3_si_scls @@ -454,6 +464,7 @@ module FatesHistoryInterfaceMod integer :: ih_m8_si_scls integer :: ih_m9_si_scls integer :: ih_m10_si_scls + integer :: ih_m11_si_scls integer :: ih_m10_si_cacls integer :: ih_nplant_si_cacls @@ -620,6 +631,54 @@ module FatesHistoryInterfaceMod integer :: ih_parprof_dir_si_cnlfpft integer :: ih_parprof_dif_si_cnlfpft + ! indices to site x crown damage variables + ! site x crown damage x pft x sizeclass + ! site x crown damage x size class + integer :: ih_nplant_si_cdpf + integer :: ih_nplant_si_cdsc + integer :: ih_nplant_canopy_si_cdpf + integer :: ih_nplant_understory_si_cdpf + integer :: ih_nplant_canopy_si_cdsc + integer :: ih_nplant_understory_si_cdsc + integer :: ih_mortality_si_cdsc + integer :: ih_mortality_si_cdpf + integer :: ih_mortality_canopy_si_cdpf + integer :: ih_mortality_understory_si_cdpf + integer :: ih_m3_si_cdpf + integer :: ih_m3_si_cdsc + integer :: ih_m11_si_cdpf + integer :: ih_m11_si_cdsc + integer :: ih_m3_mortality_canopy_si_cdsc + integer :: ih_m3_mortality_understory_si_cdsc + integer :: ih_m3_mortality_canopy_si_cdpf + integer :: ih_m3_mortality_understory_si_cdpf + integer :: ih_m11_mortality_canopy_si_cdsc + integer :: ih_m11_mortality_understory_si_cdsc + integer :: ih_m11_mortality_canopy_si_cdpf + integer :: ih_m11_mortality_understory_si_cdpf + integer :: ih_trimming_damage_si_cdsc + integer :: ih_ddbh_si_cdsc + integer :: ih_ddbh_si_cdpf + integer :: ih_ddbh_canopy_si_cdpf + integer :: ih_ddbh_understory_si_cdpf + + ! damage carbonflux + integer :: ih_damage_cflux_si_cdcd + integer :: ih_damage_rate_si_cdcd + integer :: ih_recovery_cflux_si_cdcd + integer :: ih_recovery_rate_si_cdcd + integer :: ih_crownarea_canopy_damage_si + integer :: ih_crownarea_ustory_damage_si + + integer :: ih_totvegc_cdpf + integer :: ih_leafc_cdpf + integer :: ih_fnrtc_cdpf + integer :: ih_storec_cdpf + integer :: ih_sapwc_cdpf + integer :: ih_reproc_cdpf + integer :: ih_cefflux_cdpf + + ! indices to (site x canopy layer) variables integer :: ih_parsun_top_si_can integer :: ih_parsha_top_si_can @@ -660,6 +719,8 @@ module FatesHistoryInterfaceMod integer, private :: levscls_index_, levpft_index_, levage_index_ integer, private :: levfuel_index_, levcwdsc_index_, levscag_index_ integer, private :: levcan_index_, levcnlf_index_, levcnlfpft_index_ + integer, private :: levcdpf_index_, levcdsc_index_ + integer, private :: levcdcd_index_ integer, private :: levscagpft_index_, levagepft_index_ integer, private :: levheight_index_, levagefuel_index_ integer, private :: levelem_index_, levelpft_index_ @@ -695,6 +756,9 @@ module FatesHistoryInterfaceMod procedure :: levcan_index procedure :: levcnlf_index procedure :: levcnlfpft_index + procedure :: levcdcd_index + procedure :: levcdpf_index + procedure :: levcdsc_index procedure :: levscag_index procedure :: levscagpft_index procedure :: levagepft_index @@ -724,6 +788,9 @@ module FatesHistoryInterfaceMod procedure, private :: set_levcan_index procedure, private :: set_levcnlf_index procedure, private :: set_levcnlfpft_index + procedure, private :: set_levcdcd_index + procedure, private :: set_levcdpf_index + procedure, private :: set_levcdsc_index procedure, private :: set_levscag_index procedure, private :: set_levscagpft_index procedure, private :: set_levagepft_index @@ -760,6 +827,8 @@ subroutine Init(this, num_threads, fates_bounds) use FatesIODimensionsMod, only : levfuel, levcwdsc, levscag use FatesIODimensionsMod, only : levscagpft, levagepft use FatesIODimensionsMod, only : levcan, levcnlf, levcnlfpft + use FatesIODimensionsMod, only : levcdpf, levcdsc + use FatesIODimensionsMod, only : levcdcd use FatesIODimensionsMod, only : fates_bounds_type use FatesIODimensionsMod, only : levheight, levagefuel use FatesIODimensionsMod, only : levelem, levelpft @@ -843,6 +912,21 @@ subroutine Init(this, num_threads, fates_bounds) call this%dim_bounds(dim_count)%Init(levcnlfpft, num_threads, & fates_bounds%cnlfpft_begin, fates_bounds%cnlfpft_end) + dim_count = dim_count + 1 + call this%set_levcdcd_index(dim_count) + call this%dim_bounds(dim_count)%Init(levcdcd, num_threads, & + fates_bounds%cdcd_begin, fates_bounds%cdcd_end) + + dim_count = dim_count + 1 + call this%set_levcdpf_index(dim_count) + call this%dim_bounds(dim_count)%Init(levcdpf, num_threads, & + fates_bounds%cdpf_begin, fates_bounds%cdpf_end) + + dim_count = dim_count + 1 + call this%set_levcdsc_index(dim_count) + call this%dim_bounds(dim_count)%Init(levcdsc, num_threads, & + fates_bounds%cdsc_begin, fates_bounds%cdsc_end) + dim_count = dim_count + 1 call this%set_levscag_index(dim_count) call this%dim_bounds(dim_count)%Init(levscag, num_threads, & @@ -959,7 +1043,19 @@ subroutine SetThreadBoundsEach(this, thread_index, thread_bounds) index = this%levcnlfpft_index() call this%dim_bounds(index)%SetThreadBounds(thread_index, & thread_bounds%cnlfpft_begin, thread_bounds%cnlfpft_end) + + index = this%levcdcd_index() + call this%dim_bounds(index)%SetThreadBounds(thread_index, & + thread_bounds%cdcd_begin, thread_bounds%cdcd_end) + index = this%levcdpf_index() + call this%dim_bounds(index)%SetThreadBounds(thread_index, & + thread_bounds%cdpf_begin, thread_bounds%cdpf_end) + + index = this%levcdsc_index() + call this%dim_bounds(index)%SetThreadBounds(thread_index, & + thread_bounds%cdsc_begin, thread_bounds%cdsc_end) + index = this%levscag_index() call this%dim_bounds(index)%SetThreadBounds(thread_index, & thread_bounds%sizeage_class_begin, thread_bounds%sizeage_class_end) @@ -1012,6 +1108,7 @@ subroutine assemble_history_output_types(this) use FatesIOVariableKindMod, only : site_fuel_r8, site_cwdsc_r8, site_scag_r8 use FatesIOVariableKindMod, only : site_scagpft_r8, site_agepft_r8 use FatesIOVariableKindMod, only : site_can_r8, site_cnlf_r8, site_cnlfpft_r8 + use FatesIOVariableKindMod, only : site_cdpf_r8, site_cdsc_r8, site_cdcd_r8 use FatesIOVariableKindMod, only : site_height_r8, site_agefuel_r8 use FatesIOVariableKindMod, only : site_elem_r8, site_elpft_r8 use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8 @@ -1068,6 +1165,15 @@ subroutine assemble_history_output_types(this) call this%set_dim_indices(site_cnlfpft_r8, 1, this%column_index()) call this%set_dim_indices(site_cnlfpft_r8, 2, this%levcnlfpft_index()) + call this%set_dim_indices(site_cdcd_r8, 1, this%column_index()) + call this%set_dim_indices(site_cdcd_r8, 2, this%levcdcd_index()) + + call this%set_dim_indices(site_cdpf_r8, 1, this%column_index()) + call this%set_dim_indices(site_cdpf_r8, 2, this%levcdpf_index()) + + call this%set_dim_indices(site_cdsc_r8, 1, this%column_index()) + call this%set_dim_indices(site_cdsc_r8, 2, this%levcdsc_index()) + call this%set_dim_indices(site_scag_r8, 1, this%column_index()) call this%set_dim_indices(site_scag_r8, 2, this%levscag_index()) @@ -1334,6 +1440,48 @@ integer function levcnlfpft_index(this) class(fates_history_interface_type), intent(in) :: this levcnlfpft_index = this%levcnlfpft_index_ end function levcnlfpft_index + + ! ======================================================================= + subroutine set_levcdcd_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levcdcd_index_ = index + end subroutine set_levcdcd_index + + integer function levcdcd_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levcdcd_index = this%levcdcd_index_ + end function levcdcd_index + +! ======================================================================= + subroutine set_levcdpf_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levcdpf_index_ = index + end subroutine set_levcdpf_index + + integer function levcdpf_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levcdpf_index = this%levcdpf_index_ + end function levcdpf_index + + ! ======================================================================= + subroutine set_levcdsc_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levcdsc_index_ = index + end subroutine set_levcdsc_index + + integer function levcdsc_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levcdsc_index = this%levcdsc_index_ + end function levcdsc_index ! ====================================================================================== subroutine set_levscag_index(this, index) @@ -1561,6 +1709,8 @@ subroutine init_dim_kinds_maps(this) use FatesIOVariableKindMod, only : site_fuel_r8, site_cwdsc_r8, site_scag_r8 use FatesIOVariableKindMod, only : site_scagpft_r8, site_agepft_r8 use FatesIOVariableKindMod, only : site_can_r8, site_cnlf_r8, site_cnlfpft_r8 + use FatesIOVariableKindMod, only : site_cdpf_r8, site_cdsc_r8 + use FatesIOVariableKindMod, only : site_cdcd_r8 use FatesIOVariableKindMod, only : site_height_r8, site_agefuel_r8 use FatesIOVariableKindMod, only : site_elem_r8, site_elpft_r8 use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8 @@ -1637,6 +1787,19 @@ subroutine init_dim_kinds_maps(this) index = index + 1 call this%dim_kinds(index)%Init(site_cnlfpft_r8, 2) + ! site x crown damage x crown damage class + index = index + 1 + call this%dim_kinds(index)%Init(site_cdcd_r8, 2) + + ! site x crown damage x pft x size class + index = index + 1 + call this%dim_kinds(index)%Init(site_cdpf_r8, 2) + + ! site x crowndamage x size class + index = index + 1 + call this%dim_kinds(index)%Init(site_cdsc_r8, 2) + + ! site x size-class x age class index = index + 1 call this%dim_kinds(index)%Init(site_scag_r8, 2) @@ -1702,9 +1865,13 @@ subroutine update_history_dyn(this,nc,nsites,sites) use FatesSizeAgeTypeIndicesMod, only : get_age_class_index use FatesSizeAgeTypeIndicesMod, only : get_height_index use FatesSizeAgeTypeIndicesMod, only : sizetype_class_index + use FatesSizeAgeTypeIndicesMod, only : get_cdamagesize_class_index + use FatesSizeAgeTypeIndicesMod, only : get_cdamagesizepft_class_index use FatesSizeAgeTypeIndicesMod, only : coagetype_class_index - use EDTypesMod , only : nlevleaf - use EDParamsMod , only : ED_val_history_height_bin_edges + use EDTypesMod , only : nlevleaf + use EDParamsMod, only : ED_val_history_height_bin_edges + use FatesInterfaceTypesMod, only : ncrowndamage + use DamageMainMod , only : damage_time ! Arguments class(fates_history_interface_type) :: this @@ -1736,6 +1903,9 @@ subroutine update_history_dyn(this,nc,nsites,sites) integer :: iagepft ! age x pft index integer :: i_agefuel ! age x fuel size class index integer :: ican, ileaf, cnlf_indx ! iterators for leaf and canopy level + integer :: icdpf, icdsc, icdcd, icdi, icdj, icdam, imcdam ! iterators for the crown damage level + integer :: cdpf, cdsc + integer :: counter integer :: height_bin_max, height_bin_min ! which height bin a given cohort's canopy is in integer :: i_heightbin ! iterator for height bins integer :: el ! Loop index for elements @@ -1781,6 +1951,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) real(r8), parameter :: tiny = 1.e-5_r8 ! some small number real(r8), parameter :: reallytalltrees = 1000. ! some large number (m) + + real(r8) :: total_c ! for damage integer :: tmp @@ -1869,6 +2041,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_bleaf_understory_si_scpf => this%hvars(ih_bleaf_understory_si_scpf)%r82d, & hio_mortality_canopy_si_scpf => this%hvars(ih_mortality_canopy_si_scpf)%r82d, & hio_mortality_understory_si_scpf => this%hvars(ih_mortality_understory_si_scpf)%r82d, & + hio_m3_mortality_canopy_si_scpf => this%hvars(ih_m3_mortality_canopy_si_scpf)%r82d, & + hio_m3_mortality_understory_si_scpf => this%hvars(ih_m3_mortality_understory_si_scpf)%r82d, & hio_nplant_canopy_si_scpf => this%hvars(ih_nplant_canopy_si_scpf)%r82d, & hio_nplant_understory_si_scpf => this%hvars(ih_nplant_understory_si_scpf)%r82d, & hio_ddbh_canopy_si_scpf => this%hvars(ih_ddbh_canopy_si_scpf)%r82d, & @@ -1897,14 +2071,50 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_m8_si_scpf => this%hvars(ih_m8_si_scpf)%r82d, & hio_m9_si_scpf => this%hvars(ih_m9_si_scpf)%r82d, & hio_m10_si_scpf => this%hvars(ih_m10_si_scpf)%r82d, & + hio_m11_si_scpf => this%hvars(ih_m11_si_scpf)%r82d, & hio_m10_si_capf => this%hvars(ih_m10_si_capf)%r82d, & - + + hio_crownfiremort_si_scpf => this%hvars(ih_crownfiremort_si_scpf)%r82d, & hio_cambialfiremort_si_scpf => this%hvars(ih_cambialfiremort_si_scpf)%r82d, & hio_fire_c_to_atm_si => this%hvars(ih_fire_c_to_atm_si)%r81d, & hio_burn_flux_elem => this%hvars(ih_burn_flux_elem)%r82d, & + hio_nplant_si_cdpf => this%hvars(ih_nplant_si_cdpf)%r82d, & + hio_nplant_si_cdsc => this%hvars(ih_nplant_si_cdsc)%r82d, & + hio_mortality_si_cdsc => this%hvars(ih_mortality_si_cdsc)%r82d, & + hio_mortality_si_cdpf => this%hvars(ih_mortality_si_cdpf)%r82d, & + hio_m3_si_cdpf => this%hvars(ih_m3_si_cdpf)%r82d, & + hio_m3_si_cdsc => this%hvars(ih_m3_si_cdsc)%r82d, & + hio_m11_si_cdpf => this%hvars(ih_m11_si_cdpf)%r82d, & + hio_m11_si_cdsc => this%hvars(ih_m11_si_cdsc)%r82d, & + hio_mortality_canopy_si_cdpf => this%hvars(ih_mortality_canopy_si_cdpf)%r82d, & + hio_mortality_understory_si_cdpf => this%hvars(ih_mortality_understory_si_cdpf)%r82d, & + hio_m3_mortality_canopy_si_cdsc => this%hvars(ih_m3_mortality_canopy_si_cdsc)%r82d, & + hio_m3_mortality_understory_si_cdsc => this%hvars(ih_m3_mortality_understory_si_cdsc)%r82d, & + hio_m3_mortality_canopy_si_cdpf => this%hvars(ih_m3_mortality_canopy_si_cdpf)%r82d, & + hio_m3_mortality_understory_si_cdpf =>this%hvars(ih_m3_mortality_understory_si_cdpf)%r82d, & + hio_m11_mortality_canopy_si_cdsc => this%hvars(ih_m11_mortality_canopy_si_cdsc)%r82d, & + hio_m11_mortality_understory_si_cdsc => this%hvars(ih_m11_mortality_understory_si_cdsc)%r82d, & + hio_m11_mortality_canopy_si_cdpf => this%hvars(ih_m11_mortality_canopy_si_cdpf)%r82d, & + hio_m11_mortality_understory_si_cdpf =>this%hvars(ih_m11_mortality_understory_si_cdpf)%r82d, & + hio_nplant_canopy_si_cdsc => this%hvars(ih_nplant_canopy_si_cdsc)%r82d, & + hio_nplant_understory_si_cdsc =>this%hvars(ih_nplant_understory_si_cdsc)%r82d, & + hio_nplant_canopy_si_cdpf => this%hvars(ih_nplant_canopy_si_cdpf)%r82d, & + hio_nplant_understory_si_cdpf =>this%hvars(ih_nplant_understory_si_cdpf)%r82d, & + hio_damage_cflux_si_cdcd => this%hvars(ih_damage_cflux_si_cdcd)%r82d, & + hio_damage_rate_si_cdcd => this%hvars(ih_damage_rate_si_cdcd)%r82d, & + hio_recovery_cflux_si_cdcd => this%hvars(ih_recovery_cflux_si_cdcd)%r82d, & + hio_recovery_rate_si_cdcd => this%hvars(ih_recovery_rate_si_cdcd)%r82d, & + hio_trimming_damage_si_cdsc => this%hvars(ih_trimming_damage_si_cdsc)%r82d, & + hio_ddbh_si_cdsc => this%hvars(ih_ddbh_si_cdsc)%r82d, & + hio_ddbh_si_cdpf => this%hvars(ih_ddbh_si_cdpf)%r82d, & + hio_ddbh_canopy_si_cdpf => this%hvars(ih_ddbh_canopy_si_cdpf)%r82d, & + hio_ddbh_understory_si_cdpf => this%hvars(ih_ddbh_understory_si_cdpf)%r82d, & + hio_crownarea_canopy_damage_si => this%hvars(ih_crownarea_canopy_damage_si)%r81d, & + hio_crownarea_ustory_damage_si => this%hvars(ih_crownarea_ustory_damage_si)%r81d, & + hio_m1_si_scls => this%hvars(ih_m1_si_scls)%r82d, & hio_m2_si_scls => this%hvars(ih_m2_si_scls)%r82d, & hio_m3_si_scls => this%hvars(ih_m3_si_scls)%r82d, & @@ -1915,6 +2125,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_m8_si_scls => this%hvars(ih_m8_si_scls)%r82d, & hio_m9_si_scls => this%hvars(ih_m9_si_scls)%r82d, & hio_m10_si_scls => this%hvars(ih_m10_si_scls)%r82d, & + hio_m11_si_scls => this%hvars(ih_m11_si_scls)%r82d, & hio_m10_si_cacls => this%hvars(ih_m10_si_cacls)%r82d, & hio_c13disc_si_scpf => this%hvars(ih_c13disc_si_scpf)%r82d, & @@ -1937,6 +2148,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_sai_understory_si_scls => this%hvars(ih_sai_understory_si_scls)%r82d, & hio_mortality_canopy_si_scls => this%hvars(ih_mortality_canopy_si_scls)%r82d, & hio_mortality_understory_si_scls => this%hvars(ih_mortality_understory_si_scls)%r82d, & + hio_m3_mortality_canopy_si_scls => this%hvars(ih_m3_mortality_canopy_si_scls)%r82d, & + hio_m3_mortality_understory_si_scls => this%hvars(ih_m3_mortality_understory_si_scls)%r82d, & hio_demotion_rate_si_scls => this%hvars(ih_demotion_rate_si_scls)%r82d, & hio_demotion_carbonflux_si => this%hvars(ih_demotion_carbonflux_si)%r81d, & hio_promotion_rate_si_scls => this%hvars(ih_promotion_rate_si_scls)%r82d, & @@ -1947,6 +2160,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_promotion_carbonflux_si => this%hvars(ih_promotion_carbonflux_si)%r81d, & hio_canopy_mortality_carbonflux_si => this%hvars(ih_canopy_mortality_carbonflux_si)%r81d, & hio_understory_mortality_carbonflux_si => this%hvars(ih_understory_mortality_carbonflux_si)%r81d, & + hio_canopy_mortality_crownarea_si => this%hvars(ih_canopy_mortality_crownarea_si)%r81d, & + hio_understory_mortality_crownarea_si => this%hvars(ih_understory_mortality_crownarea_si)%r81d, & hio_leaf_md_canopy_si_scls => this%hvars(ih_leaf_md_canopy_si_scls)%r82d, & hio_root_md_canopy_si_scls => this%hvars(ih_root_md_canopy_si_scls)%r82d, & hio_carbon_balance_canopy_si_scls => this%hvars(ih_carbon_balance_canopy_si_scls)%r82d, & @@ -2038,6 +2253,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) model_day_int = nint(hlm_model_day) + ! --------------------------------------------------------------------------------- ! Loop through the FATES scale hierarchy and fill the history IO arrays ! --------------------------------------------------------------------------------- @@ -2065,7 +2281,39 @@ subroutine update_history_dyn(this,nc,nsites,sites) sites(s)%mass_balance(el)%burn_flux_to_atm * & g_per_kg * ha_per_m2 * days_per_sec - end do + end do + + ! damage variables - site level - this needs to be OUT of the patch loop + if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + + icdcd = 1 + + do icdi = 1,ncrowndamage+1 + do icdj = 1,ncrowndamage + hio_damage_cflux_si_cdcd(io_si,icdcd) = & + sites(s)%damage_cflux(icdj,icdi) * g_per_kg * days_per_sec * & + ha_per_m2 + hio_damage_rate_si_cdcd(io_si,icdcd) = & + sites(s)%damage_rate(icdj,icdi) + + hio_recovery_cflux_si_cdcd(io_si,icdcd) = & + sites(s)%recovery_cflux(icdj,icdi) * g_per_kg * days_per_sec * & + ha_per_m2 + hio_recovery_rate_si_cdcd(io_si,icdcd) = & + sites(s)%recovery_rate(icdj,icdi) + + + icdcd = icdcd + 1 + end do + end do + + hio_crownarea_canopy_damage_si(io_si) = hio_crownarea_canopy_damage_si(io_si) + & + sites(s)%crownarea_canopy_damage * days_per_year + + hio_crownarea_ustory_damage_si(io_si) = hio_crownarea_ustory_damage_si(io_si) + & + sites(s)%crownarea_ustory_damage * days_per_year + + end if hio_canopy_spread_si(io_si) = sites(s)%spread @@ -2200,7 +2448,9 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_area_plant_si(io_si) = hio_area_plant_si(io_si) + min(cpatch%total_canopy_area,cpatch%area) * AREA_INV hio_area_trees_si(io_si) = hio_area_trees_si(io_si) + min(cpatch%total_tree_area,cpatch%area) * AREA_INV - + + + ccohort => cpatch%shortest do while(associated(ccohort)) @@ -2249,6 +2499,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_canopy_height_dist_si_height(io_si,height_bin_max) + ccohort%c_area * AREA_INV endif + ! Update biomass components ! Mass pools [kgC] do el = 1, num_elements @@ -2268,6 +2519,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! Zero states, and set the fluxes if( element_list(el).eq.carbon12_element )then + total_c = total_m this%hvars(ih_storec_si)%r81d(io_si) = & this%hvars(ih_storec_si)%r81d(io_si) + ccohort%n * store_m this%hvars(ih_leafc_si)%r81d(io_si) = & @@ -2315,8 +2567,9 @@ subroutine update_history_dyn(this,nc,nsites,sites) if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then hio_biomass_secondary_forest_si(io_si) = hio_biomass_secondary_forest_si(io_si) + & total_m * ccohort%n * AREA_INV - endif - + endif + + elseif(element_list(el).eq.nitrogen_element)then store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ) @@ -2414,12 +2667,13 @@ subroutine update_history_dyn(this,nc,nsites,sites) (1._r8-prt_params%allom_agb_frac(ccohort%pft)) hio_npp_stor_si(io_si) = hio_npp_stor_si(io_si) + store_m_net_alloc * n_perm2 + associate( scpf => ccohort%size_by_pft_class, & - scls => ccohort%size_class, & + cdam => ccohort%crowndamage, & cacls => ccohort%coage_class, & capf => ccohort%coage_by_pft_class) - + gpp_cached = hio_gpp_si_scpf(io_si,scpf) @@ -2474,6 +2728,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) (ccohort%lmort_direct+ccohort%lmort_collateral+ccohort%lmort_infra) * ccohort%n hio_m8_si_scpf(io_si,scpf) = hio_m8_si_scpf(io_si,scpf) + ccohort%frmort*ccohort%n hio_m9_si_scpf(io_si,scpf) = hio_m9_si_scpf(io_si,scpf) + ccohort%smort*ccohort%n + if (hlm_use_cohort_age_tracking .eq.itrue) then hio_m10_si_scpf(io_si,scpf) = hio_m10_si_scpf(io_si,scpf) + ccohort%asmort*ccohort%n @@ -2490,10 +2745,10 @@ subroutine update_history_dyn(this,nc,nsites,sites) (ccohort%lmort_direct+ccohort%lmort_collateral+ccohort%lmort_infra) * ccohort%n hio_m8_si_scls(io_si,scls) = hio_m8_si_scls(io_si,scls) + & ccohort%frmort*ccohort%n + hio_m9_si_scls(io_si,scls) = hio_m9_si_scls(io_si,scls) + ccohort%smort*ccohort%n - !C13 discrimination if(gpp_cached + ccohort%gpp_acc_hold > 0.0_r8)then hio_c13disc_si_scpf(io_si,scpf) = ((hio_c13disc_si_scpf(io_si,scpf) * gpp_cached) + & @@ -2505,6 +2760,92 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! number density [/ha] hio_nplant_si_scpf(io_si,scpf) = hio_nplant_si_scpf(io_si,scpf) + ccohort%n + ! damage variables - cohort level + if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + + + cdpf = get_cdamagesizepft_class_index(ccohort%dbh, ccohort%crowndamage, ccohort%pft) + cdsc = get_cdamagesize_class_index(ccohort%dbh, ccohort%crowndamage) + + ! crown damage - only want cohorts > 1 cm dbh here so we can compare it with data + hio_mortality_si_cdsc(io_si,cdsc) = hio_mortality_si_cdsc(io_si,cdsc) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & + ccohort%n * sec_per_day * days_per_year + + hio_mortality_si_cdpf(io_si,cdpf) = hio_mortality_si_cdpf(io_si,cdpf) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & + ccohort%n * sec_per_day * days_per_year + + + hio_trimming_damage_si_cdsc(io_si,cdsc) = hio_trimming_damage_si_cdsc(io_si,cdsc) + & + ccohort%n * ccohort%canopy_trim + + ! crown damage by size + hio_nplant_si_cdsc(io_si, cdsc) = hio_nplant_si_cdsc(io_si, cdsc) + ccohort%n + hio_m3_si_cdsc(io_si, cdsc) = hio_m3_si_cdsc(io_si, cdsc) + ccohort%cmort * ccohort%n + + ! crown damage by size by pft + hio_nplant_si_cdpf(io_si, cdpf) = hio_nplant_si_cdpf(io_si, cdpf) + ccohort%n + hio_m3_si_cdpf(io_si, cdpf) = hio_m3_si_cdpf(io_si, cdpf) + ccohort%cmort * ccohort%n + + ! mortality + hio_m11_si_scpf(io_si,scpf) = hio_m11_si_scpf(io_si,scpf) + ccohort%dgmort*ccohort%n + hio_m11_si_scls(io_si,scls) = hio_m11_si_scls(io_si,scls) + ccohort%dgmort*ccohort%n + hio_m11_si_cdpf(io_si,cdpf) = hio_m11_si_cdpf(io_si,cdpf) + ccohort%dgmort*ccohort%n + hio_m11_si_cdsc(io_si,cdsc) = hio_m11_si_cdsc(io_si,cdsc) + ccohort%dgmort*ccohort%n + + hio_ddbh_si_cdsc(io_si,cdsc) = hio_ddbh_si_cdsc(io_si,cdsc) + & + ccohort%ddbhdt*ccohort%n + + hio_ddbh_si_cdpf(io_si,cdpf) = hio_ddbh_si_cdpf(io_si,cdpf) + & + ccohort%ddbhdt*ccohort%n + + + ! add mortality to the damage rates + + icdam = (ncrowndamage*ncrowndamage) + cdam ! to fill in the last row + + if(hlm_use_canopy_damage .eq. itrue .and. ccohort%canopy_layer == 1 .or. & + hlm_use_understory_damage .eq. itrue .and. ccohort%canopy_layer > 1) then + + hio_damage_rate_si_cdcd(io_si,icdam) = hio_damage_rate_si_cdcd(io_si,icdam) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n & + + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & + ccohort%n * sec_per_day * days_per_year + + hio_damage_cflux_si_cdcd(io_si,icdam) = hio_damage_cflux_si_cdcd(io_si,icdam) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * & + total_c * ccohort%n * g_per_kg * days_per_sec * years_per_day * ha_per_m2 + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * total_c * & + ccohort%n * g_per_kg * ha_per_m2 + + end if + + ! all crown layers go towards recovery + hio_recovery_rate_si_cdcd(io_si,icdam) = hio_recovery_rate_si_cdcd(io_si,icdam) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n & + + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & + ccohort%n * sec_per_day * days_per_year + + hio_recovery_cflux_si_cdcd(io_si,icdam) = hio_recovery_cflux_si_cdcd(io_si,icdam) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * & + total_c * ccohort%n * g_per_kg * days_per_sec * years_per_day * ha_per_m2 + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * total_c * & + ccohort%n * g_per_kg * ha_per_m2 + + + end if ! end if damage + + + ! number density along the cohort age dimension if (hlm_use_cohort_age_tracking .eq.itrue) then hio_nplant_si_capf(io_si,capf) = hio_nplant_si_capf(io_si,capf) + ccohort%n @@ -2564,7 +2905,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_nplant_canopy_si_scag(io_si,iscag) = hio_nplant_canopy_si_scag(io_si,iscag) + ccohort%n hio_mortality_canopy_si_scag(io_si,iscag) = hio_mortality_canopy_si_scag(io_si,iscag) + & (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort) * ccohort%n + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n hio_ddbh_canopy_si_scag(io_si,iscag) = hio_ddbh_canopy_si_scag(io_si,iscag) + & ccohort%ddbhdt*ccohort%n hio_bstor_canopy_si_scpf(io_si,scpf) = hio_bstor_canopy_si_scpf(io_si,scpf) + & @@ -2579,20 +2920,27 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! ccohort%frmort + ccohort%smort + ccohort%asmort) * ccohort%n hio_mortality_canopy_si_scpf(io_si,scpf) = hio_mortality_canopy_si_scpf(io_si,scpf)+ & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + ccohort%frmort + & - ccohort%smort + ccohort%asmort) * ccohort%n + & + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n + & (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & ccohort%n * sec_per_day * days_per_year + + ! canopy carbon starvation mortality by size x pft + hio_m3_mortality_canopy_si_scpf(io_si,scpf) = hio_m3_mortality_canopy_si_scpf(io_si,scpf)+& + ccohort%cmort * ccohort%n + hio_nplant_canopy_si_scpf(io_si,scpf) = hio_nplant_canopy_si_scpf(io_si,scpf) + ccohort%n hio_nplant_canopy_si_scls(io_si,scls) = hio_nplant_canopy_si_scls(io_si,scls) + ccohort%n + + hio_lai_canopy_si_scls(io_si,scls) = hio_lai_canopy_si_scls(io_si,scls) + & ccohort%treelai*ccohort%c_area * AREA_INV hio_sai_canopy_si_scls(io_si,scls) = hio_sai_canopy_si_scls(io_si,scls) + & ccohort%treesai*ccohort%c_area * AREA_INV hio_trimming_canopy_si_scls(io_si,scls) = hio_trimming_canopy_si_scls(io_si,scls) + & - ccohort%n * ccohort%canopy_trim + ccohort%canopy_trim * ccohort%n + hio_crown_area_canopy_si_scls(io_si,scls) = hio_crown_area_canopy_si_scls(io_si,scls) + & ccohort%c_area hio_gpp_canopy_si_scpf(io_si,scpf) = hio_gpp_canopy_si_scpf(io_si,scpf) + & @@ -2607,20 +2955,66 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! sum of all mortality hio_mortality_canopy_si_scls(io_si,scls) = hio_mortality_canopy_si_scls(io_si,scls) + & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort) * ccohort%n + & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n + & (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & ccohort%n * sec_per_day * days_per_year + hio_canopy_mortality_crownarea_si(io_si) = hio_canopy_mortality_crownarea_si(io_si) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * & + ccohort%c_area + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & + ccohort%c_area * sec_per_day * days_per_year + + + hio_m3_mortality_canopy_si_scls(io_si,scls) = hio_m3_mortality_canopy_si_scls(io_si,scls)+& + ccohort%cmort * ccohort%n + + ! damage variables - canopy + if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + + ! carbon starvation mortality in the canopy by size x damage x pft + hio_m3_mortality_canopy_si_cdpf(io_si,cdpf) = hio_m3_mortality_canopy_si_cdpf(io_si,cdpf)+& + ccohort%cmort * ccohort%n + ! damage mortality in the canopy by size x damage x pft + hio_m11_mortality_canopy_si_cdpf(io_si,cdpf) = hio_m11_mortality_canopy_si_cdpf(io_si,cdpf)+& + ccohort%dgmort * ccohort%n + + ! carbon starvation mortality in the canopy by size x damage + hio_m3_mortality_canopy_si_cdsc(io_si,cdsc) = hio_m3_mortality_canopy_si_cdsc(io_si,cdsc)+& + ccohort%cmort * ccohort%n + ! damage mortality in the canopy by size x damage + hio_m11_mortality_canopy_si_cdsc(io_si,cdsc) = hio_m11_mortality_canopy_si_cdsc(io_si,cdsc)+& + ccohort%dgmort * ccohort%n + + hio_mortality_canopy_si_cdpf(io_si,cdpf) = hio_mortality_canopy_si_cdpf(io_si,cdpf)+ & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + ccohort%frmort + & + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & + ccohort%n * sec_per_day * days_per_year + + ! nplants by damage + hio_nplant_canopy_si_cdpf(io_si,cdpf) = hio_nplant_canopy_si_cdpf(io_si,cdpf) + ccohort%n + hio_nplant_canopy_si_cdsc(io_si,cdsc) = hio_nplant_canopy_si_cdsc(io_si,cdsc) + ccohort%n + + ! growth rate by damage x size x pft in the canopy + hio_ddbh_canopy_si_cdpf(io_si,cdpf) = hio_ddbh_canopy_si_cdpf(io_si,cdpf) + & + ccohort%ddbhdt*ccohort%n + + end if ! end if damage + + + hio_canopy_mortality_carbonflux_si(io_si) = hio_canopy_mortality_carbonflux_si(io_si) + & (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort) * & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * & total_m * ccohort%n * g_per_kg * days_per_sec * years_per_day * ha_per_m2 + & (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * total_m * & ccohort%n * g_per_kg * ha_per_m2 - + + hio_carbon_balance_canopy_si_scls(io_si,scls) = hio_carbon_balance_canopy_si_scls(io_si,scls) + & ccohort%n * ccohort%npp_acc_hold @@ -2658,7 +3052,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_nplant_understory_si_scag(io_si,iscag) = hio_nplant_understory_si_scag(io_si,iscag) + ccohort%n hio_mortality_understory_si_scag(io_si,iscag) = hio_mortality_understory_si_scag(io_si,iscag) + & (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort) * ccohort%n + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n hio_ddbh_understory_si_scag(io_si,iscag) = hio_ddbh_understory_si_scag(io_si,iscag) + & ccohort%ddbhdt*ccohort%n hio_bstor_understory_si_scpf(io_si,scpf) = hio_bstor_understory_si_scpf(io_si,scpf) + & @@ -2672,14 +3066,17 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! (ccohort%bmort + ccohort%hmort + ccohort%cmort + ! ccohort%frmort + ccohort%smort + ccohort%asmort) * ccohort%n + ! mortality in the understory by size and by size hio_mortality_understory_si_scpf(io_si,scpf) = hio_mortality_understory_si_scpf(io_si,scpf)+ & (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort) * ccohort%n + & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n + & (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & ccohort%n * sec_per_day * days_per_year + hio_nplant_understory_si_scpf(io_si,scpf) = hio_nplant_understory_si_scpf(io_si,scpf) + ccohort%n hio_nplant_understory_si_scls(io_si,scls) = hio_nplant_understory_si_scls(io_si,scls) + ccohort%n + hio_lai_understory_si_scls(io_si,scls) = hio_lai_understory_si_scls(io_si,scls) + & ccohort%treelai*ccohort%c_area * AREA_INV hio_sai_understory_si_scls(io_si,scls) = hio_sai_understory_si_scls(io_si,scls) + & @@ -2701,19 +3098,68 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! sum of all mortality hio_mortality_understory_si_scls(io_si,scls) = hio_mortality_understory_si_scls(io_si,scls) + & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort) * ccohort%n + & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n + & (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & ccohort%n * sec_per_day * days_per_year - + + hio_m3_mortality_understory_si_scls(io_si,scls) = hio_m3_mortality_understory_si_scls(io_si,scls)+& + ccohort%cmort * ccohort%n + hio_m3_mortality_understory_si_scpf(io_si,scpf) = hio_m3_mortality_understory_si_scpf(io_si,scpf)+& + ccohort%cmort * ccohort%n + + + ! damage variables - understory + if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + + ! carbon starvation mortality in the understory by size and by size x damage + hio_m3_mortality_understory_si_cdsc(io_si,cdsc) = hio_m3_mortality_understory_si_cdsc(io_si,cdsc)+& + ccohort%cmort * ccohort%n + + ! damage mortality in the understory by size and by size x damage + hio_m11_mortality_understory_si_cdsc(io_si,cdsc) = hio_m11_mortality_understory_si_cdsc(io_si,cdsc)+& + ccohort%dgmort * ccohort%n + + ! carbon mortality in the understory by damage x size x pft + hio_m3_mortality_understory_si_cdpf(io_si,cdpf) = hio_m3_mortality_understory_si_cdpf(io_si,cdpf)+& + ccohort%cmort * ccohort%n + + ! damage in the understory by damage x size x pft + hio_m11_mortality_understory_si_cdpf(io_si,cdpf) = hio_m11_mortality_understory_si_cdpf(io_si,cdpf)+& + ccohort%dgmort * ccohort%n + + ! total mortality of understory cohorts by damage x size x pft + hio_mortality_understory_si_cdpf(io_si,cdpf) = hio_mortality_understory_si_cdpf(io_si,cdpf)+ & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & + ccohort%n * sec_per_day * days_per_year + + ! number of plants in the understory by size x damage and size x damage x pft + hio_nplant_understory_si_cdsc(io_si,cdsc) = hio_nplant_understory_si_cdsc(io_si,cdsc) + ccohort%n + hio_nplant_understory_si_cdpf(io_si,cdpf) = hio_nplant_understory_si_cdpf(io_si,cdpf) + ccohort%n + + ! growth rate by size x damage x pft - understory + hio_ddbh_understory_si_cdpf(io_si,cdpf) = hio_ddbh_understory_si_cdpf(io_si,cdpf) + & + ccohort%ddbhdt*ccohort%n + + end if ! end if damage + hio_understory_mortality_carbonflux_si(io_si) = hio_understory_mortality_carbonflux_si(io_si) + & (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort) * & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * & total_m * ccohort%n * g_per_kg * days_per_sec * years_per_day * ha_per_m2 + & (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * total_m * & ccohort%n * g_per_kg * ha_per_m2 + hio_understory_mortality_crownarea_si(io_si) = hio_understory_mortality_crownarea_si(io_si) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * & + ccohort%c_area + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & + ccohort%c_area * sec_per_day * days_per_year + + hio_carbon_balance_understory_si_scls(io_si,scls) = hio_carbon_balance_understory_si_scls(io_si,scls) + & ccohort%npp_acc_hold * ccohort%n @@ -2784,10 +3230,12 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_crownarea_si_cnlf(io_si, cnlf_indx) = hio_crownarea_si_cnlf(io_si, cnlf_indx) + & ccohort%c_area / AREA end do - + + ccohort => ccohort%taller enddo ! cohort loop - + + ! Patch specific variables that are already calculated ! These things are all duplicated. Should they all be converted to LL or array structures RF? ! define scalar to counteract the patch albedo scaling logic for conserved quantities @@ -2807,9 +3255,10 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_fire_fuel_sav_si(io_si) = hio_fire_fuel_sav_si(io_si) + cpatch%fuel_sav * cpatch%area * AREA_INV hio_fire_fuel_mef_si(io_si) = hio_fire_fuel_mef_si(io_si) + cpatch%fuel_mef * cpatch%area * AREA_INV hio_sum_fuel_si(io_si) = hio_sum_fuel_si(io_si) + cpatch%sum_fuel * g_per_kg * cpatch%area * AREA_INV - + do ilyr = 1,sites(s)%nlevsoil - hio_fragmentation_scaler_sl(io_si,ilyr) = hio_fragmentation_scaler_sl(io_si,ilyr) + cpatch%fragmentation_scaler(ilyr) * cpatch%area * AREA_INV + hio_fragmentation_scaler_sl(io_si,ilyr) = hio_fragmentation_scaler_sl(io_si,ilyr) + & + cpatch%fragmentation_scaler(ilyr) * cpatch%area * AREA_INV end do do i_fuel = 1,nfsc @@ -2856,6 +3305,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) cpatch => cpatch%younger end do !patch loop + ! divide so-far-just-summed but to-be-averaged patch-age-class variables by patch-age-class area to get mean values do ipa2 = 1, nlevage if (hio_area_si_age(io_si, ipa2) .gt. tiny) then @@ -2907,6 +3357,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_m4_si_scpf(io_si,i_scpf) = sites(s)%imort_rate(i_scls, i_pft) hio_m4_si_scls(io_si,i_scls) = hio_m4_si_scls(io_si,i_scls) + sites(s)%imort_rate(i_scls, i_pft) ! + + ! add imort to other mortality terms. consider imort as understory mortality even if it happens in ! cohorts that may have been promoted as part of the patch creation, and use the pre-calculated site-level ! values to avoid biasing the results by the dramatically-reduced number densities in cohorts that are subject to imort @@ -2942,6 +3394,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_mortality_understory_si_scls(io_si,i_scls) = hio_mortality_understory_si_scls(io_si,i_scls) + & sites(s)%fmort_rate_ustory(i_scls, i_pft) + ! ! carbon flux associated with mortality of trees dying by fire hio_canopy_mortality_carbonflux_si(io_si) = hio_canopy_mortality_carbonflux_si(io_si) + & @@ -2949,7 +3402,10 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_understory_mortality_carbonflux_si(io_si) = hio_understory_mortality_carbonflux_si(io_si) + & sites(s)%fmort_carbonflux_ustory - + + hio_understory_mortality_carbonflux_si(io_si) = hio_understory_mortality_carbonflux_si(io_si) + & + sites(s)%imort_carbonflux + ! ! for scag variables, also treat as happening in the newly-disurbed patch @@ -2970,10 +3426,103 @@ subroutine update_history_dyn(this,nc,nsites,sites) end do ! - ! treat carbon flux from imort the same way - hio_understory_mortality_carbonflux_si(io_si) = hio_understory_mortality_carbonflux_si(io_si) + & - sites(s)%imort_carbonflux - ! + if(hlm_use_canopy_damage .eq. itrue .or. & + hlm_use_understory_damage .eq. itrue ) then + + do i_pft = 1, numpft + do icdam = 1, ncrowndamage + do i_scls = 1,nlevsclass + + icdsc = (icdam-1)*nlevsclass + i_scls + icdpf = (icdam-1)*nlevsclass + i_scls + & + (i_pft-1) * nlevsclass * ncrowndamage + + hio_mortality_si_cdsc(io_si, icdsc) = hio_mortality_si_cdsc(io_si, icdsc) + & + (sites(s)%term_nindivs_canopy_damage(icdam, i_scls, i_pft) * days_per_year) + & + (sites(s)%term_nindivs_ustory_damage(icdam, i_scls, i_pft) * days_per_year) + & + sites(s)%imort_rate_damage(icdam, i_scls, i_pft) + & + sites(s)%fmort_rate_canopy_damage(icdam, i_scls, i_pft) + & + sites(s)%fmort_rate_ustory_damage(icdam, i_scls, i_pft) + + hio_mortality_si_cdpf(io_si, icdpf) = hio_mortality_si_cdpf(io_si, icdpf) + & + (sites(s)%term_nindivs_canopy_damage(icdam, i_scls, i_pft) * days_per_year) + & + (sites(s)%term_nindivs_ustory_damage(icdam, i_scls, i_pft) * days_per_year) + & + sites(s)%imort_rate_damage(icdam, i_scls, i_pft) + & + sites(s)%fmort_rate_canopy_damage(icdam, i_scls, i_pft) + & + sites(s)%fmort_rate_ustory_damage(icdam, i_scls, i_pft) + + hio_mortality_canopy_si_cdpf(io_si,icdpf) = hio_mortality_canopy_si_cdpf(io_si,icdpf) + & + sites(s)%term_nindivs_canopy_damage(icdam,i_scls,i_pft) * days_per_year + & + sites(s)%fmort_rate_canopy_damage(icdam, i_scls, i_pft) + + hio_mortality_understory_si_cdpf(io_si,icdpf) = hio_mortality_understory_si_cdpf(io_si,icdpf) + & + sites(s)%term_nindivs_ustory_damage(icdam, i_scls,i_pft) * days_per_year + & + sites(s)%imort_rate_damage(icdam, i_scls, i_pft) + & + sites(s)%fmort_rate_ustory_damage(icdam, i_scls, i_pft) + + + ! recovery is both canopy layers combined + imcdam = icdam + (ncrowndamage * ncrowndamage) + hio_recovery_rate_si_cdcd(io_si, imcdam) = hio_recovery_rate_si_cdcd(io_si, imcdam) + & + sites(s)%term_nindivs_canopy_damage(icdam, i_scls, i_pft) * days_per_year + & + sites(s)%term_nindivs_ustory_damage(icdam, i_scls, i_pft) * days_per_year + & + sites(s)%imort_rate_damage(icdam, i_scls, i_pft) + & + sites(s)%fmort_rate_canopy_damage(icdam, i_scls, i_pft) + & + sites(s)%fmort_rate_ustory_damage(icdam, i_scls, i_pft) + + hio_recovery_cflux_si_cdcd(io_si, imcdam) = hio_recovery_cflux_si_cdcd(io_si, imcdam) + & + sites(s)%imort_cflux_damage(icdam, i_scls) + & + sites(s)%term_cflux_canopy_damage(icdam, i_scls)*g_per_kg*days_per_sec*ha_per_m2 + & + sites(s)%term_cflux_ustory_damage(icdam, i_scls)*g_per_kg*days_per_sec*ha_per_m2 + & + sites(s)%fmort_cflux_canopy_damage(icdam, i_scls) + & + sites(s)%fmort_cflux_ustory_damage(icdam, i_scls) + + + end do + end do + end do + end if + + + ! only track damage in the canopy layer of interest + if(hlm_use_canopy_damage .eq. itrue ) then + do icdam = 1, ncrowndamage + do i_scls = 1,nlevsclass + do i_pft = 1, numpft + + imcdam = icdam + (ncrowndamage * ncrowndamage) + hio_damage_rate_si_cdcd(io_si, imcdam) = hio_damage_rate_si_cdcd(io_si, imcdam) + & + sites(s)%term_nindivs_canopy_damage(icdam, i_scls, i_pft) * days_per_year + & + sites(s)%fmort_rate_canopy_damage(icdam, i_scls, i_pft) + + hio_damage_cflux_si_cdcd(io_si, imcdam) = hio_damage_cflux_si_cdcd(io_si, imcdam) + & + sites(s)%term_cflux_canopy_damage(icdam, i_scls)*g_per_kg*days_per_sec*ha_per_m2 + & + sites(s)%fmort_cflux_canopy_damage(icdam, i_scls)*g_per_kg*days_per_sec*ha_per_m2 + end do + end do + end do + end if + + if(hlm_use_understory_damage .eq. itrue ) then + do icdam = 1, ncrowndamage + do i_scls = 1,nlevsclass + do i_pft = 1,numpft + + imcdam = icdam + (ncrowndamage * ncrowndamage) + hio_damage_rate_si_cdcd(io_si, imcdam) = hio_damage_rate_si_cdcd(io_si, imcdam) + & + sites(s)%term_nindivs_ustory_damage(icdam, i_scls, i_pft) * days_per_year + & + sites(s)%imort_rate_damage(icdam, i_scls, i_pft) + & + sites(s)%fmort_rate_ustory_damage(icdam, i_scls, i_pft) + + hio_damage_cflux_si_cdcd(io_si, imcdam) = hio_damage_cflux_si_cdcd(io_si, imcdam) + & + sites(s)%imort_cflux_damage(icdam, i_scls) + & + sites(s)%term_cflux_ustory_damage(icdam, i_scls)*g_per_kg*days_per_sec*ha_per_m2 + & + sites(s)%fmort_cflux_canopy_damage(icdam, i_scls) + end do + end do + end do + end if + sites(s)%term_nindivs_canopy(:,:) = 0._r8 sites(s)%term_nindivs_ustory(:,:) = 0._r8 sites(s)%imort_carbonflux = 0._r8 @@ -2986,12 +3535,30 @@ subroutine update_history_dyn(this,nc,nsites,sites) sites(s)%fmort_rate_crown(:,:) = 0._r8 sites(s)%growthflux_fusion(:,:) = 0._r8 + sites(s)%imort_rate_damage(:,:,:) = 0.0_r8 + sites(s)%term_nindivs_canopy_damage(:,:,:) = 0.0_r8 + sites(s)%term_nindivs_ustory_damage(:,:,:) = 0.0_r8 + sites(s)%imort_cflux_damage(:,:) = 0._r8 + sites(s)%term_cflux_canopy_damage(:,:) = 0._r8 + sites(s)%term_cflux_ustory_damage(:,:) = 0._r8 + sites(s)%fmort_rate_canopy_damage(:,:,:) = 0._r8 + sites(s)%fmort_rate_ustory_damage(:,:,:) = 0._r8 + sites(s)%fmort_cflux_canopy_damage(:,:) = 0._r8 + sites(s)%fmort_cflux_ustory_damage(:,:) = 0._r8 + sites(s)%damage_rate(:,:) = 0.0_r8 + sites(s)%damage_cflux(:,:) = 0.0_r8 + sites(s)%recovery_rate(:,:) = 0.0_r8 + sites(s)%recovery_cflux(:,:) = 0.0_r8 + sites(s)%crownarea_canopy_damage = 0._r8 + sites(s)%crownarea_ustory_damage = 0._r8 + + ! pass the recruitment rate as a flux to the history, and then reset the recruitment buffer do i_pft = 1, numpft hio_recruitment_si_pft(io_si,i_pft) = sites(s)%recruitment_rate(i_pft) * days_per_year end do sites(s)%recruitment_rate(:) = 0._r8 - + ! summarize all of the mortality fluxes by PFT do i_pft = 1, numpft do i_scls = 1,nlevsclass @@ -3007,11 +3574,12 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_m7_si_scpf(io_si,i_scpf) + & hio_m8_si_scpf(io_si,i_scpf) + & hio_m9_si_scpf(io_si,i_scpf) + & - hio_m10_si_scpf(io_si,i_scpf) + hio_m10_si_scpf(io_si,i_scpf) + & + hio_m11_si_scpf(io_si,i_scpf) end do end do - + ! ------------------------------------------------------------------------------ ! Some carbon only litter diagnostics (legacy) ! ------------------------------------------------------------------------------ @@ -3101,7 +3669,17 @@ subroutine update_history_dyn(this,nc,nsites,sites) this%hvars(ih_cefflux_si)%r81d(io_si) = & sum(sites(s)%flux_diags(el)%nutrient_efflux_scpf(:),dim=1) - + + if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue)then + this%hvars(ih_totvegc_cdpf)%r82d(io_si,:) = 0._r8 + this%hvars(ih_leafc_cdpf)%r82d(io_si,:) = 0._r8 + this%hvars(ih_fnrtc_cdpf)%r82d(io_si,:) = 0._r8 + this%hvars(ih_sapwc_cdpf)%r82d(io_si,:) = 0._r8 + this%hvars(ih_storec_cdpf)%r82d(io_si,:) = 0._r8 + this%hvars(ih_reproc_cdpf)%r82d(io_si,:) = 0._r8 + end if + + elseif(element_list(el).eq.nitrogen_element)then this%hvars(ih_totvegn_scpf)%r82d(io_si,:) = 0._r8 @@ -3285,7 +3863,42 @@ subroutine update_history_dyn(this,nc,nsites,sites) ccohort => ccohort%shorter end do - + + if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + ! Load Mass States + ccohort => cpatch%tallest + do while(associated(ccohort)) + + sapw_m = ccohort%prt%GetState(sapw_organ, element_list(el)) + struct_m = ccohort%prt%GetState(struct_organ, element_list(el)) + leaf_m = ccohort%prt%GetState(leaf_organ, element_list(el)) + fnrt_m = ccohort%prt%GetState(fnrt_organ, element_list(el)) + store_m = ccohort%prt%GetState(store_organ, element_list(el)) + repro_m = ccohort%prt%GetState(repro_organ, element_list(el)) + total_m = sapw_m+struct_m+leaf_m+fnrt_m+store_m+repro_m + + icdpf = get_cdamagesizepft_class_index(ccohort%dbh, ccohort%crowndamage, ccohort%pft) + + if(element_list(el).eq.carbon12_element)then + this%hvars(ih_totvegc_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_totvegc_cdpf)%r82d(io_si,icdpf) + total_m * ccohort%n + this%hvars(ih_leafc_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_leafc_cdpf)%r82d(io_si,icdpf) + leaf_m * ccohort%n + this%hvars(ih_fnrtc_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_fnrtc_cdpf)%r82d(io_si,icdpf) + fnrt_m * ccohort%n + this%hvars(ih_sapwc_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_sapwc_cdpf)%r82d(io_si,icdpf) + sapw_m * ccohort%n + this%hvars(ih_storec_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_storec_cdpf)%r82d(io_si,icdpf) + store_m * ccohort%n + this%hvars(ih_reproc_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_reproc_cdpf)%r82d(io_si,icdpf) + repro_m * ccohort%n + end if + + ccohort => ccohort%shorter + end do + end if + + cpatch => cpatch%younger end do @@ -3348,23 +3961,44 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_demotion_rate_si_scls(io_si,i_scls) = sites(s)%demotion_rate(i_scls) * days_per_year hio_promotion_rate_si_scls(io_si,i_scls) = sites(s)%promotion_rate(i_scls) * days_per_year end do + ! ! convert kg C / ha / day to gc / m2 / sec hio_demotion_carbonflux_si(io_si) = sites(s)%demotion_carbonflux * g_per_kg * ha_per_m2 * days_per_sec hio_promotion_carbonflux_si(io_si) = sites(s)%promotion_carbonflux * g_per_kg * ha_per_m2 * days_per_sec ! + + + ! mortality-associated carbon fluxes hio_canopy_mortality_carbonflux_si(io_si) = hio_canopy_mortality_carbonflux_si(io_si) + & sites(s)%term_carbonflux_canopy * g_per_kg * days_per_sec * ha_per_m2 - + hio_understory_mortality_carbonflux_si(io_si) = hio_understory_mortality_carbonflux_si(io_si) + & sites(s)%term_carbonflux_ustory * g_per_kg * days_per_sec * ha_per_m2 + ! add site level mortality counting to crownarea diagnostic + hio_canopy_mortality_crownarea_si(io_si) = hio_canopy_mortality_crownarea_si(io_si) + & + sites(s)%fmort_crownarea_canopy + & + sites(s)%term_crownarea_canopy * days_per_year + + hio_understory_mortality_crownarea_si(io_si) = hio_understory_mortality_crownarea_si(io_si) + & + sites(s)%fmort_crownarea_ustory + & + sites(s)%term_crownarea_ustory * days_per_year + & + sites(s)%imort_crownarea + + ! and zero the site-level termination carbon flux variable sites(s)%term_carbonflux_canopy = 0._r8 sites(s)%term_carbonflux_ustory = 0._r8 + sites(s)%term_crownarea_canopy = 0._r8 + sites(s)%term_crownarea_ustory = 0._r8 + sites(s)%imort_crownarea = 0._r8 + sites(s)%fmort_crownarea_ustory = 0._r8 + sites(s)%fmort_crownarea_canopy = 0._r8 ! + ! add the site-level disturbance-associated cwd and litter input fluxes to thir respective flux fields @@ -4218,6 +4852,8 @@ subroutine define_history_vars(this, initialize_variables) use FatesIOVariableKindMod, only : site_fuel_r8, site_cwdsc_r8, site_scag_r8 use FatesIOVariableKindMod, only : site_can_r8, site_cnlf_r8, site_cnlfpft_r8 + use FatesIOVariableKindMod, only : site_cdsc_r8, site_cdpf_r8 + use FatesIOVariableKindMod, only : site_cdcd_r8 use FatesIOVariableKindMod, only : site_scagpft_r8, site_agepft_r8 use FatesIOVariableKindMod, only : site_elem_r8, site_elpft_r8 use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8 @@ -5194,6 +5830,16 @@ subroutine define_history_vars(this, initialize_variables) long='flux of biomass carbon from live to dead pools from mortality of understory plants',use_default='active',& avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_understory_mortality_carbonflux_si ) + + call this%set_history_var(vname='MORTALITY_CROWNAREA_CANOPY', units = 'm2/ha/year', & + long='Crown area of canopy trees that died', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_canopy_mortality_crownarea_si ) + + call this%set_history_var(vname='MORTALITY_CROWNAREA_UNDERSTORY', units = 'm2/ha/year', & + long='Crown aera of understory trees that died',use_default='active',& + avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_understory_mortality_crownarea_si ) ! size class by age dimensioned variables call this%set_history_var(vname='NPLANT_SCAG',units = 'plants/ha', & @@ -5433,6 +6079,11 @@ subroutine define_history_vars(this, initialize_variables) long='age senescence mortality by pft/size',use_default='inactive', & avgflag='A', vtype =site_size_pft_r8, hlms='CLM:ALM', flushval=0.0_r8, & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m10_si_scpf ) + + call this%set_history_var(vname='M11_SCPF', units = 'N/ha/yr', & + long='damage mortality by pft/size',use_default='inactive', & + avgflag='A', vtype =site_size_pft_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_si_scpf ) call this%set_history_var(vname='M10_CAPF',units='N/ha/yr', & long='age senescence mortality by pft/cohort age',use_default='inactive', & @@ -5444,6 +6095,11 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', flushval=0.0_r8, & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_canopy_si_scpf ) + call this%set_history_var(vname='M3_MORTALITY_CANOPY_SCPF', units = 'N/ha/yr', & + long='C starvation mortality of canopy plants by pft/size', use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_canopy_si_scpf ) + call this%set_history_var(vname='C13disc_SCPF', units = 'per mil', & long='C13 discrimination by pft/size',use_default='inactive', & avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', flushval=0.0_r8, & @@ -5469,6 +6125,12 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', flushval=0.0_r8, & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_understory_si_scpf ) + call this%set_history_var(vname='M3_MORTALITY_UNDERSTORY_SCPF', units = 'N/ha/yr', & + long='C starvation mortality of understory plants by pft/size', use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_understory_si_scpf ) + + call this%set_history_var(vname='BSTOR_UNDERSTORY_SCPF', units = 'kgC/ha', & long='biomass carbon in storage pools of understory plants by pft/size', use_default='inactive', & avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', flushval=0.0_r8, & @@ -5618,6 +6280,13 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_size_r8, hlms='CLM:ALM', flushval=0.0_r8, & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_canopy_si_scls ) + call this%set_history_var(vname='M3_MORTALITY_CANOPY_SCLS', units = 'indiv/ha/yr', & + long='C starviation mortality of canopy trees by size class', use_default='active', & + avgflag='A', vtype=site_size_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_canopy_si_scls ) + + + call this%set_history_var(vname='NPLANT_UNDERSTORY_SCLS', units = 'indiv/ha', & long='number of understory plants by size class', use_default='active', & avgflag='A', vtype=site_size_r8, hlms='CLM:ALM', flushval=0.0_r8, & @@ -5682,7 +6351,7 @@ subroutine define_history_vars(this, initialize_variables) long='freezing mortality by size',use_default='active', & avgflag='A', vtype=site_size_r8, hlms='CLM:ALM', flushval=0.0_r8, & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m8_si_scls ) - + call this%set_history_var(vname='M9_SCLS', units = 'N/ha/yr', & long='senescence mortality by size',use_default='active', & avgflag='A', vtype=site_size_r8, hlms='CLM:ALM', flushval=0.0_r8, & @@ -5693,6 +6362,11 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_size_r8, hlms='CLM:ALM', flushval=0.0_r8, & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m10_si_scls ) + call this%set_history_var(vname='M11_SCLS', units = 'N/ha/yr', & + long='damage mortality by size',use_default='active', & + avgflag='A', vtype=site_size_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_si_scls ) + call this%set_history_var(vname='M10_CACLS', units = 'N/ha/yr', & long='age senescence mortality by cohort age',use_default='active', & avgflag='A', vtype=site_coage_r8, hlms='CLM:ALM', flushval=0.0_r8, & @@ -5713,6 +6387,11 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_size_r8, hlms='CLM:ALM', flushval=0.0_r8, & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_understory_si_scls ) + call this%set_history_var(vname='M3_MORTALITY_UNDERSTORY_SCLS', units = 'indiv/ha/yr', & + long='C starvation mortality of understory trees by size class', use_default='active', & + avgflag='A', vtype=site_size_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_understory_si_scls ) + call this%set_history_var(vname='TRIMMING_CANOPY_SCLS', units = 'indiv/ha', & long='trimming term of canopy plants by size class', use_default='inactive', & avgflag='A', vtype=site_size_r8, hlms='CLM:ALM', flushval=0.0_r8, & @@ -5934,6 +6613,203 @@ subroutine define_history_vars(this, initialize_variables) upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_resp_m_understory_si_scls ) + ! CROWN DAMAGE VARIABLES + + call this%set_history_var(vname='DAMAGE_CFLUX_CDCD', units = 'g C / m2 / sec', & + long='damage carbonflux between damage classes', use_default='inactive', & + avgflag='A', vtype=site_cdcd_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_damage_cflux_si_cdcd ) + + call this%set_history_var(vname='DAMAGE_RATE_CDCD', units = 'N / ha / year', & + long='damage rate between damage classes', use_default='inactive', & + avgflag='A', vtype=site_cdcd_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_damage_rate_si_cdcd ) + + call this%set_history_var(vname='RECOVERY_CFLUX_CDCD', units = 'g C / m2 / sec', & + long='recovery carbonflux between damage classes', use_default='inactive', & + avgflag='A', vtype=site_cdcd_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_recovery_cflux_si_cdcd ) + + call this%set_history_var(vname='RECOVERY_RATE_CDCD', units = 'N / ha / year', & + long='recovery rate between damage classes', use_default='inactive', & + avgflag='A', vtype=site_cdcd_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_recovery_rate_si_cdcd ) + + call this%set_history_var(vname='CROWNAREA_CANOPY_DAMAGE', units = 'm2 / ha / year', & + long='crownarea lost to damage each year', use_default='inactive', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_crownarea_canopy_damage_si ) + + call this%set_history_var(vname='CROWNAREA_USTORY_DAMAGE', units = 'm2 / ha / year', & + long='crownarea lost to damage each year', use_default='inactive', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_crownarea_ustory_damage_si ) + + call this%set_history_var(vname='NPLANT_CDSC', units = 'N / damage x size class / ha / yr', & + long='N. plants per damage x size class', use_default='inactive', & + avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_si_cdsc ) + + call this%set_history_var(vname='NPLANT_CDPF', units = 'N / damage x size x pft class / ha / yr', & + long='N. plants per damage x size x pft class', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_si_cdpf ) + + call this%set_history_var(vname='NPLANT_CANOPY_CDSC', units = 'N / damage x size class / ha / yr', & + long='N. plants in the canopy per damage x size class', use_default='inactive', & + avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_canopy_si_cdsc ) + + call this%set_history_var(vname='NPLANT_CANOPY_CDPF', units = 'N / damage x size x pft class / ha / yr', & + long='N. plants per damage x size x pft class', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_canopy_si_cdpf ) + + call this%set_history_var(vname='NPLANT_UNDERSTORY_CDSC', units = 'N / damage x size class / ha / yr', & + long='N. plants in the understory per damage x size class', use_default='inactive', & + avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_understory_si_cdsc ) + + call this%set_history_var(vname='NPLANT_UNDERSTORY_CDPF', units = 'N / damage x size x pft class / ha / yr', & + long='N. plants in the understory per damage x size x pft class', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_understory_si_cdpf ) + + call this%set_history_var(vname='M3_CDPF', units = 'N/ha/yr', & + long='carbon starvation mortality by damaage/pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_si_cdpf ) + + call this%set_history_var(vname='M3_CDSC', units = 'N/ha/yr', & + long='carbon starvation mortality by damage/size', use_default='inactive', & + avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_si_cdsc ) + + call this%set_history_var(vname='M11_CDPF', units = 'N/ha/yr', & + long='damage mortality by damaage/pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_si_cdpf ) + + call this%set_history_var(vname='M11_CDSC', units = 'N/ha/yr', & + long='damage mortality by damage/size', use_default='inactive', & + avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_si_cdsc ) + + call this%set_history_var(vname='MORTALITY_CDSC', units = 'N/ha/yr', & + long='mortality by damage class by size', use_default='inactive', & + avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_si_cdsc ) + + call this%set_history_var(vname='MORTALITY_CDPF', units = 'N/ha/yr', & + long='mortality by damage class by size by pft', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_si_cdpf ) + + call this%set_history_var(vname='M3_MORTALITY_CANOPY_CDSC', units = 'indiv/ha/yr', & + long='C starviation mortality of canopy trees by damage/size class', use_default='inactive', & + avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_canopy_si_cdsc) + + call this%set_history_var(vname='M3_MORTALITY_CANOPY_CDPF', units = 'N/ha/yr', & + long='C starvation mortality of canopy plants by damage/pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_canopy_si_cdpf ) + + call this%set_history_var(vname='M3_MORTALITY_UNDERSTORY_CDPF', units = 'N/ha/yr', & + long='C starvation mortality of understory plants by pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_understory_si_cdpf ) + + call this%set_history_var(vname='M3_MORTALITY_UNDERSTORY_CDSC', units = 'indiv/ha/yr', & + long='C starvation mortality of understory trees by damage/size class', use_default='inactive', & + avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_understory_si_cdsc) + + call this%set_history_var(vname='M11_MORTALITY_CANOPY_CDSC', units = 'indiv/ha/yr', & + long='damage mortality of canopy trees by damage/size class', use_default='inactive', & + avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_canopy_si_cdsc) + + call this%set_history_var(vname='M11_MORTALITY_CANOPY_CDPF', units = 'N/ha/yr', & + long='damage mortality of canopy plants by damage/pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_canopy_si_cdpf ) + + call this%set_history_var(vname='M11_MORTALITY_UNDERSTORY_CDPF', units = 'N/ha/yr', & + long='damage mortality of understory plants by pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_understory_si_cdpf ) + + call this%set_history_var(vname='MORTALITY_CANOPY_CDPF', units = 'N/ha/yr', & + long='mortality of canopy plants by damage/pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_canopy_si_cdpf ) + + call this%set_history_var(vname='MORTALITY_UNDERSTORY_CDPF', units = 'N/ha/yr', & + long='mortality of understory plants by pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_understory_si_cdpf ) + + call this%set_history_var(vname='M11_MORTALITY_UNDERSTORY_CDSC', units = 'indiv/ha/yr', & + long='damage mortality of understory trees by damage/size class', use_default='inactive', & + avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_understory_si_cdsc) + + call this%set_history_var(vname='TRIMMING_DAMAGE_CDSC', units = 'indiv/ha', & + long='trimming term of plants by size class by damage class', use_default='inactive', & + avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_trimming_damage_si_cdsc ) + + call this%set_history_var(vname='DDBH_CDSC', units = 'cm/year/ha', & + long='ddbh annual increment growth by damage and size', use_default='inactive', & + avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_si_cdsc ) + + call this%set_history_var(vname='DDBH_CDPF', units = 'cm/year/ha', & + long='ddbh annual increment growth by damage x size pft', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_si_cdpf ) + + call this%set_history_var(vname='DDBH_CANOPY_CDPF', units = 'cm/year/ha', & + long='ddbh annual canopy increment growth by damage x size pft', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_canopy_si_cdpf ) + + call this%set_history_var(vname='DDBH_UNDERSTORY_CDPF', units = 'cm/year/ha', & + long='ddbh annual understory increment growth by damage x size pft', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_understory_si_cdpf ) + + call this%set_history_var(vname='TOTVEGC_CDPF', units='kgC/ha', & + long='total vegetation carbon mass in live plants by damage x size-class x pft', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=hlm_hio_ignore_val, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_totvegc_cdpf ) + + call this%set_history_var(vname='LEAFC_CDPF', units='kgC/ha', & + long='leaf carbon mass by damage x size-class x pft', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=hlm_hio_ignore_val, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_leafc_cdpf ) + + call this%set_history_var(vname='FNRTC_CDPF', units='kgC/ha', & + long='fine-root carbon mass by damage x size-class x pft', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=hlm_hio_ignore_val, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_fnrtc_cdpf ) + + call this%set_history_var(vname='SAPWC_CDPF', units='kgC/ha', & + long='sapwood carbon mass by damage x size-class x pft', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=hlm_hio_ignore_val, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_sapwc_cdpf ) + + call this%set_history_var(vname='STOREC_CDPF', units='kgC/ha', & + long='storage carbon mass by damage x size-class x pft', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=hlm_hio_ignore_val, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_storec_cdpf ) + + call this%set_history_var(vname='REPROC_CDPF', units='kgC/ha', & + long='reproductive carbon mass (on plant) by damage x size-class x pft', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=hlm_hio_ignore_val, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_reproc_cdpf ) + ! CARBON BALANCE VARIABLES THAT DEPEND ON HLM BGC INPUTS call this%set_history_var(vname='NEP', units='gC/m^2/s', & diff --git a/main/FatesHistoryVariableType.F90 b/main/FatesHistoryVariableType.F90 index 6457e644f1..ee8aa9d858 100644 --- a/main/FatesHistoryVariableType.F90 +++ b/main/FatesHistoryVariableType.F90 @@ -12,6 +12,8 @@ module FatesHistoryVariableType use FatesIOVariableKindMod, only : site_fuel_r8, site_cwdsc_r8, site_scag_r8 use FatesIOVariableKindMod, only : site_scagpft_r8, site_agepft_r8 use FatesIOVariableKindMod, only : site_can_r8, site_cnlf_r8, site_cnlfpft_r8 + use FatesIOVariableKindMod, only : site_cdamage_r8, site_cdsc_r8, site_cdpf_r8 + use FatesIOVariableKindMod, only : site_cdcd_r8 use FatesIOVariableKindMod, only : site_elem_r8, site_elpft_r8 use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8 use FatesIOVariableKindMod, only : iotype_index, site_agefuel_r8 @@ -173,6 +175,22 @@ subroutine Init(this, vname, units, long, use_default, & allocate(this%r82d(lb1:ub1, lb2:ub2)) this%r82d(:,:) = flushval + case(site_cdamage_r8) + allocate(this%r82d(lb1:ub1, lb2:ub2)) + this%r82d(:,:) = flushval + + case(site_cdcd_r8) + allocate(this%r82d(lb1:ub1, lb2:ub2)) + this%r82d(:,:) = flushval + + case(site_cdsc_r8) + allocate(this%r82d(lb1:ub1, lb2:ub2)) + this%r82d(:,:) = flushval + + case(site_cdpf_r8) + allocate(this%r82d(lb1:ub1, lb2:ub2)) + this%r82d(:,:) = flushval + case(site_scag_r8) allocate(this%r82d(lb1:ub1, lb2:ub2)) this%r82d(:,:) = flushval @@ -316,6 +334,14 @@ subroutine Flush(this, thread, dim_bounds, dim_kinds) this%r82d(lb1:ub1, lb2:ub2) = this%flushval case(site_cnlfpft_r8) this%r82d(lb1:ub1, lb2:ub2) = this%flushval + case(site_cdamage_r8) + this%r82d(lb1:ub1, lb2:ub2) = this%flushval + case(site_cdcd_r8) + this%r82d(lb1:ub1, lb2:ub2) = this%flushval + case(site_cdsc_r8) + this%r82d(lb1:ub1, lb2:ub2) = this%flushval + case(site_cdpf_r8) + this%r82d(lb1:ub1, lb2:ub2) = this%flushval case(site_scag_r8) this%r82d(lb1:ub1, lb2:ub2) = this%flushval case(site_scagpft_r8) diff --git a/main/FatesIODimensionsMod.F90 b/main/FatesIODimensionsMod.F90 index 522da97653..58cb898632 100644 --- a/main/FatesIODimensionsMod.F90 +++ b/main/FatesIODimensionsMod.F90 @@ -27,8 +27,10 @@ module FatesIODimensionsMod character(*), parameter, public :: levcan = 'fates_levcan' ! matches histFileMod character(*), parameter, public :: levcnlf = 'fates_levcnlf' ! matches histFileMod character(*), parameter, public :: levcnlfpft = 'fates_levcnlfpf' ! matches histFileMod + character(*), parameter, public :: levcdcd = 'fates_levcdcd' ! matches histFileMod + character(*), parameter, public :: levcdsc = 'fates_levcdsc' ! matches histFileMod + character(*), parameter, public :: levcdpf = 'fates_levcdpf' ! matches histFileMod character(*), parameter, public :: levagefuel = 'fates_levagefuel' ! matches histFileMod - character(*), parameter, public :: levelem = 'fates_levelem' character(*), parameter, public :: levelpft = 'fates_levelpft' character(*), parameter, public :: levelcwd = 'fates_levelcwd' @@ -81,6 +83,15 @@ module FatesIODimensionsMod ! levcnlfpft = This is a structure that records the boundaries for the ! number of canopy layer x leaf layer x pft dimension + ! levcdcd = This is a structure that records the boundaries for the + ! number of crown damage x crown damage classes - for diagnostic fluxes + + ! levcdsc = This is a structure that records the boundaries for the + ! number of crown damage x size classes dimension + + ! levcdpf = This is a structure that records the boundaries for the + ! number of crown damage x size classes x pft dimension + ! levscag = This is a strcture that records the boundaries for the ! number of size-classes x patch age @@ -138,6 +149,14 @@ module FatesIODimensionsMod integer :: cnlf_end integer :: cnlfpft_begin integer :: cnlfpft_end + integer :: cdamage_begin + integer :: cdamage_end + integer :: cdcd_begin + integer :: cdcd_end + integer :: cdsc_begin + integer :: cdsc_end + integer :: cdpf_begin + integer :: cdpf_end integer :: elem_begin integer :: elem_end integer :: elpft_begin diff --git a/main/FatesIOVariableKindMod.F90 b/main/FatesIOVariableKindMod.F90 index 93b34ebab3..06f6c421ea 100644 --- a/main/FatesIOVariableKindMod.F90 +++ b/main/FatesIOVariableKindMod.F90 @@ -31,6 +31,10 @@ module FatesIOVariableKindMod character(*), parameter, public :: site_can_r8 = 'SI_CAN_R8' character(*), parameter, public :: site_cnlf_r8 = 'SI_CNLF_R8' character(*), parameter, public :: site_cnlfpft_r8 = 'SI_CNLFPFT_R8' + character(*), parameter, public :: site_cdamage_r8 = 'SI_CDAMAGE_R8' + character(*), parameter, public :: site_cdcd_r8 = 'SI_CDCD_R8' + character(*), parameter, public :: site_cdpf_r8 = 'SI_CDPF_R8' + character(*), parameter, public :: site_cdsc_r8 = 'SI_CDSC_R8' character(*), parameter, public :: site_scag_r8 = 'SI_SCAG_R8' character(*), parameter, public :: site_scagpft_r8 = 'SI_SCAGPFT_R8' character(*), parameter, public :: site_agepft_r8 = 'SI_AGEPFT_R8' diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 5561a78f52..61798dc7d6 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -40,6 +40,7 @@ module FatesInterfaceMod use EDParamsMod , only : ED_val_history_ageclass_bin_edges use EDParamsMod , only : ED_val_history_height_bin_edges use EDParamsMod , only : ED_val_history_coageclass_bin_edges + use EDParamsMod , only : ED_val_ncrowndamage use CLMFatesParamInterfaceMod , only : FatesReadParameters use EDTypesMod , only : p_uptake_mode use EDTypesMod , only : n_uptake_mode @@ -135,7 +136,7 @@ module FatesInterfaceMod public :: zero_bcs public :: set_bcs -contains + contains ! ==================================================================================== subroutine FatesInterfaceInit(log_unit,global_verbose) @@ -711,10 +712,14 @@ subroutine SetFatesGlobalElements(use_fates) ! ! -------------------------------------------------------------------------------- + use EDParamsMod, only : ED_val_ncrowndamage + implicit none + logical,intent(in) :: use_fates ! Is fates turned on? + integer :: i if (use_fates) then @@ -753,6 +758,10 @@ subroutine SetFatesGlobalElements(use_fates) nleafage = size(prt_params%leaf_long,dim=2) end if + ! Identify the number of damage classes + ncrowndamage = ED_val_ncrowndamage + + ! These values are used to define the restart file allocations and general structure ! of memory for the cohort arrays @@ -804,6 +813,7 @@ subroutine SetFatesGlobalElements(use_fates) nlevheight = size(ED_val_history_height_bin_edges,dim=1) nlevcoage = size(ED_val_history_coageclass_bin_edges,dim=1) + ! do some checks on the size, age, and height bin arrays to make sure they make sense: ! make sure that all start at zero, and that both are monotonically increasing if ( ED_val_history_sizeclass_bin_edges(1) .ne. 0._r8 ) then @@ -931,6 +941,7 @@ subroutine fates_history_maps use EDTypesMod, only : NFSC use EDTypesMod, only : nclmax + use FatesInterfaceTypesMod, only : ncrowndamage use EDTypesMod, only : nlevleaf use EDParamsMod, only : ED_val_history_sizeclass_bin_edges use EDParamsMod, only : ED_val_history_ageclass_bin_edges @@ -951,6 +962,8 @@ subroutine fates_history_maps integer :: icwd integer :: ifuel integer :: ican + integer :: icdam + integer :: icdcd integer :: ileaf integer :: iage integer :: iheight @@ -969,6 +982,15 @@ subroutine fates_history_maps allocate( fates_hdim_pfmap_levcapf(1:nlevcoage*numpft)) allocate( fates_hdim_camap_levcapf(1:nlevcoage*numpft)) + allocate( fates_hdim_levcdam(ncrowndamage )) + allocate( fates_hdim_cdimap_levcdcd(ncrowndamage*(ncrowndamage+1))) + allocate( fates_hdim_cdjmap_levcdcd(ncrowndamage*(ncrowndamage+1))) + allocate( fates_hdim_scmap_levcdsc(nlevsclass*ncrowndamage)) + allocate( fates_hdim_cdmap_levcdsc(nlevsclass*ncrowndamage)) + allocate( fates_hdim_scmap_levcdpf(nlevsclass*ncrowndamage * numpft)) + allocate( fates_hdim_cdmap_levcdpf(nlevsclass*ncrowndamage * numpft)) + allocate( fates_hdim_pftmap_levcdpf(nlevsclass*ncrowndamage * numpft)) + allocate( fates_hdim_levcan(nclmax)) allocate( fates_hdim_levelem(num_elements)) allocate( fates_hdim_canmap_levcnlf(nlevleaf*nclmax)) @@ -1020,6 +1042,12 @@ subroutine fates_history_maps fates_hdim_levcan(ican) = ican end do + ! make damage array + do icdam = 1,ncrowndamage + fates_hdim_levcdam(icdam) = icdam + end do + + ! Make an element array, each index is the PARTEH global identifier index do iel = 1, num_elements @@ -1090,6 +1118,25 @@ subroutine fates_history_maps end do end do + i=0 + do icdam=1,ncrowndamage + do isc=1,nlevsclass + i=i+1 + fates_hdim_scmap_levcdsc(i) = isc + fates_hdim_cdmap_levcdsc(i) = icdam + end do + end do + + i=0 + do icdam=1,ncrowndamage + do icdcd=1,ncrowndamage+1 + i=i+1 + fates_hdim_cdimap_levcdcd(i) = icdcd + fates_hdim_cdjmap_levcdcd(i) = icdam + end do + end do + + i=0 do ipft=1,numpft do ican=1,nclmax @@ -1114,6 +1161,18 @@ subroutine fates_history_maps end do end do + i=0 + do ipft=1,numpft + do icdam=1,ncrowndamage + do isc=1,nlevsclass + i=i+1 + fates_hdim_scmap_levcdpf(i) = isc + fates_hdim_cdmap_levcdpf(i) = icdam + fates_hdim_pftmap_levcdpf(i) = ipft + end do + end do + end do + i=0 do ipft=1,numpft do iage=1,nlevage @@ -1239,6 +1298,8 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) hlm_use_lu_harvest = unset_int hlm_num_lu_harvest_cats = unset_int hlm_use_cohort_age_tracking = unset_int + hlm_use_understory_damage = unset_int + hlm_use_canopy_damage = unset_int hlm_use_logging = unset_int hlm_use_ed_st3 = unset_int hlm_use_ed_prescribed_phys = unset_int @@ -1551,6 +1612,20 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) call endrun(msg=errMsg(sourcefile, __LINE__)) end if + if(hlm_use_understory_damage .eq. unset_int) then + if (fates_global_verbose()) then + write(fates_log(), *) 'switch for understory damage unset: hlm_use_understory_damage, exiting' + end if + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + if(hlm_use_canopy_damage .eq. unset_int) then + if (fates_global_verbose()) then + write(fates_log(), *) 'switch for canopy damage unset: hlm_use_canopy_damage, exiting' + end if + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + if(hlm_use_sp.eq.itrue.and.hlm_use_nocomp.eq.ifalse)then write(fates_log(), *) 'SP cannot be on if nocomp mode is off. Exiting. ' call endrun(msg=errMsg(sourcefile, __LINE__)) @@ -1723,6 +1798,18 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) if (fates_global_verbose()) then write(fates_log(),*) 'Transfering hlm_use_cohort_age_tracking= ',ival,' to FATES' end if + + case('use_understory_damage') + hlm_use_understory_damage = ival + if (fates_global_verbose()) then + write(fates_log(),*) 'Transfering hlm_use_understory_damage= ',ival,' to FATES' + end if + + case('use_canopy_damage') + hlm_use_canopy_damage = ival + if (fates_global_verbose()) then + write(fates_log(),*) 'Transfering hlm_use_canopy_damage= ',ival,' to FATES' + end if case('use_logging') hlm_use_logging = ival diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 1fe7c2fa26..b53e891ad1 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -150,6 +150,14 @@ module FatesInterfaceTypesMod integer, public :: hlm_use_cohort_age_tracking ! This flag signals whether or not to use ! cohort age tracking. 1 = TRUE, 0 = FALSE + + integer, public :: hlm_use_canopy_damage ! This flag signals whether or not to use + ! the canopy damage module. 1 = TRUE, 0 = FALSE + + integer, public :: hlm_use_understory_damage ! This flag signals whether or not to use + ! understory damage. 1 = TRUE, 0 = FALSE + + integer, public :: hlm_use_ed_st3 ! This flag signals whether or not to use ! (ST)atic (ST)and (ST)ructure mode (ST3) ! Essentially, this gives us the ability @@ -231,6 +239,15 @@ module FatesInterfaceTypesMod real(r8), public, allocatable :: fates_hdim_levsclass(:) ! plant size class lower bound dimension integer , public, allocatable :: fates_hdim_pfmap_levscpf(:) ! map of pfts into size-class x pft dimension integer , public, allocatable :: fates_hdim_scmap_levscpf(:) ! map of size-class into size-class x pft dimension + integer , public, allocatable :: fates_hdim_levcdam(:) ! crown damage dimension + integer , public, allocatable :: fates_hdim_pftmap_levcdpf(:) ! map of pfts into size x crowndamage x pft dimension + integer , public, allocatable :: fates_hdim_cdmap_levcdpf(:) ! map of crowndamage into size x crowndamage x pft + integer , public, allocatable :: fates_hdim_scmap_levcdpf(:) ! map of size into size x crowndamage x pft + integer , public, allocatable :: fates_hdim_cdmap_levcdsc(:) ! map of crowndamage into size x crowndamage + integer , public, allocatable :: fates_hdim_scmap_levcdsc(:) ! map of size into size x crowndamage + integer , public, allocatable :: fates_hdim_cdimap_levcdcd(:) ! map of current damage into damage x damage + mortality + integer , public, allocatable :: fates_hdim_cdjmap_levcdcd(:) ! map of new damage into damage x damage + mortality + real(r8), public, allocatable :: fates_hdim_levage(:) ! patch age lower bound dimension real(r8), public, allocatable :: fates_hdim_levheight(:) ! height lower bound dimension integer , public, allocatable :: fates_hdim_levpft(:) ! plant pft dimension @@ -296,7 +313,8 @@ module FatesInterfaceTypesMod integer, public :: nlevheight ! The total number of height bins output to history integer, public :: nlevcoage ! The total number of cohort age bins output to history integer, public :: nleafage ! The total number of leaf age classes - + integer, public :: ncrowndamage ! The total number of damage classes + ! ------------------------------------------------------------------------------------- ! Structured Boundary Conditions (SITE/PATCH SCALE) ! For floating point arrays, it is sometimes the convention to define the arrays as diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index 19596a833e..0080a2ec05 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -1015,29 +1015,31 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & temp_cohort%n = c_nplant * cpatch%area / real(ncohorts_to_create,r8) temp_cohort%dbh = c_dbh + temp_cohort%crowndamage = 1 ! assume undamaged call h_allom(c_dbh,temp_cohort%pft,temp_cohort%hite) temp_cohort%canopy_trim = 1.0_r8 - - call bagw_allom(temp_cohort%dbh,temp_cohort%pft,c_agw) + call bagw_allom(temp_cohort%dbh,temp_cohort%pft, & + temp_cohort%crowndamage, temp_cohort%branch_frac, c_agw) ! Calculate coarse root biomass from allometry call bbgw_allom(temp_cohort%dbh,temp_cohort%pft,c_bgw) ! Calculate the leaf biomass (calculates a maximum first, then applies canopy trim ! and sla scaling factors) - call bleaf(temp_cohort%dbh,temp_cohort%pft,temp_cohort%canopy_trim,c_leaf) - + call bleaf(temp_cohort%dbh,temp_cohort%pft,1,& + temp_cohort%canopy_trim,c_leaf) + ! Calculate fine root biomass call bfineroot(temp_cohort%dbh,temp_cohort%pft,temp_cohort%canopy_trim,c_fnrt) ! Calculate sapwood biomass - call bsap_allom(temp_cohort%dbh,temp_cohort%pft,temp_cohort%canopy_trim, a_sapw, c_sapw) - + call bsap_allom(temp_cohort%dbh,temp_cohort%pft,1, 1.0_r8,temp_cohort%canopy_trim, a_sapw, c_sapw) + call bdead_allom( c_agw, c_bgw, c_sapw, temp_cohort%pft, c_struct ) - - call bstore_allom(temp_cohort%dbh, temp_cohort%pft, temp_cohort%canopy_trim, c_store) - + + call bstore_allom(temp_cohort%dbh, temp_cohort%pft, 1, temp_cohort%canopy_trim, c_store) + temp_cohort%laimemory = 0._r8 temp_cohort%sapwmemory = 0._r8 temp_cohort%structmemory = 0._r8 @@ -1156,14 +1158,11 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & call prt_obj%CheckInitialConditions() - - ! Since spread is a canopy level calculation, we need to provide an initial guess here. - call create_cohort(csite, cpatch, temp_cohort%pft, temp_cohort%n, temp_cohort%hite, & temp_cohort%coage, temp_cohort%dbh, & prt_obj, temp_cohort%laimemory,temp_cohort%sapwmemory, temp_cohort%structmemory, & - cstatus, rstatus, temp_cohort%canopy_trim,temp_cohort%c_area, & - 1, csite%spread, bc_in) + cstatus, rstatus, temp_cohort%canopy_trim, temp_cohort%c_area, & + 1, temp_cohort%crowndamage, temp_cohort%branch_frac, csite%spread, bc_in) deallocate(temp_cohort) ! get rid of temporary cohort diff --git a/main/FatesParameterDerivedMod.F90 b/main/FatesParameterDerivedMod.F90 index 66445c1906..1857dfdffe 100644 --- a/main/FatesParameterDerivedMod.F90 +++ b/main/FatesParameterDerivedMod.F90 @@ -13,6 +13,8 @@ module FatesParameterDerivedMod use FatesConstantsMod, only : umolC_to_kgC use FatesConstantsMod, only : g_per_kg use FatesInterfaceTypesMod, only : nleafage + use FatesInterfaceTypesMod, only : ncrowndamage + use FatesGlobals , only : fates_log implicit none private @@ -25,17 +27,27 @@ module FatesParameterDerivedMod ! rate at 25C (umol CO2/m**2/s) real(r8), allocatable :: kp25top(:,:) ! canopy top: initial slope of CO2 response ! curve (C4 plants) at 25C + + real(r8), allocatable :: branch_frac(:) ! fraction of aboveground biomass in branches (as + ! oppose to stems) - for use in damage allometries + + real(r8), allocatable :: damage_transitions(:,:,:) ! matrix of transition probabilities between + ! damage classes - one per PFT + contains procedure :: Init + procedure :: InitDamageTransitions procedure :: InitAllocate + procedure :: InitAllocateDamageTransitions end type param_derived_type type(param_derived_type), public :: param_derived -contains - +contains + + ! =================================================================================== subroutine InitAllocate(this,numpft) class(param_derived_type), intent(inout) :: this @@ -44,23 +56,43 @@ subroutine InitAllocate(this,numpft) allocate(this%jmax25top(numpft,nleafage)) allocate(this%tpu25top(numpft,nleafage)) allocate(this%kp25top(numpft,nleafage)) + + allocate(this%branch_frac(numpft)) + return end subroutine InitAllocate ! ===================================================================================== - + + ! =================================================================================== + subroutine InitAllocateDamageTransitions(this,ncrowndamage, numpft) + + class(param_derived_type), intent(inout) :: this + integer, intent(in) :: ncrowndamage + integer, intent(in) :: numpft + + allocate(this%damage_transitions(ncrowndamage,ncrowndamage, numpft)) + + return + end subroutine InitAllocateDamageTransitions + + ! ===================================================================================== + subroutine Init(this,numpft) use EDPftvarcon, only: EDPftvarcon_inst - + use SFParamsMod, only: SF_val_CWD_frac + use FatesLitterMod, only : ncwd + class(param_derived_type), intent(inout) :: this integer, intent(in) :: numpft ! local variables integer :: ft ! pft index integer :: iage ! leaf age class index - + integer :: c ! cwd index + associate( vcmax25top => EDPftvarcon_inst%vcmax25top ) call this%InitAllocate(numpft) @@ -85,11 +117,61 @@ subroutine Init(this,numpft) this%kp25top(ft,iage) = 20000._r8 * vcmax25top(ft,iage) end do + + ! Allocate fraction of biomass in branches + this%branch_frac(ft) = sum(SF_val_CWD_frac(1:3)) - end do !ft + end do !ft end associate return end subroutine Init +!========================================================================= + + subroutine InitDamageTransitions(this, ncrowndamage, numpft) + + use EDPftvarcon, only: EDPftvarcon_inst + + + class(param_derived_type), intent(inout) :: this + integer, intent(in) :: ncrowndamage + integer, intent(in) :: numpft + + ! local variables + integer :: ft ! pft index + integer :: i ! crowndamage index + real(r8) :: damage_frac ! damage fraction + + + call this%InitAllocateDamageTransitions(ncrowndamage, numpft) + + do ft = 1, numpft + + damage_frac = EDPftvarcon_inst%damage_frac(ft) + + do i = 1, ncrowndamage + + ! zero the column + this%damage_transitions(i,:,ft) = 0._r8 + ! 1 - damage rate stay the same + this%damage_transitions(i,i,ft) = 1.0_r8 - damage_frac + + if(i < ncrowndamage) then + ! fraction damaged get evenly split between higher damage classes + this%damage_transitions(i,i+1:ncrowndamage,ft) = damage_frac/(ncrowndamage - i) + end if + ! Make sure it sums to one - they have to go somewhere + this%damage_transitions(i, :, ft) = this%damage_transitions(i, :, ft)/SUM(this%damage_transitions(i, :, ft)) + end do + + write(fates_log(),'(a/,5(F12.6,1x))') 'annual transition matrix : ', this%damage_transitions(:,:,ft) + end do + + + + + return + end subroutine InitDamageTransitions + end module FatesParameterDerivedMod diff --git a/main/FatesParametersInterface.F90 b/main/FatesParametersInterface.F90 index f69d4ef5bf..f37b63b93c 100644 --- a/main/FatesParametersInterface.F90 +++ b/main/FatesParametersInterface.F90 @@ -31,6 +31,7 @@ module FatesParametersInterface character(len=*), parameter, public :: dimension_name_hydr_organs = 'fates_hydr_organs' character(len=*), parameter, public :: dimension_name_prt_organs = 'fates_prt_organs' character(len=*), parameter, public :: dimension_name_leaf_age = 'fates_leafage_class' + character(len=*), parameter, public :: dimension_name_damage = 'fates_damage_class' character(len=*), parameter, public :: dimension_name_history_size_bins = 'fates_history_size_bins' character(len=*), parameter, public :: dimension_name_history_age_bins = 'fates_history_age_bins' character(len=*), parameter, public :: dimension_name_history_height_bins = 'fates_history_height_bins' diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 5fe3b267a1..e8a0469d1d 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -33,6 +33,7 @@ module FatesRestartInterfaceMod use EDCohortDynamicsMod, only : InitPRTBoundaryConditions use FatesPlantHydraulicsMod, only : InitHydrCohort use FatesInterfaceTypesMod, only : nlevsclass + use FatesInterfaceTypesMod, only : ncrowndamage use FatesLitterMod, only : litter_type use FatesLitterMod, only : ncwd use FatesLitterMod, only : ndcmpy @@ -93,6 +94,7 @@ module FatesRestartInterfaceMod integer :: ir_ncohort_pa integer :: ir_canopy_layer_co integer :: ir_canopy_layer_yesterday_co + integer :: ir_crowndamage_co integer :: ir_canopy_trim_co integer :: ir_size_class_lasttimestep_co integer :: ir_dbh_co @@ -116,6 +118,7 @@ module FatesRestartInterfaceMod integer :: ir_frmort_co integer :: ir_smort_co integer :: ir_asmort_co + integer :: ir_dgmort_co integer :: ir_c_area_co integer :: ir_treelai_co integer :: ir_treesai_co @@ -198,11 +201,16 @@ module FatesRestartInterfaceMod integer :: ir_promrate_sisc integer :: ir_termcflux_cano_si integer :: ir_termcflux_usto_si + integer :: ir_termcarea_cano_si + integer :: ir_termcarea_usto_si integer :: ir_democflux_si integer :: ir_promcflux_si integer :: ir_imortcflux_si + integer :: ir_imortcarea_si integer :: ir_fmortcflux_cano_si integer :: ir_fmortcflux_usto_si + integer :: ir_fmortcarea_cano_si + integer :: ir_fmortcarea_usto_si integer :: ir_cwdagin_flxdg integer :: ir_cwdbgin_flxdg integer :: ir_leaflittin_flxdg @@ -213,6 +221,25 @@ module FatesRestartInterfaceMod integer :: ir_errfates_mbal integer :: ir_prt_base ! Base index for all PRT variables + ! Damage x damage or damage x size + integer :: ir_imortrate_sicdpf + integer :: ir_termnindiv_cano_sicdpf + integer :: ir_termnindiv_usto_sicdpf + integer :: ir_fmortrate_cano_sicdpf + integer :: ir_fmortrate_usto_sicdpf + integer :: ir_imortcflux_sicdsc + integer :: ir_termcflux_cano_sicdsc + integer :: ir_termcflux_usto_sicdsc + integer :: ir_fmortcflux_cano_sicdsc + integer :: ir_fmortcflux_usto_sicdsc + integer :: ir_damage_cflux_sicd + integer :: ir_damage_rate_sicd + integer :: ir_recovery_cflux_sicd + integer :: ir_recovery_rate_sicd + integer :: ir_crownarea_cano_si + integer :: ir_crownarea_usto_si + + ! Hydraulic indices integer :: ir_hydro_th_ag_covec integer :: ir_hydro_th_troot @@ -671,7 +698,6 @@ subroutine define_restart_vars(this, initialize_variables) long_name='fates cohort - seed production', units='kgC/plant', flushval = flushinvalid, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_seed_prod_co ) - call this%set_restart_var(vname='fates_canopy_layer', vtype=cohort_int, & long_name='ed cohort - canopy_layer', units='unitless', flushval = flushinvalid, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_canopy_layer_co ) @@ -680,6 +706,10 @@ subroutine define_restart_vars(this, initialize_variables) long_name='ed cohort - canopy_layer_yesterday', units='unitless', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_canopy_layer_yesterday_co ) + call this%set_restart_var(vname='fates_crowndamage', vtype=cohort_int, & + long_name='ed cohort - crowndamage class', units='unitless', flushval = flushinvalid, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_crowndamage_co ) + call this%set_restart_var(vname='fates_canopy_trim', vtype=cohort_r8, & long_name='ed cohort - canopy_trim', units='fraction', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_canopy_trim_co ) @@ -835,6 +865,11 @@ subroutine define_restart_vars(this, initialize_variables) units = '/year', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_asmort_co ) + call this%set_restart_var(vname='fates_dgmort', vtype=cohort_r8, & + long_name='ed cohort - damage mortality rate', & + units = '/year', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_dgmort_co ) + call this%set_restart_var(vname='fates_lmort_direct', vtype=cohort_r8, & long_name='ed cohort - directly logging mortality rate', & units='%/event', flushval = flushzero, & @@ -1165,7 +1200,6 @@ subroutine define_restart_vars(this, initialize_variables) units='0/1', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_area_pft_sift) - call this%set_restart_var(vname='fates_fmortrate_canopy', vtype=cohort_r8, & long_name='fates diagnostics on fire mortality canopy', & units='indiv/ha/year', flushval = flushzero, & @@ -1180,7 +1214,7 @@ subroutine define_restart_vars(this, initialize_variables) long_name='fates diagnostics on impact mortality', & units='indiv/ha/year', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_imortrate_siscpf) - + call this%set_restart_var(vname='fates_fmortrate_crown', vtype=cohort_r8, & long_name='fates diagnostics on crown fire mortality', & units='indiv/ha/year', flushval = flushzero, & @@ -1220,8 +1254,13 @@ subroutine define_restart_vars(this, initialize_variables) long_name='biomass of indivs killed due to impact mort', & units='kgC/ha/day', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_imortcflux_si) + + call this%set_restart_var(vname='fates_imortcarea', vtype=site_r8, & + long_name='crownarea of indivs killed due to impact mort', & + units='m2/ha/day', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_imortcarea_si) - call this%set_restart_var(vname='fates_fmortcflux_canopy', vtype=site_r8, & + call this%set_restart_var(vname='fates_fmortcflux_canopy', vtype=site_r8, & long_name='fates diagnostic biomass of canopy fire', & units='gC/m2/sec', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_fmortcflux_cano_si) @@ -1251,6 +1290,106 @@ subroutine define_restart_vars(this, initialize_variables) units='', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_promcflux_si ) + call this%set_restart_var(vname='fates_fmortcarea_canopy', vtype=site_r8, & + long_name='fates diagnostic crownarea of canopy fire', & + units='m2/sec', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_fmortcarea_cano_si) + + call this%set_restart_var(vname='fates_fmortcarea_ustory', vtype=site_r8, & + long_name='fates diagnostic crownarea of understory fire', & + units='m2/sec', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_fmortcarea_usto_si) + + call this%set_restart_var(vname='fates_termcarea_canopy', vtype=site_r8, & + long_name='fates diagnostic term crownarea canopy', & + units='', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_termcarea_cano_si ) + + call this%set_restart_var(vname='fates_termcarea_ustory', vtype=site_r8, & + long_name='fates diagnostic term crownarea understory', & + units='', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_termcarea_usto_si ) + + ! Damage variables + call this%set_restart_var(vname='fates_imortrate_dam', vtype=cohort_r8, & + long_name='fates diagnostics on impact mortality by damage class', & + units='indiv/ha/year', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_imortrate_sicdpf) + + call this%set_restart_var(vname='fates_termn_cano_dam', vtype=cohort_r8, & + long_name='fates diagnostics on termination mortality by damage class -canopy', & + units='indiv/ha/year', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_termnindiv_cano_sicdpf) + + call this%set_restart_var(vname='fates_termn_usto_dam', vtype=cohort_r8, & + long_name='fates diagnostics on termination mortality by damage class -understory', & + units='indiv/ha/year', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_termnindiv_usto_sicdpf) + + call this%set_restart_var(vname='fates_fmortrate_cano_dam', vtype=cohort_r8, & + long_name='fates diagnostics on fire mortality by damage class', & + units='indiv/ha/year', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_fmortrate_cano_sicdpf) + + call this%set_restart_var(vname='fates_fmortrate_usto_dam', vtype=cohort_r8, & + long_name='fates diagnostics on fire mortality by damage class', & + units='indiv/ha/year', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_fmortrate_usto_sicdpf) + + call this%set_restart_var(vname='fates_imortcflux_dam', vtype=cohort_r8, & + long_name='biomass of indivs killed due to impact mort by damage class', & + units='kgC/ha/day', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_imortcflux_sicdsc) + + call this%set_restart_var(vname='fates_termcflux_cano_dam', vtype=cohort_r8, & + long_name='biomass of indivs killed due to termination mort by damage class', & + units='kgC/ha/day', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_termcflux_cano_sicdsc) + + call this%set_restart_var(vname='fates_termcflux_usto_dam', vtype=cohort_r8, & + long_name='biomass of indivs killed due to termination mort by damage class', & + units='kgC/ha/day', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_termcflux_usto_sicdsc) + + call this%set_restart_var(vname='fates_fmortcflux_cano_dam', vtype=cohort_r8, & + long_name='biomass of indivs killed due to fire mort by damage class', & + units='kgC/ha/day', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_fmortcflux_cano_sicdsc) + + call this%set_restart_var(vname='fates_fmortcflux_usto_dam', vtype=cohort_r8, & + long_name='biomass of indivs killed due to fire mort by damage class', & + units='kgC/ha/day', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_fmortcflux_usto_sicdsc) + + call this%set_restart_var(vname='fates_damage_cflux', vtype=cohort_r8, & + long_name='fates diagnostic rate of damage carbonflux', & + units='kgC/ha/day', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_damage_cflux_sicd) + + call this%set_restart_var(vname='fates_damage_rate', vtype=cohort_r8, & + long_name='fates diagnostic rate of damage transitions', & + units='indiv / ha/ day', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_damage_rate_sicd) + + call this%set_restart_var(vname='fates_recovery_cflux', vtype=cohort_r8, & + long_name='fates diagnostic rate of recovery carbonflux', & + units='kgC/ha/day', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_recovery_cflux_sicd) + + call this%set_restart_var(vname='fates_recovery_rate', vtype=cohort_r8, & + long_name='fates diagnostic rate of recovery transitions', & + units='indiv / ha/ day', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_recovery_rate_sicd) + + call this%set_restart_var(vname='fates_crownarea_canopy_damage', vtype=site_r8, & + long_name='fates area lost from damage each year', & + units='m2/ha/year', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_crownarea_cano_si) + + call this%set_restart_var(vname='fates_crownarea_understory_damage', vtype=site_r8, & + long_name='fates area lost from damage each year', & + units='m2/ha/year', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_crownarea_usto_si) @@ -1565,6 +1704,8 @@ end subroutine set_restart_var subroutine set_restart_vectors(this,nc,nsites,sites) + use FatesInterfaceTypesMod, only : hlm_use_canopy_damage + use FatesInterfaceTypesMod, only : hlm_use_understory_damage use FatesInterfaceTypesMod, only : fates_maxElementsPerPatch use FatesInterfaceTypesMod, only : numpft use EDTypesMod, only : ed_site_type @@ -1574,6 +1715,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) use EDTypesMod, only : nclmax use EDTypesMod, only : numWaterMem use EDTypesMod, only : num_vegtemp_mem + use FatesInterfaceTypesMod, only : ncrowndamage ! Arguments class(fates_restart_interface_type) :: this @@ -1608,6 +1750,9 @@ subroutine set_restart_vectors(this,nc,nsites,sites) integer :: io_idx_si_sc ! each size-class index within site integer :: io_idx_si_capf ! each cohort age-class x pft index within site integer :: io_idx_si_cacls ! each cohort age class index within site + integer :: io_idx_si_cdsc ! each damage-class x size class within site + integer :: io_idx_si_cdpf ! each damage-class x size x pft within site + integer :: io_idx_si_cdcd ! each damage x damage within site (plus mortality) integer :: io_idx_si_cwd ! each site-cwd index integer :: io_idx_si_pft ! each site-pft index integer :: io_idx_si_vtmem ! indices for veg-temp memory at site @@ -1631,7 +1776,10 @@ subroutine set_restart_vectors(this,nc,nsites,sites) integer :: i_cacls ! loop counter for cohort age class integer :: i_cwd ! loop counter for cwd integer :: i_pft ! loop counter for pft - + integer :: i_cdam ! loop counter for damage + integer :: icdi ! loop counter for damage + integer :: icdj ! loop counter for damage + type(fates_restart_variable_type) :: rvar type(ed_patch_type),pointer :: cpatch type(ed_cohort_type),pointer :: ccohort @@ -1655,6 +1803,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_solar_zenith_angle_pa => this%rvars(ir_solar_zenith_angle_pa)%r81d, & rio_canopy_layer_co => this%rvars(ir_canopy_layer_co)%int1d, & rio_canopy_layer_yesterday_co => this%rvars(ir_canopy_layer_yesterday_co)%r81d, & + rio_crowndamage_co => this%rvars(ir_crowndamage_co)%int1d, & rio_canopy_trim_co => this%rvars(ir_canopy_trim_co)%r81d, & rio_seed_prod_co => this%rvars(ir_seed_prod_co)%r81d, & rio_size_class_lasttimestep => this%rvars(ir_size_class_lasttimestep_co)%int1d, & @@ -1688,6 +1837,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_daily_p_need_co => this%rvars(ir_daily_p_need_co)%r81d, & rio_smort_co => this%rvars(ir_smort_co)%r81d, & rio_asmort_co => this%rvars(ir_asmort_co)%r81d, & + rio_dgmort_co => this%rvars(ir_dgmort_co)%r81d, & rio_frmort_co => this%rvars(ir_frmort_co)%r81d, & rio_lmort_direct_co => this%rvars(ir_lmort_direct_co)%r81d, & rio_lmort_collateral_co => this%rvars(ir_lmort_collateral_co)%r81d, & @@ -1723,13 +1873,35 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_promrate_sisc => this%rvars(ir_promrate_sisc)%r81d, & rio_termcflux_cano_si => this%rvars(ir_termcflux_cano_si)%r81d, & rio_termcflux_usto_si => this%rvars(ir_termcflux_usto_si)%r81d, & + rio_termcarea_cano_si => this%rvars(ir_termcarea_cano_si)%r81d, & + rio_termcarea_usto_si => this%rvars(ir_termcarea_usto_si)%r81d, & rio_democflux_si => this%rvars(ir_democflux_si)%r81d, & rio_promcflux_si => this%rvars(ir_promcflux_si)%r81d, & rio_imortcflux_si => this%rvars(ir_imortcflux_si)%r81d, & rio_fmortcflux_cano_si => this%rvars(ir_fmortcflux_cano_si)%r81d, & - rio_fmortcflux_usto_si => this%rvars(ir_fmortcflux_usto_si)%r81d) - - + rio_fmortcflux_usto_si => this%rvars(ir_fmortcflux_usto_si)%r81d, & + rio_imortcarea_si => this%rvars(ir_imortcarea_si)%r81d, & + rio_fmortcarea_cano_si => this%rvars(ir_fmortcarea_cano_si)%r81d, & + rio_fmortcarea_usto_si => this%rvars(ir_fmortcarea_usto_si)%r81d, & + + ! damage + rio_imortrate_sicdpf => this%rvars(ir_imortrate_sicdpf)%r81d, & + rio_imortcflux_sicdsc => this%rvars(ir_imortcflux_sicdsc)%r81d, & + rio_termcflux_cano_sicdsc => this%rvars(ir_termcflux_cano_sicdsc)%r81d, & + rio_termnindiv_cano_sicdpf => this%rvars(ir_termnindiv_cano_sicdpf)%r81d, & + rio_termcflux_usto_sicdsc => this%rvars(ir_termcflux_usto_sicdsc)%r81d, & + rio_termnindiv_usto_sicdpf => this%rvars(ir_termnindiv_usto_sicdpf)%r81d, & + rio_fmortrate_cano_sicdpf => this%rvars(ir_fmortrate_cano_sicdpf)%r81d, & + rio_fmortrate_usto_sicdpf => this%rvars(ir_fmortrate_usto_sicdpf)%r81d, & + rio_fmortcflux_cano_sicdsc => this%rvars(ir_fmortcflux_cano_sicdsc)%r81d, & + rio_fmortcflux_usto_sicdsc => this%rvars(ir_fmortcflux_usto_sicdsc)%r81d, & + rio_damage_cflux_sicd => this%rvars(ir_damage_cflux_sicd)%r81d, & + rio_damage_rate_sicd => this%rvars(ir_damage_rate_sicd)%r81d, & + rio_recovery_cflux_sicd => this%rvars(ir_recovery_cflux_sicd)%r81d, & + rio_recovery_rate_sicd => this%rvars(ir_recovery_rate_sicd)%r81d, & + rio_crownarea_cano_damage_si=> this%rvars(ir_crownarea_cano_si)%r81d, & + rio_crownarea_usto_damage_si=> this%rvars(ir_crownarea_usto_si)%r81d) + totalCohorts = 0 ! --------------------------------------------------------------------------------- @@ -1759,6 +1931,9 @@ subroutine set_restart_vectors(this,nc,nsites,sites) io_idx_si_sc = io_idx_co_1st io_idx_si_capf = io_idx_co_1st io_idx_si_cacls= io_idx_co_1st + io_idx_si_cdcd = io_idx_co_1st + io_idx_si_cdsc = io_idx_co_1st + io_idx_si_cdpf = io_idx_co_1st ! recruitment rate do i_pft = 1,numpft @@ -1884,6 +2059,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_canopy_layer_co(io_idx_co) = ccohort%canopy_layer rio_canopy_layer_yesterday_co(io_idx_co) = ccohort%canopy_layer_yesterday + rio_crowndamage_co(io_idx_co) = ccohort%crowndamage rio_canopy_trim_co(io_idx_co) = ccohort%canopy_trim rio_seed_prod_co(io_idx_co) = ccohort%seed_prod rio_size_class_lasttimestep(io_idx_co) = ccohort%size_class_lasttimestep @@ -1910,7 +2086,8 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_cmort_co(io_idx_co) = ccohort%cmort rio_smort_co(io_idx_co) = ccohort%smort rio_asmort_co(io_idx_co) = ccohort%asmort - rio_frmort_co(io_idx_co) = ccohort%frmort + rio_dgmort_co(io_idx_co) = ccohort%dgmort + rio_frmort_co(io_idx_co) = ccohort%frmort ! Nutrient uptake/efflux rio_daily_no3_uptake_co(io_idx_co) = ccohort%daily_no3_uptake @@ -2104,14 +2281,65 @@ subroutine set_restart_vectors(this,nc,nsites,sites) io_idx_si_sc = io_idx_si_sc + 1 end do + ! this only copies live portions of transitions - but that's ok because the mortality + ! bit only needs to be added for history outputs + if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + do icdi = 1,ncrowndamage + do icdj = 1,ncrowndamage+1 + + rio_damage_cflux_sicd(io_idx_si_cdcd) = & + sites(s)%damage_cflux(icdi,icdj) + rio_damage_rate_sicd(io_idx_si_cdcd) = & + sites(s)%damage_rate(icdi,icdj) + + rio_recovery_cflux_sicd(io_idx_si_cdcd) = & + sites(s)%recovery_cflux(icdi,icdj) + rio_recovery_rate_sicd(io_idx_si_cdcd) = & + sites(s)%recovery_rate(icdi,icdj) + + io_idx_si_cdcd = io_idx_si_cdcd + 1 + + end do + end do + + do i_scls = 1, nlevsclass + do i_cdam = 1, ncrowndamage + do i_pft = 1, numpft + rio_imortrate_sicdpf(io_idx_si_cdpf) = sites(s)%imort_rate_damage(i_cdam, i_scls, i_pft) + rio_termnindiv_cano_sicdpf(io_idx_si_cdpf) = sites(s)%term_nindivs_canopy_damage(i_cdam,i_scls,i_pft) + rio_termnindiv_usto_sicdpf(io_idx_si_cdpf) = sites(s)%term_nindivs_ustory_damage(i_cdam,i_scls,i_pft) + rio_imortcflux_sicdsc(io_idx_si_cdsc) = sites(s)%imort_cflux_damage(i_cdam, i_scls) + rio_termcflux_cano_sicdsc(io_idx_si_cdsc) = sites(s)%term_cflux_canopy_damage(i_cdam, i_scls) + rio_termcflux_usto_sicdsc(io_idx_si_cdsc) = sites(s)%term_cflux_ustory_damage(i_cdam, i_scls) + rio_fmortrate_cano_sicdpf(io_idx_si_cdpf) = sites(s)%fmort_rate_canopy_damage(i_cdam, i_scls, i_pft) + rio_fmortrate_usto_sicdpf(io_idx_si_cdpf) = sites(s)%fmort_rate_ustory_damage(i_cdam, i_scls, i_pft) + rio_fmortcflux_cano_sicdsc(io_idx_si_cdsc) = sites(s)%fmort_cflux_canopy_damage(i_cdam, i_scls) + rio_fmortcflux_usto_sicdsc(io_idx_si_cdsc) = sites(s)%fmort_cflux_ustory_damage(i_cdam, i_scls) + io_idx_si_cdsc = io_idx_si_cdsc + 1 + io_idx_si_cdpf = io_idx_si_cdpf + 1 + end do + end do + end do + + rio_crownarea_cano_damage_si(io_idx_si) = sites(s)%crownarea_canopy_damage + rio_crownarea_usto_damage_si(io_idx_si) = sites(s)%crownarea_ustory_damage + + end if + rio_termcflux_cano_si(io_idx_si) = sites(s)%term_carbonflux_canopy rio_termcflux_usto_si(io_idx_si) = sites(s)%term_carbonflux_ustory + rio_termcarea_cano_si(io_idx_si) = sites(s)%term_crownarea_canopy + rio_termcarea_usto_si(io_idx_si) = sites(s)%term_crownarea_ustory rio_democflux_si(io_idx_si) = sites(s)%demotion_carbonflux rio_promcflux_si(io_idx_si) = sites(s)%promotion_carbonflux rio_imortcflux_si(io_idx_si) = sites(s)%imort_carbonflux + rio_imortcarea_si(io_idx_si) = sites(s)%imort_crownarea rio_fmortcflux_cano_si(io_idx_si) = sites(s)%fmort_carbonflux_canopy rio_fmortcflux_usto_si(io_idx_si) = sites(s)%fmort_carbonflux_ustory + rio_fmortcarea_cano_si(io_idx_si) = sites(s)%fmort_crownarea_canopy + rio_fmortcarea_usto_si(io_idx_si) = sites(s)%fmort_crownarea_ustory + rio_cd_status_si(io_idx_si) = sites(s)%cstatus rio_dd_status_si(io_idx_si) = sites(s)%dstatus rio_nchill_days_si(io_idx_si) = sites(s)%nchilldays @@ -2391,7 +2619,10 @@ subroutine get_restart_vectors(this, nc, nsites, sites) use EDTypesMod, only : numWaterMem use EDTypesMod, only : num_vegtemp_mem use FatesSizeAgeTypeIndicesMod, only : get_age_class_index - + use FatesInterfaceTypesMod, only : hlm_use_canopy_damage + use FatesInterfaceTypesMod, only : hlm_use_understory_damage + + ! !ARGUMENTS: class(fates_restart_interface_type) , intent(inout) :: this integer , intent(in) :: nc @@ -2432,8 +2663,12 @@ subroutine get_restart_vectors(this, nc, nsites, sites) integer :: io_idx_si_sc ! each size-class index within site integer :: io_idx_si_cacls ! each coage class index within site integer :: io_idx_si_capf ! each cohort age class x pft index within site + integer :: io_idx_si_cdcd ! each damage x damage class within site + mortality integer :: io_idx_si_cwd integer :: io_idx_si_pft + integer :: io_idx_si_cdsc ! each damage x size class within site + integer :: io_idx_si_cdpf ! damage x size x pft within site + integer :: io_idx_pa_ncl ! each canopy layer within each patch ! Some counters (for checking mostly) @@ -2451,6 +2686,9 @@ subroutine get_restart_vectors(this, nc, nsites, sites) integer :: i_pft ! loop counter for pft integer :: i_scls ! loop counter for size-clas integer :: i_cacls ! loop counter for cohort age class + integer :: i_cdam ! loop counter for damage class + integer :: icdj ! loop counter for damage class + integer :: icdi ! loop counter for damage class associate( rio_npatch_si => this%rvars(ir_npatch_si)%int1d, & rio_cd_status_si => this%rvars(ir_cd_status_si)%int1d, & @@ -2470,6 +2708,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_solar_zenith_angle_pa => this%rvars(ir_solar_zenith_angle_pa)%r81d, & rio_canopy_layer_co => this%rvars(ir_canopy_layer_co)%int1d, & rio_canopy_layer_yesterday_co => this%rvars(ir_canopy_layer_yesterday_co)%r81d, & + rio_crowndamage_co => this%rvars(ir_crowndamage_co)%int1d, & rio_canopy_trim_co => this%rvars(ir_canopy_trim_co)%r81d, & rio_seed_prod_co => this%rvars(ir_seed_prod_co)%r81d, & rio_size_class_lasttimestep => this%rvars(ir_size_class_lasttimestep_co)%int1d, & @@ -2503,6 +2742,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_daily_p_need_co => this%rvars(ir_daily_p_need_co)%r81d, & rio_smort_co => this%rvars(ir_smort_co)%r81d, & rio_asmort_co => this%rvars(ir_asmort_co)%r81d, & + rio_dgmort_co => this%rvars(ir_dgmort_co)%r81d, & rio_frmort_co => this%rvars(ir_frmort_co)%r81d, & rio_lmort_direct_co => this%rvars(ir_lmort_direct_co)%r81d, & rio_lmort_collateral_co => this%rvars(ir_lmort_collateral_co)%r81d, & @@ -2542,7 +2782,33 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_promcflux_si => this%rvars(ir_promcflux_si)%r81d, & rio_imortcflux_si => this%rvars(ir_imortcflux_si)%r81d, & rio_fmortcflux_cano_si => this%rvars(ir_fmortcflux_cano_si)%r81d, & - rio_fmortcflux_usto_si => this%rvars(ir_fmortcflux_usto_si)%r81d) + rio_fmortcflux_usto_si => this%rvars(ir_fmortcflux_usto_si)%r81d, & + rio_termcarea_cano_si => this%rvars(ir_termcarea_cano_si)%r81d, & + rio_termcarea_usto_si => this%rvars(ir_termcarea_usto_si)%r81d, & + rio_imortcarea_si => this%rvars(ir_imortcarea_si)%r81d, & + rio_fmortcarea_cano_si => this%rvars(ir_fmortcarea_cano_si)%r81d, & + rio_fmortcarea_usto_si => this%rvars(ir_fmortcarea_usto_si)%r81d, & + + + ! Damage + rio_damage_cflux_sicd => this%rvars(ir_damage_cflux_sicd)%r81d, & + rio_damage_rate_sicd => this%rvars(ir_damage_rate_sicd)%r81d, & + rio_recovery_cflux_sicd => this%rvars(ir_recovery_cflux_sicd)%r81d, & + rio_recovery_rate_sicd => this%rvars(ir_recovery_rate_sicd)%r81d, & + rio_imortrate_sicdpf => this%rvars(ir_imortrate_sicdpf)%r81d, & + rio_termnindiv_cano_sicdpf => this%rvars(ir_termnindiv_cano_sicdpf)%r81d, & + rio_termnindiv_usto_sicdpf => this%rvars(ir_termnindiv_usto_sicdpf)%r81d, & + rio_imortcflux_sicdsc => this%rvars(ir_imortcflux_sicdsc)%r81d, & + rio_termcflux_cano_sicdsc => this%rvars(ir_termcflux_cano_sicdsc)%r81d, & + rio_termcflux_usto_sicdsc => this%rvars(ir_termcflux_usto_sicdsc)%r81d, & + rio_fmortrate_cano_sicdpf => this%rvars(ir_fmortrate_cano_sicdpf)%r81d, & + rio_fmortrate_usto_sicdpf => this%rvars(ir_fmortrate_usto_sicdpf)%r81d, & + rio_fmortcflux_cano_sicdsc => this%rvars(ir_fmortcflux_cano_sicdsc)%r81d, & + rio_fmortcflux_usto_sicdsc => this%rvars(ir_fmortcflux_usto_sicdsc)%r81d, & + rio_crownarea_cano_damage_si=> this%rvars(ir_crownarea_cano_si)%r81d, & + rio_crownarea_usto_damage_si=> this%rvars(ir_crownarea_usto_si)%r81d ) + + totalcohorts = 0 @@ -2565,7 +2831,10 @@ subroutine get_restart_vectors(this, nc, nsites, sites) io_idx_si_sc = io_idx_co_1st io_idx_si_capf = io_idx_co_1st io_idx_si_cacls= io_idx_co_1st - + io_idx_si_cdcd = io_idx_co_1st + io_idx_si_cdsc = io_idx_co_1st + io_idx_si_cdpf = io_idx_co_1st + ! read seed_bank info(site-level, but PFT-resolved) do i_pft = 1,numpft sites(s)%recruitment_rate(i_pft) = rio_recrate_sift(io_idx_co_1st+i_pft-1) @@ -2672,6 +2941,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ccohort%canopy_layer = rio_canopy_layer_co(io_idx_co) ccohort%canopy_layer_yesterday = rio_canopy_layer_yesterday_co(io_idx_co) + ccohort%crowndamage = rio_crowndamage_co(io_idx_co) ccohort%canopy_trim = rio_canopy_trim_co(io_idx_co) ccohort%seed_prod = rio_seed_prod_co(io_idx_co) ccohort%size_class_lasttimestep = rio_size_class_lasttimestep(io_idx_co) @@ -2696,6 +2966,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ccohort%cmort = rio_cmort_co(io_idx_co) ccohort%smort = rio_smort_co(io_idx_co) ccohort%asmort = rio_asmort_co(io_idx_co) + ccohort%dgmort = rio_dgmort_co(io_idx_co) ccohort%frmort = rio_frmort_co(io_idx_co) ! Nutrient uptake / efflux @@ -2946,14 +3217,57 @@ subroutine get_restart_vectors(this, nc, nsites, sites) io_idx_si_sc = io_idx_si_sc + 1 end do + + if (hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + do i_cdam = 1, ncrowndamage + do i_pft = 1, numpft + do i_scls = 1, nlevsclass + sites(s)%imort_rate_damage(i_cdam, i_scls, i_pft) = rio_imortrate_sicdpf(io_idx_si_cdpf) + sites(s)%term_nindivs_canopy_damage(i_cdam,i_scls,i_pft) = rio_termnindiv_cano_sicdpf(io_idx_si_cdpf) + sites(s)%term_nindivs_ustory_damage(i_cdam,i_scls,i_pft) = rio_termnindiv_usto_sicdpf(io_idx_si_cdpf) + sites(s)%imort_cflux_damage(i_cdam, i_scls) = rio_imortcflux_sicdsc(io_idx_si_cdsc) + sites(s)%term_cflux_canopy_damage(i_cdam, i_scls) = rio_termcflux_cano_sicdsc(io_idx_si_cdsc) + sites(s)%term_cflux_ustory_damage(i_cdam, i_scls) = rio_termcflux_usto_sicdsc(io_idx_si_cdsc) + sites(s)%fmort_rate_canopy_damage(i_cdam, i_scls, i_pft) = rio_fmortrate_cano_sicdpf(io_idx_si_cdpf) + sites(s)%fmort_rate_ustory_damage(i_cdam, i_scls, i_pft) = rio_fmortrate_usto_sicdpf(io_idx_si_cdpf) + sites(s)%fmort_cflux_canopy_damage(i_cdam, i_scls) = rio_fmortcflux_cano_sicdsc(io_idx_si_cdsc) + sites(s)%fmort_cflux_ustory_damage(i_cdam, i_scls) = rio_fmortcflux_usto_sicdsc(io_idx_si_cdsc) + io_idx_si_cdsc = io_idx_si_cdsc + 1 + io_idx_si_cdpf = io_idx_si_cdpf + 1 + end do + end do + end do + + sites(s)%crownarea_canopy_damage = rio_crownarea_cano_damage_si(io_idx_si) + sites(s)%crownarea_ustory_damage = rio_crownarea_usto_damage_si(io_idx_si) + + ! this only copies live portions of transitions - but that's ok because the mortality + ! bit only needs to be added for history outputs + do icdi = 1,ncrowndamage + do icdj = 1,ncrowndamage+1 + sites(s)%damage_cflux(icdi,icdj) = rio_damage_cflux_sicd(io_idx_si_cdcd) + sites(s)%damage_rate(icdi,icdj) = rio_damage_rate_sicd(io_idx_si_cdcd) + sites(s)%recovery_cflux(icdi,icdj) = rio_recovery_cflux_sicd(io_idx_si_cdcd) + sites(s)%recovery_rate(icdi,icdj) = rio_recovery_rate_sicd(io_idx_si_cdcd) + io_idx_si_cdcd = io_idx_si_cdcd + 1 + end do + end do + end if + + sites(s)%term_carbonflux_canopy = rio_termcflux_cano_si(io_idx_si) sites(s)%term_carbonflux_ustory = rio_termcflux_usto_si(io_idx_si) + sites(s)%term_crownarea_canopy = rio_termcarea_cano_si(io_idx_si) + sites(s)%term_crownarea_ustory = rio_termcarea_usto_si(io_idx_si) sites(s)%demotion_carbonflux = rio_democflux_si(io_idx_si) sites(s)%promotion_carbonflux = rio_promcflux_si(io_idx_si) sites(s)%imort_carbonflux = rio_imortcflux_si(io_idx_si) + sites(s)%imort_crownarea = rio_imortcarea_si(io_idx_si) sites(s)%fmort_carbonflux_canopy = rio_fmortcflux_cano_si(io_idx_si) sites(s)%fmort_carbonflux_ustory = rio_fmortcflux_usto_si(io_idx_si) + sites(s)%fmort_crownarea_canopy = rio_fmortcarea_cano_si(io_idx_si) + sites(s)%fmort_crownarea_ustory = rio_fmortcarea_usto_si(io_idx_si) ! Site level phenology status flags diff --git a/main/FatesSizeAgeTypeIndicesMod.F90 b/main/FatesSizeAgeTypeIndicesMod.F90 index d624db1e24..91dbc5455c 100644 --- a/main/FatesSizeAgeTypeIndicesMod.F90 +++ b/main/FatesSizeAgeTypeIndicesMod.F90 @@ -1,15 +1,16 @@ module FatesSizeAgeTypeIndicesMod use FatesConstantsMod, only : r8 => fates_r8 + use FatesInterfaceTypesMod, only : nlevsclass use FatesInterfaceTypesMod, only : nlevage use FatesInterfaceTypesMod, only : nlevheight use FatesInterfaceTypesMod, only : nlevcoage + use FatesInterfaceTypesMod, only : ncrowndamage use EDParamsMod, only : ED_val_history_sizeclass_bin_edges use EDParamsMod, only : ED_val_history_ageclass_bin_edges use EDParamsMod, only : ED_val_history_height_bin_edges use EDParamsMod, only : ED_val_history_coageclass_bin_edges - implicit none private ! Modules are private by default @@ -21,6 +22,8 @@ module FatesSizeAgeTypeIndicesMod public :: get_height_index public :: get_sizeagepft_class_index public :: get_agepft_class_index + public :: get_cdamagesize_class_index + public :: get_cdamagesizepft_class_index public :: coagetype_class_index public :: get_coage_class_index public :: get_agefuel_class_index @@ -39,7 +42,8 @@ function get_age_class_index(age) result( patch_age_class ) end function get_age_class_index - ! ===================================================================================== + ! ===================================================================================== + function get_sizeage_class_index(dbh,age) result(size_by_age_class) @@ -59,6 +63,25 @@ function get_sizeage_class_index(dbh,age) result(size_by_age_class) end function get_sizeage_class_index + !====================================================================================== + + + function get_cdamagesize_class_index(dbh,cdamage) result(cdamage_by_size_class) + + ! Arguments + real(r8),intent(in) :: dbh + integer,intent(in) :: cdamage + + integer :: size_class + integer :: cdamage_by_size_class + + size_class = get_size_class_index(dbh) + + cdamage_by_size_class = (cdamage-1)*nlevsclass + size_class + + end function get_cdamagesize_class_index + + ! ===================================================================================== subroutine sizetype_class_index(dbh,pft,size_class,size_by_pft_class) @@ -153,6 +176,25 @@ function get_sizeagepft_class_index(dbh,age,pft) result(size_by_age_by_pft_class end function get_sizeagepft_class_index + ! ===================================================================================== + + function get_cdamagesizepft_class_index(dbh,cdamage,pft) result(cdamage_by_size_by_pft_class) + + ! Arguments + real(r8),intent(in) :: dbh + integer,intent(in) :: cdamage + integer,intent(in) :: pft + + integer :: size_class + integer :: cdamage_by_size_by_pft_class + + size_class = get_size_class_index(dbh) + + cdamage_by_size_by_pft_class = (cdamage-1)*nlevsclass + size_class + & + (pft-1) * nlevsclass * ncrowndamage + + end function get_cdamagesizepft_class_index + ! ===================================================================================== function get_agepft_class_index(age,pft) result(age_by_pft_class) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 39adab94f6..ea363ba20f 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -7,7 +7,7 @@ dimensions: fates_history_coage_bins = 2 ; fates_hydr_organs = 4 ; fates_leafage_class = 1 ; - fates_litterclass = 6 ; + fates_litterclass = 6 ; fates_pft = 12 ; fates_prt_organs = 4 ; fates_string_length = 60 ; @@ -153,7 +153,22 @@ variables: double fates_branch_turnover(fates_pft) ; fates_branch_turnover:units = "yr" ; fates_branch_turnover:long_name = "turnover time of branches" ; - double fates_c2b(fates_pft) ; + double fates_damage_frac(fates_pft) ; + fates_damage_frac:units = "fraction"; + fates_damage_frac:long_name = "fraction of cohort damaged in each damage event"; + double fates_damage_mort_p1(fates_pft) ; + fates_damage_mort_p1:units = "fraction crown loss - a value of 0.8 means 50% mortality with 80% loss of crown"; + fates_damage_mort_p1:long_name = "inflection point of damage mortality function - to turn off damage mortality set this to a large number" ; + double fates_damage_mort_p2(fates_pft) ; + fates_damage_mort_p2:units = "unitless"; + fates_damage_mort_p2:long_name = "rate of mortality increase with damage"; + double fates_damage_recovery_scalar(fates_pft) ; + fates_damage_recovery_scalar:units = "unitless"; + fates_damage_recovery_scalar:long_name = "fraction of cohort that recovers from damage"; + double fates_ncrowndamage ; + fates_ncrowndamage: units = "unitless" ; + fates_ncrowndamage: long_name = "number of crowndamage classes" ; + double fates_c2b(fates_pft) ; fates_c2b:units = "ratio" ; fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; double fates_dev_arbitrary_pft(fates_pft) ; @@ -896,6 +911,19 @@ data: fates_branch_turnover = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; + fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01, 0.01 ; + + fates_damage_mort_p1 = 0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9 ; + + fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, + 5.5, 5.5 ; + + fates_damage_recovery_scalar = 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0 ; + + fates_ncrowndamage = 5 ; + fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 5617d71e5d..4ac203f431 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -136,8 +136,11 @@ module PRTAllometricCNPMod integer, public, parameter :: acnp_bc_inout_id_dbh = 1 ! Plant DBH integer, public, parameter :: acnp_bc_inout_id_rmaint_def = 2 ! Index for any accumulated - ! maintenance respiration deficit - integer, public, parameter :: num_bc_inout = 2 + integer, public, parameter :: acnp_bc_inout_id_cdamage = 3 ! Crown damage index + integer, public, parameter :: acnp_bc_inout_id_num = 4 ! Number of plants + + ! maintenance respiration deficit + integer, public, parameter :: num_bc_inout = 4 ! ------------------------------------------------------------------------------------- ! Input only Boundary Indices (These are public) @@ -150,9 +153,10 @@ module PRTAllometricCNPMod integer, public, parameter :: acnp_bc_in_id_netdnh4 = 5 ! Index for the net daily NH4 input BC integer, public, parameter :: acnp_bc_in_id_netdno3 = 6 ! Index for the net daily NO3 input BC integer, public, parameter :: acnp_bc_in_id_netdp = 7 ! Index for the net daily P input BC + integer, public, parameter :: acnp_bc_in_id_branch_frac = 8 ! Index for branch fraction ! 0=leaf off, 1=leaf on - integer, parameter :: num_bc_in = 7 + integer, parameter :: num_bc_in = 8 ! ------------------------------------------------------------------------------------- ! Output Boundary Indices (These are public) @@ -327,9 +331,11 @@ subroutine DailyPRTAllometricCNP(this) ! Pointers to in-out bcs real(r8),pointer :: dbh ! Diameter at breast height [cm] real(r8),pointer :: maint_r_def ! Current maintenance respiration deficit [kgC] + integer ,pointer :: cdamage ! Crown damage ! Input only bcs integer :: ipft ! Plant Functional Type index + real(r8) :: branch_frac ! fraction crown in branches real(r8) :: c_gain ! Daily carbon balance for this cohort [kgC] real(r8) :: n_gain ! Daily nitrogen uptake through fine-roots [kgN] real(r8) :: p_gain ! Daily phosphorus uptake through fine-roots [kgN] @@ -373,6 +379,7 @@ subroutine DailyPRTAllometricCNP(this) real(r8) :: n_gain0 real(r8) :: p_gain0 real(r8) :: maint_r_def0 + integer :: cdamage0 ! Used for mass checking, total mass allocated based ! on change in the states, should match gain0's @@ -396,6 +403,7 @@ subroutine DailyPRTAllometricCNP(this) p_gain = this%bc_in(acnp_bc_in_id_netdp)%rval; p_gain0 = p_gain canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival + branch_frac = this%bc_in(acnp_bc_in_id_branch_frac)%rval ! Output only boundary conditions c_efflux => this%bc_out(acnp_bc_out_id_cefflux)%rval; c_efflux = 0._r8 @@ -408,6 +416,7 @@ subroutine DailyPRTAllometricCNP(this) ! In/out boundary conditions maint_r_def => this%bc_inout(acnp_bc_inout_id_rmaint_def)%rval; maint_r_def0 = maint_r_def dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval; dbh0 = dbh + cdamage => this%bc_inout(acnp_bc_inout_id_cdamage)%ival; cdamage0 = cdamage @@ -430,14 +439,15 @@ subroutine DailyPRTAllometricCNP(this) ! Set carbon targets based on the plant's current stature target_c(:) = fates_unset_r8 target_dcdd(:) = fates_unset_r8 - call bsap_allom(dbh,ipft,canopy_trim,sapw_area,target_c(sapw_id),target_dcdd(sapw_id) ) - call bagw_allom(dbh,ipft,agw_c_target,agw_dcdd_target) + call bsap_allom(dbh,ipft,cdamage, branch_frac, canopy_trim, & + sapw_area,target_c(sapw_id),target_dcdd(sapw_id) ) + call bagw_allom(dbh,ipft,cdamage, branch_frac, agw_c_target,agw_dcdd_target) call bbgw_allom(dbh,ipft,bgw_c_target,bgw_dcdd_target) call bdead_allom(agw_c_target,bgw_c_target, target_c(sapw_id), ipft, target_c(struct_id), & agw_dcdd_target, bgw_dcdd_target, target_dcdd(sapw_id), target_dcdd(struct_id)) - call bleaf(dbh,ipft,canopy_trim, target_c(leaf_id), target_dcdd(leaf_id)) + call bleaf(dbh,ipft,cdamage, canopy_trim, target_c(leaf_id), target_dcdd(leaf_id)) call bfineroot(dbh,ipft,canopy_trim, target_c(fnrt_id), target_dcdd(fnrt_id)) - call bstore_allom(dbh,ipft,canopy_trim, target_c(store_id), target_dcdd(store_id)) + call bstore_allom(dbh,ipft,cdamage, canopy_trim, target_c(store_id), target_dcdd(store_id)) target_c(repro_id) = 0._r8 target_dcdd(repro_id) = 0._r8 @@ -1010,6 +1020,8 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & integer :: ipft real(r8) :: canopy_trim real(r8) :: leaf_status + real(r8) :: branch_frac + integer :: icrowndamage integer :: i, ii ! organ index loops (masked and unmasked) integer :: istep ! outer step iteration loop @@ -1091,6 +1103,8 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval + icrowndamage = this%bc_inout(acnp_bc_inout_id_cdamage)%ival + branch_frac = this%bc_in(acnp_bc_in_id_branch_frac)%rval cnp_limiter = 0 @@ -1357,7 +1371,8 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & leafc_tp1 = leafc_tp1 + this%variables(i_var)%val(i) end do - call CheckIntegratedAllometries(state_array_out(dbh_id),ipft,canopy_trim, & + call CheckIntegratedAllometries(state_array_out(dbh_id),ipft, & + icrowndamage, branch_frac, canopy_trim, & leafc_tp1, state_array_out(fnrt_id), state_array_out(sapw_id), & state_array_out(store_id), state_array_out(struct_id), & state_mask(leaf_id), state_mask(fnrt_id), state_mask(sapw_id), & @@ -1447,13 +1462,13 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & storec_tp1 = state_array_out(store_id) structc_tp1 = state_array_out(struct_id) - call bleaf(dbh_tp1,ipft,canopy_trim,leaf_c_target_tp1) + call bleaf(dbh_tp1,ipft,icrowndamage, canopy_trim,leaf_c_target_tp1) call bfineroot(dbh_tp1,ipft,canopy_trim,fnrt_c_target_tp1) - call bsap_allom(dbh_tp1,ipft,canopy_trim,sapw_area,sapw_c_target_tp1) - call bagw_allom(dbh_tp1,ipft,agw_c_target_tp1) + call bsap_allom(dbh_tp1,ipft,icrowndamage,branch_frac,canopy_trim,sapw_area,sapw_c_target_tp1) + call bagw_allom(dbh_tp1,ipft,icrowndamage, branch_frac, agw_c_target_tp1) call bbgw_allom(dbh_tp1,ipft,bgw_c_target_tp1) call bdead_allom(agw_c_target_tp1,bgw_c_target_tp1, sapw_c_target_tp1, ipft, struct_c_target_tp1) - call bstore_allom(dbh_tp1,ipft,canopy_trim,store_c_target_tp1) + call bstore_allom(dbh_tp1,ipft,icrowndamage, canopy_trim,store_c_target_tp1) write(fates_log(),*) 'leaf_c: ',leafc_tp1, leaf_c_target_tp1,leafc_tp1-leaf_c_target_tp1 write(fates_log(),*) 'fnrt_c: ',fnrtc_tp1, fnrt_c_target_tp1,fnrtc_tp1- fnrt_c_target_tp1 @@ -1561,11 +1576,13 @@ subroutine CNPAllocateRemainder(this,c_gain, n_gain, p_gain, & real(r8), pointer :: dbh integer :: ipft real(r8) :: canopy_trim + integer, pointer :: icrowndamage dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival + icrowndamage => this%bc_inout(acnp_bc_inout_id_cdamage)%ival ! ----------------------------------------------------------------------------------- ! If nutrients are still available, then we can bump up the values in the pools @@ -1617,7 +1634,7 @@ subroutine CNPAllocateRemainder(this,c_gain, n_gain, p_gain, & if(c_gain>calloc_abs_error) then ! Update carbon based allometric targets - call bstore_allom(dbh,ipft,canopy_trim, store_c_target) + call bstore_allom(dbh,ipft,icrowndamage, canopy_trim, store_c_target) ! Estimate the overflow store_c_target = store_c_target * (1.0_r8 + store_overflow_frac) @@ -1703,6 +1720,7 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe real(r8) :: target_c real(r8),pointer :: dbh + integer, pointer :: cdamage real(r8) :: canopy_trim integer :: ipft integer :: i_cvar @@ -1711,13 +1729,13 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe real(r8) :: sapw_c_target,agw_c_target real(r8) :: bgw_c_target,struct_c_target - - dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival i_cvar = prt_global%sp_organ_map(organ_id,carbon12_element) + cdamage => this%bc_inout(acnp_bc_inout_id_cdamage)%ival + ! Storage of nutrients are assumed to have different compartments than ! for carbon, and thus their targets are not associated with a tissue @@ -1726,10 +1744,10 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe if(organ_id == store_organ) then - call bleaf(dbh,ipft,canopy_trim,leaf_c_target) + call bleaf(dbh,ipft,1, canopy_trim,leaf_c_target) call bfineroot(dbh,ipft,canopy_trim,fnrt_c_target) - call bsap_allom(dbh,ipft,canopy_trim,sapw_area,sapw_c_target) - call bagw_allom(dbh,ipft,agw_c_target) + call bsap_allom(dbh,ipft,1, 1.0_r8, canopy_trim,sapw_area,sapw_c_target) + call bagw_allom(dbh,ipft,1, 1.0_r8, agw_c_target) call bbgw_allom(dbh,ipft,bgw_c_target) call bdead_allom(agw_c_target,bgw_c_target, sapw_c_target, ipft, struct_c_target) @@ -2084,6 +2102,8 @@ function AllomCNPGrowthDeriv(l_state_array,l_state_mask,cbalance,intgr_params) r ! locals integer :: ipft ! PFT index real(r8) :: canopy_trim ! Canopy trimming function (boundary condition [0-1] + integer :: icrowndamage ! crown damage index + real(r8) :: branch_frac real(r8) :: leaf_c_target ! target leaf biomass, dummy var (kgC) real(r8) :: fnrt_c_target ! target fine-root biomass, dummy var (kgC) real(r8) :: sapw_c_target ! target sapwood biomass, dummy var (kgC) @@ -2122,15 +2142,17 @@ function AllomCNPGrowthDeriv(l_state_array,l_state_mask,cbalance,intgr_params) r canopy_trim = intgr_params(acnp_bc_in_id_ctrim) ipft = int(intgr_params(acnp_bc_in_id_pft)) + branch_frac = intgr_params(acnp_bc_in_id_branch_frac) + icrowndamage = int(intgr_params(acnp_bc_inout_id_cdamage)) - call bleaf(dbh,ipft,canopy_trim,leaf_c_target,leaf_dcdd_target) + call bleaf(dbh,ipft,icrowndamage, canopy_trim,leaf_c_target,leaf_dcdd_target) call bfineroot(dbh,ipft,canopy_trim,fnrt_c_target,fnrt_dcdd_target) - call bsap_allom(dbh,ipft,canopy_trim,sapw_area,sapw_c_target,sapw_dcdd_target) - call bagw_allom(dbh,ipft,agw_c_target,agw_dcdd_target) + call bsap_allom(dbh,ipft,icrowndamage, branch_frac,canopy_trim,sapw_area,sapw_c_target,sapw_dcdd_target) + call bagw_allom(dbh,ipft,icrowndamage, branch_frac, agw_c_target,agw_dcdd_target) call bbgw_allom(dbh,ipft,bgw_c_target,bgw_dcdd_target) call bdead_allom(agw_c_target,bgw_c_target, sapw_c_target, ipft, struct_c_target, & agw_dcdd_target, bgw_dcdd_target, sapw_dcdd_target, struct_dcdd_target) - call bstore_allom(dbh,ipft,canopy_trim,store_c_target,store_dcdd_target) + call bstore_allom(dbh,ipft,icrowndamage,canopy_trim,store_c_target,store_dcdd_target) if (mask_repro) then ! fraction of carbon going towards reproduction diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 5bdf624502..509ef4a35f 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -87,14 +87,18 @@ module PRTAllometricCarbonMod integer, public, parameter :: ac_bc_inout_id_dbh = 1 ! Plant DBH integer, public, parameter :: ac_bc_inout_id_netdc = 2 ! Index for the net daily C input BC - integer, parameter :: num_bc_inout = 2 ! Number of in & output boundary conditions + integer, public, parameter :: ac_bc_inout_id_n = 3 ! Number of plants + integer, public, parameter :: ac_bc_inout_id_cdamage = 4 ! Index for the crowndamage input BC + integer, parameter :: num_bc_inout = 4 ! Number of in & output boundary conditions integer, public, parameter :: ac_bc_in_id_pft = 1 ! Index for the PFT input BC integer, public, parameter :: ac_bc_in_id_ctrim = 2 ! Index for the canopy trim function integer, public, parameter :: ac_bc_in_id_lstat = 3 ! Leaf status (on or off) - integer, parameter :: num_bc_in = 3 ! Number of input boundary conditions + integer, public, parameter :: ac_bc_in_id_branch_frac = 4 ! index for the branch fraction input BC + integer, parameter :: num_bc_in = 4 ! Number of input boundary conditions + ! THere are no purely output boundary conditions integer, parameter :: num_bc_out = 0 ! Number of purely output boundary condtions @@ -120,6 +124,7 @@ module PRTAllometricCarbonMod procedure :: DailyPRT => DailyPRTAllometricCarbon procedure :: FastPRT => FastPRTAllometricCarbon + procedure :: DamageRecovery => PRTDamageRecovery end type callom_prt_vartypes @@ -292,10 +297,14 @@ subroutine DailyPRTAllometricCarbon(this) ! this local will point to both in and out bc's real(r8),pointer :: carbon_balance ! Daily carbon balance for this cohort [kgC] + real(r8), pointer :: n ! number of plants + integer, pointer :: crowndamage ! which crown damage class + + real(r8) :: canopy_trim ! The canopy trimming function [0-1] integer :: ipft ! Plant Functional Type index - - + real(r8) :: branch_frac + real(r8) :: target_leaf_c ! target leaf carbon [kgC] real(r8) :: target_fnrt_c ! target fine-root carbon [kgC] real(r8) :: target_sapw_c ! target sapwood carbon [kgC] @@ -358,7 +367,22 @@ subroutine DailyPRTAllometricCarbon(this) integer :: leaf_status ! are leaves on (2) or off (1) real(r8) :: leaf_age_flux ! carbon mass flux between leaf age classification pools - + ! for recovery dynamics + real(r8) :: mass_d + real(r8) :: mass_dminus1 + real(r8) :: recovery_demand + real(r8) :: targetn_sapw_c + real(r8) :: targetn_agw_c + real(r8) :: targetn_bgw_c + real(r8) :: targetn_struct_c + real(r8) :: targetn_leaf_c + real(r8) :: targetn_store_c + real(r8) :: targetn_fnrt_c + real(r8) :: max_recover_n + real(r8) :: n_recover + real(r8) :: damage_recovery_scalar + real(r8) :: carbon_balance2 + ! Integegrator variables c_pool is "mostly" carbon variables, it also includes ! dbh... ! ----------------------------------------------------------------------------------- @@ -377,12 +401,16 @@ subroutine DailyPRTAllometricCarbon(this) ! leaf age class, and therefore ! all new allocation goes into that pool - real(r8) :: intgr_params(num_bc_in) ! The boundary conditions to this routine, + real(r8) :: intgr_params(num_bc_in+1) ! The boundary conditions to this routine, ! are pressed into an array that is also ! passed to the integrators + ! add one because we pass crown damage also + ! which is not a bc_in + associate( & - leaf_c => this%variables(leaf_c_id)%val, & + + leaf_c => this%variables(leaf_c_id)%val, & fnrt_c => this%variables(fnrt_c_id)%val(icd), & sapw_c => this%variables(sapw_c_id)%val(icd), & store_c => this%variables(store_c_id)%val(icd), & @@ -398,26 +426,30 @@ subroutine DailyPRTAllometricCarbon(this) dbh => this%bc_inout(ac_bc_inout_id_dbh)%rval carbon_balance => this%bc_inout(ac_bc_inout_id_netdc)%rval - + n => this%bc_inout(ac_bc_inout_id_n)%rval + crowndamage => this%bc_inout(ac_bc_inout_id_cdamage)%ival + canopy_trim = this%bc_in(ac_bc_in_id_ctrim)%rval ipft = this%bc_in(ac_bc_in_id_pft)%ival leaf_status = this%bc_in(ac_bc_in_id_lstat)%ival - + branch_frac = this%bc_in(ac_bc_in_id_branch_frac)%rval + intgr_params(:) = un_initialized intgr_params(ac_bc_in_id_ctrim) = this%bc_in(ac_bc_in_id_ctrim)%rval intgr_params(ac_bc_in_id_pft) = real(this%bc_in(ac_bc_in_id_pft)%ival) + intgr_params(ac_bc_in_id_branch_frac) = this%bc_in(ac_bc_in_id_branch_frac)%rval + intgr_params(num_bc_in + 1) = real(this%bc_inout(ac_bc_inout_id_cdamage)%ival) - - nleafage = prt_global%state_descriptor(leaf_c_id)%num_pos ! Number of leaf age class + damage_recovery_scalar = prt_params%damage_recovery_scalar(ipft) + ! ----------------------------------------------------------------------------------- ! Call the routine that advances leaves in age. ! This will move a portion of the leaf mass in each ! age bin, to the next bin. This will not handle movement ! of mass from the oldest bin into the litter pool, that is something else. ! ----------------------------------------------------------------------------------- - call this%AgeLeaves(ipft,sec_per_day) ! ----------------------------------------------------------------------------------- @@ -432,17 +464,16 @@ subroutine DailyPRTAllometricCarbon(this) store_c0 = store_c ! Set initial storage carbon repro_c0 = repro_c ! Set initial reproductive carbon struct_c0 = struct_c ! Set initial structural carbon - ! ----------------------------------------------------------------------------------- ! II. Calculate target size of the biomass compartment for a given dbh. ! ----------------------------------------------------------------------------------- ! Target sapwood biomass according to allometry and trimming [kgC] - call bsap_allom(dbh,ipft,canopy_trim,sapw_area,target_sapw_c) + call bsap_allom(dbh,ipft, crowndamage, branch_frac, canopy_trim,sapw_area,target_sapw_c) ! Target total above ground biomass in woody/fibrous tissues [kgC] - call bagw_allom(dbh,ipft,target_agw_c) + call bagw_allom(dbh,ipft, crowndamage, branch_frac, target_agw_c) ! Target total below ground biomass in woody/fibrous tissues [kgC] call bbgw_allom(dbh,ipft,target_bgw_c) @@ -452,7 +483,7 @@ subroutine DailyPRTAllometricCarbon(this) ! Target leaf biomass according to allometry and trimming if(leaf_status==2) then - call bleaf(dbh,ipft,canopy_trim,target_leaf_c) + call bleaf(dbh,ipft,crowndamage, canopy_trim,target_leaf_c) else target_leaf_c = 0._r8 end if @@ -461,7 +492,7 @@ subroutine DailyPRTAllometricCarbon(this) call bfineroot(dbh,ipft,canopy_trim,target_fnrt_c) ! Target storage carbon [kgC,kgC/cm] - call bstore_allom(dbh,ipft,canopy_trim,target_store_c) + call bstore_allom(dbh,ipft,crowndamage,canopy_trim,target_store_c) ! ----------------------------------------------------------------------------------- @@ -633,6 +664,91 @@ subroutine DailyPRTAllometricCarbon(this) ! left to allocate, and thus it must be on allometry when its not. ! ----------------------------------------------------------------------------------- + !----------------------------------------------------------------------------------- + ! JN March 2021 + ! At this point it is possible that damaged cohorts have reached their + ! target allometries. There is a choice now - if they have excess carbon, + ! they can use it to grow along their reduced allometric targets - i.e. + ! dbh and all carbon pools grow out together. OR they can use excess carbon to + ! jump to a lower damage class by changing their target allometry and growing + ! to meet new C pools for same dbh. + ! + ! d = damage class + + if (crowndamage > 1 .and. carbon_balance > calloc_abs_error) then + + if(damage_recovery_scalar > 0.0_r8) then + ! 1. What is excess carbon? + ! carbon_balance + + ! 2. What is biomass required to go from current damage level to next damage level? + + ! mass of this damage class + mass_d = (sum(leaf_c(1:nleafage)) + fnrt_c + store_c + sapw_c + struct_c ) + + ! Target sapwood biomass according to allometry and trimming [kgC] + call bsap_allom(dbh,ipft, crowndamage-1, branch_frac, canopy_trim,sapw_area,targetn_sapw_c) + ! Target total above ground biomass in woody/fibrous tissues [kgC] + call bagw_allom(dbh,ipft, crowndamage-1, branch_frac, targetn_agw_c) + ! Target total below ground biomass in woody/fibrous tissues [kgC] + call bbgw_allom(dbh,ipft,targetn_bgw_c) + ! Target total dead (structrual) biomass [kgC] + call bdead_allom( targetn_agw_c, targetn_bgw_c, targetn_sapw_c, ipft, targetn_struct_c) + ! Target fine-root biomass and deriv. according to allometry and trimming [kgC, kgC/cm] + call bfineroot(dbh,ipft,canopy_trim,targetn_fnrt_c) + ! Target storage carbon [kgC,kgC/cm] + call bstore_allom(dbh,ipft,crowndamage-1, canopy_trim,targetn_store_c) + ! Target leaf biomass according to allometry and trimming + if(leaf_status==2) then + call bleaf(dbh,ipft,crowndamage-1, canopy_trim,targetn_leaf_c) + else + targetn_leaf_c = 0._r8 + end if + + + mass_dminus1 = (max(sum(leaf_c), targetn_leaf_c) + max(fnrt_c, targetn_fnrt_c) + & + max(store_c, targetn_store_c) + max(sapw_c, targetn_sapw_c) + & + max(struct_c, targetn_struct_c)) + + ! Carbon needed to get from current mass to allometric target mass of next damage class up + recovery_demand = mass_dminus1 - mass_d + + ! 3. How many trees can get there with excess carbon? + max_recover_n = carbon_balance * n / recovery_demand + + ! 4. Use the scalar to decide how many to recover + n_recover = max_recover_n * damage_recovery_scalar + + ! carbon balance needs to be updated + + ! there is a special case where damage_recovery_scalar = 1, but + ! max_recover_n > n (i.e. there is more carbon than needed for all + ! individuals to recover to the next damage class. + ! in this case we can cheat, by making n_recover 0 and simply + ! allowing the donor cohort to recover and then go through + ! prt - will this work though? if they are not anywhere near allometry? + + + if(damage_recovery_scalar .eq. 1.0_r8 .and. max_recover_n > n) then + n_recover = 0.0_r8 + crowndamage = crowndamage - 1 + ! call prt from within itself here? + else + carbon_balance = (n * carbon_balance - (recovery_demand * n_recover)) /(n-n_recover) + end if + + ! we reduce number density here and continue on with daily prt for the + ! part of the cohort that is not recovering - staying fixed on its + ! current reduced allometries + n = n - n_recover + + ! Outside of parteh we will copy the cohort and allow the + ! recovery portion to change allometric targets. + + end if ! end if some recovery is permited + end if ! end if crowndamage + !------------------------------------------------------------------------------------ + if_stature_growth: if( carbon_balance > calloc_abs_error ) then ! This routine checks that actual carbon is not below that targets. It does @@ -712,7 +828,7 @@ subroutine DailyPRTAllometricCarbon(this) end if do_solve_check: do while( ierr .ne. 0 ) - + deltaC = min(totalC,this%ode_opt_step) if(ODESolve == 1) then call RKF45(AllomCGrowthDeriv,c_pool,c_mask,deltaC,totalC, & @@ -731,11 +847,12 @@ subroutine DailyPRTAllometricCarbon(this) ! we halve the step-size, and then retry. If that step was fine, then ! we remember the current step size as a good next guess. - call CheckIntegratedAllometries(c_pool_out(dbh_id),ipft,canopy_trim, & - c_pool_out(leaf_c_id), c_pool_out(fnrt_c_id), c_pool_out(sapw_c_id), & + call CheckIntegratedAllometries(c_pool_out(dbh_id),ipft,& + crowndamage, branch_frac, canopy_trim, & + c_pool_out(leaf_c_id), c_pool_out(fnrt_c_id), c_pool_out(sapw_c_id), & c_pool_out(store_c_id), c_pool_out(struct_c_id), & c_mask(leaf_c_id), c_mask(fnrt_c_id), c_mask(sapw_c_id), & - c_mask(store_c_id),c_mask(struct_c_id), max_trunc_error, step_pass) + c_mask(store_c_id), c_mask(struct_c_id), max_trunc_error, step_pass) if(step_pass) then this%ode_opt_step = deltaC else @@ -755,6 +872,7 @@ subroutine DailyPRTAllometricCarbon(this) end if if(nsteps > max_substeps ) then + write(fates_log(),*) 'crowndamage : ', crowndamage write(fates_log(),*) 'Plant Growth Integrator could not find' write(fates_log(),*) 'a solution in less than ',max_substeps,' tries' write(fates_log(),*) 'Aborting' @@ -765,7 +883,7 @@ subroutine DailyPRTAllometricCarbon(this) write(fates_log(),*) 'fnrt:',grow_fnrt,target_fnrt_c,target_fnrt_c - fnrt_c write(fates_log(),*) 'sap:',grow_sapw,target_sapw_c, target_sapw_c - sapw_c write(fates_log(),*) 'store:',grow_store,target_store_c,target_store_c - store_c - write(fates_log(),*) 'dead:',target_struct_c,target_struct_c - struct_c + write(fates_log(),*) 'dead:',target_struct_c,target_struct_c - struct_c call endrun(msg=errMsg(sourcefile, __LINE__)) end if @@ -835,7 +953,7 @@ subroutine DailyPRTAllometricCarbon(this) ! Track the net allocations and transport from this routine ! (the AgeLeaves() routine handled tracking allocation through aging) - + this%variables(leaf_c_id)%net_alloc(icd) = & this%variables(leaf_c_id)%net_alloc(icd) + (leaf_c(icd) - leaf_c0(icd)) @@ -890,6 +1008,8 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) ! locals integer :: ipft ! PFT index + integer :: crowndamage + real(r8) :: branch_frac real(r8) :: canopy_trim ! Canopy trimming function (boundary condition [0-1] real(r8) :: ct_leaf ! target leaf biomass, dummy var (kgC) real(r8) :: ct_fnrt ! target fine-root biomass, dummy var (kgC) @@ -927,17 +1047,17 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) canopy_trim = intgr_params(ac_bc_in_id_ctrim) ipft = int(intgr_params(ac_bc_in_id_pft)) - - - call bleaf(dbh,ipft,canopy_trim,ct_leaf,ct_dleafdd) + branch_frac = intgr_params(ac_bc_in_id_branch_frac) + crowndamage = int(intgr_params(num_bc_in + 1)) + + call bleaf(dbh,ipft,crowndamage,canopy_trim,ct_leaf, dbldd=ct_dleafdd) call bfineroot(dbh,ipft,canopy_trim,ct_fnrt,ct_dfnrtdd) - call bsap_allom(dbh,ipft,canopy_trim,sapw_area,ct_sap,ct_dsapdd) - - call bagw_allom(dbh,ipft,ct_agw,ct_dagwdd) - call bbgw_allom(dbh,ipft,ct_bgw,ct_dbgwdd) + call bsap_allom(dbh,ipft, crowndamage, branch_frac, canopy_trim,sapw_area,ct_sap,ct_dsapdd) + call bagw_allom(dbh,ipft,crowndamage, branch_frac, ct_agw,ct_dagwdd) + call bbgw_allom(dbh,ipft,ct_bgw, ct_dbgwdd) call bdead_allom(ct_agw,ct_bgw, ct_sap, ipft, ct_dead, & ct_dagwdd, ct_dbgwdd, ct_dsapdd, ct_ddeaddd) - call bstore_allom(dbh,ipft,canopy_trim,ct_store,ct_dstoredd) + call bstore_allom(dbh,ipft,crowndamage, canopy_trim,ct_store,ct_dstoredd) ! fraction of carbon going towards reproduction if (dbh <= prt_params%dbh_repro_threshold(ipft)) then ! cap on leaf biomass @@ -1097,8 +1217,74 @@ subroutine FastPRTAllometricCarbon(this) return - end subroutine FastPRTAllometricCarbon + end subroutine FastPRTAllometricCarbon + !------------------------------------------------------------------------------- + subroutine PRTDamageRecovery(this) + ! ---------------------------------------------------------------------------------- + ! We are assigning mass to each organ based on the allometric targets + ! ---------------------------------------------------------------------------------- + class(callom_prt_vartypes) :: this + + + real(r8),pointer :: dbh + integer, pointer :: crowndamage + real(r8) :: canopy_trim + integer :: ipft + real(r8) :: branch_frac + real(r8) :: target_leaf_c ! target leaf carbon [kgC] + real(r8) :: target_fnrt_c ! target fine-root carbon [kgC] + real(r8) :: target_sapw_c ! target sapwood carbon [kgC] + real(r8) :: target_store_c ! target storage carbon [kgC] + real(r8) :: target_agw_c ! target above ground carbon in woody tissues [kgC] + real(r8) :: target_bgw_c ! target below ground carbon in woody tissues [kgC] + real(r8) :: target_struct_c ! target structural carbon [kgC] + real(r8) :: sapw_area ! dummy var, x-section area of sapwood [m2] + integer :: leaf_status + real(r8) :: leaf_c_flux + integer, parameter :: iexp_leaf = 1 ! index 1 is the expanding leaf age class and + ! therefore all new carbon goes into that pool + + associate ( & + leaf_c => this%variables(leaf_c_id)%val, & + fnrt_c => this%variables(fnrt_c_id)%val(icd), & + sapw_c => this%variables(sapw_c_id)%val(icd), & + store_c => this%variables(store_c_id)%val(icd), & + repro_c => this%variables(repro_c_id)%val(icd), & + struct_c => this%variables(struct_c_id)%val(icd)) + + dbh => this%bc_inout(ac_bc_inout_id_dbh)%rval + crowndamage => this%bc_inout(ac_bc_inout_id_cdamage)%ival + canopy_trim = this%bc_in(ac_bc_in_id_ctrim)%rval + ipft = this%bc_in(ac_bc_in_id_pft)%ival + leaf_status = this%bc_in(ac_bc_in_id_lstat)%ival + branch_frac = this%bc_in(ac_bc_in_id_branch_frac)%rval + + ! Get allometric targets for this dbh and crown damage class + call bsap_allom(dbh, ipft, crowndamage, branch_frac, canopy_trim, sapw_area, target_sapw_c) + call bagw_allom(dbh, ipft, crowndamage, branch_frac, target_agw_c) + call bbgw_allom(dbh, ipft, target_bgw_c) + call bdead_allom(target_agw_c, target_bgw_c, target_sapw_c, ipft, target_struct_c) + if(leaf_status ==2)then + call bleaf(dbh, ipft, crowndamage, canopy_trim, target_leaf_c) + else + target_leaf_c = 0.0_r8 + end if + call bfineroot(dbh, ipft, canopy_trim, target_fnrt_c) + call bstore_allom(dbh, ipft,crowndamage, canopy_trim, target_store_c) + + ! Now we assign these targets to the actual biomass pools + fnrt_c = max(target_fnrt_c, fnrt_c) + store_c = max(target_store_c, store_c) + sapw_c = max(target_sapw_c, sapw_c) + struct_c = max(target_struct_c, struct_c) + leaf_c_flux = target_leaf_c - sum(leaf_c) + leaf_c(iexp_leaf) = leaf_c(iexp_leaf) + leaf_c_flux + + end associate + end subroutine PRTDamageRecovery + ! ===================================================================================== + end module PRTAllometricCarbonMod diff --git a/parteh/PRTGenericMod.F90 b/parteh/PRTGenericMod.F90 index 76d0e01eda..2a14f57533 100644 --- a/parteh/PRTGenericMod.F90 +++ b/parteh/PRTGenericMod.F90 @@ -185,8 +185,9 @@ module PRTGenericMod ! over the control period 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 :: herbiv(:) ! Losses due to herbivory [kg] ! Placeholder ! To save on memory, keep this commented out, or simply @@ -241,6 +242,7 @@ module PRTGenericMod procedure :: DailyPRT => DailyPRTBase procedure :: FastPRT => FastPRTBase + procedure :: DamageRecovery => DamageRecoveryBase procedure :: GetNutrientTarget => GetNutrientTargetBase ! These are generic functions that should work on all hypotheses @@ -262,7 +264,8 @@ module PRTGenericMod procedure, non_overridable :: DeallocatePRTVartypes procedure, non_overridable :: WeightedFusePRTVartypes procedure, non_overridable :: CopyPRTVartypes - + + procedure :: AgeLeaves ! This routine may be used generically ! but also leaving the door open for over-rides @@ -542,7 +545,8 @@ subroutine InitAllocate(this) allocate(this%variables(i_var)%turnover(num_pos)) 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)) + end do @@ -567,6 +571,7 @@ subroutine InitializeInitialConditions(this) this%variables(i_var)%val0(:) = un_initialized this%variables(i_var)%turnover(:) = un_initialized this%variables(i_var)%burned(:) = un_initialized + this%variables(i_var)%damaged(:) = un_initialized this%variables(i_var)%net_alloc(:) = un_initialized end do @@ -787,6 +792,7 @@ subroutine CopyPRTVartypes(this, donor_prt_obj) this%variables(i_var)%net_alloc(:) = donor_prt_obj%variables(i_var)%net_alloc(:) 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(:) end do this%ode_opt_step = donor_prt_obj%ode_opt_step @@ -834,6 +840,9 @@ subroutine WeightedFusePRTVartypes(this,donor_prt_obj, recipient_fuse_weight) this%variables(i_var)%burned(pos_id) = recipient_fuse_weight * this%variables(i_var)%burned(pos_id) + & (1.0_r8-recipient_fuse_weight) * donor_prt_obj%variables(i_var)%burned(pos_id) + 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) + end do end do @@ -872,6 +881,7 @@ subroutine DeallocatePRTVartypes(this) deallocate(this%variables(i_var)%net_alloc) deallocate(this%variables(i_var)%turnover) deallocate(this%variables(i_var)%burned) + deallocate(this%variables(i_var)%damaged) end do deallocate(this%variables) @@ -914,6 +924,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)%damaged(:) = 0.0_r8 end do end subroutine ZeroRates @@ -949,14 +960,16 @@ subroutine CheckMassConservation(this,ipft,position_id) err = abs((this%variables(i_var)%val(i_pos) - 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)%damaged(i_pos))) + if(this%variables(i_var)%val(i_pos) > nearzero ) then rel_err = err / this%variables(i_var)%val(i_pos) else rel_err = 0.0_r8 end if + if( abs(err) > calloc_abs_error ) then write(fates_log(),*) 'PARTEH mass conservation check failed' write(fates_log(),*) ' Change in mass over control period should' @@ -973,7 +986,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)%damaged(i_pos) write(fates_log(),*) ' Exiting.' call endrun(msg=errMsg(sourcefile, __LINE__)) end if @@ -1251,17 +1265,28 @@ end subroutine DailyPRTBase ! ==================================================================================== - subroutine FastPRTBase(this) + subroutine DamageRecoveryBase(this) class(prt_vartypes) :: this - write(fates_log(),*)'FastReactiveTransport must be extended by a child class.' + write(fates_log(),*)'?' call endrun(msg=errMsg(sourcefile, __LINE__)) - end subroutine FastPRTBase + end subroutine DamageRecoveryBase ! ==================================================================================== + ! ==================================================================================== + + subroutine FastPRTBase(this) + + class(prt_vartypes) :: this + + write(fates_log(),*)'FastReactiveTransport must be extended by a child class' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end subroutine FastPRTBase + + !==================================================================================== subroutine SetState(prt,organ_id, element_id, state_val, position_id) ! This routine should only be called for initalizing the state value diff --git a/parteh/PRTLossFluxesMod.F90 b/parteh/PRTLossFluxesMod.F90 index 13b09b2e37..078d2465f9 100644 --- a/parteh/PRTLossFluxesMod.F90 +++ b/parteh/PRTLossFluxesMod.F90 @@ -1,3 +1,4 @@ + module PRTLossFluxesMod @@ -64,7 +65,9 @@ module PRTLossFluxesMod public :: PRTBurnLosses public :: PRTPhenologyFlush public :: PRTReproRelease - + public :: PRTDamageLosses + public :: PRTDamageRecoveryFluxes + contains @@ -335,7 +338,62 @@ subroutine PRTBurnLosses(prt, organ_id, mass_fraction) end associate end subroutine PRTBurnLosses + ! ===================================================================================== + subroutine PRTDamageLosses(prt, organ_id, mass_fraction) + + ! ---------------------------------------------------------------------------------- + ! This subroutine assumes that there is no re-translocation associated + ! with damage. There is only one destiny for damaged mass within + ! the organ, and that is outside the plant. + ! It is also assumed that non PARTEH parts of the code (ie the damage-model) + ! will decide what to do with the damaged mass (i.e. sent it to the litter + ! pool, or.. other?) + ! ---------------------------------------------------------------------------------- + + 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) :: damaged_mass ! Lost 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 + damaged_mass = mass_fraction * prt%variables(i_var)%val(i_pos) + + ! Track the amount of mass being lost (+ is amount lost) + prt%variables(i_var)%damaged(i_pos) = prt%variables(i_var)%damaged(i_pos) & + + damaged_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) & + - damaged_mass + + end do + + end do + + end associate + end subroutine PRTDamageLosses + ! ===================================================================================== @@ -811,6 +869,30 @@ subroutine MaintTurnoverSimpleRetranslocation(prt,ipft,is_drought) return end subroutine MaintTurnoverSimpleRetranslocation + !---------------------------------------------------------------------------------------------- + + subroutine PRTDamageRecoveryFluxes(prt, organ_id, mass_0, mass, cc_mass) + + class(prt_vartypes) :: prt + integer,intent(in) :: organ_id + real(r8),intent(in) :: mass_0 + real(r8),intent(in) :: mass + real(r8),intent(in) :: cc_mass + + integer, parameter :: icd = 1 + + ! Remove the amount that was copied from old cohort + prt%variables(organ_id)%net_alloc(icd) = prt%variables(organ_id)%net_alloc(icd) & + - (cc_mass - mass_0) + + + ! Track the amount of mass being lost (+ is amount lost) + prt%variables(organ_id)%net_alloc(icd) = prt%variables(organ_id)%net_alloc(icd) & + + (mass - mass_0) + + end subroutine PRTDamageRecoveryFluxes + + ! ===================================================================================== diff --git a/parteh/PRTParametersMod.F90 b/parteh/PRTParametersMod.F90 index dcf20dbd14..b7da7e95ed 100644 --- a/parteh/PRTParametersMod.F90 +++ b/parteh/PRTParametersMod.F90 @@ -26,6 +26,7 @@ module PRTParametersMod ! one class to the next [yr] real(r8), allocatable :: root_long(:) ! root turnover time (longevity) (pft) [yr] real(r8), allocatable :: branch_long(:) ! Turnover time for branchfall on live trees (pft) [yr] + real(r8), allocatable :: damage_recovery_scalar(:) ! what fraction of cohort gets to recover real(r8), allocatable :: turnover_retrans_mode(:) ! Retranslocation method (pft) real(r8), allocatable :: turnover_carb_retrans(:,:) ! carbon re-translocation fraction (pft x organ) real(r8), allocatable :: turnover_nitr_retrans(:,:) ! nitrogen re-translocation fraction (pft x organ) diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index dce172d47d..3947b067ce 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -359,8 +359,10 @@ subroutine PRTRegisterPFT(fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - - + name = 'fates_damage_recovery_scalar' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_nitr_store_ratio' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -368,7 +370,7 @@ subroutine PRTRegisterPFT(fates_params) name = 'fates_phos_store_ratio' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - + end subroutine PRTRegisterPFT !----------------------------------------------------------------------- @@ -603,6 +605,10 @@ subroutine PRTReceivePFT(fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%turnover_retrans_mode) + name = 'fates_damage_recovery_scalar' + call fates_params%RetreiveParameterAllocate(name=name, & + data=prt_params%damage_recovery_scalar) + name = 'fates_nitr_store_ratio' call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%nitr_store_ratio) @@ -610,8 +616,7 @@ subroutine PRTReceivePFT(fates_params) name = 'fates_phos_store_ratio' call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%phos_store_ratio) - - + end subroutine PRTReceivePFT !----------------------------------------------------------------------- @@ -867,6 +872,7 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'grperc = ',prt_params%grperc write(fates_log(),fmt0) 'c2b = ',prt_params%c2b write(fates_log(),fmt0) 'branch_turnover = ',prt_params%branch_long + write(fates_log(),fmt0) 'damage_recovery_scalar = ', prt_params%damage_recovery_scalar write(fates_log(),fmt0) 'allom_hmode = ',prt_params%allom_hmode write(fates_log(),fmt0) 'allom_lmode = ',prt_params%allom_lmode write(fates_log(),fmt0) 'allom_fmode = ',prt_params%allom_fmode @@ -1436,6 +1442,7 @@ function NewRecruitTotalStoichiometry(ft,element_id) result(recruit_stoich) integer,intent(in) :: ft integer,intent(in) :: element_id + real(r8) :: recruit_stoich ! nutrient to carbon ratio of recruit real(r8) :: dbh ! dbh of the new recruit [cm] @@ -1449,15 +1456,18 @@ function NewRecruitTotalStoichiometry(ft,element_id) result(recruit_stoich) real(r8) :: c_store ! target Storage biomass [kgC] real(r8) :: c_total ! total target carbon real(r8) :: nutr_total ! total target nutrient - + + + ! Since recruits have no damage we can put 1 for crown damage class and + ! branch fraction call h2d_allom(EDPftvarcon_inst%hgt_min(ft),ft,dbh) - call bleaf(dbh,ft,init_recruit_trim,c_leaf) + call bleaf(dbh,ft,1, init_recruit_trim,c_leaf) call bfineroot(dbh,ft,init_recruit_trim,c_fnrt) - call bsap_allom(dbh,ft,init_recruit_trim,a_sapw, c_sapw) - call bagw_allom(dbh,ft,c_agw) + call bsap_allom(dbh,ft,1,1.0_r8,init_recruit_trim,a_sapw, c_sapw) + call bagw_allom(dbh,ft,1,1.0_r8,c_agw) call bbgw_allom(dbh,ft,c_bgw) call bdead_allom(c_agw,c_bgw,c_sapw,ft,c_struct) - call bstore_allom(dbh,ft,init_recruit_trim,c_store) + call bstore_allom(dbh,ft,1,init_recruit_trim,c_store) ! Total carbon in a newly recruited plant c_total = c_leaf + c_fnrt + c_sapw + c_struct + c_store From d090bfd647dc4bb499c7be7f92061438ba40e953 Mon Sep 17 00:00:00 2001 From: JessicaNeedham Date: Thu, 30 Sep 2021 16:03:27 -0700 Subject: [PATCH 059/852] [ Uncomment a check that was breaking runs ] [ This check is not related to damage work and is being addressed in other issues/PRs ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary:no testing --- main/EDPftvarcon.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 3e932a51ed..36c9c1a4c8 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1790,7 +1790,7 @@ subroutine FatesCheckParams(is_master) write(fates_log(),*) 'Error is:',sumarea-1.0_r8 write(fates_log(),*) 'and the hlm_pft_map is:', EDPftvarcon_inst%hlm_pft_map(1:npft,hlm_pft) write(fates_log(),*) 'Aborting' -! call endrun(msg=errMsg(sourcefile, __LINE__)) + call endrun(msg=errMsg(sourcefile, __LINE__)) end if end do !hlm_pft end do !ipft From fc3ed80288a0b29e9df90c5bb99b4436ed45215e Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Fri, 1 Oct 2021 12:00:11 -0700 Subject: [PATCH 060/852] [ Fix bug with understory number densities ] [ ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary: no testing --- biogeochem/EDPatchDynamicsMod.F90 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 0652559ad8..df2512f208 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1342,8 +1342,13 @@ subroutine spawn_patches( currentSite, bc_in) end do ! end crowndamage loop ! Reduce currentCohort%n now based on sum of all new damage classes - currentCohort%n = currentCohort%n - cd_n_total + if(hlm_use_canopy_damage .eq. itrue) then + currentCohort%n = currentCohort%n - cd_n_total + else if(hlm_use_understory_damage .eq. itrue) then + nc%n = nc%n - cd_n_total + end if + end if ! end if not new end if ! end if canopy and woody end if ! end if damage time From d4e35f06ac27d5be5312937519b681cb4354eddc Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 6 Oct 2021 13:41:20 -0400 Subject: [PATCH 061/852] Encapsulating all write/print statements to logging in either a debug clause, or ensuring there is an endrun following. --- biogeochem/EDCanopyStructureMod.F90 | 9 +- biogeochem/EDCohortDynamicsMod.F90 | 13 +- biogeochem/EDLoggingMortalityMod.F90 | 3 +- biogeochem/EDMortalityFunctionsMod.F90 | 10 +- biogeochem/EDPatchDynamicsMod.F90 | 11 +- biogeochem/EDPhysiologyMod.F90 | 9 - biogeochem/FatesAllometryMod.F90 | 9 +- biogeophys/EDAccumulateFluxesMod.F90 | 4 +- biogeophys/EDBtranMod.F90 | 10 +- biogeophys/EDSurfaceAlbedoMod.F90 | 139 +++++++------ biogeophys/FatesPlantHydraulicsMod.F90 | 33 ++-- biogeophys/FatesPlantRespPhotosynthMod.F90 | 1 + fire/SFMainMod.F90 | 12 +- main/EDInitMod.F90 | 8 +- main/EDMainMod.F90 | 2 + main/EDPftvarcon.F90 | 2 +- main/FatesHistoryInterfaceMod.F90 | 15 +- main/FatesHistoryVariableType.F90 | 15 +- main/FatesIOVariableKindMod.F90 | 8 +- main/FatesInterfaceMod.F90 | 214 ++++++--------------- main/FatesInventoryInitMod.F90 | 10 +- main/FatesParametersInterface.F90 | 1 - main/FatesRestartInterfaceMod.F90 | 3 +- main/FatesRestartVariableType.F90 | 14 +- parteh/PRTParamsFATESMod.F90 | 2 + 25 files changed, 257 insertions(+), 300 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 08e6c0513f..01cc0d32e5 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1930,7 +1930,10 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) ifp = ifp+1 if ( currentPatch%total_canopy_area-currentPatch%area > 0.000001_r8 ) then - write(fates_log(),*) 'ED: canopy area bigger than area',currentPatch%total_canopy_area ,currentPatch%area + if(debug)then + write(fates_log(),*) 'ED: canopy area bigger than area', & + currentPatch%total_canopy_area ,currentPatch%area + end if currentPatch%total_canopy_area = currentPatch%area endif @@ -2219,7 +2222,9 @@ function NumPotentialCanopyLayers(currentPatch,site_spread,include_substory) res if(arealayer > currentPatch%area)then z = z + 1 if(hlm_use_sp.eq.itrue)then - write(fates_log(),*) 'SPmode, canopy_layer full:',arealayer,currentPatch%area + if(debug)then + write(fates_log(),*) 'SPmode, canopy_layer full:',arealayer,currentPatch%area + end if end if endif diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 2fa98aa59f..420e7c92ad 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -1537,7 +1537,6 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) !---------------------------------------------------------------------! dynamic_size_fusion_tolerance = dynamic_size_fusion_tolerance * 1.1_r8 dynamic_age_fusion_tolerance = dynamic_age_fusion_tolerance * 1.1_r8 - !write(fates_log(),*) 'maxcohorts exceeded',dynamic_fusion_tolerance else @@ -1552,7 +1551,6 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) ! Making profile tolerance larger means that more fusion will happen ! !---------------------------------------------------------------------! dynamic_size_fusion_tolerance = dynamic_size_fusion_tolerance * 1.1_r8 - !write(fates_log(),*) 'maxcohorts exceeded',dynamic_fusion_tolerance else @@ -1931,10 +1929,13 @@ subroutine count_cohorts( currentPatch ) currentCohort => currentCohort%shorter enddo - if (backcount /= currentPatch%countcohorts) then - write(fates_log(),*) 'problem with linked list, not symmetrical' - endif - + if(debug) then + if (backcount /= currentPatch%countcohorts) then + write(fates_log(),*) 'problem with linked list, not symmetrical' + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + end if + end subroutine count_cohorts ! =================================================================================== diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index f1f23d9f33..52178f46cf 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -73,7 +73,8 @@ module EDLoggingMortalityMod logical, protected :: logging_time ! If true, logging should be ! performed during the current time-step - + logical, parameter :: debug = .false. + ! harvest litter localization specifies how much of the litter from a falling ! tree lands within the newly generated patch, and how much lands outside of ! the new patch, and thus in the original patch. By setting this to zero, diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index 6eb5ec3097..ca4b3a5dad 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -6,6 +6,8 @@ module EDMortalityFunctionsMod use FatesConstantsMod , only : r8 => fates_r8 use FatesGlobals , only : fates_log + use FatesGlobals , only : endrun => fates_endrun + use FatesGlobals , only : fates_log use EDPftvarcon , only : EDPftvarcon_inst use EDTypesMod , only : ed_cohort_type use EDTypesMod , only : ed_site_type @@ -22,10 +24,15 @@ module EDMortalityFunctionsMod use PRTGenericMod, only : all_carbon_elements use PRTGenericMod, only : store_organ - + use shr_log_mod , only : errMsg => shr_log_errMsg + implicit none private + + logical, parameter :: debug = .false. + character(len=*), parameter, private :: sourcefile = & + __FILE__ public :: mortality_rates public :: Mortality_Derivative @@ -164,6 +171,7 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmor else write(fates_log(),*) 'dbh problem in mortality_rates', & cohort_in%dbh,cohort_in%pft,cohort_in%n,cohort_in%canopy_layer + call endrun(msg=errMsg(sourcefile, __LINE__)) endif !-------------------------------------------------------------------------------- ! Mortality due to cold and freezing stress (frmort), based on ED2 and: diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index c08e93565e..fda538e36e 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -335,8 +335,8 @@ subroutine disturbance_rates( site_in, bc_in) ! Fires can't burn the whole patch, as this causes /0 errors. if (debug) then if (currentPatch%disturbance_rates(dtype_ifire) > 0.98_r8)then - write(fates_log(),*) 'very high fire areas', & - currentPatch%disturbance_rates(dtype_ifire),currentPatch%frac_burnt + write(fates_log(),*) 'very high fire areas', & + currentPatch%disturbance_rates(dtype_ifire),currentPatch%frac_burnt endif endif @@ -2295,7 +2295,8 @@ subroutine fuse_patches( csite, bc_in ) do while(associated(tpp)) if(.not.associated(currentPatch))then - write(fates_log(),*) 'ED: issue with currentPatch' + write(fates_log(),*) 'FATES fuse_patches(): currentPatch is not associated?' + call endrun(msg=errMsg(sourcefile, __LINE__)) endif if(associated(tpp).and.associated(currentPatch))then @@ -2414,9 +2415,7 @@ subroutine fuse_patches( csite, bc_in ) !------------------------------------------------------------------------! profiletol = ED_val_patch_fusion_tol - - else - ! write(fates_log(),*) 'patches not fused' + endif endif !are both patches the same anthropogenic disturbance category as the disturbance type loop iterator? endif !are both patches associated? diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 859f6e3534..1ca5b06546 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -590,11 +590,6 @@ subroutine trim_canopy( currentSite ) ! Make sure the cohort trim fraction is great than the pft trim limit if (currentCohort%canopy_trim > EDPftvarcon_inst%trim_limit(ipft)) then - ! if ( debug ) then - ! write(fates_log(),*) 'trimming leaves', & - ! currentCohort%canopy_trim,currentCohort%leaf_cost - ! endif - ! keep trimming until none of the canopy is in negative carbon balance. if (currentCohort%hite > EDPftvarcon_inst%hgt_min(ipft)) then currentCohort%canopy_trim = currentCohort%canopy_trim - & @@ -620,10 +615,6 @@ subroutine trim_canopy( currentSite ) call dgels(trans, m, n, nrhs, nnu_clai_a, lda, nnu_clai_b, ldb, work, lwork, info) lwork = int(work(1)) ! Pick the optimum. TBD, can work(1) come back with greater than work size? - ! if (debug) then - ! write(fates_log(),*) 'LLSF lwork output (info, lwork):', info, lwork - ! endif - ! Compute the minimum of 2-norm of of the least squares fit to solve for X ! Note that dgels returns the solution by overwriting the nnu_clai_b array. ! The result has the form: X = [b; m] diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index e47934715d..396cee9a60 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -2448,9 +2448,12 @@ subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl ) end if call h_allom(d,ipft,h) - if(counter>10)then - write(fates_log(),*) 'dbh counter: ',counter,' is woody: ',& - int(prt_params%woody(ipft))==itrue + + if(debug) then + if(counter>10)then + write(fates_log(),*) 'dbh counter: ',counter,' is woody: ',& + int(prt_params%woody(ipft))==itrue + end if end if diff --git a/biogeophys/EDAccumulateFluxesMod.F90 b/biogeophys/EDAccumulateFluxesMod.F90 index a0fe4dd7df..090b7848b0 100644 --- a/biogeophys/EDAccumulateFluxesMod.F90 +++ b/biogeophys/EDAccumulateFluxesMod.F90 @@ -9,11 +9,11 @@ module EDAccumulateFluxesMod ! Rosie Fisher. March 2014. ! ! !USES: - use FatesGlobals, only : fates_endrun + use FatesGlobals, only : endrun => fates_endrun use FatesGlobals, only : fates_log use shr_log_mod , only : errMsg => shr_log_errMsg use FatesConstantsMod , only : r8 => fates_r8 - + use shr_log_mod , only : errMsg => shr_log_errMsg implicit none private diff --git a/biogeophys/EDBtranMod.F90 b/biogeophys/EDBtranMod.F90 index e36642447e..52577b1b92 100644 --- a/biogeophys/EDBtranMod.F90 +++ b/biogeophys/EDBtranMod.F90 @@ -19,11 +19,16 @@ module EDBtranMod use FatesInterfaceTypesMod , only : hlm_use_planthydro use FatesGlobals , only : fates_log use FatesAllometryMod , only : set_root_fraction + use shr_log_mod , only : errMsg => shr_log_errMsg + use FatesGlobals, only : endrun => fates_endrun ! implicit none private + + logical, parameter :: debug = .false. + public :: btran_ed public :: get_active_suction_layers public :: check_layer_water @@ -231,10 +236,13 @@ subroutine btran_ed( nsites, sites, bc_in, bc_out) temprootr = sum(bc_out(s)%rootr_pasl(ifp,1:bc_in(s)%nlevsoil)) if(abs(1.0_r8-temprootr) > 1.0e-10_r8 .and. temprootr > 1.0e-10_r8)then - write(fates_log(),*) 'error with rootr in canopy fluxes',temprootr,sum_pftgs + + if(debug) write(fates_log(),*) 'error with rootr in canopy fluxes',temprootr,sum_pftgs + do j = 1,bc_in(s)%nlevsoil bc_out(s)%rootr_pasl(ifp,j) = bc_out(s)%rootr_pasl(ifp,j)/temprootr enddo + end if endif ! not bare ground cpatch => cpatch%younger diff --git a/biogeophys/EDSurfaceAlbedoMod.F90 b/biogeophys/EDSurfaceAlbedoMod.F90 index ebc01b1b69..b77f87b95d 100644 --- a/biogeophys/EDSurfaceAlbedoMod.F90 +++ b/biogeophys/EDSurfaceAlbedoMod.F90 @@ -44,7 +44,8 @@ module EDSurfaceRadiationMod public :: ED_SunShadeFracs logical :: debug = .false. ! for debugging this module - + character(len=*), parameter, private :: sourcefile = & + __FILE__ real(r8), public :: albice(maxSWb) = & ! albedo land ice by waveband (1=vis, 2=nir) (/ 0.80_r8, 0.55_r8 /) @@ -339,13 +340,16 @@ subroutine PatchNormanRadiation (currentPatch, & end do !iv end do !ft1 end do !L - if (sum(ftweight(1,:,1))<0.999_r8)then - write(fates_log(),*) 'canopy not full',ftweight(1,:,1) - endif - if (sum(ftweight(1,:,1))>1.0001_r8)then - write(fates_log(),*) 'canopy too full',ftweight(1,:,1) - endif + if(debug)then + if (sum(ftweight(1,:,1))<0.999_r8)then + write(fates_log(),*) 'canopy not full',ftweight(1,:,1) + endif + if (sum(ftweight(1,:,1))>1.0001_r8)then + write(fates_log(),*) 'canopy too full',ftweight(1,:,1) + endif + end if + do L = 1,currentPatch%NCL_p !start at the top canopy layer (1 is the top layer.) weighted_dir_tr(L) = 0.0_r8 @@ -397,11 +401,13 @@ subroutine PatchNormanRadiation (currentPatch, & !where there is a partly empty leaf layer, some fluxes go straight through. lai_change(L,ft,iv) = ftweight(L,ft,iv)-ftweight(L,ft,iv+1) endif - if (ftweight(L,ft,iv+1) - ftweight(L,ft,iv) > 1.e-10_r8)then - write(fates_log(),*) 'lower layer has more coverage. This is wrong' , & - ftweight(L,ft,iv),ftweight(L,ft,iv+1),ftweight(L,ft,iv+1)-ftweight(L,ft,iv) - endif - + if(debug)then + if (ftweight(L,ft,iv+1) - ftweight(L,ft,iv) > 1.e-10_r8)then + write(fates_log(),*) 'lower layer has more coverage. This is wrong' , & + ftweight(L,ft,iv),ftweight(L,ft,iv+1),ftweight(L,ft,iv+1)-ftweight(L,ft,iv) + endif + end if + !n.b. in theory lai_change could be calculated daily in the ED code. !This is light coming striaght through the canopy. if (L==1)then @@ -922,26 +928,30 @@ subroutine PatchNormanRadiation (currentPatch, & error = abs(currentPatch%sabs_dir(ib) - (currentPatch%tr_soil_dir(ib) * & (1.0_r8-currentPatch%gnd_alb_dir(ib) ) + & currentPatch%tr_soil_dir_dif(ib) * (1.0_r8-currentPatch%gnd_alb_dif(ib) ))) - if ( abs(error) > 0.0001)then - write(fates_log(),*)'dir ground absorption error',error,currentPatch%sabs_dir(ib), & - currentPatch%tr_soil_dir(ib)* & - (1.0_r8-currentPatch%gnd_alb_dir(ib) ),currentPatch%NCL_p,ib,sum(ftweight(1,1:numpft,1)) - write(fates_log(),*) 'albedos',currentPatch%sabs_dir(ib) ,currentPatch%tr_soil_dir(ib), & - (1.0_r8-currentPatch%gnd_alb_dir(ib) ) - - do ft =1,3 - iv = currentPatch%nrad(1,ft) + 1 - write(fates_log(),*) 'abs soil fluxes', Abs_dir_z(ft,iv),Abs_dif_z(ft,iv) - end do + if(debug)then + if ( abs(error) > 0.0001)then + write(fates_log(),*)'dir ground absorption error',error,currentPatch%sabs_dir(ib), & + currentPatch%tr_soil_dir(ib)* & + (1.0_r8-currentPatch%gnd_alb_dir(ib) ),currentPatch%NCL_p,ib,sum(ftweight(1,1:numpft,1)) + write(fates_log(),*) 'albedos',currentPatch%sabs_dir(ib) ,currentPatch%tr_soil_dir(ib), & + (1.0_r8-currentPatch%gnd_alb_dir(ib) ) + do ft =1,numpft + iv = currentPatch%nrad(1,ft) + 1 + write(fates_log(),*) 'abs soil fluxes', Abs_dir_z(ft,iv),Abs_dif_z(ft,iv) + end do + end if end if + else - if ( abs(currentPatch%sabs_dif(ib)-(currentPatch%tr_soil_dif(ib) * & - (1.0_r8-currentPatch%gnd_alb_dif(ib) ))) > 0.0001_r8)then - write(fates_log(),*)'dif ground absorption error',currentPatch%sabs_dif(ib) , & - (currentPatch%tr_soil_dif(ib)* & - (1.0_r8-currentPatch%gnd_alb_dif(ib) )),currentPatch%NCL_p,ib,sum(ftweight(1,1:numpft,1)) - endif + if (debug) then + if ( abs(currentPatch%sabs_dif(ib)-(currentPatch%tr_soil_dif(ib) * & + (1.0_r8-currentPatch%gnd_alb_dif(ib) ))) > 0.0001_r8)then + write(fates_log(),*)'dif ground absorption error',currentPatch%sabs_dif(ib) , & + (currentPatch%tr_soil_dif(ib)* & + (1.0_r8-currentPatch%gnd_alb_dif(ib) )),currentPatch%NCL_p,ib,sum(ftweight(1,1:numpft,1)) + endif + end if endif if (radtype == idirect)then @@ -976,17 +986,19 @@ subroutine PatchNormanRadiation (currentPatch, & ! to the complexity of this code, but where the system generates occasional errors, we ! will deal with them for now. end if + if (abs(error) > 0.15_r8)then - write(fates_log(),*) 'Large Dir Radn consvn error',error ,ib - write(fates_log(),*) 'diags', albd_parb_out(ib), ftdd_parb_out(ib), & - ftid_parb_out(ib), fabd_parb_out(ib) - write(fates_log(),*) 'lai_change',lai_change(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) - write(fates_log(),*) 'elai',currentpatch%elai_profile(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) - write(fates_log(),*) 'esai',currentpatch%esai_profile(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) - write(fates_log(),*) 'ftweight',ftweight(1,1:numpft,1:diag_nlevleaf) - write(fates_log(),*) 'cp',currentPatch%area, currentPatch%patchno - write(fates_log(),*) 'ground albedo diffuse (ib)', currentPatch%gnd_alb_dir(ib) - + if(debug)then + write(fates_log(),*) 'Large Dir Radn consvn error',error ,ib + write(fates_log(),*) 'diags', albd_parb_out(ib), ftdd_parb_out(ib), & + ftid_parb_out(ib), fabd_parb_out(ib) + write(fates_log(),*) 'lai_change',lai_change(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) + write(fates_log(),*) 'elai',currentpatch%elai_profile(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) + write(fates_log(),*) 'esai',currentpatch%esai_profile(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) + write(fates_log(),*) 'ftweight',ftweight(1,1:numpft,1:diag_nlevleaf) + write(fates_log(),*) 'cp',currentPatch%area, currentPatch%patchno + write(fates_log(),*) 'ground albedo diffuse (ib)', currentPatch%gnd_alb_dir(ib) + end if albd_parb_out(ib) = albd_parb_out(ib) + error end if else @@ -996,20 +1008,21 @@ subroutine PatchNormanRadiation (currentPatch, & end if if (abs(error) > 0.15_r8)then - write(fates_log(),*) '>5% Dif Radn consvn error',error ,ib - write(fates_log(),*) 'diags', albi_parb_out(ib), ftii_parb_out(ib), & - fabi_parb_out(ib) - write(fates_log(),*) 'lai_change',lai_change(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) - write(fates_log(),*) 'elai',currentpatch%elai_profile(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) - write(fates_log(),*) 'esai',currentpatch%esai_profile(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) - write(fates_log(),*) 'ftweight',ftweight(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) - write(fates_log(),*) 'cp',currentPatch%area, currentPatch%patchno - write(fates_log(),*) 'ground albedo diffuse (ib)', currentPatch%gnd_alb_dir(ib) - write(fates_log(),*) 'rhol',rhol(1:numpft,:) - write(fates_log(),*) 'ftw',sum(ftweight(1,1:numpft,1)),ftweight(1,1:numpft,1) - write(fates_log(),*) 'present',currentPatch%canopy_mask(1,1:numpft) - write(fates_log(),*) 'CAP',currentPatch%canopy_area_profile(1,1:numpft,1) - + if(debug)then + write(fates_log(),*) '>5% Dif Radn consvn error',error ,ib + write(fates_log(),*) 'diags', albi_parb_out(ib), ftii_parb_out(ib), & + fabi_parb_out(ib) + write(fates_log(),*) 'lai_change',lai_change(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) + write(fates_log(),*) 'elai',currentpatch%elai_profile(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) + write(fates_log(),*) 'esai',currentpatch%esai_profile(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) + write(fates_log(),*) 'ftweight',ftweight(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) + write(fates_log(),*) 'cp',currentPatch%area, currentPatch%patchno + write(fates_log(),*) 'ground albedo diffuse (ib)', currentPatch%gnd_alb_dir(ib) + write(fates_log(),*) 'rhol',rhol(1:numpft,:) + write(fates_log(),*) 'ftw',sum(ftweight(1,1:numpft,1)),ftweight(1,1:numpft,1) + write(fates_log(),*) 'present',currentPatch%canopy_mask(1,1:numpft) + write(fates_log(),*) 'CAP',currentPatch%canopy_area_profile(1,1:numpft,1) + end if albi_parb_out(ib) = albi_parb_out(ib) + error end if @@ -1021,10 +1034,12 @@ subroutine PatchNormanRadiation (currentPatch, & (fabi_parb_out(ib) + albi_parb_out(ib) + currentPatch%sabs_dif(ib)) endif - if (abs(error) > 0.00000001_r8)then - write(fates_log(),*) 'there is still error after correction',error ,ib + if(debug) then + if (abs(error) > 0.00000001_r8)then + write(fates_log(),*) 'there is still error after correction',error ,ib + end if end if - + end if end do !hlm_numSWb @@ -1132,11 +1147,13 @@ subroutine ED_SunShadeFracs(nsites, sites,bc_in,bc_out) bc_out(s)%fsun_pa(ifp) = 0._r8 endif - if(bc_out(s)%fsun_pa(ifp) > 1._r8)then - write(fates_log(),*) 'too much leaf area in profile', bc_out(s)%fsun_pa(ifp), & - sunlai,shalai - endif - + if(debug)then + if(bc_out(s)%fsun_pa(ifp) > 1._r8)then + write(fates_log(),*) 'too much leaf area in profile', bc_out(s)%fsun_pa(ifp), & + sunlai,shalai + endif + end if + elai = calc_areaindex(cpatch,'elai') bc_out(s)%laisun_pa(ifp) = elai*bc_out(s)%fsun_pa(ifp) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 98aaad6488..de3953a46a 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -2682,16 +2682,17 @@ subroutine hydraulics_bc ( nsites, sites, bc_in, bc_out, dtime) wb_check_site = delta_plant_storage+delta_soil_storage+site_runoff+transp_flux ! Now check on total error - if( abs(wb_check_site) > 1.e-4_r8 ) then - write(fates_log(),*) 'FATES hydro water balance is not so great [kg/m2]' - write(fates_log(),*) 'site_hydr%errh2o_hyd: ',wb_check_site - write(fates_log(),*) 'delta_plant_storage: ',delta_plant_storage - write(fates_log(),*) 'delta_soil_storage: ',delta_soil_storage - write(fates_log(),*) 'site_runoff: ',site_runoff - write(fates_log(),*) 'transp_flux: ',transp_flux + if(debug)then + if( abs(wb_check_site) > 1.e-4_r8 ) then + write(fates_log(),*) 'FATES hydro water balance is not so great [kg/m2]' + write(fates_log(),*) 'site_hydr%errh2o_hyd: ',wb_check_site + write(fates_log(),*) 'delta_plant_storage: ',delta_plant_storage + write(fates_log(),*) 'delta_soil_storage: ',delta_soil_storage + write(fates_log(),*) 'site_runoff: ',site_runoff + write(fates_log(),*) 'transp_flux: ',transp_flux + end if end if - site_hydr%h2oveg_hydro_err = site_hydr%h2oveg_hydro_err + site_hydr%errh2o_hyd @@ -3868,10 +3869,6 @@ subroutine Report1DError(cohort, site_hydr, ilayer, z_node, v_node, & write(fates_log(),*) 'inner shell kmaxs: ',site_hydr%kmax_lower_shell(:,1)*aroot_frac_plant - - - - deallocate(psi_node) deallocate(h_node) @@ -4897,7 +4894,9 @@ subroutine MatSolve2D(bc_in,site_hydr,cohort,cohort_hydr, & enddo if ( nwtn_iter > max_newton_iter) then icnv = icnv_fail_round - write(fates_log(),*) 'Newton hydraulics solve failed',residual_amax,nsd,tm + if(debug)then + write(fates_log(),*) 'Newton hydraulics solve failed',residual_amax,nsd,tm + end if endif ! Three scenarios: @@ -5089,10 +5088,12 @@ subroutine MatSolve2D(bc_in,site_hydr,cohort,cohort_hydr, & end do outerloop - if(cohort_hydr%iterh1>1._r8) then - write(fates_log(),*) "hydro solve info: i1: ",cohort_hydr%iterh1,"i2: ",cohort_hydr%iterh2 + if(debug)then + if(cohort_hydr%iterh1>1._r8) then + write(fates_log(),*) "hydro solve info: i1: ",cohort_hydr%iterh1,"i2: ",cohort_hydr%iterh2 + end if end if - + ! Save flux diagnostics ! ------------------------------------------------------ diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 4ff827443b..c58205d89e 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -1212,6 +1212,7 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in if (abs(gs_mol-gs_mol_err) > 1.e-01_r8) then write (fates_log(),*) 'Stomatal model error check - stomatal conductance error:' write (fates_log(),*) gs_mol, gs_mol_err + call endrun(msg=errMsg(sourcefile, __LINE__)) end if enddo !sunsha loop diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index 127dfa43f9..0b367b862d 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -65,8 +65,8 @@ module SFMainMod ! The following parameter represents one of the values of hlm_spitfire_mode ! and more of these appear in subroutine area_burnt_intensity below ! NB. The same parameters are set in /src/biogeochem/CNFireFactoryMod - integer :: write_SF = 0 ! for debugging - logical :: debug = .false. ! for debugging + integer :: write_SF = ifalse ! for debugging + logical :: debug = .false. ! for debugging ! ============================================================================ ! ============================================================================ @@ -94,7 +94,7 @@ subroutine fire_model( currentSite, bc_in) currentPatch => currentPatch%older enddo - if(write_SF==1)then + if(write_SF==itrue)then write(fates_log(),*) 'spitfire_mode', hlm_spitfire_mode endif @@ -303,8 +303,10 @@ subroutine charecteristics_of_fuel ( currentSite ) endif currentPatch%fuel_sav = sum(SF_val_SAV(1:nfsc))/(nfsc) ! make average sav to avoid crashing code. - if ( hlm_masterproc == itrue ) write(fates_log(),*) 'problem with spitfire fuel averaging' - + if ( hlm_masterproc == itrue .and. write_SF == itrue)then + write(fates_log(),*) 'problem with spitfire fuel averaging' + end if + ! FIX(SPM,032414) refactor...should not have 0 fuel unless everything is burnt ! off. currentPatch%fuel_eff_moist = 0.0000000001_r8 diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index c3b503a729..35cf871b75 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -333,7 +333,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) do ft = 1,numpft if(sites(s)%area_pft(ft).lt.0.01_r8.and.sites(s)%area_pft(ft).gt.0.0_r8)then - write(fates_log(),*) 'removing small pft patches',s,ft,sites(s)%area_pft(ft) + if(debug) write(fates_log(),*) 'removing small pft patches',s,ft,sites(s)%area_pft(ft) sites(s)%area_pft(ft)=0.0_r8 ! remove tiny patches to prevent numerical errors in terminate patches endif @@ -581,13 +581,13 @@ subroutine init_patches( nsites, sites, bc_in) ! remove or add extra area ! if the oldest patch has enough area, use that sites(s)%oldest_patch%area = sites(s)%oldest_patch%area - (tota-area) - write(*,*) 'fixing patch precision - oldest',s, tota-area + if(debug) write(fates_log(),*) 'fixing patch precision - oldest',s, tota-area else ! or otherwise take the area from the youngest patch. sites(s)%youngest_patch%area = sites(s)%oldest_patch%area - (tota-area) - write(*,*) 'fixing patch precision -youngest ',s, tota-area + if(debug) write(fates_log(),*) 'fixing patch precision -youngest ',s, tota-area endif else !this is a big error not just a precision error. - write(*,*) 'issue with patch area in EDinit',tota-area,tota + write(fates_log(),*) 'issue with patch area in EDinit',tota-area,tota call endrun(msg=errMsg(sourcefile, __LINE__)) endif ! big error end if ! too much patch area diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 48820e5ad6..219e5a1e3c 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -349,6 +349,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) if( currentPatch%age < 0._r8 )then write(fates_log(),*) 'negative patch age?',currentPatch%age, & currentPatch%patchno,currentPatch%area + call endrun(msg=errMsg(sourcefile, __LINE__)) endif ! add age increment to secondary forest patches as well @@ -560,6 +561,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentCohort%coage = currentCohort%coage + hlm_freq_day if(currentCohort%coage < 0.0_r8)then write(fates_log(),*) 'negative cohort age?',currentCohort%coage + call endrun(msg=errMsg(sourcefile, __LINE__)) end if ! update cohort age class and age x pft class diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index c89e63df98..eeea523f79 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1442,7 +1442,7 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'phen_cold_size_threshold = ',EDPftvarcon_inst%phen_cold_size_threshold write(fates_log(),fmt0) 'phen_stem_drop_fraction',EDpftvarcon_inst%phen_stem_drop_fraction write(fates_log(),fmt0) 'fire_alpha_SH = ',EDPftvarcon_inst%fire_alpha_SH - write(fates_log(),fmt0) 'allom_frbstor_repro = ',EDPftvarcon_inst%allom_frbstor_repro + write(fates_log(),fmt0) 'allom_frbstor_repro = ',EDPftvarcon_inst%allom_frbstor_repro write(fates_log(),fmt0) 'hydr_p_taper = ',EDPftvarcon_inst%hydr_p_taper write(fates_log(),fmt0) 'hydr_rs2 = ',EDPftvarcon_inst%hydr_rs2 write(fates_log(),fmt0) 'hydr_srl = ',EDPftvarcon_inst%hydr_srl diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 97f3342b43..94f9e9c25d 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -1123,8 +1123,7 @@ subroutine set_dim_indices(this, dk_name, idim, dim_index) write(fates_log(), *) 'Trying to define dimension size to a dim-type structure' write(fates_log(), *) 'but the dimension index does not exist' write(fates_log(), *) 'type: ',dk_name,' ndims: ',this%dim_kinds(ityp)%ndims,' input dim:',idim - stop - !end_run + call endrun(msg=errMsg(sourcefile, __LINE__)) end if if (idim == 1) then @@ -2236,11 +2235,6 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_leaf_height_dist_si_height(io_si,i_heightbin) = & hio_leaf_height_dist_si_height(io_si,i_heightbin) + & ccohort%c_area * AREA_INV * ccohort%treelai * frac_canopy_in_bin - - ! if ( ( ccohort%c_area * AREA_INV * ccohort%treelai * frac_canopy_in_bin) .lt. 0._r8) then - ! write(fates_log(),*) ' negative hio_leaf_height_dist_si_height:' - ! write(fates_log(),*) ' c_area, treelai, frac_canopy_in_bin:', ccohort%c_area, ccohort%treelai, frac_canopy_in_bin - ! endif end do if (ccohort%canopy_layer .eq. 1) then @@ -4132,11 +4126,8 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) end if if(print_iterations) then -! print*,' Mean solves: ',sum(hio_iterh2_scpf(io_si,:))/real(count(ncohort_scpf(:)>0._r8),r8), & -! ' Mean failures: ',sum(hio_iterh1_scpf(io_si,:))/real(count(ncohort_scpf(:)>0._r8),r8) - write(fmt_char,'(I2)') iterh2_nhist - write(fates_log(),fmt='(A,'//fmt_char//'I5)') 'Solves: ',int(iterh2_histy(:)) - !write(*,*) 'Histogram: ',int(iterh2_histy(:)) + write(fmt_char,'(I2)') iterh2_nhist + write(fates_log(),fmt='(A,'//fmt_char//'I5)') 'Solves: ',int(iterh2_histy(:)) end if diff --git a/main/FatesHistoryVariableType.F90 b/main/FatesHistoryVariableType.F90 index 6457e644f1..75a6d30f3f 100644 --- a/main/FatesHistoryVariableType.F90 +++ b/main/FatesHistoryVariableType.F90 @@ -1,7 +1,8 @@ module FatesHistoryVariableType use FatesConstantsMod, only : r8 => fates_r8 - use FatesGlobals, only : fates_log + use FatesGlobals, only : fates_log + use FatesGlobals , only : endrun => fates_endrun use FatesIODimensionsMod, only : fates_io_dimension_type use FatesIOVariableKindMod, only : fates_io_variable_kind_type use FatesIOVariableKindMod, only : patch_r8, patch_ground_r8, patch_size_pft_r8 @@ -15,12 +16,16 @@ module FatesHistoryVariableType use FatesIOVariableKindMod, only : site_elem_r8, site_elpft_r8 use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8 use FatesIOVariableKindMod, only : iotype_index, site_agefuel_r8 - + use shr_log_mod , only : errMsg => shr_log_errMsg + implicit none private ! By default everything is private ! Make public necessary subroutines and functions + + character(len=*), parameter, private :: sourcefile = & + __FILE__ ! This type is instanteated in the HLM-FATES interface (clmfates_interfaceMod.F90) @@ -208,8 +213,7 @@ subroutine Init(this, vname, units, long, use_default, & case default write(fates_log(),*) 'Incompatible vtype passed to set_history_var' write(fates_log(),*) 'vtype = ',trim(vtype),' ?' - stop - ! end_run + call endrun(msg=errMsg(sourcefile, __LINE__)) end select end subroutine Init @@ -336,8 +340,7 @@ subroutine Flush(this, thread, dim_bounds, dim_kinds) this%r82d(lb1:ub1, lb2:ub2) = this%flushval case default write(fates_log(),*) 'fates history variable type undefined while flushing history variables' - stop - !end_run + call endrun(msg=errMsg(sourcefile, __LINE__)) end select end subroutine Flush diff --git a/main/FatesIOVariableKindMod.F90 b/main/FatesIOVariableKindMod.F90 index 93b34ebab3..02eb39f594 100644 --- a/main/FatesIOVariableKindMod.F90 +++ b/main/FatesIOVariableKindMod.F90 @@ -3,10 +3,16 @@ module FatesIOVariableKindMod use FatesConstantsMod, only : fates_long_string_length use FatesGlobals, only : fates_log use FatesIODimensionsMod, only : fates_io_dimension_type + use FatesGlobals , only : endrun => fates_endrun + use shr_log_mod , only : errMsg => shr_log_errMsg + implicit none private + character(len=*), parameter, private :: sourcefile = & + __FILE__ + ! FIXME(bja, 2016-10) do these need to be strings, or can they be integer enumerations? ! FIXME(rgk, 2016-11) these should probably be moved to varkindmod? @@ -122,7 +128,7 @@ function iotype_index(iotype_name, num_dim_kinds, dim_kinds) result(dk_index) end if end do write(fates_log(),*) 'An IOTYPE THAT DOESNT EXIST WAS SPECIFIED' - !end_run + call endrun(msg=errMsg(sourcefile, __LINE__)) end function iotype_index diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 5561a78f52..bc7cb4e7ea 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1251,36 +1251,28 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) case('check_allset') if(hlm_numSWb .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'FATES dimension/parameter unset: num_sw_rad_bbands' - end if + write(fates_log(), *) 'FATES dimension/parameter unset: num_sw_rad_bbands' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_masterproc .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'FATES parameter unset: hlm_masterproc' - end if + write(fates_log(), *) 'FATES parameter unset: hlm_masterproc' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_numSWb > maxSWb) then - if (fates_global_verbose()) then - write(fates_log(), *) 'FATES sets a maximum number of shortwave bands' - write(fates_log(), *) 'for some scratch-space, maxSWb' - write(fates_log(), *) 'it defaults to 2, but can be increased as needed' - write(fates_log(), *) 'your driver or host model is intending to drive' - write(fates_log(), *) 'FATES with:',hlm_numSWb,' bands.' - write(fates_log(), *) 'please increase maxSWb in EDTypes to match' - write(fates_log(), *) 'or exceed this value' - end if + write(fates_log(), *) 'FATES sets a maximum number of shortwave bands' + write(fates_log(), *) 'for some scratch-space, maxSWb' + write(fates_log(), *) 'it defaults to 2, but can be increased as needed' + write(fates_log(), *) 'your driver or host model is intending to drive' + write(fates_log(), *) 'FATES with:',hlm_numSWb,' bands.' + write(fates_log(), *) 'please increase maxSWb in EDTypes to match' + write(fates_log(), *) 'or exceed this value' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if ( .not.((hlm_use_planthydro.eq.1).or.(hlm_use_planthydro.eq.0)) ) then - if (fates_global_verbose()) then - write(fates_log(), *) 'The FATES namelist planthydro flag must be 0 or 1, exiting' - end if + write(fates_log(), *) 'The FATES namelist planthydro flag must be 0 or 1, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) elseif (hlm_use_planthydro.eq.1 ) then write(fates_log(), *) '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' @@ -1293,30 +1285,23 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) end if if ( (hlm_use_lu_harvest .lt. 0).or.(hlm_use_lu_harvest .gt. 1) ) then - if (fates_global_verbose()) then - write(fates_log(), *) 'The FATES lu_harvest flag must be 0 or 1, exiting' - end if + write(fates_log(), *) 'The FATES lu_harvest flag must be 0 or 1, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if ( (hlm_num_lu_harvest_cats .lt. 0) ) then - if (fates_global_verbose()) then - write(fates_log(), *) 'The FATES number of hlm harvest cats must be >= 0, exiting' - end if + write(fates_log(), *) 'The FATES number of hlm harvest cats must be >= 0, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if ( .not.((hlm_use_logging .eq.1).or.(hlm_use_logging.eq.0)) ) then - if (fates_global_verbose()) then - write(fates_log(), *) 'The FATES namelist use_logging flag must be 0 or 1, exiting' - end if + write(fates_log(), *) 'The FATES namelist use_logging flag must be 0 or 1, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if ( ( ANY(EDPftvarcon_inst%mort_ip_age_senescence < fates_check_param_set )) .and. & (hlm_use_cohort_age_tracking .eq.0 ) ) then - write(fates_log(),*) 'Age dependent mortality cannot be on if' write(fates_log(),*) 'cohort age tracking is off.' write(fates_log(),*) 'Set hlm_use_cohort_age_tracking = .true.' @@ -1324,191 +1309,136 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) write(fates_log(),*) 'Aborting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if ( .not.((hlm_use_ed_st3.eq.1).or.(hlm_use_ed_st3.eq.0)) ) then - if (fates_global_verbose()) then - write(fates_log(), *) 'The FATES namelist stand structure flag must be 0 or 1, exiting' - end if + write(fates_log(), *) 'The FATES namelist stand structure flag must be 0 or 1, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if ( .not.((hlm_use_ed_prescribed_phys.eq.1).or.(hlm_use_ed_prescribed_phys.eq.0)) ) then - if (fates_global_verbose()) then - write(fates_log(), *) 'The FATES namelist prescribed physiology flag must be 0 or 1, exiting' - end if + write(fates_log(), *) 'The FATES namelist prescribed physiology flag must be 0 or 1, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if ( hlm_use_ed_prescribed_phys.eq.1 .and. hlm_use_ed_st3.eq.1 ) then - if (fates_global_verbose()) then - write(fates_log(), *) 'FATES ST3 and prescribed physiology cannot both be turned on.' - write(fates_log(), *) 'Review the namelist entries, exiting' - end if + write(fates_log(), *) 'FATES ST3 and prescribed physiology cannot both be turned on.' + write(fates_log(), *) 'Review the namelist entries, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if ( hlm_use_inventory_init.eq.1 .and. hlm_use_cohort_age_tracking .eq.1) then - if (fates_global_verbose()) then - write(fates_log(), *) 'Fates inventory init cannot be used with age dependent mortality' - write(fates_log(), *) 'Set hlm_use_cohort_age_tracking to 0 or turn off inventory init' - end if + write(fates_log(), *) 'Fates inventory init cannot be used with age dependent mortality' + write(fates_log(), *) 'Set hlm_use_cohort_age_tracking to 0 or turn off inventory init' call endrun(msg=errMsg(sourcefile, __LINE__)) end if - - if ( .not.((hlm_use_inventory_init.eq.1).or.(hlm_use_inventory_init.eq.0)) ) then - if (fates_global_verbose()) then - write(fates_log(), *) 'The FATES NL inventory flag must be 0 or 1, exiting' - end if + write(fates_log(), *) 'The FATES NL inventory flag must be 0 or 1, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(trim(hlm_inventory_ctrl_file) .eq. 'unset') then - if (fates_global_verbose()) then - write(fates_log(),*) 'namelist entry for fates inventory control file is unset, exiting' - end if + write(fates_log(),*) 'namelist entry for fates inventory control file is unset, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_ivis .ne. ivis) then - if (fates_global_verbose()) then - write(fates_log(), *) 'FATES assumption about the index of visible shortwave' - write(fates_log(), *) 'radiation is different from the HLM, exiting' - end if + write(fates_log(), *) 'FATES assumption about the index of visible shortwave' + write(fates_log(), *) 'radiation is different from the HLM, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_inir .ne. inir) then - if (fates_global_verbose()) then - write(fates_log(), *) 'FATES assumption about the index of NIR shortwave' - write(fates_log(), *) 'radiation is different from the HLM, exiting' - end if + write(fates_log(), *) 'FATES assumption about the index of NIR shortwave' + write(fates_log(), *) 'radiation is different from the HLM, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_is_restart .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'FATES parameter unset: hlm_is_restart, exiting' - end if + write(fates_log(), *) 'FATES parameter unset: hlm_is_restart, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_numlevgrnd .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'FATES dimension/parameter unset: numlevground, exiting' - end if + write(fates_log(), *) 'FATES dimension/parameter unset: numlevground, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(trim(hlm_name) .eq. 'unset') then - if (fates_global_verbose()) then - write(fates_log(),*) 'FATES dimension/parameter unset: hlm_name, exiting' - end if + write(fates_log(),*) 'FATES dimension/parameter unset: hlm_name, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(trim(hlm_nu_com) .eq. 'unset') then - if (fates_global_verbose()) then - write(fates_log(),*) 'FATES dimension/parameter unset: hlm_nu_com, exiting' - end if + write(fates_log(),*) 'FATES dimension/parameter unset: hlm_nu_com, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_nitrogen_spec .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(),*) 'FATES parameters unset: hlm_nitrogen_spec, exiting' - end if + write(fates_log(),*) 'FATES parameters unset: hlm_nitrogen_spec, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_phosphorus_spec .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(),*) 'FATES parameters unset: hlm_phosphorus_spec, exiting' - end if + write(fates_log(),*) 'FATES parameters unset: hlm_phosphorus_spec, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if( abs(hlm_hio_ignore_val-unset_double)<1e-10 ) then - if (fates_global_verbose()) then - write(fates_log(),*) 'FATES dimension/parameter unset: hio_ignore' - end if + write(fates_log(),*) 'FATES dimension/parameter unset: hio_ignore' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_ipedof .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'index for the HLMs pedotransfer function unset: hlm_ipedof, exiting' - end if + write(fates_log(), *) 'index for the HLMs pedotransfer function unset: hlm_ipedof, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_max_patch_per_site .eq. unset_int ) then - if (fates_global_verbose()) then - write(fates_log(), *) 'the number of patch-space per site unset: hlm_max_patch_per_site, exiting' - end if + write(fates_log(), *) 'the number of patch-space per site unset: hlm_max_patch_per_site, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) elseif(hlm_max_patch_per_site < maxPatchesPerSite ) then - if (fates_global_verbose()) then - write(fates_log(), *) 'FATES is trying to allocate space for more patches per site, than the HLM has space for.' - write(fates_log(), *) 'hlm_max_patch_per_site (HLM side): ', hlm_max_patch_per_site - write(fates_log(), *) 'maxPatchesPerSite (FATES side): ', maxPatchesPerSite - write(fates_log(), *) - end if + write(fates_log(), *) 'FATES is trying to allocate space for more patches per site, than the HLM has space for.' + write(fates_log(), *) 'hlm_max_patch_per_site (HLM side): ', hlm_max_patch_per_site + write(fates_log(), *) 'maxPatchesPerSite (FATES side): ', maxPatchesPerSite + write(fates_log(), *) call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_parteh_mode .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'switch deciding which plant reactive transport model to use is unset, hlm_parteh_mode, exiting' - end if + write(fates_log(), *) 'switch deciding which plant reactive transport model to use is unset, hlm_parteh_mode, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_use_ch4 .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'switch for the HLMs CH4 module unset: hlm_use_ch4, exiting' - end if + write(fates_log(), *) 'switch for the HLMs CH4 module unset: hlm_use_ch4, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_use_vertsoilc .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'switch for the HLMs soil carbon discretization unset: hlm_use_vertsoilc, exiting' - end if + write(fates_log(), *) 'switch for the HLMs soil carbon discretization unset: hlm_use_vertsoilc, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_spitfire_mode .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'switch for SPITFIRE unset: hlm_spitfire_mode, exiting' - end if + write(fates_log(), *) 'switch for SPITFIRE unset: hlm_spitfire_mode, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_sf_nofire_def .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'definition of no-fire mode unset: hlm_sf_nofire_def, exiting' - end if + write(fates_log(), *) 'definition of no-fire mode unset: hlm_sf_nofire_def, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_sf_scalar_lightning_def .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'definition of scalar lightning mode unset: hlm_sf_scalltng_def, exiting' - end if + write(fates_log(), *) 'definition of scalar lightning mode unset: hlm_sf_scalltng_def, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_sf_successful_ignitions_def .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'definition of successful ignition mode unset: hlm_sf_successful, exiting' - end if + write(fates_log(), *) 'definition of successful ignition mode unset: hlm_sf_successful, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_sf_anthro_ignitions_def .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'definition of anthro-ignition mode unset: hlm_sf_anthig_def, exiting' - end if + write(fates_log(), *) 'definition of anthro-ignition mode unset: hlm_sf_anthig_def, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if @@ -1521,33 +1451,24 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) call endrun(msg=errMsg(sourcefile, __LINE__)) end if end if - if(hlm_use_fixed_biogeog.eq.unset_int) then - if(fates_global_verbose()) then - write(fates_log(), *) 'switch for fixed biogeog unset: him_use_fixed_biogeog, exiting' - end if - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(), *) 'switch for fixed biogeog unset: him_use_fixed_biogeog, exiting' + call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_use_nocomp.eq.unset_int) then - if(fates_global_verbose()) then - write(fates_log(), *) 'switch for no competition mode. ' - end if - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(), *) 'switch for no competition mode. ' + call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_use_sp.eq.unset_int) then - if(fates_global_verbose()) then - write(fates_log(), *) 'switch for SP mode. ' - end if - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(), *) 'switch for SP mode. ' + call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_use_cohort_age_tracking .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'switch for cohort_age_tracking unset: hlm_use_cohort_age_tracking, exiting' - end if + write(fates_log(), *) 'switch for cohort_age_tracking unset: hlm_use_cohort_age_tracking, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if @@ -1556,7 +1477,6 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if(hlm_use_sp.eq.itrue.and.hlm_use_fixed_biogeog.eq.ifalse)then write(fates_log(), *) 'SP cannot be on if fixed biogeog mode is off. Exiting. ' call endrun(msg=errMsg(sourcefile, __LINE__)) @@ -1565,7 +1485,6 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) if (fates_global_verbose()) then write(fates_log(), *) 'Checked. All control parameters sent to FATES.' end if - case default @@ -1695,10 +1614,10 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) end if case('use_sp') - hlm_use_sp = ival - if (fates_global_verbose()) then - write(fates_log(),*) 'Transfering hlm_use_sp= ',ival,' to FATES' - end if + hlm_use_sp = ival + if (fates_global_verbose()) then + write(fates_log(),*) 'Transfering hlm_use_sp= ',ival,' to FATES' + end if case('use_planthydro') hlm_use_planthydro = ival @@ -1749,11 +1668,8 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) end if case default - if (fates_global_verbose()) then - write(fates_log(), *) 'tag not recognized:',trim(tag) - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - ! end_run + write(fates_log(), *) 'fates NL tag not recognized:',trim(tag) + call endrun(msg=errMsg(sourcefile, __LINE__)) end select end if @@ -1766,10 +1682,8 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) write(fates_log(),*) 'Transfering hio_ignore_val = ',rval,' to FATES' end if case default - if (fates_global_verbose()) then - write(fates_log(),*) 'tag not recognized:',trim(tag) - end if - ! end_run + write(fates_log(),*) 'fates NL tag not recognized:',trim(tag) + call endrun(msg=errMsg(sourcefile, __LINE__)) end select end if @@ -1795,10 +1709,8 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) end if case default - if (fates_global_verbose()) then - write(fates_log(),*) 'tag not recognized:',trim(tag) - end if - ! end_run + write(fates_log(),*) 'fates NL tag not recognized:',trim(tag) + call endrun(msg=errMsg(sourcefile, __LINE__)) end select end if diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index 19596a833e..cc939f6a33 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -484,7 +484,7 @@ subroutine initialize_sites_by_inventory(nsites,sites,bc_in) write(fates_log(),*) 'Lat: ',sites(s)%lat,' Lon: ',sites(s)%lon write(fates_log(),*) basal_area_pref,' [m2/ha]' write(fates_log(),*) '-------------------------------------------------------' - + ! Update the patch index numbers and fuse the cohorts in the patches ! ---------------------------------------------------------------------------------------- ipa=1 @@ -994,9 +994,11 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & end if if (c_pft .eq. 0 ) then - write(fates_log(), *) 'inventory pft: ',c_pft - write(fates_log(), *) 'SPECIAL CASE TRIGGERED: PFT == 0 and therefore this subroutine' - write(fates_log(), *) 'will assign a cohort with n = n_orig/numpft to every cohort in range 1 to numpft' + if(debug_inv)then + write(fates_log(), *) 'inventory pft: ',c_pft + write(fates_log(), *) 'SPECIAL CASE TRIGGERED: PFT == 0 and therefore this subroutine' + write(fates_log(), *) 'will assign a cohort with n = n_orig/numpft to every cohort in range 1 to numpft' + end if ncohorts_to_create = numpft else ncohorts_to_create = 1 diff --git a/main/FatesParametersInterface.F90 b/main/FatesParametersInterface.F90 index f69d4ef5bf..2e5895c472 100644 --- a/main/FatesParametersInterface.F90 +++ b/main/FatesParametersInterface.F90 @@ -370,7 +370,6 @@ subroutine SetDimensionSizes(this, is_host_file, num_used_dimensions, dimension_ ! non-empty dimension name, set the size do i = 1, num_used_dimensions if (trim(dimension_names(i)) == trim(dim_name)) then - !write(*, *) '--> ', trim(this%parameters(p)%name), ' setting ', trim(dim_name), ' d = ', d, 'size = ', dimension_sizes(i) this%parameters(p)%dimension_sizes(d) = dimension_sizes(i) exit end if diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 5fe3b267a1..c138724711 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -410,8 +410,7 @@ subroutine set_dim_indices(this, dk_name, idim, dim_index) write(fates_log(), *) 'Trying to define dimension size to a dim-type structure' write(fates_log(), *) 'but the dimension index does not exist' write(fates_log(), *) 'type: ',dk_name,' ndims: ',this%dim_kinds(ityp)%ndims,' input dim:',idim - stop - !end_run + call endrun(msg=errMsg(sourcefile, __LINE__)) end if if (idim == 1) then diff --git a/main/FatesRestartVariableType.F90 b/main/FatesRestartVariableType.F90 index 48152ec955..501dfe7023 100644 --- a/main/FatesRestartVariableType.F90 +++ b/main/FatesRestartVariableType.F90 @@ -3,10 +3,16 @@ module FatesRestartVariableMod use FatesConstantsMod, only : r8 => fates_r8 use FatesGlobals, only : fates_log use FatesIOVariableKindMod, only : fates_io_variable_kind_type - + use FatesGlobals , only : endrun => fates_endrun + use shr_log_mod , only : errMsg => shr_log_errMsg + implicit none private ! Modules are private by default + + character(len=*), parameter, private :: sourcefile = & + __FILE__ + ! This type is instanteated in the HLM-FATES interface (clmfates_interfaceMod.F90) type, public :: fates_restart_variable_type @@ -108,8 +114,7 @@ subroutine Init(this, vname, units, long, vtype, flushval, num_dim_kinds, dim_ki case default write(fates_log(),*) 'Incompatible vtype passed to set_restart_var' write(fates_log(),*) 'vtype = ',trim(vtype),' ?' - stop - ! end_run + call endrun(msg=errMsg(sourcefile, __LINE__)) end select end subroutine Init @@ -200,8 +205,7 @@ subroutine flush(this, thread, dim_bounds, dim_kinds) case default write(fates_log(),*) 'fates history variable type undefined while flushing history variables' - stop - !end_run + call endrun(msg=errMsg(sourcefile, __LINE__)) end select end subroutine Flush diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index dce172d47d..3332b38f9b 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -1016,6 +1016,7 @@ subroutine PRTCheckParams(is_master) write(fates_log(),*) 'the parameter file organ list' write(fates_log(),*) 'fates_prt_organ_id: ',prt_params%organ_id(:) write(fates_log(),*) 'Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(prt_params%organ_id(io) == store_organ) then write(fates_log(),*) 'with flexible cnp or c-only alloc hypothesese' @@ -1024,6 +1025,7 @@ subroutine PRTCheckParams(is_master) write(fates_log(),*) 'the parameter file organ list' write(fates_log(),*) 'fates_prt_organ_id: ',prt_params%organ_id(:) write(fates_log(),*) 'Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) end if end do From ef9126a51884811af0b4cdb2b1d54dfd52fdc6ed Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 6 Oct 2021 14:22:02 -0400 Subject: [PATCH 062/852] Added metadata fix to the decompmicc parameter --- 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 39adab94f6..8eb8a7cd09 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -167,7 +167,7 @@ variables: fates_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; double fates_eca_decompmicc(fates_pft) ; fates_eca_decompmicc:units = "gC/m3" ; - fates_eca_decompmicc:long_name = "mean soil microbial decomposer biomass (ECA)" ; + fates_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; double fates_eca_km_nh4(fates_pft) ; fates_eca_km_nh4:units = "gN/m3" ; fates_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; From 4acc184bb759da250eedd78635bac9cc4238a439 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 6 Oct 2021 14:33:03 -0400 Subject: [PATCH 063/852] Fixed some text describing parameters in microbial biomass attenuation function --- biogeochem/FatesSoilBGCFluxMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index 9f210e8404..45e71dea05 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -677,7 +677,7 @@ subroutine PrepNutrientAquisitionBCs(csite, bc_in, bc_out) bc_out%veg_rootc(icomp,id) = bc_out%veg_rootc(icomp,id) + veg_rootc - ! We use a 3 parameter exponential attenuation function to estimate decomposer biomass + ! We use a 2 parameter exponential attenuation function to estimate decomposer biomass ! The parameter EDPftvarcon_inst%decompmicc(pft) is the maximum amount found at depth ! decompmicc_zmax, and the profile attenuates with strength lambda From 75e37c6e18614709ddcffc619674678f5141e062 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 18 Oct 2021 13:15:37 -0400 Subject: [PATCH 064/852] First pass at adding warning functions --- biogeochem/EDPatchDynamicsMod.F90 | 16 +++--- main/FatesGlobals.F90 | 85 ++++++++++++++++++++++++++++++- 2 files changed, 92 insertions(+), 9 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index fda538e36e..b877028e2a 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -3,7 +3,8 @@ module EDPatchDynamicsMod ! ============================================================================ ! Controls formation, creation, fusing and termination of patch level processes. ! ============================================================================ - use FatesGlobals , only : fates_log + use FatesGlobals , only : fates_log + use FatesGlobals , only : FatesWarn,N2S,A2S use FatesInterfaceTypesMod , only : hlm_freq_day use EDPftvarcon , only : EDPftvarcon_inst use EDPftvarcon , only : GetDecompyFrac @@ -132,7 +133,8 @@ module EDPatchDynamicsMod real(r8), parameter :: treefall_localization = 0.0_r8 real(r8), parameter :: burn_localization = 0.0_r8 - + character(len=512) :: msg ! Message string for warnings and logging + ! 10/30/09: Created by Rosie Fisher ! ============================================================================ @@ -333,15 +335,15 @@ subroutine disturbance_rates( site_in, bc_in) end do ! Fires can't burn the whole patch, as this causes /0 errors. - if (debug) then - if (currentPatch%disturbance_rates(dtype_ifire) > 0.98_r8)then - write(fates_log(),*) 'very high fire areas', & - currentPatch%disturbance_rates(dtype_ifire),currentPatch%frac_burnt - endif + !if (currentPatch%disturbance_rates(dtype_ifire) > 0.98_r8)then + if(.true.)then + msg = 'very high fire areas'//trim(A2S(currentPatch%disturbance_rates(:)))//trim(N2S(currentPatch%frac_burnt)) + call FatesWarn(msg,index=2) endif + ! ------------------------------------------------------------------------------------------ ! Determine which disturbance is dominant, and force mortality diagnostics in the upper ! canopy to be zero for the non-dominant mode. Note: upper-canopy tree-fall mortality is diff --git a/main/FatesGlobals.F90 b/main/FatesGlobals.F90 index d37ffe3b2a..48f8ffcdcb 100644 --- a/main/FatesGlobals.F90 +++ b/main/FatesGlobals.F90 @@ -17,7 +17,32 @@ module FatesGlobals public :: fates_log public :: fates_global_verbose public :: fates_endrun - + public :: FatesWarn + public :: A2S + public :: N2S + + ! ------------------------------------------------------------------------------------- + ! Warning handling + ! The objective here is to stop writing the same warning over and over again. After + ! we've seen the same machine print out the same warning over and over again, we get + ! the point and don't have to continue seeing the message. + ! We also allow warnings to have their own unique or group identifier, which will + ! make is to you only turn off warnings that are particularly chatty, and continue + ! to allow warnings elsewhere that have not tripped as often. + ! ------------------------------------------------------------------------------------- + + integer, parameter :: max_ids = 200 ! Maximum number of unique warning ids + ! expand as necessary + integer :: warn_counts(0:max_ids) = 0 ! Total number of times each id has warned + integer, parameter :: max_warnings = 100 ! The maximum number of warnings before we + ! stop writing the warning + logical :: warn_active(0:max_ids) = .true. ! The current status of the warning. + logical, parameter :: warning_override = .false. ! If you really don't want any warnings + ! you can set this to true to avoid + ! printing any of these warnings to the log + ! It should also bypass the logicals bound inside + ! at the compiler level (?) and be faster + contains @@ -67,6 +92,62 @@ subroutine fates_endrun(msg) end subroutine fates_endrun ! ===================================================================================== - + subroutine FatesWarn(msg,index) + + character(len=*), intent(in) :: msg ! string to be printed + integer,optional,intent(in) :: index ! warning index + + integer :: ind + + if(warning_override) return ! Exit early if we are turning off warnings + + if(present(index))then + ind = index + else + ind = 0 + end if + + ! Don't check if the index is within bounds, this routine could already + ! be too expensive if this is in cohort loops + warn_counts(ind) = warn_counts(ind) + 1 + + if(warn_active(ind))then + write(fates_log(),*) 'FWARN: ',ind,'m: ',msg + if(warn_counts(ind)> max_warnings) then + warn_active(ind) = .false. + write(fates_log(),*) 'FWARN: ',ind,'has saturated messaging, no longer reporting' + end if + end if + return + end subroutine FatesWarn + + ! ===================================================================================== + + function N2S(real_in) result(str) + + real(r8) :: real_in + character(len=16) :: str + + !write(str,*) real_in + write(str,'(a,E12.6)') ', ',real_in + + end function N2S + + ! ===================================================================================== + + function A2S(reals_in) result(str) + + real(r8) :: reals_in(:) + character(len=512) :: str + character(len=16) :: str_frag + integer :: i, nreal + + str = ', ' + do i = 1,ubound(reals_in,1) + str = trim(str)//', '//N2S(reals_in(i)) + end do + + end function A2S + end module FatesGlobals From 751490c7373ac7a50303186b03bdcd04803cce7d Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 18 Oct 2021 14:39:51 -0400 Subject: [PATCH 065/852] Setting target_m to dummy value to overcome IBM issues with base functions not setting output result --- parteh/PRTGenericMod.F90 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/parteh/PRTGenericMod.F90 b/parteh/PRTGenericMod.F90 index 76d0e01eda..3dab9563a3 100644 --- a/parteh/PRTGenericMod.F90 +++ b/parteh/PRTGenericMod.F90 @@ -1396,6 +1396,8 @@ function GetNutrientTargetBase(this,element_id,organ_id,stoich_mode) result(targ integer, intent(in),optional :: stoich_mode real(r8) :: target_m ! Target amount of nutrient for this organ [kg] + target_m = 0._r8 + write(fates_log(),*)'GetNutrientTargetBase must be extended by a child class.' call endrun(msg=errMsg(sourcefile, __LINE__)) From 9563af17d08f7153ff75040ff676fd9ed1fa5b0e Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 28 Oct 2021 15:07:40 -0400 Subject: [PATCH 066/852] NCLMax = 3 --- main/EDTypesMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 5da7babc54..ad1c6668c9 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -30,7 +30,7 @@ module EDTypesMod (/ 10, 4 /) !!! MUST SUM TO maxPatchesPerSite !!! integer, public :: maxCohortsPerPatch = 100 ! maximum number of cohorts per patch - integer, parameter, public :: nclmax = 2 ! Maximum number of canopy layers + integer, parameter, public :: nclmax = 3 ! Maximum number of canopy layers integer, parameter, public :: ican_upper = 1 ! Nominal index for the upper canopy integer, parameter, public :: ican_ustory = 2 ! Nominal index for diagnostics that refer ! to understory layers (all layers that From 7191021a890cba1e8ee002e96c603819e8d88246 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Sat, 30 Oct 2021 13:13:08 -0400 Subject: [PATCH 067/852] Added nutrient storage limit and derivative to test effects on stature growth --- parteh/PRTAllometricCNPMod.F90 | 139 +++++++++++++-------------------- 1 file changed, 53 insertions(+), 86 deletions(-) diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 5617d71e5d..85bc11aa3e 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -167,6 +167,9 @@ module PRTAllometricCNPMod integer, parameter :: num_bc_out = 5 ! Total number of + + real(r8), parameter :: min_stf_growth = 0.9_r8 ! Plants are only allowed to increase in stature + ! if they have more than 90% of their stores full ! ------------------------------------------------------------------------------------- @@ -374,6 +377,14 @@ subroutine DailyPRTAllometricCNP(this) real(r8) :: p_gain0 real(r8) :: maint_r_def0 + ! Knowing the stored N and P helps + ! to identify if the plant is net + ! gaining nutrients after replacement + real(r8) :: n_store0 + real(r8) :: p_store0 + real(r8) :: net_n_gain + real(r8) :: net_p_gain + ! Used for mass checking, total mass allocated based ! on change in the states, should match gain0's real(r8) :: allocated_c @@ -470,10 +481,12 @@ subroutine DailyPRTAllometricCNP(this) i_var = prt_global%sp_organ_map(store_organ,nitrogen_element) n_gain = n_gain + sum(this%variables(i_var)%val(:)) + net_n_gain = - sum(this%variables(i_var)%val(:)) this%variables(i_var)%val(:) = 0._r8 i_var = prt_global%sp_organ_map(store_organ,phosphorus_element) p_gain = p_gain + sum(this%variables(i_var)%val(:)) + net_p_gain = - sum(this%variables(i_var)%val(:)) this%variables(i_var)%val(:) = 0._r8 ! =================================================================================== @@ -484,6 +497,7 @@ subroutine DailyPRTAllometricCNP(this) call this%CNPPrioritizedReplacement(maint_r_def, c_gain, n_gain, p_gain, & state_c, state_n, state_p, target_c) + sum_c = 0._r8 do i_org = 1,num_organs sum_c = sum_c+state_c(i_org)%ptr @@ -504,8 +518,12 @@ subroutine DailyPRTAllometricCNP(this) ! Attempts have been made to get all pools and species closest to allometric ! targets based on prioritized relative demand and allometry functions. ! =================================================================================== + + net_n_gain = net_n_gain + n_gain + net_p_gain = net_p_gain + p_gain - call this%CNPStatureGrowth(c_gain, n_gain, p_gain, & + call this%CNPStatureGrowth(c_gain, n_gain, p_gain, & + net_n_gain, net_p_gain, & state_c, state_n, state_p, target_c, target_dcdd, cnp_limiter) sum_c = 0._r8 @@ -626,7 +644,7 @@ subroutine CNPPrioritizedReplacement(this, & real(r8), intent(inout) :: c_gain real(r8), intent(inout) :: n_gain real(r8), intent(inout) :: p_gain - real(r8), intent(inout) :: maint_r_deficit + real(r8), intent(inout) :: maint_r_deficit ! Not currently used type(parray_type) :: state_c(:) ! State array for carbon, by organ [kg] type(parray_type) :: state_n(:) ! State array for N, by organ [kg] type(parray_type) :: state_p(:) ! State array for P, by organ [kg] @@ -989,16 +1007,21 @@ end subroutine CNPPrioritizedReplacement ! ===================================================================================== - subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & + subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, net_n_gain, net_p_gain, & state_c, state_n, state_p, & target_c, target_dcdd, cnp_limiter) class(cnp_allom_prt_vartypes) :: this - real(r8), intent(inout) :: c_gain - real(r8), intent(inout) :: n_gain - real(r8), intent(inout) :: p_gain - real(r8), pointer :: maint_r_deficit + real(r8), intent(inout) :: c_gain ! Total daily C gain that remains to be used + real(r8), intent(inout) :: n_gain ! Total N available for allocation + ! (new uptake + storage) + real(r8), intent(inout) :: p_gain ! Total P available for allocation + ! (new uptake + storage) + real(r8), intent(in) :: net_n_gain ! How much N was gained or lost in the + ! process of net uptake and turnover replacment + real(r8), intent(in) :: net_p_gain ! How much P was gained or lost in the + ! process of net uptake and turnover replacment type(parray_type) :: state_c(:) ! State array for carbon, by organ [kg] type(parray_type) :: state_n(:) ! State array for N, by organ [kg] type(parray_type) :: state_p(:) ! State array for P, by organ [kg] @@ -1028,6 +1051,8 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & real(r8) :: sum_c_flux ! Sum of the carbon allocated, as reported ! by the ODE solver. [kg] real(r8) :: np_limit + real(r8) :: n_stf ! nitrogen storage target fraction (stf) [-] + real(r8) :: p_stf ! phosphorus storage target fraction (stf) [-] real(r8) :: n_match real(r8) :: p_match real(r8) :: c_flux_adj ! Adjustment to total carbon flux during stature growth @@ -1086,6 +1111,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & integer, parameter :: c_limited = 1 integer, parameter :: n_limited = 2 integer, parameter :: p_limited = 3 + leaf_status = this%bc_in(acnp_bc_in_id_lstat)%ival dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval @@ -1101,11 +1127,21 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & ! a plant had a productive last day before the phenology scheme ! signaled a drop. If this is the case, we can't grow stature ! cause that would force the leaves back on, so just leave. + + + target_n = this%GetNutrientTarget(nitrogen_element,store_organ,stoich_growth_min) + n_stf = max(state_n(store_id)%ptr/target_n,0._r8) + + target_p = this%GetNutrientTarget(phosphorus_element,store_organ,stoich_growth_min) + p_stf = max(state_p(store_id)%ptr/target_p,0._r8) - if( c_gain <= calloc_abs_error .or. & - n_gain <= 0.1_r8*calloc_abs_error .or. & - p_gain <= 0.02_r8*calloc_abs_error .or. & - leaf_status.eq.leaves_off ) then + if( c_gain <= calloc_abs_error .or. & + net_n_gain < 0._r8 .or. & + net_p_gain < 0._r8 .or. & + leaf_status.eq.leaves_off .or. & + n_stf < min_stf_growth .or. & + p_stf < min_stf_growth & + ) then return end if @@ -1230,82 +1266,13 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & end if end if - - select case(grow_lim_type) - case(1) - - - ! Calculate an approximation of the total amount of carbon that would be needed - ! to match the amount of each nutrient used. We also add in the amount of nutrient - ! that may or may-not exist above each pool's minimum stoichiometry... - ! -------------------------------------------------------------------------------- - - grow_c_from_c = 0._r8 - grow_c_from_n = 0._r8 - grow_c_from_p = 0._r8 - do ii = 1, n_mask_organs - i = mask_organs(ii) - if(organ_list(i).ne.store_organ)then - call this%GrowEquivC(c_gain,n_gain,p_gain, & - frac_c(i),ipft,organ_list(i), & - grow_c_from_c,grow_c_from_n,grow_c_from_p) - end if - end do - - ! -------------------------------------------------------------------------------- - ! We limit growth to align with the species would motivate the least flux of - ! carbon into growing tissues to match. This is only an approximation of how much - ! growth we get out of each, and they don't have to be perfect. As long as we - ! don't use more carbon than we have (we wont) and if we use the actual numerical - ! integrator in the trasfer step, the nutrients will be transferred linearly in - ! the next step. if they dip slightly above or below their target allometries, - ! its no big deal. - ! -------------------------------------------------------------------------------- - - if(grow_c_from_c > nearzero) then - c_gstature = c_gain * min(grow_c_from_c, grow_c_from_n, grow_c_from_p)/grow_c_from_c - else - write(fates_log(),*) 'Somehow grow_c_from_c is near zero',grow_c_from_c - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - case(2) - - n_match = 0._r8 - p_match = 0._r8 - do ii = 1, n_mask_organs - i = mask_organs(ii) - if(organ_list(i).ne.store_organ)then - call this%NAndPToMatchC(c_gain*frac_c(i),target_dcdd(i), & - ipft,organ_list(i),n_match,p_match) - end if - end do - - np_limit = min(min(1._r8, n_gain/n_match), min(1._r8, p_gain/p_match)) - - if( (n_gain/n_match)>1._r8 .and. (p_gain/p_match)>1._r8 ) then - cnp_limiter = c_limited - else - if( n_gain/n_match < p_gain/p_match ) then - cnp_limiter = n_limited - else - cnp_limiter = p_limited - end if - end if - - c_gstature = c_gain * np_limit - - case(3) - - ! No mathematical co-limitation of growth - ! This assumes that limitations will prevent - ! organs from allowing the growth step to even occur - ! and thus from an algorithmic level limit growth - - c_gstature = c_gain - - - end select + ! No mathematical co-limitation of growth + ! This assumes that limitations will prevent + ! organs from allowing the growth step to even occur + ! and thus from an algorithmic level limit growth + + c_gstature = c_gain if_stature_growth: if(c_gstature > nearzero) then From 949e9caddbbf826042cea64fd8bdc90afb5e152e Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 3 Nov 2021 16:11:38 -0400 Subject: [PATCH 068/852] fixed logic limiting growth --- parteh/PRTAllometricCNPMod.F90 | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 85bc11aa3e..30b3ad71c2 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -1136,12 +1136,9 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, net_n_gain, net_p_gain, p_stf = max(state_p(store_id)%ptr/target_p,0._r8) if( c_gain <= calloc_abs_error .or. & - net_n_gain < 0._r8 .or. & - net_p_gain < 0._r8 .or. & leaf_status.eq.leaves_off .or. & - n_stf < min_stf_growth .or. & - p_stf < min_stf_growth & - ) then + (n_stf < min_stf_growth .and. net_n_gain < 0._r8) .or. & + (p_stf < min_stf_growth .and. net_p_gain < 0._r8) ) then return end if From 5084a1da2a9852cdc238db5e3009170dec79eb78 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 4 Nov 2021 10:51:35 -0400 Subject: [PATCH 069/852] Adjusted growth restrictions and uptake downregulation so that downregulation would not occur at nutrient storage fractions less than the growth cutoff. --- biogeochem/FatesSoilBGCFluxMod.F90 | 6 +++--- parteh/PRTAllometricCNPMod.F90 | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index 9f210e8404..9815af8096 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -1185,13 +1185,13 @@ function ECACScalar(ccohort, element_id) result(c_scalar) integer, parameter :: downreg_type = downreg_linear - real(r8), parameter :: logi_k = 25.0_r8 ! logistic function k - real(r8), parameter :: store_x0 = 1.0_r8 ! storage fraction inflection point + real(r8), parameter :: logi_k = 30.0_r8 ! logistic function k + real(r8), parameter :: store_x0 = 0.9_r8 ! storage fraction inflection point real(r8), parameter :: logi_min = 0.0_r8 ! minimum cn_scalar for logistic ! This is the storage fraction where downregulation starts if using ! a linear function - real(r8), parameter :: store_frac0 = 0.5_r8 + real(r8), parameter :: store_frac0 = 0.85_r8 real(r8), parameter :: c_max = 1.0_r8 real(r8), parameter :: c_min = 1.e-3_r8 diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 30b3ad71c2..3d5eb85b61 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -168,8 +168,8 @@ module PRTAllometricCNPMod - real(r8), parameter :: min_stf_growth = 0.9_r8 ! Plants are only allowed to increase in stature - ! if they have more than 90% of their stores full + real(r8), parameter :: min_stf_growth = 0.8_r8 ! Plants are only allowed to increase in stature + ! if they have more than 80% of their stores full ! ------------------------------------------------------------------------------------- @@ -1137,8 +1137,8 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, net_n_gain, net_p_gain, if( c_gain <= calloc_abs_error .or. & leaf_status.eq.leaves_off .or. & - (n_stf < min_stf_growth .and. net_n_gain < 0._r8) .or. & - (p_stf < min_stf_growth .and. net_p_gain < 0._r8) ) then + (n_stf < min_stf_growth ) .or. & !.and. net_n_gain < 0._r8) .or. & + (p_stf < min_stf_growth ) ) then !.and. net_p_gain < 0._r8) ) then return end if From 760e8705b7dc9170ea35343237fd1c78d10b071c Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Sat, 6 Nov 2021 10:00:10 -0400 Subject: [PATCH 070/852] First complete pass-through on having a dynamic root response to nutrient storage --- biogeochem/EDCohortDynamicsMod.F90 | 22 ++- biogeochem/EDPhysiologyMod.F90 | 5 +- biogeochem/FatesAllometryMod.F90 | 61 ++---- biogeochem/FatesSoilBGCFluxMod.F90 | 105 +--------- main/EDInitMod.F90 | 12 +- main/EDTypesMod.F90 | 9 + main/FatesInventoryInitMod.F90 | 5 +- parameter_files/fates_params_default.cdl | 13 +- parteh/PRTAllometricCNPMod.F90 | 239 ++++++++++++++++++++--- parteh/PRTAllometricCarbonMod.F90 | 20 +- parteh/PRTParametersMod.F90 | 5 +- parteh/PRTParamsFATESMod.F90 | 19 +- 12 files changed, 315 insertions(+), 200 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index b6714ee3e9..341cf3c836 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -90,6 +90,7 @@ module EDCohortDynamicsMod use PRTAllometricCNPMod, only : cnp_allom_prt_vartypes use PRTAllometricCNPMod, only : acnp_bc_in_id_pft, acnp_bc_in_id_ctrim use PRTAllometricCNPMod, only : acnp_bc_in_id_lstat, acnp_bc_inout_id_dbh + use PRTAllometricCNPMod, only : acnp_bc_inout_id_l2fr use PRTAllometricCNPMod, only : acnp_bc_inout_id_rmaint_def, acnp_bc_in_id_netdc use PRTAllometricCNPMod, only : acnp_bc_in_id_netdnh4, acnp_bc_in_id_netdno3, acnp_bc_in_id_netdp use PRTAllometricCNPMod, only : acnp_bc_out_id_cefflux, acnp_bc_out_id_nefflux @@ -236,6 +237,16 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & new_cohort%sapwmemory = sapwmemory new_cohort%structmemory = structmemory + ! Initialize the leaf to fineroot biomass ratio + ! for C-only, this will stay constant, for nutrient enabled + ! this will be dynamic. In both cases, new cohorts are + ! initialized with the minimum. This works in the nutrient + ! enabled case, because cohorts are also initialized with + ! full stores, which match with minimum fr biomass + + new_cohort%l2fr = prt_params%allom_l2fr_min(pft) + + ! This sets things like vcmax25top, that depend on the ! leaf age fractions (which are defined by PARTEH) call UpdateCohortBioPhysRates(new_cohort) @@ -393,7 +404,7 @@ subroutine InitPRTBoundaryConditions(new_cohort) call new_cohort%prt%RegisterBCIn(ac_bc_in_id_pft,bc_ival = new_cohort%pft) call new_cohort%prt%RegisterBCIn(ac_bc_in_id_ctrim,bc_rval = new_cohort%canopy_trim) call new_cohort%prt%RegisterBCIn(ac_bc_in_id_lstat,bc_ival = new_cohort%status_coh) - + case (prt_cnp_flex_allom_hyp) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_pft,bc_ival = new_cohort%pft) @@ -406,6 +417,7 @@ subroutine InitPRTBoundaryConditions(new_cohort) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_dbh,bc_rval = new_cohort%dbh) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_rmaint_def,bc_rval = new_cohort%resp_m_def) + call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_l2fr,bc_rval = new_cohort%l2fr) call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_cefflux, bc_rval = new_cohort%daily_c_efflux) call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_nefflux, bc_rval = new_cohort%daily_n_efflux) @@ -1173,7 +1185,10 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) ! Leaf biophysical rates (use leaf mass weighting) ! ----------------------------------------------------------------- call UpdateCohortBioPhysRates(currentCohort) - + + currentCohort%l2fr = (currentCohort%n*currentCohort%l2fr& + + nextc%n*nextc%l2fr)/newn + currentCohort%laimemory = (currentCohort%n*currentCohort%laimemory & + nextc%n*nextc%laimemory)/newn @@ -1788,7 +1803,8 @@ subroutine copy_cohort( currentCohort,copyc ) n%coage_by_pft_class = o%coage_by_pft_class ! This transfers the PRT objects over. call n%prt%CopyPRTVartypes(o%prt) - + n%l2fr = o%l2fr + ! Leaf biophysical rates n%vcmax25top = o%vcmax25top n%jmax25top = o%jmax25top diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index fe184dd343..c7e0515f39 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -482,7 +482,7 @@ subroutine trim_canopy( currentSite ) if ( int(prt_params%allom_fmode(ipft)) .eq. 1 ) then ! only query fine root biomass if using a fine root allometric model that takes leaf trim into account - call bfineroot(currentcohort%dbh,ipft,currentcohort%canopy_trim,tar_bfr) + call bfineroot(currentcohort%dbh,ipft,currentcohort%canopy_trim,currentcohort%l2fr,tar_bfr) bfr_per_bleaf = tar_bfr/tar_bl endif @@ -1625,13 +1625,14 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) temp_cohort%pft = ft temp_cohort%hite = EDPftvarcon_inst%hgt_min(ft) temp_cohort%coage = 0.0_r8 + temp_cohort%l2fr = prt_params%allom_l2fr_min(ft) stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(ft) call h2d_allom(temp_cohort%hite,ft,temp_cohort%dbh) ! Initialize live pools call bleaf(temp_cohort%dbh,ft,temp_cohort%canopy_trim,c_leaf) - call bfineroot(temp_cohort%dbh,ft,temp_cohort%canopy_trim,c_fnrt) + call bfineroot(temp_cohort%dbh,ft,temp_cohort%canopy_trim,temp_cohort%l2fr,c_fnrt) call bsap_allom(temp_cohort%dbh,ft,temp_cohort%canopy_trim,a_sapw, c_sapw) call bagw_allom(temp_cohort%dbh,ft,c_agw) call bbgw_allom(temp_cohort%dbh,ft,c_bgw) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index 8e27faae22..0012d1b735 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -156,7 +156,7 @@ module FatesAllometryMod ! ============================================================================ - subroutine CheckIntegratedAllometries(dbh,ipft,canopy_trim, & + subroutine CheckIntegratedAllometries(dbh,ipft,canopy_trim,l2fr, & bl,bfr,bsap,bstore,bdead, & grow_leaf, grow_fr, grow_sap, grow_store, grow_dead, & max_err, l_pass) @@ -172,6 +172,7 @@ subroutine CheckIntegratedAllometries(dbh,ipft,canopy_trim, & real(r8),intent(in) :: dbh ! diameter of plant [cm] integer,intent(in) :: ipft ! plant functional type index real(r8),intent(in) :: canopy_trim ! trimming function + real(r8),intent(in) :: l2fr ! leaf to fine-root biomass multiplier (fr/leaf) real(r8),intent(in) :: bl ! integrated leaf biomass [kgC] real(r8),intent(in) :: bfr ! integrated fine root biomass [kgC] real(r8),intent(in) :: bsap ! integrated sapwood biomass [kgC] @@ -215,7 +216,7 @@ subroutine CheckIntegratedAllometries(dbh,ipft,canopy_trim, & end if if (grow_fr) then - call bfineroot(dbh,ipft,canopy_trim,bfr_diag) + call bfineroot(dbh,ipft,canopy_trim,l2fr,bfr_diag) if( abs(bfr_diag-bfr) > max_err ) then if(verbose_logging) then write(fates_log(),*) 'disparity in integrated/diagnosed fineroot carbon' @@ -860,18 +861,22 @@ end subroutine bbgw_allom ! Fine root biomass allometry wrapper ! ============================================================================ - subroutine bfineroot(d,ipft,canopy_trim,bfr,dbfrdd) + subroutine bfineroot(d,ipft,canopy_trim,l2fr,bfr,dbfrdd) ! ------------------------------------------------------------------------- ! This subroutine calculates the actual target fineroot biomass ! based on functions that may or may not have prognostic properties. ! ------------------------------------------------------------------------- - real(r8),intent(in) :: d ! plant diameter [cm] - integer(i4),intent(in) :: ipft ! PFT index - real(r8),intent(in) :: canopy_trim ! trimming function - real(r8),intent(out) :: bfr ! fine root biomass [kgC] - real(r8),intent(out),optional :: dbfrdd ! change leaf bio per diameter [kgC/cm] + real(r8),intent(in) :: d ! plant diameter [cm] + integer(i4),intent(in) :: ipft ! PFT index + real(r8),intent(in) :: canopy_trim ! trimming function + real(r8),intent(in) :: l2fr ! leaf to fineroot scaler + ! this is either a PFT parameter + ! constant (when no nutrient model) + ! or dynamic (with nutrient model) + real(r8),intent(out) :: bfr ! fine root biomass [kgC] + real(r8),intent(out),optional :: dbfrdd ! change leaf bio per diameter [kgC/cm] real(r8) :: blmax ! maximum leaf biomss per allometry real(r8) :: dblmaxdd @@ -883,18 +888,20 @@ subroutine bfineroot(d,ipft,canopy_trim,bfr,dbfrdd) case(1) ! "constant proportionality with TRIMMED target bleaf" call blmax_allom(d,ipft,blmax,dblmaxdd) - call bfrmax_const(d,blmax,dblmaxdd,ipft,bfrmax,dbfrmaxdd) - bfr = bfrmax * canopy_trim + + bfr = blmax*l2fr*canopy_trim + if(present(dbfrdd))then - dbfrdd = dbfrmaxdd * canopy_trim + dbfrdd = dblmaxdd*l2fr * canopy_trim + end if case(2) ! "constant proportionality with UNTRIMMED target bleaf" call blmax_allom(d,ipft,blmax,dblmaxdd) - call bfrmax_const(d,blmax,dblmaxdd,ipft,bfrmax,dbfrmaxdd) - bfr = bfrmax + + bfr = blmax*l2fr if(present(dbfrdd))then - dbfrdd = dbfrmaxdd + dbfrdd = dbfrmaxdd*l2fr end if case DEFAULT @@ -1005,32 +1012,6 @@ subroutine bdead_allom(bagw,bbgw,bsap,ipft,bdead,dbagwdd,dbbgwdd,dbsapdd,dbdeadd return end subroutine bdead_allom - ! ============================================================================ - ! Specific bfrmax relationships - ! ============================================================================ - - subroutine bfrmax_const(d,blmax,dblmaxdd,ipft,bfrmax,dbfrmaxdd) - - - real(r8),intent(in) :: d ! plant diameter [cm] - real(r8),intent(in) :: blmax ! max leaf biomass [kgC] - real(r8),intent(in) :: dblmaxdd ! change in blmax per diam [kgC/cm] - integer(i4),intent(in) :: ipft ! PFT index - real(r8),intent(out) :: bfrmax ! max fine-root root biomass [kgC] - real(r8),intent(out),optional :: dbfrmaxdd ! change frmax bio per diam [kgC/cm] - - associate( l2fr => prt_params%allom_l2fr(ipft) ) - - bfrmax = blmax*l2fr - - ! dbfr/dd = dbfrmax/dblmax * dblmax/dd - if(present(dbfrmaxdd))then - dbfrmaxdd = dblmaxdd*l2fr - end if - - end associate - return - end subroutine bfrmax_const ! ============================================================================ ! Specific bbgw relationships diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index 9815af8096..b42b60a6ec 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -38,7 +38,6 @@ module FatesSoilBGCFluxMod use FatesAllometryMod , only : bagw_allom use FatesAllometryMod , only : bsap_allom use FatesAllometryMod , only : bleaf - use FatesAllometryMod , only : bfineroot use FatesAllometryMod , only : bdead_allom use FatesAllometryMod , only : bstore_allom use FatesAllometryMod , only : bbgw_allom @@ -724,8 +723,8 @@ subroutine PrepNutrientAquisitionBCs(csite, bc_in, bc_out) icomp = pft end if - bc_out%cn_scalar(icomp) = bc_out%cn_scalar(icomp) + & - ECACScalar(ccohort, nitrogen_element) + bc_out%cn_scalar(icomp) = 1.0_r8 + ccohort => ccohort%shorter end do @@ -763,8 +762,7 @@ subroutine PrepNutrientAquisitionBCs(csite, bc_in, bc_out) icomp = pft end if - bc_out%cp_scalar(icomp) = bc_out%cp_scalar(icomp) + & - ECACScalar(ccohort, phosphorus_element) + bc_out%cp_scalar(icomp) = 1.0_r8 ccohort => ccohort%shorter end do @@ -1146,104 +1144,7 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) return end subroutine FluxIntoLitterPools - ! ===================================================================================== - - function ECACScalar(ccohort, element_id) result(c_scalar) - - ! ----------------------------------------------------------------------------------- - ! This function returns the cn_scalar or cp_scalar term - ! described in: - ! Zhu, Q et al. Representing Nitrogen, Phosphorus and Carbon - ! interactions in the E3SM land model: Development and Global benchmarking. - ! Journal of Advances in Modeling Earth Systems, 11, 2238-2258, 2019. - ! https://doi.org/10.1029/2018MS001571 - ! - ! In the manuscript c_scalar is described as: "f(CN) and f(CP) account for the - ! regulation of plant nutritional level on nutrient carrier enzyme activity" - ! Also, see equations 4 and 5. - ! ----------------------------------------------------------------------------------- - - - ! Arguments (in) - type(ed_cohort_type), pointer :: ccohort ! current cohort pointer - integer :: element_id ! element id consistent with parteh/PRTGenericMod.F90 - - ! Arguments (out) - real(r8) :: c_scalar - - ! Locals - real(r8) :: store_frac ! Current nutrient storage relative to max - real(r8) :: store_max ! Maximum nutrient storable by plant - real(r8) :: store_c ! Current storage carbon - real(r8) :: store_c_max ! Current maximum storage carbon - integer :: icode ! real variable checking code - - integer, parameter :: downreg_linear = 1 - integer, parameter :: downreg_logi = 2 - integer, parameter :: downreg_CN_logi = 3 - - integer, parameter :: downreg_type = downreg_linear - - - real(r8), parameter :: logi_k = 30.0_r8 ! logistic function k - real(r8), parameter :: store_x0 = 0.9_r8 ! storage fraction inflection point - real(r8), parameter :: logi_min = 0.0_r8 ! minimum cn_scalar for logistic - - ! This is the storage fraction where downregulation starts if using - ! a linear function - real(r8), parameter :: store_frac0 = 0.85_r8 - - real(r8), parameter :: c_max = 1.0_r8 - real(r8), parameter :: c_min = 1.e-3_r8 - - - store_max = ccohort%prt%GetNutrientTarget(element_id,store_organ,stoich_max) - store_frac = min(2.0_r8,ccohort%prt%GetState(store_organ, element_id)/store_max) - - if(downreg_type == downreg_linear) then - - c_scalar = min(c_max,max(c_min,1.0 - (store_frac - store_frac0)/(1.0_r8-store_frac0))) - - elseif(downreg_type == downreg_logi) then - - ! In this method, we define the c_scalar term - ! with a logistic function that goes to 1 (full need) - ! as the plant's nutrien storage hits a low threshold - ! and goes to 0, no demand, as the plant's nutrient - ! storage approaches it's maximum holding capacity - - - - c_scalar = max(c_min,min(c_max,logi_min + (1.0_r8-logi_min)/(1.0_r8 + exp(logi_k*(store_frac-store_x0))))) - - call check_var_real(c_scalar,'c_scalar',icode) - if (icode .ne. 0) then - write(fates_log(),*) 'c_scalar is invalid, element: ',element_id - write(fates_log(),*) 'ending' - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - - else - - store_c = ccohort%prt%GetState(store_organ, carbon12_element) - call bstore_allom(ccohort%dbh,ccohort%pft,ccohort%canopy_trim,store_c_max) - - ! Fraction of N per fraction of C - ! If this is greater than 1, then we have more N in storage than - ! we have C, so we downregulate. If this is less than 1, then - ! we have less N in storage than we have C, so up-regulate - - store_frac = store_frac / (store_c/store_c_max) - - c_scalar = max(c_min,min(c_max,logi_min + (1.0_r8-logi_min)/(1.0_r8 + exp(logi_k*(store_frac-store_x0))))) - - - - - end if - - end function ECACScalar end module FatesSoilBGCFluxMod diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 9c3059312d..875fe4c730 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -529,11 +529,11 @@ subroutine init_cohorts( site_in, patch_in, bc_in) allocate(temp_cohort) ! temporary cohort - temp_cohort%pft = pft - temp_cohort%n = EDPftvarcon_inst%initd(pft) * patch_in%area - temp_cohort%hite = EDPftvarcon_inst%hgt_min(pft) + temp_cohort%pft = pft + temp_cohort%n = EDPftvarcon_inst%initd(pft) * patch_in%area + temp_cohort%hite = EDPftvarcon_inst%hgt_min(pft) + temp_cohort%l2fr = prt_params%allom_l2fr_min(pft) - ! Calculate the plant diameter from height call h2d_allom(temp_cohort%hite,pft,temp_cohort%dbh) @@ -551,7 +551,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) ! Calculate fine root biomass from allometry ! (calculates a maximum and then trimming value) - call bfineroot(temp_cohort%dbh,pft,temp_cohort%canopy_trim,c_fnrt) + call bfineroot(temp_cohort%dbh,pft,temp_cohort%canopy_trim,temp_cohort%l2fr,c_fnrt) ! Calculate sapwood biomass call bsap_allom(temp_cohort%dbh,pft,temp_cohort%canopy_trim,a_sapw,c_sapw) @@ -665,7 +665,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) call create_cohort(site_in, patch_in, pft, temp_cohort%n, temp_cohort%hite, & temp_cohort%coage, temp_cohort%dbh, prt_obj, temp_cohort%laimemory, & temp_cohort%sapwmemory, temp_cohort%structmemory, cstatus, rstatus, & - temp_cohort%canopy_trim, 1, site_in%spread, bc_in) + temp_cohort%canopy_trim, 1, site_in%spread, bc_in) deallocate(temp_cohort) ! get rid of temporary cohort diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index ad1c6668c9..e8fa27ee8e 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -209,6 +209,14 @@ module EDTypesMod class(prt_vartypes), pointer :: prt + real(r8) :: l2fr ! leaf to fineroot biomass ratio (this is constant + ! in carbon only simulations, and is set by the + ! allom_l2fr_min parameter. In nutrient + ! enabled simulations, this is dynamic, will + ! vary between allom_l2fr_min and allom_l2fr_max + ! parameters, with a tendency driven by + ! nutrient storage) + ! VEGETATION STRUCTURE integer :: pft ! pft number real(r8) :: n ! number of individuals in cohort per 'area' (10000m2 default) @@ -1028,6 +1036,7 @@ subroutine dump_cohort(ccohort) write(fates_log(),*) 'co%laimemory = ', ccohort%laimemory write(fates_log(),*) 'co%sapwmemory = ', ccohort%sapwmemory write(fates_log(),*) 'co%structmemory = ', ccohort%structmemory + write(fates_log(),*) 'co%l2fr = ', ccohort%l2fr write(fates_log(),*) 'leaf carbon = ', ccohort%prt%GetState(leaf_organ,all_carbon_elements) write(fates_log(),*) 'fineroot carbon = ', ccohort%prt%GetState(fnrt_organ,all_carbon_elements) diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index efdebb8708..4d3dc256e7 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -1028,7 +1028,8 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & call bleaf(temp_cohort%dbh,temp_cohort%pft,temp_cohort%canopy_trim,c_leaf) ! Calculate fine root biomass - call bfineroot(temp_cohort%dbh,temp_cohort%pft,temp_cohort%canopy_trim,c_fnrt) + temp_cohort%l2fr = prt_params%allom_l2fr_min(temp_cohort%pft) + call bfineroot(temp_cohort%dbh,temp_cohort%pft,temp_cohort%canopy_trim,temp_cohort%l2fr,c_fnrt) ! Calculate sapwood biomass call bsap_allom(temp_cohort%dbh,temp_cohort%pft,temp_cohort%canopy_trim, a_sapw, c_sapw) @@ -1042,7 +1043,7 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & temp_cohort%structmemory = 0._r8 cstatus = leaves_on - stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(temp_cohort%pft) + stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(temp_cohort%pft) if( prt_params%season_decid(temp_cohort%pft) == itrue .and. & any(csite%cstatus == [phen_cstat_nevercold,phen_cstat_iscold])) then diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 86d46710da..3e30fef4b4 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -100,9 +100,12 @@ variables: fates_allom_hmode:units = "index" ; fates_allom_hmode:long_name = "height allometry function index." ; fates_allom_hmode:possible_values = "1: OBrien 1995; 2: Poorter 2006; 3: 2 parameter power law; 4: Chave 2014; 5: Martinez-Cano 2019." ; - double fates_allom_l2fr(fates_pft) ; - fates_allom_l2fr:units = "gC/gC" ; - fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; + double fates_allom_l2fr_min(fates_pft) ; + fates_allom_l2fr_min:units = "gC/gC" ; + fates_allom_l2fr_min:long_name = "Allocation parameter: minimum fine root C per leaf C (definitive l2fr for Carbon-only)" ; + double fates_allom_l2fr_max(fates_pft) ; + fates_allom_l2fr_max:units = "gC/gC" ; + fates_allom_l2fr_max:long_name = "Allocation parameter: maximum fine root C per leaf C (NOT USED IN Carbon-only, only CNP)" ; double fates_allom_la_per_sa_int(fates_pft) ; fates_allom_la_per_sa_int:units = "m2/cm2" ; fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; @@ -781,7 +784,9 @@ data: fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_allom_l2fr_min = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_l2fr_max = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 ; diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 3d5eb85b61..109cb4cf0d 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -124,7 +124,7 @@ module PRTAllometricCNPMod integer, parameter :: num_intgr_vars = 7 - + ! ------------------------------------------------------------------------------------- ! Input/Output Boundary Indices (These are public, and therefore ! each boundary condition across all modules must @@ -137,7 +137,9 @@ module PRTAllometricCNPMod integer, public, parameter :: acnp_bc_inout_id_dbh = 1 ! Plant DBH integer, public, parameter :: acnp_bc_inout_id_rmaint_def = 2 ! Index for any accumulated ! maintenance respiration deficit - integer, public, parameter :: num_bc_inout = 2 + integer, public, parameter :: acnp_bc_inout_id_l2fr = 3 ! leaf 2 fineroot scalar, this + ! is dynamic with CNP + integer, public, parameter :: num_bc_inout = 3 ! ------------------------------------------------------------------------------------- ! Input only Boundary Indices (These are public) @@ -167,6 +169,12 @@ module PRTAllometricCNPMod integer, parameter :: num_bc_out = 5 ! Total number of + ! Indices for parameters passed to the integrator + integer,private, parameter :: intgr_parm_ctrim = 1 + integer,private, parameter :: intgr_parm_pft = 2 + integer,private, parameter :: intgr_parm_l2fr = 3 + integer,private, parameter :: num_intgr_parm = 3 + real(r8), parameter :: min_stf_growth = 0.8_r8 ! Plants are only allowed to increase in stature ! if they have more than 80% of their stores full @@ -192,8 +200,14 @@ module PRTAllometricCNPMod ! in the same priority group as fineroots. logical, parameter :: reproduce_conly = .false. - + ! Definitions for the regulation functions. These typically translate + ! a storage fraction into a scalar used to regulate resources somehow + + integer, parameter :: regulate_linear = 1 + integer, parameter :: regulate_logi = 2 + integer, parameter :: regulate_CN_logi = 3 + ! Array of pointers are difficult in F90 ! This structure is a necessary intermediate type :: parray_type @@ -217,10 +231,12 @@ module PRTAllometricCNPMod ! Extended functions specific to Allometric CNP procedure :: CNPPrioritizedReplacement procedure :: CNPStatureGrowth + procedure :: CNPAdjustFRootTargets procedure :: CNPAllocateRemainder procedure :: GetDeficit procedure :: GrowEquivC procedure :: NAndPToMatchC + procedure :: StorageRegulator end type cnp_allom_prt_vartypes @@ -330,6 +346,7 @@ subroutine DailyPRTAllometricCNP(this) ! Pointers to in-out bcs real(r8),pointer :: dbh ! Diameter at breast height [cm] real(r8),pointer :: maint_r_def ! Current maintenance respiration deficit [kgC] + real(r8),pointer :: l2fr ! Leaf to fineroot ratio of target biomass ! Input only bcs integer :: ipft ! Plant Functional Type index @@ -415,11 +432,10 @@ subroutine DailyPRTAllometricCNP(this) n_need => this%bc_out(acnp_bc_out_id_nneed)%rval; n_need = fates_unset_r8 p_need => this%bc_out(acnp_bc_out_id_pneed)%rval; p_need = fates_unset_r8 - ! In/out boundary conditions maint_r_def => this%bc_inout(acnp_bc_inout_id_rmaint_def)%rval; maint_r_def0 = maint_r_def dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval; dbh0 = dbh - + l2fr => this%bc_out(acnp_bc_inout_id_l2fr)%rval ! If more than 1 leaf age bin is present, this @@ -447,7 +463,7 @@ subroutine DailyPRTAllometricCNP(this) call bdead_allom(agw_c_target,bgw_c_target, target_c(sapw_id), ipft, target_c(struct_id), & agw_dcdd_target, bgw_dcdd_target, target_dcdd(sapw_id), target_dcdd(struct_id)) call bleaf(dbh,ipft,canopy_trim, target_c(leaf_id), target_dcdd(leaf_id)) - call bfineroot(dbh,ipft,canopy_trim, target_c(fnrt_id), target_dcdd(fnrt_id)) + call bfineroot(dbh,ipft,canopy_trim, l2fr, target_c(fnrt_id), target_dcdd(fnrt_id)) call bstore_allom(dbh,ipft,canopy_trim, target_c(store_id), target_dcdd(store_id)) target_c(repro_id) = 0._r8 target_dcdd(repro_id) = 0._r8 @@ -488,9 +504,22 @@ subroutine DailyPRTAllometricCNP(this) p_gain = p_gain + sum(this%variables(i_var)%val(:)) net_p_gain = - sum(this%variables(i_var)%val(:)) this%variables(i_var)%val(:) = 0._r8 + + + ! =================================================================================== + ! Step 1: Evaluate nutrient storage in the plant. Depending on how low + ! these stores are, we will move proportionally more or less of the daily carbon + ! gain to increase the target fine-root biomass, fill up to target + ! and then attempt to get them up to stoichiometry targets. + ! =================================================================================== + + ! This routine actually just updates the l2fr variable + call this%CNPAdjustFRootTargets() + + call bfineroot(dbh,ipft,canopy_trim, l2fr, target_c(fnrt_id), target_dcdd(fnrt_id)) ! =================================================================================== - ! Step 1. Prioritized allocation to replace tissues from turnover, and/or pay + ! Step 2. Prioritized allocation to replace tissues from turnover, and/or pay ! any un-paid maintenance respiration from storage. ! =================================================================================== @@ -513,7 +542,7 @@ subroutine DailyPRTAllometricCNP(this) end if ! =================================================================================== - ! Step 2. Grow out the stature of the plant by allocating to tissues beyond + ! Step 3. Grow out the stature of the plant by allocating to tissues beyond ! current targets. ! Attempts have been made to get all pools and species closest to allometric ! targets based on prioritized relative demand and allometry functions. @@ -521,7 +550,7 @@ subroutine DailyPRTAllometricCNP(this) net_n_gain = net_n_gain + n_gain net_p_gain = net_p_gain + p_gain - + call this%CNPStatureGrowth(c_gain, n_gain, p_gain, & net_n_gain, net_p_gain, & state_c, state_n, state_p, target_c, target_dcdd, cnp_limiter) @@ -629,7 +658,61 @@ subroutine DailyPRTAllometricCNP(this) end subroutine DailyPRTAllometricCNP ! ===================================================================================== - + subroutine CNPAdjustFRootTargets(this) + + class(cnp_allom_prt_vartypes) :: this + + real(r8), pointer :: l2fr ! leaf to fineroot target biomass scaler + integer :: ipft ! PFT index + + real(r8) :: n_regulator ! Nitrogen storage regulation function scaler + real(r8) :: p_regulator ! Phosphorus storage regulation function scaler + real(r8) :: np_regulator ! Combined NP storage regulation function scaler + + + ipft = this%bc_in(acnp_bc_in_id_pft)%ival + l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval + + associate( l2fr_min => prt_params%allom_l2fr_min(ipft), & + l2fr_max => prt_params%allom_l2fr_max(ipft)) + + n_regulator = this%StorageRegulator(nitrogen_element, regulate_logi) + p_regulator = this%StorageRegulator(phosphorus_element, regulate_logi) + + ! We take the maximum here, because the maximum is reflective of the + ! element with the lowest storage, which is the limiting element + + np_regulator = max(n_regulator,p_regulator) + + ! Update the leaf-to-fineroot ratio used + ! to set fine-root biomass allometry + l2fr = l2fr_min + np_regulator*(l2fr_max-l2fr_min) + + ! Find the updated target fineroot biomass + ! call bfineroot(dbh,ipft,canopy_trim, l2fr, target_fnrt) + + ! Consider removing biomass immediately too... + ! we could send it to the turnover flux + ! c_to_froot = max(0._r8,target_fnrt - state_c(fnrt_id)%ptr) + + ! Update the actual carbon + ! state_c(fnrt_id)%ptr = state_c(fnrt_id)%ptr + c_to_froot + + ! Push nitrogen into fineroots to get to stoichiometry + ! call ProportionalNutrAllocation(state_n, deficit_n, & + ! n_gain, nitrogen_element, fnrt_id) + + ! Push phos into fineroots to get to stoichiometry + ! call ProportionalNutrAllocation(state_p, deficit_p, & + ! p_gain, phosphorus_element, fnrt_id) + + end associate + + return + end subroutine CNPAdjustFRootTargets + + ! ===================================================================================== + subroutine CNPPrioritizedReplacement(this, & maint_r_deficit, c_gain, n_gain, p_gain, & state_c, state_n, state_p, target_c) @@ -1033,6 +1116,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, net_n_gain, net_p_gain, integer :: ipft real(r8) :: canopy_trim real(r8) :: leaf_status + real(r8) :: l2fr integer :: i, ii ! organ index loops (masked and unmasked) integer :: istep ! outer step iteration loop @@ -1100,7 +1184,8 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, net_n_gain, net_p_gain, integer , parameter :: max_substeps = 300 ! Maximum allowable iterations real(r8), parameter :: max_trunc_error = 1.0_r8 ! Maximum allowable truncation error integer, parameter :: ODESolve = 2 ! 1=RKF45, 2=Euler - real(r8) :: intgr_params(num_bc_in) + + real(r8) :: intgr_params(num_intgr_parm) integer, parameter :: grow_lim_type = 3 ! Dev flag for growth limitation algorithm ! 1 = tries to calculate equivalent carbon @@ -1117,7 +1202,9 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, net_n_gain, net_p_gain, dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval - + l2fr = this%bc_inout(acnp_bc_inout_id_l2fr)%rval ! This variable is not updated in this + ! routine, and is therefore not a pointer + cnp_limiter = 0 ! If any of these resources is essentially tapped out, @@ -1143,10 +1230,10 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, net_n_gain, net_p_gain, end if - intgr_params(:) = fates_unset_r8 - intgr_params(acnp_bc_in_id_ctrim) = this%bc_in(acnp_bc_in_id_ctrim)%rval - intgr_params(acnp_bc_in_id_pft) = real(this%bc_in(acnp_bc_in_id_pft)%ival) - + intgr_params(:) = fates_unset_r8 + intgr_params(intgr_parm_ctrim) = this%bc_in(acnp_bc_in_id_ctrim)%rval + intgr_params(intgr_parm_pft) = real(this%bc_in(acnp_bc_in_id_pft)%ival) + intgr_params(intgr_parm_l2fr) = this%bc_in(acnp_bc_inout_id_l2fr)%rval state_mask(:) = .false. mask_organs(:) = fates_unset_int @@ -1321,7 +1408,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, net_n_gain, net_p_gain, leafc_tp1 = leafc_tp1 + this%variables(i_var)%val(i) end do - call CheckIntegratedAllometries(state_array_out(dbh_id),ipft,canopy_trim, & + call CheckIntegratedAllometries(state_array_out(dbh_id),ipft,canopy_trim, l2fr, & leafc_tp1, state_array_out(fnrt_id), state_array_out(sapw_id), & state_array_out(store_id), state_array_out(struct_id), & state_mask(leaf_id), state_mask(fnrt_id), state_mask(sapw_id), & @@ -1412,7 +1499,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, net_n_gain, net_p_gain, structc_tp1 = state_array_out(struct_id) call bleaf(dbh_tp1,ipft,canopy_trim,leaf_c_target_tp1) - call bfineroot(dbh_tp1,ipft,canopy_trim,fnrt_c_target_tp1) + call bfineroot(dbh_tp1,ipft,canopy_trim,l2fr,fnrt_c_target_tp1) call bsap_allom(dbh_tp1,ipft,canopy_trim,sapw_area,sapw_c_target_tp1) call bagw_allom(dbh_tp1,ipft,agw_c_target_tp1) call bbgw_allom(dbh_tp1,ipft,bgw_c_target_tp1) @@ -1668,20 +1755,19 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe real(r8) :: target_c real(r8),pointer :: dbh real(r8) :: canopy_trim + real(r8) :: l2fr integer :: ipft integer :: i_cvar real(r8) :: sapw_area real(r8) :: leaf_c_target,fnrt_c_target real(r8) :: sapw_c_target,agw_c_target real(r8) :: bgw_c_target,struct_c_target - - - dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival i_cvar = prt_global%sp_organ_map(organ_id,carbon12_element) + l2fr = this%bc_inout(acnp_bc_inout_id_l2fr)%rval ! Storage of nutrients are assumed to have different compartments than ! for carbon, and thus their targets are not associated with a tissue @@ -1691,7 +1777,7 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe if(organ_id == store_organ) then call bleaf(dbh,ipft,canopy_trim,leaf_c_target) - call bfineroot(dbh,ipft,canopy_trim,fnrt_c_target) + call bfineroot(dbh,ipft,canopy_trim,l2fr,fnrt_c_target) call bsap_allom(dbh,ipft,canopy_trim,sapw_area,sapw_c_target) call bagw_allom(dbh,ipft,agw_c_target) call bbgw_allom(dbh,ipft,bgw_c_target) @@ -2048,6 +2134,7 @@ function AllomCNPGrowthDeriv(l_state_array,l_state_mask,cbalance,intgr_params) r ! locals integer :: ipft ! PFT index real(r8) :: canopy_trim ! Canopy trimming function (boundary condition [0-1] + real(r8) :: l2fr ! leaf to fineroot biomass multiplier real(r8) :: leaf_c_target ! target leaf biomass, dummy var (kgC) real(r8) :: fnrt_c_target ! target fine-root biomass, dummy var (kgC) real(r8) :: sapw_c_target ! target sapwood biomass, dummy var (kgC) @@ -2083,12 +2170,12 @@ function AllomCNPGrowthDeriv(l_state_array,l_state_mask,cbalance,intgr_params) r mask_struct => l_state_mask(struct_id), & mask_repro => l_state_mask(repro_id) ) - - canopy_trim = intgr_params(acnp_bc_in_id_ctrim) - ipft = int(intgr_params(acnp_bc_in_id_pft)) + canopy_trim = intgr_params(intgr_parm_ctrim) + ipft = int(intgr_params(intgr_parm_pft)) + l2fr = intgr_params(intgr_parm_l2fr) call bleaf(dbh,ipft,canopy_trim,leaf_c_target,leaf_dcdd_target) - call bfineroot(dbh,ipft,canopy_trim,fnrt_c_target,fnrt_dcdd_target) + call bfineroot(dbh,ipft,canopy_trim,l2fr,fnrt_c_target,fnrt_dcdd_target) call bsap_allom(dbh,ipft,canopy_trim,sapw_area,sapw_c_target,sapw_dcdd_target) call bagw_allom(dbh,ipft,agw_c_target,agw_dcdd_target) call bbgw_allom(dbh,ipft,bgw_c_target,bgw_dcdd_target) @@ -2255,7 +2342,105 @@ subroutine TargetAllometryCheck(bleaf,bfroot,bsap,bstore,bdead, & end subroutine TargetAllometryCheck - + ! ===================================================================================== + function StorageRegulator(this,element_id,regulate_type) result(c_scalar) + + ! ----------------------------------------------------------------------------------- + ! This function returns the cn_scalar or cp_scalar term + ! described in: + ! Zhu, Q et al. Representing Nitrogen, Phosphorus and Carbon + ! interactions in the E3SM land model: Development and Global benchmarking. + ! Journal of Advances in Modeling Earth Systems, 11, 2238-2258, 2019. + ! https://doi.org/10.1029/2018MS001571 + ! + ! In the manuscript c_scalar is described as: "f(CN) and f(CP) account for the + ! regulation of plant nutritional level on nutrient carrier enzyme activity" + ! Also, see equations 4 and 5. + ! ----------------------------------------------------------------------------------- + + + ! Arguments (in) + class(cnp_allom_prt_vartypes) :: this + integer,intent(in) :: element_id ! element id consistent with parteh/PRTGenericMod.F90 + integer,intent(in) :: regulate_type + + + ! Arguments (out) + real(r8) :: c_scalar + + ! Locals + real(r8) :: store_frac ! Current nutrient storage relative to max + real(r8) :: store_max ! Maximum nutrient storable by plant + real(r8) :: store_c ! Current storage carbon + real(r8) :: store_c_max ! Current maximum storage carbon + integer :: icode ! real variable checking code + + real(r8), parameter :: logi_k = 30.0_r8 ! logistic function k + real(r8), parameter :: store_x0 = 0.7_r8 ! storage fraction inflection point + real(r8), parameter :: logi_min = 0.0_r8 ! minimum cn_scalar for logistic + + ! This is the storage fraction where downregulation starts if using + ! a linear function + real(r8), parameter :: store_frac0 = 0.85_r8 + + real(r8), parameter :: c_max = 1.0_r8 ! Maximum allowable result of the function + real(r8), parameter :: c_min = 0.0_r8 ! Minimum allowable result of the function + + associate(dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval, & + canopy_trim => this%bc_in(acnp_bc_in_id_ctrim)%rval, & + ipft => this%bc_in(acnp_bc_in_id_pft)%ival) + + store_max = this%GetNutrientTarget(element_id,store_organ,stoich_max) + + ! Storage fractions could more than the target, depending on the + ! hypothesis and functions involved, but should typically be 0-1 + ! The cap of 2 is for numerics and preventing weird math + store_frac = min(2.0_r8,this%GetState(store_organ, element_id)/store_max) + + if(regulate_type == regulate_linear) then + + c_scalar = min(c_max,max(c_min,1.0 - (store_frac - store_frac0)/(1.0_r8-store_frac0))) + + elseif(regulate_type == regulate_logi) then + + ! In this method, we define the c_scalar term + ! with a logistic function that goes to 1 (full need) + ! as the plant's nutrien storage hits a low threshold + ! and goes to 0, no demand, as the plant's nutrient + ! storage approaches it's maximum holding capacity + + c_scalar = max(c_min,min(c_max,logi_min + (1.0_r8-logi_min)/(1.0_r8 + exp(logi_k*(store_frac-store_x0))))) + + !call check_var_real(c_scalar,'c_scalar',icode) + !if (icode .ne. 0) then + ! write(fates_log(),*) 'c_scalar is invalid, element: ',element_id + ! write(fates_log(),*) 'ending' + ! call endrun(msg=errMsg(sourcefile, __LINE__)) + !endif + + else + + store_c = this%GetState(store_organ, carbon12_element) + call bstore_allom(dbh,ipft,canopy_trim,store_c_max) + + ! Fraction of N per fraction of C + ! If this is greater than 1, then we have more N in storage than + ! we have C, so we downregulate. If this is less than 1, then + ! we have less N in storage than we have C, so up-regulate + + store_frac = store_frac / (store_c/store_c_max) + + c_scalar = max(c_min,min(c_max,logi_min + (1.0_r8-logi_min)/(1.0_r8 + exp(logi_k*(store_frac-store_x0))))) + + end if + + end associate + + + end function StorageRegulator + + + end module PRTAllometricCNPMod diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 5bdf624502..bb05e1c365 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -381,14 +381,17 @@ subroutine DailyPRTAllometricCarbon(this) ! are pressed into an array that is also ! passed to the integrators + + ipft = this%bc_in(ac_bc_in_id_pft)%ival + associate( & leaf_c => this%variables(leaf_c_id)%val, & fnrt_c => this%variables(fnrt_c_id)%val(icd), & sapw_c => this%variables(sapw_c_id)%val(icd), & store_c => this%variables(store_c_id)%val(icd), & repro_c => this%variables(repro_c_id)%val(icd), & - struct_c => this%variables(struct_c_id)%val(icd)) - + struct_c => this%variables(struct_c_id)%val(icd), & + l2fr => prt_params%allom_l2fr_min(ipft) ) ! ----------------------------------------------------------------------------------- ! 0. @@ -400,9 +403,9 @@ subroutine DailyPRTAllometricCarbon(this) carbon_balance => this%bc_inout(ac_bc_inout_id_netdc)%rval canopy_trim = this%bc_in(ac_bc_in_id_ctrim)%rval - ipft = this%bc_in(ac_bc_in_id_pft)%ival + leaf_status = this%bc_in(ac_bc_in_id_lstat)%ival - + intgr_params(:) = un_initialized intgr_params(ac_bc_in_id_ctrim) = this%bc_in(ac_bc_in_id_ctrim)%rval intgr_params(ac_bc_in_id_pft) = real(this%bc_in(ac_bc_in_id_pft)%ival) @@ -458,7 +461,7 @@ subroutine DailyPRTAllometricCarbon(this) end if ! Target fine-root biomass and deriv. according to allometry and trimming [kgC, kgC/cm] - call bfineroot(dbh,ipft,canopy_trim,target_fnrt_c) + call bfineroot(dbh,ipft,canopy_trim,l2fr,target_fnrt_c) ! Target storage carbon [kgC,kgC/cm] call bstore_allom(dbh,ipft,canopy_trim,target_store_c) @@ -731,7 +734,7 @@ subroutine DailyPRTAllometricCarbon(this) ! we halve the step-size, and then retry. If that step was fine, then ! we remember the current step size as a good next guess. - call CheckIntegratedAllometries(c_pool_out(dbh_id),ipft,canopy_trim, & + call CheckIntegratedAllometries(c_pool_out(dbh_id),ipft,canopy_trim,l2fr, & c_pool_out(leaf_c_id), c_pool_out(fnrt_c_id), c_pool_out(sapw_c_id), & c_pool_out(store_c_id), c_pool_out(struct_c_id), & c_mask(leaf_c_id), c_mask(fnrt_c_id), c_mask(sapw_c_id), & @@ -891,6 +894,7 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) ! locals integer :: ipft ! PFT index real(r8) :: canopy_trim ! Canopy trimming function (boundary condition [0-1] + real(r8) :: l2fr ! leaf to fine root biomass multiplier real(r8) :: ct_leaf ! target leaf biomass, dummy var (kgC) real(r8) :: ct_fnrt ! target fine-root biomass, dummy var (kgC) real(r8) :: ct_sap ! target sapwood biomass, dummy var (kgC) @@ -927,10 +931,10 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) canopy_trim = intgr_params(ac_bc_in_id_ctrim) ipft = int(intgr_params(ac_bc_in_id_pft)) - + l2fr = prt_params%allom_l2fr_min(ipft) call bleaf(dbh,ipft,canopy_trim,ct_leaf,ct_dleafdd) - call bfineroot(dbh,ipft,canopy_trim,ct_fnrt,ct_dfnrtdd) + call bfineroot(dbh,ipft,canopy_trim,l2fr,ct_fnrt,ct_dfnrtdd) call bsap_allom(dbh,ipft,canopy_trim,sapw_area,ct_sap,ct_dsapdd) call bagw_allom(dbh,ipft,ct_agw,ct_dagwdd) diff --git a/parteh/PRTParametersMod.F90 b/parteh/PRTParametersMod.F90 index 6e2c17ac66..1200cb17a6 100644 --- a/parteh/PRTParametersMod.F90 +++ b/parteh/PRTParametersMod.F90 @@ -118,7 +118,10 @@ module PRTParametersMod ! (sapwood area / leaf area) [cm2/m2] real(r8), allocatable :: allom_la_per_sa_slp(:) ! Leaf area to sap area conversion, slope ! (sapwood area / leaf area / diameter) [cm2/m2/cm] - real(r8), allocatable :: allom_l2fr(:) ! Fine root biomass per leaf biomass ratio [kgC/kgC] + real(r8), allocatable :: allom_l2fr_min(:) ! Minimum fine root biomass per leaf biomass ratio [kgC/kgC] + ! FOR C-ONLY, THIS IS THE ONLY AND STATIC L2FR + real(r8), allocatable :: allom_l2fr_max(:) ! Maximum fine root biomass per leaf biomass ratio [kgC/kgC] + ! for nutrient enabled runs real(r8), allocatable :: allom_agb_frac(:) ! Fraction of stem above ground [-] real(r8), allocatable :: allom_d2h1(:) ! Parameter 1 for d2h allometry (intercept, or "c") real(r8), allocatable :: allom_d2h2(:) ! Parameter 2 for d2h allometry (slope, or "m") diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index 4442c090e8..da8a9c0448 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -227,10 +227,14 @@ subroutine PRTRegisterPFT(fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_allom_l2fr' + name = 'fates_allom_l2fr_min' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_allom_l2fr_max' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_grperc' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -495,9 +499,13 @@ subroutine PRTReceivePFT(fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%allom_la_per_sa_slp) - name = 'fates_allom_l2fr' + name = 'fates_allom_l2fr_min' + call fates_params%RetreiveParameterAllocate(name=name, & + data=prt_params%allom_l2fr_min) + + name = 'fates_allom_l2fr_max' call fates_params%RetreiveParameterAllocate(name=name, & - data=prt_params%allom_l2fr) + data=prt_params%allom_l2fr_max) name = 'fates_allom_agb_frac' call fates_params%RetreiveParameterAllocate(name=name, & @@ -835,7 +843,8 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'allom_smode = ',prt_params%allom_smode write(fates_log(),fmt0) 'allom_la_per_sa_int = ',prt_params%allom_la_per_sa_int write(fates_log(),fmt0) 'allom_la_per_sa_slp = ',prt_params%allom_la_per_sa_slp - write(fates_log(),fmt0) 'allom_l2fr = ',prt_params%allom_l2fr + write(fates_log(),fmt0) 'allom_l2fr_min = ',prt_params%allom_l2fr_min + write(fates_log(),fmt0) 'allom_l2fr_max = ',prt_params%allom_l2fr_max write(fates_log(),fmt0) 'allom_agb_frac = ',prt_params%allom_agb_frac write(fates_log(),fmt0) 'allom_d2h1 = ',prt_params%allom_d2h1 write(fates_log(),fmt0) 'allom_d2h2 = ',prt_params%allom_d2h2 @@ -1405,7 +1414,7 @@ function NewRecruitTotalStoichiometry(ft,element_id) result(recruit_stoich) call h2d_allom(EDPftvarcon_inst%hgt_min(ft),ft,dbh) call bleaf(dbh,ft,init_recruit_trim,c_leaf) - call bfineroot(dbh,ft,init_recruit_trim,c_fnrt) + call bfineroot(dbh,ft,init_recruit_trim,prt_params%allom_l2fr_min(ft),c_fnrt) call bsap_allom(dbh,ft,init_recruit_trim,a_sapw, c_sapw) call bagw_allom(dbh,ft,c_agw) call bbgw_allom(dbh,ft,c_bgw) From 6f1b1ca8a81d224afc3adfeb7f33f10382024e91 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 18 Nov 2021 10:38:18 -0500 Subject: [PATCH 071/852] Work on dynamic root responses to nutrient availability --- biogeochem/FatesSoilBGCFluxMod.F90 | 548 ++++++----------------------- main/EDPftvarcon.F90 | 8 - main/FatesConstantsMod.F90 | 13 +- main/FatesHistoryInterfaceMod.F90 | 50 ++- main/FatesInterfaceMod.F90 | 66 ++-- main/FatesInterfaceTypesMod.F90 | 8 +- parteh/PRTAllometricCNPMod.F90 | 106 +++--- 7 files changed, 254 insertions(+), 545 deletions(-) diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index b42b60a6ec..e3dd7a76f1 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -62,8 +62,7 @@ module FatesSoilBGCFluxMod use FatesConstantsMod, only : g_per_kg use FatesConstantsMod, only : kg_per_g use FatesConstantsMod, only : fates_np_comp_scaling - use FatesConstantsMod, only : cohort_np_comp_scaling - use FatesConstantsMod, only : pft_np_comp_scaling + use FatesConstantsMod, only : coupled_np_comp_scaling use FatesConstantsMod, only : trivial_np_comp_scaling use FatesConstantsMod, only : rsnbl_math_prec use FatesConstantsMod, only : days_per_year @@ -196,27 +195,9 @@ subroutine UnPackNutrientAquisitionBCs(sites, bc_in) type(ed_patch_type), pointer :: cpatch ! current patch pointer type(ed_cohort_type), pointer :: ccohort ! current cohort pointer real(r8) :: fnrt_c ! fine-root carbon [kg] - real(r8) :: fnrt_c_pft(numpft) ! total mass of root for each PFT [kgC] nsites = size(sites,dim=1) - - ! Zero the uptake rates - do s = 1, nsites - cpatch => sites(s)%oldest_patch - do while (associated(cpatch)) - ccohort => cpatch%tallest - do while (associated(ccohort)) - ccohort%daily_nh4_uptake = 0._r8 - ccohort%daily_no3_uptake = 0._r8 - ccohort%daily_p_uptake = 0._r8 - ccohort => ccohort%shorter - end do - cpatch => cpatch%younger - end do - - end do - ! We can exit if this is a c-only simulation if(hlm_parteh_mode.eq.prt_carbon_allom_hyp) then ! These can now be zero'd @@ -238,20 +219,39 @@ subroutine UnPackNutrientAquisitionBCs(sites, bc_in) ! the plant demand. if (n_uptake_mode.eq.prescribed_n_uptake) then + cpatch => sites(s)%oldest_patch do while (associated(cpatch)) ccohort => cpatch%tallest do while (associated(ccohort)) pft = ccohort%pft - ccohort%daily_n_demand = GetPlantDemand(ccohort,nitrogen_element) ccohort%daily_nh4_uptake = EDPftvarcon_inst%prescribed_nuptake(pft) * ccohort%daily_n_demand ccohort%daily_no3_uptake = 0._r8 - ccohort => ccohort%shorter end do cpatch => cpatch%younger end do + + elseif(n_uptake_mode.eq.coupled_n_uptake) then + + icomp = 0 + cpatch => sites(s)%oldest_patch + do while (associated(cpatch)) + ccohort => cpatch%tallest + do while (associated(ccohort)) + icomp = icomp+1 + fnrt_c = ccohort%prt%GetState(fnrt_organ, carbon12_element) + ccohort%daily_n_demand = fnrt_c * ccohort%n * AREA_INV * & + EDPftvarcon_inst%eca_vmax_nh4(ccohort%pft) * sec_per_day + ! N Uptake: Convert g/m2/day -> kg/plant/day + ccohort%daily_nh4_uptake = bc_in(s)%plant_nh4_uptake_flux(icomp,1)*kg_per_g*AREA/ccohort%n + ccohort%daily_no3_uptake = bc_in(s)%plant_no3_uptake_flux(icomp,1)*kg_per_g*AREA/ccohort%n + ccohort => ccohort%shorter + end do + cpatch => cpatch%younger + end do + end if if (p_uptake_mode.eq.prescribed_p_uptake) then @@ -260,151 +260,33 @@ subroutine UnPackNutrientAquisitionBCs(sites, bc_in) ccohort => cpatch%tallest do while (associated(ccohort)) pft = ccohort%pft - ccohort%daily_p_demand = GetPlantDemand(ccohort,phosphorus_element) ccohort%daily_p_uptake = EDPftvarcon_inst%prescribed_puptake(pft) * ccohort%daily_p_demand - ccohort => ccohort%shorter end do cpatch => cpatch%younger end do - end if - - - ! If nutrient competition is sent to the BGC model as PFTs - ! and not as individual cohorts, we need to unravel the input - ! boundary condition and send to cohort. We do this downscaling - ! by finding each cohort's fraction of total fine-root for the group - - n_or_p_coupled_if: if(n_uptake_mode.eq.coupled_n_uptake .or. p_uptake_mode.eq.coupled_p_uptake)then - - ! Note there are two scaling methods. Either competition for - ! N and/or P was performed by cohorts acting individually - ! (cohort_np_comp_scaling) , or as PFTs (pft_np_comp_scaling) - ! If we opt for the latter, then we assume that the nutrient - ! uptake share of the cohort, matches the fraction of root - ! mass it contributes to the group (PFT). - if(fates_np_comp_scaling.eq.pft_np_comp_scaling) then - - ! *Currently, all cohorts in a PFT have the same root - ! fraction, so all we have to to is find its total mass fraction. - - fnrt_c_pft(:) = 0._r8 - cpatch => sites(s)%oldest_patch - do while (associated(cpatch)) - ccohort => cpatch%tallest - do while (associated(ccohort)) - pft = ccohort%pft - fnrt_c_pft(pft) = fnrt_c_pft(pft) + & - ccohort%prt%GetState(fnrt_organ, all_carbon_elements)*ccohort%n - ccohort => ccohort%shorter - end do - cpatch => cpatch%younger + elseif(p_uptake_mode.eq.coupled_p_uptake) then + + icomp = 0 + cpatch => sites(s)%oldest_patch + do while (associated(cpatch)) + ccohort => cpatch%tallest + do while (associated(ccohort)) + icomp = icomp+1 + fnrt_c = ccohort%prt%GetState(fnrt_organ, carbon12_element) + ccohort%daily_p_demand = fnrt_c * ccohort%n * AREA_INV * & + EDPftvarcon_inst%eca_vmax_p(ccohort%pft) * sec_per_day + ! P Uptake: Convert g/m2/day -> kg/plant/day + ccohort%daily_p_uptake = bc_in(s)%plant_p_uptake_flux(icomp,1)*kg_per_g*AREA/ccohort%n + ccohort => ccohort%shorter end do - - end if ! end if(fates_np_comp_scaling.eq.pft_np_comp_scaling) then + cpatch => cpatch%younger + end do + + end if - ! -------------------------------------------------------------------------------- - ! Now that we have the arrays ready for downscaling (if needed) - ! loop through all cohorts and acquire nutrient - ! -------------------------------------------------------------------------------- - - if(n_uptake_mode.eq.coupled_n_uptake) then - - if(fates_np_comp_scaling.eq.cohort_np_comp_scaling) then - - icomp = 0 - cpatch => sites(s)%oldest_patch - do while (associated(cpatch)) - ccohort => cpatch%tallest - do while (associated(ccohort)) - icomp = icomp+1 - - ! N Uptake: Convert g/m2/day -> kg/plant/day - - ccohort%daily_nh4_uptake = sum(bc_in(s)%plant_nh4_uptake_flux(icomp,:))*kg_per_g*AREA/ccohort%n - ccohort%daily_no3_uptake = sum(bc_in(s)%plant_no3_uptake_flux(icomp,:))*kg_per_g*AREA/ccohort%n - - ccohort => ccohort%shorter - end do - cpatch => cpatch%younger - end do - - else - - cpatch => sites(s)%oldest_patch - do while (associated(cpatch)) - ccohort => cpatch%tallest - do while (associated(ccohort)) - pft = ccohort%pft - - ! Total fine-root carbon of the cohort [kgC/ha] - fnrt_c = ccohort%prt%GetState(fnrt_organ, all_carbon_elements)*ccohort%n - - ! Loop through soil layers, add up the uptake this cohort gets from each layer - do id = 1,bc_in(s)%nlevdecomp - ccohort%daily_nh4_uptake = ccohort%daily_nh4_uptake + & - bc_in(s)%plant_nh4_uptake_flux(pft,id) * & - (fnrt_c/fnrt_c_pft(pft))*kg_per_g*AREA/ccohort%n - ccohort%daily_no3_uptake = ccohort%daily_no3_uptake + & - bc_in(s)%plant_no3_uptake_flux(pft,id) * & - (fnrt_c/fnrt_c_pft(pft))*kg_per_g*AREA/ccohort%n - end do - - ccohort => ccohort%shorter - end do - cpatch => cpatch%younger - end do - - end if - - end if - - if(p_uptake_mode.eq.coupled_p_uptake) then - - if(fates_np_comp_scaling.eq.cohort_np_comp_scaling) then - - icomp = 0 - cpatch => sites(s)%oldest_patch - do while (associated(cpatch)) - ccohort => cpatch%tallest - do while (associated(ccohort)) - icomp = icomp+1 - ! P Uptake: Convert g/m2/day -> kg/plant/day - ccohort%daily_p_uptake = ccohort%daily_p_uptake + & - sum(bc_in(s)%plant_p_uptake_flux(icomp,:))*kg_per_g*AREA/ccohort%n - ccohort => ccohort%shorter - end do - cpatch => cpatch%younger - end do - - else - - cpatch => sites(s)%oldest_patch - do while (associated(cpatch)) - ccohort => cpatch%tallest - do while (associated(ccohort)) - pft = ccohort%pft - ! Total fine-root carbon of the cohort [kgC/ha] - fnrt_c = ccohort%prt%GetState(fnrt_organ, all_carbon_elements)*ccohort%n - ! Loop through soil layers, add up the uptake this cohort gets from each layer - do id = 1,bc_in(s)%nlevdecomp - ccohort%daily_p_uptake = ccohort%daily_p_uptake + & - bc_in(s)%plant_p_uptake_flux(pft,id) * & - (fnrt_c/fnrt_c_pft(pft))*kg_per_g*AREA/ccohort%n - end do - ccohort => ccohort%shorter - end do - cpatch => cpatch%younger - end do - - end if - - end if - - end if n_or_p_coupled_if - ! These can now be zero'd bc_in(s)%plant_nh4_uptake_flux(:,:) = 0._r8 bc_in(s)%plant_no3_uptake_flux(:,:) = 0._r8 @@ -579,303 +461,107 @@ subroutine PrepNutrientAquisitionBCs(csite, bc_in, bc_out) type(bc_out_type), intent(inout) :: bc_out ! Locals - integer :: icomp ! competitor index - integer :: j ! soil layer index - integer :: id ! decomp index (might == j) - integer :: pft ! plant functional type - type(ed_patch_type), pointer :: cpatch ! current patch pointer - type(ed_cohort_type), pointer :: ccohort ! current cohort pointer - real(r8) :: fnrt_c ! fine-root carbon [kg] - real(r8) :: veg_rootc ! fine root carbon in each layer [g/m3] - real(r8) :: dbh ! dbh (cm) - real(r8) :: npp_n_demand ! Nitrogen needed to keep up with NPP [kgN] - real(r8) :: npp_p_demand ! Phosphorus needed to keep up with NPP [kgP] - real(r8) :: deficit_n_demand ! Nitrogen needed to get stoich back to - ! optimal [kgN] - real(r8) :: deficit_p_demand ! Phosphorus needed to get stoich back to - ! optimal [kgP] - real(r8) :: comp_per_pft(numpft) ! Competitors per PFT, used for averaging - real(r8) :: decompmicc_layer ! Microbial dedcomposer biomass for current layer - integer :: comp_scaling ! Flag that defines the boundary condition scaling method (includes trivial) - - real(r8), parameter :: decompmicc_lambda = 2.5_r8 ! Depth attenuation exponent for decomposer biomass + integer :: icomp ! competitor index + integer :: j ! soil layer index + integer :: id ! decomp index (might == j) + integer :: pft ! plant functional type + type(ed_patch_type), pointer :: cpatch ! current patch pointer + type(ed_cohort_type), pointer :: ccohort ! current cohort pointer + real(r8) :: fnrt_c ! fine-root carbon [kg] + real(r8) :: veg_rootc ! fine root carbon in each layer [g/m3] + real(r8) :: decompmicc_layer ! Microbial dedcomposer biomass for current layer + + real(r8), parameter :: decompmicc_lambda = 2.5_r8 ! Depth attenuation exponent for decomposer biomass real(r8), parameter :: decompmicc_zmax = 7.0e-2_r8 ! Depth of maximum decomposer biomass - ! Determine the scaling approach - if((hlm_parteh_mode.eq.prt_cnp_flex_allom_hyp) .and. & - ((n_uptake_mode.eq.coupled_n_uptake) .or. & - (p_uptake_mode.eq.coupled_p_uptake))) then - comp_scaling = fates_np_comp_scaling - - else - - comp_scaling = trivial_np_comp_scaling - - ! Note: With ECA, we still need to update the - ! decomp microbe density even if we are not - ! fully coupled, so can't exit yet - - if(trim(hlm_nu_com).eq.'RD') then - bc_out%num_plant_comps = 1 - bc_out%n_demand(1) = 0._r8 - bc_out%p_demand(1) = 0._r8 - return + + ! Whether this is a trivial or coupled run, + ! the following variables get initialized in the same way + bc_out%veg_rootc(:,:) = 0._r8 + bc_out%ft_index(:) = -1 + if(trim(hlm_nu_com).eq.'ECA')then + bc_out%decompmicc(:) = 0._r8 + bc_out%cn_scalar(:) = 1._r8 + bc_out%cp_scalar(:) = 1._r8 + end if + + if(fates_np_comp_scaling == trivial_np_comp_scaling) then + if(trim(hlm_nu_com).eq.'RD')then + bc_out%num_plant_comps = 1 + bc_out%ft_index(1) = 1 + return end if - end if - - ! ECA Specific Parameters - ! -------------------------------------------------------------------------------- - if(trim(hlm_nu_com).eq.'ECA')then - - bc_out%veg_rootc(:,:) = 0._r8 ! Zero this, it will be incremented - bc_out%decompmicc(:) = 0._r8 - bc_out%cn_scalar(:) = 0._r8 - bc_out%cp_scalar(:) = 0._r8 - bc_out%ft_index(:) = -1 - - ! Loop over all patches and sum up the seed input for each PFT - icomp = 0 - comp_per_pft(:) = 0 ! This counts how many competitors per - ! pft, used for averaging - - cpatch => csite%oldest_patch - do while (associated(cpatch)) - - ccohort => cpatch%tallest - do while (associated(ccohort)) - - pft = ccohort%pft - ! If we are not coupling plant uptake - ! with ECA, then we send 1 token - ! competitor with plant root biomass, but no - ! uptake affinity + ! For both the trivial case with ECA, and the coupled case + ! we still need to calculate the root biomass and decompmicc + ! arrays (the former for the latter when trivial). So we + ! don't differentiate - if(comp_scaling.eq.cohort_np_comp_scaling) then - icomp = icomp+1 - bc_out%ft_index(icomp) = pft - else - icomp = pft - comp_per_pft(pft) = comp_per_pft(pft) + 1 - bc_out%ft_index(icomp) = pft - end if - - call set_root_fraction(csite%rootfrac_scr, pft, csite%zi_soil, & - bc_in%max_rooting_depth_index_col ) - - fnrt_c = ccohort%prt%GetState(fnrt_organ, carbon12_element) - - ! Map the soil layers to the decomposition layers - ! (which may be synonomous) - ! veg_rootc in units: [g/m3] = [kgC/plant] * [plant/ha] * [ha/ 10k m2] * [1000 g / kg] * [1/m] + icomp = 0 + cpatch => csite%oldest_patch + do while (associated(cpatch)) + ccohort => cpatch%tallest + do while (associated(ccohort)) - do j = 1, bc_in%nlevdecomp - id = bc_in%decomp_id(j) ! Map from soil layer to decomp layer - veg_rootc = fnrt_c * ccohort%n * csite%rootfrac_scr(j) * AREA_INV * g_per_kg / csite%dz_soil(j) - - bc_out%veg_rootc(icomp,id) = bc_out%veg_rootc(icomp,id) + veg_rootc + if(fates_np_comp_scaling .eq. coupled_np_comp_scaling) then + icomp = icomp+1 + else + icomp = 1 + end if + + pft = ccohort%pft + bc_out%ft_index(icomp) = pft + + call set_root_fraction(csite%rootfrac_scr, pft, csite%zi_soil, & + bc_in%max_rooting_depth_index_col ) + + fnrt_c = ccohort%prt%GetState(fnrt_organ, carbon12_element) + + ! Map the soil layers to the decomposition layers (which may be synonomous) + ! veg_rootc in units: [gC/m3] = [kgC/plant] * [plant/ha] * [ha/ 10k m2] * [1000 g / kg] * [1/m] + + do j = 1, bc_in%nlevdecomp + id = bc_in%decomp_id(j) ! Map from soil layer to decomp layer + veg_rootc = fnrt_c * ccohort%n * csite%rootfrac_scr(j) * AREA_INV * g_per_kg / csite%dz_soil(j) + + bc_out%veg_rootc(icomp,id) = bc_out%veg_rootc(icomp,id) + veg_rootc + + if(trim(hlm_nu_com).eq.'ECA')then ! We use a 3 parameter exponential attenuation function to estimate decomposer biomass ! The parameter EDPftvarcon_inst%decompmicc(pft) is the maximum amount found at depth ! decompmicc_zmax, and the profile attenuates with strength lambda - + decompmicc_layer = EDPftvarcon_inst%decompmicc(pft) * & exp(-decompmicc_lambda*abs(csite%z_soil(j)-decompmicc_zmax)) - + + bc_out%decompmicc(id) = bc_out%decompmicc(id) + decompmicc_layer * veg_rootc - end do - ccohort => ccohort%shorter + end if + end do - - cpatch => cpatch%younger + ccohort => ccohort%shorter end do - ! We calculate the decomposer microbial biomass by weighting with the - ! root biomass. This is just the normalization step + cpatch => cpatch%younger + end do + + ! We calculate the decomposer microbial biomass by weighting with the + ! root biomass. This is just the normalization step + if(trim(hlm_nu_com).eq.'ECA')then do id = 1,bc_in%nlevdecomp bc_out%decompmicc(id) = bc_out%decompmicc(id) / & max(nearzero,sum(bc_out%veg_rootc(:,id),dim=1)) end do + end if - if(comp_scaling.eq.cohort_np_comp_scaling) then - bc_out%num_plant_comps = icomp - elseif(comp_scaling.eq.pft_np_comp_scaling) then - bc_out%num_plant_comps = numpft - elseif(comp_scaling.eq.trivial_np_comp_scaling) then - bc_out%num_plant_comps = 1 - ! Now that the microbial density is calculated - ! we can exit the trivial case - return - end if - - coupled_n_if: if(n_uptake_mode.eq.coupled_n_uptake) then - icomp = 0 - cpatch => csite%oldest_patch - do while (associated(cpatch)) - ccohort => cpatch%tallest - do while (associated(ccohort)) - - pft = ccohort%pft - if(fates_np_comp_scaling.eq.cohort_np_comp_scaling) then - icomp = icomp+1 - else - icomp = pft - end if - - bc_out%cn_scalar(icomp) = 1.0_r8 - - - ccohort => ccohort%shorter - end do - cpatch => cpatch%younger - end do - - ! Normalize the sum to a mean, if this is a PFT scale - ! boundary flux - if(fates_np_comp_scaling.eq.pft_np_comp_scaling) then - do icomp = 1, numpft - bc_out%cn_scalar(icomp) = bc_out%cn_scalar(icomp)/real(comp_per_pft(icomp),r8) - end do - end if - - else - - ! If we are not coupling N, then make sure to set affinity of plants to 0 - ! (it is possible to be here if P is coupled but N is not) - bc_out%cn_scalar(:) = 0._r8 - - end if coupled_n_if - - coupled_p_if: if(p_uptake_mode.eq.coupled_p_uptake) then - - icomp = 0 - cpatch => csite%oldest_patch - do while (associated(cpatch)) - ccohort => cpatch%tallest - do while (associated(ccohort)) - - pft = ccohort%pft - if(fates_np_comp_scaling.eq.cohort_np_comp_scaling) then - icomp = icomp+1 - else - icomp = pft - end if - - bc_out%cp_scalar(icomp) = 1.0_r8 - - ccohort => ccohort%shorter - end do - cpatch => cpatch%younger - end do - - if(fates_np_comp_scaling.eq.pft_np_comp_scaling) then - do icomp = 1, numpft - bc_out%cp_scalar(icomp) = bc_out%cp_scalar(icomp)/real(comp_per_pft(icomp),r8) - end do - end if - else - - ! If we are not coupling P, then make sure to set affinity of plants to 0 - ! (it is possible to be here if N is coupled but P is not) - bc_out%cp_scalar(:) = 0._r8 - - end if coupled_p_if - - elseif(trim(hlm_nu_com).eq.'RD') then - - ! If we are using RD competition and coupling that into FATES, - ! we must update the plant's demand - ! (if this is un-coupled, the demand is handled completely in - ! the UnPack code) - ! ----------------------------------------------------------------------------------- - - if(n_uptake_mode .eq. coupled_n_uptake ) then - cpatch => csite%oldest_patch - do while (associated(cpatch)) - ccohort => cpatch%tallest - do while (associated(ccohort)) - ccohort%daily_n_demand = GetPlantDemand(ccohort,nitrogen_element) - ccohort => ccohort%shorter - end do - cpatch => cpatch%younger - end do - - end if - - if(p_uptake_mode .eq. coupled_p_uptake ) then - cpatch => csite%oldest_patch - do while (associated(cpatch)) - ccohort => cpatch%tallest - do while (associated(ccohort)) - ccohort%daily_p_demand = GetPlantDemand(ccohort,phosphorus_element) - ccohort => ccohort%shorter - end do - cpatch => cpatch%younger - end do - end if - - ! -------------------------------------------------------------------------------- - ! Units on demand: - ! [gX/m2/s] convert [kgX/plant/day] * [plant/ha] * - ! [ha/10000 m2] * [1000 g/kg] * [1 day /86400 sec] - ! -------------------------------------------------------------------------------- - - bc_out%n_demand(:) = 0._r8 - bc_out%p_demand(:) = 0._r8 - - if(n_uptake_mode.eq.coupled_n_uptake) then - icomp = 0 - cpatch => csite%oldest_patch - do while (associated(cpatch)) - ccohort => cpatch%tallest - do while (associated(ccohort)) - pft = ccohort%pft - if(fates_np_comp_scaling.eq.cohort_np_comp_scaling) then - icomp = icomp+1 - else - icomp = pft - end if - bc_out%n_demand(icomp) = bc_out%n_demand(icomp) + & - ccohort%daily_n_demand*ccohort%n*AREA_INV*g_per_kg*days_per_sec - - ccohort => ccohort%shorter - end do - cpatch => cpatch%younger - end do - end if - - if(p_uptake_mode.eq.coupled_p_uptake) then - icomp = 0 - cpatch => csite%oldest_patch - do while (associated(cpatch)) - ccohort => cpatch%tallest - do while (associated(ccohort)) - pft = ccohort%pft - if(fates_np_comp_scaling.eq.cohort_np_comp_scaling) then - icomp = icomp+1 - else - icomp = pft - end if - bc_out%p_demand(icomp) = bc_out%p_demand(icomp) + & - ccohort%daily_p_demand*ccohort%n*AREA_INV*g_per_kg*days_per_sec - ccohort => ccohort%shorter - end do - cpatch => cpatch%younger - end do - end if - - if(comp_scaling.eq.cohort_np_comp_scaling) then - bc_out%num_plant_comps = icomp - elseif(comp_scaling.eq.pft_np_comp_scaling) then - bc_out%num_plant_comps = numpft - else - bc_out%num_plant_comps = 1 - end if - + if(fates_np_comp_scaling == coupled_np_comp_scaling) then + bc_out%num_plant_comps = icomp + else + bc_out%num_plant_comps = 1 end if - return end subroutine PrepNutrientAquisitionBCs diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 61f095a758..1f608efa3e 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1462,9 +1462,6 @@ subroutine FatesCheckParams(is_master) write(fates_log(),*) ' Aborting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if - n_uptake_mode = prescribed_n_uptake - else - n_uptake_mode = coupled_n_uptake end if ! logging parameters, make sure they make sense @@ -1494,13 +1491,8 @@ subroutine FatesCheckParams(is_master) write(fates_log(),*) ' Aborting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if - p_uptake_mode = prescribed_p_uptake - else - p_uptake_mode = coupled_p_uptake end if - - do ipft = 1,npft diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index 7e19856aa2..cf1e7edafa 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -47,15 +47,10 @@ module FatesConstantsMod integer, public, parameter :: coupled_n_uptake = 2 - integer, public, parameter :: cohort_np_comp_scaling = 1 ! This flag definition indicates that EVERY cohort on - ! the column should compete independently in the soil - ! BGC nitrogen and phosphorus acquisition scheme. + integer, public, parameter :: coupled_np_comp_scaling = 1 ! This flag signals that at least 1 chemical element (ie N or P) + ! is dynamic and exchanged between FATES and the HLM - integer, public, parameter :: pft_np_comp_scaling = 2 ! This flag definition indicates that cohorts should - ! be grouped into PFTs, and each PFT will be represented - ! as the competitor, in the BGC N and P acquisition scheme - - integer, public, parameter :: trivial_np_comp_scaling = 3 ! This flag definition indicates that either + integer, public, parameter :: trivial_np_comp_scaling = 2 ! This flag definition indicates that either ! nutrients are turned off in FATES, or, that the ! plants are not coupled with below ground chemistry. In ! this situation, we send token boundary condition information. @@ -64,7 +59,7 @@ module FatesConstantsMod ! This flag specifies the scaling of how we present ! nutrient competitors to the HLM's soil BGC model - integer, public, parameter :: fates_np_comp_scaling = cohort_np_comp_scaling + integer, public :: fates_np_comp_scaling = -1 real(fates_r8), parameter, public :: secondary_age_threshold = 94._fates_r8 ! less than this value is young secondary land ! based on average age of global diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 97f3342b43..b7b1ae2f34 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -170,6 +170,9 @@ module FatesHistoryInterfaceMod integer :: ih_reprop_si integer :: ih_totvegp_si + integer :: ih_l2fr_si + integer :: ih_l2fr_scpf + integer,public :: ih_nh4uptake_si integer,public :: ih_no3uptake_si integer,public :: ih_puptake_si @@ -1787,6 +1790,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) associate( hio_npatches_si => this%hvars(ih_npatches_si)%r81d, & hio_ncohorts_si => this%hvars(ih_ncohorts_si)%r81d, & hio_trimming_si => this%hvars(ih_trimming_si)%r81d, & + hio_l2fr_si => this%hvars(ih_l2fr_si)%r81d, & + hio_l2fr_scpf => this%hvars(ih_l2fr_scpf)%r82d, & hio_area_plant_si => this%hvars(ih_area_plant_si)%r81d, & hio_area_trees_si => this%hvars(ih_area_trees_si)%r81d, & hio_canopy_spread_si => this%hvars(ih_canopy_spread_si)%r81d, & @@ -2209,8 +2214,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) call sizetype_class_index(ccohort%dbh, ccohort%pft, ccohort%size_class, ccohort%size_by_pft_class) call coagetype_class_index(ccohort%coage, ccohort%pft, & ccohort%coage_class, ccohort%coage_by_pft_class) - - ! Increment the number of cohorts per site + + ! Increment the number of cohorts per site hio_ncohorts_si(io_si) = hio_ncohorts_si(io_si) + 1._r8 n_perm2 = ccohort%n * AREA_INV @@ -2268,6 +2273,14 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! Zero states, and set the fluxes if( element_list(el).eq.carbon12_element )then + + ! These L2FR diagnostics are weighted by fineroot carbon biomass + hio_l2fr_si(io_si) = hio_l2fr_si(io_si) + ccohort%n*fnrt_m*ccohort%l2fr + + hio_l2fr_scpf(io_si,ccohort%size_by_pft_class) = & + hio_l2fr_scpf(io_si,ccohort%size_by_pft_class) + & + ccohort%n*fnrt_m*ccohort%l2fr + this%hvars(ih_storec_si)%r81d(io_si) = & this%hvars(ih_storec_si)%r81d(io_si) + ccohort%n * store_m this%hvars(ih_leafc_si)%r81d(io_si) = & @@ -2856,6 +2869,10 @@ subroutine update_history_dyn(this,nc,nsites,sites) cpatch => cpatch%younger end do !patch loop + ! Normalize the l2fr value by total biomass + hio_l2fr_si(io_si) = hio_l2fr_si(io_si)/this%hvars(ih_fnrtc_si)%r81d(io_si) + + ! divide so-far-just-summed but to-be-averaged patch-age-class variables by patch-age-class area to get mean values do ipa2 = 1, nlevage if (hio_area_si_age(io_si, ipa2) .gt. tiny) then @@ -2878,6 +2895,9 @@ subroutine update_history_dyn(this,nc,nsites,sites) do i_pft = 1, numpft do i_scls = 1,nlevsclass i_scpf = (i_pft-1)*nlevsclass + i_scls + + + ! ! termination mortality. sum of canopy and understory indices hio_m6_si_scpf(io_si,i_scpf) = (sites(s)%term_nindivs_canopy(i_scls,i_pft) + & @@ -3004,7 +3024,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_m4_si_scpf(io_si,i_scpf) + & hio_m5_si_scpf(io_si,i_scpf) + & hio_m6_si_scpf(io_si,i_scpf) + & - hio_m7_si_scpf(io_si,i_scpf) + & + hio_m7_si_scpf(io_si,i_scpf) + & hio_m8_si_scpf(io_si,i_scpf) + & hio_m9_si_scpf(io_si,i_scpf) + & hio_m10_si_scpf(io_si,i_scpf) @@ -3157,8 +3177,6 @@ subroutine update_history_dyn(this,nc,nsites,sites) area_frac = cpatch%area * AREA_INV - - ! Sum up all output fluxes (fragmentation) hio_litter_out_elem(io_si,el) = hio_litter_out_elem(io_si,el) + & (sum(litt%leaf_fines_frag(:)) + & @@ -3302,7 +3320,12 @@ subroutine update_history_dyn(this,nc,nsites,sites) do i_pft = 1, numpft do i_scls = 1,nlevsclass i_scpf = (i_pft-1)*nlevsclass + i_scls - + + if(this%hvars(ih_fnrtc_scpf)%r82d(io_si,i_scpf)>nearzero)then + hio_l2fr_scpf(io_si,i_scpf) = hio_l2fr_scpf(io_si,i_scpf) / & + this%hvars(ih_fnrtc_scpf)%r82d(io_si,i_scpf) + end if + if( hio_nplant_canopy_si_scpf(io_si,i_scpf)>nearzero ) then this%hvars(ih_storentfrac_canopy_scpf)%r82d(io_si,i_scpf) = & this%hvars(ih_storentfrac_canopy_scpf)%r82d(io_si,i_scpf) / & @@ -4244,12 +4267,23 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_ncohorts_si) - ! Patch variables call this%set_history_var(vname='TRIMMING', units='none', & long='Degree to which canopy expansion is limited by leaf economics', & use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_trimming_si) + + call this%set_history_var(vname='LEAF2FNRT', units='none', & + long='The leaf to fineroot biomass multiplier for target allometry', & + use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_l2fr_si) + + call this%set_history_var(vname='LEAF2FNRT_SCPF', units='none', & + long='The leaf to fineroot biomass multiplier for target allometry', & + use_default='active', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_l2fr_scpf) call this%set_history_var(vname='AREA_PLANT', units='m2/m2', & long='area occupied by all plants', use_default='active', & @@ -4592,6 +4626,8 @@ subroutine define_history_vars(this, initialize_variables) ivar=ivar, initialize=initialize_variables, index = ih_burnt_frac_litter_si_fuel ) + + ! Litter Variables call this%set_history_var(vname='LITTER_IN', units='gC m-2 s-1', & diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 0156beb2dc..46abeb14ab 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -49,8 +49,8 @@ module FatesInterfaceMod use FatesConstantsMod , only : coupled_p_uptake use FatesConstantsMod , only : coupled_n_uptake use FatesConstantsMod , only : fates_np_comp_scaling - use FatesConstantsMod , only : cohort_np_comp_scaling - use FatesConstantsMod , only : pft_np_comp_scaling + use FatesConstantsMod , only : coupled_np_comp_scaling + use FatesConstantsMod , only : trivial_np_comp_scaling use PRTGenericMod , only : num_elements use PRTGenericMod , only : element_list use PRTGenericMod , only : element_pos @@ -214,13 +214,6 @@ subroutine set_bcpconst(bc_pconst,nlevdecomp) bc_pconst%eca_alpha_ptase(1:numpft) = EDPftvarcon_inst%eca_alpha_ptase(1:numpft) bc_pconst%eca_lambda_ptase(1:numpft) = EDPftvarcon_inst%eca_lambda_ptase(1:numpft) bc_pconst%eca_plant_escalar = eca_plant_escalar - if(fates_np_comp_scaling.eq.cohort_np_comp_scaling) then - bc_pconst%j_uptake(1:nlevdecomp) = 1 - else - do j=1,nlevdecomp - bc_pconst%j_uptake(j) = j - end do - end if return end subroutine set_bcpconst @@ -421,15 +414,9 @@ subroutine allocate_bcin(bc_in, nlevsoil_in, nlevdecomp_in, num_lu_harvest_cats) ! Allocating differently could save a lot of memory and time if (hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) then - if(fates_np_comp_scaling.eq.cohort_np_comp_scaling) then - allocate(bc_in%plant_nh4_uptake_flux(max_comp_per_site,1)) - allocate(bc_in%plant_no3_uptake_flux(max_comp_per_site,1)) - allocate(bc_in%plant_p_uptake_flux(max_comp_per_site,1)) - else - allocate(bc_in%plant_nh4_uptake_flux(max_comp_per_site,bc_in%nlevdecomp)) - allocate(bc_in%plant_no3_uptake_flux(max_comp_per_site,bc_in%nlevdecomp)) - allocate(bc_in%plant_p_uptake_flux(max_comp_per_site,bc_in%nlevdecomp)) - end if + allocate(bc_in%plant_nh4_uptake_flux(max_comp_per_site,1)) + allocate(bc_in%plant_no3_uptake_flux(max_comp_per_site,1)) + allocate(bc_in%plant_p_uptake_flux(max_comp_per_site,1)) else allocate(bc_in%plant_nh4_uptake_flux(1,1)) allocate(bc_in%plant_no3_uptake_flux(1,1)) @@ -569,15 +556,17 @@ subroutine allocate_bcout(bc_out, nlevsoil_in, nlevdecomp_in) ! When FATES does not have nutrients enabled, these ! arrays are indexed by 1. - if(trim(hlm_nu_com).eq.'RD') then - allocate(bc_out%n_demand(max_comp_per_site)) - allocate(bc_out%p_demand(max_comp_per_site)) - end if - + !if(trim(hlm_nu_com).eq.'RD') then + ! allocate(bc_out%n_demand(max_comp_per_site)) + ! allocate(bc_out%p_demand(max_comp_per_site)) + !end if + + ! Used in both + allocate(bc_out%veg_rootc(max_comp_per_site,nlevdecomp_in)) + allocate(bc_out%ft_index(max_comp_per_site)) + if(trim(hlm_nu_com).eq.'ECA') then - allocate(bc_out%veg_rootc(max_comp_per_site,nlevdecomp_in)) allocate(bc_out%decompmicc(nlevdecomp_in)) - allocate(bc_out%ft_index(max_comp_per_site)) allocate(bc_out%cn_scalar(max_comp_per_site)) allocate(bc_out%cp_scalar(max_comp_per_site)) end if @@ -772,20 +761,33 @@ subroutine SetFatesGlobalElements(use_fates) ! Note: since BGC code may be active even when no nutrients ! present, we still need to allocate things when no nutrients + + if (any(abs(EDPftvarcon_inst%prescribed_nuptake(:)) > nearzero )) then + n_uptake_mode = prescribed_n_uptake + else + n_uptake_mode = coupled_n_uptake + end if + + if (any(abs(EDPftvarcon_inst%prescribed_puptake(:)) > nearzero )) then + p_uptake_mode = prescribed_p_uptake + else + p_uptake_mode = coupled_p_uptake + end if + if (hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp ) then - if(fates_np_comp_scaling.eq.cohort_np_comp_scaling) then + + if((p_uptake_mode==coupled_p_uptake) .or. (n_uptake_mode==coupled_n_uptake))then max_comp_per_site = fates_maxElementsPerSite - elseif(fates_np_comp_scaling.eq.pft_np_comp_scaling) then - max_comp_per_site = numpft + fates_np_comp_scaling = coupled_np_comp_scaling else - write(fates_log(), *) 'An unknown nutrient competitor scaling method was chosen?' - call endrun(msg=errMsg(sourcefile, __LINE__)) + max_comp_per_site = 1 + fates_np_comp_scaling = trivial_np_comp_scaling end if + else max_comp_per_site = 1 + fates_np_comp_scaling = trivial_np_comp_scaling end if - - ! Identify number of size and age class bins for history output ! assume these arrays are 1-indexed diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 1052ef251e..5dee182d1a 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -628,10 +628,10 @@ module FatesInterfaceTypesMod ! RD Nutrient Boundary Conditions ! --------------------------------------------------------------------------------- - real(r8), pointer :: n_demand(:) ! Nitrogen demand from each competitor - ! for use in ELMs CTC/RD [g/m2/s] - real(r8), pointer :: p_demand(:) ! Phosophorus demand from each competitor - ! for use in ELMs CTC/RD [g/m2/s] + !real(r8), pointer :: n_demand(:) ! Nitrogen demand from each competitor + ! ! for use in ELMs CTC/RD [g/m2/s] + !real(r8), pointer :: p_demand(:) ! Phosophorus demand from each competitor + ! ! for use in ELMs CTC/RD [g/m2/s] ! CH4 Boundary Conditions diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 109cb4cf0d..56c5f13ff7 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -394,14 +394,6 @@ subroutine DailyPRTAllometricCNP(this) real(r8) :: p_gain0 real(r8) :: maint_r_def0 - ! Knowing the stored N and P helps - ! to identify if the plant is net - ! gaining nutrients after replacement - real(r8) :: n_store0 - real(r8) :: p_store0 - real(r8) :: net_n_gain - real(r8) :: net_p_gain - ! Used for mass checking, total mass allocated based ! on change in the states, should match gain0's real(r8) :: allocated_c @@ -435,7 +427,7 @@ subroutine DailyPRTAllometricCNP(this) ! In/out boundary conditions maint_r_def => this%bc_inout(acnp_bc_inout_id_rmaint_def)%rval; maint_r_def0 = maint_r_def dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval; dbh0 = dbh - l2fr => this%bc_out(acnp_bc_inout_id_l2fr)%rval + l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval ! If more than 1 leaf age bin is present, this @@ -488,6 +480,17 @@ subroutine DailyPRTAllometricCNP(this) end do + ! =================================================================================== + ! Step 1: Evaluate nutrient storage in the plant. Depending on how low + ! these stores are, we will move proportionally more or less of the daily carbon + ! gain to increase the target fine-root biomass, fill up to target + ! and then attempt to get them up to stoichiometry targets. + ! =================================================================================== + + ! This routine actually just updates the l2fr variable + call this%CNPAdjustFRootTargets() + call bfineroot(dbh,ipft,canopy_trim, l2fr, target_c(fnrt_id), target_dcdd(fnrt_id)) + ! =================================================================================== ! Step 0. Transfer all stored nutrient into the daily uptake pool. ! Storage in nutrients does not need to have a buffer like @@ -495,28 +498,15 @@ subroutine DailyPRTAllometricCNP(this) ! anything left at the end is added back (CNPAllocateRemainder()) ! =================================================================================== + + i_var = prt_global%sp_organ_map(store_organ,nitrogen_element) n_gain = n_gain + sum(this%variables(i_var)%val(:)) - net_n_gain = - sum(this%variables(i_var)%val(:)) this%variables(i_var)%val(:) = 0._r8 i_var = prt_global%sp_organ_map(store_organ,phosphorus_element) p_gain = p_gain + sum(this%variables(i_var)%val(:)) - net_p_gain = - sum(this%variables(i_var)%val(:)) this%variables(i_var)%val(:) = 0._r8 - - - ! =================================================================================== - ! Step 1: Evaluate nutrient storage in the plant. Depending on how low - ! these stores are, we will move proportionally more or less of the daily carbon - ! gain to increase the target fine-root biomass, fill up to target - ! and then attempt to get them up to stoichiometry targets. - ! =================================================================================== - - ! This routine actually just updates the l2fr variable - call this%CNPAdjustFRootTargets() - - call bfineroot(dbh,ipft,canopy_trim, l2fr, target_c(fnrt_id), target_dcdd(fnrt_id)) ! =================================================================================== ! Step 2. Prioritized allocation to replace tissues from turnover, and/or pay @@ -548,11 +538,7 @@ subroutine DailyPRTAllometricCNP(this) ! targets based on prioritized relative demand and allometry functions. ! =================================================================================== - net_n_gain = net_n_gain + n_gain - net_p_gain = net_p_gain + p_gain - call this%CNPStatureGrowth(c_gain, n_gain, p_gain, & - net_n_gain, net_p_gain, & state_c, state_n, state_p, target_c, target_dcdd, cnp_limiter) sum_c = 0._r8 @@ -676,8 +662,8 @@ subroutine CNPAdjustFRootTargets(this) associate( l2fr_min => prt_params%allom_l2fr_min(ipft), & l2fr_max => prt_params%allom_l2fr_max(ipft)) - n_regulator = this%StorageRegulator(nitrogen_element, regulate_logi) - p_regulator = this%StorageRegulator(phosphorus_element, regulate_logi) + call this%StorageRegulator(nitrogen_element, regulate_logi,n_regulator) + call this%StorageRegulator(phosphorus_element, regulate_logi,p_regulator) ! We take the maximum here, because the maximum is reflective of the ! element with the lowest storage, which is the limiting element @@ -686,8 +672,9 @@ subroutine CNPAdjustFRootTargets(this) ! Update the leaf-to-fineroot ratio used ! to set fine-root biomass allometry - l2fr = l2fr_min + np_regulator*(l2fr_max-l2fr_min) + l2fr = l2fr_min + max(0._r8,min(1.0_r8,np_regulator))*(l2fr_max-l2fr_min) + ! Find the updated target fineroot biomass ! call bfineroot(dbh,ipft,canopy_trim, l2fr, target_fnrt) @@ -1090,7 +1077,7 @@ end subroutine CNPPrioritizedReplacement ! ===================================================================================== - subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, net_n_gain, net_p_gain, & + subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & state_c, state_n, state_p, & target_c, target_dcdd, cnp_limiter) @@ -1101,10 +1088,6 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, net_n_gain, net_p_gain, ! (new uptake + storage) real(r8), intent(inout) :: p_gain ! Total P available for allocation ! (new uptake + storage) - real(r8), intent(in) :: net_n_gain ! How much N was gained or lost in the - ! process of net uptake and turnover replacment - real(r8), intent(in) :: net_p_gain ! How much P was gained or lost in the - ! process of net uptake and turnover replacment type(parray_type) :: state_c(:) ! State array for carbon, by organ [kg] type(parray_type) :: state_n(:) ! State array for N, by organ [kg] type(parray_type) :: state_p(:) ! State array for P, by organ [kg] @@ -1223,9 +1206,9 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, net_n_gain, net_p_gain, p_stf = max(state_p(store_id)%ptr/target_p,0._r8) if( c_gain <= calloc_abs_error .or. & - leaf_status.eq.leaves_off .or. & - (n_stf < min_stf_growth ) .or. & !.and. net_n_gain < 0._r8) .or. & - (p_stf < min_stf_growth ) ) then !.and. net_p_gain < 0._r8) ) then + leaf_status.eq.leaves_off .or. & + n_gain <= 0.1_r8*calloc_abs_error .or. & + p_gain <= 0.02_r8*calloc_abs_error ) then return end if @@ -1233,7 +1216,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, net_n_gain, net_p_gain, intgr_params(:) = fates_unset_r8 intgr_params(intgr_parm_ctrim) = this%bc_in(acnp_bc_in_id_ctrim)%rval intgr_params(intgr_parm_pft) = real(this%bc_in(acnp_bc_in_id_pft)%ival) - intgr_params(intgr_parm_l2fr) = this%bc_in(acnp_bc_inout_id_l2fr)%rval + intgr_params(intgr_parm_l2fr) = this%bc_inout(acnp_bc_inout_id_l2fr)%rval state_mask(:) = .false. mask_organs(:) = fates_unset_int @@ -1652,11 +1635,11 @@ subroutine CNPAllocateRemainder(this,c_gain, n_gain, p_gain, & ! If any N or P is still hanging around, put it in storage - state_n(store_id)%ptr = state_n(store_id)%ptr + n_gain - state_p(store_id)%ptr = state_p(store_id)%ptr + p_gain + !state_n(store_id)%ptr = state_n(store_id)%ptr + n_gain + !state_p(store_id)%ptr = state_p(store_id)%ptr + p_gain - n_gain = 0._r8 - p_gain = 0._r8 + !n_gain = 0._r8 + !p_gain = 0._r8 ! ----------------------------------------------------------------------------------- @@ -1689,13 +1672,13 @@ subroutine CNPAllocateRemainder(this,c_gain, n_gain, p_gain, & ! ----------------------------------------------------------------------------------- c_efflux = max(0.0_r8,c_gain) -! n_efflux = max(0.0_r8,n_gain) -! p_efflux = max(0.0_r8,p_gain) + n_efflux = max(0.0_r8,n_gain) + p_efflux = max(0.0_r8,p_gain) c_gain = 0.0_r8 -! n_gain = 0.0_r8 -! p_gain = 0.0_r8 + n_gain = 0.0_r8 + p_gain = 0.0_r8 return end subroutine CNPAllocateRemainder @@ -2345,7 +2328,7 @@ end subroutine TargetAllometryCheck ! ===================================================================================== - function StorageRegulator(this,element_id,regulate_type) result(c_scalar) + subroutine StorageRegulator(this,element_id,regulate_type,c_scalar) ! ----------------------------------------------------------------------------------- ! This function returns the cn_scalar or cp_scalar term @@ -2376,11 +2359,15 @@ function StorageRegulator(this,element_id,regulate_type) result(c_scalar) real(r8) :: store_c ! Current storage carbon real(r8) :: store_c_max ! Current maximum storage carbon integer :: icode ! real variable checking code + real(r8) :: store_x + integer :: i_var - real(r8), parameter :: logi_k = 30.0_r8 ! logistic function k - real(r8), parameter :: store_x0 = 0.7_r8 ! storage fraction inflection point - real(r8), parameter :: logi_min = 0.0_r8 ! minimum cn_scalar for logistic + ! For N/C logistic + real(r8) :: logi_k ! logistic function k + real(r8) :: store_x0 ! storage fraction inflection point + real(r8) :: logi_min ! minimum cn_scalar for logistic + ! This is the storage fraction where downregulation starts if using ! a linear function real(r8), parameter :: store_frac0 = 0.85_r8 @@ -2399,12 +2386,19 @@ function StorageRegulator(this,element_id,regulate_type) result(c_scalar) ! The cap of 2 is for numerics and preventing weird math store_frac = min(2.0_r8,this%GetState(store_organ, element_id)/store_max) + i_var = prt_global%sp_organ_map(store_organ,element_id ) + store_x = sum(this%variables(i_var)%val(:)) + if(regulate_type == regulate_linear) then c_scalar = min(c_max,max(c_min,1.0 - (store_frac - store_frac0)/(1.0_r8-store_frac0))) elseif(regulate_type == regulate_logi) then + logi_k = 30.0_r8 + store_x0 = 0.7_r8 + logi_min = 0.0_r8 + ! In this method, we define the c_scalar term ! with a logistic function that goes to 1 (full need) ! as the plant's nutrien storage hits a low threshold @@ -2422,6 +2416,10 @@ function StorageRegulator(this,element_id,regulate_type) result(c_scalar) else + logi_k = 30.0_r8 + store_x0 = 1.0_r8 + logi_min = 0.0_r8 + store_c = this%GetState(store_organ, carbon12_element) call bstore_allom(dbh,ipft,canopy_trim,store_c_max) @@ -2430,7 +2428,7 @@ function StorageRegulator(this,element_id,regulate_type) result(c_scalar) ! we have C, so we downregulate. If this is less than 1, then ! we have less N in storage than we have C, so up-regulate - store_frac = store_frac / (store_c/store_c_max) + store_frac = max(0.1_r8,store_frac) / max(0.1_r8,(store_c/store_c_max)) c_scalar = max(c_min,min(c_max,logi_min + (1.0_r8-logi_min)/(1.0_r8 + exp(logi_k*(store_frac-store_x0))))) @@ -2439,7 +2437,7 @@ function StorageRegulator(this,element_id,regulate_type) result(c_scalar) end associate - end function StorageRegulator + end subroutine StorageRegulator From e1d88b1fdb2110927bfb3061c94dd2fed44c3499 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 23 Nov 2021 21:25:39 -0500 Subject: [PATCH 072/852] version 2 of fates nutrient aquisition, bug fixes and enabling dynamic roots --- main/FatesHistoryInterfaceMod.F90 | 32 +++- parteh/PRTAllometricCNPMod.F90 | 272 +++++------------------------- 2 files changed, 69 insertions(+), 235 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index b7b1ae2f34..8675cf1141 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -62,13 +62,14 @@ module FatesHistoryInterfaceMod use FatesConstantsMod , only : years_per_day use FatesLitterMod , only : litter_type use FatesConstantsMod , only : secondaryforest - + use FatesAllometryMod , only : bstore_allom use PRTGenericMod , only : leaf_organ, fnrt_organ, sapw_organ use PRTGenericMod , only : struct_organ, store_organ, repro_organ use PRTGenericMod , only : all_carbon_elements use PRTGenericMod , only : carbon12_element use PRTGenericMod , only : nitrogen_element, phosphorus_element use PRTGenericMod , only : prt_carbon_allom_hyp + use PRTAllometricCNPMod , only : stoich_max implicit none private ! By default everything is private @@ -148,6 +149,7 @@ module FatesHistoryInterfaceMod ! Indices to 1D Patch variables integer :: ih_storec_si + integer :: ih_storectfrac_si integer :: ih_leafc_si integer :: ih_sapwc_si integer :: ih_fnrtc_si @@ -2283,6 +2285,12 @@ subroutine update_history_dyn(this,nc,nsites,sites) this%hvars(ih_storec_si)%r81d(io_si) = & this%hvars(ih_storec_si)%r81d(io_si) + ccohort%n * store_m + + call bstore_allom(ccohort%dbh,ccohort%pft,ccohort%canopy_trim, store_max) + this%hvars(ih_storectfrac_si)%r81d(io_si) = & + this%hvars(ih_storectfrac_si)%r81d(io_si) + ccohort%n * store_max + + this%hvars(ih_leafc_si)%r81d(io_si) = & this%hvars(ih_leafc_si)%r81d(io_si) + ccohort%n * leaf_m this%hvars(ih_fnrtc_si)%r81d(io_si) = & @@ -2332,7 +2340,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) elseif(element_list(el).eq.nitrogen_element)then - store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ) + store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_max) this%hvars(ih_storen_si)%r81d(io_si) = & this%hvars(ih_storen_si)%r81d(io_si) + ccohort%n * store_m @@ -2352,7 +2360,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) elseif(element_list(el).eq.phosphorus_element) then - store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ) + store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_max) this%hvars(ih_storep_si)%r81d(io_si) = & this%hvars(ih_storep_si)%r81d(io_si) + ccohort%n * store_m @@ -3251,7 +3259,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) this%hvars(ih_reproc_scpf)%r82d(io_si,i_scpf) + repro_m * ccohort%n elseif(element_list(el).eq.nitrogen_element)then - store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ) + store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_max) this%hvars(ih_totvegn_scpf)%r82d(io_si,i_scpf) = & this%hvars(ih_totvegn_scpf)%r82d(io_si,i_scpf) + total_m * ccohort%n @@ -3276,7 +3284,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) elseif(element_list(el).eq.phosphorus_element)then - store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ) + store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_max) this%hvars(ih_totvegp_scpf)%r82d(io_si,i_scpf) = & this%hvars(ih_totvegp_scpf)%r82d(io_si,i_scpf) + total_m * ccohort%n @@ -3312,7 +3320,14 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! Normalize nutrient storage fractions do el = 1, num_elements - if(element_list(el).eq.nitrogen_element)then + + if(element_list(el).eq.carbon12_element)then + if( this%hvars(ih_storectfrac_si)%r81d(io_si)>nearzero ) then + this%hvars(ih_storectfrac_si)%r81d(io_si) = this%hvars(ih_storec_si)%r81d(io_si) / & + this%hvars(ih_storectfrac_si)%r81d(io_si) + end if + + elseif(element_list(el).eq.nitrogen_element)then if( this%hvars(ih_storentfrac_si)%r81d(io_si)>nearzero ) then this%hvars(ih_storentfrac_si)%r81d(io_si) = this%hvars(ih_storen_si)%r81d(io_si) / & this%hvars(ih_storentfrac_si)%r81d(io_si) @@ -4691,6 +4706,11 @@ subroutine define_history_vars(this, initialize_variables) long='Total carbon in live plant storage', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_storec_si ) + + call this%set_history_var(vname='STOREC_TFRAC', units='-', & + long='Storage C fraction of target', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_storectfrac_si ) call this%set_history_var(vname='TOTVEGC', units='kgC ha-1', & long='Total carbon in live plants', use_default='active', & diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 56c5f13ff7..e20c2febce 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -234,8 +234,6 @@ module PRTAllometricCNPMod procedure :: CNPAdjustFRootTargets procedure :: CNPAllocateRemainder procedure :: GetDeficit - procedure :: GrowEquivC - procedure :: NAndPToMatchC procedure :: StorageRegulator end type cnp_allom_prt_vartypes @@ -630,8 +628,8 @@ subroutine DailyPRTAllometricCNP(this) end if end if - target_n = this%GetNutrientTarget(nitrogen_element,store_organ) - target_p = this%GetNutrientTarget(phosphorus_element,store_organ) + target_n = this%GetNutrientTarget(nitrogen_element,store_organ,stoich_max) + target_p = this%GetNutrientTarget(phosphorus_element,store_organ,stoich_max) n_need = target_n - state_n(store_id)%ptr p_need = target_p - state_p(store_id)%ptr @@ -662,8 +660,8 @@ subroutine CNPAdjustFRootTargets(this) associate( l2fr_min => prt_params%allom_l2fr_min(ipft), & l2fr_max => prt_params%allom_l2fr_max(ipft)) - call this%StorageRegulator(nitrogen_element, regulate_logi,n_regulator) - call this%StorageRegulator(phosphorus_element, regulate_logi,p_regulator) + call this%StorageRegulator(nitrogen_element, regulate_CN_logi,n_regulator) + call this%StorageRegulator(phosphorus_element, regulate_CN_logi,p_regulator) ! We take the maximum here, because the maximum is reflective of the ! element with the lowest storage, which is the limiting element @@ -811,10 +809,10 @@ subroutine CNPPrioritizedReplacement(this, & ! ----------------------------------------------------------------------------------- sum_c_demand = 0._r8 - do ii = 1,n_curpri_org - i = curpri_org(ii) + do i = 1,n_curpri_org + ii = curpri_org(i) - i_cvar = prt_global%sp_organ_map(organ_list(i),carbon12_element) + i_cvar = prt_global%sp_organ_map(organ_list(ii),carbon12_element) sum_c_demand = sum_c_demand + prt_params%leaf_stor_priority(ipft) * & sum(this%variables(i_cvar)%turnover(:)) @@ -914,7 +912,7 @@ subroutine CNPPrioritizedReplacement(this, & store_c_flux = min(store_below_target,store_demand) c_gain = c_gain - store_c_flux - state_c(store_id)%ptr = state_c(store_id)%ptr + store_c_flux + state_c(store_id)%ptr = state_c(store_id)%ptr + store_c_flux end if @@ -1036,14 +1034,11 @@ subroutine CNPPrioritizedReplacement(this, & end do end if - - - ! Determine nutrient demand and make tansfers do i = 1, n_curpri_org i_org = curpri_org(i) - if(organ_list(i_org).ne.store_organ)then +! if(organ_list(i_org).ne.store_organ)then ! Update the nitrogen deficits ! Note that the nitrogen target is tied to the stoichiometry of thegrowing pool only target_n = this%GetNutrientTarget(nitrogen_element,organ_list(i_org),stoich_growth_min) @@ -1053,10 +1048,10 @@ subroutine CNPPrioritizedReplacement(this, & ! Note that the phsophorus target is tied to the stoichiometry of thegrowing pool only (also) target_p = this%GetNutrientTarget(phosphorus_element,organ_list(i_org),stoich_growth_min) deficit_p(i_org) = max(0.0_r8, target_p - state_p(i_org)%ptr ) - else - deficit_n(i_org) = 0._r8 - deficit_p(i_org) = 0._r8 - end if +! else +! deficit_n(i_org) = 0._r8 +! deficit_p(i_org) = 0._r8 +! end if end do ! Allocate nutrients at this priority level @@ -1070,6 +1065,9 @@ subroutine CNPPrioritizedReplacement(this, & end do priority_loop + + + return end subroutine CNPPrioritizedReplacement @@ -1532,23 +1530,17 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & sum_n_demand = 0._r8 ! For error checking sum_p_demand = 0._r8 ! For error checking do ii = 1, n_mask_organs + i = mask_organs(ii) - if(organ_list(i).ne.store_organ)then - ! Update the nitrogen deficits (which are based off of carbon actual..) - ! Note that the nitrogen target is tied to the stoichiometry of thegrowing pool only - target_n = this%GetNutrientTarget(nitrogen_element,organ_list(i),stoich_growth_min) - deficit_n(i) = this%GetDeficit(nitrogen_element,organ_list(i),target_n) - sum_n_demand = sum_n_demand+max(0._r8,deficit_n(i)) - - ! Update the nitrogen deficits (which are based off of carbon actual..) - ! Note that the nitrogen target is tied to the stoichiometry of thegrowing pool only - target_p = this%GetNutrientTarget(phosphorus_element,organ_list(i),stoich_growth_min) - deficit_p(i) = this%GetDeficit(phosphorus_element,organ_list(i),target_p) - sum_p_demand = sum_p_demand+max(0._r8,deficit_p(i)) - else - deficit_n(i) = 0._r8 - deficit_p(i) = 0._r8 - end if + + target_n = this%GetNutrientTarget(nitrogen_element,organ_list(i),stoich_growth_min) + target_p = this%GetNutrientTarget(phosphorus_element,organ_list(i),stoich_growth_min) + + deficit_n(i) = this%GetDeficit(nitrogen_element,organ_list(i),target_n) + sum_n_demand = sum_n_demand+max(0._r8,deficit_n(i)) + + deficit_p(i) = this%GetDeficit(phosphorus_element,organ_list(i),target_p) + sum_p_demand = sum_p_demand+max(0._r8,deficit_p(i)) end do @@ -1590,7 +1582,7 @@ subroutine CNPAllocateRemainder(this,c_gain, n_gain, p_gain, & real(r8) :: store_c_target ! Target amount of C in storage including "overflow" [kgC] real(r8) :: total_c_flux ! Total C flux from gains into storage and growth R [kgC] real(r8) :: growth_r_flux ! Growth respiration for filling storage [kgC] - real(r8) :: store_c_flux ! Flux into storage [kgC] + real(r8) :: store_m_flux ! Flux into storage [kg] integer, dimension(num_organs),parameter :: all_organs = [1,2,3,4,5,6] real(r8), pointer :: dbh integer :: ipft @@ -1600,7 +1592,8 @@ subroutine CNPAllocateRemainder(this,c_gain, n_gain, p_gain, & dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival - + + ! ----------------------------------------------------------------------------------- ! If nutrients are still available, then we can bump up the values in the pools ! towards the OPTIMAL target values. @@ -1633,6 +1626,7 @@ subroutine CNPAllocateRemainder(this,c_gain, n_gain, p_gain, & p_gain, phosphorus_element, all_organs) + ! Optional hypothesis ( ! If any N or P is still hanging around, put it in storage !state_n(store_id)%ptr = state_n(store_id)%ptr + n_gain @@ -1777,13 +1771,18 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe sapw_c_target*prt_params%nitr_stoich_p2(ipft,prt_params%organ_param_id(sapw_organ)), & struct_c_target*prt_params%nitr_stoich_p2(ipft,prt_params%organ_param_id(struct_organ))) else - + target_m = StorageNutrientTarget(ipft, element_id, & leaf_c_target*prt_params%phos_stoich_p2(ipft,prt_params%organ_param_id(leaf_organ)), & fnrt_c_target*prt_params%phos_stoich_p2(ipft,prt_params%organ_param_id(fnrt_organ)), & sapw_c_target*prt_params%phos_stoich_p2(ipft,prt_params%organ_param_id(sapw_organ)), & struct_c_target*prt_params%phos_stoich_p2(ipft,prt_params%organ_param_id(struct_organ))) - + + end if + + ! Hard-code the growth minimum storage stoichiometry to 75% of maximum + if( stoich_mode == stoich_growth_min ) then + target_m = target_m*0.75_r8 end if elseif(organ_id == repro_organ) then @@ -1898,192 +1897,6 @@ subroutine ProportionalNutrAllocation(state_m, deficit_m, gain_m, element_id, li return end subroutine ProportionalNutrAllocation - ! ===================================================================================== - - - subroutine NAndPToMatchC(this,c_gain_org,dc_dd,ipft,organ_id,n_match,p_match) - - class(cnp_allom_prt_vartypes) :: this ! - real(r8),intent(in) :: c_gain_org ! Fraction of C sent to this organ - ! (does not include resp tax) - real(r8),intent(in) :: dc_dd ! derivative of the target value - integer, intent(in) :: ipft ! pft index - integer, intent(in) :: organ_id ! global organ index - real(r8), intent(inout) :: n_match ! N needed to match C growth - real(r8), intent(inout) :: p_match ! P needed to match C growth - - integer :: c_var_id ! Data array index of the carbon state variable - integer :: np_var_id ! Data array index of the N and P states - real(r8) :: grow_c ! Amount of C that would go into the organs tissue - real(r8) :: c0,d0 ! Variables to save the original C and dbh states - real(r8) :: np_target ! The target amount of N or P at the future C/DBH - - - ! All states are drawn from index 1, which is the growing index - ! for leaves, and the only index of non-leaves. Remember, if - ! this routine is being called, the initial amount of carbon - ! is the on-allometry value. - - c_var_id = prt_global%sp_organ_map(organ_id,carbon12_element) - - ! Save the current carbon and dbh state (we need dbh also - ! because nutient targets may not queue off of current mass, - ! but off of stature) - - c0 = this%variables(c_var_id)%val(1) - d0 = this%bc_inout(acnp_bc_inout_id_dbh)%rval - - ! Given the desired growth, imagine what the future C and dbh states are - this%variables(c_var_id)%val(1) = this%variables(c_var_id)%val(1)+c_gain_org - - ! Reproductive tissues may not have an allometry curve, their - ! target will be based off of actual C anyway - if(dc_dd>nearzero) then - this%bc_inout(acnp_bc_inout_id_dbh)%rval = & - this%bc_inout(acnp_bc_inout_id_dbh)%rval + c_gain_org/dc_dd - end if - - ! Calculate the nitrogen target at this future - np_var_id = prt_global%sp_organ_map(organ_id,nitrogen_element) - np_target = this%GetNutrientTarget(nitrogen_element,organ_id,stoich_growth_min) - - - ! Determine N needed to get match predicted C - n_match = n_match + max(0._r8, np_target - this%variables(np_var_id)%val(1)) - - - - ! Calculate the phosphorus target at this future - np_var_id = prt_global%sp_organ_map(organ_id,phosphorus_element) - np_target = this%GetNutrientTarget(phosphorus_element,organ_id,stoich_growth_min) - - - ! Determine P needed to get match predicted C - p_match = p_match + max(0._r8, np_target - this%variables(np_var_id)%val(1)) - - - ! Return out predictions back to their initial states - ! Save the current carbon and dbh state - this%variables(c_var_id)%val(1) = c0 - this%bc_inout(acnp_bc_inout_id_dbh)%rval = d0 - - - return - end subroutine NAndPToMatchC - - - - - ! ===================================================================================== - - subroutine GrowEquivC(this,carbon_gain,nitrogen_gain,phosphorus_gain, & - alloc_frac,ipft,organ_id,& - grow_c_from_c,grow_c_from_n,grow_c_from_p) - - ! ----------------------------------------------------------------------------------- - ! This subroutine calculates how much growth to expect in the specified organ - ! in terms of equivalent carbon, for each of C, N and P. - ! Total carbon allocated is roughly a function of how much carbon is available, - ! and the growth respiration tax. - ! Equivalent carbon allocated for each nutrient, is roughly the amount of - ! nutrient available, divided through by its stoichiometry, and also incremented - ! by any extra nutrient that may be in the tissues because of flexible stoich. - ! ----------------------------------------------------------------------------------- - - ! Arguments - class(cnp_allom_prt_vartypes) :: this ! - real(r8),intent(in) :: carbon_gain ! Total carbon available for allocation - real(r8),intent(in) :: nitrogen_gain ! Total N available for allocation - real(r8),intent(in) :: phosphorus_gain ! Total P available for allocation - real(r8),intent(in) :: alloc_frac ! - - integer,intent(in) :: ipft - integer,intent(in) :: organ_id - real(r8),intent(inout) :: grow_c_from_c - real(r8),intent(inout) :: grow_c_from_n - real(r8),intent(inout) :: grow_c_from_p - - ! Locals - real(r8) :: grow_c - real(r8) :: c_from_n_headstart - real(r8) :: c_from_n_gain - real(r8) :: c_from_p_headstart - real(r8) :: c_from_p_gain - integer :: c_var_id - integer :: n_var_id - integer :: p_var_id - real(r8) :: c_state - real(r8) :: n_target - real(r8) :: p_target - - ! Calculate gains from carbon - ! ----------------------------------------------------------------------------------- - grow_c = carbon_gain*alloc_frac - - grow_c_from_c = grow_c_from_c + grow_c - - c_var_id = prt_global%sp_organ_map(organ_id,carbon12_element) - - ! Calculate gains from Nitrogen - ! ----------------------------------------------------------------------------------- - - if(prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(organ_id))>nearzero)then - - ! The amount of C we could match with N in the aquisition pool - c_from_n_gain = nitrogen_gain * alloc_frac / prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(organ_id)) - - ! It is possible that the nutrient pool of interest is already above the minimum - ! requirement. In this case, we add that into the amount that the equivalent - ! carbon for that nutrient can get. Its like giving it a head start. - - n_var_id = prt_global%sp_organ_map(organ_id,nitrogen_element) - n_target = this%GetNutrientTarget(nitrogen_element,organ_id,stoich_growth_min) - - c_from_n_headstart = max(0.0_r8, sum(this%variables(n_var_id)%val(:),dim=1) - n_target ) / & - prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(organ_id)) - - - ! Increment the amount of C that we could match with N, as the minimum - ! of what C could do itself, and what N could do. We need this minimum - ! because some pools may have excess, but those excesses cannot travel between - ! pools and contribute to the total allocation - grow_c_from_n = grow_c_from_n + min(grow_c,c_from_n_gain+c_from_n_headstart) - - - - end if - - ! Calculate gains from phosphorus - ! ----------------------------------------------------------------------------------- - - if(prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(organ_id))>nearzero) then - - - c_from_p_gain = phosphorus_gain * alloc_frac / prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(organ_id)) - - ! It is possible that the nutrient pool of interest is already above the minimum - ! requirement. In this case, we add that into the amount that the equivalent - ! carbon for that nutrient can get. Its like giving it a head start. - - p_var_id = prt_global%sp_organ_map(organ_id,phosphorus_element) - p_target = this%GetNutrientTarget(phosphorus_element,organ_id,stoich_growth_min) - - c_from_p_headstart = max(0.0_r8,sum(this%variables(p_var_id)%val(:),dim=1) - p_target ) / & - prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(organ_id)) - - ! Increment the amount of C that we could match with P, as the minimum - ! of what C could do itself, and what P could do. We need this minimum - ! because some pools may have excess, but those excesses cannot travel between - ! pools and contribute to the total allocation - grow_c_from_p = grow_c_from_p + min(grow_c,c_from_p_gain+c_from_p_headstart) - - - end if - - return - end subroutine GrowEquivC - - ! ===================================================================================== function AllomCNPGrowthDeriv(l_state_array,l_state_mask,cbalance,intgr_params) result(dCdx) @@ -2379,7 +2192,7 @@ subroutine StorageRegulator(this,element_id,regulate_type,c_scalar) canopy_trim => this%bc_in(acnp_bc_in_id_ctrim)%rval, & ipft => this%bc_in(acnp_bc_in_id_pft)%ival) - store_max = this%GetNutrientTarget(element_id,store_organ,stoich_max) + store_max = this%GetNutrientTarget(element_id,store_organ,stoich_growth_min) ! Storage fractions could more than the target, depending on the ! hypothesis and functions involved, but should typically be 0-1 @@ -2416,8 +2229,8 @@ subroutine StorageRegulator(this,element_id,regulate_type,c_scalar) else - logi_k = 30.0_r8 - store_x0 = 1.0_r8 + logi_k = 2.0_r8 + store_x0 = 0.0_r8 logi_min = 0.0_r8 store_c = this%GetState(store_organ, carbon12_element) @@ -2428,10 +2241,11 @@ subroutine StorageRegulator(this,element_id,regulate_type,c_scalar) ! we have C, so we downregulate. If this is less than 1, then ! we have less N in storage than we have C, so up-regulate - store_frac = max(0.1_r8,store_frac) / max(0.1_r8,(store_c/store_c_max)) + store_frac = log(max(0.01_r8,store_frac) / max(0.01_r8,(store_c/store_c_max))) - c_scalar = max(c_min,min(c_max,logi_min + (1.0_r8-logi_min)/(1.0_r8 + exp(logi_k*(store_frac-store_x0))))) + c_scalar = max(0._r8,min(1._r8,logi_min + (1._r8-logi_min)/(1.0 + exp(logi_k*(store_frac-store_x0))))) + end if end associate From 561750f0d7a01a1411e2469149d6f7afc16d0394 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 3 Dec 2021 13:59:56 -0500 Subject: [PATCH 073/852] Updates to fates nutrient coupling and feedback algorithm. Modified plants to hold overflow storage in the CNP version, which prevents dumping to soil which would otherwise promote decomposition from reducing mineralized pools. Also, changed storage nutrients to not key off of target root biomass, which was creating an instability in the dynamic root code. --- biogeochem/EDCohortDynamicsMod.F90 | 17 ------------- biogeochem/FatesSoilBGCFluxMod.F90 | 20 +++++++--------- main/EDInitMod.F90 | 2 +- main/EDMainMod.F90 | 12 +++++----- main/EDTypesMod.F90 | 17 ++++--------- main/FatesHistoryInterfaceMod.F90 | 36 ++++++++++++++-------------- main/FatesRestartInterfaceMod.F90 | 20 ---------------- parteh/PRTAllometricCNPMod.F90 | 38 ++++++++++++++---------------- parteh/PRTGenericMod.F90 | 6 ++--- 9 files changed, 58 insertions(+), 110 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 341cf3c836..ea0024eb04 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -95,8 +95,6 @@ module EDCohortDynamicsMod use PRTAllometricCNPMod, only : acnp_bc_in_id_netdnh4, acnp_bc_in_id_netdno3, acnp_bc_in_id_netdp use PRTAllometricCNPMod, only : acnp_bc_out_id_cefflux, acnp_bc_out_id_nefflux use PRTAllometricCNPMod, only : acnp_bc_out_id_pefflux - use PRTAllometricCNPMod, only : acnp_bc_out_id_nneed - use PRTAllometricCNPMod, only : acnp_bc_out_id_pneed use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) @@ -422,8 +420,6 @@ subroutine InitPRTBoundaryConditions(new_cohort) call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_cefflux, bc_rval = new_cohort%daily_c_efflux) call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_nefflux, bc_rval = new_cohort%daily_n_efflux) call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_pefflux, bc_rval = new_cohort%daily_p_efflux) - call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_nneed, bc_rval = new_cohort%daily_n_need) - call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_pneed, bc_rval = new_cohort%daily_p_need) case DEFAULT @@ -576,8 +572,6 @@ subroutine nan_cohort(cc_p) currentCohort%daily_c_efflux = nan currentCohort%daily_n_efflux = nan currentCohort%daily_p_efflux = nan - currentCohort%daily_n_need = nan - currentCohort%daily_p_need = nan currentCohort%daily_n_demand = nan currentCohort%daily_p_demand = nan @@ -695,9 +689,6 @@ subroutine zero_cohort(cc_p) currentCohort%daily_c_efflux = 0._r8 currentCohort%daily_n_efflux = 0._r8 currentCohort%daily_p_efflux = 0._r8 - - currentCohort%daily_n_need = 0._r8 - currentCohort%daily_p_need = 0._r8 ! Initialize these as negative currentCohort%daily_p_demand = -9._r8 @@ -1429,12 +1420,6 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) currentCohort%daily_p_efflux = (currentCohort%n*currentCohort%daily_p_efflux + & nextc%n*nextc%daily_p_efflux)/newn - currentCohort%daily_n_need = (currentCohort%n*currentCohort%daily_n_need + & - nextc%n*nextc%daily_n_need)/newn - currentCohort%daily_p_need = (currentCohort%n*currentCohort%daily_p_need + & - nextc%n*nextc%daily_p_need)/newn - - ! logging mortality, Yi Xu currentCohort%lmort_direct = (currentCohort%n*currentCohort%lmort_direct + & nextc%n*nextc%lmort_direct)/newn @@ -1835,8 +1820,6 @@ subroutine copy_cohort( currentCohort,copyc ) n%daily_c_efflux = o%daily_c_efflux n%daily_n_efflux = o%daily_n_efflux n%daily_p_efflux = o%daily_p_efflux - n%daily_n_need = o%daily_n_need - n%daily_p_need = o%daily_p_need n%daily_n_demand = o%daily_n_demand n%daily_p_demand = o%daily_p_demand diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index e3dd7a76f1..90b79559a2 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -121,7 +121,7 @@ function GetPlantDemand(ccohort,element_id) result(plant_demand) real(r8) :: plant_max_x ! Maximum mass for element of interest [kg] integer :: pft real(r8) :: dbh - real(r8) :: leafm,fnrtm,sapwm,structm,storem + real(r8) :: fnrt_c real(r8), parameter :: smth_fac = 0.1_r8 ! Smoothing factor for updating ! demand. @@ -145,18 +145,19 @@ function GetPlantDemand(ccohort,element_id) result(plant_demand) return end if - + fnrt_c = ccohort%prt%GetState(fnrt_organ, carbon12_element) + ! If the plant is not a newly recruited plant ! We use other methods of specifying nutrient demand ! ----------------------------------------------------------------------------------- if(element_id.eq.nitrogen_element) then - plant_demand = smth_fac*ccohort%daily_n_demand + (1._r8-smth_fac)*max(0._r8,ccohort%daily_n_need) + plant_demand = fnrt_c * EDPftvarcon_inst%eca_vmax_nh4(ccohort%pft) * sec_per_day elseif(element_id.eq.phosphorus_element) then - - plant_demand = smth_fac*ccohort%daily_p_demand + (1._r8-smth_fac)*max(0._r8,ccohort%daily_p_need) + + plant_demand = fnrt_c * EDPftvarcon_inst%eca_vmax_p(ccohort%pft) * sec_per_day end if @@ -241,9 +242,7 @@ subroutine UnPackNutrientAquisitionBCs(sites, bc_in) ccohort => cpatch%tallest do while (associated(ccohort)) icomp = icomp+1 - fnrt_c = ccohort%prt%GetState(fnrt_organ, carbon12_element) - ccohort%daily_n_demand = fnrt_c * ccohort%n * AREA_INV * & - EDPftvarcon_inst%eca_vmax_nh4(ccohort%pft) * sec_per_day + ccohort%daily_n_demand = GetPlantDemand(ccohort,nitrogen_element) ! N Uptake: Convert g/m2/day -> kg/plant/day ccohort%daily_nh4_uptake = bc_in(s)%plant_nh4_uptake_flux(icomp,1)*kg_per_g*AREA/ccohort%n ccohort%daily_no3_uptake = bc_in(s)%plant_no3_uptake_flux(icomp,1)*kg_per_g*AREA/ccohort%n @@ -275,9 +274,7 @@ subroutine UnPackNutrientAquisitionBCs(sites, bc_in) ccohort => cpatch%tallest do while (associated(ccohort)) icomp = icomp+1 - fnrt_c = ccohort%prt%GetState(fnrt_organ, carbon12_element) - ccohort%daily_p_demand = fnrt_c * ccohort%n * AREA_INV * & - EDPftvarcon_inst%eca_vmax_p(ccohort%pft) * sec_per_day + ccohort%daily_p_demand = GetPlantDemand(ccohort,phosphorus_element) ! P Uptake: Convert g/m2/day -> kg/plant/day ccohort%daily_p_uptake = bc_in(s)%plant_p_uptake_flux(icomp,1)*kg_per_g*AREA/ccohort%n ccohort => ccohort%shorter @@ -596,7 +593,6 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) ! ----------------------------------------------------------------------------------- - use FatesConstantsMod, only : sec_per_day use FatesInterfaceTypesMod, only : bc_in_type, bc_out_type use FatesInterfaceTypesMod, only : hlm_use_vertsoilc use FatesInterfaceTypesMod, only : hlm_numlevgrnd diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 875fe4c730..3cdeaf48ea 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -135,7 +135,7 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) allocate(site_in%flux_diags(el)%root_litter_input(1:numpft)) allocate(site_in%flux_diags(el)%nutrient_efflux_scpf(nlevsclass*numpft)) allocate(site_in%flux_diags(el)%nutrient_uptake_scpf(nlevsclass*numpft)) - allocate(site_in%flux_diags(el)%nutrient_need_scpf(nlevsclass*numpft)) + allocate(site_in%flux_diags(el)%nutrient_demand_scpf(nlevsclass*numpft)) end do ! Initialize the static soil diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 5deb2c5084..7d75d8a885 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -493,13 +493,13 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentCohort%daily_c_efflux*currentCohort%n ! Diagnostics on plant nutrient need - currentSite%flux_diags(element_pos(nitrogen_element))%nutrient_need_scpf(iscpf) = & - currentSite%flux_diags(element_pos(nitrogen_element))%nutrient_need_scpf(iscpf) + & - currentCohort%daily_n_need*currentCohort%n + currentSite%flux_diags(element_pos(nitrogen_element))%nutrient_demand_scpf(iscpf) = & + currentSite%flux_diags(element_pos(nitrogen_element))%nutrient_demand_scpf(iscpf) + & + currentCohort%daily_n_demand*currentCohort%n - currentSite%flux_diags(element_pos(phosphorus_element))%nutrient_need_scpf(iscpf) = & - currentSite%flux_diags(element_pos(phosphorus_element))%nutrient_need_scpf(iscpf) + & - currentCohort%daily_p_need*currentCohort%n + currentSite%flux_diags(element_pos(phosphorus_element))%nutrient_demand_scpf(iscpf) = & + currentSite%flux_diags(element_pos(phosphorus_element))%nutrient_demand_scpf(iscpf) + & + currentCohort%daily_p_demand*currentCohort%n end if diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index e8fa27ee8e..6f347b8b41 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -301,17 +301,8 @@ module EDTypesMod real(r8) :: daily_n_efflux ! daily mean efflux of excess nitrogen from roots into labile pool [kg N/plant/day] real(r8) :: daily_p_efflux ! daily mean efflux of excess phophorus from roots into labile pool [kg P/plant/day] - real(r8) :: daily_n_need ! Generic Nitrogen need of the plant, (hypothesis dependent) [kgN/plant/day] - real(r8) :: daily_p_need ! Generic Phosphorus need of the plant, (hypothesis dependent) [kgN/plant/day] - - - ! These two variables may use the previous "need" variables, by applying a smoothing function. - ! These variables are used in two scenarios. 1) They work with the prescribed uptake fraction - ! in un-coupled mode, and 2) They are the plant's demand subbmitted to the Relative-Demand - ! type soil BGC scheme. - - real(r8) :: daily_n_demand ! The daily amount of N demanded by the plant [kgN] - real(r8) :: daily_p_demand ! The daily amount of P demanded by the plant [kgN] + real(r8) :: daily_n_demand ! The daily amount of N demanded by the plant [kgN/plant/day] + real(r8) :: daily_p_demand ! The daily amount of P demanded by the plant [kgN/plant/day] ! The following four biophysical rates are assumed to be @@ -611,7 +602,7 @@ module EDTypesMod real(r8),allocatable :: nutrient_uptake_scpf(:) real(r8),allocatable :: nutrient_efflux_scpf(:) - real(r8),allocatable :: nutrient_need_scpf(:) + real(r8),allocatable :: nutrient_demand_scpf(:) contains @@ -847,7 +838,7 @@ subroutine ZeroFluxDiags(this) this%root_litter_input(:) = 0._r8 this%nutrient_uptake_scpf(:) = 0._r8 this%nutrient_efflux_scpf(:) = 0._r8 - this%nutrient_need_scpf(:) = 0._r8 + this%nutrient_demand_scpf(:) = 0._r8 return end subroutine ZeroFluxDiags diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 8675cf1141..d1dd3b4294 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -181,8 +181,8 @@ module FatesHistoryInterfaceMod integer :: ih_cefflux_si integer :: ih_nefflux_si integer :: ih_pefflux_si - integer :: ih_nneed_si - integer :: ih_pneed_si + integer :: ih_ndemand_si + integer :: ih_pdemand_si integer :: ih_trimming_si integer :: ih_area_plant_si @@ -229,7 +229,7 @@ module FatesHistoryInterfaceMod integer,public :: ih_nh4uptake_scpf integer,public :: ih_no3uptake_scpf integer :: ih_nefflux_scpf - integer :: ih_nneed_scpf + integer :: ih_ndemand_scpf integer :: ih_totvegc_scpf integer :: ih_leafc_scpf @@ -249,7 +249,7 @@ module FatesHistoryInterfaceMod integer :: ih_sapwp_scpf integer,public :: ih_puptake_scpf integer :: ih_pefflux_scpf - integer :: ih_pneed_scpf + integer :: ih_pdemand_scpf integer :: ih_daily_temp integer :: ih_daily_rh @@ -3144,11 +3144,11 @@ subroutine update_history_dyn(this,nc,nsites,sites) this%hvars(ih_nefflux_scpf)%r82d(io_si,:) = & sites(s)%flux_diags(el)%nutrient_efflux_scpf(:) - this%hvars(ih_nneed_scpf)%r82d(io_si,:) = & - sites(s)%flux_diags(el)%nutrient_need_scpf(:) + this%hvars(ih_ndemand_scpf)%r82d(io_si,:) = & + sites(s)%flux_diags(el)%nutrient_demand_scpf(:) - this%hvars(ih_nneed_si)%r81d(io_si) = & - sum(sites(s)%flux_diags(el)%nutrient_need_scpf(:),dim=1) + this%hvars(ih_ndemand_si)%r81d(io_si) = & + sum(sites(s)%flux_diags(el)%nutrient_demand_scpf(:),dim=1) this%hvars(ih_nefflux_si)%r81d(io_si) = & sum(sites(s)%flux_diags(el)%nutrient_efflux_scpf(:),dim=1) @@ -3166,11 +3166,11 @@ subroutine update_history_dyn(this,nc,nsites,sites) this%hvars(ih_pefflux_scpf)%r82d(io_si,:) = & sites(s)%flux_diags(el)%nutrient_efflux_scpf(:) - this%hvars(ih_pneed_scpf)%r82d(io_si,:) = & - sites(s)%flux_diags(el)%nutrient_need_scpf(:) + this%hvars(ih_pdemand_scpf)%r82d(io_si,:) = & + sites(s)%flux_diags(el)%nutrient_demand_scpf(:) - this%hvars(ih_pneed_si)%r81d(io_si) = & - sum(sites(s)%flux_diags(el)%nutrient_need_scpf(:),dim=1) + this%hvars(ih_pdemand_si)%r81d(io_si) = & + sum(sites(s)%flux_diags(el)%nutrient_demand_scpf(:),dim=1) this%hvars(ih_pefflux_si)%r81d(io_si) = & sum(sites(s)%flux_diags(el)%nutrient_efflux_scpf(:),dim=1) @@ -4797,7 +4797,7 @@ subroutine define_history_vars(this, initialize_variables) call this%set_history_var(vname='NNEED', units='kgN d-1 ha-1', & long='Plant nitrogen need (algorithm dependent)', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_nneed_si ) + ivar=ivar, initialize=initialize_variables, index = ih_ndemand_si ) end if nitrogen_active_if @@ -4851,7 +4851,7 @@ subroutine define_history_vars(this, initialize_variables) call this%set_history_var(vname='PNEED', units='kgP ha-1 d-1', & long='Plant phosphorus need (algorithm dependent)', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_pneed_si ) + ivar=ivar, initialize=initialize_variables, index = ih_pdemand_si ) end if phosphorus_active_if @@ -6141,10 +6141,10 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', flushval=hlm_hio_ignore_val, & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nefflux_scpf ) - call this%set_history_var(vname='NNEED_SCPF', units='kgN d-1 ha-1', & + call this%set_history_var(vname='NDEMAND_SCPF', units='kgN d-1 ha-1', & long='plant N need (algorithm dependent), by size-class x pft', use_default='inactive', & avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', flushval=hlm_hio_ignore_val, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nneed_scpf ) + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ndemand_scpf ) end if nitrogen_active_if2 @@ -6200,10 +6200,10 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', flushval=hlm_hio_ignore_val, & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_pefflux_scpf ) - call this%set_history_var(vname='PNEED_SCPF', units='kg/ha/day', & + call this%set_history_var(vname='PDEMAND_SCPF', units='kg/ha/day', & long='plant P need (algorithm dependent), by size-class x pft', use_default='inactive', & avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', flushval=hlm_hio_ignore_val, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_pneed_scpf ) + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_pdemand_scpf ) end if phosphorus_active_if2 diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 7ae00ed0b2..d436924cc8 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -123,8 +123,6 @@ module FatesRestartInterfaceMod integer :: ir_daily_p_efflux_co integer :: ir_daily_n_demand_co integer :: ir_daily_p_demand_co - integer :: ir_daily_n_need_co - integer :: ir_daily_p_need_co !Logging integer :: ir_lmort_direct_co @@ -801,16 +799,6 @@ subroutine define_restart_vars(this, initialize_variables) units='kgN/plant/day', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_daily_n_demand_co ) - call this%set_restart_var(vname='fates_daily_p_need', vtype=cohort_r8, & - long_name='fates cohort- daily phosphorus need', & - units='kgP/plant/day', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_daily_p_need_co ) - - call this%set_restart_var(vname='fates_daily_n_need', vtype=cohort_r8, & - long_name='fates cohort- daily nitrogen need', & - units='kgN/plant/day', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_daily_n_need_co ) - call this%set_restart_var(vname='fates_frmort', vtype=cohort_r8, & long_name='ed cohort - freezing mortality rate', & units='/year', flushval = flushzero, & @@ -1642,8 +1630,6 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_daily_p_efflux_co => this%rvars(ir_daily_p_efflux_co)%r81d, & rio_daily_n_demand_co => this%rvars(ir_daily_n_demand_co)%r81d, & rio_daily_p_demand_co => this%rvars(ir_daily_p_demand_co)%r81d, & - rio_daily_n_need_co => this%rvars(ir_daily_n_need_co)%r81d, & - rio_daily_p_need_co => this%rvars(ir_daily_p_need_co)%r81d, & rio_smort_co => this%rvars(ir_smort_co)%r81d, & rio_asmort_co => this%rvars(ir_asmort_co)%r81d, & rio_frmort_co => this%rvars(ir_frmort_co)%r81d, & @@ -1880,8 +1866,6 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_daily_n_demand_co(io_idx_co) = ccohort%daily_n_demand rio_daily_p_demand_co(io_idx_co) = ccohort%daily_p_demand - rio_daily_n_need_co(io_idx_co) = ccohort%daily_n_need - rio_daily_p_need_co(io_idx_co) = ccohort%daily_p_need !Logging rio_lmort_direct_co(io_idx_co) = ccohort%lmort_direct @@ -2426,8 +2410,6 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_daily_p_efflux_co => this%rvars(ir_daily_p_efflux_co)%r81d, & rio_daily_n_demand_co => this%rvars(ir_daily_n_demand_co)%r81d, & rio_daily_p_demand_co => this%rvars(ir_daily_p_demand_co)%r81d, & - rio_daily_n_need_co => this%rvars(ir_daily_n_need_co)%r81d, & - rio_daily_p_need_co => this%rvars(ir_daily_p_need_co)%r81d, & rio_smort_co => this%rvars(ir_smort_co)%r81d, & rio_asmort_co => this%rvars(ir_asmort_co)%r81d, & rio_frmort_co => this%rvars(ir_frmort_co)%r81d, & @@ -2633,8 +2615,6 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ccohort%daily_n_demand = rio_daily_n_demand_co(io_idx_co) ccohort%daily_p_demand = rio_daily_p_demand_co(io_idx_co) - ccohort%daily_n_need = rio_daily_n_need_co(io_idx_co) - ccohort%daily_p_need = rio_daily_p_need_co(io_idx_co) !Logging ccohort%lmort_direct = rio_lmort_direct_co(io_idx_co) diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index e20c2febce..86c392f755 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -163,8 +163,6 @@ module PRTAllometricCNPMod integer, public, parameter :: acnp_bc_out_id_cefflux = 1 ! Daily exudation of C [kg] integer, public, parameter :: acnp_bc_out_id_nefflux = 2 ! Daily exudation of N [kg] integer, public, parameter :: acnp_bc_out_id_pefflux = 3 ! Daily exudation of P [kg] - integer, public, parameter :: acnp_bc_out_id_nneed = 4 ! N need [kgN] - integer, public, parameter :: acnp_bc_out_id_pneed = 5 ! P need [kgP] integer, parameter :: num_bc_out = 5 ! Total number of @@ -189,6 +187,7 @@ module PRTAllometricCNPMod real(r8), parameter :: store_overflow_frac = 0.15 ! The fraction above target allowed in storage + logical, parameter :: force_store_c_overflow = .true. ! User may want to attempt matching results with the ! C-only allocation module. If so, then set reproduce_conly @@ -297,8 +296,6 @@ subroutine InitPRTGlobalAllometricCNP() call endrun(msg=errMsg(sourcefile, __LINE__)) end if - - call prt_global_acnp%RegisterVarInGlobal(leaf_c_id,'Leaf Carbon','leaf_c',leaf_organ,carbon12_element,nleafage) call prt_global_acnp%RegisterVarInGlobal(fnrt_c_id,'Fine Root Carbon','fnrt_c',fnrt_organ,carbon12_element,icd) call prt_global_acnp%RegisterVarInGlobal(sapw_c_id,'Sapwood Carbon','sapw_c',sapw_organ,carbon12_element,icd) @@ -357,8 +354,6 @@ subroutine DailyPRTAllometricCNP(this) real(r8),pointer :: c_efflux ! Total plant efflux of carbon (kgC) real(r8),pointer :: n_efflux ! Total plant efflux of nitrogen (kgN) real(r8),pointer :: p_efflux ! Total plant efflux of phosphorus (kgP) - real(r8),pointer :: n_need ! N need (algorithm dependant) (kgN) - real(r8),pointer :: p_need ! P need (algorithm dependant) (kgP) real(r8),pointer :: growth_r ! Total plant growth respiration this step (kgC) ! These are pointers to the state variables, rearranged in organ dimensioned @@ -419,8 +414,6 @@ subroutine DailyPRTAllometricCNP(this) c_efflux => this%bc_out(acnp_bc_out_id_cefflux)%rval; c_efflux = 0._r8 n_efflux => this%bc_out(acnp_bc_out_id_nefflux)%rval; n_efflux = 0._r8 p_efflux => this%bc_out(acnp_bc_out_id_pefflux)%rval; p_efflux = 0._r8 - n_need => this%bc_out(acnp_bc_out_id_nneed)%rval; n_need = fates_unset_r8 - p_need => this%bc_out(acnp_bc_out_id_pneed)%rval; p_need = fates_unset_r8 ! In/out boundary conditions maint_r_def => this%bc_inout(acnp_bc_inout_id_rmaint_def)%rval; maint_r_def0 = maint_r_def @@ -631,9 +624,6 @@ subroutine DailyPRTAllometricCNP(this) target_n = this%GetNutrientTarget(nitrogen_element,store_organ,stoich_max) target_p = this%GetNutrientTarget(phosphorus_element,store_organ,stoich_max) - n_need = target_n - state_n(store_id)%ptr - p_need = target_p - state_p(store_id)%ptr - deallocate(state_c) deallocate(state_n) deallocate(state_p) @@ -1644,18 +1634,26 @@ subroutine CNPAllocateRemainder(this,c_gain, n_gain, p_gain, & if(c_gain>calloc_abs_error) then - ! Update carbon based allometric targets - call bstore_allom(dbh,ipft,canopy_trim, store_c_target) - - ! Estimate the overflow - store_c_target = store_c_target * (1.0_r8 + store_overflow_frac) - - total_c_flux = min(c_gain,max(0.0, (store_c_target - state_c(store_id)%ptr))) - + + if(force_store_c_overflow)then + + total_c_flux = c_gain + else + + ! Update carbon based allometric targets + call bstore_allom(dbh,ipft,canopy_trim, store_c_target) + + ! Estimate the overflow + store_c_target = store_c_target * (1.0_r8 + store_overflow_frac) + + total_c_flux = min(c_gain,max(0.0, (store_c_target - state_c(store_id)%ptr))) + + end if ! Transfer excess carbon into storage overflow state_c(store_id)%ptr = state_c(store_id)%ptr + total_c_flux c_gain = c_gain - total_c_flux - + + end if diff --git a/parteh/PRTGenericMod.F90 b/parteh/PRTGenericMod.F90 index 3dab9563a3..cfd398ec58 100644 --- a/parteh/PRTGenericMod.F90 +++ b/parteh/PRTGenericMod.F90 @@ -1425,10 +1425,10 @@ function StorageNutrientTarget(pft, element_id, leaf_target, fnrt_target, sapw_t ! total nitrogen content of 1 or more sets of organs ! ------------------------------------------------------------------------------------- - integer, parameter :: lfs_store_prop = 1 ! leaf-fnrt-sapw proportional storage + integer, parameter :: lfs_store_prop = 1 ! leaf-sapwood proportional storage integer, parameter :: lfss_store_prop = 2 ! leaf-fnrt-sapw-struct proportional storage integer, parameter :: fnrt_store_prop = 3 ! fineroot proportional storage - integer, parameter :: store_prop = fnrt_store_prop + integer, parameter :: store_prop = lfs_store_prop select case(element_id) @@ -1441,7 +1441,7 @@ function StorageNutrientTarget(pft, element_id, leaf_target, fnrt_target, sapw_t if (store_prop == lfs_store_prop) then - store_target = prt_params%nitr_store_ratio(pft) * (leaf_target + fnrt_target + sapw_target) + store_target = prt_params%nitr_store_ratio(pft) * (leaf_target + sapw_target) elseif(store_prop==lfss_store_prop) then From 177876b7ec484ba11108e8cffa0f95541947202b Mon Sep 17 00:00:00 2001 From: JessicaNeedham Date: Thu, 9 Dec 2021 09:44:02 -0800 Subject: [PATCH 074/852] [moving damage module to biogeochem ] [ ] Fixes: [NGT-ED Github issue #] User interface changes?: [ No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary: no testing --- {main => biogeochem}/DamageMainMod.F90 | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {main => biogeochem}/DamageMainMod.F90 (100%) diff --git a/main/DamageMainMod.F90 b/biogeochem/DamageMainMod.F90 similarity index 100% rename from main/DamageMainMod.F90 rename to biogeochem/DamageMainMod.F90 From d700c60e3bc340041b578dc0294f0fe59ea28b58 Mon Sep 17 00:00:00 2001 From: JessicaNeedham Date: Thu, 9 Dec 2021 11:13:56 -0800 Subject: [PATCH 075/852] [bracket the increase in maxCohortsPerPatch in logic so it only increases when damage module is on. ] [don't change maxCohortsPerPatch in EDTypesMod but instead in FatesInterfaceMod ] Fixes: [NGT-ED Github issue #] User interface changes?: [No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary:no testing --- main/EDTypesMod.F90 | 3 ++- main/FatesInterfaceMod.F90 | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 5fde9eef56..9b955bb297 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -20,6 +20,7 @@ module EDTypesMod use FatesConstantsMod, only : days_per_year use FatesInterfaceTypesMod,only : bc_in_type use FatesInterfaceTypesMod,only : bc_out_type + use FatesInterfaceTypesMod,only : hlm_use_canopy_damage, hlm_use_understory_damage implicit none private ! By default everything is private @@ -28,7 +29,7 @@ module EDTypesMod integer, parameter, public :: maxPatchesPerSite = 14 ! maximum number of patches to live on a site integer, parameter, public :: maxPatchesPerSite_by_disttype(n_anthro_disturbance_categories) = & (/ 10, 4 /) !!! MUST SUM TO maxPatchesPerSite !!! - integer, public :: maxCohortsPerPatch = 300 ! maximum number of cohorts per patch + integer, public :: maxCohortsPerPatch = 100 ! maximum number of cohorts per patch integer, parameter, public :: nclmax = 3 ! Maximum number of canopy layers integer, parameter, public :: ican_upper = 1 ! Nominal index for the upper canopy diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 61798dc7d6..17d50b7562 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -765,7 +765,8 @@ subroutine SetFatesGlobalElements(use_fates) ! These values are used to define the restart file allocations and general structure ! of memory for the cohort arrays - if ( hlm_use_cohort_age_tracking .eq. itrue) then + if ( hlm_use_cohort_age_tracking .eq. itrue .or. & + hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then maxCohortsPerPatch = 300 else maxCohortsPerPatch = 100 From 63e513d7324a573d15f90b60ce72a286ca84c849 Mon Sep 17 00:00:00 2001 From: JessicaNeedham Date: Thu, 9 Dec 2021 11:24:14 -0800 Subject: [PATCH 076/852] [ Revert number of canopy layers back to 2 ] [Increased it to 3 to work with Ryan's bci param file but reverting it to 2 for PR ] Fixes: [NGT-ED Github issue #] User interface changes?: [No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary:no testing --- main/EDTypesMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 9b955bb297..2d00a4c6b7 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -31,7 +31,7 @@ module EDTypesMod (/ 10, 4 /) !!! MUST SUM TO maxPatchesPerSite !!! integer, public :: maxCohortsPerPatch = 100 ! maximum number of cohorts per patch - integer, parameter, public :: nclmax = 3 ! Maximum number of canopy layers + integer, parameter, public :: nclmax = 2 ! Maximum number of canopy layers integer, parameter, public :: ican_upper = 1 ! Nominal index for the upper canopy integer, parameter, public :: ican_ustory = 2 ! Nominal index for diagnostics that refer ! to understory layers (all layers that From 7c585f9912eec29b6156ceafd14050017fe99340 Mon Sep 17 00:00:00 2001 From: JessicaNeedham Date: Wed, 15 Dec 2021 07:26:52 -0800 Subject: [PATCH 077/852] [Change min_n_safemath and min_npm2 to default values. ] [Can't remember why I changed these. Possibly to do with termination mortality? ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary:no testing --- main/EDTypesMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 2d00a4c6b7..4bbd2f8ca8 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -167,7 +167,7 @@ module EDTypesMod ! COHORT TERMINATION - real(r8), parameter, public :: min_npm2 = 1.0E-12_r8 ! minimum cohort number density per m2 before termination + real(r8), parameter, public :: min_npm2 = 1.0E-7_r8 ! minimum cohort number density per m2 before termination real(r8), parameter, public :: min_patch_area = 0.01_r8 ! smallest allowable patch area before termination real(r8), parameter, public :: min_patch_area_forced = 0.0001_r8 ! patch termination will not fuse the youngest patch ! if the area is less than min_patch_area. @@ -175,7 +175,7 @@ module EDTypesMod ! if the fusion area is less than min_patch_area_forced real(r8), parameter, public :: min_nppatch = min_npm2*min_patch_area ! minimum number of cohorts per patch (min_npm2*min_patch_area) - real(r8), parameter, public :: min_n_safemath = 1.0E-15_r8 ! in some cases, we want to immediately remove super small + real(r8), parameter, public :: min_n_safemath = 1.0E-12_r8 ! in some cases, we want to immediately remove super small ! number densities of cohorts to prevent FPEs character*4 yearchar From 21b802ba0b7524c5e0311c2463a9e2f74edee58e Mon Sep 17 00:00:00 2001 From: JessicaNeedham Date: Wed, 15 Dec 2021 10:03:45 -0800 Subject: [PATCH 078/852] [ Remove unnecessary history variables] [ Remove the crowndamage x crowndamage dimension, remove unecessary history variables and put all damage history variables in an if statement ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary: no testing --- main/FatesHistoryInterfaceMod.F90 | 587 ++++++++---------------------- main/FatesHistoryVariableType.F90 | 11 +- main/FatesIODimensionsMod.F90 | 6 - main/FatesIOVariableKindMod.F90 | 1 - main/FatesInterfaceMod.F90 | 13 - main/FatesInterfaceTypesMod.F90 | 2 - main/FatesRestartInterfaceMod.F90 | 36 +- 7 files changed, 162 insertions(+), 494 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 7232bc84f7..824b8d4691 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -656,28 +656,15 @@ Module FatesHistoryInterfaceMod integer :: ih_m11_mortality_understory_si_cdsc integer :: ih_m11_mortality_canopy_si_cdpf integer :: ih_m11_mortality_understory_si_cdpf - integer :: ih_trimming_damage_si_cdsc integer :: ih_ddbh_si_cdsc integer :: ih_ddbh_si_cdpf integer :: ih_ddbh_canopy_si_cdpf integer :: ih_ddbh_understory_si_cdpf - ! damage carbonflux - integer :: ih_damage_cflux_si_cdcd - integer :: ih_damage_rate_si_cdcd - integer :: ih_recovery_cflux_si_cdcd - integer :: ih_recovery_rate_si_cdcd + ! crownarea damaged integer :: ih_crownarea_canopy_damage_si integer :: ih_crownarea_ustory_damage_si - integer :: ih_totvegc_cdpf - integer :: ih_leafc_cdpf - integer :: ih_fnrtc_cdpf - integer :: ih_storec_cdpf - integer :: ih_sapwc_cdpf - integer :: ih_reproc_cdpf - integer :: ih_cefflux_cdpf - ! indices to (site x canopy layer) variables integer :: ih_parsun_top_si_can @@ -720,7 +707,6 @@ Module FatesHistoryInterfaceMod integer, private :: levfuel_index_, levcwdsc_index_, levscag_index_ integer, private :: levcan_index_, levcnlf_index_, levcnlfpft_index_ integer, private :: levcdpf_index_, levcdsc_index_ - integer, private :: levcdcd_index_ integer, private :: levscagpft_index_, levagepft_index_ integer, private :: levheight_index_, levagefuel_index_ integer, private :: levelem_index_, levelpft_index_ @@ -756,7 +742,6 @@ Module FatesHistoryInterfaceMod procedure :: levcan_index procedure :: levcnlf_index procedure :: levcnlfpft_index - procedure :: levcdcd_index procedure :: levcdpf_index procedure :: levcdsc_index procedure :: levscag_index @@ -788,7 +773,6 @@ Module FatesHistoryInterfaceMod procedure, private :: set_levcan_index procedure, private :: set_levcnlf_index procedure, private :: set_levcnlfpft_index - procedure, private :: set_levcdcd_index procedure, private :: set_levcdpf_index procedure, private :: set_levcdsc_index procedure, private :: set_levscag_index @@ -828,7 +812,6 @@ subroutine Init(this, num_threads, fates_bounds) use FatesIODimensionsMod, only : levscagpft, levagepft use FatesIODimensionsMod, only : levcan, levcnlf, levcnlfpft use FatesIODimensionsMod, only : levcdpf, levcdsc - use FatesIODimensionsMod, only : levcdcd use FatesIODimensionsMod, only : fates_bounds_type use FatesIODimensionsMod, only : levheight, levagefuel use FatesIODimensionsMod, only : levelem, levelpft @@ -911,11 +894,6 @@ subroutine Init(this, num_threads, fates_bounds) call this%set_levcnlfpft_index(dim_count) call this%dim_bounds(dim_count)%Init(levcnlfpft, num_threads, & fates_bounds%cnlfpft_begin, fates_bounds%cnlfpft_end) - - dim_count = dim_count + 1 - call this%set_levcdcd_index(dim_count) - call this%dim_bounds(dim_count)%Init(levcdcd, num_threads, & - fates_bounds%cdcd_begin, fates_bounds%cdcd_end) dim_count = dim_count + 1 call this%set_levcdpf_index(dim_count) @@ -1043,11 +1021,7 @@ subroutine SetThreadBoundsEach(this, thread_index, thread_bounds) index = this%levcnlfpft_index() call this%dim_bounds(index)%SetThreadBounds(thread_index, & thread_bounds%cnlfpft_begin, thread_bounds%cnlfpft_end) - - index = this%levcdcd_index() - call this%dim_bounds(index)%SetThreadBounds(thread_index, & - thread_bounds%cdcd_begin, thread_bounds%cdcd_end) - + index = this%levcdpf_index() call this%dim_bounds(index)%SetThreadBounds(thread_index, & thread_bounds%cdpf_begin, thread_bounds%cdpf_end) @@ -1108,7 +1082,7 @@ subroutine assemble_history_output_types(this) use FatesIOVariableKindMod, only : site_fuel_r8, site_cwdsc_r8, site_scag_r8 use FatesIOVariableKindMod, only : site_scagpft_r8, site_agepft_r8 use FatesIOVariableKindMod, only : site_can_r8, site_cnlf_r8, site_cnlfpft_r8 - use FatesIOVariableKindMod, only : site_cdpf_r8, site_cdsc_r8, site_cdcd_r8 + use FatesIOVariableKindMod, only : site_cdpf_r8, site_cdsc_r8 use FatesIOVariableKindMod, only : site_height_r8, site_agefuel_r8 use FatesIOVariableKindMod, only : site_elem_r8, site_elpft_r8 use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8 @@ -1165,9 +1139,6 @@ subroutine assemble_history_output_types(this) call this%set_dim_indices(site_cnlfpft_r8, 1, this%column_index()) call this%set_dim_indices(site_cnlfpft_r8, 2, this%levcnlfpft_index()) - call this%set_dim_indices(site_cdcd_r8, 1, this%column_index()) - call this%set_dim_indices(site_cdcd_r8, 2, this%levcdcd_index()) - call this%set_dim_indices(site_cdpf_r8, 1, this%column_index()) call this%set_dim_indices(site_cdpf_r8, 2, this%levcdpf_index()) @@ -1442,20 +1413,6 @@ integer function levcnlfpft_index(this) end function levcnlfpft_index ! ======================================================================= - subroutine set_levcdcd_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levcdcd_index_ = index - end subroutine set_levcdcd_index - - integer function levcdcd_index(this) - implicit none - class(fates_history_interface_type), intent(in) :: this - levcdcd_index = this%levcdcd_index_ - end function levcdcd_index - -! ======================================================================= subroutine set_levcdpf_index(this, index) implicit none class(fates_history_interface_type), intent(inout) :: this @@ -1710,7 +1667,6 @@ subroutine init_dim_kinds_maps(this) use FatesIOVariableKindMod, only : site_scagpft_r8, site_agepft_r8 use FatesIOVariableKindMod, only : site_can_r8, site_cnlf_r8, site_cnlfpft_r8 use FatesIOVariableKindMod, only : site_cdpf_r8, site_cdsc_r8 - use FatesIOVariableKindMod, only : site_cdcd_r8 use FatesIOVariableKindMod, only : site_height_r8, site_agefuel_r8 use FatesIOVariableKindMod, only : site_elem_r8, site_elpft_r8 use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8 @@ -1786,11 +1742,7 @@ subroutine init_dim_kinds_maps(this) ! site x cnlfpft class index = index + 1 call this%dim_kinds(index)%Init(site_cnlfpft_r8, 2) - - ! site x crown damage x crown damage class - index = index + 1 - call this%dim_kinds(index)%Init(site_cdcd_r8, 2) - + ! site x crown damage x pft x size class index = index + 1 call this%dim_kinds(index)%Init(site_cdpf_r8, 2) @@ -1903,7 +1855,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) integer :: iagepft ! age x pft index integer :: i_agefuel ! age x fuel size class index integer :: ican, ileaf, cnlf_indx ! iterators for leaf and canopy level - integer :: icdpf, icdsc, icdcd, icdi, icdj, icdam, imcdam ! iterators for the crown damage level + integer :: icdpf, icdsc, icdi, icdj, icdam, imcdam ! iterators for the crown damage level integer :: cdpf, cdsc integer :: counter integer :: height_bin_max, height_bin_min ! which height bin a given cohort's canopy is in @@ -2103,11 +2055,6 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_nplant_understory_si_cdsc =>this%hvars(ih_nplant_understory_si_cdsc)%r82d, & hio_nplant_canopy_si_cdpf => this%hvars(ih_nplant_canopy_si_cdpf)%r82d, & hio_nplant_understory_si_cdpf =>this%hvars(ih_nplant_understory_si_cdpf)%r82d, & - hio_damage_cflux_si_cdcd => this%hvars(ih_damage_cflux_si_cdcd)%r82d, & - hio_damage_rate_si_cdcd => this%hvars(ih_damage_rate_si_cdcd)%r82d, & - hio_recovery_cflux_si_cdcd => this%hvars(ih_recovery_cflux_si_cdcd)%r82d, & - hio_recovery_rate_si_cdcd => this%hvars(ih_recovery_rate_si_cdcd)%r82d, & - hio_trimming_damage_si_cdsc => this%hvars(ih_trimming_damage_si_cdsc)%r82d, & hio_ddbh_si_cdsc => this%hvars(ih_ddbh_si_cdsc)%r82d, & hio_ddbh_si_cdpf => this%hvars(ih_ddbh_si_cdpf)%r82d, & hio_ddbh_canopy_si_cdpf => this%hvars(ih_ddbh_canopy_si_cdpf)%r82d, & @@ -2283,36 +2230,15 @@ subroutine update_history_dyn(this,nc,nsites,sites) end do - ! damage variables - site level - this needs to be OUT of the patch loop + ! damage variables - site level - this needs to be OUT of the patch loop if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then - icdcd = 1 - - do icdi = 1,ncrowndamage+1 - do icdj = 1,ncrowndamage - hio_damage_cflux_si_cdcd(io_si,icdcd) = & - sites(s)%damage_cflux(icdj,icdi) * g_per_kg * days_per_sec * & - ha_per_m2 - hio_damage_rate_si_cdcd(io_si,icdcd) = & - sites(s)%damage_rate(icdj,icdi) - - hio_recovery_cflux_si_cdcd(io_si,icdcd) = & - sites(s)%recovery_cflux(icdj,icdi) * g_per_kg * days_per_sec * & - ha_per_m2 - hio_recovery_rate_si_cdcd(io_si,icdcd) = & - sites(s)%recovery_rate(icdj,icdi) - - - icdcd = icdcd + 1 - end do - end do - hio_crownarea_canopy_damage_si(io_si) = hio_crownarea_canopy_damage_si(io_si) + & sites(s)%crownarea_canopy_damage * days_per_year hio_crownarea_ustory_damage_si(io_si) = hio_crownarea_ustory_damage_si(io_si) + & sites(s)%crownarea_ustory_damage * days_per_year - + end if hio_canopy_spread_si(io_si) = sites(s)%spread @@ -2780,10 +2706,6 @@ subroutine update_history_dyn(this,nc,nsites,sites) (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & ccohort%n * sec_per_day * days_per_year - - hio_trimming_damage_si_cdsc(io_si,cdsc) = hio_trimming_damage_si_cdsc(io_si,cdsc) + & - ccohort%n * ccohort%canopy_trim - ! crown damage by size hio_nplant_si_cdsc(io_si, cdsc) = hio_nplant_si_cdsc(io_si, cdsc) + ccohort%n hio_m3_si_cdsc(io_si, cdsc) = hio_m3_si_cdsc(io_si, cdsc) + ccohort%cmort * ccohort%n @@ -2804,48 +2726,10 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_ddbh_si_cdpf(io_si,cdpf) = hio_ddbh_si_cdpf(io_si,cdpf) + & ccohort%ddbhdt*ccohort%n + end if + - ! add mortality to the damage rates - - icdam = (ncrowndamage*ncrowndamage) + cdam ! to fill in the last row - - if(hlm_use_canopy_damage .eq. itrue .and. ccohort%canopy_layer == 1 .or. & - hlm_use_understory_damage .eq. itrue .and. ccohort%canopy_layer > 1) then - - hio_damage_rate_si_cdcd(io_si,icdam) = hio_damage_rate_si_cdcd(io_si,icdam) + & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n & - + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & - ccohort%n * sec_per_day * days_per_year - - hio_damage_cflux_si_cdcd(io_si,icdam) = hio_damage_cflux_si_cdcd(io_si,icdam) + & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * & - total_c * ccohort%n * g_per_kg * days_per_sec * years_per_day * ha_per_m2 + & - (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * total_c * & - ccohort%n * g_per_kg * ha_per_m2 - - end if - - ! all crown layers go towards recovery - hio_recovery_rate_si_cdcd(io_si,icdam) = hio_recovery_rate_si_cdcd(io_si,icdam) + & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n & - + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & - ccohort%n * sec_per_day * days_per_year - - hio_recovery_cflux_si_cdcd(io_si,icdam) = hio_recovery_cflux_si_cdcd(io_si,icdam) + & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * & - total_c * ccohort%n * g_per_kg * days_per_sec * years_per_day * ha_per_m2 + & - (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * total_c * & - ccohort%n * g_per_kg * ha_per_m2 - - - end if ! end if damage - - - + ! number density along the cohort age dimension if (hlm_use_cohort_age_tracking .eq.itrue) then hio_nplant_si_capf(io_si,capf) = hio_nplant_si_capf(io_si,capf) + ccohort%n @@ -3460,69 +3344,12 @@ subroutine update_history_dyn(this,nc,nsites,sites) sites(s)%imort_rate_damage(icdam, i_scls, i_pft) + & sites(s)%fmort_rate_ustory_damage(icdam, i_scls, i_pft) - - ! recovery is both canopy layers combined - imcdam = icdam + (ncrowndamage * ncrowndamage) - hio_recovery_rate_si_cdcd(io_si, imcdam) = hio_recovery_rate_si_cdcd(io_si, imcdam) + & - sites(s)%term_nindivs_canopy_damage(icdam, i_scls, i_pft) * days_per_year + & - sites(s)%term_nindivs_ustory_damage(icdam, i_scls, i_pft) * days_per_year + & - sites(s)%imort_rate_damage(icdam, i_scls, i_pft) + & - sites(s)%fmort_rate_canopy_damage(icdam, i_scls, i_pft) + & - sites(s)%fmort_rate_ustory_damage(icdam, i_scls, i_pft) - - hio_recovery_cflux_si_cdcd(io_si, imcdam) = hio_recovery_cflux_si_cdcd(io_si, imcdam) + & - sites(s)%imort_cflux_damage(icdam, i_scls) + & - sites(s)%term_cflux_canopy_damage(icdam, i_scls)*g_per_kg*days_per_sec*ha_per_m2 + & - sites(s)%term_cflux_ustory_damage(icdam, i_scls)*g_per_kg*days_per_sec*ha_per_m2 + & - sites(s)%fmort_cflux_canopy_damage(icdam, i_scls) + & - sites(s)%fmort_cflux_ustory_damage(icdam, i_scls) - - end do end do end do end if - ! only track damage in the canopy layer of interest - if(hlm_use_canopy_damage .eq. itrue ) then - do icdam = 1, ncrowndamage - do i_scls = 1,nlevsclass - do i_pft = 1, numpft - - imcdam = icdam + (ncrowndamage * ncrowndamage) - hio_damage_rate_si_cdcd(io_si, imcdam) = hio_damage_rate_si_cdcd(io_si, imcdam) + & - sites(s)%term_nindivs_canopy_damage(icdam, i_scls, i_pft) * days_per_year + & - sites(s)%fmort_rate_canopy_damage(icdam, i_scls, i_pft) - - hio_damage_cflux_si_cdcd(io_si, imcdam) = hio_damage_cflux_si_cdcd(io_si, imcdam) + & - sites(s)%term_cflux_canopy_damage(icdam, i_scls)*g_per_kg*days_per_sec*ha_per_m2 + & - sites(s)%fmort_cflux_canopy_damage(icdam, i_scls)*g_per_kg*days_per_sec*ha_per_m2 - end do - end do - end do - end if - - if(hlm_use_understory_damage .eq. itrue ) then - do icdam = 1, ncrowndamage - do i_scls = 1,nlevsclass - do i_pft = 1,numpft - - imcdam = icdam + (ncrowndamage * ncrowndamage) - hio_damage_rate_si_cdcd(io_si, imcdam) = hio_damage_rate_si_cdcd(io_si, imcdam) + & - sites(s)%term_nindivs_ustory_damage(icdam, i_scls, i_pft) * days_per_year + & - sites(s)%imort_rate_damage(icdam, i_scls, i_pft) + & - sites(s)%fmort_rate_ustory_damage(icdam, i_scls, i_pft) - - hio_damage_cflux_si_cdcd(io_si, imcdam) = hio_damage_cflux_si_cdcd(io_si, imcdam) + & - sites(s)%imort_cflux_damage(icdam, i_scls) + & - sites(s)%term_cflux_ustory_damage(icdam, i_scls)*g_per_kg*days_per_sec*ha_per_m2 + & - sites(s)%fmort_cflux_canopy_damage(icdam, i_scls) - end do - end do - end do - end if - sites(s)%term_nindivs_canopy(:,:) = 0._r8 sites(s)%term_nindivs_ustory(:,:) = 0._r8 sites(s)%imort_carbonflux = 0._r8 @@ -3670,16 +3497,6 @@ subroutine update_history_dyn(this,nc,nsites,sites) this%hvars(ih_cefflux_si)%r81d(io_si) = & sum(sites(s)%flux_diags(el)%nutrient_efflux_scpf(:),dim=1) - if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue)then - this%hvars(ih_totvegc_cdpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_leafc_cdpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_fnrtc_cdpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_sapwc_cdpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_storec_cdpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_reproc_cdpf)%r82d(io_si,:) = 0._r8 - end if - - elseif(element_list(el).eq.nitrogen_element)then this%hvars(ih_totvegn_scpf)%r82d(io_si,:) = 0._r8 @@ -3864,41 +3681,6 @@ subroutine update_history_dyn(this,nc,nsites,sites) ccohort => ccohort%shorter end do - if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then - ! Load Mass States - ccohort => cpatch%tallest - do while(associated(ccohort)) - - sapw_m = ccohort%prt%GetState(sapw_organ, element_list(el)) - struct_m = ccohort%prt%GetState(struct_organ, element_list(el)) - leaf_m = ccohort%prt%GetState(leaf_organ, element_list(el)) - fnrt_m = ccohort%prt%GetState(fnrt_organ, element_list(el)) - store_m = ccohort%prt%GetState(store_organ, element_list(el)) - repro_m = ccohort%prt%GetState(repro_organ, element_list(el)) - total_m = sapw_m+struct_m+leaf_m+fnrt_m+store_m+repro_m - - icdpf = get_cdamagesizepft_class_index(ccohort%dbh, ccohort%crowndamage, ccohort%pft) - - if(element_list(el).eq.carbon12_element)then - this%hvars(ih_totvegc_cdpf)%r82d(io_si,icdpf) = & - this%hvars(ih_totvegc_cdpf)%r82d(io_si,icdpf) + total_m * ccohort%n - this%hvars(ih_leafc_cdpf)%r82d(io_si,icdpf) = & - this%hvars(ih_leafc_cdpf)%r82d(io_si,icdpf) + leaf_m * ccohort%n - this%hvars(ih_fnrtc_cdpf)%r82d(io_si,icdpf) = & - this%hvars(ih_fnrtc_cdpf)%r82d(io_si,icdpf) + fnrt_m * ccohort%n - this%hvars(ih_sapwc_cdpf)%r82d(io_si,icdpf) = & - this%hvars(ih_sapwc_cdpf)%r82d(io_si,icdpf) + sapw_m * ccohort%n - this%hvars(ih_storec_cdpf)%r82d(io_si,icdpf) = & - this%hvars(ih_storec_cdpf)%r82d(io_si,icdpf) + store_m * ccohort%n - this%hvars(ih_reproc_cdpf)%r82d(io_si,icdpf) = & - this%hvars(ih_reproc_cdpf)%r82d(io_si,icdpf) + repro_m * ccohort%n - end if - - ccohort => ccohort%shorter - end do - end if - - cpatch => cpatch%younger end do @@ -4853,7 +4635,6 @@ subroutine define_history_vars(this, initialize_variables) use FatesIOVariableKindMod, only : site_fuel_r8, site_cwdsc_r8, site_scag_r8 use FatesIOVariableKindMod, only : site_can_r8, site_cnlf_r8, site_cnlfpft_r8 use FatesIOVariableKindMod, only : site_cdsc_r8, site_cdpf_r8 - use FatesIOVariableKindMod, only : site_cdcd_r8 use FatesIOVariableKindMod, only : site_scagpft_r8, site_agepft_r8 use FatesIOVariableKindMod, only : site_elem_r8, site_elpft_r8 use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8 @@ -6080,11 +5861,6 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype =site_size_pft_r8, hlms='CLM:ALM', flushval=0.0_r8, & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m10_si_scpf ) - call this%set_history_var(vname='M11_SCPF', units = 'N/ha/yr', & - long='damage mortality by pft/size',use_default='inactive', & - avgflag='A', vtype =site_size_pft_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_si_scpf ) - call this%set_history_var(vname='M10_CAPF',units='N/ha/yr', & long='age senescence mortality by pft/cohort age',use_default='inactive', & avgflag='A', vtype =site_coage_pft_r8, hlms='CLM:ALM', flushval=0.0_r8, & @@ -6611,204 +6387,157 @@ subroutine define_history_vars(this, initialize_variables) long='RESP_M for understory plants by size class', use_default='inactive', & avgflag='A', vtype=site_size_r8, hlms='CLM:ALM', flushval=0.0_r8, & upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_resp_m_understory_si_scls ) - - - ! CROWN DAMAGE VARIABLES - - call this%set_history_var(vname='DAMAGE_CFLUX_CDCD', units = 'g C / m2 / sec', & - long='damage carbonflux between damage classes', use_default='inactive', & - avgflag='A', vtype=site_cdcd_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_damage_cflux_si_cdcd ) - - call this%set_history_var(vname='DAMAGE_RATE_CDCD', units = 'N / ha / year', & - long='damage rate between damage classes', use_default='inactive', & - avgflag='A', vtype=site_cdcd_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_damage_rate_si_cdcd ) - - call this%set_history_var(vname='RECOVERY_CFLUX_CDCD', units = 'g C / m2 / sec', & - long='recovery carbonflux between damage classes', use_default='inactive', & - avgflag='A', vtype=site_cdcd_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_recovery_cflux_si_cdcd ) - - call this%set_history_var(vname='RECOVERY_RATE_CDCD', units = 'N / ha / year', & - long='recovery rate between damage classes', use_default='inactive', & - avgflag='A', vtype=site_cdcd_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_recovery_rate_si_cdcd ) - - call this%set_history_var(vname='CROWNAREA_CANOPY_DAMAGE', units = 'm2 / ha / year', & - long='crownarea lost to damage each year', use_default='inactive', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_crownarea_canopy_damage_si ) - - call this%set_history_var(vname='CROWNAREA_USTORY_DAMAGE', units = 'm2 / ha / year', & - long='crownarea lost to damage each year', use_default='inactive', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_crownarea_ustory_damage_si ) - - call this%set_history_var(vname='NPLANT_CDSC', units = 'N / damage x size class / ha / yr', & - long='N. plants per damage x size class', use_default='inactive', & - avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_si_cdsc ) - - call this%set_history_var(vname='NPLANT_CDPF', units = 'N / damage x size x pft class / ha / yr', & - long='N. plants per damage x size x pft class', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_si_cdpf ) - - call this%set_history_var(vname='NPLANT_CANOPY_CDSC', units = 'N / damage x size class / ha / yr', & - long='N. plants in the canopy per damage x size class', use_default='inactive', & - avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_canopy_si_cdsc ) - - call this%set_history_var(vname='NPLANT_CANOPY_CDPF', units = 'N / damage x size x pft class / ha / yr', & - long='N. plants per damage x size x pft class', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_canopy_si_cdpf ) - - call this%set_history_var(vname='NPLANT_UNDERSTORY_CDSC', units = 'N / damage x size class / ha / yr', & - long='N. plants in the understory per damage x size class', use_default='inactive', & - avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_understory_si_cdsc ) - - call this%set_history_var(vname='NPLANT_UNDERSTORY_CDPF', units = 'N / damage x size x pft class / ha / yr', & - long='N. plants in the understory per damage x size x pft class', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_understory_si_cdpf ) - - call this%set_history_var(vname='M3_CDPF', units = 'N/ha/yr', & - long='carbon starvation mortality by damaage/pft/size', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_si_cdpf ) - - call this%set_history_var(vname='M3_CDSC', units = 'N/ha/yr', & - long='carbon starvation mortality by damage/size', use_default='inactive', & - avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_si_cdsc ) - - call this%set_history_var(vname='M11_CDPF', units = 'N/ha/yr', & - long='damage mortality by damaage/pft/size', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_si_cdpf ) - call this%set_history_var(vname='M11_CDSC', units = 'N/ha/yr', & - long='damage mortality by damage/size', use_default='inactive', & - avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_si_cdsc ) - - call this%set_history_var(vname='MORTALITY_CDSC', units = 'N/ha/yr', & - long='mortality by damage class by size', use_default='inactive', & - avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_si_cdsc ) - - call this%set_history_var(vname='MORTALITY_CDPF', units = 'N/ha/yr', & - long='mortality by damage class by size by pft', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_si_cdpf ) - call this%set_history_var(vname='M3_MORTALITY_CANOPY_CDSC', units = 'indiv/ha/yr', & - long='C starviation mortality of canopy trees by damage/size class', use_default='inactive', & - avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_canopy_si_cdsc) - - call this%set_history_var(vname='M3_MORTALITY_CANOPY_CDPF', units = 'N/ha/yr', & - long='C starvation mortality of canopy plants by damage/pft/size', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_canopy_si_cdpf ) + ! CROWN DAMAGE VARIABLES + if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + + call this%set_history_var(vname='CROWNAREA_CANOPY_DAMAGE', units = 'm2 / ha / year', & + long='crownarea lost to damage each year', use_default='inactive', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_crownarea_canopy_damage_si ) + + call this%set_history_var(vname='CROWNAREA_USTORY_DAMAGE', units = 'm2 / ha / year', & + long='crownarea lost to damage each year', use_default='inactive', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_crownarea_ustory_damage_si ) + + call this%set_history_var(vname='NPLANT_CDSC', units = 'N / damage x size class / ha / yr', & + long='N. plants per damage x size class', use_default='inactive', & + avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_si_cdsc ) + + call this%set_history_var(vname='NPLANT_CDPF', units = 'N / damage x size x pft class / ha / yr', & + long='N. plants per damage x size x pft class', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_si_cdpf ) + + call this%set_history_var(vname='NPLANT_CANOPY_CDSC', units = 'N / damage x size class / ha / yr', & + long='N. plants in the canopy per damage x size class', use_default='inactive', & + avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_canopy_si_cdsc ) + + call this%set_history_var(vname='NPLANT_CANOPY_CDPF', units = 'N / damage x size x pft class / ha / yr', & + long='N. plants per damage x size x pft class', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_canopy_si_cdpf ) + + call this%set_history_var(vname='NPLANT_UNDERSTORY_CDSC', units = 'N / damage x size class / ha / yr', & + long='N. plants in the understory per damage x size class', use_default='inactive', & + avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_understory_si_cdsc ) + + call this%set_history_var(vname='NPLANT_UNDERSTORY_CDPF', units = 'N / damage x size x pft class / ha / yr', & + long='N. plants in the understory per damage x size x pft class', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_understory_si_cdpf ) + + call this%set_history_var(vname='M3_CDPF', units = 'N/ha/yr', & + long='carbon starvation mortality by damaage/pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_si_cdpf ) + + call this%set_history_var(vname='M3_CDSC', units = 'N/ha/yr', & + long='carbon starvation mortality by damage/size', use_default='inactive', & + avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_si_cdsc ) + + call this%set_history_var(vname='M11_SCPF', units = 'N/ha/yr', & + long='damage mortality by pft/size',use_default='inactive', & + avgflag='A', vtype =site_size_pft_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_si_scpf ) + + call this%set_history_var(vname='M11_CDPF', units = 'N/ha/yr', & + long='damage mortality by damaage/pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_si_cdpf ) + + call this%set_history_var(vname='M11_CDSC', units = 'N/ha/yr', & + long='damage mortality by damage/size', use_default='inactive', & + avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_si_cdsc ) + + call this%set_history_var(vname='MORTALITY_CDSC', units = 'N/ha/yr', & + long='mortality by damage class by size', use_default='inactive', & + avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_si_cdsc ) + + call this%set_history_var(vname='MORTALITY_CDPF', units = 'N/ha/yr', & + long='mortality by damage class by size by pft', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_si_cdpf ) + + call this%set_history_var(vname='M3_MORTALITY_CANOPY_CDSC', units = 'indiv/ha/yr', & + long='C starviation mortality of canopy trees by damage/size class', use_default='inactive', & + avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_canopy_si_cdsc) + + call this%set_history_var(vname='M3_MORTALITY_CANOPY_CDPF', units = 'N/ha/yr', & + long='C starvation mortality of canopy plants by damage/pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_canopy_si_cdpf ) + + call this%set_history_var(vname='M3_MORTALITY_UNDERSTORY_CDPF', units = 'N/ha/yr', & + long='C starvation mortality of understory plants by pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_understory_si_cdpf ) + + call this%set_history_var(vname='M3_MORTALITY_UNDERSTORY_CDSC', units = 'indiv/ha/yr', & + long='C starvation mortality of understory trees by damage/size class', use_default='inactive', & + avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_understory_si_cdsc) + + call this%set_history_var(vname='M11_MORTALITY_CANOPY_CDSC', units = 'indiv/ha/yr', & + long='damage mortality of canopy trees by damage/size class', use_default='inactive', & + avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_canopy_si_cdsc) + + call this%set_history_var(vname='M11_MORTALITY_CANOPY_CDPF', units = 'N/ha/yr', & + long='damage mortality of canopy plants by damage/pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_canopy_si_cdpf ) + + call this%set_history_var(vname='M11_MORTALITY_UNDERSTORY_CDPF', units = 'N/ha/yr', & + long='damage mortality of understory plants by pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_understory_si_cdpf ) + + call this%set_history_var(vname='MORTALITY_CANOPY_CDPF', units = 'N/ha/yr', & + long='mortality of canopy plants by damage/pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_canopy_si_cdpf ) + + call this%set_history_var(vname='MORTALITY_UNDERSTORY_CDPF', units = 'N/ha/yr', & + long='mortality of understory plants by pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_understory_si_cdpf ) + + call this%set_history_var(vname='M11_MORTALITY_UNDERSTORY_CDSC', units = 'indiv/ha/yr', & + long='damage mortality of understory trees by damage/size class', use_default='inactive', & + avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_understory_si_cdsc) + + call this%set_history_var(vname='DDBH_CDSC', units = 'cm/year/ha', & + long='ddbh annual increment growth by damage and size', use_default='inactive', & + avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_si_cdsc ) + + call this%set_history_var(vname='DDBH_CDPF', units = 'cm/year/ha', & + long='ddbh annual increment growth by damage x size pft', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_si_cdpf ) + + call this%set_history_var(vname='DDBH_CANOPY_CDPF', units = 'cm/year/ha', & + long='ddbh annual canopy increment growth by damage x size pft', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_canopy_si_cdpf ) + + call this%set_history_var(vname='DDBH_UNDERSTORY_CDPF', units = 'cm/year/ha', & + long='ddbh annual understory increment growth by damage x size pft', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_understory_si_cdpf ) - call this%set_history_var(vname='M3_MORTALITY_UNDERSTORY_CDPF', units = 'N/ha/yr', & - long='C starvation mortality of understory plants by pft/size', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_understory_si_cdpf ) - - call this%set_history_var(vname='M3_MORTALITY_UNDERSTORY_CDSC', units = 'indiv/ha/yr', & - long='C starvation mortality of understory trees by damage/size class', use_default='inactive', & - avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_understory_si_cdsc) - - call this%set_history_var(vname='M11_MORTALITY_CANOPY_CDSC', units = 'indiv/ha/yr', & - long='damage mortality of canopy trees by damage/size class', use_default='inactive', & - avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_canopy_si_cdsc) - - call this%set_history_var(vname='M11_MORTALITY_CANOPY_CDPF', units = 'N/ha/yr', & - long='damage mortality of canopy plants by damage/pft/size', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_canopy_si_cdpf ) - - call this%set_history_var(vname='M11_MORTALITY_UNDERSTORY_CDPF', units = 'N/ha/yr', & - long='damage mortality of understory plants by pft/size', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_understory_si_cdpf ) - - call this%set_history_var(vname='MORTALITY_CANOPY_CDPF', units = 'N/ha/yr', & - long='mortality of canopy plants by damage/pft/size', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_canopy_si_cdpf ) - - call this%set_history_var(vname='MORTALITY_UNDERSTORY_CDPF', units = 'N/ha/yr', & - long='mortality of understory plants by pft/size', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_understory_si_cdpf ) - - call this%set_history_var(vname='M11_MORTALITY_UNDERSTORY_CDSC', units = 'indiv/ha/yr', & - long='damage mortality of understory trees by damage/size class', use_default='inactive', & - avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_understory_si_cdsc) - - call this%set_history_var(vname='TRIMMING_DAMAGE_CDSC', units = 'indiv/ha', & - long='trimming term of plants by size class by damage class', use_default='inactive', & - avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_trimming_damage_si_cdsc ) - - call this%set_history_var(vname='DDBH_CDSC', units = 'cm/year/ha', & - long='ddbh annual increment growth by damage and size', use_default='inactive', & - avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_si_cdsc ) - - call this%set_history_var(vname='DDBH_CDPF', units = 'cm/year/ha', & - long='ddbh annual increment growth by damage x size pft', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_si_cdpf ) - - call this%set_history_var(vname='DDBH_CANOPY_CDPF', units = 'cm/year/ha', & - long='ddbh annual canopy increment growth by damage x size pft', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_canopy_si_cdpf ) - - call this%set_history_var(vname='DDBH_UNDERSTORY_CDPF', units = 'cm/year/ha', & - long='ddbh annual understory increment growth by damage x size pft', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_understory_si_cdpf ) - - call this%set_history_var(vname='TOTVEGC_CDPF', units='kgC/ha', & - long='total vegetation carbon mass in live plants by damage x size-class x pft', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=hlm_hio_ignore_val, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_totvegc_cdpf ) - - call this%set_history_var(vname='LEAFC_CDPF', units='kgC/ha', & - long='leaf carbon mass by damage x size-class x pft', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=hlm_hio_ignore_val, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_leafc_cdpf ) - - call this%set_history_var(vname='FNRTC_CDPF', units='kgC/ha', & - long='fine-root carbon mass by damage x size-class x pft', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=hlm_hio_ignore_val, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_fnrtc_cdpf ) - - call this%set_history_var(vname='SAPWC_CDPF', units='kgC/ha', & - long='sapwood carbon mass by damage x size-class x pft', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=hlm_hio_ignore_val, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_sapwc_cdpf ) - - call this%set_history_var(vname='STOREC_CDPF', units='kgC/ha', & - long='storage carbon mass by damage x size-class x pft', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=hlm_hio_ignore_val, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_storec_cdpf ) - - call this%set_history_var(vname='REPROC_CDPF', units='kgC/ha', & - long='reproductive carbon mass (on plant) by damage x size-class x pft', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', flushval=hlm_hio_ignore_val, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_reproc_cdpf ) + end if ! CARBON BALANCE VARIABLES THAT DEPEND ON HLM BGC INPUTS diff --git a/main/FatesHistoryVariableType.F90 b/main/FatesHistoryVariableType.F90 index ee8aa9d858..5263bf3ec2 100644 --- a/main/FatesHistoryVariableType.F90 +++ b/main/FatesHistoryVariableType.F90 @@ -13,7 +13,6 @@ module FatesHistoryVariableType use FatesIOVariableKindMod, only : site_scagpft_r8, site_agepft_r8 use FatesIOVariableKindMod, only : site_can_r8, site_cnlf_r8, site_cnlfpft_r8 use FatesIOVariableKindMod, only : site_cdamage_r8, site_cdsc_r8, site_cdpf_r8 - use FatesIOVariableKindMod, only : site_cdcd_r8 use FatesIOVariableKindMod, only : site_elem_r8, site_elpft_r8 use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8 use FatesIOVariableKindMod, only : iotype_index, site_agefuel_r8 @@ -175,15 +174,11 @@ subroutine Init(this, vname, units, long, use_default, & allocate(this%r82d(lb1:ub1, lb2:ub2)) this%r82d(:,:) = flushval - case(site_cdamage_r8) + case(site_cdsc_r8) allocate(this%r82d(lb1:ub1, lb2:ub2)) this%r82d(:,:) = flushval - case(site_cdcd_r8) - allocate(this%r82d(lb1:ub1, lb2:ub2)) - this%r82d(:,:) = flushval - - case(site_cdsc_r8) + case(site_cdamage_r8) allocate(this%r82d(lb1:ub1, lb2:ub2)) this%r82d(:,:) = flushval @@ -336,8 +331,6 @@ subroutine Flush(this, thread, dim_bounds, dim_kinds) this%r82d(lb1:ub1, lb2:ub2) = this%flushval case(site_cdamage_r8) this%r82d(lb1:ub1, lb2:ub2) = this%flushval - case(site_cdcd_r8) - this%r82d(lb1:ub1, lb2:ub2) = this%flushval case(site_cdsc_r8) this%r82d(lb1:ub1, lb2:ub2) = this%flushval case(site_cdpf_r8) diff --git a/main/FatesIODimensionsMod.F90 b/main/FatesIODimensionsMod.F90 index 58cb898632..09bead9bc4 100644 --- a/main/FatesIODimensionsMod.F90 +++ b/main/FatesIODimensionsMod.F90 @@ -27,7 +27,6 @@ module FatesIODimensionsMod character(*), parameter, public :: levcan = 'fates_levcan' ! matches histFileMod character(*), parameter, public :: levcnlf = 'fates_levcnlf' ! matches histFileMod character(*), parameter, public :: levcnlfpft = 'fates_levcnlfpf' ! matches histFileMod - character(*), parameter, public :: levcdcd = 'fates_levcdcd' ! matches histFileMod character(*), parameter, public :: levcdsc = 'fates_levcdsc' ! matches histFileMod character(*), parameter, public :: levcdpf = 'fates_levcdpf' ! matches histFileMod character(*), parameter, public :: levagefuel = 'fates_levagefuel' ! matches histFileMod @@ -83,9 +82,6 @@ module FatesIODimensionsMod ! levcnlfpft = This is a structure that records the boundaries for the ! number of canopy layer x leaf layer x pft dimension - ! levcdcd = This is a structure that records the boundaries for the - ! number of crown damage x crown damage classes - for diagnostic fluxes - ! levcdsc = This is a structure that records the boundaries for the ! number of crown damage x size classes dimension @@ -151,8 +147,6 @@ module FatesIODimensionsMod integer :: cnlfpft_end integer :: cdamage_begin integer :: cdamage_end - integer :: cdcd_begin - integer :: cdcd_end integer :: cdsc_begin integer :: cdsc_end integer :: cdpf_begin diff --git a/main/FatesIOVariableKindMod.F90 b/main/FatesIOVariableKindMod.F90 index 06f6c421ea..749ced2c35 100644 --- a/main/FatesIOVariableKindMod.F90 +++ b/main/FatesIOVariableKindMod.F90 @@ -32,7 +32,6 @@ module FatesIOVariableKindMod character(*), parameter, public :: site_cnlf_r8 = 'SI_CNLF_R8' character(*), parameter, public :: site_cnlfpft_r8 = 'SI_CNLFPFT_R8' character(*), parameter, public :: site_cdamage_r8 = 'SI_CDAMAGE_R8' - character(*), parameter, public :: site_cdcd_r8 = 'SI_CDCD_R8' character(*), parameter, public :: site_cdpf_r8 = 'SI_CDPF_R8' character(*), parameter, public :: site_cdsc_r8 = 'SI_CDSC_R8' character(*), parameter, public :: site_scag_r8 = 'SI_SCAG_R8' diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 17d50b7562..50b11093b8 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -964,7 +964,6 @@ subroutine fates_history_maps integer :: ifuel integer :: ican integer :: icdam - integer :: icdcd integer :: ileaf integer :: iage integer :: iheight @@ -984,8 +983,6 @@ subroutine fates_history_maps allocate( fates_hdim_camap_levcapf(1:nlevcoage*numpft)) allocate( fates_hdim_levcdam(ncrowndamage )) - allocate( fates_hdim_cdimap_levcdcd(ncrowndamage*(ncrowndamage+1))) - allocate( fates_hdim_cdjmap_levcdcd(ncrowndamage*(ncrowndamage+1))) allocate( fates_hdim_scmap_levcdsc(nlevsclass*ncrowndamage)) allocate( fates_hdim_cdmap_levcdsc(nlevsclass*ncrowndamage)) allocate( fates_hdim_scmap_levcdpf(nlevsclass*ncrowndamage * numpft)) @@ -1128,16 +1125,6 @@ subroutine fates_history_maps end do end do - i=0 - do icdam=1,ncrowndamage - do icdcd=1,ncrowndamage+1 - i=i+1 - fates_hdim_cdimap_levcdcd(i) = icdcd - fates_hdim_cdjmap_levcdcd(i) = icdam - end do - end do - - i=0 do ipft=1,numpft do ican=1,nclmax diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index b53e891ad1..f0b3b7b09d 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -245,8 +245,6 @@ module FatesInterfaceTypesMod integer , public, allocatable :: fates_hdim_scmap_levcdpf(:) ! map of size into size x crowndamage x pft integer , public, allocatable :: fates_hdim_cdmap_levcdsc(:) ! map of crowndamage into size x crowndamage integer , public, allocatable :: fates_hdim_scmap_levcdsc(:) ! map of size into size x crowndamage - integer , public, allocatable :: fates_hdim_cdimap_levcdcd(:) ! map of current damage into damage x damage + mortality - integer , public, allocatable :: fates_hdim_cdjmap_levcdcd(:) ! map of new damage into damage x damage + mortality real(r8), public, allocatable :: fates_hdim_levage(:) ! patch age lower bound dimension real(r8), public, allocatable :: fates_hdim_levheight(:) ! height lower bound dimension diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index e8a0469d1d..42be152cb7 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -1752,7 +1752,6 @@ subroutine set_restart_vectors(this,nc,nsites,sites) integer :: io_idx_si_cacls ! each cohort age class index within site integer :: io_idx_si_cdsc ! each damage-class x size class within site integer :: io_idx_si_cdpf ! each damage-class x size x pft within site - integer :: io_idx_si_cdcd ! each damage x damage within site (plus mortality) integer :: io_idx_si_cwd ! each site-cwd index integer :: io_idx_si_pft ! each site-pft index integer :: io_idx_si_vtmem ! indices for veg-temp memory at site @@ -1931,7 +1930,6 @@ subroutine set_restart_vectors(this,nc,nsites,sites) io_idx_si_sc = io_idx_co_1st io_idx_si_capf = io_idx_co_1st io_idx_si_cacls= io_idx_co_1st - io_idx_si_cdcd = io_idx_co_1st io_idx_si_cdsc = io_idx_co_1st io_idx_si_cdpf = io_idx_co_1st @@ -2284,23 +2282,6 @@ subroutine set_restart_vectors(this,nc,nsites,sites) ! this only copies live portions of transitions - but that's ok because the mortality ! bit only needs to be added for history outputs if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then - do icdi = 1,ncrowndamage - do icdj = 1,ncrowndamage+1 - - rio_damage_cflux_sicd(io_idx_si_cdcd) = & - sites(s)%damage_cflux(icdi,icdj) - rio_damage_rate_sicd(io_idx_si_cdcd) = & - sites(s)%damage_rate(icdi,icdj) - - rio_recovery_cflux_sicd(io_idx_si_cdcd) = & - sites(s)%recovery_cflux(icdi,icdj) - rio_recovery_rate_sicd(io_idx_si_cdcd) = & - sites(s)%recovery_rate(icdi,icdj) - - io_idx_si_cdcd = io_idx_si_cdcd + 1 - - end do - end do do i_scls = 1, nlevsclass do i_cdam = 1, ncrowndamage @@ -2663,7 +2644,6 @@ subroutine get_restart_vectors(this, nc, nsites, sites) integer :: io_idx_si_sc ! each size-class index within site integer :: io_idx_si_cacls ! each coage class index within site integer :: io_idx_si_capf ! each cohort age class x pft index within site - integer :: io_idx_si_cdcd ! each damage x damage class within site + mortality integer :: io_idx_si_cwd integer :: io_idx_si_pft integer :: io_idx_si_cdsc ! each damage x size class within site @@ -2831,7 +2811,6 @@ subroutine get_restart_vectors(this, nc, nsites, sites) io_idx_si_sc = io_idx_co_1st io_idx_si_capf = io_idx_co_1st io_idx_si_cacls= io_idx_co_1st - io_idx_si_cdcd = io_idx_co_1st io_idx_si_cdsc = io_idx_co_1st io_idx_si_cdpf = io_idx_co_1st @@ -3240,21 +3219,10 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%crownarea_canopy_damage = rio_crownarea_cano_damage_si(io_idx_si) sites(s)%crownarea_ustory_damage = rio_crownarea_usto_damage_si(io_idx_si) - - ! this only copies live portions of transitions - but that's ok because the mortality - ! bit only needs to be added for history outputs - do icdi = 1,ncrowndamage - do icdj = 1,ncrowndamage+1 - sites(s)%damage_cflux(icdi,icdj) = rio_damage_cflux_sicd(io_idx_si_cdcd) - sites(s)%damage_rate(icdi,icdj) = rio_damage_rate_sicd(io_idx_si_cdcd) - sites(s)%recovery_cflux(icdi,icdj) = rio_recovery_cflux_sicd(io_idx_si_cdcd) - sites(s)%recovery_rate(icdi,icdj) = rio_recovery_rate_sicd(io_idx_si_cdcd) - io_idx_si_cdcd = io_idx_si_cdcd + 1 - end do - end do + end if - + sites(s)%term_carbonflux_canopy = rio_termcflux_cano_si(io_idx_si) sites(s)%term_carbonflux_ustory = rio_termcflux_usto_si(io_idx_si) From efeb6802235def56b3b1d3c10b5435f6ed123c53 Mon Sep 17 00:00:00 2001 From: JessicaNeedham Date: Thu, 16 Dec 2021 03:26:25 -0800 Subject: [PATCH 079/852] [ Add comments to FatesAllometry related to crown damage ] [ ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary:no testing --- biogeochem/FatesAllometryMod.F90 | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index d94b5d4adb..8ea994d7fd 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -172,7 +172,7 @@ subroutine CheckIntegratedAllometries(dbh,ipft,crowndamage, branch_frac, & real(r8),intent(in) :: dbh ! diameter of plant [cm] integer,intent(in) :: ipft ! plant functional type index - integer,intent(in) :: crowndamage + integer,intent(in) :: crowndamage ! crowndamage [1: undamaged, >1 damaged] real(r8),intent(in) :: branch_frac real(r8),intent(in) :: canopy_trim ! trimming function real(r8),intent(in) :: bl ! integrated leaf biomass [kgC] @@ -367,7 +367,7 @@ subroutine bagw_allom(d,ipft,crowndamage, branch_frac, bagw,dbagwdd) real(r8),intent(in) :: d ! plant diameter [cm] integer(i4),intent(in) :: ipft ! PFT index - integer(i4),intent(in) :: crowndamage + integer(i4),intent(in) :: crowndamage ! crowndamage [1: undamaged, >1: damaged] real(r8),intent(in) :: branch_frac real(r8),intent(out) :: bagw ! biomass above ground woody tissues real(r8),intent(out),optional :: dbagwdd ! change in agbw per diameter [kgC/cm] @@ -460,7 +460,7 @@ subroutine carea_allom(dbh,nplant,site_spread,ipft,crowndamage,c_area,inverse) real(r8),intent(in) :: site_spread ! site level spread factor (crowdedness) real(r8),intent(in) :: nplant ! number of plants [1/ha] integer(i4),intent(in) :: ipft ! PFT index - integer(i4),intent(in) :: crowndamage ! crown damage class of the cohort + integer(i4),intent(in) :: crowndamage ! crown damage class [1: undamaged, >1: damaged] real(r8),intent(inout) :: c_area ! crown area per cohort (m2) logical,optional,intent(in) :: inverse ! if true, calculate dbh from crown area ! instead of crown area from dbh @@ -545,7 +545,7 @@ subroutine bleaf(d,ipft,crowndamage,canopy_trim,bl,dbldd) real(r8),intent(in) :: d ! plant diameter [cm] integer(i4),intent(in) :: ipft ! PFT index - integer(i4),intent(in) :: crowndamage ! crown damage class + integer(i4),intent(in) :: crowndamage ! crown damage class [1: undamaged, >1: damaged] real(r8),intent(in) :: canopy_trim ! trimming function real(r8),intent(out) :: bl ! plant leaf biomass [kg] real(r8),intent(out),optional :: dbldd ! change leaf bio per diameter [kgC/cm] @@ -897,7 +897,7 @@ subroutine bsap_allom(d,ipft,crowndamage, branch_frac, canopy_trim,sapw_area,bsa real(r8),intent(in) :: d ! plant diameter [cm] integer(i4),intent(in) :: ipft ! PFT index - integer(i4),intent(in) :: crowndamage + integer(i4),intent(in) :: crowndamage ! Crown damage class [1: undamaged, >1: damaged] real(r8),intent(in) :: branch_frac real(r8),intent(in) :: canopy_trim real(r8),intent(out) :: sapw_area ! cross section area of @@ -1067,7 +1067,7 @@ subroutine bstore_allom(d,ipft,crowndamage, canopy_trim,bstore,dbstoredd) real(r8),intent(in) :: d ! plant diameter [cm] integer(i4),intent(in) :: ipft ! PFT index - integer(i4),intent(in) :: crowndamage ! Crowndamage class + integer(i4),intent(in) :: crowndamage ! Crowndamage class [1: undamaged, >1: damaged] real(r8),intent(in) :: canopy_trim ! Crown trimming function [0-1] real(r8),intent(out) :: bstore ! allometric target storage [kgC] real(r8),intent(out),optional :: dbstoredd ! change storage per cm [kgC/cm] @@ -2089,7 +2089,7 @@ subroutine carea_2pwr(dbh,spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max,c_area,inv real(r8),intent(in) :: d2ca_max ! maximum diameter to crown area scaling factor real(r8),intent(inout) :: c_area ! crown area for one plant [m2] logical,intent(in) :: inverse ! if true, calculate dbh from crown area rather than its reverse - integer,intent(in) :: crowndamage + integer,intent(in) :: crowndamage ! crowndamage class [1: undamaged, >1: damaged] real(r8) :: crown_area_to_dbh_exponent real(r8) :: spreadterm ! Effective 2bh to crown area scaling factor @@ -2409,7 +2409,7 @@ subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl, crowndamage, branch_fra integer(i4),intent(in) :: ipft ! PFT index - integer(i4),intent(in),optional :: crowndamage ! crowndamage + integer(i4),intent(in),optional :: crowndamage ! crowndamage [1: undamaged, >1: damaged] real(r8),intent(in) :: canopy_trim real(r8),intent(inout) :: d ! plant diameter [cm] real(r8),intent(out) :: h ! plant height From 7484d25c728bff5cbc110b21d7bbabcd62a82cfd Mon Sep 17 00:00:00 2001 From: JessicaNeedham Date: Thu, 16 Dec 2021 03:41:13 -0800 Subject: [PATCH 080/852] [ Correct typo in parameter file ] [ crowndamage to crown damage ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary:no testing --- 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 ea363ba20f..1b32af9f95 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -167,7 +167,7 @@ variables: fates_damage_recovery_scalar:long_name = "fraction of cohort that recovers from damage"; double fates_ncrowndamage ; fates_ncrowndamage: units = "unitless" ; - fates_ncrowndamage: long_name = "number of crowndamage classes" ; + fates_ncrowndamage: long_name = "number of crown damage classes" ; double fates_c2b(fates_pft) ; fates_c2b:units = "ratio" ; fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; From c00b89db72d0af358e32ae8ac5e1f14783cb8c9f Mon Sep 17 00:00:00 2001 From: JessicaNeedham Date: Thu, 16 Dec 2021 03:55:53 -0800 Subject: [PATCH 081/852] [Update comments in parameter file with more details on frequency of damage events. ] [ ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary:no testing --- 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 1b32af9f95..57efe0fa61 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -155,7 +155,7 @@ variables: fates_branch_turnover:long_name = "turnover time of branches" ; double fates_damage_frac(fates_pft) ; fates_damage_frac:units = "fraction"; - fates_damage_frac:long_name = "fraction of cohort damaged in each damage event"; + fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)"; double fates_damage_mort_p1(fates_pft) ; fates_damage_mort_p1:units = "fraction crown loss - a value of 0.8 means 50% mortality with 80% loss of crown"; fates_damage_mort_p1:long_name = "inflection point of damage mortality function - to turn off damage mortality set this to a large number" ; From 827fe3062a820b6295e86c0940d4395a03fd1408 Mon Sep 17 00:00:00 2001 From: adamhb Date: Thu, 16 Dec 2021 13:10:51 -0800 Subject: [PATCH 082/852] fixed parameter mixup in reproductive allocation scheme --- biogeochem/EDPhysiologyMod.F90 | 11 ++++------- parteh/PRTAllometricCarbonMod.F90 | 20 ++++++++++++++------ 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 50b4da3413..b1404fc7a1 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1371,10 +1371,7 @@ subroutine SeedIn( currentSite, bc_in ) real(r8) :: site_seed_rain(maxpft) ! This is the sum of seed-rain for the site [kg/site/day] real(r8) :: seed_in_external ! Mass of externally generated seeds [kg/m2/day] real(r8) :: seed_stoich ! Mass ratio of nutrient per C12 in seeds [kg/kg] - real(r8) :: repro_mass_prod ! Mass of reproductive material produced [kg/day] ; added by ahb 7/8/2021 - real(r8), parameter :: repro_frac_seed = 0.5 !added by ahb 7/12/2021; move this to param file real(r8) :: seed_prod ! Seed produced in this dynamics step [kg/day] - real(r8) :: non_seed_repro_prod ! Mass of non-seed reproductive material produced [kg/day] ; added by ahb 7/10/2021 integer :: n_litt_types ! number of litter element types (c,n,p, etc) integer :: el ! loop counter for litter element types integer :: element_id ! element id consistent with parteh/PRTGenericMod.F90 @@ -1452,10 +1449,10 @@ subroutine SeedIn( currentSite, bc_in ) litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)/area !New regeneration code added by ahb on 7/15/2021 - !The original code sends all reproductive tissue to seed - !This new code is designed to send some reproductive biomass - !straight to the leaf litter pool to account for non-seed reproductive - !biomass. Also see small change to SeedDecay subroutine. + !The original code sent all reproductive carbon to seed + !The code below sends a fraction of reproductive carbon to the leaf litter pool + !to account for non-seed reproductive carbon (e.g. flower, fruit, etc.) + !PICK UP HERE WITH ADDING SWITCH !-------------------------------- litt%seed_decay(pft) = litt%seed_in_local(pft) * (1.0_r8 - EDPftvarcon_inst%repro_frac_seed(pft)) !ahb !-------------------------------- diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index c988bb9a30..54a7804ade 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -909,6 +909,7 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) real(r8) :: ct_ddeaddd ! target structural biomass derivative wrt diameter, (kgC/cm) real(r8) :: ct_dtotaldd ! target total (not reproductive) biomass derivative wrt diameter, (kgC/cm) real(r8) :: repro_fraction ! fraction of carbon balance directed towards reproduction (kgC/kgC) + integer :: regen_model=2 associate( dbh => c_pools(dbh_id), & cleaf => c_pools(leaf_c_id), & @@ -941,16 +942,22 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) ! fraction of carbon going towards reproduction + !START ahb's changes + if ( regen_model == 1 .or. ipft > 6) then !the Tree Recruitment Scheme is not parameterized + !to work with non-tree pfts + !original code !------------------------------------------------------------------------------------- - !if (dbh <= prt_params%dbh_repro_threshold(ipft)) then ! cap on leaf biomass - ! repro_fraction = prt_params%seed_alloc(ipft) - !else - ! repro_fraction = prt_params%seed_alloc(ipft) + prt_params%seed_alloc_mature(ipft) - !end if + if (dbh <= prt_params%dbh_repro_threshold(ipft)) then ! cap on leaf biomass + repro_fraction = prt_params%seed_alloc(ipft) + else + repro_fraction = prt_params%seed_alloc(ipft) + prt_params%seed_alloc_mature(ipft) + end if !------------------------------------------------------------------------------------- + else if ( regen_model == 2 .and. ipft < 7) then !tree pfts only + !new regeneration code !------------------------------------------------------------------------------------- !This reproductive allocation function calculates the fraction of available carbon @@ -963,9 +970,10 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) !------------------------------------------------------------------------------------- repro_fraction = prt_params%seed_alloc(ipft) * & (exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm) / & - (1 + exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_b(ipft)*dbh*mm_per_cm))) + (1 + exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm))) !-------------------------------------------------------------------------------------! + end if !regen model switch !END ahb's changes dCdx = 0.0_r8 From 212bd7dd225ad9b3ecc9483f2ebeb922cd157db7 Mon Sep 17 00:00:00 2001 From: adamhb Date: Thu, 16 Dec 2021 14:22:53 -0800 Subject: [PATCH 083/852] added regeneration switch to reproductive allocation --- parteh/PRTAllometricCarbonMod.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 54a7804ade..8fdca37449 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -944,10 +944,10 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) !START ahb's changes - if ( regen_model == 1 .or. ipft > 6) then !the Tree Recruitment Scheme is not parameterized + if ( regen_model == 1 .or. ipft > 6) then !The Tree Recruitment Scheme is not parameterized !to work with non-tree pfts - !original code + !Original code !------------------------------------------------------------------------------------- if (dbh <= prt_params%dbh_repro_threshold(ipft)) then ! cap on leaf biomass repro_fraction = prt_params%seed_alloc(ipft) @@ -958,7 +958,7 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) else if ( regen_model == 2 .and. ipft < 7) then !tree pfts only - !new regeneration code + !New regeneration code !------------------------------------------------------------------------------------- !This reproductive allocation function calculates the fraction of available carbon !allocated to reproductive tissue based on a cohort's size. This function is based on From 1e1242b717816b25483d216f56779ae7e2d12607 Mon Sep 17 00:00:00 2001 From: JessicaNeedham Date: Fri, 17 Dec 2021 07:45:12 -0800 Subject: [PATCH 084/852] [ Add comments on crowndamage declaration ] [ ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary: no testing --- main/EDTypesMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 4bbd2f8ca8..77311ae426 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -221,7 +221,7 @@ module EDTypesMod real(r8) :: sapwmemory ! target sapwood biomass- set from previous year: kGC per indiv real(r8) :: structmemory ! target structural biomass- set from previous year: kGC per indiv integer :: canopy_layer ! canopy status of cohort (1 = canopy, 2 = understorey, etc.) - integer :: crowndamage ! crown damage class of the cohort + integer :: crowndamage ! crown damage class of the cohort [1: undamaged, >1: damaged] real(r8) :: canopy_layer_yesterday ! recent canopy status of cohort ! (1 = canopy, 2 = understorey, etc.) ! real to be conservative during fusion From 91cff2ff411a853058dc743d82acd5b6b58aa431 Mon Sep 17 00:00:00 2001 From: adamhb Date: Fri, 17 Dec 2021 13:12:47 -0800 Subject: [PATCH 085/852] fixed bugs in the regeneration running means --- main/FatesInterfaceMod.F90 | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 978a02a178..d6747de5a0 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -883,26 +883,6 @@ subroutine SetFatesGlobalElements(use_fates) call fates_history_maps() - ! Instantiate the time-averaging method globals - allocate(ema_24hr) - call ema_24hr%define(sec_per_day, hlm_stepsize, moving_ema_window) - allocate(fixed_24hr) - call fixed_24hr%define(sec_per_day, hlm_stepsize, fixed_window) - allocate(ema_lpa) - call ema_lpa%define(photo_temp_acclim_timescale*sec_per_day, & - hlm_stepsize,moving_ema_window) - allocate(ema_sdlng_emerg_h2o) - call ema_sdlng_emerg_h2o%define(sdlng_emerg_h2o_timescale*sec_per_day, & - hlm_stepsize,moving_ema_window) - allocate(ema_sdlng_mort_par) - call ema_sdlng_mort_par%define(sdlng_mort_par_timescale*sec_per_day, & - hlm_stepsize,moving_ema_window) - allocate(ema_sdlng2sap_par) - call ema_sdlng2sap_par%define(sdlng2sap_par_timescale*sec_per_day, & - hlm_stepsize,moving_ema_window) - allocate(ema_sdlng_mdd) - call ema_sdlng_mdd%define(sdlng_mdd_timescale*sec_per_day, & - hlm_stepsize,moving_ema_window) @@ -938,6 +918,18 @@ subroutine InitTimeAveragingGlobals() allocate(ema_lpa) call ema_lpa%define(photo_temp_acclim_timescale*sec_per_day, & hlm_stepsize,moving_ema_window) + allocate(ema_sdlng_emerg_h2o) + call ema_sdlng_emerg_h2o%define(sdlng_emerg_h2o_timescale*sec_per_day, & + hlm_stepsize,moving_ema_window) + allocate(ema_sdlng_mort_par) + call ema_sdlng_mort_par%define(sdlng_mort_par_timescale*sec_per_day, & + hlm_stepsize,moving_ema_window) + allocate(ema_sdlng2sap_par) + call ema_sdlng2sap_par%define(sdlng2sap_par_timescale*sec_per_day, & + hlm_stepsize,moving_ema_window) + allocate(ema_sdlng_mdd) + call ema_sdlng_mdd%define(sdlng_mdd_timescale*sec_per_day, & + hlm_stepsize,moving_ema_window) return end subroutine InitTimeAveragingGlobals From 31b7719f5cc11830dbfcfb860b8c8d650e806b97 Mon Sep 17 00:00:00 2001 From: adamhb Date: Fri, 17 Dec 2021 15:47:19 -0800 Subject: [PATCH 086/852] added a parameter that allows uses to switch between the Tree Recruitment Scheme and the default fates regeneration scheme --- main/EDParamsMod.F90 | 15 +++++++++++++++ parteh/PRTAllometricCarbonMod.F90 | 22 +++++++++++++--------- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index ea12daabe3..7bb8c14c94 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -70,6 +70,10 @@ module EDParamsMod real(r8),protected, public :: ED_val_patch_fusion_tol 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 :: regeneration_model !switch for choosing between regeneration models, 1 for Fates basic, 2 for the Tree Recruitment Scheme + !Hanbury-Brown et al., 2022 + + logical,protected, public :: active_crown_fire ! flag, 1=active crown fire 0=no active crown fire character(len=param_string_length),parameter :: fates_name_active_crown_fire = "fates_fire_active_crown_fire" @@ -134,6 +138,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_regeneration_model= "fates_regeneration_model" character(len=param_string_length),parameter,public :: name_theta_cj_c3 = "fates_theta_cj_c3" character(len=param_string_length),parameter,public :: name_theta_cj_c4 = "fates_theta_cj_c4" @@ -255,6 +260,7 @@ subroutine FatesParamsInit() ED_val_patch_fusion_tol = nan ED_val_canopy_closure_thresh = nan stomatal_model = -9 + regeneration_model = -9 hydr_kmax_rsurf1 = nan hydr_kmax_rsurf2 = nan hydr_psi0 = nan @@ -401,6 +407,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_regeneration_model, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=hydr_name_kmax_rsurf1, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -590,6 +599,10 @@ subroutine FatesReceiveParams(fates_params) data=tmpreal) stomatal_model = nint(tmpreal) + call fates_params%RetreiveParameter(name=ED_name_regeneration_model, & + data=tmpreal) + regeneration_model = nint(tmpreal) + call fates_params%RetreiveParameter(name=hydr_name_kmax_rsurf1, & data=hydr_kmax_rsurf1) @@ -721,6 +734,8 @@ subroutine FatesReportParams(is_master) 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) 'stomatal_model = ',stomatal_model + write(fates_log(),fmt0) 'regeneration_model = ',regeneration_model + write(fates_log(),fmt0) 'hydr_kmax_rsurf1 = ',hydr_kmax_rsurf1 write(fates_log(),fmt0) 'hydr_kmax_rsurf1 = ',hydr_kmax_rsurf1 write(fates_log(),fmt0) 'hydr_kmax_rsurf2 = ',hydr_kmax_rsurf2 write(fates_log(),fmt0) 'hydr_psi0 = ',hydr_psi0 diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 8fdca37449..c5fa8eb6ce 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -51,6 +51,7 @@ module PRTAllometricCarbonMod use FatesConstantsMod , only : years_per_day use PRTParametersMod , only : prt_params + use EDParamsMod , only : regeneration_model implicit none private @@ -909,7 +910,9 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) real(r8) :: ct_ddeaddd ! target structural biomass derivative wrt diameter, (kgC/cm) real(r8) :: ct_dtotaldd ! target total (not reproductive) biomass derivative wrt diameter, (kgC/cm) real(r8) :: repro_fraction ! fraction of carbon balance directed towards reproduction (kgC/kgC) - integer :: regen_model=2 + integer, parameter :: TRS = 2 !Switch option to use the Tree Recruitment Scheme + integer, parameter :: default_regeneration = 1 !Switch option to use the FATES's default regeneration scheme + associate( dbh => c_pools(dbh_id), & cleaf => c_pools(leaf_c_id), & @@ -944,10 +947,10 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) !START ahb's changes - if ( regen_model == 1 .or. ipft > 6) then !The Tree Recruitment Scheme is not parameterized - !to work with non-tree pfts + if ( regeneration_model == default_regeneration .or. ipft > 6) then !The Tree Recruitment Scheme + !is only for tree pfts - !Original code + !Default reproductive allocation !------------------------------------------------------------------------------------- if (dbh <= prt_params%dbh_repro_threshold(ipft)) then ! cap on leaf biomass repro_fraction = prt_params%seed_alloc(ipft) @@ -956,13 +959,14 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) end if !------------------------------------------------------------------------------------- - else if ( regen_model == 2 .and. ipft < 7) then !tree pfts only + else if ( regeneration_model == TRS .and. ipft < 7) then - !New regeneration code + !Use Tree Recruitment Scheme's (TRS) approach to reproductive allocation !------------------------------------------------------------------------------------- !This reproductive allocation function calculates the fraction of available carbon - !allocated to reproductive tissue based on a cohort's size. This function is based on - !empirical data and analysis at BCI (Visser et al., 2016). + !allocated to reproductive tissue based on a cohort's dbh (mm). This function is based on + !empirical data and analysis at BCI (Visser et al., 2016). See Hanbury-Brown et al., 2022 + !for more details. !Visser MD, Bruijning M, Wright SJ, Muller-Landau HC, Jongejans E, Comita LS, !de Kroon H. 2016. Functional traits as predictors of vital rates across the life cycle @@ -973,7 +977,7 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) (1 + exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm))) !-------------------------------------------------------------------------------------! - end if !regen model switch + end if !regeneration model switch !END ahb's changes dCdx = 0.0_r8 From 34dc02ca982e65f8c038d2a08ed21b43be71cab9 Mon Sep 17 00:00:00 2001 From: adamhb Date: Fri, 17 Dec 2021 16:52:21 -0800 Subject: [PATCH 087/852] added switch to allocation to non-seed reproductive carbon --- biogeochem/EDPhysiologyMod.F90 | 29 ++++++++++++++++++++--------- parteh/PRTAllometricCarbonMod.F90 | 10 ++++------ 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index e340e63790..86d8bd97f7 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -74,6 +74,7 @@ module EDPhysiologyMod use EDParamsMod , only : q10_mr use EDParamsMod , only : q10_froz use EDParamsMod , only : logging_export_frac + use EDParamsMod , only : regeneration_model use FatesPlantHydraulicsMod , only : AccumulateMortalityWaterStorage use FatesConstantsMod , only : itrue,ifalse use FatesConstantsMod , only : calloc_abs_error @@ -274,7 +275,6 @@ end subroutine PreDisturbanceLitterFluxes subroutine PreDisturbanceIntegrateLitter(currentPatch) ! ----------------------------------------------------------------------------------- - ! ! This step applies the litter fluxes to the prognostic state variables. ! This procedure is called in response to fluxes generated from: ! 1) seed rain, @@ -1609,6 +1609,8 @@ subroutine SeedIn( currentSite, bc_in ) integer :: n_litt_types ! number of litter element types (c,n,p, etc) integer :: el ! loop counter for litter element types integer :: element_id ! element id consistent with parteh/PRTGenericMod.F90 + integer, parameter :: TRS = 2 ! Switch option to use the Tree Recruitment Scheme + integer, parameter :: default_regeneration = 1 !Switch option to use FATES's default regeneration scheme !------------------------------------------------------------------------------------ do el = 1, num_elements @@ -1682,14 +1684,23 @@ subroutine SeedIn( currentSite, bc_in ) ! Seed input from local sources (within site) litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)/area - !New regeneration code added by ahb on 7/15/2021 - !The original code sent all reproductive carbon to seed - !The code below sends a fraction of reproductive carbon to the leaf litter pool - !to account for non-seed reproductive carbon (e.g. flower, fruit, etc.) - !PICK UP HERE WITH ADDING SWITCH - !-------------------------------- - litt%seed_decay(pft) = litt%seed_in_local(pft) * (1.0_r8 - EDPftvarcon_inst%repro_frac_seed(pft)) !ahb - !-------------------------------- + + !START ahb's changes + + if ( regeneration_model == TRS .and. pft < 7) then + + !Send a fraction of reproductive carbon to litter to account for + !non-seed reproductive carbon (e.g. flowers, fruit, etc.) + !If using default_regeneration then all reproductive carbon becomes seed + !This process will be more important if/when FATES fixes the structural issue + !that all carbon used to make recruits comes from reproductive carbon. + + litt%seed_decay(pft) = litt%seed_in_local(pft) * (1.0_r8 - EDPftvarcon_inst%repro_frac_seed(pft)) + + end if + + !Default regeneration scheme sends all reproductive carbon to seed + !END ahb's changes ! If there is forced external seed rain, we calculate the input mass flux ! from the different elements, usung the seed optimal stoichiometry diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index c5fa8eb6ce..e46a0a543a 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -942,27 +942,25 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) call bdead_allom(ct_agw,ct_bgw, ct_sap, ipft, ct_dead, & ct_dagwdd, ct_dbgwdd, ct_dsapdd, ct_ddeaddd) call bstore_allom(dbh,ipft,canopy_trim,ct_store,ct_dstoredd) - + + ! fraction of carbon going towards reproduction - !START ahb's changes if ( regeneration_model == default_regeneration .or. ipft > 6) then !The Tree Recruitment Scheme !is only for tree pfts !Default reproductive allocation - !------------------------------------------------------------------------------------- if (dbh <= prt_params%dbh_repro_threshold(ipft)) then ! cap on leaf biomass repro_fraction = prt_params%seed_alloc(ipft) else repro_fraction = prt_params%seed_alloc(ipft) + prt_params%seed_alloc_mature(ipft) end if - !------------------------------------------------------------------------------------- else if ( regeneration_model == TRS .and. ipft < 7) then - !Use Tree Recruitment Scheme's (TRS) approach to reproductive allocation !------------------------------------------------------------------------------------- + !Use Tree Recruitment Scheme's (TRS) approach to reproductive allocation. !This reproductive allocation function calculates the fraction of available carbon !allocated to reproductive tissue based on a cohort's dbh (mm). This function is based on !empirical data and analysis at BCI (Visser et al., 2016). See Hanbury-Brown et al., 2022 @@ -972,10 +970,10 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) !de Kroon H. 2016. Functional traits as predictors of vital rates across the life cycle !of tropical trees. Functional Ecology 30: 168–180. !------------------------------------------------------------------------------------- + repro_fraction = prt_params%seed_alloc(ipft) * & (exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm) / & (1 + exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm))) - !-------------------------------------------------------------------------------------! end if !regeneration model switch !END ahb's changes From 05e25472aa4a497004d5cc0a32c191244921850a Mon Sep 17 00:00:00 2001 From: adamhb Date: Mon, 20 Dec 2021 14:09:18 -0800 Subject: [PATCH 088/852] updated the TRS switch --- biogeochem/EDPhysiologyMod.F90 | 40 +++++++++++++++++++++---------- main/FatesConstantsMod.F90 | 8 +++++++ parteh/PRTAllometricCarbonMod.F90 | 16 +++++++------ 3 files changed, 44 insertions(+), 20 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 86d8bd97f7..4da7ec85fc 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -22,6 +22,9 @@ module EDPhysiologyMod use FatesConstantsMod, only : r8 => fates_r8 use FatesConstantsMod, only : nearzero use FatesConstantsMod, only : sec_per_day + use FatesConstantsMod, only : TRS + use FatesConstantsMod, only : default_regeneration + use FatesConstantsMod, only : min_max_dbh_for_trees use FatesConstantsMod, only : megajoules_per_joule use FatesConstantsMod, only : mpa_per_mm_suction use EDPftvarcon , only : EDPftvarcon_inst @@ -1687,7 +1690,8 @@ subroutine SeedIn( currentSite, bc_in ) !START ahb's changes - if ( regeneration_model == TRS .and. pft < 7) then + if ( regeneration_model == TRS .and. & + prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees) then !Send a fraction of reproductive carbon to litter to account for !non-seed reproductive carbon (e.g. flowers, fruit, etc.) @@ -1699,7 +1703,7 @@ subroutine SeedIn( currentSite, bc_in ) end if - !Default regeneration scheme sends all reproductive carbon to seed + !Default regeneration scheme sends all reproductive carbon to seed (i.e. do nothing here) !END ahb's changes ! If there is forced external seed rain, we calculate the input mass flux @@ -1742,7 +1746,7 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) ! ! !DESCRIPTION: ! 1. Flux from seed pool into leaf litter pool - ! 2. Flux from seedling pool into leaf litter pool + ! 2. (if TRS is on) Seedling mortality (i.e. flux from seedling pool into leaf litter pool) ! ! !ARGUMENTS type(litter_type) :: litt @@ -1767,20 +1771,30 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) ! Assume that decay rates are same for all chemical species ! START ahb's changes + !===================================================================================== do pft = 1,numpft - litt%seed_decay(pft) = litt%seed(pft) * & - EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day + & ! "+ &" added by ahb (7/10/2021) - litt%seed_decay(pft) ! line added by ahb so that the flux from non-seed reproductive - ! biomass (from SeedIn subroutine) is not lost (7/10/2021) - - ! 2. Flux from seedling pool into leaf litter pool - - ! ORIGINAL CODE - !---------------------------------------------------------------------- + + !If the TRS is switched off or the pft is not a tree then use the default + !regeneration scheme. + if ( regeneration_model == default_regeneration .or. & + prt_params%allom_dbh_maxheight(ipft) < min_max_dbh_for_trees ) + + !Default seed decay scheme (original code) litt%seed_germ_decay(pft) = litt%seed_germ(pft) * & EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day - !---------------------------------------------------------------------- + !If the TRS is switched on and the pft is a tree then use the TRS + else if ( regeneration_model == TRS .and. & + prt_params%allom_dbh_maxheight(ipft) > min_max_dbh_for_trees ) then + + !---------------------------------------------------------------------- + !With respect to seed decay, the only difference with the TRS here is adding the flux + !from non-seed reproductive biomass (which was sent to litt%seed_decay in the SeedIn subroutine) + + litt%seed_decay(pft) = litt%seed_decay(pft) + &!from non-seed reproductive biomass; working? + litt%seed(pft) * EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day + + ! 2. Flux from seedling pool into leaf litter pool !---------------------------------------------------------------------- !NEW CODE FOR ENVIRONMENTALLY SENSITIVE SEEDLING MORTALITY !Step 1. Calculate the daily seedling mortality rate from light stress diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index 8f2b296feb..08b7a463de 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -46,6 +46,14 @@ module FatesConstantsMod integer, public, parameter :: prescribed_n_uptake = 1 integer, public, parameter :: coupled_n_uptake = 2 + !Flags specifying how tree regeneration works + integer, public, parameter :: TRS = 2 !Constant defining the Tree Recruitment Scheme switch + integer, public, parameter :: default_regeneration = 1 !Constant defining FATES's default regeneration scheme switch + real(fates_r8), public, parameter :: min_max_dbh_for_trees = 15._fates_r8 !cm; if pfts have a max dbh less + !than this value FATES + !will use the default regeneration scheme. This is to avoid + !the TRS being used for shrubs and grasses. + integer, public, parameter :: cohort_np_comp_scaling = 1 ! This flag definition indicates that EVERY cohort on ! the column should compete independently in the soil diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index e46a0a543a..904342520e 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -42,7 +42,10 @@ module PRTAllometricCarbonMod use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : i4 => fates_int use FatesConstantsMod , only : sec_per_day - use FatesConstantsMod , only : mm_per_cm !ahb added this 7/7/2021 + use FatesConstantsMod , only : mm_per_cm !ahb + use FatesConstantsMod , only : TRS !ahb + use FatesConstantsMod , only : default_regeneration !ahb + use FatesConstantsMod , only : min_max_dbh_for_trees !ahb use FatesIntegratorsMod , only : RKF45 use FatesIntegratorsMod , only : Euler use FatesConstantsMod , only : calloc_abs_error @@ -910,9 +913,6 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) real(r8) :: ct_ddeaddd ! target structural biomass derivative wrt diameter, (kgC/cm) real(r8) :: ct_dtotaldd ! target total (not reproductive) biomass derivative wrt diameter, (kgC/cm) real(r8) :: repro_fraction ! fraction of carbon balance directed towards reproduction (kgC/kgC) - integer, parameter :: TRS = 2 !Switch option to use the Tree Recruitment Scheme - integer, parameter :: default_regeneration = 1 !Switch option to use the FATES's default regeneration scheme - associate( dbh => c_pools(dbh_id), & cleaf => c_pools(leaf_c_id), & @@ -947,8 +947,9 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) ! fraction of carbon going towards reproduction !START ahb's changes - if ( regeneration_model == default_regeneration .or. ipft > 6) then !The Tree Recruitment Scheme - !is only for tree pfts + if ( regeneration_model == default_regeneration .or. & + prt_params%allom_dbh_maxheight(ipft) < min_max_dbh_for_trees ) then !The Tree Recruitment Scheme + !is only for tree pfts !Default reproductive allocation if (dbh <= prt_params%dbh_repro_threshold(ipft)) then ! cap on leaf biomass @@ -957,7 +958,8 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) repro_fraction = prt_params%seed_alloc(ipft) + prt_params%seed_alloc_mature(ipft) end if - else if ( regeneration_model == TRS .and. ipft < 7) then + else if ( regeneration_model == TRS .and. & + prt_params%allom_dbh_maxheight(ipft) > min_max_dbh_for_trees ) then !------------------------------------------------------------------------------------- !Use Tree Recruitment Scheme's (TRS) approach to reproductive allocation. From 4b13b5b3de79bae9a70b68d61f479190b3f1934a Mon Sep 17 00:00:00 2001 From: adamhb Date: Mon, 20 Dec 2021 16:54:18 -0800 Subject: [PATCH 089/852] updated light and moisture-based seedling germination rates in SeedGermination subroutine --- biogeochem/EDPhysiologyMod.F90 | 197 ++++++++++++++++++--------------- 1 file changed, 105 insertions(+), 92 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 4da7ec85fc..1942aed90b 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1762,7 +1762,7 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) !---------------------------------------------------------------------- - ! 1. Flux from seed pool into leaf litter pool + ! 1. Seed mortality (i.e. flux from seed bank to litter) ! default value from Liscke and Loffler 2006 ; making this a PFT-specific parameter ! decays the seed pool according to exponential model @@ -1774,65 +1774,67 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) !===================================================================================== do pft = 1,numpft - !If the TRS is switched off or the pft is not a tree then use the default - !regeneration scheme. - if ( regeneration_model == default_regeneration .or. & - prt_params%allom_dbh_maxheight(ipft) < min_max_dbh_for_trees ) + !If the TRS is switched off or the pft is not a tree then use the default + !regeneration scheme. + if ( regeneration_model == default_regeneration .or. & + prt_params%allom_dbh_maxheight(pft) < min_max_dbh_for_trees ) then - !Default seed decay scheme (original code) - litt%seed_germ_decay(pft) = litt%seed_germ(pft) * & + !Default seed decay scheme (original code) + litt%seed_decay(pft) = litt%seed(pft) * & EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day - !If the TRS is switched on and the pft is a tree then use the TRS - else if ( regeneration_model == TRS .and. & - prt_params%allom_dbh_maxheight(ipft) > min_max_dbh_for_trees ) then + !If the TRS is switched on and the pft is a tree then use the TRS + else if ( regeneration_model == TRS .and. & + prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees ) then - !---------------------------------------------------------------------- - !With respect to seed decay, the only difference with the TRS here is adding the flux - !from non-seed reproductive biomass (which was sent to litt%seed_decay in the SeedIn subroutine) + !---------------------------------------------------------------------- + !With respect to seed decay, the only difference with the TRS here is adding the flux + !from non-seed reproductive biomass (which was sent to litt%seed_decay in the SeedIn subroutine) litt%seed_decay(pft) = litt%seed_decay(pft) + &!from non-seed reproductive biomass; working? litt%seed(pft) * EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day - - ! 2. Flux from seedling pool into leaf litter pool - !---------------------------------------------------------------------- - !NEW CODE FOR ENVIRONMENTALLY SENSITIVE SEEDLING MORTALITY - !Step 1. Calculate the daily seedling mortality rate from light stress + + end if !regeneration model switch + + ! 2. Seedling mortality (i.e. fluxes from seedling pool (seed_germ) to litter) + !---------------------------------------------------------------------- + !NEW CODE FOR ENVIRONMENTALLY SENSITIVE SEEDLING MORTALITY + !Step 1. Calculate the daily seedling mortality rate from light stress - !ADD CODE FOR CUMULATIVE LIGHT - ! seedling_layer_par = ( currentPatch%parprof_dir_z(currentPatch%ncl_p,max(currentPatch%ncan(currentPatch%ncl_p,:))) ) ! + & + !ADD CODE FOR CUMULATIVE LIGHT + !seedling_layer_par = ( currentPatch%parprof_dir_z(currentPatch%ncl_p,max(currentPatch%ncan(currentPatch%ncl_p,:))) ) ! + & ! currentPatch%parprof_dif_z(currentPatch%ncl_p,max(currentPatch%ncan(currentPatch%ncl_p,:))) ) ! * & ! megajoules_per_joule * sec_per_day * seedling_light_mort_window - ! seedling_light_mort_rate = exp(EDPftvarcon_inst%seedling_light_mort_a(pft) * & - ! seedling_layer_par + EDPftvarcon_inst%seedling_light_mort_b(pft)) + !seedling_light_mort_rate = exp(EDPftvarcon_inst%seedling_light_mort_a(pft) * & + !seedling_layer_par + EDPftvarcon_inst%seedling_light_mort_b(pft)) - ! write(fates_log(),*) 'seedling layer par ', seedling_layer_par - ! write(fates_log(),*) 'seedling light mort rate ', seedling_light_mort_rate + !write(fates_log(),*) 'seedling layer par ', seedling_layer_par + !write(fates_log(),*) 'seedling light mort rate ', seedling_light_mort_rate - !Step 2. Calculate the moisture deficit days !this code is a placeholder for now + !Step 2. Calculate the moisture deficit days !this code is a placeholder for now - !ilayer_swater_emerg = minloc(abs(bc_in%z_sisl(:)-emerg_soil_depth),dim=1) !define soil layer + !ilayer_swater_emerg = minloc(abs(bc_in%z_sisl(:)-emerg_soil_depth),dim=1) !define soil layer - !moisture_def_days = abs(bc_in%smp_sl(ilayer_swater_emerg) * mpa_per_mm_suction) - & !calculate smp (mm H20 suction?) - ! abs(EDPftvarcon_inst%seedling_smp_crit(pft)) + !moisture_def_days = abs(bc_in%smp_sl(ilayer_swater_emerg) * mpa_per_mm_suction) - & !calculate smp (mm H20 suction?) + ! abs(EDPftvarcon_inst%seedling_smp_crit(pft)) - !Step 3. Calculate the daily seedling mortality rate from moisture stress + !Step 3. Calculate the daily seedling mortality rate from moisture stress - !seedling_h2o_mort_rate = EDPftvarcon_inst%seedling_h2o_mort_a(pft) * moisture_def_days**2 + & - ! EDPftvarcon_inst%seedling_h2o_mort_b(pft) * moisture_def_days + & - ! EDPftvarcon_inst%seedling_h2o_mort_c(pft) + !seedling_h2o_mort_rate = EDPftvarcon_inst%seedling_h2o_mort_a(pft) * moisture_def_days**2 + & + ! EDPftvarcon_inst%seedling_h2o_mort_b(pft) * moisture_def_days + & + ! EDPftvarcon_inst%seedling_h2o_mort_c(pft) - !if (moisture_def_days < EDPftvarcon_inst%moisture_dd_crit(pft) ) then - ! seedling_h2o_mort_rate = 0.0_r8 - !end if + !if (moisture_def_days < EDPftvarcon_inst%moisture_dd_crit(pft) ) then + ! seedling_h2o_mort_rate = 0.0_r8 + !end if - !Step 4. Add background mortality and send seedling carbon to litter flux (i.e. to 'seed_germ_decay' flux) + !Step 4. Add background mortality and send seedling carbon to litter flux (i.e. to 'seed_germ_decay' flux) !litt%seed_germ_decay(pft) = (litt%seed_germ(pft) * seedling_light_mort_rate) !+ & !(litt%seed_germ(pft) * seedling_h2o_mort_rate) + & !(litt%seed_germ(pft) * EDPftvarcon_inst%background_seedling_mort(pft) & @@ -1871,15 +1873,12 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) !------------------------------------------------------------------------------------------------------------ integer :: ilayer_seedling_root ! the soil layer at seedling rooting depth real(r8) :: seedling_layer_smp ! soil matric potential at seedling rooting depth - real(r8) :: wetness_index ! a soil 'wetness index' calculated from soil matric potential - - real(r8) :: seedling_layer_par ! photosynthetically active radiation at the seedling layer - real(r8) :: slsmp_emerg - real(r8) :: slparmort - real(r8) :: slpartrans - + real(r8) :: wetness_index ! a soil 'wetness index' (1 / - SoilMatricPotetial (MPa) ) + real(r8) :: seedling_layer_par ! par at the seedling layer (MJ m-2 day-1) + real(r8) :: slsmp_emerg !temp + real(r8) :: slparmort !temp + real(r8) :: slpartrans !temp real(r8) :: photoblastic_germ_modifier ! seedling emergence rate modifier for light-sensitive germination - ! used in the moisture-sensitive emergence function real(r8) :: seedling_emerg_rate ! the fraction of the seed bank emerging in the current time step !------------------------------------------------------------------------------------------------------------- @@ -1897,22 +1896,62 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) ! that times the ratio of (hypothetical) seed mass to recruit biomass !START ahb's CHANGES - !ORIGINAL CODE - !------------------------------------------------------------------------------------------- - do pft = 1,numpft - ! litt%seed_germ_in(pft) = min(litt%seed(pft) * EDPftvarcon_inst%germination_rate(pft), & - ! max_germination)*years_per_day - !------------------------------------------------------------------------------------------- - - !This code adds light and moisture-sensitive seedling emergence from the seed bank. - !It replaces the old prescribed seed germination rate parameter. - !------------------------------------------------------------------------------------------- - !Step 1. calculate the photoblastic germination rate modifier + !============================================================================================== + do pft = 1,numpft + if ( regeneration_model == default_regeneration .or. & + prt_params%allom_dbh_maxheight(pft) < min_max_dbh_for_trees ) then + + !FATES default germination scheme + litt%seed_germ_in(pft) = min(litt%seed(pft) * EDPftvarcon_inst%germination_rate(pft), & + max_germination)*years_per_day + + else if ( regeneration_model == TRS .and. & + prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees ) then + + !------------------------------------------------------------------------------------------- + !The Tree Recruitment Scheme calculates seedling emergence (i.e. germination) as a pft-specific + !function of understory light and soil moisture + + !Step 1. Calculate how germination rate is modified by understory light. + ! This applies to photoblastic germinators (e.g. many tropical pioneers) + + !Calculate par at the seedling layer (MJ m-2 day-1) + !The running mean variable is in W m-2 over prior 24 hours. It is converted to MJ m-2 day-1 + !to work with the TRS function. + + seedling_layer_par = currentPatch%seedling_layer_par24%GetMean() * sec_per_day * megajoules_per_joule + + !Calculate the photoblastic germination rate modifier (see eqn. 3 of Hanbury-Brown et al., 2022) + photoblastic_germ_modifier = seedling_layer_par / & + (seedling_layer_par + EDPftvarcon_inst%par_crit_germ(pft)) + + !Step 2. Calculate the soil matric potential at the seedling rooting depth + + !Define soil layer based on pft-specific rooting depth + !ilayer_seedling_root = minloc(abs(bc_in%z_sisl(:)-EDPftvarcon_inst%seedling_root_depth(pft)),dim=1) + + !Get running mean of soil matric potential (mm of H2O suction) at the seedling rooting depth + seedling_layer_smp = currentPatch%sdlng_emerg_smp(pft)%p%GetMean() - seedling_layer_par = currentPatch%seedling_layer_par24%GetMean() - !slsmp_emerg = currentPatch%sdlng_emerg_smp%GetMean() - !slparmort = currentPatch%sdlng_mort_par%GetMean() - !slpartrans = currentPatch%sdlng2sap_par%GetMean() + !Calculate a soil wetness index (1 / -soil matric pontential (MPa) ) used by the TRS moisture-based + !seedling mortality function + wetness_index = 1.0_r8 / (seedling_layer_smp * (-1.0_r8) * mpa_per_mm_suction) + + !Step 3. Calculate the seedling emergence rate based on soil moisture and germination + ! rate modifier (i.e. Step 1). See eqn. 4 of Hanbury-Brown et al., 2022 + + seedling_emerg_rate = photoblastic_germ_modifier * EDPftvarcon_inst%a_emerg(pft) * & + wetness_index**EDPftvarcon_inst%b_emerg(pft) + + !Step 4. Calculate the amount of carbon germinating out of the seed bank + litt%seed_germ_in(pft) = litt%seed(pft) * seedling_emerg_rate + + end if !regeneration model switch + !-------------------------------------------------------------------------------------------- + !TEMP + !slsmp_emerg = currentPatch%sdlng_emerg_smp%GetMean() + !slparmort = currentPatch%sdlng_mort_par%GetMean() + !slpartrans = currentPatch%sdlng2sap_par%GetMean() ! write(fates_log(),*) 'nrm parprof', currentPatch%nrmlzd_parprof_dir_z(:,:,:) ! write(fates_log(),*) 'parprof', currentPatch%parprof_dif_z(1,:) @@ -1924,45 +1963,19 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) ! write(fates_log(),*) 'seedling_mort_par', slparmort ! write(fates_log(),*) 'seedling2sap_trans_par', slpartrans ! write(fates_log(),*) 'tveg_lpa', currentPatch%tveg_lpa%GetMean() - - seedling_layer_par = seedling_layer_par * 4.6_r8 !covert to umol s-1 of PAR - !1 W/m2 ≈ 4.6 μmole.m2/s - - photoblastic_germ_modifier = seedling_layer_par / & - (seedling_layer_par + EDPftvarcon_inst%par_crit_germ(pft)) - - !Step 2. calculate the soil matric potential at the seedling root depth - - !define soil layer - ilayer_seedling_root = minloc(abs(bc_in%z_sisl(:)-EDPftvarcon_inst%seedling_root_depth(pft)),dim=1) - - !get soil matric potential (mm of H2O suction) at the seedling rooting depth - seedling_layer_smp = bc_in%smp_sl(ilayer_seedling_root) + !================================================================================================ + !END ahb changes - !calculate a soil wetness index, which is used by the moisture-based seedling mortality function - wetness_index = 1.0_r8 / (seedling_layer_smp * (-1.0_r8) * mpa_per_mm_suction) - - !Step 3. calculate the seedling emergence rate based on soil moisture and par - seedling_emerg_rate = photoblastic_germ_modifier * EDPftvarcon_inst%a_emerg(pft) * & - wetness_index**EDPftvarcon_inst%b_emerg(pft) - - !Step 4. calculate the 'seed_germ_in' flux - - !do pft = 1,numpft - litt%seed_germ_in(pft) = min(litt%seed(pft) * seedling_emerg_rate, max_germination) - !------------------------------------------------------------------------------------------- - !END ahb changes + !set the germination only under the growing season...c.xu - !set the germination only under the growing season...c.xu - - if ((prt_params%season_decid(pft) == itrue ) .and. & + if ((prt_params%season_decid(pft) == itrue ) .and. & (any(cold_stat == [phen_cstat_nevercold,phen_cstat_iscold]))) then litt%seed_germ_in(pft) = 0.0_r8 - endif - if ((prt_params%stress_decid(pft) == itrue ) .and. & + endif + if ((prt_params%stress_decid(pft) == itrue ) .and. & (any(drought_stat == [phen_dstat_timeoff,phen_dstat_moistoff]))) then litt%seed_germ_in(pft) = 0.0_r8 - end if + end if enddo From 7d7b52dba3f9ead1fb887bcae2bf60007e8f7efd Mon Sep 17 00:00:00 2001 From: adamhb Date: Tue, 21 Dec 2021 18:50:04 -0800 Subject: [PATCH 090/852] finished seedling germination functions; fates-trs working --- biogeochem/EDPhysiologyMod.F90 | 23 +++++++++++++++-------- main/EDPftvarcon.F90 | 10 ++++++++++ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 1942aed90b..f481be8f73 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1904,13 +1904,14 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) !FATES default germination scheme litt%seed_germ_in(pft) = min(litt%seed(pft) * EDPftvarcon_inst%germination_rate(pft), & max_germination)*years_per_day - - else if ( regeneration_model == TRS .and. & - prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees ) then - + !end FATES default germination scheme + !------------------------------------------------------------------------------------------- !The Tree Recruitment Scheme calculates seedling emergence (i.e. germination) as a pft-specific !function of understory light and soil moisture + + else if ( regeneration_model == TRS .and. & + prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees ) then !Step 1. Calculate how germination rate is modified by understory light. ! This applies to photoblastic germinators (e.g. many tropical pioneers) @@ -1939,12 +1940,18 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) !Step 3. Calculate the seedling emergence rate based on soil moisture and germination ! rate modifier (i.e. Step 1). See eqn. 4 of Hanbury-Brown et al., 2022 - + + if ( seedling_layer_smp * mpa_per_mm_suction .GE. EDPftvarcon_inst%seedling_psi_emerg(pft) ) then seedling_emerg_rate = photoblastic_germ_modifier * EDPftvarcon_inst%a_emerg(pft) * & wetness_index**EDPftvarcon_inst%b_emerg(pft) - - !Step 4. Calculate the amount of carbon germinating out of the seed bank - litt%seed_germ_in(pft) = litt%seed(pft) * seedling_emerg_rate + else + + seedling_emerg_rate = 0.0_r8 + + end if !soil-moisture based seedling emergence rate + + !Step 4. Calculate the amount of carbon germinating out of the seed bank + litt%seed_germ_in(pft) = litt%seed(pft) * seedling_emerg_rate end if !regeneration model switch !-------------------------------------------------------------------------------------------- diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 4c56b4e004..431b472565 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -104,6 +104,7 @@ module EDPftvarcon real(r8), allocatable :: a_emerg(:) !added by ahb 7/19/2021 real(r8), allocatable :: b_emerg(:) !added by ahb 7/19/2021 real(r8), allocatable :: par_crit_germ(:) !added by ahb 7/19/2021 + real(r8), allocatable :: seedling_psi_emerg(:) !added by ahb 7/19/2021 real(r8), allocatable :: seedling_root_depth(:) !added by ahb 7/27/2021 real(r8), allocatable :: seedling_light_mort_a(:) !added by ahb on 7/27/2021 real(r8), allocatable :: seedling_light_mort_b(:) !added by ahb on 7/27/2021 @@ -559,6 +560,10 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_seedling_psi_emerg' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_seedling_root_depth' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -938,6 +943,10 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=this%par_crit_germ) + name = 'fates_seedling_psi_emerg' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%seedling_psi_emerg) + name = 'fates_seedling_root_depth' call fates_params%RetreiveParameterAllocate(name=name, & data=this%seedling_root_depth) @@ -1502,6 +1511,7 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'a_emerg = ',EDPftvarcon_inst%a_emerg write(fates_log(),fmt0) 'b_emerg = ',EDPftvarcon_inst%b_emerg write(fates_log(),fmt0) 'par_crit_germ = ',EDPftvarcon_inst%par_crit_germ + write(fates_log(),fmt0) 'seedling_psi_emerg = ',EDPftvarcon_inst%seedling_psi_emerg write(fates_log(),fmt0) 'seedling_root_depth = ',EDPftvarcon_inst%seedling_root_depth write(fates_log(),fmt0) 'trim_limit = ',EDPftvarcon_inst%trim_limit write(fates_log(),fmt0) 'trim_inc = ',EDPftvarcon_inst%trim_inc From 35fcdb3e53279dcc1c0c21cc2c308dc22b12183c Mon Sep 17 00:00:00 2001 From: adamhb Date: Tue, 21 Dec 2021 20:52:50 -0800 Subject: [PATCH 091/852] added light based seedling mortality; model working --- biogeochem/EDPhysiologyMod.F90 | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index f481be8f73..49bbf9ca84 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -78,6 +78,7 @@ module EDPhysiologyMod use EDParamsMod , only : q10_froz use EDParamsMod , only : logging_export_frac use EDParamsMod , only : regeneration_model + use EDParamsMod , only : sdlng_mort_par_timescale use FatesPlantHydraulicsMod , only : AccumulateMortalityWaterStorage use FatesConstantsMod , only : itrue,ifalse use FatesConstantsMod , only : calloc_abs_error @@ -1798,29 +1799,25 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) ! 2. Seedling mortality (i.e. fluxes from seedling pool (seed_germ) to litter) !---------------------------------------------------------------------- - !NEW CODE FOR ENVIRONMENTALLY SENSITIVE SEEDLING MORTALITY !Step 1. Calculate the daily seedling mortality rate from light stress - !ADD CODE FOR CUMULATIVE LIGHT - !seedling_layer_par = ( currentPatch%parprof_dir_z(currentPatch%ncl_p,max(currentPatch%ncan(currentPatch%ncl_p,:))) ) ! + & - ! currentPatch%parprof_dif_z(currentPatch%ncl_p,max(currentPatch%ncan(currentPatch%ncl_p,:))) ) - ! * & - ! megajoules_per_joule * sec_per_day * seedling_light_mort_window + !Calculate the cumulative light at the seedling layer over a prior number of + !days set by the "sdlng_mort_par_timescale" parameter - !seedling_light_mort_rate = exp(EDPftvarcon_inst%seedling_light_mort_a(pft) * & - !seedling_layer_par + EDPftvarcon_inst%seedling_light_mort_b(pft)) - + seedling_layer_par = currentPatch%sdlng_mort_par%GetMean() * megajoules_per_joule * & + sec_per_day * sdlng_mort_par_timescale + seedling_light_mort_rate = exp( EDPftvarcon_inst%seedling_light_mort_a(pft) * & + seedling_layer_par + EDPftvarcon_inst%seedling_light_mort_b(pft )) + + !TEMP !write(fates_log(),*) 'seedling layer par ', seedling_layer_par !write(fates_log(),*) 'seedling light mort rate ', seedling_light_mort_rate - !Step 2. Calculate the moisture deficit days !this code is a placeholder for now + !Step 2. Calculate the seedling moisture deficit days - !ilayer_swater_emerg = minloc(abs(bc_in%z_sisl(:)-emerg_soil_depth),dim=1) !define soil layer - !moisture_def_days = abs(bc_in%smp_sl(ilayer_swater_emerg) * mpa_per_mm_suction) - & !calculate smp (mm H20 suction?) - ! abs(EDPftvarcon_inst%seedling_smp_crit(pft)) !Step 3. Calculate the daily seedling mortality rate from moisture stress From 0c81c9c6870c1175c15f8f9463937d3c356dec11 Mon Sep 17 00:00:00 2001 From: adamhb Date: Wed, 22 Dec 2021 12:13:50 -0800 Subject: [PATCH 092/852] adding seedling mortality functions; fates-trs working --- biogeochem/EDPhysiologyMod.F90 | 47 ++++++++++++++++--------------- main/EDPftvarcon.F90 | 51 ++++++++++++++++++++++++++++++++++ main/FatesInterfaceMod.F90 | 5 ++-- 3 files changed, 78 insertions(+), 25 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 49bbf9ca84..514142e685 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1758,8 +1758,10 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) integer :: pft real(r8) :: seedling_layer_par !cumulative light at the seedling layer (MJ) over prior window of days !(defined by 'light_mort_window' param) - real(r8), parameter :: seedling_light_mort_window = 64.0 !days; move to pft-level parameter real(r8) :: seedling_light_mort_rate !the daily seedling mortality rate from light stress + real(r8) :: seedling_h2o_mort_rate !the daily seedling mortality rate from moisture stress + real(r8) :: seedling_mdds !moisture deficit days accumulated in the seedling layer + !---------------------------------------------------------------------- @@ -1808,34 +1810,33 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) sec_per_day * sdlng_mort_par_timescale seedling_light_mort_rate = exp( EDPftvarcon_inst%seedling_light_mort_a(pft) * & - seedling_layer_par + EDPftvarcon_inst%seedling_light_mort_b(pft )) + seedling_layer_par + EDPftvarcon_inst%seedling_light_mort_b(pft) ) !TEMP !write(fates_log(),*) 'seedling layer par ', seedling_layer_par !write(fates_log(),*) 'seedling light mort rate ', seedling_light_mort_rate - - !Step 2. Calculate the seedling moisture deficit days - - - - !Step 3. Calculate the daily seedling mortality rate from moisture stress - - !seedling_h2o_mort_rate = EDPftvarcon_inst%seedling_h2o_mort_a(pft) * moisture_def_days**2 + & - ! EDPftvarcon_inst%seedling_h2o_mort_b(pft) * moisture_def_days + & - ! EDPftvarcon_inst%seedling_h2o_mort_c(pft) - - !if (moisture_def_days < EDPftvarcon_inst%moisture_dd_crit(pft) ) then - ! seedling_h2o_mort_rate = 0.0_r8 - !end if - + + !Get the current seedling moisture deficit days + !Calculated as (abs(seedling_psi_crit) - abs(seedling_layer_smp))* -1 * mddWindow + + seedling_mdds = currentPatch%sdlng_mdd(pft)%p%GetMean() - !Step 4. Add background mortality and send seedling carbon to litter flux (i.e. to 'seed_germ_decay' flux) - !litt%seed_germ_decay(pft) = (litt%seed_germ(pft) * seedling_light_mort_rate) !+ & - !(litt%seed_germ(pft) * seedling_h2o_mort_rate) + & - !(litt%seed_germ(pft) * EDPftvarcon_inst%background_seedling_mort(pft) & - !*years_per_day) + !Calculate seedling mortality as a function of moisture deficit days + seedling_h2o_mort_rate = EDPftvarcon_inst%seedling_h2o_mort_a(pft) * seedling_mdds**2 + & + EDPftvarcon_inst%seedling_h2o_mort_b(pft) * seedling_mdds + & + EDPftvarcon_inst%seedling_h2o_mort_c(pft) + + if (seedling_mdds < EDPftvarcon_inst%seedling_mdd_crit(pft)) then + seedling_h2o_mort_rate = 0.0_r8 + end if + + !Step 4. Add background mortality and send dead seedling carbon to litter (i.e. to seed_germ_decay flux) + litt%seed_germ_decay(pft) = (litt%seed_germ(pft) * seedling_light_mort_rate) + & + (litt%seed_germ(pft) * seedling_h2o_mort_rate) + & + (litt%seed_germ(pft) * EDPftvarcon_inst%background_seedling_mort(pft) & + * years_per_day) !----------------------------------------------------------------------- !END ahb's changes @@ -1938,7 +1939,7 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) !Step 3. Calculate the seedling emergence rate based on soil moisture and germination ! rate modifier (i.e. Step 1). See eqn. 4 of Hanbury-Brown et al., 2022 - if ( seedling_layer_smp * mpa_per_mm_suction .GE. EDPftvarcon_inst%seedling_psi_emerg(pft) ) then + if ( seedling_layer_smp .GE. EDPftvarcon_inst%seedling_psi_emerg(pft) ) then seedling_emerg_rate = photoblastic_germ_modifier * EDPftvarcon_inst%a_emerg(pft) * & wetness_index**EDPftvarcon_inst%b_emerg(pft) else diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 431b472565..60888a3549 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -105,6 +105,11 @@ module EDPftvarcon real(r8), allocatable :: b_emerg(:) !added by ahb 7/19/2021 real(r8), allocatable :: par_crit_germ(:) !added by ahb 7/19/2021 real(r8), allocatable :: seedling_psi_emerg(:) !added by ahb 7/19/2021 + real(r8), allocatable :: seedling_psi_crit(:) !added by ahb 7/19/2021 + real(r8), allocatable :: seedling_mdd_crit(:) !added by ahb 7/19/2021 + real(r8), allocatable :: seedling_h2o_mort_a(:) !added by ahb 7/19/2021 + real(r8), allocatable :: seedling_h2o_mort_b(:) !added by ahb 7/19/2021 + real(r8), allocatable :: seedling_h2o_mort_c(:) !added by ahb 7/19/2021 real(r8), allocatable :: seedling_root_depth(:) !added by ahb 7/27/2021 real(r8), allocatable :: seedling_light_mort_a(:) !added by ahb on 7/27/2021 real(r8), allocatable :: seedling_light_mort_b(:) !added by ahb on 7/27/2021 @@ -563,6 +568,26 @@ subroutine Register_PFT(this, fates_params) name = 'fates_seedling_psi_emerg' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_seedling_psi_crit' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_seedling_mdd_crit' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_seedling_h2o_mort_a' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_seedling_h2o_mort_b' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_seedling_h2o_mort_c' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) name = 'fates_seedling_root_depth' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & @@ -946,6 +971,26 @@ subroutine Receive_PFT(this, fates_params) name = 'fates_seedling_psi_emerg' call fates_params%RetreiveParameterAllocate(name=name, & data=this%seedling_psi_emerg) + + name = 'fates_seedling_psi_crit' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%seedling_psi_crit) + + name = 'fates_seedling_mdd_crit' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%seedling_mdd_crit) + + name = 'fates_seedling_h2o_mort_a' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%seedling_h2o_mort_a) + + name = 'fates_seedling_h2o_mort_b' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%seedling_h2o_mort_b) + + name = 'fates_seedling_h2o_mort_c' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%seedling_h2o_mort_c) name = 'fates_seedling_root_depth' call fates_params%RetreiveParameterAllocate(name=name, & @@ -1512,7 +1557,13 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'b_emerg = ',EDPftvarcon_inst%b_emerg write(fates_log(),fmt0) 'par_crit_germ = ',EDPftvarcon_inst%par_crit_germ write(fates_log(),fmt0) 'seedling_psi_emerg = ',EDPftvarcon_inst%seedling_psi_emerg + write(fates_log(),fmt0) 'seedling_psi_crit = ',EDPftvarcon_inst%seedling_psi_crit + write(fates_log(),fmt0) 'seedling_mdd_crit = ',EDPftvarcon_inst%seedling_mdd_crit + write(fates_log(),fmt0) 'background_seedling_mort = ',EDPftvarcon_inst%background_seedling_mort write(fates_log(),fmt0) 'seedling_root_depth = ',EDPftvarcon_inst%seedling_root_depth + write(fates_log(),fmt0) 'seedling_h2o_mort_a = ',EDPftvarcon_inst%seedling_h2o_mort_a + write(fates_log(),fmt0) 'seedling_h2o_mort_b = ',EDPftvarcon_inst%seedling_h2o_mort_b + write(fates_log(),fmt0) 'seedling_h2o_mort_c = ',EDPftvarcon_inst%seedling_h2o_mort_c write(fates_log(),fmt0) 'trim_limit = ',EDPftvarcon_inst%trim_limit write(fates_log(),fmt0) 'trim_inc = ',EDPftvarcon_inst%trim_inc write(fates_log(),fmt0) 'rhol = ',EDPftvarcon_inst%rhol diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index d6747de5a0..d37086a818 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1981,8 +1981,9 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) new_seedling_layer_smp(pft) = bc_in(s)%smp_sl(ilayer_seedling_root(pft)) !calculate the new moisture deficit day (mdd) value for each pft - new_seedling_mdd(pft) = (abs(seedling_smp_crit) - abs(new_seedling_layer_smp(pft))) * (-1.0_r8) - + new_seedling_mdd(pft) = (abs(EDPftvarcon_inst%seedling_psi_crit(pft)) - abs(new_seedling_layer_smp(pft))) & + * (-1.0_r8) * sdlng_mdd_timescale + ! if mdds are negative then it means that soil is wetter than smp_crit and the moisture ! deficit is 0 if (new_seedling_mdd(pft) < 0.0_r8) then From 6177e63247c1ba088a89808394c0a75f085dfe47 Mon Sep 17 00:00:00 2001 From: adamhb Date: Wed, 22 Dec 2021 16:45:13 -0800 Subject: [PATCH 093/852] finished adding all TRS processes; model working --- biogeochem/EDPhysiologyMod.F90 | 33 ++++++++++++++++++++++++++++++++- main/EDPftvarcon.F90 | 22 +++++++++++++++++++++- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 514142e685..8f20576c3a 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2039,7 +2039,9 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) real(r8) :: mass_demand ! Total mass demanded by the plant to achieve the stoichiometric targets ! of all the organs in the recruits. Used for both [kg per plant] and [kg per cohort] real(r8) :: stem_drop_fraction - + real(r8) :: sdlng2sap_par ! running mean of par at the seedlng layer [MJ m-2 day-1] + real(r8) :: seedling_layer_smp !soil matric potential at seedling rooting depth [mm H20 suction] + integer :: ilayer_seedling_root ! the soil layer at seedling rooting depth !---------------------------------------------------------------------- allocate(temp_cohort) ! create temporary cohort @@ -2163,8 +2165,37 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) call endrun(msg=errMsg(sourcefile, __LINE__)) end select + !START ahb's changes + !================================================================================= + if ( regeneration_model == default_regeneration .or. & + prt_params%allom_dbh_maxheight(ft) < min_max_dbh_for_trees ) then + mass_avail = currentPatch%area * currentPatch%litter(el)%seed_germ(ft) + else if ( regeneration_model == TRS .and. & + prt_params%allom_dbh_maxheight(ft) > min_max_dbh_for_trees ) then + + sdlng2sap_par = currentPatch%sdlng2sap_par%GetMean() * sec_per_day * megajoules_per_joule + + mass_avail = currentPatch%area * currentPatch%litter(el)%seed_germ(ft) * & + EDPftvarcon_inst%seedling_light_rec_a(ft) * & + sdlng2sap_par**EDPftvarcon_inst%seedling_light_rec_b(ft) + + !If soil moisture is below the moisture stress threshold recruitment does not occur + ilayer_seedling_root = minloc(abs(bc_in%z_sisl(:)-EDPftvarcon_inst%seedling_root_depth(ft)),dim=1) + + seedling_layer_smp = bc_in%smp_sl(ilayer_seedling_root) + + if ( seedling_layer_smp < EDPftvarcon_inst%seedling_psi_crit(ft) ) then + + mass_avail = 0.0_r8 + + end if !check on soil moisture + + end if !regeneration model + + !================================================================================== + !END ahb's changes ! ------------------------------------------------------------------------ ! Update number density if this is the limiting mass ! ------------------------------------------------------------------------ diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 60888a3549..ba88de9760 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -106,6 +106,8 @@ module EDPftvarcon real(r8), allocatable :: par_crit_germ(:) !added by ahb 7/19/2021 real(r8), allocatable :: seedling_psi_emerg(:) !added by ahb 7/19/2021 real(r8), allocatable :: seedling_psi_crit(:) !added by ahb 7/19/2021 + real(r8), allocatable :: seedling_light_rec_a(:) !added by ahb 7/19/2021 + real(r8), allocatable :: seedling_light_rec_b(:) !added by ahb 7/19/2021 real(r8), allocatable :: seedling_mdd_crit(:) !added by ahb 7/19/2021 real(r8), allocatable :: seedling_h2o_mort_a(:) !added by ahb 7/19/2021 real(r8), allocatable :: seedling_h2o_mort_b(:) !added by ahb 7/19/2021 @@ -573,6 +575,14 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_seedling_light_rec_a' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_seedling_light_rec_b' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_seedling_mdd_crit' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -975,7 +985,15 @@ subroutine Receive_PFT(this, fates_params) name = 'fates_seedling_psi_crit' call fates_params%RetreiveParameterAllocate(name=name, & data=this%seedling_psi_crit) - + + name = 'fates_seedling_light_rec_a' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%seedling_light_rec_a) + + name = 'fates_seedling_light_rec_b' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%seedling_light_rec_b) + name = 'fates_seedling_mdd_crit' call fates_params%RetreiveParameterAllocate(name=name, & data=this%seedling_mdd_crit) @@ -1559,6 +1577,8 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'seedling_psi_emerg = ',EDPftvarcon_inst%seedling_psi_emerg write(fates_log(),fmt0) 'seedling_psi_crit = ',EDPftvarcon_inst%seedling_psi_crit write(fates_log(),fmt0) 'seedling_mdd_crit = ',EDPftvarcon_inst%seedling_mdd_crit + write(fates_log(),fmt0) 'seedling_light_rec_a = ',EDPftvarcon_inst%seedling_light_rec_a + write(fates_log(),fmt0) 'seedling_light_rec_b = ',EDPftvarcon_inst%seedling_light_rec_b write(fates_log(),fmt0) 'background_seedling_mort = ',EDPftvarcon_inst%background_seedling_mort write(fates_log(),fmt0) 'seedling_root_depth = ',EDPftvarcon_inst%seedling_root_depth write(fates_log(),fmt0) 'seedling_h2o_mort_a = ',EDPftvarcon_inst%seedling_h2o_mort_a From f2a9b05b92cb8f003407046614c2b05b504afebe Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Sat, 1 Jan 2022 11:21:13 -0500 Subject: [PATCH 094/852] Adding l2fr to the restarts, updating soil root biomass diagnostic --- main/FatesHistoryInterfaceMod.F90 | 25 +++++++++++++++++++++---- main/FatesRestartInterfaceMod.F90 | 9 +++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index d1dd3b4294..c3e94bebae 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -63,6 +63,7 @@ module FatesHistoryInterfaceMod use FatesLitterMod , only : litter_type use FatesConstantsMod , only : secondaryforest use FatesAllometryMod , only : bstore_allom + use FatesAllometryMod , only : set_root_fraction use PRTGenericMod , only : leaf_organ, fnrt_organ, sapw_organ use PRTGenericMod , only : struct_organ, store_organ, repro_organ use PRTGenericMod , only : all_carbon_elements @@ -153,6 +154,7 @@ module FatesHistoryInterfaceMod integer :: ih_leafc_si integer :: ih_sapwc_si integer :: ih_fnrtc_si + integer :: ih_fnrtc_sl integer :: ih_reproc_si integer :: ih_totvegc_si @@ -1688,7 +1690,7 @@ end subroutine init_dim_kinds_maps ! ==================================================================================== - subroutine update_history_dyn(this,nc,nsites,sites) + subroutine update_history_dyn(this,nc,nsites,sites,bc_in) ! --------------------------------------------------------------------------------- ! This is the call to update the history IO arrays that are expected to only change @@ -1716,6 +1718,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) integer , intent(in) :: nc ! clump index integer , intent(in) :: nsites type(ed_site_type) , intent(inout), target :: sites(nsites) + type(bc_in_type) , intent(in) :: bc_in(nsites) ! Locals type(litter_type), pointer :: litt_c ! Pointer to the carbon12 litter pool @@ -2295,6 +2298,17 @@ subroutine update_history_dyn(this,nc,nsites,sites) this%hvars(ih_leafc_si)%r81d(io_si) + ccohort%n * leaf_m this%hvars(ih_fnrtc_si)%r81d(io_si) = & this%hvars(ih_fnrtc_si)%r81d(io_si) + ccohort%n * fnrt_m + + ! Determine the root carbon biomass in kg/m3 + ! [kg/m3] = [kg/plant] * [plant/ha] / [m3/ha] * [fraction] / [m] + + call set_root_fraction(sites(s)%rootfrac_scr, ccohort%pft, sites(s)%zi_soil, & + bc_in(s)%max_rooting_depth_index_col ) + do ilyr = 1,sites(s)%nlevsoil + this%hvars(ih_fnrtc_sl)%r82d(io_si,ilyr) = this%hvars(ih_fnrtc_sl)%r82d(io_si,ilyr) + & + fnrt_m * ccohort%n / area * sites(s)%rootfrac_scr(ilyr) / sites(s)%dz_soil(ilyr) + end do + this%hvars(ih_reproc_si)%r81d(io_si) = & this%hvars(ih_reproc_si)%r81d(io_si)+ ccohort%n * repro_m this%hvars(ih_sapwc_si)%r81d(io_si) = & @@ -2830,7 +2844,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_sum_fuel_si(io_si) = hio_sum_fuel_si(io_si) + cpatch%sum_fuel * g_per_kg * cpatch%area * AREA_INV do ilyr = 1,sites(s)%nlevsoil - hio_fragmentation_scaler_sl(io_si,ilyr) = hio_fragmentation_scaler_sl(io_si,ilyr) + cpatch%fragmentation_scaler(ilyr) * cpatch%area * AREA_INV + hio_fragmentation_scaler_sl(io_si,ilyr) = hio_fragmentation_scaler_sl(io_si,ilyr) + cpatch%fragmentation_scaler(ilyr) * cpatch%area * AREA_INV end do do i_fuel = 1,nfsc @@ -2903,8 +2917,6 @@ subroutine update_history_dyn(this,nc,nsites,sites) do i_pft = 1, numpft do i_scls = 1,nlevsclass i_scpf = (i_pft-1)*nlevsclass + i_scls - - ! ! termination mortality. sum of canopy and understory indices @@ -4732,6 +4744,11 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_fnrtc_si ) + call this%set_history_var(vname='FNRTC_SL', units='kgC m-3', & + long='Total carbon in live plant fine-roots over depth', use_default='active', & + avgflag='A', vtype=site_ground_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_fnrtc_sl ) + call this%set_history_var(vname='REPROC', units='kgC ha-1', & long='Total carbon in live plant reproductive tissues', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index d436924cc8..688ddc1f7a 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -92,6 +92,7 @@ module FatesRestartInterfaceMod integer :: ir_canopy_layer_co integer :: ir_canopy_layer_yesterday_co integer :: ir_canopy_trim_co + integer :: ir_l2fr_co integer :: ir_size_class_lasttimestep_co integer :: ir_dbh_co integer :: ir_coage_co @@ -673,6 +674,10 @@ subroutine define_restart_vars(this, initialize_variables) long_name='ed cohort - canopy_trim', units='fraction', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_canopy_trim_co ) + call this%set_restart_var(vname='fates_l2fr', vtype=cohort_r8, & + long_name='ed cohort - l2fr', units='fraction', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_l2fr_co ) + call this%set_restart_var(vname='fates_size_class_lasttimestep', vtype=cohort_int, & long_name='ed cohort - size-class last timestep', units='index', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_size_class_lasttimestep_co ) @@ -1602,6 +1607,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_canopy_layer_co => this%rvars(ir_canopy_layer_co)%int1d, & rio_canopy_layer_yesterday_co => this%rvars(ir_canopy_layer_yesterday_co)%r81d, & rio_canopy_trim_co => this%rvars(ir_canopy_trim_co)%r81d, & + rio_l2fr_co => this%rvars(ir_l2fr_co)%r81d, & rio_seed_prod_co => this%rvars(ir_seed_prod_co)%r81d, & rio_size_class_lasttimestep => this%rvars(ir_size_class_lasttimestep_co)%int1d, & rio_dbh_co => this%rvars(ir_dbh_co)%r81d, & @@ -1828,6 +1834,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_canopy_layer_co(io_idx_co) = ccohort%canopy_layer rio_canopy_layer_yesterday_co(io_idx_co) = ccohort%canopy_layer_yesterday rio_canopy_trim_co(io_idx_co) = ccohort%canopy_trim + rio_l2fr_co(io_idx_co) = ccohort%l2fr rio_seed_prod_co(io_idx_co) = ccohort%seed_prod rio_size_class_lasttimestep(io_idx_co) = ccohort%size_class_lasttimestep rio_dbh_co(io_idx_co) = ccohort%dbh @@ -2382,6 +2389,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_canopy_layer_co => this%rvars(ir_canopy_layer_co)%int1d, & rio_canopy_layer_yesterday_co => this%rvars(ir_canopy_layer_yesterday_co)%r81d, & rio_canopy_trim_co => this%rvars(ir_canopy_trim_co)%r81d, & + rio_l2fr_co => this%rvars(ir_l2fr_co)%r81d, & rio_seed_prod_co => this%rvars(ir_seed_prod_co)%r81d, & rio_size_class_lasttimestep => this%rvars(ir_size_class_lasttimestep_co)%int1d, & rio_dbh_co => this%rvars(ir_dbh_co)%r81d, & @@ -2580,6 +2588,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ccohort%canopy_layer = rio_canopy_layer_co(io_idx_co) ccohort%canopy_layer_yesterday = rio_canopy_layer_yesterday_co(io_idx_co) ccohort%canopy_trim = rio_canopy_trim_co(io_idx_co) + ccohort%l2fr = rio_l2fr_co(io_idx_co) ccohort%seed_prod = rio_seed_prod_co(io_idx_co) ccohort%size_class_lasttimestep = rio_size_class_lasttimestep(io_idx_co) ccohort%dbh = rio_dbh_co(io_idx_co) From b2937abbd365d5aae03aae3ec46f345cb5bef669 Mon Sep 17 00:00:00 2001 From: JessicaNeedham Date: Mon, 10 Jan 2022 08:28:14 -0800 Subject: [PATCH 095/852] [ Remove old damage history dimensions and fix bugs with damage history outputs ] [ Remove damage only history dimension. Fix bug with crownarea by damage and mortality. ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary:no testing --- main/FatesHistoryInterfaceMod.F90 | 80 ++++++++++++++++++++++++++++--- main/FatesHistoryVariableType.F90 | 8 +--- main/FatesIOVariableKindMod.F90 | 1 - 3 files changed, 74 insertions(+), 15 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 7cc50efc4b..47f4f3503a 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -1791,11 +1791,10 @@ subroutine init_dim_kinds_maps(this) index = index + 1 call this%dim_kinds(index)%Init(site_cdpf_r8, 2) - ! site x crowndamage x size class + ! site x crown damage x size class index = index + 1 call this%dim_kinds(index)%Init(site_cdsc_r8, 2) - ! site x size-class x age class index = index + 1 call this%dim_kinds(index)%Init(site_scag_r8, 2) @@ -1899,8 +1898,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) integer :: iagepft ! age x pft index integer :: i_agefuel ! age x fuel size class index integer :: ican, ileaf, cnlf_indx ! iterators for leaf and canopy level - integer :: icdpf, icdsc, icdi, icdj, icdam, imcdam ! iterators for the crown damage level - integer :: cdpf, cdsc + integer :: icdpf, icdsc, icdam, cdpf, cdsc ! iterators for the crown damage level integer :: counter integer :: height_bin_max, height_bin_min ! which height bin a given cohort's canopy is in integer :: i_heightbin ! iterator for height bins @@ -1948,7 +1946,6 @@ subroutine update_history_dyn(this,nc,nsites,sites) real(r8), parameter :: tiny = 1.e-5_r8 ! some small number real(r8), parameter :: reallytalltrees = 1000. ! some large number (m) - real(r8) :: total_c ! for damage integer :: tmp @@ -2030,8 +2027,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_bleaf_understory_si_scpf => this%hvars(ih_bleaf_understory_si_scpf)%r82d, & hio_mortality_canopy_si_scpf => this%hvars(ih_mortality_canopy_si_scpf)%r82d, & hio_mortality_understory_si_scpf => this%hvars(ih_mortality_understory_si_scpf)%r82d, & - hio_m3_mortality_canopy_si_scpf => this%hvars(ih_m3_mortality_canopy_si_scpf)%r82d, & - hio_m3_mortality_understory_si_scpf => this%hvars(ih_m3_mortality_understory_si_scpf)%r82d, & + hio_m3_mortality_canopy_si_scpf => this%hvars(ih_m3_mortality_canopy_si_scpf)%r82d, & + hio_m3_mortality_understory_si_scpf => this%hvars(ih_m3_mortality_understory_si_scpf)%r82d, & hio_nplant_canopy_si_scpf => this%hvars(ih_nplant_canopy_si_scpf)%r82d, & hio_nplant_understory_si_scpf => this%hvars(ih_nplant_understory_si_scpf)%r82d, & hio_ddbh_canopy_si_scpf => this%hvars(ih_ddbh_canopy_si_scpf)%r82d, & @@ -2920,6 +2917,13 @@ subroutine update_history_dyn(this,nc,nsites,sites) (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & ccohort%n * sec_per_day * days_per_year / m2_per_ha + hio_canopy_mortality_crownarea_si(io_si) = hio_canopy_mortality_crownarea_si(io_si) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * & + ccohort%c_area + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & + ccohort%c_area * sec_per_day * days_per_year + hio_canopy_mortality_carbonflux_si(io_si) = hio_canopy_mortality_carbonflux_si(io_si) + & (ccohort%bmort + ccohort%hmort + ccohort%cmort + & ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * & @@ -3054,6 +3058,14 @@ subroutine update_history_dyn(this,nc,nsites,sites) total_m * ccohort%n * days_per_sec * years_per_day * ha_per_m2 + & (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * total_m * & ccohort%n * ha_per_m2 + + hio_understory_mortality_crownarea_si(io_si) = hio_understory_mortality_crownarea_si(io_si) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * & + ccohort%c_area + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & + ccohort%c_area * sec_per_day * days_per_year + hio_carbon_balance_understory_si_scls(io_si,scls) = hio_carbon_balance_understory_si_scls(io_si,scls) + & ccohort%npp_acc_hold * ccohort%n / m2_per_ha / days_per_year / sec_per_day @@ -3807,6 +3819,17 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_understory_mortality_carbonflux_si(io_si) = hio_understory_mortality_carbonflux_si(io_si) + & sites(s)%term_carbonflux_ustory * days_per_sec * ha_per_m2 + + ! add site level mortality counting to crownarea diagnostic + hio_canopy_mortality_crownarea_si(io_si) = hio_canopy_mortality_crownarea_si(io_si) + & + sites(s)%fmort_crownarea_canopy + & + sites(s)%term_crownarea_canopy * days_per_year + + hio_understory_mortality_crownarea_si(io_si) = hio_understory_mortality_crownarea_si(io_si) + & + sites(s)%fmort_crownarea_ustory + & + sites(s)%term_crownarea_ustory * days_per_year + & + sites(s)%imort_crownarea + ! and zero the site-level termination carbon flux variable sites(s)%term_carbonflux_canopy = 0._r8 sites(s)%term_carbonflux_ustory = 0._r8 @@ -5780,6 +5803,20 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_understory_mortality_carbonflux_si) + call this%set_history_var(vname='MORTALITY_CROWNAREA_CANOPY', & + units = 'm2/ha/year', & + long='Crown area of canopy trees that died', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_canopy_mortality_crownarea_si ) + + call this%set_history_var(vname='MORTALITY_CROWNAREA_UNDERSTORY', & + units = 'm2/ha/year', & + long='Crown aera of understory trees that died', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_understory_mortality_crownarea_si ) + ! size class by age dimensioned variables call this%set_history_var(vname='FATES_NPLANT_SZAP', units = 'm-2', & @@ -6110,6 +6147,20 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index = ih_mortality_canopy_si_scpf) + call this%set_history_var(vname='FATES_M3_MORTALITY_CANOPY_SZPF', & + units = 'N/ha/yr', & + long='C starvation mortality of canopy plants by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m3_mortality_canopy_si_scpf ) + + call this%set_history_var(vname='FATES_M3_MORTALITY_USTORY_SZPF', & + units = 'N/ha/yr', & + long='C starvation mortality of understory plants by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m3_mortality_understory_si_scpf ) + call this%set_history_var(vname='FATES_C13DISC_SZPF', units = 'per mil', & long='C13 discrimination by pft/size',use_default='inactive', & avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & @@ -6351,6 +6402,21 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index = ih_nplant_understory_si_scls) + call this%set_history_var(vname='FATES_M3_MORTALITY_CANOPY_SZ', & + units = 'N/ha/yr', & + long='C starvation mortality of canopy plants by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m3_mortality_canopy_si_scls ) + + call this%set_history_var(vname='FATES_M3_MORTALITY_USTORY_SZ', & + units = 'N/ha/yr', & + long='C starvation mortality of understory plants by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m3_mortality_understory_si_scls ) + + call this%set_history_var(vname='FATES_LAI_USTORY_SZ', & units = 'm2 m-2', & long='leaf area index (LAI) of understory plants by size class', & diff --git a/main/FatesHistoryVariableType.F90 b/main/FatesHistoryVariableType.F90 index 5263bf3ec2..4102d93112 100644 --- a/main/FatesHistoryVariableType.F90 +++ b/main/FatesHistoryVariableType.F90 @@ -12,7 +12,7 @@ module FatesHistoryVariableType use FatesIOVariableKindMod, only : site_fuel_r8, site_cwdsc_r8, site_scag_r8 use FatesIOVariableKindMod, only : site_scagpft_r8, site_agepft_r8 use FatesIOVariableKindMod, only : site_can_r8, site_cnlf_r8, site_cnlfpft_r8 - use FatesIOVariableKindMod, only : site_cdamage_r8, site_cdsc_r8, site_cdpf_r8 + use FatesIOVariableKindMod, only : site_cdsc_r8, site_cdpf_r8 use FatesIOVariableKindMod, only : site_elem_r8, site_elpft_r8 use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8 use FatesIOVariableKindMod, only : iotype_index, site_agefuel_r8 @@ -178,10 +178,6 @@ subroutine Init(this, vname, units, long, use_default, & allocate(this%r82d(lb1:ub1, lb2:ub2)) this%r82d(:,:) = flushval - case(site_cdamage_r8) - allocate(this%r82d(lb1:ub1, lb2:ub2)) - this%r82d(:,:) = flushval - case(site_cdpf_r8) allocate(this%r82d(lb1:ub1, lb2:ub2)) this%r82d(:,:) = flushval @@ -329,8 +325,6 @@ subroutine Flush(this, thread, dim_bounds, dim_kinds) this%r82d(lb1:ub1, lb2:ub2) = this%flushval case(site_cnlfpft_r8) this%r82d(lb1:ub1, lb2:ub2) = this%flushval - case(site_cdamage_r8) - this%r82d(lb1:ub1, lb2:ub2) = this%flushval case(site_cdsc_r8) this%r82d(lb1:ub1, lb2:ub2) = this%flushval case(site_cdpf_r8) diff --git a/main/FatesIOVariableKindMod.F90 b/main/FatesIOVariableKindMod.F90 index 749ced2c35..a40f1c2dbe 100644 --- a/main/FatesIOVariableKindMod.F90 +++ b/main/FatesIOVariableKindMod.F90 @@ -31,7 +31,6 @@ module FatesIOVariableKindMod character(*), parameter, public :: site_can_r8 = 'SI_CAN_R8' character(*), parameter, public :: site_cnlf_r8 = 'SI_CNLF_R8' character(*), parameter, public :: site_cnlfpft_r8 = 'SI_CNLFPFT_R8' - character(*), parameter, public :: site_cdamage_r8 = 'SI_CDAMAGE_R8' character(*), parameter, public :: site_cdpf_r8 = 'SI_CDPF_R8' character(*), parameter, public :: site_cdsc_r8 = 'SI_CDSC_R8' character(*), parameter, public :: site_scag_r8 = 'SI_SCAG_R8' From ca903c4c5083836cdd655ba6e7bfdf09296b83e9 Mon Sep 17 00:00:00 2001 From: JessicaNeedham Date: Mon, 10 Jan 2022 10:58:14 -0800 Subject: [PATCH 096/852] [ update units on damage history variables ] [ update damage history variable units to be in line with recent history output refactor ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary: no testing --- main/FatesHistoryInterfaceMod.F90 | 163 ++++++++++++++++-------------- 1 file changed, 86 insertions(+), 77 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 47f4f3503a..0c641c655d 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -69,7 +69,6 @@ Module FatesHistoryInterfaceMod use FatesConstantsMod , only : years_per_day use FatesConstantsMod , only : m2_per_km2 use FatesConstantsMod , only : J_per_kJ - use FatesConstantsMod , only : m2_per_ha use FatesConstantsMod , only : m_per_cm use FatesConstantsMod , only : sec_per_min use FatesConstantsMod , only : umol_per_mol @@ -2267,10 +2266,10 @@ subroutine update_history_dyn(this,nc,nsites,sites) if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then hio_crownarea_canopy_damage_si(io_si) = hio_crownarea_canopy_damage_si(io_si) + & - sites(s)%crownarea_canopy_damage * days_per_year + sites(s)%crownarea_canopy_damage * days_per_year * 1 / m2_per_ha hio_crownarea_ustory_damage_si(io_si) = hio_crownarea_ustory_damage_si(io_si) + & - sites(s)%crownarea_ustory_damage * days_per_year + sites(s)%crownarea_ustory_damage * days_per_year * 1 / m2_per_ha end if @@ -2788,36 +2787,42 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! crown damage - only want cohorts > 1 cm dbh here so we can compare it with data hio_mortality_si_cdsc(io_si,cdsc) = hio_mortality_si_cdsc(io_si,cdsc) + & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + ccohort%frmort + & + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + & (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & - ccohort%n * sec_per_day * days_per_year + ccohort%n * sec_per_day * days_per_year / m2_per_ha hio_mortality_si_cdpf(io_si,cdpf) = hio_mortality_si_cdpf(io_si,cdpf) + & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + ccohort%frmort + & + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + & (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & - ccohort%n * sec_per_day * days_per_year + ccohort%n * sec_per_day * days_per_year / m2_per_ha ! crown damage by size - hio_nplant_si_cdsc(io_si, cdsc) = hio_nplant_si_cdsc(io_si, cdsc) + ccohort%n - hio_m3_si_cdsc(io_si, cdsc) = hio_m3_si_cdsc(io_si, cdsc) + ccohort%cmort * ccohort%n + hio_nplant_si_cdsc(io_si, cdsc) = hio_nplant_si_cdsc(io_si, cdsc) + ccohort%n / m2_per_ha + hio_m3_si_cdsc(io_si, cdsc) = hio_m3_si_cdsc(io_si, cdsc) + & + ccohort%cmort * ccohort%n / m2_per_ha ! crown damage by size by pft - hio_nplant_si_cdpf(io_si, cdpf) = hio_nplant_si_cdpf(io_si, cdpf) + ccohort%n - hio_m3_si_cdpf(io_si, cdpf) = hio_m3_si_cdpf(io_si, cdpf) + ccohort%cmort * ccohort%n + hio_nplant_si_cdpf(io_si, cdpf) = hio_nplant_si_cdpf(io_si, cdpf) + ccohort%n / m2_per_ha + hio_m3_si_cdpf(io_si, cdpf) = hio_m3_si_cdpf(io_si, cdpf) + & + ccohort%cmort * ccohort%n / m2_per_ha ! mortality - hio_m11_si_scpf(io_si,scpf) = hio_m11_si_scpf(io_si,scpf) + ccohort%dgmort*ccohort%n - hio_m11_si_scls(io_si,scls) = hio_m11_si_scls(io_si,scls) + ccohort%dgmort*ccohort%n - hio_m11_si_cdpf(io_si,cdpf) = hio_m11_si_cdpf(io_si,cdpf) + ccohort%dgmort*ccohort%n - hio_m11_si_cdsc(io_si,cdsc) = hio_m11_si_cdsc(io_si,cdsc) + ccohort%dgmort*ccohort%n + hio_m11_si_scpf(io_si,scpf) = hio_m11_si_scpf(io_si,scpf) + & + ccohort%dgmort*ccohort%n / m2_per_ha + hio_m11_si_scls(io_si,scls) = hio_m11_si_scls(io_si,scls) + & + ccohort%dgmort*ccohort%n / m2_per_ha + hio_m11_si_cdpf(io_si,cdpf) = hio_m11_si_cdpf(io_si,cdpf) + & + ccohort%dgmort*ccohort%n / m2_per_ha + hio_m11_si_cdsc(io_si,cdsc) = hio_m11_si_cdsc(io_si,cdsc) + & + ccohort%dgmort*ccohort%n / m2_per_ha hio_ddbh_si_cdsc(io_si,cdsc) = hio_ddbh_si_cdsc(io_si,cdsc) + & - ccohort%ddbhdt*ccohort%n + ccohort%ddbhdt*ccohort%n / m2_per_ha * m_per_cm hio_ddbh_si_cdpf(io_si,cdpf) = hio_ddbh_si_cdpf(io_si,cdpf) + & - ccohort%ddbhdt*ccohort%n + ccohort%ddbhdt*ccohort%n / m2_per_ha * m_per_cm end if @@ -2943,31 +2948,33 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! carbon starvation mortality in the canopy by size x damage x pft hio_m3_mortality_canopy_si_cdpf(io_si,cdpf) = hio_m3_mortality_canopy_si_cdpf(io_si,cdpf)+& - ccohort%cmort * ccohort%n + ccohort%cmort * ccohort%n / m2_per_ha ! damage mortality in the canopy by size x damage x pft hio_m11_mortality_canopy_si_cdpf(io_si,cdpf) = hio_m11_mortality_canopy_si_cdpf(io_si,cdpf)+& - ccohort%dgmort * ccohort%n + ccohort%dgmort * ccohort%n / m2_per_ha ! carbon starvation mortality in the canopy by size x damage hio_m3_mortality_canopy_si_cdsc(io_si,cdsc) = hio_m3_mortality_canopy_si_cdsc(io_si,cdsc)+& - ccohort%cmort * ccohort%n + ccohort%cmort * ccohort%n / m2_per_ha ! damage mortality in the canopy by size x damage hio_m11_mortality_canopy_si_cdsc(io_si,cdsc) = hio_m11_mortality_canopy_si_cdsc(io_si,cdsc)+& - ccohort%dgmort * ccohort%n + ccohort%dgmort * ccohort%n / m2_per_ha hio_mortality_canopy_si_cdpf(io_si,cdpf) = hio_mortality_canopy_si_cdpf(io_si,cdpf)+ & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + ccohort%frmort + & - ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + ccohort%frmort + ccohort%smort + & + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + & (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & - ccohort%n * sec_per_day * days_per_year + ccohort%n * sec_per_day * days_per_year / m2_per_ha ! nplants by damage - hio_nplant_canopy_si_cdpf(io_si,cdpf) = hio_nplant_canopy_si_cdpf(io_si,cdpf) + ccohort%n - hio_nplant_canopy_si_cdsc(io_si,cdsc) = hio_nplant_canopy_si_cdsc(io_si,cdsc) + ccohort%n + hio_nplant_canopy_si_cdpf(io_si,cdpf) = hio_nplant_canopy_si_cdpf(io_si,cdpf) + & + ccohort%n / m2_per_ha + hio_nplant_canopy_si_cdsc(io_si,cdsc) = hio_nplant_canopy_si_cdsc(io_si,cdsc) + & + ccohort%n / m2_per_ha ! growth rate by damage x size x pft in the canopy hio_ddbh_canopy_si_cdpf(io_si,cdpf) = hio_ddbh_canopy_si_cdpf(io_si,cdpf) + & - ccohort%ddbhdt*ccohort%n + ccohort%ddbhdt*ccohort%n / m2_per_ha * m_per_cm end if ! end if damage @@ -3076,34 +3083,36 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! carbon starvation mortality in the understory by size and by size x damage hio_m3_mortality_understory_si_cdsc(io_si,cdsc) = hio_m3_mortality_understory_si_cdsc(io_si,cdsc)+& - ccohort%cmort * ccohort%n + ccohort%cmort * ccohort%n / m2_per_ha ! damage mortality in the understory by size and by size x damage hio_m11_mortality_understory_si_cdsc(io_si,cdsc) = hio_m11_mortality_understory_si_cdsc(io_si,cdsc)+& - ccohort%dgmort * ccohort%n + ccohort%dgmort * ccohort%n / m2_per_ha ! carbon mortality in the understory by damage x size x pft hio_m3_mortality_understory_si_cdpf(io_si,cdpf) = hio_m3_mortality_understory_si_cdpf(io_si,cdpf)+& - ccohort%cmort * ccohort%n + ccohort%cmort * ccohort%n / m2_per_ha ! damage in the understory by damage x size x pft hio_m11_mortality_understory_si_cdpf(io_si,cdpf) = hio_m11_mortality_understory_si_cdpf(io_si,cdpf)+& - ccohort%dgmort * ccohort%n + ccohort%dgmort * ccohort%n / m2_per_ha ! total mortality of understory cohorts by damage x size x pft hio_mortality_understory_si_cdpf(io_si,cdpf) = hio_mortality_understory_si_cdpf(io_si,cdpf)+ & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + ccohort%frmort + & + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + & (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & - ccohort%n * sec_per_day * days_per_year + ccohort%n * sec_per_day * days_per_year / m2_per_ha ! number of plants in the understory by size x damage and size x damage x pft - hio_nplant_understory_si_cdsc(io_si,cdsc) = hio_nplant_understory_si_cdsc(io_si,cdsc) + ccohort%n - hio_nplant_understory_si_cdpf(io_si,cdpf) = hio_nplant_understory_si_cdpf(io_si,cdpf) + ccohort%n + hio_nplant_understory_si_cdsc(io_si,cdsc) = hio_nplant_understory_si_cdsc(io_si,cdsc) + & + ccohort%n / m2_per_ha + hio_nplant_understory_si_cdpf(io_si,cdpf) = hio_nplant_understory_si_cdpf(io_si,cdpf) + & + ccohort%n / m2_per_ha ! growth rate by size x damage x pft - understory hio_ddbh_understory_si_cdpf(io_si,cdpf) = hio_ddbh_understory_si_cdpf(io_si,cdpf) + & - ccohort%ddbhdt*ccohort%n + ccohort%ddbhdt*ccohort%n / m2_per_ha * m_per_cm end if ! end if damage @@ -3365,27 +3374,27 @@ subroutine update_history_dyn(this,nc,nsites,sites) (i_pft-1) * nlevsclass * ncrowndamage hio_mortality_si_cdsc(io_si, icdsc) = hio_mortality_si_cdsc(io_si, icdsc) + & - (sites(s)%term_nindivs_canopy_damage(icdam, i_scls, i_pft) * days_per_year) + & + ( (sites(s)%term_nindivs_canopy_damage(icdam, i_scls, i_pft) * days_per_year ) + & (sites(s)%term_nindivs_ustory_damage(icdam, i_scls, i_pft) * days_per_year) + & sites(s)%imort_rate_damage(icdam, i_scls, i_pft) + & sites(s)%fmort_rate_canopy_damage(icdam, i_scls, i_pft) + & - sites(s)%fmort_rate_ustory_damage(icdam, i_scls, i_pft) + sites(s)%fmort_rate_ustory_damage(icdam, i_scls, i_pft) ) / m2_per_ha hio_mortality_si_cdpf(io_si, icdpf) = hio_mortality_si_cdpf(io_si, icdpf) + & - (sites(s)%term_nindivs_canopy_damage(icdam, i_scls, i_pft) * days_per_year) + & + ( (sites(s)%term_nindivs_canopy_damage(icdam, i_scls, i_pft) * days_per_year) + & (sites(s)%term_nindivs_ustory_damage(icdam, i_scls, i_pft) * days_per_year) + & sites(s)%imort_rate_damage(icdam, i_scls, i_pft) + & sites(s)%fmort_rate_canopy_damage(icdam, i_scls, i_pft) + & - sites(s)%fmort_rate_ustory_damage(icdam, i_scls, i_pft) + sites(s)%fmort_rate_ustory_damage(icdam, i_scls, i_pft) ) / m2_per_ha hio_mortality_canopy_si_cdpf(io_si,icdpf) = hio_mortality_canopy_si_cdpf(io_si,icdpf) + & - sites(s)%term_nindivs_canopy_damage(icdam,i_scls,i_pft) * days_per_year + & - sites(s)%fmort_rate_canopy_damage(icdam, i_scls, i_pft) + ( sites(s)%term_nindivs_canopy_damage(icdam,i_scls,i_pft) * days_per_year + & + sites(s)%fmort_rate_canopy_damage(icdam, i_scls, i_pft) )/ m2_per_ha hio_mortality_understory_si_cdpf(io_si,icdpf) = hio_mortality_understory_si_cdpf(io_si,icdpf) + & - sites(s)%term_nindivs_ustory_damage(icdam, i_scls,i_pft) * days_per_year + & + ( sites(s)%term_nindivs_ustory_damage(icdam, i_scls,i_pft) * days_per_year + & sites(s)%imort_rate_damage(icdam, i_scls, i_pft) + & - sites(s)%fmort_rate_ustory_damage(icdam, i_scls, i_pft) + sites(s)%fmort_rate_ustory_damage(icdam, i_scls, i_pft) )/ m2_per_ha end do end do @@ -6861,152 +6870,152 @@ subroutine define_history_vars(this, initialize_variables) ! CROWN DAMAGE VARIABLES if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then - call this%set_history_var(vname='FATES_CROWNAREA_CANOPY_CD', units = 'm2 / ha / yr', & + call this%set_history_var(vname='FATES_CROWNAREA_CANOPY_CD', units = 'm2 m-2 yr-1', & long='crownarea lost to damage each year', use_default='inactive', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_crownarea_canopy_damage_si ) - call this%set_history_var(vname='FATES_CROWNAREA_USTORY_CD', units = 'm2 / ha / yr', & + call this%set_history_var(vname='FATES_CROWNAREA_USTORY_CD', units = 'm2 m-2 yr-1', & long='crownarea lost to damage each year', use_default='inactive', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_crownarea_ustory_damage_si ) - call this%set_history_var(vname='FATES_NPLANT_SZCD', units = 'N / damage x size class / ha / yr', & + call this%set_history_var(vname='FATES_NPLANT_SZCD', units = 'm-2', & long='N. plants per damage x size class', use_default='inactive', & avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_si_cdsc ) - call this%set_history_var(vname='FATES_NPLANT_CDPF', units = 'N / damage x size x pft class / ha / yr', & + call this%set_history_var(vname='FATES_NPLANT_CDPF', units = 'm-2', & long='N. plants per damage x size x pft class', use_default='inactive', & avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_si_cdpf ) - call this%set_history_var(vname='FATES_NPLANT_CANOPY_SZCD', units = 'N / damage x size class / ha / yr', & + call this%set_history_var(vname='FATES_NPLANT_CANOPY_SZCD', units = 'm-2', & long='N. plants in the canopy per damage x size class', use_default='inactive', & avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_canopy_si_cdsc ) - call this%set_history_var(vname='FATES_NPLANT_CANOPY_CDPF', units = 'N / damage x size x pft class / ha / yr', & + call this%set_history_var(vname='FATES_NPLANT_CANOPY_CDPF', units = 'm-2', & long='N. plants per damage x size x pft class', use_default='inactive', & avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_canopy_si_cdpf ) - call this%set_history_var(vname='FATES_NPLANT_USTORY_SZCD', units = 'N / damage x size class / ha / yr', & + call this%set_history_var(vname='FATES_NPLANT_USTORY_SZCD', units = 'm-2', & long='N. plants in the understory per damage x size class', use_default='inactive', & avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_understory_si_cdsc ) - call this%set_history_var(vname='FATES_NPLANT_USTORY_CDPF', units = 'N / damage x size x pft class / ha / yr', & + call this%set_history_var(vname='FATES_NPLANT_USTORY_CDPF', units = 'm-2', & long='N. plants in the understory per damage x size x pft class', use_default='inactive', & avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_understory_si_cdpf ) - call this%set_history_var(vname='FATES_M3_CDPF', units = 'N/ha/yr', & + call this%set_history_var(vname='FATES_M3_CDPF', units = 'm-2 yr-1', & long='carbon starvation mortality by damaage/pft/size', use_default='inactive', & avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_si_cdpf ) - call this%set_history_var(vname='FATES_M3_SZCD', units = 'N/ha/yr', & + call this%set_history_var(vname='FATES_M3_SZCD', units = 'm-2 yr-1', & long='carbon starvation mortality by damage/size', use_default='inactive', & avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_si_cdsc ) - call this%set_history_var(vname='FATES_M11_SZ', units = 'N/ha/yr', & + call this%set_history_var(vname='FATES_M11_SZ', units = 'm-2 yr-1', & long='damage mortality by size',use_default='inactive', & avgflag='A', vtype=site_size_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_si_scls ) - call this%set_history_var(vname='FATES_M11_SZPF', units = 'N/ha/yr', & + call this%set_history_var(vname='FATES_M11_SZPF', units = 'm-2 yr-1', & long='damage mortality by pft/size',use_default='inactive', & avgflag='A', vtype =site_size_pft_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_si_scpf ) - call this%set_history_var(vname='FATES_M11_CDPF', units = 'N/ha/yr', & + call this%set_history_var(vname='FATES_M11_CDPF', units = 'm-2 yr-1', & long='damage mortality by damaage/pft/size', use_default='inactive', & avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_si_cdpf ) - call this%set_history_var(vname='FATES_M11_SZCD', units = 'N/ha/yr', & + call this%set_history_var(vname='FATES_M11_SZCD', units = 'm-2 yr-1', & long='damage mortality by damage/size', use_default='inactive', & avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_si_cdsc ) - call this%set_history_var(vname='FATES_MORTALITY_SZCD', units = 'N/ha/yr', & + call this%set_history_var(vname='FATES_MORTALITY_SZCD', units = 'm-2 yr-1', & long='mortality by damage class by size', use_default='inactive', & avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_si_cdsc ) - call this%set_history_var(vname='FATES_MORTALITY_CDPF', units = 'N/ha/yr', & + call this%set_history_var(vname='FATES_MORTALITY_CDPF', units = 'm-2 yr-1', & long='mortality by damage class by size by pft', use_default='inactive', & avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_si_cdpf ) - call this%set_history_var(vname='FATES_M3_MORTALITY_CANOPY_SZCD', units = 'N/ha/yr', & + call this%set_history_var(vname='FATES_M3_MORTALITY_CANOPY_SZCD', units = 'm-2 yr-1', & long='C starviation mortality of canopy trees by damage/size class', use_default='inactive', & avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_canopy_si_cdsc) - call this%set_history_var(vname='FATES_M3_MORTALITY_USTORY_SZCD', units = 'N/ha/yr', & + call this%set_history_var(vname='FATES_M3_MORTALITY_USTORY_SZCD', units = 'm-2 yr-1', & long='C starviation mortality of understory trees by damage/size class', use_default='inactive', & avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_understory_si_cdsc) - call this%set_history_var(vname='FATES_M3_MORTALITY_CANOPY_CDPF', units = 'N/ha/yr', & + call this%set_history_var(vname='FATES_M3_MORTALITY_CANOPY_CDPF', units = 'm-2 yr-1', & long='C starvation mortality of canopy plants by damage/pft/size', use_default='inactive', & avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_canopy_si_cdpf ) - call this%set_history_var(vname='FATES_M3_MORTALITY_USTORY_CDPF', units = 'N/ha/yr', & + call this%set_history_var(vname='FATES_M3_MORTALITY_USTORY_CDPF', units = 'm-2 yr-1', & long='C starvation mortality of understory plants by pft/size', use_default='inactive', & avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_understory_si_cdpf ) - call this%set_history_var(vname='FATES_M11_MORTALITY_CANOPY_SZCD', units = 'N/ha/yr', & + call this%set_history_var(vname='FATES_M11_MORTALITY_CANOPY_SZCD', units = 'm-2 yr-1', & long='damage mortality of canopy trees by damage/size class', use_default='inactive', & avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_canopy_si_cdsc) - call this%set_history_var(vname='FATES_M11_MORTALITY_CANOPY_CDPF', units = 'N/ha/yr', & + call this%set_history_var(vname='FATES_M11_MORTALITY_CANOPY_CDPF', units = 'm-2 yr-1', & long='damage mortality of canopy plants by damage/pft/size', use_default='inactive', & avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_canopy_si_cdpf ) - call this%set_history_var(vname='FATES_M11_MORTALITY_USTORY_CDPF', units = 'N/ha/yr', & + call this%set_history_var(vname='FATES_M11_MORTALITY_USTORY_CDPF', units = 'm-2 yr-1', & long='damage mortality of understory plants by pft/size', use_default='inactive', & avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_understory_si_cdpf ) - call this%set_history_var(vname='FATES_MORTALITY_CANOPY_CDPF', units = 'N/ha/yr', & + call this%set_history_var(vname='FATES_MORTALITY_CANOPY_CDPF', units = 'm-2 yr-1', & long='mortality of canopy plants by damage/pft/size', use_default='inactive', & avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_canopy_si_cdpf ) - call this%set_history_var(vname='FATES_MORTALITY_USTORY_CDPF', units = 'N/ha/yr', & + call this%set_history_var(vname='FATES_MORTALITY_USTORY_CDPF', units = 'm-2 yr-1', & long='mortality of understory plants by pft/size', use_default='inactive', & avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_understory_si_cdpf ) - call this%set_history_var(vname='FATES_M11_MORTALITY_USTORY_SZCD', units = 'indiv/ha/yr', & + call this%set_history_var(vname='FATES_M11_MORTALITY_USTORY_SZCD', units = 'm-2 yr-1', & long='damage mortality of understory trees by damage/size class', use_default='inactive', & avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_understory_si_cdsc) - call this%set_history_var(vname='FATES_DDBH_SZCD', units = 'cm/year/ha', & + call this%set_history_var(vname='FATES_DDBH_SZCD', units = 'm m-2 yr-1', & long='ddbh annual increment growth by damage and size', use_default='inactive', & avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_si_cdsc ) - call this%set_history_var(vname='FATES_DDBH_CDPF', units = 'cm/year/ha', & + call this%set_history_var(vname='FATES_DDBH_CDPF', units = 'm m-2 yr-1', & long='ddbh annual increment growth by damage x size pft', use_default='inactive', & avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_si_cdpf ) - call this%set_history_var(vname='FATES_DDBH_CANOPY_CDPF', units = 'cm/year/ha', & + call this%set_history_var(vname='FATES_DDBH_CANOPY_CDPF', units = 'm m-2 yr-1', & long='ddbh annual canopy increment growth by damage x size pft', use_default='inactive', & avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_canopy_si_cdpf ) - call this%set_history_var(vname='FATES_DDBH_USTORY_CDPF', units = 'cm/year/ha', & + call this%set_history_var(vname='FATES_DDBH_USTORY_CDPF', units = 'm m-2 yr-1', & long='ddbh annual understory increment growth by damage x size pft', use_default='inactive', & avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_understory_si_cdpf ) From b0704f3c23cf2ab5c1e639e78b1d6da348d70271 Mon Sep 17 00:00:00 2001 From: Shijie Shu Date: Mon, 10 Jan 2022 16:41:00 -0800 Subject: [PATCH 097/852] Pass Harvested C from FATES to ELM --- biogeochem/EDCanopyStructureMod.F90 | 4 ++ biogeochem/EDLoggingMortalityMod.F90 | 82 +++++++++++++++++++++++++++- biogeochem/EDPatchDynamicsMod.F90 | 2 +- main/FatesInterfaceMod.F90 | 3 + main/FatesInterfaceTypesMod.F90 | 3 + 5 files changed, 90 insertions(+), 4 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 1d49e37823..d25d44bcb2 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -24,6 +24,7 @@ module EDCanopyStructureMod use EDTypesMod , only : nclmax use EDTypesMod , only : nlevleaf use EDtypesMod , only : AREA + use EDLoggingMortalityMod , only : UpdateHarvestC use FatesGlobals , only : endrun => fates_endrun use FatesInterfaceTypesMod , only : hlm_days_per_year use FatesInterfaceTypesMod , only : hlm_use_planthydro @@ -2023,6 +2024,9 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) if (hlm_use_planthydro.eq.itrue) then call UpdateH2OVeg(sites(s),bc_out(s),bc_out(s)%plant_stored_h2o_si,1) end if + + ! Pass FATES Harvested C to bc_out. + call UpdateHarvestC(sites(s),bc_out(s)) end do diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index a6228e7b20..8dd13bc39b 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -53,6 +53,7 @@ module EDLoggingMortalityMod use FatesConstantsMod , only : itrue,ifalse use FatesGlobals , only : endrun => fates_endrun use FatesGlobals , only : fates_log + use FatesGlobals , only : fates_global_verbose use shr_log_mod , only : errMsg => shr_log_errMsg use FatesPlantHydraulicsMod, only : AccumulateMortalityWaterStorage use PRTGenericMod , only : all_carbon_elements,carbon12_element @@ -61,7 +62,7 @@ module EDLoggingMortalityMod use FatesAllometryMod , only : set_root_fraction use FatesConstantsMod , only : primaryforest, secondaryforest, secondary_age_threshold use FatesConstantsMod , only : fates_tiny - use FatesConstantsMod , only : months_per_year + use FatesConstantsMod , only : months_per_year, days_per_sec, years_per_day use FatesConstantsMod , only : hlm_harvest_area_fraction use FatesConstantsMod , only : hlm_harvest_carbon use FatesConstantsMod, only : fates_check_param_set @@ -91,6 +92,7 @@ module EDLoggingMortalityMod public :: logging_time public :: IsItLoggingTime public :: get_harvest_rate_area + public :: UpdateHarvestC contains @@ -248,9 +250,15 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & call get_harvest_rate_area (patch_anthro_disturbance_label, hlm_harvest_catnames, & hlm_harvest_rates, frac_site_primary, secondary_age, harvest_rate) + if (fates_global_verbose()) then + write(fates_log(), *) 'Successfully Read Harvest Rate from HLM.', hlm_harvest_rates(:), harvest_rate + end if + else if (hlm_use_lu_harvest == itrue .and. hlm_harvest_units == hlm_harvest_carbon) then ! 2=use carbon from hlm ! not implemented yet + ! Shijie: Shall call another function, which transfer biomass/carbon into fraction? + ! Is it the correct place to call the function? write(fates_log(),*) 'HLM harvest carbon data not implemented yet. Exiting.' call endrun(msg=errMsg(sourcefile, __LINE__)) endif @@ -356,7 +364,7 @@ subroutine get_harvest_rate_area (patch_anthro_disturbance_label, hlm_harvest_ca ! Normalize by site-level primary or secondary forest fraction ! since harvest_rate is specified as a fraction of the gridcell - ! also need to put a cap so as not to harvest more primary or secondary area than there is in a gridcell + ! also need to put a cap so as not to harvest more primary or secondary area than there is in a gridcell if (patch_anthro_disturbance_label .eq. primaryforest) then if (frac_site_primary .gt. fates_tiny) then harvest_rate = min((harvest_rate / frac_site_primary),frac_site_primary) @@ -685,7 +693,7 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site ! This is for checking the total mass balance [kg/site/day] site_mass%wood_product = site_mass%wood_product + & ag_wood * logging_export_frac - + new_litt%ag_cwd(ncwd) = new_litt%ag_cwd(ncwd) + ag_wood * & (1._r8-logging_export_frac)*donate_frac/newPatch%area @@ -791,4 +799,72 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site return end subroutine logging_litter_fluxes + ! ===================================================================================== + + subroutine UpdateHarvestC(currentSite,bc_out) + + ! ---------------------------------------------------------------------------------- + ! Added by Shijie Shu. + ! This subroutine is called when logging is completed and need to update + ! Harvested C flux in HLM. + ! ---------------------------------------------------------------------------------- + use EDtypesMod , only : ed_site_type + use FatesInterfaceTypesMod , only : bc_out_type + use PRTGenericMod , only : num_elements + use pftvarcon , only : pprodharv10 + + ! Arguments + type(ed_site_type), intent(inout), target :: currentSite ! site structure + type(bc_out_type), intent(inout) :: bc_out + + integer :: el + integer :: icode + real(r8) :: unit_trans_factor + + ! Flush the older value before update + if(logging_time) then + bc_out%hrv_deadstemc_to_prod10c = 0._r8 + bc_out%hrv_deadstemc_to_prod100c = 0._r8 + end if + + ! First test tropic forest (PFT=1) + ! Calculate the unit transfer factor (from kgC m-2 day-1 to gC m-2 s-1) + ! for icode == 2, icode < 0, and icode > 10000 is one time harvest, thus + ! shall distribute into everyday + icode = int(logging_event_code) + if(icode .eq. 1) then + ! Logging is turned off + unit_trans_factor = 1._r8 + else if(icode .eq. 3) then + ! Logging event every day - this may not work due to the mortality exclusivity + unit_trans_factor = 1000._r8 * days_per_sec + else if(icode .eq. 4) then + ! Logging event once a month + ! Shijie: Shall think about a better if expreession? + if ((hlm_current_month == 1) .or. (hlm_current_month == 3) .or. & + (hlm_current_month == 5) .or. (hlm_current_month == 7) .or. & + (hlm_current_month == 8) .or. (hlm_current_month == 10) .or. & + (hlm_current_month == 12)) then + unit_trans_factor = 1000._r8 * days_per_sec / 31._r8 + else if((hlm_current_month == 4) .or. (hlm_current_month == 6) .or. & + (hlm_current_month == 9) .or. (hlm_current_month == 11)) then + unit_trans_factor = 1000._r8 * days_per_sec / 30._r8 + else + unit_trans_factor = 1000._r8 * days_per_sec / 28._r8 + end if + else + ! Logging event one time every year + unit_trans_factor = 1000._r8 * days_per_sec * years_per_day + end if + + do el = 1,num_elements + bc_out%hrv_deadstemc_to_prod10c = bc_out%hrv_deadstemc_to_prod10c + & + currentSite%harvest_carbon_flux * pprodharv10(1) * unit_trans_factor + bc_out%hrv_deadstemc_to_prod100c = bc_out%hrv_deadstemc_to_prod100c + & + currentSite%harvest_carbon_flux * (1-pprodharv10(1)) * unit_trans_factor + end do + + return + end subroutine UpdateHarvestC + end module EDLoggingMortalityMod diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index e5bd982225..ec04c7eb36 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -298,7 +298,7 @@ subroutine disturbance_rates( site_in, bc_in) enddo !currentCohort ! for non-closed-canopy areas subject to logging, add an additional increment of area disturbed - ! equivalent to the fradction loged to account for transfer of interstitial ground area to new secondary lands + ! equivalent to the fradction logged to account for transfer of interstitial ground area to new secondary lands if ( logging_time .and. & (currentPatch%area - currentPatch%total_canopy_area) .gt. fates_tiny ) then ! The canopy is NOT closed. diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 48aef9deed..16f0607e7d 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -306,6 +306,9 @@ subroutine zero_bcs(fates,s) fates%bc_out(s)%qflx_ro_sisl(:) = 0.0_r8 end if fates%bc_out(s)%plant_stored_h2o_si = 0.0_r8 + + fates%bc_out(s)%hrv_deadstemc_to_prod10c = 0.0_r8 + fates%bc_out(s)%hrv_deadstemc_to_prod100c = 0.0_r8 return end subroutine zero_bcs diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 5b069709cc..b0bebad637 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -673,6 +673,9 @@ module FatesInterfaceTypesMod ! small fluxes for various reasons ! [mm H2O/s] + ! FATES LULCC + real(r8) :: hrv_deadstemc_to_prod10c ! Harvested C flux to 10-yr wood product pool [Site-Level, gC m-2 s-1] + real(r8) :: hrv_deadstemc_to_prod100c ! Harvested C flux to 100-yr wood product pool [Site-Level, gC m-2 s-1] end type bc_out_type From 31918cf456fa217cff8d82fb4871507954426c2b Mon Sep 17 00:00:00 2001 From: adamhb Date: Tue, 11 Jan 2022 16:08:07 -0800 Subject: [PATCH 098/852] started diagnostics --- biogeochem/EDPhysiologyMod.F90 | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 8f20576c3a..04a9f416b4 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2065,7 +2065,14 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(ft) call h2d_allom(temp_cohort%hite,ft,temp_cohort%dbh) + + !ahb diagnostic + if (hlm_day_of_year == 40) then + write(fates_log(),*) 'min_dbh:', temp_cohort%dbh + end if + !end ahb diagnostic + ! Initialize live pools call bleaf(temp_cohort%dbh,ft,temp_cohort%canopy_trim,c_leaf) call bfineroot(temp_cohort%dbh,ft,temp_cohort%canopy_trim,c_fnrt) @@ -2133,6 +2140,12 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) case(carbon12_element) mass_demand = c_struct+c_leaf+c_fnrt+c_sapw+c_store + + !ahb diagnostic + if (hlm_day_of_year == 40) then + write(fates_log(),*) 'mass demand:', mass_demand + end if + !end ahb diagnostic case(nitrogen_element) From 7b3a7ac2879641310ef7fd5980fed54943c522bf Mon Sep 17 00:00:00 2001 From: adamhb Date: Wed, 12 Jan 2022 08:55:10 -0800 Subject: [PATCH 099/852] made new regeneration parameter file the default on this branch' --- parameter_files/fates_params_default.cdl | 420 +++++++++++++++-------- 1 file changed, 277 insertions(+), 143 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 6d5fa2cb4e..89d89cdf2a 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -137,19 +137,19 @@ variables: fates_allom_stmode:possible_values = "1: target storage proportional to trimmed maximum leaf biomass." ; double fates_allom_zroot_k(fates_pft) ; fates_allom_zroot_k:units = "unitless" ; - fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; + fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model (NOT USED)" ; double fates_allom_zroot_max_dbh(fates_pft) ; fates_allom_zroot_max_dbh:units = "cm" ; - fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; + fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth (NOT USED)" ; double fates_allom_zroot_max_z(fates_pft) ; fates_allom_zroot_max_z:units = "m" ; - fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh (NOT USED). note: max_z=min_z=large, sets rooting depth to soil depth" ; double fates_allom_zroot_min_dbh(fates_pft) ; fates_allom_zroot_min_dbh:units = "cm" ; - fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; + fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined (NOT USED)" ; double fates_allom_zroot_min_z(fates_pft) ; fates_allom_zroot_min_z:units = "m" ; - fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh (NOT USED) note: max_z=min_z=large, sets rooting depth to soil depth" ; double fates_branch_turnover(fates_pft) ; fates_branch_turnover:units = "yr" ; fates_branch_turnover:long_name = "turnover time of branches" ; @@ -431,10 +431,10 @@ variables: fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; double fates_prescribed_nuptake(fates_pft) ; - fates_prescribed_nuptake:units = "fraction" ; + fates_prescribed_nuptake:units = "fraction" ; fates_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; double fates_prescribed_puptake(fates_pft) ; - fates_prescribed_puptake:units = "fraction" ; + fates_prescribed_puptake:units = "fraction" ; fates_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; double fates_prescribed_recruitment(fates_pft) ; fates_prescribed_recruitment:units = "n/yr" ; @@ -478,7 +478,61 @@ variables: double fates_seed_alloc(fates_pft) ; fates_seed_alloc:units = "fraction" ; fates_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; - double fates_seed_alloc_mature(fates_pft) ; + double fates_repro_alloc_a(fates_pft) ; + fates_repro_alloc_a:units = "fraction" ; + fates_repro_alloc_a:long_name = "shape parameter for sigmoidal function relating dbh to reproductive allocation" ; + double fates_repro_alloc_b(fates_pft) ; + fates_repro_alloc_b:units = "fraction" ; + fates_repro_alloc_b:long_name = "intercept parameter for sigmoidal function relating dbh to reproductive allocation" ; + double fates_repro_frac_seed(fates_pft) ; + fates_repro_frac_seed:units = "fraction" ; + fates_repro_frac_seed:long_name = "fraction of reproductive mass that is seed" ; + double fates_a_emerg(fates_pft) ; + fates_a_emerg:units = "day -1" ; + fates_a_emerg:long_name = "mean fraction of seed bank emerging" ; + double fates_b_emerg(fates_pft) ; + fates_b_emerg:units = "day -1" ; + fates_b_emerg:long_name = "seedling emergence sensitivity to soil moisture" ; + double fates_par_crit_germ(fates_pft) ; + fates_par_crit_germ:units = "Megajoules m2-1 day-1 " ; + fates_par_crit_germ:long_name = "critical light level for germination" ; + double fates_seedling_root_depth(fates_pft) ; + fates_seedling_root_depth:units = "m" ; + fates_seedling_root_depth:long_name = "rooting depth of seedlings" ; + double fates_seedling_psi_emerg(fates_pft) ; + fates_seedling_psi_emerg:units = "mm h20 suction" ; + fates_seedling_psi_emerg:long_name = "critical soil moisture for seedling emergence" ; + double fates_seedling_psi_crit(fates_pft) ; + fates_seedling_psi_crit:units = "mm h20 suction" ; + fates_seedling_psi_crit:long_name = "critical soil moisture for seedling stress" ; + double fates_seedling_mdd_crit(fates_pft) ; + fates_seedling_mdd_crit:units = "moisture deficit days (mm h2o suction * days)" ; + fates_seedling_mdd_crit:long_name = "critical moisture deficit day accumulation for seedling moisture-based seedling mortality to begin" ; + double fates_seedling_h2o_mort_a(fates_pft) ; + fates_seedling_h2o_mort_a:units = "-" ; + fates_seedling_h2o_mort_a:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_seedling_h2o_mort_b(fates_pft) ; + fates_seedling_h2o_mort_b:units = "-" ; + fates_seedling_h2o_mort_b:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_seedling_h2o_mort_c(fates_pft) ; + fates_seedling_h2o_mort_c:units = "-" ; + fates_seedling_h2o_mort_c:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_seedling_light_mort_a(fates_pft) ; + fates_seedling_light_mort_a:units = "-" ; + fates_seedling_light_mort_a:long_name = "light-based seedling mortality coefficient" ; + double fates_seedling_light_mort_b(fates_pft) ; + fates_seedling_light_mort_b:units = "-" ; + fates_seedling_light_mort_b:long_name = "light-based seedling mortality coefficient" ; + double fates_background_seedling_mort(fates_pft) ; + fates_background_seedling_mort:units = "yr-1" ; + fates_background_seedling_mort:long_name = "background seedling mortality rate" ; + double fates_seedling_light_rec_a(fates_pft) ; + fates_seedling_light_rec_a:units = "-" ; + fates_seedling_light_rec_a:long_name = "coefficient in light-based seedling to sapling transition" ; + double fates_seedling_light_rec_b(fates_pft) ; + fates_seedling_light_rec_b:units = "-" ; + fates_seedling_light_rec_b:long_name = "coefficient in light-based seedling to sapling transition" ; + double fates_seed_alloc_mature(fates_pft) ; fates_seed_alloc_mature:units = "fraction" ; fates_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; double fates_seed_dbh_repro_threshold(fates_pft) ; @@ -542,9 +596,9 @@ variables: double fates_z0mr(fates_pft) ; fates_z0mr:units = "unitless" ; fates_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; - double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; - fates_hlm_pft_map:units = "area fraction" ; - fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; double fates_fire_FBD(fates_litterclass) ; fates_fire_FBD:units = "kg Biomass/m3" ; fates_fire_FBD:long_name = "fuel bulk density" ; @@ -662,7 +716,10 @@ variables: double fates_leaf_stomatal_model ; fates_leaf_stomatal_model:units = "unitless" ; fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; - double fates_logging_coll_under_frac ; + double fates_regeneration_model ; + fates_regeneration_model:units = "unitless" ; + fates_regeneration_model:long_name = "switch for choosing between FATES's default regeneration scheme (1) or the Tree Recruitment Scheme (Hanbury-Brown et al., 2022;2)" ; + double fates_logging_coll_under_frac ; fates_logging_coll_under_frac:units = "fraction" ; fates_logging_coll_under_frac:long_name = "Fraction of stems killed in the understory when logging generates disturbance" ; double fates_logging_collateral_frac ; @@ -731,6 +788,18 @@ variables: double fates_photo_temp_acclim_timescale ; fates_photo_temp_acclim_timescale:units = "days" ; fates_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; + double fates_sdlng_emerg_h2o_timescale ; + fates_sdlng_emerg_h2o_timescale:units = "days" ; + fates_sdlng_emerg_h2o_timescale:long_name = "Length of the window for the exponential moving average of smp used to calculate seedling emergence" ; + double fates_sdlng_mort_par_timescale ; + fates_sdlng_mort_par_timescale:units = "days" ; + fates_sdlng_mort_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling mortality" ; + double fates_sdlng_mdd_timescale ; + fates_sdlng_mdd_timescale:units = "days" ; + fates_sdlng_mdd_timescale:long_name = "Length of the window for the exponential moving average of moisture deficit days used to calculate seedling mortality" ; + double fates_sdlng2sap_par_timescale ; + fates_sdlng2sap_par_timescale:units = "days" ; + fates_sdlng2sap_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling to sapling transition rates" ; double fates_photo_tempsens_model ; fates_photo_tempsens_model:units = "unitless" ; fates_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; @@ -766,7 +835,7 @@ data: fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; - fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, + fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100 ; fates_hydr_htftype_node = 1, 1, 1, 1 ; @@ -807,22 +876,22 @@ data: "sapwood ", "structure " ; - fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 ; - fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, + fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; - fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, + fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572 ; - fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, + fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94 ; - fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, + fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931 ; - fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6 ; fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -831,30 +900,30 @@ data: fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07 ; - fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, + fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3 ; - fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, + fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55 ; - fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, + fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464 ; - fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, + fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119 ; - fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, + fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64 ; - fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, + fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37 ; - fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, + fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 ; fates_allom_dbh_maxheight = 90, 90, 90, 90, 90, 90, 3, 3, 2, 0.35, 0.35, 0.35 ; @@ -867,14 +936,14 @@ data: fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 ; fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -885,13 +954,13 @@ data: fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; - fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 ; - fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, + fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; - fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 ; fates_branch_turnover = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; @@ -900,19 +969,19 @@ data: fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; - fates_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, + fates_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67 ; - fates_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + fates_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + fates_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280 ; - fates_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, + fates_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14 ; - fates_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, + fates_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27 ; fates_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; @@ -921,28 +990,28 @@ data: fates_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_eca_vmax_nh4 = 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, + fates_eca_vmax_nh4 = 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07 ; - fates_eca_vmax_no3 = 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, + fates_eca_vmax_no3 = 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08 ; - fates_eca_vmax_p = 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, + fates_eca_vmax_p = 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09 ; - fates_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + fates_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 ; - fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07 ; - fates_fire_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, + fates_fire_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, 0.95, 1, 1, 1 ; - fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, + fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775 ; fates_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; @@ -953,16 +1022,16 @@ data: fates_fr_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_fr_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + fates_fr_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25 ; - fates_fr_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + fates_fr_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25 ; - fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, + fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - fates_hydr_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + fates_hydr_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5 ; fates_hydr_avuln_node = @@ -991,34 +1060,34 @@ data: -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; - fates_hydr_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + fates_hydr_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5 ; fates_hydr_p50_node = - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25 ; - fates_hydr_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, + fates_hydr_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333 ; fates_hydr_pinot_node = - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; fates_hydr_pitlp_node = - -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, @@ -1030,10 +1099,10 @@ data: 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - fates_hydr_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + fates_hydr_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625 ; - fates_hydr_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, + fates_hydr_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; fates_hydr_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; @@ -1045,13 +1114,13 @@ data: 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; fates_hydr_vg_alpha_node = - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005 ; fates_hydr_vg_m_node = @@ -1068,79 +1137,79 @@ data: fates_leaf_c3psn = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ; - fates_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, + fates_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, 0.9, 0.75, 0.75, 0.75 ; - fates_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, + fates_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04 ; - fates_leaf_jmaxha = 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, + fates_leaf_jmaxha = 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540 ; - fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, + fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040 ; - fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, + fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495 ; fates_leaf_long = 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, + fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, 0.03, 0.03, 0.03, 0.03, 0.03 ; - fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, + fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, 0.03, 0.03, 0.03, 0.03 ; - fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, + fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 40000 ; fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, + fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, 4.7, 2.2, 5.3, 1.6 ; - fates_leaf_stor_priority = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + fates_leaf_stor_priority = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 ; fates_leaf_vcmax25top = 50, 65, 39, 62, 41, 58, 62, 54, 54, 78, 78, 78 ; - fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, + fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330 ; - fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, + fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250 ; - fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, + fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485 ; - fates_leaf_xl = 0.1, 0.01, 0.01, 0.1, 0.01, 0.25, 0.01, 0.25, 0.25, -0.3, + fates_leaf_xl = 0.1, 0.01, 0.01, 0.1, 0.01, 0.25, 0.01, 0.25, 0.25, -0.3, -0.3, -0.3 ; fates_lf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_lf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + fates_lf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25 ; - fates_lf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + fates_lf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25 ; - fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, + fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014 ; - fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -60, -10, -80, -80, + fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -60, -10, -80, -80, -20, 2.5 ; - fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, + fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; @@ -1153,17 +1222,17 @@ data: fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6 ; - fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6 ; fates_nfix1 = _, _, _, _, _, _, _, _, _, _, _, _ ; fates_nfix2 = _, _, _, _, _, _, _, _, _, _, _, _ ; - fates_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + fates_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5 ; fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; @@ -1178,26 +1247,26 @@ data: fates_phenflush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + fates_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5 ; - fates_prescribed_mortality_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, + fates_prescribed_mortality_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; - fates_prescribed_mortality_understory = 0.025, 0.025, 0.025, 0.025, 0.025, + fates_prescribed_mortality_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; - fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, + fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4 ; - fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, + fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; fates_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_prescribed_recruitment = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, + fates_prescribed_recruitment = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02 ; fates_prt_alloc_priority = @@ -1208,97 +1277,152 @@ data: fates_prt_nitr_stoich_p1 = 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047 ; fates_prt_nitr_stoich_p2 = 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047 ; fates_prt_phos_stoich_p1 = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047 ; fates_prt_phos_stoich_p2 = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047 ; - fates_recruit_hgt_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, + fates_recruit_hgt_min = 2.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, 0.125, 0.125, 0.125 ; - fates_recruit_initd = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + fates_recruit_initd = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 ; - fates_rholnir = 0.45, 0.35, 0.35, 0.45, 0.45, 0.45, 0.35, 0.45, 0.45, 0.35, + fates_rholnir = 0.45, 0.35, 0.35, 0.45, 0.45, 0.45, 0.35, 0.45, 0.45, 0.35, 0.35, 0.35 ; fates_rholvis = 0.1, 0.07, 0.07, 0.1, 0.1, 0.1, 0.07, 0.1, 0.1, 0.1, 0.1, 0.1 ; - fates_rhosnir = 0.39, 0.39, 0.39, 0.39, 0.39, 0.39, 0.39, 0.39, 0.39, 0.53, + fates_rhosnir = 0.39, 0.39, 0.39, 0.39, 0.39, 0.39, 0.39, 0.39, 0.39, 0.53, 0.53, 0.53 ; - fates_rhosvis = 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.31, + fates_rhosvis = 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.31, 0.31, 0.31 ; fates_root_long = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; fates_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; + fates_repro_alloc_a = 0.0058, 0.0058, 0.0058, 0.0058, 0.0058, 0.0058, 0.0058, + 0.0058, 0.0058, 0.0058, 0.0058, 0.0058 ; + + fates_repro_alloc_b = -3.138, -3.138, -3.138, -3.138, + -3.138, -3.138, -3.138, -3.138, -3.138, -3.138, -3.138, -3.138 ; + + fates_repro_frac_seed = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_a_emerg = 0.0006, 0.0006, 0.0006, 0.0006, + 0.0006, 0.0006, 0.0006, 0.0006, 0.0006, 0.0006, 0.0006, 0.0006 ; + + fates_b_emerg = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 ; + + fates_par_crit_germ = 0.656, 0.656, 0.656, 0.656, 0.656, 0.656, + 0.656, 0.656, 0.656, 0.656, 0.656, 0.656 ; + + fates_seedling_psi_emerg = -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, + -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65 ; + + fates_seedling_psi_crit = -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, + -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7 ; + + fates_seedling_mdd_crit = 1400000.0, 1400000.0, 1400000.0, 1400000.0, 1400000.0, + 1400000.0, 1400000.0, 1400000.0, 1400000.0, 1400000.0, 1400000.0, 1400000.0 ; + + fates_seedling_h2o_mort_a = 4.070565e-17, 4.070565e-17, 4.070565e-17, + 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, + 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17 ; + + fates_seedling_h2o_mort_b = -6.390757e-11, -6.390757e-11, -6.390757e-11, + -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, + -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11 ; + + fates_seedling_h2o_mort_c = 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, + 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, + 1.268992e-05, 1.268992e-05 ; + + fates_seedling_light_mort_a = -0.0099, -0.0099, -0.0099, -0.0099, -0.0099, -0.0099, -0.0099, + -0.0099, -0.0099, -0.0099, -0.0099, -0.0099 ; + + fates_seedling_light_mort_b = -7.148243, -7.148243, -7.148243, -7.148243, -7.148243, -7.148243, + -7.148243, -7.148243, -7.148243, -7.148243, -7.148243, -7.148243 ; + + fates_background_seedling_mort = 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, + 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371 ; + + fates_seedling_root_depth = 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, + 0.06, 0.06, 0.06, 0.06, 0.06, 0.06 ; + + fates_seedling_light_rec_a = 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, + 0.007, 0.007, 0.007 ; + + fates_seedling_light_rec_b = 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, + 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615 ; + fates_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9 ; - fates_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, 1.47, + fates_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, 1.47, 1.47, 1.47 ; - fates_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, + fates_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51 ; - fates_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + fates_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; fates_seed_suppl = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_senleaf_long_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, -255000, + fates_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, -255000, -255000, -255000, -255000, -255000, -255000 ; - fates_smpso = -66000, -66000, -66000, -66000, -66000, -66000, -66000, + fates_smpso = -66000, -66000, -66000, -66000, -66000, -66000, -66000, -66000, -66000, -66000, -66000, -66000 ; - fates_taulnir = 0.25, 0.1, 0.1, 0.25, 0.25, 0.25, 0.1, 0.25, 0.25, 0.34, + fates_taulnir = 0.25, 0.1, 0.1, 0.25, 0.25, 0.25, 0.1, 0.25, 0.25, 0.34, 0.34, 0.34 ; - fates_taulvis = 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, + fates_taulvis = 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05 ; - fates_tausnir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + fates_tausnir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.25, 0.25, 0.25 ; - fates_tausvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + fates_tausvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.12, 0.12, 0.12 ; - fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, + fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03 ; fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; @@ -1323,29 +1447,29 @@ data: fates_turnover_retrans_mode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, + fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7 ; fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; - fates_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, + fates_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055 ; fates_hlm_pft_map = - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; @@ -1425,6 +1549,8 @@ data: fates_leaf_stomatal_model = 1 ; + fates_regeneration_model = 2 ; + fates_logging_coll_under_frac = 0.55983 ; fates_logging_collateral_frac = 0.05 ; @@ -1471,6 +1597,14 @@ data: fates_photo_temp_acclim_timescale = 30 ; + fates_sdlng_emerg_h2o_timescale = 14 ; + + fates_sdlng_mort_par_timescale = 64 ; + + fates_sdlng_mdd_timescale = 126 ; + + fates_sdlng2sap_par_timescale = 64 ; + fates_photo_tempsens_model = 1 ; fates_q10_froz = 1.5 ; From 49a4d4ecebd2a18a59059597fcc4fc93ccfd59d7 Mon Sep 17 00:00:00 2001 From: adamhb Date: Wed, 12 Jan 2022 13:14:37 -0800 Subject: [PATCH 100/852] updated the fates-trs default param file --- parameter_files/fates_params_default.cdl | 32 ++++++------ .../patch_TRS_bciopt_1_12_2022.xml | 52 +++++++++++++++++++ 2 files changed, 69 insertions(+), 15 deletions(-) create mode 100644 parameter_files/patch_TRS_bciopt_1_12_2022.xml diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 89d89cdf2a..a8a614cf36 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1313,7 +1313,7 @@ data: 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047 ; - fates_recruit_hgt_min = 2.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, + fates_recruit_hgt_min = 2.345, 2.345, 2.345, 2.345, 2.345, 2.345, 0.75, 0.75, 0.75, 0.125, 0.125, 0.125 ; fates_recruit_initd = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, @@ -1334,16 +1334,17 @@ data: fates_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; - fates_repro_alloc_a = 0.0058, 0.0058, 0.0058, 0.0058, 0.0058, 0.0058, 0.0058, - 0.0058, 0.0058, 0.0058, 0.0058, 0.0058 ; + fates_repro_alloc_a = 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, + 0.0049, 0.0049, 0.0049, 0.0049, 0.0049 ; - fates_repro_alloc_b = -3.138, -3.138, -3.138, -3.138, - -3.138, -3.138, -3.138, -3.138, -3.138, -3.138, -3.138, -3.138 ; + fates_repro_alloc_b = -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, + -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171 ; - fates_repro_frac_seed = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + fates_repro_frac_seed = 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, + 0.24, 0.24, 0.24 ; - fates_a_emerg = 0.0006, 0.0006, 0.0006, 0.0006, - 0.0006, 0.0006, 0.0006, 0.0006, 0.0006, 0.0006, 0.0006, 0.0006 ; + fates_a_emerg = 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, + 0.0003, 0.0003, 0.0003, 0.0003 ; fates_b_emerg = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 ; @@ -1371,11 +1372,12 @@ data: 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05 ; - fates_seedling_light_mort_a = -0.0099, -0.0099, -0.0099, -0.0099, -0.0099, -0.0099, -0.0099, - -0.0099, -0.0099, -0.0099, -0.0099, -0.0099 ; + fates_seedling_light_mort_a = -0.009897694, -0.009897694, -0.009897694, -0.009897694, + -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, + -0.009897694, -0.009897694 ; - fates_seedling_light_mort_b = -7.148243, -7.148243, -7.148243, -7.148243, -7.148243, -7.148243, - -7.148243, -7.148243, -7.148243, -7.148243, -7.148243, -7.148243 ; + fates_seedling_light_mort_b = -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, + -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063 ; fates_background_seedling_mort = 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371 ; @@ -1597,13 +1599,13 @@ data: fates_photo_temp_acclim_timescale = 30 ; - fates_sdlng_emerg_h2o_timescale = 14 ; + fates_sdlng_emerg_h2o_timescale = 7 ; - fates_sdlng_mort_par_timescale = 64 ; + fates_sdlng_mort_par_timescale = 32 ; fates_sdlng_mdd_timescale = 126 ; - fates_sdlng2sap_par_timescale = 64 ; + fates_sdlng2sap_par_timescale = 32 ; fates_photo_tempsens_model = 1 ; diff --git a/parameter_files/patch_TRS_bciopt_1_12_2022.xml b/parameter_files/patch_TRS_bciopt_1_12_2022.xml new file mode 100644 index 0000000000..4e135f9d5b --- /dev/null +++ b/parameter_files/patch_TRS_bciopt_1_12_2022.xml @@ -0,0 +1,52 @@ + + + This parameter dataset was created by Ryan Knox rgknox@lbl.gov. Please contact if using in published work. The calibration uses the following datasets: [1] Ely et al. 2019. Leaf mass area, Panama. NGEE-Tropics data collection.http://dx.doi.org/10.15486/ngt/1411973 and [2] Condit et al. 2019. Complete data from the Barro Colorado 50-ha plot. https://doi.org/10.15146/5xcp-0d46. [3] Koven et al. 2019. Benchmarking and parameter sensitivity of physiological and vegetation dynamics using the functionally assembled terrestrial ecosystem simulator. Biogeosciences. The ECA nutrient aquisition parmeters are unconstrained, the file output naming convention vmn6phi is shorthand for vmax for nitrogen uptake is order e-6 and for phosphorus is excessively high. These parameters were calibrated with the special fates modification in main/EDTypesMod.F90: nclmax = 3 + fates_params_default.cdl + fates_params_TRS_bci_opt224_vmn6phi_011222.cdl + 1 + + 0 + 0 + 1,1,3,4 + 0.03347526,0.024,1e-08,0.0047 + 0.03347526,0.024,1e-08,0.0047 + 0.025,0,0,0 + 0.45,0.25,0,0 + 0.8012471 + 30.94711 + 0.0673 + 0.976 + -9 + -9 + 3 + 0.1266844 + 1.281329 + -9 + 0.768654 + 0.768654 + 57.6 + 0.74 + 21.6 + 200 + 2 + 5 + 0.4863088 + 3 + 3e-06 + 3e-06 + 3e-07 + 3e-08 + 0.03991654 + 0.01995827 + 0.01303514 + 0.02955703 + 3 + 3 + 0.04680188 + 0.001 + 0.8374751 + -1 + 0.5 + 1 + + From 41c8837a1255e479a2593c917c835b117093bd80 Mon Sep 17 00:00:00 2001 From: adamhb Date: Wed, 12 Jan 2022 16:11:06 -0800 Subject: [PATCH 101/852] =?UTF-8?q?added=20diagnostic=20print=20statements?= =?UTF-8?q?=20to=20write=20to=20fates=20log=20and=20the=20following=20hist?= =?UTF-8?q?ory=20vars:=20FATES=5FSEED=5FBANK=5FTRS','FATES=5FSEEDLING=5FPO?= =?UTF-8?q?OL=5FTRS=E2=80=99,=E2=80=99FATES=5FSEEDS=5FIN=5FLOCAL'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- biogeochem/EDPhysiologyMod.F90 | 62 +++++++++++++++++++++++++++---- main/FatesHistoryInterfaceMod.F90 | 51 ++++++++++++++++++++++--- parteh/PRTAllometricCarbonMod.F90 | 18 +++++++++ 3 files changed, 119 insertions(+), 12 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 04a9f416b4..494e352840 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -132,10 +132,11 @@ module EDPhysiologyMod public :: SeedIn logical, parameter :: debug = .false. ! local debug flag + logical, parameter :: debug_trs = .true. ! local debug flag character(len=*), parameter, private :: sourcefile = & __FILE__ - integer, parameter :: dleafon_drycheck = 100 ! Drought deciduous leaves max days on check parameter + integer, parameter :: dleafon_drycheck = 100 ! drought deciduous leaves max days on check parameter ! ============================================================================ @@ -1837,7 +1838,20 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) (litt%seed_germ(pft) * seedling_h2o_mort_rate) + & (litt%seed_germ(pft) * EDPftvarcon_inst%background_seedling_mort(pft) & * years_per_day) - + !ahb diagnostic + if (debug_trs) then + if (hlm_day_of_year == 40 .OR. hlm_day_of_year == 270) then + write(fates_log(),*) 'day_of_year:', hlm_day_of_year + write(fates_log(),*) 'patch_age:', currentPatch%age + write(fates_log(),*) 'pft', pft + write(fates_log(),*) 'seedling_light_mort_rate (day -1):', seedling_light_mort_rate + write(fates_log(),*) 'seedling_h2o_mort_rate (day -1):', seedling_h2o_mort_rate + write(fates_log(),*) 'seedling mdds ([0,1]):', seedling_mdds + end if + + end if !debug flag + !end ahb diagnostic + !----------------------------------------------------------------------- !END ahb's changes @@ -1919,7 +1933,7 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) !to work with the TRS function. seedling_layer_par = currentPatch%seedling_layer_par24%GetMean() * sec_per_day * megajoules_per_joule - + !Calculate the photoblastic germination rate modifier (see eqn. 3 of Hanbury-Brown et al., 2022) photoblastic_germ_modifier = seedling_layer_par / & (seedling_layer_par + EDPftvarcon_inst%par_crit_germ(pft)) @@ -1950,7 +1964,22 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) !Step 4. Calculate the amount of carbon germinating out of the seed bank litt%seed_germ_in(pft) = litt%seed(pft) * seedling_emerg_rate - + + !ahb diagnostic + if (debug_trs) then + if (hlm_day_of_year == 40 .OR. hlm_day_of_year == 270) then + write(fates_log(),*) 'day_of_year:', hlm_day_of_year + write(fates_log(),*) 'patch_age:', currentPatch%age + write(fates_log(),*) 'pft', pft + write(fates_log(),*) 'seedling_layer_par (MJ m-2 day-1):', seedling_layer_par + write(fates_log(),*) 'seedling_layer_smp (mm h2o suction):', seedling_layer_smp + write(fates_log(),*) 'photoblastic_germ_modifier ([0,1]):', photoblastic_germ_modifier + write(fates_log(),*) 'seedling_emerg_rate (day-1):', seedling_emerg_rate + end if + + end if !debug flag + !end ahb diagnostic + end if !regeneration model switch !-------------------------------------------------------------------------------------------- !TEMP @@ -2067,9 +2096,11 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) call h2d_allom(temp_cohort%hite,ft,temp_cohort%dbh) !ahb diagnostic - if (hlm_day_of_year == 40) then + if (debug_trs) then + if (hlm_day_of_year == 40 .OR. hlm_day_of_year == 270) then write(fates_log(),*) 'min_dbh:', temp_cohort%dbh - end if + end if !day condition + end if !debug condition !end ahb diagnostic @@ -2193,7 +2224,24 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) mass_avail = currentPatch%area * currentPatch%litter(el)%seed_germ(ft) * & EDPftvarcon_inst%seedling_light_rec_a(ft) * & sdlng2sap_par**EDPftvarcon_inst%seedling_light_rec_b(ft) - + + + !ahb diagnostic + if (debug_trs) then + if (hlm_day_of_year == 40 .OR. hlm_day_of_year == 270) then + write(fates_log(),*) 'day_of_year:', hlm_day_of_year + write(fates_log(),*) 'patch_age:', currentPatch%age + write(fates_log(),*) 'pft', ft + write(fates_log(),*) 'sdlng2sap_par (MJ m-2 day-1):', sdlng2sap_par + write(fates_log(),*) 'seedling_2_sapling_transition_rate (day -1):', & + EDPftvarcon_inst%seedling_light_rec_a(ft) * & + sdlng2sap_par**EDPftvarcon_inst%seedling_light_rec_b(ft) + end if + end if !debug flag + !end ahb diagnostic + + + !If soil moisture is below the moisture stress threshold recruitment does not occur ilayer_seedling_root = minloc(abs(bc_in%z_sisl(:)-EDPftvarcon_inst%seedling_root_depth(ft)),dim=1) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 20918251d2..dc8da2a166 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -194,11 +194,14 @@ module FatesHistoryInterfaceMod integer :: ih_cwd_elcwd - integer :: ih_litter_in_si ! carbon only - integer :: ih_litter_out_si ! carbon only - integer :: ih_seed_bank_si ! carbon only - integer :: ih_seeds_in_si ! carbon only - + integer :: ih_litter_in_si ! carbon only + integer :: ih_litter_out_si ! carbon only + integer :: ih_seed_bank_si ! carbon only + integer :: ih_seeds_in_si ! carbon only + integer :: ih_seeds_in_local_si ! carbon only + integer :: ih_seed_bank_trs_si ! carbon only + integer :: ih_seedling_pool_trs_si ! carbon only + integer :: ih_litter_in_elem integer :: ih_litter_out_elem integer :: ih_seed_bank_elem @@ -1863,7 +1866,10 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_litter_in_si => this%hvars(ih_litter_in_si)%r81d, & hio_litter_out_si => this%hvars(ih_litter_out_si)%r81d, & hio_seed_bank_si => this%hvars(ih_seed_bank_si)%r81d, & + hio_seed_bank_trs_si => this%hvars(ih_seed_bank_trs_si)%r81d, & + hio_seedling_pool_trs_si => this%hvars(ih_seedling_pool_trs_si)%r81d, & hio_seeds_in_si => this%hvars(ih_seeds_in_si)%r81d, & + hio_seeds_in_local_si => this%hvars(ih_seeds_in_local_si)%r81d, & hio_litter_in_elem => this%hvars(ih_litter_in_elem)%r82d, & hio_litter_out_elem => this%hvars(ih_litter_out_elem)%r82d, & hio_seed_bank_elem => this%hvars(ih_seed_bank_elem)%r82d, & @@ -3107,7 +3113,10 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_litter_out_si(io_si) = 0._r8 hio_seed_bank_si(io_si) = 0._r8 + hio_seed_bank_trs_si(io_si) = 0._r8 + hio_seedling_pool_trs_si(io_si) = 0._r8 hio_seeds_in_si(io_si) = 0._r8 + hio_seeds_in_local_si(io_si) = 0._r8 cpatch => sites(s)%oldest_patch do while(associated(cpatch)) @@ -3128,11 +3137,25 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_seed_bank_si(io_si) = hio_seed_bank_si(io_si) + & (sum(litt%seed(:))+sum(litt%seed_germ(:))) * & area_frac * days_per_sec + + ! Sum up total seed bank (just ungerminated) + hio_seed_bank_trs_si(io_si) = hio_seed_bank_trs_si(io_si) + & + sum(litt%seed(:)) * area_frac + + ! Sum up total seedling pool + hio_seedling_pool_trs_si(io_si) = hio_seedling_pool_trs_si(io_si) + & + sum(litt%seed_germ(:)) * area_frac ! Sum up the input flux into the seed bank (local and external) hio_seeds_in_si(io_si) = hio_seeds_in_si(io_si) + & (sum(litt%seed_in_local(:)) + sum(litt%seed_in_extern(:))) * & area_frac * days_per_sec + + hio_seeds_in_si(io_si) = hio_seeds_in_si(io_si) + & + sum(litt%seed_in_local(:)) * & + area_frac * days_per_sec + + cpatch => cpatch%younger end do @@ -4785,6 +4808,18 @@ subroutine define_history_vars(this, initialize_variables) use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_seed_bank_si) + + call this%set_history_var(vname='FATES_SEED_BANK_TRS', units='kg m-2', & + long='total seed mass of all PFTs in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_seed_bank_trs_si) + + call this%set_history_var(vname='FATES_SEEDLING_POOL_TRS', units='kg m-2', & + long='total seed mass of all PFTs in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_seedling_pool_trs_si) call this%set_history_var(vname='FATES_SEEDS_IN', units='kg m-2 s-1', & long='seed production rate in kg carbon per m2 second', & @@ -4792,6 +4827,12 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_seeds_in_si) + call this%set_history_var(vname='FATES_SEEDS_IN_LOCAL', units='kg m-2 s-1', & + long='local seed production rate in kg carbon per m2 second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_seeds_in_local_si) + call this%set_history_var(vname='FATES_LITTER_IN_EL', units='kg m-2 s-1', & long='litter flux in in kg element per m2 per second', & use_default='active', avgflag='A', vtype=site_elem_r8, & diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 904342520e..8cbc30494b 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -52,6 +52,8 @@ module PRTAllometricCarbonMod use FatesConstantsMod , only : nearzero use FatesConstantsMod , only : itrue use FatesConstantsMod , only : years_per_day + use FatesInterfaceTypesMod, only : hlm_day_of_year + use PRTParametersMod , only : prt_params use EDParamsMod , only : regeneration_model @@ -72,6 +74,7 @@ module PRTAllometricCarbonMod integer, parameter :: repro_c_id = 5 ! Unique object index for reproductive carbon integer, parameter :: struct_c_id = 6 ! Unique object index for structural carbon integer, parameter :: num_vars = 6 ! THIS MUST MATCH THE LARGEST INDEX ABOVE + logical, parameter :: debug_trs = .true. ! local debug flag ! For this hypothesis, we integrate dbh along with the other 6. Since this @@ -977,6 +980,21 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) (exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm) / & (1 + exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm))) + + !ahb diagnostic + if (debug_trs) then + if (hlm_day_of_year == 40 .OR. hlm_day_of_year == 270) then + + write(fates_log(),*) 'day_of_year:', hlm_day_of_year + write(fates_log(),*) 'pft:', ipft + write(fates_log(),*) 'dbh (cm):', dbh + write(fates_log(),*) 'repro_fraction:', repro_fraction + + end if !day condition + end if !debug condition + !end ahb diagnostic + + end if !regeneration model switch !END ahb's changes From a2eaf3009aa110826ec60b93af4a13cdd84e4938 Mon Sep 17 00:00:00 2001 From: Adrianna Foster Date: Thu, 13 Jan 2022 12:18:05 -0700 Subject: [PATCH 102/852] typo fix and remove 'event' --- main/FatesHistoryInterfaceMod.F90 | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 20918251d2..72451f6878 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2199,7 +2199,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! 24hr veg temperature hio_tveg24(io_si) = hio_tveg24(io_si) + & (cpatch%tveg24%GetMean()- t_water_freeze_k_1atm)*cpatch%area*AREA_INV - + ! Increment some patch-age-resolved diagnostics hio_lai_si_age(io_si,cpatch%age_class) = hio_lai_si_age(io_si,cpatch%age_class) & @@ -3599,7 +3599,7 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) hio_parsun_top_si_can => this%hvars(ih_parsun_top_si_can)%r82d, & hio_parsha_top_si_can => this%hvars(ih_parsha_top_si_can)%r82d, & hio_tveg => this%hvars(ih_tveg_si)%r81d) - + ! Flush the relevant history variables call this%flush_hvars(nc,upfreq_in=2) @@ -3645,10 +3645,10 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) hio_rad_error_si(io_si) = hio_rad_error_si(io_si) + & cpatch%radiation_error * cpatch%area * AREA_INV - + hio_tveg(io_si) = hio_tveg(io_si) + & (bc_in(s)%t_veg_pa(cpatch%patchno) - t_water_freeze_k_1atm)*cpatch%area*area_inv - + ccohort => cpatch%shortest do while(associated(ccohort)) @@ -4705,7 +4705,7 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index = ih_fire_fuel_eff_moist_si) - call this%set_history_var(vname='FATES_FUEL_SAV', units='per m', & + call this%set_history_var(vname='FATES_FUEL_SAV', units='m-1', & long='spitfire fuel surface area to volume ratio', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & @@ -5112,19 +5112,19 @@ subroutine define_history_vars(this, initialize_variables) ivar=ivar, initialize=initialize_variables, index = ih_c_lblayer_si) ! Temperature - + call this%set_history_var(vname='FATES_TVEG24', units='degree_Celsius', & long='fates 24-hr running mean vegetation temperature by site', & use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_tveg24_si ) - + call this%set_history_var(vname='FATES_TVEG', units='degree_Celsius', & long='fates instantaneous mean vegetation temperature by site', & use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & ivar=ivar, initialize=initialize_variables, index = ih_tveg_si ) - + ! radiation error call this%set_history_var(vname='FATES_RAD_ERROR', units='W m-2 ', & @@ -5728,7 +5728,7 @@ subroutine define_history_vars(this, initialize_variables) call this%set_history_var(vname='FATES_MORTALITY_LOGGING_SZPF', & units = 'm-2 yr-1', & - long='logging mortality by pft/size in number of plants per m2 per ', & + long='logging mortality by pft/size in number of plants per m2 per year', & use_default='inactive', & avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_m7_si_scpf) @@ -6078,21 +6078,21 @@ subroutine define_history_vars(this, initialize_variables) call this%set_history_var(vname='FATES_MORTALITY_LOGGING_SZ', & units = 'm-2 yr-1', & - long='logging mortality by size in number of plants per m2 per event', & + long='logging mortality by size in number of plants per m2 per year', & use_default='active', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index = ih_m7_si_scls) call this%set_history_var(vname='FATES_MORTALITY_FREEZING_SZ', & - units = 'm-2 event-1', & - long='freezing mortality by size in number of plants per m2 per event', & + units = 'm-2 yr-1', & + long='freezing mortality by size in number of plants per m2 per year', & use_default='active', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index = ih_m8_si_scls) call this%set_history_var(vname='FATES_MORTALITY_SENESCENCE_SZ', & units = 'm-2 yr-1', & - long='senescence mortality by size in number of plants per m2 per event', & + long='senescence mortality by size in number of plants per m2 per year', & use_default='active', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index = ih_m9_si_scls) From 96758c40d8b8f6e6c88d19d9eab3afe9206a12d4 Mon Sep 17 00:00:00 2001 From: adamhb Date: Thu, 13 Jan 2022 15:23:18 -0800 Subject: [PATCH 103/852] fixed typos in the FatesHistoryInterfaceMod; fates-trs is working well! Its predictions of recruitment are in line with observations at BCI and the offline-trs --- main/FatesHistoryInterfaceMod.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index dc8da2a166..61cb0ed86e 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -3151,7 +3151,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) (sum(litt%seed_in_local(:)) + sum(litt%seed_in_extern(:))) * & area_frac * days_per_sec - hio_seeds_in_si(io_si) = hio_seeds_in_si(io_si) + & + hio_seeds_in_local_si(io_si) = hio_seeds_in_local_si(io_si) + & sum(litt%seed_in_local(:)) * & area_frac * days_per_sec @@ -4533,7 +4533,7 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_gpp_si_pft) - call this%set_history_var(vname='FATES_NPP_PF', units='kg m-2 yr-1', & + call this%set_history_var(vname='FATES_NPP_PF', units='kg m-2 s-1', & long='total PFT-level NPP in kg carbon per m2 land area per second', & use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & @@ -4816,7 +4816,7 @@ subroutine define_history_vars(this, initialize_variables) index = ih_seed_bank_trs_si) call this%set_history_var(vname='FATES_SEEDLING_POOL_TRS', units='kg m-2', & - long='total seed mass of all PFTs in kg carbon per m2 land area', & + long='total seedling mass of all PFTs in kg carbon per m2 land area', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_seedling_pool_trs_si) From 5721c209c0e0117a41169564977f4805046b17b0 Mon Sep 17 00:00:00 2001 From: Azamat Mametjanov Date: Thu, 13 Jan 2022 18:58:31 -0500 Subject: [PATCH 104/852] Add return status checks in cohort deallocations --- biogeochem/EDCohortDynamicsMod.F90 | 29 ++++++++++++++++++------ parteh/PRTAllometricCNPMod.F90 | 36 +++++++++++++++++------------- parteh/PRTGenericMod.F90 | 28 ++++++++++++++--------- 3 files changed, 60 insertions(+), 33 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index b6714ee3e9..0e0b8812cc 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -733,6 +733,8 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_ integer :: terminate ! do we terminate (itrue) or not (ifalse) integer :: c ! counter for litter size class. integer :: levcan ! canopy level + integer :: istat ! return status code + character(len=255) :: smsg !---------------------------------------------------------------------- currentCohort => currentPatch%shortest @@ -848,9 +850,12 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_ call DeallocateCohort(currentCohort) - deallocate(currentCohort) - nullify(currentCohort) - + deallocate(currentCohort, stat=istat, errmsg=smsg) + if (istat/=0) then + if (debug) write(fates_log(),*) 'warning: stat/=0 in deallocate(currentCohort):'//trim(smsg) + nullify(currentCohort) + endif + endif currentCohort => tallerCohort enddo @@ -991,6 +996,8 @@ subroutine DeallocateCohort(currentCohort) ! ---------------------------------------------------------------------------------- type(ed_cohort_type),intent(inout) :: currentCohort + integer :: istat ! return status code + character(len=255) :: smsg ! At this point, nothing should be pointing to current Cohort if (hlm_use_planthydro.eq.itrue) call DeallocateHydrCohort(currentCohort) @@ -999,7 +1006,11 @@ subroutine DeallocateCohort(currentCohort) call currentCohort%prt%DeallocatePRTVartypes() ! Deallocate the PRT object - deallocate(currentCohort%prt) + deallocate(currentCohort%prt, stat=istat, errmsg=smsg) + if (istat/=0) then + if (debug) write(fates_log(),*) 'warning: stat/=0 in deallocate(currentCohort%prt):'//trim(smsg) + nullify(currentCohort%prt) + endif return end subroutine DeallocateCohort @@ -1056,6 +1067,8 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) logical, parameter :: fuse_debug = .false. ! This debug is over-verbose ! and gets its own flag + integer :: istat ! return status code + character(len=255) :: smsg !---------------------------------------------------------------------- @@ -1482,9 +1495,11 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) endif call DeallocateCohort(nextc) - deallocate(nextc) - nullify(nextc) - + deallocate(nextc, stat=istat, errmsg=smsg) + if (istat/=0) then + if (debug) write(fates_log(),*) 'warning: stat/=0 on deallocate(nextc):'//trim(smsg) + nullify(nextc) + endif endif ! if( currentCohort%isnew.eqv.nextc%isnew ) then endif !canopy layer diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 5617d71e5d..625fdf1dbd 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -254,10 +254,13 @@ subroutine InitPRTGlobalAllometricCNP() ! waste memory on it. ! ----------------------------------------------------------------------------------- - integer :: nleafage + integer :: nleafage, istat + character(len=255) :: smsg - allocate(prt_global_acnp) - allocate(prt_global_acnp%state_descriptor(num_vars)) + allocate(prt_global_acnp, stat=istat) + if (istat/=0) call endrun(msg='allocate stat/=0:'//trim(smsg)//errMsg(sourcefile, __LINE__)) + allocate(prt_global_acnp%state_descriptor(num_vars), stat=istat) + if (istat/=0) call endrun(msg='allocate stat/=0:'//trim(smsg)//errMsg(sourcefile, __LINE__)) prt_global_acnp%hyp_name = 'Allometric Flexible C+N+P' @@ -341,13 +344,12 @@ subroutine DailyPRTAllometricCNP(this) real(r8),pointer :: p_efflux ! Total plant efflux of phosphorus (kgP) real(r8),pointer :: n_need ! N need (algorithm dependant) (kgN) real(r8),pointer :: p_need ! P need (algorithm dependant) (kgP) - real(r8),pointer :: growth_r ! Total plant growth respiration this step (kgC) ! These are pointers to the state variables, rearranged in organ dimensioned ! arrays. This is useful because we loop through organs so often - type(parray_type),pointer :: state_c(:) ! State array for carbon, by organ [kg] - type(parray_type),pointer :: state_n(:) ! State array for N, by organ [kg] - type(parray_type),pointer :: state_p(:) ! State array for P, by organ [kg] + type(parray_type), dimension(num_organs) :: state_c ! State array for carbon, by organ [kg] + type(parray_type), dimension(num_organs) :: state_n ! State array for N, by organ [kg] + type(parray_type), dimension(num_organs) :: state_p ! State array for P, by organ [kg] integer :: i_org ! organ index integer :: i_var ! variable index @@ -423,10 +425,6 @@ subroutine DailyPRTAllometricCNP(this) ! point to that bin. However, we need to account for all bins ! when we calculate the deficit - allocate(state_c(num_organs)) - allocate(state_n(num_organs)) - allocate(state_p(num_organs)) - ! Set carbon targets based on the plant's current stature target_c(:) = fates_unset_r8 target_dcdd(:) = fates_unset_r8 @@ -603,9 +601,10 @@ subroutine DailyPRTAllometricCNP(this) n_need = target_n - state_n(store_id)%ptr p_need = target_p - state_p(store_id)%ptr - deallocate(state_c) - deallocate(state_n) - deallocate(state_p) + do i_org = 1,num_organs + nullify(state_c(i_org)%ptr, state_n(i_org)%ptr, state_p(i_org)%ptr) + end do + nullify(dbh, maint_r_def, c_efflux, n_efflux, p_efflux, n_need, p_need) return end subroutine DailyPRTAllometricCNP @@ -998,7 +997,6 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & real(r8), intent(inout) :: c_gain real(r8), intent(inout) :: n_gain real(r8), intent(inout) :: p_gain - real(r8), pointer :: maint_r_deficit type(parray_type) :: state_c(:) ! State array for carbon, by organ [kg] type(parray_type) :: state_n(:) ! State array for N, by organ [kg] type(parray_type) :: state_p(:) ! State array for P, by organ [kg] @@ -1528,6 +1526,8 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & end if if_stature_growth + + nullify(dbh) return end subroutine CNPStatureGrowth @@ -1646,6 +1646,8 @@ subroutine CNPAllocateRemainder(this,c_gain, n_gain, p_gain, & ! n_gain = 0.0_r8 ! p_gain = 0.0_r8 + nullify(dbh) + return end subroutine CNPAllocateRemainder @@ -1795,7 +1797,9 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe call endrun(msg=errMsg(sourcefile, __LINE__)) end if end if - + + nullify(dbh) + return end function GetNutrientTargetCNP diff --git a/parteh/PRTGenericMod.F90 b/parteh/PRTGenericMod.F90 index 3dab9563a3..b85573dca1 100644 --- a/parteh/PRTGenericMod.F90 +++ b/parteh/PRTGenericMod.F90 @@ -861,31 +861,39 @@ subroutine DeallocatePRTVartypes(this) ! --------------------------------------------------------------------------------- class(prt_vartypes) :: this - integer :: i_var + integer :: i_var, istat + character(len=255) :: smsg ! Check to see if there is any value in these pools? ! SHould not deallocate if there is any carbon left do i_var = 1, prt_global%num_vars - deallocate(this%variables(i_var)%val) - deallocate(this%variables(i_var)%val0) - deallocate(this%variables(i_var)%net_alloc) - deallocate(this%variables(i_var)%turnover) - deallocate(this%variables(i_var)%burned) + deallocate( & + & this%variables(i_var)%val, & + & this%variables(i_var)%val0, & + & this%variables(i_var)%net_alloc, & + & this%variables(i_var)%turnover, & + & this%variables(i_var)%burned, & + & stat=istat, errmsg=smsg ) + if (istat/=0) call endrun(msg='deallocate stat/=0:'//trim(smsg)//errMsg(sourcefile, __LINE__)) end do - deallocate(this%variables) + deallocate(this%variables, stat=istat, errmsg=smsg) + if (istat/=0) call endrun(msg='deallocate stat/=0:'//trim(smsg)//errMsg(sourcefile, __LINE__)) if(allocated(this%bc_in))then - deallocate(this%bc_in) + deallocate(this%bc_in, stat=istat, errmsg=smsg) + if (istat/=0) call endrun(msg='deallocate stat/=0:'//trim(smsg)//errMsg(sourcefile, __LINE__)) end if if(allocated(this%bc_out))then - deallocate(this%bc_out) + deallocate(this%bc_out, stat=istat, errmsg=smsg) + if (istat/=0) call endrun(msg='deallocate stat/=0:'//trim(smsg)//errMsg(sourcefile, __LINE__)) end if if(allocated(this%bc_inout))then - deallocate(this%bc_inout) + deallocate(this%bc_inout, stat=istat, errmsg=smsg) + if (istat/=0) call endrun(msg='deallocate stat/=0:'//trim(smsg)//errMsg(sourcefile, __LINE__)) end if return From 9b5074466f6a3e0961d61c6a9f43405fbc8894dc Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 20 Jan 2022 16:42:18 -0500 Subject: [PATCH 105/852] Updates to fates history variables for NP cycling --- biogeochem/FatesSoilBGCFluxMod.F90 | 14 ++++++++++++-- main/EDMainMod.F90 | 1 + main/EDTypesMod.F90 | 28 +++++++++++++++++++++++++++- main/FatesHistoryInterfaceMod.F90 | 20 ++++++++++++++++++++ 4 files changed, 60 insertions(+), 3 deletions(-) diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index 90b79559a2..73572851fe 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -718,14 +718,24 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) elseif(element_list(el).eq.phosphorus_element) then efflux_ptr => currentCohort%daily_p_efflux end if + + call set_root_fraction(csite%rootfrac_scr, currentCohort%pft, csite%zi_soil, & + bc_in%max_rooting_depth_index_col ) ! Unit conversion ! kg/plant/day * plant/ha * ha/m2 -> kg/m2/day + ! Also, lets efflux out through the roots - do id = 1,nlev_eff_decomp + !do id = 1,nlev_eff_decomp + ! flux_lab_si(id) = flux_lab_si(id) + & + ! efflux_ptr * currentCohort%n* AREA_INV * surface_prof(id) + !end do + + do id = 1,nlev_eff_soil flux_lab_si(id) = flux_lab_si(id) + & - efflux_ptr * currentCohort%n* AREA_INV * surface_prof(id) + efflux_ptr * currentCohort%n* AREA_INV *csite%rootfrac_scr(id) end do + end if currentCohort => currentCohort%shorter end do diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 7d75d8a885..66288650b3 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -107,6 +107,7 @@ module EDMainMod ! !PUBLIC MEMBER FUNCTIONS: public :: ed_ecosystem_dynamics public :: ed_update_site + ! ! !PRIVATE MEMBER FUNCTIONS: diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 6f347b8b41..40420da88d 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -190,7 +190,9 @@ module EDTypesMod integer, public :: n_uptake_mode integer, public :: p_uptake_mode + + !************************************ !** COHORT type structure ** @@ -824,9 +826,33 @@ module EDTypesMod public :: dump_patch public :: dump_cohort public :: dump_cohort_hydr - + public :: CanUpperUnder contains + ! ===================================================================================== + + function CanUpperUnder(ccohort) result(can_position) + + ! This simple function is used to determine if a + ! cohort's crown position is in the upper portion (ie the canopy) + ! or the understory. This differentiation is only used for + ! diagnostic purposes. Functionally, the model uses + ! the canopy layer position, which may have more than two layers + ! at any given time. Utlimately, every plant that is not in the + ! top layer (canopy), is considered understory. + + type(ed_cohort_type) :: ccohort ! Current cohort of interest + integer :: can_position + + if(ccohort%canopy_layer == 1)then + can_position = ican_upper + else + can_position = ican_ustory + end if + + end function CanUpperUnder + + ! ===================================================================================== subroutine ZeroFluxDiags(this) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index c3e94bebae..98a4ab730e 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -176,6 +176,8 @@ module FatesHistoryInterfaceMod integer :: ih_l2fr_si integer :: ih_l2fr_scpf + integer :: ih_l2fr_canopy_scpf + integer :: ih_l2fr_understory_scpf integer,public :: ih_nh4uptake_si integer,public :: ih_no3uptake_si @@ -1797,6 +1799,8 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_trimming_si => this%hvars(ih_trimming_si)%r81d, & hio_l2fr_si => this%hvars(ih_l2fr_si)%r81d, & hio_l2fr_scpf => this%hvars(ih_l2fr_scpf)%r82d, & + hio_l2fr_canopy_scpf => this%hvars(ih_l2fr_canopy_scpf)%r82d, & + hio_l2fr_understory_scpf => this%hvars(ih_l2fr_understory_scpf)%r82d, & hio_area_plant_si => this%hvars(ih_area_plant_si)%r81d, & hio_area_trees_si => this%hvars(ih_area_trees_si)%r81d, & hio_canopy_spread_si => this%hvars(ih_canopy_spread_si)%r81d, & @@ -2282,6 +2286,10 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) ! These L2FR diagnostics are weighted by fineroot carbon biomass hio_l2fr_si(io_si) = hio_l2fr_si(io_si) + ccohort%n*fnrt_m*ccohort%l2fr + hio_l2fr_scpf(io_si,ccohort%size_by_pft_class) = & + hio_l2fr_scpf(io_si,ccohort%size_by_pft_class) + & + ccohort%n*fnrt_m*ccohort%l2fr + hio_l2fr_scpf(io_si,ccohort%size_by_pft_class) = & hio_l2fr_scpf(io_si,ccohort%size_by_pft_class) + & ccohort%n*fnrt_m*ccohort%l2fr @@ -4311,6 +4319,18 @@ subroutine define_history_vars(this, initialize_variables) use_default='active', & avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_l2fr_scpf) + + call this%set_history_var(vname='LEAF2FNRT_CANOPY_SCPF', units='none', & + long='The leaf to fineroot biomass multiplier for target allometry in canopy plants', & + use_default='active', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_l2fr_canopy_scpf) + + call this%set_history_var(vname='LEAF2FNRT_UNDERSTORY_SCPF', units='none', & + long='The leaf to fineroot biomass multiplier for target allometry in understory plants', & + use_default='active', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_l2fr_understory_scpf) call this%set_history_var(vname='AREA_PLANT', units='m2/m2', & long='area occupied by all plants', use_default='active', & From 6517c7dc6c64c8fc4d6570daa5262453b22165f0 Mon Sep 17 00:00:00 2001 From: Shijie Shu Date: Thu, 20 Jan 2022 14:00:22 -0800 Subject: [PATCH 106/852] Pass parameter from HLM through bc_in instead of modules. --- biogeochem/EDCanopyStructureMod.F90 | 10 +- biogeochem/EDLoggingMortalityMod.F90 | 143 ++++++++++++++------------- main/FatesInterfaceTypesMod.F90 | 2 + 3 files changed, 83 insertions(+), 72 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index d25d44bcb2..aef8e3bfa5 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1869,7 +1869,7 @@ end subroutine leaf_area_profile ! ====================================================================================== - subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) + subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_in,bc_out) ! ---------------------------------------------------------------------------------- ! The purpose of this routine is to package output boundary conditions related @@ -1878,13 +1878,14 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) use EDTypesMod , only : ed_patch_type, ed_cohort_type, & ed_site_type, AREA - use FatesInterfaceTypesMod , only : bc_out_type + use FatesInterfaceTypesMod , only : bc_in_type, bc_out_type ! ! !ARGUMENTS integer, intent(in) :: nsites type(ed_site_type), intent(inout), target :: sites(nsites) integer, intent(in) :: fcolumn(nsites) + type(bc_in_type), intent(in) :: bc_in(nsites) type(bc_out_type), intent(inout) :: bc_out(nsites) ! Locals @@ -1912,14 +1913,13 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) currentPatch%total_canopy_area = currentPatch%area endif - if (associated(currentPatch%tallest)) then bc_out(s)%htop_pa(ifp) = currentPatch%tallest%hite else ! FIX(RF,040113) - should this be a parameter for the minimum possible vegetation height? bc_out(s)%htop_pa(ifp) = 0.1_r8 endif - + bc_out(s)%hbot_pa(ifp) = max(0._r8, min(0.2_r8, bc_out(s)%htop_pa(ifp)- 1.0_r8)) ! Use leaf area weighting for all cohorts in the patch to define the characteristic @@ -2026,7 +2026,7 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) end if ! Pass FATES Harvested C to bc_out. - call UpdateHarvestC(sites(s),bc_out(s)) + call UpdateHarvestC(sites(s),bc_in(s),bc_out(s)) end do diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 8dd13bc39b..976fea5a1c 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -84,6 +84,11 @@ module EDLoggingMortalityMod real(r8), parameter :: harvest_litter_localization = 0.0_r8 + ! ! transfer factor from kg biomass (dry matter) to kg carbon + ! ! now we applied a simple fraction of 50% based on the IPCC + ! ! guideline + ! real(r8), parameter :: carbon_per_kg_biomass = 0.5_r8 + character(len=*), parameter, private :: sourcefile = & __FILE__ @@ -251,16 +256,23 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & hlm_harvest_rates, frac_site_primary, secondary_age, harvest_rate) if (fates_global_verbose()) then - write(fates_log(), *) 'Successfully Read Harvest Rate from HLM.', hlm_harvest_rates(:), harvest_rate + write(fates_log(), *) 'Successfully Read Harvest Rate from HLM.' end if else if (hlm_use_lu_harvest == itrue .and. hlm_harvest_units == hlm_harvest_carbon) then ! 2=use carbon from hlm - ! not implemented yet ! Shijie: Shall call another function, which transfer biomass/carbon into fraction? ! Is it the correct place to call the function? - write(fates_log(),*) 'HLM harvest carbon data not implemented yet. Exiting.' - call endrun(msg=errMsg(sourcefile, __LINE__)) + ! Inputs: patch_area, patch_biomass, what else? + + ! call get_harvest_rate_carbon (patch_anthro_disturbance_label, hlm_harvest_catnames, & + ! hlm_harvest_rates, frac_site_primary, secondary_age, harvest_rate) + + ! if (fates_global_verbose()) then + ! write(fates_log(), *) 'Successfully Read Harvest Rate from HLM.', hlm_harvest_rates(:), harvest_rate + ! end if + !write(fates_log(),*) 'HLM harvest carbon data not implemented yet. Exiting.' + !call endrun(msg=errMsg(sourcefile, __LINE__)) endif ! transfer of area to secondary land is based on overall area affected, not just logged crown area @@ -801,70 +813,67 @@ end subroutine logging_litter_fluxes ! ===================================================================================== - subroutine UpdateHarvestC(currentSite,bc_out) - - ! ---------------------------------------------------------------------------------- - ! Added by Shijie Shu. - ! This subroutine is called when logging is completed and need to update - ! Harvested C flux in HLM. - ! ---------------------------------------------------------------------------------- - use EDtypesMod , only : ed_site_type - use FatesInterfaceTypesMod , only : bc_out_type - use PRTGenericMod , only : num_elements - use pftvarcon , only : pprodharv10 - - ! Arguments - type(ed_site_type), intent(inout), target :: currentSite ! site structure - type(bc_out_type), intent(inout) :: bc_out - - integer :: el - integer :: icode - real(r8) :: unit_trans_factor - - ! Flush the older value before update - if(logging_time) then - bc_out%hrv_deadstemc_to_prod10c = 0._r8 - bc_out%hrv_deadstemc_to_prod100c = 0._r8 - end if - - ! First test tropic forest (PFT=1) - ! Calculate the unit transfer factor (from kgC m-2 day-1 to gC m-2 s-1) - ! for icode == 2, icode < 0, and icode > 10000 is one time harvest, thus - ! shall distribute into everyday - icode = int(logging_event_code) - if(icode .eq. 1) then - ! Logging is turned off - unit_trans_factor = 1._r8 - else if(icode .eq. 3) then - ! Logging event every day - this may not work due to the mortality exclusivity - unit_trans_factor = 1000._r8 * days_per_sec - else if(icode .eq. 4) then - ! Logging event once a month - ! Shijie: Shall think about a better if expreession? - if ((hlm_current_month == 1) .or. (hlm_current_month == 3) .or. & - (hlm_current_month == 5) .or. (hlm_current_month == 7) .or. & - (hlm_current_month == 8) .or. (hlm_current_month == 10) .or. & - (hlm_current_month == 12)) then - unit_trans_factor = 1000._r8 * days_per_sec / 31._r8 - else if((hlm_current_month == 4) .or. (hlm_current_month == 6) .or. & - (hlm_current_month == 9) .or. (hlm_current_month == 11)) then - unit_trans_factor = 1000._r8 * days_per_sec / 30._r8 + subroutine UpdateHarvestC(currentSite,bc_in,bc_out) + + ! ---------------------------------------------------------------------------------- + ! Added by Shijie Shu. + ! This subroutine is called when logging is completed and need to update + ! Harvested C flux in HLM. + ! ---------------------------------------------------------------------------------- + use EDtypesMod , only : ed_site_type + use FatesInterfaceTypesMod , only : bc_in_type, bc_out_type + + ! Arguments + type(ed_site_type), intent(inout), target :: currentSite ! site structure + type(bc_in_type), intent(in) :: bc_in + type(bc_out_type), intent(inout) :: bc_out + + integer :: icode + real(r8) :: unit_trans_factor + + + ! Flush the older value before update + if(logging_time) then + bc_out%hrv_deadstemc_to_prod10c = 0._r8 + bc_out%hrv_deadstemc_to_prod100c = 0._r8 + end if + + ! First test tropic forest (PFT=1) + ! Calculate the unit transfer factor (from kgC m-2 day-1 to gC m-2 s-1) + ! for icode == 2, icode < 0, and icode > 10000 is one time harvest, thus + ! shall distribute into everyday + icode = int(logging_event_code) + if(icode .eq. 1) then + ! Logging is turned off + unit_trans_factor = 1._r8 + else if(icode .eq. 3) then + ! Logging event every day - this may not work due to the mortality exclusivity + unit_trans_factor = 1000._r8 * days_per_sec + else if(icode .eq. 4) then + ! Logging event once a month + ! Shijie: Shall think about a better if expreession? + if ((hlm_current_month == 1) .or. (hlm_current_month == 3) .or. & + (hlm_current_month == 5) .or. (hlm_current_month == 7) .or. & + (hlm_current_month == 8) .or. (hlm_current_month == 10) .or. & + (hlm_current_month == 12)) then + unit_trans_factor = 1000._r8 * days_per_sec / 31._r8 + else if((hlm_current_month == 4) .or. (hlm_current_month == 6) .or. & + (hlm_current_month == 9) .or. (hlm_current_month == 11)) then + unit_trans_factor = 1000._r8 * days_per_sec / 30._r8 + else + unit_trans_factor = 1000._r8 * days_per_sec / 28._r8 + end if else - unit_trans_factor = 1000._r8 * days_per_sec / 28._r8 + ! Logging event one time every year + unit_trans_factor = 1000._r8 * days_per_sec * years_per_day end if - else - ! Logging event one time every year - unit_trans_factor = 1000._r8 * days_per_sec * years_per_day - end if - - do el = 1,num_elements - bc_out%hrv_deadstemc_to_prod10c = bc_out%hrv_deadstemc_to_prod10c + & - currentSite%harvest_carbon_flux * pprodharv10(1) * unit_trans_factor - bc_out%hrv_deadstemc_to_prod100c = bc_out%hrv_deadstemc_to_prod100c + & - currentSite%harvest_carbon_flux * (1-pprodharv10(1)) * unit_trans_factor - end do - - return - end subroutine UpdateHarvestC + + bc_out%hrv_deadstemc_to_prod10c = bc_out%hrv_deadstemc_to_prod10c + & + currentSite%harvest_carbon_flux * bc_in%pprodharv10_forest_mean * unit_trans_factor + bc_out%hrv_deadstemc_to_prod100c = bc_out%hrv_deadstemc_to_prod100c + & + currentSite%harvest_carbon_flux * (1-bc_in%pprodharv10_forest_mean) * unit_trans_factor + + return + end subroutine UpdateHarvestC end module EDLoggingMortalityMod diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index b0bebad637..f7e1b95d20 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -507,6 +507,8 @@ module FatesInterfaceTypesMod character(len=64), allocatable :: hlm_harvest_catnames(:) ! names of hlm_harvest d1 integer :: hlm_harvest_units ! what units are the harvest rates specified in? [area vs carbon] + + real(r8) :: pprodharv10_forest_mean ! harvest mortality proportion of deadstem to 10-yr pool ! Fixed biogeography mode real(r8), allocatable :: pft_areafrac(:) ! Fractional area of the FATES column occupied by each PFT From 816176b80f67fe09b409ca5054bcec627fff3e25 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 21 Jan 2022 16:51:17 -0800 Subject: [PATCH 107/852] adding comments regarding sp mode --- biogeochem/EDCohortDynamicsMod.F90 | 1 + biogeochem/EDPhysiologyMod.F90 | 1 + 2 files changed, 2 insertions(+) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 5446c94dda..d5cc4d1877 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -1323,6 +1323,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) currentCohort%canopy_layer, currentPatch%canopy_layer_tlai, & currentCohort%vcmax25top) + ! We don't need check on sp mode here since we don't fuse_cohorts with sp mode currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_trim, & currentCohort%c_area, newn, currentCohort%canopy_layer, & currentPatch%canopy_layer_tlai, currentCohort%treelai,currentCohort%vcmax25top,1 ) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index c51ab7867e..9b071d5fc3 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -467,6 +467,7 @@ subroutine trim_canopy( currentSite ) currentCohort%n, currentCohort%canopy_layer, & currentPatch%canopy_layer_tlai,currentCohort%vcmax25top ) + ! We don't need check on sp mode here since we don't trim_canopy with sp mode currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_trim, & currentCohort%c_area, currentCohort%n, currentCohort%canopy_layer, & currentPatch%canopy_layer_tlai, currentCohort%treelai, & From 6214207c64e9e960036599df85c88646515ea326 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 21 Jan 2022 16:53:15 -0800 Subject: [PATCH 108/852] initial refactor of the patch-level lai update in leaf_area_profile --- biogeochem/EDCanopyStructureMod.F90 | 123 ++++++++++++++++++---------- 1 file changed, 79 insertions(+), 44 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 130fd776f7..1dfba3f6f5 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1523,8 +1523,6 @@ subroutine leaf_area_profile( currentSite ) ! calculate tree lai and sai. ! -------------------------------------------------------------------------------- - currentPatch%canopy_layer_tlai(:) = 0._r8 - currentPatch%ncan(:,:) = 0 currentPatch%nrad(:,:) = 0 patch_lai = 0._r8 currentPatch%tlai_profile(:,:,:) = 0._r8 @@ -1542,45 +1540,7 @@ subroutine leaf_area_profile( currentSite ) if (currentPatch%total_canopy_area > nearzero ) then - - currentCohort => currentPatch%tallest - do while(associated(currentCohort)) - - ft = currentCohort%pft - cl = currentCohort%canopy_layer - - ! Calculate LAI of layers above - ! Note that the canopy_layer_lai is also calculated in this loop - ! but since we go top down in terms of plant size, we should be okay - - leaf_c = currentCohort%prt%GetState(leaf_organ,all_carbon_elements) - - currentCohort%treelai = tree_lai(leaf_c, currentCohort%pft, currentCohort%c_area, & - currentCohort%n, currentCohort%canopy_layer, & - currentPatch%canopy_layer_tlai,currentCohort%vcmax25top ) - - if (hlm_use_sp .eq. ifalse) then - currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_trim, & - currentCohort%c_area, currentCohort%n, currentCohort%canopy_layer, & - currentPatch%canopy_layer_tlai, currentCohort%treelai , & - currentCohort%vcmax25top,4) - end if - - currentCohort%lai = currentCohort%treelai *currentCohort%c_area/currentPatch%total_canopy_area - currentCohort%sai = currentCohort%treesai *currentCohort%c_area/currentPatch%total_canopy_area - - ! Number of actual vegetation layers in this cohort's crown - currentCohort%nv = count((currentCohort%treelai+currentCohort%treesai) .gt. dlower_vai(:)) + 1 - - currentPatch%ncan(cl,ft) = max(currentPatch%ncan(cl,ft),currentCohort%NV) - - patch_lai = patch_lai + currentCohort%lai - - currentPatch%canopy_layer_tlai(cl) = currentPatch%canopy_layer_tlai(cl) + currentCohort%lai - - currentCohort => currentCohort%shorter - - enddo !currentCohort + call UpdatePatchLAI(currentPatch, patch_lai) if(smooth_leaf_distribution == 1)then @@ -2211,8 +2171,8 @@ subroutine CanopyLayerArea(currentPatch,site_spread,layer_index,layer_area) real(r8),intent(inout) :: layer_area type(ed_cohort_type), pointer :: currentCohort - - + + layer_area = 0.0_r8 currentCohort => currentPatch%tallest do while (associated(currentCohort)) @@ -2224,7 +2184,82 @@ subroutine CanopyLayerArea(currentPatch,site_spread,layer_index,layer_area) currentCohort => currentCohort%shorter enddo return - end subroutine CanopyLayerArea + end subroutine CanopyLayerArea + + ! =============================================================================================== + + subroutine UpdatePatchLAI(currentPatch, patch_lai) + + ! -------------------------------------------------------------------------------------------- + ! This subroutine works through the current patch cohorts and updates the canopy_layer_tlai + ! and related variables + ! --------------------------------------------------------------------------------------------- + + ! Arguments + type(ed_patch_type),intent(inout), target :: currentPatch + real(r8), intent(out) :: patch_lai + + ! Local Variables + type(ed_cohort_type), pointer :: currentCohort + integer :: cl ! Canopy layer index + integer :: ft ! Plant functional type index + + ! Zero out the patch-level canopy layer variables + currentPatch%canopy_layer_tlai(:) = 0._r8 + currentPatch%ncan(:,:) = 0 + + ! Calculate LAI of layers above. Because it is possible for some understory cohorts + ! to be taller than cohorts in the top canopy layer, we must iterate through the + ! patch by canopy layer first. Given that canopy_layer_tlai is a patch level variable + ! we could iterate through each cohort in any direction as long as we go down through + ! the canopy layers. + + !canopyloop: do cl = 1,nclmax + currentCohort => currentPatch%tallest + cohortloop: do while(associated(currentCohort)) + + ! Only update the current cohort tree lai if lai of the above layers have been calculated + !if (currentCohort%canopy_layer .eq. cl) then + cl = currentCohort%canopy_layer + ft = currentCohort%pft + leaf_c = currentCohort%prt%GetState(leaf_organ,all_carbon_elements) + + ! Note that tree_lai has an internal check on the canopy + currentCohort%treelai = tree_lai(leaf_c, currentCohort%pft, currentCohort%c_area, & + currentCohort%n, currentCohort%canopy_layer, & + currentPatch%canopy_layer_tlai,currentCohort%vcmax25top ) + + if (hlm_use_sp .eq. ifalse) then + currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_trim, & + currentCohort%c_area, currentCohort%n, currentCohort%canopy_layer, & + currentPatch%canopy_layer_tlai, currentCohort%treelai , & + currentCohort%vcmax25top,4) + end if + + ! Update the cohort lai and sai + currentCohort%lai = currentCohort%treelai *currentCohort%c_area/currentPatch%total_canopy_area + currentCohort%sai = currentCohort%treesai *currentCohort%c_area/currentPatch%total_canopy_area + + ! Number of actual vegetation layers in this cohort's crown + currentCohort%nv = count((currentCohort%treelai+currentCohort%treesai) .gt. dlower_vai(:)) + 1 + + ! Update the number of number of vegetation layers + currentPatch%ncan(cl,ft) = max(currentPatch%ncan(cl,ft),currentCohort%NV) + + ! Update the patch canopy layer tlai + currentPatch%canopy_layer_tlai(cl) = currentPatch%canopy_layer_tlai(cl) + currentCohort%lai + + ! Calculate the total patch lai + patch_lai = patch_lai + currentCohort%lai + + !end if + + currentCohort => currentCohort%shorter + + end do cohortloop + !end do canopyloop + + end subroutine UpdatePatchLAI ! =============================================================================================== From cc5a60bf289819232c48b3d4defbd6157fe95903 Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Fri, 28 Jan 2022 15:36:01 -0800 Subject: [PATCH 109/852] [ Remove branch frac as a cohort variable ] [ Branch frac does not need to be associated with cohorts. This simplifies many of the calls to allometry functions. ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary:no testing --- biogeochem/DamageMainMod.F90 | 5 ++- biogeochem/EDCohortDynamicsMod.F90 | 21 +++------ biogeochem/EDPatchDynamicsMod.F90 | 22 ++++++---- biogeochem/EDPhysiologyMod.F90 | 13 ++---- biogeochem/FatesAllometryMod.F90 | 51 ++++++++++++---------- biogeophys/FatesPlantHydraulicsMod.F90 | 4 +- biogeophys/FatesPlantRespPhotosynthMod.F90 | 14 +++--- main/EDInitMod.F90 | 12 ++--- main/FatesInventoryInitMod.F90 | 7 +-- parteh/PRTAllometricCNPMod.F90 | 29 +++++------- parteh/PRTAllometricCarbonMod.F90 | 31 +++++-------- parteh/PRTParamsFATESMod.F90 | 4 +- 12 files changed, 95 insertions(+), 118 deletions(-) diff --git a/biogeochem/DamageMainMod.F90 b/biogeochem/DamageMainMod.F90 index 7dbe385cbf..6947aac992 100644 --- a/biogeochem/DamageMainMod.F90 +++ b/biogeochem/DamageMainMod.F90 @@ -84,9 +84,10 @@ subroutine get_damage_frac(cc_cd, nc_cd, pft, dist_frac) integer, intent(in) :: pft real(r8), intent(out) :: dist_frac ! probability of current cohort moving to new damage level - dist_frac = param_derived%damage_transitions(cc_cd, nc_cd, pft) !* years_per_day (if damage is occuring annually don't do this) - + dist_frac = param_derived%damage_transitions(cc_cd, nc_cd, pft) !* years_per_day + ! (if damage is occuring annually don't do this) + end subroutine get_damage_frac !------------------------------------------------------- diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index bf9a752f2a..8f3e00d74c 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -87,7 +87,6 @@ Module EDCohortDynamicsMod use PRTAllometricCarbonMod, only : ac_bc_inout_id_netdc use PRTAllometricCarbonMod, only : ac_bc_in_id_pft use PRTAllometricCarbonMod, only : ac_bc_inout_id_cdamage - use PRTAllometricCarbonMod, only : ac_bc_in_id_branch_frac use PRTAllometricCarbonMod, only : ac_bc_inout_id_n use PRTAllometricCarbonMod, only : ac_bc_in_id_ctrim use PRTAllometricCarbonMod, only : ac_bc_inout_id_dbh @@ -147,7 +146,7 @@ Module EDCohortDynamicsMod subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & prt, laimemory, sapwmemory, structmemory, & status, recruitstatus,ctrim,carea, & - clayer, crowndamage,branch_frac, spread, bc_in) + clayer, crowndamage, spread, bc_in) ! ! !DESCRIPTION: @@ -169,7 +168,6 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & integer, intent(in) :: pft ! Cohort Plant Functional Type integer, intent(in) :: crowndamage ! Cohort damage class - real(r8), intent(in) :: branch_frac ! Fraction of biomass in branches integer, intent(in) :: clayer ! canopy status of cohort ! (1 = canopy, 2 = understorey, etc.) integer, intent(in) :: status ! growth status of plant @@ -232,7 +230,6 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & new_cohort%pft = pft new_cohort%crowndamage = crowndamage - new_cohort%branch_frac = branch_frac new_cohort%status_coh = status new_cohort%n = nn new_cohort%hite = hite @@ -415,7 +412,6 @@ subroutine InitPRTBoundaryConditions(new_cohort) call new_cohort%prt%RegisterBCIn(ac_bc_in_id_pft,bc_ival = new_cohort%pft) call new_cohort%prt%RegisterBCIn(ac_bc_in_id_ctrim,bc_rval = new_cohort%canopy_trim) call new_cohort%prt%RegisterBCIn(ac_bc_in_id_lstat,bc_ival = new_cohort%status_coh) - call new_cohort%prt%RegisterBCIn(ac_bc_in_id_branch_frac,bc_rval = new_cohort%branch_frac) case (prt_cnp_flex_allom_hyp) @@ -1314,8 +1310,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) call ForceDBH( currentCohort%pft, currentCohort%canopy_trim, & currentCohort%dbh, currentCohort%hite, & bdead = currentCohort%prt%GetState(struct_organ,all_carbon_elements), & - crowndamage = currentCohort%crowndamage, & - branch_frac = currentCohort%branch_frac) + crowndamage = currentCohort%crowndamage) end if ! @@ -1353,8 +1348,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) call ForceDBH( currentCohort%pft, currentCohort%canopy_trim, & currentCohort%dbh, currentCohort%hite, & bdead = currentCohort%prt%GetState(struct_organ,all_carbon_elements),& - crowndamage = currentCohort%crowndamage, & - branch_frac = currentCohort%branch_frac) + crowndamage = currentCohort%crowndamage) end if ! @@ -1841,7 +1835,6 @@ subroutine copy_cohort( currentCohort,copyc ) ! VEGETATION STRUCTURE n%pft = o%pft n%crowndamage = o%crowndamage - n%branch_frac = o%branch_frac n%n = o%n n%dbh = o%dbh n%coage = o%coage @@ -2103,7 +2096,6 @@ subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) real(r8) :: canopy_trim integer :: ipft integer :: icrowndamage - real(r8) :: branch_frac real(r8) :: sapw_area real(r8) :: target_sapw_c real(r8) :: target_agw_c @@ -2118,7 +2110,6 @@ subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) dbh = currentCohort%dbh ipft = currentCohort%pft icrowndamage = currentCohort%crowndamage - branch_frac = currentCohort%branch_frac canopy_trim = currentCohort%canopy_trim delta_dbh = 0._r8 @@ -2129,10 +2120,10 @@ subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) ! Target sapwood biomass according to allometry and trimming [kgC] - call bsap_allom(dbh,ipft,icrowndamage, branch_frac, canopy_trim,sapw_area,target_sapw_c) + call bsap_allom(dbh,ipft,icrowndamage,canopy_trim,sapw_area,target_sapw_c) ! Target total above ground biomass in woody/fibrous tissues [kgC] - call bagw_allom(dbh,ipft, icrowndamage, branch_frac, target_agw_c) + call bagw_allom(dbh,ipft, icrowndamage,target_agw_c) ! Target total below ground biomass in woody/fibrous tissues [kgC] call bbgw_allom(dbh,ipft,target_bgw_c) @@ -2149,7 +2140,7 @@ subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) if( (struct_c - target_struct_c ) > calloc_abs_error ) then call ForceDBH( ipft,canopy_trim, dbh, hite_out, bdead=struct_c, & - crowndamage = icrowndamage, branch_frac = branch_frac) + crowndamage = icrowndamage) delta_dbh = dbh - currentCohort%dbh delta_hite = hite_out - currentCohort%hite diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 3ec4f88d59..3af8aae71d 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -475,7 +475,8 @@ subroutine spawn_patches( currentSite, bc_in) use FatesInterfaceTypesMod, only : hlm_use_canopy_damage use FatesInterfaceTypesMod, only : hlm_use_understory_damage use FatesInterfaceTypesMod, only : ncrowndamage - + use FatesParameterDerivedMod, only : param_derived + ! ! !ARGUMENTS: type (ed_site_type), intent(inout), target :: currentSite @@ -533,6 +534,7 @@ subroutine spawn_patches( currentSite, bc_in) integer :: cd ! crowndamage counter real(r8) :: cd_frac ! fraction of cohort going to new damage class real(r8) :: agb_frac ! agoveground biomass fraction of cohort + real(r8) :: branch_frac ! branch fraction of aboveground biomass logical :: found_youngest_primary ! logical for finding the first primary forest patch @@ -783,7 +785,8 @@ subroutine spawn_patches( currentSite, bc_in) call zero_cohort(nc) agb_frac = prt_params%allom_agb_frac(currentCohort%pft) - + branch_frac = param_derived%branch_frac(currentCohort%pft) + allocate(nc) ! new cohort surviving if(hlm_use_planthydro.eq.itrue) call InitHydrCohort(CurrentSite,nc) @@ -1299,20 +1302,20 @@ subroutine spawn_patches( currentSite, bc_in) sapw_m_pre = nc_d%prt%GetState(sapw_organ, all_carbon_elements) call PRTDamageLosses(nc_d%prt, sapw_organ, mass_frac * & - nc_d%branch_frac * agb_frac) + branch_frac * agb_frac) sapw_m_post = nc_d%prt%GetState(sapw_organ, all_carbon_elements) sapw_loss_prt = sapw_loss_prt + (sapw_m_pre - sapw_m_post)*nc_d%n struct_m_pre = nc_d%prt%GetState(struct_organ, all_carbon_elements) call PRTDamageLosses(nc_d%prt, struct_organ, mass_frac * & - nc_d%branch_frac * agb_frac) + branch_frac * agb_frac) struct_m_post = nc_d%prt%GetState(struct_organ, all_carbon_elements) struct_loss_prt = struct_loss_prt + (struct_m_pre - struct_m_post)* & nc_d%n store_m_pre = nc_d%prt%GetState(store_organ, all_carbon_elements) call PRTDamageLosses(nc_d%prt, store_organ, mass_frac * & - nc_d%branch_frac * agb_frac) + branch_frac * agb_frac) store_m_post = nc_d%prt%GetState(store_organ, all_carbon_elements) store_loss_prt = store_loss_prt + (store_m_pre - store_m_post)* & nc_d%n @@ -2385,7 +2388,7 @@ subroutine damage_litter_fluxes(currentSite, currentPatch, newPatch,patch_site_a use FatesInterfaceTypesMod, only : hlm_use_canopy_damage use FatesInterfaceTypesMod, only : hlm_use_understory_damage use FatesConstantsMod, only : itrue - + use FatesParameterDerivedMod, only : param_derived ! ! !ARGUMENTS: @@ -2432,6 +2435,7 @@ subroutine damage_litter_fluxes(currentSite, currentPatch, newPatch,patch_site_a integer :: cd real(r8) :: cd_frac real(r8) :: agb_frac + real(r8) :: branch_frac integer :: ncwd_no_trunk real(r8), allocatable :: SF_val_CWD_frac_canopy(:) real(r8) :: cd_n_tot @@ -2480,8 +2484,10 @@ subroutine damage_litter_fluxes(currentSite, currentPatch, newPatch,patch_site_a do while(associated(currentCohort)) - agb_frac = prt_params%allom_agb_frac(currentCohort%pft) pft = currentCohort%pft + agb_frac = prt_params%allom_agb_frac(pft) + branch_frac = param_derived%branch_frac(pft) + ! Get mass in Kg of the element in the specified organ sapw_m = currentCohort%prt%GetState(sapw_organ, element_id) struct_m = currentCohort%prt%GetState(struct_organ, element_id) @@ -2544,7 +2550,7 @@ subroutine damage_litter_fluxes(currentSite, currentPatch, newPatch,patch_site_a ! branch loss branch_loss = (sapw_m + struct_m + store_m) * crown_reduction * & - currentCohort%branch_frac * agb_frac * num_trees_cd + branch_frac * agb_frac * num_trees_cd do c=1,(ncwd_no_trunk) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 2db7ba5c2a..7a220e63f9 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1887,19 +1887,14 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) call h2d_allom(temp_cohort%hite,ft,temp_cohort%dbh) - temp_cohort%branch_frac = 0.0_r8 - do c = 1, (ncwd-1) - temp_cohort%branch_frac = temp_cohort%branch_frac + & - SF_val_CWD_frac(c) - end do - + ! Initialize live pools call bleaf(temp_cohort%dbh,ft,temp_cohort%crowndamage,& temp_cohort%canopy_trim,c_leaf) call bfineroot(temp_cohort%dbh,ft,temp_cohort%canopy_trim,c_fnrt) - call bsap_allom(temp_cohort%dbh,ft,temp_cohort%crowndamage, temp_cohort%branch_frac, & + call bsap_allom(temp_cohort%dbh,ft,temp_cohort%crowndamage, & temp_cohort%canopy_trim,a_sapw, c_sapw) - call bagw_allom(temp_cohort%dbh,ft,temp_cohort%crowndamage, temp_cohort%branch_frac, c_agw) + call bagw_allom(temp_cohort%dbh,ft,temp_cohort%crowndamage, c_agw) call bbgw_allom(temp_cohort%dbh,ft,c_bgw) call bdead_allom(c_agw,c_bgw,c_sapw,ft,c_struct) call bstore_allom(temp_cohort%dbh,ft, temp_cohort%crowndamage, & @@ -2124,7 +2119,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) cohortstatus, recruitstatus, & temp_cohort%canopy_trim,temp_cohort%c_area, & currentPatch%NCL_p, & - temp_cohort%crowndamage, temp_cohort%branch_frac, & + temp_cohort%crowndamage, & currentSite%spread, bc_in) ! Note that if hydraulics is on, the number of cohorts may had diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index b441b0fa37..325dcb938e 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -157,7 +157,7 @@ module FatesAllometryMod ! ============================================================================ - subroutine CheckIntegratedAllometries(dbh,ipft,crowndamage, branch_frac, & + subroutine CheckIntegratedAllometries(dbh,ipft,crowndamage, & canopy_trim, bl,bfr,bsap,bstore,bdead, & grow_leaf, grow_fr, grow_sap, grow_store, grow_dead, & max_err, l_pass) @@ -173,7 +173,6 @@ subroutine CheckIntegratedAllometries(dbh,ipft,crowndamage, branch_frac, & real(r8),intent(in) :: dbh ! diameter of plant [cm] integer,intent(in) :: ipft ! plant functional type index integer,intent(in) :: crowndamage ! crowndamage [1: undamaged, >1 damaged] - real(r8),intent(in) :: branch_frac real(r8),intent(in) :: canopy_trim ! trimming function real(r8),intent(in) :: bl ! integrated leaf biomass [kgC] real(r8),intent(in) :: bfr ! integrated fine root biomass [kgC] @@ -232,7 +231,7 @@ subroutine CheckIntegratedAllometries(dbh,ipft,crowndamage, branch_frac, & end if if (grow_sap) then - call bsap_allom(dbh,ipft,crowndamage, branch_frac, canopy_trim,asap_diag,bsap_diag) + call bsap_allom(dbh,ipft,crowndamage, canopy_trim,asap_diag,bsap_diag) if( abs(bsap_diag-bsap) > max_err ) then if(verbose_logging) then write(fates_log(),*) 'disparity in integrated/diagnosed sapwood carbon' @@ -260,8 +259,8 @@ subroutine CheckIntegratedAllometries(dbh,ipft,crowndamage, branch_frac, & end if if (grow_dead) then - call bsap_allom(dbh,ipft,crowndamage, branch_frac, canopy_trim,asap_diag,bsap_diag) - call bagw_allom(dbh,ipft,crowndamage, branch_frac, bagw_diag) + call bsap_allom(dbh,ipft,crowndamage, canopy_trim,asap_diag,bsap_diag) + call bagw_allom(dbh,ipft,crowndamage, bagw_diag) call bbgw_allom(dbh,ipft,bbgw_diag) call bdead_allom( bagw_diag, bbgw_diag, bsap_diag, ipft, bdead_diag ) if( abs(bdead_diag-bdead) > max_err ) then @@ -361,21 +360,22 @@ end subroutine h_allom ! Generic AGB interface ! ============================================================================ - subroutine bagw_allom(d,ipft,crowndamage, branch_frac, bagw,dbagwdd) + subroutine bagw_allom(d,ipft,crowndamage, bagw,dbagwdd) use DamageMainMod, only : get_crown_reduction - + use FatesParameterDerivedMod, only : param_derived + real(r8),intent(in) :: d ! plant diameter [cm] integer(i4),intent(in) :: ipft ! PFT index integer(i4),intent(in) :: crowndamage ! crowndamage [1: undamaged, >1: damaged] - real(r8),intent(in) :: branch_frac real(r8),intent(out) :: bagw ! biomass above ground woody tissues real(r8),intent(out),optional :: dbagwdd ! change in agbw per diameter [kgC/cm] real(r8) :: h ! height real(r8) :: dhdd ! change in height wrt d - real(r8) :: crown_reduction - + real(r8) :: crown_reduction ! crown reduction from damage + real(r8) :: branch_frac ! fraction of aboveground biomass in branches + associate( p1 => prt_params%allom_agb1(ipft), & p2 => prt_params%allom_agb2(ipft), & p3 => prt_params%allom_agb3(ipft), & @@ -384,6 +384,8 @@ subroutine bagw_allom(d,ipft,crowndamage, branch_frac, bagw,dbagwdd) c2b => prt_params%c2b(ipft), & agb_frac => prt_params%allom_agb_frac(ipft), & allom_amode => prt_params%allom_amode(ipft)) + + branch_frac = param_derived%branch_frac(ipft) select case(int(allom_amode)) case (1) !"salda") @@ -891,14 +893,14 @@ end function leafc_from_treelai ! Generic sapwood biomass interface ! ============================================================================ - subroutine bsap_allom(d,ipft,crowndamage, branch_frac, canopy_trim,sapw_area,bsap,dbsapdd) + subroutine bsap_allom(d,ipft,crowndamage,canopy_trim,sapw_area,bsap,dbsapdd) use DamageMainMod , only : get_crown_reduction + use FatesParameterDerivedMod, only : param_derived real(r8),intent(in) :: d ! plant diameter [cm] integer(i4),intent(in) :: ipft ! PFT index integer(i4),intent(in) :: crowndamage ! Crown damage class [1: undamaged, >1: damaged] - real(r8),intent(in) :: branch_frac real(r8),intent(in) :: canopy_trim real(r8),intent(out) :: sapw_area ! cross section area of ! plant sapwood at reference [m2] @@ -918,14 +920,16 @@ subroutine bsap_allom(d,ipft,crowndamage, branch_frac, canopy_trim,sapw_area,bsa ! than some specified proportion of woody biomass ! should not trip, and only in small plants - real(r8) :: crown_reduction - real(r8) :: agb_frac + real(r8) :: crown_reduction ! amount that crown is damage by + real(r8) :: agb_frac ! aboveground biomass fraction + real(r8) :: branch_frac ! fraction of aboveground biomass in branches ! Constrain sapwood so that its above ground portion be no larger than ! X% of total woody/fibrous (ie non leaf/fineroot) tissues real(r8),parameter :: max_frac = 0.95_r8 agb_frac = prt_params%allom_agb_frac(ipft) + branch_frac = param_derived%branch_frac(ipft) select case(int(prt_params%allom_smode(ipft))) @@ -953,7 +957,7 @@ subroutine bsap_allom(d,ipft,crowndamage, branch_frac, canopy_trim,sapw_area,bsa ! Perform a capping/check on total woody biomass - call bagw_allom(d,ipft,crowndamage, branch_frac, bagw,dbagwdd) + call bagw_allom(d,ipft,crowndamage, bagw,dbagwdd) call bbgw_allom(d,ipft,bbgw,dbbgwdd) ! Force sapwood to be less than a maximum fraction of total biomass @@ -996,7 +1000,7 @@ subroutine bbgw_allom(d,ipft,bbgw,dbbgwdd) select case(int(prt_params%allom_cmode(ipft))) case(1) !"constant") ! bbgw not affected by damage so use target allometry no damage - call bagw_allom(d,ipft,1, 1.0_r8, bagw,dbagwdd) + call bagw_allom(d,ipft,1, bagw,dbagwdd) call bbgw_const(d,bagw,dbagwdd,ipft,bbgw,dbbgwdd) case DEFAULT write(fates_log(),*) 'An undefined coarse root allometry was specified: ', & @@ -2399,7 +2403,7 @@ real(r8) function decay_coeff_kn(pft,vcmax25top) end function decay_coeff_kn ! ===================================================================================== -subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl, crowndamage, branch_frac ) +subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl, crowndamage) ! ========================================================================= ! This subroutine estimates the diameter based on either the structural biomass @@ -2420,8 +2424,7 @@ subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl, crowndamage, branch_fra real(r8),intent(out) :: h ! plant height real(r8),intent(in),optional :: bdead ! Structural biomass real(r8),intent(in),optional :: bl ! Leaf biomass - real(r8),intent(in),optional :: branch_frac - + ! Locals real(r8) :: bt_sap,dbt_sap_dd ! target sap wood at current d @@ -2440,7 +2443,7 @@ subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl, crowndamage, branch_fra integer :: counter real(r8), parameter :: step_frac0 = 0.9_r8 integer, parameter :: max_counter = 200 - + ! Do reduce "if" calls, we break this call into two parts if ( int(prt_params%woody(ipft)) == itrue ) then @@ -2450,8 +2453,8 @@ subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl, crowndamage, branch_fra call endrun(msg=errMsg(sourcefile, __LINE__)) end if - call bsap_allom(d,ipft,crowndamage, branch_frac, canopy_trim,at_sap,bt_sap,dbt_sap_dd) - call bagw_allom(d,ipft,crowndamage, branch_frac, bt_agw,dbt_agw_dd) + call bsap_allom(d,ipft,crowndamage, canopy_trim,at_sap,bt_sap,dbt_sap_dd) + call bagw_allom(d,ipft,crowndamage, bt_agw,dbt_agw_dd) call bbgw_allom(d,ipft,bt_bgw,dbt_bgw_dd) call bdead_allom(bt_agw,bt_bgw, bt_sap, ipft, bt_dead, dbt_agw_dd, & @@ -2468,8 +2471,8 @@ subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl, crowndamage, branch_fra dd = step_frac*(bdead-bt_dead)/dbt_dead_dd d_try = d + dd - call bsap_allom(d_try,ipft,crowndamage, branch_frac, canopy_trim,at_sap,bt_sap,dbt_sap_dd) - call bagw_allom(d_try,ipft,crowndamage, branch_frac, bt_agw,dbt_agw_dd) + call bsap_allom(d_try,ipft,crowndamage, canopy_trim,at_sap,bt_sap,dbt_sap_dd) + call bagw_allom(d_try,ipft,crowndamage, bt_agw,dbt_agw_dd) call bbgw_allom(d_try,ipft, bt_bgw,dbt_bgw_dd) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index da55e85938..906b4ba067 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -922,7 +922,7 @@ subroutine UpdatePlantHydrLenVol(ccohort,site_hydr) ! v_stem = c_stem_biom / (prt_params%wood_density(ft) * kg_per_g * cm3_per_m3 ) ! calculate the sapwood cross-sectional area - call bsap_allom(ccohort%dbh,ccohort%pft,ccohort%crowndamage, ccohort%branch_frac, & + call bsap_allom(ccohort%dbh,ccohort%pft,ccohort%crowndamage, & ccohort%canopy_trim,a_sapwood_target,sapw_c_target) ! uncomment this if you want to use @@ -2866,7 +2866,7 @@ subroutine UpdatePlantKmax(ccohort_hydr,ccohort,csite_hydr) pft = ccohort%pft ! Get the cross-section of the plant's sapwood area [m2] - call bsap_allom(ccohort%dbh,pft,ccohort%crowndamage,ccohort%branch_frac, & + call bsap_allom(ccohort%dbh,pft,ccohort%crowndamage, & ccohort%canopy_trim,a_sapwood,c_sap_dummy) ! Leaf Maximum Hydraulic Conductance diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 7256561422..319a3ad405 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -243,12 +243,12 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) real(r8) :: leaf_psi ! leaf xylem matric potential [MPa] (only meaningful/used w/ hydro) real(r8), allocatable :: rootfr_ft(:,:) ! Root fractions per depth and PFT - real(r8) :: branch_frac - real(r8) :: agb_frac - real(r8) :: crown_reduction - real(r8) :: sapw_c_predamage - real(r8) :: sapw_n - real(r8) :: sapw_n_predamage + real(r8) :: agb_frac ! fraction of biomass aboveground + real(r8) :: branch_frac ! fraction of aboveground biomass in branches + real(r8) :: crown_reduction ! reduction in crown biomass from damage + real(r8) :: sapw_c_predamage ! pre damage sapwood + real(r8) :: sapw_n ! sapwood n + real(r8) :: sapw_n_predamage ! pre damage sapwood n ! ----------------------------------------------------------------------------------- ! Keeping these two definitions in case they need to be added later @@ -651,7 +651,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) if (hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then agb_frac = prt_params%allom_agb_frac(currentCohort%pft) - branch_frac = currentCohort%branch_frac + branch_frac = param_derived%branch_frac(currentCohort%pft) call get_crown_reduction(currentCohort%crowndamage, crown_reduction) ! need the undamaged version if using ratios with roots diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 1205ad01af..27666a06e5 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -725,7 +725,6 @@ subroutine init_cohorts( site_in, patch_in, bc_in) ! initialize new cohorts on bare ground ! ! !USES: - use FatesParameterDerivedMod , only : param_derived ! ! !ARGUMENTS @@ -739,7 +738,6 @@ subroutine init_cohorts( site_in, patch_in, bc_in) integer :: cstatus integer :: pft integer :: crowndamage ! which crown damage class - real :: branch_frac ! fraction of biomass in branches integer :: iage ! index for leaf age loop integer :: el ! index for element loop integer :: element_id ! element index consistent with defs in PRTGeneric @@ -823,8 +821,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) else temp_cohort%hite = EDPftvarcon_inst%hgt_min(pft) - temp_cohort%branch_frac = param_derived%branch_frac(pft) - + ! Assume no damage to begin with - since we assume no damage ! we do not need to initialise branch frac just yet. temp_cohort%crowndamage = 1 @@ -839,8 +836,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) end if ! sp mode ! Calculate total above-ground biomass from allometry - call bagw_allom(temp_cohort%dbh,pft,temp_cohort%crowndamage, & - 1.0_r8, c_agw) + call bagw_allom(temp_cohort%dbh,pft,temp_cohort%crowndamage,c_agw) ! Calculate coarse root biomass from allometry call bbgw_allom(temp_cohort%dbh,pft,c_bgw) @@ -850,7 +846,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) call bfineroot(temp_cohort%dbh,pft,temp_cohort%canopy_trim,c_fnrt) ! Calculate sapwood biomass - call bsap_allom(temp_cohort%dbh,pft,temp_cohort%crowndamage, 1.0_r8, & + call bsap_allom(temp_cohort%dbh,pft,temp_cohort%crowndamage, & temp_cohort%canopy_trim,a_sapw,c_sapw) call bdead_allom( c_agw, c_bgw, c_sapw, pft, c_struct ) @@ -967,7 +963,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) temp_cohort%coage, temp_cohort%dbh, prt_obj, temp_cohort%laimemory,& temp_cohort%sapwmemory, temp_cohort%structmemory, cstatus, rstatus, & temp_cohort%canopy_trim, temp_cohort%c_area, 1, temp_cohort%crowndamage,& - temp_cohort%branch_frac, site_in%spread, bc_in) + site_in%spread, bc_in) deallocate(temp_cohort) ! get rid of temporary cohort diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index d71de108ba..28749b5a08 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -917,7 +917,7 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & real(r8) :: m_repro ! Generic mass for reproductive tissues [kg] real(r8) :: stem_drop_fraction integer :: i_pft, ncohorts_to_create - + character(len=128),parameter :: wr_fmt = & '(F7.1,2X,A20,2X,A20,2X,F5.2,2X,F5.2,2X,I4,2X,F5.2,2X,F5.2,2X,F5.2,2X,F5.2)' @@ -925,6 +925,7 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & real(r8), parameter :: abnormal_large_dbh = 500.0_r8 ! I've never heard of a tree > 3m integer, parameter :: recruitstatus = 0 + read(css_file_unit,fmt=*,iostat=ios) c_time, p_name, c_name, c_dbh, c_height, & c_pft, c_nplant, c_bdead, c_balive, c_avgRG @@ -1022,7 +1023,7 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & temp_cohort%canopy_trim = 1.0_r8 call bagw_allom(temp_cohort%dbh,temp_cohort%pft, & - temp_cohort%crowndamage, temp_cohort%branch_frac, c_agw) + temp_cohort%crowndamage, c_agw) ! Calculate coarse root biomass from allometry call bbgw_allom(temp_cohort%dbh,temp_cohort%pft,c_bgw) @@ -1168,7 +1169,7 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & temp_cohort%coage, temp_cohort%dbh, & prt_obj, temp_cohort%laimemory,temp_cohort%sapwmemory, temp_cohort%structmemory, & cstatus, rstatus, temp_cohort%canopy_trim, temp_cohort%c_area, & - 1, temp_cohort%crowndamage, temp_cohort%branch_frac, csite%spread, bc_in) + 1, temp_cohort%crowndamage, csite%spread, bc_in) deallocate(temp_cohort) ! get rid of temporary cohort diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 4ac203f431..3c93b8232a 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -153,10 +153,9 @@ module PRTAllometricCNPMod integer, public, parameter :: acnp_bc_in_id_netdnh4 = 5 ! Index for the net daily NH4 input BC integer, public, parameter :: acnp_bc_in_id_netdno3 = 6 ! Index for the net daily NO3 input BC integer, public, parameter :: acnp_bc_in_id_netdp = 7 ! Index for the net daily P input BC - integer, public, parameter :: acnp_bc_in_id_branch_frac = 8 ! Index for branch fraction ! 0=leaf off, 1=leaf on - integer, parameter :: num_bc_in = 8 + integer, parameter :: num_bc_in = 7 ! ------------------------------------------------------------------------------------- ! Output Boundary Indices (These are public) @@ -335,7 +334,6 @@ subroutine DailyPRTAllometricCNP(this) ! Input only bcs integer :: ipft ! Plant Functional Type index - real(r8) :: branch_frac ! fraction crown in branches real(r8) :: c_gain ! Daily carbon balance for this cohort [kgC] real(r8) :: n_gain ! Daily nitrogen uptake through fine-roots [kgN] real(r8) :: p_gain ! Daily phosphorus uptake through fine-roots [kgN] @@ -403,7 +401,6 @@ subroutine DailyPRTAllometricCNP(this) p_gain = this%bc_in(acnp_bc_in_id_netdp)%rval; p_gain0 = p_gain canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival - branch_frac = this%bc_in(acnp_bc_in_id_branch_frac)%rval ! Output only boundary conditions c_efflux => this%bc_out(acnp_bc_out_id_cefflux)%rval; c_efflux = 0._r8 @@ -439,9 +436,9 @@ subroutine DailyPRTAllometricCNP(this) ! Set carbon targets based on the plant's current stature target_c(:) = fates_unset_r8 target_dcdd(:) = fates_unset_r8 - call bsap_allom(dbh,ipft,cdamage, branch_frac, canopy_trim, & + call bsap_allom(dbh,ipft,cdamage, canopy_trim, & sapw_area,target_c(sapw_id),target_dcdd(sapw_id) ) - call bagw_allom(dbh,ipft,cdamage, branch_frac, agw_c_target,agw_dcdd_target) + call bagw_allom(dbh,ipft,cdamage, agw_c_target,agw_dcdd_target) call bbgw_allom(dbh,ipft,bgw_c_target,bgw_dcdd_target) call bdead_allom(agw_c_target,bgw_c_target, target_c(sapw_id), ipft, target_c(struct_id), & agw_dcdd_target, bgw_dcdd_target, target_dcdd(sapw_id), target_dcdd(struct_id)) @@ -1020,7 +1017,6 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & integer :: ipft real(r8) :: canopy_trim real(r8) :: leaf_status - real(r8) :: branch_frac integer :: icrowndamage integer :: i, ii ! organ index loops (masked and unmasked) @@ -1104,8 +1100,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & ipft = this%bc_in(acnp_bc_in_id_pft)%ival canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval icrowndamage = this%bc_inout(acnp_bc_inout_id_cdamage)%ival - branch_frac = this%bc_in(acnp_bc_in_id_branch_frac)%rval - + cnp_limiter = 0 ! If any of these resources is essentially tapped out, @@ -1372,7 +1367,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & end do call CheckIntegratedAllometries(state_array_out(dbh_id),ipft, & - icrowndamage, branch_frac, canopy_trim, & + icrowndamage, canopy_trim, & leafc_tp1, state_array_out(fnrt_id), state_array_out(sapw_id), & state_array_out(store_id), state_array_out(struct_id), & state_mask(leaf_id), state_mask(fnrt_id), state_mask(sapw_id), & @@ -1464,8 +1459,8 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & call bleaf(dbh_tp1,ipft,icrowndamage, canopy_trim,leaf_c_target_tp1) call bfineroot(dbh_tp1,ipft,canopy_trim,fnrt_c_target_tp1) - call bsap_allom(dbh_tp1,ipft,icrowndamage,branch_frac,canopy_trim,sapw_area,sapw_c_target_tp1) - call bagw_allom(dbh_tp1,ipft,icrowndamage, branch_frac, agw_c_target_tp1) + call bsap_allom(dbh_tp1,ipft,icrowndamage,canopy_trim,sapw_area,sapw_c_target_tp1) + call bagw_allom(dbh_tp1,ipft,icrowndamage, agw_c_target_tp1) call bbgw_allom(dbh_tp1,ipft,bgw_c_target_tp1) call bdead_allom(agw_c_target_tp1,bgw_c_target_tp1, sapw_c_target_tp1, ipft, struct_c_target_tp1) call bstore_allom(dbh_tp1,ipft,icrowndamage, canopy_trim,store_c_target_tp1) @@ -1746,8 +1741,8 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe call bleaf(dbh,ipft,1, canopy_trim,leaf_c_target) call bfineroot(dbh,ipft,canopy_trim,fnrt_c_target) - call bsap_allom(dbh,ipft,1, 1.0_r8, canopy_trim,sapw_area,sapw_c_target) - call bagw_allom(dbh,ipft,1, 1.0_r8, agw_c_target) + call bsap_allom(dbh,ipft,1, canopy_trim,sapw_area,sapw_c_target) + call bagw_allom(dbh,ipft,1, agw_c_target) call bbgw_allom(dbh,ipft,bgw_c_target) call bdead_allom(agw_c_target,bgw_c_target, sapw_c_target, ipft, struct_c_target) @@ -2103,7 +2098,6 @@ function AllomCNPGrowthDeriv(l_state_array,l_state_mask,cbalance,intgr_params) r integer :: ipft ! PFT index real(r8) :: canopy_trim ! Canopy trimming function (boundary condition [0-1] integer :: icrowndamage ! crown damage index - real(r8) :: branch_frac real(r8) :: leaf_c_target ! target leaf biomass, dummy var (kgC) real(r8) :: fnrt_c_target ! target fine-root biomass, dummy var (kgC) real(r8) :: sapw_c_target ! target sapwood biomass, dummy var (kgC) @@ -2142,13 +2136,12 @@ function AllomCNPGrowthDeriv(l_state_array,l_state_mask,cbalance,intgr_params) r canopy_trim = intgr_params(acnp_bc_in_id_ctrim) ipft = int(intgr_params(acnp_bc_in_id_pft)) - branch_frac = intgr_params(acnp_bc_in_id_branch_frac) icrowndamage = int(intgr_params(acnp_bc_inout_id_cdamage)) call bleaf(dbh,ipft,icrowndamage, canopy_trim,leaf_c_target,leaf_dcdd_target) call bfineroot(dbh,ipft,canopy_trim,fnrt_c_target,fnrt_dcdd_target) - call bsap_allom(dbh,ipft,icrowndamage, branch_frac,canopy_trim,sapw_area,sapw_c_target,sapw_dcdd_target) - call bagw_allom(dbh,ipft,icrowndamage, branch_frac, agw_c_target,agw_dcdd_target) + call bsap_allom(dbh,ipft,icrowndamage, canopy_trim,sapw_area,sapw_c_target,sapw_dcdd_target) + call bagw_allom(dbh,ipft,icrowndamage, agw_c_target,agw_dcdd_target) call bbgw_allom(dbh,ipft,bgw_c_target,bgw_dcdd_target) call bdead_allom(agw_c_target,bgw_c_target, sapw_c_target, ipft, struct_c_target, & agw_dcdd_target, bgw_dcdd_target, sapw_dcdd_target, struct_dcdd_target) diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 509ef4a35f..f3e8a44a3b 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -95,8 +95,7 @@ module PRTAllometricCarbonMod integer, public, parameter :: ac_bc_in_id_pft = 1 ! Index for the PFT input BC integer, public, parameter :: ac_bc_in_id_ctrim = 2 ! Index for the canopy trim function integer, public, parameter :: ac_bc_in_id_lstat = 3 ! Leaf status (on or off) - integer, public, parameter :: ac_bc_in_id_branch_frac = 4 ! index for the branch fraction input BC - integer, parameter :: num_bc_in = 4 ! Number of input boundary conditions + integer, parameter :: num_bc_in = 3 ! Number of input boundary conditions ! THere are no purely output boundary conditions @@ -303,7 +302,6 @@ subroutine DailyPRTAllometricCarbon(this) real(r8) :: canopy_trim ! The canopy trimming function [0-1] integer :: ipft ! Plant Functional Type index - real(r8) :: branch_frac real(r8) :: target_leaf_c ! target leaf carbon [kgC] real(r8) :: target_fnrt_c ! target fine-root carbon [kgC] @@ -432,17 +430,14 @@ subroutine DailyPRTAllometricCarbon(this) canopy_trim = this%bc_in(ac_bc_in_id_ctrim)%rval ipft = this%bc_in(ac_bc_in_id_pft)%ival leaf_status = this%bc_in(ac_bc_in_id_lstat)%ival - branch_frac = this%bc_in(ac_bc_in_id_branch_frac)%rval intgr_params(:) = un_initialized intgr_params(ac_bc_in_id_ctrim) = this%bc_in(ac_bc_in_id_ctrim)%rval intgr_params(ac_bc_in_id_pft) = real(this%bc_in(ac_bc_in_id_pft)%ival) - intgr_params(ac_bc_in_id_branch_frac) = this%bc_in(ac_bc_in_id_branch_frac)%rval intgr_params(num_bc_in + 1) = real(this%bc_inout(ac_bc_inout_id_cdamage)%ival) nleafage = prt_global%state_descriptor(leaf_c_id)%num_pos ! Number of leaf age class damage_recovery_scalar = prt_params%damage_recovery_scalar(ipft) - ! ----------------------------------------------------------------------------------- ! Call the routine that advances leaves in age. @@ -470,10 +465,10 @@ subroutine DailyPRTAllometricCarbon(this) ! ----------------------------------------------------------------------------------- ! Target sapwood biomass according to allometry and trimming [kgC] - call bsap_allom(dbh,ipft, crowndamage, branch_frac, canopy_trim,sapw_area,target_sapw_c) + call bsap_allom(dbh,ipft, crowndamage, canopy_trim,sapw_area,target_sapw_c) ! Target total above ground biomass in woody/fibrous tissues [kgC] - call bagw_allom(dbh,ipft, crowndamage, branch_frac, target_agw_c) + call bagw_allom(dbh,ipft, crowndamage, target_agw_c) ! Target total below ground biomass in woody/fibrous tissues [kgC] call bbgw_allom(dbh,ipft,target_bgw_c) @@ -687,9 +682,9 @@ subroutine DailyPRTAllometricCarbon(this) mass_d = (sum(leaf_c(1:nleafage)) + fnrt_c + store_c + sapw_c + struct_c ) ! Target sapwood biomass according to allometry and trimming [kgC] - call bsap_allom(dbh,ipft, crowndamage-1, branch_frac, canopy_trim,sapw_area,targetn_sapw_c) + call bsap_allom(dbh,ipft, crowndamage-1, canopy_trim,sapw_area,targetn_sapw_c) ! Target total above ground biomass in woody/fibrous tissues [kgC] - call bagw_allom(dbh,ipft, crowndamage-1, branch_frac, targetn_agw_c) + call bagw_allom(dbh,ipft, crowndamage-1, targetn_agw_c) ! Target total below ground biomass in woody/fibrous tissues [kgC] call bbgw_allom(dbh,ipft,targetn_bgw_c) ! Target total dead (structrual) biomass [kgC] @@ -848,7 +843,7 @@ subroutine DailyPRTAllometricCarbon(this) ! we remember the current step size as a good next guess. call CheckIntegratedAllometries(c_pool_out(dbh_id),ipft,& - crowndamage, branch_frac, canopy_trim, & + crowndamage, canopy_trim, & c_pool_out(leaf_c_id), c_pool_out(fnrt_c_id), c_pool_out(sapw_c_id), & c_pool_out(store_c_id), c_pool_out(struct_c_id), & c_mask(leaf_c_id), c_mask(fnrt_c_id), c_mask(sapw_c_id), & @@ -1009,7 +1004,6 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) ! locals integer :: ipft ! PFT index integer :: crowndamage - real(r8) :: branch_frac real(r8) :: canopy_trim ! Canopy trimming function (boundary condition [0-1] real(r8) :: ct_leaf ! target leaf biomass, dummy var (kgC) real(r8) :: ct_fnrt ! target fine-root biomass, dummy var (kgC) @@ -1047,13 +1041,12 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) canopy_trim = intgr_params(ac_bc_in_id_ctrim) ipft = int(intgr_params(ac_bc_in_id_pft)) - branch_frac = intgr_params(ac_bc_in_id_branch_frac) crowndamage = int(intgr_params(num_bc_in + 1)) call bleaf(dbh,ipft,crowndamage,canopy_trim,ct_leaf, dbldd=ct_dleafdd) call bfineroot(dbh,ipft,canopy_trim,ct_fnrt,ct_dfnrtdd) - call bsap_allom(dbh,ipft, crowndamage, branch_frac, canopy_trim,sapw_area,ct_sap,ct_dsapdd) - call bagw_allom(dbh,ipft,crowndamage, branch_frac, ct_agw,ct_dagwdd) + call bsap_allom(dbh,ipft, crowndamage, canopy_trim,sapw_area,ct_sap,ct_dsapdd) + call bagw_allom(dbh,ipft,crowndamage, ct_agw,ct_dagwdd) call bbgw_allom(dbh,ipft,ct_bgw, ct_dbgwdd) call bdead_allom(ct_agw,ct_bgw, ct_sap, ipft, ct_dead, & ct_dagwdd, ct_dbgwdd, ct_dsapdd, ct_ddeaddd) @@ -1232,7 +1225,6 @@ subroutine PRTDamageRecovery(this) integer, pointer :: crowndamage real(r8) :: canopy_trim integer :: ipft - real(r8) :: branch_frac real(r8) :: target_leaf_c ! target leaf carbon [kgC] real(r8) :: target_fnrt_c ! target fine-root carbon [kgC] real(r8) :: target_sapw_c ! target sapwood carbon [kgC] @@ -1259,11 +1251,10 @@ subroutine PRTDamageRecovery(this) canopy_trim = this%bc_in(ac_bc_in_id_ctrim)%rval ipft = this%bc_in(ac_bc_in_id_pft)%ival leaf_status = this%bc_in(ac_bc_in_id_lstat)%ival - branch_frac = this%bc_in(ac_bc_in_id_branch_frac)%rval - + ! Get allometric targets for this dbh and crown damage class - call bsap_allom(dbh, ipft, crowndamage, branch_frac, canopy_trim, sapw_area, target_sapw_c) - call bagw_allom(dbh, ipft, crowndamage, branch_frac, target_agw_c) + call bsap_allom(dbh, ipft, crowndamage, canopy_trim, sapw_area, target_sapw_c) + call bagw_allom(dbh, ipft, crowndamage, target_agw_c) call bbgw_allom(dbh, ipft, target_bgw_c) call bdead_allom(target_agw_c, target_bgw_c, target_sapw_c, ipft, target_struct_c) if(leaf_status ==2)then diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index 3255e14f9c..c5e8b84de8 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -1472,8 +1472,8 @@ function NewRecruitTotalStoichiometry(ft,element_id) result(recruit_stoich) call h2d_allom(EDPftvarcon_inst%hgt_min(ft),ft,dbh) call bleaf(dbh,ft,1, init_recruit_trim,c_leaf) call bfineroot(dbh,ft,init_recruit_trim,c_fnrt) - call bsap_allom(dbh,ft,1,1.0_r8,init_recruit_trim,a_sapw, c_sapw) - call bagw_allom(dbh,ft,1,1.0_r8,c_agw) + call bsap_allom(dbh,ft,1,init_recruit_trim,a_sapw, c_sapw) + call bagw_allom(dbh,ft,1,c_agw) call bbgw_allom(dbh,ft,c_bgw) call bdead_allom(c_agw,c_bgw,c_sapw,ft,c_struct) call bstore_allom(dbh,ft,1,init_recruit_trim,c_store) From 04c454ff0283adedf4061a4377213959614be483 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 2 Feb 2022 11:59:54 -0500 Subject: [PATCH 110/852] Incremental work on l2fr searching --- main/EDMainMod.F90 | 1 + main/FatesHistoryInterfaceMod.F90 | 66 ++++++++++++--- parteh/PRTAllometricCNPMod.F90 | 131 ++++++++++++++++++++++++------ 3 files changed, 161 insertions(+), 37 deletions(-) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 66288650b3..de2bf7b778 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -321,6 +321,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) !----------------------------------------------------------------------- real(r8) :: frac_site_primary + print*,"DYNAMICS" call get_frac_site_primary(currentSite, frac_site_primary) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 98a4ab730e..f0ab692c7d 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -1714,7 +1714,8 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) use FatesSizeAgeTypeIndicesMod, only : coagetype_class_index use EDTypesMod , only : nlevleaf use EDParamsMod , only : ED_val_history_height_bin_edges - + use FatesUtilsMod , only : check_var_real + ! Arguments class(fates_history_interface_type) :: this integer , intent(in) :: nc ! clump index @@ -1785,7 +1786,10 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) real(r8) :: struct_m_net_alloc real(r8) :: repro_m_net_alloc real(r8) :: area_frac - + real(r8) :: fnrtc_canopy_scpf(numpft*nlevsclass) + real(r8) :: fnrtc_understory_scpf(numpft*nlevsclass) + integer :: return_code + type(ed_patch_type),pointer :: cpatch type(ed_cohort_type),pointer :: ccohort @@ -2052,6 +2056,9 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) model_day_int = nint(hlm_model_day) + + + ! --------------------------------------------------------------------------------- ! Loop through the FATES scale hierarchy and fill the history IO arrays ! --------------------------------------------------------------------------------- @@ -2059,6 +2066,10 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) do s = 1,nsites io_si = sites(s)%h_gid + + ! These are weighting factors used for calculating l2fr_scpf + fnrtc_canopy_scpf(:) = 0._r8 + fnrtc_understory_scpf(:) = 0._r8 ! Total carbon model error [kgC/day -> mgC/day] hio_cbal_err_fates_si(io_si) = & @@ -2283,6 +2294,8 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) if( element_list(el).eq.carbon12_element )then + call check_var_real(ccohort%l2fr, 'l2fr', return_code) + ! These L2FR diagnostics are weighted by fineroot carbon biomass hio_l2fr_si(io_si) = hio_l2fr_si(io_si) + ccohort%n*fnrt_m*ccohort%l2fr @@ -2290,9 +2303,23 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_l2fr_scpf(io_si,ccohort%size_by_pft_class) + & ccohort%n*fnrt_m*ccohort%l2fr - hio_l2fr_scpf(io_si,ccohort%size_by_pft_class) = & - hio_l2fr_scpf(io_si,ccohort%size_by_pft_class) + & - ccohort%n*fnrt_m*ccohort%l2fr + if (ccohort%canopy_layer .eq. 1) then + hio_l2fr_canopy_scpf(io_si,ccohort%size_by_pft_class) = & + hio_l2fr_canopy_scpf(io_si,ccohort%size_by_pft_class) + & + ccohort%n*fnrt_m*ccohort%l2fr + + fnrtc_canopy_scpf(ccohort%size_by_pft_class) = & + fnrtc_canopy_scpf(ccohort%size_by_pft_class) + ccohort%n*fnrt_m + + else + hio_l2fr_understory_scpf(io_si,ccohort%size_by_pft_class) = & + hio_l2fr_understory_scpf(io_si,ccohort%size_by_pft_class) + & + ccohort%n*fnrt_m*ccohort%l2fr + fnrtc_understory_scpf(ccohort%size_by_pft_class) = & + fnrtc_understory_scpf(ccohort%size_by_pft_class) + ccohort%n*fnrt_m + + end if + this%hvars(ih_storec_si)%r81d(io_si) = & this%hvars(ih_storec_si)%r81d(io_si) + ccohort%n * store_m @@ -3345,6 +3372,30 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) if( this%hvars(ih_storectfrac_si)%r81d(io_si)>nearzero ) then this%hvars(ih_storectfrac_si)%r81d(io_si) = this%hvars(ih_storec_si)%r81d(io_si) / & this%hvars(ih_storectfrac_si)%r81d(io_si) + + do i_pft = 1, numpft + do i_scls = 1,nlevsclass + i_scpf = (i_pft-1)*nlevsclass + i_scls + + if(this%hvars(ih_fnrtc_scpf)%r82d(io_si,i_scpf)>nearzero)then + hio_l2fr_scpf(io_si,i_scpf) = hio_l2fr_scpf(io_si,i_scpf) / & + this%hvars(ih_fnrtc_scpf)%r82d(io_si,i_scpf) + end if + + if(fnrtc_canopy_scpf(i_scpf)>nearzero)then + hio_l2fr_canopy_scpf(io_si,i_scpf) = & + hio_l2fr_canopy_scpf(io_si,i_scpf)/fnrtc_canopy_scpf(i_scpf) + end if + + if(fnrtc_understory_scpf(i_scpf)>nearzero)then + hio_l2fr_understory_scpf(io_si,i_scpf) = & + hio_l2fr_understory_scpf(io_si,i_scpf)/fnrtc_understory_scpf(i_scpf) + end if + + + end do + end do + end if elseif(element_list(el).eq.nitrogen_element)then @@ -3355,11 +3406,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) do i_pft = 1, numpft do i_scls = 1,nlevsclass i_scpf = (i_pft-1)*nlevsclass + i_scls - - if(this%hvars(ih_fnrtc_scpf)%r82d(io_si,i_scpf)>nearzero)then - hio_l2fr_scpf(io_si,i_scpf) = hio_l2fr_scpf(io_si,i_scpf) / & - this%hvars(ih_fnrtc_scpf)%r82d(io_si,i_scpf) - end if if( hio_nplant_canopy_si_scpf(io_si,i_scpf)>nearzero ) then this%hvars(ih_storentfrac_canopy_scpf)%r82d(io_si,i_scpf) = & diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 86c392f755..24849e40bc 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -46,6 +46,7 @@ module PRTAllometricCNPMod use FatesConstantsMod , only : i4 => fates_int use FatesConstantsMod , only : calloc_abs_error use FatesConstantsMod , only : rsnbl_math_prec + use FatesConstantsMod , only : years_per_day use FatesIntegratorsMod , only : RKF45 use FatesIntegratorsMod , only : Euler use FatesConstantsMod , only : calloc_abs_error @@ -206,7 +207,8 @@ module PRTAllometricCNPMod integer, parameter :: regulate_linear = 1 integer, parameter :: regulate_logi = 2 integer, parameter :: regulate_CN_logi = 3 - + integer, parameter :: regulate_CN_dfdd = 4 + ! Array of pointers are difficult in F90 ! This structure is a necessary intermediate type :: parray_type @@ -436,7 +438,7 @@ subroutine DailyPRTAllometricCNP(this) allocate(state_c(num_organs)) allocate(state_n(num_organs)) allocate(state_p(num_organs)) - + ! Set carbon targets based on the plant's current stature target_c(:) = fates_unset_r8 target_dcdd(:) = fates_unset_r8 @@ -638,20 +640,30 @@ subroutine CNPAdjustFRootTargets(this) real(r8), pointer :: l2fr ! leaf to fineroot target biomass scaler integer :: ipft ! PFT index + real(r8), pointer :: dbh + real(r8) :: canopy_trim - real(r8) :: n_regulator ! Nitrogen storage regulation function scaler - real(r8) :: p_regulator ! Phosphorus storage regulation function scaler - real(r8) :: np_regulator ! Combined NP storage regulation function scaler + real(r8) :: fnrt_c_target ! Target fineroot C before we change l2fr + real(r8) :: n_regulator ! Nitrogen storage regulation function scaler + real(r8) :: p_regulator ! Phosphorus storage regulation function scaler + real(r8) :: np_regulator ! Combined NP storage regulation function scaler + real(r8) :: turnfrac ! The factional amount of root biomass that may + ! remain after a day of root turnover without + ! replacement + real(r8) :: fnrt_frac ! fine-root's current fraction of the target + integer, parameter :: regulate_type = regulate_CN_logi !regulate_CN_dfdd ipft = this%bc_in(acnp_bc_in_id_pft)%ival l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval - + dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval + canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval + associate( l2fr_min => prt_params%allom_l2fr_min(ipft), & l2fr_max => prt_params%allom_l2fr_max(ipft)) - call this%StorageRegulator(nitrogen_element, regulate_CN_logi,n_regulator) - call this%StorageRegulator(phosphorus_element, regulate_CN_logi,p_regulator) + call this%StorageRegulator(nitrogen_element, regulate_type,n_regulator) + call this%StorageRegulator(phosphorus_element, regulate_type,p_regulator) ! We take the maximum here, because the maximum is reflective of the ! element with the lowest storage, which is the limiting element @@ -661,7 +673,48 @@ subroutine CNPAdjustFRootTargets(this) ! Update the leaf-to-fineroot ratio used ! to set fine-root biomass allometry - l2fr = l2fr_min + max(0._r8,min(1.0_r8,np_regulator))*(l2fr_max-l2fr_min) + if(regulate_type == regulate_CN_logi)then + + l2fr = l2fr_min + max(0._r8,min(1.0_r8,np_regulator))*(l2fr_max-l2fr_min) + + elseif(regulate_type == regulate_CN_dfdd)then + + ! Also, we aren't allowed to increase root biomass target if + ! we are very low on root biomass relative to the target + ! And we aren't allowed to reduce the target if we are above the target + + call bfineroot(dbh,ipft,canopy_trim,l2fr,fnrt_c_target) + fnrt_frac = this%GetState(fnrt_organ, carbon12_element)/fnrt_c_target + + turnfrac = (years_per_day / prt_params%root_long(ipft)) + + ! If there is low root compared to the max, don't allow cap growth + if(fnrt_frac < 1._r8-1.5_r8*turnfrac)then + np_regulator = min(np_regulator,1.0) + end if + + ! If there is high root compared to the max, don't allow cap decrease + if(fnrt_frac > 1.0_r8+1.5_r8*turnfrac)then + np_regulator = max(np_regulator,1.0) + end if + + ! Don't allow us to drop l2fr more than what the maximum loss to turnover + ! would be for one day. + ! this will prevent the algorithm from snowballing. This is doubly important + ! because if C is low compared to N or P, then the plant is probably + ! not very productive, and will not be growing. A growing plant can reach + ! equilibrium root mass more quickly. (might be unnecessary given + ! the growth caps prior to this...?) + + + + !print*,dbh,fnrt_frac,l2fr,min(max(np_regulator,1._r8-turnfrac),1._r8+turnfrac) + + l2fr = l2fr * min(max(np_regulator,1._r8-2._r8*turnfrac),1._r8+2._r8*turnfrac) + + end if + + ! Find the updated target fineroot biomass ! call bfineroot(dbh,ipft,canopy_trim, l2fr, target_fnrt) @@ -2142,16 +2195,10 @@ end subroutine TargetAllometryCheck subroutine StorageRegulator(this,element_id,regulate_type,c_scalar) ! ----------------------------------------------------------------------------------- - ! This function returns the cn_scalar or cp_scalar term - ! described in: - ! Zhu, Q et al. Representing Nitrogen, Phosphorus and Carbon - ! interactions in the E3SM land model: Development and Global benchmarking. - ! Journal of Advances in Modeling Earth Systems, 11, 2238-2258, 2019. - ! https://doi.org/10.1029/2018MS001571 - ! - ! In the manuscript c_scalar is described as: "f(CN) and f(CP) account for the - ! regulation of plant nutritional level on nutrient carrier enzyme activity" - ! Also, see equations 4 and 5. + ! This function evaluates the storage of either N or P, and returns + ! a scalar that is used to regulate fine-root biomass in some way. Depending + ! on the type of method, this may either be an absolute scalar on biomass + ! or it may be a rate of change on that scalar. ! ----------------------------------------------------------------------------------- @@ -2165,14 +2212,20 @@ subroutine StorageRegulator(this,element_id,regulate_type,c_scalar) real(r8) :: c_scalar ! Locals - real(r8) :: store_frac ! Current nutrient storage relative to max - real(r8) :: store_max ! Maximum nutrient storable by plant - real(r8) :: store_c ! Current storage carbon - real(r8) :: store_c_max ! Current maximum storage carbon - integer :: icode ! real variable checking code + real(r8) :: store_frac ! Current nutrient storage relative to max + real(r8) :: store_max ! Maximum nutrient storable by plant + real(r8) :: store_c ! Current storage carbon + real(r8) :: store_c_max ! Current maximum storage carbon + integer :: icode ! real variable checking code real(r8) :: store_x integer :: i_var - + real(r8) :: c_eq_offset ! This shifts the center-point + ! of the N:C or P:C storage equlibrium + ! by multiplying the C term. If its less than 1 it + ! shifts left and great than one it shifts right. + ! It should shift left to help mitigate wasted N and P + ! storage overflow + ! For N/C logistic real(r8) :: logi_k ! logistic function k real(r8) :: store_x0 ! storage fraction inflection point @@ -2225,8 +2278,8 @@ subroutine StorageRegulator(this,element_id,regulate_type,c_scalar) ! call endrun(msg=errMsg(sourcefile, __LINE__)) !endif - else - + elseif(regulate_type == regulate_CN_logi) then + logi_k = 2.0_r8 store_x0 = 0.0_r8 logi_min = 0.0_r8 @@ -2243,6 +2296,30 @@ subroutine StorageRegulator(this,element_id,regulate_type,c_scalar) c_scalar = max(0._r8,min(1._r8,logi_min + (1._r8-logi_min)/(1.0 + exp(logi_k*(store_frac-store_x0))))) + elseif(regulate_type == regulate_CN_dfdd) then + + store_c = this%GetState(store_organ, carbon12_element) + call bstore_allom(dbh,ipft,canopy_trim,store_c_max) + + ! Fraction of N per fraction of C + ! If this is greater than 1, then we have more N in storage than + ! we have C, so we downregulate. If this is less than 1, then + ! we have less N in storage than we have C, so up-regulate + + ! Note also, we do not allow the plants to dump C + ! but we do allow them to exude either P or N. Because of this + ! we shift our equilibrium point from a ratio of 1:1 to something + ! with a slightly lower C fraction equilibrium (ie > 1) + ! This will reduce N and P uptake inefficiencies by reducing + ! storage overflow and dumping. + + c_eq_offset = 0.75 + + store_frac = max(0.01_r8,store_frac) / max(0.01_r8,c_eq_offset*(store_c/store_c_max)) + + c_scalar = 1._r8 - 0.02_r8*log(store_frac) + + !print*,element_id,store_frac,c_scalar end if From 6bd5eb1ba452311cb0c0c32fe94b2ec074a17b28 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 3 Feb 2022 17:47:15 -0500 Subject: [PATCH 111/852] Updated l2fr diagnostics to be canopy and understory --- main/FatesHistoryInterfaceMod.F90 | 55 +++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index a15f910c6c..ac986de9d2 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -1497,7 +1497,7 @@ subroutine zero_site_hvars(this, currentSite, upfreq_in) integer :: ndims ! number of dimensions do ivar=1,ubound(this%hvars,1) - if (this%hvars(ivar)%upfreq == upfreq_in) then ! Only flush variables with update on dynamics step + if (this%hvars(ivar)%upfreq == upfreq_in) then ndims = this%dim_kinds(this%hvars(ivar)%dim_kinds_index)%ndims @@ -1834,7 +1834,10 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) real(r8) :: repro_m_net_alloc real(r8) :: area_frac real(r8) :: crown_depth - + real(r8) :: fnrtc_canopy_scpf(numpft*nlevsclass) + real(r8) :: fnrtc_understory_scpf(numpft*nlevsclass) + integer :: return_code + type(ed_patch_type),pointer :: cpatch type(ed_cohort_type),pointer :: ccohort @@ -2099,6 +2102,10 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) io_si = sites(s)%h_gid + ! These are weighting factors used for calculating l2fr_scpf + fnrtc_canopy_scpf(:) = 0._r8 + fnrtc_understory_scpf(:) = 0._r8 + ! Total carbon model error [kgC/day -> kgC/s] hio_cbal_err_fates_si(io_si) = & sites(s)%mass_balance(element_pos(carbon12_element))%err_fates / sec_per_day @@ -2379,14 +2386,24 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) ! These L2FR diagnostics are weighted by fineroot carbon biomass hio_l2fr_si(io_si) = hio_l2fr_si(io_si) + ccohort%n*fnrt_m*ccohort%l2fr - hio_l2fr_scpf(io_si,ccohort%size_by_pft_class) = & - hio_l2fr_scpf(io_si,ccohort%size_by_pft_class) + & - ccohort%n*fnrt_m*ccohort%l2fr - hio_l2fr_scpf(io_si,ccohort%size_by_pft_class) = & hio_l2fr_scpf(io_si,ccohort%size_by_pft_class) + & ccohort%n*fnrt_m*ccohort%l2fr + if (ccohort%canopy_layer .eq. 1) then + hio_l2fr_canopy_scpf(io_si,ccohort%size_by_pft_class) = & + hio_l2fr_canopy_scpf(io_si,ccohort%size_by_pft_class) + & + ccohort%n*fnrt_m*ccohort%l2fr + fnrtc_canopy_scpf(ccohort%size_by_pft_class) = & + fnrtc_canopy_scpf(ccohort%size_by_pft_class) + ccohort%n*fnrt_m + else + hio_l2fr_understory_scpf(io_si,ccohort%size_by_pft_class) = & + hio_l2fr_understory_scpf(io_si,ccohort%size_by_pft_class) + & + ccohort%n*fnrt_m*ccohort%l2fr + fnrtc_understory_scpf(ccohort%size_by_pft_class) = & + fnrtc_understory_scpf(ccohort%size_by_pft_class) + ccohort%n*fnrt_m + end if + call bstore_allom(ccohort%dbh,ccohort%pft,ccohort%canopy_trim, store_max) this%hvars(ih_storectfrac_si)%r81d(io_si) = & this%hvars(ih_storectfrac_si)%r81d(io_si) + ccohort%n * store_max @@ -3447,18 +3464,30 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) end do ! end element loop - - - ! Normalize storage fractions + ! Normalize storage fractions and L2FR if( this%hvars(ih_storectfrac_si)%r81d(io_si)>nearzero ) then this%hvars(ih_storectfrac_si)%r81d(io_si) = this%hvars(ih_storec_si)%r81d(io_si) / & this%hvars(ih_storectfrac_si)%r81d(io_si) end if - if(this%hvars(ih_fnrtc_scpf)%r82d(io_si,i_scpf)>nearzero)then - hio_l2fr_scpf(io_si,i_scpf) = hio_l2fr_scpf(io_si,i_scpf) / & - this%hvars(ih_fnrtc_scpf)%r82d(io_si,i_scpf) - end if + + do i_pft = 1, numpft + do i_scls = 1,nlevsclass + i_scpf = (i_pft-1)*nlevsclass + i_scls + if(this%hvars(ih_fnrtc_scpf)%r82d(io_si,i_scpf)>nearzero)then + hio_l2fr_scpf(io_si,i_scpf) = hio_l2fr_scpf(io_si,i_scpf) / & + this%hvars(ih_fnrtc_scpf)%r82d(io_si,i_scpf) + end if + if(fnrtc_canopy_scpf(i_scpf)>nearzero)then + hio_l2fr_canopy_scpf(io_si,i_scpf) = & + hio_l2fr_canopy_scpf(io_si,i_scpf)/fnrtc_canopy_scpf(i_scpf) + end if + if(fnrtc_understory_scpf(i_scpf)>nearzero)then + hio_l2fr_understory_scpf(io_si,i_scpf) = & + hio_l2fr_understory_scpf(io_si,i_scpf)/fnrtc_understory_scpf(i_scpf) + end if + end do + end do do el = 1, num_elements From b570617f9912220ec1edc8a66a859b12c4b0ab53 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 8 Feb 2022 16:23:57 -0500 Subject: [PATCH 112/852] Fixed l2fr and storage fraction history fields, updated some name conventions --- main/FatesHistoryInterfaceMod.F90 | 161 ++++++++++++++++-------------- 1 file changed, 88 insertions(+), 73 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index ac986de9d2..15b7e479bc 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -169,7 +169,6 @@ module FatesHistoryInterfaceMod integer :: ih_totvegc_si integer :: ih_storen_si - integer :: ih_storentfrac_si integer :: ih_leafn_si integer :: ih_sapwn_si integer :: ih_fnrtn_si @@ -177,7 +176,7 @@ module FatesHistoryInterfaceMod integer :: ih_totvegn_si integer :: ih_storep_si - integer :: ih_storeptfrac_si + integer :: ih_leafp_si integer :: ih_sapwp_si integer :: ih_fnrtp_si @@ -239,6 +238,7 @@ module FatesHistoryInterfaceMod integer :: ih_leafn_scpf integer :: ih_fnrtn_scpf integer :: ih_storen_scpf + integer :: ih_storentfrac_si integer :: ih_storentfrac_canopy_scpf integer :: ih_storentfrac_understory_scpf integer :: ih_sapwn_scpf @@ -261,6 +261,7 @@ module FatesHistoryInterfaceMod integer :: ih_fnrtp_scpf integer :: ih_reprop_scpf integer :: ih_storep_scpf + integer :: ih_storeptfrac_si integer :: ih_storeptfrac_canopy_scpf integer :: ih_storeptfrac_understory_scpf integer :: ih_sapwp_scpf @@ -1834,8 +1835,14 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) real(r8) :: repro_m_net_alloc real(r8) :: area_frac real(r8) :: crown_depth + real(r8) :: fnrtc_canopy_scpf(numpft*nlevsclass) real(r8) :: fnrtc_understory_scpf(numpft*nlevsclass) + real(r8) :: storen_canopy_scpf(numpft*nlevsclass) + real(r8) :: storen_understory_scpf(numpft*nlevsclass) + real(r8) :: storep_canopy_scpf(numpft*nlevsclass) + real(r8) :: storep_understory_scpf(numpft*nlevsclass) + integer :: return_code type(ed_patch_type),pointer :: cpatch @@ -2105,7 +2112,11 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) ! These are weighting factors used for calculating l2fr_scpf fnrtc_canopy_scpf(:) = 0._r8 fnrtc_understory_scpf(:) = 0._r8 - + storen_canopy_scpf(:) = 0._r8 + storen_understory_scpf(:) = 0._r8 + storep_canopy_scpf(:) = 0._r8 + storep_understory_scpf(:) = 0._r8 + ! Total carbon model error [kgC/day -> kgC/s] hio_cbal_err_fates_si(io_si) = & sites(s)%mass_balance(element_pos(carbon12_element))%err_fates / sec_per_day @@ -2342,6 +2353,9 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_canopy_height_dist_si_height(io_si,height_bin_max) + ccohort%c_area * AREA_INV endif + call set_root_fraction(sites(s)%rootfrac_scr, ccohort%pft, sites(s)%zi_soil, & + bc_in(s)%max_rooting_depth_index_col ) + ! Update biomass components ! Mass pools [kg] elloop: do el = 1, num_elements @@ -2356,11 +2370,12 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) alive_m = leaf_m + fnrt_m + sapw_m total_m = alive_m + store_m + struct_m + i_scpf = ccohort%size_by_pft_class + + ! Plant multi-element states and fluxes ! Zero states, and set the fluxes if( element_list(el).eq.carbon12_element )then - - ! mass in different tissues [kg/ha] -> [kg/m2] this%hvars(ih_storec_si)%r81d(io_si) = & @@ -2384,35 +2399,29 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) ! These L2FR diagnostics are weighted by fineroot carbon biomass - hio_l2fr_si(io_si) = hio_l2fr_si(io_si) + ccohort%n*fnrt_m*ccohort%l2fr + hio_l2fr_si(io_si) = hio_l2fr_si(io_si) + ccohort%n*fnrt_m/m2_per_ha*ccohort%l2fr - hio_l2fr_scpf(io_si,ccohort%size_by_pft_class) = & - hio_l2fr_scpf(io_si,ccohort%size_by_pft_class) + & - ccohort%n*fnrt_m*ccohort%l2fr + hio_l2fr_scpf(io_si,i_scpf) = & + hio_l2fr_scpf(io_si,i_scpf) + ccohort%n*fnrt_m/m2_per_ha*ccohort%l2fr if (ccohort%canopy_layer .eq. 1) then - hio_l2fr_canopy_scpf(io_si,ccohort%size_by_pft_class) = & - hio_l2fr_canopy_scpf(io_si,ccohort%size_by_pft_class) + & - ccohort%n*fnrt_m*ccohort%l2fr - fnrtc_canopy_scpf(ccohort%size_by_pft_class) = & - fnrtc_canopy_scpf(ccohort%size_by_pft_class) + ccohort%n*fnrt_m + hio_l2fr_canopy_scpf(io_si,i_scpf) = & + hio_l2fr_canopy_scpf(io_si,i_scpf) + ccohort%n*fnrt_m *ccohort%l2fr + fnrtc_canopy_scpf(i_scpf) = fnrtc_canopy_scpf(i_scpf) + ccohort%n*fnrt_m else - hio_l2fr_understory_scpf(io_si,ccohort%size_by_pft_class) = & - hio_l2fr_understory_scpf(io_si,ccohort%size_by_pft_class) + & - ccohort%n*fnrt_m*ccohort%l2fr - fnrtc_understory_scpf(ccohort%size_by_pft_class) = & - fnrtc_understory_scpf(ccohort%size_by_pft_class) + ccohort%n*fnrt_m + hio_l2fr_understory_scpf(io_si,i_scpf) = & + hio_l2fr_understory_scpf(io_si,i_scpf) + ccohort%n*fnrt_m*ccohort%l2fr + fnrtc_understory_scpf(i_scpf) = fnrtc_understory_scpf(i_scpf) + ccohort%n*fnrt_m end if call bstore_allom(ccohort%dbh,ccohort%pft,ccohort%canopy_trim, store_max) this%hvars(ih_storectfrac_si)%r81d(io_si) = & - this%hvars(ih_storectfrac_si)%r81d(io_si) + ccohort%n * store_max + this%hvars(ih_storectfrac_si)%r81d(io_si) + ccohort%n * store_max/m2_per_ha ! Determine the root carbon biomass in kg/m3 ! [kg/m3] = [kg/plant] * [plant/ha] / [m3/ha] * [fraction] / [m] - call set_root_fraction(sites(s)%rootfrac_scr, ccohort%pft, sites(s)%zi_soil, & - bc_in(s)%max_rooting_depth_index_col ) + do ilyr = 1,sites(s)%nlevsoil this%hvars(ih_fnrtc_sl)%r82d(io_si,ilyr) = this%hvars(ih_fnrtc_sl)%r82d(io_si,ilyr) + & fnrt_m * ccohort%n / area * sites(s)%rootfrac_scr(ilyr) / sites(s)%dz_soil(ilyr) @@ -2474,6 +2483,20 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) this%hvars(ih_totvegn_si)%r81d(io_si) + ccohort%n * & total_m / m2_per_ha + if (ccohort%canopy_layer .eq. 1) then + storen_canopy_scpf(i_scpf) = & + storen_canopy_scpf(i_scpf) + ccohort%n * store_m + this%hvars(ih_storentfrac_canopy_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_storentfrac_canopy_scpf)%r82d(io_si,i_scpf) + & + ccohort%n * store_max + else + storen_understory_scpf(i_scpf) = & + storen_understory_scpf(i_scpf) + ccohort%n * store_m + this%hvars(ih_storentfrac_understory_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_storentfrac_understory_scpf)%r82d(io_si,i_scpf) + & + ccohort%n * store_max + end if + elseif(element_list(el).eq.phosphorus_element) then store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_max) @@ -2500,6 +2523,21 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) this%hvars(ih_totvegp_si)%r81d(io_si)+ ccohort%n * & total_m / m2_per_ha + if (ccohort%canopy_layer .eq. 1) then + storep_canopy_scpf(i_scpf) = & + storep_canopy_scpf(i_scpf) + ccohort%n * store_m + this%hvars(ih_storeptfrac_canopy_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_storeptfrac_canopy_scpf)%r82d(io_si,i_scpf) + & + ccohort%n * store_max + else + storep_understory_scpf(i_scpf) = & + storep_understory_scpf(i_scpf) + ccohort%n * store_m + this%hvars(ih_storeptfrac_understory_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_storeptfrac_understory_scpf)%r82d(io_si,i_scpf) + & + ccohort%n * store_max + end if + + end if end do elloop @@ -3183,7 +3221,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) area_frac = cpatch%area * AREA_INV - ! Sum up all output fluxes (fragmentation) kgC/m2/day -> gC/m2/s + ! Sum up all output fluxes (fragmentation) kgC/m2/day -> kgC/m2/s hio_litter_out_si(io_si) = hio_litter_out_si(io_si) + & (sum(litt%leaf_fines_frag(:)) + & sum(litt%root_fines_frag(:,:)) + & @@ -3256,8 +3294,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) this%hvars(ih_fnrtn_scpf)%r82d(io_si,:) = 0._r8 this%hvars(ih_sapwn_scpf)%r82d(io_si,:) = 0._r8 this%hvars(ih_storen_scpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_storentfrac_canopy_scpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_storentfrac_understory_scpf)%r82d(io_si,:) = 0._r8 this%hvars(ih_repron_scpf)%r82d(io_si,:) = 0._r8 this%hvars(ih_nefflux_scpf)%r82d(io_si,:) = & @@ -3282,8 +3318,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) this%hvars(ih_fnrtp_scpf)%r82d(io_si,:) = 0._r8 this%hvars(ih_sapwp_scpf)%r82d(io_si,:) = 0._r8 this%hvars(ih_storep_scpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_storeptfrac_canopy_scpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_storeptfrac_understory_scpf)%r82d(io_si,:) = 0._r8 this%hvars(ih_reprop_scpf)%r82d(io_si,:) = 0._r8 this%hvars(ih_pdemand_scpf)%r82d(io_si,:) = & @@ -3295,7 +3329,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) m2_per_ha / sec_per_day this%hvars(ih_pdemand_si)%r81d(io_si) = & - sum(sites(s)%flux_diags(el)%nutrient_demand_scpf(:),dim=1) + sum(sites(s)%flux_diags(el)%nutrient_demand_scpf(:),dim=1) / & m2_per_ha / sec_per_day this%hvars(ih_pefflux_si)%r81d(io_si) = & @@ -3414,14 +3448,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) this%hvars(ih_repron_scpf)%r82d(io_si,i_scpf) + & repro_m * ccohort%n / m2_per_ha - if (ccohort%canopy_layer .eq. 1) then - this%hvars(ih_storentfrac_canopy_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_storentfrac_canopy_scpf)%r82d(io_si,i_scpf) + store_m/store_max * ccohort%n - else - this%hvars(ih_storentfrac_understory_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_storentfrac_understory_scpf)%r82d(io_si,i_scpf) + store_m/store_max * ccohort%n - end if - elseif(element_list(el).eq.phosphorus_element)then store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_max) @@ -3445,14 +3471,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) this%hvars(ih_reprop_scpf)%r82d(io_si,i_scpf) + & repro_m * ccohort%n / m2_per_ha - if (ccohort%canopy_layer .eq. 1) then - this%hvars(ih_storeptfrac_canopy_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_storeptfrac_canopy_scpf)%r82d(io_si,i_scpf) + store_m/store_max * ccohort%n - else - this%hvars(ih_storeptfrac_understory_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_storeptfrac_understory_scpf)%r82d(io_si,i_scpf) + store_m/store_max * ccohort%n - end if - end if ccohort => ccohort%shorter @@ -3491,7 +3509,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) do el = 1, num_elements - if(element_list(el).eq.nitrogen_element)then if( this%hvars(ih_storentfrac_si)%r81d(io_si)>nearzero ) then this%hvars(ih_storentfrac_si)%r81d(io_si) = this%hvars(ih_storen_si)%r81d(io_si) / & @@ -3501,16 +3518,15 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) do i_scls = 1,nlevsclass i_scpf = (i_pft-1)*nlevsclass + i_scls - if( hio_nplant_canopy_si_scpf(io_si,i_scpf)>nearzero ) then + if( this%hvars(ih_storentfrac_canopy_scpf)%r82d(io_si,i_scpf)>nearzero ) then this%hvars(ih_storentfrac_canopy_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_storentfrac_canopy_scpf)%r82d(io_si,i_scpf) / & - (hio_nplant_canopy_si_scpf(io_si,i_scpf)*m2_per_ha) + storen_canopy_scpf(i_scpf) / & + this%hvars(ih_storentfrac_canopy_scpf)%r82d(io_si,i_scpf) end if - - if( hio_nplant_understory_si_scpf(io_si,i_scpf)>nearzero ) then + if( this%hvars(ih_storentfrac_understory_scpf)%r82d(io_si,i_scpf)>nearzero ) then this%hvars(ih_storentfrac_understory_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_storentfrac_understory_scpf)%r82d(io_si,i_scpf) / & - (hio_nplant_understory_si_scpf(io_si,i_scpf)*m2_per_ha) + storen_understory_scpf(i_scpf) / & + this%hvars(ih_storentfrac_understory_scpf)%r82d(io_si,i_scpf) end if end do @@ -3524,16 +3540,15 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) do i_scls = 1,nlevsclass i_scpf = (i_pft-1)*nlevsclass + i_scls - if( hio_nplant_canopy_si_scpf(io_si,i_scpf)>nearzero ) then + if( this%hvars(ih_storeptfrac_canopy_scpf)%r82d(io_si,i_scpf)>nearzero ) then this%hvars(ih_storeptfrac_canopy_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_storeptfrac_canopy_scpf)%r82d(io_si,i_scpf) /& - (hio_nplant_canopy_si_scpf(io_si,i_scpf)*m2_per_ha) - + storep_canopy_scpf(i_scpf) / & + this%hvars(ih_storeptfrac_canopy_scpf)%r82d(io_si,i_scpf) end if - if( hio_nplant_understory_si_scpf(io_si,i_scpf)>nearzero ) then + if( this%hvars(ih_storeptfrac_understory_scpf)%r82d(io_si,i_scpf)>nearzero ) then this%hvars(ih_storeptfrac_understory_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_storeptfrac_understory_scpf)%r82d(io_si,i_scpf) /& - (hio_nplant_understory_si_scpf(io_si,i_scpf)*m2_per_ha) + storep_understory_scpf(i_scpf) / & + this%hvars(ih_storeptfrac_understory_scpf)%r82d(io_si,i_scpf) end if end do @@ -4487,25 +4502,25 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_trimming_si) - call this%set_history_var(vname='FATES_LEAF2FNRT', units='kg kg-1', & + call this%set_history_var(vname='FATES_L2FR', units='kg kg-1', & long='The leaf to fineroot biomass multiplier for target allometry', & use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_l2fr_si) - call this%set_history_var(vname='FATES_LEAF2FNRT_SCPF', units='kg kg-1', & + call this%set_history_var(vname='FATES_L2FR_SZPF', units='kg kg-1', & long='The leaf to fineroot biomass multiplier for target allometry', & use_default='active', & avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_l2fr_scpf) - call this%set_history_var(vname='FATES_LEAF2FNRT_CANOPY_SCPF', units='kg kg-1', & + call this%set_history_var(vname='FATES_L2FR_CANOPY_SZPF', units='kg kg-1', & long='The leaf to fineroot biomass multiplier for target allometry in canopy plants', & use_default='active', & avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_l2fr_canopy_scpf) - call this%set_history_var(vname='FATES_LEAF2FNRT_UNDERSTORY_SCPF', units='kg kg-1', & + call this%set_history_var(vname='FATES_L2FR_USTORY_SZPF', units='kg kg-1', & long='The leaf to fineroot biomass multiplier for target allometry in understory plants', & use_default='active', & avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & @@ -4959,7 +4974,7 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_storec_si) - call this%set_history_var(vname='STOREC_TFRAC', units='kg kg-1', & + call this%set_history_var(vname='FATES_STOREC_TFRAC', units='kg kg-1', & long='Storage C fraction of target', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_storectfrac_si ) @@ -5012,7 +5027,7 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_storen_si) - call this%set_history_var(vname='FATES_STOREN_TF', units='1', & + call this%set_history_var(vname='FATES_STOREN_TFRAC', units='1', & long='storage N fraction of target', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index = ih_storentfrac_si) @@ -5078,7 +5093,7 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_storep_si) - call this%set_history_var(vname='FATES_STOREP_TF', units='1', & + call this%set_history_var(vname='FATES_STOREP_TFRAC', units='1', & long='storage P fraction of target', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, & @@ -5330,14 +5345,14 @@ subroutine define_history_vars(this, initialize_variables) upfreq=2, ivar=ivar, initialize=initialize_variables, & index = ih_ar_canopy_si) - call this%set_history_var(vname='FATES_GPP_UNDERSTORY', & + call this%set_history_var(vname='FATES_GPP_USTORY', & units='kg m-2 s-1', & long='gross primary production of understory plants in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=2, ivar=ivar, initialize=initialize_variables, & index = ih_gpp_understory_si) - call this%set_history_var(vname='FATES_AUTORESP_UNDERSTORY', & + call this%set_history_var(vname='FATES_AUTORESP_USTORY', & units='kg m-2 s-1', & long='autotrophic respiration of understory plants in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & @@ -5557,7 +5572,7 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_canopy_mortality_carbonflux_si) - call this%set_history_var(vname='FATES_MORTALITY_CFLUX_UNDERSTORY', & + call this%set_history_var(vname='FATES_MORTALITY_CFLUX_USTORY', & units = 'kg m-2 s-1', & long='flux of biomass carbon from live to dead pools from mortality of understory plants in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & @@ -6723,14 +6738,14 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index = ih_storen_scpf) - call this%set_history_var(vname='FATES_STOREN_TF_CANOPY_SZPF', & + call this%set_history_var(vname='FATES_STOREN_TFRAC_CANOPY_SZPF', & units='1', & long='storage nitrogen fraction (0-1) of target, in canopy, by size-class x pft', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index = ih_storentfrac_canopy_scpf) - call this%set_history_var(vname='FATES_STOREN_TF_USTORY_SZPF', & + call this%set_history_var(vname='FATES_STOREN_TFRAC_USTORY_SZPF', & units='1', & long='storage nitrogen fraction (0-1) of target, in understory, by size-class x pft', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & @@ -6805,14 +6820,14 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index = ih_storep_scpf) - call this%set_history_var(vname='FATES_STOREP_TF_CANOPY_SZPF', & + call this%set_history_var(vname='FATES_STOREP_TFRAC_CANOPY_SZPF', & units='1', & long='storage phosphorus fraction (0-1) of target, in canopy, by size-class x pft', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index = ih_storeptfrac_canopy_scpf) - call this%set_history_var(vname='FATES_STOREP_TF_USTORY_SZPF', & + call this%set_history_var(vname='FATES_STOREP_TFRAC_USTORY_SZPF', & units='1', & long='storage phosphorus fraction (0-1) of target, in understory, by size-class x pft', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & From a5f752b584fe68294d72b0aff2099136ae60dfad Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Mon, 14 Feb 2022 08:43:34 -0800 Subject: [PATCH 113/852] [ Fix merge conflicts in EDCanopySturctureMod ] [Add cohort crowndamage status to calls to tree_sai ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary:no testing --- biogeochem/EDCanopyStructureMod.F90 | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 9709d87f31..1d7381846b 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1925,6 +1925,7 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) real(r8) :: bare_frac_area real(r8) :: total_patch_area real(r8) :: total_canopy_area + real(r8) :: total_patch_leaf_stem_area real(r8) :: weight ! Weighting for cohort variables in patch do s = 1,nsites @@ -1936,6 +1937,7 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) bc_out(s)%dleaf_pa(:) = 0._r8 bc_out(s)%z0m_pa(:) = 0._r8 bc_out(s)%displa_pa(:) = 0._r8 + currentPatch => sites(s)%oldest_patch c = fcolumn(s) @@ -1986,13 +1988,14 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) if (hlm_use_sp.eq.ifalse) then ! make sure that allometries are correct call carea_allom(currentCohort%dbh,currentCohort%n,sites(s)%spread,& - currentCohort%pft,currentCohort%c_area) + currentCohort%pft,currentCohort%crowndamage, currentCohort%c_area) currentCohort%treelai = tree_lai(currentCohort%prt%GetState(leaf_organ, all_carbon_elements), & currentCohort%pft, currentCohort%c_area, currentCohort%n, & currentCohort%canopy_layer, currentPatch%canopy_layer_tlai,currentCohort%vcmax25top ) - currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_trim, & + currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, sites(s)%spread, & + currentCohort%canopy_trim, & currentCohort%c_area, currentCohort%n, currentCohort%canopy_layer, & currentPatch%canopy_layer_tlai, currentCohort%treelai , & currentCohort%vcmax25top,4) From 14399fc2ee8862ef83d081d0d6bfd1d5ff71a46d Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Mon, 14 Feb 2022 11:43:47 -0800 Subject: [PATCH 114/852] [ Add damage x damage dimension back ] [ Needed for damage transition matrix ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary:no testing --- main/FatesIODimensionsMod.F90 | 10 ++++++++-- main/FatesIOVariableKindMod.F90 | 1 + main/FatesInterfaceMod.F90 | 12 ++++++++++++ main/FatesInterfaceTypesMod.F90 | 2 ++ 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/main/FatesIODimensionsMod.F90 b/main/FatesIODimensionsMod.F90 index 09bead9bc4..2289749d1a 100644 --- a/main/FatesIODimensionsMod.F90 +++ b/main/FatesIODimensionsMod.F90 @@ -28,6 +28,7 @@ module FatesIODimensionsMod character(*), parameter, public :: levcnlf = 'fates_levcnlf' ! matches histFileMod character(*), parameter, public :: levcnlfpft = 'fates_levcnlfpf' ! matches histFileMod character(*), parameter, public :: levcdsc = 'fates_levcdsc' ! matches histFileMod + character(*), parameter, public :: levcdcd = 'fates_levcdcd' ! matches histFileMod character(*), parameter, public :: levcdpf = 'fates_levcdpf' ! matches histFileMod character(*), parameter, public :: levagefuel = 'fates_levagefuel' ! matches histFileMod character(*), parameter, public :: levelem = 'fates_levelem' @@ -85,6 +86,9 @@ module FatesIODimensionsMod ! levcdsc = This is a structure that records the boundaries for the ! number of crown damage x size classes dimension + ! levcdcd = This is a structure that records the boundaries for the + ! number of crown damage x crown damage classes - for damage transitions + ! levcdpf = This is a structure that records the boundaries for the ! number of crown damage x size classes x pft dimension @@ -145,8 +149,10 @@ module FatesIODimensionsMod integer :: cnlf_end integer :: cnlfpft_begin integer :: cnlfpft_end - integer :: cdamage_begin - integer :: cdamage_end + ! integer :: cdamage_begin + ! integer :: cdamage_end + integer :: cdcd_begin + integer :: cdcd_end integer :: cdsc_begin integer :: cdsc_end integer :: cdpf_begin diff --git a/main/FatesIOVariableKindMod.F90 b/main/FatesIOVariableKindMod.F90 index a40f1c2dbe..3b10d698cd 100644 --- a/main/FatesIOVariableKindMod.F90 +++ b/main/FatesIOVariableKindMod.F90 @@ -33,6 +33,7 @@ module FatesIOVariableKindMod character(*), parameter, public :: site_cnlfpft_r8 = 'SI_CNLFPFT_R8' character(*), parameter, public :: site_cdpf_r8 = 'SI_CDPF_R8' character(*), parameter, public :: site_cdsc_r8 = 'SI_CDSC_R8' + character(*), parameter, public :: site_cdcd_r8 = 'SI_CDCD_R8' character(*), parameter, public :: site_scag_r8 = 'SI_SCAG_R8' character(*), parameter, public :: site_scagpft_r8 = 'SI_SCAGPFT_R8' character(*), parameter, public :: site_agepft_r8 = 'SI_AGEPFT_R8' diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index a5c35bebf6..d0fc4e8315 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1000,6 +1000,7 @@ subroutine fates_history_maps integer :: ifuel integer :: ican integer :: icdam + integer :: icdcd integer :: ileaf integer :: iage integer :: iheight @@ -1019,6 +1020,8 @@ subroutine fates_history_maps allocate( fates_hdim_camap_levcapf(1:nlevcoage*numpft)) allocate( fates_hdim_levcdam(ncrowndamage )) + allocate( fates_hdim_cdimap_levcdcd(ncrowndamage*(ncrowndamage+1))) + allocate( fates_hdim_cdjmap_levcdcd(ncrowndamage*(ncrowndamage+1))) allocate( fates_hdim_scmap_levcdsc(nlevsclass*ncrowndamage)) allocate( fates_hdim_cdmap_levcdsc(nlevsclass*ncrowndamage)) allocate( fates_hdim_scmap_levcdpf(nlevsclass*ncrowndamage * numpft)) @@ -1161,6 +1164,15 @@ subroutine fates_history_maps end do end do + i=0 + do icdam=1,ncrowndamage + do icdcd=1,ncrowndamage+1 + i=i+1 + fates_hdim_cdimap_levcdcd(i) = icdcd + fates_hdim_cdjmap_levcdcd(i) = icdam + end do + end do + i=0 do ipft=1,numpft do ican=1,nclmax diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index c605c55a7c..3bde7550ea 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -247,6 +247,8 @@ module FatesInterfaceTypesMod integer , public, allocatable :: fates_hdim_scmap_levcdpf(:) ! map of size into size x crowndamage x pft integer , public, allocatable :: fates_hdim_cdmap_levcdsc(:) ! map of crowndamage into size x crowndamage integer , public, allocatable :: fates_hdim_scmap_levcdsc(:) ! map of size into size x crowndamage + integer , public, allocatable :: fates_hdim_cdimap_levcdcd(:) ! map of current damage into damage x damage + integer , public, allocatable :: fates_hdim_cdjmap_levcdcd(:) ! map of new damage into damage x damage real(r8), public, allocatable :: fates_hdim_levage(:) ! patch age lower bound dimension real(r8), public, allocatable :: fates_hdim_levheight(:) ! height lower bound dimension From 1c33686593e1a1418daf1a0779450ae9e19250f1 Mon Sep 17 00:00:00 2001 From: Adrianna Foster Date: Tue, 15 Feb 2022 10:04:45 -0700 Subject: [PATCH 115/852] update UNDERSTORY to USTORY --- main/FatesHistoryInterfaceMod.F90 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 72451f6878..4e291e0d31 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -5204,14 +5204,14 @@ subroutine define_history_vars(this, initialize_variables) upfreq=2, ivar=ivar, initialize=initialize_variables, & index = ih_ar_canopy_si) - call this%set_history_var(vname='FATES_GPP_UNDERSTORY', & + call this%set_history_var(vname='FATES_GPP_USTORY', & units='kg m-2 s-1', & long='gross primary production of understory plants in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=2, ivar=ivar, initialize=initialize_variables, & index = ih_gpp_understory_si) - call this%set_history_var(vname='FATES_AUTORESP_UNDERSTORY', & + call this%set_history_var(vname='FATES_AUTORESP_USTORY', & units='kg m-2 s-1', & long='autotrophic respiration of understory plants in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & @@ -5431,7 +5431,7 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_canopy_mortality_carbonflux_si) - call this%set_history_var(vname='FATES_MORTALITY_CFLUX_UNDERSTORY', & + call this%set_history_var(vname='FATES_MORTALITY_CFLUX_USTORY', & units = 'kg m-2 s-1', & long='flux of biomass carbon from live to dead pools from mortality of understory plants in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & @@ -6686,7 +6686,7 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index = ih_storeptfrac_canopy_scpf) - call this%set_history_var(vname='FATES_STOREP_TF_USTORY_SZPF', & + call this%set_history_var(vname='FATES_STOREP_TF_USTORY_SZPF', & units='1', & long='storage phosphorus fraction (0-1) of target, in understory, by size-class x pft', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & From 6a5d0c69339e991b764b1db00761fcc74b983687 Mon Sep 17 00:00:00 2001 From: ckoven Date: Tue, 15 Feb 2022 14:03:15 -0700 Subject: [PATCH 116/852] added FATES_FRACTION variable to keep track of what gridcell fraction is FATES --- main/FatesHistoryInterfaceMod.F90 | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 20918251d2..9893314c9e 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -192,6 +192,8 @@ module FatesHistoryInterfaceMod integer :: ih_area_plant_si integer :: ih_area_trees_si + integer :: ih_fates_fraction_si + integer :: ih_cwd_elcwd integer :: ih_litter_in_si ! carbon only @@ -1563,8 +1565,14 @@ subroutine set_history_var(this, vname, units, long, use_default, avgflag, vtype ! Flushing to the ignore val coerces all FATES diagnostics to be ! relevant only on FATES sites. This way we do not average zero's ! at locations not on FATES columns + ! We make one exception to this rule, for the fates_fraction variable. That way + ! we can always know what fraction of the gridcell FATES is occupying. - flushval = hlm_hio_ignore_val + if ( trim(vname) .ne. 'FATES_FRACTION') then + flushval = hlm_hio_ignore_val + else + flushval = 0._r8 + endif write_var = check_hlm_list(trim(hlms), trim(hlm_name)) if( write_var ) then @@ -1834,6 +1842,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_trimming_si => this%hvars(ih_trimming_si)%r81d, & hio_area_plant_si => this%hvars(ih_area_plant_si)%r81d, & hio_area_trees_si => this%hvars(ih_area_trees_si)%r81d, & + hio_fates_fraction_si => this%hvars(ih_fates_fraction_si)%r81d, & hio_canopy_spread_si => this%hvars(ih_canopy_spread_si)%r81d, & hio_biomass_si_pft => this%hvars(ih_biomass_si_pft)%r82d, & hio_leafbiomass_si_pft => this%hvars(ih_leafbiomass_si_pft)%r82d, & @@ -2081,6 +2090,10 @@ subroutine update_history_dyn(this,nc,nsites,sites) io_si = sites(s)%h_gid + ! set the fates fraction to one, since it is zero on non-fates columns, & + ! the average is the total gridcell fates fraction + hio_fates_fraction_si(io_si) = 1._r8 + ! Total carbon model error [kgC/day -> kgC/s] hio_cbal_err_fates_si(io_si) = & sites(s)%mass_balance(element_pos(carbon12_element))%err_fates / sec_per_day @@ -4406,6 +4419,12 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_area_trees_si) + call this%set_history_var(vname='FATES_FRACTION', units='m2 m-2', & + long='total gridcell fraction which FATES is running over', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_fates_fraction_si) + call this%set_history_var(vname='FATES_COLD_STATUS', units='', & long='site-level cold status, 0=not cold-dec, 1=too cold for leaves, 2=not too cold', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & From 1324109d32ac3b7c8233a21d44aead8ffb5d9f95 Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Wed, 16 Feb 2022 15:38:06 -0800 Subject: [PATCH 117/852] [ Fix bug with if statements in fateshistoryinterface ] [ because damage history variables are defined in an if statment they need to be references by this%hvars and not hio_ ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary:no testing --- main/FatesHistoryInterfaceMod.F90 | 236 +++++++----------------------- main/FatesIODimensionsMod.F90 | 2 - main/FatesInterfaceMod.F90 | 5 - main/FatesInterfaceTypesMod.F90 | 1 - 4 files changed, 56 insertions(+), 188 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 0c641c655d..053e5b0772 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -463,8 +463,7 @@ Module FatesHistoryInterfaceMod integer :: ih_m8_si_scls integer :: ih_m9_si_scls integer :: ih_m10_si_scls - integer :: ih_m11_si_scls - + integer :: ih_m10_si_cacls integer :: ih_nplant_si_cacls @@ -634,28 +633,17 @@ Module FatesHistoryInterfaceMod ! site x crown damage x pft x sizeclass ! site x crown damage x size class integer :: ih_nplant_si_cdpf - integer :: ih_nplant_si_cdsc integer :: ih_nplant_canopy_si_cdpf integer :: ih_nplant_understory_si_cdpf - integer :: ih_nplant_canopy_si_cdsc - integer :: ih_nplant_understory_si_cdsc - integer :: ih_mortality_si_cdsc integer :: ih_mortality_si_cdpf integer :: ih_mortality_canopy_si_cdpf integer :: ih_mortality_understory_si_cdpf integer :: ih_m3_si_cdpf - integer :: ih_m3_si_cdsc integer :: ih_m11_si_cdpf - integer :: ih_m11_si_cdsc - integer :: ih_m3_mortality_canopy_si_cdsc - integer :: ih_m3_mortality_understory_si_cdsc integer :: ih_m3_mortality_canopy_si_cdpf integer :: ih_m3_mortality_understory_si_cdpf - integer :: ih_m11_mortality_canopy_si_cdsc - integer :: ih_m11_mortality_understory_si_cdsc integer :: ih_m11_mortality_canopy_si_cdpf integer :: ih_m11_mortality_understory_si_cdpf - integer :: ih_ddbh_si_cdsc integer :: ih_ddbh_si_cdpf integer :: ih_ddbh_canopy_si_cdpf integer :: ih_ddbh_understory_si_cdpf @@ -2056,7 +2044,6 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_m8_si_scpf => this%hvars(ih_m8_si_scpf)%r82d, & hio_m9_si_scpf => this%hvars(ih_m9_si_scpf)%r82d, & hio_m10_si_scpf => this%hvars(ih_m10_si_scpf)%r82d, & - hio_m11_si_scpf => this%hvars(ih_m11_si_scpf)%r82d, & hio_m10_si_capf => this%hvars(ih_m10_si_capf)%r82d, & hio_crownfiremort_si_scpf => this%hvars(ih_crownfiremort_si_scpf)%r82d, & @@ -2065,35 +2052,6 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_fire_c_to_atm_si => this%hvars(ih_fire_c_to_atm_si)%r81d, & hio_burn_flux_elem => this%hvars(ih_burn_flux_elem)%r82d, & - hio_nplant_si_cdpf => this%hvars(ih_nplant_si_cdpf)%r82d, & - hio_nplant_si_cdsc => this%hvars(ih_nplant_si_cdsc)%r82d, & - hio_mortality_si_cdsc => this%hvars(ih_mortality_si_cdsc)%r82d, & - hio_mortality_si_cdpf => this%hvars(ih_mortality_si_cdpf)%r82d, & - hio_m3_si_cdpf => this%hvars(ih_m3_si_cdpf)%r82d, & - hio_m3_si_cdsc => this%hvars(ih_m3_si_cdsc)%r82d, & - hio_m11_si_cdpf => this%hvars(ih_m11_si_cdpf)%r82d, & - hio_m11_si_cdsc => this%hvars(ih_m11_si_cdsc)%r82d, & - hio_mortality_canopy_si_cdpf => this%hvars(ih_mortality_canopy_si_cdpf)%r82d, & - hio_mortality_understory_si_cdpf => this%hvars(ih_mortality_understory_si_cdpf)%r82d, & - hio_m3_mortality_canopy_si_cdsc => this%hvars(ih_m3_mortality_canopy_si_cdsc)%r82d, & - hio_m3_mortality_understory_si_cdsc => this%hvars(ih_m3_mortality_understory_si_cdsc)%r82d, & - hio_m3_mortality_canopy_si_cdpf => this%hvars(ih_m3_mortality_canopy_si_cdpf)%r82d, & - hio_m3_mortality_understory_si_cdpf =>this%hvars(ih_m3_mortality_understory_si_cdpf)%r82d, & - hio_m11_mortality_canopy_si_cdsc => this%hvars(ih_m11_mortality_canopy_si_cdsc)%r82d, & - hio_m11_mortality_understory_si_cdsc => this%hvars(ih_m11_mortality_understory_si_cdsc)%r82d, & - hio_m11_mortality_canopy_si_cdpf => this%hvars(ih_m11_mortality_canopy_si_cdpf)%r82d, & - hio_m11_mortality_understory_si_cdpf =>this%hvars(ih_m11_mortality_understory_si_cdpf)%r82d, & - hio_nplant_canopy_si_cdsc => this%hvars(ih_nplant_canopy_si_cdsc)%r82d, & - hio_nplant_understory_si_cdsc =>this%hvars(ih_nplant_understory_si_cdsc)%r82d, & - hio_nplant_canopy_si_cdpf => this%hvars(ih_nplant_canopy_si_cdpf)%r82d, & - hio_nplant_understory_si_cdpf =>this%hvars(ih_nplant_understory_si_cdpf)%r82d, & - hio_ddbh_si_cdsc => this%hvars(ih_ddbh_si_cdsc)%r82d, & - hio_ddbh_si_cdpf => this%hvars(ih_ddbh_si_cdpf)%r82d, & - hio_ddbh_canopy_si_cdpf => this%hvars(ih_ddbh_canopy_si_cdpf)%r82d, & - hio_ddbh_understory_si_cdpf => this%hvars(ih_ddbh_understory_si_cdpf)%r82d, & - hio_crownarea_canopy_damage_si => this%hvars(ih_crownarea_canopy_damage_si)%r81d, & - hio_crownarea_ustory_damage_si => this%hvars(ih_crownarea_ustory_damage_si)%r81d, & - hio_m1_si_scls => this%hvars(ih_m1_si_scls)%r82d, & hio_m2_si_scls => this%hvars(ih_m2_si_scls)%r82d, & hio_m3_si_scls => this%hvars(ih_m3_si_scls)%r82d, & @@ -2104,7 +2062,6 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_m8_si_scls => this%hvars(ih_m8_si_scls)%r82d, & hio_m9_si_scls => this%hvars(ih_m9_si_scls)%r82d, & hio_m10_si_scls => this%hvars(ih_m10_si_scls)%r82d, & - hio_m11_si_scls => this%hvars(ih_m11_si_scls)%r82d, & hio_m10_si_cacls => this%hvars(ih_m10_si_cacls)%r82d, & hio_c13disc_si_scpf => this%hvars(ih_c13disc_si_scpf)%r82d, & @@ -2265,10 +2222,12 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! damage variables - site level - this needs to be OUT of the patch loop if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then - hio_crownarea_canopy_damage_si(io_si) = hio_crownarea_canopy_damage_si(io_si) + & + this%hvars(ih_crownarea_canopy_damage_si)%r81d(io_si) = & + this%hvars(ih_crownarea_canopy_damage_si)%r81d(io_si) + & sites(s)%crownarea_canopy_damage * days_per_year * 1 / m2_per_ha - hio_crownarea_ustory_damage_si(io_si) = hio_crownarea_ustory_damage_si(io_si) + & + this%hvars(ih_crownarea_ustory_damage_si)%r81d(io_si) = & + this%hvars(ih_crownarea_ustory_damage_si)%r81d(io_si) + & sites(s)%crownarea_ustory_damage * days_per_year * 1 / m2_per_ha end if @@ -2783,45 +2742,31 @@ subroutine update_history_dyn(this,nc,nsites,sites) if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then cdpf = get_cdamagesizepft_class_index(ccohort%dbh, ccohort%crowndamage, ccohort%pft) - cdsc = get_cdamagesize_class_index(ccohort%dbh, ccohort%crowndamage) - - ! crown damage - only want cohorts > 1 cm dbh here so we can compare it with data - hio_mortality_si_cdsc(io_si,cdsc) = hio_mortality_si_cdsc(io_si,cdsc) + & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + ccohort%frmort + & - ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + & - (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & - ccohort%n * sec_per_day * days_per_year / m2_per_ha - - hio_mortality_si_cdpf(io_si,cdpf) = hio_mortality_si_cdpf(io_si,cdpf) + & + + this%hvars(ih_mortality_si_cdpf)%r82d(io_si,cdpf) = & + this%hvars(ih_mortality_si_cdpf)%r82d(io_si,cdpf) + & (ccohort%bmort + ccohort%hmort + ccohort%cmort + ccohort%frmort + & ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + & (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & ccohort%n * sec_per_day * days_per_year / m2_per_ha - ! crown damage by size - hio_nplant_si_cdsc(io_si, cdsc) = hio_nplant_si_cdsc(io_si, cdsc) + ccohort%n / m2_per_ha - hio_m3_si_cdsc(io_si, cdsc) = hio_m3_si_cdsc(io_si, cdsc) + & - ccohort%cmort * ccohort%n / m2_per_ha - ! crown damage by size by pft - hio_nplant_si_cdpf(io_si, cdpf) = hio_nplant_si_cdpf(io_si, cdpf) + ccohort%n / m2_per_ha - hio_m3_si_cdpf(io_si, cdpf) = hio_m3_si_cdpf(io_si, cdpf) + & + this%hvars(ih_nplant_si_cdpf)%r82d(io_si, cdpf) = & + this%hvars(ih_nplant_si_cdpf)%r82d(io_si, cdpf) + ccohort%n / m2_per_ha + this%hvars(ih_m3_si_cdpf)%r82d(io_si, cdpf) = & + this%hvars(ih_m3_si_cdpf)%r82d(io_si, cdpf) + & ccohort%cmort * ccohort%n / m2_per_ha ! mortality - hio_m11_si_scpf(io_si,scpf) = hio_m11_si_scpf(io_si,scpf) + & - ccohort%dgmort*ccohort%n / m2_per_ha - hio_m11_si_scls(io_si,scls) = hio_m11_si_scls(io_si,scls) + & - ccohort%dgmort*ccohort%n / m2_per_ha - hio_m11_si_cdpf(io_si,cdpf) = hio_m11_si_cdpf(io_si,cdpf) + & + this%hvars(ih_m11_si_scpf)%r82d(io_si,scpf) = & + this%hvars(ih_m11_si_scpf)%r82d(io_si,scpf) + & ccohort%dgmort*ccohort%n / m2_per_ha - hio_m11_si_cdsc(io_si,cdsc) = hio_m11_si_cdsc(io_si,cdsc) + & + this%hvars(ih_m11_si_cdpf)%r82d(io_si,cdpf) = & + this%hvars(ih_m11_si_cdpf)%r82d(io_si,cdpf) + & ccohort%dgmort*ccohort%n / m2_per_ha - - hio_ddbh_si_cdsc(io_si,cdsc) = hio_ddbh_si_cdsc(io_si,cdsc) + & - ccohort%ddbhdt*ccohort%n / m2_per_ha * m_per_cm - - hio_ddbh_si_cdpf(io_si,cdpf) = hio_ddbh_si_cdpf(io_si,cdpf) + & + + this%hvars(ih_ddbh_si_cdpf)%r82d(io_si,cdpf) = & + this%hvars(ih_ddbh_si_cdpf)%r82d(io_si,cdpf) + & ccohort%ddbhdt*ccohort%n / m2_per_ha * m_per_cm end if @@ -2947,33 +2892,30 @@ subroutine update_history_dyn(this,nc,nsites,sites) if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then ! carbon starvation mortality in the canopy by size x damage x pft - hio_m3_mortality_canopy_si_cdpf(io_si,cdpf) = hio_m3_mortality_canopy_si_cdpf(io_si,cdpf)+& + this%hvars(ih_m3_mortality_canopy_si_cdpf)%r82d(io_si,cdpf) = & + this%hvars(ih_m3_mortality_canopy_si_cdpf)%r82d(io_si,cdpf)+& ccohort%cmort * ccohort%n / m2_per_ha ! damage mortality in the canopy by size x damage x pft - hio_m11_mortality_canopy_si_cdpf(io_si,cdpf) = hio_m11_mortality_canopy_si_cdpf(io_si,cdpf)+& - ccohort%dgmort * ccohort%n / m2_per_ha - - ! carbon starvation mortality in the canopy by size x damage - hio_m3_mortality_canopy_si_cdsc(io_si,cdsc) = hio_m3_mortality_canopy_si_cdsc(io_si,cdsc)+& - ccohort%cmort * ccohort%n / m2_per_ha - ! damage mortality in the canopy by size x damage - hio_m11_mortality_canopy_si_cdsc(io_si,cdsc) = hio_m11_mortality_canopy_si_cdsc(io_si,cdsc)+& + this%hvars(ih_m11_mortality_canopy_si_cdpf)%r82d(io_si,cdpf) = & + this%hvars(ih_m11_mortality_canopy_si_cdpf)%r82d(io_si,cdpf)+& ccohort%dgmort * ccohort%n / m2_per_ha - hio_mortality_canopy_si_cdpf(io_si,cdpf) = hio_mortality_canopy_si_cdpf(io_si,cdpf)+ & + + this%hvars(ih_mortality_canopy_si_cdpf)%r82d(io_si,cdpf) = & + this%hvars(ih_mortality_canopy_si_cdpf)%r82d(io_si,cdpf)+ & (ccohort%bmort + ccohort%hmort + ccohort%cmort + ccohort%frmort + ccohort%smort + & ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + & (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & ccohort%n * sec_per_day * days_per_year / m2_per_ha ! nplants by damage - hio_nplant_canopy_si_cdpf(io_si,cdpf) = hio_nplant_canopy_si_cdpf(io_si,cdpf) + & - ccohort%n / m2_per_ha - hio_nplant_canopy_si_cdsc(io_si,cdsc) = hio_nplant_canopy_si_cdsc(io_si,cdsc) + & + this%hvars(ih_nplant_canopy_si_cdpf)%r82d(io_si,cdpf) = & + this%hvars(ih_nplant_canopy_si_cdpf)%r82d(io_si,cdpf) + & ccohort%n / m2_per_ha - + ! growth rate by damage x size x pft in the canopy - hio_ddbh_canopy_si_cdpf(io_si,cdpf) = hio_ddbh_canopy_si_cdpf(io_si,cdpf) + & + this%hvars(ih_ddbh_canopy_si_cdpf)%r82d(io_si,cdpf) = & + this%hvars(ih_ddbh_canopy_si_cdpf)%r82d(io_si,cdpf) + & ccohort%ddbhdt*ccohort%n / m2_per_ha * m_per_cm end if ! end if damage @@ -3081,37 +3023,31 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! damage variables - understory if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then - ! carbon starvation mortality in the understory by size and by size x damage - hio_m3_mortality_understory_si_cdsc(io_si,cdsc) = hio_m3_mortality_understory_si_cdsc(io_si,cdsc)+& - ccohort%cmort * ccohort%n / m2_per_ha - - ! damage mortality in the understory by size and by size x damage - hio_m11_mortality_understory_si_cdsc(io_si,cdsc) = hio_m11_mortality_understory_si_cdsc(io_si,cdsc)+& - ccohort%dgmort * ccohort%n / m2_per_ha - ! carbon mortality in the understory by damage x size x pft - hio_m3_mortality_understory_si_cdpf(io_si,cdpf) = hio_m3_mortality_understory_si_cdpf(io_si,cdpf)+& + this%hvars(ih_m3_mortality_understory_si_cdpf)%r82d(io_si,cdpf) = & + this%hvars(ih_m3_mortality_understory_si_cdpf)%r82d(io_si,cdpf) + & ccohort%cmort * ccohort%n / m2_per_ha ! damage in the understory by damage x size x pft - hio_m11_mortality_understory_si_cdpf(io_si,cdpf) = hio_m11_mortality_understory_si_cdpf(io_si,cdpf)+& + this%hvars(ih_m11_mortality_understory_si_cdpf)%r82d(io_si,cdpf) = & + this%hvars(ih_m11_mortality_understory_si_cdpf)%r82d(io_si,cdpf) + & ccohort%dgmort * ccohort%n / m2_per_ha ! total mortality of understory cohorts by damage x size x pft - hio_mortality_understory_si_cdpf(io_si,cdpf) = hio_mortality_understory_si_cdpf(io_si,cdpf)+ & + this%hvars(ih_mortality_understory_si_cdpf)%r82d(io_si,cdpf) = & + this%hvars(ih_mortality_understory_si_cdpf)%r82d(io_si,cdpf) + & (ccohort%bmort + ccohort%hmort + ccohort%cmort + ccohort%frmort + & ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + & (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & ccohort%n * sec_per_day * days_per_year / m2_per_ha - ! number of plants in the understory by size x damage and size x damage x pft - hio_nplant_understory_si_cdsc(io_si,cdsc) = hio_nplant_understory_si_cdsc(io_si,cdsc) + & - ccohort%n / m2_per_ha - hio_nplant_understory_si_cdpf(io_si,cdpf) = hio_nplant_understory_si_cdpf(io_si,cdpf) + & + this%hvars(ih_nplant_understory_si_cdpf)%r82d(io_si,cdpf) = & + this%hvars(ih_nplant_understory_si_cdpf)%r82d(io_si,cdpf) + & ccohort%n / m2_per_ha ! growth rate by size x damage x pft - understory - hio_ddbh_understory_si_cdpf(io_si,cdpf) = hio_ddbh_understory_si_cdpf(io_si,cdpf) + & + this%hvars(ih_ddbh_understory_si_cdpf)%r82d(io_si,cdpf) = & + this%hvars(ih_ddbh_understory_si_cdpf)%r82d(io_si,cdpf) + & ccohort%ddbhdt*ccohort%n / m2_per_ha * m_per_cm end if ! end if damage @@ -3373,25 +3309,21 @@ subroutine update_history_dyn(this,nc,nsites,sites) icdpf = (icdam-1)*nlevsclass + i_scls + & (i_pft-1) * nlevsclass * ncrowndamage - hio_mortality_si_cdsc(io_si, icdsc) = hio_mortality_si_cdsc(io_si, icdsc) + & - ( (sites(s)%term_nindivs_canopy_damage(icdam, i_scls, i_pft) * days_per_year ) + & - (sites(s)%term_nindivs_ustory_damage(icdam, i_scls, i_pft) * days_per_year) + & - sites(s)%imort_rate_damage(icdam, i_scls, i_pft) + & - sites(s)%fmort_rate_canopy_damage(icdam, i_scls, i_pft) + & - sites(s)%fmort_rate_ustory_damage(icdam, i_scls, i_pft) ) / m2_per_ha - - hio_mortality_si_cdpf(io_si, icdpf) = hio_mortality_si_cdpf(io_si, icdpf) + & + this%hvars(ih_mortality_si_cdpf)%r82d(io_si, icdpf) = & + this%hvars(ih_mortality_si_cdpf)%r82d(io_si, icdpf) + & ( (sites(s)%term_nindivs_canopy_damage(icdam, i_scls, i_pft) * days_per_year) + & (sites(s)%term_nindivs_ustory_damage(icdam, i_scls, i_pft) * days_per_year) + & sites(s)%imort_rate_damage(icdam, i_scls, i_pft) + & sites(s)%fmort_rate_canopy_damage(icdam, i_scls, i_pft) + & sites(s)%fmort_rate_ustory_damage(icdam, i_scls, i_pft) ) / m2_per_ha - hio_mortality_canopy_si_cdpf(io_si,icdpf) = hio_mortality_canopy_si_cdpf(io_si,icdpf) + & + this%hvars(ih_mortality_canopy_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_mortality_canopy_si_cdpf)%r82d(io_si,icdpf) + & ( sites(s)%term_nindivs_canopy_damage(icdam,i_scls,i_pft) * days_per_year + & sites(s)%fmort_rate_canopy_damage(icdam, i_scls, i_pft) )/ m2_per_ha - hio_mortality_understory_si_cdpf(io_si,icdpf) = hio_mortality_understory_si_cdpf(io_si,icdpf) + & + this%hvars(ih_mortality_understory_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_mortality_understory_si_cdpf)%r82d(io_si,icdpf) + & ( sites(s)%term_nindivs_ustory_damage(icdam, i_scls,i_pft) * days_per_year + & sites(s)%imort_rate_damage(icdam, i_scls, i_pft) + & sites(s)%fmort_rate_ustory_damage(icdam, i_scls, i_pft) )/ m2_per_ha @@ -3448,8 +3380,13 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_m7_si_scpf(io_si,i_scpf) + & hio_m8_si_scpf(io_si,i_scpf) + & hio_m9_si_scpf(io_si,i_scpf) + & - hio_m10_si_scpf(io_si,i_scpf)+ & - hio_m11_si_scpf(io_si,i_scpf) + hio_m10_si_scpf(io_si,i_scpf) + + if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + hio_mortality_si_pft(io_si, i_pft) = hio_mortality_si_pft(io_si,i_pft) + & + this%hvars(ih_m11_si_scpf)%r82d(io_si,i_scpf) + end if + end do end do @@ -4734,7 +4671,6 @@ subroutine define_history_vars(this, initialize_variables) ! plant functional type (site_pft_r8) : PF ! soil layer (site_ground_r8) : SL ! cohort size (site_size_r8) : SZ - ! cohort crown damage (site_cd_r8) : CD ! Multiple dimensions should have multiple two-code suffixes: ! cohort age x pft (site_cooage_r8) : ACPF @@ -6880,31 +6816,16 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_crownarea_ustory_damage_si ) - call this%set_history_var(vname='FATES_NPLANT_SZCD', units = 'm-2', & - long='N. plants per damage x size class', use_default='inactive', & - avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_si_cdsc ) - call this%set_history_var(vname='FATES_NPLANT_CDPF', units = 'm-2', & long='N. plants per damage x size x pft class', use_default='inactive', & avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_si_cdpf ) - - call this%set_history_var(vname='FATES_NPLANT_CANOPY_SZCD', units = 'm-2', & - long='N. plants in the canopy per damage x size class', use_default='inactive', & - avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_canopy_si_cdsc ) - + call this%set_history_var(vname='FATES_NPLANT_CANOPY_CDPF', units = 'm-2', & long='N. plants per damage x size x pft class', use_default='inactive', & avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_canopy_si_cdpf ) - call this%set_history_var(vname='FATES_NPLANT_USTORY_SZCD', units = 'm-2', & - long='N. plants in the understory per damage x size class', use_default='inactive', & - avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_understory_si_cdsc ) - call this%set_history_var(vname='FATES_NPLANT_USTORY_CDPF', units = 'm-2', & long='N. plants in the understory per damage x size x pft class', use_default='inactive', & avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & @@ -6915,16 +6836,6 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_si_cdpf ) - call this%set_history_var(vname='FATES_M3_SZCD', units = 'm-2 yr-1', & - long='carbon starvation mortality by damage/size', use_default='inactive', & - avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_si_cdsc ) - - call this%set_history_var(vname='FATES_M11_SZ', units = 'm-2 yr-1', & - long='damage mortality by size',use_default='inactive', & - avgflag='A', vtype=site_size_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_si_scls ) - call this%set_history_var(vname='FATES_M11_SZPF', units = 'm-2 yr-1', & long='damage mortality by pft/size',use_default='inactive', & avgflag='A', vtype =site_size_pft_r8, hlms='CLM:ALM', & @@ -6935,31 +6846,11 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_si_cdpf ) - call this%set_history_var(vname='FATES_M11_SZCD', units = 'm-2 yr-1', & - long='damage mortality by damage/size', use_default='inactive', & - avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_si_cdsc ) - - call this%set_history_var(vname='FATES_MORTALITY_SZCD', units = 'm-2 yr-1', & - long='mortality by damage class by size', use_default='inactive', & - avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_si_cdsc ) - call this%set_history_var(vname='FATES_MORTALITY_CDPF', units = 'm-2 yr-1', & long='mortality by damage class by size by pft', use_default='inactive', & avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_si_cdpf ) - call this%set_history_var(vname='FATES_M3_MORTALITY_CANOPY_SZCD', units = 'm-2 yr-1', & - long='C starviation mortality of canopy trees by damage/size class', use_default='inactive', & - avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_canopy_si_cdsc) - - call this%set_history_var(vname='FATES_M3_MORTALITY_USTORY_SZCD', units = 'm-2 yr-1', & - long='C starviation mortality of understory trees by damage/size class', use_default='inactive', & - avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_understory_si_cdsc) - call this%set_history_var(vname='FATES_M3_MORTALITY_CANOPY_CDPF', units = 'm-2 yr-1', & long='C starvation mortality of canopy plants by damage/pft/size', use_default='inactive', & avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & @@ -6970,11 +6861,6 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_understory_si_cdpf ) - call this%set_history_var(vname='FATES_M11_MORTALITY_CANOPY_SZCD', units = 'm-2 yr-1', & - long='damage mortality of canopy trees by damage/size class', use_default='inactive', & - avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_canopy_si_cdsc) - call this%set_history_var(vname='FATES_M11_MORTALITY_CANOPY_CDPF', units = 'm-2 yr-1', & long='damage mortality of canopy plants by damage/pft/size', use_default='inactive', & avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & @@ -6994,17 +6880,7 @@ subroutine define_history_vars(this, initialize_variables) long='mortality of understory plants by pft/size', use_default='inactive', & avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_understory_si_cdpf ) - - call this%set_history_var(vname='FATES_M11_MORTALITY_USTORY_SZCD', units = 'm-2 yr-1', & - long='damage mortality of understory trees by damage/size class', use_default='inactive', & - avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_understory_si_cdsc) - - call this%set_history_var(vname='FATES_DDBH_SZCD', units = 'm m-2 yr-1', & - long='ddbh annual increment growth by damage and size', use_default='inactive', & - avgflag='A', vtype=site_cdsc_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_si_cdsc ) - + call this%set_history_var(vname='FATES_DDBH_CDPF', units = 'm m-2 yr-1', & long='ddbh annual increment growth by damage x size pft', use_default='inactive', & avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & diff --git a/main/FatesIODimensionsMod.F90 b/main/FatesIODimensionsMod.F90 index 09bead9bc4..52e3dee6c3 100644 --- a/main/FatesIODimensionsMod.F90 +++ b/main/FatesIODimensionsMod.F90 @@ -145,8 +145,6 @@ module FatesIODimensionsMod integer :: cnlf_end integer :: cnlfpft_begin integer :: cnlfpft_end - integer :: cdamage_begin - integer :: cdamage_end integer :: cdsc_begin integer :: cdsc_end integer :: cdpf_begin diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 38ff625b68..5f9712f786 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1031,7 +1031,6 @@ subroutine fates_history_maps allocate( fates_hdim_pfmap_levcapf(1:nlevcoage*numpft)) allocate( fates_hdim_camap_levcapf(1:nlevcoage*numpft)) - allocate( fates_hdim_levcdam(ncrowndamage )) allocate( fates_hdim_scmap_levcdsc(nlevsclass*ncrowndamage)) allocate( fates_hdim_cdmap_levcdsc(nlevsclass*ncrowndamage)) allocate( fates_hdim_scmap_levcdpf(nlevsclass*ncrowndamage * numpft)) @@ -1091,10 +1090,6 @@ subroutine fates_history_maps fates_hdim_levcan(ican) = ican end do - ! make damage array - do icdam = 1,ncrowndamage - fates_hdim_levcdam(icdam) = icdam - end do ! Make an element array, each index is the PARTEH global identifier index diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 2f3b8aaf96..b75994f1a0 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -241,7 +241,6 @@ module FatesInterfaceTypesMod real(r8), public, allocatable :: fates_hdim_levsclass(:) ! plant size class lower bound dimension integer , public, allocatable :: fates_hdim_pfmap_levscpf(:) ! map of pfts into size-class x pft dimension integer , public, allocatable :: fates_hdim_scmap_levscpf(:) ! map of size-class into size-class x pft dimension - integer , public, allocatable :: fates_hdim_levcdam(:) ! crown damage dimension integer , public, allocatable :: fates_hdim_pftmap_levcdpf(:) ! map of pfts into size x crowndamage x pft dimension integer , public, allocatable :: fates_hdim_cdmap_levcdpf(:) ! map of crowndamage into size x crowndamage x pft integer , public, allocatable :: fates_hdim_scmap_levcdpf(:) ! map of size into size x crowndamage x pft From 156f7bdef52818f7e3f06b7a3e485c5076215e58 Mon Sep 17 00:00:00 2001 From: ckoven Date: Wed, 16 Feb 2022 18:21:59 -0700 Subject: [PATCH 118/852] some changes to allow tracking mortality carbon flux vars --- biogeochem/EDCohortDynamicsMod.F90 | 4 +-- biogeochem/EDPatchDynamicsMod.F90 | 17 +++++---- main/EDInitMod.F90 | 12 +++---- main/EDTypesMod.F90 | 16 ++++----- main/FatesHistoryInterfaceMod.F90 | 57 +++++++++++++++++++++--------- 5 files changed, 67 insertions(+), 39 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 5446c94dda..cb11005dc4 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -825,13 +825,13 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_ currentSite%term_nindivs_canopy(currentCohort%size_class,currentCohort%pft) = & currentSite%term_nindivs_canopy(currentCohort%size_class,currentCohort%pft) + currentCohort%n - currentSite%term_carbonflux_canopy = currentSite%term_carbonflux_canopy + & + currentSite%term_carbonflux_canopy(currentCohort%pft) = currentSite%term_carbonflux_canopy(currentCohort%pft) + & currentCohort%n * (struct_c+sapw_c+leaf_c+fnrt_c+store_c+repro_c) else currentSite%term_nindivs_ustory(currentCohort%size_class,currentCohort%pft) = & currentSite%term_nindivs_ustory(currentCohort%size_class,currentCohort%pft) + currentCohort%n - currentSite%term_carbonflux_ustory = currentSite%term_carbonflux_ustory + & + currentSite%term_carbonflux_ustory(currentCohort%pft) = currentSite%term_carbonflux_ustory(currentCohort%pft) + & currentCohort%n * (struct_c+sapw_c+leaf_c+fnrt_c+store_c+repro_c) end if diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 5f89ba0b07..230b8ede73 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -194,7 +194,7 @@ subroutine disturbance_rates( site_in, bc_in) ! first calculate the fractino of the site that is primary land call get_frac_site_primary(site_in, frac_site_primary) - site_in%harvest_carbon_flux = 0._r8 + site_in%harvest_carbon_flux(:) = 0._r8 currentPatch => site_in%oldest_patch do while (associated(currentPatch)) @@ -233,7 +233,8 @@ subroutine disturbance_rates( site_in, bc_in) ! estimate the wood product (trunk_product_site) if (currentCohort%canopy_layer>=1) then - site_in%harvest_carbon_flux = site_in%harvest_carbon_flux + & + site_in%harvest_carbon_flux(currentCohort%pft) = & + site_in%harvest_carbon_flux(currentCohort%pft) + & currentCohort%lmort_direct * currentCohort%n * & ( currentCohort%prt%GetState(sapw_organ, all_carbon_elements) + & currentCohort%prt%GetState(struct_organ, all_carbon_elements)) * & @@ -780,7 +781,8 @@ subroutine spawn_patches( currentSite, bc_in) nc%n * ED_val_understorey_death / hlm_freq_day - currentSite%imort_carbonflux = currentSite%imort_carbonflux + & + currentSite%imort_carbonflux(currentCohort%pft) = & + currentSite%imort_carbonflux(currentCohort%pft) + & (nc%n * ED_val_understorey_death / hlm_freq_day ) * & total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 @@ -856,7 +858,8 @@ subroutine spawn_patches( currentSite, bc_in) currentSite%fmort_rate_canopy(currentCohort%size_class, currentCohort%pft) + & nc%n * currentCohort%fire_mort / hlm_freq_day - currentSite%fmort_carbonflux_canopy = currentSite%fmort_carbonflux_canopy + & + currentSite%fmort_carbonflux_canopy(currentCohort%pft) = & + currentSite%fmort_carbonflux_canopy(currentCohort%pft) + & (nc%n * currentCohort%fire_mort) * & total_c * g_per_kg * days_per_sec * ha_per_m2 @@ -865,7 +868,8 @@ subroutine spawn_patches( currentSite, bc_in) currentSite%fmort_rate_ustory(currentCohort%size_class, currentCohort%pft) + & nc%n * currentCohort%fire_mort / hlm_freq_day - currentSite%fmort_carbonflux_ustory = currentSite%fmort_carbonflux_ustory + & + currentSite%fmort_carbonflux_ustory(currentCohort%pft) = & + currentSite%fmort_carbonflux_ustory(currentCohort%pft) + & (nc%n * currentCohort%fire_mort) * & total_c * g_per_kg * days_per_sec * ha_per_m2 end if @@ -997,7 +1001,8 @@ subroutine spawn_patches( currentSite, bc_in) nc%n * currentPatch%fract_ldist_not_harvested * & logging_coll_under_frac / hlm_freq_day - currentSite%imort_carbonflux = currentSite%imort_carbonflux + & + currentSite%imort_carbonflux(currentCohort%pft) = & + currentSite%imort_carbonflux(currentCohort%pft) + & (nc%n * currentPatch%fract_ldist_not_harvested * & logging_coll_under_frac/ hlm_freq_day ) * & total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index bb83ffb668..1c43542894 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -203,7 +203,7 @@ subroutine zero_site( site_in ) ! Disturbance rates tracking site_in%primary_land_patchfusion_error = 0.0_r8 - site_in%harvest_carbon_flux = 0.0_r8 + site_in%harvest_carbon_flux(:) = 0.0_r8 site_in%potential_disturbance_rates(:) = 0.0_r8 site_in%disturbance_rates_secondary_to_secondary(:) = 0.0_r8 site_in%disturbance_rates_primary_to_secondary(:) = 0.0_r8 @@ -225,15 +225,15 @@ subroutine zero_site( site_in ) ! termination and recruitment info site_in%term_nindivs_canopy(:,:) = 0._r8 site_in%term_nindivs_ustory(:,:) = 0._r8 - site_in%term_carbonflux_canopy = 0._r8 - site_in%term_carbonflux_ustory = 0._r8 + site_in%term_carbonflux_canopy(:) = 0._r8 + site_in%term_carbonflux_ustory(:) = 0._r8 site_in%recruitment_rate(:) = 0._r8 site_in%imort_rate(:,:) = 0._r8 - site_in%imort_carbonflux = 0._r8 + site_in%imort_carbonflux(:) = 0._r8 site_in%fmort_rate_canopy(:,:) = 0._r8 site_in%fmort_rate_ustory(:,:) = 0._r8 - site_in%fmort_carbonflux_canopy = 0._r8 - site_in%fmort_carbonflux_ustory = 0._r8 + site_in%fmort_carbonflux_canopy(:) = 0._r8 + site_in%fmort_carbonflux_ustory(:) = 0._r8 site_in%fmort_rate_cambial(:,:) = 0._r8 site_in%fmort_rate_crown(:,:) = 0._r8 diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 9ce4d5fe44..8275f38cb7 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -797,15 +797,16 @@ module EDTypesMod real(r8), allocatable :: term_nindivs_ustory(:,:) ! number of understory individuals that were in cohorts which ! were terminated this timestep, on size x pft - real(r8) :: term_carbonflux_canopy ! carbon flux from live to dead pools associated + real(r8) :: term_carbonflux_canopy(1:maxpft) ! carbon flux from live to dead pools associated ! with termination mortality, per canopy level - real(r8) :: term_carbonflux_ustory ! carbon flux from live to dead pools associated + real(r8) :: term_carbonflux_ustory(1:maxpft) ! carbon flux from live to dead pools associated ! with termination mortality, per canopy level - real(r8) :: demotion_carbonflux ! biomass of demoted individuals from canopy to understory [kgC/ha/day] - real(r8) :: promotion_carbonflux ! biomass of promoted individuals from understory to canopy [kgC/ha/day] - real(r8) :: imort_carbonflux ! biomass of individuals killed due to impact mortality per year. [kgC/ha/day] - real(r8) :: fmort_carbonflux_canopy ! biomass of canopy indivs killed due to fire per year. [gC/m2/sec] - real(r8) :: fmort_carbonflux_ustory ! biomass of understory indivs killed due to fire per year [gC/m2/sec] + real(r8) :: demotion_carbonflux ! biomass of demoted individuals from canopy to understory [kgC/ha/day] + real(r8) :: promotion_carbonflux ! biomass of promoted individuals from understory to canopy [kgC/ha/day] + real(r8) :: imort_carbonflux(1:maxpft) ! biomass of individuals killed due to impact mortality per year. [kgC/ha/day] + real(r8) :: fmort_carbonflux_canopy(1:maxpft) ! biomass of canopy indivs killed due to fire per year. [gC/m2/sec] + real(r8) :: fmort_carbonflux_ustory(1:maxpft) ! biomass of understory indivs killed due to fire per year [gC/m2/sec] + real(r8) :: harvest_carbon_flux(1:maxpft) ! diagnostic site level flux of carbon as harvested plants [kg C / m2 / day] real(r8) :: recruitment_rate(1:maxpft) ! number of individuals that were recruited into new cohorts real(r8), allocatable :: demotion_rate(:) ! rate of individuals demoted from canopy to understory per FATES timestep @@ -839,7 +840,6 @@ module EDTypesMod real(r8) :: disturbance_rates_secondary_to_secondary(N_DIST_TYPES) ! actual disturbance rates from secondary patches to secondary patches [m2/m2/day] real(r8) :: potential_disturbance_rates(N_DIST_TYPES) ! "potential" disturb rates (i.e. prior to the "which is most" logic) [m2/m2/day] real(r8) :: primary_land_patchfusion_error ! error term in total area of primary patches associated with patch fusion [m2/m2/day] - real(r8) :: harvest_carbon_flux ! diagnostic site level flux of carbon as harvested plants [kg C / m2 / day] end type ed_site_type diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 20918251d2..358eb0e932 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -509,6 +509,7 @@ module FatesHistoryInterfaceMod integer :: ih_nindivs_si_pft integer :: ih_recruitment_si_pft integer :: ih_mortality_si_pft + integer :: ih_mortality_carbonflux_si_pft integer :: ih_crownarea_si_pft integer :: ih_canopycrownarea_si_pft integer :: ih_gpp_si_pft @@ -1841,6 +1842,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_nindivs_si_pft => this%hvars(ih_nindivs_si_pft)%r82d, & hio_recruitment_si_pft => this%hvars(ih_recruitment_si_pft)%r82d, & hio_mortality_si_pft => this%hvars(ih_mortality_si_pft)%r82d, & + hio_mortality_carbonflux_si_pft => this%hvars(ih_mortality_carbonflux_si_pft)%r82d, & hio_crownarea_si_pft => this%hvars(ih_crownarea_si_pft)%r82d, & hio_canopycrownarea_si_pft => this%hvars(ih_canopycrownarea_si_pft)%r82d, & hio_gpp_si_pft => this%hvars(ih_gpp_si_pft)%r82d, & @@ -2179,7 +2181,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_potential_disturbance_rate_si(io_si) = sum(sites(s)%potential_disturbance_rates(1:N_DIST_TYPES)) * days_per_year ! harvest carbon flux in [kgC/m2/d] -> [kgC/m2/yr] - hio_harvest_carbonflux_si(io_si) = sites(s)%harvest_carbon_flux * & + hio_harvest_carbonflux_si(io_si) = sum(sites(s)%harvest_carbon_flux(:)) * & days_per_year ! Loop through patches to sum up diagonistics @@ -2590,6 +2592,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) ccohort%frmort*ccohort%n / m2_per_ha hio_m9_si_scls(io_si,scls) = hio_m9_si_scls(io_si,scls) + ccohort%smort*ccohort%n / m2_per_ha + !C13 discrimination if(gpp_cached + ccohort%gpp_acc_hold > 0.0_r8)then hio_c13disc_si_scpf(io_si,scpf) = ((hio_c13disc_si_scpf(io_si,scpf) * gpp_cached) + & @@ -2617,6 +2620,12 @@ subroutine update_history_dyn(this,nc,nsites,sites) alive_m = leaf_m + fnrt_m + sapw_m total_m = alive_m + store_m + struct_m + hio_mortality_carbonflux_si_pft(io_si,ccohort%pft) = hio_mortality_carbonflux_si_pft(io_si,ccohort%pft) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort) * & + total_m * ccohort%n * days_per_sec * years_per_day * ha_per_m2 + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * total_m * & + ccohort%n * ha_per_m2 ! number density by size and biomass hio_agb_si_scls(io_si,scls) = hio_agb_si_scls(io_si,scls) + & @@ -3028,14 +3037,6 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_mortality_understory_si_scls(io_si,i_scls) = hio_mortality_understory_si_scls(io_si,i_scls) + & sites(s)%fmort_rate_ustory(i_scls, i_pft) / m2_per_ha - ! - ! carbon flux associated with mortality of trees dying by fire - hio_canopy_mortality_carbonflux_si(io_si) = hio_canopy_mortality_carbonflux_si(io_si) + & - sites(s)%fmort_carbonflux_canopy / g_per_kg - - hio_understory_mortality_carbonflux_si(io_si) = hio_understory_mortality_carbonflux_si(io_si) + & - sites(s)%fmort_carbonflux_ustory / g_per_kg - ! ! for scag variables, also treat as happening in the newly-disurbed patch @@ -3051,18 +3052,34 @@ subroutine update_history_dyn(this,nc,nsites,sites) end do end do + ! + ! carbon flux associated with mortality of trees dying by fire + hio_canopy_mortality_carbonflux_si(io_si) = hio_canopy_mortality_carbonflux_si(io_si) + & + sum(sites(s)%fmort_carbonflux_canopy(:)) / g_per_kg + + hio_understory_mortality_carbonflux_si(io_si) = hio_understory_mortality_carbonflux_si(io_si) + & + sum(sites(s)%fmort_carbonflux_ustory(:)) / g_per_kg + ! treat carbon flux from imort the same way hio_understory_mortality_carbonflux_si(io_si) = hio_understory_mortality_carbonflux_si(io_si) + & - sites(s)%imort_carbonflux / g_per_kg + sum(sites(s)%imort_carbonflux(:)) / g_per_kg ! + do i_pft = 1, numpft + hio_mortality_carbonflux_si_pft(io_si,ccohort%pft) = hio_mortality_carbonflux_si_pft(io_si,ccohort%pft) + & + (sites(s)%fmort_carbonflux_canopy(i_pft) + & + sites(s)%fmort_carbonflux_ustory(i_pft) + & + sites(s)%imort_carbonflux(i_pft) + & + sites(s)%harvest_carbon_flux(i_pft)) / g_per_kg !cdk + end do + sites(s)%term_nindivs_canopy(:,:) = 0._r8 sites(s)%term_nindivs_ustory(:,:) = 0._r8 - sites(s)%imort_carbonflux = 0._r8 + sites(s)%imort_carbonflux(:) = 0._r8 sites(s)%imort_rate(:,:) = 0._r8 sites(s)%fmort_rate_canopy(:,:) = 0._r8 sites(s)%fmort_rate_ustory(:,:) = 0._r8 - sites(s)%fmort_carbonflux_canopy = 0._r8 - sites(s)%fmort_carbonflux_ustory = 0._r8 + sites(s)%fmort_carbonflux_canopy(:) = 0._r8 + sites(s)%fmort_carbonflux_ustory(:) = 0._r8 sites(s)%fmort_rate_cambial(:,:) = 0._r8 sites(s)%fmort_rate_crown(:,:) = 0._r8 sites(s)%growthflux_fusion(:,:) = 0._r8 @@ -3462,14 +3479,14 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! mortality-associated carbon fluxes hio_canopy_mortality_carbonflux_si(io_si) = hio_canopy_mortality_carbonflux_si(io_si) + & - sites(s)%term_carbonflux_canopy * days_per_sec * ha_per_m2 + sum(sites(s)%term_carbonflux_canopy(:)) * days_per_sec * ha_per_m2 hio_understory_mortality_carbonflux_si(io_si) = hio_understory_mortality_carbonflux_si(io_si) + & - sites(s)%term_carbonflux_ustory * days_per_sec * ha_per_m2 + sum(sites(s)%term_carbonflux_ustory(:)) * days_per_sec * ha_per_m2 ! and zero the site-level termination carbon flux variable - sites(s)%term_carbonflux_canopy = 0._r8 - sites(s)%term_carbonflux_ustory = 0._r8 + sites(s)%term_carbonflux_canopy(:) = 0._r8 + sites(s)%term_carbonflux_ustory(:) = 0._r8 ! ! add the site-level disturbance-associated cwd and litter input fluxes to thir respective flux fields @@ -5438,6 +5455,12 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_understory_mortality_carbonflux_si) + call this%set_history_var(vname='FATES_MORTALITY_CFLUX_PF', units='kg m-2 s-1', & + long='PFT-level flux of biomass carbon from live to dead pool from mortality', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_mortality_carbonflux_si_pft) + ! size class by age dimensioned variables call this%set_history_var(vname='FATES_NPLANT_SZAP', units = 'm-2', & From 6b6ed7fac7dc745352c8d5875223fa40f7f0dd73 Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Thu, 17 Feb 2022 11:09:18 -0800 Subject: [PATCH 119/852] [ Remove cdcd dimension ] [ Remove the damage x damage dimension. Not needed. ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary: no testing --- main/FatesIODimensionsMod.F90 | 4 ---- main/FatesIOVariableKindMod.F90 | 1 - main/FatesInterfaceMod.F90 | 11 +---------- main/FatesInterfaceTypesMod.F90 | 2 -- 4 files changed, 1 insertion(+), 17 deletions(-) diff --git a/main/FatesIODimensionsMod.F90 b/main/FatesIODimensionsMod.F90 index b5eafb2cef..52e3dee6c3 100644 --- a/main/FatesIODimensionsMod.F90 +++ b/main/FatesIODimensionsMod.F90 @@ -28,7 +28,6 @@ module FatesIODimensionsMod character(*), parameter, public :: levcnlf = 'fates_levcnlf' ! matches histFileMod character(*), parameter, public :: levcnlfpft = 'fates_levcnlfpf' ! matches histFileMod character(*), parameter, public :: levcdsc = 'fates_levcdsc' ! matches histFileMod - character(*), parameter, public :: levcdcd = 'fates_levcdcd' ! matches histFileMod character(*), parameter, public :: levcdpf = 'fates_levcdpf' ! matches histFileMod character(*), parameter, public :: levagefuel = 'fates_levagefuel' ! matches histFileMod character(*), parameter, public :: levelem = 'fates_levelem' @@ -86,9 +85,6 @@ module FatesIODimensionsMod ! levcdsc = This is a structure that records the boundaries for the ! number of crown damage x size classes dimension - ! levcdcd = This is a structure that records the boundaries for the - ! number of crown damage x crown damage classes - for damage transitions - ! levcdpf = This is a structure that records the boundaries for the ! number of crown damage x size classes x pft dimension diff --git a/main/FatesIOVariableKindMod.F90 b/main/FatesIOVariableKindMod.F90 index 3b10d698cd..a40f1c2dbe 100644 --- a/main/FatesIOVariableKindMod.F90 +++ b/main/FatesIOVariableKindMod.F90 @@ -33,7 +33,6 @@ module FatesIOVariableKindMod character(*), parameter, public :: site_cnlfpft_r8 = 'SI_CNLFPFT_R8' character(*), parameter, public :: site_cdpf_r8 = 'SI_CDPF_R8' character(*), parameter, public :: site_cdsc_r8 = 'SI_CDSC_R8' - character(*), parameter, public :: site_cdcd_r8 = 'SI_CDCD_R8' character(*), parameter, public :: site_scag_r8 = 'SI_SCAG_R8' character(*), parameter, public :: site_scagpft_r8 = 'SI_SCAGPFT_R8' character(*), parameter, public :: site_agepft_r8 = 'SI_AGEPFT_R8' diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 0d2463bf0a..56edc4df7f 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1013,7 +1013,6 @@ subroutine fates_history_maps integer :: ifuel integer :: ican integer :: icdam - integer :: icdcd integer :: ileaf integer :: iage integer :: iheight @@ -1172,15 +1171,7 @@ subroutine fates_history_maps end do end do - i=0 - do icdam=1,ncrowndamage - do icdcd=1,ncrowndamage+1 - i=i+1 - fates_hdim_cdimap_levcdcd(i) = icdcd - fates_hdim_cdjmap_levcdcd(i) = icdam - end do - end do - + i=0 do ipft=1,numpft do ican=1,nclmax diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index aa5444fb0b..b75994f1a0 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -246,8 +246,6 @@ module FatesInterfaceTypesMod integer , public, allocatable :: fates_hdim_scmap_levcdpf(:) ! map of size into size x crowndamage x pft integer , public, allocatable :: fates_hdim_cdmap_levcdsc(:) ! map of crowndamage into size x crowndamage integer , public, allocatable :: fates_hdim_scmap_levcdsc(:) ! map of size into size x crowndamage - integer , public, allocatable :: fates_hdim_cdimap_levcdcd(:) ! map of current damage into damage x damage - integer , public, allocatable :: fates_hdim_cdjmap_levcdcd(:) ! map of new damage into damage x damage real(r8), public, allocatable :: fates_hdim_levage(:) ! patch age lower bound dimension real(r8), public, allocatable :: fates_hdim_levheight(:) ! height lower bound dimension From 9ccbcb6fcbaed08d1f733513caafe5098abb3102 Mon Sep 17 00:00:00 2001 From: ckoven Date: Thu, 17 Feb 2022 13:22:50 -0700 Subject: [PATCH 120/852] undid changes to harvest_carbon_flux and added restart variables --- biogeochem/EDPatchDynamicsMod.F90 | 5 ++-- main/EDInitMod.F90 | 2 +- main/EDTypesMod.F90 | 2 +- main/FatesHistoryInterfaceMod.F90 | 5 ++-- main/FatesRestartInterfaceMod.F90 | 47 +++++++++++++++++++------------ 5 files changed, 35 insertions(+), 26 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 230b8ede73..e8e0190e5e 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -194,7 +194,7 @@ subroutine disturbance_rates( site_in, bc_in) ! first calculate the fractino of the site that is primary land call get_frac_site_primary(site_in, frac_site_primary) - site_in%harvest_carbon_flux(:) = 0._r8 + site_in%harvest_carbon_flux = 0._r8 currentPatch => site_in%oldest_patch do while (associated(currentPatch)) @@ -233,8 +233,7 @@ subroutine disturbance_rates( site_in, bc_in) ! estimate the wood product (trunk_product_site) if (currentCohort%canopy_layer>=1) then - site_in%harvest_carbon_flux(currentCohort%pft) = & - site_in%harvest_carbon_flux(currentCohort%pft) + & + site_in%harvest_carbon_flux = site_in%harvest_carbon_flux + & currentCohort%lmort_direct * currentCohort%n * & ( currentCohort%prt%GetState(sapw_organ, all_carbon_elements) + & currentCohort%prt%GetState(struct_organ, all_carbon_elements)) * & diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 1c43542894..63ec3fc280 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -203,7 +203,7 @@ subroutine zero_site( site_in ) ! Disturbance rates tracking site_in%primary_land_patchfusion_error = 0.0_r8 - site_in%harvest_carbon_flux(:) = 0.0_r8 + site_in%harvest_carbon_flux = 0.0_r8 site_in%potential_disturbance_rates(:) = 0.0_r8 site_in%disturbance_rates_secondary_to_secondary(:) = 0.0_r8 site_in%disturbance_rates_primary_to_secondary(:) = 0.0_r8 diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 8275f38cb7..3c9e44b5b8 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -806,7 +806,7 @@ module EDTypesMod real(r8) :: imort_carbonflux(1:maxpft) ! biomass of individuals killed due to impact mortality per year. [kgC/ha/day] real(r8) :: fmort_carbonflux_canopy(1:maxpft) ! biomass of canopy indivs killed due to fire per year. [gC/m2/sec] real(r8) :: fmort_carbonflux_ustory(1:maxpft) ! biomass of understory indivs killed due to fire per year [gC/m2/sec] - real(r8) :: harvest_carbon_flux(1:maxpft) ! diagnostic site level flux of carbon as harvested plants [kg C / m2 / day] + real(r8) :: harvest_carbon_flux ! diagnostic site level flux of carbon as harvested plants [kg C / m2 / day] real(r8) :: recruitment_rate(1:maxpft) ! number of individuals that were recruited into new cohorts real(r8), allocatable :: demotion_rate(:) ! rate of individuals demoted from canopy to understory per FATES timestep diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 358eb0e932..5c784a6677 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2181,7 +2181,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_potential_disturbance_rate_si(io_si) = sum(sites(s)%potential_disturbance_rates(1:N_DIST_TYPES)) * days_per_year ! harvest carbon flux in [kgC/m2/d] -> [kgC/m2/yr] - hio_harvest_carbonflux_si(io_si) = sum(sites(s)%harvest_carbon_flux(:)) * & + hio_harvest_carbonflux_si(io_si) = sites(s)%harvest_carbon_flux * & days_per_year ! Loop through patches to sum up diagonistics @@ -3068,8 +3068,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_mortality_carbonflux_si_pft(io_si,ccohort%pft) = hio_mortality_carbonflux_si_pft(io_si,ccohort%pft) + & (sites(s)%fmort_carbonflux_canopy(i_pft) + & sites(s)%fmort_carbonflux_ustory(i_pft) + & - sites(s)%imort_carbonflux(i_pft) + & - sites(s)%harvest_carbon_flux(i_pft)) / g_per_kg !cdk + sites(s)%imort_carbonflux(i_pft) ) / g_per_kg !cdk end do sites(s)%term_nindivs_canopy(:,:) = 0._r8 diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 0605767cd6..e2824a716b 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -208,9 +208,9 @@ module FatesRestartInterfaceMod integer :: ir_termcflux_usto_si integer :: ir_democflux_si integer :: ir_promcflux_si - integer :: ir_imortcflux_si - integer :: ir_fmortcflux_cano_si - integer :: ir_fmortcflux_usto_si + integer :: ir_imortcflux_sipft + integer :: ir_fmortcflux_cano_sipft + integer :: ir_fmortcflux_usto_sipft integer :: ir_cwdagin_flxdg integer :: ir_cwdbgin_flxdg integer :: ir_leaflittin_flxdg @@ -1230,20 +1230,20 @@ subroutine define_restart_vars(this, initialize_variables) units='indiv/ha/da', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_promrate_sisc) - call this%set_restart_var(vname='fates_imortcflux', vtype=site_r8, & + call this%set_restart_var(vname='fates_imortcflux', vtype=cohort_r8, & long_name='biomass of indivs killed due to impact mort', & units='kgC/ha/day', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_imortcflux_si) + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_imortcflux_sipft) - call this%set_restart_var(vname='fates_fmortcflux_canopy', vtype=site_r8, & + call this%set_restart_var(vname='fates_fmortcflux_canopy', vtype=cohort_r8, & long_name='fates diagnostic biomass of canopy fire', & units='gC/m2/sec', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_fmortcflux_cano_si) + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_fmortcflux_cano_sipft) - call this%set_restart_var(vname='fates_fmortcflux_ustory', vtype=site_r8, & + call this%set_restart_var(vname='fates_fmortcflux_ustory', vtype=cohort_r8, & long_name='fates diagnostic biomass of understory fire', & units='gC/m2/sec', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_fmortcflux_usto_si) + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_fmortcflux_usto_sipft) call this%set_restart_var(vname='fates_termcflux_canopy', vtype=site_r8, & long_name='fates diagnostic term carbon flux canopy', & @@ -2224,9 +2224,16 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_termcflux_usto_si(io_idx_si) = sites(s)%term_carbonflux_ustory rio_democflux_si(io_idx_si) = sites(s)%demotion_carbonflux rio_promcflux_si(io_idx_si) = sites(s)%promotion_carbonflux - rio_imortcflux_si(io_idx_si) = sites(s)%imort_carbonflux - rio_fmortcflux_cano_si(io_idx_si) = sites(s)%fmort_carbonflux_canopy - rio_fmortcflux_usto_si(io_idx_si) = sites(s)%fmort_carbonflux_ustory + + io_idx_si_pft = io_idx_co_1st + do i_pft = 1, numpft + rio_fmortcflux_cano_sipft(io_idx_si, io_idx_si_pft) = sites(s)%fmort_carbonflux_canopy(i_pft) + rio_fmortcflux_usto_sipft(io_idx_si, io_idx_si_pft) = sites(s)%fmort_carbonflux_ustory(i_pft) + + rio_imortcflux_sipft(io_idx_si, io_idx_si_pft) = sites(s)%imort_carbonflux(i_pft) + + io_idx_si_pft = io_idx_si_pft + 1 + end do rio_cd_status_si(io_idx_si) = sites(s)%cstatus rio_dd_status_si(io_idx_si) = sites(s)%dstatus @@ -2663,9 +2670,9 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_termcflux_usto_si => this%rvars(ir_termcflux_usto_si)%r81d, & rio_democflux_si => this%rvars(ir_democflux_si)%r81d, & rio_promcflux_si => this%rvars(ir_promcflux_si)%r81d, & - rio_imortcflux_si => this%rvars(ir_imortcflux_si)%r81d, & - rio_fmortcflux_cano_si => this%rvars(ir_fmortcflux_cano_si)%r81d, & - rio_fmortcflux_usto_si => this%rvars(ir_fmortcflux_usto_si)%r81d) + rio_imortcflux_sipft => this%rvars(ir_imortcflux_sipft)%r81d, & + rio_fmortcflux_cano_sipft => this%rvars(ir_fmortcflux_cano_sipft)%r81d, & + rio_fmortcflux_usto_sipft => this%rvars(ir_fmortcflux_usto_sipft)%r81d) totalcohorts = 0 @@ -3082,10 +3089,14 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%term_carbonflux_ustory = rio_termcflux_usto_si(io_idx_si) sites(s)%demotion_carbonflux = rio_democflux_si(io_idx_si) sites(s)%promotion_carbonflux = rio_promcflux_si(io_idx_si) - sites(s)%imort_carbonflux = rio_imortcflux_si(io_idx_si) - sites(s)%fmort_carbonflux_canopy = rio_fmortcflux_cano_si(io_idx_si) - sites(s)%fmort_carbonflux_ustory = rio_fmortcflux_usto_si(io_idx_si) + io_idx_si_pft = io_idx_co_1st + do i_pft = 1, numpft + sites(s)%fmort_carbonflux_canopy(i_pft) = rio_fmortcflux_cano_sipft(io_idx_si, io_idx_si_pft) + sites(s)%fmort_carbonflux_ustory(i_pft) = rio_fmortcflux_usto_sipft(io_idx_si, io_idx_si_pft) + sites(s)%imort_carbonflux(i_pft) = rio_imortcflux_sipft(io_idx_si, io_idx_si_pft) + io_idx_si_pft = io_idx_si_pft + 1 + end do ! Site level phenology status flags From 96aac267371c43bbf27f361aa2fa4898109e6498 Mon Sep 17 00:00:00 2001 From: ckoven Date: Thu, 17 Feb 2022 18:18:14 -0700 Subject: [PATCH 121/852] fixes to restart file --- main/FatesRestartInterfaceMod.F90 | 46 +++++++++++++++---------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index e2824a716b..6a3297714f 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -204,8 +204,8 @@ module FatesRestartInterfaceMod integer :: ir_growflx_fusion_siscpf integer :: ir_demorate_sisc integer :: ir_promrate_sisc - integer :: ir_termcflux_cano_si - integer :: ir_termcflux_usto_si + integer :: ir_termcflux_cano_sipft + integer :: ir_termcflux_usto_sipft integer :: ir_democflux_si integer :: ir_promcflux_si integer :: ir_imortcflux_sipft @@ -1245,15 +1245,15 @@ subroutine define_restart_vars(this, initialize_variables) units='gC/m2/sec', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_fmortcflux_usto_sipft) - call this%set_restart_var(vname='fates_termcflux_canopy', vtype=site_r8, & + call this%set_restart_var(vname='fates_termcflux_canopy', vtype=cohort_r8, & long_name='fates diagnostic term carbon flux canopy', & units='', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_termcflux_cano_si ) + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_termcflux_cano_sipft ) - call this%set_restart_var(vname='fates_termcflux_ustory', vtype=site_r8, & + call this%set_restart_var(vname='fates_termcflux_ustory', vtype=cohort_r8, & long_name='fates diagnostic term carbon flux understory', & units='', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_termcflux_usto_si ) + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_termcflux_usto_sipft ) call this%set_restart_var(vname='fates_democflux', vtype=site_r8, & long_name='fates diagnostic demotion carbon flux', & @@ -1828,13 +1828,13 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_growflx_fusion_siscpf => this%rvars(ir_growflx_fusion_siscpf)%r81d, & rio_demorate_sisc => this%rvars(ir_demorate_sisc)%r81d, & rio_promrate_sisc => this%rvars(ir_promrate_sisc)%r81d, & - rio_termcflux_cano_si => this%rvars(ir_termcflux_cano_si)%r81d, & - rio_termcflux_usto_si => this%rvars(ir_termcflux_usto_si)%r81d, & + rio_termcflux_cano_sipft => this%rvars(ir_termcflux_cano_sipft)%r81d, & + rio_termcflux_usto_sipft => this%rvars(ir_termcflux_usto_sipft)%r81d, & rio_democflux_si => this%rvars(ir_democflux_si)%r81d, & rio_promcflux_si => this%rvars(ir_promcflux_si)%r81d, & - rio_imortcflux_si => this%rvars(ir_imortcflux_si)%r81d, & - rio_fmortcflux_cano_si => this%rvars(ir_fmortcflux_cano_si)%r81d, & - rio_fmortcflux_usto_si => this%rvars(ir_fmortcflux_usto_si)%r81d) + rio_imortcflux_sipft => this%rvars(ir_imortcflux_sipft)%r81d, & + rio_fmortcflux_cano_sipft => this%rvars(ir_fmortcflux_cano_sipft)%r81d, & + rio_fmortcflux_usto_sipft => this%rvars(ir_fmortcflux_usto_sipft)%r81d) totalCohorts = 0 @@ -2220,17 +2220,17 @@ subroutine set_restart_vectors(this,nc,nsites,sites) io_idx_si_sc = io_idx_si_sc + 1 end do - rio_termcflux_cano_si(io_idx_si) = sites(s)%term_carbonflux_canopy - rio_termcflux_usto_si(io_idx_si) = sites(s)%term_carbonflux_ustory rio_democflux_si(io_idx_si) = sites(s)%demotion_carbonflux rio_promcflux_si(io_idx_si) = sites(s)%promotion_carbonflux io_idx_si_pft = io_idx_co_1st do i_pft = 1, numpft - rio_fmortcflux_cano_sipft(io_idx_si, io_idx_si_pft) = sites(s)%fmort_carbonflux_canopy(i_pft) - rio_fmortcflux_usto_sipft(io_idx_si, io_idx_si_pft) = sites(s)%fmort_carbonflux_ustory(i_pft) + rio_termcflux_cano_sipft(io_idx_si_pft) = sites(s)%term_carbonflux_canopy(i_pft) + rio_termcflux_usto_sipft(io_idx_si_pft) = sites(s)%term_carbonflux_ustory(i_pft) + rio_fmortcflux_cano_sipft(io_idx_si_pft) = sites(s)%fmort_carbonflux_canopy(i_pft) + rio_fmortcflux_usto_sipft(io_idx_si_pft) = sites(s)%fmort_carbonflux_ustory(i_pft) - rio_imortcflux_sipft(io_idx_si, io_idx_si_pft) = sites(s)%imort_carbonflux(i_pft) + rio_imortcflux_sipft(io_idx_si_pft) = sites(s)%imort_carbonflux(i_pft) io_idx_si_pft = io_idx_si_pft + 1 end do @@ -2666,8 +2666,8 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_growflx_fusion_siscpf => this%rvars(ir_growflx_fusion_siscpf)%r81d, & rio_demorate_sisc => this%rvars(ir_demorate_sisc)%r81d, & rio_promrate_sisc => this%rvars(ir_promrate_sisc)%r81d, & - rio_termcflux_cano_si => this%rvars(ir_termcflux_cano_si)%r81d, & - rio_termcflux_usto_si => this%rvars(ir_termcflux_usto_si)%r81d, & + rio_termcflux_cano_sipft => this%rvars(ir_termcflux_cano_sipft)%r81d, & + rio_termcflux_usto_sipft => this%rvars(ir_termcflux_usto_sipft)%r81d, & rio_democflux_si => this%rvars(ir_democflux_si)%r81d, & rio_promcflux_si => this%rvars(ir_promcflux_si)%r81d, & rio_imortcflux_sipft => this%rvars(ir_imortcflux_sipft)%r81d, & @@ -3085,16 +3085,16 @@ subroutine get_restart_vectors(this, nc, nsites, sites) io_idx_si_sc = io_idx_si_sc + 1 end do - sites(s)%term_carbonflux_canopy = rio_termcflux_cano_si(io_idx_si) - sites(s)%term_carbonflux_ustory = rio_termcflux_usto_si(io_idx_si) sites(s)%demotion_carbonflux = rio_democflux_si(io_idx_si) sites(s)%promotion_carbonflux = rio_promcflux_si(io_idx_si) io_idx_si_pft = io_idx_co_1st do i_pft = 1, numpft - sites(s)%fmort_carbonflux_canopy(i_pft) = rio_fmortcflux_cano_sipft(io_idx_si, io_idx_si_pft) - sites(s)%fmort_carbonflux_ustory(i_pft) = rio_fmortcflux_usto_sipft(io_idx_si, io_idx_si_pft) - sites(s)%imort_carbonflux(i_pft) = rio_imortcflux_sipft(io_idx_si, io_idx_si_pft) + sites(s)%term_carbonflux_canopy(i_pft) = rio_termcflux_cano_sipft(io_idx_si_pft) + sites(s)%term_carbonflux_ustory(i_pft) = rio_termcflux_usto_sipft(io_idx_si_pft) + sites(s)%fmort_carbonflux_canopy(i_pft) = rio_fmortcflux_cano_sipft(io_idx_si_pft) + sites(s)%fmort_carbonflux_ustory(i_pft) = rio_fmortcflux_usto_sipft(io_idx_si_pft) + sites(s)%imort_carbonflux(i_pft) = rio_imortcflux_sipft(io_idx_si_pft) io_idx_si_pft = io_idx_si_pft + 1 end do From 48ab4505ca05f2565655ad110aa6b3bb114f1b07 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 18 Feb 2022 15:37:46 -0800 Subject: [PATCH 122/852] adding missing local variables --- biogeochem/EDCanopyStructureMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 1dfba3f6f5..aaed60cd31 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1504,7 +1504,6 @@ subroutine leaf_area_profile( currentSite ) real(r8) :: min_chite ! bottom of cohort canopy (m) real(r8) :: max_chite ! top of cohort canopy (m) real(r8) :: lai ! summed lai for checking m2 m-2 - real(r8) :: leaf_c ! leaf carbon [kg] !---------------------------------------------------------------------- @@ -2197,12 +2196,13 @@ subroutine UpdatePatchLAI(currentPatch, patch_lai) ! Arguments type(ed_patch_type),intent(inout), target :: currentPatch - real(r8), intent(out) :: patch_lai + real(r8), intent(inout) :: patch_lai ! Local Variables type(ed_cohort_type), pointer :: currentCohort integer :: cl ! Canopy layer index integer :: ft ! Plant functional type index + real(r8) :: leaf_c ! leaf carbon [kg] ! Zero out the patch-level canopy layer variables currentPatch%canopy_layer_tlai(:) = 0._r8 From 5beb7fbdc54d4d18225e492ae358796510505e81 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 18 Feb 2022 15:56:22 -0800 Subject: [PATCH 123/852] misded dlower_vai --- biogeochem/EDCanopyStructureMod.F90 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index aaed60cd31..b3686ae047 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -2194,6 +2194,9 @@ subroutine UpdatePatchLAI(currentPatch, patch_lai) ! and related variables ! --------------------------------------------------------------------------------------------- + ! Uses + use EDtypesMod, only : dlower_vai + ! Arguments type(ed_patch_type),intent(inout), target :: currentPatch real(r8), intent(inout) :: patch_lai From d451203d51a559ad5697d2456461ad65ebd15ea0 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 18 Feb 2022 23:45:48 -0800 Subject: [PATCH 124/852] putting ncan and canopy_layer_tlai back outside of update call --- biogeochem/EDCanopyStructureMod.F90 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index b3686ae047..3443f7bc06 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1522,6 +1522,8 @@ subroutine leaf_area_profile( currentSite ) ! calculate tree lai and sai. ! -------------------------------------------------------------------------------- + currentPatch%canopy_layer_tlai(:) = 0._r8 + currentPatch%ncan(:,:) = 0 currentPatch%nrad(:,:) = 0 patch_lai = 0._r8 currentPatch%tlai_profile(:,:,:) = 0._r8 @@ -2208,8 +2210,8 @@ subroutine UpdatePatchLAI(currentPatch, patch_lai) real(r8) :: leaf_c ! leaf carbon [kg] ! Zero out the patch-level canopy layer variables - currentPatch%canopy_layer_tlai(:) = 0._r8 - currentPatch%ncan(:,:) = 0 + !currentPatch%canopy_layer_tlai(:) = 0._r8 + !currentPatch%ncan(:,:) = 0 ! Calculate LAI of layers above. Because it is possible for some understory cohorts ! to be taller than cohorts in the top canopy layer, we must iterate through the From 355a9458a7c510f731a7df398b4373e2f9a7ca34 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Sat, 19 Feb 2022 23:03:36 -0700 Subject: [PATCH 125/852] adding canopy layer loop to fix #823 --- biogeochem/EDCanopyStructureMod.F90 | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 3443f7bc06..6392b1f448 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -2209,22 +2209,18 @@ subroutine UpdatePatchLAI(currentPatch, patch_lai) integer :: ft ! Plant functional type index real(r8) :: leaf_c ! leaf carbon [kg] - ! Zero out the patch-level canopy layer variables - !currentPatch%canopy_layer_tlai(:) = 0._r8 - !currentPatch%ncan(:,:) = 0 - ! Calculate LAI of layers above. Because it is possible for some understory cohorts ! to be taller than cohorts in the top canopy layer, we must iterate through the ! patch by canopy layer first. Given that canopy_layer_tlai is a patch level variable ! we could iterate through each cohort in any direction as long as we go down through ! the canopy layers. - !canopyloop: do cl = 1,nclmax + canopyloop: do cl = 1,nclmax currentCohort => currentPatch%tallest cohortloop: do while(associated(currentCohort)) ! Only update the current cohort tree lai if lai of the above layers have been calculated - !if (currentCohort%canopy_layer .eq. cl) then + if (currentCohort%canopy_layer .eq. cl) then cl = currentCohort%canopy_layer ft = currentCohort%pft leaf_c = currentCohort%prt%GetState(leaf_organ,all_carbon_elements) @@ -2256,13 +2252,11 @@ subroutine UpdatePatchLAI(currentPatch, patch_lai) ! Calculate the total patch lai patch_lai = patch_lai + currentCohort%lai - - !end if - + end if currentCohort => currentCohort%shorter end do cohortloop - !end do canopyloop + end do canopyloop end subroutine UpdatePatchLAI From 7a4a95a19537546c329ac573678dd65f271cc2d4 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Sun, 20 Feb 2022 12:32:18 -0500 Subject: [PATCH 126/852] Incremental work towards getting dynamic root response c/n balance to be boundless --- biogeochem/EDCanopyStructureMod.F90 | 22 +- biogeochem/EDCohortDynamicsMod.F90 | 22 +- biogeochem/EDPatchDynamicsMod.F90 | 12 +- main/EDMainMod.F90 | 26 +- main/EDTypesMod.F90 | 3 + main/FatesHistoryInterfaceMod.F90 | 25 +- main/FatesInterfaceMod.F90 | 11 +- main/FatesRunningMeanMod.F90 | 15 +- parteh/PRTAllometricCNPMod.F90 | 406 ++++++++++++++++------------ parteh/PRTLossFluxesMod.F90 | 2 +- 10 files changed, 331 insertions(+), 213 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 130fd776f7..e2db556bdb 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -42,7 +42,7 @@ module EDCanopyStructureMod use PRTGenericMod, only : repro_organ use PRTGenericMod, only : struct_organ use PRTGenericMod, only : SetState - use FatesRunningMeanMod, only : ema_lpa + use FatesRunningMeanMod, only : ema_lpa, ema_60day ! CIME Globals use shr_log_mod , only : errMsg => shr_log_errMsg @@ -659,6 +659,14 @@ subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr,bc_in) allocate(copyc) + ! (keep as an example) + ! Initialize running means + !allocate(copyc%tveg_lpa) + allocate(copyc%l2fr_ema) + ! Note, no need to give a starter value here, + ! that will be taken care of in copy_cohort() + call copyc%l2fr_ema%InitRMean(ema_60day) + ! Initialize the PARTEH object and point to the ! correct boundary condition fields copyc%prt => null() @@ -669,12 +677,6 @@ subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr,bc_in) call InitHydrCohort(currentSite,copyc) endif - ! (keep as an example) - ! Initialize running means - !allocate(copyc%tveg_lpa) - !call copyc%tveg_lpa%InitRMean(ema_lpa, & - ! init_value=currentPatch%tveg_lpa%GetMean()) - call copy_cohort(currentCohort, copyc) newarea = currentCohort%c_area - cc_loss @@ -1118,6 +1120,12 @@ subroutine PromoteIntoLayer(currentSite,currentPatch,i_lyr) allocate(copyc) + + allocate(copyc%l2fr_ema) + ! Note, no need to give a starter value here, + ! that will be taken care of in copy_cohort() + call copyc%l2fr_ema%InitRMean(ema_60day) + ! Initialize the PARTEH object and point to the ! correct boundary condition fields copyc%prt => null() diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 4297375c13..7fe667ed33 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -18,7 +18,8 @@ module EDCohortDynamicsMod use FatesConstantsMod , only : fates_unset_r8 use FatesConstantsMod , only : nearzero use FatesConstantsMod , only : calloc_abs_error - use FatesRunningMeanMod , only : ema_lpa + use FatesConstantsMod , only : sec_per_day + use FatesRunningMeanMod , only : ema_lpa, ema_60day use FatesInterfaceTypesMod , only : hlm_days_per_year use FatesInterfaceTypesMod , only : nleafage use SFParamsMod , only : SF_val_CWD_frac @@ -93,11 +94,13 @@ module EDCohortDynamicsMod use PRTAllometricCNPMod, only : cnp_allom_prt_vartypes use PRTAllometricCNPMod, only : acnp_bc_in_id_pft, acnp_bc_in_id_ctrim use PRTAllometricCNPMod, only : acnp_bc_in_id_lstat, acnp_bc_inout_id_dbh + use PRTAllometricCNPMod, only : acnp_bc_in_id_l2fr_ema use PRTAllometricCNPMod, only : acnp_bc_inout_id_l2fr use PRTAllometricCNPMod, only : acnp_bc_inout_id_rmaint_def, acnp_bc_in_id_netdc use PRTAllometricCNPMod, only : acnp_bc_in_id_netdnh4, acnp_bc_in_id_netdno3, acnp_bc_in_id_netdp use PRTAllometricCNPMod, only : acnp_bc_out_id_cefflux, acnp_bc_out_id_nefflux use PRTAllometricCNPMod, only : acnp_bc_out_id_pefflux + use PRTAllometricCNPMod, only : fnrt_adapt_tscl use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) @@ -315,15 +318,17 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & patchptr%shortest => new_cohort endif - call InitPRTBoundaryConditions(new_cohort) - - ! Allocate running mean functions ! (Keeping as an example) !! allocate(new_cohort%tveg_lpa) !! call new_cohort%tveg_lpa%InitRMean(ema_lpa,init_value=patchptr%tveg_lpa%GetMean()) + allocate(new_cohort%l2fr_ema) + call new_cohort%l2fr_ema%InitRMean(ema_60day,init_value=new_cohort%l2fr,init_offset=fnrt_adapt_tscl*sec_per_day) + + call InitPRTBoundaryConditions(new_cohort) + ! Recuits do not have mortality rates, nor have they moved any ! carbon when they are created. They will bias our statistics @@ -426,7 +431,8 @@ subroutine InitPRTBoundaryConditions(new_cohort) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdnh4, bc_rval = new_cohort%daily_nh4_uptake) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdno3, bc_rval = new_cohort%daily_no3_uptake) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdp, bc_rval = new_cohort%daily_p_uptake) - + call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_l2fr_ema, bc_rval = new_cohort%l2fr_ema%l_mean) + call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_dbh,bc_rval = new_cohort%dbh) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_rmaint_def,bc_rval = new_cohort%resp_m_def) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_l2fr,bc_rval = new_cohort%l2fr) @@ -1011,7 +1017,8 @@ subroutine DeallocateCohort(currentCohort) ! (Keeping as an example) ! Remove the running mean structure ! deallocate(currentCohort%tveg_lpa) - + deallocate(currentCohort%l2fr_ema) + ! At this point, nothing should be pointing to current Cohort if (hlm_use_planthydro.eq.itrue) call DeallocateHydrCohort(currentCohort) @@ -1179,6 +1186,8 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) ! Running mean fuses based on number density fraction just ! like other variables !!call currentCohort%tveg_lpa%FuseRMean(nextc%tveg_lpa,currentCohort%n/newn) + + call currentCohort%l2fr_ema%FuseRMean(nextc%l2fr_ema,currentCohort%n/newn) ! new cohort age is weighted mean of two cohorts currentCohort%coage = & @@ -1823,6 +1832,7 @@ subroutine copy_cohort( currentCohort,copyc ) ! (Keeping as an example) ! Copy over running means ! call n%tveg_lpa%CopyFromDonor(o%tveg_lpa) + call n%l2fr_ema%CopyFromDonor(o%l2fr_ema) ! CARBON FLUXES n%gpp_acc_hold = o%gpp_acc_hold diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 5f89ba0b07..17f72aff8f 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -89,7 +89,7 @@ module EDPatchDynamicsMod use SFParamsMod, only : SF_VAL_CWD_FRAC use EDParamsMod, only : logging_event_code use EDParamsMod, only : logging_export_frac - use FatesRunningMeanMod, only : ema_24hr, fixed_24hr, ema_lpa + use FatesRunningMeanMod, only : ema_24hr, fixed_24hr, ema_lpa, ema_60day ! CIME globals use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) @@ -697,6 +697,11 @@ subroutine spawn_patches( currentSite, bc_in) allocate(nc) if(hlm_use_planthydro.eq.itrue) call InitHydrCohort(CurrentSite,nc) + + allocate(nc%l2fr_ema) + ! Note, no need to give a starter value here, + ! that will be taken care of in copy_cohort() + call nc%l2fr_ema%InitRMean(ema_60day) ! Initialize the PARTEH object and point to the ! correct boundary condition fields @@ -704,11 +709,6 @@ subroutine spawn_patches( currentSite, bc_in) call InitPRTObject(nc%prt) call InitPRTBoundaryConditions(nc) - ! (Keeping as an example) - ! Allocate running mean functions - !allocate(nc%tveg_lpa) - !call nc%tveg_lpa%InitRMean(ema_lpa,init_value=new_patch%tveg_lpa%GetMean()) - call zero_cohort(nc) ! nc is the new cohort that goes in the disturbed patch (new_patch)... currentCohort diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index d9ef3d07a0..3399c1122f 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -79,6 +79,7 @@ module EDMainMod use FatesPlantHydraulicsMod , only : UpdateSizeDepRhizHydProps use FatesPlantHydraulicsMod , only : AccumulateMortalityWaterStorage use FatesAllometryMod , only : h_allom,tree_sai,tree_lai + use FatesAllometryMod , only : bleaf use FatesPlantHydraulicsMod , only : UpdateSizeDepRhizHydStates use EDLoggingMortalityMod , only : IsItLoggingTime use EDPatchDynamicsMod , only : get_frac_site_primary @@ -335,23 +336,23 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) logical :: is_drought ! logical for if the plant (site) is in a drought state real(r8) :: delta_dbh ! correction for dbh real(r8) :: delta_hite ! correction for hite - + real(r8) :: actual_l2fr ! The fine-root/leaf carbon biomass ratio following allocation + ! note, this is not the target, but the actual + real(r8) :: leaf_c_target ! target leaf crabon [kg] real(r8) :: current_npp ! place holder for calculating npp each year in prescribed physiology mode !----------------------------------------------------------------------- real(r8) :: frac_site_primary - print*,"DYNAMICS" - call get_frac_site_primary(currentSite, frac_site_primary) ! Set a pointer to this sites carbon12 mass balance site_cmass => currentSite%mass_balance(element_pos(carbon12_element)) currentPatch => currentSite%youngest_patch - do while(associated(currentPatch)) - + !print*,"PATCH" + currentPatch%age = currentPatch%age + hlm_freq_day ! FIX(SPM,032414) valgrind 'Conditional jump or move depends on uninitialised value' if( currentPatch%age < 0._r8 )then @@ -443,9 +444,22 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! Growth and Allocation (PARTEH) ! ----------------------------------------------------------------------------- - call currentCohort%prt%DailyPRT() + + + ! Update the moving average of actual L2FR + call bleaf(currentCohort%dbh,currentCohort%pft,currentCohort%canopy_trim,leaf_c_target) + if(currentCohort%prt%GetState(leaf_organ, carbon12_element)/leaf_c_target>0.01_r8)then + actual_l2fr = currentCohort%prt%GetState(fnrt_organ, carbon12_element) / & + currentCohort%prt%GetState(leaf_organ, carbon12_element) + actual_l2fr = max(0.05_r8,min(10._r8,actual_l2fr)) + + call currentCohort%l2fr_ema%UpdateRMean(actual_l2fr) + end if + + call currentCohort%prt%DailyPRT() + ! Update the mass balance tracking for the daily nutrient uptake flux ! Then zero out the daily uptakes, they have been used ! ----------------------------------------------------------------------------- diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index da5198d842..041626447c 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -221,6 +221,9 @@ module EDTypesMod ! parameters, with a tendency driven by ! nutrient storage) + + class(rmean_type), pointer :: l2fr_ema ! Exponential moving average of the L2FR + ! VEGETATION STRUCTURE integer :: pft ! pft number real(r8) :: n ! number of individuals in cohort per 'area' (10000m2 default) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 15b7e479bc..34fa749dbb 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -184,6 +184,7 @@ module FatesHistoryInterfaceMod integer :: ih_totvegp_si integer :: ih_l2fr_si + integer :: ih_l2fr_ema_si integer :: ih_l2fr_scpf integer :: ih_l2fr_canopy_scpf integer :: ih_l2fr_understory_scpf @@ -1857,6 +1858,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_ncohorts_si => this%hvars(ih_ncohorts_si)%r81d, & hio_trimming_si => this%hvars(ih_trimming_si)%r81d, & hio_l2fr_si => this%hvars(ih_l2fr_si)%r81d, & + hio_l2fr_ema_si => this%hvars(ih_l2fr_ema_si)%r81d, & hio_l2fr_scpf => this%hvars(ih_l2fr_scpf)%r82d, & hio_l2fr_canopy_scpf => this%hvars(ih_l2fr_canopy_scpf)%r82d, & hio_l2fr_understory_scpf => this%hvars(ih_l2fr_understory_scpf)%r82d, & @@ -2400,6 +2402,9 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) ! These L2FR diagnostics are weighted by fineroot carbon biomass hio_l2fr_si(io_si) = hio_l2fr_si(io_si) + ccohort%n*fnrt_m/m2_per_ha*ccohort%l2fr + + + hio_l2fr_ema_si(io_si) = hio_l2fr_ema_si(io_si) + ccohort%n*fnrt_m/m2_per_ha*ccohort%l2fr_ema%GetMean() hio_l2fr_scpf(io_si,i_scpf) = & hio_l2fr_scpf(io_si,i_scpf) + ccohort%n*fnrt_m/m2_per_ha*ccohort%l2fr @@ -3045,7 +3050,8 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) ! Normalize the l2fr value by total biomass hio_l2fr_si(io_si) = hio_l2fr_si(io_si)/this%hvars(ih_fnrtc_si)%r81d(io_si) - + hio_l2fr_ema_si(io_si) = hio_l2fr_ema_si(io_si)/this%hvars(ih_fnrtc_si)%r81d(io_si) + ! divide so-far-just-summed but to-be-averaged patch-age-class variables by patch-age-class area to get mean values do ipa2 = 1, nlevage @@ -3226,7 +3232,9 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) (sum(litt%leaf_fines_frag(:)) + & sum(litt%root_fines_frag(:,:)) + & sum(litt%ag_cwd_frag(:)) + & - sum(litt%bg_cwd_frag(:,:))) * & + sum(litt%bg_cwd_frag(:,:)) + & + sum(litt%seed_decay(:)) + & + sum(litt%seed_germ_decay(:))) * & area_frac * days_per_sec ! Sum up total seed bank (germinated and ungerminated) @@ -4502,12 +4510,19 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_trimming_si) - call this%set_history_var(vname='FATES_L2FR', units='kg kg-1', & + call this%set_history_var(vname='FATES_L2FR', units='kg kg-1', & long='The leaf to fineroot biomass multiplier for target allometry', & use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_l2fr_si) + call this%set_history_var(vname='FATES_L2FR_EMA', units='kg kg-1', & + long='Moving average of the leaf to fineroot biomass multiplier for target allometry', & + use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_l2fr_ema_si) + + call this%set_history_var(vname='FATES_L2FR_SZPF', units='kg kg-1', & long='The leaf to fineroot biomass multiplier for target allometry', & use_default='active', & @@ -4906,7 +4921,7 @@ subroutine define_history_vars(this, initialize_variables) index = ih_litter_in_si) call this%set_history_var(vname='FATES_LITTER_OUT', units='kg m-2 s-1', & - long='litter flux out in kg carbon per m2 per second', & + long='litter flux out in kg carbon (fragmentation AND seed decay)', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_litter_out_si) @@ -4930,7 +4945,7 @@ subroutine define_history_vars(this, initialize_variables) index = ih_litter_in_elem) call this%set_history_var(vname='FATES_LITTER_OUT_EL', units='kg m-2 s-1', & - long='litter flux out (fragmentation only) in kg element per m2 per second', & + long='litter flux out (fragmentation and seed decay) in kg element', & use_default='active', avgflag='A', vtype=site_elem_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_litter_out_elem) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 947dabf179..2ad860ef47 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -80,10 +80,11 @@ module FatesInterfaceMod use FatesRunningMeanMod , only : ema_24hr use FatesRunningMeanMod , only : fixed_24hr use FatesRunningMeanMod , only : ema_lpa + use FatesRunningMeanMod , only : ema_60day use FatesRunningMeanMod , only : moving_ema_window use FatesRunningMeanMod , only : fixed_window use FatesHistoryInterfaceMod , only : fates_hist - + use PRTAllometricCNPMod , only : fnrt_adapt_tscl ! CIME Globals use shr_log_mod , only : errMsg => shr_log_errMsg @@ -926,7 +927,13 @@ subroutine InitTimeAveragingGlobals() allocate(ema_lpa) call ema_lpa%define(photo_temp_acclim_timescale*sec_per_day, & hlm_stepsize,moving_ema_window) + allocate(ema_60day) + call ema_60day%define(fnrt_adapt_tscl*sec_per_day,sec_per_day,moving_ema_window) + !class(rmean_arr_type), pointer :: ema_fnrt_tscale(:) + !rmean_arr_type + + return end subroutine InitTimeAveragingGlobals @@ -1909,7 +1916,7 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) call cpatch%tveg24%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) call cpatch%tveg_lpa%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) - ! (Keeping as an example) + !ccohort => cpatch%tallest !do while (associated(ccohort)) ! call ccohort%tveg_lpa%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) diff --git a/main/FatesRunningMeanMod.F90 b/main/FatesRunningMeanMod.F90 index 7fa3bfd7cc..f7887f3fb4 100644 --- a/main/FatesRunningMeanMod.F90 +++ b/main/FatesRunningMeanMod.F90 @@ -91,6 +91,15 @@ module FatesRunningMeanMod class(rmean_def_type), public, pointer :: ema_24hr ! Exponential moving average - 24hr window class(rmean_def_type), public, pointer :: fixed_24hr ! Fixed, 24-hour window class(rmean_def_type), public, pointer :: ema_lpa ! Exponential moving average - leaf photo acclimation + class(rmean_def_type), public, pointer :: ema_60day ! Exponential moving average, 60 day + ! Updated daily + + + ! If we want to have different running mean specs based on + ! pft or other types of constants + type, public :: rmean_arr_type + class(rmean_def_type), pointer :: p + end type rmean_arr_type contains @@ -197,7 +206,11 @@ subroutine InitRMean(this,rmean_def,init_value,init_offset) if(present(init_value))then this%c_mean = init_value this%l_mean = init_value - this%c_index = 1 + if(present(init_offset))then + this%c_index = min(nint(init_offset/rmean_def%up_period),rmean_def%n_mem) + else + this%c_index = 1 + end if else this%c_mean = nan this%l_mean = nan diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 24849e40bc..75aac5c285 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -146,16 +146,17 @@ module PRTAllometricCNPMod ! Input only Boundary Indices (These are public) ! ------------------------------------------------------------------------------------- - integer, public, parameter :: acnp_bc_in_id_pft = 1 ! Index for the PFT input BC - integer, public, parameter :: acnp_bc_in_id_ctrim = 2 ! Index for the canopy trim function - integer, public, parameter :: acnp_bc_in_id_lstat = 3 ! phenology status logical - integer, public, parameter :: acnp_bc_in_id_netdc = 4 ! Index for the net daily C input BC - integer, public, parameter :: acnp_bc_in_id_netdnh4 = 5 ! Index for the net daily NH4 input BC - integer, public, parameter :: acnp_bc_in_id_netdno3 = 6 ! Index for the net daily NO3 input BC - integer, public, parameter :: acnp_bc_in_id_netdp = 7 ! Index for the net daily P input BC + integer, public, parameter :: acnp_bc_in_id_pft = 1 ! Index for the PFT input BC + integer, public, parameter :: acnp_bc_in_id_ctrim = 2 ! Index for the canopy trim function + integer, public, parameter :: acnp_bc_in_id_lstat = 3 ! phenology status logical + integer, public, parameter :: acnp_bc_in_id_netdc = 4 ! Index for the net daily C input BC + integer, public, parameter :: acnp_bc_in_id_netdnh4 = 5 ! Index for the net daily NH4 input BC + integer, public, parameter :: acnp_bc_in_id_netdno3 = 6 ! Index for the net daily NO3 input BC + integer, public, parameter :: acnp_bc_in_id_netdp = 7 ! Index for the net daily P input BC + integer, public, parameter :: acnp_bc_in_id_l2fr_ema = 8 ! Index for the moving average ema ! 0=leaf off, 1=leaf on - integer, parameter :: num_bc_in = 7 + integer, parameter :: num_bc_in = 8 ! ------------------------------------------------------------------------------------- ! Output Boundary Indices (These are public) @@ -174,11 +175,6 @@ module PRTAllometricCNPMod integer,private, parameter :: intgr_parm_l2fr = 3 integer,private, parameter :: num_intgr_parm = 3 - - real(r8), parameter :: min_stf_growth = 0.8_r8 ! Plants are only allowed to increase in stature - ! if they have more than 80% of their stores full - - ! ------------------------------------------------------------------------------------- ! Define the size of the coorindate vector. For this hypothesis, there is only ! one pool per each species x organ combination, except for leaves (WHICH HAVE AGE) @@ -208,6 +204,12 @@ module PRTAllometricCNPMod integer, parameter :: regulate_logi = 2 integer, parameter :: regulate_CN_logi = 3 integer, parameter :: regulate_CN_dfdd = 4 + integer, parameter :: regulate_CN_ema = 5 + + + !real(r8), public, parameter :: fnrt_adapt_tscl = 365._r8 ! Fine-root adaptation timescale (days) + + real(r8), public, parameter :: fnrt_adapt_tscl = 30._r8 ! Fine-root adaptation timescale (days) ! Array of pointers are difficult in F90 ! This structure is a necessary intermediate @@ -351,6 +353,7 @@ subroutine DailyPRTAllometricCNP(this) real(r8) :: n_gain ! Daily nitrogen uptake through fine-roots [kgN] real(r8) :: p_gain ! Daily phosphorus uptake through fine-roots [kgN] real(r8) :: canopy_trim ! The canopy trimming function [0-1] + real(r8) :: l2fr_ema ! Mean (EMA) l2fr ! Pointers to output bcs real(r8),pointer :: c_efflux ! Total plant efflux of carbon (kgC) @@ -397,6 +400,19 @@ subroutine DailyPRTAllometricCNP(this) real(r8) :: target_n,target_p real(r8) :: sum_c ! error checking sum + + + ! =================================================================================== + ! Step 1: Evaluate nutrient storage in the plant. Depending on how low + ! these stores are, we will move proportionally more or less of the daily carbon + ! gain to increase the target fine-root biomass, fill up to target + ! and then attempt to get them up to stoichiometry targets. + ! =================================================================================== + + ! This routine actually just updates the l2fr variable + call this%CNPAdjustFRootTargets() + + ! integrator variables ! Copy the input only boundary conditions into readable local variables @@ -411,7 +427,8 @@ subroutine DailyPRTAllometricCNP(this) p_gain = this%bc_in(acnp_bc_in_id_netdp)%rval; p_gain0 = p_gain canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival - + + ! Output only boundary conditions c_efflux => this%bc_out(acnp_bc_out_id_cefflux)%rval; c_efflux = 0._r8 n_efflux => this%bc_out(acnp_bc_out_id_nefflux)%rval; n_efflux = 0._r8 @@ -473,25 +490,16 @@ subroutine DailyPRTAllometricCNP(this) end do - ! =================================================================================== - ! Step 1: Evaluate nutrient storage in the plant. Depending on how low - ! these stores are, we will move proportionally more or less of the daily carbon - ! gain to increase the target fine-root biomass, fill up to target - ! and then attempt to get them up to stoichiometry targets. - ! =================================================================================== - - ! This routine actually just updates the l2fr variable - call this%CNPAdjustFRootTargets() + call bfineroot(dbh,ipft,canopy_trim, l2fr, target_c(fnrt_id), target_dcdd(fnrt_id)) ! =================================================================================== ! Step 0. Transfer all stored nutrient into the daily uptake pool. - ! Storage in nutrients does not need to have a buffer like - ! carbon does, so we simply use it when we want it, and then - ! anything left at the end is added back (CNPAllocateRemainder()) ! =================================================================================== - + !i_var = prt_global%sp_organ_map(store_organ,carbon12_element) + !c_gain = c_gain + max(0._r8,sum(this%variables(i_var)%val(:))-target_c(store_id)) + !this%variables(i_var)%val(1) = this%variables(i_var)%val(1)-max(0._r8,sum(this%variables(i_var)%val(:))-target_c(store_id)) i_var = prt_global%sp_organ_map(store_organ,nitrogen_element) n_gain = n_gain + sum(this%variables(i_var)%val(:)) @@ -623,8 +631,8 @@ subroutine DailyPRTAllometricCNP(this) end if end if - target_n = this%GetNutrientTarget(nitrogen_element,store_organ,stoich_max) - target_p = this%GetNutrientTarget(phosphorus_element,store_organ,stoich_max) + !target_n = this%GetNutrientTarget(nitrogen_element,store_organ,stoich_max) + !target_p = this%GetNutrientTarget(phosphorus_element,store_organ,stoich_max) deallocate(state_c) deallocate(state_n) @@ -642,8 +650,11 @@ subroutine CNPAdjustFRootTargets(this) integer :: ipft ! PFT index real(r8), pointer :: dbh real(r8) :: canopy_trim + real(r8) :: l2fr_ema ! Moving average L2FR (EMA) + real(r8) :: l2fr_actual real(r8) :: fnrt_c_target ! Target fineroot C before we change l2fr + real(r8) :: leaf_c_target real(r8) :: n_regulator ! Nitrogen storage regulation function scaler real(r8) :: p_regulator ! Phosphorus storage regulation function scaler real(r8) :: np_regulator ! Combined NP storage regulation function scaler @@ -651,13 +662,18 @@ subroutine CNPAdjustFRootTargets(this) ! remain after a day of root turnover without ! replacement real(r8) :: fnrt_frac ! fine-root's current fraction of the target - - integer, parameter :: regulate_type = regulate_CN_logi !regulate_CN_dfdd + real(r8) :: loss_flux_c + real(r8) :: loss_flux_n + real(r8) :: loss_flux_p + real(r8) :: fnrt_c_above_target + + integer, parameter :: regulate_type = regulate_CN_ema ipft = this%bc_in(acnp_bc_in_id_pft)%ival l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval + l2fr_ema = this%bc_in(acnp_bc_in_id_l2fr_ema)%rval associate( l2fr_min => prt_params%allom_l2fr_min(ipft), & l2fr_max => prt_params%allom_l2fr_max(ipft)) @@ -675,7 +691,23 @@ subroutine CNPAdjustFRootTargets(this) if(regulate_type == regulate_CN_logi)then - l2fr = l2fr_min + max(0._r8,min(1.0_r8,np_regulator))*(l2fr_max-l2fr_min) + l2fr = l2fr_min + max(0._r8,min(1.0_r8,np_regulator))*(l2fr_max-l2fr_min) + + + elseif(regulate_type == regulate_CN_ema) then + + ! To prevent the target l2fr from diverging too far from the + ! actual l2fr, create some constraints. + l2fr_actual = this%GetState(fnrt_organ, carbon12_element)/this%GetState(leaf_organ, carbon12_element) + + ! Only update L2FR if some leaves are out + call bleaf(dbh,ipft,canopy_trim,leaf_c_target) + if(this%GetState(leaf_organ, carbon12_element)/leaf_c_target>0.5_r8) then + l2fr = l2fr_ema * np_regulator + !l2fr = l2fr_actual * np_regulator + !l2fr = l2fr * np_regulator + end if + elseif(regulate_type == regulate_CN_dfdd)then @@ -706,33 +738,40 @@ subroutine CNPAdjustFRootTargets(this) ! equilibrium root mass more quickly. (might be unnecessary given ! the growth caps prior to this...?) - - - !print*,dbh,fnrt_frac,l2fr,min(max(np_regulator,1._r8-turnfrac),1._r8+turnfrac) - l2fr = l2fr * min(max(np_regulator,1._r8-2._r8*turnfrac),1._r8+2._r8*turnfrac) end if - - ! Find the updated target fineroot biomass - ! call bfineroot(dbh,ipft,canopy_trim, l2fr, target_fnrt) + call bfineroot(dbh,ipft,canopy_trim, l2fr, fnrt_c_target) + + fnrt_c_above_target = max(0._r8,this%GetState(fnrt_organ, carbon12_element) - fnrt_c_target) - ! Consider removing biomass immediately too... - ! we could send it to the turnover flux - ! c_to_froot = max(0._r8,target_fnrt - state_c(fnrt_id)%ptr) + ! Allow no reabsorption? (any reabsorption of nutrients will further push the N/C or P/C imbalance + ! and if we are dropping roots, its because we had excess nutrient compared to carbon anyway + ! Stop the positive feedback - ! Update the actual carbon - ! state_c(fnrt_id)%ptr = state_c(fnrt_id)%ptr + c_to_froot + ! Since this is really a stop gap, we want to allow allocation to handle most of the + ! fine-root adaption, and only have this kick in when the target starts to drift significantly + ! from the actual - ! Push nitrogen into fineroots to get to stoichiometry - ! call ProportionalNutrAllocation(state_n, deficit_n, & - ! n_gain, nitrogen_element, fnrt_id) + loss_flux_c = 0._r8 + + !loss_flux_c = fnrt_c_above_target*max(fnrt_c_above_target/fnrt_c_target-0.1_r8,0._r8) + + + loss_flux_n = loss_flux_c*this%variables(fnrt_n_id)%val(1)/this%variables(fnrt_c_id)%val(1) + this%variables(fnrt_n_id)%val(1) = this%variables(fnrt_n_id)%val(1) - loss_flux_n + this%variables(fnrt_n_id)%turnover(1) = this%variables(fnrt_n_id)%turnover(1) + loss_flux_p + + loss_flux_p = loss_flux_c*this%variables(fnrt_p_id)%val(1)/this%variables(fnrt_c_id)%val(1) + this%variables(fnrt_p_id)%val(1) = this%variables(fnrt_p_id)%val(1) - loss_flux_p + this%variables(fnrt_p_id)%turnover(1) = this%variables(fnrt_p_id)%turnover(1) + loss_flux_p + + this%variables(fnrt_c_id)%val(1) = this%variables(fnrt_c_id)%val(1) - loss_flux_c + this%variables(fnrt_c_id)%turnover(1) = this%variables(fnrt_c_id)%turnover(1) + loss_flux_c - ! Push phos into fineroots to get to stoichiometry - ! call ProportionalNutrAllocation(state_p, deficit_p, & - ! p_gain, phosphorus_element, fnrt_id) + end associate @@ -775,7 +814,6 @@ subroutine CNPPrioritizedReplacement(this, & real(r8) :: canopy_trim ! trim factor for maximum leaf biomass real(r8) :: target_n ! Target mass of N for a given organ [kg] real(r8) :: target_p ! Target mass of P for a given organ [kg] - real(r8) :: c_gain0 integer :: priority_code ! Index for priority level of each organ real(r8) :: sum_c_demand ! Carbon demanded to bring tissues up to allometry (kg) real(r8) :: sum_n_deficit ! The nitrogen deficit of all pools for given priority level (kg) @@ -798,9 +836,6 @@ subroutine CNPPrioritizedReplacement(this, & ! the total number organs plus 1, which allows ! each organ to have its own level, and ignore ! the specialized priority 1 - - - c_gain0 = c_gain leaf_status = this%bc_in(acnp_bc_in_id_lstat)%ival ipft = this%bc_in(acnp_bc_in_id_pft)%ival @@ -874,14 +909,8 @@ subroutine CNPPrioritizedReplacement(this, & i_cvar = prt_global%sp_organ_map(organ_list(i),carbon12_element) - if(reproduce_conly) then - c_flux = min(prt_params%leaf_stor_priority(ipft)*sum(this%variables(i_cvar)%turnover(:)), & - max(0.0_r8, (state_c(store_id)%ptr+c_gain)* & - (prt_params%leaf_stor_priority(ipft)*sum(this%variables(i_cvar)%turnover(:))/sum_c_demand) )) - else - c_flux = sum_c_flux*(prt_params%leaf_stor_priority(ipft) * & - sum(this%variables(i_cvar)%turnover(:))/sum_c_demand) - end if + c_flux = sum_c_flux*(prt_params%leaf_stor_priority(ipft) * & + sum(this%variables(i_cvar)%turnover(:))/sum_c_demand) ! Add carbon to the pool state_c(i)%ptr = state_c(i)%ptr + c_flux @@ -892,7 +921,7 @@ subroutine CNPPrioritizedReplacement(this, & end do end if - ! Determine nutrient demand and make tansfers (ignore replacing storage) + ! Determine nutrient demand and make tansfers do i = 1, n_curpri_org i_org = curpri_org(i) @@ -900,19 +929,13 @@ subroutine CNPPrioritizedReplacement(this, & ! Update the nitrogen deficits ! Note that the nitrogen target is tied to the stoichiometry of thegrowing pool only - if(organ_list(i_org).ne.store_organ)then - - target_n = this%GetNutrientTarget(nitrogen_element,organ_list(i_org),stoich_growth_min) - deficit_n(i_org) = max(0.0_r8, target_n - state_n(i_org)%ptr ) - - ! Update the phosphorus deficits (which are based off of carbon actual..) - ! Note that the phsophorus target is tied to the stoichiometry of thegrowing pool only (also) - target_p = this%GetNutrientTarget(phosphorus_element,organ_list(i_org),stoich_growth_min) - deficit_p(i_org) = max(0.0_r8, target_p - state_p(i_org)%ptr ) - else - deficit_n(i_org) = 0._r8 - deficit_p(i_org) = 0._r8 - end if + target_n = this%GetNutrientTarget(nitrogen_element,organ_list(i_org),stoich_growth_min) + deficit_n(i_org) = max(0.0_r8, target_n - state_n(i_org)%ptr ) + + ! Update the phosphorus deficits (which are based off of carbon actual..) + ! Note that the phsophorus target is tied to the stoichiometry of thegrowing pool only (also) + target_p = this%GetNutrientTarget(phosphorus_element,organ_list(i_org),stoich_growth_min) + deficit_p(i_org) = max(0.0_r8, target_p - state_p(i_org)%ptr ) end do @@ -936,8 +959,8 @@ subroutine CNPPrioritizedReplacement(this, & ! Storage will have to pay for any negative gains store_c_flux = -c_gain - c_gain = c_gain + store_c_flux - state_c(store_id)%ptr = state_c(store_id)%ptr - store_c_flux + c_gain = c_gain + store_c_flux + state_c(store_id)%ptr = state_c(store_id)%ptr - store_c_flux else @@ -949,8 +972,6 @@ subroutine CNPPrioritizedReplacement(this, & store_demand = max(c_gain*(exp(-1.*store_target_fraction**4._r8) - exp( -1.0_r8 )),0._r8) - - ! The flux is the (positive) minimum of all three store_c_flux = min(store_below_target,store_demand) @@ -996,7 +1017,7 @@ subroutine CNPPrioritizedReplacement(this, & ! (this prevents accidental re-flushing on the day they drop) if((leaf_status.eq.leaves_off) .and. (organ_list(ii).eq.leaf_organ)) cycle - ! 1 is the highest priority code possible + if( priority_code == i_pri ) then deficit_c(ii) = max(0._r8,this%GetDeficit(carbon12_element,organ_list(ii),target_c(ii))) i = i + 1 @@ -1010,9 +1031,6 @@ subroutine CNPPrioritizedReplacement(this, & n_curpri_org = i - ! The total amount of carbon needed to be replaced - ! is the deficit and the growth respiration needed - ! accomany replacing that deficit sum_c_demand = 0._r8 do i=1,n_curpri_org @@ -1028,12 +1046,7 @@ subroutine CNPPrioritizedReplacement(this, & i_org = curpri_org(i) - if(reproduce_conly) then - c_flux = min(deficit_c(i_org), & - c_gain*(deficit_c(i_org)/sum_c_demand)) - else - c_flux = sum_c_flux*deficit_c(i_org)/sum_c_demand - end if + c_flux = sum_c_flux*deficit_c(i_org)/sum_c_demand ! Update the carbon pool state_c(i_org)%ptr = state_c(i_org)%ptr + c_flux @@ -1047,58 +1060,24 @@ subroutine CNPPrioritizedReplacement(this, & end do end if - - sum_c_demand = 0._r8 - do i=1,n_curpri_org - i_org = curpri_org(i) - deficit_c(i_org) = max(0._r8,this%GetDeficit(carbon12_element,organ_list(i_org),target_c(i_org))) - sum_c_demand = sum_c_demand + deficit_c(i_org) - end do - - sum_c_flux = min(c_gain, sum_c_demand) - - ! Transfer carbon into pools if there is any (second round to match C-only) - if (sum_c_flux>nearzero) then - do i = 1, n_curpri_org - - i_org = curpri_org(i) - - c_flux = sum_c_flux*deficit_c(i_org)/sum_c_demand - - ! Update the carbon pool - state_c(i_org)%ptr = state_c(i_org)%ptr + c_flux - - ! Update carbon pools deficit - deficit_c(i_org) = max(0._r8,deficit_c(i_org) - c_flux) - - ! Reduce the carbon gain - c_gain = c_gain - c_flux - - end do - end if - ! Determine nutrient demand and make tansfers do i = 1, n_curpri_org i_org = curpri_org(i) -! if(organ_list(i_org).ne.store_organ)then - ! Update the nitrogen deficits - ! Note that the nitrogen target is tied to the stoichiometry of thegrowing pool only - target_n = this%GetNutrientTarget(nitrogen_element,organ_list(i_org),stoich_growth_min) - deficit_n(i_org) = max(0.0_r8, target_n - state_n(i_org)%ptr ) + + ! Update the nitrogen deficits + ! Note that the nitrogen target is tied to the stoichiometry of thegrowing pool only + target_n = this%GetNutrientTarget(nitrogen_element,organ_list(i_org),stoich_growth_min) + deficit_n(i_org) = max(0.0_r8, target_n - state_n(i_org)%ptr ) - ! Update the phosphorus deficits (which are based off of carbon actual..) - ! Note that the phsophorus target is tied to the stoichiometry of thegrowing pool only (also) - target_p = this%GetNutrientTarget(phosphorus_element,organ_list(i_org),stoich_growth_min) - deficit_p(i_org) = max(0.0_r8, target_p - state_p(i_org)%ptr ) -! else -! deficit_n(i_org) = 0._r8 -! deficit_p(i_org) = 0._r8 -! end if + ! Update the phosphorus deficits (which are based off of carbon actual..) + ! Note that the phsophorus target is tied to the stoichiometry of thegrowing pool only (also) + target_p = this%GetNutrientTarget(phosphorus_element,organ_list(i_org),stoich_growth_min) + deficit_p(i_org) = max(0.0_r8, target_p - state_p(i_org)%ptr ) + end do - ! Allocate nutrients at this priority level - ! Nitrogen + ! Allocate nutrients at this priority level Nitrogen call ProportionalNutrAllocation(state_n, deficit_n, & n_gain, nitrogen_element, curpri_org(1:n_curpri_org)) @@ -1159,8 +1138,6 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & real(r8) :: sum_c_flux ! Sum of the carbon allocated, as reported ! by the ODE solver. [kg] real(r8) :: np_limit - real(r8) :: n_stf ! nitrogen storage target fraction (stf) [-] - real(r8) :: p_stf ! phosphorus storage target fraction (stf) [-] real(r8) :: n_match real(r8) :: p_match real(r8) :: c_flux_adj ! Adjustment to total carbon flux during stature growth @@ -1239,12 +1216,6 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & ! signaled a drop. If this is the case, we can't grow stature ! cause that would force the leaves back on, so just leave. - - target_n = this%GetNutrientTarget(nitrogen_element,store_organ,stoich_growth_min) - n_stf = max(state_n(store_id)%ptr/target_n,0._r8) - - target_p = this%GetNutrientTarget(phosphorus_element,store_organ,stoich_growth_min) - p_stf = max(state_p(store_id)%ptr/target_p,0._r8) if( c_gain <= calloc_abs_error .or. & leaf_status.eq.leaves_off .or. & @@ -1688,6 +1659,17 @@ subroutine CNPAllocateRemainder(this,c_gain, n_gain, p_gain, & if(c_gain>calloc_abs_error) then +! select(c_overlow_method) +! case(store_c_overflow) + +! case(efflux_c_overflow) + +! case(burn_c_overflow) + +! end if + + + if(force_store_c_overflow)then total_c_flux = c_gain @@ -1768,7 +1750,6 @@ function GetDeficit(this,element_id,organ_id,target_m) result(deficit_m) return end function GetDeficit - ! ===================================================================================== @@ -1833,7 +1814,7 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe ! Hard-code the growth minimum storage stoichiometry to 75% of maximum if( stoich_mode == stoich_growth_min ) then - target_m = target_m*0.75_r8 + target_m = target_m*0.25_r8 end if elseif(organ_id == repro_organ) then @@ -2219,18 +2200,25 @@ subroutine StorageRegulator(this,element_id,regulate_type,c_scalar) integer :: icode ! real variable checking code real(r8) :: store_x integer :: i_var - real(r8) :: c_eq_offset ! This shifts the center-point - ! of the N:C or P:C storage equlibrium - ! by multiplying the C term. If its less than 1 it - ! shifts left and great than one it shifts right. - ! It should shift left to help mitigate wasted N and P - ! storage overflow + real(r8), parameter :: c_eq_offset = 0.95 ! This shifts the center-point + ! of the N:C or P:C storage equlibrium + ! by multiplying the C term. If its less than 1 it + ! shifts left and great than one it shifts right. + ! It should shift left to help mitigate wasted N and P + ! storage overflow ! For N/C logistic real(r8) :: logi_k ! logistic function k real(r8) :: store_x0 ! storage fraction inflection point real(r8) :: logi_min ! minimum cn_scalar for logistic - + real(r8) :: l2fr_delta_max + real(r8) :: l2fr_delta_min + real(r8) :: l2fr_actual + real(r8) :: leaf_c_target + real(r8) :: log_nc_frac + real(r8) :: store_c_frac + real(r8) :: c_gain + real(r8) :: target_fnrt_c ! This is the storage fraction where downregulation starts if using ! a linear function @@ -2239,19 +2227,26 @@ subroutine StorageRegulator(this,element_id,regulate_type,c_scalar) real(r8), parameter :: c_max = 1.0_r8 ! Maximum allowable result of the function real(r8), parameter :: c_min = 0.0_r8 ! Minimum allowable result of the function + ! This fraction governs + ! how much carbon from daily gains + storage overflow, is allowed to + ! be spent on growing out roots. This inludes getting roots + ! back on allometry before growing out + + real(r8), parameter :: max_l2fr_cgain_frac = 0.5_r8 + associate(dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval, & canopy_trim => this%bc_in(acnp_bc_in_id_ctrim)%rval, & - ipft => this%bc_in(acnp_bc_in_id_pft)%ival) + ipft => this%bc_in(acnp_bc_in_id_pft)%ival, & + l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval, & + l2fr_ema => this%bc_in(acnp_bc_in_id_l2fr_ema)%rval) - store_max = this%GetNutrientTarget(element_id,store_organ,stoich_growth_min) + + store_max = this%GetNutrientTarget(element_id,store_organ,stoich_max) ! Storage fractions could more than the target, depending on the ! hypothesis and functions involved, but should typically be 0-1 ! The cap of 2 is for numerics and preventing weird math - store_frac = min(2.0_r8,this%GetState(store_organ, element_id)/store_max) - - i_var = prt_global%sp_organ_map(store_organ,element_id ) - store_x = sum(this%variables(i_var)%val(:)) + store_frac = max(0.01_r8,min(1.0_r8,this%GetState(store_organ, element_id)/store_max)) if(regulate_type == regulate_linear) then @@ -2278,24 +2273,84 @@ subroutine StorageRegulator(this,element_id,regulate_type,c_scalar) ! call endrun(msg=errMsg(sourcefile, __LINE__)) !endif - elseif(regulate_type == regulate_CN_logi) then - + elseif(regulate_type == regulate_CN_logi .or. regulate_type == regulate_CN_ema) then + logi_k = 2.0_r8 store_x0 = 0.0_r8 logi_min = 0.0_r8 - - store_c = this%GetState(store_organ, carbon12_element) - call bstore_allom(dbh,ipft,canopy_trim,store_c_max) - - ! Fraction of N per fraction of C - ! If this is greater than 1, then we have more N in storage than - ! we have C, so we downregulate. If this is less than 1, then - ! we have less N in storage than we have C, so up-regulate - - store_frac = log(max(0.01_r8,store_frac) / max(0.01_r8,(store_c/store_c_max))) - c_scalar = max(0._r8,min(1._r8,logi_min + (1._r8-logi_min)/(1.0 + exp(logi_k*(store_frac-store_x0))))) + ! Only update L2FR if some leaves are out + call bleaf(dbh,ipft,canopy_trim,leaf_c_target) + if(this%GetState(leaf_organ, carbon12_element)/leaf_c_target>0.01_r8) then + store_max = this%GetNutrientTarget(element_id,store_organ,stoich_max) + + ! Storage fractions could be more than the target, depending on the + ! hypothesis and functions involved, but should typically be 0-1 + ! The cap of 2 is for numerics and preventing weird math + + store_frac = max(0.01_r8,min(2.0_r8,this%GetState(store_organ, element_id)/store_max)) + + + call bstore_allom(dbh,ipft,canopy_trim,store_c_max) + + ! Since we don't dump storage carbon + ! these stores can actually get pretty large, so the cap of 10x is numerically + ! feasable, and should also minimize stress on the logistic function + store_c_frac = max(0.01_r8,min(10.0_r8,c_eq_offset*(this%GetState(store_organ, carbon12_element)/store_c_max))) + + + ! ----------------------------------------------------------------------------- + ! To decide the upper limit on expanding root growth, we perform a carbon + ! balance. Note that if we are growing roots out more, than we have proportionaly + ! more C compared to other resources. Specifically, we want to limit root growth + ! such that allocation to roots can't exceed a certain fraction of the daily + ! available carbon. This fraction is "max_l2fr_cgain_frac". + ! Additional notes. When calculating the "allocation to roots", we consider + ! both the carbon necessary to get the roots "on allometry" plux the carbon + ! necessary to expand them. + ! + ! (l2fr_delta_max*target_fnrt_c + target_fnrt_c-actual_fnrt_c )/c_gain + ! < max_l2fr_cgain_frac + ! + ! ------------------------------------------------------------------------------ + + call bfineroot(dbh,ipft,canopy_trim, l2fr, target_fnrt_c) + + ! If there is overflow storage, add this to the gain + c_gain = this%bc_in(acnp_bc_in_id_netdc)%rval + & + max(0._r8,this%GetState(store_organ, carbon12_element)-store_c_max) + + l2fr_delta_max = max(0._r8, & + c_gain*max_l2fr_cgain_frac - & + target_fnrt_c-this%GetState(fnrt_organ, carbon12_element))/target_fnrt_c + + ! Since we use l2fr_ema as the basis, we need to transform this + ! l2fr_actual*(1+l2fr_delta_max) = l2fr_ema*(1+l2fr_delta_eff) + + l2fr_actual = this%GetState(fnrt_organ, carbon12_element) / & + this%GetState(leaf_organ, carbon12_element) + ! RE + !l2fr_delta_max = l2fr_actual*(1+l2fr_delta_max)/l2fr_ema - 1.0_r8 + l2fr_delta_min = (years_per_day / prt_params%root_long(ipft)) + + log_nc_frac = log( store_frac / store_c_frac ) + + ! This is a logistic between -1 and 1 + c_scalar = 2._r8*max(0._r8, & + min(1._r8,logi_min + (1._r8-logi_min)/(1._r8 + exp(logi_k*(log_nc_frac-store_x0)))))-1.0_r8 + + if(c_scalar>0.0_r8)then + c_scalar = 1._r8+c_scalar*l2fr_delta_max + else + c_scalar = 1._r8+c_scalar*l2fr_delta_min + end if + + else + c_scalar = 1._r8 + end if + + elseif(regulate_type == regulate_CN_dfdd) then store_c = this%GetState(store_organ, carbon12_element) @@ -2306,14 +2361,7 @@ subroutine StorageRegulator(this,element_id,regulate_type,c_scalar) ! we have C, so we downregulate. If this is less than 1, then ! we have less N in storage than we have C, so up-regulate - ! Note also, we do not allow the plants to dump C - ! but we do allow them to exude either P or N. Because of this - ! we shift our equilibrium point from a ratio of 1:1 to something - ! with a slightly lower C fraction equilibrium (ie > 1) - ! This will reduce N and P uptake inefficiencies by reducing - ! storage overflow and dumping. - - c_eq_offset = 0.75 + store_frac = max(0.01_r8,store_frac) / max(0.01_r8,c_eq_offset*(store_c/store_c_max)) diff --git a/parteh/PRTLossFluxesMod.F90 b/parteh/PRTLossFluxesMod.F90 index 13b09b2e37..b95e074f2d 100644 --- a/parteh/PRTLossFluxesMod.F90 +++ b/parteh/PRTLossFluxesMod.F90 @@ -538,7 +538,7 @@ subroutine DeciduousTurnoverSimpleRetranslocation(prt,ipft,organ_id,mass_fractio ! 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 + ! The mass that is leaving the plant turnover_mass = (1.0_r8 - retrans) * mass_fraction * prt%variables(i_var)%val(i_pos) ! The mass that is going towards storage From 12f824dd00186a84d4399f62a6de681a7e5ab40e Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 24 Feb 2022 11:46:08 -0500 Subject: [PATCH 127/852] Incremental changes towards fine-root biomass adaptation to N:C and P:C storage fractions --- biogeochem/EDCanopyStructureMod.F90 | 12 ++--- biogeochem/EDCohortDynamicsMod.F90 | 14 ++--- biogeochem/EDPatchDynamicsMod.F90 | 4 +- main/EDMainMod.F90 | 2 +- main/EDTypesMod.F90 | 2 +- main/FatesHistoryInterfaceMod.F90 | 18 +++---- parteh/PRTAllometricCNPMod.F90 | 81 ++++++++++++++++++----------- 7 files changed, 78 insertions(+), 55 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index e2db556bdb..2d3dc30e97 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -662,10 +662,10 @@ subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr,bc_in) ! (keep as an example) ! Initialize running means !allocate(copyc%tveg_lpa) - allocate(copyc%l2fr_ema) - ! Note, no need to give a starter value here, - ! that will be taken care of in copy_cohort() - call copyc%l2fr_ema%InitRMean(ema_60day) + !!allocate(copyc%l2fr_ema) + ! Note, no need to give a starter value here, + ! that will be taken care of in copy_cohort() + !!call copyc%l2fr_ema%InitRMean(ema_60day) ! Initialize the PARTEH object and point to the ! correct boundary condition fields @@ -1121,10 +1121,10 @@ subroutine PromoteIntoLayer(currentSite,currentPatch,i_lyr) allocate(copyc) - allocate(copyc%l2fr_ema) + !!allocate(copyc%l2fr_ema) ! Note, no need to give a starter value here, ! that will be taken care of in copy_cohort() - call copyc%l2fr_ema%InitRMean(ema_60day) + !!call copyc%l2fr_ema%InitRMean(ema_60day) ! Initialize the PARTEH object and point to the ! correct boundary condition fields diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 7fe667ed33..a0df486966 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -94,7 +94,7 @@ module EDCohortDynamicsMod use PRTAllometricCNPMod, only : cnp_allom_prt_vartypes use PRTAllometricCNPMod, only : acnp_bc_in_id_pft, acnp_bc_in_id_ctrim use PRTAllometricCNPMod, only : acnp_bc_in_id_lstat, acnp_bc_inout_id_dbh - use PRTAllometricCNPMod, only : acnp_bc_in_id_l2fr_ema + !use PRTAllometricCNPMod, only : acnp_bc_in_id_l2fr_ema use PRTAllometricCNPMod, only : acnp_bc_inout_id_l2fr use PRTAllometricCNPMod, only : acnp_bc_inout_id_rmaint_def, acnp_bc_in_id_netdc use PRTAllometricCNPMod, only : acnp_bc_in_id_netdnh4, acnp_bc_in_id_netdno3, acnp_bc_in_id_netdp @@ -324,8 +324,8 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & !! allocate(new_cohort%tveg_lpa) !! call new_cohort%tveg_lpa%InitRMean(ema_lpa,init_value=patchptr%tveg_lpa%GetMean()) - allocate(new_cohort%l2fr_ema) - call new_cohort%l2fr_ema%InitRMean(ema_60day,init_value=new_cohort%l2fr,init_offset=fnrt_adapt_tscl*sec_per_day) + !!allocate(new_cohort%l2fr_ema) + !!call new_cohort%l2fr_ema%InitRMean(ema_60day,init_value=new_cohort%l2fr,init_offset=fnrt_adapt_tscl*sec_per_day) call InitPRTBoundaryConditions(new_cohort) @@ -431,7 +431,7 @@ subroutine InitPRTBoundaryConditions(new_cohort) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdnh4, bc_rval = new_cohort%daily_nh4_uptake) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdno3, bc_rval = new_cohort%daily_no3_uptake) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdp, bc_rval = new_cohort%daily_p_uptake) - call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_l2fr_ema, bc_rval = new_cohort%l2fr_ema%l_mean) + !!call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_l2fr_ema, bc_rval = new_cohort%l2fr_ema%l_mean) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_dbh,bc_rval = new_cohort%dbh) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_rmaint_def,bc_rval = new_cohort%resp_m_def) @@ -1017,7 +1017,7 @@ subroutine DeallocateCohort(currentCohort) ! (Keeping as an example) ! Remove the running mean structure ! deallocate(currentCohort%tveg_lpa) - deallocate(currentCohort%l2fr_ema) + !!deallocate(currentCohort%l2fr_ema) ! At this point, nothing should be pointing to current Cohort if (hlm_use_planthydro.eq.itrue) call DeallocateHydrCohort(currentCohort) @@ -1187,7 +1187,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) ! like other variables !!call currentCohort%tveg_lpa%FuseRMean(nextc%tveg_lpa,currentCohort%n/newn) - call currentCohort%l2fr_ema%FuseRMean(nextc%l2fr_ema,currentCohort%n/newn) + !!call currentCohort%l2fr_ema%FuseRMean(nextc%l2fr_ema,currentCohort%n/newn) ! new cohort age is weighted mean of two cohorts currentCohort%coage = & @@ -1832,7 +1832,7 @@ subroutine copy_cohort( currentCohort,copyc ) ! (Keeping as an example) ! Copy over running means ! call n%tveg_lpa%CopyFromDonor(o%tveg_lpa) - call n%l2fr_ema%CopyFromDonor(o%l2fr_ema) + !!call n%l2fr_ema%CopyFromDonor(o%l2fr_ema) ! CARBON FLUXES n%gpp_acc_hold = o%gpp_acc_hold diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 17f72aff8f..4fee51a877 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -698,10 +698,10 @@ subroutine spawn_patches( currentSite, bc_in) allocate(nc) if(hlm_use_planthydro.eq.itrue) call InitHydrCohort(CurrentSite,nc) - allocate(nc%l2fr_ema) + !!allocate(nc%l2fr_ema) ! Note, no need to give a starter value here, ! that will be taken care of in copy_cohort() - call nc%l2fr_ema%InitRMean(ema_60day) + !!call nc%l2fr_ema%InitRMean(ema_60day) ! Initialize the PARTEH object and point to the ! correct boundary condition fields diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 3399c1122f..aeec0c7974 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -455,7 +455,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) actual_l2fr = max(0.05_r8,min(10._r8,actual_l2fr)) - call currentCohort%l2fr_ema%UpdateRMean(actual_l2fr) + !!call currentCohort%l2fr_ema%UpdateRMean(actual_l2fr) end if call currentCohort%prt%DailyPRT() diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 041626447c..dc9753f9c3 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -222,7 +222,7 @@ module EDTypesMod ! nutrient storage) - class(rmean_type), pointer :: l2fr_ema ! Exponential moving average of the L2FR + !!class(rmean_type), pointer :: l2fr_ema ! Exponential moving average of the L2FR ! VEGETATION STRUCTURE integer :: pft ! pft number diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 34fa749dbb..07359802c0 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -184,7 +184,7 @@ module FatesHistoryInterfaceMod integer :: ih_totvegp_si integer :: ih_l2fr_si - integer :: ih_l2fr_ema_si + !!integer :: ih_l2fr_ema_si integer :: ih_l2fr_scpf integer :: ih_l2fr_canopy_scpf integer :: ih_l2fr_understory_scpf @@ -1858,7 +1858,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_ncohorts_si => this%hvars(ih_ncohorts_si)%r81d, & hio_trimming_si => this%hvars(ih_trimming_si)%r81d, & hio_l2fr_si => this%hvars(ih_l2fr_si)%r81d, & - hio_l2fr_ema_si => this%hvars(ih_l2fr_ema_si)%r81d, & + !!hio_l2fr_ema_si => this%hvars(ih_l2fr_ema_si)%r81d, & hio_l2fr_scpf => this%hvars(ih_l2fr_scpf)%r82d, & hio_l2fr_canopy_scpf => this%hvars(ih_l2fr_canopy_scpf)%r82d, & hio_l2fr_understory_scpf => this%hvars(ih_l2fr_understory_scpf)%r82d, & @@ -2404,7 +2404,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_l2fr_si(io_si) = hio_l2fr_si(io_si) + ccohort%n*fnrt_m/m2_per_ha*ccohort%l2fr - hio_l2fr_ema_si(io_si) = hio_l2fr_ema_si(io_si) + ccohort%n*fnrt_m/m2_per_ha*ccohort%l2fr_ema%GetMean() + !!hio_l2fr_ema_si(io_si) = hio_l2fr_ema_si(io_si) + ccohort%n*fnrt_m/m2_per_ha*ccohort%l2fr_ema%GetMean() hio_l2fr_scpf(io_si,i_scpf) = & hio_l2fr_scpf(io_si,i_scpf) + ccohort%n*fnrt_m/m2_per_ha*ccohort%l2fr @@ -3050,7 +3050,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) ! Normalize the l2fr value by total biomass hio_l2fr_si(io_si) = hio_l2fr_si(io_si)/this%hvars(ih_fnrtc_si)%r81d(io_si) - hio_l2fr_ema_si(io_si) = hio_l2fr_ema_si(io_si)/this%hvars(ih_fnrtc_si)%r81d(io_si) + !!hio_l2fr_ema_si(io_si) = hio_l2fr_ema_si(io_si)/this%hvars(ih_fnrtc_si)%r81d(io_si) ! divide so-far-just-summed but to-be-averaged patch-age-class variables by patch-age-class area to get mean values @@ -4516,11 +4516,11 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_l2fr_si) - call this%set_history_var(vname='FATES_L2FR_EMA', units='kg kg-1', & - long='Moving average of the leaf to fineroot biomass multiplier for target allometry', & - use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_l2fr_ema_si) + !!call this%set_history_var(vname='FATES_L2FR_EMA', units='kg kg-1', & + !! long='Moving average of the leaf to fineroot biomass multiplier for target allometry', & + !! use_default='active', & + !! avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + !! ivar=ivar, initialize=initialize_variables, index = ih_l2fr_ema_si) call this%set_history_var(vname='FATES_L2FR_SZPF', units='kg kg-1', & diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 75aac5c285..2e79fe93b6 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -153,10 +153,12 @@ module PRTAllometricCNPMod integer, public, parameter :: acnp_bc_in_id_netdnh4 = 5 ! Index for the net daily NH4 input BC integer, public, parameter :: acnp_bc_in_id_netdno3 = 6 ! Index for the net daily NO3 input BC integer, public, parameter :: acnp_bc_in_id_netdp = 7 ! Index for the net daily P input BC - integer, public, parameter :: acnp_bc_in_id_l2fr_ema = 8 ! Index for the moving average ema + !integer, public, parameter :: acnp_bc_in_id_l2fr_ema = 7 ! Index for the moving average ema + !integer, public, parameter :: acnp_bc_in_id_ncs_ema = 9 ! Index for N/C storage ratio (EMA) + !integer, public, parameter :: acnp_bc_in_id_pcs_ema = 10 ! Index for P/C storage ratio (EMA) ! 0=leaf off, 1=leaf on - integer, parameter :: num_bc_in = 8 + integer, parameter :: num_bc_in = 7 ! ------------------------------------------------------------------------------------- ! Output Boundary Indices (These are public) @@ -166,7 +168,7 @@ module PRTAllometricCNPMod integer, public, parameter :: acnp_bc_out_id_nefflux = 2 ! Daily exudation of N [kg] integer, public, parameter :: acnp_bc_out_id_pefflux = 3 ! Daily exudation of P [kg] - integer, parameter :: num_bc_out = 5 ! Total number of + integer, parameter :: num_bc_out = 3 ! Total number of ! Indices for parameters passed to the integrator @@ -207,9 +209,12 @@ module PRTAllometricCNPMod integer, parameter :: regulate_CN_ema = 5 - !real(r8), public, parameter :: fnrt_adapt_tscl = 365._r8 ! Fine-root adaptation timescale (days) - - real(r8), public, parameter :: fnrt_adapt_tscl = 30._r8 ! Fine-root adaptation timescale (days) + real(r8), public, parameter :: fnrt_adapt_tscl = 100._r8 ! Fine-root adaptation timescale (days) + ! or, how many days it takes + ! for a doubling or halving of the l2fr + + + ! Array of pointers are difficult in F90 ! This structure is a necessary intermediate @@ -353,7 +358,7 @@ subroutine DailyPRTAllometricCNP(this) real(r8) :: n_gain ! Daily nitrogen uptake through fine-roots [kgN] real(r8) :: p_gain ! Daily phosphorus uptake through fine-roots [kgN] real(r8) :: canopy_trim ! The canopy trimming function [0-1] - real(r8) :: l2fr_ema ! Mean (EMA) l2fr + !real(r8) :: l2fr_ema ! Mean (EMA) l2fr ! Pointers to output bcs real(r8),pointer :: c_efflux ! Total plant efflux of carbon (kgC) @@ -650,7 +655,7 @@ subroutine CNPAdjustFRootTargets(this) integer :: ipft ! PFT index real(r8), pointer :: dbh real(r8) :: canopy_trim - real(r8) :: l2fr_ema ! Moving average L2FR (EMA) + !!real(r8) :: l2fr_ema ! Moving average L2FR (EMA) real(r8) :: l2fr_actual real(r8) :: fnrt_c_target ! Target fineroot C before we change l2fr @@ -673,7 +678,7 @@ subroutine CNPAdjustFRootTargets(this) l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval - l2fr_ema = this%bc_in(acnp_bc_in_id_l2fr_ema)%rval + !!l2fr_ema = this%bc_in(acnp_bc_in_id_l2fr_ema)%rval associate( l2fr_min => prt_params%allom_l2fr_min(ipft), & l2fr_max => prt_params%allom_l2fr_max(ipft)) @@ -703,9 +708,7 @@ subroutine CNPAdjustFRootTargets(this) ! Only update L2FR if some leaves are out call bleaf(dbh,ipft,canopy_trim,leaf_c_target) if(this%GetState(leaf_organ, carbon12_element)/leaf_c_target>0.5_r8) then - l2fr = l2fr_ema * np_regulator - !l2fr = l2fr_actual * np_regulator - !l2fr = l2fr * np_regulator + l2fr = l2fr * np_regulator end if @@ -2214,11 +2217,12 @@ subroutine StorageRegulator(this,element_id,regulate_type,c_scalar) real(r8) :: l2fr_delta_max real(r8) :: l2fr_delta_min real(r8) :: l2fr_actual + real(r8) :: leaf_c, fnrt_c real(r8) :: leaf_c_target real(r8) :: log_nc_frac real(r8) :: store_c_frac real(r8) :: c_gain - real(r8) :: target_fnrt_c + real(r8) :: fnrt_c_target ! This is the storage fraction where downregulation starts if using ! a linear function @@ -2237,10 +2241,8 @@ subroutine StorageRegulator(this,element_id,regulate_type,c_scalar) associate(dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval, & canopy_trim => this%bc_in(acnp_bc_in_id_ctrim)%rval, & ipft => this%bc_in(acnp_bc_in_id_pft)%ival, & - l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval, & - l2fr_ema => this%bc_in(acnp_bc_in_id_l2fr_ema)%rval) - - + l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval) + store_max = this%GetNutrientTarget(element_id,store_organ,stoich_max) ! Storage fractions could more than the target, depending on the @@ -2275,7 +2277,7 @@ subroutine StorageRegulator(this,element_id,regulate_type,c_scalar) elseif(regulate_type == regulate_CN_logi .or. regulate_type == regulate_CN_ema) then - logi_k = 2.0_r8 + logi_k = 1.0_r8 store_x0 = 0.0_r8 logi_min = 0.0_r8 @@ -2312,27 +2314,48 @@ subroutine StorageRegulator(this,element_id,regulate_type,c_scalar) ! (l2fr_delta_max*target_fnrt_c + target_fnrt_c-actual_fnrt_c )/c_gain ! < max_l2fr_cgain_frac ! + ! or + ! + ! l2fr_delta_max*target_fnrt_c < max_l2fr_cgain_frac * (c_gain - + ! (target_fnrt_c-actual_fnrt_c) - + ! (target_leaf_c-actual_leaf_c)) + ! ! ------------------------------------------------------------------------------ - call bfineroot(dbh,ipft,canopy_trim, l2fr, target_fnrt_c) + call bfineroot(dbh,ipft,canopy_trim, l2fr, fnrt_c_target) + call bleaf(dbh,ipft,canopy_trim,leaf_c_target) ! If there is overflow storage, add this to the gain c_gain = this%bc_in(acnp_bc_in_id_netdc)%rval + & max(0._r8,this%GetState(store_organ, carbon12_element)-store_c_max) + + fnrt_c = this%GetState(fnrt_organ, carbon12_element) + leaf_c = this%GetState(leaf_organ, carbon12_element) + + l2fr_delta_max = max_l2fr_cgain_frac / fnrt_c_target * & + (c_gain - (fnrt_c_target-fnrt_c) - (leaf_c_target-leaf_c)) + + ! This value could be negative if there is no gain, or less gain + ! than what can replace leaf/root, just ensure the multiplier is GT 1 - l2fr_delta_max = max(0._r8, & - c_gain*max_l2fr_cgain_frac - & - target_fnrt_c-this%GetState(fnrt_organ, carbon12_element))/target_fnrt_c + l2fr_delta_max = max(1._r8,l2fr_delta_max) + + + ! Second constraint, folding timescale + ! 2.0 = l2fr_delta_max^frnt_adapt_tscl + l2fr_delta_max = min(l2fr_delta_max, 2._r8**(1._r8/fnrt_adapt_tscl)) - ! Since we use l2fr_ema as the basis, we need to transform this - ! l2fr_actual*(1+l2fr_delta_max) = l2fr_ema*(1+l2fr_delta_eff) l2fr_actual = this%GetState(fnrt_organ, carbon12_element) / & this%GetState(leaf_organ, carbon12_element) - ! RE - !l2fr_delta_max = l2fr_actual*(1+l2fr_delta_max)/l2fr_ema - 1.0_r8 - l2fr_delta_min = (years_per_day / prt_params%root_long(ipft)) + ! Constrain change in l2fr minimum to be no more than what is lost + ! in turnover for a day + l2fr_delta_min = 1._r8-(years_per_day / prt_params%root_long(ipft)) + + ! Second constraint, folding timescale + l2fr_delta_min = max(l2fr_delta_min, 0.5_r8**(1._r8/fnrt_adapt_tscl)) + log_nc_frac = log( store_frac / store_c_frac ) @@ -2341,9 +2364,9 @@ subroutine StorageRegulator(this,element_id,regulate_type,c_scalar) min(1._r8,logi_min + (1._r8-logi_min)/(1._r8 + exp(logi_k*(log_nc_frac-store_x0)))))-1.0_r8 if(c_scalar>0.0_r8)then - c_scalar = 1._r8+c_scalar*l2fr_delta_max + c_scalar = 1._r8 + c_scalar*(l2fr_delta_max-1._r8) else - c_scalar = 1._r8+c_scalar*l2fr_delta_min + c_scalar = 1._r8 + c_scalar*(1._r8-l2fr_delta_min) end if else From d017a3108ddafdf432bd24de2f4ee297c024d055 Mon Sep 17 00:00:00 2001 From: ckoven Date: Fri, 29 Oct 2021 17:09:33 -0600 Subject: [PATCH 128/852] merging in Charlies sym fix code --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 44 +++++++++++++++++----- main/EDTypesMod.F90 | 4 +- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index adffe67d85..5a0c55183b 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -237,6 +237,9 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) real(r8) :: lai_current ! the LAI in the current leaf layer real(r8) :: cumulative_lai ! the cumulative LAI, top down, to the leaf layer of interest real(r8) :: leaf_psi ! leaf xylem matric potential [MPa] (only meaningful/used w/ hydro) + real(r8) :: fnrt_mr_layer ! fine root maintenance respiation per layer [kgC/plant/s] + real(r8) :: c_cost_nfix ! carbon cost of N fixation [kgC/kgN] + real(r8), allocatable :: rootfr_ft(:,:) ! Root fractions per depth and PFT ! ----------------------------------------------------------------------------------- @@ -263,6 +266,11 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! (gC/gN/s) ! ------------------------------------------------------------------------ + ! N fixation parameters from Houlton et al (2008) and Fisher et al (2010) + real(r8), parameter :: s_fix = -6.25_r8 ! s parameter from FUN model (fisher et al 2010) + real(r8), parameter :: a_fix = -3.62_r8 ! a parameter from Houlton et al. 2010 (a = -3.62 +/- 0.52) + real(r8), parameter :: b_fix = 0.27_r8 ! b parameter from Houlton et al. 2010 (b = 0.27 +/-0.04) + real(r8), parameter :: c_fix = 25.15_r8 ! c parameter from Houlton et al. 2010 (c = 25.15 +/- 0.66) ! ----------------------------------------------------------------------------------- ! Photosynthesis and stomatal conductance parameters, from: ! Bonan et al (2011) JGR, 116, doi:10.1029/2010JG001593 @@ -695,12 +703,28 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! Fine Root MR (kgC/plant/s) + ! and calculate the N fixation rate as a function of the fixation-specific root respiration + ! for now use dev_arbitrary_pft as scaling term between 0 and 1 as additional increment of root respiration used for N fixation ! ------------------------------------------------------------------ currentCohort%froot_mr = 0._r8 + + ! n_fixation is integrated over the course of the day + currentCohort%n_fixation = 0._r8 + do j = 1,bc_in(s)%nlevsoil tcsoi = q10_mr**((bc_in(s)%t_soisno_sl(j)-tfrz - 20.0_r8)/10.0_r8) - currentCohort%froot_mr = currentCohort%froot_mr + & - fnrt_n * ED_val_base_mr_20 * tcsoi * rootfr_ft(ft,j) * maintresp_reduction_factor + + fnrt_mr_layer = fnrt_n * ED_val_base_mr_20 * tcsoi * rootfr_ft(ft,j) * maintresp_reduction_factor + + currentCohort%froot_mr = currentCohort%froot_mr + fnrt_mr_layer * (1._r8 + EDPftvarcon_inst%dev_arbitrary_pft(ft)) + + ! calculate the cost of carbon for N fixation in each soil layer and calculate N fixation rate based on that [kgC / kgN] + + c_cost_nfix = s_fix * (exp(a_fix + b_fix * (bc_in(s)%t_soisno_sl(j)-tfrz) & + * (1._r8 - 0.5_r8 * (bc_in(s)%t_soisno_sl(j)-tfrz) / c_fix)) - 2._r8) + + currentCohort%n_fixation = currentCohort%n_fixation + fnrt_mr_layer * EDPftvarcon_inst%dev_arbitrary_pft / c_cost_nfix + enddo ! Coarse Root MR (kgC/plant/s) (below ground sapwood) @@ -1434,14 +1458,14 @@ subroutine ScaleLeafLayerFluxToCohort(nv, & ! in currentCohort%nv real(r8), intent(in) :: nplant ! indiv/m2 real(r8), intent(in) :: rb ! leaf boundary layer resistance (s/m) real(r8), intent(in) :: maintresp_reduction_factor ! factor by which to reduce maintenance respiration - real(r8), intent(out) :: g_sb_laweight ! Combined conductance (stomatal + boundary layer) for the cohort - ! weighted by leaf area [m/s]*[m2] - real(r8), intent(out) :: gpp ! GPP (kgC/indiv/s) - real(r8), intent(out) :: rdark ! Dark Leaf Respiration (kgC/indiv/s) - real(r8), intent(out) :: cohort_eleaf_area ! Effective leaf area of the cohort [m2] - real(r8), intent(out) :: c13disc_clm ! unpacked Cohort level c13 discrimination - real(r8) :: sum_weight ! sum of weight for unpacking d13c flux (c13disc_z) from - ! (canopy_layer, pft, leaf_layer) matrix to cohort (c13disc_clm) + real(r8), intent(out) :: g_sb_laweight ! Combined conductance (stomatal + boundary layer) for the cohort + ! weighted by leaf area [m/s]*[m2] + real(r8), intent(out) :: gpp ! GPP (kgC/indiv/s) + real(r8), intent(out) :: rdark ! Dark Leaf Respiration (kgC/indiv/s) + real(r8), intent(out) :: cohort_eleaf_area ! Effective leaf area of the cohort [m2] + real(r8), intent(out) :: c13disc_clm ! unpacked Cohort level c13 discrimination + real(r8) :: sum_weight ! sum of weight for unpacking d13c flux (c13disc_z) from + ! (canopy_layer, pft, leaf_layer) matrix to cohort (c13disc_clm) ! GPP IN THIS SUBROUTINE IS A RATE. THE CALLING ARGUMENT IS GPP_TSTEP. AFTER THIS ! CALL THE RATE WILL BE MULTIPLIED BY THE INTERVAL TO GIVE THE INTEGRATED QUANT. diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index dc9753f9c3..94a02d9672 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -311,7 +311,9 @@ module EDTypesMod real(r8) :: daily_n_demand ! The daily amount of N demanded by the plant [kgN/plant/day] real(r8) :: daily_p_demand ! The daily amount of P demanded by the plant [kgN/plant/day] - + ! N fixation rate + real(r8) :: n_fixation ! Rate of N fixation from the roots [kgN/indiv/s] + ! The following four biophysical rates are assumed to be ! at the canopy top, at reference temp 25C, and based on the ! leaf age weighted average of the PFT parameterized values. The last From d15081feac9ea5c87bea035a15c84cd84a66a042 Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Mon, 28 Feb 2022 14:29:15 -0800 Subject: [PATCH 129/852] [ update comments on branch_frac ] [] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary: --- biogeochem/FatesAllometryMod.F90 | 4 ++-- biogeophys/FatesPlantRespPhotosynthMod.F90 | 2 +- main/EDTypesMod.F90 | 2 +- main/FatesParameterDerivedMod.F90 | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index c3df74183d..862a837782 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -374,7 +374,7 @@ subroutine bagw_allom(d,ipft,crowndamage, bagw,dbagwdd) real(r8) :: h ! height real(r8) :: dhdd ! change in height wrt d real(r8) :: crown_reduction ! crown reduction from damage - real(r8) :: branch_frac ! fraction of aboveground biomass in branches + real(r8) :: branch_frac ! fraction of aboveground woody biomass in branches associate( p1 => prt_params%allom_agb1(ipft), & p2 => prt_params%allom_agb2(ipft), & @@ -923,7 +923,7 @@ subroutine bsap_allom(d,ipft,crowndamage,canopy_trim,sapw_area,bsap,dbsapdd) real(r8) :: crown_reduction ! amount that crown is damage by real(r8) :: agb_frac ! aboveground biomass fraction - real(r8) :: branch_frac ! fraction of aboveground biomass in branches + real(r8) :: branch_frac ! fraction of aboveground woody biomass in branches ! Constrain sapwood so that its above ground portion be no larger than ! X% of total woody/fibrous (ie non leaf/fineroot) tissues diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index accf729e8d..3bf35c6849 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -245,7 +245,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) real(r8), allocatable :: rootfr_ft(:,:) ! Root fractions per depth and PFT real(r8) :: agb_frac ! fraction of biomass aboveground - real(r8) :: branch_frac ! fraction of aboveground biomass in branches + real(r8) :: branch_frac ! fraction of aboveground woody biomass in branches real(r8) :: crown_reduction ! reduction in crown biomass from damage real(r8) :: sapw_c_predamage ! pre damage sapwood real(r8) :: sapw_n ! sapwood n diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 50cab343aa..3762efd610 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -345,7 +345,7 @@ module EDTypesMod real(r8) :: froot_mr ! Live fine root maintenance respiration: kgC/indiv/s !DAMAGE - real(r8) :: branch_frac ! Fraction of aboveground biomass in branches + real(r8) :: branch_frac ! Fraction of aboveground woody biomass in branches !MORTALITY real(r8) :: dmort ! proportional mortality rate. (year-1) diff --git a/main/FatesParameterDerivedMod.F90 b/main/FatesParameterDerivedMod.F90 index 1857dfdffe..f63df66318 100644 --- a/main/FatesParameterDerivedMod.F90 +++ b/main/FatesParameterDerivedMod.F90 @@ -28,7 +28,7 @@ module FatesParameterDerivedMod real(r8), allocatable :: kp25top(:,:) ! canopy top: initial slope of CO2 response ! curve (C4 plants) at 25C - real(r8), allocatable :: branch_frac(:) ! fraction of aboveground biomass in branches (as + real(r8), allocatable :: branch_frac(:) ! fraction of aboveground woody biomass in branches (as ! oppose to stems) - for use in damage allometries real(r8), allocatable :: damage_transitions(:,:,:) ! matrix of transition probabilities between @@ -118,7 +118,7 @@ subroutine Init(this,numpft) end do - ! Allocate fraction of biomass in branches + ! Allocate fraction of aboveground woody biomass in branches this%branch_frac(ft) = sum(SF_val_CWD_frac(1:3)) end do !ft From a3bb261bb087e27bb2e5b96540b08cae7f56a502 Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Tue, 1 Mar 2022 14:33:15 -0800 Subject: [PATCH 130/852] [ delete old variables from EDInitMod] [ ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary: no testing --- main/EDInitMod.F90 | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 27666a06e5..0f92b29916 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -132,10 +132,6 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) allocate(site_in%flux_diags(1:num_elements)) if (hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then - allocate(site_in%damage_cflux(1:ncrowndamage, 1:ncrowndamage+1)) - allocate(site_in%damage_rate(1:ncrowndamage, 1:ncrowndamage+1)) - allocate(site_in%recovery_cflux(1:ncrowndamage, 1:ncrowndamage+1)) - allocate(site_in%recovery_rate(1:ncrowndamage, 1:ncrowndamage+1)) allocate(site_in%term_nindivs_canopy_damage(1:ncrowndamage, 1:nlevsclass, 1:numpft)) allocate(site_in%term_nindivs_ustory_damage(1:ncrowndamage, 1:nlevsclass, 1:numpft)) allocate(site_in%imort_rate_damage(1:ncrowndamage, 1:nlevsclass, 1:numpft)) @@ -147,10 +143,6 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) allocate(site_in%fmort_cflux_canopy_damage(1:ncrowndamage, 1:nlevsclass)) allocate(site_in%fmort_cflux_ustory_damage(1:ncrowndamage, 1:nlevsclass)) else - allocate(site_in%damage_cflux(1, 1)) - allocate(site_in%damage_rate(1, 1)) - allocate(site_in%recovery_cflux(1, 1)) - allocate(site_in%recovery_rate(1, 1)) allocate(site_in%term_nindivs_canopy_damage(1,1,1)) allocate(site_in%term_nindivs_ustory_damage(1,1,1)) allocate(site_in%imort_rate_damage(1,1,1)) @@ -288,10 +280,6 @@ subroutine zero_site( site_in ) site_in%promotion_carbonflux = 0._r8 ! damage transition info - site_in%damage_cflux(:,:) = 0._r8 - site_in%damage_rate(:,:) = 0._r8 - site_in%recovery_cflux(:,:) = 0._r8 - site_in%recovery_rate(:,:) = 0._r8 site_in%imort_rate_damage(:,:,:) = 0._r8 site_in%term_nindivs_canopy_damage(:,:,:) = 0._r8 site_in%term_nindivs_ustory_damage(:,:,:) = 0._r8 From 36e8faf7db80251a08099907d58e9d3f9631a807 Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Wed, 2 Mar 2022 09:29:49 -0800 Subject: [PATCH 131/852] [ Remove old history variables ] [Get rid of remaining damage_cflux and damage_rate variables ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary: no testing --- main/EDTypesMod.F90 | 6 ------ main/FatesRestartInterfaceMod.F90 | 32 ------------------------------- 2 files changed, 38 deletions(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 3762efd610..8f367f78de 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -840,12 +840,6 @@ module EDTypesMod real(r8), allocatable :: growthflux_fusion(:,:) ! rate of individuals moving into a given size class bin ! due to fusion in a given day. on size x pft array - - ! Damage fluxes - real(r8), allocatable :: damage_cflux(:,:) ! carbon flux into each damage class each timestep - real(r8), allocatable :: damage_rate(:,:) ! number of individuals moving into a damage class - real(r8), allocatable :: recovery_cflux(:,:) ! carbon flux from recovery each timestep - real(r8), allocatable :: recovery_rate(:,:) ! number of individuals recovering each timesept real(r8), allocatable :: imort_rate_damage(:,:,:) ! number of individuals per damage class that die from impact mortality real(r8), allocatable :: term_nindivs_canopy_damage(:,:,:) ! number of individuals per damage class that die from termination mortality - canopy diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index e111a9e699..4512448504 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -240,10 +240,6 @@ module FatesRestartInterfaceMod integer :: ir_termcflux_usto_sicdsc integer :: ir_fmortcflux_cano_sicdsc integer :: ir_fmortcflux_usto_sicdsc - integer :: ir_damage_cflux_sicd - integer :: ir_damage_rate_sicd - integer :: ir_recovery_cflux_sicd - integer :: ir_recovery_rate_sicd integer :: ir_crownarea_cano_si integer :: ir_crownarea_usto_si @@ -1375,26 +1371,6 @@ subroutine define_restart_vars(this, initialize_variables) units='kgC/ha/day', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_fmortcflux_usto_sicdsc) - call this%set_restart_var(vname='fates_damage_cflux', vtype=cohort_r8, & - long_name='fates diagnostic rate of damage carbonflux', & - units='kgC/ha/day', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_damage_cflux_sicd) - - call this%set_restart_var(vname='fates_damage_rate', vtype=cohort_r8, & - long_name='fates diagnostic rate of damage transitions', & - units='indiv / ha/ day', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_damage_rate_sicd) - - call this%set_restart_var(vname='fates_recovery_cflux', vtype=cohort_r8, & - long_name='fates diagnostic rate of recovery carbonflux', & - units='kgC/ha/day', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_recovery_cflux_sicd) - - call this%set_restart_var(vname='fates_recovery_rate', vtype=cohort_r8, & - long_name='fates diagnostic rate of recovery transitions', & - units='indiv / ha/ day', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_recovery_rate_sicd) - call this%set_restart_var(vname='fates_crownarea_canopy_damage', vtype=site_r8, & long_name='fates area lost from damage each year', & units='m2/ha/year', flushval = flushzero, & @@ -2001,10 +1977,6 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_fmortrate_usto_sicdpf => this%rvars(ir_fmortrate_usto_sicdpf)%r81d, & rio_fmortcflux_cano_sicdsc => this%rvars(ir_fmortcflux_cano_sicdsc)%r81d, & rio_fmortcflux_usto_sicdsc => this%rvars(ir_fmortcflux_usto_sicdsc)%r81d, & - rio_damage_cflux_sicd => this%rvars(ir_damage_cflux_sicd)%r81d, & - rio_damage_rate_sicd => this%rvars(ir_damage_rate_sicd)%r81d, & - rio_recovery_cflux_sicd => this%rvars(ir_recovery_cflux_sicd)%r81d, & - rio_recovery_rate_sicd => this%rvars(ir_recovery_rate_sicd)%r81d, & rio_crownarea_cano_damage_si=> this%rvars(ir_crownarea_cano_si)%r81d, & rio_crownarea_usto_damage_si=> this%rvars(ir_crownarea_usto_si)%r81d) @@ -2894,10 +2866,6 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ! Damage - rio_damage_cflux_sicd => this%rvars(ir_damage_cflux_sicd)%r81d, & - rio_damage_rate_sicd => this%rvars(ir_damage_rate_sicd)%r81d, & - rio_recovery_cflux_sicd => this%rvars(ir_recovery_cflux_sicd)%r81d, & - rio_recovery_rate_sicd => this%rvars(ir_recovery_rate_sicd)%r81d, & rio_imortrate_sicdpf => this%rvars(ir_imortrate_sicdpf)%r81d, & rio_termnindiv_cano_sicdpf => this%rvars(ir_termnindiv_cano_sicdpf)%r81d, & rio_termnindiv_usto_sicdpf => this%rvars(ir_termnindiv_usto_sicdpf)%r81d, & From 73c6c53b42352f24b05fb4290b9711999400ed6e Mon Sep 17 00:00:00 2001 From: ckoven Date: Fri, 4 Mar 2022 10:55:40 -0700 Subject: [PATCH 132/852] added drought and c starvation mortality metrics --- main/FatesHistoryInterfaceMod.F90 | 36 +++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 5c784a6677..2a0975d51d 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -510,6 +510,9 @@ module FatesHistoryInterfaceMod integer :: ih_recruitment_si_pft integer :: ih_mortality_si_pft integer :: ih_mortality_carbonflux_si_pft + integer :: ih_hydraulicmortality_carbonflux_si_pft + integer :: ih_cstarvmortality_carbonflux_si_pft + integer :: ih_firemortality_carbonflux_si_pft integer :: ih_crownarea_si_pft integer :: ih_canopycrownarea_si_pft integer :: ih_gpp_si_pft @@ -1843,6 +1846,9 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_recruitment_si_pft => this%hvars(ih_recruitment_si_pft)%r82d, & hio_mortality_si_pft => this%hvars(ih_mortality_si_pft)%r82d, & hio_mortality_carbonflux_si_pft => this%hvars(ih_mortality_carbonflux_si_pft)%r82d, & + hio_cstarvmortality_carbonflux_si_pft => this%hvars(ih_cstarvmortality_carbonflux_si_pft)%r82d, & + hio_hydraulicmortality_carbonflux_si_pft => this%hvars(ih_hydraulicmortality_carbonflux_si_pft)%r82d, & + hio_firemortality_carbonflux_si_pft => this%hvars(ih_firemortality_carbonflux_si_pft)%r82d, & hio_crownarea_si_pft => this%hvars(ih_crownarea_si_pft)%r82d, & hio_canopycrownarea_si_pft => this%hvars(ih_canopycrownarea_si_pft)%r82d, & hio_gpp_si_pft => this%hvars(ih_gpp_si_pft)%r82d, & @@ -2627,6 +2633,12 @@ subroutine update_history_dyn(this,nc,nsites,sites) (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * total_m * & ccohort%n * ha_per_m2 + hio_hydraulicmortality_carbonflux_si_pft(io_si,ccohort%pft) = hio_hydraulicmortality_carbonflux_si_pft(io_si,ccohort%pft) + & + ccohort%hmort * total_m * ccohort%n * days_per_sec * years_per_day * ha_per_m2 + + hio_cstarvmortality_carbonflux_si_pft(io_si,ccohort%pft) = hio_cstarvmortality_carbonflux_si_pft(io_si,ccohort%pft) + & + ccohort%cmort * total_m * ccohort%n * days_per_sec * years_per_day * ha_per_m2 + ! number density by size and biomass hio_agb_si_scls(io_si,scls) = hio_agb_si_scls(io_si,scls) + & total_m * ccohort%n * prt_params%allom_agb_frac(ccohort%pft) * AREA_INV @@ -3063,12 +3075,14 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! treat carbon flux from imort the same way hio_understory_mortality_carbonflux_si(io_si) = hio_understory_mortality_carbonflux_si(io_si) + & sum(sites(s)%imort_carbonflux(:)) / g_per_kg - ! + do i_pft = 1, numpft - hio_mortality_carbonflux_si_pft(io_si,ccohort%pft) = hio_mortality_carbonflux_si_pft(io_si,ccohort%pft) + & + hio_mortality_carbonflux_si_pft(io_si,i_pft) = hio_mortality_carbonflux_si_pft(io_si,i_pft) + & (sites(s)%fmort_carbonflux_canopy(i_pft) + & sites(s)%fmort_carbonflux_ustory(i_pft) + & sites(s)%imort_carbonflux(i_pft) ) / g_per_kg !cdk + + hio_firemortality_carbonflux_si_pft(io_si,i_pft) = sites(s)%fmort_carbonflux_canopy(i_pft) / g_per_kg end do sites(s)%term_nindivs_canopy(:,:) = 0._r8 @@ -5460,6 +5474,24 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_mortality_carbonflux_si_pft) + call this%set_history_var(vname='FATES_MORTALITY_FIRE_CFLUX_PF', units='kg m-2 s-1', & + long='PFT-level flux of biomass carbon from live to dead pool from fire mortality', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_firemortality_carbonflux_si_pft) + + call this%set_history_var(vname='FATES_MORTALITY_HYDRAULIC_CFLUX_PF', units='kg m-2 s-1', & + long='PFT-level flux of biomass carbon from live to dead pool from hydraulic failure mortality', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_hydraulicmortality_carbonflux_si_pft) + + call this%set_history_var(vname='FATES_MORTALITY_CSTARV_CFLUX_PF', units='kg m-2 s-1', & + long='PFT-level flux of biomass carbon from live to dead pool from carbon starvation mortality', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_cstarvmortality_carbonflux_si_pft) + ! size class by age dimensioned variables call this%set_history_var(vname='FATES_NPLANT_SZAP', units = 'm-2', & From 420431fb2a1a69b2c65124c8dc5224135b81e4b2 Mon Sep 17 00:00:00 2001 From: Shijie Shu Date: Mon, 7 Mar 2022 21:12:31 -0800 Subject: [PATCH 133/852] Added C based logging in FATES. Passed validation. --- biogeochem/EDLoggingMortalityMod.F90 | 316 +++++++++++++++++++++++-- biogeochem/EDMortalityFunctionsMod.F90 | 16 +- biogeochem/EDPatchDynamicsMod.F90 | 48 +++- main/EDInitMod.F90 | 1 + main/EDMainMod.F90 | 12 +- main/EDTypesMod.F90 | 5 + main/FatesHistoryInterfaceMod.F90 | 8 + main/FatesInterfaceMod.F90 | 14 ++ main/FatesInterfaceTypesMod.F90 | 8 + 9 files changed, 393 insertions(+), 35 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 976fea5a1c..0fb884df04 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -14,6 +14,7 @@ module EDLoggingMortalityMod ! ==================================================================================== use FatesConstantsMod , only : r8 => fates_r8 + use FatesConstantsMod , only : rsnbl_math_prec use EDTypesMod , only : ed_cohort_type use EDTypesMod , only : ed_patch_type use EDTypesMod , only : site_massbal_type @@ -47,6 +48,7 @@ module EDLoggingMortalityMod use FatesInterfaceTypesMod , only : hlm_day_of_year use FatesInterfaceTypesMod , only : hlm_days_per_year use FatesInterfaceTypesMod , only : hlm_use_lu_harvest + use FatesInterfaceTypesMod , only : hlm_harvest_bypass_criteria use FatesInterfaceTypesMod , only : hlm_num_lu_harvest_cats use FatesInterfaceTypesMod , only : hlm_use_logging use FatesInterfaceTypesMod , only : hlm_use_planthydro @@ -97,6 +99,8 @@ module EDLoggingMortalityMod public :: logging_time public :: IsItLoggingTime public :: get_harvest_rate_area + public :: get_harvestable_carbon + public :: get_harvest_rate_carbon public :: UpdateHarvestC contains @@ -197,7 +201,8 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & hlm_harvest_rates, hlm_harvest_catnames, & hlm_harvest_units, & patch_anthro_disturbance_label, secondary_age, & - frac_site_primary) + frac_site_primary, harvestable_forest_c, & + available_forest_c, harvest_tag) ! Arguments integer, intent(in) :: pft_i ! pft index @@ -208,6 +213,11 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & integer, intent(in) :: hlm_harvest_units ! unit type of hlm harvest rates: [area vs. mass] integer, intent(in) :: patch_anthro_disturbance_label ! patch level anthro_disturbance_label real(r8), intent(in) :: secondary_age ! patch level age_since_anthro_disturbance + real(r8), intent(in) :: harvestable_forest_c(:) ! total harvestable forest carbon + ! of all hlm harvest categories + real(r8), intent(in) :: available_forest_c(:) ! total forest carbon available for + ! harvest of all hlm harvest categories + real(r8), intent(in) :: frac_site_primary real(r8), intent(out) :: lmort_direct ! direct (harvestable) mortality fraction real(r8), intent(out) :: lmort_collateral ! collateral damage mortality fraction real(r8), intent(out) :: lmort_infra ! infrastructure mortality fraction @@ -215,10 +225,13 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & ! but suffer from forest degradation (i.e. they ! are moved to newly-anthro-disturbed secondary ! forest patch) - real(r8), intent(in) :: frac_site_primary + integer, intent(out) :: harvest_tag(:) ! tag to record the harvest status, 0 - successful; + ! 1 - can be successful if ignoring the criteria; + ! 2 - unsuccessful since not enough carbon ! Local variables - real(r8) :: harvest_rate ! the final harvest rate to apply to this cohort today + integer :: cur_harvest_tag ! the harvest tag of the cohort today + real(r8) :: harvest_rate ! the final harvest rate to apply to this cohort today ! todo: probably lower the dbhmin default value to 30 cm ! todo: change the default logging_event_code to 1 september (-244) @@ -255,40 +268,48 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & call get_harvest_rate_area (patch_anthro_disturbance_label, hlm_harvest_catnames, & hlm_harvest_rates, frac_site_primary, secondary_age, harvest_rate) + ! For area-based harvest, harvest_tag shall always be 0. + harvest_tag = 0 + cur_harvest_tag = 0 + if (fates_global_verbose()) then - write(fates_log(), *) 'Successfully Read Harvest Rate from HLM.' + write(fates_log(), *) 'Successfully Read Harvest Rate from HLM.', hlm_harvest_rates(:), harvest_rate end if else if (hlm_use_lu_harvest == itrue .and. hlm_harvest_units == hlm_harvest_carbon) then ! 2=use carbon from hlm - ! Shijie: Shall call another function, which transfer biomass/carbon into fraction? - ! Is it the correct place to call the function? - ! Inputs: patch_area, patch_biomass, what else? + ! shall call another subroutine, which transfers biomass/carbon into fraction - ! call get_harvest_rate_carbon (patch_anthro_disturbance_label, hlm_harvest_catnames, & - ! hlm_harvest_rates, frac_site_primary, secondary_age, harvest_rate) + call get_harvest_rate_carbon (patch_anthro_disturbance_label, hlm_harvest_catnames, & + hlm_harvest_rates, secondary_age, harvestable_forest_c, available_forest_c, & + harvest_rate, harvest_tag, cur_harvest_tag) - ! if (fates_global_verbose()) then - ! write(fates_log(), *) 'Successfully Read Harvest Rate from HLM.', hlm_harvest_rates(:), harvest_rate - ! end if + if (fates_global_verbose()) then + write(fates_log(), *) 'Successfully Read Harvest Rate from HLM.', hlm_harvest_rates(:), harvest_rate, & + harvestable_forest_c, available_forest_c + end if !write(fates_log(),*) 'HLM harvest carbon data not implemented yet. Exiting.' !call endrun(msg=errMsg(sourcefile, __LINE__)) - endif + end if ! transfer of area to secondary land is based on overall area affected, not just logged crown area ! l_degrad accounts for the affected area between logged crowns - if(int(prt_params%woody(pft_i)) == 1)then ! only set logging rates for trees - - ! direct logging rates, based on dbh min and max criteria - if (dbh >= logging_dbhmin .and. .not. & - ((logging_dbhmax < fates_check_param_set) .and. (dbh >= logging_dbhmax )) ) then - ! the logic of the above line is a bit unintuitive but allows turning off the dbhmax comparison entirely. - ! since there is an .and. .not. after the first conditional, the dbh:dbhmax comparison needs to be - ! the opposite of what would otherwise be expected... - lmort_direct = harvest_rate * logging_direct_frac - + if(int(prt_params%woody(pft_i)) == 1) then ! only set logging rates for trees + if (cur_harvest_tag == 0) then + ! direct logging rates, based on dbh min and max criteria + if (dbh >= logging_dbhmin .and. .not. & + ((logging_dbhmax < fates_check_param_set) .and. (dbh >= logging_dbhmax )) ) then + ! the logic of the above line is a bit unintuitive but allows turning off the dbhmax comparison entirely. + ! since there is an .and. .not. after the first conditional, the dbh:dbhmax comparison needs to be + ! the opposite of what would otherwise be expected... + lmort_direct = harvest_rate * logging_direct_frac + else + lmort_direct = 0.0_r8 + end if + else if (cur_harvest_tag == 1 .and. hlm_harvest_bypass_criteria == 1) then + lmort_direct = harvest_rate * logging_direct_frac else - lmort_direct = 0.0_r8 + lmort_direct = 0.0_r8 end if ! infrastructure (roads, skid trails, etc) mortality rates @@ -414,6 +435,253 @@ end subroutine get_harvest_rate_area ! ============================================================================ + subroutine get_harvestable_carbon (csite, site_area, hlm_harvest_catnames, harvestable_forest_c, available_forest_c) + + !USES: + use SFParamsMod, only : SF_val_cwd_frac + use EDTypesMod, only : AREA_INV + + + ! ------------------------------------------------------------------------------------------- + ! + ! DESCRIPTION: + ! get the total carbon availale for harvest for three different harvest categories: + ! primary forest, secondary mature forest and secondary young forest + ! under two different scenarios: + ! harvestable carbon: aggregate all cohorts matching the dbhmin harvest criteria + ! available carbon: aggregate all cohorts + ! + ! this subroutine shall be called outside the patch loop + ! output will be used to estimate the area-based harvest rate (get_harvest_rate_carbon) + ! for each cohort. + + ! Arguments + type(ed_site_type), intent(in), target :: csite + real(r8), intent(in) :: site_area ! temporary variable + character(len=64), intent(in) :: hlm_harvest_catnames(:) ! names of hlm harvest categories + + real(r8), intent(out) :: harvestable_forest_c(hlm_num_lu_harvest_cats) + real(r8), intent(out) :: available_forest_c(hlm_num_lu_harvest_cats) + + ! Local Variables + type(ed_patch_type), pointer :: currentPatch + type(ed_cohort_type), pointer :: currentCohort + real(r8) :: harvestable_patch_c ! temporary variable + real(r8) :: harvestable_cohort_c ! temporary variable + real(r8) :: available_patch_c ! temporary variable + real(r8) :: available_cohort_c ! temporary variable + real(r8) :: sapw_m ! Biomass of sap wood + real(r8) :: struct_m ! Biomass of structural organs + integer :: pft ! Index of plant functional type + integer :: h_index ! for looping over harvest categories + + ! Initialization + harvestable_forest_c = 0._r8 + available_forest_c = 0._r8 + + ! loop over patches + currentPatch => csite%oldest_patch + do while (associated(currentPatch)) + harvestable_patch_c = 0._r8 + available_patch_c = 0._r8 + currentCohort => currentPatch%tallest + + do while (associated(currentCohort)) + pft = currentCohort%pft + + ! only account for cohorts matching the following conditions + if(int(prt_params%woody(pft)) == 1)then ! only set logging rates for trees + sapw_m = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) + struct_m = currentCohort%prt%GetState(struct_organ, all_carbon_elements) + ! logging_direct_frac shall be 1 for LUH2 driven simulation and global simulation + ! in site level study logging_direct_frac shall be surveyed + ! unit: [kgC ] = [kgC/plant] * [plant/ha] * [ha/ 10k m2] * [ m2 area ] + harvestable_cohort_c = logging_direct_frac * ( sapw_m + struct_m ) * & + prt_params%allom_agb_frac(currentCohort%pft) * & + SF_val_CWD_frac(ncwd) * logging_export_frac * & + currentCohort%n * AREA_INV * site_area + + ! No harvest for trees without canopy + if (currentCohort%canopy_layer>=1) then + ! logging amount are based on dbh min and max criteria + if (currentCohort%dbh >= logging_dbhmin .and. .not. & + ((logging_dbhmax < fates_check_param_set) .and. (currentCohort%dbh >= logging_dbhmax )) ) then + ! Harvestable C: aggregate cohorts fit the criteria + harvestable_patch_c = harvestable_patch_c + harvestable_cohort_c + ! Available C: aggregate all cohorts + available_patch_c = available_patch_c + harvestable_cohort_c + else + available_patch_c = available_patch_c + harvestable_cohort_c + end if + end if + end if + currentCohort => currentCohort%shorter + end do + + ! judge which category the current patch belong to + ! since we have not separated forest vs. non-forest + ! all carbon belongs to the forest categories + do h_index = 1,hlm_num_lu_harvest_cats + if (currentPatch%anthro_disturbance_label .eq. primaryforest) then + ! Primary + if(hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1") then + harvestable_forest_c(h_index) = harvestable_forest_c(h_index) + harvestable_patch_c + available_forest_c(h_index) = available_forest_c(h_index) + available_patch_c + end if + else if (currentPatch%anthro_disturbance_label .eq. secondaryforest .and. & + currentPatch%age_since_anthro_disturbance >= secondary_age_threshold) then + ! Secondary mature + if(hlm_harvest_catnames(h_index) .eq. "HARVEST_SH1") then + harvestable_forest_c(h_index) = harvestable_forest_c(h_index) + harvestable_patch_c + available_forest_c(h_index) = available_forest_c(h_index) + available_patch_c + end if + else if (currentPatch%anthro_disturbance_label .eq. secondaryforest .and. & + currentPatch%age_since_anthro_disturbance < secondary_age_threshold) then + ! Secondary young + if(hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2") then + harvestable_forest_c(h_index) = harvestable_forest_c(h_index) + harvestable_patch_c + available_forest_c(h_index) = available_forest_c(h_index) + available_patch_c + end if + end if + end do + currentPatch => currentPatch%younger + end do + + end subroutine get_harvestable_carbon + + ! ============================================================================ + + subroutine get_harvest_rate_carbon (patch_anthro_disturbance_label, hlm_harvest_catnames, & + hlm_harvest_rates, secondary_age, harvestable_forest_c, available_forest_c, & + harvest_rate, harvest_tag, cur_harvest_tag) + + ! ------------------------------------------------------------------------------------------- + ! + ! DESCRIPTION: + ! get the carbon-based harvest rates based on info passed to FATES from the boundary conditions in. + ! assumes logging_time == true + + ! Arguments + real(r8), intent(in) :: hlm_harvest_rates(:) ! annual harvest rate per hlm category + character(len=64), intent(in) :: hlm_harvest_catnames(:) ! names of hlm harvest categories + integer, intent(in) :: patch_anthro_disturbance_label ! patch level anthro_disturbance_label + real(r8), intent(in) :: secondary_age ! patch level age_since_anthro_disturbance + real(r8), intent(in) :: harvestable_forest_c(:) ! site level forest c matching criteria available for harvest + real(r8), intent(in) :: available_forest_c(:) ! site level total forest c available for harvest + real(r8), intent(out) :: harvest_rate + integer, intent(inout) :: harvest_tag(:) ! 0. normal harvest; 1. current site does not have enough C but + ! can perform harvest by ignoring criteria; 2. current site does + ! not have enough carbon + ! This harvest tag shall be a patch level variable but since all + ! logging functions happen within cohort loop we can only put the + ! calculation here. Can think about optimizing the logging calculation + ! in the future. + integer, intent(out), optional :: cur_harvest_tag ! harvest tag of the current cohort + + ! Local Variables + integer :: h_index ! for looping over harvest categories + integer :: icode ! Integer equivalent of the event code (parameter file only allows reals) + real(r8) :: harvest_rate_c ! Temporary variable + real(r8) :: harvest_rate_supply ! Temporary variable + + ! Loop around harvest categories to determine the hlm harvest rate demand and actual harvest rate for the + ! current cohort based on patch history info + harvest_rate = 0._r8 + harvest_rate_c = 0._r8 + harvest_rate_supply = 0._r8 + harvest_tag = 2 + + do h_index = 1,hlm_num_lu_harvest_cats + if (patch_anthro_disturbance_label .eq. primaryforest) then + if(hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1" .or. & + hlm_harvest_catnames(h_index) .eq. "HARVEST_VH2") then + harvest_rate_c = harvest_rate_c + hlm_harvest_rates(h_index) + ! Determine the total supply of available C for harvest + if(harvestable_forest_c(h_index) >= harvest_rate_c) then + harvest_rate_supply = harvest_rate_supply + harvestable_forest_c(h_index) + harvest_tag(h_index) = 0 + else if (available_forest_c(h_index) >= harvest_rate_c) then + harvest_rate_supply = harvest_rate_supply + available_forest_c(h_index) + harvest_tag(h_index) = 1 + else + harvest_tag(h_index) = 2 + end if + endif + else if (patch_anthro_disturbance_label .eq. secondaryforest .and. & + secondary_age >= secondary_age_threshold) then + if(hlm_harvest_catnames(h_index) .eq. "HARVEST_SH1") then + harvest_rate_c = harvest_rate_c + hlm_harvest_rates(h_index) + if(harvestable_forest_c(h_index) >= harvest_rate_c) then + harvest_rate_supply = harvest_rate_supply + harvestable_forest_c(h_index) + harvest_tag(h_index) = 0 + else if (available_forest_c(h_index) >= harvest_rate_c) then + harvest_rate_supply = harvest_rate_supply + available_forest_c(h_index) + harvest_tag(h_index) = 1 + else + harvest_tag(h_index) = 2 + end if + endif + else if (patch_anthro_disturbance_label .eq. secondaryforest .and. & + secondary_age < secondary_age_threshold) then + if(hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2" .or. & + hlm_harvest_catnames(h_index) .eq. "HARVEST_SH3") then + harvest_rate_c = harvest_rate_c + hlm_harvest_rates(h_index) + if(harvestable_forest_c(h_index) >= harvest_rate_c) then + harvest_rate_supply = harvest_rate_supply + harvestable_forest_c(h_index) + harvest_tag(h_index) = 0 + else if (available_forest_c(h_index) >= harvest_rate_c) then + harvest_rate_supply = harvest_rate_supply + available_forest_c(h_index) + harvest_tag(h_index) = 1 + else + harvest_tag(h_index) = 2 + end if + endif + endif + end do + + ! If any harvest category available, assign to cur_harvest_tag and trigger logging event + if(present(cur_harvest_tag))then + cur_harvest_tag = minval(harvest_tag) + !write(fates_log(), *) 'cur_harvest_tag:', cur_harvest_tag + !write(fates_log(), *) 'harvest tags:', harvest_tag + !write(fates_log(), *) 'harvest rate c:', harvest_rate_c + !write(fates_log(), *) 'harvest rate supply:', harvest_rate_supply + !write(fates_log(), *) 'hlm harvest rates:', hlm_harvest_rates + end if + + ! Transfer carbon-based harvest rate to area-based harvest rate + if (harvest_rate_supply > rsnbl_math_prec .and. harvest_rate_supply > harvest_rate_c) then + harvest_rate = harvest_rate_c / harvest_rate_supply + else + harvest_rate = 0._r8 + end if + + ! For carbon-based harvest rate, normalizing by site-level primary or secondary forest fraction + ! is not needed + + ! calculate today's harvest rate + ! whether to harvest today has already been determined by IsItLoggingTime + ! for icode == 2, icode < 0, and icode > 10000 apply the annual rate one time (no calc) + ! Bad logging event flag is caught in IsItLoggingTime, so don't check it here + icode = int(logging_event_code) + if(icode .eq. 1) then + ! Logging is turned off - not sure why we need another switch + harvest_rate = 0._r8 + else if(icode .eq. 3) then + ! Logging event every day - this may not work due to the mortality exclusivity + harvest_rate = harvest_rate / hlm_days_per_year + else if(icode .eq. 4) then + ! logging event once a month + if(hlm_current_day.eq.1 ) then + harvest_rate = harvest_rate / months_per_year + end if + end if + + end subroutine get_harvest_rate_carbon + + ! ============================================================================ + + subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site_areadis) ! ------------------------------------------------------------------------------------------- diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index fa0b933fc5..318d6e3801 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -208,7 +208,8 @@ end subroutine mortality_rates ! ============================================================================ - subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_primary) + subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_primary, & + harvestable_forest_c, available_forest_c, harvest_tag) ! ! !DESCRIPTION: @@ -217,7 +218,6 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_pr ! elsewhere). ! ! !USES: - use FatesInterfaceTypesMod, only : hlm_freq_day ! ! !ARGUMENTS @@ -225,6 +225,10 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_pr type(ed_cohort_type),intent(inout), target :: currentCohort type(bc_in_type), intent(in) :: bc_in real(r8), intent(in) :: frac_site_primary + real(r8), intent(in) :: harvestable_forest_c(:) + real(r8), intent(in) :: available_forest_c(:) + integer, intent(inout) :: harvest_tag(:) + ! ! !LOCAL VARIABLES: real(r8) :: cmort ! starvation mortality rate (fraction per year) @@ -235,6 +239,7 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_pr real(r8) :: asmort ! age dependent senescence mortality rate (fraction per year) real(r8) :: dndt_logging ! Mortality rate (per day) associated with the a logging event integer :: ipft ! local copy of the pft index + !---------------------------------------------------------------------- ipft = currentCohort%pft @@ -252,10 +257,11 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_pr bc_in%hlm_harvest_units, & currentCohort%patchptr%anthro_disturbance_label, & currentCohort%patchptr%age_since_anthro_disturbance, & - frac_site_primary) + frac_site_primary, & + harvestable_forest_c, & + available_forest_c, & + harvest_tag) - - if (currentCohort%canopy_layer > 1)then ! Include understory logging mortality rates not associated with disturbance diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index ec04c7eb36..7062c4243f 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -45,6 +45,8 @@ module EDPatchDynamicsMod use FatesInterfaceTypesMod , only : bc_in_type use FatesInterfaceTypesMod , only : hlm_days_per_year use FatesInterfaceTypesMod , only : numpft + use FatesInterfaceTypesMod , only : hlm_num_lu_harvest_cats + use FatesInterfaceTypesMod , only : hlm_harvest_bypass_criteria use FatesGlobals , only : endrun => fates_endrun use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : itrue, ifalse @@ -54,6 +56,8 @@ module EDPatchDynamicsMod use EDLoggingMortalityMod, only : logging_litter_fluxes use EDLoggingMortalityMod, only : logging_time use EDLoggingMortalityMod, only : get_harvest_rate_area + use EDLoggingMortalityMod, only : get_harvest_rate_carbon + use EDLoggingMortalityMod, only : get_harvestable_carbon use EDParamsMod , only : fates_mortality_disturbance_fraction use FatesAllometryMod , only : carea_allom use FatesAllometryMod , only : set_root_fraction @@ -66,6 +70,7 @@ module EDPatchDynamicsMod use FatesConstantsMod , only : n_anthro_disturbance_categories use FatesConstantsMod , only : fates_unset_r8 use FatesConstantsMod , only : fates_unset_int + use FatesConstantsMod , only : hlm_harvest_carbon use EDCohortDynamicsMod , only : InitPRTObject use EDCohortDynamicsMod , only : InitPRTBoundaryConditions use ChecksBalancesMod, only : SiteMassStock @@ -151,7 +156,7 @@ subroutine disturbance_rates( site_in, bc_in) use EDMortalityFunctionsMod , only : mortality_rates ! loging flux use EDLoggingMortalityMod , only : LoggingMortality_frac - + use EDTypesMod , only : ed_resources_management_type ! !ARGUMENTS: type(ed_site_type) , intent(inout), target :: site_in @@ -177,8 +182,12 @@ subroutine disturbance_rates( site_in, bc_in) real(r8) :: dist_rate_ldist_notharvested integer :: threshold_sizeclass integer :: i_dist + integer :: h_index real(r8) :: frac_site_primary real(r8) :: harvest_rate + real(r8) :: harvestable_forest_c(hlm_num_lu_harvest_cats) + real(r8) :: available_forest_c(hlm_num_lu_harvest_cats) + integer :: harvest_tag(hlm_num_lu_harvest_cats) !---------------------------------------------------------------------------------------------- ! Calculate Mortality Rates (these were previously calculated during growth derivatives) @@ -187,6 +196,9 @@ subroutine disturbance_rates( site_in, bc_in) ! first calculate the fractino of the site that is primary land call get_frac_site_primary(site_in, frac_site_primary) + + ! get available biomass for harvest for all patches + call get_harvestable_carbon(site_in, bc_in%site_area, bc_in%hlm_harvest_catnames, harvestable_forest_c, available_forest_c) site_in%harvest_carbon_flux = 0._r8 @@ -218,7 +230,10 @@ subroutine disturbance_rates( site_in, bc_in) bc_in%hlm_harvest_units, & currentPatch%anthro_disturbance_label, & currentPatch%age_since_anthro_disturbance, & - frac_site_primary) + frac_site_primary, & + harvestable_forest_c, & + available_forest_c, & + harvest_tag) currentCohort%lmort_direct = lmort_direct currentCohort%lmort_collateral = lmort_collateral @@ -227,12 +242,13 @@ subroutine disturbance_rates( site_in, bc_in) ! estimate the wood product (trunk_product_site) if (currentCohort%canopy_layer>=1) then + ! kgC m-2 day-1 site_in%harvest_carbon_flux = site_in%harvest_carbon_flux + & currentCohort%lmort_direct * currentCohort%n * & ( currentCohort%prt%GetState(sapw_organ, all_carbon_elements) + & currentCohort%prt%GetState(struct_organ, all_carbon_elements)) * & prt_params%allom_agb_frac(currentCohort%pft) * & - SF_val_CWD_frac(ncwd) * logging_export_frac + SF_val_CWD_frac(ncwd) * logging_export_frac * AREA_INV endif currentCohort => currentCohort%taller @@ -241,6 +257,17 @@ subroutine disturbance_rates( site_in, bc_in) currentPatch => currentPatch%younger end do + ! Determine harvest debt from all three categories + do h_index = 1, hlm_num_lu_harvest_cats + if (harvest_tag(h_index) == 2 .or. & + (harvest_tag(h_index) == 1 .and. .not. (hlm_harvest_bypass_criteria))) then + if(logging_time) then + site_in%resources_management%harvest_debt = site_in%resources_management%harvest_debt + & + bc_in%hlm_harvest_rates(h_index) + end if + end if + end do + ! --------------------------------------------------------------------------------------------- ! Calculate Disturbance Rates based on the mortality rates just calculated ! --------------------------------------------------------------------------------------------- @@ -288,6 +315,11 @@ subroutine disturbance_rates( site_in, bc_in) currentCohort%lmort_infra + & currentCohort%l_degrad ) * & currentCohort%c_area/currentPatch%area + + if(currentPatch%disturbance_rates(dtype_ilog)>1.0) then + write(fates_log(),*) 'See luc mortalities:', currentCohort%lmort_direct, & + currentCohort%lmort_collateral, currentCohort%lmort_infra, currentCohort%l_degrad + end if ! Non-harvested part of the logging disturbance rate dist_rate_ldist_notharvested = dist_rate_ldist_notharvested + currentCohort%l_degrad * & @@ -303,8 +335,14 @@ subroutine disturbance_rates( site_in, bc_in) (currentPatch%area - currentPatch%total_canopy_area) .gt. fates_tiny ) then ! The canopy is NOT closed. - call get_harvest_rate_area (currentPatch%anthro_disturbance_label, bc_in%hlm_harvest_catnames, & - bc_in%hlm_harvest_rates, frac_site_primary, currentPatch%age_since_anthro_disturbance, harvest_rate) + if(bc_in%hlm_harvest_units == hlm_harvest_carbon) then + call get_harvest_rate_carbon (currentPatch%anthro_disturbance_label, bc_in%hlm_harvest_catnames, & + bc_in%hlm_harvest_rates, currentPatch%age_since_anthro_disturbance, harvestable_forest_c, & + available_forest_c, harvest_rate, harvest_tag) + else + call get_harvest_rate_area (currentPatch%anthro_disturbance_label, bc_in%hlm_harvest_catnames, & + bc_in%hlm_harvest_rates, frac_site_primary, currentPatch%age_since_anthro_disturbance, harvest_rate) + end if currentPatch%disturbance_rates(dtype_ilog) = currentPatch%disturbance_rates(dtype_ilog) + & (currentPatch%area - currentPatch%total_canopy_area) * harvest_rate / currentPatch%area diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index bb380b0a00..5ad29d9846 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -223,6 +223,7 @@ subroutine zero_site( site_in ) site_in%promotion_carbonflux = 0._r8 ! Resources management (logging/harvesting, etc) + site_in%resources_management%harvest_debt = 0.0_r8 site_in%resources_management%trunk_product_site = 0.0_r8 ! canopy spread diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 3d70760090..678ce56502 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -75,6 +75,7 @@ module EDMainMod use FatesAllometryMod , only : h_allom,tree_sai,tree_lai use FatesPlantHydraulicsMod , only : UpdateSizeDepRhizHydStates use EDLoggingMortalityMod , only : IsItLoggingTime + use EDLoggingMortalityMod , only : get_harvestable_carbon use EDPatchDynamicsMod , only : get_frac_site_primary use FatesGlobals , only : endrun => fates_endrun use ChecksBalancesMod , only : SiteMassStock @@ -288,6 +289,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! FIX(SPM,032414) refactor so everything goes through interface ! ! !USES: + use FatesInterfaceTypesMod, only : hlm_num_lu_harvest_cats use FatesInterfaceTypesMod, only : hlm_use_cohort_age_tracking use FatesConstantsMod, only : itrue ! !ARGUMENTS: @@ -317,9 +319,16 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) !----------------------------------------------------------------------- real(r8) :: frac_site_primary + real(r8) :: harvestable_forest_c(hlm_num_lu_harvest_cats) + real(r8) :: available_forest_c(hlm_num_lu_harvest_cats) + integer :: harvest_tag(hlm_num_lu_harvest_cats) + call get_frac_site_primary(currentSite, frac_site_primary) + ! Patch level biomass are required for C-based harvest + call get_harvestable_carbon(currentSite, bc_in%site_area, bc_in%hlm_harvest_catnames, harvestable_forest_c, available_forest_c) + ! Set a pointer to this sites carbon12 mass balance site_cmass => currentSite%mass_balance(element_pos(carbon12_element)) @@ -352,7 +361,8 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ft = currentCohort%pft ! Calculate the mortality derivatives - call Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_primary ) + call Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_primary, & + harvestable_forest_c, available_forest_c, harvest_tag) ! ----------------------------------------------------------------------------- ! Apply Plant Allocation and Reactive Transport diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index e77a83e00d..678fcfe40c 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -574,6 +574,7 @@ module EDTypesMod type, public :: ed_resources_management_type real(r8) :: trunk_product_site ! Actual trunk product at site level KgC/site + real(r8) :: harvest_debt ! the amount of kgC per site that did not successfully harvested !debug variables real(r8) :: delta_litter_stock ! kgC/site = kgC/ha @@ -1076,6 +1077,9 @@ subroutine dump_cohort(ccohort) write(fates_log(),*) 'co%hmort = ', ccohort%hmort write(fates_log(),*) 'co%frmort = ', ccohort%frmort write(fates_log(),*) 'co%asmort = ', ccohort%asmort + write(fates_log(),*) 'co%lmort_direct = ', ccohort%lmort_direct + write(fates_log(),*) 'co%lmort_collateral = ', ccohort%lmort_collateral + write(fates_log(),*) 'co%lmort_infra = ', ccohort%lmort_infra write(fates_log(),*) 'co%isnew = ', ccohort%isnew write(fates_log(),*) 'co%dndt = ', ccohort%dndt write(fates_log(),*) 'co%dhdt = ', ccohort%dhdt @@ -1087,6 +1091,7 @@ subroutine dump_cohort(ccohort) write(fates_log(),*) 'co%cambial_mort = ', ccohort%cambial_mort write(fates_log(),*) 'co%size_class = ', ccohort%size_class write(fates_log(),*) 'co%size_by_pft_class = ', ccohort%size_by_pft_class + if (associated(ccohort%co_hydr) ) then call dump_cohort_hydr(ccohort) endif diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index f9fa005b4c..6b1c015791 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -274,6 +274,7 @@ module FatesHistoryInterfaceMod integer :: ih_fall_disturbance_rate_si integer :: ih_potential_disturbance_rate_si integer :: ih_harvest_carbonflux_si + integer :: ih_harvest_debt_si ! Indices to site by size-class by age variables integer :: ih_nplant_si_scag @@ -1859,6 +1860,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_fall_disturbance_rate_si => this%hvars(ih_fall_disturbance_rate_si)%r81d, & hio_potential_disturbance_rate_si => this%hvars(ih_potential_disturbance_rate_si)%r81d, & hio_harvest_carbonflux_si => this%hvars(ih_harvest_carbonflux_si)%r81d, & + hio_harvest_debt_si => this%hvars(ih_harvest_debt_si)%r81d, & hio_gpp_si_scpf => this%hvars(ih_gpp_si_scpf)%r82d, & hio_npp_totl_si_scpf => this%hvars(ih_npp_totl_si_scpf)%r82d, & hio_npp_leaf_si_scpf => this%hvars(ih_npp_leaf_si_scpf)%r82d, & @@ -2148,6 +2150,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_potential_disturbance_rate_si(io_si) = sum(sites(s)%potential_disturbance_rates(1:N_DIST_TYPES)) hio_harvest_carbonflux_si(io_si) = sites(s)%harvest_carbon_flux + hio_harvest_debt_si(io_si) = sites(s)%resources_management%harvest_debt ipa = 0 cpatch => sites(s)%oldest_patch @@ -4852,6 +4855,11 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_harvest_carbonflux_si ) + call this%set_history_var(vname='HARVEST_DEBT', units='kg C', & + long='Accumulated carbon failed to be harvested', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_harvest_debt_si ) + ! Canopy Resistance call this%set_history_var(vname='C_STOMATA', units='umol m-2 s-1', & diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 16f0607e7d..f3fc165037 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1171,6 +1171,7 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) hlm_sf_anthro_ignitions_def = unset_int hlm_use_planthydro = unset_int hlm_use_lu_harvest = unset_int + hlm_harvest_bypass_criteria = unset_int hlm_num_lu_harvest_cats = unset_int hlm_use_cohort_age_tracking = unset_int hlm_use_logging = unset_int @@ -1232,6 +1233,13 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) call endrun(msg=errMsg(sourcefile, __LINE__)) end if + if ( (hlm_harvest_bypass_criteria .lt. 0).or.(hlm_harvest_bypass_criteria .gt. 1) ) then + if (fates_global_verbose()) then + write(fates_log(), *) 'The FATES bypass harvest scenario flag must be 0 or 1, exiting' + end if + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + if ( (hlm_num_lu_harvest_cats .lt. 0) ) then if (fates_global_verbose()) then write(fates_log(), *) 'The FATES number of hlm harvest cats must be >= 0, exiting' @@ -1611,6 +1619,12 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) write(fates_log(),*) 'Transfering hlm_use_lu_harvest= ',ival,' to FATES' end if + case('use_harvest_bypass_criteria') + hlm_harvest_bypass_criteria = ival + if (fates_global_verbose()) then + write(fates_log(),*) 'Transfering hlm_harvest_bypass_criteria= ',ival,' to FATES' + end if + case('num_lu_harvest_cats') hlm_num_lu_harvest_cats = ival if (fates_global_verbose()) then diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index f7e1b95d20..3c33a4088e 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -117,6 +117,12 @@ module FatesInterfaceTypesMod ! If 1, it automatically sets ! hlm_use_logging to 1 + integer, public :: hlm_harvest_bypass_criteria ! This flag signals whether or not to bypass the logging criteria + ! when using carbon-based harvest and all available forest C under + ! criteria are not enough + ! 0 = do not bypass criteria + ! 1 = allow to bypass the criteria + integer, public :: hlm_num_lu_harvest_cats ! number of hlm harvest categories (e.g. primary forest harvest, secondary young forest harvest, etc.) ! this is the first dimension of: ! harvest_rates in dynHarvestMod @@ -510,6 +516,8 @@ module FatesInterfaceTypesMod real(r8) :: pprodharv10_forest_mean ! harvest mortality proportion of deadstem to 10-yr pool + real(r8) :: site_area ! Actual area of current site [m2], only used in carbon-based harvest + ! Fixed biogeography mode real(r8), allocatable :: pft_areafrac(:) ! Fractional area of the FATES column occupied by each PFT From dd380e5fe2b86977eba22b49d9dc5e71c80d7c8b Mon Sep 17 00:00:00 2001 From: Adrianna Foster Date: Tue, 8 Mar 2022 08:43:50 -0700 Subject: [PATCH 134/852] update history variables --- main/FatesHistoryInterfaceMod.F90 | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 19eee6b97d..5f6f1e6dbe 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -1530,7 +1530,7 @@ end subroutine flush_hvars ! ===================================================================================== subroutine set_history_var(this, vname, units, long, use_default, avgflag, vtype, & - hlms, upfreq, ivar, initialize, index) + hlms, upfreq, ivar, initialize, index, flush_to_zero) use FatesUtilsMod, only : check_hlm_list use FatesInterfaceTypesMod, only : hlm_name @@ -1554,6 +1554,7 @@ subroutine set_history_var(this, vname, units, long, use_default, avgflag, vtype ! explict name (for fast reference during update) ! A zero is passed back when the variable is ! not used + logical, intent(in), optional :: flush_to_zero ! locals integer :: ub1, lb1, ub2, lb2 ! Bounds for allocating the var @@ -1568,10 +1569,10 @@ subroutine set_history_var(this, vname, units, long, use_default, avgflag, vtype ! We make one exception to this rule, for the fates_fraction variable. That way ! we can always know what fraction of the gridcell FATES is occupying. - if ( trim(vname) .ne. 'FATES_FRACTION') then - flushval = hlm_hio_ignore_val + if (present(flush_to_zero) .and. flush_to_zero) then + flushval = 0.0_r8 else - flushval = 0._r8 + flushval = hlm_hio_ignore_val endif write_var = check_hlm_list(trim(hlms), trim(hlm_name)) @@ -4419,11 +4420,11 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_area_trees_si) - call this%set_history_var(vname='FATES_FRACTION', units='m2 m-2', & + call this%set_history_var(vname='FATES_FRACTION', units='m2 m-2', & long='total gridcell fraction which FATES is running over', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_fates_fraction_si) + index=ih_fates_fraction_si, flush_to_zero=.true.) call this%set_history_var(vname='FATES_COLD_STATUS', units='', & long='site-level cold status, 0=not cold-dec, 1=too cold for leaves, 2=not too cold', & From 7ed9029549aa61d20583e7b9605da9ddb3d549a4 Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Wed, 2 Mar 2022 09:36:49 -0800 Subject: [PATCH 135/852] [ and remove the last damage_clux and damage_rate variables ] [ ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary: no testing --- main/EDMainMod.F90 | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index bcee878b3e..3b92b68e73 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -597,12 +597,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentCohort%pft, currentCohort%crowndamage, currentCohort%c_area) - currentSite%recovery_rate(currentCohort%crowndamage, nc%crowndamage) = & - currentSite%recovery_rate(currentCohort%crowndamage, nc%crowndamage) + nc%n - currentSite%recovery_cflux(currentCohort%crowndamage, nc%crowndamage) = & - currentSite%recovery_cflux(currentCohort%crowndamage, nc%crowndamage) + & - nc%n * nc_carbon - + !----------- Insert copy into linked list ----------------------! nc%shorter => currentCohort if(associated(currentCohort%taller))then @@ -618,15 +613,6 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) end if ! end if crowndamage > 1 - - ! fill in the diagonals - i.e. those that did not recover - currentSite%recovery_rate(currentCohort%crowndamage, currentCohort%crowndamage) = & - currentSite%recovery_rate(currentCohort%crowndamage, currentCohort%crowndamage) +& - currentCohort%n - currentSite%recovery_cflux(currentCohort%crowndamage, currentCohort%crowndamage) = & - currentSite%recovery_cflux(currentCohort%crowndamage, currentCohort%crowndamage) + & - currentCohort%n * cc_carbon - end if ! end if crowndamage is on From 63edb539bb980be6ac989c628e48e4b14091878a Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Mon, 7 Mar 2022 13:19:40 -0800 Subject: [PATCH 136/852] [ Change default damage param values ] [ Increase fates_damage_mort_p1 so that damage-dependent mortality is off by default. ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary:no testing --- 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 4a9d10b1f5..80518fd58e 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -914,7 +914,7 @@ data: fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; - fates_damage_mort_p1 = 0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9 ; + fates_damage_mort_p1 = 9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0 ; fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5 ; From 672582234c50b4fd7ad005d9ab910fe59d317c68 Mon Sep 17 00:00:00 2001 From: Shijie Shu Date: Thu, 10 Mar 2022 12:55:42 -0800 Subject: [PATCH 137/852] Updated minor corrections from fatesluc branch. --- biogeochem/EDLoggingMortalityMod.F90 | 6 ++++-- biogeochem/FatesAllometryMod.F90 | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 0fb884df04..4062b8c2d4 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -1137,9 +1137,11 @@ subroutine UpdateHarvestC(currentSite,bc_in,bc_out) end if bc_out%hrv_deadstemc_to_prod10c = bc_out%hrv_deadstemc_to_prod10c + & - currentSite%harvest_carbon_flux * bc_in%pprodharv10_forest_mean * unit_trans_factor + currentSite%mass_balance(element_pos(carbon12_element))%wood_product * & + AREA_INV * pprodharv10_forest_mean * unit_trans_factor bc_out%hrv_deadstemc_to_prod100c = bc_out%hrv_deadstemc_to_prod100c + & - currentSite%harvest_carbon_flux * (1-bc_in%pprodharv10_forest_mean) * unit_trans_factor + currentSite%mass_balance(element_pos(carbon12_element))%wood_product * & + AREA_INV * (1 - pprodharv10_forest_mean) * unit_trans_factor return end subroutine UpdateHarvestC diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index a24653e652..99f7b80688 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -2336,7 +2336,7 @@ subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl ) end if call h_allom(d,ipft,h) - if(counter>10)then + if(counter>20)then write(fates_log(),*) 'dbh counter: ',counter,' is woody: ',& int(prt_params%woody(ipft))==itrue end if From c8d86d1517580b26cef43557bbd8f077fe802929 Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Thu, 10 Mar 2022 15:55:52 -0800 Subject: [PATCH 138/852] [ remove damage_cflux ] [ . ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary: no testing --- biogeochem/EDPatchDynamicsMod.F90 | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 3af8aae71d..63e29f6f6c 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1322,13 +1322,6 @@ subroutine spawn_patches( currentSite, bc_in) fnrt_c = nc_d%prt%GetState(fnrt_organ, all_carbon_elements) - currentSite%damage_cflux(currentCohort%crowndamage, cd) = & - currentSite%damage_cflux(currentCohort%crowndamage, cd) + & - (leaf_m_post + sapw_m_post + struct_m_post + store_m_post + fnrt_c) * cd_n * & - hlm_days_per_year - - currentSite%damage_rate(currentCohort%crowndamage, cd) = & - currentSite%damage_rate(currentCohort%crowndamage, cd) + cd_n * hlm_days_per_year if(hlm_use_canopy_damage .eq. itrue) then currentSite%crownarea_canopy_damage = currentSite%crownarea_canopy_damage + & @@ -1383,29 +1376,6 @@ subroutine spawn_patches( currentSite, bc_in) end if ! end if damage is on - if(hlm_use_canopy_damage .eq. itrue .and. currentCohort%canopy_layer == 1 .or.& - hlm_use_understory_damage .eq. itrue .and. currentCohort%canopy_layer > 1) then - - if(.not. currentCohort%isnew) then - - ! Keep track of number and carbon that stayed in the same damage class - sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) - struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) - leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) - fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) - store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) - repro_c = currentCohort%prt%GetState(repro_organ, all_carbon_elements) - - currentSite%damage_cflux(currentCohort%crowndamage, currentCohort%crowndamage) = & - currentSite%damage_cflux(currentCohort%crowndamage, currentCohort%crowndamage) + & - (sapw_c + struct_c + leaf_c + fnrt_c + store_c + repro_c) * currentCohort%n - - currentSite%damage_rate(currentCohort%crowndamage, currentCohort%crowndamage) = & - currentSite%damage_rate(currentCohort%crowndamage, currentCohort%crowndamage) + currentCohort%n - - end if - end if ! end if damage is on - ! Put new undamaged cohorts in the correct place in the linked list if (nc%n > 0.0_r8) then storebigcohort => new_patch%tallest From 6c83771030b53dac65ae53701f9ad6fa1f2bb569 Mon Sep 17 00:00:00 2001 From: Shijie Shu Date: Thu, 10 Mar 2022 16:58:00 -0800 Subject: [PATCH 139/852] Remove harvest_carbon_flux and redefine pprodharv10_forest_mean as a FATES parameter. --- biogeochem/EDCanopyStructureMod.F90 | 2 +- biogeochem/EDLoggingMortalityMod.F90 | 15 ++++++++++----- biogeochem/EDPatchDynamicsMod.F90 | 12 ------------ main/EDParamsMod.F90 | 8 ++++++++ main/EDTypesMod.F90 | 1 - main/FatesHistoryInterfaceMod.F90 | 2 +- main/FatesInterfaceTypesMod.F90 | 2 -- parameter_files/fates_params_default.cdl | 5 +++++ 8 files changed, 25 insertions(+), 22 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index aef8e3bfa5..e1fad85b66 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -2026,7 +2026,7 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_in,bc_out) end if ! Pass FATES Harvested C to bc_out. - call UpdateHarvestC(sites(s),bc_in(s),bc_out(s)) + call UpdateHarvestC(sites(s),bc_out(s)) end do diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 976fea5a1c..a61ef78426 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -813,7 +813,7 @@ end subroutine logging_litter_fluxes ! ===================================================================================== - subroutine UpdateHarvestC(currentSite,bc_in,bc_out) + subroutine UpdateHarvestC(currentSite,bc_out) ! ---------------------------------------------------------------------------------- ! Added by Shijie Shu. @@ -821,11 +821,14 @@ subroutine UpdateHarvestC(currentSite,bc_in,bc_out) ! Harvested C flux in HLM. ! ---------------------------------------------------------------------------------- use EDtypesMod , only : ed_site_type - use FatesInterfaceTypesMod , only : bc_in_type, bc_out_type + use EDTypesMod , only : AREA_INV + use PRTGenericMod , only : element_pos + use PRTGenericMod , only : carbon12_element + use FatesInterfaceTypesMod , only : bc_out_type + use EDParamsMod , only : pprodharv10_forest_mean ! Arguments type(ed_site_type), intent(inout), target :: currentSite ! site structure - type(bc_in_type), intent(in) :: bc_in type(bc_out_type), intent(inout) :: bc_out integer :: icode @@ -869,9 +872,11 @@ subroutine UpdateHarvestC(currentSite,bc_in,bc_out) end if bc_out%hrv_deadstemc_to_prod10c = bc_out%hrv_deadstemc_to_prod10c + & - currentSite%harvest_carbon_flux * bc_in%pprodharv10_forest_mean * unit_trans_factor + currentSite%mass_balance(element_pos(carbon12_element))%wood_product * & + AREA_INV * pprodharv10_forest_mean * unit_trans_factor bc_out%hrv_deadstemc_to_prod100c = bc_out%hrv_deadstemc_to_prod100c + & - currentSite%harvest_carbon_flux * (1-bc_in%pprodharv10_forest_mean) * unit_trans_factor + currentSite%mass_balance(element_pos(carbon12_element))%wood_product * & + AREA_INV * (1 - pprodharv10_forest_mean) * unit_trans_factor return end subroutine UpdateHarvestC diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index ec04c7eb36..c2ad0236c7 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -188,8 +188,6 @@ subroutine disturbance_rates( site_in, bc_in) ! first calculate the fractino of the site that is primary land call get_frac_site_primary(site_in, frac_site_primary) - site_in%harvest_carbon_flux = 0._r8 - currentPatch => site_in%oldest_patch do while (associated(currentPatch)) @@ -225,16 +223,6 @@ subroutine disturbance_rates( site_in, bc_in) currentCohort%lmort_infra = lmort_infra currentCohort%l_degrad = l_degrad - ! estimate the wood product (trunk_product_site) - if (currentCohort%canopy_layer>=1) then - site_in%harvest_carbon_flux = site_in%harvest_carbon_flux + & - currentCohort%lmort_direct * currentCohort%n * & - ( currentCohort%prt%GetState(sapw_organ, all_carbon_elements) + & - currentCohort%prt%GetState(struct_organ, all_carbon_elements)) * & - prt_params%allom_agb_frac(currentCohort%pft) * & - SF_val_CWD_frac(ncwd) * logging_export_frac - endif - currentCohort => currentCohort%taller end do currentPatch%disturbance_mode = fates_unset_int diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 8162939bc3..825d42b400 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -152,6 +152,10 @@ module EDParamsMod ! leftovers will be left onsite as large CWD character(len=param_string_length),parameter,public :: logging_name_export_frac ="fates_logging_export_frac" + real(r8),protected,public :: pprodharv10_forest_mean ! "mean harvest mortality proportion of deadstem to 10-yr + ! product pool (pprodharv10) of all woody PFT types + character(len=param_string_length),parameter,public :: logging_name_pprodharv10="fates_pprodharv10_forest_mean" + real(r8),protected,public :: eca_plant_escalar ! scaling factor for plant fine root biomass to ! calculate nutrient carrier enzyme abundance (ECA) @@ -208,6 +212,7 @@ subroutine FatesParamsInit() logging_event_code = nan logging_dbhmax_infra = nan logging_export_frac = nan + pprodharv10_forest_mean = nan eca_plant_escalar = nan q10_mr = nan q10_froz = nan @@ -500,6 +505,9 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetreiveParameter(name=logging_name_export_frac, & data=logging_export_frac) + call fates_params%RetreiveParameter(name=logging_name_pprodharv10, & + data=pprodharv10_forest_mean) + call fates_params%RetreiveParameter(name=eca_name_plant_escalar, & data=eca_plant_escalar) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index e77a83e00d..a52f73f8ec 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -812,7 +812,6 @@ module EDTypesMod real(r8) :: disturbance_rates_secondary_to_secondary(N_DIST_TYPES) ! actual disturbance rates from secondary patches to secondary patches [m2/m2/day] real(r8) :: potential_disturbance_rates(N_DIST_TYPES) ! "potential" disturb rates (i.e. prior to the "which is most" logic) [m2/m2/day] real(r8) :: primary_land_patchfusion_error ! error term in total area of primary patches associated with patch fusion [m2/m2/day] - real(r8) :: harvest_carbon_flux ! diagnostic site level flux of carbon as harvested plants [kg C / m2 / day] end type ed_site_type diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index f9fa005b4c..d8368966b7 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2147,7 +2147,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_potential_disturbance_rate_si(io_si) = sum(sites(s)%potential_disturbance_rates(1:N_DIST_TYPES)) - hio_harvest_carbonflux_si(io_si) = sites(s)%harvest_carbon_flux + hio_harvest_carbonflux_si(io_si) = sites(s)%mass_balance(element_pos(carbon12_element))%wood_product * AREA_INV ipa = 0 cpatch => sites(s)%oldest_patch diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index f7e1b95d20..f3982f235a 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -508,8 +508,6 @@ module FatesInterfaceTypesMod integer :: hlm_harvest_units ! what units are the harvest rates specified in? [area vs carbon] - real(r8) :: pprodharv10_forest_mean ! harvest mortality proportion of deadstem to 10-yr pool - ! Fixed biogeography mode real(r8), allocatable :: pft_areafrac(:) ! Fractional area of the FATES column occupied by each PFT diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 333167ef5d..370f3f5d9e 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -632,6 +632,9 @@ variables: double fates_logging_mechanical_frac ; fates_logging_mechanical_frac:units = "fraction" ; fates_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; + double fates_pprodharv10_forest_mean ; + fates_pprodharv10_forest_mean:units = "fraction" ; + fates_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types." ; double fates_mort_disturb_frac ; fates_mort_disturb_frac:units = "fraction" ; fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; @@ -1306,6 +1309,8 @@ data: fates_logging_mechanical_frac = 0.05 ; + fates_pprodharv10_forest_mean = 0.8125 ; + fates_mort_disturb_frac = 1 ; fates_mort_understorey_death = 0.55983 ; From 3a593ad8a438c994888a877daaae24543cd5f084 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 11 Mar 2022 11:15:47 -0800 Subject: [PATCH 140/852] remove the redundant calls in update_hlm_dynamics. See discussion in #823 and #821 --- biogeochem/EDCanopyStructureMod.F90 | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 58552ffa11..eb3ef5fbfd 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1936,21 +1936,6 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) currentCohort => currentPatch%shortest do while(associated(currentCohort)) - if (hlm_use_sp.eq.ifalse) then - ! make sure that allometries are correct - call carea_allom(currentCohort%dbh,currentCohort%n,sites(s)%spread,& - currentCohort%pft,currentCohort%c_area) - - currentCohort%treelai = tree_lai(currentCohort%prt%GetState(leaf_organ, all_carbon_elements), & - currentCohort%pft, currentCohort%c_area, currentCohort%n, & - currentCohort%canopy_layer, currentPatch%canopy_layer_tlai,currentCohort%vcmax25top ) - - currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_trim, & - currentCohort%c_area, currentCohort%n, currentCohort%canopy_layer, & - currentPatch%canopy_layer_tlai, currentCohort%treelai , & - currentCohort%vcmax25top,4) - endif - total_patch_leaf_stem_area = total_patch_leaf_stem_area + & (currentCohort%treelai + currentCohort%treesai) * currentCohort%c_area currentCohort => currentCohort%taller From d1a2bddf02bd4d602dd49704a628066e0e398ad8 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 11 Mar 2022 12:24:56 -0800 Subject: [PATCH 141/852] refactoring UpdatePatchLAI to break out the cohort lai updates to a separate subroutine --- biogeochem/EDCanopyStructureMod.F90 | 69 ++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 21 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index eb3ef5fbfd..d354c13fc6 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -55,6 +55,8 @@ module EDCanopyStructureMod public :: canopy_summarization public :: update_hlm_dynamics public :: UpdateFatesAvgSnowDepth + public :: UpdatePatchLAI + public :: UpdateCohortLAI logical, parameter :: debug=.false. @@ -2206,27 +2208,10 @@ subroutine UpdatePatchLAI(currentPatch, patch_lai) if (currentCohort%canopy_layer .eq. cl) then cl = currentCohort%canopy_layer ft = currentCohort%pft - leaf_c = currentCohort%prt%GetState(leaf_organ,all_carbon_elements) - - ! Note that tree_lai has an internal check on the canopy - currentCohort%treelai = tree_lai(leaf_c, currentCohort%pft, currentCohort%c_area, & - currentCohort%n, currentCohort%canopy_layer, & - currentPatch%canopy_layer_tlai,currentCohort%vcmax25top ) - - if (hlm_use_sp .eq. ifalse) then - currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_trim, & - currentCohort%c_area, currentCohort%n, currentCohort%canopy_layer, & - currentPatch%canopy_layer_tlai, currentCohort%treelai , & - currentCohort%vcmax25top,4) - end if - - ! Update the cohort lai and sai - currentCohort%lai = currentCohort%treelai *currentCohort%c_area/currentPatch%total_canopy_area - currentCohort%sai = currentCohort%treesai *currentCohort%c_area/currentPatch%total_canopy_area - - ! Number of actual vegetation layers in this cohort's crown - currentCohort%nv = count((currentCohort%treelai+currentCohort%treesai) .gt. dlower_vai(:)) + 1 - + + ! Update the cohort level lai and related variables + call UpdateCohortLAI(currentCohort,currentPatch%canopy_layer_tlai,currentPatch%total_canopy_area) + ! Update the number of number of vegetation layers currentPatch%ncan(cl,ft) = max(currentPatch%ncan(cl,ft),currentCohort%NV) @@ -2242,7 +2227,49 @@ subroutine UpdatePatchLAI(currentPatch, patch_lai) end do canopyloop end subroutine UpdatePatchLAI + ! =============================================================================================== + + subroutine UpdateCohortLAI(currentCohort, canopy_layer_tlai, patcharea) + + ! We need to pass in the the patch as well, since this cohort might not yet + ! be inserted into the cohort list such as during create_cohort procedure + + ! patch area could be patch%total_canopy_area or patch%area depending on call + + + ! Uses + use EDtypesMod, only : dlower_vai + + ! Arguments + type(ed_cohort_type),intent(inout), target :: currentCohort + real(r8), intent(in) :: canopy_layer_tlai(nclmax) ! total leaf area index of each canopy layer + real(r8), intent(in) :: patcharea ! either patch%total_canopy_area or patch%area + + ! Obtain the leaf carbon + leaf_c = currentCohort%prt%GetState(leaf_organ,all_carbon_elements) + + ! Note that tree_lai has an internal check on the canopy locatoin + currentCohort%treelai = tree_lai(leaf_c, currentCohort%pft, currentCohort%c_area, & + currentCohort%n, currentCohort%canopy_layer, & + canopy_layer_tlai,currentCohort%vcmax25top ) + + if (hlm_use_sp .eq. ifalse) then + currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_trim, & + currentCohort%c_area, currentCohort%n, currentCohort%canopy_layer, & + canopy_layer_tlai, currentCohort%treelai , & + currentCohort%vcmax25top,4) + end if + + ! Update the cohort lai and sai + currentCohort%lai = currentCohort%treelai *currentCohort%c_area/patcharea + currentCohort%sai = currentCohort%treesai *currentCohort%c_area/patcharea + + ! Number of actual vegetation layers in this cohort's crown + currentCohort%nv = count((currentCohort%treelai+currentCohort%treesai) .gt. dlower_vai(:)) + 1 + + end subroutine UpdateCohortLAI + ! =============================================================================================== function NumPotentialCanopyLayers(currentPatch,site_spread,include_substory) result(z) From 53d1312754c71f912aff35f30dbee10ff29a76e3 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 11 Mar 2022 14:31:23 -0800 Subject: [PATCH 142/852] forgot to remove the cl index inside the do loop --- biogeochem/EDCanopyStructureMod.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 58552ffa11..919e8c2290 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -2219,7 +2219,6 @@ subroutine UpdatePatchLAI(currentPatch, patch_lai) ! Only update the current cohort tree lai if lai of the above layers have been calculated if (currentCohort%canopy_layer .eq. cl) then - cl = currentCohort%canopy_layer ft = currentCohort%pft leaf_c = currentCohort%prt%GetState(leaf_organ,all_carbon_elements) From 1fdf747ee98a747ce9543a620d2162541dd63707 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 11 Mar 2022 15:02:26 -0800 Subject: [PATCH 143/852] fix missing local variable --- biogeochem/EDCanopyStructureMod.F90 | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 9539ab0b17..99cac36684 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -2192,7 +2192,6 @@ subroutine UpdatePatchLAI(currentPatch, patch_lai) type(ed_cohort_type), pointer :: currentCohort integer :: cl ! Canopy layer index integer :: ft ! Plant functional type index - real(r8) :: leaf_c ! leaf carbon [kg] ! Calculate LAI of layers above. Because it is possible for some understory cohorts ! to be taller than cohorts in the top canopy layer, we must iterate through the @@ -2230,11 +2229,7 @@ end subroutine UpdatePatchLAI subroutine UpdateCohortLAI(currentCohort, canopy_layer_tlai, patcharea) - ! We need to pass in the the patch as well, since this cohort might not yet - ! be inserted into the cohort list such as during create_cohort procedure - - ! patch area could be patch%total_canopy_area or patch%area depending on call - + ! Update LAI and related variables for a given cohort ! Uses use EDtypesMod, only : dlower_vai @@ -2244,6 +2239,8 @@ subroutine UpdateCohortLAI(currentCohort, canopy_layer_tlai, patcharea) real(r8), intent(in) :: canopy_layer_tlai(nclmax) ! total leaf area index of each canopy layer real(r8), intent(in) :: patcharea ! either patch%total_canopy_area or patch%area + ! Local variables + real(r8) :: leaf_c ! leaf carbon [kg] ! Obtain the leaf carbon leaf_c = currentCohort%prt%GetState(leaf_organ,all_carbon_elements) From b83eeff7a13154a82be1a379440106ce46b5e655 Mon Sep 17 00:00:00 2001 From: Shijie Shu <92333861+sshu88@users.noreply.github.com> Date: Mon, 14 Mar 2022 12:13:35 -0500 Subject: [PATCH 144/852] Update biogeochem/EDLoggingMortalityMod.F90 Co-authored-by: Gregory Lemieux <7565064+glemieux@users.noreply.github.com> --- biogeochem/EDLoggingMortalityMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index a61ef78426..2a451358d7 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -62,7 +62,7 @@ module EDLoggingMortalityMod use FatesAllometryMod , only : set_root_fraction use FatesConstantsMod , only : primaryforest, secondaryforest, secondary_age_threshold use FatesConstantsMod , only : fates_tiny - use FatesConstantsMod , only : months_per_year, days_per_sec, years_per_day + use FatesConstantsMod , only : months_per_year, days_per_sec, years_per_day, g_per_kg use FatesConstantsMod , only : hlm_harvest_area_fraction use FatesConstantsMod , only : hlm_harvest_carbon use FatesConstantsMod, only : fates_check_param_set From c07fbdb77f99ee471f31c6081491a8efaff691a9 Mon Sep 17 00:00:00 2001 From: Shijie Shu <92333861+sshu88@users.noreply.github.com> Date: Mon, 14 Mar 2022 12:13:48 -0500 Subject: [PATCH 145/852] Update biogeochem/EDLoggingMortalityMod.F90 Co-authored-by: Gregory Lemieux <7565064+glemieux@users.noreply.github.com> --- biogeochem/EDLoggingMortalityMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 2a451358d7..c1ac6694c8 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -862,7 +862,7 @@ subroutine UpdateHarvestC(currentSite,bc_out) unit_trans_factor = 1000._r8 * days_per_sec / 31._r8 else if((hlm_current_month == 4) .or. (hlm_current_month == 6) .or. & (hlm_current_month == 9) .or. (hlm_current_month == 11)) then - unit_trans_factor = 1000._r8 * days_per_sec / 30._r8 + unit_trans_factor = g_per_kg * days_per_sec / 30._r8 else unit_trans_factor = 1000._r8 * days_per_sec / 28._r8 end if From c4422f1e0781b46ea31ee8c206b97fffb179b9d1 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 15 Mar 2022 12:17:40 -0400 Subject: [PATCH 146/852] various updates to the cnp acquisition algorithm, including symbiotic fixation --- biogeochem/EDCanopyStructureMod.F90 | 52 +- biogeochem/EDCohortDynamicsMod.F90 | 57 +- biogeochem/EDLoggingMortalityMod.F90 | 2 +- biogeochem/EDMortalityFunctionsMod.F90 | 5 +- biogeochem/EDPatchDynamicsMod.F90 | 17 +- biogeochem/EDPhysiologyMod.F90 | 13 +- biogeochem/FatesAllometryMod.F90 | 3 +- biogeochem/FatesSoilBGCFluxMod.F90 | 121 ++- biogeophys/FatesPlantRespPhotosynthMod.F90 | 39 +- fire/SFMainMod.F90 | 9 +- main/ChecksBalancesMod.F90 | 11 - main/EDInitMod.F90 | 3 - main/EDMainMod.F90 | 146 +-- main/EDPftvarcon.F90 | 21 +- main/EDTypesMod.F90 | 34 +- main/FatesHistoryInterfaceMod.F90 | 244 +++-- main/FatesRestartInterfaceMod.F90 | 92 +- parteh/PRTAllometricCNPMod.F90 | 1083 +++++++++----------- parteh/PRTGenericMod.F90 | 159 +-- 19 files changed, 979 insertions(+), 1132 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 2d3dc30e97..2e0ad6159e 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -19,7 +19,7 @@ module EDCanopyStructureMod use EDCohortDynamicsMod , only : InitPRTBoundaryConditions use EDCohortDynamicsMod , only : SendCohortToLitter use FatesAllometryMod , only : tree_lai - use FatesAllometryMod , only : tree_sai + use FatesAllometryMod , only : tree_sai,bstore_allom use EDtypesMod , only : ed_site_type, ed_patch_type, ed_cohort_type use EDTypesMod , only : nclmax use EDTypesMod , only : nlevleaf @@ -34,7 +34,6 @@ module EDCanopyStructureMod use FatesPlantHydraulicsMod, only : UpdateH2OVeg,InitHydrCohort, RecruitWaterStorage use EDTypesMod , only : maxCohortsPerPatch use PRTGenericMod, only : leaf_organ - use PRTGenericMod, only : all_carbon_elements use PRTGenericMod, only : leaf_organ use PRTGenericMod, only : fnrt_organ use PRTGenericMod, only : sapw_organ @@ -42,6 +41,7 @@ module EDCanopyStructureMod use PRTGenericMod, only : repro_organ use PRTGenericMod, only : struct_organ use PRTGenericMod, only : SetState + use PRTGenericMod, only : carbon12_element use FatesRunningMeanMod, only : ema_lpa, ema_60day ! CIME Globals @@ -142,7 +142,7 @@ subroutine canopy_structure( currentSite , bc_in ) logical :: area_not_balanced ! logical controlling if the patch layer areas ! have successfully been redistributed integer :: return_code ! math checks on variables will return>0 if problems exist - + real(r8) :: target_storec ! We only iterate because of possible imprecisions generated by the cohort ! termination process. These should be super small, so at the most ! try to re-balance 3 times. If that doesn't give layer areas @@ -320,7 +320,7 @@ subroutine canopy_structure( currentSite , bc_in ) currentCohort => currentCohort%shorter enddo endif - + currentPatch => currentPatch%younger enddo !patch @@ -625,11 +625,11 @@ subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr,bc_in) if(currentCohort%canopy_layer == i_lyr )then cc_loss = currentCohort%excl_weight - leaf_c = currentCohort%prt%GetState(leaf_organ,all_carbon_elements) - store_c = currentCohort%prt%GetState(store_organ,all_carbon_elements) - fnrt_c = currentCohort%prt%GetState(fnrt_organ,all_carbon_elements) - sapw_c = currentCohort%prt%GetState(sapw_organ,all_carbon_elements) - struct_c = currentCohort%prt%GetState(struct_organ,all_carbon_elements) + leaf_c = currentCohort%prt%GetState(leaf_organ,carbon12_element) + store_c = currentCohort%prt%GetState(store_organ,carbon12_element) + fnrt_c = currentCohort%prt%GetState(fnrt_organ,carbon12_element) + sapw_c = currentCohort%prt%GetState(sapw_organ,carbon12_element) + struct_c = currentCohort%prt%GetState(struct_organ,carbon12_element) if ( (cc_loss-currentCohort%c_area) > -nearzero .and. & (cc_loss-currentCohort%c_area) < area_target_precision ) then @@ -833,11 +833,11 @@ subroutine PromoteIntoLayer(currentSite,currentPatch,i_lyr) !look at the cohorts in the canopy layer below... if(currentCohort%canopy_layer == i_lyr+1)then - leaf_c = currentCohort%prt%GetState(leaf_organ,all_carbon_elements) - store_c = currentCohort%prt%GetState(store_organ,all_carbon_elements) - fnrt_c = currentCohort%prt%GetState(fnrt_organ,all_carbon_elements) - sapw_c = currentCohort%prt%GetState(sapw_organ,all_carbon_elements) - struct_c = currentCohort%prt%GetState(struct_organ,all_carbon_elements) + leaf_c = currentCohort%prt%GetState(leaf_organ,carbon12_element) + store_c = currentCohort%prt%GetState(store_organ,carbon12_element) + fnrt_c = currentCohort%prt%GetState(fnrt_organ,carbon12_element) + sapw_c = currentCohort%prt%GetState(sapw_organ,carbon12_element) + struct_c = currentCohort%prt%GetState(struct_organ,carbon12_element) currentCohort%canopy_layer = i_lyr call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread, & @@ -1097,11 +1097,11 @@ subroutine PromoteIntoLayer(currentSite,currentPatch,i_lyr) if( (currentCohort%canopy_layer == i_lyr+1) ) then cc_gain = currentCohort%prom_weight - leaf_c = currentCohort%prt%GetState(leaf_organ,all_carbon_elements) - store_c = currentCohort%prt%GetState(store_organ,all_carbon_elements) - fnrt_c = currentCohort%prt%GetState(fnrt_organ,all_carbon_elements) - sapw_c = currentCohort%prt%GetState(sapw_organ,all_carbon_elements) - struct_c = currentCohort%prt%GetState(struct_organ,all_carbon_elements) + leaf_c = currentCohort%prt%GetState(leaf_organ,carbon12_element) + store_c = currentCohort%prt%GetState(store_organ,carbon12_element) + fnrt_c = currentCohort%prt%GetState(fnrt_organ,carbon12_element) + sapw_c = currentCohort%prt%GetState(sapw_organ,carbon12_element) + struct_c = currentCohort%prt%GetState(struct_organ,carbon12_element) if ( (cc_gain-currentCohort%c_area) > -nearzero .and. & (cc_gain-currentCohort%c_area) < area_target_precision ) then @@ -1333,11 +1333,11 @@ subroutine canopy_summarization( nsites, sites, bc_in ) ft = currentCohort%pft - leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) - sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) - struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) - fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) - store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) + leaf_c = currentCohort%prt%GetState(leaf_organ, carbon12_element) + sapw_c = currentCohort%prt%GetState(sapw_organ, carbon12_element) + struct_c = currentCohort%prt%GetState(struct_organ, carbon12_element) + fnrt_c = currentCohort%prt%GetState(fnrt_organ, carbon12_element) + store_c = currentCohort%prt%GetState(store_organ, carbon12_element) ! Update the cohort's index within the size bin classes ! Update the cohort's index within the SCPF classification system @@ -1561,7 +1561,7 @@ subroutine leaf_area_profile( currentSite ) ! Note that the canopy_layer_lai is also calculated in this loop ! but since we go top down in terms of plant size, we should be okay - leaf_c = currentCohort%prt%GetState(leaf_organ,all_carbon_elements) + leaf_c = currentCohort%prt%GetState(leaf_organ,carbon12_element) currentCohort%treelai = tree_lai(leaf_c, currentCohort%pft, currentCohort%c_area, & currentCohort%n, currentCohort%canopy_layer, & @@ -1990,7 +1990,7 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) call carea_allom(currentCohort%dbh,currentCohort%n,sites(s)%spread,& currentCohort%pft,currentCohort%c_area) - currentCohort%treelai = tree_lai(currentCohort%prt%GetState(leaf_organ, all_carbon_elements), & + currentCohort%treelai = tree_lai(currentCohort%prt%GetState(leaf_organ, carbon12_element), & currentCohort%pft, currentCohort%c_area, currentCohort%n, & currentCohort%canopy_layer, currentPatch%canopy_layer_tlai,currentCohort%vcmax25top ) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index a0df486966..7c3fe61322 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -65,6 +65,7 @@ module EDCohortDynamicsMod use FatesAllometryMod , only : bagw_allom use FatesAllometryMod , only : bbgw_allom use FatesAllometryMod , only : bdead_allom + use FatesAllometryMod , only : bstore_allom use FatesAllometryMod , only : h_allom use FatesAllometryMod , only : carea_allom use FatesAllometryMod , only : ForceDBH @@ -73,7 +74,6 @@ module EDCohortDynamicsMod use PRTGenericMod, only : prt_carbon_allom_hyp use PRTGenericMod, only : prt_cnp_flex_allom_hyp use PRTGenericMod, only : prt_vartypes - use PRTGenericMod, only : all_carbon_elements use PRTGenericMod, only : carbon12_element use PRTGenericMod, only : nitrogen_element use PRTGenericMod, only : phosphorus_element @@ -96,8 +96,8 @@ module EDCohortDynamicsMod use PRTAllometricCNPMod, only : acnp_bc_in_id_lstat, acnp_bc_inout_id_dbh !use PRTAllometricCNPMod, only : acnp_bc_in_id_l2fr_ema use PRTAllometricCNPMod, only : acnp_bc_inout_id_l2fr - use PRTAllometricCNPMod, only : acnp_bc_inout_id_rmaint_def, acnp_bc_in_id_netdc - use PRTAllometricCNPMod, only : acnp_bc_in_id_netdnh4, acnp_bc_in_id_netdno3, acnp_bc_in_id_netdp + use PRTAllometricCNPMod, only : acnp_bc_inout_id_resp_excess, acnp_bc_in_id_netdc + use PRTAllometricCNPMod, only : acnp_bc_in_id_netdn, acnp_bc_in_id_netdp use PRTAllometricCNPMod, only : acnp_bc_out_id_cefflux, acnp_bc_out_id_nefflux use PRTAllometricCNPMod, only : acnp_bc_out_id_pefflux use PRTAllometricCNPMod, only : fnrt_adapt_tscl @@ -428,13 +428,12 @@ subroutine InitPRTBoundaryConditions(new_cohort) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_ctrim,bc_rval = new_cohort%canopy_trim) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_lstat,bc_ival = new_cohort%status_coh) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdc, bc_rval = new_cohort%npp_acc) - call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdnh4, bc_rval = new_cohort%daily_nh4_uptake) - call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdno3, bc_rval = new_cohort%daily_no3_uptake) + call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdn, bc_rval = new_cohort%daily_n_gain) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdp, bc_rval = new_cohort%daily_p_uptake) !!call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_l2fr_ema, bc_rval = new_cohort%l2fr_ema%l_mean) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_dbh,bc_rval = new_cohort%dbh) - call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_rmaint_def,bc_rval = new_cohort%resp_m_def) + call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_resp_excess,bc_rval = new_cohort%resp_excess) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_l2fr,bc_rval = new_cohort%l2fr) call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_cefflux, bc_rval = new_cohort%daily_c_efflux) @@ -587,6 +586,8 @@ subroutine nan_cohort(cc_p) ! Fluxes from nutrient allocation currentCohort%daily_nh4_uptake = nan currentCohort%daily_no3_uptake = nan + currentCohort%daily_n_gain = nan + currentCohort%daily_n_fixation = nan currentCohort%daily_p_uptake = nan currentCohort%daily_c_efflux = nan currentCohort%daily_n_efflux = nan @@ -601,7 +602,7 @@ subroutine nan_cohort(cc_p) !RESPIRATION currentCohort%rdark = nan currentCohort%resp_m = nan ! Maintenance respiration. kGC/cohort/year - currentCohort%resp_m_def = nan ! Maintenance respiration deficit kgC/plant + currentCohort%resp_excess = nan ! Respiration of excess (unallocatable) carbon currentCohort%livestem_mr = nan ! Live stem maintenance respiration. kgC/indiv/s-1 currentCohort%livecroot_mr = nan ! Coarse root maintenance respiration. kgC/indiv/s-1 currentCohort%froot_mr = nan ! Fine root maintenance respiration. kgC/indiv/s-1 @@ -658,7 +659,7 @@ subroutine zero_cohort(cc_p) currentCohort%status_coh = 0 currentCohort%rdark = 0._r8 currentCohort%resp_m = 0._r8 - currentCohort%resp_m_def = 0._r8 + currentCohort%resp_excess = 0._r8 currentCohort%resp_g_tstep = 0._r8 currentCohort%livestem_mr = 0._r8 currentCohort%livecroot_mr = 0._r8 @@ -713,6 +714,11 @@ subroutine zero_cohort(cc_p) currentCohort%daily_p_demand = -9._r8 currentCohort%daily_n_demand = -9._r8 + ! Fixation is also integrated over the course of the day + ! and must be zeroid upon creation and after plant + ! resource allocation + currentCohort%daily_n_fixation = 0._r8 + end subroutine zero_cohort @@ -1075,7 +1081,8 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) real(r8) :: dynamic_age_fusion_tolerance real(r8) :: dbh real(r8) :: leaf_c ! leaf carbon [kg] - + real(r8) :: target_storec ! Target storage C + integer :: largersc, smallersc, sc_i ! indices for tracking the growth flux caused by fusion real(r8) :: larger_n, smaller_n integer :: oldercacls, youngercacls, cacls_i ! indices for tracking the age flux caused by fusion @@ -1281,7 +1288,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) call ForceDBH( currentCohort%pft, currentCohort%canopy_trim, & currentCohort%dbh, currentCohort%hite, & - bdead = currentCohort%prt%GetState(struct_organ,all_carbon_elements)) + bdead = currentCohort%prt%GetState(struct_organ,carbon12_element)) end if ! @@ -1318,7 +1325,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) if( prt_params%woody(currentCohort%pft) == itrue ) then call ForceDBH( currentCohort%pft, currentCohort%canopy_trim, & currentCohort%dbh, currentCohort%hite, & - bdead = currentCohort%prt%GetState(struct_organ,all_carbon_elements)) + bdead = currentCohort%prt%GetState(struct_organ,carbon12_element)) end if ! @@ -1330,7 +1337,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) call endrun(msg=errMsg(sourcefile, __LINE__)) end select - leaf_c = currentCohort%prt%GetState(leaf_organ,all_carbon_elements) + leaf_c = currentCohort%prt%GetState(leaf_organ,carbon12_element) currentCohort%treelai = tree_lai(leaf_c, currentCohort%pft, currentCohort%c_area, newn, & currentCohort%canopy_layer, currentPatch%canopy_layer_tlai, & @@ -1412,11 +1419,8 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) (currentCohort%n*currentCohort%gpp_acc_hold + & nextc%n*nextc%gpp_acc_hold)/newn - ! This carbon variable needs continuity from day to day, as resp_m_def - ! needs to hold mass and be conservative - - currentCohort%resp_m_def = (currentCohort%n*currentCohort%resp_m_def + & - nextc%n*nextc%resp_m_def)/newn + currentCohort%resp_excess = (currentCohort%n*currentCohort%resp_excess + & + nextc%n*nextc%resp_excess)/newn currentCohort%dmort = (currentCohort%n*currentCohort%dmort + & nextc%n*nextc%dmort)/newn @@ -1437,9 +1441,16 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) nextc%n*nextc%daily_nh4_uptake)/newn currentCohort%daily_no3_uptake = (currentCohort%n*currentCohort%daily_no3_uptake + & nextc%n*nextc%daily_no3_uptake)/newn + currentCohort%daily_n_fixation = (currentCohort%n*currentCohort%daily_n_fixation + & + nextc%n*nextc%daily_n_fixation)/newn + currentCohort%daily_n_gain = (currentCohort%n*currentCohort%daily_n_gain + & + nextc%n*nextc%daily_n_gain)/newn + currentCohort%daily_p_uptake = (currentCohort%n*currentCohort%daily_p_uptake + & nextc%n*nextc%daily_p_uptake)/newn - + + + currentCohort%daily_p_demand = (currentCohort%n*currentCohort%daily_p_demand + & nextc%n*nextc%daily_p_demand)/newn currentCohort%daily_n_demand = (currentCohort%n*currentCohort%daily_n_demand + & @@ -1854,6 +1865,8 @@ subroutine copy_cohort( currentCohort,copyc ) n%daily_nh4_uptake = o%daily_nh4_uptake n%daily_no3_uptake = o%daily_no3_uptake + n%daily_n_fixation = o%daily_n_fixation + n%daily_n_gain = o%daily_n_gain n%daily_p_uptake = o%daily_p_uptake n%daily_c_efflux = o%daily_c_efflux n%daily_n_efflux = o%daily_n_efflux @@ -1868,7 +1881,7 @@ subroutine copy_cohort( currentCohort,copyc ) !RESPIRATION n%rdark = o%rdark n%resp_m = o%resp_m - n%resp_m_def = o%resp_m_def + n%resp_excess = o%resp_excess n%resp_g_tstep = o%resp_g_tstep n%livestem_mr = o%livestem_mr n%livecroot_mr = o%livecroot_mr @@ -1993,7 +2006,7 @@ subroutine UpdateCohortBioPhysRates(currentCohort) do iage = 1, nleafage frac_leaf_aclass(iage) = & - currentCohort%prt%GetState(leaf_organ, all_carbon_elements,iage) + currentCohort%prt%GetState(leaf_organ, carbon12_element,iage) end do ! If there are leaves, then perform proportional weighting on the four rates @@ -2080,7 +2093,7 @@ subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) if( int(prt_params%woody(currentCohort%pft)) == itrue) then - struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) + struct_c = currentCohort%prt%GetState(struct_organ, carbon12_element) ! Target sapwood biomass according to allometry and trimming [kgC] call bsap_allom(dbh,ipft,canopy_trim,sapw_area,target_sapw_c) @@ -2111,7 +2124,7 @@ subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) else ! This returns the sum of leaf carbon over all (age) bins - leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) + leaf_c = currentCohort%prt%GetState(leaf_organ, carbon12_element) ! Target leaf biomass according to allometry and trimming call bleaf(dbh,ipft,canopy_trim,target_leaf_c) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index f1f23d9f33..38afb74dc3 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -56,7 +56,7 @@ module EDLoggingMortalityMod use FatesGlobals , only : fates_log use shr_log_mod , only : errMsg => shr_log_errMsg use FatesPlantHydraulicsMod, only : AccumulateMortalityWaterStorage - use PRTGenericMod , only : all_carbon_elements,carbon12_element + use PRTGenericMod , only : carbon12_element use PRTGenericMod , only : sapw_organ, struct_organ, leaf_organ use PRTGenericMod , only : fnrt_organ, store_organ, repro_organ use FatesAllometryMod , only : set_root_fraction diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index e4a0b3c138..b337b9a751 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -19,9 +19,8 @@ module EDMortalityFunctionsMod use FatesInterfaceTypesMod , only : hlm_use_planthydro use EDLoggingMortalityMod , only : LoggingMortality_frac use EDParamsMod , only : fates_mortality_disturbance_fraction - - use PRTGenericMod, only : all_carbon_elements use PRTGenericMod, only : store_organ + use PRTGenericMod, only : carbon12_element implicit none private @@ -150,7 +149,7 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmor if ( cohort_in%dbh > 0._r8 ) then call bleaf(cohort_in%dbh,cohort_in%pft,cohort_in%canopy_trim,leaf_c_target) - store_c = cohort_in%prt%GetState(store_organ,all_carbon_elements) + store_c = cohort_in%prt%GetState(store_organ,carbon12_element) call storage_fraction_of_target(leaf_c_target, store_c, frac) if( frac .lt. 1._r8) then diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 4fee51a877..456f49304c 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -74,7 +74,6 @@ module EDPatchDynamicsMod use EDCohortDynamicsMod , only : InitPRTObject use EDCohortDynamicsMod , only : InitPRTBoundaryConditions use ChecksBalancesMod, only : SiteMassStock - use PRTGenericMod, only : all_carbon_elements use PRTGenericMod, only : carbon12_element use PRTGenericMod, only : leaf_organ use PRTGenericMod, only : fnrt_organ @@ -235,8 +234,8 @@ subroutine disturbance_rates( site_in, bc_in) if (currentCohort%canopy_layer>=1) then site_in%harvest_carbon_flux = site_in%harvest_carbon_flux + & currentCohort%lmort_direct * currentCohort%n * & - ( currentCohort%prt%GetState(sapw_organ, all_carbon_elements) + & - currentCohort%prt%GetState(struct_organ, all_carbon_elements)) * & + ( currentCohort%prt%GetState(sapw_organ, carbon12_element) + & + currentCohort%prt%GetState(struct_organ, carbon12_element)) * & prt_params%allom_agb_frac(currentCohort%pft) * & SF_val_CWD_frac(ncwd) * logging_export_frac endif @@ -720,11 +719,11 @@ subroutine spawn_patches( currentSite, bc_in) nc%canopy_layer = 1 nc%canopy_layer_yesterday = 1._r8 - sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) - struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) - leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) - fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) - store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) + sapw_c = currentCohort%prt%GetState(sapw_organ, carbon12_element) + struct_c = currentCohort%prt%GetState(struct_organ, carbon12_element) + leaf_c = currentCohort%prt%GetState(leaf_organ, carbon12_element) + fnrt_c = currentCohort%prt%GetState(fnrt_organ, carbon12_element) + store_c = currentCohort%prt%GetState(store_organ, carbon12_element) total_c = sapw_c + struct_c + leaf_c + fnrt_c + store_c ! treefall mortality is the dominant disturbance @@ -2954,7 +2953,7 @@ subroutine patch_pft_size_profile(cp_pnt) currentPatch%pft_agb_profile(currentCohort%pft,j) = & currentPatch%pft_agb_profile(currentCohort%pft,j) + & - currentCohort%prt%GetState(struct_organ, all_carbon_elements) * & + currentCohort%prt%GetState(struct_organ, carbon12_element) * & currentCohort%n/currentPatch%area endif diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index c286188d2c..0fb17d5b39 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -92,7 +92,6 @@ module EDPhysiologyMod use PRTGenericMod, only : prt_vartypes use PRTGenericMod, only : leaf_organ use PRTGenericMod, only : sapw_organ, struct_organ - use PRTGenericMod, only : all_carbon_elements use PRTGenericMod, only : carbon12_element use PRTGenericMod, only : nitrogen_element use PRTGenericMod, only : phosphorus_element @@ -427,7 +426,7 @@ subroutine trim_canopy( currentSite ) real(r8) :: optimum_trim ! Optimum trim value real(r8) :: initial_laimem ! Initial laimemory real(r8) :: optimum_laimem ! Optimum laimemory - + real(r8) :: target_storec !---------------------------------------------------------------------- ipatch = 1 ! Start counting patches @@ -461,7 +460,7 @@ subroutine trim_canopy( currentSite ) ipft = currentCohort%pft call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread,currentCohort%pft,currentCohort%c_area) - leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) + leaf_c = currentCohort%prt%GetState(leaf_organ, carbon12_element) currentCohort%treelai = tree_lai(leaf_c, currentCohort%pft, currentCohort%c_area, & currentCohort%n, currentCohort%canopy_layer, & @@ -1105,10 +1104,10 @@ subroutine phenology_leafonoff(currentSite) if(debug) call currentCohort%prt%CheckMassConservation(ipft,0) - store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) - leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) - sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) - struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) + store_c = currentCohort%prt%GetState(store_organ, carbon12_element) + leaf_c = currentCohort%prt%GetState(leaf_organ, carbon12_element) + sapw_c = currentCohort%prt%GetState(sapw_organ, carbon12_element) + struct_c = currentCohort%prt%GetState(struct_organ, carbon12_element) stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(ipft) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index ef6ea7151e..511bb90592 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -1031,7 +1031,8 @@ subroutine bstore_allom(d,ipft,canopy_trim,bstore,dbstoredd) case(1) ! Storage is constant proportionality of trimmed maximum leaf ! biomass (ie cushion * bleaf) - call bleaf(d,ipft,canopy_trim,bl,dbldd) + !call bleaf(d,ipft,canopy_trim,bl,dbldd) + call bleaf(d,ipft,1.0_r8,bl,dbldd) call bstore_blcushion(d,bl,dbldd,cushion,ipft,bstore,dbstoredd) case DEFAULT diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index caab5e8d54..3556013556 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -20,7 +20,6 @@ module FatesSoilBGCFluxMod use PRTGenericMod , only : prt_vartypes use PRTGenericMod , only : leaf_organ use PRTGenericMod , only : sapw_organ, struct_organ - use PRTGenericMod , only : all_carbon_elements use PRTGenericMod , only : carbon12_element use PRTGenericMod , only : nitrogen_element use PRTGenericMod , only : phosphorus_element @@ -86,7 +85,7 @@ module FatesSoilBGCFluxMod public :: PrepNutrientAquisitionBCs public :: UnPackNutrientAquisitionBCs public :: FluxIntoLitterPools - + public :: EffluxIntoLitterPools logical, parameter :: debug = .false. ! local debug flag character(len=*), parameter, private :: sourcefile = & @@ -562,6 +561,71 @@ subroutine PrepNutrientAquisitionBCs(csite, bc_in, bc_out) return end subroutine PrepNutrientAquisitionBCs + ! ===================================================================================== + + subroutine EffluxIntoLitterPools(csite, cpatch, ccohort, bc_in ) + + ! ----------------------------------------------------------------------------------- + ! This subroutine just handles the transfer of exudation/efflux from plants + ! to the HLM. We "root_fines_frag" array to save memory, and because it has + ! a labile component, soil discretization, and already has routines + ! in place for restarting and mass balancing through disturbance. + ! ----------------------------------------------------------------------------------- + + ! Arguments + type(ed_site_type), intent(inout) :: csite + type(ed_patch_type), intent(inout) :: cpatch + type(ed_cohort_type), intent(inout),target :: ccohort + type(bc_in_type), intent(in) :: bc_in + + ! locals + integer :: el ! element loop index + integer :: j ! soil layer loop index + real(r8), pointer :: efflux_ptr ! pointer to cohort efflux + type(litter_type), pointer :: litt + + call set_root_fraction(csite%rootfrac_scr, & + ccohort%pft, csite%zi_soil, & + bc_in%max_rooting_depth_index_col ) + + ! Loop over the different elements. + do el = 1, num_elements + + select case (element_list(el)) + case (carbon12_element) + + efflux_ptr => ccohort%daily_c_efflux + + case (nitrogen_element) + + efflux_ptr => ccohort%daily_n_efflux + + case (phosphorus_element) + + efflux_ptr => ccohort%daily_p_efflux + + end select + + litt => cpatch%litter(el) + + do j = 1,csite%nlevsoil + + ! kg/m2/day + litt%root_fines_frag(ilabile,j) = litt%root_fines_frag(ilabile,j) + & + efflux_ptr * ccohort%n * AREA_INV * csite%rootfrac_scr(j) + + ! Note: we do not increment the site-level mass flux checking + ! variable site_mass%frag_out This will be incremented later + ! in the call sequence, and we don't want to double count. + + end do + + end do + + return + end subroutine EffluxIntoLitterPools + + ! ===================================================================================== subroutine FluxIntoLitterPools(csite, bc_in, bc_out) @@ -677,21 +741,19 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) select case (element_list(el)) case (carbon12_element) - bc_out%litt_flux_cel_c_si(:) = 0.0_r8 - bc_out%litt_flux_lig_c_si(:) = 0.0_r8 - bc_out%litt_flux_lab_c_si(:) = 0.0_r8 + bc_out%litt_flux_cel_c_si(:) = 0._r8 + bc_out%litt_flux_lig_c_si(:) = 0._r8 + bc_out%litt_flux_lab_c_si(:) = 0._r8 flux_cel_si => bc_out%litt_flux_cel_c_si(:) flux_lab_si => bc_out%litt_flux_lab_c_si(:) flux_lig_si => bc_out%litt_flux_lig_c_si(:) - - case (nitrogen_element) + case (nitrogen_element) bc_out%litt_flux_cel_n_si(:) = 0._r8 bc_out%litt_flux_lig_n_si(:) = 0._r8 bc_out%litt_flux_lab_n_si(:) = 0._r8 flux_cel_si => bc_out%litt_flux_cel_n_si(:) flux_lab_si => bc_out%litt_flux_lab_n_si(:) flux_lig_si => bc_out%litt_flux_lig_n_si(:) - case (phosphorus_element) bc_out%litt_flux_cel_p_si(:) = 0._r8 bc_out%litt_flux_lig_p_si(:) = 0._r8 @@ -699,52 +761,11 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) flux_cel_si => bc_out%litt_flux_cel_p_si(:) flux_lab_si => bc_out%litt_flux_lab_p_si(:) flux_lig_si => bc_out%litt_flux_lig_p_si(:) - end select - - ! If there is any efflux (from stores overflowing) - ! than pass that to the labile litter pool - - do id = 1,nlev_eff_decomp - flux_lab_si(id) = flux_lab_si(id) + & - sum(csite%flux_diags(el)%nutrient_efflux_scpf(:)) * & - area_inv * surface_prof(id) - end do - currentPatch => csite%oldest_patch do while (associated(currentPatch)) - ! If there is any efflux (from stores overflowing) - ! than pass that to the labile litter pool - if(.false.)then - currentCohort => currentPatch%tallest - do while(associated(currentCohort)) - if(.not.currentCohort%isnew)then - if(element_list(el).eq.carbon12_element) then - efflux_ptr => currentCohort%daily_c_efflux - elseif(element_list(el).eq.nitrogen_element) then - efflux_ptr => currentCohort%daily_n_efflux - elseif(element_list(el).eq.phosphorus_element) then - efflux_ptr => currentCohort%daily_p_efflux - end if - - call set_root_fraction(csite%rootfrac_scr, currentCohort%pft, csite%zi_soil, & - bc_in%max_rooting_depth_index_col ) - - ! Unit conversion - ! kg/plant/day * plant/ha * ha/m2 -> kg/m2/day - - do id = 1,nlev_eff_soil - flux_lab_si(id) = flux_lab_si(id) + & - efflux_ptr * currentCohort%n* AREA_INV *csite%rootfrac_scr(id) - end do - - end if - currentCohort => currentCohort%shorter - end do - end if - ! Set a pointer to the litter object ! for the current element on the current ! patch @@ -808,9 +829,7 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) end do end do - do j = 1, nlev_eff_soil - id = bc_in%decomp_id(j) flux_lab_si(id) = flux_lab_si(id) + & litt%root_fines_frag(ilabile,j) * area_frac diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 5a0c55183b..f4d918c9c8 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -41,7 +41,7 @@ module FATESPlantRespPhotosynthMod use EDParamsMod, only : q10_mr use PRTGenericMod, only : prt_carbon_allom_hyp use PRTGenericMod, only : prt_cnp_flex_allom_hyp - use PRTGenericMod, only : all_carbon_elements + use PRTGenericMod, only : carbon12_element use PRTGenericMod, only : nitrogen_element use PRTGenericMod, only : leaf_organ use PRTGenericMod, only : fnrt_organ @@ -221,7 +221,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) real(r8) :: maintresp_reduction_factor ! factor by which to reduce maintenance - ! respiration when storage pools are low + ! respiration when storage pools are low real(r8) :: b_leaf ! leaf biomass kgC real(r8) :: frac ! storage pool as a fraction of target leaf biomass real(r8) :: check_elai ! This is a check on the effective LAI that is calculated @@ -239,7 +239,8 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) real(r8) :: leaf_psi ! leaf xylem matric potential [MPa] (only meaningful/used w/ hydro) real(r8) :: fnrt_mr_layer ! fine root maintenance respiation per layer [kgC/plant/s] real(r8) :: c_cost_nfix ! carbon cost of N fixation [kgC/kgN] - + real(r8) :: c_spent_nfix ! carbon spent on N fixation, per layer [kgC/plant/timestep] + real(r8), allocatable :: rootfr_ft(:,:) ! Root fractions per depth and PFT ! ----------------------------------------------------------------------------------- @@ -398,16 +399,16 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! currentCohort%canopy_trim,store_c_target) call storage_fraction_of_target(store_c_target, & - currentCohort%prt%GetState(store_organ, all_carbon_elements), & + currentCohort%prt%GetState(store_organ, carbon12_element), & frac) call lowstorage_maintresp_reduction(frac,currentCohort%pft, & maintresp_reduction_factor) ! are there any leaves of this pft in this layer? - if(currentPatch%canopy_mask(cl,ft) == 1)then + canopy_mask_if: if(currentPatch%canopy_mask(cl,ft) == 1)then ! Loop over leaf-layers - do iv = 1,currentCohort%nv + leaf_layer_loop : do iv = 1,currentCohort%nv ! ------------------------------------------------------------ ! If we are doing plant hydro-dynamics (or any run-type @@ -422,7 +423,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! age classes ! ------------------------------------------------------------ - if ( .not.rate_mask_z(iv,ft,cl) .or. & + rate_mask_if: if ( .not.rate_mask_z(iv,ft,cl) .or. & (hlm_use_planthydro.eq.itrue) .or. & (nleafage > 1) .or. & (hlm_parteh_mode .ne. prt_carbon_allom_hyp ) ) then @@ -494,7 +495,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) case (prt_cnp_flex_allom_hyp) - leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) + leaf_c = currentCohort%prt%GetState(leaf_organ, carbon12_element) if( (leaf_c*slatop(ft)) > nearzero) then leaf_n = currentCohort%prt%GetState(leaf_organ, nitrogen_element) lnc_top = leaf_n / (slatop(ft) * leaf_c ) @@ -578,8 +579,9 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) c13disc_z(cl,ft,iv)) ! out rate_mask_z(iv,ft,cl) = .true. - end if - end do + + end if rate_mask_if + end do leaf_layer_loop ! Zero cohort flux accumulators. currentCohort%npp_tstep = 0.0_r8 @@ -628,7 +630,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) currentCohort%g_sb_laweight = 0.0_r8 currentCohort%ts_net_uptake(:) = 0.0_r8 - end if ! if(currentPatch%canopy_mask(cl,ft) == 1)then + end if canopy_mask_if ! ------------------------------------------------------------------ @@ -643,8 +645,8 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! Units are in (kgN/plant) ! ------------------------------------------------------------------ - sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) - fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) + sapw_c = currentCohort%prt%GetState(sapw_organ, carbon12_element) + fnrt_c = currentCohort%prt%GetState(fnrt_organ, carbon12_element) select case(hlm_parteh_mode) case (prt_carbon_allom_hyp) @@ -709,21 +711,24 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) currentCohort%froot_mr = 0._r8 ! n_fixation is integrated over the course of the day - currentCohort%n_fixation = 0._r8 + ! this variable is zeroed at the end of the FATES dynamics sequence do j = 1,bc_in(s)%nlevsoil tcsoi = q10_mr**((bc_in(s)%t_soisno_sl(j)-tfrz - 20.0_r8)/10.0_r8) fnrt_mr_layer = fnrt_n * ED_val_base_mr_20 * tcsoi * rootfr_ft(ft,j) * maintresp_reduction_factor - currentCohort%froot_mr = currentCohort%froot_mr + fnrt_mr_layer * (1._r8 + EDPftvarcon_inst%dev_arbitrary_pft(ft)) + currentCohort%froot_mr = currentCohort%froot_mr + fnrt_mr_layer * (1._r8 + EDPftvarcon_inst%nfix_mresp_scfrac(ft)) ! calculate the cost of carbon for N fixation in each soil layer and calculate N fixation rate based on that [kgC / kgN] c_cost_nfix = s_fix * (exp(a_fix + b_fix * (bc_in(s)%t_soisno_sl(j)-tfrz) & * (1._r8 - 0.5_r8 * (bc_in(s)%t_soisno_sl(j)-tfrz) / c_fix)) - 2._r8) + + ! Time integrated amount of carbon spent on fixation (in this layer) [kgC/plant/layer/tstep] + c_spent_nfix = fnrt_mr_layer * dtime * EDPftvarcon_inst%nfix_mresp_scfrac(ft) - currentCohort%n_fixation = currentCohort%n_fixation + fnrt_mr_layer * EDPftvarcon_inst%dev_arbitrary_pft / c_cost_nfix + currentCohort%daily_n_fixation = currentCohort%daily_n_fixation + c_spent_nfix / c_cost_nfix enddo @@ -2089,7 +2094,7 @@ subroutine LeafLayerBiophysicalRates( parsun_lsl, & vcmax = vcmax * btran return -end subroutine LeafLayerBiophysicalRates + end subroutine LeafLayerBiophysicalRates subroutine lowstorage_maintresp_reduction(frac, pft, maintresp_reduction_factor) diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index aedcb4aa7c..c0d30fa3fb 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -37,7 +37,6 @@ module SFMainMod use PRTGenericMod, only : leaf_organ use PRTGenericMod, only : carbon12_element - use PRTGenericMod, only : all_carbon_elements use PRTGenericMod, only : leaf_organ use PRTGenericMod, only : fnrt_organ use PRTGenericMod, only : sapw_organ @@ -195,7 +194,7 @@ subroutine charecteristics_of_fuel ( currentSite ) if( int(prt_params%woody(currentCohort%pft)) == ifalse)then currentPatch%livegrass = currentPatch%livegrass + & - currentCohort%prt%GetState(leaf_organ, all_carbon_elements) * & + currentCohort%prt%GetState(leaf_organ, carbon12_element) * & currentCohort%n/currentPatch%area endif @@ -866,9 +865,9 @@ subroutine crown_scorching ( currentSite ) do while(associated(currentCohort)) if ( int(prt_params%woody(currentCohort%pft)) == itrue) then !trees only - leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) - sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) - struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) + leaf_c = currentCohort%prt%GetState(leaf_organ, carbon12_element) + sapw_c = currentCohort%prt%GetState(sapw_organ, carbon12_element) + struct_c = currentCohort%prt%GetState(struct_organ, carbon12_element) tree_ag_biomass = tree_ag_biomass + & currentCohort%n * (leaf_c + & diff --git a/main/ChecksBalancesMod.F90 b/main/ChecksBalancesMod.F90 index 9a17fbfc33..ab76715fe6 100644 --- a/main/ChecksBalancesMod.F90 +++ b/main/ChecksBalancesMod.F90 @@ -15,7 +15,6 @@ module ChecksBalancesMod use FatesLitterMod, only : litter_type use FatesLitterMod, only : ncwd use FatesLitterMod, only : ndcmpy - use PRTGenericMod, only : all_carbon_elements use PRTGenericMod, only : carbon12_element use PRTGenericMod, only : leaf_organ use PRTGenericMod, only : fnrt_organ @@ -121,16 +120,6 @@ subroutine PatchMassStock(currentPatch,el,live_stock,seed_stock,litter_stock) currentCohort => currentCohort%shorter enddo !end cohort loop - - if(element_id.eq.carbon12_element) then - currentCohort => currentPatch%tallest - do while(associated(currentCohort)) - live_stock = live_stock - & - (currentCohort%resp_m_def*currentCohort%n) - currentCohort => currentCohort%shorter - enddo !end cohort loop - end if - return end subroutine PatchMassStock diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 671bc7c7a0..854b9ecebe 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -152,9 +152,6 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) do el=1,num_elements allocate(site_in%flux_diags(el)%leaf_litter_input(1:numpft)) allocate(site_in%flux_diags(el)%root_litter_input(1:numpft)) - allocate(site_in%flux_diags(el)%nutrient_efflux_scpf(nlevsclass*numpft)) - allocate(site_in%flux_diags(el)%nutrient_uptake_scpf(nlevsclass*numpft)) - allocate(site_in%flux_diags(el)%nutrient_demand_scpf(nlevsclass*numpft)) end do ! Initialize the static soil diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index aeec0c7974..28fefe9da2 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -49,6 +49,7 @@ module EDMainMod use EDPhysiologyMod , only : PreDisturbanceLitterFluxes use EDPhysiologyMod , only : PreDisturbanceIntegrateLitter use FatesSoilBGCFluxMod , only : FluxIntoLitterPools + use FatesSoilBGCFluxMod , only : EffluxIntoLitterPools use EDCohortDynamicsMod , only : UpdateCohortBioPhysRates use FatesSoilBGCFluxMod , only : PrepNutrientAquisitionBCs use FatesSoilBGCFluxMod , only : PrepCH4BCs @@ -79,7 +80,7 @@ module EDMainMod use FatesPlantHydraulicsMod , only : UpdateSizeDepRhizHydProps use FatesPlantHydraulicsMod , only : AccumulateMortalityWaterStorage use FatesAllometryMod , only : h_allom,tree_sai,tree_lai - use FatesAllometryMod , only : bleaf + use FatesAllometryMod , only : bleaf,bstore_allom use FatesPlantHydraulicsMod , only : UpdateSizeDepRhizHydStates use EDLoggingMortalityMod , only : IsItLoggingTime use EDPatchDynamicsMod , only : get_frac_site_primary @@ -88,7 +89,6 @@ module EDMainMod use EDMortalityFunctionsMod , only : Mortality_Derivative use EDTypesMod , only : AREA_INV use PRTGenericMod, only : carbon12_element - use PRTGenericMod, only : all_carbon_elements use PRTGenericMod, only : leaf_organ use PRTGenericMod, only : fnrt_organ use PRTGenericMod, only : sapw_organ @@ -98,8 +98,6 @@ module EDMainMod use PRTLossFluxesMod, only : PRTMaintTurnover use PRTLossFluxesMod, only : PRTReproRelease use EDPftvarcon, only : EDPftvarcon_inst - use FatesHistoryInterfaceMod, only : ih_nh4uptake_si, ih_no3uptake_si, ih_puptake_si - use FatesHistoryInterfaceMod, only : ih_nh4uptake_scpf, ih_no3uptake_scpf, ih_puptake_scpf use FatesHistoryInterfaceMod, only : fates_hist ! CIME Globals @@ -166,6 +164,8 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) ! zero dynamics (upfreq_in = 1) output history variables call fates_hist%zero_site_hvars(currentSite,upfreq_in=1) + ! zero nutrient fluxes (upfreq_in=5) output hist variables + call fates_hist%zero_site_hvars(currentSite,upfreq_in=5) ! Call a routine that simply identifies if logging should occur ! This is limited to a global event until more structured event handling is enabled @@ -340,6 +340,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! note, this is not the target, but the actual real(r8) :: leaf_c_target ! target leaf crabon [kg] real(r8) :: current_npp ! place holder for calculating npp each year in prescribed physiology mode + real(r8) :: target_storec !----------------------------------------------------------------------- real(r8) :: frac_site_primary @@ -351,8 +352,6 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentPatch => currentSite%youngest_patch do while(associated(currentPatch)) - !print*,"PATCH" - currentPatch%age = currentPatch%age + hlm_freq_day ! FIX(SPM,032414) valgrind 'Conditional jump or move depends on uninitialised value' if( currentPatch%age < 0._r8 )then @@ -373,9 +372,8 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentCohort => currentPatch%shortest do while(associated(currentCohort)) - ft = currentCohort%pft - + ! Calculate the mortality derivatives call Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_primary ) @@ -440,115 +438,56 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) hite_old = currentCohort%hite dbh_old = currentCohort%dbh + ! Plants can acquire N from 3 sources (excluding re-absorption), + ! the source doesn't affect how its allocated (yet), so they + ! are combined into daily_n_gain, which is the value used in the following + ! allocation scheme + + currentCohort%daily_n_gain = currentCohort%daily_nh4_uptake + & + currentCohort%daily_no3_uptake + currentCohort%daily_n_fixation + ! ----------------------------------------------------------------------------- ! Growth and Allocation (PARTEH) ! ----------------------------------------------------------------------------- + currentCohort%resp_excess = 0._r8 + + call currentCohort%prt%DailyPRT() + ! Send any efflux/exudates to the labile litter pools in the HLM + ! ----------------------------------------------------------------------------- + call EffluxIntoLitterPools(currentSite, currentPatch, currentCohort, bc_in ) - ! Update the moving average of actual L2FR - call bleaf(currentCohort%dbh,currentCohort%pft,currentCohort%canopy_trim,leaf_c_target) - if(currentCohort%prt%GetState(leaf_organ, carbon12_element)/leaf_c_target>0.01_r8)then - actual_l2fr = currentCohort%prt%GetState(fnrt_organ, carbon12_element) / & - currentCohort%prt%GetState(leaf_organ, carbon12_element) + ! Update history diagnostics related to Nutrient fluxes and C efflux (if any) + ! ----------------------------------------------------------------------------- + + call fates_hist%update_history_nutrflux(currentSite,currentPatch,currentCohort) - actual_l2fr = max(0.05_r8,min(10._r8,actual_l2fr)) + + currentCohort%daily_n_fixation = 0._r8 - !!call currentCohort%l2fr_ema%UpdateRMean(actual_l2fr) - end if + ! Mass balance for N uptake + currentSite%mass_balance(element_pos(nitrogen_element))%net_root_uptake = & + currentSite%mass_balance(element_pos(nitrogen_element))%net_root_uptake + & + (currentCohort%daily_n_gain-currentCohort%daily_n_efflux)*currentCohort%n - call currentCohort%prt%DailyPRT() + ! Mass balance for P uptake + currentSite%mass_balance(element_pos(phosphorus_element))%net_root_uptake = & + currentSite%mass_balance(element_pos(phosphorus_element))%net_root_uptake + & + (currentCohort%daily_p_uptake-currentCohort%daily_p_efflux)*currentCohort%n + + ! mass balance for C efflux (if any) + currentSite%mass_balance(element_pos(carbon12_element))%net_root_uptake = & + currentSite%mass_balance(element_pos(carbon12_element))%net_root_uptake - & + currentCohort%daily_c_efflux*currentCohort%n - ! Update the mass balance tracking for the daily nutrient uptake flux - ! Then zero out the daily uptakes, they have been used - ! ----------------------------------------------------------------------------- - - if(hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp ) then - - ! Mass balance for N uptake - currentSite%mass_balance(element_pos(nitrogen_element))%net_root_uptake = & - currentSite%mass_balance(element_pos(nitrogen_element))%net_root_uptake + & - (currentCohort%daily_nh4_uptake+currentCohort%daily_no3_uptake- & - currentCohort%daily_n_efflux)*currentCohort%n - - ! Mass balance for P uptake - currentSite%mass_balance(element_pos(phosphorus_element))%net_root_uptake = & - currentSite%mass_balance(element_pos(phosphorus_element))%net_root_uptake + & - (currentCohort%daily_p_uptake-currentCohort%daily_p_efflux)*currentCohort%n - - ! mass balance for C efflux (if any) - currentSite%mass_balance(element_pos(carbon12_element))%net_root_uptake = & - currentSite%mass_balance(element_pos(carbon12_element))%net_root_uptake - & - currentCohort%daily_c_efflux*currentCohort%n - - ! size class index - iscpf = currentCohort%size_by_pft_class - - ! Diagnostics for uptake, by size and pft, [kgX/ha/day] - - io_si = currentSite%h_gid - - fates_hist%hvars(ih_nh4uptake_scpf)%r82d(io_si,iscpf) = & - fates_hist%hvars(ih_nh4uptake_scpf)%r82d(io_si,iscpf) + & - currentCohort%daily_nh4_uptake*currentCohort%n / & - m2_per_ha / sec_per_day - - fates_hist%hvars(ih_no3uptake_scpf)%r82d(io_si,iscpf) = & - fates_hist%hvars(ih_no3uptake_scpf)%r82d(io_si,iscpf) + & - currentCohort%daily_no3_uptake*currentCohort%n / & - m2_per_ha / sec_per_day - - fates_hist%hvars(ih_puptake_scpf)%r82d(io_si,iscpf) = & - fates_hist%hvars(ih_puptake_scpf)%r82d(io_si,iscpf) + & - currentCohort%daily_p_uptake*currentCohort%n / & - m2_per_ha / sec_per_day - - fates_hist%hvars(ih_nh4uptake_si)%r81d(io_si) = & - fates_hist%hvars(ih_nh4uptake_si)%r81d(io_si) + & - currentCohort%daily_nh4_uptake*currentCohort%n / & - m2_per_ha / sec_per_day - - fates_hist%hvars(ih_no3uptake_si)%r81d(io_si) = & - fates_hist%hvars(ih_no3uptake_si)%r81d(io_si) + & - currentCohort%daily_no3_uptake*currentCohort%n / & - m2_per_ha / sec_per_day - - fates_hist%hvars(ih_puptake_si)%r81d(io_si) = & - fates_hist%hvars(ih_puptake_si)%r81d(io_si) + & - currentCohort%daily_p_uptake*currentCohort%n / & - m2_per_ha / sec_per_day - - - ! Diagnostics on efflux, size and pft [kgX/ha/day] - currentSite%flux_diags(element_pos(nitrogen_element))%nutrient_efflux_scpf(iscpf) = & - currentSite%flux_diags(element_pos(nitrogen_element))%nutrient_efflux_scpf(iscpf) + & - currentCohort%daily_n_efflux*currentCohort%n - - currentSite%flux_diags(element_pos(phosphorus_element))%nutrient_efflux_scpf(iscpf) = & - currentSite%flux_diags(element_pos(phosphorus_element))%nutrient_efflux_scpf(iscpf) + & - currentCohort%daily_p_efflux*currentCohort%n - - currentSite%flux_diags(element_pos(carbon12_element))%nutrient_efflux_scpf(iscpf) = & - currentSite%flux_diags(element_pos(carbon12_element))%nutrient_efflux_scpf(iscpf) + & - currentCohort%daily_c_efflux*currentCohort%n - - ! Diagnostics on plant nutrient need - currentSite%flux_diags(element_pos(nitrogen_element))%nutrient_demand_scpf(iscpf) = & - currentSite%flux_diags(element_pos(nitrogen_element))%nutrient_demand_scpf(iscpf) + & - currentCohort%daily_n_demand*currentCohort%n - - currentSite%flux_diags(element_pos(phosphorus_element))%nutrient_demand_scpf(iscpf) = & - currentSite%flux_diags(element_pos(phosphorus_element))%nutrient_demand_scpf(iscpf) + & - currentCohort%daily_p_demand*currentCohort%n - - end if - ! And simultaneously add the input fluxes to mass balance accounting site_cmass%gpp_acc = site_cmass%gpp_acc + & currentCohort%gpp_acc * currentCohort%n + site_cmass%aresp_acc = site_cmass%aresp_acc + & - currentCohort%resp_acc * currentCohort%n + (currentCohort%resp_acc+currentCohort%resp_excess) * currentCohort%n call currentCohort%prt%CheckMassConservation(ft,5) @@ -885,12 +824,13 @@ subroutine TotalBalanceCheck (currentSite, call_index ) write(fates_log(),*) 'leaf: ',leaf_m,' structure: ',struct_m,' store: ',store_m write(fates_log(),*) 'fineroot: ',fnrt_m,' repro: ',repro_m,' sapwood: ',sapw_m write(fates_log(),*) 'num plant: ',currentCohort%n - write(fates_log(),*) 'resp m def: ',currentCohort%resp_m_def*currentCohort%n + write(fates_log(),*) 'resp excess: ',currentCohort%resp_excess*currentCohort%n if(element_list(el).eq.nitrogen_element) then write(fates_log(),*) 'NH4 uptake: ',currentCohort%daily_nh4_uptake*currentCohort%n write(fates_log(),*) 'NO3 uptake: ',currentCohort%daily_no3_uptake*currentCohort%n write(fates_log(),*) 'N efflux: ',currentCohort%daily_n_efflux*currentCohort%n + write(fates_log(),*) 'N fixation: ',currentCohort%daily_n_fixation*currentCohort%n elseif(element_list(el).eq.phosphorus_element) then write(fates_log(),*) 'P uptake: ',currentCohort%daily_p_uptake*currentCohort%n write(fates_log(),*) 'P efflux: ',currentCohort%daily_p_efflux*currentCohort%n diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 9dd076debc..387edc70f8 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -157,8 +157,9 @@ module EDPftvarcon ! biochemical production, fraction based how much ! more in need a plant is for P versus N [/] - !real(r8), allocatable :: nfix1(:) ! nitrogen fixation parameter 1 - !real(r8), allocatable :: nfix2(:) ! nitrogen fixation parameter 2 + ! Maintenance respiration surcharge for obligate fixation [fraction of existing respiration] + real(r8), allocatable :: nfix_mresp_scfrac(:) + ! Turnover related things @@ -572,7 +573,6 @@ subroutine Register_PFT(this, fates_params) ! Nutrient competition parameters - name = 'fates_eca_decompmicc' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -925,9 +925,10 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=this%prescribed_puptake) + ! TEMPORARILY USING DEV_ARIBITRARY_PFT FOR FIXATION PARAMETER name = 'fates_dev_arbitrary_pft' call fates_params%RetreiveParameterAllocate(name=name, & - data=this%dev_arbitrary_pft) + data=this%nfix_mresp_scfrac) name = 'fates_eca_decompmicc' call fates_params%RetreiveParameterAllocate(name=name, & @@ -1514,6 +1515,18 @@ subroutine FatesCheckParams(is_master) call endrun(msg=errMsg(sourcefile, __LINE__)) end if + ! Make sure that the N fixation respiration surcharge fraction is + ! between 0 and 1 + + if(any(EDpftvarcon_inst%nfix_mresp_scfrac(:)<0._r8) .or. any(EDpftvarcon_inst%nfix_mresp_scfrac(:)>1.0_r8)) then + write(fates_log(),*) 'The N fixation surcharge nfix_mresp_sfrac must be between 0-1.' + write(fates_log(),*) 'This parameter is temporarily using the parameter file field: dev_arbitrary_pft' + write(fates_log(),*) 'here are the values: ',EDpftvarcon_inst%nfix_mresp_scfrac(:) + write(fates_log(),*) 'Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + ! If nitrogen is turned on, check to make sure there are valid ammonium ! parameters if(hlm_nitrogen_spec>0)then diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 94a02d9672..772a9d0e09 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -9,11 +9,11 @@ module EDTypesMod use PRTGenericMod, only : prt_vartypes use PRTGenericMod, only : leaf_organ, fnrt_organ, sapw_organ use PRTGenericMod, only : repro_organ, store_organ, struct_organ - use PRTGenericMod, only : all_carbon_elements use PRTGenericMod, only : num_organ_types use PRTGenericMod, only : num_elements use PRTGenericMod, only : element_list use PRTGenericMod, only : num_element_types + use PRTGenericMod, only : carbon12_element use FatesLitterMod, only : litter_type use FatesLitterMod, only : ncwd use FatesConstantsMod, only : n_anthro_disturbance_categories @@ -302,6 +302,8 @@ module EDTypesMod real(r8) :: daily_nh4_uptake ! integrated daily uptake of mineralized ammonium through competitive acquisition in soil [kg N / plant/ day] real(r8) :: daily_no3_uptake ! integrated daily uptake of mineralized nitrate through competitive acquisition in soil [kg N / plant/ day] + real(r8) :: daily_n_fixation ! Rate of N fixation from the roots [kgN/indiv/day] + real(r8) :: daily_n_gain ! sum of fixation and uptake of mineralized nh4/no3 in solution real(r8) :: daily_p_uptake ! integrated daily uptake of mineralized P through competitive acquisition in soil [kg P / plant/ day] real(r8) :: daily_c_efflux ! daily mean efflux of excess carbon from roots into labile pool [kg C/plant/day] @@ -312,7 +314,7 @@ module EDTypesMod real(r8) :: daily_p_demand ! The daily amount of P demanded by the plant [kgN/plant/day] ! N fixation rate - real(r8) :: n_fixation ! Rate of N fixation from the roots [kgN/indiv/s] + ! The following four biophysical rates are assumed to be ! at the canopy top, at reference temp 25C, and based on the @@ -338,10 +340,7 @@ module EDTypesMod real(r8) :: resp_g_tstep ! Growth respiration: kgC/indiv/timestep real(r8) :: resp_m ! Maintenance respiration: kgC/indiv/timestep - real(r8) :: resp_m_def ! Optional: (NOT IMPLEMENTED YET) - ! It may be possible to not respire at desired rate - ! because of low carbon stores, and thus build - ! up a deficit. This tracks that deficit. kgC/indiv + real(r8) :: resp_excess ! Respiration of excess carbon kgC/indiv/day real(r8) :: livestem_mr ! Live stem maintenance respiration: kgC/indiv/s ! (Above ground) real(r8) :: livecroot_mr ! Live stem maintenance respiration: kgC/indiv/s @@ -623,10 +622,6 @@ module EDTypesMod real(r8) :: cwd_bg_input(1:ncwd) real(r8),allocatable :: leaf_litter_input(:) real(r8),allocatable :: root_litter_input(:) - - real(r8),allocatable :: nutrient_uptake_scpf(:) - real(r8),allocatable :: nutrient_efflux_scpf(:) - real(r8),allocatable :: nutrient_demand_scpf(:) contains @@ -659,7 +654,8 @@ module EDTypesMod real(r8) :: aresp_acc ! Accumulated autotrophic respiration [kg/site/day] real(r8) :: net_root_uptake ! Net uptake of carbon or nutrients through the roots [kg/site/day] - ! (if carbon most likely exudation, if even active) + ! could include exudation, and for N this also includes symbiotic + ! fixation real(r8) :: seed_in ! Total mass of external seed rain into fates site [kg/site/day] ! This is from external grid-cells or from user parameterization @@ -890,9 +886,6 @@ subroutine ZeroFluxDiags(this) this%cwd_bg_input(:) = 0._r8 this%leaf_litter_input(:) = 0._r8 this%root_litter_input(:) = 0._r8 - this%nutrient_uptake_scpf(:) = 0._r8 - this%nutrient_efflux_scpf(:) = 0._r8 - this%nutrient_demand_scpf(:) = 0._r8 return end subroutine ZeroFluxDiags @@ -1083,12 +1076,12 @@ subroutine dump_cohort(ccohort) write(fates_log(),*) 'co%structmemory = ', ccohort%structmemory write(fates_log(),*) 'co%l2fr = ', ccohort%l2fr - write(fates_log(),*) 'leaf carbon = ', ccohort%prt%GetState(leaf_organ,all_carbon_elements) - write(fates_log(),*) 'fineroot carbon = ', ccohort%prt%GetState(fnrt_organ,all_carbon_elements) - write(fates_log(),*) 'sapwood carbon = ', ccohort%prt%GetState(sapw_organ,all_carbon_elements) - write(fates_log(),*) 'structural (dead) carbon = ', ccohort%prt%GetState(struct_organ,all_carbon_elements) - write(fates_log(),*) 'storage carbon = ', ccohort%prt%GetState(store_organ,all_carbon_elements) - write(fates_log(),*) 'reproductive carbon = ', ccohort%prt%GetState(repro_organ,all_carbon_elements) + write(fates_log(),*) 'leaf carbon = ', ccohort%prt%GetState(leaf_organ,carbon12_element) + write(fates_log(),*) 'fineroot carbon = ', ccohort%prt%GetState(fnrt_organ,carbon12_element) + write(fates_log(),*) 'sapwood carbon = ', ccohort%prt%GetState(sapw_organ,carbon12_element) + write(fates_log(),*) 'structural (dead) carbon = ', ccohort%prt%GetState(struct_organ,carbon12_element) + write(fates_log(),*) 'storage carbon = ', ccohort%prt%GetState(store_organ,carbon12_element) + write(fates_log(),*) 'reproductive carbon = ', ccohort%prt%GetState(repro_organ,carbon12_element) write(fates_log(),*) 'co%lai = ', ccohort%lai write(fates_log(),*) 'co%sai = ', ccohort%sai @@ -1116,7 +1109,6 @@ subroutine dump_cohort(ccohort) write(fates_log(),*) 'co%resp_acc_hold = ', ccohort%resp_acc_hold write(fates_log(),*) 'co%rdark = ', ccohort%rdark write(fates_log(),*) 'co%resp_m = ', ccohort%resp_m - write(fates_log(),*) 'co%resp_m_def = ', ccohort%resp_m_def write(fates_log(),*) 'co%resp_g_tstep = ', ccohort%resp_g_tstep write(fates_log(),*) 'co%livestem_mr = ', ccohort%livestem_mr write(fates_log(),*) 'co%livecroot_mr = ', ccohort%livecroot_mr diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 07359802c0..48d0efb3c1 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -62,11 +62,13 @@ module FatesHistoryInterfaceMod use FatesConstantsMod , only : ha_per_m2 use FatesConstantsMod , only : days_per_sec use FatesConstantsMod , only : sec_per_day + use FatesConstantsMod , only : days_per_sec use FatesConstantsMod , only : days_per_year use FatesConstantsMod , only : years_per_day use FatesConstantsMod , only : m2_per_km2 use FatesConstantsMod , only : J_per_kJ use FatesConstantsMod , only : m2_per_ha + use FatesConstantsMod , only : ha_per_m2 use FatesConstantsMod , only : m_per_cm use FatesConstantsMod , only : sec_per_min use FatesConstantsMod , only : umol_per_mol @@ -76,7 +78,6 @@ module FatesHistoryInterfaceMod use PRTGenericMod , only : leaf_organ, fnrt_organ, sapw_organ use PRTGenericMod , only : struct_organ, store_organ, repro_organ - use PRTGenericMod , only : all_carbon_elements use PRTGenericMod , only : carbon12_element use PRTGenericMod , only : nitrogen_element, phosphorus_element use PRTGenericMod , only : prt_carbon_allom_hyp @@ -189,9 +190,9 @@ module FatesHistoryInterfaceMod integer :: ih_l2fr_canopy_scpf integer :: ih_l2fr_understory_scpf - integer,public :: ih_nh4uptake_si - integer,public :: ih_no3uptake_si - integer,public :: ih_puptake_si + integer :: ih_nh4uptake_si + integer :: ih_no3uptake_si + integer :: ih_puptake_si integer :: ih_cefflux_si integer :: ih_nefflux_si integer :: ih_pefflux_si @@ -199,7 +200,8 @@ module FatesHistoryInterfaceMod integer :: ih_ndemand_scpf integer :: ih_pdemand_si integer :: ih_pdemand_scpf - + integer :: ih_nfix_si + integer :: ih_nfix_scpf integer :: ih_trimming_si integer :: ih_area_plant_si @@ -278,6 +280,7 @@ module FatesHistoryInterfaceMod integer :: ih_aresp_si integer :: ih_maint_resp_si integer :: ih_growth_resp_si + integer :: ih_excess_resp_si integer :: ih_ar_canopy_si integer :: ih_gpp_canopy_si integer :: ih_ar_understory_si @@ -692,7 +695,8 @@ module FatesHistoryInterfaceMod procedure :: update_history_dyn procedure :: update_history_hifrq procedure :: update_history_hydraulics - + procedure :: update_history_nutrflux + ! 'get' methods used by external callers to access private read only data procedure :: num_history_vars @@ -752,6 +756,7 @@ module FatesHistoryInterfaceMod procedure, public :: flush_hvars procedure, public :: zero_site_hvars + end type fates_history_interface_type @@ -1738,7 +1743,133 @@ end subroutine init_dim_kinds_maps ! ======================================================================= + subroutine update_history_nutrflux(this,csite,cpatch,ccohort) + + ! Update history diagnostics for nutrient fluxes. + ! This is a separate routine because we like to handle these + ! things before patches are reshuffled during disturbance, and + ! thus this is called immediately after PARTEH allocation + ! These diagnostics must be zero'd at the beginning + ! of the dynamics call (not here, because this is a + ! being called at the cohort level) + + ! Arguments + class(fates_history_interface_type) :: this + type(ed_site_type), intent(in) :: csite + type(ed_patch_type), intent(in) :: cpatch + type(ed_cohort_type), intent(in) :: ccohort + + ! locals + integer :: iscpf ! Size x pft class index + integer :: io_si ! site's global index in the history vector + integer :: el ! element loop index + real(r8):: uconv ! combined unit conversion factor + + ! size class index + iscpf = ccohort%size_by_pft_class + + ! history site index + io_si = csite%h_gid + + ! unit conversion factor to get x/plant/day -> x/m2/sec + uconv = ccohort%n * ha_per_m2 * days_per_sec + + ! Loop over the different elements. + do el = 1, num_elements + + select case (element_list(el)) + case (carbon12_element) + + ! Excess carbon respired + this%hvars(ih_excess_resp_si)%r81d(io_si) = & + this%hvars(ih_excess_resp_si)%r81d(io_si) + & + ccohort%resp_excess*uconv + + ! Efflux/exudation + this%hvars(ih_cefflux_scpf)%r82d(io_si,iscpf) = & + this%hvars(ih_cefflux_scpf)%r82d(io_si,iscpf) + & + ccohort%daily_c_efflux*uconv + + this%hvars(ih_cefflux_si)%r81d(io_si) = & + this%hvars(ih_cefflux_si)%r81d(io_si)+ & + ccohort%daily_c_efflux*uconv + + case (nitrogen_element) + + ! Mineralized uptake of NH4, NO3 + fates_hist%hvars(ih_nh4uptake_scpf)%r82d(io_si,iscpf) = & + fates_hist%hvars(ih_nh4uptake_scpf)%r82d(io_si,iscpf) + & + ccohort%daily_nh4_uptake*uconv + + fates_hist%hvars(ih_no3uptake_scpf)%r82d(io_si,iscpf) = & + fates_hist%hvars(ih_no3uptake_scpf)%r82d(io_si,iscpf) + & + ccohort%daily_no3_uptake*uconv + + fates_hist%hvars(ih_nh4uptake_si)%r81d(io_si) = & + fates_hist%hvars(ih_nh4uptake_si)%r81d(io_si) + & + ccohort%daily_nh4_uptake*uconv + + fates_hist%hvars(ih_no3uptake_si)%r81d(io_si) = & + fates_hist%hvars(ih_no3uptake_si)%r81d(io_si) + & + ccohort%daily_no3_uptake*uconv + + ! Symbiotic Fixation + fates_hist%hvars(ih_nfix_si)%r81d(io_si) = & + fates_hist%hvars(ih_nfix_si)%r81d(io_si) + & + ccohort%daily_n_fixation*uconv + + fates_hist%hvars(ih_nfix_scpf)%r82d(io_si,iscpf) = & + fates_hist%hvars(ih_nfix_scpf)%r82d(io_si,iscpf) + & + ccohort%daily_n_fixation*uconv + + ! Efflux/exudation + this%hvars(ih_nefflux_scpf)%r82d(io_si,iscpf) = & + this%hvars(ih_nefflux_scpf)%r82d(io_si,iscpf) + & + ccohort%daily_n_efflux*uconv + + this%hvars(ih_nefflux_si)%r81d(io_si) = & + this%hvars(ih_nefflux_si)%r81d(io_si) + & + ccohort%daily_n_efflux*uconv + + ! Demand + this%hvars(ih_ndemand_scpf)%r82d(io_si,iscpf) = & + this%hvars(ih_ndemand_scpf)%r82d(io_si,iscpf) + & + ccohort%daily_n_demand*uconv + + this%hvars(ih_ndemand_si)%r81d(io_si) = & + this%hvars(ih_ndemand_si)%r81d(io_si) + & + ccohort%daily_n_demand*uconv + + case (phosphorus_element) + + fates_hist%hvars(ih_puptake_scpf)%r82d(io_si,iscpf) = & + fates_hist%hvars(ih_puptake_scpf)%r82d(io_si,iscpf) + & + ccohort%daily_p_uptake*uconv + fates_hist%hvars(ih_puptake_si)%r81d(io_si) = & + fates_hist%hvars(ih_puptake_si)%r81d(io_si) + & + ccohort%daily_p_uptake*uconv + + this%hvars(ih_pefflux_scpf)%r82d(io_si,iscpf) = & + this%hvars(ih_pefflux_scpf)%r82d(io_si,iscpf) + & + ccohort%daily_p_efflux*uconv + + this%hvars(ih_pefflux_si)%r81d(io_si) = & + this%hvars(ih_pefflux_si)%r81d(io_si) + & + ccohort%daily_p_efflux*uconv + + this%hvars(ih_pdemand_scpf)%r82d(io_si,iscpf) = & + this%hvars(ih_pdemand_scpf)%r82d(io_si,iscpf) + & + ccohort%daily_p_demand*uconv + + this%hvars(ih_pdemand_si)%r81d(io_si) = & + ccohort%daily_p_demand*uconv + end select + end do + return + end subroutine update_history_nutrflux + + ! ==================================================================================== @@ -3049,7 +3180,9 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) end do patchloop !patch loop ! Normalize the l2fr value by total biomass - hio_l2fr_si(io_si) = hio_l2fr_si(io_si)/this%hvars(ih_fnrtc_si)%r81d(io_si) + if(this%hvars(ih_fnrtc_si)%r81d(io_si)>nearzero)then + hio_l2fr_si(io_si) = hio_l2fr_si(io_si)/this%hvars(ih_fnrtc_si)%r81d(io_si) + end if !!hio_l2fr_ema_si(io_si) = hio_l2fr_ema_si(io_si)/this%hvars(ih_fnrtc_si)%r81d(io_si) @@ -3287,13 +3420,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) this%hvars(ih_storec_scpf)%r82d(io_si,:) = 0._r8 this%hvars(ih_reproc_scpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_cefflux_scpf)%r82d(io_si,:) = & - sites(s)%flux_diags(el)%nutrient_efflux_scpf(:) / & - m2_per_ha / sec_per_day - this%hvars(ih_cefflux_si)%r81d(io_si) = & - sum(sites(s)%flux_diags(el)%nutrient_efflux_scpf(:),dim=1) / & - m2_per_ha / sec_per_day elseif(element_list(el).eq.nitrogen_element)then @@ -3304,21 +3431,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) this%hvars(ih_storen_scpf)%r82d(io_si,:) = 0._r8 this%hvars(ih_repron_scpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_nefflux_scpf)%r82d(io_si,:) = & - sites(s)%flux_diags(el)%nutrient_efflux_scpf(:) / & - m2_per_ha / sec_per_day - - this%hvars(ih_ndemand_scpf)%r82d(io_si,:) = & - sites(s)%flux_diags(el)%nutrient_demand_scpf(:) / & - m2_per_ha / sec_per_day - - this%hvars(ih_nefflux_si)%r81d(io_si) = & - sum(sites(s)%flux_diags(el)%nutrient_efflux_scpf(:),dim=1) / & - m2_per_ha / sec_per_day - - this%hvars(ih_ndemand_si)%r81d(io_si) = & - sum(sites(s)%flux_diags(el)%nutrient_demand_scpf(:),dim=1) / & - m2_per_ha / sec_per_day + elseif(element_list(el).eq.phosphorus_element)then this%hvars(ih_totvegp_scpf)%r82d(io_si,:) = 0._r8 @@ -3328,21 +3441,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) this%hvars(ih_storep_scpf)%r82d(io_si,:) = 0._r8 this%hvars(ih_reprop_scpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_pdemand_scpf)%r82d(io_si,:) = & - sites(s)%flux_diags(el)%nutrient_demand_scpf(:) / & - m2_per_ha / sec_per_day - - this%hvars(ih_pefflux_scpf)%r82d(io_si,:) = & - sites(s)%flux_diags(el)%nutrient_efflux_scpf(:) / & - m2_per_ha / sec_per_day - - this%hvars(ih_pdemand_si)%r81d(io_si) = & - sum(sites(s)%flux_diags(el)%nutrient_demand_scpf(:),dim=1) / & - m2_per_ha / sec_per_day - - this%hvars(ih_pefflux_si)%r81d(io_si) = & - sum(sites(s)%flux_diags(el)%nutrient_efflux_scpf(:),dim=1) / & - m2_per_ha / sec_per_day + end if @@ -4489,6 +4588,9 @@ subroutine define_history_vars(this, initialize_variables) ! cohort size x pft (site_size_pft_r8) : SZPF + + + ! Site level counting variables call this%set_history_var(vname='FATES_NPATCHES', units='', & @@ -4921,7 +5023,7 @@ subroutine define_history_vars(this, initialize_variables) index = ih_litter_in_si) call this%set_history_var(vname='FATES_LITTER_OUT', units='kg m-2 s-1', & - long='litter flux out in kg carbon (fragmentation AND seed decay)', & + long='litter flux out in kg carbon (exudation, fragmentation, seed decay)', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_litter_out_si) @@ -4945,7 +5047,7 @@ subroutine define_history_vars(this, initialize_variables) index = ih_litter_in_elem) call this%set_history_var(vname='FATES_LITTER_OUT_EL', units='kg m-2 s-1', & - long='litter flux out (fragmentation and seed decay) in kg element', & + long='litter flux out (exudation, fragmentation and seed decay) in kg element', & use_default='active', avgflag='A', vtype=site_elem_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_litter_out_elem) @@ -5032,7 +5134,7 @@ subroutine define_history_vars(this, initialize_variables) call this%set_history_var(vname='FATES_CEFFLUX', units='kg m-2 s-1', & long='carbon efflux, root to soil, in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + upfreq=5, ivar=ivar, initialize=initialize_variables, & index = ih_cefflux_si) @@ -5077,27 +5179,34 @@ subroutine define_history_vars(this, initialize_variables) call this%set_history_var(vname='FATES_NH4UPTAKE', units='kg m-2 s-1', & long='ammonium uptake rate by plants in kg NH4 per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + upfreq=5, ivar=ivar, initialize=initialize_variables, & index = ih_nh4uptake_si) call this%set_history_var(vname='FATES_NO3UPTAKE', units='kg m-2 s-1', & long='nitrate uptake rate by plants in kg NO3 per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + upfreq=5, ivar=ivar, initialize=initialize_variables, & index = ih_no3uptake_si) call this%set_history_var(vname='FATES_NEFFLUX', units='kg m-2 s-1', & long='nitrogen effluxed from plant in kg N per m2 per second (unused)', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + upfreq=5, ivar=ivar, initialize=initialize_variables, & index = ih_nefflux_si) call this%set_history_var(vname='FATES_NDEMAND', units='kg m-2 s-1', & long='plant nitrogen need (algorithm dependent) in kg N per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + upfreq=5, ivar=ivar, initialize=initialize_variables, & index = ih_ndemand_si) + call this%set_history_var(vname='FATES_SYMNFIX', units='kg m-2 s-1', & + long='symbiotic dinitrogen fixation in kg N per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=5, ivar=ivar, initialize=initialize_variables, & + index = ih_nfix_si) + + end if nitrogen_active_if @@ -5145,19 +5254,19 @@ subroutine define_history_vars(this, initialize_variables) call this%set_history_var(vname='FATES_PUPTAKE', units='kg m-2 s-1', & long='mineralized phosphorus uptake rate of plants in kg P per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + upfreq=5, ivar=ivar, initialize=initialize_variables, & index = ih_puptake_si) call this%set_history_var(vname='FATES_PEFFLUX', units='kg m-2 s-1', & long='phosphorus effluxed from plant in kg P per m2 per second (unused)', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + upfreq=5, ivar=ivar, initialize=initialize_variables, & index = ih_pefflux_si) call this%set_history_var(vname='FATES_PDEMAND', units='kg m-2 s-1', & long='plant phosphorus need (algorithm dependent) in kg P per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + upfreq=5, ivar=ivar, initialize=initialize_variables, & index = ih_pdemand_si) end if phosphorus_active_if @@ -5318,6 +5427,12 @@ subroutine define_history_vars(this, initialize_variables) upfreq=2, ivar=ivar, initialize=initialize_variables, & index = ih_maint_resp_si) + call this%set_history_var(vname='FATES_EXCESS_RESP', units='kg m-2 s-1', & + long='respiration of un-allocatable carbon gain', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=5, ivar=ivar, initialize=initialize_variables, & + index = ih_excess_resp_si) + ! Canopy resistance call this%set_history_var(vname='FATES_STOMATAL_COND_AP', & @@ -6716,7 +6831,7 @@ subroutine define_history_vars(this, initialize_variables) call this%set_history_var(vname='FATES_CEFFLUX_SZPF', units='kg m-2 s-1', & long='carbon efflux, root to soil, by size-class x pft in kg carbon per m2 per second', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + hlms='CLM:ALM', upfreq=5, ivar=ivar, initialize=initialize_variables, & index = ih_cefflux_scpf) ! NITROGEN @@ -6778,28 +6893,35 @@ subroutine define_history_vars(this, initialize_variables) units='kg m-2 s-1', & long='ammonium uptake rate by plants by size-class x pft in kg NH4 per m2 per second', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & + hlms='CLM:ALM', upfreq=5, ivar=ivar, & initialize=initialize_variables, index = ih_nh4uptake_scpf) call this%set_history_var(vname='FATES_NO3UPTAKE_SZPF', & units='kg m-2 s-1', & long='nitrate uptake rate by plants by size-class x pft in kg NO3 per m2 per second', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & + hlms='CLM:ALM', upfreq=5, ivar=ivar, & initialize=initialize_variables, index = ih_no3uptake_scpf) call this%set_history_var(vname='FATES_NEFFLUX_SZPF', units='kg m-2 s-1', & long='nitrogen efflux, root to soil, by size-class x pft in kg N per m2 per second', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & + hlms='CLM:ALM', upfreq=5, ivar=ivar, & initialize=initialize_variables, index = ih_nefflux_scpf) call this%set_history_var(vname='FATES_NDEMAND_SZPF', units='kg m-2 s-1', & long='plant N need (algorithm dependent), by size-class x pft in kg N per m2 per second', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & + hlms='CLM:ALM', upfreq=5, ivar=ivar, & initialize=initialize_variables, index = ih_ndemand_scpf) + call this%set_history_var(vname='FATES_SYMNFIX_SZPF', units='kg m-2 s-1', & + long='symbiotic dinitrogen fixation, by size-class x pft in kg N per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=5, ivar=ivar, & + initialize=initialize_variables, index = ih_nfix_scpf) + + end if nitrogen_active_if2 ! PHOSPHORUS @@ -6860,20 +6982,20 @@ subroutine define_history_vars(this, initialize_variables) units='kg m-2 s-1', & long='phosphorus uptake rate by plants, by size-class x pft in kg P per m2 per second', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & + hlms='CLM:ALM', upfreq=5, ivar=ivar, & initialize=initialize_variables, index = ih_puptake_scpf) call this%set_history_var(vname='FATES_PEFFLUX_SZPF', & units='kg m-2 s-1', & long='phosphorus efflux, root to soil, by size-class x pft in kg P per m2 per second', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & + hlms='CLM:ALM', upfreq=5, ivar=ivar, & initialize=initialize_variables, index = ih_pefflux_scpf) call this%set_history_var(vname='FATES_PDEMAND_SZPF', units='kg m-2 s-1', & long='plant P need (algorithm dependent), by size-class x pft in kg P per m2 per second', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & + hlms='CLM:ALM', upfreq=5, ivar=ivar, & initialize=initialize_variables, index = ih_pdemand_scpf) end if phosphorus_active_if2 diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index eb93ab70cc..23787241bb 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -111,7 +111,7 @@ module FatesRestartInterfaceMod integer :: ir_gpp_acc_hold_co integer :: ir_npp_acc_hold_co integer :: ir_resp_acc_hold_co - integer :: ir_resp_m_def_co + integer :: ir_resp_excess_co integer :: ir_bmort_co integer :: ir_hmort_co integer :: ir_cmort_co @@ -125,10 +125,8 @@ module FatesRestartInterfaceMod integer :: ir_daily_nh4_uptake_co integer :: ir_daily_no3_uptake_co + integer :: ir_daily_n_fixation_co integer :: ir_daily_p_uptake_co - integer :: ir_daily_c_efflux_co - integer :: ir_daily_n_efflux_co - integer :: ir_daily_p_efflux_co integer :: ir_daily_n_demand_co integer :: ir_daily_p_demand_co @@ -214,8 +212,6 @@ module FatesRestartInterfaceMod integer :: ir_cwdbgin_flxdg integer :: ir_leaflittin_flxdg integer :: ir_rootlittin_flxdg - integer :: ir_efflux_flxdg - integer :: ir_uptake_flxdg integer :: ir_oldstock_mbal integer :: ir_errfates_mbal integer :: ir_prt_base ! Base index for all PRT variables @@ -767,10 +763,10 @@ subroutine define_restart_vars(this, initialize_variables) units='kgC/indiv/year', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_resp_acc_hold_co ) - call this%set_restart_var(vname='fates_resp_m_def', vtype=cohort_r8, & + call this%set_restart_var(vname='fates_resp_excess', vtype=cohort_r8, & long_name='ed cohort - maintenance respiration deficit', & units='kgC/indiv', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_resp_m_def_co ) + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_resp_excess_co ) call this%set_restart_var(vname='fates_bmort', vtype=cohort_r8, & long_name='ed cohort - background mortality rate', & @@ -797,26 +793,16 @@ subroutine define_restart_vars(this, initialize_variables) units='kg/plant/day', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_daily_no3_uptake_co ) + call this%set_restart_var(vname='fates_daily_n_fixation', vtype=cohort_r8, & + long_name='fates cohort- daily N symbiotic fixation', & + units='kg/plant/day', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_daily_n_fixation_co ) + call this%set_restart_var(vname='fates_daily_p_uptake', vtype=cohort_r8, & long_name='fates cohort- daily phosphorus uptake', & units='kg/plant/day', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_daily_p_uptake_co ) - call this%set_restart_var(vname='fates_daily_c_efflux', vtype=cohort_r8, & - long_name='fates cohort- daily carbon efflux', & - units='kg/plant/day', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_daily_c_efflux_co ) - - call this%set_restart_var(vname='fates_daily_n_efflux', vtype=cohort_r8, & - long_name='fates cohort- daily nitrogen efflux', & - units='kg/plant/day', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_daily_n_efflux_co ) - - call this%set_restart_var(vname='fates_daily_p_efflux', vtype=cohort_r8, & - long_name='fates cohort- daily phosphorus efflux', & - units='kg/plant/day', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_daily_p_efflux_co ) - call this%set_restart_var(vname='fates_daily_p_demand', vtype=cohort_r8, & long_name='fates cohort- daily phosphorus demand', & units='kgP/plant/day', flushval = flushzero, & @@ -1027,17 +1013,6 @@ subroutine define_restart_vars(this, initialize_variables) units='kg/ha', veclength=num_elements, flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_rootlittin_flxdg) - call this%RegisterCohortVector(symbol_base='fates_efflux_scpf', vtype=cohort_r8, & - long_name_base='Efflux from plants to soil through roots', & - units='kg/day/ha', veclength=num_elements, flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_efflux_flxdg) - - call this%RegisterCohortVector(symbol_base='fates_uptake_scpf', vtype=cohort_r8, & - long_name_base='Daily uptake for plants through roots', & - units='kg/day/ha', veclength=num_elements, flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_uptake_flxdg) - - ! Site level Mass Balance State Accounting call this%RegisterCohortVector(symbol_base='fates_oldstock', vtype=site_r8, & @@ -1773,16 +1748,14 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_gpp_acc_hold_co => this%rvars(ir_gpp_acc_hold_co)%r81d, & rio_resp_acc_hold_co => this%rvars(ir_resp_acc_hold_co)%r81d, & rio_npp_acc_hold_co => this%rvars(ir_npp_acc_hold_co)%r81d, & - rio_resp_m_def_co => this%rvars(ir_resp_m_def_co)%r81d, & + rio_resp_excess_co => this%rvars(ir_resp_excess_co)%r81d, & rio_bmort_co => this%rvars(ir_bmort_co)%r81d, & rio_hmort_co => this%rvars(ir_hmort_co)%r81d, & rio_cmort_co => this%rvars(ir_cmort_co)%r81d, & rio_daily_nh4_uptake_co => this%rvars(ir_daily_nh4_uptake_co)%r81d, & rio_daily_no3_uptake_co => this%rvars(ir_daily_no3_uptake_co)%r81d, & + rio_daily_n_fixation_co => this%rvars(ir_daily_n_fixation_co)%r81d, & rio_daily_p_uptake_co => this%rvars(ir_daily_p_uptake_co)%r81d, & - rio_daily_c_efflux_co => this%rvars(ir_daily_c_efflux_co)%r81d, & - rio_daily_n_efflux_co => this%rvars(ir_daily_n_efflux_co)%r81d, & - rio_daily_p_efflux_co => this%rvars(ir_daily_p_efflux_co)%r81d, & rio_daily_n_demand_co => this%rvars(ir_daily_n_demand_co)%r81d, & rio_daily_p_demand_co => this%rvars(ir_daily_p_demand_co)%r81d, & rio_smort_co => this%rvars(ir_smort_co)%r81d, & @@ -1890,17 +1863,6 @@ subroutine set_restart_vectors(this,nc,nsites,sites) io_idx_si_pft = io_idx_si_pft + 1 end do - iscpf = 1 - do i_scls = 1, nlevsclass - do i_pft = 1, numpft - this%rvars(ir_efflux_flxdg+el-1)%r81d(io_idx_si_scpf) = sites(s)%flux_diags(el)%nutrient_efflux_scpf(iscpf) - this%rvars(ir_uptake_flxdg+el-1)%r81d(io_idx_si_scpf) = sites(s)%flux_diags(el)%nutrient_uptake_scpf(iscpf) - iscpf = iscpf + 1 - io_idx_si_scpf = io_idx_si_scpf + 1 - end do - end do - - this%rvars(ir_oldstock_mbal+el-1)%r81d(io_idx_si) = sites(s)%mass_balance(el)%old_stock this%rvars(ir_errfates_mbal+el-1)%r81d(io_idx_si) = sites(s)%mass_balance(el)%err_fates @@ -2003,7 +1965,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_resp_acc_hold_co(io_idx_co) = ccohort%resp_acc_hold rio_npp_acc_hold_co(io_idx_co) = ccohort%npp_acc_hold - rio_resp_m_def_co(io_idx_co) = ccohort%resp_m_def + rio_resp_excess_co(io_idx_co) = ccohort%resp_excess rio_bmort_co(io_idx_co) = ccohort%bmort rio_hmort_co(io_idx_co) = ccohort%hmort @@ -2016,11 +1978,8 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_daily_no3_uptake_co(io_idx_co) = ccohort%daily_no3_uptake rio_daily_nh4_uptake_co(io_idx_co) = ccohort%daily_nh4_uptake rio_daily_p_uptake_co(io_idx_co) = ccohort%daily_p_uptake - - rio_daily_c_efflux_co(io_idx_co) = ccohort%daily_c_efflux - rio_daily_n_efflux_co(io_idx_co) = ccohort%daily_n_efflux - rio_daily_p_efflux_co(io_idx_co) = ccohort%daily_p_efflux - + rio_daily_n_fixation_co(io_idx_co) = ccohort%daily_n_fixation + rio_daily_n_demand_co(io_idx_co) = ccohort%daily_n_demand rio_daily_p_demand_co(io_idx_co) = ccohort%daily_p_demand @@ -2602,16 +2561,14 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_gpp_acc_hold_co => this%rvars(ir_gpp_acc_hold_co)%r81d, & rio_resp_acc_hold_co => this%rvars(ir_resp_acc_hold_co)%r81d, & rio_npp_acc_hold_co => this%rvars(ir_npp_acc_hold_co)%r81d, & - rio_resp_m_def_co => this%rvars(ir_resp_m_def_co)%r81d, & + rio_resp_excess_co => this%rvars(ir_resp_excess_co)%r81d, & rio_bmort_co => this%rvars(ir_bmort_co)%r81d, & rio_hmort_co => this%rvars(ir_hmort_co)%r81d, & rio_cmort_co => this%rvars(ir_cmort_co)%r81d, & rio_daily_nh4_uptake_co => this%rvars(ir_daily_nh4_uptake_co)%r81d, & rio_daily_no3_uptake_co => this%rvars(ir_daily_no3_uptake_co)%r81d, & + rio_daily_n_fixation_co => this%rvars(ir_daily_n_fixation_co)%r81d, & rio_daily_p_uptake_co => this%rvars(ir_daily_p_uptake_co)%r81d, & - rio_daily_c_efflux_co => this%rvars(ir_daily_c_efflux_co)%r81d, & - rio_daily_n_efflux_co => this%rvars(ir_daily_n_efflux_co)%r81d, & - rio_daily_p_efflux_co => this%rvars(ir_daily_p_efflux_co)%r81d, & rio_daily_n_demand_co => this%rvars(ir_daily_n_demand_co)%r81d, & rio_daily_p_demand_co => this%rvars(ir_daily_p_demand_co)%r81d, & rio_smort_co => this%rvars(ir_smort_co)%r81d, & @@ -2709,17 +2666,6 @@ subroutine get_restart_vectors(this, nc, nsites, sites) io_idx_si_pft = io_idx_si_pft + 1 end do - iscpf = 1 - do i_scls = 1, nlevsclass - do i_pft = 1, numpft - sites(s)%flux_diags(el)%nutrient_efflux_scpf(iscpf) = this%rvars(ir_efflux_flxdg+el-1)%r81d(io_idx_si_scpf) - sites(s)%flux_diags(el)%nutrient_uptake_scpf(iscpf) = this%rvars(ir_uptake_flxdg+el-1)%r81d(io_idx_si_scpf) - iscpf = iscpf + 1 - io_idx_si_scpf = io_idx_si_scpf + 1 - end do - end do - - sites(s)%mass_balance(el)%old_stock = this%rvars(ir_oldstock_mbal+el-1)%r81d(io_idx_si) sites(s)%mass_balance(el)%err_fates = this%rvars(ir_errfates_mbal+el-1)%r81d(io_idx_si) @@ -2803,7 +2749,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ccohort%gpp_acc_hold = rio_gpp_acc_hold_co(io_idx_co) ccohort%resp_acc_hold = rio_resp_acc_hold_co(io_idx_co) ccohort%npp_acc_hold = rio_npp_acc_hold_co(io_idx_co) - ccohort%resp_m_def = rio_resp_m_def_co(io_idx_co) + ccohort%resp_excess = rio_resp_excess_co(io_idx_co) ccohort%bmort = rio_bmort_co(io_idx_co) ccohort%hmort = rio_hmort_co(io_idx_co) @@ -2815,10 +2761,8 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ! Nutrient uptake / efflux ccohort%daily_nh4_uptake = rio_daily_nh4_uptake_co(io_idx_co) ccohort%daily_no3_uptake = rio_daily_no3_uptake_co(io_idx_co) + ccohort%daily_n_fixation = rio_daily_n_fixation_co(io_idx_co) ccohort%daily_p_uptake = rio_daily_p_uptake_co(io_idx_co) - ccohort%daily_c_efflux = rio_daily_c_efflux_co(io_idx_co) - ccohort%daily_n_efflux = rio_daily_n_efflux_co(io_idx_co) - ccohort%daily_p_efflux = rio_daily_p_efflux_co(io_idx_co) ccohort%daily_n_demand = rio_daily_n_demand_co(io_idx_co) ccohort%daily_p_demand = rio_daily_p_demand_co(io_idx_co) diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 2e79fe93b6..2392f42f46 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -25,7 +25,7 @@ module PRTAllometricCNPMod use PRTGenericMod , only : store_organ use PRTGenericMod , only : repro_organ use PRTGenericMod , only : struct_organ - use PRTGenericMod , only : all_organs + use PRTGenericMod , only : num_organ_types use PRTGenericMod , only : prt_cnp_flex_allom_hyp use PRTGenericMod , only : StorageNutrientTarget @@ -108,9 +108,11 @@ module PRTAllometricCNPMod integer, parameter :: num_organs = 6 ! Converting from local to global organ id - integer, parameter,dimension(num_organs) :: organ_list = & + integer, parameter,dimension(num_organs) :: l2g_organ_list = & [leaf_organ, fnrt_organ, sapw_organ, store_organ, repro_organ, struct_organ] + + ! These are local indices associated with organs and quantities ! that can be integrated (namely, growth respiration during stature growth ! and dbh) @@ -136,8 +138,7 @@ module PRTAllometricCNPMod integer, public, parameter :: acnp_bc_inout_id_dbh = 1 ! Plant DBH - integer, public, parameter :: acnp_bc_inout_id_rmaint_def = 2 ! Index for any accumulated - ! maintenance respiration deficit + integer, public, parameter :: acnp_bc_inout_id_resp_excess = 2 ! Respiration of excess storage integer, public, parameter :: acnp_bc_inout_id_l2fr = 3 ! leaf 2 fineroot scalar, this ! is dynamic with CNP integer, public, parameter :: num_bc_inout = 3 @@ -150,15 +151,11 @@ module PRTAllometricCNPMod integer, public, parameter :: acnp_bc_in_id_ctrim = 2 ! Index for the canopy trim function integer, public, parameter :: acnp_bc_in_id_lstat = 3 ! phenology status logical integer, public, parameter :: acnp_bc_in_id_netdc = 4 ! Index for the net daily C input BC - integer, public, parameter :: acnp_bc_in_id_netdnh4 = 5 ! Index for the net daily NH4 input BC - integer, public, parameter :: acnp_bc_in_id_netdno3 = 6 ! Index for the net daily NO3 input BC - integer, public, parameter :: acnp_bc_in_id_netdp = 7 ! Index for the net daily P input BC - !integer, public, parameter :: acnp_bc_in_id_l2fr_ema = 7 ! Index for the moving average ema - !integer, public, parameter :: acnp_bc_in_id_ncs_ema = 9 ! Index for N/C storage ratio (EMA) - !integer, public, parameter :: acnp_bc_in_id_pcs_ema = 10 ! Index for P/C storage ratio (EMA) + integer, public, parameter :: acnp_bc_in_id_netdn = 5 ! Index for the net daily NH4 input BC + integer, public, parameter :: acnp_bc_in_id_netdp = 6 ! Index for the net daily P input BC ! 0=leaf off, 1=leaf on - integer, parameter :: num_bc_in = 7 + integer, parameter :: num_bc_in = 6 ! ------------------------------------------------------------------------------------- ! Output Boundary Indices (These are public) @@ -184,29 +181,24 @@ module PRTAllometricCNPMod integer, parameter :: icd = 1 - real(r8), parameter :: store_overflow_frac = 0.15 ! The fraction above target allowed in storage - - logical, parameter :: force_store_c_overflow = .true. + real(r8), parameter :: store_overflow_frac = 1.0_r8 ! The fraction above target allowed in storage - ! User may want to attempt matching results with the - ! C-only allocation module. If so, then set reproduce_conly - ! and make sure both fnrt and leaf are set to the highest - ! priority order, sapwood and storage are set to the - ! second highest, and then structure is last. When this is - ! flagged as true, it changes the logic in the first allocation - ! phase, to give first dibs to leaves, even though they are - ! in the same priority group as fineroots. - - logical, parameter :: reproduce_conly = .false. + integer, parameter :: exude_c_store_overflow = 1 + integer, parameter :: retain_c_store_overflow = 2 + integer, parameter :: burn_c_store_overflow = 3 + + integer, parameter :: store_c_overflow = burn_c_store_overflow + ! Following growth, if desired, you can prioritize reproductive + logical, parameter :: prioritize_repro_nutr_growth = .false. + ! Definitions for the regulation functions. These typically translate ! a storage fraction into a scalar used to regulate resources somehow - integer, parameter :: regulate_linear = 1 - integer, parameter :: regulate_logi = 2 - integer, parameter :: regulate_CN_logi = 3 + integer, parameter :: regulate_linear = 1 ! DEPRECATED + integer, parameter :: regulate_logi = 2 ! DEPRECATED + integer, parameter :: regulate_CN_logi = 3 ! almost deprecated integer, parameter :: regulate_CN_dfdd = 4 - integer, parameter :: regulate_CN_ema = 5 real(r8), public, parameter :: fnrt_adapt_tscl = 100._r8 ! Fine-root adaptation timescale (days) @@ -214,14 +206,6 @@ module PRTAllometricCNPMod ! for a doubling or halving of the l2fr - - - ! Array of pointers are difficult in F90 - ! This structure is a necessary intermediate - type :: parray_type - real(r8), pointer :: ptr - end type parray_type - ! ------------------------------------------------------------------------------------- ! This is the core type that holds this specific ! plant reactive transport (PRT) module @@ -258,7 +242,7 @@ module PRTAllometricCNPMod class(prt_global_type), public, target, allocatable :: prt_global_acnp character(len=*), parameter, private :: sourcefile = __FILE__ - logical, parameter :: debug = .false. + logical, parameter :: debug = .true. public :: InitPRTGlobalAllometricCNP @@ -349,7 +333,7 @@ subroutine DailyPRTAllometricCNP(this) ! Pointers to in-out bcs real(r8),pointer :: dbh ! Diameter at breast height [cm] - real(r8),pointer :: maint_r_def ! Current maintenance respiration deficit [kgC] + real(r8),pointer :: resp_excess ! Respiration of any un-allocatable C real(r8),pointer :: l2fr ! Leaf to fineroot ratio of target biomass ! Input only bcs @@ -358,36 +342,28 @@ subroutine DailyPRTAllometricCNP(this) real(r8) :: n_gain ! Daily nitrogen uptake through fine-roots [kgN] real(r8) :: p_gain ! Daily phosphorus uptake through fine-roots [kgN] real(r8) :: canopy_trim ! The canopy trimming function [0-1] - !real(r8) :: l2fr_ema ! Mean (EMA) l2fr ! Pointers to output bcs real(r8),pointer :: c_efflux ! Total plant efflux of carbon (kgC) real(r8),pointer :: n_efflux ! Total plant efflux of nitrogen (kgN) real(r8),pointer :: p_efflux ! Total plant efflux of phosphorus (kgP) - real(r8),pointer :: growth_r ! Total plant growth respiration this step (kgC) - ! These are pointers to the state variables, rearranged in organ dimensioned - ! arrays. This is useful because we loop through organs so often - type(parray_type),pointer :: state_c(:) ! State array for carbon, by organ [kg] - type(parray_type),pointer :: state_n(:) ! State array for N, by organ [kg] - type(parray_type),pointer :: state_p(:) ! State array for P, by organ [kg] + ! Allometry targets (kg/plant) and (kg/cm/plant) + real(r8), dimension(num_organ_types) :: target_c, target_dcdd + ! Initial states (for accounting) (kg/plant) + real(r8), dimension(num_organ_types) :: state_c0, state_n0, state_p0 + ! Allometry partial targets + real(r8) :: agw_c_target,agw_dcdd_target + real(r8) :: bgw_c_target,bgw_dcdd_target + real(r8) :: sapw_area + integer :: i ! generic organ loop index integer :: i_org ! organ index integer :: i_var ! variable index ! Agruments for allometry functions, that are not in the target_c array - real(r8) :: agw_c_target,agw_dcdd_target - real(r8) :: bgw_c_target,bgw_dcdd_target - real(r8) :: sapw_area - integer :: cnp_limiter + real(r8) :: max_store_n - ! These arrays hold various support variables dimensioned by organ - ! Zero suffix indicates the initial state values at the beginning of the routine - ! _unl suffix indicates values used for tracking nutrient need (ie unlimited) - ! target is the target masses associated with the plant stature, and - ! also the derivative of c wrt diameter at current diameter - real(r8), dimension(num_organs) :: target_c, target_dcdd - real(r8), dimension(num_organs) :: state_c0, state_n0, state_p0 ! These are daily mass gains, frozen in time, not drawn from, and thus ! these are only used for evaluating mass balancing at the end @@ -395,7 +371,7 @@ subroutine DailyPRTAllometricCNP(this) real(r8) :: c_gain0 real(r8) :: n_gain0 real(r8) :: p_gain0 - real(r8) :: maint_r_def0 + real(r8) :: resp_excess0 ! Used for mass checking, total mass allocated based ! on change in the states, should match gain0's @@ -406,18 +382,18 @@ subroutine DailyPRTAllometricCNP(this) real(r8) :: sum_c ! error checking sum - - ! =================================================================================== - ! Step 1: Evaluate nutrient storage in the plant. Depending on how low - ! these stores are, we will move proportionally more or less of the daily carbon - ! gain to increase the target fine-root biomass, fill up to target - ! and then attempt to get them up to stoichiometry targets. - ! =================================================================================== - - ! This routine actually just updates the l2fr variable - call this%CNPAdjustFRootTargets() + ! If more than 1 leaf age bin is present, this + ! call advances leaves in their age, but does + ! not actually remove any biomass from the plant + + call this%AgeLeaves(ipft,sec_per_day) + ! In/out boundary conditions + resp_excess => this%bc_inout(acnp_bc_inout_id_resp_excess)%rval; resp_excess0 = resp_excess + dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval; dbh0 = dbh + l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval + ! integrator variables ! Copy the input only boundary conditions into readable local variables @@ -426,85 +402,75 @@ subroutine DailyPRTAllometricCNP(this) ! for checking and resetting if needed ! ----------------------------------------------------------------------------------- c_gain = this%bc_in(acnp_bc_in_id_netdc)%rval; c_gain0 = c_gain - n_gain = this%bc_in(acnp_bc_in_id_netdnh4)%rval + & - this%bc_in(acnp_bc_in_id_netdno3)%rval - n_gain0 = n_gain + n_gain = this%bc_in(acnp_bc_in_id_netdn)%rval; n_gain0 = n_gain p_gain = this%bc_in(acnp_bc_in_id_netdp)%rval; p_gain0 = p_gain canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival + ! Calculate Carbon allocation targets + ! ----------------------------------------------------------------------------------- + + ! Set carbon targets based on the plant's current stature + target_c(:) = fates_unset_r8 + target_dcdd(:) = fates_unset_r8 + call bsap_allom(dbh,ipft,canopy_trim,sapw_area,target_c(sapw_organ),target_dcdd(sapw_organ)) + call bagw_allom(dbh,ipft,agw_c_target,agw_dcdd_target) + call bbgw_allom(dbh,ipft,bgw_c_target,bgw_dcdd_target) + call bdead_allom(agw_c_target,bgw_c_target,target_c(sapw_organ),ipft,target_c(struct_organ), & + agw_dcdd_target,bgw_dcdd_target,target_dcdd(sapw_organ),target_dcdd(struct_organ)) + call bleaf(dbh,ipft,canopy_trim, target_c(leaf_organ), target_dcdd(leaf_organ)) + call bfineroot(dbh,ipft,canopy_trim, l2fr, target_c(fnrt_organ), target_dcdd(fnrt_organ)) + call bstore_allom(dbh,ipft,canopy_trim, target_c(store_organ), target_dcdd(store_organ)) + target_c(repro_organ) = 0._r8 + target_dcdd(repro_organ) = 0._r8 + + + ! =================================================================================== + ! Step 1: Evaluate nutrient storage in the plant. Depending on how low + ! these stores are, we will move proportionally more or less of the daily carbon + ! gain to increase the target fine-root biomass, fill up to target + ! and then attempt to get them up to stoichiometry targets. + ! =================================================================================== + + ! This routine updates the l2fr (leaf 2 fine-root multiplier) variable + call this%CNPAdjustFRootTargets(target_c) + + + c_gain0 = c_gain + n_gain0 = n_gain + p_gain0 = p_gain + ! Output only boundary conditions c_efflux => this%bc_out(acnp_bc_out_id_cefflux)%rval; c_efflux = 0._r8 n_efflux => this%bc_out(acnp_bc_out_id_nefflux)%rval; n_efflux = 0._r8 p_efflux => this%bc_out(acnp_bc_out_id_pefflux)%rval; p_efflux = 0._r8 - ! In/out boundary conditions - maint_r_def => this%bc_inout(acnp_bc_inout_id_rmaint_def)%rval; maint_r_def0 = maint_r_def - dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval; dbh0 = dbh - l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval - - - ! If more than 1 leaf age bin is present, this - ! call advances leaves in their age, but does - ! not actually remove any biomass from the plant - call this%AgeLeaves(ipft,sec_per_day) + - ! Set all of the per-organ pointer arrays - ! Note: Since growth only happens in the 1st leaf bin, we only - ! point to that bin. However, we need to account for all bins - ! when we calculate the deficit + + - allocate(state_c(num_organs)) - allocate(state_n(num_organs)) - allocate(state_p(num_organs)) + ! Remember the original C,N,P states to help with final + ! evaluation of how much was allocated + ! ----------------------------------------------------------------------------------- - ! Set carbon targets based on the plant's current stature - target_c(:) = fates_unset_r8 - target_dcdd(:) = fates_unset_r8 - call bsap_allom(dbh,ipft,canopy_trim,sapw_area,target_c(sapw_id),target_dcdd(sapw_id) ) - call bagw_allom(dbh,ipft,agw_c_target,agw_dcdd_target) - call bbgw_allom(dbh,ipft,bgw_c_target,bgw_dcdd_target) - call bdead_allom(agw_c_target,bgw_c_target, target_c(sapw_id), ipft, target_c(struct_id), & - agw_dcdd_target, bgw_dcdd_target, target_dcdd(sapw_id), target_dcdd(struct_id)) - call bleaf(dbh,ipft,canopy_trim, target_c(leaf_id), target_dcdd(leaf_id)) - call bfineroot(dbh,ipft,canopy_trim, l2fr, target_c(fnrt_id), target_dcdd(fnrt_id)) - call bstore_allom(dbh,ipft,canopy_trim, target_c(store_id), target_dcdd(store_id)) - target_c(repro_id) = 0._r8 - target_dcdd(repro_id) = 0._r8 - - ! Initialize the the state, and keep a record of this state - ! as we may actuall run the allocation process twice, and - ! will need this state to both reset, and measure total - ! mass fluxes - do i_org = 1,num_organs - - i_var = prt_global%sp_organ_map(organ_list(i_org),carbon12_element) - state_c(i_org)%ptr => this%variables(i_var)%val(1) + do i = 1,num_organs + i_org = l2g_organ_list(i) ! global index from PRTGeneric + i_var = prt_global%sp_organ_map(i_org,carbon12_element) state_c0(i_org) = this%variables(i_var)%val(1) - - i_var = prt_global%sp_organ_map(organ_list(i_org),nitrogen_element) - state_n(i_org)%ptr => this%variables(i_var)%val(1) + i_var = prt_global%sp_organ_map(i_org,nitrogen_element) state_n0(i_org) = this%variables(i_var)%val(1) - - i_var = prt_global%sp_organ_map(organ_list(i_org),phosphorus_element) - state_p(i_org)%ptr => this%variables(i_var)%val(1) + i_var = prt_global%sp_organ_map(i_org,phosphorus_element) state_p0(i_org) = this%variables(i_var)%val(1) - end do - call bfineroot(dbh,ipft,canopy_trim, l2fr, target_c(fnrt_id), target_dcdd(fnrt_id)) - ! =================================================================================== ! Step 0. Transfer all stored nutrient into the daily uptake pool. ! =================================================================================== - - !i_var = prt_global%sp_organ_map(store_organ,carbon12_element) - !c_gain = c_gain + max(0._r8,sum(this%variables(i_var)%val(:))-target_c(store_id)) - !this%variables(i_var)%val(1) = this%variables(i_var)%val(1)-max(0._r8,sum(this%variables(i_var)%val(:))-target_c(store_id)) i_var = prt_global%sp_organ_map(store_organ,nitrogen_element) n_gain = n_gain + sum(this%variables(i_var)%val(:)) @@ -519,21 +485,21 @@ subroutine DailyPRTAllometricCNP(this) ! any un-paid maintenance respiration from storage. ! =================================================================================== - call this%CNPPrioritizedReplacement(maint_r_def, c_gain, n_gain, p_gain, & - state_c, state_n, state_p, target_c) - - + call this%CNPPrioritizedReplacement(c_gain, n_gain, p_gain, target_c) + sum_c = 0._r8 - do i_org = 1,num_organs - sum_c = sum_c+state_c(i_org)%ptr + do i = 1,num_organs + i_org = l2g_organ_list(i) + i_var = prt_global%sp_organ_map(i_org,carbon12_element) + sum_c = sum_c+this%variables(i_var)%val(1) end do if( abs((c_gain0-c_gain) - & - (sum_c-sum(state_c0(:),dim=1)+(maint_r_def0-maint_r_def))) >calloc_abs_error ) then + (sum_c-sum(state_c0(:),dim=1))) >calloc_abs_error ) then write(fates_log(),*) 'Carbon not balancing I' - do i_org = 1,num_organs - write(fates_log(),*) 'state_c: ',state_c(i_org)%ptr,state_c0(i_org) + do i = 1,num_organs + i_org = l2g_organ_list(i) + write(fates_log(),*) 'c: ',this%variables(prt_global%sp_organ_map(i_org,carbon12_element))%val(1) end do - write(fates_log(),*) maint_r_def0-maint_r_def call endrun(msg=errMsg(sourcefile, __LINE__)) end if @@ -544,23 +510,24 @@ subroutine DailyPRTAllometricCNP(this) ! targets based on prioritized relative demand and allometry functions. ! =================================================================================== - call this%CNPStatureGrowth(c_gain, n_gain, p_gain, & - state_c, state_n, state_p, target_c, target_dcdd, cnp_limiter) - + call this%CNPStatureGrowth(c_gain, n_gain, p_gain, target_c, target_dcdd) + sum_c = 0._r8 - do i_org = 1,num_organs - sum_c = sum_c+state_c(i_org)%ptr + do i = 1,num_organs + i_org = l2g_organ_list(i) + i_var = prt_global%sp_organ_map(i_org,carbon12_element) + sum_c = sum_c+this%variables(i_var)%val(1) end do if( abs((c_gain0-c_gain) - & - (sum_c-sum(state_c0(:),dim=1)+(maint_r_def0-maint_r_def))) >calloc_abs_error ) then - write(fates_log(),*) 'Carbon not balanceing II' - do i_org = 1,num_organs - write(fates_log(),*) 'state_c: ',state_c(i_org)%ptr,state_c0(i_org) + (sum_c-sum(state_c0(:),dim=1))) >calloc_abs_error ) then + write(fates_log(),*) 'Carbon not balancing II' + do i = 1,num_organs + i_org = l2g_organ_list(i) + write(fates_log(),*) 'c: ',this%variables(prt_global%sp_organ_map(i_org,carbon12_element))%val(1) end do - write(fates_log(),*) maint_r_def0-maint_r_def call endrun(msg=errMsg(sourcefile, __LINE__)) end if - + ! =================================================================================== ! Step 3. ! At this point, at least 1 of the 3 resources have been used up. @@ -568,8 +535,9 @@ subroutine DailyPRTAllometricCNP(this) ! =================================================================================== call this%CNPAllocateRemainder(c_gain, n_gain, p_gain, & - state_c, state_n, state_p, c_efflux, n_efflux, p_efflux) + c_efflux, n_efflux, p_efflux) + ! Error Check: Make sure that the mass gains are completely used up if( abs(c_gain) > calloc_abs_error .or. & abs(n_gain) > 0.1_r8*calloc_abs_error .or. & @@ -585,33 +553,34 @@ subroutine DailyPRTAllometricCNP(this) ! Perform a final tally on what was used (allocated) ! Since this is also a check against what was available - ! we include maintenance pay-back and efflux to the "allocated" - ! pool to make sure everything balances. + ! we include what is lost through respiration of excess storage - allocated_c = (maint_r_def0-maint_r_def) + c_efflux + allocated_c = (resp_excess-resp_excess0) + c_efflux allocated_n = n_efflux allocated_p = p_efflux ! Update the allocation flux diagnostic arrays for each 3 elements - do i_org = 1,num_organs - - i_var = prt_global%sp_organ_map(organ_list(i_org),carbon12_element) + do i = 1,num_organs + + i_org = l2g_organ_list(i) + + i_var = prt_global%sp_organ_map(i_org,carbon12_element) this%variables(i_var)%net_alloc(1) = & - this%variables(i_var)%net_alloc(1) + (state_c(i_org)%ptr - state_c0(i_org)) + this%variables(i_var)%net_alloc(1) + (this%variables(i_var)%val(1) - state_c0(i_org)) - allocated_c = allocated_c + (state_c(i_org)%ptr - state_c0(i_org)) + allocated_c = allocated_c + (this%variables(i_var)%val(1) - state_c0(i_org)) - i_var = prt_global%sp_organ_map(organ_list(i_org),nitrogen_element) + i_var = prt_global%sp_organ_map(i_org,nitrogen_element) this%variables(i_var)%net_alloc(1) = & - this%variables(i_var)%net_alloc(1) + (state_n(i_org)%ptr - state_n0(i_org)) + this%variables(i_var)%net_alloc(1) + (this%variables(i_var)%val(1) - state_n0(i_org)) - allocated_n = allocated_n + (state_n(i_org)%ptr - state_n0(i_org)) + allocated_n = allocated_n + (this%variables(i_var)%val(1) - state_n0(i_org)) - i_var = prt_global%sp_organ_map(organ_list(i_org),phosphorus_element) + i_var = prt_global%sp_organ_map(i_org,phosphorus_element) this%variables(i_var)%net_alloc(1) = & - this%variables(i_var)%net_alloc(1) + (state_p(i_org)%ptr - state_p0(i_org)) + this%variables(i_var)%net_alloc(1) + (this%variables(i_var)%val(1) - state_p0(i_org)) - allocated_p = allocated_p + (state_p(i_org)%ptr - state_p0(i_org)) + allocated_p = allocated_p + (this%variables(i_var)%val(1) - state_p0(i_org)) end do @@ -628,29 +597,24 @@ subroutine DailyPRTAllometricCNP(this) write(fates_log(),*) 'n_gain0: ',n_gain0,' allocated_n: ',allocated_n write(fates_log(),*) 'p_gain0: ',p_gain0,' allocated_p: ',allocated_p - do i_org = 1,num_organs - write(fates_log(),*) i_org, state_c(i_org)%ptr-state_c0(i_org) + do i = 1,num_organs + i_org = l2g_organ_list(i) + i_var = prt_global%sp_organ_map(i_org,carbon12_element) + write(fates_log(),*) i_org, this%variables(i_var)%val(1)-state_c0(i_org) end do - write(fates_log(),*) (maint_r_def0-maint_r_def), c_efflux call endrun(msg=errMsg(sourcefile, __LINE__)) end if end if - - !target_n = this%GetNutrientTarget(nitrogen_element,store_organ,stoich_max) - !target_p = this%GetNutrientTarget(phosphorus_element,store_organ,stoich_max) - - deallocate(state_c) - deallocate(state_n) - deallocate(state_p) return end subroutine DailyPRTAllometricCNP ! ===================================================================================== - subroutine CNPAdjustFRootTargets(this) + subroutine CNPAdjustFRootTargets(this, target_c) class(cnp_allom_prt_vartypes) :: this - + real(r8) :: target_c(:) + real(r8), pointer :: l2fr ! leaf to fineroot target biomass scaler integer :: ipft ! PFT index real(r8), pointer :: dbh @@ -658,8 +622,6 @@ subroutine CNPAdjustFRootTargets(this) !!real(r8) :: l2fr_ema ! Moving average L2FR (EMA) real(r8) :: l2fr_actual - real(r8) :: fnrt_c_target ! Target fineroot C before we change l2fr - real(r8) :: leaf_c_target real(r8) :: n_regulator ! Nitrogen storage regulation function scaler real(r8) :: p_regulator ! Phosphorus storage regulation function scaler real(r8) :: np_regulator ! Combined NP storage regulation function scaler @@ -672,19 +634,18 @@ subroutine CNPAdjustFRootTargets(this) real(r8) :: loss_flux_p real(r8) :: fnrt_c_above_target - integer, parameter :: regulate_type = regulate_CN_ema + integer, parameter :: regulate_type = regulate_CN_dfdd ipft = this%bc_in(acnp_bc_in_id_pft)%ival l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval - !!l2fr_ema = this%bc_in(acnp_bc_in_id_l2fr_ema)%rval associate( l2fr_min => prt_params%allom_l2fr_min(ipft), & l2fr_max => prt_params%allom_l2fr_max(ipft)) - call this%StorageRegulator(nitrogen_element, regulate_type,n_regulator) - call this%StorageRegulator(phosphorus_element, regulate_type,p_regulator) + call this%StorageRegulator(nitrogen_element, regulate_type,target_c,n_regulator) + call this%StorageRegulator(phosphorus_element, regulate_type,target_c,p_regulator) ! We take the maximum here, because the maximum is reflective of the ! element with the lowest storage, which is the limiting element @@ -698,57 +659,23 @@ subroutine CNPAdjustFRootTargets(this) l2fr = l2fr_min + max(0._r8,min(1.0_r8,np_regulator))*(l2fr_max-l2fr_min) - - elseif(regulate_type == regulate_CN_ema) then + elseif(regulate_type == regulate_CN_dfdd) then ! To prevent the target l2fr from diverging too far from the ! actual l2fr, create some constraints. l2fr_actual = this%GetState(fnrt_organ, carbon12_element)/this%GetState(leaf_organ, carbon12_element) ! Only update L2FR if some leaves are out - call bleaf(dbh,ipft,canopy_trim,leaf_c_target) - if(this%GetState(leaf_organ, carbon12_element)/leaf_c_target>0.5_r8) then + if(this%GetState(leaf_organ, carbon12_element)/target_c(leaf_organ) >0.5_r8) then l2fr = l2fr * np_regulator end if - - elseif(regulate_type == regulate_CN_dfdd)then - - ! Also, we aren't allowed to increase root biomass target if - ! we are very low on root biomass relative to the target - ! And we aren't allowed to reduce the target if we are above the target - - call bfineroot(dbh,ipft,canopy_trim,l2fr,fnrt_c_target) - fnrt_frac = this%GetState(fnrt_organ, carbon12_element)/fnrt_c_target - - turnfrac = (years_per_day / prt_params%root_long(ipft)) - - ! If there is low root compared to the max, don't allow cap growth - if(fnrt_frac < 1._r8-1.5_r8*turnfrac)then - np_regulator = min(np_regulator,1.0) - end if - - ! If there is high root compared to the max, don't allow cap decrease - if(fnrt_frac > 1.0_r8+1.5_r8*turnfrac)then - np_regulator = max(np_regulator,1.0) - end if - - ! Don't allow us to drop l2fr more than what the maximum loss to turnover - ! would be for one day. - ! this will prevent the algorithm from snowballing. This is doubly important - ! because if C is low compared to N or P, then the plant is probably - ! not very productive, and will not be growing. A growing plant can reach - ! equilibrium root mass more quickly. (might be unnecessary given - ! the growth caps prior to this...?) - - l2fr = l2fr * min(max(np_regulator,1._r8-2._r8*turnfrac),1._r8+2._r8*turnfrac) - end if ! Find the updated target fineroot biomass - call bfineroot(dbh,ipft,canopy_trim, l2fr, fnrt_c_target) + call bfineroot(dbh,ipft,canopy_trim, l2fr, target_c(fnrt_organ)) - fnrt_c_above_target = max(0._r8,this%GetState(fnrt_organ, carbon12_element) - fnrt_c_target) + fnrt_c_above_target = max(0._r8,this%GetState(fnrt_organ, carbon12_element) - target_c(fnrt_organ)) ! Allow no reabsorption? (any reabsorption of nutrients will further push the N/C or P/C imbalance ! and if we are dropping roots, its because we had excess nutrient compared to carbon anyway @@ -765,7 +692,7 @@ subroutine CNPAdjustFRootTargets(this) loss_flux_n = loss_flux_c*this%variables(fnrt_n_id)%val(1)/this%variables(fnrt_c_id)%val(1) this%variables(fnrt_n_id)%val(1) = this%variables(fnrt_n_id)%val(1) - loss_flux_n - this%variables(fnrt_n_id)%turnover(1) = this%variables(fnrt_n_id)%turnover(1) + loss_flux_p + this%variables(fnrt_n_id)%turnover(1) = this%variables(fnrt_n_id)%turnover(1) + loss_flux_n loss_flux_p = loss_flux_c*this%variables(fnrt_p_id)%val(1)/this%variables(fnrt_c_id)%val(1) this%variables(fnrt_p_id)%val(1) = this%variables(fnrt_p_id)%val(1) - loss_flux_p @@ -783,10 +710,8 @@ end subroutine CNPAdjustFRootTargets ! ===================================================================================== - subroutine CNPPrioritizedReplacement(this, & - maint_r_deficit, c_gain, n_gain, p_gain, & - state_c, state_n, state_p, target_c) - + subroutine CNPPrioritizedReplacement(this,c_gain, n_gain, p_gain, target_c) + ! ----------------------------------------------------------------------------------- ! Alternative allocation hypothesis for the prioritized replacement phase. @@ -797,19 +722,17 @@ subroutine CNPPrioritizedReplacement(this, & real(r8), intent(inout) :: c_gain real(r8), intent(inout) :: n_gain real(r8), intent(inout) :: p_gain - real(r8), intent(inout) :: maint_r_deficit ! Not currently used - type(parray_type) :: state_c(:) ! State array for carbon, by organ [kg] - type(parray_type) :: state_n(:) ! State array for N, by organ [kg] - type(parray_type) :: state_p(:) ! State array for P, by organ [kg] - real(r8), intent(in) :: target_c(:) - + real(r8), intent(in) :: target_c(:) ! Indexed by global organ (from PRTGenericMod) + integer :: n_curpri_org - integer, dimension(num_organs) :: curpri_org ! C variable ID's of the current priority level + + integer, dimension(num_organs) :: curpri_org ! organ ID's of the current priority level real(r8), dimension(num_organs) :: deficit_c ! Deficit to get to target from current [kg] real(r8), dimension(num_organs) :: deficit_n ! Deficit to get to target from current [kg] real(r8), dimension(num_organs) :: deficit_p ! Deficit to get to target from current [kg] + integer :: i, ii, i_org ! Loop indices (mostly for organs) - integer :: i_cvar ! variable index + integer :: i_var ! variable index integer :: i_pri ! loop index for priority integer :: ipft ! Plant functional type index of this plant integer :: leaf_status ! Is this plant in a leaf on or off status? @@ -818,7 +741,7 @@ subroutine CNPPrioritizedReplacement(this, & real(r8) :: target_n ! Target mass of N for a given organ [kg] real(r8) :: target_p ! Target mass of P for a given organ [kg] integer :: priority_code ! Index for priority level of each organ - real(r8) :: sum_c_demand ! Carbon demanded to bring tissues up to allometry (kg) + real(r8) :: sum_c_demand ! Carbon demanded to bring tissues up to allometry (kg) real(r8) :: sum_n_deficit ! The nitrogen deficit of all pools for given priority level (kg) real(r8) :: sum_p_deficit ! The phosphorus deficit of all pools for given priority level (kg) real(r8) :: store_below_target @@ -832,17 +755,45 @@ subroutine CNPPrioritizedReplacement(this, & real(r8) :: gr_flux ! carbon flux to fulfill growth respiration of an arbitrary pool (kg) real(r8) :: n_flux ! nitrogen flux into an arbitrary pool (kg) real(r8) :: p_flux ! phosphorus flux into an arbitrary pool (kg) - real(r8) :: maint_r_def_flux ! Flux into maintenance respiration during priority 1 allocation real(r8) :: c_gain_flux ! Flux used to pay back negative carbon gain (from storage) (kgC) real(r8) :: sapw_area - integer, parameter :: n_max_priority = num_organs + 1 ! Maximum possible number of priority levels is - ! the total number organs plus 1, which allows - ! each organ to have its own level, and ignore - ! the specialized priority 1 + + integer :: n_max_priority ! Maximum possible number of priority levels is + ! the total number organs plus 1, which allows + ! each organ to have its own level, and ignore + ! the specialized priority 1 + leaf_status = this%bc_in(acnp_bc_in_id_lstat)%ival ipft = this%bc_in(acnp_bc_in_id_pft)%ival canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval + + + n_max_priority = maxval(prt_params%organ_param_id(:)) + if(n_max_priority>10 .or. n_max_priority<0)then + write(fates_log(),*) 'was unable to interpret prt_params%organ_param_id' + write(fates_log(),*) 'for cnp allocation, there should be non-zero values <10' + write(fates_log(),*) 'your values: ',prt_params%organ_param_id(:) + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + ! ----------------------------------------------------------------------------------- + ! Notes on indexes: + ! + ! i_org: this is the index that matches the global organ indices found in PRTGenericMod + ! + ! prt_params%alloc_priority is a parameter array that only holds a subset of the + ! organs. For instance it does not include reproductive and storage, because those + ! organs are special. We can find out the global organ index (ie i_org) from the + ! parameter array prt_params%organ_id + ! + ! i and ii are just local indices used to iterate through sub-groups of organs. + ! for instance, i will generally iterate through the curpri_org, which is an + ! array of the global organ indices (i_org) for the current subset of organs that + ! should be allocated at the current priority level + ! + ! ----------------------------------------------------------------------------------- + ! ----------------------------------------------------------------------------------- ! Preferential transfer of available carbon and nutrients into the highest @@ -851,30 +802,30 @@ subroutine CNPPrioritizedReplacement(this, & ! If it is, then we track the variable ids associated with that pool for each CNP ! species. It "should" work fine if there are NO priority=1 pools... ! ----------------------------------------------------------------------------------- - + curpri_org(:) = fates_unset_int ! reset "current-priority" organ ids i = 0 - do ii = 1, num_organs - - deficit_c(ii) = max(0._r8,this%GetDeficit(carbon12_element,organ_list(ii),target_c(ii))) + do ii = 1, size(prt_params%organ_id,1) - ! The following logic bars any organs that were not given allocation priority - if( prt_params%organ_param_id(organ_list(ii)) < 1 ) cycle + ! universal organ index from PRTGenericMod + i_org = prt_params%organ_id(ii) - ! The priority code associated with this organ - priority_code = int(prt_params%alloc_priority(ipft, prt_params%organ_param_id(organ_list(ii)))) - ! Don't allow allocation to leaves if they are in an "off" status. ! Also, dont allocate to replace turnover if this is not evergreen ! (this prevents accidental re-flushing on the day they drop) if( ((leaf_status.eq.leaves_off) .or. (prt_params%evergreen(ipft) .ne. itrue)) & - .and. (organ_list(ii).eq.leaf_organ)) cycle + .and. (i_org.eq.leaf_organ)) cycle + + ! The priority code associated with this organ + priority_code = int(prt_params%alloc_priority(ipft, ii)) ! 1 is the highest priority code possible if( priority_code == 1 ) then i = i + 1 - curpri_org(i) = ii + curpri_org(i) = i_org + deficit_c(i) = max(0._r8,this%GetDeficit(carbon12_element,i_org,target_c(i_org))) end if + end do @@ -891,32 +842,29 @@ subroutine CNPPrioritizedReplacement(this, & sum_c_demand = 0._r8 do i = 1,n_curpri_org - ii = curpri_org(i) - - i_cvar = prt_global%sp_organ_map(organ_list(ii),carbon12_element) + i_org = curpri_org(i) + i_var = prt_global%sp_organ_map(i_org,carbon12_element) sum_c_demand = sum_c_demand + prt_params%leaf_stor_priority(ipft) * & - sum(this%variables(i_cvar)%turnover(:)) - + sum(this%variables(i_var)%turnover(:)) end do - - sum_c_flux = max(0._r8,min(sum_c_demand,state_c(store_id)%ptr+c_gain)) + sum_c_flux = max(0._r8,min(sum_c_demand,this%variables(store_c_id)%val(1)+c_gain)) if (sum_c_flux> nearzero ) then ! We pay this even if we don't have the carbon ! Just don't pay so much carbon that storage+carbon_balance can't pay for it - do ii = 1,n_curpri_org - i = curpri_org(ii) - - i_cvar = prt_global%sp_organ_map(organ_list(i),carbon12_element) + do i = 1,n_curpri_org - c_flux = sum_c_flux*(prt_params%leaf_stor_priority(ipft) * & - sum(this%variables(i_cvar)%turnover(:))/sum_c_demand) + i_org = curpri_org(i) + i_var = prt_global%sp_organ_map(i_org,carbon12_element) + c_flux = sum_c_flux*(prt_params%leaf_stor_priority(ipft) * & + sum(this%variables(i_var)%turnover(:))/sum_c_demand) + ! Add carbon to the pool - state_c(i)%ptr = state_c(i)%ptr + c_flux + this%variables(i_var)%val(1) = this%variables(i_var)%val(1) + c_flux ! Remove from daily carbon gain c_gain = c_gain - c_flux @@ -930,29 +878,27 @@ subroutine CNPPrioritizedReplacement(this, & i_org = curpri_org(i) ! Update the nitrogen deficits - ! Note that the nitrogen target is tied to the stoichiometry of thegrowing pool only + ! Note that the nitrogen target is tied to the stoichiometry of the growing pool only (pos = 1) - target_n = this%GetNutrientTarget(nitrogen_element,organ_list(i_org),stoich_growth_min) - deficit_n(i_org) = max(0.0_r8, target_n - state_n(i_org)%ptr ) + target_n = this%GetNutrientTarget(nitrogen_element,i_org,stoich_growth_min) + deficit_n(i) = max(0.0_r8, target_n - this%GetState(i_org, nitrogen_element,1)) ! Update the phosphorus deficits (which are based off of carbon actual..) ! Note that the phsophorus target is tied to the stoichiometry of thegrowing pool only (also) - target_p = this%GetNutrientTarget(phosphorus_element,organ_list(i_org),stoich_growth_min) - deficit_p(i_org) = max(0.0_r8, target_p - state_p(i_org)%ptr ) + target_p = this%GetNutrientTarget(phosphorus_element,i_org,stoich_growth_min) + deficit_p(i) = max(0.0_r8, target_p - this%GetState(i_org, phosphorus_element,1)) end do ! Allocate nutrients at this priority level ! Nitrogen - call ProportionalNutrAllocation(state_n, deficit_n, & + call ProportionalNutrAllocation(this,deficit_n(1:n_curpri_org), & n_gain, nitrogen_element, curpri_org(1:n_curpri_org)) ! Phosphorus - call ProportionalNutrAllocation(state_p, deficit_p, & + call ProportionalNutrAllocation(this,deficit_p(1:n_curpri_org), & p_gain, phosphorus_element, curpri_org(1:n_curpri_org)) - - ! ----------------------------------------------------------------------------------- ! IV. if carbon balance is negative, re-coup the losses from storage ! if it is positive, give some love to storage carbon @@ -963,15 +909,16 @@ subroutine CNPPrioritizedReplacement(this, & ! Storage will have to pay for any negative gains store_c_flux = -c_gain c_gain = c_gain + store_c_flux - state_c(store_id)%ptr = state_c(store_id)%ptr - store_c_flux + + this%variables(store_c_id)%val(1) = this%variables(store_c_id)%val(1) - store_c_flux else ! This is just a cap, don't fill up more than is needed (shouldn't even apply) - store_below_target = max(target_c(store_id) - state_c(store_id)%ptr,0._r8) + store_below_target = max(target_c(store_organ) - this%variables(store_c_id)%val(1),0._r8) ! This is the desired need for carbon - store_target_fraction = max(state_c(store_id)%ptr/target_c(store_id),0._r8) + store_target_fraction = max(this%variables(store_c_id)%val(1)/target_c(store_organ),0._r8) store_demand = max(c_gain*(exp(-1.*store_target_fraction**4._r8) - exp( -1.0_r8 )),0._r8) @@ -979,8 +926,8 @@ subroutine CNPPrioritizedReplacement(this, & store_c_flux = min(store_below_target,store_demand) c_gain = c_gain - store_c_flux - state_c(store_id)%ptr = state_c(store_id)%ptr + store_c_flux - + + this%variables(store_c_id)%val(1) = this%variables(store_c_id)%val(1) + store_c_flux end if @@ -992,6 +939,7 @@ subroutine CNPPrioritizedReplacement(this, & ! ----------------------------------------------------------------------------------- ! Bring all pools, in priority order, up to allometric targets if possible + ! Repeat priority order 1 as well. ! ----------------------------------------------------------------------------------- priority_loop: do i_pri = 1, n_max_priority @@ -999,46 +947,48 @@ subroutine CNPPrioritizedReplacement(this, & curpri_org(:) = fates_unset_int ! "current-priority" organ indices i = 0 - do ii = 1, num_organs + + ! Storage has a special hard-coded priority level of 2 + if( i_pri == 2 ) then + curpri_org(1) = store_organ + i=1 + end if - ! The priority code associated with this organ - ! Storage has a special hard-coded priority level of 2 - ! Note that it is also implicitly part of step 1 + ! Loop over all organs in the CNP routine, which + do ii = 1, size(prt_params%organ_id,1) - if( organ_list(ii).eq.store_organ ) then - priority_code = 2 - else - if( prt_params%organ_param_id(organ_list(ii)) <1 ) then - priority_code = -1 - else - priority_code = int(prt_params%alloc_priority(ipft,prt_params%organ_param_id(organ_list(ii)))) - end if - end if - + ! universal organ index from PRTGenericMod + i_org = prt_params%organ_id(ii) + + ! The priority code associated with this organ + + priority_code = int(prt_params%alloc_priority(ipft,ii)) ! Don't allow allocation to leaves if they are in an "off" status. ! (this prevents accidental re-flushing on the day they drop) - if((leaf_status.eq.leaves_off) .and. (organ_list(ii).eq.leaf_organ)) cycle - + if((leaf_status.eq.leaves_off) .and. (i_org.eq.leaf_organ)) cycle if( priority_code == i_pri ) then - deficit_c(ii) = max(0._r8,this%GetDeficit(carbon12_element,organ_list(ii),target_c(ii))) i = i + 1 - curpri_org(i) = ii + curpri_org(i) = i_org end if end do + n_curpri_org = i + + do i = 1,n_curpri_org + i_org = curpri_org(i) + deficit_c(i) = max(0._r8,this%GetDeficit(carbon12_element,i_org,target_c(i_org))) + end do + ! Bring carbon up to target first, this order is required ! because we need to know the resulting carbon concentrations ! before we set the allometric targets for the nutrients - n_curpri_org = i - - sum_c_demand = 0._r8 do i=1,n_curpri_org i_org = curpri_org(i) - sum_c_demand = sum_c_demand + deficit_c(i_org) + sum_c_demand = sum_c_demand + deficit_c(i) end do sum_c_flux = min(c_gain, sum_c_demand) @@ -1049,13 +999,14 @@ subroutine CNPPrioritizedReplacement(this, & i_org = curpri_org(i) - c_flux = sum_c_flux*deficit_c(i_org)/sum_c_demand + c_flux = sum_c_flux*deficit_c(i)/sum_c_demand ! Update the carbon pool - state_c(i_org)%ptr = state_c(i_org)%ptr + c_flux + i_var = prt_global%sp_organ_map(i_org,carbon12_element) + this%variables(i_var)%val(1) = this%variables(i_var)%val(1) + c_flux ! Update carbon pools deficit - deficit_c(i_org) = max(0._r8,deficit_c(i_org) - c_flux) + deficit_c(i) = max(0._r8,deficit_c(i) - c_flux) ! Reduce the carbon gain c_gain = c_gain - c_flux @@ -1070,22 +1021,22 @@ subroutine CNPPrioritizedReplacement(this, & ! Update the nitrogen deficits ! Note that the nitrogen target is tied to the stoichiometry of thegrowing pool only - target_n = this%GetNutrientTarget(nitrogen_element,organ_list(i_org),stoich_growth_min) - deficit_n(i_org) = max(0.0_r8, target_n - state_n(i_org)%ptr ) + target_n = this%GetNutrientTarget(nitrogen_element,i_org,stoich_growth_min) + deficit_n(i) = max(0.0_r8, target_n - this%GetState(i_org, nitrogen_element,1) ) ! Update the phosphorus deficits (which are based off of carbon actual..) ! Note that the phsophorus target is tied to the stoichiometry of thegrowing pool only (also) - target_p = this%GetNutrientTarget(phosphorus_element,organ_list(i_org),stoich_growth_min) - deficit_p(i_org) = max(0.0_r8, target_p - state_p(i_org)%ptr ) + target_p = this%GetNutrientTarget(phosphorus_element,i_org,stoich_growth_min) + deficit_p(i) = max(0.0_r8, target_p - this%GetState(i_org, phosphorus_element,1) ) end do ! Allocate nutrients at this priority level Nitrogen - call ProportionalNutrAllocation(state_n, deficit_n, & + call ProportionalNutrAllocation(this,deficit_n(1:n_curpri_org), & n_gain, nitrogen_element, curpri_org(1:n_curpri_org)) ! Phosphorus - call ProportionalNutrAllocation(state_p, deficit_p, & + call ProportionalNutrAllocation(this,deficit_p(1:n_curpri_org), & p_gain, phosphorus_element, curpri_org(1:n_curpri_org)) @@ -1101,8 +1052,7 @@ end subroutine CNPPrioritizedReplacement ! ===================================================================================== subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & - state_c, state_n, state_p, & - target_c, target_dcdd, cnp_limiter) + target_c, target_dcdd) class(cnp_allom_prt_vartypes) :: this @@ -1111,12 +1061,8 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & ! (new uptake + storage) real(r8), intent(inout) :: p_gain ! Total P available for allocation ! (new uptake + storage) - type(parray_type) :: state_c(:) ! State array for carbon, by organ [kg] - type(parray_type) :: state_n(:) ! State array for N, by organ [kg] - type(parray_type) :: state_p(:) ! State array for P, by organ [kg] real(r8), intent(in) :: target_c(:) real(r8), intent(in) :: target_dcdd(:) - integer, intent(out) :: cnp_limiter real(r8), pointer :: dbh integer :: ipft @@ -1125,6 +1071,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & real(r8) :: l2fr integer :: i, ii ! organ index loops (masked and unmasked) + integer :: i_org ! global organ index integer :: istep ! outer step iteration loop real(r8) :: grow_c_from_c ! carbon transferred into tissues real(r8) :: grow_c_from_n ! carbon needed to match N transfers to tissues @@ -1146,18 +1093,18 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & real(r8) :: c_flux_adj ! Adjustment to total carbon flux during stature growth ! intended to correct integration error (kg/kg) real(r8) :: c_flux ! Carbon flux from the gain pool to an organ (kgC) + real(r8) :: n_flux,p_flux real(r8) :: gr_flux ! Growth respiration flux for the current transaction (kgC) real(r8) :: c_gstature ! Carbon reserved for stature growth (kg) real(r8) :: target_n ! Target mass of N for a given organ [kg] real(r8) :: target_p ! Target mass of P for a given organ [kg] real(r8) :: sum_n_demand ! Total N deficit to overcome after C stature growth [kg] real(r8) :: sum_p_demand ! Total P deficit to overcome after C stature growth [kg] - real(r8), dimension(num_organs) :: frac_c ! Fraction of C going towards each pool - ! (only used when calculating which species limits) real(r8), dimension(num_organs) :: deficit_n ! Deficit to get to target from current [kg] real(r8), dimension(num_organs) :: deficit_p ! Deficit to get to target from current [kg] integer,dimension(num_organs) :: mask_organs ! This works with "state_mask", the list - ! of organs in the mask + ! of organs (local ids) in the mask + integer,dimension(num_organs) :: mask_gorgans ! List of organ global indices in the mask integer :: n_mask_organs ! Integrator error checking @@ -1208,9 +1155,6 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval l2fr = this%bc_inout(acnp_bc_inout_id_l2fr)%rval ! This variable is not updated in this ! routine, and is therefore not a pointer - - cnp_limiter = 0 - ! If any of these resources is essentially tapped out, ! then there is no point in performing growth ! It also seems impossible that we would be in a leaf-off status @@ -1235,6 +1179,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & state_mask(:) = .false. mask_organs(:) = fates_unset_int + mask_gorgans(:) = fates_unset_int ! Go through and flag the integrating variables as either pools that ! are growing in this iteration, or not. At this point, if carbon for growth @@ -1246,7 +1191,9 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & ii = 0 do i = 1, num_organs - cdeficit = this%GetDeficit(carbon12_element,organ_list(i),target_c(i)) + i_org = l2g_organ_list(i) + + cdeficit = this%GetDeficit(carbon12_element,i_org,target_c(i_org)) if ( cdeficit > calloc_abs_error ) then ! In this case, we somehow still have carbon to play with, @@ -1254,10 +1201,10 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & ! gracefully fail write(fates_log(),*) 'A carbon pool has reached the stature growth step' write(fates_log(),*) 'yet its deficit is too large to integrate ' - write(fates_log(),*) 'organ: ',i + write(fates_log(),*) 'organ: ',i_org write(fates_log(),*) 'carbon gain: ',c_gain write(fates_log(),*) 'leaves status:', leaf_status - write(fates_log(),*) cdeficit, target_c(i), state_c(i)%ptr + write(fates_log(),*) cdeficit, target_c(i_org) call endrun(msg=errMsg(sourcefile, __LINE__)) elseif( (-cdeficit) > calloc_abs_error ) then ! In this case, we are above our target (ie negative deficit (fusion?)) @@ -1271,9 +1218,10 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & ! Reproduction is a special case, don't add it to the ! list of organs... yet - if (organ_list(i).ne.repro_organ) then + if (i_org.ne.repro_organ) then ii=ii+1 mask_organs(ii) = i + mask_gorgans(ii) = i_org end if end if @@ -1290,8 +1238,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & write(fates_log(),*) 'plants, and roots in grasses are not allowed above target.' write(fates_log(),*) 'pft: ',ipft write(fates_log(),*) 'dbh: ',dbh - write(fates_log(),*) 'c state1 : ',state_c(1)%ptr - write(fates_log(),*) 'c targets: ',target_c(1:num_organs) + write(fates_log(),*) 'c targets: ',target_c(:) call endrun(msg=errMsg(sourcefile, __LINE__)) end if end if @@ -1309,9 +1256,9 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & if(repro_c_frac>nearzero)then state_mask(repro_id) = .true. - ii = ii + 1 - n_mask_organs = ii - mask_organs(ii) = repro_id + n_mask_organs = n_mask_organs + 1 + mask_organs(n_mask_organs) = repro_id + mask_gorgans(n_mask_organs) = repro_organ else state_mask(repro_id) = .false. end if @@ -1328,27 +1275,11 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & total_dcostdd = 0._r8 - do ii = 1, n_mask_organs - i = mask_organs(ii) - total_dcostdd = total_dcostdd + target_dcdd(i) + do i = 1, n_mask_organs + i_org = mask_gorgans(ii) + total_dcostdd = total_dcostdd + target_dcdd(i_org) end do - frac_c(:) = 0._r8 - do ii = 1, n_mask_organs - i = mask_organs(ii) - frac_c(i) = target_dcdd(i)/total_dcostdd * (1.0_r8 - repro_c_frac) - end do - frac_c(repro_id) = repro_c_frac - - if(debug) then - if ( abs(sum(frac_c,dim=1)-1._r8)>rsnbl_math_prec ) then - write(fates_log(),*) 'predicted carbon allocation fractions dont sum to 1?' - write(fates_log(),*) 'frac_c(:):',frac_c - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - end if - - ! No mathematical co-limitation of growth ! This assumes that limitations will prevent ! organs from allowing the growth step to even occur @@ -1374,7 +1305,9 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & ! Fill the state array with element masses for each organ do i = 1, num_organs - state_array(i) = state_c(i)%ptr + i_org = l2g_organ_list(i) + i_var = prt_global%sp_organ_map(i_org,carbon12_element) + state_array(i) = this%variables(i_var)%val(1) end do state_mask(dbh_id) = .true. @@ -1445,8 +1378,10 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & sum_c_flux = 0.0_r8 do ii = 1, n_mask_organs - i = mask_organs(ii) - sum_c_flux = sum_c_flux + (state_array(i) - state_c(i)%ptr) + i = mask_organs(ii) + i_org = mask_gorgans(ii) + i_var = prt_global%sp_organ_map(i_org,carbon12_element) + sum_c_flux = sum_c_flux + (state_array(i) - this%variables(i_var)%val(1)) end do ! This is a correction factor that forces @@ -1455,13 +1390,15 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & do ii = 1, n_mask_organs - i = mask_organs(ii) + i = mask_organs(ii) + i_org = mask_gorgans(ii) + i_var = prt_global%sp_organ_map(i_org,carbon12_element) ! Calculate adjusted flux - c_flux = (state_array(i) - state_c(i)%ptr)*c_flux_adj + c_flux = (state_array(i) - this%variables(i_var)%val(1))*c_flux_adj ! update the carbon pool (in all pools flux goes into the first pool) - state_c(i)%ptr = state_c(i)%ptr + c_flux + this%variables(i_var)%val(1) = this%variables(i_var)%val(1) + c_flux ! Remove carbon from the daily gain c_gain = c_gain - c_flux @@ -1483,11 +1420,11 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & write(fates_log(),*) 'totalC',totalC write(fates_log(),*) 'pft: ',ipft write(fates_log(),*) 'dbh: ',dbh - write(fates_log(),*) 'dCleaf_dd: ',target_dcdd(leaf_id) - write(fates_log(),*) 'dCfnrt_dd: ',target_dcdd(fnrt_id) - write(fates_log(),*) 'dCstore_dd: ',target_dcdd(store_id) - write(fates_log(),*) 'dCsapw_dd: ',target_dcdd(sapw_id) - write(fates_log(),*) 'dCstruct_dd: ',target_dcdd(struct_id) + write(fates_log(),*) 'dCleaf_dd: ',target_dcdd(leaf_organ) + write(fates_log(),*) 'dCfnrt_dd: ',target_dcdd(fnrt_organ) + write(fates_log(),*) 'dCstore_dd: ',target_dcdd(store_organ) + write(fates_log(),*) 'dCsapw_dd: ',target_dcdd(sapw_organ) + write(fates_log(),*) 'dCstruct_dd: ',target_dcdd(struct_organ) write(fates_log(),*) 'repro c frac: ',repro_c_frac dbh_tp1 = state_array_out(dbh_id) leafc_tp1 = state_array_out(leaf_id) @@ -1509,8 +1446,6 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & write(fates_log(),*) 'sapw_c: ',sapwc_tp1, sapw_c_target_tp1 ,sapwc_tp1- sapw_c_target_tp1 write(fates_log(),*) 'store_c: ',storec_tp1, store_c_target_tp1,storec_tp1- store_c_target_tp1 write(fates_log(),*) 'struct_c: ',structc_tp1, struct_c_target_tp1,structc_tp1- struct_c_target_tp1 - write(fates_log(),*) 'sapw_c_t0: ',state_c(sapw_id)%ptr, target_c(sapw_id) - call endrun(msg=errMsg(sourcefile, __LINE__)) end if if_step_exceedance @@ -1526,18 +1461,23 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & ! have their maximum stoichiometry in each organ. The total stoichiometry ! of the recruits should match the stoichiometry of the seeds - !!target_n = this%GetNutrientTarget(nitrogen_element,repro_organ,stoich_growth_min) - !!deficit_n(repro_id) = this%GetDeficit(nitrogen_element,repro_organ,target_n) + if(prioritize_repro_nutr_growth)then - !!target_p = this%GetNutrientTarget(phosphorus_element,repro_organ,stoich_growth_min) - !!deficit_p(repro_id) = this%GetDeficit(phosphorus_element,repro_organ,target_p) - - ! Nitrogen for - !!call ProportionalNutrAllocation(state_n, deficit_n, n_gain, nitrogen_element,[repro_id]) - - ! Phosphorus - !!call ProportionalNutrAllocation(state_p, deficit_p, p_gain, phosphorus_element,[repro_id]) + target_n = this%GetNutrientTarget(nitrogen_element,repro_organ,stoich_growth_min) + deficit_n(1) = this%GetDeficit(nitrogen_element,repro_organ,target_n) + n_flux = max(0._r8,min(n_gain,deficit_n(1))) + + target_p = this%GetNutrientTarget(phosphorus_element,repro_organ,stoich_growth_min) + deficit_p(1) = this%GetDeficit(phosphorus_element,repro_organ,target_p) + p_flux = max(0._r8,min(p_gain,deficit_p(1))) + + this%variables(repro_n_id)%val(1) = this%variables(repro_n_id)%val(1) + n_flux + this%variables(repro_p_id)%val(1) = this%variables(repro_p_id)%val(1) + p_flux + n_gain = n_gain - n_flux + p_gain = p_gain - p_flux + + end if ! ----------------------------------------------------------------------------------- ! Nutrient Fluxes proportionally to each pool (these should be fully actualized) @@ -1548,26 +1488,29 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & sum_p_demand = 0._r8 ! For error checking do ii = 1, n_mask_organs - i = mask_organs(ii) - - target_n = this%GetNutrientTarget(nitrogen_element,organ_list(i),stoich_growth_min) - target_p = this%GetNutrientTarget(phosphorus_element,organ_list(i),stoich_growth_min) + i = mask_organs(ii) + i_org = mask_gorgans(ii) + + target_n = this%GetNutrientTarget(nitrogen_element,i_org,stoich_growth_min) + target_p = this%GetNutrientTarget(phosphorus_element,i_org,stoich_growth_min) - deficit_n(i) = this%GetDeficit(nitrogen_element,organ_list(i),target_n) - sum_n_demand = sum_n_demand+max(0._r8,deficit_n(i)) + deficit_n(ii) = this%GetDeficit(nitrogen_element,i_org,target_n) + sum_n_demand = sum_n_demand+max(0._r8,deficit_n(ii)) - deficit_p(i) = this%GetDeficit(phosphorus_element,organ_list(i),target_p) - sum_p_demand = sum_p_demand+max(0._r8,deficit_p(i)) + deficit_p(ii) = this%GetDeficit(phosphorus_element,i_org,target_p) + sum_p_demand = sum_p_demand+max(0._r8,deficit_p(ii)) end do - - ! Nitrogen - call ProportionalNutrAllocation(state_n,deficit_n, & - n_gain, nitrogen_element,mask_organs(1:n_mask_organs)) - - ! Phosphorus - call ProportionalNutrAllocation(state_p, deficit_p, & - p_gain, phosphorus_element,mask_organs(1:n_mask_organs)) + + ! TODO: mask_organs should be a vector of global organs + + ! Nitrogen + call ProportionalNutrAllocation(this,deficit_n(1:n_mask_organs), & + n_gain, nitrogen_element,mask_gorgans(1:n_mask_organs)) + + ! Phosphorus + call ProportionalNutrAllocation(this,deficit_p(1:n_mask_organs), & + p_gain, phosphorus_element,mask_gorgans(1:n_mask_organs)) end if if_stature_growth @@ -1577,16 +1520,13 @@ end subroutine CNPStatureGrowth ! ===================================================================================== - subroutine CNPAllocateRemainder(this,c_gain, n_gain, p_gain, & - state_c, state_n, state_p, c_efflux, n_efflux, p_efflux) + subroutine CNPAllocateRemainder(this, c_gain, n_gain, p_gain, & + c_efflux, n_efflux, p_efflux) class(cnp_allom_prt_vartypes) :: this real(r8), intent(inout) :: c_gain real(r8), intent(inout) :: n_gain real(r8), intent(inout) :: p_gain - type(parray_type) :: state_c(:) ! State array for carbon, by organ [kg] - type(parray_type) :: state_n(:) ! State array for N, by organ [kg] - type(parray_type) :: state_p(:) ! State array for P, by organ [kg] real(r8), intent(inout) :: c_efflux real(r8), intent(inout) :: n_efflux real(r8), intent(inout) :: p_efflux @@ -1598,18 +1538,17 @@ subroutine CNPAllocateRemainder(this,c_gain, n_gain, p_gain, & real(r8) :: target_p real(r8) :: store_c_target ! Target amount of C in storage including "overflow" [kgC] real(r8) :: total_c_flux ! Total C flux from gains into storage and growth R [kgC] - real(r8) :: growth_r_flux ! Growth respiration for filling storage [kgC] real(r8) :: store_m_flux ! Flux into storage [kg] - integer, dimension(num_organs),parameter :: all_organs = [1,2,3,4,5,6] real(r8), pointer :: dbh + real(r8), pointer :: resp_excess integer :: ipft real(r8) :: canopy_trim - + dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival - + resp_excess => this%bc_inout(acnp_bc_inout_id_resp_excess)%rval ! ----------------------------------------------------------------------------------- ! If nutrients are still available, then we can bump up the values in the pools @@ -1619,11 +1558,11 @@ subroutine CNPAllocateRemainder(this,c_gain, n_gain, p_gain, & do i = 1, num_organs ! Update the nitrogen and phosphorus deficits - target_n = this%GetNutrientTarget(nitrogen_element,organ_list(i),stoich_max) - deficit_n(i) = max(0._r8,this%GetDeficit(nitrogen_element,organ_list(i),target_n)) + target_n = this%GetNutrientTarget(nitrogen_element,l2g_organ_list(i),stoich_max) + deficit_n(i) = max(0._r8,this%GetDeficit(nitrogen_element,l2g_organ_list(i),target_n)) - target_p = this%GetNutrientTarget(phosphorus_element,organ_list(i),stoich_max) - deficit_p(i) = max(0._r8,this%GetDeficit(phosphorus_element,organ_list(i),target_p)) + target_p = this%GetNutrientTarget(phosphorus_element,l2g_organ_list(i),stoich_max) + deficit_p(i) = max(0._r8,this%GetDeficit(phosphorus_element,l2g_organ_list(i),target_p)) end do @@ -1633,26 +1572,13 @@ subroutine CNPAllocateRemainder(this,c_gain, n_gain, p_gain, & ! ----------------------------------------------------------------------------------- ! Nitrogen - call ProportionalNutrAllocation(state_n(1:num_organs), & - deficit_n(1:num_organs), & - n_gain, nitrogen_element, all_organs) + call ProportionalNutrAllocation(this,deficit_n(1:num_organs), & + n_gain, nitrogen_element, l2g_organ_list(1:num_organs)) ! Phosphorus - call ProportionalNutrAllocation(state_p(1:num_organs), & - deficit_p(1:num_organs), & - p_gain, phosphorus_element, all_organs) - - - ! Optional hypothesis ( - ! If any N or P is still hanging around, put it in storage + call ProportionalNutrAllocation(this,deficit_p(1:num_organs), & + p_gain, phosphorus_element, l2g_organ_list(1:num_organs)) - !state_n(store_id)%ptr = state_n(store_id)%ptr + n_gain - !state_p(store_id)%ptr = state_p(store_id)%ptr + p_gain - - !n_gain = 0._r8 - !p_gain = 0._r8 - - ! ----------------------------------------------------------------------------------- ! If carbon is still available, lets cram some into storage overflow ! We will do this last, because we wanted the non-overflow storage @@ -1661,40 +1587,45 @@ subroutine CNPAllocateRemainder(this,c_gain, n_gain, p_gain, & if(c_gain>calloc_abs_error) then + if(store_c_overflow == retain_c_store_overflow)then + + total_c_flux = c_gain + ! Transfer excess carbon into storage overflow + this%variables(store_c_id)%val(1) = this%variables(store_c_id)%val(1) + total_c_flux + c_gain = c_gain - total_c_flux + + elseif(store_c_overflow == burn_c_store_overflow) then -! select(c_overlow_method) -! case(store_c_overflow) - -! case(efflux_c_overflow) - -! case(burn_c_overflow) - -! end if - - - - if(force_store_c_overflow)then + ! Update carbon based allometric targets + call bstore_allom(dbh,ipft,canopy_trim, store_c_target) + + ! Allow some overflow + store_c_target = store_c_target * (1.0_r8 + store_overflow_frac) - total_c_flux = c_gain - else + total_c_flux = min(c_gain,max(0.0, (store_c_target - this%variables(store_c_id)%val(1)))) + ! Transfer excess carbon into storage overflow + this%variables(store_c_id)%val(1) = this%variables(store_c_id)%val(1) + total_c_flux + c_gain = c_gain - total_c_flux + + resp_excess = c_gain + c_gain = 0._r8 + elseif(store_c_overflow == exude_c_store_overflow)then + ! Update carbon based allometric targets call bstore_allom(dbh,ipft,canopy_trim, store_c_target) ! Estimate the overflow store_c_target = store_c_target * (1.0_r8 + store_overflow_frac) - total_c_flux = min(c_gain,max(0.0, (store_c_target - state_c(store_id)%ptr))) + total_c_flux = min(c_gain,max(0.0, (store_c_target - this%variables(store_c_id)%val(1)))) + ! Transfer excess carbon into storage overflow + this%variables(store_c_id)%val(1) = this%variables(store_c_id)%val(1) + total_c_flux + c_gain = c_gain - total_c_flux end if - ! Transfer excess carbon into storage overflow - state_c(store_id)%ptr = state_c(store_id)%ptr + total_c_flux - c_gain = c_gain - total_c_flux - - end if - ! Figure out what to do with excess carbon and nutrients @@ -1815,7 +1746,7 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe end if - ! Hard-code the growth minimum storage stoichiometry to 75% of maximum + ! Hard-code the growth minimum storage stoichiometry to 25% of maximum if( stoich_mode == stoich_growth_min ) then target_m = target_m*0.25_r8 end if @@ -1870,7 +1801,7 @@ end function GetNutrientTargetCNP ! ===================================================================================== - subroutine ProportionalNutrAllocation(state_m, deficit_m, gain_m, element_id, list) + subroutine ProportionalNutrAllocation(this,deficit_m, gain_m, element_id, list) ! ----------------------------------------------------------------------------------- ! This routine allocates nutrients to a set of organs based on proportional @@ -1879,19 +1810,18 @@ subroutine ProportionalNutrAllocation(state_m, deficit_m, gain_m, element_id, li ! Note: this may or may not be called inside some preferential organ filter. ! ----------------------------------------------------------------------------------- - type(parray_type) :: state_m(:) ! Current mass of nutrient - ! of arbitrary species - ! over some arbitrary set of organs + class(cnp_allom_prt_vartypes) :: this real(r8),intent(inout) :: deficit_m(:) ! Nutrient mass deficit of species ! over set of organs - integer, intent(in) :: list(:) ! List of indices if sparse + integer, intent(in) :: list(:) ! List of organ indices from PRTGenericMod real(r8),intent(inout) :: gain_m ! Total nutrient mass gain to ! work with - integer,intent(in) :: element_id ! Element global index (for debugging) + integer,intent(in) :: element_id ! Element global index ! locals integer :: num_organs - integer :: i,ii + integer :: i,i_org + integer :: i_var real(r8) :: flux real(r8) :: sum_deficit real(r8) :: sum_flux @@ -1899,8 +1829,8 @@ subroutine ProportionalNutrAllocation(state_m, deficit_m, gain_m, element_id, li num_organs = size(list,dim=1) sum_deficit = 0._r8 - do ii = 1, num_organs - i = list(ii) + do i = 1, num_organs + i_org = list(i) sum_deficit = sum_deficit + max(0._r8,deficit_m(i)) end do @@ -1908,11 +1838,14 @@ subroutine ProportionalNutrAllocation(state_m, deficit_m, gain_m, element_id, li sum_flux = min(gain_m, sum_deficit) - do ii = 1, num_organs - i = list(ii) + do i = 1, num_organs + i_org = list(i) + + flux = sum_flux * max(0._r8,deficit_m(i))/sum_deficit + + i_var = prt_global%sp_organ_map(i_org,element_id) + this%variables(i_var)%val(1) = this%variables(i_var)%val(1) + flux - flux = sum_flux * max(0._r8,deficit_m(i))/sum_deficit - state_m(i)%ptr = state_m(i)%ptr + flux deficit_m(i) = deficit_m(i) - flux gain_m = gain_m - flux @@ -2176,7 +2109,7 @@ end subroutine TargetAllometryCheck ! ===================================================================================== - subroutine StorageRegulator(this,element_id,regulate_type,c_scalar) + subroutine StorageRegulator(this,element_id,regulate_type,target_c,c_scalar) ! ----------------------------------------------------------------------------------- ! This function evaluates the storage of either N or P, and returns @@ -2190,7 +2123,8 @@ subroutine StorageRegulator(this,element_id,regulate_type,c_scalar) class(cnp_allom_prt_vartypes) :: this integer,intent(in) :: element_id ! element id consistent with parteh/PRTGenericMod.F90 integer,intent(in) :: regulate_type - + real(r8) :: target_c(:) + ! Arguments (out) real(r8) :: c_scalar @@ -2198,12 +2132,10 @@ subroutine StorageRegulator(this,element_id,regulate_type,c_scalar) ! Locals real(r8) :: store_frac ! Current nutrient storage relative to max real(r8) :: store_max ! Maximum nutrient storable by plant - real(r8) :: store_c ! Current storage carbon - real(r8) :: store_c_max ! Current maximum storage carbon integer :: icode ! real variable checking code real(r8) :: store_x integer :: i_var - real(r8), parameter :: c_eq_offset = 0.95 ! This shifts the center-point + real(r8), parameter :: c_eq_offset = 1.0_r8 ! This shifts the center-point ! of the N:C or P:C storage equlibrium ! by multiplying the C term. If its less than 1 it ! shifts left and great than one it shifts right. @@ -2216,18 +2148,15 @@ subroutine StorageRegulator(this,element_id,regulate_type,c_scalar) real(r8) :: logi_min ! minimum cn_scalar for logistic real(r8) :: l2fr_delta_max real(r8) :: l2fr_delta_min + real(r8) :: l2fr_delta_scale real(r8) :: l2fr_actual real(r8) :: leaf_c, fnrt_c - real(r8) :: leaf_c_target + real(r8) :: struct_c, sapw_c, store_c real(r8) :: log_nc_frac + real(r8) :: nc_frac real(r8) :: store_c_frac real(r8) :: c_gain - real(r8) :: fnrt_c_target - ! This is the storage fraction where downregulation starts if using - ! a linear function - real(r8), parameter :: store_frac0 = 0.85_r8 - real(r8), parameter :: c_max = 1.0_r8 ! Maximum allowable result of the function real(r8), parameter :: c_min = 0.0_r8 ! Minimum allowable result of the function @@ -2235,162 +2164,140 @@ subroutine StorageRegulator(this,element_id,regulate_type,c_scalar) ! how much carbon from daily gains + storage overflow, is allowed to ! be spent on growing out roots. This inludes getting roots ! back on allometry before growing out - + integer, parameter :: limit_all = 1 + integer, parameter :: limit_lf = 2 + + integer :: lim_l2fr_max_type = limit_all real(r8), parameter :: max_l2fr_cgain_frac = 0.5_r8 associate(dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval, & canopy_trim => this%bc_in(acnp_bc_in_id_ctrim)%rval, & ipft => this%bc_in(acnp_bc_in_id_pft)%ival, & l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval) - - store_max = this%GetNutrientTarget(element_id,store_organ,stoich_max) - ! Storage fractions could more than the target, depending on the - ! hypothesis and functions involved, but should typically be 0-1 - ! The cap of 2 is for numerics and preventing weird math - store_frac = max(0.01_r8,min(1.0_r8,this%GetState(store_organ, element_id)/store_max)) + logi_k = 2._r8 + store_x0 = 0.0_r8 + logi_min = 0.0_r8 - if(regulate_type == regulate_linear) then - c_scalar = min(c_max,max(c_min,1.0 - (store_frac - store_frac0)/(1.0_r8-store_frac0))) + if(regulate_type == regulate_CN_logi) then + + store_c = this%GetState(store_organ, carbon12_element) - elseif(regulate_type == regulate_logi) then + ! Fraction of N per fraction of C + ! If this is greater than 1, then we have more N in storage than + ! we have C, so we downregulate. If this is less than 1, then + ! we have less N in storage than we have C, so up-regulate + + store_frac = log(max(0.01_r8,store_frac) / max(0.01_r8,(store_c/target_c(store_organ)))) + + c_scalar = max(0._r8,min(1._r8,logi_min + (1._r8-logi_min)/(1.0 + exp(logi_k*(store_frac-store_x0))))) + + elseif(regulate_type == regulate_CN_dfdd) then - logi_k = 30.0_r8 - store_x0 = 0.7_r8 - logi_min = 0.0_r8 - ! In this method, we define the c_scalar term - ! with a logistic function that goes to 1 (full need) - ! as the plant's nutrien storage hits a low threshold - ! and goes to 0, no demand, as the plant's nutrient - ! storage approaches it's maximum holding capacity - - c_scalar = max(c_min,min(c_max,logi_min + (1.0_r8-logi_min)/(1.0_r8 + exp(logi_k*(store_frac-store_x0))))) - - !call check_var_real(c_scalar,'c_scalar',icode) - !if (icode .ne. 0) then - ! write(fates_log(),*) 'c_scalar is invalid, element: ',element_id - ! write(fates_log(),*) 'ending' - ! call endrun(msg=errMsg(sourcefile, __LINE__)) - !endif - - elseif(regulate_type == regulate_CN_logi .or. regulate_type == regulate_CN_ema) then - - logi_k = 1.0_r8 - store_x0 = 0.0_r8 - logi_min = 0.0_r8 - - ! Only update L2FR if some leaves are out - call bleaf(dbh,ipft,canopy_trim,leaf_c_target) - if(this%GetState(leaf_organ, carbon12_element)/leaf_c_target>0.01_r8) then - store_max = this%GetNutrientTarget(element_id,store_organ,stoich_max) - - ! Storage fractions could be more than the target, depending on the - ! hypothesis and functions involved, but should typically be 0-1 - ! The cap of 2 is for numerics and preventing weird math - - store_frac = max(0.01_r8,min(2.0_r8,this%GetState(store_organ, element_id)/store_max)) - - - call bstore_allom(dbh,ipft,canopy_trim,store_c_max) - - ! Since we don't dump storage carbon - ! these stores can actually get pretty large, so the cap of 10x is numerically - ! feasable, and should also minimize stress on the logistic function - store_c_frac = max(0.01_r8,min(10.0_r8,c_eq_offset*(this%GetState(store_organ, carbon12_element)/store_c_max))) - - - ! ----------------------------------------------------------------------------- - ! To decide the upper limit on expanding root growth, we perform a carbon - ! balance. Note that if we are growing roots out more, than we have proportionaly - ! more C compared to other resources. Specifically, we want to limit root growth - ! such that allocation to roots can't exceed a certain fraction of the daily - ! available carbon. This fraction is "max_l2fr_cgain_frac". - ! Additional notes. When calculating the "allocation to roots", we consider - ! both the carbon necessary to get the roots "on allometry" plux the carbon - ! necessary to expand them. - ! - ! (l2fr_delta_max*target_fnrt_c + target_fnrt_c-actual_fnrt_c )/c_gain - ! < max_l2fr_cgain_frac - ! - ! or - ! - ! l2fr_delta_max*target_fnrt_c < max_l2fr_cgain_frac * (c_gain - - ! (target_fnrt_c-actual_fnrt_c) - - ! (target_leaf_c-actual_leaf_c)) - ! - ! ------------------------------------------------------------------------------ - - call bfineroot(dbh,ipft,canopy_trim, l2fr, fnrt_c_target) - call bleaf(dbh,ipft,canopy_trim,leaf_c_target) - - ! If there is overflow storage, add this to the gain - c_gain = this%bc_in(acnp_bc_in_id_netdc)%rval + & - max(0._r8,this%GetState(store_organ, carbon12_element)-store_c_max) + store_max = this%GetNutrientTarget(element_id,store_organ,stoich_max) - fnrt_c = this%GetState(fnrt_organ, carbon12_element) - leaf_c = this%GetState(leaf_organ, carbon12_element) - - l2fr_delta_max = max_l2fr_cgain_frac / fnrt_c_target * & - (c_gain - (fnrt_c_target-fnrt_c) - (leaf_c_target-leaf_c)) + ! Storage fractions could be more than the target, depending on the + ! hypothesis and functions involved, but should typically be 0-1 + ! The cap of 5 is for numerics and preventing weird math - ! This value could be negative if there is no gain, or less gain - ! than what can replace leaf/root, just ensure the multiplier is GT 1 + + store_frac = max(0.01_r8,min(5.0_r8,this%GetState(store_organ, element_id)/store_max)) + + ! Since we don't dump storage carbon + ! these stores can actually get pretty large, so the cap of 10x is numerically + ! feasable, and should also minimize stress on the logistic function + store_c_frac = max(0.01_r8,min(5.0_r8,c_eq_offset*(this%GetState(store_organ, carbon12_element)/target_c(store_organ) ))) + + + ! ----------------------------------------------------------------------------- + ! To decide the upper limit on expanding root growth, we perform a carbon + ! balance. Note that if we are growing roots out more, than we have proportionaly + ! more C compared to other resources. Specifically, we want to limit root growth + ! such that allocation to roots can't exceed a certain fraction of the daily + ! available carbon. This fraction is "max_l2fr_cgain_frac". + ! Additional notes. When calculating the "allocation to roots", we consider + ! both the carbon necessary to get the roots "on allometry" plux the carbon + ! necessary to expand them. + ! + ! (l2fr_delta_max*target_fnrt_c + target_fnrt_c-actual_fnrt_c )/c_gain + ! < max_l2fr_cgain_frac + ! + ! or + ! + ! l2fr_delta_max*target_fnrt_c < max_l2fr_cgain_frac * (c_gain - + ! (target_fnrt_c-actual_fnrt_c) - + ! (target_leaf_c-actual_leaf_c)) + ! + ! or + ! as much as you like as long as turnover is replaced + ! + ! l2fr_delta_max*target_fnrt_c < c_gain - (target_fnrt_c-actual_fnrt_c) - + ! (target_leaf_c-actual_leaf_c) - + ! (target_sapw_c-actual_sapw_c) - + ! (target_dead_c-actual_dead_c) - + ! (target_stor_c-actual_stor_c) + ! + ! ------------------------------------------------------------------------------ + + ! If there is overflow storage, add this to the gain + c_gain = this%bc_in(acnp_bc_in_id_netdc)%rval + + fnrt_c = this%GetState(fnrt_organ, carbon12_element) + leaf_c = this%GetState(leaf_organ, carbon12_element) + store_c = this%GetState(store_organ, carbon12_element) + struct_c = this%GetState(struct_organ, carbon12_element) + sapw_c = this%GetState(sapw_organ, carbon12_element) + + if(lim_l2fr_max_type == limit_lf)then + l2fr_delta_max = max_l2fr_cgain_frac / target_c(fnrt_organ) * & + (c_gain - max(0._r8,target_c(fnrt_organ)-fnrt_c) - max(0._r8,target_c(leaf_organ)-leaf_c)) + + elseif(lim_l2fr_max_type ==limit_all)then + l2fr_delta_max = 1._r8/target_c(fnrt_organ) * & + (c_gain - & + max(0._r8,target_c(fnrt_organ)-fnrt_c) - & + max(0._r8,target_c(leaf_organ)-leaf_c) - & + max(0._r8,target_c(sapw_organ)-sapw_c) - & + max(0._r8,target_c(struct_organ)-struct_c) - & + max(0._r8,target_c(store_organ)-store_c) ) - l2fr_delta_max = max(1._r8,l2fr_delta_max) + end if + ! This value could be negative if there is no gain, or less gain + ! than what can replace leaf/root, just ensure the multiplier is GT 1 - ! Second constraint, folding timescale - ! 2.0 = l2fr_delta_max^frnt_adapt_tscl - l2fr_delta_max = min(l2fr_delta_max, 2._r8**(1._r8/fnrt_adapt_tscl)) - - - l2fr_actual = this%GetState(fnrt_organ, carbon12_element) / & - this%GetState(leaf_organ, carbon12_element) + l2fr_delta_max = max(1._r8,l2fr_delta_max) - ! Constrain change in l2fr minimum to be no more than what is lost - ! in turnover for a day - l2fr_delta_min = 1._r8-(years_per_day / prt_params%root_long(ipft)) + ! Constrain change in l2fr minimum to be no more than what is lost + ! in turnover for a day + l2fr_delta_min = 1._r8-(years_per_day / prt_params%root_long(ipft)) - ! Second constraint, folding timescale - l2fr_delta_min = max(l2fr_delta_min, 0.5_r8**(1._r8/fnrt_adapt_tscl)) + ! Determine the max change for the doubling timescale + ! 2.0 = l2fr_delta_max^frnt_adapt_tscl + l2fr_delta_scale = 2._r8**(1._r8/fnrt_adapt_tscl)-1.0_r8 - - log_nc_frac = log( store_frac / store_c_frac ) - - ! This is a logistic between -1 and 1 - c_scalar = 2._r8*max(0._r8, & - min(1._r8,logi_min + (1._r8-logi_min)/(1._r8 + exp(logi_k*(log_nc_frac-store_x0)))))-1.0_r8 - - if(c_scalar>0.0_r8)then - c_scalar = 1._r8 + c_scalar*(l2fr_delta_max-1._r8) - else - c_scalar = 1._r8 + c_scalar*(1._r8-l2fr_delta_min) - end if - - else - c_scalar = 1._r8 - end if - - - elseif(regulate_type == regulate_CN_dfdd) then + ! Determiine the change for the halving timescale + !l2fr_scale_min = 0.5_r8**(1._r8/fnrt_adapt_tscl) - store_c = this%GetState(store_organ, carbon12_element) - call bstore_allom(dbh,ipft,canopy_trim,store_c_max) + !log_nc_frac = log( store_frac / store_c_frac ) - ! Fraction of N per fraction of C - ! If this is greater than 1, then we have more N in storage than - ! we have C, so we downregulate. If this is less than 1, then - ! we have less N in storage than we have C, so up-regulate + ! This is a logistic between -1 and 1 + !c_scalar = l2fr_delta_scale*2._r8*max(0._r8, & + ! min(1._r8,logi_min + (1._r8-logi_min)/(1._r8 + exp(logi_k*(log_nc_frac-store_x0)))))-1.0_r8 - + nc_frac = store_frac / store_c_frac - store_frac = max(0.01_r8,store_frac) / max(0.01_r8,c_eq_offset*(store_c/store_c_max)) + c_scalar = l2fr_delta_scale*(2.0_r8/(1.0_r8 + nc_frac**logi_k)-1.0_r8)+1.0_r8 - c_scalar = 1._r8 - 0.02_r8*log(store_frac) + + if(c_scalar>1.0_r8)then + c_scalar = min(c_scalar,l2fr_delta_max) + else + c_scalar = max(c_scalar,l2fr_delta_min) + end if - !print*,element_id,store_frac,c_scalar end if diff --git a/parteh/PRTGenericMod.F90 b/parteh/PRTGenericMod.F90 index cfd398ec58..b92a1e14a7 100644 --- a/parteh/PRTGenericMod.F90 +++ b/parteh/PRTGenericMod.F90 @@ -100,7 +100,6 @@ module PRTGenericMod ! element. At the time of writing this, we are very far away from ! creating allocation schemes that even use potassium. - integer, parameter, public :: all_carbon_elements = 0 integer, parameter, public :: carbon12_element = 1 integer, parameter, public :: carbon13_element = 2 integer, parameter, public :: carbon14_element = 3 @@ -136,7 +135,7 @@ module PRTGenericMod ! List of all carbon elements, the special index "all_carbon_elements" - ! implies the following list of carbon organs + ! implies the following list of carbon organs (NOT USED) integer, parameter, dimension(3), public :: carbon_elements_list = & [carbon12_element, carbon13_element, carbon14_element] @@ -999,44 +998,23 @@ function GetState(this, organ_id, element_id, position_id) result(state_val) integer,intent(in) :: element_id ! Element type querried integer,intent(in),optional :: position_id ! Position querried real(r8) :: state_val ! Mass (value) of state variable [kg] - integer :: i_pos ! position loop counter - integer :: i_element ! element loop counter - integer :: num_element ! total number of elements - integer,dimension(max_spec_per_group) :: element_ids ! element ids (if element list) integer :: i_var ! variable id - - state_val = 0.0_r8 - - if(element_id == all_carbon_elements) then - element_ids(1:3) = carbon_elements_list(1:3) - num_element = 3 - else - num_element = 1 - element_ids(1) = element_id - end if if(present(position_id)) then - i_pos = position_id - - do i_element = 1,num_element - i_var = prt_global%sp_organ_map(organ_id,element_ids(i_element)) - if (i_var>0) state_val = state_val + this%variables(i_var)%val(i_pos) - end do + i_pos = position_id + i_var = prt_global%sp_organ_map(organ_id,element_id) + state_val = this%variables(i_var)%val(i_pos) + else - do i_element = 1,num_element - - i_var = prt_global%sp_organ_map(organ_id,element_ids(i_element)) - if(i_var>0)then - do i_pos = 1, prt_global%state_descriptor(i_var)%num_pos - state_val = state_val + this%variables(i_var)%val(i_pos) - end do - end if - + state_val = 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 + state_val = state_val + this%variables(i_var)%val(i_pos) end do - + end if return @@ -1060,43 +1038,23 @@ function GetTurnover(this, organ_id, element_id, position_id) result(turnover_va integer,intent(in) :: element_id ! Element type querried integer,intent(in),optional :: position_id ! Position querried real(r8) :: turnover_val ! Amount (value) of turnover [kg] - integer :: i_pos ! position loop counter - integer :: i_element ! element loop counter - integer :: num_element ! total number of elements - integer,dimension(max_spec_per_group) :: element_ids ! element ids (if element list) integer :: i_var ! variable id - turnover_val = 0.0_r8 - - if(element_id == all_carbon_elements) then - element_ids(1:3) = carbon_elements_list(1:3) - num_element = 3 - else - num_element = 1 - element_ids(1) = element_id - end if - if(present(position_id)) then + i_pos = position_id - - do i_element = 1,num_element - i_var = prt_global%sp_organ_map(organ_id,element_ids(i_element)) - if(i_var>0) turnover_val = turnover_val + & - this%variables(i_var)%turnover(i_pos) - end do + i_var = prt_global%sp_organ_map(organ_id,element_id) + turnover_val = this%variables(i_var)%turnover(i_pos) else - do i_element = 1,num_element - i_var = prt_global%sp_organ_map(organ_id,element_ids(i_element)) - if(i_var>0) then - do i_pos = 1, prt_global%state_descriptor(i_var)%num_pos - turnover_val = turnover_val + this%variables(i_var)%turnover(i_pos) - end do - end if - + turnover_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 + turnover_val = turnover_val + this%variables(i_var)%turnover(i_pos) end do + end if @@ -1117,43 +1075,21 @@ function GetBurned(this, organ_id, element_id, position_id) result(burned_val) integer,intent(in) :: element_id ! Element type querried integer,intent(in),optional :: position_id ! Position querried real(r8) :: burned_val ! Amount (value) of burned [kg] - integer :: i_pos ! position loop counter - integer :: i_element ! element loop counter - integer :: num_element ! total number of elements - integer,dimension(max_spec_per_group) :: element_ids ! element ids (if element list) integer :: i_var ! variable id - - burned_val = 0.0_r8 - - if(element_id == all_carbon_elements) then - element_ids(1:3) = carbon_elements_list(1:3) - num_element = 3 - else - num_element = 1 - element_ids(1) = element_id - end if - if(present(position_id)) then + i_pos = position_id - - do i_element = 1,num_element - i_var = prt_global%sp_organ_map(organ_id,element_ids(i_element)) - if(i_var>0) burned_val = burned_val + & - this%variables(i_var)%burned(i_pos) - end do + i_var = prt_global%sp_organ_map(organ_id,element_id) + burned_val = this%variables(i_var)%burned(i_pos) else - do i_element = 1,num_element - i_var = prt_global%sp_organ_map(organ_id,element_ids(i_element)) - if(i_var>0) then - do i_pos = 1, prt_global%state_descriptor(i_var)%num_pos - burned_val = burned_val + this%variables(i_var)%burned(i_pos) - end do - end if - + burned_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 + burned_val = burned_val + this%variables(i_var)%burned(i_pos) end do end if @@ -1176,42 +1112,21 @@ function GetNetAlloc(this, organ_id, element_id, position_id) result(val_netallo integer,intent(in) :: element_id ! Element type querried integer,intent(in),optional :: position_id ! Position querried real(r8) :: val_netalloc ! Amount (value) of allocation [kg] - integer :: i_pos ! position loop counter - integer :: i_element ! element loop counter - integer :: num_element ! total number of elements - integer,dimension(max_spec_per_group) :: element_ids ! element ids (if element list) integer :: i_var ! variable id - - val_netalloc = 0.0_r8 - if(element_id == all_carbon_elements) then - element_ids(1:3) = carbon_elements_list(1:3) - num_element = 3 - else - num_element = 1 - element_ids(1) = element_id - end if - if(present(position_id)) then - i_pos = position_id - - do i_element = 1,num_element - i_var = prt_global%sp_organ_map(organ_id,element_ids(i_element)) - if(i_var>0) val_netalloc = val_netalloc + & - this%variables(i_var)%net_alloc(i_pos) - end do - else + i_pos = position_id + i_var = prt_global%sp_organ_map(organ_id,element_id) + val_netalloc = this%variables(i_var)%net_alloc(i_pos) - do i_element = 1,num_element - i_var = prt_global%sp_organ_map(organ_id,element_ids(i_element)) - if(i_var>0) then - do i_pos = 1, prt_global%state_descriptor(i_var)%num_pos - val_netalloc = val_netalloc + this%variables(i_var)%net_alloc(i_pos) - end do - end if - + else + + val_netalloc = 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 + val_netalloc = val_netalloc + this%variables(i_var)%net_alloc(i_pos) end do end if @@ -1280,12 +1195,6 @@ subroutine SetState(prt,organ_id, element_id, state_val, position_id) integer :: i_var ! variable loop counter integer :: i_pos ! position loop counter - if(element_id == all_carbon_elements) then - write(fates_log(),*) 'You cannot set the state of all isotopes simultaneously.' - write(fates_log(),*) 'You can only set 1. Exiting.' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - if( present(position_id) ) then i_pos = position_id else From d5bd30485ad654a59432eb8edb53cfa65e9ec6e1 Mon Sep 17 00:00:00 2001 From: Shijie Shu Date: Thu, 17 Mar 2022 12:56:23 -0700 Subject: [PATCH 147/852] Updated changes from parent branch "fatesluc". --- biogeochem/EDLoggingMortalityMod.F90 | 5 +++++ main/EDParamsMod.F90 | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 4062b8c2d4..c78a64d598 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -1089,6 +1089,11 @@ subroutine UpdateHarvestC(currentSite,bc_in,bc_out) ! Harvested C flux in HLM. ! ---------------------------------------------------------------------------------- use EDtypesMod , only : ed_site_type + use EDTypesMod , only : AREA_INV + use PRTGenericMod , only : element_pos + use PRTGenericMod , only : carbon12_element + use EDParamsMod , only : pprodharv10_forest_mean + use FatesInterfaceTypesMod , only : bc_in_type, bc_out_type ! Arguments diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 8162939bc3..921513a2ac 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -151,6 +151,9 @@ module EDParamsMod real(r8),protected,public :: logging_export_frac ! "fraction of trunk product being shipped offsite, the ! leftovers will be left onsite as large CWD character(len=param_string_length),parameter,public :: logging_name_export_frac ="fates_logging_export_frac" + real(r8),protected,public :: pprodharv10_forest_mean ! "mean harvest mortality proportion of deadstem to 10-yr + ! product pool (pprodharv10) of all woody PFT types + character(len=param_string_length),parameter,public :: logging_name_pprodharv10="fates_pprodharv10_forest_mean" real(r8),protected,public :: eca_plant_escalar ! scaling factor for plant fine root biomass to ! calculate nutrient carrier enzyme abundance (ECA) @@ -208,6 +211,7 @@ subroutine FatesParamsInit() logging_event_code = nan logging_dbhmax_infra = nan logging_export_frac = nan + pprodharv10_forest_mean = nan eca_plant_escalar = nan q10_mr = nan q10_froz = nan @@ -348,6 +352,9 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=logging_name_export_frac, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=logging_name_pprodharv10, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=eca_name_plant_escalar, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -500,6 +507,9 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetreiveParameter(name=logging_name_export_frac, & data=logging_export_frac) + call fates_params%RetreiveParameter(name=logging_name_pprodharv10, & + data=pprodharv10_forest_mean) + call fates_params%RetreiveParameter(name=eca_name_plant_escalar, & data=eca_plant_escalar) From a04f297ac519a080d6c2d19f68a4286fce942afc Mon Sep 17 00:00:00 2001 From: Shijie Shu Date: Fri, 18 Mar 2022 15:03:59 -0700 Subject: [PATCH 148/852] Revise the unit transfer codes in subroutine UpdateHarvestC. --- biogeochem/EDLoggingMortalityMod.F90 | 37 +++------------------------- main/EDParamsMod.F90 | 3 +++ 2 files changed, 7 insertions(+), 33 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index a61ef78426..adc295e19b 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -821,7 +821,7 @@ subroutine UpdateHarvestC(currentSite,bc_out) ! Harvested C flux in HLM. ! ---------------------------------------------------------------------------------- use EDtypesMod , only : ed_site_type - use EDTypesMod , only : AREA_INV + use EDTypesMod , only : AREA_INV use PRTGenericMod , only : element_pos use PRTGenericMod , only : carbon12_element use FatesInterfaceTypesMod , only : bc_out_type @@ -836,40 +836,11 @@ subroutine UpdateHarvestC(currentSite,bc_out) ! Flush the older value before update - if(logging_time) then - bc_out%hrv_deadstemc_to_prod10c = 0._r8 - bc_out%hrv_deadstemc_to_prod100c = 0._r8 - end if + bc_out%hrv_deadstemc_to_prod10c = 0._r8 + bc_out%hrv_deadstemc_to_prod100c = 0._r8 - ! First test tropic forest (PFT=1) ! Calculate the unit transfer factor (from kgC m-2 day-1 to gC m-2 s-1) - ! for icode == 2, icode < 0, and icode > 10000 is one time harvest, thus - ! shall distribute into everyday - icode = int(logging_event_code) - if(icode .eq. 1) then - ! Logging is turned off - unit_trans_factor = 1._r8 - else if(icode .eq. 3) then - ! Logging event every day - this may not work due to the mortality exclusivity - unit_trans_factor = 1000._r8 * days_per_sec - else if(icode .eq. 4) then - ! Logging event once a month - ! Shijie: Shall think about a better if expreession? - if ((hlm_current_month == 1) .or. (hlm_current_month == 3) .or. & - (hlm_current_month == 5) .or. (hlm_current_month == 7) .or. & - (hlm_current_month == 8) .or. (hlm_current_month == 10) .or. & - (hlm_current_month == 12)) then - unit_trans_factor = 1000._r8 * days_per_sec / 31._r8 - else if((hlm_current_month == 4) .or. (hlm_current_month == 6) .or. & - (hlm_current_month == 9) .or. (hlm_current_month == 11)) then - unit_trans_factor = 1000._r8 * days_per_sec / 30._r8 - else - unit_trans_factor = 1000._r8 * days_per_sec / 28._r8 - end if - else - ! Logging event one time every year - unit_trans_factor = 1000._r8 * days_per_sec * years_per_day - end if + unit_trans_factor = 1000._r8 * days_per_sec bc_out%hrv_deadstemc_to_prod10c = bc_out%hrv_deadstemc_to_prod10c + & currentSite%mass_balance(element_pos(carbon12_element))%wood_product * & diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 825d42b400..bda572db88 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -353,6 +353,9 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=logging_name_export_frac, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=logging_name_pprodharv10, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=eca_name_plant_escalar, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) From 442639fa86f51b3ed0245433b8b9e33178e4d75d Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Tue, 22 Mar 2022 13:57:11 -0700 Subject: [PATCH 149/852] [ Add damage only dimension back. ] [ Useful in python scripts to know how many damage classes there are ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary:no testing --- main/FatesIODimensionsMod.F90 | 8 +++++++- main/FatesIOVariableKindMod.F90 | 1 + main/FatesInterfaceMod.F90 | 1 + main/FatesInterfaceTypesMod.F90 | 1 + 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/main/FatesIODimensionsMod.F90 b/main/FatesIODimensionsMod.F90 index 325ef44d6b..d8923b60dd 100644 --- a/main/FatesIODimensionsMod.F90 +++ b/main/FatesIODimensionsMod.F90 @@ -28,6 +28,7 @@ module FatesIODimensionsMod character(*), parameter, public :: levcnlfpft = 'fates_levcnlfpf' ! matches histFileMod character(*), parameter, public :: levcdsc = 'fates_levcdsc' ! matches histFileMod character(*), parameter, public :: levcdpf = 'fates_levcdpf' ! matches histFileMod + character(*), parameter, public :: levcdam = 'fates_levcdam' ! matches histFileMod character(*), parameter, public :: levagefuel = 'fates_levagefuel' ! matches histFileMod character(*), parameter, public :: levelem = 'fates_levelem' character(*), parameter, public :: levelpft = 'fates_levelpft' @@ -82,7 +83,10 @@ module FatesIODimensionsMod ! levcdpf = This is a structure that records the boundaries for the ! number of crown damage x size classes x pft dimension - + + ! levcdam = This is the structure that records the boundaries for the + ! number of crown damage classes dimension + ! levscag = This is a strcture that records the boundaries for the ! number of size-classes x patch age @@ -142,6 +146,8 @@ module FatesIODimensionsMod integer :: cdsc_end integer :: cdpf_begin integer :: cdpf_end + integer :: cdam_begin + integer :: cdam_end integer :: elem_begin integer :: elem_end integer :: elpft_begin diff --git a/main/FatesIOVariableKindMod.F90 b/main/FatesIOVariableKindMod.F90 index c35ca67507..66db1caf57 100644 --- a/main/FatesIOVariableKindMod.F90 +++ b/main/FatesIOVariableKindMod.F90 @@ -29,6 +29,7 @@ module FatesIOVariableKindMod character(*), parameter, public :: site_cnlfpft_r8 = 'SI_CNLFPFT_R8' character(*), parameter, public :: site_cdpf_r8 = 'SI_CDPF_R8' character(*), parameter, public :: site_cdsc_r8 = 'SI_CDSC_R8' + character(*), parameter, public :: site_cdam_r8 = 'SI_CDAM_R8' character(*), parameter, public :: site_scag_r8 = 'SI_SCAG_R8' character(*), parameter, public :: site_scagpft_r8 = 'SI_SCAGPFT_R8' character(*), parameter, public :: site_agepft_r8 = 'SI_AGEPFT_R8' diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index a75d91063d..4a060acd3a 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1031,6 +1031,7 @@ subroutine fates_history_maps allocate( fates_hdim_pfmap_levcapf(1:nlevcoage*numpft)) allocate( fates_hdim_camap_levcapf(1:nlevcoage*numpft)) + allocate( fates_hdim_levcdam(1:ncrowndamage )) allocate( fates_hdim_scmap_levcdsc(nlevsclass*ncrowndamage)) allocate( fates_hdim_cdmap_levcdsc(nlevsclass*ncrowndamage)) allocate( fates_hdim_scmap_levcdpf(nlevsclass*ncrowndamage * numpft)) diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index cfd710d2d3..a9bb7efba5 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -244,6 +244,7 @@ module FatesInterfaceTypesMod integer , public, allocatable :: fates_hdim_scmap_levcdpf(:) ! map of size into size x crowndamage x pft integer , public, allocatable :: fates_hdim_cdmap_levcdsc(:) ! map of crowndamage into size x crowndamage integer , public, allocatable :: fates_hdim_scmap_levcdsc(:) ! map of size into size x crowndamage + integer , public, allocatable :: fates_hdim_levcdam(:) ! plant damage class lower bound dimension real(r8), public, allocatable :: fates_hdim_levage(:) ! patch age lower bound dimension real(r8), public, allocatable :: fates_hdim_levheight(:) ! height lower bound dimension From 6f0e6821dacb466826604239e5473b968584650a Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Tue, 22 Mar 2022 16:59:16 -0700 Subject: [PATCH 150/852] [ Make crown damage bin edges flexible ] [Allow for uneven spacing of damage bins. ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary:no testing --- biogeochem/DamageMainMod.F90 | 10 +++---- biogeochem/EDPatchDynamicsMod.F90 | 8 +++--- main/EDInitMod.F90 | 22 ++++++++-------- main/EDMainMod.F90 | 2 +- main/EDParamsMod.F90 | 26 +++++++++---------- main/FatesHistoryInterfaceMod.F90 | 8 +++--- main/FatesInterfaceMod.F90 | 33 ++++++++++-------------- main/FatesInterfaceTypesMod.F90 | 2 +- main/FatesParameterDerivedMod.F90 | 20 +++++++------- main/FatesParametersInterface.F90 | 1 + main/FatesRestartInterfaceMod.F90 | 8 +++--- main/FatesSizeAgeTypeIndicesMod.F90 | 6 +++-- parameter_files/fates_params_default.cdl | 13 +++++----- 13 files changed, 78 insertions(+), 81 deletions(-) diff --git a/biogeochem/DamageMainMod.F90 b/biogeochem/DamageMainMod.F90 index 6947aac992..20c9358a28 100644 --- a/biogeochem/DamageMainMod.F90 +++ b/biogeochem/DamageMainMod.F90 @@ -73,7 +73,7 @@ subroutine get_damage_frac(cc_cd, nc_cd, pft, dist_frac) ! Consults a look up table of transitions from param derived. ! USES - use FatesInterfaceTypesMod, only : ncrowndamage + use FatesInterfaceTypesMod, only : nlevdamage use FatesConstantsMod, only : years_per_day use FatesParameterDerivedMod, only : param_derived @@ -101,7 +101,7 @@ subroutine get_crown_reduction(crowndamage, crown_reduction) ! before multiplying by 0.2 ! Therefore, first damage class is 20% loss of crown, second 40% etc. !------------------------------------------------------------------- - use FatesInterfaceTypesMod , only : ncrowndamage + use FatesInterfaceTypesMod , only : nlevdamage integer(i4), intent(in) :: crowndamage real(r8), intent(out) :: crown_reduction @@ -109,7 +109,7 @@ subroutine get_crown_reduction(crowndamage, crown_reduction) ! local variables real(r8) :: class_width - class_width = 1.0_r8/ncrowndamage + class_width = 1.0_r8/nlevdamage crown_reduction = min(1.0_r8, (real(crowndamage) - 1.0_r8) * class_width) return @@ -121,7 +121,7 @@ end subroutine get_crown_reduction subroutine get_damage_mortality(crowndamage,pft, dgmort) - use FatesInterfaceTypesMod , only : ncrowndamage + use FatesInterfaceTypesMod , only : nlevdamage use EDPftvarcon , only : EDPftvarcon_inst integer(i4), intent(in) :: crowndamage @@ -134,7 +134,7 @@ subroutine get_damage_mortality(crowndamage,pft, dgmort) real(r8) :: class_width real(r8) :: crown_loss - class_width = 1.0_r8/real(ncrowndamage) + class_width = 1.0_r8/real(nlevdamage) ! parameter to determine slope of exponential damage_mort_p1 = EDPftvarcon_inst%damage_mort_p1(pft) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 16ba988385..92a69389e0 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -474,7 +474,7 @@ subroutine spawn_patches( currentSite, bc_in) use ChecksBalancesMod , only : SiteMassStock use FatesInterfaceTypesMod, only : hlm_use_canopy_damage use FatesInterfaceTypesMod, only : hlm_use_understory_damage - use FatesInterfaceTypesMod, only : ncrowndamage + use FatesInterfaceTypesMod, only : nlevdamage use FatesParameterDerivedMod, only : param_derived ! @@ -1264,7 +1264,7 @@ subroutine spawn_patches( currentSite, bc_in) cd_n_total = 0.0_r8 ! for each damage class find the number density and if big enough allocate a new cohort - do cd = currentCohort%crowndamage+1, ncrowndamage + do cd = currentCohort%crowndamage+1, nlevdamage call get_damage_frac(currentCohort%crowndamage, cd, currentCohort%pft, cd_frac) @@ -2377,7 +2377,7 @@ subroutine damage_litter_fluxes(currentSite, currentPatch, newPatch,patch_site_a use DamageMainMod, only : get_crown_reduction use DamageMainMod , only : get_damage_frac use SFParamsMod , only : SF_val_cwd_frac - use FatesInterfaceTypesMod , only : ncrowndamage + use FatesInterfaceTypesMod , only : nlevdamage use EDParamsMod , only : ED_val_understorey_death use FatesInterfaceTypesMod, only : hlm_use_canopy_damage use FatesInterfaceTypesMod, only : hlm_use_understory_damage @@ -2511,7 +2511,7 @@ subroutine damage_litter_fluxes(currentSite, currentPatch, newPatch,patch_site_a - do cd = currentCohort%crowndamage+1, ncrowndamage + do cd = currentCohort%crowndamage+1, nlevdamage call get_damage_frac(currentCohort%crowndamage, cd, currentCohort%pft, cd_frac) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index e4590caca1..b49c757e3c 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -50,7 +50,7 @@ module EDInitMod use FatesInterfaceTypesMod , only : nleafage use FatesInterfaceTypesMod , only : nlevsclass use FatesInterfaceTypesMod , only : nlevcoage - use FatesInterfaceTypesMod , only : ncrowndamage + use FatesInterfaceTypesMod , only : nlevdamage use FatesInterfaceTypesMod , only : hlm_use_nocomp use FatesInterfaceTypesMod , only : nlevage @@ -132,16 +132,16 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) allocate(site_in%flux_diags(1:num_elements)) if (hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then - allocate(site_in%term_nindivs_canopy_damage(1:ncrowndamage, 1:nlevsclass, 1:numpft)) - allocate(site_in%term_nindivs_ustory_damage(1:ncrowndamage, 1:nlevsclass, 1:numpft)) - allocate(site_in%imort_rate_damage(1:ncrowndamage, 1:nlevsclass, 1:numpft)) - allocate(site_in%imort_cflux_damage(1:ncrowndamage, 1:nlevsclass)) - allocate(site_in%term_cflux_canopy_damage(1:ncrowndamage, 1:nlevsclass)) - allocate(site_in%term_cflux_ustory_damage(1:ncrowndamage, 1:nlevsclass)) - allocate(site_in%fmort_rate_canopy_damage(1:ncrowndamage, 1:nlevsclass, 1:numpft)) - allocate(site_in%fmort_rate_ustory_damage(1:ncrowndamage, 1:nlevsclass, 1:numpft)) - allocate(site_in%fmort_cflux_canopy_damage(1:ncrowndamage, 1:nlevsclass)) - allocate(site_in%fmort_cflux_ustory_damage(1:ncrowndamage, 1:nlevsclass)) + allocate(site_in%term_nindivs_canopy_damage(1:nlevdamage, 1:nlevsclass, 1:numpft)) + allocate(site_in%term_nindivs_ustory_damage(1:nlevdamage, 1:nlevsclass, 1:numpft)) + allocate(site_in%imort_rate_damage(1:nlevdamage, 1:nlevsclass, 1:numpft)) + allocate(site_in%imort_cflux_damage(1:nlevdamage, 1:nlevsclass)) + allocate(site_in%term_cflux_canopy_damage(1:nlevdamage, 1:nlevsclass)) + allocate(site_in%term_cflux_ustory_damage(1:nlevdamage, 1:nlevsclass)) + allocate(site_in%fmort_rate_canopy_damage(1:nlevdamage, 1:nlevsclass, 1:numpft)) + allocate(site_in%fmort_rate_ustory_damage(1:nlevdamage, 1:nlevsclass, 1:numpft)) + allocate(site_in%fmort_cflux_canopy_damage(1:nlevdamage, 1:nlevsclass)) + allocate(site_in%fmort_cflux_ustory_damage(1:nlevdamage, 1:nlevsclass)) else allocate(site_in%term_nindivs_canopy_damage(1,1,1)) allocate(site_in%term_nindivs_ustory_damage(1,1,1)) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index b9f5cde62d..ce5a2dda76 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -312,7 +312,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! FIX(SPM,032414) refactor so everything goes through interface ! ! !USES: - use FatesInterfaceTypesMod, only : ncrowndamage + use FatesInterfaceTypesMod, only : nlevdamage use FatesAllometryMod , only : bleaf use FatesAllometryMod , only : carea_allom use PRTGenericMod , only : leaf_organ diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 612a844364..f474a20cab 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -44,7 +44,6 @@ module EDParamsMod real(r8),protected, public :: ED_val_init_litter real(r8),protected, public :: ED_val_nignitions real(r8),protected, public :: ED_val_understorey_death - real(r8),protected, public :: ED_val_ncrowndamage real(r8),protected, public :: ED_val_cwd_fcel real(r8),protected, public :: ED_val_cwd_flig real(r8),protected, public :: ED_val_base_mr_20 @@ -88,7 +87,8 @@ module EDParamsMod real(r8),protected,allocatable,public :: ED_val_history_ageclass_bin_edges(:) real(r8),protected,allocatable,public :: ED_val_history_height_bin_edges(:) real(r8),protected,allocatable,public :: ED_val_history_coageclass_bin_edges(:) - + real(r8),protected,allocatable,public :: ED_val_history_damage_bin_edges(:) + ! Switch that defines the current pressure-volume and pressure-conductivity model ! to be used at each node (compartment/organ) ! 1 = Christofferson et al. 2016 (TFS), 2 = Van Genuchten 1980 @@ -115,7 +115,6 @@ module EDParamsMod character(len=param_string_length),parameter,public :: ED_name_init_litter = "fates_init_litter" character(len=param_string_length),parameter,public :: ED_name_nignitions = "fates_fire_nignitions" character(len=param_string_length),parameter,public :: ED_name_understorey_death = "fates_mort_understorey_death" - character(len=param_string_length),parameter,public :: ED_name_ncrowndamage = 'fates_ncrowndamage' character(len=param_string_length),parameter,public :: ED_name_cwd_fcel= "fates_cwd_fcel" character(len=param_string_length),parameter,public :: ED_name_cwd_flig= "fates_cwd_flig" character(len=param_string_length),parameter,public :: ED_name_base_mr_20= "fates_base_mr_20" @@ -146,7 +145,7 @@ module EDParamsMod character(len=param_string_length),parameter,public :: ED_name_history_height_bin_edges= "fates_history_height_bin_edges" 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) ! ---------------------------------------------------------------------------------------------- @@ -238,7 +237,6 @@ subroutine FatesParamsInit() ED_val_init_litter = nan ED_val_nignitions = nan ED_val_understorey_death = nan - ED_val_ncrowndamage = nan ED_val_cwd_fcel = nan ED_val_cwd_flig = nan ED_val_base_mr_20 = nan @@ -286,7 +284,7 @@ subroutine FatesRegisterParams(fates_params) use FatesParametersInterface, only : fates_parameters_type, dimension_name_scalar, dimension_shape_1d use FatesParametersInterface, only : dimension_name_history_size_bins, dimension_name_history_age_bins use FatesParametersInterface, only : dimension_name_history_height_bins, dimension_name_hydr_organs - use FatesParametersInterface, only : dimension_name_history_coage_bins + use FatesParametersInterface, only : dimension_name_history_coage_bins, dimension_name_history_damage_bins use FatesParametersInterface, only : dimension_shape_scalar implicit none @@ -298,6 +296,7 @@ subroutine FatesRegisterParams(fates_params) character(len=param_string_length), parameter :: dim_names_ageclass(1) = (/dimension_name_history_age_bins/) character(len=param_string_length), parameter :: dim_names_height(1) = (/dimension_name_history_height_bins/) character(len=param_string_length), parameter :: dim_names_coageclass(1) = (/dimension_name_history_coage_bins/) + character(len=param_string_length), parameter :: dim_names_damageclass(1)= (/dimension_name_history_damage_bins/) character(len=param_string_length), parameter :: dim_names_hydro_organs(1) = (/dimension_name_hydr_organs/) call FatesParamsInit() @@ -337,10 +336,7 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=ED_name_understorey_death, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) - - call fates_params%RegisterParameter(name=ED_name_ncrowndamage, dimension_shape=dimension_shape_scalar, & - dimension_names=dim_names_scalar) - + call fates_params%RegisterParameter(name=ED_name_cwd_fcel, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -469,6 +465,9 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=ED_name_history_coageclass_bin_edges, dimension_shape=dimension_shape_1d, & dimension_names=dim_names_coageclass) + call fates_params%RegisterParameter(name=ED_name_history_damage_bin_edges, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names_damageclass) + end subroutine FatesRegisterParams @@ -517,9 +516,6 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetreiveParameter(name=ED_name_understorey_death, & data=ED_val_understorey_death) - call fates_params%RetreiveParameter(name=ED_name_ncrowndamage, & - data=ED_val_ncrowndamage) - call fates_params%RetreiveParameter(name=ED_name_cwd_fcel, & data=ED_val_cwd_fcel) @@ -652,6 +648,9 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetreiveParameterAllocate(name=ED_name_history_coageclass_bin_edges, & data=ED_val_history_coageclass_bin_edges) + call fates_params%RetreiveParameterAllocate(name=ED_name_history_damage_bin_edges, & + data=ED_val_history_damage_bin_edges) + call fates_params%RetreiveParameterAllocate(name=ED_name_hydr_htftype_node, & data=hydr_htftype_real) allocate(hydr_htftype_node(size(hydr_htftype_real))) @@ -684,7 +683,6 @@ subroutine FatesReportParams(is_master) write(fates_log(),fmt0) 'ED_val_init_litter = ',ED_val_init_litter write(fates_log(),fmt0) 'ED_val_nignitions = ',ED_val_nignitions write(fates_log(),fmt0) 'ED_val_understorey_death = ',ED_val_understorey_death - write(fates_log(),fmt0) 'ED_val_ncrowndamage = ', ED_val_ncrowndamage write(fates_log(),fmt0) 'ED_val_cwd_fcel = ',ED_val_cwd_fcel write(fates_log(),fmt0) 'ED_val_cwd_flig = ',ED_val_cwd_flig write(fates_log(),fmt0) 'ED_val_base_mr_20 = ', ED_val_base_mr_20 diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index cc139454c8..2a29f2d9d0 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -50,7 +50,7 @@ Module FatesHistoryInterfaceMod use FatesInterfaceTypesMod , only : bc_in_type use FatesInterfaceTypesMod , only : hlm_model_day use FatesInterfaceTypesMod , only : nlevcoage - use FatesInterfaceTypesMod , only : ncrowndamage + use FatesInterfaceTypesMod , only : nlevdamage use FatesInterfaceTypesMod , only : hlm_use_nocomp use FatesAllometryMod , only : CrownDepth @@ -1808,7 +1808,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) use FatesSizeAgeTypeIndicesMod, only : coagetype_class_index use EDTypesMod , only : nlevleaf use EDParamsMod, only : ED_val_history_height_bin_edges - use FatesInterfaceTypesMod, only : ncrowndamage + use FatesInterfaceTypesMod, only : nlevdamage use DamageMainMod , only : damage_time ! Arguments @@ -3272,12 +3272,12 @@ subroutine update_history_dyn(this,nc,nsites,sites) hlm_use_understory_damage .eq. itrue ) then do i_pft = 1, numpft - do icdam = 1, ncrowndamage + do icdam = 1, nlevdamage do i_scls = 1,nlevsclass icdsc = (icdam-1)*nlevsclass + i_scls icdpf = (icdam-1)*nlevsclass + i_scls + & - (i_pft-1) * nlevsclass * ncrowndamage + (i_pft-1) * nlevsclass * nlevdamage this%hvars(ih_mortality_si_cdpf)%r82d(io_si, icdpf) = & this%hvars(ih_mortality_si_cdpf)%r82d(io_si, icdpf) + & diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 4a060acd3a..b929af26c3 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -50,7 +50,7 @@ module FatesInterfaceMod use EDParamsMod , only : ED_val_history_ageclass_bin_edges use EDParamsMod , only : ED_val_history_height_bin_edges use EDParamsMod , only : ED_val_history_coageclass_bin_edges - use EDParamsMod , only : ED_val_ncrowndamage + use EDParamsMod , only : ED_val_history_damage_bin_edges use CLMFatesParamInterfaceMod , only : FatesReadParameters use EDTypesMod , only : p_uptake_mode use EDTypesMod , only : n_uptake_mode @@ -730,9 +730,7 @@ subroutine SetFatesGlobalElements(use_fates) ! ! -------------------------------------------------------------------------------- - use EDParamsMod, only : ED_val_ncrowndamage - - + implicit none @@ -776,10 +774,7 @@ subroutine SetFatesGlobalElements(use_fates) nleafage = size(prt_params%leaf_long,dim=2) end if - ! Identify the number of damage classes - ncrowndamage = ED_val_ncrowndamage - - + ! These values are used to define the restart file allocations and general structure ! of memory for the cohort arrays @@ -840,7 +835,7 @@ subroutine SetFatesGlobalElements(use_fates) nlevage = size(ED_val_history_ageclass_bin_edges,dim=1) nlevheight = size(ED_val_history_height_bin_edges,dim=1) nlevcoage = size(ED_val_history_coageclass_bin_edges,dim=1) - + nlevdamage = size(ED_val_history_damage_bin_edges, dim=1) ! do some checks on the size, age, and height bin arrays to make sure they make sense: ! make sure that all start at zero, and that both are monotonically increasing @@ -991,13 +986,13 @@ subroutine fates_history_maps use EDTypesMod, only : NFSC use EDTypesMod, only : nclmax - use FatesInterfaceTypesMod, only : ncrowndamage use EDTypesMod, only : nlevleaf use EDParamsMod, only : ED_val_history_sizeclass_bin_edges use EDParamsMod, only : ED_val_history_ageclass_bin_edges use EDParamsMod, only : ED_val_history_height_bin_edges use EDParamsMod, only : ED_val_history_coageclass_bin_edges - + use EDParamsMod, only : ED_val_history_damage_bin_edges + ! ------------------------------------------------------------------------------------------ ! This subroutine allocates and populates the variables ! that define the mapping of variables in history files in multiplexed dimensions like @@ -1031,12 +1026,12 @@ subroutine fates_history_maps allocate( fates_hdim_pfmap_levcapf(1:nlevcoage*numpft)) allocate( fates_hdim_camap_levcapf(1:nlevcoage*numpft)) - allocate( fates_hdim_levcdam(1:ncrowndamage )) - allocate( fates_hdim_scmap_levcdsc(nlevsclass*ncrowndamage)) - allocate( fates_hdim_cdmap_levcdsc(nlevsclass*ncrowndamage)) - allocate( fates_hdim_scmap_levcdpf(nlevsclass*ncrowndamage * numpft)) - allocate( fates_hdim_cdmap_levcdpf(nlevsclass*ncrowndamage * numpft)) - allocate( fates_hdim_pftmap_levcdpf(nlevsclass*ncrowndamage * numpft)) + allocate( fates_hdim_levcdam(1:nlevdamage )) + allocate( fates_hdim_scmap_levcdsc(nlevsclass*nlevdamage)) + allocate( fates_hdim_cdmap_levcdsc(nlevsclass*nlevdamage)) + allocate( fates_hdim_scmap_levcdpf(nlevsclass*nlevdamage * numpft)) + allocate( fates_hdim_cdmap_levcdpf(nlevsclass*nlevdamage * numpft)) + allocate( fates_hdim_pftmap_levcdpf(nlevsclass*nlevdamage * numpft)) allocate( fates_hdim_levcan(nclmax)) allocate( fates_hdim_levelem(num_elements)) @@ -1164,7 +1159,7 @@ subroutine fates_history_maps end do i=0 - do icdam=1,ncrowndamage + do icdam=1,nlevdamage do isc=1,nlevsclass i=i+1 fates_hdim_scmap_levcdsc(i) = isc @@ -1199,7 +1194,7 @@ subroutine fates_history_maps i=0 do ipft=1,numpft - do icdam=1,ncrowndamage + do icdam=1,nlevdamage do isc=1,nlevsclass i=i+1 fates_hdim_scmap_levcdpf(i) = isc diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index a9bb7efba5..b6826d2ce5 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -312,7 +312,7 @@ module FatesInterfaceTypesMod integer, public :: nlevheight ! The total number of height bins output to history integer, public :: nlevcoage ! The total number of cohort age bins output to history integer, public :: nleafage ! The total number of leaf age classes - integer, public :: ncrowndamage ! The total number of damage classes + integer, public :: nlevdamage ! The total number of damage classes ! ------------------------------------------------------------------------------------- ! Structured Boundary Conditions (SITE/PATCH SCALE) diff --git a/main/FatesParameterDerivedMod.F90 b/main/FatesParameterDerivedMod.F90 index f63df66318..0214224ee3 100644 --- a/main/FatesParameterDerivedMod.F90 +++ b/main/FatesParameterDerivedMod.F90 @@ -13,7 +13,7 @@ module FatesParameterDerivedMod use FatesConstantsMod, only : umolC_to_kgC use FatesConstantsMod, only : g_per_kg use FatesInterfaceTypesMod, only : nleafage - use FatesInterfaceTypesMod, only : ncrowndamage + use FatesInterfaceTypesMod, only : nlevdamage use FatesGlobals , only : fates_log implicit none @@ -66,13 +66,13 @@ end subroutine InitAllocate ! ===================================================================================== ! =================================================================================== - subroutine InitAllocateDamageTransitions(this,ncrowndamage, numpft) + subroutine InitAllocateDamageTransitions(this,nlevdamage, numpft) class(param_derived_type), intent(inout) :: this - integer, intent(in) :: ncrowndamage + integer, intent(in) :: nlevdamage integer, intent(in) :: numpft - allocate(this%damage_transitions(ncrowndamage,ncrowndamage, numpft)) + allocate(this%damage_transitions(nlevdamage,nlevdamage, numpft)) return end subroutine InitAllocateDamageTransitions @@ -129,13 +129,13 @@ end subroutine Init !========================================================================= - subroutine InitDamageTransitions(this, ncrowndamage, numpft) + subroutine InitDamageTransitions(this, nlevdamage, numpft) use EDPftvarcon, only: EDPftvarcon_inst class(param_derived_type), intent(inout) :: this - integer, intent(in) :: ncrowndamage + integer, intent(in) :: nlevdamage integer, intent(in) :: numpft ! local variables @@ -144,22 +144,22 @@ subroutine InitDamageTransitions(this, ncrowndamage, numpft) real(r8) :: damage_frac ! damage fraction - call this%InitAllocateDamageTransitions(ncrowndamage, numpft) + call this%InitAllocateDamageTransitions(nlevdamage, numpft) do ft = 1, numpft damage_frac = EDPftvarcon_inst%damage_frac(ft) - do i = 1, ncrowndamage + do i = 1, nlevdamage ! zero the column this%damage_transitions(i,:,ft) = 0._r8 ! 1 - damage rate stay the same this%damage_transitions(i,i,ft) = 1.0_r8 - damage_frac - if(i < ncrowndamage) then + if(i < nlevdamage) then ! fraction damaged get evenly split between higher damage classes - this%damage_transitions(i,i+1:ncrowndamage,ft) = damage_frac/(ncrowndamage - i) + this%damage_transitions(i,i+1:nlevdamage,ft) = damage_frac/(nlevdamage - i) end if ! Make sure it sums to one - they have to go somewhere this%damage_transitions(i, :, ft) = this%damage_transitions(i, :, ft)/SUM(this%damage_transitions(i, :, ft)) diff --git a/main/FatesParametersInterface.F90 b/main/FatesParametersInterface.F90 index f37b63b93c..f2bfabc125 100644 --- a/main/FatesParametersInterface.F90 +++ b/main/FatesParametersInterface.F90 @@ -36,6 +36,7 @@ module FatesParametersInterface character(len=*), parameter, public :: dimension_name_history_age_bins = 'fates_history_age_bins' character(len=*), parameter, public :: dimension_name_history_height_bins = 'fates_history_height_bins' character(len=*), parameter, public :: dimension_name_history_coage_bins = 'fates_history_coage_bins' + character(len=*), parameter, public :: dimension_name_history_damage_bins = 'fates_history_damage_bins' character(len=*), parameter, public :: dimension_name_hlm_pftno = 'fates_hlm_pftno' ! Dimensions in the host namespace: diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 4512448504..41bc8e58f0 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -33,7 +33,7 @@ module FatesRestartInterfaceMod use EDCohortDynamicsMod, only : InitPRTBoundaryConditions use FatesPlantHydraulicsMod, only : InitHydrCohort use FatesInterfaceTypesMod, only : nlevsclass - use FatesInterfaceTypesMod, only : ncrowndamage + use FatesInterfaceTypesMod, only : nlevdamage use FatesLitterMod, only : litter_type use FatesLitterMod, only : ncwd use FatesLitterMod, only : ndcmpy @@ -1797,7 +1797,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) use EDTypesMod, only : nclmax use EDTypesMod, only : numWaterMem use EDTypesMod, only : num_vegtemp_mem - use FatesInterfaceTypesMod, only : ncrowndamage + use FatesInterfaceTypesMod, only : nlevdamage ! Arguments class(fates_restart_interface_type) :: this @@ -2372,7 +2372,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then do i_scls = 1, nlevsclass - do i_cdam = 1, ncrowndamage + do i_cdam = 1, nlevdamage do i_pft = 1, numpft rio_imortrate_sicdpf(io_idx_si_cdpf) = sites(s)%imort_rate_damage(i_cdam, i_scls, i_pft) rio_termnindiv_cano_sicdpf(io_idx_si_cdpf) = sites(s)%term_nindivs_canopy_damage(i_cdam,i_scls,i_pft) @@ -3297,7 +3297,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) end do if (hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then - do i_cdam = 1, ncrowndamage + do i_cdam = 1, nlevdamage do i_pft = 1, numpft do i_scls = 1, nlevsclass sites(s)%imort_rate_damage(i_cdam, i_scls, i_pft) = rio_imortrate_sicdpf(io_idx_si_cdpf) diff --git a/main/FatesSizeAgeTypeIndicesMod.F90 b/main/FatesSizeAgeTypeIndicesMod.F90 index 91dbc5455c..66e3edab28 100644 --- a/main/FatesSizeAgeTypeIndicesMod.F90 +++ b/main/FatesSizeAgeTypeIndicesMod.F90 @@ -6,11 +6,13 @@ module FatesSizeAgeTypeIndicesMod use FatesInterfaceTypesMod, only : nlevage use FatesInterfaceTypesMod, only : nlevheight use FatesInterfaceTypesMod, only : nlevcoage - use FatesInterfaceTypesMod, only : ncrowndamage + use FatesInterfaceTypesMod, only : nlevdamage use EDParamsMod, only : ED_val_history_sizeclass_bin_edges use EDParamsMod, only : ED_val_history_ageclass_bin_edges use EDParamsMod, only : ED_val_history_height_bin_edges use EDParamsMod, only : ED_val_history_coageclass_bin_edges + use EDParamsMod, only : ED_val_history_damage_bin_edges + implicit none private ! Modules are private by default @@ -191,7 +193,7 @@ function get_cdamagesizepft_class_index(dbh,cdamage,pft) result(cdamage_by_size_ size_class = get_size_class_index(dbh) cdamage_by_size_by_pft_class = (cdamage-1)*nlevsclass + size_class + & - (pft-1) * nlevsclass * ncrowndamage + (pft-1) * nlevsclass * nlevdamage end function get_cdamagesizepft_class_index diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 83ecec6ad7..4df45c465d 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -5,7 +5,8 @@ dimensions: fates_history_height_bins = 6 ; fates_history_size_bins = 13 ; fates_history_coage_bins = 2 ; - fates_hydr_organs = 4 ; + fates_history_damage_bins = 6 ; + fates_hydr_organs = 4 ; fates_leafage_class = 1 ; fates_litterclass = 6 ; fates_pft = 12 ; @@ -25,6 +26,9 @@ variables: double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; fates_history_sizeclass_bin_edges:units = "cm" ; fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; + double fates_history_damage_bin_edges(fates_history_damage_bins) ; + fates_history_damage_bin_edges:units = "% crown loss" ; + fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; double fates_hydr_htftype_node(fates_hydr_organs) ; fates_hydr_htftype_node:units = "unitless" ; fates_hydr_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; @@ -165,9 +169,6 @@ variables: double fates_damage_recovery_scalar(fates_pft) ; fates_damage_recovery_scalar:units = "unitless"; fates_damage_recovery_scalar:long_name = "fraction of cohort that recovers from damage"; - double fates_ncrowndamage ; - fates_ncrowndamage: units = "unitless" ; - fates_ncrowndamage: long_name = "number of crown damage classes" ; double fates_c2b(fates_pft) ; fates_c2b:units = "ratio" ; fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; @@ -779,6 +780,8 @@ data: fates_history_coageclass_bin_edges = 0, 5 ; + fates_history_damage_bin_edges = 0, 20, 40, 60, 80 100 ; + fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, @@ -922,8 +925,6 @@ data: fates_damage_recovery_scalar = 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ; - fates_ncrowndamage = 5 ; - fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; From 78b4f1a69a7af058dce558159c98f399cdc59210 Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Wed, 23 Mar 2022 12:38:54 -0700 Subject: [PATCH 151/852] [ Fixing flexible damage bins ] [ Ensure damage bin edges are properly output in fates history ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary: no testing --- main/FatesHistoryInterfaceMod.F90 | 47 ++++++++++++++++++++++++++----- main/FatesInterfaceMod.F90 | 4 ++- main/FatesInterfaceTypesMod.F90 | 2 +- 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 2a29f2d9d0..0ce2ee34c9 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -697,7 +697,7 @@ Module FatesHistoryInterfaceMod integer, private :: levscls_index_, levpft_index_, levage_index_ integer, private :: levfuel_index_, levcwdsc_index_, levscag_index_ integer, private :: levcan_index_, levcnlf_index_, levcnlfpft_index_ - integer, private :: levcdpf_index_, levcdsc_index_ + integer, private :: levcdpf_index_, levcdsc_index_, levcdam_index_ integer, private :: levscagpft_index_, levagepft_index_ integer, private :: levheight_index_, levagefuel_index_ integer, private :: levelem_index_, levelpft_index_ @@ -734,6 +734,7 @@ Module FatesHistoryInterfaceMod procedure :: levcnlfpft_index procedure :: levcdpf_index procedure :: levcdsc_index + procedure :: levcdam_index procedure :: levscag_index procedure :: levscagpft_index procedure :: levagepft_index @@ -764,6 +765,7 @@ Module FatesHistoryInterfaceMod procedure, private :: set_levcnlfpft_index procedure, private :: set_levcdpf_index procedure, private :: set_levcdsc_index + procedure, private :: set_levcdam_index procedure, private :: set_levscag_index procedure, private :: set_levscagpft_index procedure, private :: set_levagepft_index @@ -801,7 +803,7 @@ subroutine Init(this, num_threads, fates_bounds) use FatesIODimensionsMod, only : levfuel, levcwdsc, levscag use FatesIODimensionsMod, only : levscagpft, levagepft use FatesIODimensionsMod, only : levcan, levcnlf, levcnlfpft - use FatesIODimensionsMod, only : levcdpf, levcdsc + use FatesIODimensionsMod, only : levcdpf, levcdsc, levcdam use FatesIODimensionsMod, only : fates_bounds_type use FatesIODimensionsMod, only : levheight, levagefuel use FatesIODimensionsMod, only : levelem, levelpft @@ -890,6 +892,11 @@ subroutine Init(this, num_threads, fates_bounds) call this%dim_bounds(dim_count)%Init(levcdsc, num_threads, & fates_bounds%cdsc_begin, fates_bounds%cdsc_end) + dim_count = dim_count + 1 + call this%set_levcdam_index(dim_count) + call this%dim_bounds(dim_count)%Init(levcdam, num_threads, & + fates_bounds%cdam_begin, fates_bounds%cdam_end) + dim_count = dim_count + 1 call this%set_levscag_index(dim_count) call this%dim_bounds(dim_count)%Init(levscag, num_threads, & @@ -1011,6 +1018,10 @@ subroutine SetThreadBoundsEach(this, thread_index, thread_bounds) call this%dim_bounds(index)%SetThreadBounds(thread_index, & thread_bounds%cdsc_begin, thread_bounds%cdsc_end) + index = this%levcdam_index() + call this%dim_bounds(index)%SetThreadBounds(thread_index, & + thread_bounds%cdam_begin, thread_bounds%cdam_end) + index = this%levscag_index() call this%dim_bounds(index)%SetThreadBounds(thread_index, & thread_bounds%sizeage_class_begin, thread_bounds%sizeage_class_end) @@ -1062,7 +1073,7 @@ subroutine assemble_history_output_types(this) use FatesIOVariableKindMod, only : site_fuel_r8, site_cwdsc_r8, site_scag_r8 use FatesIOVariableKindMod, only : site_scagpft_r8, site_agepft_r8 use FatesIOVariableKindMod, only : site_can_r8, site_cnlf_r8, site_cnlfpft_r8 - use FatesIOVariableKindMod, only : site_cdpf_r8, site_cdsc_r8 + use FatesIOVariableKindMod, only : site_cdpf_r8, site_cdsc_r8, site_cdam_r8 use FatesIOVariableKindMod, only : site_height_r8, site_agefuel_r8 use FatesIOVariableKindMod, only : site_elem_r8, site_elpft_r8 use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8 @@ -1116,7 +1127,10 @@ subroutine assemble_history_output_types(this) call this%set_dim_indices(site_cdsc_r8, 1, this%column_index()) call this%set_dim_indices(site_cdsc_r8, 2, this%levcdsc_index()) - + + call this%set_dim_indices(site_cdam_r8, 1, this%column_index()) + call this%set_dim_indices(site_cdam_r8, 2, this%levcdam_index()) + call this%set_dim_indices(site_scag_r8, 1, this%column_index()) call this%set_dim_indices(site_scag_r8, 2, this%levscag_index()) @@ -1398,6 +1412,20 @@ integer function levcdsc_index(this) levcdsc_index = this%levcdsc_index_ end function levcdsc_index + ! ======================================================================= + subroutine set_levcdam_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levcdam_index_ = index + end subroutine set_levcdam_index + + integer function levcdam_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levcdam_index = this%levcdam_index_ + end function levcdam_index + ! ====================================================================================== subroutine set_levscag_index(this, index) implicit none @@ -1665,7 +1693,7 @@ subroutine init_dim_kinds_maps(this) use FatesIOVariableKindMod, only : site_fuel_r8, site_cwdsc_r8, site_scag_r8 use FatesIOVariableKindMod, only : site_scagpft_r8, site_agepft_r8 use FatesIOVariableKindMod, only : site_can_r8, site_cnlf_r8, site_cnlfpft_r8 - use FatesIOVariableKindMod, only : site_cdpf_r8, site_cdsc_r8 + use FatesIOVariableKindMod, only : site_cdpf_r8, site_cdsc_r8, site_cdam_r8 use FatesIOVariableKindMod, only : site_height_r8, site_agefuel_r8 use FatesIOVariableKindMod, only : site_elem_r8, site_elpft_r8 use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8 @@ -1738,6 +1766,10 @@ subroutine init_dim_kinds_maps(this) index = index + 1 call this%dim_kinds(index)%Init(site_cdsc_r8, 2) + ! site x crown damage + index = index + 1 + call this%dim_kinds(index)%Init(site_cdam_r8, 2) + ! site x size-class x age class index = index + 1 call this%dim_kinds(index)%Init(site_scag_r8, 2) @@ -4626,7 +4658,7 @@ subroutine define_history_vars(this, initialize_variables) use FatesIOVariableKindMod, only : site_fuel_r8, site_cwdsc_r8, site_scag_r8 use FatesIOVariableKindMod, only : site_can_r8, site_cnlf_r8, site_cnlfpft_r8 - use FatesIOVariableKindMod, only : site_cdsc_r8, site_cdpf_r8 + use FatesIOVariableKindMod, only : site_cdsc_r8, site_cdpf_r8, site_cdam_r8 use FatesIOVariableKindMod, only : site_scagpft_r8, site_agepft_r8 use FatesIOVariableKindMod, only : site_elem_r8, site_elpft_r8 use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8 @@ -4656,6 +4688,7 @@ subroutine define_history_vars(this, initialize_variables) ! plant functional type (site_pft_r8) : PF ! soil layer (site_soil_r8) : SL ! cohort size (site_size_r8) : SZ + ! cohort crown damage (site_cd_r8) : CD ! Multiple dimensions should have multiple two-code suffixes: ! cohort age x pft (site_cooage_r8) : ACPF @@ -4669,7 +4702,7 @@ subroutine define_history_vars(this, initialize_variables) ! cohort size x pft (site_size_pft_r8) : SZPF ! cohort size x crown damage (site_cdsc_r8) : SZCD ! cohort size x crown damage x pft (site_cdpf_r8) : CDPF - + ! Site level counting variables call this%set_history_var(vname='FATES_NPATCHES', units='', & diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index b929af26c3..1f103b1033 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1026,7 +1026,7 @@ subroutine fates_history_maps allocate( fates_hdim_pfmap_levcapf(1:nlevcoage*numpft)) allocate( fates_hdim_camap_levcapf(1:nlevcoage*numpft)) - allocate( fates_hdim_levcdam(1:nlevdamage )) + allocate( fates_hdim_levdamage(1:nlevdamage )) allocate( fates_hdim_scmap_levcdsc(nlevsclass*nlevdamage)) allocate( fates_hdim_cdmap_levcdsc(nlevsclass*nlevdamage)) allocate( fates_hdim_scmap_levcdpf(nlevsclass*nlevdamage * numpft)) @@ -1064,8 +1064,10 @@ subroutine fates_history_maps fates_hdim_levage(:) = ED_val_history_ageclass_bin_edges(:) fates_hdim_levheight(:) = ED_val_history_height_bin_edges(:) fates_hdim_levcoage(:) = ED_val_history_coageclass_bin_edges(:) + fates_hdim_levdamage(:) = ED_val_history_damage_bin_edges(:) fates_hdim_levleaf(:) = dlower_vai(:) + ! make pft array do ipft=1,numpft fates_hdim_levpft(ipft) = ipft diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index b6826d2ce5..26d36f62fa 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -244,7 +244,7 @@ module FatesInterfaceTypesMod integer , public, allocatable :: fates_hdim_scmap_levcdpf(:) ! map of size into size x crowndamage x pft integer , public, allocatable :: fates_hdim_cdmap_levcdsc(:) ! map of crowndamage into size x crowndamage integer , public, allocatable :: fates_hdim_scmap_levcdsc(:) ! map of size into size x crowndamage - integer , public, allocatable :: fates_hdim_levcdam(:) ! plant damage class lower bound dimension + integer , public, allocatable :: fates_hdim_levdamage(:) ! plant damage class lower bound dimension real(r8), public, allocatable :: fates_hdim_levage(:) ! patch age lower bound dimension real(r8), public, allocatable :: fates_hdim_levheight(:) ! height lower bound dimension From 5427615235a1657c062365116f2b9c300167ffeb Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 29 Mar 2022 21:44:12 -0700 Subject: [PATCH 152/852] Correcting missed conflicts Missed a conflict with the parameter file. Also need to remove the recent addition of harvest_carbon_flux initialization. --- main/EDInitMod.F90 | 1 - parameter_files/fates_params_default.cdl | 4 ---- 2 files changed, 5 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 06bcd1858a..7463a2a8a4 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -203,7 +203,6 @@ subroutine zero_site( site_in ) ! Disturbance rates tracking site_in%primary_land_patchfusion_error = 0.0_r8 - site_in%harvest_carbon_flux = 0.0_r8 site_in%potential_disturbance_rates(:) = 0.0_r8 site_in%disturbance_rates_secondary_to_secondary(:) = 0.0_r8 site_in%disturbance_rates_primary_to_secondary(:) = 0.0_r8 diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index e4ae8bb9fc..c69b2b8df8 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1446,14 +1446,10 @@ data: fates_logging_mechanical_frac = 0.05 ; -<<<<<<< HEAD fates_pprodharv10_forest_mean = 0.8125 ; -||||||| 36e60bb3 -======= fates_maintresp_model = 1 ; ->>>>>>> master fates_mort_disturb_frac = 1 ; fates_mort_understorey_death = 0.55983 ; From 1e34c399f25c76408809147f3821bcc8184b7e61 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 1 Apr 2022 11:37:12 -0400 Subject: [PATCH 153/852] Various updates to l2fr search algorithm --- biogeochem/EDCohortDynamicsMod.F90 | 9 +- biogeochem/FatesSoilBGCFluxMod.F90 | 8 +- main/EDMainMod.F90 | 2 +- main/FatesHistoryInterfaceMod.F90 | 12 +- parteh/PRTAllometricCNPMod.F90 | 442 +++++++++++++++++++++-------- 5 files changed, 333 insertions(+), 140 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 7c3fe61322..c6dc4fea72 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -97,7 +97,7 @@ module EDCohortDynamicsMod !use PRTAllometricCNPMod, only : acnp_bc_in_id_l2fr_ema use PRTAllometricCNPMod, only : acnp_bc_inout_id_l2fr use PRTAllometricCNPMod, only : acnp_bc_inout_id_resp_excess, acnp_bc_in_id_netdc - use PRTAllometricCNPMod, only : acnp_bc_in_id_netdn, acnp_bc_in_id_netdp + use PRTAllometricCNPMod, only : acnp_bc_inout_id_netdn, acnp_bc_inout_id_netdp use PRTAllometricCNPMod, only : acnp_bc_out_id_cefflux, acnp_bc_out_id_nefflux use PRTAllometricCNPMod, only : acnp_bc_out_id_pefflux use PRTAllometricCNPMod, only : fnrt_adapt_tscl @@ -428,14 +428,15 @@ subroutine InitPRTBoundaryConditions(new_cohort) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_ctrim,bc_rval = new_cohort%canopy_trim) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_lstat,bc_ival = new_cohort%status_coh) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdc, bc_rval = new_cohort%npp_acc) - call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdn, bc_rval = new_cohort%daily_n_gain) - call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdp, bc_rval = new_cohort%daily_p_uptake) + !!call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_l2fr_ema, bc_rval = new_cohort%l2fr_ema%l_mean) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_dbh,bc_rval = new_cohort%dbh) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_resp_excess,bc_rval = new_cohort%resp_excess) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_l2fr,bc_rval = new_cohort%l2fr) - + call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_netdn, bc_rval = new_cohort%daily_n_gain) + call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_netdp, bc_rval = new_cohort%daily_p_uptake) + call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_cefflux, bc_rval = new_cohort%daily_c_efflux) call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_nefflux, bc_rval = new_cohort%daily_n_efflux) call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_pefflux, bc_rval = new_cohort%daily_p_efflux) diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index 3556013556..00dd0202cd 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -225,8 +225,8 @@ subroutine UnPackNutrientAquisitionBCs(sites, bc_in) ccohort => cpatch%tallest do while (associated(ccohort)) pft = ccohort%pft - ccohort%daily_n_demand = GetPlantDemand(ccohort,nitrogen_element) - ccohort%daily_nh4_uptake = EDPftvarcon_inst%prescribed_nuptake(pft) * ccohort%daily_n_demand + !ccohort%daily_n_demand = GetPlantDemand(ccohort,nitrogen_element) + ccohort%daily_nh4_uptake = -9._r8 !EDPftvarcon_inst%prescribed_nuptake(pft) * ccohort%daily_n_demand ccohort%daily_no3_uptake = 0._r8 ccohort => ccohort%shorter end do @@ -258,8 +258,8 @@ subroutine UnPackNutrientAquisitionBCs(sites, bc_in) ccohort => cpatch%tallest do while (associated(ccohort)) pft = ccohort%pft - ccohort%daily_p_demand = GetPlantDemand(ccohort,phosphorus_element) - ccohort%daily_p_uptake = EDPftvarcon_inst%prescribed_puptake(pft) * ccohort%daily_p_demand + !ccohort%daily_p_demand = GetPlantDemand(ccohort,phosphorus_element) + ccohort%daily_p_uptake = -9._r8 !EDPftvarcon_inst%prescribed_puptake(pft) * ccohort%daily_p_demand ccohort => ccohort%shorter end do cpatch => cpatch%younger diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 28fefe9da2..d866ca0c2e 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -452,7 +452,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentCohort%resp_excess = 0._r8 call currentCohort%prt%DailyPRT() - + ! Send any efflux/exudates to the labile litter pools in the HLM ! ----------------------------------------------------------------------------- diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 48d0efb3c1..4acf85bddb 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -81,7 +81,7 @@ module FatesHistoryInterfaceMod use PRTGenericMod , only : carbon12_element use PRTGenericMod , only : nitrogen_element, phosphorus_element use PRTGenericMod , only : prt_carbon_allom_hyp - use PRTAllometricCNPMod , only : stoich_max + use PRTAllometricCNPMod , only : stoich_max,stoich_growth_min,stoich_center implicit none private ! By default everything is private @@ -2550,7 +2550,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) fnrtc_understory_scpf(i_scpf) = fnrtc_understory_scpf(i_scpf) + ccohort%n*fnrt_m end if - call bstore_allom(ccohort%dbh,ccohort%pft,ccohort%canopy_trim, store_max) + call bstore_allom(ccohort%dbh,ccohort%pft,ccohort%canopy_trim, store_growth_min) this%hvars(ih_storectfrac_si)%r81d(io_si) = & this%hvars(ih_storectfrac_si)%r81d(io_si) + ccohort%n * store_max/m2_per_ha @@ -2595,7 +2595,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) elseif(element_list(el).eq.nitrogen_element)then - store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_max) + store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_center) this%hvars(ih_storen_si)%r81d(io_si) = & this%hvars(ih_storen_si)%r81d(io_si) + ccohort%n * & @@ -2635,7 +2635,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) elseif(element_list(el).eq.phosphorus_element) then - store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_max) + store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_center) this%hvars(ih_storep_si)%r81d(io_si) = & this%hvars(ih_storep_si)%r81d(io_si) + ccohort%n * & @@ -3534,7 +3534,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) repro_m * ccohort%n / m2_per_ha elseif(element_list(el).eq.nitrogen_element)then - store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_max) + store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_center) this%hvars(ih_totvegn_scpf)%r82d(io_si,i_scpf) = & this%hvars(ih_totvegn_scpf)%r82d(io_si,i_scpf) + & @@ -3557,7 +3557,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) elseif(element_list(el).eq.phosphorus_element)then - store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_max) + store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_center) this%hvars(ih_totvegp_scpf)%r82d(io_si,i_scpf) = & this%hvars(ih_totvegp_scpf)%r82d(io_si,i_scpf) + & diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 2392f42f46..67cf24ca65 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -57,6 +57,10 @@ module PRTAllometricCNPMod use FatesConstantsMod , only : sec_per_day use PRTParametersMod , only : prt_params use EDTypesMod , only : leaves_on,leaves_off + use EDTypesMod , only : p_uptake_mode + use EDTypesMod , only : n_uptake_mode + use FatesConstantsMod , only : prescribed_p_uptake + use FatesConstantsMod , only : prescribed_n_uptake implicit none private @@ -100,7 +104,8 @@ module PRTAllometricCNPMod ! minimum needed for growth integer,public, parameter :: stoich_max = 2 ! Flag for stoichiometry associated with ! maximum for that organ - + integer,public, parameter :: stoich_center=3 + ! This is the ordered list of organs used in this module ! ------------------------------------------------------------------------------------- @@ -141,7 +146,10 @@ module PRTAllometricCNPMod integer, public, parameter :: acnp_bc_inout_id_resp_excess = 2 ! Respiration of excess storage integer, public, parameter :: acnp_bc_inout_id_l2fr = 3 ! leaf 2 fineroot scalar, this ! is dynamic with CNP - integer, public, parameter :: num_bc_inout = 3 + integer, public, parameter :: acnp_bc_inout_id_netdn = 4 ! Index for the net daily NH4 input BC + integer, public, parameter :: acnp_bc_inout_id_netdp = 5 ! Index for the net daily P input BC + + integer, public, parameter :: num_bc_inout = 5 ! ------------------------------------------------------------------------------------- ! Input only Boundary Indices (These are public) @@ -151,11 +159,10 @@ module PRTAllometricCNPMod integer, public, parameter :: acnp_bc_in_id_ctrim = 2 ! Index for the canopy trim function integer, public, parameter :: acnp_bc_in_id_lstat = 3 ! phenology status logical integer, public, parameter :: acnp_bc_in_id_netdc = 4 ! Index for the net daily C input BC - integer, public, parameter :: acnp_bc_in_id_netdn = 5 ! Index for the net daily NH4 input BC - integer, public, parameter :: acnp_bc_in_id_netdp = 6 ! Index for the net daily P input BC + ! 0=leaf off, 1=leaf on - integer, parameter :: num_bc_in = 6 + integer, parameter :: num_bc_in = 4 ! ------------------------------------------------------------------------------------- ! Output Boundary Indices (These are public) @@ -190,7 +197,7 @@ module PRTAllometricCNPMod integer, parameter :: store_c_overflow = burn_c_store_overflow ! Following growth, if desired, you can prioritize reproductive - logical, parameter :: prioritize_repro_nutr_growth = .false. + logical, parameter :: prioritize_repro_nutr_growth = .true. ! Definitions for the regulation functions. These typically translate ! a storage fraction into a scalar used to regulate resources somehow @@ -223,6 +230,7 @@ module PRTAllometricCNPMod ! Extended functions specific to Allometric CNP procedure :: CNPPrioritizedReplacement procedure :: CNPStatureGrowth + procedure :: EstimateGrowthNC procedure :: CNPAdjustFRootTargets procedure :: CNPAllocateRemainder procedure :: GetDeficit @@ -339,8 +347,8 @@ subroutine DailyPRTAllometricCNP(this) ! Input only bcs integer :: ipft ! Plant Functional Type index real(r8) :: c_gain ! Daily carbon balance for this cohort [kgC] - real(r8) :: n_gain ! Daily nitrogen uptake through fine-roots [kgN] - real(r8) :: p_gain ! Daily phosphorus uptake through fine-roots [kgN] + real(r8),pointer :: n_gain ! Daily nitrogen uptake through fine-roots [kgN] + real(r8),pointer :: p_gain ! Daily phosphorus uptake through fine-roots [kgN] real(r8) :: canopy_trim ! The canopy trimming function [0-1] ! Pointers to output bcs @@ -356,7 +364,7 @@ subroutine DailyPRTAllometricCNP(this) real(r8) :: agw_c_target,agw_dcdd_target real(r8) :: bgw_c_target,bgw_dcdd_target real(r8) :: sapw_area - + real(r8) :: store_c_flux integer :: i ! generic organ loop index integer :: i_org ! organ index integer :: i_var ! variable index @@ -393,7 +401,9 @@ subroutine DailyPRTAllometricCNP(this) resp_excess => this%bc_inout(acnp_bc_inout_id_resp_excess)%rval; resp_excess0 = resp_excess dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval; dbh0 = dbh l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval - + n_gain => this%bc_inout(acnp_bc_inout_id_netdn)%rval; + p_gain => this%bc_inout(acnp_bc_inout_id_netdp)%rval; + ! integrator variables ! Copy the input only boundary conditions into readable local variables @@ -402,10 +412,23 @@ subroutine DailyPRTAllometricCNP(this) ! for checking and resetting if needed ! ----------------------------------------------------------------------------------- c_gain = this%bc_in(acnp_bc_in_id_netdc)%rval; c_gain0 = c_gain - n_gain = this%bc_in(acnp_bc_in_id_netdn)%rval; n_gain0 = n_gain - p_gain = this%bc_in(acnp_bc_in_id_netdp)%rval; p_gain0 = p_gain + canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival + + ! If either n or p uptake is in prescribed mode + ! set the gains to something massive. 1 kilo of pure + ! nutrient should be wayyy more than enough + if(n_uptake_mode.eq.prescribed_n_uptake) then + n_gain = 1.e3 + end if + if(p_uptake_mode.eq.prescribed_p_uptake) then + p_gain = 1.e3 + end if + + n_gain0 = n_gain + p_gain0 = p_gain + ! Calculate Carbon allocation targets ! ----------------------------------------------------------------------------------- @@ -424,35 +447,10 @@ subroutine DailyPRTAllometricCNP(this) target_c(repro_organ) = 0._r8 target_dcdd(repro_organ) = 0._r8 - - ! =================================================================================== - ! Step 1: Evaluate nutrient storage in the plant. Depending on how low - ! these stores are, we will move proportionally more or less of the daily carbon - ! gain to increase the target fine-root biomass, fill up to target - ! and then attempt to get them up to stoichiometry targets. - ! =================================================================================== - - ! This routine updates the l2fr (leaf 2 fine-root multiplier) variable - call this%CNPAdjustFRootTargets(target_c) - - c_gain0 = c_gain n_gain0 = n_gain p_gain0 = p_gain - - - ! Output only boundary conditions - c_efflux => this%bc_out(acnp_bc_out_id_cefflux)%rval; c_efflux = 0._r8 - n_efflux => this%bc_out(acnp_bc_out_id_nefflux)%rval; n_efflux = 0._r8 - p_efflux => this%bc_out(acnp_bc_out_id_pefflux)%rval; p_efflux = 0._r8 - - - - - - - ! Remember the original C,N,P states to help with final ! evaluation of how much was allocated ! ----------------------------------------------------------------------------------- @@ -466,19 +464,38 @@ subroutine DailyPRTAllometricCNP(this) i_var = prt_global%sp_organ_map(i_org,phosphorus_element) state_p0(i_org) = this%variables(i_var)%val(1) end do + + ! =================================================================================== + ! Step 1: Evaluate nutrient storage in the plant. Depending on how low + ! these stores are, we will move proportionally more or less of the daily carbon + ! gain to increase the target fine-root biomass, fill up to target + ! and then attempt to get them up to stoichiometry targets. + ! =================================================================================== + ! This routine updates the l2fr (leaf 2 fine-root multiplier) variable + call this%CNPAdjustFRootTargets(target_c) + + ! Output only boundary conditions + c_efflux => this%bc_out(acnp_bc_out_id_cefflux)%rval; c_efflux = 0._r8 + n_efflux => this%bc_out(acnp_bc_out_id_nefflux)%rval; n_efflux = 0._r8 + p_efflux => this%bc_out(acnp_bc_out_id_pefflux)%rval; p_efflux = 0._r8 ! =================================================================================== - ! Step 0. Transfer all stored nutrient into the daily uptake pool. + ! Step 0. Transfer all stored nutrient into the daily uptake pool. Also + ! transfer C storage that is above the target (ie transfer overflow) ! =================================================================================== + + ! Put overflow storage into the net daily pool + store_c_flux = max(0._r8, this%variables(store_c_id)%val(1) - target_c(store_organ)) + + c_gain = c_gain + store_c_flux + this%variables(store_c_id)%val(1) = this%variables(store_c_id)%val(1) - store_c_flux - i_var = prt_global%sp_organ_map(store_organ,nitrogen_element) - n_gain = n_gain + sum(this%variables(i_var)%val(:)) - this%variables(i_var)%val(:) = 0._r8 + n_gain = n_gain + sum(this%variables(store_n_id)%val(:)) + this%variables(store_n_id)%val(:) = 0._r8 - i_var = prt_global%sp_organ_map(store_organ,phosphorus_element) - p_gain = p_gain + sum(this%variables(i_var)%val(:)) - this%variables(i_var)%val(:) = 0._r8 + p_gain = p_gain + sum(this%variables(store_p_id)%val(:)) + this%variables(store_p_id)%val(:) = 0._r8 ! =================================================================================== ! Step 2. Prioritized allocation to replace tissues from turnover, and/or pay @@ -537,20 +554,32 @@ subroutine DailyPRTAllometricCNP(this) call this%CNPAllocateRemainder(c_gain, n_gain, p_gain, & c_efflux, n_efflux, p_efflux) + + if(n_uptake_mode.ne.prescribed_n_uptake) then + if( abs(n_gain) > 0.1_r8*calloc_abs_error) then + write(fates_log(),*) 'Allocation scheme should had used up all mass gain pools' + write(fates_log(),*) 'Any mass that cannot be allocated should be effluxed' + write(fates_log(),*) 'n_gain: ',n_gain + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + end if + + if(p_uptake_mode.ne.prescribed_p_uptake) then + if( abs(p_gain) > 0.01_r8*calloc_abs_error) then + write(fates_log(),*) 'Allocation scheme should had used up all mass gain pools' + write(fates_log(),*) 'Any mass that cannot be allocated should be effluxed' + write(fates_log(),*) 'p_gain: ',p_gain + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + end if - ! Error Check: Make sure that the mass gains are completely used up - if( abs(c_gain) > calloc_abs_error .or. & - abs(n_gain) > 0.1_r8*calloc_abs_error .or. & - abs(p_gain) > 0.02_r8*calloc_abs_error ) then + if( abs(c_gain) > calloc_abs_error) then write(fates_log(),*) 'Allocation scheme should had used up all mass gain pools' write(fates_log(),*) 'Any mass that cannot be allocated should be effluxed' write(fates_log(),*) 'c_gain: ',c_gain - write(fates_log(),*) 'n_gain: ',n_gain - write(fates_log(),*) 'p_gain: ',p_gain call endrun(msg=errMsg(sourcefile, __LINE__)) end if - ! Perform a final tally on what was used (allocated) ! Since this is also a check against what was available ! we include what is lost through respiration of excess storage @@ -589,9 +618,9 @@ subroutine DailyPRTAllometricCNP(this) ! Error Check: Do a final balance between how much mass ! we had to work with, and how much was allocated - if ( abs(allocated_c - c_gain0) > calloc_abs_error .or. & - abs(allocated_n - n_gain0) > calloc_abs_error .or. & - abs(allocated_p - p_gain0) > calloc_abs_error ) then + if ( abs(allocated_c - (c_gain0-c_gain)) > calloc_abs_error .or. & + abs(allocated_n - (n_gain0-n_gain)) > calloc_abs_error .or. & + abs(allocated_p - (p_gain0-p_gain)) > calloc_abs_error ) then write(fates_log(),*) 'CNP allocation scheme did not balance mass.' write(fates_log(),*) 'c_gain0: ',c_gain0,' allocated_c: ',allocated_c write(fates_log(),*) 'n_gain0: ',n_gain0,' allocated_n: ',allocated_n @@ -605,6 +634,24 @@ subroutine DailyPRTAllometricCNP(this) call endrun(msg=errMsg(sourcefile, __LINE__)) end if end if + + ! IF this was prescribed, then we dictate the uptake + ! and pass that back as an output, otherwise + ! we set the gains to what we started with so that + ! it can be used again for mass balance checking and diagnostics + + if(n_uptake_mode.eq.prescribed_n_uptake) then + n_gain = n_gain0-n_gain + else + n_gain = n_gain0 + end if + if(p_uptake_mode.eq.prescribed_p_uptake) then + p_gain = p_gain0-p_gain + else + p_gain = p_gain0 + end if + + return end subroutine DailyPRTAllometricCNP @@ -644,14 +691,31 @@ subroutine CNPAdjustFRootTargets(this, target_c) associate( l2fr_min => prt_params%allom_l2fr_min(ipft), & l2fr_max => prt_params%allom_l2fr_max(ipft)) - call this%StorageRegulator(nitrogen_element, regulate_type,target_c,n_regulator) - call this%StorageRegulator(phosphorus_element, regulate_type,target_c,p_regulator) + if(n_uptake_mode.eq.prescribed_n_uptake)then + n_regulator = 1._r8 + else + call this%StorageRegulator(nitrogen_element, regulate_type,target_c,n_regulator) + end if + if(p_uptake_mode.eq.prescribed_p_uptake)then + p_regulator = 1._r8 + else + call this%StorageRegulator(phosphorus_element, regulate_type,target_c,p_regulator) + end if + ! We take the maximum here, because the maximum is reflective of the ! element with the lowest storage, which is the limiting element + if(n_uptake_mode.eq.prescribed_n_uptake)then + np_regulator = p_regulator + else + if(p_uptake_mode.eq.prescribed_p_uptake)then + np_regulator = n_regulator + else + np_regulator = max(n_regulator,p_regulator) + end if + end if + - np_regulator = max(n_regulator,p_regulator) - ! Update the leaf-to-fineroot ratio used ! to set fine-root biomass allometry @@ -661,10 +725,6 @@ subroutine CNPAdjustFRootTargets(this, target_c) elseif(regulate_type == regulate_CN_dfdd) then - ! To prevent the target l2fr from diverging too far from the - ! actual l2fr, create some constraints. - l2fr_actual = this%GetState(fnrt_organ, carbon12_element)/this%GetState(leaf_organ, carbon12_element) - ! Only update L2FR if some leaves are out if(this%GetState(leaf_organ, carbon12_element)/target_c(leaf_organ) >0.5_r8) then l2fr = l2fr * np_regulator @@ -675,15 +735,16 @@ subroutine CNPAdjustFRootTargets(this, target_c) ! Find the updated target fineroot biomass call bfineroot(dbh,ipft,canopy_trim, l2fr, target_c(fnrt_organ)) - fnrt_c_above_target = max(0._r8,this%GetState(fnrt_organ, carbon12_element) - target_c(fnrt_organ)) - ! Allow no reabsorption? (any reabsorption of nutrients will further push the N/C or P/C imbalance - ! and if we are dropping roots, its because we had excess nutrient compared to carbon anyway - ! Stop the positive feedback + ! The following section allows forceful turnover of fine-roots if a new L2FR is generated + ! that is lower than the previous l2fr. The maintenance turnover (background) rate + ! will automatically accomodate a lower l2fr, but if the change is large it will + ! not keep pace. Note 1: however, that the algorithm in StorageRegulator() will prevent + ! large drops in l2fr (unless that safegaurd is removed). Note 2: this section may also + ! generate mass check errors in the main CNPAllocation routine, this is because the "val" is + ! changing but the net_allocated is not reciprocating, which is expected. - ! Since this is really a stop gap, we want to allow allocation to handle most of the - ! fine-root adaption, and only have this kick in when the target starts to drift significantly - ! from the actual + fnrt_c_above_target = max(0._r8,this%GetState(fnrt_organ, carbon12_element) - target_c(fnrt_organ)) loss_flux_c = 0._r8 @@ -1083,6 +1144,8 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & real(r8) :: cdeficit ! carbon deficit from target integer :: ierr ! error flag for allometric growth step integer :: nsteps ! number of sub-steps + real(r8) :: avg_nc,avg_pc ! Estimated average N/C and P/C ratios of + ! allocated carbon during stature growth real(r8) :: repro_c_frac ! Fraction of C allocated to reproduction ! at current stature (dbh) [/] real(r8) :: sum_c_flux ! Sum of the carbon allocated, as reported @@ -1138,11 +1201,12 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & real(r8) :: intgr_params(num_intgr_parm) - integer, parameter :: grow_lim_type = 3 ! Dev flag for growth limitation algorithm - ! 1 = tries to calculate equivalent carbon - ! 2 = modification of 1 - ! 3 = don't limit, and assume nutrient limitations will prevent calling - ! of this step on the next cycle if they exist + integer, parameter :: grow_lim_conly = 1 ! Just use C to decide stature on this step + integer, parameter :: grow_lim_estNP = 2 ! Estimate equivalent C from N and P + + integer, parameter :: grow_lim_type = grow_lim_estNP + + integer, parameter :: c_limited = 1 integer, parameter :: n_limited = 2 @@ -1170,6 +1234,9 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & p_gain <= 0.02_r8*calloc_abs_error ) then return end if + + + intgr_params(:) = fates_unset_r8 @@ -1279,13 +1346,25 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & i_org = mask_gorgans(ii) total_dcostdd = total_dcostdd + target_dcdd(i_org) end do - - ! No mathematical co-limitation of growth - ! This assumes that limitations will prevent - ! organs from allowing the growth step to even occur - ! and thus from an algorithmic level limit growth - c_gstature = c_gain + ! We can either proceed with stature growth by using all of the carbon + ! available, or we can try to estimate the limitations of N and P + ! and thereby reduce the amount of C we are willing to use to try + ! and match what is available in n_gain and p_gain. Note that the + ! c-only option does allow limitations to eventually occur, because + ! it is assumed that in the dynamics call that follows this one, there may + ! or not be enough N or P to reach the stature growth step at all. + + if(grow_lim_type == grow_lim_conly) then + c_gstature = c_gain + elseif (grow_lim_type == grow_lim_estNP) then + + call EstimateGrowthNC(this,target_c,target_dcdd,state_mask,avg_nc,avg_pc) + + c_gstature = min(c_gain,n_gain/avg_nc) + c_gstature = min(c_gstature,p_gain/avg_pc) + + end if if_stature_growth: if(c_gstature > nearzero) then @@ -1632,14 +1711,29 @@ subroutine CNPAllocateRemainder(this, c_gain, n_gain, p_gain, & ! 1) excude through roots cap at 0 to flush out imprecisions ! ----------------------------------------------------------------------------------- - c_efflux = max(0.0_r8,c_gain) - n_efflux = max(0.0_r8,n_gain) - p_efflux = max(0.0_r8,p_gain) - + ! If either n or p uptake is in prescribed mode + ! don't efflux anything, we will use the remainder + ! n_gain and p_gain to specify the demand as what was used + ! and what was uptaken + + if(n_uptake_mode.eq.prescribed_n_uptake) then + n_efflux = 0._r8 + else + n_efflux = max(0.0_r8,n_gain) + n_gain = 0._r8 + end if + + if(p_uptake_mode.eq.prescribed_p_uptake) then + p_efflux = 0._r8 + else + p_efflux = max(0.0_r8,p_gain) + p_gain = 0._r8 + end if + c_efflux = max(0.0_r8,c_gain) c_gain = 0.0_r8 - n_gain = 0.0_r8 - p_gain = 0.0_r8 + + return end subroutine CNPAllocateRemainder @@ -1746,11 +1840,18 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe end if - ! Hard-code the growth minimum storage stoichiometry to 25% of maximum - if( stoich_mode == stoich_growth_min ) then - target_m = target_m*0.25_r8 + ! This is only called during phase 3, remainder and allows + ! us to have some overflow to avoid exudation/efflux if possible + if( stoich_mode == stoich_max ) then + target_m = target_m*(1._r8 + store_overflow_frac) end if - + !if( stoich_mode == stoich_growth_min ) then + ! target_m = 0.1_r8*target_m + !end if + !if( stoich_mode == stoich_center ) then + ! do nothing, target_m is unchanged + !end if + elseif(organ_id == repro_organ) then target_c = this%variables(i_cvar)%val(1) @@ -2132,15 +2233,11 @@ subroutine StorageRegulator(this,element_id,regulate_type,target_c,c_scalar) ! Locals real(r8) :: store_frac ! Current nutrient storage relative to max real(r8) :: store_max ! Maximum nutrient storable by plant + real(r8) :: store_c_max integer :: icode ! real variable checking code real(r8) :: store_x integer :: i_var - real(r8), parameter :: c_eq_offset = 1.0_r8 ! This shifts the center-point - ! of the N:C or P:C storage equlibrium - ! by multiplying the C term. If its less than 1 it - ! shifts left and great than one it shifts right. - ! It should shift left to help mitigate wasted N and P - ! storage overflow + ! For N/C logistic real(r8) :: logi_k ! logistic function k @@ -2156,10 +2253,9 @@ subroutine StorageRegulator(this,element_id,regulate_type,target_c,c_scalar) real(r8) :: nc_frac real(r8) :: store_c_frac real(r8) :: c_gain + real(r8) :: c_fnrt_expand ! predicted carbon available to expand fine-roots + ! after replacement of turnover - real(r8), parameter :: c_max = 1.0_r8 ! Maximum allowable result of the function - real(r8), parameter :: c_min = 0.0_r8 ! Minimum allowable result of the function - ! This fraction governs ! how much carbon from daily gains + storage overflow, is allowed to ! be spent on growing out roots. This inludes getting roots @@ -2167,10 +2263,15 @@ subroutine StorageRegulator(this,element_id,regulate_type,target_c,c_scalar) integer, parameter :: limit_all = 1 integer, parameter :: limit_lf = 2 - integer :: lim_l2fr_max_type = limit_all - real(r8), parameter :: max_l2fr_cgain_frac = 0.5_r8 + integer, parameter :: lim_l2fr_max_type = limit_all + real(r8), parameter :: max_l2fr_cgain_frac = 0.95_r8 - associate(dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval, & + real(r8), parameter :: nc_frac_offset = 1.0_r8 ! This shifts the center-point + ! of the N:C or P:C storage equlibrium + ! by multiplying the N term. + + + associate(dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval, & canopy_trim => this%bc_in(acnp_bc_in_id_ctrim)%rval, & ipft => this%bc_in(acnp_bc_in_id_pft)%ival, & l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval) @@ -2178,7 +2279,6 @@ subroutine StorageRegulator(this,element_id,regulate_type,target_c,c_scalar) logi_k = 2._r8 store_x0 = 0.0_r8 logi_min = 0.0_r8 - if(regulate_type == regulate_CN_logi) then @@ -2196,20 +2296,21 @@ subroutine StorageRegulator(this,element_id,regulate_type,target_c,c_scalar) elseif(regulate_type == regulate_CN_dfdd) then - store_max = this%GetNutrientTarget(element_id,store_organ,stoich_max) + store_max = this%GetNutrientTarget(element_id,store_organ,stoich_center) !*(1._r8 + 0.5*store_overflow_frac) ! Storage fractions could be more than the target, depending on the ! hypothesis and functions involved, but should typically be 0-1 ! The cap of 5 is for numerics and preventing weird math - store_frac = max(0.01_r8,min(5.0_r8,this%GetState(store_organ, element_id)/store_max)) ! Since we don't dump storage carbon ! these stores can actually get pretty large, so the cap of 10x is numerically ! feasable, and should also minimize stress on the logistic function - store_c_frac = max(0.01_r8,min(5.0_r8,c_eq_offset*(this%GetState(store_organ, carbon12_element)/target_c(store_organ) ))) + store_c_max = target_c(store_organ) !*(1._r8 + 0.5*store_overflow_frac) + + store_c_frac = max(0.01_r8,min(5.0_r8,this%GetState(store_organ, carbon12_element)/store_c_max )) ! ----------------------------------------------------------------------------- ! To decide the upper limit on expanding root growth, we perform a carbon @@ -2233,7 +2334,8 @@ subroutine StorageRegulator(this,element_id,regulate_type,target_c,c_scalar) ! or ! as much as you like as long as turnover is replaced ! - ! l2fr_delta_max*target_fnrt_c < c_gain - (target_fnrt_c-actual_fnrt_c) - + ! l2fr_delta_max*target_fnrt_c - target_fnrt_c < + ! c_gain - (target_fnrt_c-actual_fnrt_c) - ! (target_leaf_c-actual_leaf_c) - ! (target_sapw_c-actual_sapw_c) - ! (target_dead_c-actual_dead_c) - @@ -2241,27 +2343,31 @@ subroutine StorageRegulator(this,element_id,regulate_type,target_c,c_scalar) ! ! ------------------------------------------------------------------------------ - ! If there is overflow storage, add this to the gain - c_gain = this%bc_in(acnp_bc_in_id_netdc)%rval - fnrt_c = this%GetState(fnrt_organ, carbon12_element) leaf_c = this%GetState(leaf_organ, carbon12_element) store_c = this%GetState(store_organ, carbon12_element) struct_c = this%GetState(struct_organ, carbon12_element) sapw_c = this%GetState(sapw_organ, carbon12_element) + ! If there is overflow storage, add this to the gain + c_gain = this%bc_in(acnp_bc_in_id_netdc)%rval + max(0._r8,store_c-target_c(store_organ)) + + if(lim_l2fr_max_type == limit_lf)then l2fr_delta_max = max_l2fr_cgain_frac / target_c(fnrt_organ) * & (c_gain - max(0._r8,target_c(fnrt_organ)-fnrt_c) - max(0._r8,target_c(leaf_organ)-leaf_c)) elseif(lim_l2fr_max_type ==limit_all)then - l2fr_delta_max = 1._r8/target_c(fnrt_organ) * & - (c_gain - & + + c_fnrt_expand = max_l2fr_cgain_frac* ( c_gain - & max(0._r8,target_c(fnrt_organ)-fnrt_c) - & max(0._r8,target_c(leaf_organ)-leaf_c) - & max(0._r8,target_c(sapw_organ)-sapw_c) - & max(0._r8,target_c(struct_organ)-struct_c) - & - max(0._r8,target_c(store_organ)-store_c) ) + max(0._r8,target_c(store_organ)-store_c)) + + l2fr_delta_max = (c_fnrt_expand + target_c(fnrt_organ))/target_c(fnrt_organ) + end if @@ -2277,21 +2383,11 @@ subroutine StorageRegulator(this,element_id,regulate_type,target_c,c_scalar) ! Determine the max change for the doubling timescale ! 2.0 = l2fr_delta_max^frnt_adapt_tscl l2fr_delta_scale = 2._r8**(1._r8/fnrt_adapt_tscl)-1.0_r8 - - ! Determiine the change for the halving timescale - !l2fr_scale_min = 0.5_r8**(1._r8/fnrt_adapt_tscl) - - !log_nc_frac = log( store_frac / store_c_frac ) - - ! This is a logistic between -1 and 1 - !c_scalar = l2fr_delta_scale*2._r8*max(0._r8, & - ! min(1._r8,logi_min + (1._r8-logi_min)/(1._r8 + exp(logi_k*(log_nc_frac-store_x0)))))-1.0_r8 - - nc_frac = store_frac / store_c_frac + + nc_frac = nc_frac_offset * store_frac / store_c_frac c_scalar = l2fr_delta_scale*(2.0_r8/(1.0_r8 + nc_frac**logi_k)-1.0_r8)+1.0_r8 - if(c_scalar>1.0_r8)then c_scalar = min(c_scalar,l2fr_delta_max) else @@ -2306,6 +2402,102 @@ subroutine StorageRegulator(this,element_id,regulate_type,target_c,c_scalar) end subroutine StorageRegulator + ! ==================================================================================== + + subroutine EstimateGrowthNC(this,target_c,target_dcdd,state_mask,avg_nc,avg_pc) + + ! This routine predicts the effective nutrient/carbon allocation ratio + ! for the forthcoming growth step. This helps the growth step predict + ! which element will be limiting, and reduce the amount of carbon + ! used to make the step. + class(cnp_allom_prt_vartypes) :: this + real(r8) :: target_c(:) + real(r8) :: target_dcdd(:) + logical :: state_mask(:) + real(r8) :: avg_nc ! Average N:C ratio + real(r8) :: avg_pc ! Average P:C ratio + + real(r8) :: repro_c_frac + real(r8) :: total_w ! Weight (dC/dd) for the ratios + real(r8) :: store_nc + real(r8) :: store_pc + real(r8) :: repro_w,leaf_w,fnrt_w,sapw_w,struct_w,store_w + + associate(dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval, & + ipft => this%bc_in(acnp_bc_in_id_pft)%ival ) + + if(state_mask(repro_id)) then + if (dbh <= prt_params%dbh_repro_threshold(ipft)) then + repro_c_frac = prt_params%seed_alloc(ipft) + else + repro_c_frac = prt_params%seed_alloc(ipft) + prt_params%seed_alloc_mature(ipft) + end if + else + repro_c_frac = 0._r8 + end if + + ! Estimate the total weight + total_w = 0._r8 + avg_nc = 0._r8 + avg_pc = 0._r8 + + if(state_mask(leaf_id)) then + leaf_w = target_dcdd(leaf_organ) * (1._r8 - repro_c_frac) + total_w = total_w + leaf_w + avg_nc = avg_nc + leaf_w * prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(leaf_organ)) + avg_pc = avg_pc + leaf_w * prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(leaf_organ)) + end if + if(state_mask(fnrt_id)) then + fnrt_w = target_dcdd(fnrt_organ) * (1._r8 - repro_c_frac) + total_w = total_w + fnrt_w + avg_nc = avg_nc + fnrt_w * prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(fnrt_organ)) + avg_pc = avg_nc + fnrt_w * prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(fnrt_organ)) + end if + if(state_mask(sapw_id)) then + sapw_w = target_dcdd(sapw_organ) * (1._r8 - repro_c_frac) + total_w = total_w + sapw_w + avg_nc = avg_nc + sapw_w * prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(sapw_organ)) + avg_pc = avg_pc + sapw_w * prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(sapw_organ)) + end if + if(state_mask(struct_id)) then + struct_w = target_dcdd(struct_organ) * (1._r8 - repro_c_frac) + total_w = total_w + struct_w + avg_nc = avg_nc + struct_w * prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(struct_organ)) + avg_pc = avg_pc + struct_w * prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(struct_organ)) + end if + if(state_mask(store_id)) then + store_w = target_dcdd(store_organ) * (1._r8 - repro_c_frac) + total_w = total_w + store_w + store_nc = this%GetNutrientTarget(nitrogen_element,store_organ,stoich_growth_min) / target_c(store_organ) + store_pc = this%GetNutrientTarget(phosphorus_element,store_organ,stoich_growth_min) / target_c(store_organ) + avg_nc = avg_nc + store_w * store_nc + avg_pc = avg_pc + store_w * store_pc + end if + + if(state_mask(repro_id)) then + + ! total = total_w + repro_w + ! repro_w = total*repro_c_frac + ! repro_w = (total_w + repro_w)*repro_c_frac = total_w*repro_c_frac + repro_w*repro_c_frac + ! repro_w * (1 - repro_c_frac) = total_w*repro_c_frac + ! repro_w = total_w * repro_c_frac/(1-repro_c_frac) + + repro_w = total_w * repro_c_frac/(1._r8 - repro_c_frac) + total_w = total_w + repro_w + avg_nc = avg_nc + repro_w * prt_params%nitr_recr_stoich(ipft) + avg_pc = avg_pc + repro_w * prt_params%phos_recr_stoich(ipft) + end if + + + avg_nc = avg_nc / total_w + avg_pc = avg_pc / total_w + + end associate + + return + end subroutine EstimateGrowthNC + + end module PRTAllometricCNPMod From d9ee7ab2ccbf4fe4cdae839d9ba5780b8e27e842 Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Sun, 3 Apr 2022 14:05:30 -0700 Subject: [PATCH 154/852] [Fix bug in defining nlevdamage ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary: no testing --- main/FatesInterfaceMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 1f103b1033..a76c036ca7 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -835,7 +835,7 @@ subroutine SetFatesGlobalElements(use_fates) nlevage = size(ED_val_history_ageclass_bin_edges,dim=1) nlevheight = size(ED_val_history_height_bin_edges,dim=1) nlevcoage = size(ED_val_history_coageclass_bin_edges,dim=1) - nlevdamage = size(ED_val_history_damage_bin_edges, dim=1) + nlevdamage = size(ED_val_history_damage_bin_edges, dim=1) - 1 ! do some checks on the size, age, and height bin arrays to make sure they make sense: ! make sure that all start at zero, and that both are monotonically increasing From f0352aa6e8eb6a8c5190b536aea94dd1bb918a98 Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Sun, 3 Apr 2022 15:15:01 -0700 Subject: [PATCH 155/852] [ fixing canopy_too_full error - possibly from bad merge ] [ looks like a merge with master messed up EDCanopyStrucutreMod ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary:no testing --- biogeochem/EDCanopyStructureMod.F90 | 75 ++++++++++++++--------------- 1 file changed, 35 insertions(+), 40 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index ea7590a78b..42b5fa3e2e 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -380,7 +380,7 @@ subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr,bc_in) currentCohort => currentPatch%shortest do while (associated(currentCohort)) call carea_allom(currentCohort%dbh,currentCohort%n, & - currentSite%spread,currentCohort%pft,& + currentSite%spread,currentCohort%pft, & currentCohort%crowndamage, currentCohort%c_area) if(debug) then @@ -728,8 +728,8 @@ subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr,bc_in) deallocate(currentCohort) else call carea_allom(currentCohort%dbh,currentCohort%n, & - currentSite%spread,currentCohort%pft,& - currentCohort%crowndamage, currentCohort%c_area) + currentSite%spread,currentCohort%pft,currentCohort%crowndamage, & + currentCohort%c_area) end if endif !canopy layer = i_ly @@ -866,7 +866,7 @@ subroutine PromoteIntoLayer(currentSite,currentPatch,i_lyr) currentCohort => currentPatch%tallest do while (associated(currentCohort)) call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread, & - currentCohort%pft,currentCohort%crowndamage, currentCohort%c_area) + currentCohort%pft,currentCohort%c_area) if(currentCohort%canopy_layer == i_lyr+1)then !look at the cohorts in the canopy layer below... if (ED_val_comp_excln .ge. 0.0_r8 ) then @@ -1161,7 +1161,7 @@ subroutine PromoteIntoLayer(currentSite,currentPatch,i_lyr) call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread, & currentCohort%pft,currentCohort%crowndamage, currentCohort%c_area) call carea_allom(copyc%dbh,copyc%n,currentSite%spread,copyc%pft,& - copyc%crowndamage, copyc%c_area) + copyc%crowndamage,copyc%c_area) !----------- Insert copy into linked list ------------------------! copyc%shorter => currentCohort @@ -1238,9 +1238,8 @@ subroutine canopy_spread( currentSite ) currentCohort => currentPatch%tallest do while (associated(currentCohort)) call carea_allom(currentCohort%dbh,currentCohort%n, & - currentSite%spread,currentCohort%pft, & - currentCohort%crowndamage, currentCohort%c_area) - + currentSite%spread,currentCohort%pft,currentCohort%crowndamage, & + currentCohort%c_area) if( ( int(prt_params%woody(currentCohort%pft)) .eq. itrue ) .and. & (currentCohort%canopy_layer .eq. 1 ) ) then sitelevel_canopyarea = sitelevel_canopyarea + currentCohort%c_area @@ -1338,7 +1337,7 @@ subroutine canopy_summarization( nsites, sites, bc_in ) ! Update the cohort's index within the size bin classes ! Update the cohort's index within the SCPF classification system call sizetype_class_index(currentCohort%dbh,currentCohort%pft, & - currentCohort%size_class,currentCohort%size_by_pft_class) + currentCohort%size_class,currentCohort%size_by_pft_class) if (hlm_use_cohort_age_tracking .eq. itrue) then call coagetype_class_index(currentCohort%coage,currentCohort%pft, & @@ -1347,7 +1346,7 @@ subroutine canopy_summarization( nsites, sites, bc_in ) if(hlm_use_sp.eq.ifalse)then call carea_allom(currentCohort%dbh,currentCohort%n,sites(s)%spread,& - currentCohort%pft,currentCohort%crowndamage,currentCohort%c_area) + currentCohort%pft,currentCohort%crowndamage, currentCohort%c_area) endif if(currentCohort%canopy_layer==1)then @@ -1455,7 +1454,7 @@ subroutine leaf_area_profile( currentSite ) ! currentCohort%treesai ! SAI per unit crown area (m2/m2) ! currentCohort%lai ! LAI per unit canopy area (m2/m2) ! currentCohort%sai ! SAI per unit canopy area (m2/m2) - ! currentCohort%nv ! The number of discrete vegetation + ! currentCohort%NV ! The number of discrete vegetation ! ! layers needed to describe this crown ! ! The following patch level diagnostics are updated here: @@ -1508,9 +1507,8 @@ subroutine leaf_area_profile( currentSite ) real(r8) :: min_chite ! bottom of cohort canopy (m) real(r8) :: max_chite ! top of cohort canopy (m) real(r8) :: lai ! summed lai for checking m2 m-2 - real(r8) :: snow_depth_avg ! avg snow over whole site - real(r8) :: leaf_c ! leaf carbon [kgC] - real(r8) :: target_c_area ! crown area of undamaged cohort given dbh + real(r8) :: leaf_c ! leaf carbon [kg] + !---------------------------------------------------------------------- smooth_leaf_distribution = 0 @@ -1563,6 +1561,7 @@ subroutine leaf_area_profile( currentSite ) currentCohort%treelai = tree_lai(leaf_c, currentCohort%pft, currentCohort%c_area, & currentCohort%n, currentCohort%canopy_layer, & currentPatch%canopy_layer_tlai,currentCohort%vcmax25top ) + if (hlm_use_sp .eq. ifalse) then currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh,& currentSite%spread, currentCohort%canopy_trim, & @@ -1935,7 +1934,6 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) bc_out(s)%dleaf_pa(:) = 0._r8 bc_out(s)%z0m_pa(:) = 0._r8 bc_out(s)%displa_pa(:) = 0._r8 - currentPatch => sites(s)%oldest_patch c = fcolumn(s) @@ -1992,8 +1990,8 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) currentCohort%pft, currentCohort%c_area, currentCohort%n, & currentCohort%canopy_layer, currentPatch%canopy_layer_tlai,currentCohort%vcmax25top ) - currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, sites(s)%spread, & - currentCohort%canopy_trim, & + currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, & + site(s)%spread, currentCohort%canopy_trim, & currentCohort%c_area, currentCohort%n, currentCohort%canopy_layer, & currentPatch%canopy_layer_tlai, currentCohort%treelai , & currentCohort%vcmax25top,4) @@ -2025,9 +2023,6 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) bc_out(s)%dleaf_pa(ifp) = EDPftvarcon_inst%dleaf(1) endif ! ----------------------------------------------------------------------------- - bc_out(s)%z0m_pa(ifp) = EDPftvarcon_inst%z0mr(1) * bc_out(s)%htop_pa(ifp) - bc_out(s)%displa_pa(ifp) = EDPftvarcon_inst%displar(1) * bc_out(s)%htop_pa(ifp) - bc_out(s)%dleaf_pa(ifp) = EDPftvarcon_inst%dleaf(1) ! We are assuming here that grass is all located underneath tree canopies. ! The alternative is to assume it is all spatial distinct from tree canopies. @@ -2075,9 +2070,9 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) end if else ! nocomp or SP, and currentPatch%nocomp_pft_label .eq. 0 - + total_patch_area = total_patch_area + currentPatch%area/AREA - + end if currentPatch => currentPatch%younger end do @@ -2110,26 +2105,26 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) endif - ! If running hydro, perform a final check to make sure that we - ! have conserved water. Since this is the very end of the dynamics - ! cycle. No water should had been added or lost to the site during dynamics. - ! With growth and death, we may have shuffled it around. - ! For recruitment, we initialized their water, but flagged them - ! to not be included in the site level balance yet, for they - ! will demand the water for their initialization on the first hydraulics time-step + ! If running hydro, perform a final check to make sure that we + ! have conserved water. Since this is the very end of the dynamics + ! cycle. No water should had been added or lost to the site during dynamics. + ! With growth and death, we may have shuffled it around. + ! For recruitment, we initialized their water, but flagged them + ! to not be included in the site level balance yet, for they + ! will demand the water for their initialization on the first hydraulics time-step - if (hlm_use_planthydro.eq.itrue) then - call UpdateH2OVeg(sites(s),bc_out(s),bc_out(s)%plant_stored_h2o_si,1) - end if + if (hlm_use_planthydro.eq.itrue) then + call UpdateH2OVeg(sites(s),bc_out(s),bc_out(s)%plant_stored_h2o_si,1) + end if end do - ! This call to RecruitWaterStorage() makes an accounting of - ! how much water is used to intialize newly recruited plants. - ! However, it does not actually move water from the soil or create - ! a flux, it is just accounting for diagnostics purposes. The water - ! will not actually be moved until the beginning of the first hydraulics - ! call during the fast timestep sequence + ! This call to RecruitWaterStorage() makes an accounting of + ! how much water is used to intialize newly recruited plants. + ! However, it does not actually move water from the soil or create + ! a flux, it is just accounting for diagnostics purposes. The water + ! will not actually be moved until the beginning of the first hydraulics + ! call during the fast timestep sequence if (hlm_use_planthydro.eq.itrue) then call RecruitWaterStorage(nsites,sites,bc_out) @@ -2271,8 +2266,8 @@ function NumPotentialCanopyLayers(currentPatch,site_spread,include_substory) res currentCohort => currentPatch%tallest do while (associated(currentCohort)) if(currentCohort%canopy_layer == z) then - call carea_allom(currentCohort%dbh,currentCohort%n,site_spread,& - currentCohort%pft,currentCohort%crowndamage, c_area) + call carea_allom(currentCohort%dbh,currentCohort%n,site_spread,currentCohort%pft, & + currentCohort%crowndamage, c_area) arealayer = arealayer + c_area end if currentCohort => currentCohort%shorter From 4cbf4f2f44c7f7ac53c9f67e6a1e273fbcca85fe Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 6 Apr 2022 10:48:16 -0400 Subject: [PATCH 156/852] Initial work on FATES mimics coupling --- biogeochem/FatesSoilBGCFluxMod.F90 | 39 ++++++++++++++++++++++++++++++ main/EDPftvarcon.F90 | 2 ++ main/FatesInterfaceTypesMod.F90 | 8 ++++++ 3 files changed, 49 insertions(+) diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index d14ce7b005..467c91e6eb 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -55,6 +55,7 @@ module FatesSoilBGCFluxMod use FatesInterfaceTypesMod, only : hlm_nu_com use FatesInterfaceTypesMod, only : hlm_parteh_mode use FatesInterfaceTypesMod, only : hlm_use_ch4 + use FatesInterfaceTypesMod, only : hlm_use_mimics use FatesConstantsMod , only : prescribed_p_uptake use FatesConstantsMod , only : prescribed_n_uptake use FatesConstantsMod , only : coupled_p_uptake @@ -993,6 +994,9 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) ! Zero out the boundary flux arrays ! Make a pointer to the cellulose, labile and lignan ! flux partitions. + if(hlm_use_mimics) then + bc_out%litt_flux_ligc_per_n(:) = 0._r8 + end if select case (element_list(el)) case (carbon12_element) @@ -1126,6 +1130,41 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) end do ! do elements + + if(hlm_use_mimics) then + + ! If we track nitrogen (ie cnp or other) then + ! we diagnose the c-lig/n ratio directly from the pools + if(element_pos(nitrogen_element)>0) then + + ! Sum ligC and totalN fluxes over depth + sum_N = sum((bc_out%litt_flux_cel_n_si(1:nlev_eff_soil) + & + bc_out%litt_flux_lig_n_si(1:nlev_eff_soil) + & + bc_out%litt_flux_lab_n_si(1:nlev_eff_soil)) * & + bc_in%dz_sisl(1:nlev_eff_soil)) + + sum_ligC = sum(bc_out%litt_flux_lig_c_si(1:nlev_eff_soil) * bc_in%dz_sisl(1:nlev_eff_soil)) + + if(sum_N>nearzero)then + bc_out%litt_flux_ligc_per_n = sum_ligC / sum_N + else + bc_out%litt_flux_ligc_per_n = 0._r8 + end if + + else + + write(fates_log(),*) 'If FATES is coupled with MIMICS, N cycling' + write(fates_log(),*) 'must be turned on. Both coupled N cycling, as' + write(fates_log(),*) 'well as a prescribed N cycle' + call endrun(msg=errMsg(sourcefile, __LINE__)) + + end if + + end if + + + + return end subroutine FluxIntoLitterPools diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index a149132a8d..faa0144d7d 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1605,7 +1605,9 @@ subroutine FatesCheckParams(is_master) p_uptake_mode = coupled_p_uptake end if + + do ipft = 1,npft diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index ee18396d70..3f154532f6 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -602,6 +602,11 @@ module FatesInterfaceTypesMod real(r8), allocatable :: litt_flux_lig_p_si(:) ! lignan phosphorus litter, fates->BGC g/m3/s real(r8), allocatable :: litt_flux_lab_p_si(:) ! labile phosphorus litter, fates->BGC g/m3/s + ! MIMICS Boundary Conditions + ! ----------------------------------------------------------------------------------- + real(r8), allocatable :: litt_flux_ligc_per_n(:) ! Grams of lignin carbon per grams of nitrogen + ! in the fragmentation flux, per square meter + ! Nutrient competition boundary conditions ! (These are all pointer allocations, this is because the host models @@ -641,6 +646,9 @@ module FatesInterfaceTypesMod ! for use in ELMs CTC/RD [g/m2/s] + + + ! CH4 Boundary Conditions ! ----------------------------------------------------------------------------------- real(r8), pointer :: annavg_agnpp_pa(:) ! annual average patch npp above ground (gC/m2/s) From c14c30939a489d0128f55263ce717725c9e81743 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 6 Apr 2022 15:37:17 -0400 Subject: [PATCH 157/852] More code to add in the litter quality flux for mimics. incremental --- biogeochem/FatesSoilBGCFluxMod.F90 | 69 +++++++++++++++++++++++++++--- main/FatesInterfaceMod.F90 | 39 ++++++++++++++++- main/FatesInterfaceTypesMod.F90 | 11 +++-- parteh/PRTGenericMod.F90 | 2 +- 4 files changed, 110 insertions(+), 11 deletions(-) diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index 467c91e6eb..75459fdce0 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -955,6 +955,16 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) integer :: ic ! CWD type index integer :: ipft ! PFT index + ! The following are used for the MIMICS ligC/N boundary condition + real(r8) :: leaf_c, sapw_c ! leaf and sapwood carbon, per plant [kg] + real(r8) :: fnrt_c, struct_c ! fineroot and struct carbon, per plant [kg] + real(r8) :: leaf_n, sapw_n ! leaf and sapwood N, per plant [kg] + real(r8) :: fnrt_n, struct_n ! fineroot and struct N, per plant [kg] + real(r8) :: total_c, total_n ! Total estimated C and N for plants, [kg/m2] + real(r8) :: sum_ligC ! Flux of lignan C [kg/m2/s] + real(r8) :: sum_C ! Flux of all C [kg/m2/s] + real(r8) :: sum_N ! Flux of all N [kg/m2/s] + ! NOTE(rgk, 201705) this parameter was brought over from SoilBiogeochemVerticalProfile ! how steep profile is for surface components (1/ e_folding depth) (1/m) real(r8), parameter :: surfprof_exp = 10. @@ -1131,7 +1141,7 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) end do ! do elements - if(hlm_use_mimics) then + if(trim(hlm_decomp).eq.'MIMICS') then ! If we track nitrogen (ie cnp or other) then ! we diagnose the c-lig/n ratio directly from the pools @@ -1152,11 +1162,60 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) end if else + + ! In this case (Carbon Only), we use the stoichiometry parameters to estimate + ! the C:N of live vegetation and the seedbank, and use that + ! as a proxy for the C:N of the litter flux + + total_c = 0._r8 + total_n = 0._r8 + currentPatch => csite%oldest_patch + do while (associated(currentPatch)) + + litt => currentPatch%litter(element_pos(carbon12_element)) + area_frac = currentPatch%area*area_inv + + do ipft = 1,numpft + total_c = total_c + & + area_frac*(litt%seed(ipft) + litt%seed_germ(ipft)) + total_n = total_n + area_frac*prt_params%nitr_recr_stoich(ipft) * & + (litt%seed(ipft) + litt%seed_germ(ipft)) + end do - write(fates_log(),*) 'If FATES is coupled with MIMICS, N cycling' - write(fates_log(),*) 'must be turned on. Both coupled N cycling, as' - write(fates_log(),*) 'well as a prescribed N cycle' - call endrun(msg=errMsg(sourcefile, __LINE__)) + ccohort => cpatch%tallest + do while (associated(ccohort)) + + leaf_c = ccohort%prt%GetState(leaf_organ, carbon12_element) + sapw_c = ccohort%prt%GetState(sapw_organ, carbon12_element) + fnrt_c = ccohort%prt%GetState(fnrt_organ, carbon12_element) + struct_c = ccohort%prt%GetState(struct_organ, carbon12_element) + + leaf_n = leaf_c*prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(leaf_organ)) + sapw_n = sapw_c*prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(sapw_organ)) + fnrt_n = fnrt_c*prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(fnrt_organ)) + struct_n = struct_c*prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(struct_organ)) + + total_c = total_c + ccohort%n * area_inv * (leaf_c+fnrt_c+sapw_c+struct_c) + total_n = total_n + ccohort%n * area_inv * (leaf_n+fnrt_n+sapw_n+struct_n) + + ccohort => ccohort%shorter + end do + + currentPatch => currentPatch%younger + end do + + sum_ligC = sum(bc_out%litt_flux_lig_c_si(1:nlev_eff_soil) * bc_in%dz_sisl(1:nlev_eff_soil)) + sum_C = sum( (bc_out%litt_flux_cel_c_si(1:nlev_eff_soil)+ & + bc_out%litt_flux_lab_c_si(1:nlev_eff_soil)+ & + bc_out%litt_flux_lig_c_si(1:nlev_eff_soil)) * bc_in%dz_sisl(1:nlev_eff_soil)) + + !bc_out%litt_flux_ligc_per_n = ligC/TotalN = ligC/totalC * (totalC/totalN) + + if((sum_C>nearzero) .and. (total_n>nearzero))then + bc_out%litt_flux_ligc_per_n = sum_ligC/sum_C * total_c/total_n + else + bc_out%litt_flux_ligc_per_n = 0._r8 + end if end if diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 3ce7589f48..c7bc24acca 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -36,6 +36,7 @@ module FatesInterfaceMod use FatesGlobals , only : fates_global_verbose use FatesGlobals , only : fates_log use FatesGlobals , only : endrun => fates_endrun + use FatesGlobals , only : fates_unset_r8 use FatesLitterMod , only : ncwd use FatesLitterMod , only : ndcmpy use EDPftvarcon , only : FatesReportPFTParams @@ -304,6 +305,10 @@ subroutine zero_bcs(fates,s) fates%bc_out(s)%rootr_pasl(:,:) = 0.0_r8 fates%bc_out(s)%btran_pa(:) = 0.0_r8 + ! MIMIC litter quality, always initialize to unset + fates%bc_out(s)%litt_flux_ligc_per_n = fates_unset_r8 + + ! Fates -> BGC fragmentation mass fluxes select case(hlm_parteh_mode) case(prt_carbon_allom_hyp) @@ -624,7 +629,6 @@ subroutine allocate_bcout(bc_out, nlevsoil_in, nlevdecomp_in) bc_out%rootfr_pa(0,1:nlevsoil_in)=1._r8/real(nlevsoil_in,r8) end if - ! Fates -> BGC fragmentation mass fluxes select case(hlm_parteh_mode) case(prt_carbon_allom_hyp) @@ -1275,10 +1279,12 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) hlm_masterproc = unset_int hlm_ipedof = unset_int hlm_nu_com = 'unset' + hlm_decomp = 'unset' hlm_nitrogen_spec = unset_int hlm_phosphorus_spec = unset_int hlm_max_patch_per_site = unset_int hlm_use_ch4 = unset_int + hlm_use_mimics = unset_int hlm_use_vertsoilc = unset_int hlm_parteh_mode = unset_int hlm_spitfire_mode = unset_int @@ -1460,6 +1466,28 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) call endrun(msg=errMsg(sourcefile, __LINE__)) end if + if(trim(hlm_decomp) .eq. 'unset') then + if (fates_global_verbose()) then + write(fates_log(),*) 'FATES dimension/parameter unset: hlm_decomp, exiting' + write(fates_log(),*) 'valid: MIMICS, CENTURY, CTC' + end if + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + if( .not. ((trim(hlm_decomp) .eq. 'MIMICS') .or. & + (trim(hlm_decomp) .eq. 'CENTURY') .or. & + (trim(hlm_decomp) .eq. 'CTC') .or. & + (trim(hlm_decomp) .eq. 'NONE')) ) then + if (fates_global_verbose()) then + write(fates_log(),*) 'FATES dimension/parameter unset: hlm_decomp, exiting' + write(fates_log(),*) 'valid: NONE, MIMICS, CENTURY, CTC, yours: ',trim(hlm_decomp) + end if + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + print*,trim(hlm_decomp) + stop + + if(trim(hlm_nu_com) .eq. 'unset') then if (fates_global_verbose()) then write(fates_log(),*) 'FATES dimension/parameter unset: hlm_nu_com, exiting' @@ -1467,6 +1495,7 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) call endrun(msg=errMsg(sourcefile, __LINE__)) end if + if(hlm_nitrogen_spec .eq. unset_int) then if (fates_global_verbose()) then write(fates_log(),*) 'FATES parameters unset: hlm_nitrogen_spec, exiting' @@ -1524,7 +1553,7 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) end if call endrun(msg=errMsg(sourcefile, __LINE__)) end if - + if(hlm_use_vertsoilc .eq. unset_int) then if (fates_global_verbose()) then write(fates_log(), *) 'switch for the HLMs soil carbon discretization unset: hlm_use_vertsoilc, exiting' @@ -1839,6 +1868,12 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) write(fates_log(),*) 'Transfering the nutrient competition name = ',trim(cval) end if + case('decomp_method') + hlm_decomp = trim(cval) + if (fates_global_verbose()) then + write(fates_log(),*) 'Transfering the decomp method name = ',trim(cval) + end if + case('inventory_ctrl_file') hlm_inventory_ctrl_file = trim(cval) if (fates_global_verbose()) then diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 3f154532f6..3e3e0191a3 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -46,7 +46,11 @@ module FatesInterfaceTypesMod ! specficially packaged for them. ! This string sets which filter is enacted. - + character(len=16), public :: hlm_decomp ! This string defines which soil decomposition + ! scheme is active + ! expected values are one of CENTURY,MIMICS,CTC + + character(len=16), public :: hlm_nu_com ! This string defines which soil ! nutrient competition scheme is in use. ! current options with @@ -602,10 +606,11 @@ module FatesInterfaceTypesMod real(r8), allocatable :: litt_flux_lig_p_si(:) ! lignan phosphorus litter, fates->BGC g/m3/s real(r8), allocatable :: litt_flux_lab_p_si(:) ! labile phosphorus litter, fates->BGC g/m3/s + ! MIMICS Boundary Conditions ! ----------------------------------------------------------------------------------- - real(r8), allocatable :: litt_flux_ligc_per_n(:) ! Grams of lignin carbon per grams of nitrogen - ! in the fragmentation flux, per square meter + real(r8) :: litt_flux_ligc_per_n ! lignin carbon per total nitrogen + ! in the fragmentation flux, per square meter [g/g] ! Nutrient competition boundary conditions diff --git a/parteh/PRTGenericMod.F90 b/parteh/PRTGenericMod.F90 index 3dab9563a3..35488bd8cc 100644 --- a/parteh/PRTGenericMod.F90 +++ b/parteh/PRTGenericMod.F90 @@ -279,7 +279,7 @@ module PRTGenericMod ! examples are carbon12_element ! nitrogen_element, etc. - integer, public :: element_pos(num_organ_types) ! This is the reverse lookup + integer, public :: element_pos(num_element_types) ! This is the reverse lookup ! for element types. Pick an element ! global index, and it gives you ! the position in the element_list From 40ee5cdbfe3e49f07f12c39a8601ff69ea83ddec Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Wed, 6 Apr 2022 14:54:24 -0600 Subject: [PATCH 158/852] add the continous taper function --- biogeophys/FatesPlantHydraulicsMod.F90 | 109 ++++++++++++++----------- 1 file changed, 63 insertions(+), 46 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 5571adc089..4e75f792b2 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -4605,56 +4605,73 @@ end subroutine shellGeom ! ===================================================================================== -function xylemtaper(p, dz) result(chi_tapnotap) +function xylemtaper(pexp, dz) result(chi_tapnotap) - ! !ARGUMENTS: - real(r8) , intent(in) :: p ! Savage et al. (2010) taper exponent - real(r8) , intent(in) :: dz ! hydraulic distance from petiole to node of interest [m] - ! - ! !LOCAL VARIABLES: - real(r8) :: atap,btap ! scaling exponents for total conductance ~ tree size (ratio of stem radius to terminal twig radius) - real(r8) :: anotap,bnotap ! same as atap, btap, but not acounting for xylem taper (Savage et al. (2010) p = 0) - ! NOTE: these scaling exponents were digitized from Fig 2a of Savage et al. (2010) - ! Savage VM, Bentley LP, Enquist BJ, Sperry JS, Smith DD, Reich PB, von Allmen EI. 2010. - ! Hydraulic trade-offs and space filling enable better predictions of vascular structure - ! and function in plants. Proceedings of the National Academy of Sciences 107(52): 22722-22727. - real(r8) :: lN=0.04_r8 ! petiole length [m] - real(r8) :: little_n=2._r8 ! number of daughter branches per parent branch, assumed constant throughout tree (self-similarity) [-] - real(r8) :: big_n ! number of branching levels (allowed here to take on non-integer values): increases with tree size [-] - real(r8) :: ktap ! hydraulic conductance along the pathway, accounting for xylem taper [kg s-1 MPa-1] - real(r8) :: knotap ! hydraulic conductance along the pathway, not accounting for xylem taper [kg s-1 MPa-1] - real(r8) :: num ! temporary - real(r8) :: den ! temporary - ! - ! !RESULT - real(r8) :: chi_tapnotap ! ratio of total tree conductance accounting for xylem taper to that without, over interval dz - ! - !------------------------------------------------------------------------ + use FatesConstantsMod, only : pi => pi_const - anotap = 7.19903e-13_r8 - bnotap = 1.326105578_r8 - if (p >= 1.0_r8) then - btap = 2.00586217_r8 - atap = 1.82513E-12_r8 - else if (p >= (1._r8/3._r8) .AND. p < 1._r8) then - btap = 1.854812819_r8 - atap = 6.66908E-13_r8 - else if (p >= (1._r8/6._r8) .AND. p < (1._r8/3._r8)) then - btap = 1.628179741_r8 - atap = 6.58345E-13_r8 - else - btap = bnotap - atap = anotap - end if + ! !DESCRIPTION: Following the theory presented i + ! Savage VM, Bentley LP, Enquist BJ, Sperry JS, Smith DD, Reich PB, von + ! Allmen EI. 2010. + ! Hydraulic trade-offs and space filling enable better predictions of + ! vascular structure + ! and function in plants. Proceedings of the National Academy of Sciences + ! 107(52): 22722-22727. - num = 3._r8*log(1._r8 - dz/lN * (1._r8-little_n**(1._r8/3._r8))) - den = log(little_n) - big_n = num/den - 1._r8 - ktap = atap * (little_n**(big_N* btap/2._r8)) - knotap = anotap * (little_n**(big_N*bnotap/2._r8)) - chi_tapnotap = ktap / knotap + ! Revised 2019-01-03 BOC: total conductance exponent (qexp) is now a + ! continuous function of the xylem taper exponent (pexp). + ! renamed btap to qexp, a[tap][notap] to kN, + ! little_n to n_ext, to match variable names + ! in Savage et al. - return + ! !ARGUMENTS: + real(r8) , intent(in) :: pexp ! Savage et al. (2010) taper exponent[-] + real(r8) , intent(in) :: dz ! hydraulic distance from petiole to node of interest[m] + ! + ! !LOCAL VARIABLES: + real(r8) :: qexp ! total conductance exponent (as in Fig. 2b of Savage et al. (2010) + real(r8) :: qexp_notap ! same as qexp, but without xylem taper; i.e., pexp = 0 + real(r8) :: lN=0.005_r8 ! petiole length[m] + real(r8) :: mu=1.0E-03_r8 ! viscosity[kg m-1 s-1] + real(r8) :: rintN=0.00001_r8 ! internal conduit diameter in petiole[m] + real(r8) :: NsegintN=200 ! number of conduits in a single terminal twig[-] + real(r8) :: kN ! conductance for laminar flow through all conduits in a terminal twig, according to Hagen-Poiseuille[kg Pa-1 s-1] + real(r8) :: n_ext=2._r8 ! number of daughter branches per parent branch, assumed constant throughout tree (self-similarity) [-] + real(r8) :: big_n ! number of branching levels (allowed here to take on non-integer values): increases with tree size [-] + real(r8) :: r0rN ! ratio of stem radius to terminal twig radius; r.ext0/r.extN (x-axis of Savage et al. (2010) Fig 2a)[-] + real(r8) :: ktap ! hydraulic conductance along the pathway,accounting for xylem taper [kg s-1 MPa-1] + real(r8) :: knotap ! hydraulic conductance along the pathway,not accounting for xylem taper [kg s-1 MPa-1] + real(r8) :: num ! temporary + real(r8) :: den ! temporary + real(r8) :: a5,a4,a3,a2,a1,a0 ! coefficients of 5th-order polynomial fit to Savage et al. Fig. 2b (qexp vs. pexp) + ! NOTE: These were obtained by digitizing + ! Fig. 2b (dashed line) and fitting a + ! polynomial using nls() in R + ! + ! !RESULT + real(r8) :: chi_tapnotap ! ratio of total tree conductance accounting for xylem taper to that without, over interval dz + ! + !------------------------------------------------------------------------ + + kN = NsegintN*pi*rintN**(4.0_r8)/(8.0_r8*mu*lN) + + a5 = -3.555547_r8 + a4 = 9.760275_r8 + a3 = -8.468005_r8 + a2 = 1.096488_r8 + a1 = 1.844792_r8 + a0 = 1.320732_r8 + qexp = a5*pexp**5 + a4*pexp**4 + a3*pexp**3 + a2*pexp**2 + a1*pexp + a0 + qexp_notap = a0 + + num = 3._r8*log(1._r8 - dz/lN * (1._r8-n_ext**(1._r8/3._r8))) + den = log(n_ext) + big_N = num/den - 1._r8 + r0rN = n_ext**(big_N/2._r8) + ktap = kN * (r0rN**qexp) + knotap = kN * (r0rN**qexp_notap) + chi_tapnotap = ktap / knotap + + return end function xylemtaper From ede09355962751fae522ab0cf376732ef93ef7ba Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 6 Apr 2022 17:54:19 -0400 Subject: [PATCH 159/852] Restructured the C-only method of calculating litter N flux for MIMICS --- biogeochem/FatesSoilBGCFluxMod.F90 | 118 +++++++++++++++++------------ 1 file changed, 71 insertions(+), 47 deletions(-) diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index 75459fdce0..bb6c8efe28 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -960,10 +960,15 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) real(r8) :: fnrt_c, struct_c ! fineroot and struct carbon, per plant [kg] real(r8) :: leaf_n, sapw_n ! leaf and sapwood N, per plant [kg] real(r8) :: fnrt_n, struct_n ! fineroot and struct N, per plant [kg] - real(r8) :: total_c, total_n ! Total estimated C and N for plants, [kg/m2] real(r8) :: sum_ligC ! Flux of lignan C [kg/m2/s] - real(r8) :: sum_C ! Flux of all C [kg/m2/s] real(r8) :: sum_N ! Flux of all N [kg/m2/s] + real(r8) :: tot_leaf_c ! total leaf C of all cohorts in patch [kg/m2] + real(r8) :: tot_leaf_n ! total leaf N of all cohorts in patch [kg/m2] + real(r8) :: tot_fnrt_c ! total fineroot C of all cohorts in patch [kg/m2] + real(r8) :: tot_fnrt_n ! total fineroot N of all cohorts in patch [kg/m2] + real(r8) :: tot_wood_c ! total wood C of all cohorts in patch [kg/m2] + real(r8) :: tot_wood_n ! total wood N of all cohorts in patch [kg/m2] + ! NOTE(rgk, 201705) this parameter was brought over from SoilBiogeochemVerticalProfile ! how steep profile is for surface components (1/ e_folding depth) (1/m) @@ -998,6 +1003,10 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) surface_prof(id) = surface_prof(id)/surface_prof_tot end do + + + + ! Loop over the different elements. do el = 1, num_elements @@ -1062,6 +1071,7 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) flux_lig_si(id) = flux_lig_si(id) + & litt%ag_cwd_frag(ic) * ED_val_cwd_flig * area_frac * surface_prof(id) + end do do j = 1, nlev_eff_soil @@ -1077,6 +1087,9 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) end do end do + + + ! leaf and fine root fragmentation fluxes do id = 1,nlev_eff_decomp @@ -1140,26 +1153,23 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) end do ! do elements - + ! If we are coupled with MIMICS, then we need some assessment of litter quality + ! ie ligC/totalN. If we are not tracking N in the litter flux (ie C-only model) + ! then we need to approximate this by estimating the mean C:N ratios of each + ! plant organ, and mulitplying that by the different C Fluxes to get a total + ! approximate N flux. Note, in C-only, we will not capture any re-absorption. + if(trim(hlm_decomp).eq.'MIMICS') then ! If we track nitrogen (ie cnp or other) then ! we diagnose the c-lig/n ratio directly from the pools if(element_pos(nitrogen_element)>0) then - ! Sum ligC and totalN fluxes over depth + ! Sum totalN fluxes over depth [g/m2] sum_N = sum((bc_out%litt_flux_cel_n_si(1:nlev_eff_soil) + & bc_out%litt_flux_lig_n_si(1:nlev_eff_soil) + & bc_out%litt_flux_lab_n_si(1:nlev_eff_soil)) * & bc_in%dz_sisl(1:nlev_eff_soil)) - - sum_ligC = sum(bc_out%litt_flux_lig_c_si(1:nlev_eff_soil) * bc_in%dz_sisl(1:nlev_eff_soil)) - - if(sum_N>nearzero)then - bc_out%litt_flux_ligc_per_n = sum_ligC / sum_N - else - bc_out%litt_flux_ligc_per_n = 0._r8 - end if else @@ -1167,58 +1177,72 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) ! the C:N of live vegetation and the seedbank, and use that ! as a proxy for the C:N of the litter flux - total_c = 0._r8 - total_n = 0._r8 + sum_N = 0._r8 + currentPatch => csite%oldest_patch do while (associated(currentPatch)) litt => currentPatch%litter(element_pos(carbon12_element)) area_frac = currentPatch%area*area_inv - do ipft = 1,numpft - total_c = total_c + & - area_frac*(litt%seed(ipft) + litt%seed_germ(ipft)) - total_n = total_n + area_frac*prt_params%nitr_recr_stoich(ipft) * & - (litt%seed(ipft) + litt%seed_germ(ipft)) - end do + tot_leaf_c = 0._r8 + tot_leaf_n = 0._r8 + tot_fnrt_c = 0._r8 + tot_fnrt_n = 0._r8 + tot_wood_c = 0._r8 + tot_wood_n = 0._r8 ccohort => cpatch%tallest do while (associated(ccohort)) - - leaf_c = ccohort%prt%GetState(leaf_organ, carbon12_element) - sapw_c = ccohort%prt%GetState(sapw_organ, carbon12_element) - fnrt_c = ccohort%prt%GetState(fnrt_organ, carbon12_element) - struct_c = ccohort%prt%GetState(struct_organ, carbon12_element) - - leaf_n = leaf_c*prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(leaf_organ)) - sapw_n = sapw_c*prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(sapw_organ)) - fnrt_n = fnrt_c*prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(fnrt_organ)) - struct_n = struct_c*prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(struct_organ)) - - total_c = total_c + ccohort%n * area_inv * (leaf_c+fnrt_c+sapw_c+struct_c) - total_n = total_n + ccohort%n * area_inv * (leaf_n+fnrt_n+sapw_n+struct_n) - + leaf_c = ccohort%n * area_inv * ccohort%n*ccohort%prt%GetState(leaf_organ, carbon12_element) + sapw_c = ccohort%n * area_inv * ccohort%n*ccohort%prt%GetState(sapw_organ, carbon12_element) + fnrt_c = ccohort%n * area_inv * ccohort%n*ccohort%prt%GetState(fnrt_organ, carbon12_element) + struct_c = ccohort%n * area_inv * ccohort%n*ccohort%prt%GetState(struct_organ, carbon12_element) + leaf_n = leaf_c * prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(leaf_organ)) + sapw_n = sapw_c * prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(sapw_organ)) + fnrt_n = fnrt_c * prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(fnrt_organ)) + struct_n = struct_c * prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(struct_organ)) + tot_leaf_c = tot_leaf_c + leaf_c + tot_leaf_n = tot_leaf_n + leaf_n + tot_fnrt_c = tot_fnrt_c + fnrt_c + tot_fnrt_n = tot_fnrt_n + fnrt_n + tot_wood_c = tot_wood_c + sapw_c + struct_c + tot_wood_n = tot_wood_n + sapw_n + struct_n ccohort => ccohort%shorter end do + + if(tot_wood_c>nearzero) then + sum_N = sum_N + area_frac*sum(litt%ag_cwd_frag)*(tot_wood_n/tot_wood_c) + sum_N = sum_N + area_frac*sum(litt%bg_cwd_frag)*(tot_wood_n/tot_wood_c) + end if + if(tot_leaf_c>nearzero)then + sum_N = sum_N + area_frac*sum(litt%leaf_fines_frag)*(tot_leaf_n / tot_leaf_c) + end if + if(tot_fnrt_c>nearzero)then + sum_N = sum_N + area_frac*sum(litt%root_fines_frag)*(tot_fnrt_n / tot_fnrt_c) + end if + do ipft = 1,numpft + sum_N = sum_N + area_frac * prt_params%nitr_recr_stoich(ipft) * & + (litt%seed_decay(ipft) + litt%seed_germ_decay(ipft)) + end do currentPatch => currentPatch%younger end do - - sum_ligC = sum(bc_out%litt_flux_lig_c_si(1:nlev_eff_soil) * bc_in%dz_sisl(1:nlev_eff_soil)) - sum_C = sum( (bc_out%litt_flux_cel_c_si(1:nlev_eff_soil)+ & - bc_out%litt_flux_lab_c_si(1:nlev_eff_soil)+ & - bc_out%litt_flux_lig_c_si(1:nlev_eff_soil)) * bc_in%dz_sisl(1:nlev_eff_soil)) - !bc_out%litt_flux_ligc_per_n = ligC/TotalN = ligC/totalC * (totalC/totalN) - - if((sum_C>nearzero) .and. (total_n>nearzero))then - bc_out%litt_flux_ligc_per_n = sum_ligC/sum_C * total_c/total_n - else - bc_out%litt_flux_ligc_per_n = 0._r8 - end if + ! Convert from kg/m2/day -> g/m2/s + sum_N = sum_N * days_per_sec * g_per_kg end if - + + ! Sum over layers and multiply by depth g/m3/s * m -> g/m2/s + sum_ligC = sum(bc_out%litt_flux_lig_c_si(1:nlev_eff_soil) * bc_in%dz_sisl(1:nlev_eff_soil)) + + if(sum_N>nearzero)then + bc_out%litt_flux_ligc_per_n = sum_ligC / sum_N + else + bc_out%litt_flux_ligc_per_n = 0._r8 + end if + end if From bc1c39f61e498049e9808a82dfc0de2bc15766d5 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 6 Apr 2022 17:55:52 -0400 Subject: [PATCH 160/852] Removed unnecessary zeroing of ligCN bcout --- biogeochem/FatesSoilBGCFluxMod.F90 | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index bb6c8efe28..0815e4ecc0 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -1002,21 +1002,10 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) do id = 1,nlev_eff_decomp surface_prof(id) = surface_prof(id)/surface_prof_tot end do - - - - ! Loop over the different elements. do el = 1, num_elements - ! Zero out the boundary flux arrays - ! Make a pointer to the cellulose, labile and lignan - ! flux partitions. - if(hlm_use_mimics) then - bc_out%litt_flux_ligc_per_n(:) = 0._r8 - end if - select case (element_list(el)) case (carbon12_element) bc_out%litt_flux_cel_c_si(:) = 0.0_r8 From fe891c7992079614ef1b4791fe43860c0a08eeb2 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 6 Apr 2022 17:56:41 -0400 Subject: [PATCH 161/852] Fixed comments --- biogeochem/FatesSoilBGCFluxMod.F90 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index 0815e4ecc0..75dc65f3c2 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -1006,6 +1006,10 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) ! Loop over the different elements. do el = 1, num_elements + ! Zero out the boundary flux arrays + ! Make a pointer to the cellulose, labile and lignan + ! flux partitions. + select case (element_list(el)) case (carbon12_element) bc_out%litt_flux_cel_c_si(:) = 0.0_r8 From c87dc5cea74652716028a7d1c8d702535a96eed8 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 6 Apr 2022 19:06:48 -0400 Subject: [PATCH 162/852] debugging mimics coupling, adding print statements --- biogeochem/FatesSoilBGCFluxMod.F90 | 26 +++++++++++++++++++------- main/FatesInterfaceMod.F90 | 8 +++----- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index 75dc65f3c2..74160bb8cf 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -55,7 +55,7 @@ module FatesSoilBGCFluxMod use FatesInterfaceTypesMod, only : hlm_nu_com use FatesInterfaceTypesMod, only : hlm_parteh_mode use FatesInterfaceTypesMod, only : hlm_use_ch4 - use FatesInterfaceTypesMod, only : hlm_use_mimics + use FatesInterfaceTypesMod, only : hlm_decomp use FatesConstantsMod , only : prescribed_p_uptake use FatesConstantsMod , only : prescribed_n_uptake use FatesConstantsMod , only : coupled_p_uptake @@ -931,7 +931,7 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) ! !LOCAL VARIABLES: type (ed_patch_type), pointer :: currentPatch - type (ed_cohort_type), pointer :: currentCohort + type (ed_cohort_type), pointer :: ccohort real(r8), pointer :: flux_cel_si(:) real(r8), pointer :: flux_lab_si(:) real(r8), pointer :: flux_lig_si(:) @@ -1185,12 +1185,13 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) tot_wood_c = 0._r8 tot_wood_n = 0._r8 - ccohort => cpatch%tallest + ccohort => currentPatch%tallest do while (associated(ccohort)) - leaf_c = ccohort%n * area_inv * ccohort%n*ccohort%prt%GetState(leaf_organ, carbon12_element) - sapw_c = ccohort%n * area_inv * ccohort%n*ccohort%prt%GetState(sapw_organ, carbon12_element) - fnrt_c = ccohort%n * area_inv * ccohort%n*ccohort%prt%GetState(fnrt_organ, carbon12_element) - struct_c = ccohort%n * area_inv * ccohort%n*ccohort%prt%GetState(struct_organ, carbon12_element) + ipft = ccohort%pft + leaf_c = ccohort%n * area_inv * ccohort%prt%GetState(leaf_organ, carbon12_element) + sapw_c = ccohort%n * area_inv * ccohort%prt%GetState(sapw_organ, carbon12_element) + fnrt_c = ccohort%n * area_inv * ccohort%prt%GetState(fnrt_organ, carbon12_element) + struct_c = ccohort%n * area_inv * ccohort%prt%GetState(struct_organ, carbon12_element) leaf_n = leaf_c * prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(leaf_organ)) sapw_n = sapw_c * prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(sapw_organ)) fnrt_n = fnrt_c * prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(fnrt_organ)) @@ -1204,6 +1205,13 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) ccohort => ccohort%shorter end do + !print*,prt_params%nitr_stoich_p1(ipft,:), & + ! prt_params%organ_param_id(leaf_organ), & + ! prt_params%organ_param_id(sapw_organ), & + ! prt_params%organ_param_id(fnrt_organ), & + ! prt_params%organ_param_id(struct_organ) + !stop + if(tot_wood_c>nearzero) then sum_N = sum_N + area_frac*sum(litt%ag_cwd_frag)*(tot_wood_n/tot_wood_c) sum_N = sum_N + area_frac*sum(litt%bg_cwd_frag)*(tot_wood_n/tot_wood_c) @@ -1218,6 +1226,8 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) sum_N = sum_N + area_frac * prt_params%nitr_recr_stoich(ipft) * & (litt%seed_decay(ipft) + litt%seed_germ_decay(ipft)) end do + +! print*,(tot_leaf_n / tot_leaf_c),(tot_fnrt_n / tot_fnrt_c),(tot_wood_n/tot_wood_c),prt_params%nitr_recr_stoich(1) currentPatch => currentPatch%younger end do @@ -1235,6 +1245,8 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) else bc_out%litt_flux_ligc_per_n = 0._r8 end if + + print*,"--",bc_out%litt_flux_ligc_per_n,sum_ligC,sum_N end if diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index c7bc24acca..6e84921f4f 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -36,7 +36,7 @@ module FatesInterfaceMod use FatesGlobals , only : fates_global_verbose use FatesGlobals , only : fates_log use FatesGlobals , only : endrun => fates_endrun - use FatesGlobals , only : fates_unset_r8 + use FatesConstantsMod , only : fates_unset_r8 use FatesLitterMod , only : ncwd use FatesLitterMod , only : ndcmpy use EDPftvarcon , only : FatesReportPFTParams @@ -1284,7 +1284,6 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) hlm_phosphorus_spec = unset_int hlm_max_patch_per_site = unset_int hlm_use_ch4 = unset_int - hlm_use_mimics = unset_int hlm_use_vertsoilc = unset_int hlm_parteh_mode = unset_int hlm_spitfire_mode = unset_int @@ -1484,9 +1483,8 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - print*,trim(hlm_decomp) - stop - + ! TEMPORARY TESTING OVERRIDE !!!!!!!! + hlm_decomp = 'MIMICS' if(trim(hlm_nu_com) .eq. 'unset') then if (fates_global_verbose()) then From ece2cb2da05b1e8a33bd4314e8f68baf15bf1f77 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 6 Apr 2022 19:08:41 -0400 Subject: [PATCH 163/852] Removed mimics forced override and comments --- biogeochem/FatesSoilBGCFluxMod.F90 | 11 ----------- main/FatesInterfaceMod.F90 | 2 +- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index 74160bb8cf..9f5d37187b 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -1205,13 +1205,6 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) ccohort => ccohort%shorter end do - !print*,prt_params%nitr_stoich_p1(ipft,:), & - ! prt_params%organ_param_id(leaf_organ), & - ! prt_params%organ_param_id(sapw_organ), & - ! prt_params%organ_param_id(fnrt_organ), & - ! prt_params%organ_param_id(struct_organ) - !stop - if(tot_wood_c>nearzero) then sum_N = sum_N + area_frac*sum(litt%ag_cwd_frag)*(tot_wood_n/tot_wood_c) sum_N = sum_N + area_frac*sum(litt%bg_cwd_frag)*(tot_wood_n/tot_wood_c) @@ -1227,8 +1220,6 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) (litt%seed_decay(ipft) + litt%seed_germ_decay(ipft)) end do -! print*,(tot_leaf_n / tot_leaf_c),(tot_fnrt_n / tot_fnrt_c),(tot_wood_n/tot_wood_c),prt_params%nitr_recr_stoich(1) - currentPatch => currentPatch%younger end do @@ -1246,8 +1237,6 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) bc_out%litt_flux_ligc_per_n = 0._r8 end if - print*,"--",bc_out%litt_flux_ligc_per_n,sum_ligC,sum_N - end if diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 6e84921f4f..093d822969 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1484,7 +1484,7 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) end if ! TEMPORARY TESTING OVERRIDE !!!!!!!! - hlm_decomp = 'MIMICS' + ! hlm_decomp = 'MIMICS' if(trim(hlm_nu_com) .eq. 'unset') then if (fates_global_verbose()) then From cc833b51fc0f4f1d2aaaf2420d555c06d644a825 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 7 Apr 2022 10:37:44 -0400 Subject: [PATCH 164/852] Removed unused whitespace changes --- main/EDPftvarcon.F90 | 2 -- 1 file changed, 2 deletions(-) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index faa0144d7d..a149132a8d 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1605,9 +1605,7 @@ subroutine FatesCheckParams(is_master) p_uptake_mode = coupled_p_uptake end if - - do ipft = 1,npft From 232645943fbed3619996ff7eb10c32da85bd5ed5 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 15 Apr 2022 11:53:55 -0400 Subject: [PATCH 165/852] Added some parameters that were hard coded constants to the parameter file --- biogeochem/EDCohortDynamicsMod.F90 | 7 +- biogeochem/EDPhysiologyMod.F90 | 2 +- biogeophys/FatesPlantRespPhotosynthMod.F90 | 4 +- main/EDInitMod.F90 | 2 +- main/EDPftvarcon.F90 | 20 +----- main/EDTypesMod.F90 | 6 +- main/FatesHistoryInterfaceMod.F90 | 12 ++-- main/FatesInterfaceMod.F90 | 5 +- main/FatesInventoryInitMod.F90 | 2 +- parameter_files/fates_params_default.cdl | 24 ++++--- parameter_files/patch_default_bciopt224.xml | 16 +++-- parteh/PRTAllometricCNPMod.F90 | 80 ++++++++++----------- parteh/PRTAllometricCarbonMod.F90 | 4 +- parteh/PRTParametersMod.F90 | 27 +++++-- parteh/PRTParamsFATESMod.F90 | 51 ++++++++++--- 15 files changed, 144 insertions(+), 118 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index c6dc4fea72..c1bffe6313 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -100,7 +100,7 @@ module EDCohortDynamicsMod use PRTAllometricCNPMod, only : acnp_bc_inout_id_netdn, acnp_bc_inout_id_netdp use PRTAllometricCNPMod, only : acnp_bc_out_id_cefflux, acnp_bc_out_id_nefflux use PRTAllometricCNPMod, only : acnp_bc_out_id_pefflux - use PRTAllometricCNPMod, only : fnrt_adapt_tscl + use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) @@ -248,7 +248,7 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & ! enabled case, because cohorts are also initialized with ! full stores, which match with minimum fr biomass - new_cohort%l2fr = prt_params%allom_l2fr_min(pft) + new_cohort%l2fr = prt_params%allom_l2fr(pft) ! This sets things like vcmax25top, that depend on the @@ -324,9 +324,6 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & !! allocate(new_cohort%tveg_lpa) !! call new_cohort%tveg_lpa%InitRMean(ema_lpa,init_value=patchptr%tveg_lpa%GetMean()) - !!allocate(new_cohort%l2fr_ema) - !!call new_cohort%l2fr_ema%InitRMean(ema_60day,init_value=new_cohort%l2fr,init_offset=fnrt_adapt_tscl*sec_per_day) - call InitPRTBoundaryConditions(new_cohort) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 0fb17d5b39..c55110c266 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1866,7 +1866,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) temp_cohort%pft = ft temp_cohort%hite = EDPftvarcon_inst%hgt_min(ft) temp_cohort%coage = 0.0_r8 - temp_cohort%l2fr = prt_params%allom_l2fr_min(ft) + temp_cohort%l2fr = prt_params%allom_l2fr(ft) stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(ft) call h2d_allom(temp_cohort%hite,ft,temp_cohort%dbh) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index f4d918c9c8..80228bb582 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -718,7 +718,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) fnrt_mr_layer = fnrt_n * ED_val_base_mr_20 * tcsoi * rootfr_ft(ft,j) * maintresp_reduction_factor - currentCohort%froot_mr = currentCohort%froot_mr + fnrt_mr_layer * (1._r8 + EDPftvarcon_inst%nfix_mresp_scfrac(ft)) + currentCohort%froot_mr = currentCohort%froot_mr + fnrt_mr_layer * (1._r8 + prt_params%nfix_mresp_scfrac(ft)) ! calculate the cost of carbon for N fixation in each soil layer and calculate N fixation rate based on that [kgC / kgN] @@ -726,7 +726,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) * (1._r8 - 0.5_r8 * (bc_in(s)%t_soisno_sl(j)-tfrz) / c_fix)) - 2._r8) ! Time integrated amount of carbon spent on fixation (in this layer) [kgC/plant/layer/tstep] - c_spent_nfix = fnrt_mr_layer * dtime * EDPftvarcon_inst%nfix_mresp_scfrac(ft) + c_spent_nfix = fnrt_mr_layer * dtime * prt_params%nfix_mresp_scfrac(ft) currentCohort%daily_n_fixation = currentCohort%daily_n_fixation + c_spent_nfix / c_cost_nfix diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 854b9ecebe..e51d506b05 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -745,7 +745,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) endif temp_cohort%canopy_trim = 1.0_r8 - temp_cohort%l2fr = prt_params%allom_l2fr_min(pft) + temp_cohort%l2fr = prt_params%allom_l2fr(pft) ! h,dbh,leafc,n from SP values or from small initial size. diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 387edc70f8..4513307677 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -157,10 +157,6 @@ module EDPftvarcon ! biochemical production, fraction based how much ! more in need a plant is for P versus N [/] - ! Maintenance respiration surcharge for obligate fixation [fraction of existing respiration] - real(r8), allocatable :: nfix_mresp_scfrac(:) - - ! Turnover related things @@ -925,10 +921,9 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=this%prescribed_puptake) - ! TEMPORARILY USING DEV_ARIBITRARY_PFT FOR FIXATION PARAMETER name = 'fates_dev_arbitrary_pft' call fates_params%RetreiveParameterAllocate(name=name, & - data=this%nfix_mresp_scfrac) + data=this%dev_arbitrary_pft) name = 'fates_eca_decompmicc' call fates_params%RetreiveParameterAllocate(name=name, & @@ -1034,8 +1029,6 @@ subroutine Register_PFT_numrad(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names) - - end subroutine Register_PFT_numrad !----------------------------------------------------------------------- @@ -1515,17 +1508,6 @@ subroutine FatesCheckParams(is_master) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - ! Make sure that the N fixation respiration surcharge fraction is - ! between 0 and 1 - - if(any(EDpftvarcon_inst%nfix_mresp_scfrac(:)<0._r8) .or. any(EDpftvarcon_inst%nfix_mresp_scfrac(:)>1.0_r8)) then - write(fates_log(),*) 'The N fixation surcharge nfix_mresp_sfrac must be between 0-1.' - write(fates_log(),*) 'This parameter is temporarily using the parameter file field: dev_arbitrary_pft' - write(fates_log(),*) 'here are the values: ',EDpftvarcon_inst%nfix_mresp_scfrac(:) - write(fates_log(),*) 'Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - ! If nitrogen is turned on, check to make sure there are valid ammonium ! parameters diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 772a9d0e09..4ae673d5aa 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -28,10 +28,10 @@ module EDTypesMod private ! By default everything is private save - integer, parameter, public :: maxPatchesPerSite = 14 ! maximum number of patches to live on a site + integer, parameter, public :: maxPatchesPerSite = 6 ! maximum number of patches to live on a site integer, parameter, public :: maxPatchesPerSite_by_disttype(n_anthro_disturbance_categories) = & - (/ 10, 4 /) !!! MUST SUM TO maxPatchesPerSite !!! - integer, public :: maxCohortsPerPatch = 100 ! maximum number of cohorts per patch + (/ 5, 1 /) !!! MUST SUM TO maxPatchesPerSite !!! + integer, public :: maxCohortsPerPatch ! maximum number of cohorts per patch integer, parameter, public :: nclmax = 3 ! Maximum number of canopy layers integer, parameter, public :: ican_upper = 1 ! Nominal index for the upper canopy diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 4acf85bddb..1c455565f2 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -81,7 +81,7 @@ module FatesHistoryInterfaceMod use PRTGenericMod , only : carbon12_element use PRTGenericMod , only : nitrogen_element, phosphorus_element use PRTGenericMod , only : prt_carbon_allom_hyp - use PRTAllometricCNPMod , only : stoich_max,stoich_growth_min,stoich_center + use PRTAllometricCNPMod , only : stoich_max,stoich_growth_min implicit none private ! By default everything is private @@ -2550,7 +2550,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) fnrtc_understory_scpf(i_scpf) = fnrtc_understory_scpf(i_scpf) + ccohort%n*fnrt_m end if - call bstore_allom(ccohort%dbh,ccohort%pft,ccohort%canopy_trim, store_growth_min) + call bstore_allom(ccohort%dbh,ccohort%pft,ccohort%canopy_trim, store_max) this%hvars(ih_storectfrac_si)%r81d(io_si) = & this%hvars(ih_storectfrac_si)%r81d(io_si) + ccohort%n * store_max/m2_per_ha @@ -2595,7 +2595,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) elseif(element_list(el).eq.nitrogen_element)then - store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_center) + store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_growth_min) this%hvars(ih_storen_si)%r81d(io_si) = & this%hvars(ih_storen_si)%r81d(io_si) + ccohort%n * & @@ -2635,7 +2635,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) elseif(element_list(el).eq.phosphorus_element) then - store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_center) + store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_growth_min) this%hvars(ih_storep_si)%r81d(io_si) = & this%hvars(ih_storep_si)%r81d(io_si) + ccohort%n * & @@ -3534,7 +3534,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) repro_m * ccohort%n / m2_per_ha elseif(element_list(el).eq.nitrogen_element)then - store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_center) + store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_growth_min) this%hvars(ih_totvegn_scpf)%r82d(io_si,i_scpf) = & this%hvars(ih_totvegn_scpf)%r82d(io_si,i_scpf) + & @@ -3557,7 +3557,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) elseif(element_list(el).eq.phosphorus_element)then - store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_center) + store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_growth_min) this%hvars(ih_totvegp_scpf)%r82d(io_si,i_scpf) = & this%hvars(ih_totvegp_scpf)%r82d(io_si,i_scpf) + & diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 2ad860ef47..b70d680437 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -84,7 +84,6 @@ module FatesInterfaceMod use FatesRunningMeanMod , only : moving_ema_window use FatesRunningMeanMod , only : fixed_window use FatesHistoryInterfaceMod , only : fates_hist - use PRTAllometricCNPMod , only : fnrt_adapt_tscl ! CIME Globals use shr_log_mod , only : errMsg => shr_log_errMsg @@ -927,9 +926,9 @@ subroutine InitTimeAveragingGlobals() allocate(ema_lpa) call ema_lpa%define(photo_temp_acclim_timescale*sec_per_day, & hlm_stepsize,moving_ema_window) - allocate(ema_60day) - call ema_60day%define(fnrt_adapt_tscl*sec_per_day,sec_per_day,moving_ema_window) + !allocate(ema_60day) + !call ema_60day%define(prt_params%fnrt_adapt_tscl*sec_per_day,sec_per_day,moving_ema_window) !class(rmean_arr_type), pointer :: ema_fnrt_tscale(:) !rmean_arr_type diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index ff511b662b..c73b78a3a0 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -1031,7 +1031,7 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & ! Calculate fine root biomass - temp_cohort%l2fr = prt_params%allom_l2fr_min(temp_cohort%pft) + temp_cohort%l2fr = prt_params%allom_l2fr(temp_cohort%pft) call bfineroot(temp_cohort%dbh,temp_cohort%pft,temp_cohort%canopy_trim,temp_cohort%l2fr,c_fnrt) ! Calculate sapwood biomass diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 344f5ee4ab..3028fcb968 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -44,6 +44,9 @@ variables: char fates_prt_organ_name(fates_prt_organs, fates_string_length) ; fates_prt_organ_name:units = "unitless - string" ; fates_prt_organ_name:long_name = "Name of plant organs (order must match PRTGenericMod.F90)" ; + double fates_fnrt_adapt_tscale(fates_pft) ; + fates_fnrt_adapt_tscale:units = "fraction" ; + fates_fnrt_adapt_tscale:long_name = "Number of days that is the shortest possible doubling period for CNP fine-root adaptation" ; double fates_alloc_storage_cushion(fates_pft) ; fates_alloc_storage_cushion:units = "fraction" ; fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; @@ -111,12 +114,9 @@ variables: fates_allom_hmode:units = "index" ; fates_allom_hmode:long_name = "height allometry function index." ; fates_allom_hmode:possible_values = "1: OBrien 1995; 2: Poorter 2006; 3: 2 parameter power law; 4: Chave 2014; 5: Martinez-Cano 2019." ; - double fates_allom_l2fr_min(fates_pft) ; - fates_allom_l2fr_min:units = "gC/gC" ; - fates_allom_l2fr_min:long_name = "Allocation parameter: minimum fine root C per leaf C (definitive l2fr for Carbon-only)" ; - double fates_allom_l2fr_max(fates_pft) ; - fates_allom_l2fr_max:units = "gC/gC" ; - fates_allom_l2fr_max:long_name = "Allocation parameter: maximum fine root C per leaf C (NOT USED IN Carbon-only, only CNP)" ; + double fates_allom_l2fr(fates_pft) ; + fates_allom_l2fr:units = "gC/gC" ; + fates_allom_l2fr:long_name = "Allocation parameter: static or initial fine root C per leaf C" ; double fates_allom_la_per_sa_int(fates_pft) ; fates_allom_la_per_sa_int:units = "m2/cm2" ; fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; @@ -505,6 +505,9 @@ variables: double fates_smpso(fates_pft) ; fates_smpso:units = "mm" ; fates_smpso:long_name = "Soil water potential at full stomatal opening" ; + double fates_store_ovrflw_frac(fates_pft) ; + fates_store_ovrflw_frac:units = "fraction" ; + fates_store_ovrflw_frac:long_name = "size of overflow storage (CNP only) as a fraction of storage target" ; double fates_taulnir(fates_pft) ; fates_taulnir:units = "fraction" ; fates_taulnir:long_name = "Leaf transmittance: near-IR" ; @@ -810,6 +813,9 @@ data: "sapwood ", "structure " ; + + fates_fnrt_adapt_tscale = 30.0,30.0,30.0,30.0,30.0,30.0,30.0,30.0, 30.0,30.0,30.0,30.0; + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 ; @@ -868,9 +874,7 @@ data: fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_l2fr_min = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_l2fr_max = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 ; @@ -1291,6 +1295,8 @@ data: fates_smpso = -66000, -66000, -66000, -66000, -66000, -66000, -66000, -66000, -66000, -66000, -66000, -66000 ; + fates_store_ovrflw_frac = 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 ; + fates_taulnir = 0.25, 0.1, 0.1, 0.25, 0.25, 0.25, 0.1, 0.25, 0.25, 0.34, 0.34, 0.34 ; diff --git a/parameter_files/patch_default_bciopt224.xml b/parameter_files/patch_default_bciopt224.xml index bfcc288efa..73f37057d6 100644 --- a/parameter_files/patch_default_bciopt224.xml +++ b/parameter_files/patch_default_bciopt224.xml @@ -2,16 +2,17 @@ This parameter dataset was created by Ryan Knox rgknox@lbl.gov. Please contact if using in published work. The calibration uses the following datasets: [1] Ely et al. 2019. Leaf mass area, Panama. NGEE-Tropics data collection.http://dx.doi.org/10.15486/ngt/1411973 and [2] Condit et al. 2019. Complete data from the Barro Colorado 50-ha plot. https://doi.org/10.15146/5xcp-0d46. [3] Koven et al. 2019. Benchmarking and parameter sensitivity of physiological and vegetation dynamics using the functionally assembled terrestrial ecosystem simulator. Biogeosciences. The ECA nutrient aquisition parmeters are unconstrained, the file output naming convention vmn6phi is shorthand for vmax for nitrogen uptake is order e-6 and for phosphorus is excessively high. These parameters were calibrated with the special fates modification in main/EDTypesMod.F90: nclmax = 3 fates_params_default.cdl - fates_params_opt224_vmn6phi_080621.cdl + fates_params_opt224_040822.cdl 1 0 0 1,1,3,4 0.03347526,0.024,1e-08,0.0047 - 0.03347526,0.024,1e-08,0.0047 - 0.025,0,0,0 + 0.002675,0.0005,0.00015,0.00015 + 0.0,0,0,0 0.45,0.25,0,0 + 0.65,0.25,0,0 0.8012471 30.94711 0.0673 @@ -31,10 +32,13 @@ 2 5 0.4863088 + 0.0 + 10 + 1 3 - 3e-06 - 3e-06 - 3e-07 + 5e-09 + 5e-09 + 5e-10 3e-08 0.03991654 0.01995827 diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 67cf24ca65..4e411d3d5d 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -61,6 +61,7 @@ module PRTAllometricCNPMod use EDTypesMod , only : n_uptake_mode use FatesConstantsMod , only : prescribed_p_uptake use FatesConstantsMod , only : prescribed_n_uptake + use EDPftvarcon, only : EDPftvarcon_inst implicit none private @@ -104,8 +105,6 @@ module PRTAllometricCNPMod ! minimum needed for growth integer,public, parameter :: stoich_max = 2 ! Flag for stoichiometry associated with ! maximum for that organ - integer,public, parameter :: stoich_center=3 - ! This is the ordered list of organs used in this module ! ------------------------------------------------------------------------------------- @@ -187,9 +186,6 @@ module PRTAllometricCNPMod ! ------------------------------------------------------------------------------------- integer, parameter :: icd = 1 - - real(r8), parameter :: store_overflow_frac = 1.0_r8 ! The fraction above target allowed in storage - integer, parameter :: exude_c_store_overflow = 1 integer, parameter :: retain_c_store_overflow = 2 integer, parameter :: burn_c_store_overflow = 3 @@ -208,11 +204,6 @@ module PRTAllometricCNPMod integer, parameter :: regulate_CN_dfdd = 4 - real(r8), public, parameter :: fnrt_adapt_tscl = 100._r8 ! Fine-root adaptation timescale (days) - ! or, how many days it takes - ! for a doubling or halving of the l2fr - - ! ------------------------------------------------------------------------------------- ! This is the core type that holds this specific ! plant reactive transport (PRT) module @@ -398,11 +389,19 @@ subroutine DailyPRTAllometricCNP(this) ! In/out boundary conditions - resp_excess => this%bc_inout(acnp_bc_inout_id_resp_excess)%rval; resp_excess0 = resp_excess + resp_excess => this%bc_inout(acnp_bc_inout_id_resp_excess)%rval; dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval; dbh0 = dbh l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval n_gain => this%bc_inout(acnp_bc_inout_id_netdn)%rval; p_gain => this%bc_inout(acnp_bc_inout_id_netdp)%rval; + + + ! Assume that there is no other source of excess respiration + ! so it is safe to zero it. In the third stage we will + ! decide if this should be updated + resp_excess = 0._r8 + resp_excess0 = resp_excess + ! integrator variables @@ -688,8 +687,7 @@ subroutine CNPAdjustFRootTargets(this, target_c) dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval - associate( l2fr_min => prt_params%allom_l2fr_min(ipft), & - l2fr_max => prt_params%allom_l2fr_max(ipft)) + associate( l2fr_min => prt_params%allom_l2fr(ipft) ) if(n_uptake_mode.eq.prescribed_n_uptake)then n_regulator = 1._r8 @@ -721,7 +719,7 @@ subroutine CNPAdjustFRootTargets(this, target_c) if(regulate_type == regulate_CN_logi)then - l2fr = l2fr_min + max(0._r8,min(1.0_r8,np_regulator))*(l2fr_max-l2fr_min) + l2fr = l2fr_min + max(0._r8,min(1.0_r8,np_regulator))*(10._r8*l2fr_min-l2fr_min) elseif(regulate_type == regulate_CN_dfdd) then @@ -1677,17 +1675,18 @@ subroutine CNPAllocateRemainder(this, c_gain, n_gain, p_gain, & ! Update carbon based allometric targets call bstore_allom(dbh,ipft,canopy_trim, store_c_target) - + + ! Allow some overflow - store_c_target = store_c_target * (1.0_r8 + store_overflow_frac) + store_c_target = store_c_target * (1._r8 + prt_params%store_ovrflw_frac(ipft)) - total_c_flux = min(c_gain,max(0.0, (store_c_target - this%variables(store_c_id)%val(1)))) - ! Transfer excess carbon into storage overflow + total_c_flux = min(c_gain,max(0.0_r8, ( store_c_target - this%variables(store_c_id)%val(1) ))) + ! Transfer excess carbon INTO storage overflow this%variables(store_c_id)%val(1) = this%variables(store_c_id)%val(1) + total_c_flux c_gain = c_gain - total_c_flux - resp_excess = c_gain - c_gain = 0._r8 + resp_excess = resp_excess + c_gain + c_gain = 0._r8 elseif(store_c_overflow == exude_c_store_overflow)then @@ -1695,7 +1694,7 @@ subroutine CNPAllocateRemainder(this, c_gain, n_gain, p_gain, & call bstore_allom(dbh,ipft,canopy_trim, store_c_target) ! Estimate the overflow - store_c_target = store_c_target * (1.0_r8 + store_overflow_frac) + store_c_target = store_c_target * (1._r8 + prt_params%store_ovrflw_frac(ipft)) total_c_flux = min(c_gain,max(0.0, (store_c_target - this%variables(store_c_id)%val(1)))) ! Transfer excess carbon into storage overflow @@ -1826,31 +1825,25 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe if( element_id == nitrogen_element) then target_m = StorageNutrientTarget(ipft, element_id, & - leaf_c_target*prt_params%nitr_stoich_p2(ipft,prt_params%organ_param_id(leaf_organ)), & - fnrt_c_target*prt_params%nitr_stoich_p2(ipft,prt_params%organ_param_id(fnrt_organ)), & - sapw_c_target*prt_params%nitr_stoich_p2(ipft,prt_params%organ_param_id(sapw_organ)), & - struct_c_target*prt_params%nitr_stoich_p2(ipft,prt_params%organ_param_id(struct_organ))) + leaf_c_target*prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(leaf_organ)), & + fnrt_c_target*prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(fnrt_organ)), & + sapw_c_target*prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(sapw_organ)), & + struct_c_target*prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(struct_organ))) else target_m = StorageNutrientTarget(ipft, element_id, & - leaf_c_target*prt_params%phos_stoich_p2(ipft,prt_params%organ_param_id(leaf_organ)), & - fnrt_c_target*prt_params%phos_stoich_p2(ipft,prt_params%organ_param_id(fnrt_organ)), & - sapw_c_target*prt_params%phos_stoich_p2(ipft,prt_params%organ_param_id(sapw_organ)), & - struct_c_target*prt_params%phos_stoich_p2(ipft,prt_params%organ_param_id(struct_organ))) + leaf_c_target*prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(leaf_organ)), & + fnrt_c_target*prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(fnrt_organ)), & + sapw_c_target*prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(sapw_organ)), & + struct_c_target*prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(struct_organ))) end if ! This is only called during phase 3, remainder and allows ! us to have some overflow to avoid exudation/efflux if possible if( stoich_mode == stoich_max ) then - target_m = target_m*(1._r8 + store_overflow_frac) + target_m = target_m*(1._r8 + prt_params%store_ovrflw_frac(ipft)) end if - !if( stoich_mode == stoich_growth_min ) then - ! target_m = 0.1_r8*target_m - !end if - !if( stoich_mode == stoich_center ) then - ! do nothing, target_m is unchanged - !end if elseif(organ_id == repro_organ) then @@ -2255,7 +2248,7 @@ subroutine StorageRegulator(this,element_id,regulate_type,target_c,c_scalar) real(r8) :: c_gain real(r8) :: c_fnrt_expand ! predicted carbon available to expand fine-roots ! after replacement of turnover - + ! This fraction governs ! how much carbon from daily gains + storage overflow, is allowed to ! be spent on growing out roots. This inludes getting roots @@ -2276,10 +2269,13 @@ subroutine StorageRegulator(this,element_id,regulate_type,target_c,c_scalar) ipft => this%bc_in(acnp_bc_in_id_pft)%ival, & l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval) - logi_k = 2._r8 + + logi_k = EDPftvarcon_inst%dev_arbitrary_pft(ipft) !2._r8 store_x0 = 0.0_r8 logi_min = 0.0_r8 + ! TEMPORARY OVERRIDE + if(regulate_type == regulate_CN_logi) then store_c = this%GetState(store_organ, carbon12_element) @@ -2296,7 +2292,7 @@ subroutine StorageRegulator(this,element_id,regulate_type,target_c,c_scalar) elseif(regulate_type == regulate_CN_dfdd) then - store_max = this%GetNutrientTarget(element_id,store_organ,stoich_center) !*(1._r8 + 0.5*store_overflow_frac) + store_max = this%GetNutrientTarget(element_id,store_organ,stoich_growth_min) ! Storage fractions could be more than the target, depending on the ! hypothesis and functions involved, but should typically be 0-1 @@ -2308,7 +2304,7 @@ subroutine StorageRegulator(this,element_id,regulate_type,target_c,c_scalar) ! these stores can actually get pretty large, so the cap of 10x is numerically ! feasable, and should also minimize stress on the logistic function - store_c_max = target_c(store_organ) !*(1._r8 + 0.5*store_overflow_frac) + store_c_max = target_c(store_organ) store_c_frac = max(0.01_r8,min(5.0_r8,this%GetState(store_organ, carbon12_element)/store_c_max )) @@ -2382,8 +2378,8 @@ subroutine StorageRegulator(this,element_id,regulate_type,target_c,c_scalar) ! Determine the max change for the doubling timescale ! 2.0 = l2fr_delta_max^frnt_adapt_tscl - l2fr_delta_scale = 2._r8**(1._r8/fnrt_adapt_tscl)-1.0_r8 - + l2fr_delta_scale = 2._r8**(1._r8/prt_params%fnrt_adapt_tscale(ipft))-1.0_r8 + nc_frac = nc_frac_offset * store_frac / store_c_frac c_scalar = l2fr_delta_scale*(2.0_r8/(1.0_r8 + nc_frac**logi_k)-1.0_r8)+1.0_r8 diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index bb05e1c365..407d3e2c88 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -391,7 +391,7 @@ subroutine DailyPRTAllometricCarbon(this) store_c => this%variables(store_c_id)%val(icd), & repro_c => this%variables(repro_c_id)%val(icd), & struct_c => this%variables(struct_c_id)%val(icd), & - l2fr => prt_params%allom_l2fr_min(ipft) ) + l2fr => prt_params%allom_l2fr(ipft) ) ! ----------------------------------------------------------------------------------- ! 0. @@ -931,7 +931,7 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) canopy_trim = intgr_params(ac_bc_in_id_ctrim) ipft = int(intgr_params(ac_bc_in_id_pft)) - l2fr = prt_params%allom_l2fr_min(ipft) + l2fr = prt_params%allom_l2fr(ipft) call bleaf(dbh,ipft,canopy_trim,ct_leaf,ct_dleafdd) call bfineroot(dbh,ipft,canopy_trim,l2fr,ct_fnrt,ct_dfnrtdd) diff --git a/parteh/PRTParametersMod.F90 b/parteh/PRTParametersMod.F90 index cbb9e4ad86..e1f418f09e 100644 --- a/parteh/PRTParametersMod.F90 +++ b/parteh/PRTParametersMod.F90 @@ -94,9 +94,9 @@ module PRTParametersMod ! Root profile parameters. Note we have separate parameters for those that govern ! hydraulics, and those that govern biomass (for decomposition and respiration) - real(r8), allocatable :: fnrt_prof_mode(:) ! Fine root profile functional form - real(r8), allocatable :: fnrt_prof_a(:) ! Fine root profile scaling parameter A - real(r8), allocatable :: fnrt_prof_b(:) ! Fine root profile scaling parameter B + real(r8), allocatable :: fnrt_prof_mode(:) ! Fine root profile functional form + real(r8), allocatable :: fnrt_prof_a(:) ! Fine root profile scaling parameter A + real(r8), allocatable :: fnrt_prof_b(:) ! Fine root profile scaling parameter B real(r8), allocatable :: c2b(:) ! Carbon to biomass multiplier [kg/kgC] real(r8), allocatable :: wood_density(:) ! wood density g cm^-3 ... @@ -119,10 +119,9 @@ module PRTParametersMod ! (sapwood area / leaf area) [cm2/m2] real(r8), allocatable :: allom_la_per_sa_slp(:) ! Leaf area to sap area conversion, slope ! (sapwood area / leaf area / diameter) [cm2/m2/cm] - real(r8), allocatable :: allom_l2fr_min(:) ! Minimum fine root biomass per leaf biomass ratio [kgC/kgC] - ! FOR C-ONLY, THIS IS THE ONLY AND STATIC L2FR - real(r8), allocatable :: allom_l2fr_max(:) ! Maximum fine root biomass per leaf biomass ratio [kgC/kgC] - ! for nutrient enabled runs + real(r8), allocatable :: allom_l2fr(:) ! Fine root biomass per leaf biomass ratio [kgC/kgC] + ! FOR C-ONLY: this is the static, unchanging ratio + ! FOR CNP: this is the initial value a cohort starts with real(r8), allocatable :: allom_agb_frac(:) ! Fraction of stem above ground [-] real(r8), allocatable :: allom_d2h1(:) ! Parameter 1 for d2h allometry (intercept, or "c") real(r8), allocatable :: allom_d2h2(:) ! Parameter 2 for d2h allometry (slope, or "m") @@ -147,6 +146,20 @@ module PRTParametersMod real(r8), allocatable :: allom_zroot_min_z(:) ! the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh [m] real(r8), allocatable :: allom_zroot_k(:) ! scale coefficient of logistic rooting depth model + + real(r8), allocatable :: fnrt_adapt_tscale(:) ! The time-scale over which you could see a doubling (or halving) + ! of fineroot biomass in response to a nutrient/carbon storage disparity + ! assuming no constraints on turnover or carbon availability (days) + + real(r8), allocatable :: store_ovrflw_frac(:) ! For a coupled nutrient enabled simulation with dynamic fine-root biomass, + ! there will be an excess of at least two of the three species C, N or P. + ! This specifies how much excess (overflow) is allowed to be retained in storage + ! beyond the target level before it is either burned (C) or exuded (N or P). The + ! maximum value is the target * (1+store_ovrflw_frac) + + + real(r8), allocatable :: nfix_mresp_scfrac(:) ! Surcharge (as a fraction) to add to maintentance respiration + ! that is used to pay for N-Fixation end type prt_param_type diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index 8a34af48c6..fb1338c5cd 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -231,11 +231,19 @@ subroutine PRTRegisterPFT(fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_allom_l2fr_min' + name = 'fates_allom_l2fr' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_allom_l2fr_max' + name = 'fates_fnrt_adapt_tscale' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_store_ovrflw_frac' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_nfix1' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -527,14 +535,22 @@ subroutine PRTReceivePFT(fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%allom_la_per_sa_slp) - name = 'fates_allom_l2fr_min' + name = 'fates_allom_l2fr' call fates_params%RetreiveParameterAllocate(name=name, & - data=prt_params%allom_l2fr_min) + data=prt_params%allom_l2fr) - name = 'fates_allom_l2fr_max' + name = 'fates_fnrt_adapt_tscale' call fates_params%RetreiveParameterAllocate(name=name, & - data=prt_params%allom_l2fr_max) - + data=prt_params%fnrt_adapt_tscale) + + name = 'fates_store_ovrflw_frac' + call fates_params%RetreiveParameterAllocate(name=name, & + data=prt_params%store_ovrflw_frac) + + name = 'fates_nfix1' + call fates_params%RetreiveParameterAllocate(name=name, & + data=prt_params%nfix_mresp_scfrac) + name = 'fates_allom_agb_frac' call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%allom_agb_frac) @@ -626,7 +642,7 @@ subroutine PRTReceivePFT(fates_params) name = 'fates_phos_store_ratio' call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%phos_store_ratio) - + end subroutine PRTReceivePFT @@ -891,8 +907,9 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'allom_smode = ',prt_params%allom_smode write(fates_log(),fmt0) 'allom_la_per_sa_int = ',prt_params%allom_la_per_sa_int write(fates_log(),fmt0) 'allom_la_per_sa_slp = ',prt_params%allom_la_per_sa_slp - write(fates_log(),fmt0) 'allom_l2fr_min = ',prt_params%allom_l2fr_min - write(fates_log(),fmt0) 'allom_l2fr_max = ',prt_params%allom_l2fr_max + write(fates_log(),fmt0) 'allom_l2fr = ',prt_params%allom_l2fr + write(fates_log(),fmt0) 'fnrt_adapt_tscale = ',prt_params%fnrt_adapt_tscale + write(fates_log(),fmt0) 'store_ovrflw_frac = ',prt_params%store_ovrflw_frac write(fates_log(),fmt0) 'allom_agb_frac = ',prt_params%allom_agb_frac write(fates_log(),fmt0) 'allom_d2h1 = ',prt_params%allom_d2h1 write(fates_log(),fmt0) 'allom_d2h2 = ',prt_params%allom_d2h2 @@ -1046,6 +1063,18 @@ subroutine PRTCheckParams(is_master) end do end if + + ! Make sure that the N fixation respiration surcharge fraction is + ! between 0 and 1 + if (hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) then + if(any(prt_params%nfix_mresp_scfrac(:)<0._r8) .or. any(prt_params%nfix_mresp_scfrac(:)>1.0_r8)) then + write(fates_log(),*) 'The N fixation surcharge nfix_mresp_sfrac (fates_nfix1) must be between 0-1.' + write(fates_log(),*) 'here are the values: ',prt_params%nfix_mresp_scfrac(:) + write(fates_log(),*) 'Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + end if + pftloop: do ipft = 1,npft @@ -1470,7 +1499,7 @@ function NewRecruitTotalStoichiometry(ft,element_id) result(recruit_stoich) call h2d_allom(EDPftvarcon_inst%hgt_min(ft),ft,dbh) call bleaf(dbh,ft,init_recruit_trim,c_leaf) - call bfineroot(dbh,ft,init_recruit_trim,prt_params%allom_l2fr_min(ft),c_fnrt) + call bfineroot(dbh,ft,init_recruit_trim,prt_params%allom_l2fr(ft),c_fnrt) call bsap_allom(dbh,ft,init_recruit_trim,a_sapw, c_sapw) call bagw_allom(dbh,ft,c_agw) call bbgw_allom(dbh,ft,c_bgw) From 5f44bfafc4bfe30599d2dd391831cb6d34c9e4e5 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 15 Apr 2022 15:19:55 -0400 Subject: [PATCH 166/852] Added carbon storage fraction by sizexpft ustory/canopy --- main/FatesHistoryInterfaceMod.F90 | 50 +++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 1c455565f2..987b8ad87d 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -162,6 +162,8 @@ module FatesHistoryInterfaceMod integer :: ih_storec_si integer :: ih_storectfrac_si + integer :: ih_storectfrac_canopy_scpf + integer :: ih_storectfrac_ustory_scpf integer :: ih_leafc_si integer :: ih_sapwc_si integer :: ih_fnrtc_si @@ -1974,6 +1976,8 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) real(r8) :: storen_understory_scpf(numpft*nlevsclass) real(r8) :: storep_canopy_scpf(numpft*nlevsclass) real(r8) :: storep_understory_scpf(numpft*nlevsclass) + real(r8) :: storec_canopy_scpf(numpft*nlevsclass) + real(r8) :: storec_understory_scpf(numpft*nlevsclass) integer :: return_code @@ -2249,7 +2253,9 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) storen_understory_scpf(:) = 0._r8 storep_canopy_scpf(:) = 0._r8 storep_understory_scpf(:) = 0._r8 - + storec_canopy_scpf(:) = 0._r8 + storec_understory_scpf(:) = 0._r8 + ! Total carbon model error [kgC/day -> kgC/s] hio_cbal_err_fates_si(io_si) = & sites(s)%mass_balance(element_pos(carbon12_element))%err_fates / sec_per_day @@ -2593,6 +2599,21 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) total_m * ccohort%n * AREA_INV endif + if (ccohort%canopy_layer .eq. 1) then + storec_canopy_scpf(i_scpf) = & + storec_canopy_scpf(i_scpf) + ccohort%n * store_m + this%hvars(ih_storectfrac_canopy_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_storectfrac_canopy_scpf)%r82d(io_si,i_scpf) + & + ccohort%n * store_max + else + storec_understory_scpf(i_scpf) = & + storec_understory_scpf(i_scpf) + ccohort%n * store_m + this%hvars(ih_storectfrac_ustory_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_storectfrac_ustory_scpf)%r82d(io_si,i_scpf) + & + ccohort%n * store_max + end if + + elseif(element_list(el).eq.nitrogen_element)then store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_growth_min) @@ -3611,9 +3632,21 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_l2fr_understory_scpf(io_si,i_scpf) = & hio_l2fr_understory_scpf(io_si,i_scpf)/fnrtc_understory_scpf(i_scpf) end if + + if( this%hvars(ih_storectfrac_canopy_scpf)%r82d(io_si,i_scpf)>nearzero ) then + this%hvars(ih_storectfrac_canopy_scpf)%r82d(io_si,i_scpf) = & + storec_canopy_scpf(i_scpf) / & + this%hvars(ih_storectfrac_canopy_scpf)%r82d(io_si,i_scpf) + end if + if( this%hvars(ih_storectfrac_ustory_scpf)%r82d(io_si,i_scpf)>nearzero ) then + this%hvars(ih_storectfrac_ustory_scpf)%r82d(io_si,i_scpf) = & + storec_understory_scpf(i_scpf) / & + this%hvars(ih_storectfrac_ustory_scpf)%r82d(io_si,i_scpf) + end if + end do end do - + do el = 1, num_elements if(element_list(el).eq.nitrogen_element)then @@ -5096,6 +5129,19 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_storectfrac_si ) + call this%set_history_var(vname='FATES_STOREC_TFRAC_USTORY_SZPF', units='kg kg-1', & + long='Storage C fraction of target by size x pft, in the understory', use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_storectfrac_ustory_scpf ) + + + call this%set_history_var(vname='FATES_STOREC_TFRAC_CANOPY_SZPF', units='kg kg-1', & + long='Storage C fraction of target by size x pft, in the canopy', use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_storectfrac_canopy_scpf ) + + + call this%set_history_var(vname='FATES_VEGC', units='kg m-2', & long='total biomass in live plants in kg carbon per m2 land area', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & From 7b1a8b7aee6a9661184213b5a8e68f035e035084 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 15 Apr 2022 15:22:37 -0400 Subject: [PATCH 167/852] Started work on root reabsorption for cnp optimization --- parteh/PRTAllometricCNPMod.F90 | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 4e411d3d5d..064eec22a1 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -446,6 +446,19 @@ subroutine DailyPRTAllometricCNP(this) target_c(repro_organ) = 0._r8 target_dcdd(repro_organ) = 0._r8 + ! =================================================================================== + ! Step 1: Evaluate nutrient storage in the plant. Depending on how low + ! these stores are, we will move proportionally more or less of the daily carbon + ! gain to increase the target fine-root biomass, fill up to target + ! and then attempt to get them up to stoichiometry targets. + ! =================================================================================== + + ! This routine updates the l2fr (leaf 2 fine-root multiplier) variable + call this%CNPAdjustFRootTargets(target_c) + + + + c_gain0 = c_gain n_gain0 = n_gain p_gain0 = p_gain @@ -464,15 +477,7 @@ subroutine DailyPRTAllometricCNP(this) state_p0(i_org) = this%variables(i_var)%val(1) end do - ! =================================================================================== - ! Step 1: Evaluate nutrient storage in the plant. Depending on how low - ! these stores are, we will move proportionally more or less of the daily carbon - ! gain to increase the target fine-root biomass, fill up to target - ! and then attempt to get them up to stoichiometry targets. - ! =================================================================================== - - ! This routine updates the l2fr (leaf 2 fine-root multiplier) variable - call this%CNPAdjustFRootTargets(target_c) + ! Output only boundary conditions c_efflux => this%bc_out(acnp_bc_out_id_cefflux)%rval; c_efflux = 0._r8 @@ -742,7 +747,11 @@ subroutine CNPAdjustFRootTargets(this, target_c) ! generate mass check errors in the main CNPAllocation routine, this is because the "val" is ! changing but the net_allocated is not reciprocating, which is expected. - fnrt_c_above_target = max(0._r8,this%GetState(fnrt_organ, carbon12_element) - target_c(fnrt_organ)) + ! Don't remove roots that will be gone due to natural turnover + + store_c = this%GetState(fnrt_organ, carbon12_element)*(1._r8-(years_per_day / prt_params%root_long(ipft))) + + fnrt_c_above_target = max(0._r8,store_c - target_c(fnrt_organ)) loss_flux_c = 0._r8 From 8f994c29af81d7d42d994977e4c78f63df19f34d Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Fri, 15 Apr 2022 19:21:30 -0700 Subject: [PATCH 168/852] [ Fix canopy too full error with damage code ] [ Remove a bad call to carea_allom within tree_sai that was accidently changing crown area of damaged trees ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary: no testing --- biogeochem/EDCanopyStructureMod.F90 | 40 +++++++++++++++++++---------- biogeochem/EDCohortDynamicsMod.F90 | 4 +-- biogeochem/EDPatchDynamicsMod.F90 | 12 ++++++--- biogeochem/EDPhysiologyMod.F90 | 2 +- biogeochem/FatesAllometryMod.F90 | 15 +++++------ 5 files changed, 43 insertions(+), 30 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 42b5fa3e2e..f611bb4dd0 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -866,7 +866,7 @@ subroutine PromoteIntoLayer(currentSite,currentPatch,i_lyr) currentCohort => currentPatch%tallest do while (associated(currentCohort)) call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread, & - currentCohort%pft,currentCohort%c_area) + currentCohort%pft,currentCohort%crowndamage,currentCohort%c_area) if(currentCohort%canopy_layer == i_lyr+1)then !look at the cohorts in the canopy layer below... if (ED_val_comp_excln .ge. 0.0_r8 ) then @@ -1412,6 +1412,8 @@ subroutine canopy_summarization( nsites, sites, bc_in ) currentPatch => currentPatch%younger end do !patch loop + + call leaf_area_profile(sites(s)) end do ! site loop @@ -1508,7 +1510,8 @@ subroutine leaf_area_profile( currentSite ) real(r8) :: max_chite ! top of cohort canopy (m) real(r8) :: lai ! summed lai for checking m2 m-2 real(r8) :: leaf_c ! leaf carbon [kg] - + real(r8) :: target_c_area ! for tree sai - need an undamaged version + !---------------------------------------------------------------------- smooth_leaf_distribution = 0 @@ -1537,7 +1540,7 @@ subroutine leaf_area_profile( currentSite ) currentPatch%layer_height_profile(:,:,:) = 0._r8 currentPatch%canopy_area_profile(:,:,:) = 0._r8 currentPatch%canopy_mask(:,:) = 0 - + ! ------------------------------------------------------------------------------ ! It is remotely possible that in deserts we will not have any canopy ! area, ie not plants at all... @@ -1545,13 +1548,13 @@ subroutine leaf_area_profile( currentSite ) if (currentPatch%total_canopy_area > nearzero ) then - currentCohort => currentPatch%tallest do while(associated(currentCohort)) ft = currentCohort%pft cl = currentCohort%canopy_layer + ! Calculate LAI of layers above ! Note that the canopy_layer_lai is also calculated in this loop ! but since we go top down in terms of plant size, we should be okay @@ -1562,17 +1565,21 @@ subroutine leaf_area_profile( currentSite ) currentCohort%n, currentCohort%canopy_layer, & currentPatch%canopy_layer_tlai,currentCohort%vcmax25top ) + call carea_allom(currentCohort%dbh, currentCohort%n, currentSite%spread, currentCohort%pft, & + 1, target_c_area) + if (hlm_use_sp .eq. ifalse) then currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh,& - currentSite%spread, currentCohort%canopy_trim, & - currentCohort%c_area, currentCohort%n, currentCohort%canopy_layer, & + currentCohort%canopy_trim, & + target_c_area, currentCohort%n, currentCohort%canopy_layer, & currentPatch%canopy_layer_tlai, currentCohort%treelai , & currentCohort%vcmax25top,4) end if - + currentCohort%lai = currentCohort%treelai *currentCohort%c_area/currentPatch%total_canopy_area + currentCohort%sai = currentCohort%treesai *currentCohort%c_area/currentPatch%total_canopy_area - + ! Number of actual vegetation layers in this cohort's crown currentCohort%nv = count((currentCohort%treelai+currentCohort%treesai) .gt. dlower_vai(:)) + 1 @@ -1582,10 +1589,12 @@ subroutine leaf_area_profile( currentSite ) currentPatch%canopy_layer_tlai(cl) = currentPatch%canopy_layer_tlai(cl) + currentCohort%lai + currentCohort => currentCohort%shorter enddo !currentCohort + if(smooth_leaf_distribution == 1)then ! ----------------------------------------------------------------------------- @@ -1652,6 +1661,7 @@ subroutine leaf_area_profile( currentSite ) enddo !currentCohort + ! ----------------------------------------------------------------------------- ! Perform a leaf area conservation check on the LAI profile lai = 0.0_r8 @@ -1672,8 +1682,6 @@ subroutine leaf_area_profile( currentSite ) ! Go through all cohorts and add their leaf area ! and canopy area to the accumulators. ! ----------------------------------------------------------------------------- - - currentCohort => currentPatch%shortest do while(associated(currentCohort)) ft = currentCohort%pft @@ -1776,7 +1784,7 @@ subroutine leaf_area_profile( currentSite ) currentCohort => currentCohort%taller enddo !cohort - + ! -------------------------------------------------------------------------- ! If there is an upper-story, the top canopy layer @@ -1924,7 +1932,8 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) real(r8) :: total_canopy_area real(r8) :: total_patch_leaf_stem_area real(r8) :: weight ! Weighting for cohort variables in patch - + real(r8) :: target_c_area + do s = 1,nsites ifp = 0 @@ -1990,9 +1999,12 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) currentCohort%pft, currentCohort%c_area, currentCohort%n, & currentCohort%canopy_layer, currentPatch%canopy_layer_tlai,currentCohort%vcmax25top ) + call carea_allom(currentCohort%dbh,currentCohort%n,sites(s)%spread,& + currentCohort%pft,1, target_c_area) + currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, & - site(s)%spread, currentCohort%canopy_trim, & - currentCohort%c_area, currentCohort%n, currentCohort%canopy_layer, & + currentCohort%canopy_trim, & + target_c_area, currentCohort%n, currentCohort%canopy_layer, & currentPatch%canopy_layer_tlai, currentCohort%treelai , & currentCohort%vcmax25top,4) endif diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index cfbeb1c174..7d04ce2f07 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -285,7 +285,7 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & patchptr%canopy_layer_tlai,new_cohort%vcmax25top ) if(hlm_use_sp.eq.ifalse)then - new_cohort%treesai = tree_sai(new_cohort%pft, new_cohort%dbh, currentSite%spread, & + new_cohort%treesai = tree_sai(new_cohort%pft, new_cohort%dbh, & new_cohort%canopy_trim, & new_cohort%c_area, new_cohort%n, new_cohort%canopy_layer, & patchptr%canopy_layer_tlai, new_cohort%treelai,new_cohort%vcmax25top,2 ) @@ -1380,7 +1380,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh,& - currentSite%spread, currentCohort%canopy_trim, & + currentCohort%canopy_trim, & currentCohort%c_area, newn, currentCohort%canopy_layer, & currentPatch%canopy_layer_tlai, currentCohort%treelai,currentCohort%vcmax25top,1 ) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 92a69389e0..546e2727cc 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -538,6 +538,7 @@ subroutine spawn_patches( currentSite, bc_in) logical :: found_youngest_primary ! logical for finding the first primary forest patch integer :: min_nocomp_pft, max_nocomp_pft, i_nocomp_pft + !--------------------------------------------------------------------- real(r8), parameter :: damage_error_fail = 1.0e-6_r8 @@ -1308,7 +1309,7 @@ subroutine spawn_patches( currentSite, bc_in) ! update crown area here - for cohort fusion and canopy organisation below call carea_allom(nc_d%dbh, nc_d%n, currentSite%spread,& nc_d%pft, nc_d%crowndamage, nc_d%c_area) - + call get_crown_reduction(nc_d%crowndamage, mass_frac) @@ -1385,10 +1386,15 @@ subroutine spawn_patches( currentSite, bc_in) end do ! end crowndamage loop ! Reduce currentCohort%n now based on sum of all new damage classes + ! And update c_area of the undamaged cohort (since number density has changed) if(hlm_use_canopy_damage .eq. itrue) then currentCohort%n = currentCohort%n - cd_n_total + call carea_allom(currentCohort%dbh, currentCohort%n, currentSite%spread,& + currentCohort%pft, currentCohort%crowndamage, currentCohort%c_area) else if(hlm_use_understory_damage .eq. itrue) then nc%n = nc%n - cd_n_total + call carea_allom(nc%dbh, nc%n, currentSite%spread,& + nc%pft, nc%crowndamage, nc%c_area) end if @@ -1397,7 +1403,7 @@ subroutine spawn_patches( currentSite, bc_in) end if ! end if damage time end if ! end if damage is on - + ! Put new undamaged cohorts in the correct place in the linked list if (nc%n > 0.0_r8) then storebigcohort => new_patch%tallest @@ -1462,8 +1468,6 @@ subroutine spawn_patches( currentSite, bc_in) enddo ! currentPatch patch loop. - - !*************************/ !** INSERT NEW PATCH(ES) INTO LINKED LIST !*************************/ diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index d450dbcadf..92e4f60425 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -475,7 +475,7 @@ subroutine trim_canopy( currentSite ) currentCohort%treesai = tree_sai(currentCohort%pft, & currentCohort%dbh, & - currentSite%spread, currentCohort%canopy_trim, & + currentCohort%canopy_trim, & target_c_area, currentCohort%n,currentCohort%canopy_layer,& currentPatch%canopy_layer_tlai, currentCohort%treelai, & currentCohort%vcmax25top,0 ) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index 862a837782..a4858a6b25 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -737,7 +737,7 @@ end function tree_lai ! ============================================================================ - real(r8) function tree_sai(pft, dbh, site_spread, canopy_trim, target_c_area, nplant, cl, & + real(r8) function tree_sai(pft, dbh, canopy_trim, c_area, nplant, cl, & canopy_lai, treelai, vcmax25top, call_id ) ! ============================================================================ @@ -745,10 +745,9 @@ real(r8) function tree_sai(pft, dbh, site_spread, canopy_trim, target_c_area, np ! ============================================================================ integer, intent(in) :: pft - real(r8), intent(inout) :: dbh - real(r8), intent(in) :: site_spread - real(r8), intent(inout) :: target_c_area + real(r8), intent(in) :: dbh real(r8), intent(in) :: canopy_trim ! trimming function (0-1) + real(r8), intent(in) :: c_area ! crown area (m2) real(r8), intent(in) :: nplant ! number of plants integer, intent(in) :: cl ! canopy layer index real(r8), intent(in) :: canopy_lai(nclmax) ! total leaf area index of @@ -763,10 +762,8 @@ real(r8) function tree_sai(pft, dbh, site_spread, canopy_trim, target_c_area, np ! target undamaged bleaf call bleaf(dbh, pft, 1, canopy_trim, target_bleaf) - - call carea_allom(dbh, nplant, site_spread, pft, 1, target_c_area, inverse = .false.) - - target_lai = tree_lai(target_bleaf, pft, target_c_area, nplant, cl,& + + target_lai = tree_lai(target_bleaf, pft, c_area, nplant, cl,& canopy_lai, vcmax25top) tree_sai = prt_params%allom_sai_scaler(pft) * target_lai @@ -780,7 +777,7 @@ real(r8) function tree_sai(pft, dbh, site_spread, canopy_trim, target_c_area, np write(fates_log(),*) 'sai: ',tree_sai write(fates_log(),*) 'lai+sai: ',treelai+tree_sai write(fates_log(),*) 'target_bleaf: ', target_bleaf - write(fates_log(),*) 'target_c_area: ', target_c_area + write(fates_log(),*) 'area: ', c_area write(fates_log(),*) 'target_lai: ',target_lai write(fates_log(),*) 'dinc_vai:',dinc_vai write(fates_log(),*) 'nlevleaf,sum(dinc_vai):',nlevleaf,sum(dinc_vai) From 85f0dba3c8ffd9f2481ba7a0771deb23c3e38893 Mon Sep 17 00:00:00 2001 From: Jacquelyn Shuman Date: Sat, 16 Apr 2022 19:24:31 -0600 Subject: [PATCH 169/852] Update active crown fire per Scott and Reinhardt 2001, Rothermel 1977 Calculate required intensity to scorch crown and canopy, then re-calculate rate of spread and fire intensity Fixes: 573 User interface changes?: No Code review: --- fire/SFMainMod.F90 | 786 ++++++++++++++++++++++++++++++--------------- 1 file changed, 520 insertions(+), 266 deletions(-) diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index 6b0197dfcc..30a3e9e644 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -54,10 +54,12 @@ module SFMainMod public :: fire_model public :: fire_danger_index public :: characteristics_of_fuel + public :: characteristics_of_crown public :: rate_of_spread public :: ground_fuel_consumption public :: wind_effect public :: area_burnt_intensity + public :: active_crown_fire public :: crown_scorching public :: crown_damage public :: cambial_damage_kill @@ -87,13 +89,19 @@ subroutine fire_model( currentSite, bc_in) type (ed_patch_type), pointer :: currentPatch - real(r8) :: MEF(nfsc) ! Moisture extinction factor of fuels - real(r8) :: fuel_moisture(nfsc) ! Scaled moisture content of small litter fuels + real(r8) :: canopy_fuel_load ! available canopy fuel load in patch (kg biomass) + real(r8) :: passive_crown_FI ! fire intensity for ignition of passive canopy fuel (kW/m) + real(r8) :: ROS_torch ! ROS for crown torch initation (m/min) + real(r8) :: lb !length to breadth ratio of fire ellipse (unitless) + real(r8) :: heat_per_area ! heat release per unit area (kJ/m2) for surface fuel + !zero fire things currentPatch => currentSite%youngest_patch do while(associated(currentPatch)) currentPatch%frac_burnt = 0.0_r8 + currentPatch%FI = 0.0_r8 + currentPatch%FD = 0.0_r8 currentPatch%fire = 0 currentPatch%active_crown_fire_flg = 0 currentPatch => currentPatch%older @@ -106,21 +114,14 @@ subroutine fire_model( currentSite, bc_in) if( hlm_spitfire_mode > hlm_sf_nofire_def )then call fire_danger_index(currentSite, bc_in) call wind_effect(currentSite, bc_in) - call characteristics_of_fuel(currentSite, MEF, fuel_moisture) - call rate_of_spread(currentSite, MEF, fuel_moisture) + call characteristics_of_fuel(currentSite) + call characteristics_of_crown(currentSite, canopy_fuel_load, passive_crown_FI) + call rate_of_spread(currentSite, passive_crown_FI, ROS_torch, heat_per_area) call ground_fuel_consumption(currentSite) - call area_burnt_intensity(currentSite, bc_in) + call area_burnt_intensity(currentSite, bc_in, lb) + call active_crown_fire (currentSite,passive_crown_FI,canopy_fuel_load,ROS_torch,heat_per_area,lb) call crown_scorching(currentSite) call crown_damage(currentSite) - ! Begin: Repeat calls to calculate effects of active crown fire - ! TODO slevis: if (currentPatch%active_crown_fire_flg) > 0) - ! at any Patch at this Site, then execute the repeat calls. - ! NB. this subroutine runs at the Site level. -! call rate_of_spread(currentSite, MEF, fuel_moisture) -! call area_burnt_intensity(currentSite, bc_in) -! call crown_scorching(currentSite) -! call crown_damage(currentSite) - ! End: Repeat calls to calculate effects of active crown fire call cambial_damage_kill(currentSite) call post_fire_mortality(currentSite) end if @@ -166,18 +167,18 @@ subroutine fire_danger_index ( currentSite, bc_in) else yipsolon = (SF_val_fdi_a* temp_in_C)/(SF_val_fdi_b+ temp_in_C)+log(max(1.0_r8,rh)/100.0_r8) dewpoint = (SF_val_fdi_b*yipsolon)/(SF_val_fdi_a-yipsolon) !Standard met. formula - d_NI = ( temp_in_C-dewpoint)* temp_in_C !follows Nesterov 1968. Equation 5. Thonicke et al. 2010. + d_NI = ( temp_in_C-dewpoint)* temp_in_C !follows Nesterov 1968. Eq 5, Thonicke et al. 2010. if (d_NI < 0.0_r8) then !Change in NI cannot be negative. d_NI = 0.0_r8 !check endif endif - currentSite%acc_NI = currentSite%acc_NI + d_NI !Accumulate Nesterov index over the fire season. + currentSite%acc_NI = currentSite%acc_NI + d_NI !Accumulate Nesterov index over fire season. end subroutine fire_danger_index !***************************************************************** - subroutine characteristics_of_fuel ( currentSite, MEF, fuel_moisture ) + subroutine characteristics_of_fuel ( currentSite) !***************************************************************** use SFParamsMod, only: SF_val_drying_ratio, SF_val_SAV, SF_val_FBD, & @@ -189,12 +190,9 @@ subroutine characteristics_of_fuel ( currentSite, MEF, fuel_moisture ) type(ed_cohort_type), pointer :: currentCohort type(litter_type), pointer :: litt_c - ! ARGUMENTS - real(r8), intent(out) :: MEF(nfsc) ! Moisture extinction factor of fuels integer n - real(r8), intent(out) :: fuel_moisture(nfsc) ! Scaled moisture content of small litter fuels - - ! LOCAL VARIABLES real(r8) alpha_FMC(nfsc) ! Relative fuel moisture adjusted per drying ratio + real(r8) fuel_moisture(nfsc) ! Scaled moisture content of small litter fuels + real(r8) MEF(nfsc) ! Moisture extinction factor of fuels, integer n fuel_moisture(:) = 0.0_r8 @@ -254,9 +252,9 @@ subroutine characteristics_of_fuel ( currentSite, MEF, fuel_moisture ) currentPatch%fuel_frac(lg_sf) = currentPatch%livegrass / currentPatch%sum_fuel ! MEF (moisure of extinction) depends on compactness of fuel, depth, particle size, wind, slope - ! Eqn here is eqn 27 from Peterson and Ryan (1986) "Modeling Postfire Conifer Mortality for Long-Range Planning" + ! Eq here is Eq 27 from Peterson and Ryan (1986) "Modeling Postfire Conifer Mortality for Long-Range Planning" ! but lots of other approaches in use out there... - ! MEF: pine needles=0.30 (text near EQ 28 Rothermal 1972) + ! MEF: pine needles=0.30 (text near Eq 28 Rothermal 1972) ! Table II-1 NFFL mixed fuels models from Rothermal 1983 Gen. Tech. Rep. INT-143 ! MEF: short grass=0.12,tall grass=0.25,chaparral=0.20,closed timber litter=0.30,hardwood litter=0.25 ! Thonicke 2010 SAV values propagated thru P&R86 eqn below gives MEF:tw=0.355, sb=0.44, lb=0.525, tr=0.63, dg=0.248, lg=0.248 @@ -350,6 +348,156 @@ subroutine characteristics_of_fuel ( currentSite, MEF, fuel_moisture ) end subroutine characteristics_of_fuel + !**************************************************************** + subroutine characteristics_of_crown ( currentSite, canopy_fuel_load, passive_crown_FI) + !****************************************************************. + + !returns the live crown fuel characteristics within each patch. + ! passive_crown_FI is minimum fire intensity to ignite canopy crown fuel + + use SFParamsMod, only : SF_VAL_CWD_FRAC + + type(ed_site_type), intent(in), target :: currentSite + + type(ed_patch_type) , pointer :: currentPatch + type(ed_cohort_type), pointer :: currentCohort + + ! ARGUMENTS + real(r8), intent(out) :: canopy_fuel_load ! available canopy fuel load in patch (kg biomass) + real(r8), intent(out) :: passive_crown_FI ! min fire intensity to ignite canopy fuel (kW/m) + + ! LOCAL + real(r8) :: crown_depth ! depth of crown (m) + real(r8) :: height_cbb ! clear branch bole height or crown base height (m) + real(r8) :: max_height ! max cohort on patch (m) + real(r8) :: crown_ignite_energy ! heat yield for crown (kJ/kg) + real(r8) :: tree_sapw_struct_c ! above-ground tree struct and sap biomass in cohort (kgC) + real(r8) :: leaf_c ! leaf carbon (kgC) + real(r8) :: sapw_c ! sapwood carbon (kgC) + real(r8) :: struct_c ! structure carbon (kgC) + real(r8) :: twig_sapw_struct_c ! above-ground twig sap and struct in cohort (kgC) + real(r8) :: crown_fuel_c ! biomass of 1 hr fuels (leaves,twigs) in cohort (kg C) + real(r8) :: crown_fuel_biomass ! biomass of crown fuel in cohort (kg biomass) + real(r8) :: crown_fuel_per_m ! crown fuel per 1m section in cohort + real(r8) :: height_base_canopy ! lowest height of fuels in patch to carry fire in crown + real(r8) :: canopy_bulk_density ! density of canopy fuel on patch + + integer :: ih ! counter + + real, dimension(70):: biom_matrix ! matrix to track biomass from bottom to 70m + real(r8),parameter :: min_density_canopy_fuel = 0.011_r8 !min canopy fuel density (kg/m3) sufficient to + !propogate fire vertically through canopy + !Scott and Reinhardt 2001 RMRS-RP-29 + real(r8),parameter :: foliar_moist_content = 1.0_r8 !foliar moisture content default 100% Scott & Reinhardt 2001 + + + !returns the live crown fuel characteristics within each patch. + ! passive_crown_FI is the required minimum fire intensity to ignite canopy crown fuel + + currentPatch => currentSite%oldest_patch + + !! check to see if active_crown_fire is enabled? + + do while(associated(currentPatch)) + !zero Patch level variables + height_base_canopy = 0.0_r8 + canopy_fuel_load = 0.0_r8 + passive_crown_FI = 0.0_r8 + + if (currentPatch%fire == 1) then + + currentCohort=>currentPatch%tallest + do while(associated(currentCohort)) + + !zero cohort level variables + tree_sapw_struct_c = 0.0_r8 + leaf_c = 0.0_r8 + sapw_c = 0.0_r8 + struct_c = 0.0_r8 + twig_sapw_struct_c = 0.0_r8 + crown_fuel_c = 0.0_r8 + crown_fuel_biomass = 0.0_r8 + crown_fuel_per_m = 0.0_r8 + + ! Calculate crown 1hr fuel biomass (leaf, twig sapwood, twig structural biomass) + if ( int(prt_params%woody(currentCohort%pft)) == itrue) then !trees + + call CrownDepth(currentCohort%hite,currentCohort%pft,crown_depth) + height_cbb = currentCohort%hite - crown_depth + + !find patch max height for stand canopy fuel + if (currentCohort%hite > max_height) then + max_height = currentCohort%hite + endif + + leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) + sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) + struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) + + tree_sapw_struct_c = currentCohort%n * & + (prt_params%allom_agb_frac(currentCohort%pft)*(sapw_c + struct_c)) + + twig_sapw_struct_c = tree_sapw_struct_c * SF_VAL_CWD_frac(1) !only 1hr fuel + + crown_fuel_c = (currentCohort%n * leaf_c) + twig_sapw_struct_c !crown fuel (kgC) + + crown_fuel_biomass = crown_fuel_c / 0.45_r8 ! crown fuel (kg biomass) + + crown_fuel_per_m = crown_fuel_biomass / crown_depth ! kg biomass per m + + !sort crown fuel into bins from bottom to top of crown + !accumulate across cohorts to find density within canopy 1m sections + do ih = int(height_cbb), int(currentCohort%hite) + biom_matrix(ih) = biom_matrix(ih) + crown_fuel_per_m + end do + + !accumulate available canopy fuel for patch (kg biomass) + ! use this in CFB (crown fraction burn) calculation and FI final + canopy_fuel_load = canopy_fuel_load + crown_fuel_biomass !canopy fuel in patch + + endif !trees only + + currentCohort => currentCohort%shorter; + + enddo !end cohort loop + + biom_matrix(:) = biom_matrix(:) / currentPatch%area !kg biomass/m3 + + !loop from 1m to 70m to find bin with total density = 0.011 kg/m3 + !min canopy fuel density to propogate fire vertically in canopy across patch + do ih=1,70 + if (biom_matrix(ih) > min_density_canopy_fuel) then + height_base_canopy = float(ih) + exit + end if + end do + + !canopy_bulk_denisty (kg/m3) for Patch + canopy_bulk_density = sum(biom_matrix) / (max_height - height_base_canopy) + + ! Note: crown_ignition_energy to be calculated based on PFT foliar moisture content from FATES-Hydro + ! or create foliar moisture % based on BTRAN + ! Use foliar_moisture(currentCohort%pft) and compute weighted PFT average with Eq 3 Van Wagner 1977 + ! in place of foliar_moist_content parameter + + ! Eq 3 Van Wagner 1977, Eq 11 Scott & Reinhardt 2001 + ! h = 460.0 + 25.9*m + ! h = crown_ignite_energy (kJ/kg), m = foliar moisture content based on dry fuel (%) + crown_ignite_energy = 460.0 + 25.9 * foliar_moist_content + + ! Crown fuel ignition potential (kW/m), Eq 4 Van Wagner 1977, Eq 11 Scott & Reinhardt 2001 + ! FI = (Czh)**3/2 where z=canopy base height,h=heat of crown ignite energy, FI=fire intensity + ! 0.01 = C, empirical constant Van Wagner 1977 Eq 4 for 6m canopy base height, 100% FMC, FI 2500kW/m + ! passive_crown_FI = min fire intensity to ignite canopy fuel (kW/m or kJ/m/s) + passive_crown_FI = (0.01_r8 * height_base_canopy * crown_ignite_energy)**1.5_r8 + + endif ! fire? + + currentPatch => currentPatch%younger; + + enddo !end patch loop + + end subroutine characteristics_of_crown !***************************************************************** subroutine wind_effect ( currentSite, bc_in) @@ -436,14 +584,13 @@ subroutine wind_effect ( currentSite, bc_in) end subroutine wind_effect - !***************************************************************** - subroutine rate_of_spread ( currentSite, MEF, fuel_moisture ) + !******************************************************************* + subroutine rate_of_spread ( currentSite, ROS_torch, passive_crown_FI, heat_per_area) !*****************************************************************. !Routine called daily from within ED within a site loop. !Returns the updated currentPatch%ROS_front value for each patch. - use SFParamsMod, only : SF_val_SAV, & - SF_val_drying_ratio, & + use SFParamsMod, only : SF_val_miner_total, & SF_val_part_dens, & SF_val_miner_damp, & SF_val_fuel_energy @@ -453,19 +600,14 @@ subroutine rate_of_spread ( currentSite, MEF, fuel_moisture ) type(ed_site_type), intent(in), target :: currentSite type(ed_patch_type), pointer :: currentPatch - type(ed_cohort_type), pointer :: currentCohort - type(litter_type), pointer :: litt_c ! ARGUMENTS - real(r8), intent(in) :: MEF(nfsc) ! Moisture extinction factor of fuels - real(r8), intent(in) :: fuel_moisture(nfsc) ! Scaled moisture content of small litter fuels + real(r8), intent(out) :: ROS_torch ! ROS for crown torch initation (m/min) + real(r8), intent(out) :: heat_per_area ! heat release per unit area (kJ/m2) for surface fuel + real(r8), intent(in) :: passive_crown_FI ! min fire intensity to ignite canopy fuel (kW/m or kJ/m/s) ! LOCAL VARIABLES - real(r8) :: sum_fuel ! value saved for comparison - real(r8) :: leaf_c ! leaf carbon [kg] - real(r8) :: alpha_live_fuel ! ratio of mass fine live fuel to mass total fine fuel (1-hour fuels Rothermal 1972) - real(r8) :: fuel_eff_moist_dead - real(r8) :: fuel_mef_fine + ! Rothermal fire spread model parameters. real(r8) beta,beta_op ! weighted average of packing ratio (unitless) real(r8) ir ! reaction intensity (kJ/m2/min) @@ -476,15 +618,17 @@ subroutine rate_of_spread ( currentSite, MEF, fuel_moisture ) real(r8) beta_ratio ! ratio of beta/beta_op real(r8) a_beta ! dummy variable for product of a* beta_ratio for react_v_opt equation real(r8) a,b,c,e ! function of fuel sav + real(r8) time_r ! residence time (min) - logical, parameter :: debug_windspeed = .false. !for debugging - real(r8),parameter :: q_dry = 581.0_r8 !heat of pre-ignition of dry fuels (kJ/kg) + real(r8),parameter :: q_dry = 581.0_r8 !heat of pre-ignition of dry fuels (kJ/kg) + real(r8),parameter :: wind_reduce = 0.2_r8 !wind reduction factor (%) currentPatch=>currentSite%oldest_patch; - litt_c => currentPatch%litter(element_pos(carbon12_element)) do while(associated(currentPatch)) + +!! clean up this initialise to zero section?? ! ---initialise parameters to zero.--- beta_ratio = 0.0_r8; q_ig = 0.0_r8; eps = 0.0_r8; a = 0.0_r8; b = 0.0_r8; c = 0.0_r8; e = 0.0_r8 @@ -492,36 +636,6 @@ subroutine rate_of_spread ( currentSite, MEF, fuel_moisture ) moist_damp = 0.0_r8; ir = 0.0_r8; a_beta = 0.0_r8; currentPatch%ROS_front = 0.0_r8 - ! --------------------------------------------------- -! ! Active crown fire effects: https://github.com/NGEET/fates/issues/573 -! ! Update some characteristics of fuel -! ! TODO Would it make sense to move this section of code to subr. -! ! characteristics_of_fuel? -! sum_fuel = currentPatch%sum_fuel ! save for comparison later -! if (currentPatch%fire == 1 .and. currentPatch%active_crown_fire_flg == 1) then -! currentCohort=>currentPatch%tallest -! do while(associated(currentCohort)) -! ! Add the leaf carbon from each cohort to currentPatch%sum_fuel -! leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) -! currentPatch%sum_fuel = currentPatch%sum_fuel + leaf_c -! currentCohort => currentCohort%shorter; -! enddo !end cohort loop - -! ! if sum_fuel was indeed updated for a case of active crown fire, go -! ! on to update currentPatch%fuel_mef and currentPatch%fuel_eff_moist -! if (currentPatch%sum_fuel > sum_fuel) then -! alpha_live_fuel = (currentPatch%livegrass + leaf_c) / & -! (currentPatch%livegrass + leaf_c + sum(litt_c%leaf_fines(:)) + litt_c%ag_cwd(tw_sf)) -! fuel_eff_moist_dead = sum(currentPatch%fuel_frac(tw_sf:dl_sf) * fuel_moisture(tw_sf:dl_sf)) -! fuel_mef_fine = currentPatch%fuel_frac(tw_sf) * MEF(tw_sf) + & -! currentPatch%fuel_frac(dl_sf) * MEF(dl_sf) + & -! currentPatch%fuel_frac(lg_sf) * MEF(lg_sf) -! currentPatch%fuel_mef = max((2.9_r8 * ((1.0_r8 - alpha_live_fuel) / alpha_live_fuel) * (1.0_r8 - fuel_eff_moist_dead) - 0.226_r8), fuel_mef_fine) -! currentPatch%fuel_eff_moist = exp(-1.0_r8 * currentSite%acc_NI * SF_val_SAV(lg_sf) / SF_val_drying_ratio) -! end if -! end if - ! --------------------------------------------------- - ! ----start spreading--- if ( hlm_masterproc == itrue .and.debug) write(fates_log(),*) & @@ -533,7 +647,7 @@ subroutine rate_of_spread ( currentSite, MEF, fuel_moisture ) ! fraction of fuel array volume occupied by fuel or compactness of fuel bed beta = currentPatch%fuel_bulkd / SF_val_part_dens - ! Equation A6 in Thonicke et al. 2010 + ! Eq A6 in Thonicke et al. 2010 ! packing ratio (unitless) beta_op = 0.200395_r8 *(currentPatch%fuel_sav**(-0.8189_r8)) @@ -546,20 +660,20 @@ subroutine rate_of_spread ( currentSite, MEF, fuel_moisture ) endif ! ---heat of pre-ignition--- - ! Equation A4 in Thonicke et al. 2010 - ! Rothermal EQ12= 250 Btu/lb + 1116 Btu/lb * fuel_eff_moist - ! conversion of Rothermal (1972) EQ12 in BTU/lb to current kJ/kg + ! Eq A4 in Thonicke et al. 2010, Eq 12 Rothermel 1972 + ! 50 Btu/lb + 1116 Btu/lb * fuel_eff_moist + ! conversion of Rothermel (1972) Eq 12 in BTU/lb to current kJ/kg ! q_ig in kJ/kg - q_ig = q_dry +2594.0_r8 * currentPatch%fuel_eff_moist + q_ig = q_dry + 2594.0_r8 * currentPatch%fuel_eff_moist ! ---effective heating number--- - ! Equation A3 in Thonicke et al. 2010. + ! Eq A3 in Thonicke et al. 2010. eps = exp(-4.528_r8 / currentPatch%fuel_sav) - ! Equation A7 in Thonicke et al. 2010 per eqn 49 from Rothermel 1972 + ! Eq A7 in Thonicke et al. 2010 per Eq 49 Rothermel 1972 b = 0.15988_r8 * (currentPatch%fuel_sav**0.54_r8) - ! Equation A8 in Thonicke et al. 2010 per eqn 48 from Rothermel 1972 + ! Eq A8 in Thonicke et al. 2010 per Eq 48 Rothermel 1972 c = 7.47_r8 * (exp(-0.8711_r8 * (currentPatch%fuel_sav**0.55_r8))) - ! Equation A9 in Thonicke et al. 2010. (appears to have typo, using coefficient eqn.50 Rothermel 1972) + ! Eq A9 in Thonicke et al. 2010. (has typo, using coefficient Eq 50 Rothermel 1972) e = 0.715_r8 * (exp(-0.01094_r8 * currentPatch%fuel_sav)) if (debug) then @@ -571,35 +685,35 @@ subroutine rate_of_spread ( currentSite, MEF, fuel_moisture ) if ( hlm_masterproc == itrue .and.debug) write(fates_log(),*) 'SF - e ',e endif - ! Equation A5 in Thonicke et al. 2010 + ! Eq A5 in Thonicke et al. 2010 ! phi_wind (unitless) ! convert current_wspeed (wind at elev relevant to fire) from m/min to ft/min for Rothermel ROS eqn phi_wind = c * ((3.281_r8*currentPatch%effect_wspeed)**b)*(beta_ratio**(-e)) ! ---propagating flux---- - ! Equation A2 in Thonicke et al.2010 and Eq. 42 Rothermal 1972 + ! Eq A2 in Thonicke et al.2010 and Eq 42 Rothermel 1972 ! xi (unitless) xi = (exp((0.792_r8 + 3.7597_r8 * (currentPatch%fuel_sav**0.5_r8)) * (beta+0.1_r8))) / & (192_r8+7.9095_r8 * currentPatch%fuel_sav) ! ---reaction intensity---- - ! Equation in table A1 Thonicke et al. 2010. + ! Eq in table A1 Thonicke et al. 2010. a = 8.9033_r8 * (currentPatch%fuel_sav**(-0.7913_r8)) a_beta = exp(a*(1.0_r8-beta_ratio)) !dummy variable for reaction_v_opt equation - ! Equation in table A1 Thonicke et al. 2010. + ! Eq in table A1 Thonicke et al. 2010. ! reaction_v_max and reaction_v_opt = reaction velocity in units of per min - ! reaction_v_max = Equation 36 in Rothermal 1972 and Fig 12 + ! reaction_v_max = Eq 36 in Rothermel 1972 and Fig 12 reaction_v_max = 1.0_r8 / (0.0591_r8 + 2.926_r8* (currentPatch%fuel_sav**(-1.5_r8))) - ! reaction_v_opt = Equation 38 in Rothermal 1972 and Fig 11 + ! reaction_v_opt = Eq 38 in Rothermel 1972 and Fig 11 reaction_v_opt = reaction_v_max*(beta_ratio**a)*a_beta ! mw_weight = relative fuel moisture/fuel moisture of extinction ! average values for litter pools (dead leaves, twigs, small and large branches) plus grass mw_weight = currentPatch%fuel_eff_moist/currentPatch%fuel_mef - ! Equation in table A1 Thonicke et al. 2010. + ! Eq in table A1 Thonicke et al. 2010. ! moist_damp is unitless moist_damp = max(0.0_r8,(1.0_r8 - (2.59_r8 * mw_weight) + (5.11_r8 * (mw_weight**2.0_r8)) - & (3.52_r8*(mw_weight**3.0_r8)))) @@ -610,15 +724,28 @@ subroutine rate_of_spread ( currentSite, MEF, fuel_moisture ) ! write(fates_log(),*) 'ir',gamma_aptr,moist_damp,SF_val_fuel_energy,SF_val_miner_damp + if (((currentPatch%fuel_bulkd) <= 0.0_r8).or.(eps <= 0.0_r8).or.(q_ig <= 0.0_r8)) then currentPatch%ROS_front = 0.0_r8 - else ! Equation 9. Thonicke et al. 2010. + ROS_torch = 0.0_r8 + else ! Eq 9. Thonicke et al. 2010. ! forward ROS in m/min currentPatch%ROS_front = (ir*xi*(1.0_r8+phi_wind)) / (currentPatch%fuel_bulkd*eps*q_ig) ! write(fates_log(),*) 'ROS',currentPatch%ROS_front,phi_wind,currentPatch%effect_wspeed ! write(fates_log(),*) 'ros calcs',currentPatch%fuel_bulkd,ir,xi,eps,q_ig + + ! calculate heat release per unit area (HPA)(kJ/m2), Eq 2 Scott & Reinhardt 2001 + ! and residence time (min), Eq 3 Scott & Reinhardt 2001 + time_r = 12.595 / currentPatch%fuel_sav + heat_per_area = ir * time_r + + ! calculate torching index based on wind speed and crown fuels + ! ROS for crown torch initation (m/min), Eq 18 Scott & Reinhardt 2001 + ROS_torch = (1.0 / 54.683 * wind_reduce)* & + ((((60.0*passive_crown_FI*currentPatch%fuel_bulkd*eps*q_ig)/heat_per_area*ir*xi)-1.0) & + / (c*beta_ratio)**-e)**1/b endif - ! Equation 10 in Thonicke et al. 2010 + ! Eq 10 in Thonicke et al. 2010 ! backward ROS from Can FBP System (1992) in m/min ! backward ROS wind not changed by vegetation currentPatch%ROS_back = currentPatch%ROS_front*exp(-0.012_r8*currentSite%wind) @@ -653,7 +780,7 @@ subroutine ground_fuel_consumption ( currentSite ) do while(associated(currentPatch)) currentPatch%burnt_frac_litter(:) = 1.0_r8 ! Calculate fraction of litter is burnt for all classes. - ! Equation B1 in Thonicke et al. 2010--- + ! Eq B1 in Thonicke et al. 2010--- do c = 1, nfsc !work out the burnt fraction for all pools, even if those pools dont exist. moist = currentPatch%litter_moisture(c) ! 1. Very dry litter @@ -717,7 +844,7 @@ end subroutine ground_fuel_consumption !***************************************************************** - subroutine area_burnt_intensity ( currentSite, bc_in ) + subroutine area_burnt_intensity ( currentSite, bc_in, lb) !***************************************************************** !returns the updated currentPatch%FI value for each patch. @@ -733,37 +860,41 @@ subroutine area_burnt_intensity ( currentSite, bc_in ) use EDParamsMod, only : cg_strikes ! fraction of cloud-to-ground ligtning strikes use FatesConstantsMod, only : years_per_day use SFParamsMod, only : SF_val_fdi_alpha,SF_val_fuel_energy, & - SF_val_max_durat, SF_val_durat_slope, SF_val_fire_threshold + SF_val_max_durat, SF_val_durat_slope, SF_val_fire_threshold type(ed_site_type), intent(inout), target :: currentSite type(ed_patch_type), pointer :: currentPatch type(bc_in_type), intent(in) :: bc_in - real(r8) ROS !m/s - real(r8) W !kgBiomass/m2 - real(r8) :: tree_fraction_patch ! patch level. no units - real(r8) lb !length to breadth ratio of fire ellipse (unitless) - real(r8) df !distance fire has travelled forward in m - real(r8) db !distance fire has travelled backward in m - real(r8) AB !daily area burnt in m2 per km2 - - real(r8) size_of_fire !in m2 - real(r8) cloud_to_ground_strikes ! [fraction] depends on hlm_spitfire_mode - real(r8) anthro_ign_count ! anthropogenic ignition count/km2/day - integer :: iofp ! index of oldest fates patch + ! ARGUMENTS + real(r8), intent(out) :: lb !length to breadth ratio of fire ellipse (unitless) + + ! LOCAL VARIABLES + real(r8) ROS !rate of spread (m/s) + real(r8) W !available fuel (kgBiomass/m2) + real(r8) :: tree_fraction_patch !patch level. no units + real(r8) df !distance fire has travelled forward (m) + real(r8) db !distance fire has travelled backward (m) + real(r8) AB !daily area burnt (m2 per km2) + real(r8) size_of_fire !in m2 + real(r8) cloud_to_ground_strikes ! [fraction] depends on hlm_spitfire_mode + real(r8) anthro_ign_count ! anthropogenic ignition count/km2/day + integer :: iofp ! index of oldest fates patch real(r8), parameter :: pot_hmn_ign_counts_alpha = 0.0035_r8 ! Potential human ignition counts (alpha in Li et al. 2012) (#/person/month) - real(r8), parameter :: km2_to_m2 = 1000000.0_r8 !area conversion for square km to square m + real(r8), parameter :: km2_to_m2 = 1000000.0_r8 ! area conversion for square km to square m real(r8), parameter :: m_per_min__to__km_per_hour = 0.06_r8 ! convert wind speed from m/min to km/hr - real(r8), parameter :: forest_grassland_lengthtobreadth_threshold = 0.55_r8 ! tree canopy cover below which to use grassland length-to-breadth eqn + real(r8), parameter :: forest_grassland_lengthtobreadth_threshold = 0.55_r8 ! tree canopy cover below which to use + ! grassland length-to-breadth eqn + ! 0.55 = benchmark forest cover, Staver 2010 ! ---initialize site parameters to zero--- currentSite%NF_successful = 0._r8 - ! Equation 7 from Venevsky et al GCB 2002 (modification of equation 8 in Thonicke et al. 2010) + ! Eq 7 from Venevsky et al GCB 2002 (modification of Eqn 8, Thonicke et al. 2010) ! FDI 0.1 = low, 0.3 moderate, 0.75 high, and 1 = extreme ignition potential for alpha 0.000337 if (hlm_spitfire_mode == hlm_sf_successful_ignitions_def) then - currentSite%FDI = 1.0_r8 ! READING "SUCCESSFUL IGNITION" DATA - ! force ignition potential to be extreme + currentSite%FDI = 1.0_r8 ! READING "SUCCESSFUL IGNITION" DATA + ! force ignition potential to be extreme cloud_to_ground_strikes = 1.0_r8 ! cloud_to_ground = 1 = use 100% incoming observed ignitions else ! USING LIGHTNING DATA currentSite%FDI = 1.0_r8 - exp(-SF_val_fdi_alpha*currentSite%acc_NI) @@ -802,14 +933,14 @@ subroutine area_burnt_intensity ( currentSite, bc_in ) if (currentSite%NF > 0.0_r8) then - ! Equation 14 in Thonicke et al. 2010 + ! Eq 14 in Thonicke et al. 2010 ! fire duration in minutes currentPatch%FD = (SF_val_max_durat+1.0_r8) / (1.0_r8 + SF_val_max_durat * & exp(SF_val_durat_slope*currentSite%FDI)) if(write_SF == itrue)then if ( hlm_masterproc == itrue ) write(fates_log(),*) 'fire duration minutes',currentPatch%fd endif - !equation 15 in Arora and Boer CTEM model.Average fire is 1 day long. + !Eq 15 in Arora and Boer CTEM model.Average fire is 1 day long. !currentPatch%FD = 60.0_r8 * 24.0_r8 !no minutes in a day tree_fraction_patch = 0.0_r8 @@ -825,12 +956,12 @@ subroutine area_burnt_intensity ( currentSite, bc_in ) if ((currentPatch%effect_wspeed*m_per_min__to__km_per_hour) < 1._r8) then !16.67m/min = 1km/hr lb = 1.0_r8 else - if (tree_fraction_patch > forest_grassland_lengthtobreadth_threshold) then !benchmark forest cover, Staver 2010 - ! EQ 79 forest fuels (Canadian Forest Fire Behavior Prediction System Ont.Inf.Rep. ST-X-3, 1992) + if (tree_fraction_patch > forest_grassland_lengthtobreadth_threshold) then + ! Eq 79 forest fuels (Canadian Forest Fire Behavior Prediction System Ont.Inf.Rep. ST-X-3, 1992) lb = (1.0_r8 + (8.729_r8 * & ((1.0_r8 -(exp(-0.03_r8 * m_per_min__to__km_per_hour * currentPatch%effect_wspeed)))**2.155_r8))) - else ! EQ 80 grass fuels (CFFBPS Ont.Inf.Rep. ST-X-3, 1992, but with a correction from an errata published within - ! Information Report GLC-X-10 by Bottom et al., 2009 because there is a typo in CFFBPS Ont.Inf.Rep. ST-X-3, 1992) + else ! Eq 80 grass fuels (CFFBPS Ont.Inf.Rep. ST-X-3, 1992, with correction from errata published in + ! Inf.Rep. GLC-X-10 (Bottom et al., 2009) because of typo in CFFBPS Ont.Inf.Rep. ST-X-3, 1992) lb = (1.1_r8*((m_per_min__to__km_per_hour * currentPatch%effect_wspeed)**0.464_r8)) endif endif @@ -845,12 +976,12 @@ subroutine area_burnt_intensity ( currentSite, bc_in ) ! --- calculate area burnt--- if(lb > 0.0_r8) then - ! Equation 1 in Thonicke et al. 2010 + ! Eq 1 in Thonicke et al. 2010 ! To Do: Connect here with the Li & Levis GDP fire suppression algorithm. - ! Equation 16 in arora and boer model JGR 2005 + ! Eq 16 in arora and boer model JGR 2005 ! AB = AB *3.0_r8 - !size of fire = equation 14 Arora and Boer JGR 2005 (area of an ellipse) + !size of fire = Eq 14 Arora and Boer JGR 2005 (area of an ellipse) size_of_fire = ((pi_const/(4.0_r8*lb))*((df+db)**2.0_r8)) ! AB = daily area burnt = size fires in m2 * num ignitions per day per km2 * prob ignition starts fire @@ -873,12 +1004,12 @@ subroutine area_burnt_intensity ( currentSite, bc_in ) currentPatch%frac_burnt = 0._r8 endif ! lb - ROS = currentPatch%ROS_front / 60.0_r8 !m/min to m/sec - W = currentPatch%TFC_ROS / 0.45_r8 !kgC/m2 of burned area to kgbiomass/m2 of burned area + ROS = currentPatch%ROS_front / 60.0_r8 !m/min to m/sec for FI calculation + W = currentPatch%TFC_ROS / 0.45_r8 !kgC/m2 of burned area to kgbiomass/m2 of burned area - ! EQ 15 Thonicke et al 2010 - !units of fire intensity = (kJ/kg)*(kgBiomass/m2)*(m/min) - currentPatch%FI = SF_val_fuel_energy * W * ROS !kj/m/s, or kW/m + ! Eq 15 Thonicke et al 2010 + !units of fire intensity = (kJ/kg)*(kgBiomass/m2)*(m/sec) + currentPatch%FI = SF_val_fuel_energy * W * ROS !kj/m/s, or kW/m if(write_sf == itrue)then if( hlm_masterproc == itrue ) write(fates_log(),*) 'fire_intensity',currentPatch%fi,W,currentPatch%ROS_front @@ -905,6 +1036,270 @@ subroutine area_burnt_intensity ( currentSite, bc_in ) end subroutine area_burnt_intensity + !***************************************************************** + subroutine active_crown_fire ( currentSite, canopy_fuel_load, ROS_torch, & + lb, heat_per_area, passive_crown_FI) + !***************************************************************** + + !evaluates if there will be an active crown fire based on canopy fuel and rate of spread + !returns final rate of spread and fire intensity in patch with added fuel from active crown fire. + !currentCohort%fraction_crown_burned is the proportion of crown affected by fire + + use SFParamsMod, only : SF_val_miner_total, SF_val_part_dens, SF_val_miner_damp, & + SF_val_fuel_energy, SF_val_drying_ratio + + + type(ed_site_type), intent(in), target :: currentSite + + type(ed_patch_type) , pointer :: currentPatch + type(ed_cohort_type), pointer :: currentCohort + + ! ARGUMENTS + real(r8), intent(in) :: ROS_torch ! ROS for crown torch initation (m/min) + real(r8), intent(in) :: canopy_fuel_load ! available canopy fuel load in patch (kg biomass) + real(r8), intent(in) :: lb !length to breadth ratio of fire ellipse (unitless) + real(r8), intent(in) :: heat_per_area ! heat release per unit area (kJ/m2) for surface fuel + real(r8), intent(in) :: passive_crown_FI ! fire intensity for ignition of passive canopy fuel (kW/m) + + ! Active crown Rothermel fire spread model parameters using FM 10 + real(r8) beta,beta_op ! weighted average of packing ratio (unitless) + real(r8) ir ! reaction intensity (kJ/m2/min) + real(r8) xi,eps,phi_wind ! all are unitless + real(r8) q_ig ! heat of pre-ignition (kJ/kg) + real(r8) reaction_v_opt,reaction_v_max !reaction velocity (per min)!optimum and maximum + real(r8) moist_damp,mw_weight ! moisture dampening coefficient and ratio fuel moisture to extinction + real(r8) beta_ratio ! ratio of beta/beta_op + real(r8) a_beta ! dummy variable for product of a* beta_ratio for react_v_opt equation + real(r8) a,b,c,e ! function of fuel sav + real(r8) total_fuel ! total fuel (kg biomass/m2) + real(r8) net_fuel ! net fuel (kg biomass/m2) without minerals + real(r8) fuel_depth ! fuel depth (m) + real(r8) fuel_bd ! fuel bulk density (kg biomass/m3) + real(r8) fuel_sav ! fuels average sav + real(r8) fuel_eff_moist ! fuels effective moisture + real(r8) fuel_moist1hr ! moisture 1 hour fuels + real(r8) fuel_moist10hr ! moisture 10 hour fuels + real(r8) fuel_moist100hr ! moisture 100 hour fuels + real(r8) fuel_moistlive ! moisture live fuels + real(r8) SAV_1hr ! surface area to volume 1 hour fuels (twigs) + real(r8) SAV_10hr ! surface area to volume 10 hour fuels (small branches) + real(r8) SAV_100hr ! surface area to volume 100 hour fuels (large branches) + real(r8) SAV_live ! surface area to volume live fuels + real(r8) midflame_wind ! 40% of open wind speed, Scott & Reinhardt 2001 + real(r8) db ! distance fire has traveld backward (m) + real(r8) df ! distance fire has travelled forward (m) + real(r8) AB ! daily area burnt (m2 per km2) + real(r8) size_of_fire ! in m2 + real(r8) ROS_active ! actual rate of spread (m/min) using FM 10 fuels + real(r8) ROS_active_min ! minimum rate of spread to ignite active crown fire + real(r8) phi_wind_ROS_SA ! phi_wind for ROS_active_min, use to find open wind for ROS_SA + real(r8) wind_ROS_SA ! open windspeed for ROS surface fire where ROS_SA = ROS_active_min + real(r8) ROS_SA ! rate of spread for surface fire with wind_ROS_SA + real(r8) canopy_frac_burnt ! fraction of canopy fuels consumed (0, surface fire to 1,active crown fire) + real(r8) ROS_final ! final rate of spread for combined surface and canopy spread (m/min) + real(r8) FI_final ! final fireline intensity (kW/m or kJ/m/sec) with canopy consumption + + real(r8),parameter :: q_dry = 581.0_r8 !heat of pre-ignition of dry fuels (kJ/kg) + ! fuel loading, MEF, and depth from Anderson 1982 Aids to determining fuel models for fire behavior + ! SAV values from BEHAVE model Burgan & Rothermel 1984) + real(r8),parameter :: fuel_1hr = 3.01_r8 ! FM 10 1-hr fuel loading (US tons/acre) + real(r8),parameter :: fuel_10hr = 2.0_r8 ! FM 10 10-hr fuel loading (US tons/acre) + real(r8),parameter :: fuel_100hr = 5.01_r8 ! FM 10 100-hr fuel loading (US tons/acre) + real(r8),parameter :: fuel_live = 2.0_r8 ! FM 10 live fuel loading (US tons/acre) + real(r8),parameter :: fuel_mef = 0.25_r8 ! FM 10 moisture of extinction (volumetric) + real(r8),parameter :: fuel_depth_ft= 1.0_r8 ! FM 10 fuel depth (ft) + real(r8),parameter :: sav_1hr_ft = 2000.0_r8 ! FM 10 1-hr SAV (ft2/ft3) + real(r8),parameter :: sav_10hr_ft = 109.0_r8 ! FM 10 10-hr SAV (ft2/ft3) + real(r8),parameter :: sav_100hr_ft = 30.0_r8 ! FM 10 100-hr SAV (ft2/ft3) + real(r8),parameter :: sav_live_ft = 1650.0_r8 ! FM 10 live SAV (ft2/ft3) + real(r8),parameter :: tonnes_acre_to_kg_m2 = 0.2241701 ! convert tons/acre to kg/m2 + real(r8),parameter :: sqft_cubicft_to_sqm_cubicm = 0.03280844 !convert ft2/ft3 to m2/m3 + real(r8),parameter :: canopy_ignite_energy = 18000_r8 ! heat yield for canopy fuels (kJ/kg) + real(r8),parameter :: critical_mass_flow_rate = 0.05_r8 ! critical mass flow rate (kg/m2/sec)for crown fire + real(r8),parameter :: km2_to_m2 = 1000000.0_r8 ! area conversion for square km to square m + + integer :: passive_canopy_fuel_flg ! flag if canopy fuel true for vertical spread + + + currentPatch => currentSite%oldest_patch + + !! check to see if active_crown_fire is enabled + + do while(associated(currentPatch)) + + if (currentPatch%fire == 1) then + passive_canopy_fuel_flg = 0 !does patch have canopy fuels for vertical spread? + ROS_active = 0.0_r8 + + ! check initiation of passive crown fire + if (currentPatch%FI >= passive_crown_FI) then + passive_canopy_fuel_flg = 1 !enough passive canopy fuels for vertical spread + + ! Calculate rate of spread using FM 10 as in Rothermel 1977 + ! fuel characteristics + total_fuel = (fuel_1hr + fuel_10hr + fuel_100hr + fuel_live) * tonnes_acre_to_kg_m2 + + SAV_1hr = sav_1hr_ft * sqft_cubicft_to_sqm_cubicm + SAV_10hr = sav_10hr_ft * sqft_cubicft_to_sqm_cubicm + SAV_100hr = sav_100hr_ft * sqft_cubicft_to_sqm_cubicm + SAV_live = sav_live_ft * sqft_cubicft_to_sqm_cubicm + + fuel_moist1hr = exp(-1.0_r8 * ((SAV_1hr/SF_val_drying_ratio) * currentSite%acc_NI)) + fuel_moist10hr = exp(-1.0_r8 * ((SAV_10hr/SF_val_drying_ratio) * currentSite%acc_NI)) + fuel_moist100hr = exp(-1.0_r8 * ((SAV_100hr/SF_val_drying_ratio) * currentSite%acc_NI)) + fuel_moistlive = exp(-1.0_r8 * ((SAV_live/SF_val_drying_ratio) * currentSite%acc_NI)) + + fuel_depth = fuel_depth_ft *0.3048 !convert to meters + fuel_bd = total_fuel/fuel_depth + + fuel_sav = SAV_1hr *(fuel_1hr/total_fuel) + SAV_10hr*(fuel_10hr/total_fuel) + & + SAV_100hr*(fuel_100hr/total_fuel) + SAV_live*(fuel_live/total_fuel) + + fuel_eff_moist = fuel_moist1hr *(fuel_1hr/total_fuel) + fuel_moist10hr*(fuel_10hr/total_fuel) + & + fuel_moist100hr*(fuel_100hr/total_fuel) + fuel_moistlive*(fuel_live/total_fuel) + + ! remove mineral content from net fuel load + net_fuel = total_fuel * (1.0_r8 - SF_val_miner_total) !net of minerals + + ! ---start spreading--- + !beta = packing ratio (unitless) + beta = fuel_bd / SF_val_part_dens + beta_op = 0.200395_r8 *(fuel_sav**(-0.8189_r8)) + beta_ratio = beta/beta_op + + ! -- heat of pre-ignition -- + q_ig = q_dry + 2594.0 * fuel_eff_moist + + ! ---effective heating number--- + ! Eq A3 in Thonicke et al. 2010. + eps = exp(-4.528_r8 / fuel_sav) + ! Eq A7 in Thonicke et al. 2010 per Eq 49, Rothermel 1972 + b = 0.15988_r8 * (fuel_sav**0.54_r8) + ! Eq A8 in Thonicke et al. 2010 per Eq 48, Rothermel 1972 + c = 7.47_r8 * (exp(-0.8711_r8 * (fuel_sav**0.55_r8))) + ! Eq A9 in Thonicke et al. 2010. (typo in Eq A9, using coefficient Eq 50, Rothermel 1972) + e = 0.715_r8 * (exp(-0.01094_r8 * fuel_sav)) + + midflame_wind = currentSite%wind *0.40_r8 !Scott & Reinhardt 2001 40% open wind speed + + ! Eq A5 in Thonicke et al. 2010 + ! convert current_wspeed (wind at elev relevant to fire) from m/min to ft/min for Rothermel ROS eqn + phi_wind = c * ((3.281_r8*midflame_wind)**b)*(beta_ratio**(-e)) !unitless + + ! ---propagating flux = xi (unitless) + ! Eq A2 in Thonicke et al.2010 and Eq 42 Rothermel 1972 + xi = (exp((0.792_r8 + 3.7597_r8 * (fuel_sav**0.5_r8)) * (beta+0.1_r8))) / & + (192_r8+7.9095_r8 * fuel_sav) + + ! ---reaction intensity---- + ! Eq in table A1 Thonicke et al. 2010. + a = 8.9033_r8 * (fuel_sav**(-0.7913_r8)) + a_beta = exp(a*(1.0_r8-beta_ratio)) !dummy variable for reaction_v_opt equation + + ! Eq in table A1 Thonicke et al. 2010. + ! reaction_v_max and reaction_v_opt = reaction velocity in units of per min + ! reaction_v_max = Eq 36 in Rothermel 1972 and Fig 12 + reaction_v_max = 1.0_r8 / (0.0591_r8 + 2.926_r8* (fuel_sav**(-1.5_r8))) + ! reaction_v_opt = Eq 38 in Rothermel 1972 and Fig 11 + reaction_v_opt = reaction_v_max*(beta_ratio**a)*a_beta + + ! mw_weight = relative fuel moisture/fuel moisture of extinction + mw_weight = fuel_eff_moist/fuel_mef + + ! Eq in table A1 Thonicke et al. 2010. (unitless) + moist_damp = max(0.0_r8,(1.0_r8 - (2.59_r8 * mw_weight) + (5.11_r8 * (mw_weight**2.0_r8)) - & + (3.52_r8*(mw_weight**3.0_r8)))) + + ! ir = reaction intenisty in kJ/m2/min + ! sum_fuel as kgBiomass/m2 for ir calculation + ir = reaction_v_opt*(net_fuel)*SF_val_fuel_energy*moist_damp*SF_val_miner_damp + + ! actual ROS (m/min) for FM 10 fuels for open windspeed, Eq 8 Scott & Reinhardt 2001 + ROS_active = 3.34*((ir*xi*(1.0_r8+phi_wind)) / (fuel_bd * eps * q_ig)) + + ! critical min rate of spread (m/min) for active crowning + ROS_active_min = (critical_mass_flow_rate / fuel_bd) * 60.0 + + ! check threshold intensity and rate of spread + if (currentPatch%FI >= passive_crown_FI .and. ROS_active >= ROS_active_min) then + currentPatch%active_crown_fire_flg = 1 ! active crown fire ignited + !ROS_final = ROS_surface+CFB(ROS_active - ROS_surface), Eq 21 Scott & Reinhardt 2001 + !with active crown fire CFB (canopy fraction burned) = 100% + canopy_frac_burnt = 1.0_r8 + ROS_final = currentPatch%ROS_front + canopy_frac_burnt*(ROS_active-currentPatch%ROS_front) + + else + currentPatch%active_crown_fire_flg = 0 ! only passive crown fire with partial crown burnt + ! calculate canopy fraction burnt, Eq 28 Scott & Reinhardt App A + ! using wind at which ROS_active = ROS_active_min + ! solve for phi_wind associated with ROS_active_min + phi_wind_ROS_SA = ((ROS_active_min*fuel_bd*eps*q_ig)/(3.34*ir*xi))-1.0 + ! solve for open wind for that phi_wind + wind_ROS_SA = log(b)*(phi_wind_ROS_SA/(c*beta_ratio**(-e)))/log(b)*(3.28*0.4) + ! use this phi_wind for surface ROS + ROS_SA = (ir*xi*(1.0_r8+wind_ROS_SA)) / (fuel_bd*eps*q_ig) + + ! canopy fraction burnt, Eq 28 Scott & Reinhardt Appendix A + canopy_frac_burnt = (min(1.0_r8, ((currentPatch%ROS_front - ROS_active_min) & + /(ROS_SA - ROS_active_min)))) + !ROS_final = ROS_surface+CFB(ROS_active - ROS_surface), Eq 21 Scott & Reinhardt 2001 + ROS_final = currentPatch%ROS_front + canopy_frac_burnt*(ROS_active-currentPatch%ROS_front) + + endif !check intensity & ROS for active crown fire thresholds + + ! recalculate area burned with new ROS_front value from ROS_final + ! ---- re-calculate length of major axis for df using new ROS_front value from ROS final--- + db = currentPatch%ROS_back * currentPatch%FD !(m) + df = ROS_final * currentPatch%FD !(m) update with ROS final + + ! update ROS_front with ROS_final for output variable + currentPatch%ROS_front = ROS_final + + ! --- calculate updated area burnt using df from ROS final--- + if(lb > 0.0_r8) then + + ! Eq 1 in Thonicke et al. 2010 + ! To Do: Connect here with the Li & Levis GDP fire suppression algorithm. + ! Eq 16 in arora and boer model JGR 2005 + ! AB = AB *3.0_r8 + + !size of fire = Eq 14 Arora and Boer JGR 2005 (area of an ellipse) + size_of_fire = ((pi_const/(4.0_r8*lb))*((df+db)**2.0_r8)) + + ! AB = daily area burnt = size fires in m2 * num ignitions per day per km2 * prob ignition starts fire + ! AB = m2 per km2 per day + ! the denominator in the units of currentSite%NF is total gridcell area, but since we assume that ignitions + ! are equally probable across patches, currentSite%NF is equivalently per area of a given patch + ! thus AB has units of m2 burned area per km2 patch area per day + AB = size_of_fire * currentSite%NF * currentSite%FDI + + ! frac_burnt + ! just a unit conversion from AB, to become area burned per area patch per day, + ! or just the fraction of the patch burned on that day + currentPatch%frac_burnt = (min(0.99_r8, AB / km2_to_m2)) + + if(write_SF == itrue)then + if ( hlm_masterproc == itrue ) write(fates_log(),*) 'frac_burnt',currentPatch%frac_burnt + endif + + else + currentPatch%frac_burnt = 0.0_r8 + endif ! lb + + !final fireline intensity (kJ/m/sec or kW/m), Eq 22 Scott & Reinhardt 2001 + FI_final = ((heat_per_area + (canopy_fuel_load*canopy_ignite_energy*canopy_frac_burnt))& + *currentPatch%ROS_front)/60.0 + ! update patch FI to adjust according to potential canopy fuel consumed (passive and active) + currentPatch%FI = FI_final + + endif !check if passive crown fire? + endif !fire? + + currentPatch => currentPatch%younger; + + enddo !end patch loop + + end subroutine active_crown_fire !***************************************************************** @@ -968,6 +1363,7 @@ subroutine crown_scorching ( currentSite ) end subroutine crown_scorching + !***************************************************************** subroutine crown_damage ( currentSite ) !***************************************************************** @@ -975,162 +1371,21 @@ subroutine crown_damage ( currentSite ) !returns the updated currentCohort%fraction_crown_burned for each tree cohort within each patch. !currentCohort%fraction_crown_burned is the proportion of crown affected by fire - use SFParamsMod, only : SF_VAL_CWD_FRAC - type(ed_site_type), intent(in), target :: currentSite type(ed_patch_type) , pointer :: currentPatch type(ed_cohort_type), pointer :: currentCohort - real(r8), parameter :: low_heat_of_combustion = 12700.0_r8 ! [kJ/kg] - real(r8), parameter :: critical_mass_flow_rate = 0.05_r8 ! [kg/m2/s] value for conifer forests; if available for other vegetation, move to the params file? - real(r8) :: active_crown_FI ! critical fire intensity for active crown fire ignition (kW/m) - real(r8) :: ignite_active_crown ! ratio for ignition of active crown fire,EQ 14b Bessie & Johnson 1995 real(r8) :: crown_depth ! depth of crown (m) - real(r8) :: height_cbb ! clear branch bole height or crown base height (m) - real(r8) :: max_height ! max cohort on patch (m) -! real(r8) :: passive_crown_FI ! fire intensity for ignition from passive canopy fuel (kW/m), EQ 8 -! real(r8) :: ignite_passive_crown ! ratio for ignition from passive canopy fuel,EQ 14 Bessie & Johnson 1995 - real(r8) :: tree_sapw_struct_c ! above-ground tree struct and sap biomass in cohort (kgC) - real(r8) :: leaf_c ! leaf carbon (kgC) - real(r8) :: sapw_c ! sapwood carbon (kgC) - real(r8) :: struct_c ! structure carbon (kgC) - real(r8) :: twig_sapw_struct_c ! above-ground twig sap and struct in cohort (kgC) - real(r8) :: crown_fuel_c ! biomass of 1 hr fuels (leaves,twigs) in cohort (kg C) - real(r8) :: crown_fuel_biomass ! biomass of crown fuel in cohort (kg biomass) - real(r8) :: crown_fuel_per_m ! crown fuel per 1m section in cohort - real(r8) :: canopy_bulk_density ! density of canopy fuel on patch - real(r8) :: height_base_canopy ! lowest height of fuels to carry fire in crown - integer :: ih ! counter - integer :: passive_canopy_fuel_flg ! flag if canopy fuel true for vertical spread - - real, dimension(70):: biom_matrix ! matrix to track biomass from bottom to 70m - real(r8),parameter :: min_density_canopy_fuel = 0.011_r8 !min canopy fuel density (kg/m3) sufficient to - !propogate fire vertically through canopy - !Scott and Reinhardt 2001 RMRS-RP-29 - real(r8),parameter :: crown_ignite_energy = 3060_r8 !crown ignition energy (kJ/kg) Van Wagner 1977 + real(r8) :: height_cbb ! clear branch bole height or crown base height (m) for cohort currentPatch => currentSite%oldest_patch do while(associated(currentPatch)) !zero Patch level variables -! passive_crown_FI = 0.0_r8 -! ignite_passive_crown = 0.0_r8 - biom_matrix = 0.0_r8 - canopy_bulk_density = 0.0_r8 - max_height = 0.0_r8 - height_base_canopy = 0.0_r8 if (currentPatch%fire == 1) then - currentCohort=>currentPatch%tallest - do while(associated(currentCohort)) - - !zero cohort level variables - tree_sapw_struct_c = 0.0_r8 - leaf_c = 0.0_r8 - sapw_c = 0.0_r8 - struct_c = 0.0_r8 - twig_sapw_struct_c = 0.0_r8 - crown_fuel_c = 0.0_r8 - crown_fuel_biomass = 0.0_r8 - crown_fuel_per_m = 0.0_r8 - - ! Calculate crown 1hr fuel biomass (leaf, twig sapwood, twig structural biomass) - if ( int(prt_params%woody(currentCohort%pft)) == itrue) then !trees - - call CrownDepth(currentCohort%hite,currentCohort%pft,crown_depth) - height_cbb = currentCohort%hite - crown_depth - - !find patch max height for stand canopy fuel - if (currentCohort%hite > max_height) then - max_height = currentCohort%hite - endif - - leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) - sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) - struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) - - tree_sapw_struct_c = currentCohort%n * & - (prt_params%allom_agb_frac(currentCohort%pft)*(sapw_c + struct_c)) - - twig_sapw_struct_c = tree_sapw_struct_c * SF_VAL_CWD_frac(1) !only 1hr fuel - - crown_fuel_c = (currentCohort%n * leaf_c) + twig_sapw_struct_c !crown fuel (kgC) - - crown_fuel_biomass = crown_fuel_c / 0.45_r8 ! crown fuel (kg biomass) - - crown_fuel_per_m = crown_fuel_biomass / crown_depth ! kg biomass per m - - !sort crown fuel into bins from bottom to top of crown - !accumulate across cohorts to find density within canopy 1m sections - do ih = int(height_cbb), int(currentCohort%hite) - biom_matrix(ih) = biom_matrix(ih) + crown_fuel_per_m - end do - - endif !trees only - - currentCohort => currentCohort%shorter; - - enddo !end cohort loop - - biom_matrix(:) = biom_matrix(:) / currentPatch%area !kg biomass/m3 - - !loop from 1m to 70m to find bin with total density = 0.011 kg/m3 - !min canopy fuel density to propogate fire vertically in canopy across patch - do ih=1,70 - if (biom_matrix(ih) > min_density_canopy_fuel) then - height_base_canopy = float(ih) - exit - end if - end do - - !canopy_bulk_denisty (kg/m3) for Patch - canopy_bulk_density = sum(biom_matrix) / (max_height - height_base_canopy) - - ! Note: crown_ignition_energy to be calculated based on PFT foliar moisture content from FATES-Hydro - ! or create foliar_moisture based on BTRAN - ! Use foliar_moisture(currentCohort%pft) and compute weighted PFT average with EQ3 Van Wagner 1977 - ! in place of crown_ignite_energy parameter - - ! EQ 3 Van Wagner 1977 - ! h = crown_ignite_energy (kJ/kg), m = foliar moisture content based on dry fuel (%) - ! crown_ignite_energy = 460 + 26 * m - - ! Crown fuel ignition potential, EQ 8 Bessie and Johnson 1995, EQ 4 Van Wagner 1977 - ! FI = (Czh)**3/2 where z=canopy base height,h=heat of crown ignite energy, FI=fire intensity - ! 0.01 = C from Van Wagner 1977 EQ4 for canopy base height 6m, 100% FMC, and FI 2500kW/m -! passive_crown_FI = (0.01_r8 * height_base_canopy * crown_ignite_energy)**1.5_r8 - -! passive_canopy_fuel_flg = 0 !does patch have canopy fuels for vertical spread? - - ! Initiation of passive crown fire, EQ 14a Bessie and Johnson 1995 - ! Are the canopy fuels in the stand large enough to support vertical spread of fire? -! ignite_passive_crown = currentPatch%FI/passive_crown_FI - -! if (ignite_passive_crown >= 1.0_r8) then -! passive_canopy_fuel_flg = 1 !enough passive canopy fuels for vertical spread -! endif - - !evaluate active crown fire conditions - ! Critical intensity for active crowning (kW/m) - ! EQ 12 Bessie and Johnson 1995 - ! Fuels / 0.45 to get biomass. Also dividing - ! critical_mass_flow_rate by 3.34, an empirical - ! constant in Bessie & Johnson 1995 - active_crown_FI = critical_mass_flow_rate * & - low_heat_of_combustion * currentPatch%sum_fuel / & - (0.45_r8 * 3.34_r8 * canopy_bulk_density) - - ! Initiate active crown fire? - ! EQ 14b Bessie & Johnson 1995 - ignite_active_crown = currentPatch%FI / active_crown_FI - - if (ignite_active_crown >= 1.0_r8 .and. & - EDPftvarcon_inst%active_crown_fire(currentCohort%pft) > 0.0_r8) then - currentPatch%active_crown_fire_flg = 1 ! active crown fire ignited - end if - currentCohort=>currentPatch%tallest do while(associated(currentCohort)) @@ -1149,8 +1404,7 @@ subroutine crown_damage ( currentSite ) currentPatch%Scorch_ht(currentCohort%pft) >= height_cbb) then if (currentPatch%active_crown_fire_flg == 0) then currentCohort%fraction_crown_burned = min(1.0_r8, & - ((currentPatch%Scorch_ht(currentCohort%pft) - & - height_cbb) / crown_depth)) + ((currentPatch%Scorch_ht(currentCohort%pft) - height_cbb) / crown_depth)) else ! active crown fire occurring currentCohort%fraction_crown_burned = 1.0_r8 end if From cadce7cd9d1446b5e86c551037ed38013daf928e Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 18 Apr 2022 13:39:40 -0400 Subject: [PATCH 170/852] fixing the spelling of lignin. No A! --- biogeochem/FatesSoilBGCFluxMod.F90 | 4 ++-- main/EDPftvarcon.F90 | 2 +- main/FatesInterfaceTypesMod.F90 | 6 +++--- main/FatesInventoryInitMod.F90 | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index 9f5d37187b..2d06229463 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -960,7 +960,7 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) real(r8) :: fnrt_c, struct_c ! fineroot and struct carbon, per plant [kg] real(r8) :: leaf_n, sapw_n ! leaf and sapwood N, per plant [kg] real(r8) :: fnrt_n, struct_n ! fineroot and struct N, per plant [kg] - real(r8) :: sum_ligC ! Flux of lignan C [kg/m2/s] + real(r8) :: sum_ligC ! Flux of lignin C [kg/m2/s] real(r8) :: sum_N ! Flux of all N [kg/m2/s] real(r8) :: tot_leaf_c ! total leaf C of all cohorts in patch [kg/m2] real(r8) :: tot_leaf_n ! total leaf N of all cohorts in patch [kg/m2] @@ -1007,7 +1007,7 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) do el = 1, num_elements ! Zero out the boundary flux arrays - ! Make a pointer to the cellulose, labile and lignan + ! Make a pointer to the cellulose, labile and lignin ! flux partitions. select case (element_list(el)) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index a149132a8d..027abb152c 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -59,7 +59,7 @@ module EDPftvarcon real(r8), allocatable :: lf_flab(:) ! Leaf litter labile fraction [-] real(r8), allocatable :: lf_fcel(:) ! Leaf litter cellulose fraction [-] - real(r8), allocatable :: lf_flig(:) ! Leaf litter lignan fraction [-] + real(r8), allocatable :: lf_flig(:) ! Leaf litter lignin fraction [-] real(r8), allocatable :: fr_flab(:) ! Fine-root litter labile fraction [-] real(r8), allocatable :: fr_fcel(:) ! Fine-root litter cellulose fraction [-] real(r8), allocatable :: fr_flig(:) ! Fine-root litter lignatn fraction [-] diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 3e3e0191a3..e8ddf63e48 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -597,13 +597,13 @@ module FatesInterfaceTypesMod ! Mass fluxes to BGC from fragmentation of litter into decomposing pools real(r8), allocatable :: litt_flux_cel_c_si(:) ! cellulose carbon litter, fates->BGC g/m3/s - real(r8), allocatable :: litt_flux_lig_c_si(:) ! lignan carbon litter, fates->BGC g/m3/s + real(r8), allocatable :: litt_flux_lig_c_si(:) ! lignin carbon litter, fates->BGC g/m3/s real(r8), allocatable :: litt_flux_lab_c_si(:) ! labile carbon litter, fates->BGC g/m3/s real(r8), allocatable :: litt_flux_cel_n_si(:) ! cellulose nitrogen litter, fates->BGC g/m3/s - real(r8), allocatable :: litt_flux_lig_n_si(:) ! lignan nitrogen litter, fates->BGC g/m3/s + real(r8), allocatable :: litt_flux_lig_n_si(:) ! lignin nitrogen litter, fates->BGC g/m3/s real(r8), allocatable :: litt_flux_lab_n_si(:) ! labile nitrogen litter, fates->BGC g/m3/s real(r8), allocatable :: litt_flux_cel_p_si(:) ! cellulose phosphorus litter, fates->BGC g/m3/s - real(r8), allocatable :: litt_flux_lig_p_si(:) ! lignan phosphorus litter, fates->BGC g/m3/s + real(r8), allocatable :: litt_flux_lig_p_si(:) ! lignin phosphorus litter, fates->BGC g/m3/s real(r8), allocatable :: litt_flux_lab_p_si(:) ! labile phosphorus litter, fates->BGC g/m3/s diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index 507f01dbee..0d9891ee4f 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -734,7 +734,7 @@ subroutine set_inventory_edpatch_type1(newpatch,pss_file_unit,ipa,ios,patch_name ! water (NA) Water content of soil (NOT USED) ! fsc (kg/m2) Fast Soil Carbon ! stsc (kg/m2) Structural Soil Carbon - ! stsl (kg/m2) Structural Soil Lignan + ! stsl (kg/m2) Structural Soil Lignin ! ssc (kg/m2) Slow Soil Carbon ! psc (NA) Passive Soil Carbon (NOT USED) ! msn (kg/m2) Mineralized Soil Nitrogen @@ -763,7 +763,7 @@ subroutine set_inventory_edpatch_type1(newpatch,pss_file_unit,ipa,ios,patch_name real(r8) :: p_water ! Patch water (unused) real(r8) :: p_fsc ! Patch fast soil carbon real(r8) :: p_stsc ! Patch structural soil carbon - real(r8) :: p_stsl ! Patch structural soil lignans + real(r8) :: p_stsl ! Patch structural soil lignins real(r8) :: p_ssc ! Patch slow soil carbon real(r8) :: p_psc ! Patch P soil carbon real(r8) :: p_msn ! Patch mean soil nitrogen From a93375e6cf1f6e75e0572249292ac2998b888be4 Mon Sep 17 00:00:00 2001 From: Jacquelyn Shuman Date: Mon, 18 Apr 2022 12:35:30 -0600 Subject: [PATCH 171/852] Fix solve for phi wind in active fire Fix mistake in equation to solve for phi_wind as part of steps towards calculation of canopy fraction burnt. --- fire/SFMainMod.F90 | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index 30a3e9e644..977b4bf5b0 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -1233,11 +1233,12 @@ subroutine active_crown_fire ( currentSite, canopy_fuel_load, ROS_torch, & ! calculate canopy fraction burnt, Eq 28 Scott & Reinhardt App A ! using wind at which ROS_active = ROS_active_min ! solve for phi_wind associated with ROS_active_min - phi_wind_ROS_SA = ((ROS_active_min*fuel_bd*eps*q_ig)/(3.34*ir*xi))-1.0 + phi_wind_ROS_SA = (ROS_active_min * fuel_bd * eps * q_ig - 3.34 * ir * xi) & + /(3.34 * ir * xi) ! solve for open wind for that phi_wind wind_ROS_SA = log(b)*(phi_wind_ROS_SA/(c*beta_ratio**(-e)))/log(b)*(3.28*0.4) - ! use this phi_wind for surface ROS - ROS_SA = (ir*xi*(1.0_r8+wind_ROS_SA)) / (fuel_bd*eps*q_ig) + ! use this phi_wind for potential surface ROS for canopy_frac_burnt calculation + ROS_SA = (ir * xi * (1.0_r8 + wind_ROS_SA)) / (fuel_bd * eps * q_ig) ! canopy fraction burnt, Eq 28 Scott & Reinhardt Appendix A canopy_frac_burnt = (min(1.0_r8, ((currentPatch%ROS_front - ROS_active_min) & From 84a67fae3778b0e0332f94f0a46b7eb1bdde6e69 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 18 Apr 2022 15:00:44 -0400 Subject: [PATCH 172/852] small bug fix from merge --- biogeophys/FatesPlantHydraulicsMod.F90 | 1 - main/FatesGlobals.F90 | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index ecfd9d5b97..3998d963da 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -2883,7 +2883,6 @@ subroutine hydraulics_bc ( nsites, sites, bc_in, bc_out, dtime) wb_check_site = delta_plant_storage+delta_soil_storage+site_runoff+transp_flux ! Now check on total error - end if if(debug)then if( abs(wb_check_site) > 1.e-4_r8 ) then diff --git a/main/FatesGlobals.F90 b/main/FatesGlobals.F90 index 48f8ffcdcb..8d46d5a0d9 100644 --- a/main/FatesGlobals.F90 +++ b/main/FatesGlobals.F90 @@ -139,8 +139,7 @@ end function N2S function A2S(reals_in) result(str) real(r8) :: reals_in(:) - character(len=512) :: str - character(len=16) :: str_frag + character(len=1024) :: str integer :: i, nreal str = ', ' From 0f65e9151e6052e5783bb963e96e32c7c3cbd5a3 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 18 Apr 2022 16:39:21 -0400 Subject: [PATCH 173/852] Removing endruns in the NL passing --- main/FatesInterfaceMod.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 3387c18140..4c2b3cae4b 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1724,7 +1724,7 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) case default write(fates_log(), *) 'fates NL tag not recognized:',trim(tag) - call endrun(msg=errMsg(sourcefile, __LINE__)) + !! call endrun(msg=errMsg(sourcefile, __LINE__)) end select end if @@ -1738,7 +1738,7 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) end if case default write(fates_log(),*) 'fates NL tag not recognized:',trim(tag) - call endrun(msg=errMsg(sourcefile, __LINE__)) + !! call endrun(msg=errMsg(sourcefile, __LINE__)) end select end if @@ -1765,7 +1765,7 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) case default write(fates_log(),*) 'fates NL tag not recognized:',trim(tag) - call endrun(msg=errMsg(sourcefile, __LINE__)) + !! call endrun(msg=errMsg(sourcefile, __LINE__)) end select end if From 456706fed2684c5b80afe8127711d058ae41e584 Mon Sep 17 00:00:00 2001 From: Jacquelyn Shuman Date: Tue, 19 Apr 2022 09:41:38 -0600 Subject: [PATCH 174/852] comment check for active crown fire --- fire/SFMainMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index 977b4bf5b0..af38d24ea3 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -404,7 +404,7 @@ subroutine characteristics_of_crown ( currentSite, canopy_fuel_load, passive_cr canopy_fuel_load = 0.0_r8 passive_crown_FI = 0.0_r8 - if (currentPatch%fire == 1) then +! if (currentPatch%active_crown_fire == 1) then currentCohort=>currentPatch%tallest do while(associated(currentCohort)) @@ -491,7 +491,7 @@ subroutine characteristics_of_crown ( currentSite, canopy_fuel_load, passive_cr ! passive_crown_FI = min fire intensity to ignite canopy fuel (kW/m or kJ/m/s) passive_crown_FI = (0.01_r8 * height_base_canopy * crown_ignite_energy)**1.5_r8 - endif ! fire? +! endif !active crown fire? currentPatch => currentPatch%younger; From 9e90ddee7a88a74e2b5db22c8ef756c8cce1f7c1 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 20 Apr 2022 18:37:28 -0400 Subject: [PATCH 175/852] Various updates to FatesWarn --- biogeochem/EDPatchDynamicsMod.F90 | 3 +- biogeochem/FatesAllometryMod.F90 | 16 ++++++-- biogeophys/FatesPlantRespPhotosynthMod.F90 | 10 +++-- main/EDMainMod.F90 | 2 +- main/FatesGlobals.F90 | 45 ++++++++++++++++++++-- 5 files changed, 62 insertions(+), 14 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index c6eceb620c..13552c899a 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -338,8 +338,7 @@ subroutine disturbance_rates( site_in, bc_in) end do ! Fires can't burn the whole patch, as this causes /0 errors. - !if (currentPatch%disturbance_rates(dtype_ifire) > 0.98_r8)then - if(.true.)then + if (currentPatch%disturbance_rates(dtype_ifire) > 0.98_r8)then msg = 'very high fire areas'//trim(A2S(currentPatch%disturbance_rates(:)))//trim(N2S(currentPatch%frac_burnt)) call FatesWarn(msg,index=2) endif diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index ba72c539e0..df05b7de29 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -95,6 +95,7 @@ module FatesAllometryMod use shr_log_mod , only : errMsg => shr_log_errMsg use FatesGlobals , only : fates_log use FatesGlobals , only : endrun => fates_endrun + use FatesGlobals , only : FatesWarn,N2S,A2S,I2S use EDTypesMod , only : nlevleaf, dinc_vai use EDTypesMod , only : nclmax @@ -130,6 +131,8 @@ module FatesAllometryMod logical, parameter :: debug = .false. + + character(len=1024) :: warn_msg ! for defining a warning message ! If testing b4b with older versions, do not remove sapwood ! Our old methods with saldarriaga did not remove sapwood from the @@ -2455,11 +2458,16 @@ subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl ) call h_allom(d,ipft,h) - if(debug) then - if(counter>10)then - write(fates_log(),*) 'dbh counter: ',counter,' is woody: ',& - int(prt_params%woody(ipft))==itrue + if(counter>20)then + write(fates_log(),*) 'dbh counter: ',counter,' is woody: ',& + int(prt_params%woody(ipft))==itrue + + if(int(prt_params%woody(ipft))==itrue)then + warn_msg = 'dbh counter: '//trim(I2S(counter))//' is woody' + else + warn_msg = 'dbh counter: '//trim(I2S(counter))//' is not woody' end if + call FatesWarn(warn_msg,index=3) end if diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 1ab9eabdaa..bd6855bbda 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -22,6 +22,7 @@ module FATESPlantRespPhotosynthMod use FatesGlobals, only : endrun => fates_endrun use FatesGlobals, only : fates_log + use FatesGlobals, only : FatesWarn,N2S,A2S use FatesConstantsMod, only : r8 => fates_r8 use FatesConstantsMod, only : itrue use FatesConstantsMod, only : nearzero @@ -63,6 +64,10 @@ module FATESPlantRespPhotosynthMod character(len=*), parameter, private :: sourcefile = & __FILE__ + + + character(len=1024) :: warn_msg ! for defining a warning message + !------------------------------------------------------------------------------------- ! maximum stomatal resistance [s/m] (used across several procedures) @@ -1262,9 +1267,8 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in end if if (abs(gs_mol-gs_mol_err) > 1.e-01_r8) then - write (fates_log(),*) 'Stomatal model error check - stomatal conductance error:' - write (fates_log(),*) gs_mol, gs_mol_err - call endrun(msg=errMsg(sourcefile, __LINE__)) + warn_msg = 'Stomatal conductance error check - weak convergence: '//trim(N2S(gs_mol))//' '//trim(N2S(gs_mol_err)) + call FatesWarn(warn_msg,index=4) end if enddo !sunsha loop diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 0a67a313ed..d05966ef14 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -149,7 +149,7 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) !----------------------------------------------------------------------- - if ( hlm_masterproc==itrue ) write(fates_log(),'(A,I4,A,I2.2,A,I2.2)') 'FATES Dynamics: ',& + if (debug .and.( hlm_masterproc==itrue)) write(fates_log(),'(A,I4,A,I2.2,A,I2.2)') 'FATES Dynamics: ',& hlm_current_year,'-',hlm_current_month,'-',hlm_current_day ! Consider moving this towards the end, because some of these diff --git a/main/FatesGlobals.F90 b/main/FatesGlobals.F90 index 8d46d5a0d9..19713ec3f1 100644 --- a/main/FatesGlobals.F90 +++ b/main/FatesGlobals.F90 @@ -20,7 +20,9 @@ module FatesGlobals public :: FatesWarn public :: A2S public :: N2S - + public :: I2S + public :: FatesReportTotalWarnings + ! ------------------------------------------------------------------------------------- ! Warning handling ! The objective here is to stop writing the same warning over and over again. After @@ -42,6 +44,8 @@ module FatesGlobals ! printing any of these warnings to the log ! It should also bypass the logicals bound inside ! at the compiler level (?) and be faster + + contains @@ -113,15 +117,36 @@ subroutine FatesWarn(msg,index) warn_counts(ind) = warn_counts(ind) + 1 if(warn_active(ind))then - write(fates_log(),*) 'FWARN: ',ind,'m: ',msg + write(fates_log(),*) 'FWARN: '//trim(ADJUSTL(I2S(ind)))//' m: '//trim(msg) if(warn_counts(ind)> max_warnings) then warn_active(ind) = .false. - write(fates_log(),*) 'FWARN: ',ind,'has saturated messaging, no longer reporting' + write(fates_log(),*) 'FWARN: '//trim(ADJUSTL(I2S(ind)))//' has saturated messaging, no longer reporting' end if end if return end subroutine FatesWarn + ! ===================================================================================== + + + subroutine FatesReportTotalWarnings() + + integer :: ind + + do ind = 1,max_ids + + if(warn_counts(ind)>0)then + + write(fates_log(),*) 'FWARN: '//trim(ADJUSTL(I2S(ind)))//' was triggered ',trim(ADJUSTL(I2S(warn_counts(ind))))//' times' + + end if + + end do + + + end subroutine FatesReportTotalWarnings + + ! ===================================================================================== function N2S(real_in) result(str) @@ -130,9 +155,21 @@ function N2S(real_in) result(str) character(len=16) :: str !write(str,*) real_in - write(str,'(a,E12.6)') ', ',real_in + write(str,'(E12.6)') real_in end function N2S + + ! ===================================================================================== + + function I2S(int_in) result(str) + + integer :: int_in + character(len=16) :: str + + !write(str,*) real_in + write(str,'(I15)') int_in + + end function I2S ! ===================================================================================== From 9457e94a83286a515c6f0fc12b5d0f0233a4f6a3 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 22 Apr 2022 11:48:02 -0400 Subject: [PATCH 176/852] Update main/FatesGlobals.F90 Co-authored-by: Gregory Lemieux <7565064+glemieux@users.noreply.github.com> --- main/FatesGlobals.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main/FatesGlobals.F90 b/main/FatesGlobals.F90 index 19713ec3f1..f75aa32fd8 100644 --- a/main/FatesGlobals.F90 +++ b/main/FatesGlobals.F90 @@ -117,10 +117,10 @@ subroutine FatesWarn(msg,index) warn_counts(ind) = warn_counts(ind) + 1 if(warn_active(ind))then - write(fates_log(),*) 'FWARN: '//trim(ADJUSTL(I2S(ind)))//' m: '//trim(msg) + write(fates_log(),*) 'FATESWARN: '//trim(ADJUSTL(I2S(ind)))//' m: '//trim(msg) if(warn_counts(ind)> max_warnings) then warn_active(ind) = .false. - write(fates_log(),*) 'FWARN: '//trim(ADJUSTL(I2S(ind)))//' has saturated messaging, no longer reporting' + write(fates_log(),*) 'FATESWARN: '//trim(ADJUSTL(I2S(ind)))//' has saturated messaging, no longer reporting' end if end if return @@ -137,7 +137,7 @@ subroutine FatesReportTotalWarnings() if(warn_counts(ind)>0)then - write(fates_log(),*) 'FWARN: '//trim(ADJUSTL(I2S(ind)))//' was triggered ',trim(ADJUSTL(I2S(warn_counts(ind))))//' times' + write(fates_log(),*) 'FATESWARN: '//trim(ADJUSTL(I2S(ind)))//' was triggered ',trim(ADJUSTL(I2S(warn_counts(ind))))//' times' end if From d974364675b4e285a1bcb15ad8878fc4c24253fd Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 26 Apr 2022 12:35:29 -0600 Subject: [PATCH 177/852] Fixed some logging indices --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 2 +- main/FatesGlobals.F90 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index bd6855bbda..3b34342149 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -1268,7 +1268,7 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in if (abs(gs_mol-gs_mol_err) > 1.e-01_r8) then warn_msg = 'Stomatal conductance error check - weak convergence: '//trim(N2S(gs_mol))//' '//trim(N2S(gs_mol_err)) - call FatesWarn(warn_msg,index=4) + call FatesWarn(warn_msg,index=1) end if enddo !sunsha loop diff --git a/main/FatesGlobals.F90 b/main/FatesGlobals.F90 index f75aa32fd8..ebc0f326ff 100644 --- a/main/FatesGlobals.F90 +++ b/main/FatesGlobals.F90 @@ -133,7 +133,7 @@ subroutine FatesReportTotalWarnings() integer :: ind - do ind = 1,max_ids + do ind = 0,max_ids if(warn_counts(ind)>0)then From b9c88317d50090584ac1a1e093a03214668a7e2e Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 26 Apr 2022 14:30:50 -0600 Subject: [PATCH 178/852] Removed extra def of msgErr --- biogeophys/EDAccumulateFluxesMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeophys/EDAccumulateFluxesMod.F90 b/biogeophys/EDAccumulateFluxesMod.F90 index 090b7848b0..8eae0f4a50 100644 --- a/biogeophys/EDAccumulateFluxesMod.F90 +++ b/biogeophys/EDAccumulateFluxesMod.F90 @@ -13,7 +13,7 @@ module EDAccumulateFluxesMod use FatesGlobals, only : fates_log use shr_log_mod , only : errMsg => shr_log_errMsg use FatesConstantsMod , only : r8 => fates_r8 - use shr_log_mod , only : errMsg => shr_log_errMsg + implicit none private From eaf52a7d85b629342105f39209032462e3d0aeea Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 26 Apr 2022 23:02:45 -0400 Subject: [PATCH 179/852] Added hydr_solver and stomatal_assim switches to parameter file --- biogeophys/FatesPlantHydraulicsMod.F90 | 18 ++++---- biogeophys/FatesPlantRespPhotosynthMod.F90 | 11 ++--- main/EDParamsMod.F90 | 48 ++++++++++++++++------ main/FatesHydraulicsMemMod.F90 | 4 +- parameter_files/fates_params_default.cdl | 18 ++++++-- 5 files changed, 64 insertions(+), 35 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 3998d963da..1882da8b2e 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -48,7 +48,7 @@ module FatesPlantHydraulicsMod use EDParamsMod , only : hydr_psi0 use EDParamsMod , only : hydr_psicap use EDParamsMod , only : hydr_htftype_node - use EDParamsMod , only : hydr_solver_type + use EDParamsMod , only : hydr_solver use EDTypesMod , only : ed_site_type use EDTypesMod , only : ed_patch_type @@ -1468,7 +1468,7 @@ subroutine InitHydrSites(sites,bc_in) case(rhizlayer_aggmeth_none) csite_hydr%nlevrhiz = bc_in(s)%nlevsoil - call sites(s)%si_hydr%InitHydrSite(numpft,nlevsclass,hydr_solver_type,bc_in(s)%nlevsoil) + call sites(s)%si_hydr%InitHydrSite(numpft,nlevsclass,hydr_solver,bc_in(s)%nlevsoil) do j=1,csite_hydr%nlevrhiz csite_hydr%map_r2s(j,1) = j @@ -1480,7 +1480,7 @@ subroutine InitHydrSites(sites,bc_in) case(rhizlayer_aggmeth_combine12) csite_hydr%nlevrhiz = max(1,bc_in(s)%nlevsoil-1) - call sites(s)%si_hydr%InitHydrSite(numpft,nlevsclass,hydr_solver_type,bc_in(s)%nlevsoil) + call sites(s)%si_hydr%InitHydrSite(numpft,nlevsclass,hydr_solver,bc_in(s)%nlevsoil) csite_hydr%map_r2s(1,1) = 1 j_bc = min(2,bc_in(s)%nlevsoil) ! this protects 1 soil layer @@ -1498,7 +1498,7 @@ subroutine InitHydrSites(sites,bc_in) case(rhizlayer_aggmeth_balN) csite_hydr%nlevrhiz = min(aggN,bc_in(s)%nlevsoil) - call sites(s)%si_hydr%InitHydrSite(numpft,nlevsclass,hydr_solver_type,bc_in(s)%nlevsoil) + call sites(s)%si_hydr%InitHydrSite(numpft,nlevsclass,hydr_solver,bc_in(s)%nlevsoil) ntoagg = int(ceiling(real(bc_in(s)%nlevsoil)/real(csite_hydr%nlevrhiz)-nearzero)) @@ -2627,21 +2627,21 @@ subroutine hydraulics_bc ( nsites, sites, bc_in, bc_out, dtime) ! from leaf to the current soil layer. This does NOT ! update cohort%th_* - if(hydr_solver_type == hydr_solver_2DNewton) then + if(hydr_solver == hydr_solver_2DNewton) then call MatSolve2D(csite_hydr,ccohort,ccohort_hydr, & dtime,qflx_tran_veg_indiv, & sapflow,rootuptake(1:nlevrhiz),wb_err_plant,dwat_plant, & dth_layershell_col) - elseif(hydr_solver_type == hydr_solver_2DPicard) then + elseif(hydr_solver == hydr_solver_2DPicard) then call PicardSolve2D(csite_hydr,ccohort,ccohort_hydr, & dtime,qflx_tran_veg_indiv, & sapflow,rootuptake(1:nlevrhiz),wb_err_plant,dwat_plant, & dth_layershell_col,csite_hydr%num_nodes) - elseif(hydr_solver_type == hydr_solver_1DTaylor ) then + elseif(hydr_solver == hydr_solver_1DTaylor ) then ! --------------------------------------------------------------------------------- ! Approach: do nlevsoi_hyd sequential solutions to Richards' equation, @@ -4942,7 +4942,7 @@ subroutine MatSolve2D(csite_hydr,cohort,cohort_hydr, & ! This NaN's the scratch arrays - call csite_hydr%FlushSiteScratch(hydr_solver_type) + call csite_hydr%FlushSiteScratch(hydr_solver) ! This is the maximum number of iterations needed for this cohort ! (each soil layer has a different number, this saves the max) @@ -5725,7 +5725,7 @@ subroutine PicardSolve2D(csite_hydr,cohort,cohort_hydr, & ! This NaN's the scratch arrays - call csite_hydr%FlushSiteScratch(hydr_solver_type) + call csite_hydr%FlushSiteScratch(hydr_solver) ! This is the maximum number of iterations needed for this cohort ! (each soil layer has a different number, this saves the max) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 3b34342149..d488cd2ba4 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -50,7 +50,7 @@ module FATESPlantRespPhotosynthMod use PRTGenericMod, only : store_organ use PRTGenericMod, only : repro_organ use PRTGenericMod, only : struct_organ - use EDParamsMod, only : ED_val_base_mr_20, stomatal_model + use EDParamsMod, only : ED_val_base_mr_20, stomatal_model, stomatal_assim_model use PRTParametersMod, only : prt_params use EDPftvarcon , only : EDPftvarcon_inst @@ -94,11 +94,8 @@ module FATESPlantRespPhotosynthMod ! Alternatively, Gross Assimilation can be used to estimate ! leaf co2 partial pressure and therefore conductance. The default !is to use anet - logical, parameter :: use_agross = .false. - - - - + integer, parameter :: net_assim_model = 1 + integer, parameter :: gross_assim_model = 2 contains @@ -1152,7 +1149,7 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in ! using anet in calculating gs this is version B anet = agross - lmr - if (use_agross) then + if ( stomatal_assim_model == gross_assim_model ) then if ( stomatal_model == medlyn_model ) then write (fates_log(),*) 'Gross Assimilation conductance is incompatible with the Medlyn model' call endrun(msg=errMsg(sourcefile, __LINE__)) diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 51926d275a..d6cd69b3db 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -93,16 +93,6 @@ module EDParamsMod ! 1 = Christofferson et al. 2016 (TFS), 2 = Van Genuchten 1980 integer, protected,allocatable,public :: hydr_htftype_node(:) - ! Switch that defines which hydraulic solver to use - ! 1 = Taylor solution that solves plant fluxes with 1 layer - ! sequentially placing solution on top of previous layer solves - ! 2 = Newton-Raphson solution that solves all fluxes in a plant and - ! the soil simultaneously, 2D: soil x (root + shell) - ! 3 = Picard solution that solves all fluxes in a plant and - ! the soil simultaneously, 2D: soil x (root + shell) - - integer, parameter, public :: hydr_solver_type = 1 ! 1 = hydr_solver_1DTaylor - character(len=param_string_length),parameter,public :: ED_name_photo_temp_acclim_timescale = "fates_photo_temp_acclim_timescale" character(len=param_string_length),parameter,public :: name_photo_tempsens_model = "fates_photo_tempsens_model" character(len=param_string_length),parameter,public :: name_maintresp_model = "fates_maintresp_model" @@ -160,10 +150,27 @@ module EDParamsMod real(r8),protected,public :: hydr_psicap ! sapwood water potential at which capillary reserves exhausted (MPa) character(len=param_string_length),parameter,public :: hydr_name_psicap = "fates_hydr_psicap" + + ! Switch that defines which hydraulic solver to use + ! 1 = Taylor solution that solves plant fluxes with 1 layer + ! sequentially placing solution on top of previous layer solves + ! 2 = Picard solution that solves all fluxes in a plant and + ! the soil simultaneously, 2D: soil x (root + shell) + ! 3 = Newton-Raphson (Deprecated) solution that solves all fluxes in a plant and + ! the soil simultaneously, 2D: soil x (root + shell) + + integer,protected,public :: hydr_solver ! switch designating hydraulics numerical solver + character(len=param_string_length),parameter,public :: hydr_name_solver = "fates_hydr_solver" + !Soil BGC parameters, mostly used for testing FATES when not coupled to the dynamics bgc hlm ! ---------------------------------------------------------------------------------------------- real(r8),protected,public :: bgc_soil_salinity ! site-level soil salinity for FATES when not coupled to dynamic soil BGC of salinity character(len=param_string_length),parameter,public :: bgc_name_soil_salinity= "fates_soil_salinity" + + ! Switch designating whether to use net or gross assimilation in the stomata model + integer, protected, public :: stomatal_assim_model + character(len=param_string_length), parameter, public :: stomatal_assim_name = "fates_stomatal_assim" + ! Logging Control Parameters (ONLY RELEVANT WHEN USE_FATES_LOGGING = TRUE) ! ---------------------------------------------------------------------------------------------- @@ -250,10 +257,12 @@ subroutine FatesParamsInit() ED_val_patch_fusion_tol = nan ED_val_canopy_closure_thresh = nan stomatal_model = -9 + stomatal_assim_model = -9 hydr_kmax_rsurf1 = nan hydr_kmax_rsurf2 = nan hydr_psi0 = nan hydr_psicap = nan + hydr_solver = -9 bgc_soil_salinity = nan logging_dbhmin = nan logging_dbhmax = nan @@ -383,7 +392,10 @@ 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=stomatal_assim_name, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=hydr_name_kmax_rsurf1, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -561,6 +573,10 @@ subroutine FatesReceiveParams(fates_params) data=tmpreal) stomatal_model = nint(tmpreal) + call fates_params%RetreiveParameter(name=stomatal_assim_name, & + data=tmpreal) + stomatal_assim_model = nint(tmpreal) + call fates_params%RetreiveParameter(name=hydr_name_kmax_rsurf1, & data=hydr_kmax_rsurf1) @@ -572,7 +588,11 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetreiveParameter(name=hydr_name_psicap, & data=hydr_psicap) - + + call fates_params%RetreiveParameter(name=hydr_name_solver, & + data=tmpreal) + hydr_solver = nint(tmpreal) + call fates_params%RetreiveParameter(name=bgc_name_soil_salinity, & data=bgc_soil_salinity) @@ -689,11 +709,13 @@ 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) 'stomatal_model = ',stomatal_model + write(fates_log(),fmt0) 'stomatal_model = ',stomatal_model + write(fates_log(),fmt0) 'stomatal_assim_model = ',stomatal_assim_model write(fates_log(),fmt0) 'hydr_kmax_rsurf1 = ',hydr_kmax_rsurf1 write(fates_log(),fmt0) 'hydr_kmax_rsurf2 = ',hydr_kmax_rsurf2 write(fates_log(),fmt0) 'hydr_psi0 = ',hydr_psi0 write(fates_log(),fmt0) 'hydr_psicap = ',hydr_psicap + write(fates_log(),fmt0) 'hydr_solver = ',hydr_solver write(fates_log(),fmt0) 'bgc_soil_salinity = ', bgc_soil_salinity write(fates_log(),fmt0) 'logging_dbhmin = ',logging_dbhmin write(fates_log(),fmt0) 'logging_dbhmax = ',logging_dbhmax diff --git a/main/FatesHydraulicsMemMod.F90 b/main/FatesHydraulicsMemMod.F90 index 65163e1c8c..57329921b4 100644 --- a/main/FatesHydraulicsMemMod.F90 +++ b/main/FatesHydraulicsMemMod.F90 @@ -14,8 +14,8 @@ module FatesHydraulicsMemMod ! Define the various different solver options for hydraulics integer, parameter, public :: hydr_solver_1DTaylor = 1 - integer, parameter, public :: hydr_solver_2DNewton = 2 - integer, parameter, public :: hydr_solver_2DPicard = 3 + integer, parameter, public :: hydr_solver_2DNewton = 3 + integer, parameter, public :: hydr_solver_2DPicard = 2 ! Number of soil layers for indexing cohort fine root quanitities ! NOTE: The hydraulics code does have some capacity to run a single soil diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 45e4a3509c..993aaac004 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -201,9 +201,9 @@ variables: double fates_fire_bark_scaler(fates_pft) ; fates_fire_bark_scaler:units = "fraction" ; fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; - double fates_fire_crown_depth_frac(fates_pft) ; - fates_fire_crown_depth_frac:units = "fraction" ; - fates_fire_crown_depth_frac:long_name = "the depth of a cohorts crown as a fraction of its height" ; + double fates_crown_depth_frac(fates_pft) ; + fates_crown_depth_frac:units = "fraction" ; + fates_crown_depth_frac:long_name = "the depth of a cohorts crown as a fraction of its height" ; double fates_fire_crown_kill(fates_pft) ; fates_fire_crown_kill:units = "NA" ; fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; @@ -656,6 +656,9 @@ variables: double fates_hydr_psicap ; fates_hydr_psicap:units = "MPa" ; fates_hydr_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; + double fates_hydr_solver ; + fates_hydr_solver:units = "unitless" ; + fates_hydr_solver:long_name = "switch designating which numerical solver for plant hydraulics, 1 = 1D taylor, 2 = 2D Picard" ; double fates_init_litter ; fates_init_litter:units = "NA" ; fates_init_litter:long_name = "Initialization value for litter pool in cold-start (NOT USED)" ; @@ -743,6 +746,9 @@ variables: double fates_soil_salinity ; fates_soil_salinity:units = "ppt" ; fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; + double fates_stomatal_assim ; + fates_stomatal_assim:units = "unitless" ; + fates_stomatal_assim:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; double fates_theta_cj_c3 ; fates_theta_cj_c3:units = "unitless" ; fates_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; @@ -939,7 +945,7 @@ data: fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07 ; - fates_fire_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, + fates_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, 0.95, 1, 1, 1 ; fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, @@ -1421,6 +1427,8 @@ data: fates_hydr_psicap = -0.6 ; + fates_hydr_solver = 1 ; + fates_init_litter = 0.05 ; fates_leaf_stomatal_model = 1 ; @@ -1479,6 +1487,8 @@ data: fates_soil_salinity = 0.4 ; + fates_stomatal_assim = 1 ; + fates_theta_cj_c3 = 0.999 ; fates_theta_cj_c4 = 0.999 ; From 1879333f76fc546f9371f1ffbbe4bc928cebfcdc Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 27 Apr 2022 11:20:04 -0400 Subject: [PATCH 180/852] converting parameter crown to crown_depth_frac and forcing its use through the allometry routine --- biogeochem/EDCanopyStructureMod.F90 | 422 ++++++++------------- biogeochem/FatesAllometryMod.F90 | 2 +- biogeophys/FatesPlantRespPhotosynthMod.F90 | 2 +- parteh/PRTParametersMod.F90 | 2 +- parteh/PRTParamsFATESMod.F90 | 8 +- 5 files changed, 175 insertions(+), 261 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 3054fa692d..f981ba5102 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1493,7 +1493,6 @@ subroutine leaf_area_profile( currentSite ) real(r8) :: fraction_exposed ! how much of this layer is not covered by snow? real(r8) :: layer_top_hite ! notional top height of this canopy layer (m) real(r8) :: layer_bottom_hite ! notional bottom height of this canopy layer (m) - integer :: smooth_leaf_distribution ! is the leaf distribution this option (1) or not (0) real(r8) :: frac_canopy(N_HITE_BINS) ! amount of canopy in each height class real(r8) :: patch_lai ! LAI summed over the patch in m2/m2 of canopy area real(r8) :: minh(N_HITE_BINS) ! minimum height in height class (m) @@ -1503,11 +1502,10 @@ subroutine leaf_area_profile( currentSite ) real(r8) :: max_chite ! top of cohort canopy (m) real(r8) :: lai ! summed lai for checking m2 m-2 real(r8) :: leaf_c ! leaf carbon [kg] - + real(r8) :: crown_depth ! Vertical depth of the crown [m] + !---------------------------------------------------------------------- - smooth_leaf_distribution = 0 - ! Here we are trying to generate a profile of leaf area, indexed by 'z' and by pft ! We assume that each point in the canopy recieved the light attenuated by the average ! leaf area index above it, irrespective of PFT identity... @@ -1580,305 +1578,221 @@ subroutine leaf_area_profile( currentSite ) enddo !currentCohort - if(smooth_leaf_distribution == 1)then - - ! ----------------------------------------------------------------------------- - ! we are going to ignore the concept of canopy layers, and put all of the leaf - ! area into height banded bins. using the same domains as we had before, except - ! that CL always = 1 - ! ----------------------------------------------------------------------------- - - ! this is a crude way of dividing up the bins. Should it be a function of actual maximum height? - dh = 1.0_r8*(HITEMAX/N_HITE_BINS) - do iv = 1,N_HITE_BINS - if (iv == 1) then - minh(iv) = 0.0_r8 - maxh(iv) = dh - else - minh(iv) = (iv-1)*dh - maxh(iv) = (iv)*dh - endif - enddo - - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - ft = currentCohort%pft - min_chite = currentCohort%hite - currentCohort%hite * prt_params%crown(ft) - max_chite = currentCohort%hite - do iv = 1,N_HITE_BINS - frac_canopy(iv) = 0.0_r8 - ! this layer is in the middle of the canopy - if(max_chite > maxh(iv).and.min_chite < minh(iv))then - frac_canopy(iv)= min(1.0_r8,dh / (currentCohort%hite*prt_params%crown(ft))) - ! this is the layer with the bottom of the canopy in it. - elseif(min_chite < maxh(iv).and.min_chite > minh(iv).and.max_chite > maxh(iv))then - frac_canopy(iv) = (maxh(iv) -min_chite ) / (currentCohort%hite*prt_params%crown(ft)) - ! this is the layer with the top of the canopy in it. - elseif(max_chite > minh(iv).and.max_chite < maxh(iv).and.min_chite < minh(iv))then - frac_canopy(iv) = (max_chite - minh(iv)) / (currentCohort%hite*prt_params%crown(ft)) - elseif(max_chite < maxh(iv).and.min_chite > minh(iv))then !the whole cohort is within this layer. - frac_canopy(iv) = 1.0_r8 - endif + ! ----------------------------------------------------------------------------- + ! Standard canopy layering model. + ! Go through all cohorts and add their leaf area + ! and canopy area to the accumulators. + ! ----------------------------------------------------------------------------- - ! no m2 of leaf per m2 of ground in each height class - currentPatch%tlai_profile(1,ft,iv) = currentPatch%tlai_profile(1,ft,iv) + frac_canopy(iv) * & - currentCohort%lai - currentPatch%tsai_profile(1,ft,iv) = currentPatch%tsai_profile(1,ft,iv) + frac_canopy(iv) * & - currentCohort%sai - !snow burial - if(currentSite%snow_depth > maxh(iv))then - fraction_exposed = 0._r8 - endif - if(currentSite%snow_depth < minh(iv))then - fraction_exposed = 1._r8 - endif - if(currentSite%snow_depth >= minh(iv) .and. currentSite%snow_depth <= maxh(iv)) then !only partly hidden... - fraction_exposed = 1._r8 - max(0._r8,(min(1.0_r8,(currentSite%snow_depth-minh(iv))/dh))) - endif - - currentPatch%elai_profile(1,ft,iv) = currentPatch%tlai_profile(1,ft,iv) * fraction_exposed - currentPatch%esai_profile(1,ft,iv) = currentPatch%tsai_profile(1,ft,iv) * fraction_exposed - - enddo ! (iv) hite bins - - currentCohort => currentCohort%taller + currentCohort => currentPatch%shortest + do while(associated(currentCohort)) + ft = currentCohort%pft + cl = currentCohort%canopy_layer - enddo !currentCohort + ! ---------------------------------------------------------------- + ! How much of each tree is stem area index? Assuming that there is + ! This may indeed be zero if there is a sensecent grass + ! ---------------------------------------------------------------- - ! ----------------------------------------------------------------------------- - ! Perform a leaf area conservation check on the LAI profile - lai = 0.0_r8 - do ft = 1,numpft - lai = lai+ sum(currentPatch%tlai_profile(1,ft,:)) - enddo - - if(lai > patch_lai)then - write(fates_log(), *) 'FATES: problem with lai assignments' - call endrun(msg=errMsg(sourcefile, __LINE__)) + if( (currentCohort%treelai+currentCohort%treesai) > 0._r8)then + fleaf = currentCohort%lai / (currentCohort%lai + currentCohort%sai) + else + fleaf = 0._r8 endif + currentPatch%nrad(cl,ft) = currentPatch%ncan(cl,ft) - else ! smooth leaf distribution + if (currentPatch%nrad(cl,ft) > nlevleaf ) then + write(fates_log(), *) 'Number of radiative leaf layers is larger' + write(fates_log(), *) ' than the maximum allowed.' + write(fates_log(), *) ' cl: ',cl + write(fates_log(), *) ' ft: ',ft + write(fates_log(), *) ' nlevleaf: ',nlevleaf + write(fates_log(), *) ' currentPatch%nrad(cl,ft): ', currentPatch%nrad(cl,ft) + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if - ! ----------------------------------------------------------------------------- - ! Standard canopy layering model. - ! Go through all cohorts and add their leaf area - ! and canopy area to the accumulators. - ! ----------------------------------------------------------------------------- + call CrownDepth(currentCohort%hite,currentCohort%pft,crown_depth) + + ! -------------------------------------------------------------------------- + ! Whole layers. Make a weighted average of the leaf area in each layer + ! before dividing it by the total area. Fill up layer for whole layers. + ! -------------------------------------------------------------------------- + do iv = 1,currentCohort%NV - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - ft = currentCohort%pft - cl = currentCohort%canopy_layer + ! This loop builds the arrays that define the effective (not snow covered) + ! and total (includes snow covered) area indices for leaves and stems + ! We calculate the absolute elevation of each layer to help determine if the layer + ! is obscured by snow. + + layer_top_hite = currentCohort%hite - & + ( real(iv-1,r8)/currentCohort%NV * crown_depth ) - ! ---------------------------------------------------------------- - ! How much of each tree is stem area index? Assuming that there is - ! This may indeed be zero if there is a sensecent grass - ! ---------------------------------------------------------------- + layer_bottom_hite = currentCohort%hite - & + ( real(iv,r8)/currentCohort%NV * crown_depth ) - if( (currentCohort%treelai+currentCohort%treesai) > 0._r8)then - fleaf = currentCohort%lai / (currentCohort%lai + currentCohort%sai) - else - fleaf = 0._r8 + fraction_exposed = 1.0_r8 + if(currentSite%snow_depth > layer_top_hite)then + fraction_exposed = 0._r8 + endif + if(currentSite%snow_depth < layer_bottom_hite)then + fraction_exposed = 1._r8 + endif + if(currentSite%snow_depth >= layer_bottom_hite .and. & + currentSite%snow_depth <= layer_top_hite) then !only partly hidden... + fraction_exposed = 1._r8 - max(0._r8,(min(1.0_r8,(currentSite%snow_depth -layer_bottom_hite)/ & + (layer_top_hite-layer_bottom_hite )))) endif - currentPatch%nrad(cl,ft) = currentPatch%ncan(cl,ft) + if(iv==currentCohort%NV) then + remainder = (currentCohort%treelai + currentCohort%treesai) - & + (dlower_vai(iv) - dinc_vai(iv)) + if(remainder > dinc_vai(iv) )then + write(fates_log(), *)'ED: issue with remainder', & + currentCohort%treelai,currentCohort%treesai,dinc_vai(iv), & + currentCohort%NV,remainder - if (currentPatch%nrad(cl,ft) > nlevleaf ) then - write(fates_log(), *) 'Number of radiative leaf layers is larger' - write(fates_log(), *) ' than the maximum allowed.' - write(fates_log(), *) ' cl: ',cl - write(fates_log(), *) ' ft: ',ft - write(fates_log(), *) ' nlevleaf: ',nlevleaf - write(fates_log(), *) ' currentPatch%nrad(cl,ft): ', currentPatch%nrad(cl,ft) - call endrun(msg=errMsg(sourcefile, __LINE__)) + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + else + remainder = dinc_vai(iv) end if + currentPatch%tlai_profile(cl,ft,iv) = currentPatch%tlai_profile(cl,ft,iv) + & + remainder * fleaf * currentCohort%c_area/currentPatch%total_canopy_area - ! -------------------------------------------------------------------------- - ! Whole layers. Make a weighted average of the leaf area in each layer - ! before dividing it by the total area. Fill up layer for whole layers. - ! -------------------------------------------------------------------------- + currentPatch%elai_profile(cl,ft,iv) = currentPatch%elai_profile(cl,ft,iv) + & + remainder * fleaf * currentCohort%c_area/currentPatch%total_canopy_area * & + fraction_exposed - do iv = 1,currentCohort%NV + currentPatch%tsai_profile(cl,ft,iv) = currentPatch%tsai_profile(cl,ft,iv) + & + remainder * (1._r8 - fleaf) * currentCohort%c_area/currentPatch%total_canopy_area - ! This loop builds the arrays that define the effective (not snow covered) - ! and total (includes snow covered) area indices for leaves and stems - ! We calculate the absolute elevation of each layer to help determine if the layer - ! is obscured by snow. + currentPatch%esai_profile(cl,ft,iv) = currentPatch%esai_profile(cl,ft,iv) + & + remainder * (1._r8 - fleaf) * currentCohort%c_area/currentPatch%total_canopy_area * & + fraction_exposed - layer_top_hite = currentCohort%hite - & - ( real(iv-1,r8)/currentCohort%NV * currentCohort%hite * & - prt_params%crown(currentCohort%pft) ) + currentPatch%canopy_area_profile(cl,ft,iv) = currentPatch%canopy_area_profile(cl,ft,iv) + & + currentCohort%c_area/currentPatch%total_canopy_area - layer_bottom_hite = currentCohort%hite - & - ( real(iv,r8)/currentCohort%NV * currentCohort%hite * & - prt_params%crown(currentCohort%pft) ) + currentPatch%layer_height_profile(cl,ft,iv) = currentPatch%layer_height_profile(cl,ft,iv) + & + (remainder * fleaf * currentCohort%c_area/currentPatch%total_canopy_area * & + (layer_top_hite+layer_bottom_hite)/2.0_r8) !average height of layer. - fraction_exposed = 1.0_r8 - if(currentSite%snow_depth > layer_top_hite)then - fraction_exposed = 0._r8 - endif - if(currentSite%snow_depth < layer_bottom_hite)then - fraction_exposed = 1._r8 - endif - if(currentSite%snow_depth >= layer_bottom_hite .and. & - currentSite%snow_depth <= layer_top_hite) then !only partly hidden... - fraction_exposed = 1._r8 - max(0._r8,(min(1.0_r8,(currentSite%snow_depth -layer_bottom_hite)/ & - (layer_top_hite-layer_bottom_hite )))) - endif - - if(iv==currentCohort%NV) then - remainder = (currentCohort%treelai + currentCohort%treesai) - & - (dlower_vai(iv) - dinc_vai(iv)) - if(remainder > dinc_vai(iv) )then - write(fates_log(), *)'ED: issue with remainder', & - currentCohort%treelai,currentCohort%treesai,dinc_vai(iv), & - currentCohort%NV,remainder - - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - else - remainder = dinc_vai(iv) - end if + end do - currentPatch%tlai_profile(cl,ft,iv) = currentPatch%tlai_profile(cl,ft,iv) + & - remainder * fleaf * currentCohort%c_area/currentPatch%total_canopy_area + currentCohort => currentCohort%taller - currentPatch%elai_profile(cl,ft,iv) = currentPatch%elai_profile(cl,ft,iv) + & - remainder * fleaf * currentCohort%c_area/currentPatch%total_canopy_area * & - fraction_exposed + enddo !cohort - currentPatch%tsai_profile(cl,ft,iv) = currentPatch%tsai_profile(cl,ft,iv) + & - remainder * (1._r8 - fleaf) * currentCohort%c_area/currentPatch%total_canopy_area + ! -------------------------------------------------------------------------- - currentPatch%esai_profile(cl,ft,iv) = currentPatch%esai_profile(cl,ft,iv) + & - remainder * (1._r8 - fleaf) * currentCohort%c_area/currentPatch%total_canopy_area * & - fraction_exposed + ! If there is an upper-story, the top canopy layer + ! should have a value of exactly 1.0 in its top leaf layer + ! -------------------------------------------------------------------------- - currentPatch%canopy_area_profile(cl,ft,iv) = currentPatch%canopy_area_profile(cl,ft,iv) + & + if ( (currentPatch%NCL_p > 1) .and. & + (sum(currentPatch%canopy_area_profile(1,:,1)) < 0.9999 )) then + write(fates_log(), *) 'FATES: canopy_area_profile was less than 1 at the canopy top' + write(fates_log(), *) 'cl: ',1 + write(fates_log(), *) 'iv: ',1 + write(fates_log(), *) 'sum(cpatch%canopy_area_profile(1,:,1)): ', & + sum(currentPatch%canopy_area_profile(1,:,1)) + currentCohort => currentPatch%shortest + do while(associated(currentCohort)) + if(currentCohort%canopy_layer==1)then + write(fates_log(), *) 'FATES: cohorts',currentCohort%dbh,currentCohort%c_area, & + currentPatch%total_canopy_area,currentPatch%area + write(fates_log(), *) 'ED: fracarea', currentCohort%pft, & currentCohort%c_area/currentPatch%total_canopy_area - - currentPatch%layer_height_profile(cl,ft,iv) = currentPatch%layer_height_profile(cl,ft,iv) + & - (remainder * fleaf * currentCohort%c_area/currentPatch%total_canopy_area * & - (layer_top_hite+layer_bottom_hite)/2.0_r8) !average height of layer. - - end do - + endif currentCohort => currentCohort%taller + enddo !currentCohort + call endrun(msg=errMsg(sourcefile, __LINE__)) - enddo !cohort - - ! -------------------------------------------------------------------------- + end if - ! If there is an upper-story, the top canopy layer - ! should have a value of exactly 1.0 in its top leaf layer - ! -------------------------------------------------------------------------- - if ( (currentPatch%NCL_p > 1) .and. & - (sum(currentPatch%canopy_area_profile(1,:,1)) < 0.9999 )) then - write(fates_log(), *) 'FATES: canopy_area_profile was less than 1 at the canopy top' - write(fates_log(), *) 'cl: ',1 - write(fates_log(), *) 'iv: ',1 - write(fates_log(), *) 'sum(cpatch%canopy_area_profile(1,:,1)): ', & - sum(currentPatch%canopy_area_profile(1,:,1)) - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - if(currentCohort%canopy_layer==1)then - write(fates_log(), *) 'FATES: cohorts',currentCohort%dbh,currentCohort%c_area, & - currentPatch%total_canopy_area,currentPatch%area - write(fates_log(), *) 'ED: fracarea', currentCohort%pft, & - currentCohort%c_area/currentPatch%total_canopy_area - endif - currentCohort => currentCohort%taller - enddo !currentCohort - call endrun(msg=errMsg(sourcefile, __LINE__)) + ! -------------------------------------------------------------------------- + ! In the following loop we are now normalizing the effective and + ! total area profiles to convert from units of leaf/stem area per vegetated + ! canopy area, into leaf/stem area per area of their own radiative column + ! which is typically the footprint of all cohorts contained in the canopy + ! layer x pft bins. + ! Also perform some checks on area normalization. + ! Check the area of each leaf layer, across pfts. + ! It should never be larger than 1 or less than 0. + ! -------------------------------------------------------------------------- - end if + do cl = 1,currentPatch%NCL_p + do iv = 1,currentPatch%ncan(cl,ft) + if( debug .and. sum(currentPatch%canopy_area_profile(cl,:,iv)) > 1.0001_r8 ) then - ! -------------------------------------------------------------------------- - ! In the following loop we are now normalizing the effective and - ! total area profiles to convert from units of leaf/stem area per vegetated - ! canopy area, into leaf/stem area per area of their own radiative column - ! which is typically the footprint of all cohorts contained in the canopy - ! layer x pft bins. - ! Also perform some checks on area normalization. - ! Check the area of each leaf layer, across pfts. - ! It should never be larger than 1 or less than 0. - ! -------------------------------------------------------------------------- + write(fates_log(), *) 'FATES: A canopy_area_profile exceeded 1.0' + write(fates_log(), *) 'cl: ',cl + write(fates_log(), *) 'iv: ',iv + write(fates_log(), *) 'sum(cpatch%canopy_area_profile(cl,:,iv)): ', & + sum(currentPatch%canopy_area_profile(cl,:,iv)) + currentCohort => currentPatch%shortest + do while(associated(currentCohort)) + if(currentCohort%canopy_layer==cl)then + write(fates_log(), *) 'FATES: cohorts in layer cl = ',cl, & + currentCohort%dbh,currentCohort%c_area, & + currentPatch%total_canopy_area,currentPatch%area + write(fates_log(), *) 'ED: fracarea', currentCohort%pft, & + currentCohort%c_area/currentPatch%total_canopy_area + endif + currentCohort => currentCohort%taller + enddo !currentCohort + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + end do - do cl = 1,currentPatch%NCL_p + do ft = 1,numpft do iv = 1,currentPatch%ncan(cl,ft) - if( debug .and. sum(currentPatch%canopy_area_profile(cl,:,iv)) > 1.0001_r8 ) then - - write(fates_log(), *) 'FATES: A canopy_area_profile exceeded 1.0' - write(fates_log(), *) 'cl: ',cl - write(fates_log(), *) 'iv: ',iv - write(fates_log(), *) 'sum(cpatch%canopy_area_profile(cl,:,iv)): ', & - sum(currentPatch%canopy_area_profile(cl,:,iv)) - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - if(currentCohort%canopy_layer==cl)then - write(fates_log(), *) 'FATES: cohorts in layer cl = ',cl, & - currentCohort%dbh,currentCohort%c_area, & - currentPatch%total_canopy_area,currentPatch%area - write(fates_log(), *) 'ED: fracarea', currentCohort%pft, & - currentCohort%c_area/currentPatch%total_canopy_area - endif - currentCohort => currentCohort%taller - enddo !currentCohort - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - end do - - do ft = 1,numpft - do iv = 1,currentPatch%ncan(cl,ft) - - if( currentPatch%canopy_area_profile(cl,ft,iv) > nearzero ) then + if( currentPatch%canopy_area_profile(cl,ft,iv) > nearzero ) then - currentPatch%tlai_profile(cl,ft,iv) = currentPatch%tlai_profile(cl,ft,iv) / & - currentPatch%canopy_area_profile(cl,ft,iv) + currentPatch%tlai_profile(cl,ft,iv) = currentPatch%tlai_profile(cl,ft,iv) / & + currentPatch%canopy_area_profile(cl,ft,iv) - currentPatch%tsai_profile(cl,ft,iv) = currentPatch%tsai_profile(cl,ft,iv) / & - currentPatch%canopy_area_profile(cl,ft,iv) + currentPatch%tsai_profile(cl,ft,iv) = currentPatch%tsai_profile(cl,ft,iv) / & + currentPatch%canopy_area_profile(cl,ft,iv) - currentPatch%elai_profile(cl,ft,iv) = currentPatch%elai_profile(cl,ft,iv) / & - currentPatch%canopy_area_profile(cl,ft,iv) + currentPatch%elai_profile(cl,ft,iv) = currentPatch%elai_profile(cl,ft,iv) / & + currentPatch%canopy_area_profile(cl,ft,iv) - currentPatch%esai_profile(cl,ft,iv) = currentPatch%esai_profile(cl,ft,iv) / & - currentPatch%canopy_area_profile(cl,ft,iv) - end if - - if(currentPatch%tlai_profile(cl,ft,iv)>nearzero )then - currentPatch%layer_height_profile(cl,ft,iv) = currentPatch%layer_height_profile(cl,ft,iv) & - /currentPatch%tlai_profile(cl,ft,iv) - end if + currentPatch%esai_profile(cl,ft,iv) = currentPatch%esai_profile(cl,ft,iv) / & + currentPatch%canopy_area_profile(cl,ft,iv) + end if - enddo + if(currentPatch%tlai_profile(cl,ft,iv)>nearzero )then + currentPatch%layer_height_profile(cl,ft,iv) = currentPatch%layer_height_profile(cl,ft,iv) & + /currentPatch%tlai_profile(cl,ft,iv) + end if enddo - enddo - ! -------------------------------------------------------------------------- - ! Set the mask that identifies which PFT x can-layer combinations have - ! scattering elements in them. - ! -------------------------------------------------------------------------- + enddo + enddo - do cl = 1,currentPatch%NCL_p - do ft = 1,numpft - do iv = 1, currentPatch%nrad(cl,ft) - if(currentPatch%canopy_area_profile(cl,ft,iv) > 0._r8)then - currentPatch%canopy_mask(cl,ft) = 1 - endif - end do !iv - enddo !ft - enddo ! loop over cl + ! -------------------------------------------------------------------------- + ! Set the mask that identifies which PFT x can-layer combinations have + ! scattering elements in them. + ! -------------------------------------------------------------------------- - endif !leaf distribution + do cl = 1,currentPatch%NCL_p + do ft = 1,numpft + do iv = 1, currentPatch%nrad(cl,ft) + if(currentPatch%canopy_area_profile(cl,ft,iv) > 0._r8)then + currentPatch%canopy_mask(cl,ft) = 1 + endif + end do !iv + enddo !ft + enddo ! loop over cl end if diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index df05b7de29..6095f10fba 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -2008,7 +2008,7 @@ subroutine CrownDepth(height,ft,crown_depth) ! Original FATES crown depth heigh used for hydraulics ! crown_depth = min(height,0.1_r8) - crown_depth = prt_params%crown(ft) * height + crown_depth = prt_params%crown_depth_frac(ft) * height return diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index d488cd2ba4..fe7f206a45 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -93,7 +93,7 @@ module FATESPlantRespPhotosynthMod ! Alternatively, Gross Assimilation can be used to estimate ! leaf co2 partial pressure and therefore conductance. The default - !is to use anet + ! is to use anet integer, parameter :: net_assim_model = 1 integer, parameter :: gross_assim_model = 2 diff --git a/parteh/PRTParametersMod.F90 b/parteh/PRTParametersMod.F90 index 04a0f5dda0..ec41595486 100644 --- a/parteh/PRTParametersMod.F90 +++ b/parteh/PRTParametersMod.F90 @@ -101,7 +101,7 @@ module PRTParametersMod real(r8), allocatable :: c2b(:) ! Carbon to biomass multiplier [kg/kgC] real(r8), allocatable :: wood_density(:) ! wood density g cm^-3 ... real(r8), allocatable :: woody(:) ! Does the plant have wood? (1=yes, 0=no) - real(r8), allocatable :: crown(:) ! fraction of the height of the plant + real(r8), allocatable :: crown_depth_frac(:) ! fraction of the height of the plant ! that is occupied by crown real(r8), allocatable :: slamax(:) ! Maximum specific leaf area of plant (at bottom) [m2/gC] real(r8), allocatable :: slatop(:) ! Specific leaf area at canopy top [m2/gC] diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index 6e996cac3e..2f1762dd5b 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -179,7 +179,7 @@ subroutine PRTRegisterPFT(fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_fire_crown_depth_frac' + name = 'fates_crown_depth_frac' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -435,9 +435,9 @@ subroutine PRTReceivePFT(fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%fnrt_prof_mode) - name = 'fates_fire_crown_depth_frac' + name = 'fates_crown_depth_frac' call fates_params%RetreiveParameterAllocate(name=name, & - data=prt_params%crown) + data=prt_params%crown_depth_frac) name = 'fates_woody' call fates_params%RetreiveParameterAllocate(name=name, & @@ -911,7 +911,7 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'prt_phos_stoich_p2 = ',prt_params%phos_stoich_p2 write(fates_log(),fmt0) 'prt_alloc_priority = ',prt_params%alloc_priority write(fates_log(),fmt0) 'woody = ',prt_params%woody - write(fates_log(),fmt0) 'crown = ',prt_params%crown + write(fates_log(),fmt0) 'crown_depth_frac = ',prt_params%crown_depth_frac write(fates_log(),fmt0) 'roota_par = ',prt_params%fnrt_prof_a write(fates_log(),fmt0) 'rootb_par = ',prt_params%fnrt_prof_b write(fates_log(),fmt0) 'fnrt_prof_mode = ',prt_params%fnrt_prof_mode From 3a7e083bee32019c57ad982d8d0321ecde32f64a Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 27 Apr 2022 15:24:36 -0400 Subject: [PATCH 181/852] Added new param fields for phenology and damage --- parameter_files/fates_params_default.cdl | 61 +++++++++++++++++++++--- tools/ncvarsort.py | 1 + 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 993aaac004..942878c86f 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -5,6 +5,7 @@ dimensions: fates_history_height_bins = 6 ; fates_history_size_bins = 13 ; fates_history_coage_bins = 2 ; + fates_history_damage_bins = 6 ; fates_hydr_organs = 4 ; fates_leafage_class = 1 ; fates_litterclass = 6 ; @@ -25,6 +26,9 @@ variables: double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; fates_history_sizeclass_bin_edges:units = "cm" ; fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; + double fates_history_damage_bin_edges(fates_history_damage_bins) ; + fates_history_damage_bin_edges:units = "% crown loss" ; + fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; double fates_hydr_htftype_node(fates_hydr_organs) ; fates_hydr_htftype_node:units = "unitless" ; fates_hydr_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; @@ -162,6 +166,18 @@ variables: double fates_displar(fates_pft) ; fates_displar:units = "unitless" ; fates_displar:long_name = "Ratio of displacement height to canopy top height" ; + double fates_damage_frac(fates_pft) ; + fates_damage_frac:units = "fraction"; + fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)"; + double fates_damage_mort_p1(fates_pft) ; + fates_damage_mort_p1:units = "fraction crown loss - a value of 0.8 means 50% mortality with 80% loss of crown"; + fates_damage_mort_p1:long_name = "inflection point of damage mortality function - to turn off damage mortality set this to a large number" ; + double fates_damage_mort_p2(fates_pft) ; + fates_damage_mort_p2:units = "unitless"; + fates_damage_mort_p2:long_name = "rate of mortality increase with damage"; + double fates_damage_recovery_scalar(fates_pft) ; + fates_damage_recovery_scalar:units = "unitless"; + fates_damage_recovery_scalar:long_name = "fraction of cohort that recovers from damage"; double fates_eca_alpha_ptase(fates_pft) ; fates_eca_alpha_ptase:units = "g/m3" ; fates_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; @@ -207,7 +223,10 @@ variables: double fates_fire_crown_kill(fates_pft) ; fates_fire_crown_kill:units = "NA" ; fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; - double fates_fnrt_prof_a(fates_pft) ; + double fates_fnrt_adapt_tscale(fates_pft) ; + fates_fnrt_adapt_tscale:units = "days" ; + fates_fnrt_adapt_tscale:long_name = "Number of days that is the shortest possible doubling period for fine-root adaptation (CNP only)" ; + double fates_fnrt_prof_a(fates_pft) ; fates_fnrt_prof_a:units = "unitless" ; fates_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; double fates_fnrt_prof_b(fates_pft) ; @@ -722,9 +741,20 @@ variables: double fates_phen_doff_time ; fates_phen_doff_time:units = "days" ; fates_phen_doff_time:long_name = "day threshold compared against days since leaves became off-allometry" ; + double fates_phen_drought_model ; + fates_phen_drought_model:units = "none" ; + fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; double fates_phen_drought_threshold ; - fates_phen_drought_threshold:units = "m3/m3" ; - fates_phen_drought_threshold:long_name = "liquid volume in soil layer, threashold for drought phenology" ; + fates_phen_drought_threshold:units = "m3/m3 or mm" ; + fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)." ; + + double fates_phen_moist_threshold ; + fates_phen_moist_threshold:units = "m3/m3 or mm" ; + fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)." ; + double fates_phen_fnrt_drop_fraction(fates_pft) ; + fates_phen_fnrt_drop_fraction:units = "fraction" ; + fates_phen_fnrt_drop_fraction:long_name = "fraction of fine roots to drop during drought/cold" ; + double fates_phen_mindayson ; fates_phen_mindayson:units = "days" ; fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; @@ -757,10 +787,10 @@ variables: fates_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; double fates_vai_top_bin_width ; fates_vai_top_bin_width:units = "m2/m2" ; - fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer (NOT USED)" ; + fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; double fates_vai_width_increase_factor ; fates_vai_width_increase_factor:units = "unitless" ; - fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing) (NOT USED)" ; + fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; // global attributes: :history = "This parameter file is maintained in version control\nSee https://github.com/NGEET/fates/blob/master/parameter_files/fates_params_default.cdl \nFor changes, use git blame \n" ; @@ -772,8 +802,9 @@ data: fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; - fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, - 80, 90, 100 ; + fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100 ; + + fates_history_damage_bin_edges = 0, 20, 40, 60, 80, 100 ; fates_hydr_htftype_node = 1, 1, 1, 1 ; @@ -909,6 +940,14 @@ data: fates_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67 ; + fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; + + fates_damage_mort_p1 = 9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0 ; + + fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5 ; + + fates_damage_recovery_scalar = 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ; + fates_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; @@ -951,6 +990,8 @@ data: fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775 ; + fates_fnrt_adapt_tscale = 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0; + fates_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; fates_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; @@ -1172,6 +1213,8 @@ data: fates_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5 ; + fates_phen_fnrt_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; @@ -1471,8 +1514,12 @@ data: fates_phen_doff_time = 100 ; + fates_phen_drought_model = 0 ; + fates_phen_drought_threshold = 0.15 ; + fates_phen_moist_threshold = 0.5 ; + fates_phen_mindayson = 90 ; fates_phen_ncolddayslim = 5 ; diff --git a/tools/ncvarsort.py b/tools/ncvarsort.py index e9cdc422b4..84b4212726 100755 --- a/tools/ncvarsort.py +++ b/tools/ncvarsort.py @@ -38,6 +38,7 @@ def main(): (u'fates_history_coage_bins',):1, (u'fates_history_height_bins',):2, (u'fates_history_size_bins',):3, + (u'fates_history_damage_bins',):3, (u'fates_hydr_organs',):4, (u'fates_prt_organs',):4, (u'fates_pft', u'fates_string_length'):5, From 8e85fb1c885c5133d261f527ca6b3429cac75022 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 27 Apr 2022 15:25:18 -0400 Subject: [PATCH 182/852] Sorted fates default param file --- parameter_files/fates_params_default.cdl | 373 ++++++++++++----------- 1 file changed, 188 insertions(+), 185 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 942878c86f..15592091f0 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1,4 +1,4 @@ -netcdf fates_params_default.c210629_sorted { +netcdf fates_params_default.c220425_sorted { dimensions: fates_NCWD = 4 ; fates_history_age_bins = 7 ; @@ -23,12 +23,12 @@ variables: double fates_history_height_bin_edges(fates_history_height_bins) ; fates_history_height_bin_edges:units = "m" ; fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; + double fates_history_damage_bin_edges(fates_history_damage_bins) ; + fates_history_damage_bin_edges:units = "% crown loss" ; + fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; fates_history_sizeclass_bin_edges:units = "cm" ; fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; - double fates_history_damage_bin_edges(fates_history_damage_bins) ; - fates_history_damage_bin_edges:units = "% crown loss" ; - fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; double fates_hydr_htftype_node(fates_hydr_organs) ; fates_hydr_htftype_node:units = "unitless" ; fates_hydr_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; @@ -160,24 +160,27 @@ variables: double fates_c2b(fates_pft) ; fates_c2b:units = "ratio" ; fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; + double fates_crown_depth_frac(fates_pft) ; + fates_crown_depth_frac:units = "fraction" ; + fates_crown_depth_frac:long_name = "the depth of a cohorts crown as a fraction of its height" ; + double fates_damage_frac(fates_pft) ; + fates_damage_frac:units = "fraction" ; + fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; + double fates_damage_mort_p1(fates_pft) ; + fates_damage_mort_p1:units = "fraction crown loss - a value of 0.8 means 50% mortality with 80% loss of crown" ; + fates_damage_mort_p1:long_name = "inflection point of damage mortality function - to turn off damage mortality set this to a large number" ; + double fates_damage_mort_p2(fates_pft) ; + fates_damage_mort_p2:units = "unitless" ; + fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; + double fates_damage_recovery_scalar(fates_pft) ; + fates_damage_recovery_scalar:units = "unitless" ; + fates_damage_recovery_scalar:long_name = "fraction of cohort that recovers from damage" ; 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" ; double fates_displar(fates_pft) ; fates_displar:units = "unitless" ; fates_displar:long_name = "Ratio of displacement height to canopy top height" ; - double fates_damage_frac(fates_pft) ; - fates_damage_frac:units = "fraction"; - fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)"; - double fates_damage_mort_p1(fates_pft) ; - fates_damage_mort_p1:units = "fraction crown loss - a value of 0.8 means 50% mortality with 80% loss of crown"; - fates_damage_mort_p1:long_name = "inflection point of damage mortality function - to turn off damage mortality set this to a large number" ; - double fates_damage_mort_p2(fates_pft) ; - fates_damage_mort_p2:units = "unitless"; - fates_damage_mort_p2:long_name = "rate of mortality increase with damage"; - double fates_damage_recovery_scalar(fates_pft) ; - fates_damage_recovery_scalar:units = "unitless"; - fates_damage_recovery_scalar:long_name = "fraction of cohort that recovers from damage"; double fates_eca_alpha_ptase(fates_pft) ; fates_eca_alpha_ptase:units = "g/m3" ; fates_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; @@ -217,16 +220,13 @@ variables: double fates_fire_bark_scaler(fates_pft) ; fates_fire_bark_scaler:units = "fraction" ; fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; - double fates_crown_depth_frac(fates_pft) ; - fates_crown_depth_frac:units = "fraction" ; - fates_crown_depth_frac:long_name = "the depth of a cohorts crown as a fraction of its height" ; double fates_fire_crown_kill(fates_pft) ; fates_fire_crown_kill:units = "NA" ; fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; - double fates_fnrt_adapt_tscale(fates_pft) ; + double fates_fnrt_adapt_tscale(fates_pft) ; fates_fnrt_adapt_tscale:units = "days" ; fates_fnrt_adapt_tscale:long_name = "Number of days that is the shortest possible doubling period for fine-root adaptation (CNP only)" ; - double fates_fnrt_prof_a(fates_pft) ; + double fates_fnrt_prof_a(fates_pft) ; fates_fnrt_prof_a:units = "unitless" ; fates_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; double fates_fnrt_prof_b(fates_pft) ; @@ -422,6 +422,9 @@ variables: double fates_phen_evergreen(fates_pft) ; fates_phen_evergreen:units = "logical flag" ; fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; + double fates_phen_fnrt_drop_fraction(fates_pft) ; + fates_phen_fnrt_drop_fraction:units = "fraction" ; + fates_phen_fnrt_drop_fraction:long_name = "fraction of fine roots to drop during drought/cold" ; double fates_phen_season_decid(fates_pft) ; fates_phen_season_decid:units = "logical flag" ; fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; @@ -450,10 +453,10 @@ variables: fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; double fates_prescribed_nuptake(fates_pft) ; - fates_prescribed_nuptake:units = "fraction" ; + fates_prescribed_nuptake:units = "fraction" ; fates_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; double fates_prescribed_puptake(fates_pft) ; - fates_prescribed_puptake:units = "fraction" ; + fates_prescribed_puptake:units = "fraction" ; fates_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; double fates_prescribed_recruitment(fates_pft) ; fates_prescribed_recruitment:units = "n/yr" ; @@ -561,9 +564,9 @@ variables: double fates_z0mr(fates_pft) ; fates_z0mr:units = "unitless" ; fates_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; - double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; - fates_hlm_pft_map:units = "area fraction" ; - fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; double fates_fire_FBD(fates_litterclass) ; fates_fire_FBD:units = "kg Biomass/m3" ; fates_fire_FBD:long_name = "fuel bulk density" ; @@ -675,8 +678,8 @@ variables: double fates_hydr_psicap ; fates_hydr_psicap:units = "MPa" ; fates_hydr_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; - double fates_hydr_solver ; - fates_hydr_solver:units = "unitless" ; + double fates_hydr_solver ; + fates_hydr_solver:units = "unitless" ; fates_hydr_solver:long_name = "switch designating which numerical solver for plant hydraulics, 1 = 1D taylor, 2 = 2D Picard" ; double fates_init_litter ; fates_init_litter:units = "NA" ; @@ -742,22 +745,17 @@ variables: fates_phen_doff_time:units = "days" ; fates_phen_doff_time:long_name = "day threshold compared against days since leaves became off-allometry" ; double fates_phen_drought_model ; - fates_phen_drought_model:units = "none" ; - fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; + fates_phen_drought_model:units = "none" ; + fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; double fates_phen_drought_threshold ; fates_phen_drought_threshold:units = "m3/m3 or mm" ; fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)." ; - - double fates_phen_moist_threshold ; - fates_phen_moist_threshold:units = "m3/m3 or mm" ; - fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)." ; - double fates_phen_fnrt_drop_fraction(fates_pft) ; - fates_phen_fnrt_drop_fraction:units = "fraction" ; - fates_phen_fnrt_drop_fraction:long_name = "fraction of fine roots to drop during drought/cold" ; - double fates_phen_mindayson ; fates_phen_mindayson:units = "days" ; fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; + double fates_phen_moist_threshold ; + fates_phen_moist_threshold:units = "m3/m3 or mm" ; + fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)." ; double fates_phen_ncolddayslim ; fates_phen_ncolddayslim:units = "days" ; fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; @@ -777,7 +775,7 @@ variables: fates_soil_salinity:units = "ppt" ; fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; double fates_stomatal_assim ; - fates_stomatal_assim:units = "unitless" ; + fates_stomatal_assim:units = "unitless" ; fates_stomatal_assim:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; double fates_theta_cj_c3 ; fates_theta_cj_c3:units = "unitless" ; @@ -802,10 +800,11 @@ data: fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; - fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100 ; - fates_history_damage_bin_edges = 0, 20, 40, 60, 80, 100 ; + fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, + 80, 90, 100 ; + fates_hydr_htftype_node = 1, 1, 1, 1 ; fates_prt_organ_id = 1, 2, 3, 6 ; @@ -844,22 +843,22 @@ data: "sapwood ", "structure " ; - fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 ; - fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, + fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; - fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, + fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572 ; - fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, + fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94 ; - fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, + fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931 ; - fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6 ; fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -868,30 +867,30 @@ data: fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07 ; - fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, + fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3 ; - fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, + fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55 ; - fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, + fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464 ; - fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, + fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119 ; - fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, + fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64 ; - fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, + fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37 ; - fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, + fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 ; fates_allom_dbh_maxheight = 90, 90, 90, 90, 90, 90, 3, 3, 2, 0.35, 0.35, 0.35 ; @@ -904,14 +903,14 @@ data: fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 ; fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -922,42 +921,47 @@ data: fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; - fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 ; - fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, + fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; - fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 ; fates_branch_turnover = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; - fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; + fates_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, 0.95, 1, + 1, 1 ; - fates_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, - 0.67, 0.67 ; + fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01 ; + + fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; - fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; + fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, + 5.5, 5.5 ; - fates_damage_mort_p1 = 9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0 ; + fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5 ; + fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; - fates_damage_recovery_scalar = 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ; + fates_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, + 0.67, 0.67 ; - fates_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + fates_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + fates_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280 ; - fates_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, + fates_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14 ; - fates_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, + fates_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27 ; fates_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; @@ -966,31 +970,29 @@ data: fates_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_eca_vmax_nh4 = 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, + fates_eca_vmax_nh4 = 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07 ; - fates_eca_vmax_no3 = 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, + fates_eca_vmax_no3 = 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08 ; - fates_eca_vmax_p = 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, + fates_eca_vmax_p = 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09 ; - fates_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + fates_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 ; - fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07 ; - fates_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, - 0.95, 1, 1, 1 ; - - fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, + fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775 ; - fates_fnrt_adapt_tscale = 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0; + fates_fnrt_adapt_tscale = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; fates_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; @@ -1000,16 +1002,16 @@ data: fates_fr_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_fr_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + fates_fr_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25 ; - fates_fr_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + fates_fr_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25 ; - fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, + fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - fates_hydr_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + fates_hydr_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5 ; fates_hydr_avuln_node = @@ -1038,34 +1040,34 @@ data: -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; - fates_hydr_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + fates_hydr_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5 ; fates_hydr_p50_node = - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25 ; - fates_hydr_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, + fates_hydr_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333 ; fates_hydr_pinot_node = - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; fates_hydr_pitlp_node = - -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, @@ -1077,10 +1079,10 @@ data: 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - fates_hydr_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + fates_hydr_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625 ; - fates_hydr_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, + fates_hydr_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; fates_hydr_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; @@ -1092,13 +1094,13 @@ data: 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; fates_hydr_vg_alpha_node = - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005 ; fates_hydr_vg_m_node = @@ -1115,79 +1117,79 @@ data: fates_leaf_c3psn = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ; - fates_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, + fates_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, 0.9, 0.75, 0.75, 0.75 ; - fates_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, + fates_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04 ; - fates_leaf_jmaxha = 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, + fates_leaf_jmaxha = 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540 ; - fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, + fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040 ; - fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, + fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495 ; fates_leaf_long = 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, + fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, 0.03, 0.03, 0.03, 0.03, 0.03 ; - fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, + fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, 0.03, 0.03, 0.03, 0.03 ; - fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, + fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 40000 ; fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, + fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, 4.7, 2.2, 5.3, 1.6 ; - fates_leaf_stor_priority = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + fates_leaf_stor_priority = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 ; fates_leaf_vcmax25top = 50, 65, 39, 62, 41, 58, 62, 54, 54, 78, 78, 78 ; - fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, + fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330 ; - fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, + fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250 ; - fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, + fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485 ; - fates_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, -0.23, + fates_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, -0.23, -0.23, -0.23 ; fates_lf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_lf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + fates_lf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25 ; - fates_lf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + fates_lf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25 ; - fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, + fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014 ; - fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -60, -10, -80, -80, + fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -60, -10, -80, -80, -20, 2.5 ; - fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, + fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; @@ -1200,25 +1202,25 @@ data: fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6 ; - fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6 ; fates_nfix1 = _, _, _, _, _, _, _, _, _, _, _, _ ; fates_nfix2 = _, _, _, _, _, _, _, _, _, _, _, _ ; - fates_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + fates_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5 ; - fates_phen_fnrt_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; + fates_phen_fnrt_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; @@ -1227,26 +1229,26 @@ data: fates_phenflush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + fates_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5 ; - fates_prescribed_mortality_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, + fates_prescribed_mortality_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; - fates_prescribed_mortality_understory = 0.025, 0.025, 0.025, 0.025, 0.025, + fates_prescribed_mortality_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; - fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, + fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4 ; - fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, + fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; fates_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_prescribed_recruitment = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, + fates_prescribed_recruitment = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02 ; fates_prt_alloc_priority = @@ -1257,57 +1259,58 @@ data: fates_prt_nitr_stoich_p1 = 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047 ; fates_prt_nitr_stoich_p2 = 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047 ; fates_prt_phos_stoich_p1 = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047 ; fates_prt_phos_stoich_p2 = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047 ; - fates_recruit_hgt_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, + fates_recruit_hgt_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, 0.125, 0.125, 0.125 ; - fates_recruit_initd = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + fates_recruit_initd = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 ; - fates_rholnir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, 0.41, 0.28, + fates_rholnir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, 0.41, 0.28, 0.28, 0.28 ; - fates_rholvis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, 0.08, 0.05, 0.05, 0.05 ; + fates_rholvis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, 0.08, 0.05, + 0.05, 0.05 ; - fates_rhosnir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, 0.49, 0.53, + fates_rhosnir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, 0.49, 0.53, 0.53, 0.53 ; - fates_rhosvis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.31, + fates_rhosvis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.31, 0.31, 0.31 ; fates_root_long = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; @@ -1316,38 +1319,38 @@ data: fates_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9 ; - fates_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, 1.47, + fates_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, 1.47, 1.47, 1.47 ; - fates_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, + fates_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51 ; - fates_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + fates_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; fates_seed_suppl = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_senleaf_long_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, -255000, + fates_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, -255000, -255000, -255000, -255000, -255000, -255000 ; - fates_smpso = -66000, -66000, -66000, -66000, -66000, -66000, -66000, + fates_smpso = -66000, -66000, -66000, -66000, -66000, -66000, -66000, -66000, -66000, -66000, -66000, -66000 ; - fates_taulnir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, 0.43, 0.4, + fates_taulnir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, 0.43, 0.4, 0.4, 0.4 ; - fates_taulvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.05, + fates_taulvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.05, 0.05, 0.05 ; - fates_tausnir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + fates_tausnir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.25, 0.25, 0.25 ; - fates_tausvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + fates_tausvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.12, 0.12, 0.12 ; - fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, + fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03 ; fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; @@ -1372,29 +1375,29 @@ data: fates_turnover_retrans_mode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, + fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7 ; fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; - fates_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, + fates_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055 ; fates_hlm_pft_map = - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; @@ -1518,10 +1521,10 @@ data: fates_phen_drought_threshold = 0.15 ; - fates_phen_moist_threshold = 0.5 ; - fates_phen_mindayson = 90 ; + fates_phen_moist_threshold = 0.5 ; + fates_phen_ncolddayslim = 5 ; fates_photo_temp_acclim_timescale = 30 ; From 5e60f74aaf91f6901e49de9b156cbf2ffb2d73e3 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 27 Apr 2022 17:47:45 -0400 Subject: [PATCH 183/852] Added new maxpatch and harvest production parameters. --- parameter_files/fates_params_default.cdl | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 15592091f0..e508d05115 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -117,7 +117,7 @@ variables: fates_allom_hmode:possible_values = "1: OBrien 1995; 2: Poorter 2006; 3: 2 parameter power law; 4: Chave 2014; 5: Martinez-Cano 2019." ; double fates_allom_l2fr(fates_pft) ; fates_allom_l2fr:units = "gC/gC" ; - fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; + fates_allom_l2fr:long_name = "target fine root C per leaf C. for C-only: constant, for CNP: recruit initial value" ; double fates_allom_la_per_sa_int(fates_pft) ; fates_allom_la_per_sa_int:units = "m2/cm2" ; fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; @@ -717,6 +717,12 @@ variables: double fates_maintresp_model ; fates_maintresp_model:units = "unitless" ; fates_maintresp_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991) (NOT USED)" ; + double fates_maxpatch_primary ; + fates_maxpatch_primary:units = "unitless" ; + fates_maxpatch_primary:long_name = "maximum number of primary vegetation patches per site" ; + double fates_maxpatch_secondary ; + fates_maxpatch_secondary:units = "unitless" ; + fates_maxpatch_secondary:long_name = "maximum number of secondary vegetation patches per site" ; double fates_mort_disturb_frac ; fates_mort_disturb_frac:units = "fraction" ; fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; @@ -765,6 +771,9 @@ variables: double fates_photo_tempsens_model ; fates_photo_tempsens_model:units = "unitless" ; fates_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; + double fates_pprodharv10_forest_mean ; + fates_pprodharv10_forest_mean:units = "fraction" ; + fates_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types." ; double fates_q10_froz ; fates_q10_froz:units = "unitless" ; fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; @@ -1499,6 +1508,10 @@ data: fates_maintresp_model = 1 ; + fates_maxpatch_primary = 10 ; + + fates_maxpatch_secondary = 4 ; + fates_mort_disturb_frac = 1 ; fates_mort_understorey_death = 0.55983 ; @@ -1523,7 +1536,7 @@ data: fates_phen_mindayson = 90 ; - fates_phen_moist_threshold = 0.5 ; + fates_phen_moist_threshold = 0.18 ; fates_phen_ncolddayslim = 5 ; @@ -1531,6 +1544,8 @@ data: fates_photo_tempsens_model = 1 ; + fates_pprodharv10_forest_mean = 0.8125 ; + fates_q10_froz = 1.5 ; fates_q10_mr = 1.5 ; From 4d66d4918554ec655d16abd35b3a52c7976417c4 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 27 Apr 2022 18:54:43 -0400 Subject: [PATCH 184/852] Updating naming convention of nutrient enabled (CNP) allocation parameters in the parameter file. --- parameter_files/fates_params_default.cdl | 207 ++++++++++++----------- 1 file changed, 104 insertions(+), 103 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index e508d05115..6743ce2e1b 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -160,6 +160,60 @@ variables: double fates_c2b(fates_pft) ; fates_c2b:units = "ratio" ; fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; + double fates_cnp_eca_alpha_ptase(fates_pft) ; + fates_cnp_eca_alpha_ptase:units = "g/m3" ; + fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; + double fates_cnp_eca_decompmicc(fates_pft) ; + fates_cnp_eca_decompmicc:units = "gC/m3" ; + fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; + double fates_cnp_eca_km_nh4(fates_pft) ; + fates_cnp_eca_km_nh4:units = "gN/m3" ; + fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; + double fates_cnp_eca_km_no3(fates_pft) ; + fates_cnp_eca_km_no3:units = "gN/m3" ; + fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; + double fates_cnp_eca_km_p(fates_pft) ; + fates_cnp_eca_km_p:units = "gP/m3" ; + fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; + double fates_cnp_eca_km_ptase(fates_pft) ; + fates_cnp_eca_km_ptase:units = "gP/m3" ; + fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; + double fates_cnp_eca_lambda_ptase(fates_pft) ; + fates_cnp_eca_lambda_ptase:units = "g/m3" ; + fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; + double fates_cnp_eca_vmax_ptase(fates_pft) ; + fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; + fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; + double fates_cnp_fnrt_adapt_tscale(fates_pft) ; + fates_cnp_fnrt_adapt_tscale:units = "days" ; + fates_cnp_fnrt_adapt_tscale:long_name = "Number of days that is the shortest possible doubling period for fine-root adaptation (CNP only)" ; + double fates_cnp_nfix1(fates_pft) ; + fates_cnp_nfix1:units = "NA" ; + fates_cnp_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; + double fates_cnp_nfix2(fates_pft) ; + fates_cnp_nfix2:units = "NA" ; + fates_cnp_nfix2:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; + double fates_cnp_nitr_store_ratio(fates_pft) ; + fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; + fates_cnp_nitr_store_ratio:long_name = "ratio of storeable N, to functional N bound in cell structures of leaf,root,sap" ; + double fates_cnp_phos_store_ratio(fates_pft) ; + fates_cnp_phos_store_ratio:units = "(gP/gP)" ; + fates_cnp_phos_store_ratio:long_name = "ratio of storeable P, to functional P bound in cell structures of leaf,root,sap" ; + double fates_cnp_prescribed_nuptake(fates_pft) ; + fates_cnp_prescribed_nuptake:units = "fraction" ; + fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; + double fates_cnp_prescribed_puptake(fates_pft) ; + fates_cnp_prescribed_puptake:units = "fraction" ; + fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; + double fates_cnp_vmax_nh4(fates_pft) ; + fates_cnp_vmax_nh4:units = "gN/gC/s" ; + fates_cnp_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA & RD)" ; + double fates_cnp_vmax_no3(fates_pft) ; + fates_cnp_vmax_no3:units = "gN/gC/s" ; + fates_cnp_vmax_no3:long_name = "maximum production rate for plant no3 uptake (ECA & RD)" ; + double fates_cnp_vmax_p(fates_pft) ; + fates_cnp_vmax_p:units = "gP/gC/s" ; + fates_cnp_vmax_p:long_name = "maximum production rate for plant p uptake (ECA & RD)" ; double fates_crown_depth_frac(fates_pft) ; fates_crown_depth_frac:units = "fraction" ; fates_crown_depth_frac:long_name = "the depth of a cohorts crown as a fraction of its height" ; @@ -181,39 +235,6 @@ variables: double fates_displar(fates_pft) ; fates_displar:units = "unitless" ; fates_displar:long_name = "Ratio of displacement height to canopy top height" ; - double fates_eca_alpha_ptase(fates_pft) ; - fates_eca_alpha_ptase:units = "g/m3" ; - fates_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; - double fates_eca_decompmicc(fates_pft) ; - fates_eca_decompmicc:units = "gC/m3" ; - fates_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; - double fates_eca_km_nh4(fates_pft) ; - fates_eca_km_nh4:units = "gN/m3" ; - fates_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; - double fates_eca_km_no3(fates_pft) ; - fates_eca_km_no3:units = "gN/m3" ; - fates_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; - double fates_eca_km_p(fates_pft) ; - fates_eca_km_p:units = "gP/m3" ; - fates_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; - double fates_eca_km_ptase(fates_pft) ; - fates_eca_km_ptase:units = "gP/m3" ; - fates_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; - double fates_eca_lambda_ptase(fates_pft) ; - fates_eca_lambda_ptase:units = "g/m3" ; - fates_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; - double fates_eca_vmax_nh4(fates_pft) ; - fates_eca_vmax_nh4:units = "gN/gC/s" ; - fates_eca_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA)" ; - double fates_eca_vmax_no3(fates_pft) ; - fates_eca_vmax_no3:units = "gN/gC/s" ; - fates_eca_vmax_no3:long_name = "maximum production rate for plant no3 uptake (ECA)" ; - double fates_eca_vmax_p(fates_pft) ; - fates_eca_vmax_p:units = "gP/gC/s" ; - fates_eca_vmax_p:long_name = "maximum production rate for plant p uptake (ECA)" ; - double fates_eca_vmax_ptase(fates_pft) ; - fates_eca_vmax_ptase:units = "gP/m2/s" ; - fates_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; double fates_fire_alpha_SH(fates_pft) ; fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; @@ -223,9 +244,6 @@ variables: double fates_fire_crown_kill(fates_pft) ; fates_fire_crown_kill:units = "NA" ; fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; - double fates_fnrt_adapt_tscale(fates_pft) ; - fates_fnrt_adapt_tscale:units = "days" ; - fates_fnrt_adapt_tscale:long_name = "Number of days that is the shortest possible doubling period for fine-root adaptation (CNP only)" ; double fates_fnrt_prof_a(fates_pft) ; fates_fnrt_prof_a:units = "unitless" ; fates_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; @@ -407,15 +425,6 @@ variables: double fates_mort_scalar_hydrfailure(fates_pft) ; fates_mort_scalar_hydrfailure:units = "1/yr" ; fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; - double fates_nfix1(fates_pft) ; - fates_nfix1:units = "NA" ; - fates_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; - double fates_nfix2(fates_pft) ; - fates_nfix2:units = "NA" ; - fates_nfix2:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; - double fates_nitr_store_ratio(fates_pft) ; - fates_nitr_store_ratio:units = "(gN/gN)" ; - fates_nitr_store_ratio:long_name = "ratio of storeable N, to functional N bound in cell structures of leaf,root,sap" ; double fates_phen_cold_size_threshold(fates_pft) ; fates_phen_cold_size_threshold:units = "cm" ; fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; @@ -437,9 +446,6 @@ variables: double fates_phenflush_fraction(fates_pft) ; fates_phenflush_fraction:units = "fraction" ; fates_phenflush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; - double fates_phos_store_ratio(fates_pft) ; - fates_phos_store_ratio:units = "(gP/gP)" ; - fates_phos_store_ratio:long_name = "ratio of storeable P, to functional P bound in cell structures of leaf,root,sap" ; double fates_prescribed_mortality_canopy(fates_pft) ; fates_prescribed_mortality_canopy:units = "1/yr" ; fates_prescribed_mortality_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; @@ -452,12 +458,6 @@ variables: double fates_prescribed_npp_understory(fates_pft) ; fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; - double fates_prescribed_nuptake(fates_pft) ; - fates_prescribed_nuptake:units = "fraction" ; - fates_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; - double fates_prescribed_puptake(fates_pft) ; - fates_prescribed_puptake:units = "fraction" ; - fates_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; double fates_prescribed_recruitment(fates_pft) ; fates_prescribed_recruitment:units = "n/yr" ; fates_prescribed_recruitment:long_name = "recruitment rate for prescribed physiology mode" ; @@ -603,6 +603,9 @@ variables: 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" ; + double fates_cnp_eca_plant_escalar ; + fates_cnp_eca_plant_escalar:units = "" ; + fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; double fates_cohort_age_fusion_tol ; fates_cohort_age_fusion_tol:units = "unitless" ; fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; @@ -621,9 +624,6 @@ variables: double fates_dev_arbitrary ; fates_dev_arbitrary:units = "unknown" ; fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; - double fates_eca_plant_escalar ; - fates_eca_plant_escalar:units = "" ; - fates_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; double fates_fire_active_crown_fire ; fates_fire_active_crown_fire:units = "0 or 1" ; fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; @@ -943,53 +943,71 @@ data: fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; - fates_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, 0.95, 1, - 1, 1 ; + fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; - fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, - 0.01, 0.01, 0.01 ; + fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 280, 280 ; - fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; + fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, + 0.14, 0.14, 0.14 ; - fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, - 5.5, 5.5 ; + fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, + 0.27, 0.27, 0.27 ; - fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; - fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; + fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, - 0.67, 0.67 ; + fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5 ; + fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - fates_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, - 280, 280 ; + fates_cnp_fnrt_adapt_tscale = 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100 ; - fates_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, - 0.14, 0.14, 0.14 ; + fates_cnp_nfix1 = _, _, _, _, _, _, _, _, _, _, _, _ ; - fates_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, - 0.27, 0.27, 0.27 ; + fates_cnp_nfix2 = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; - fates_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; + fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; - fates_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_eca_vmax_nh4 = 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, + fates_cnp_vmax_nh4 = 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07 ; - fates_eca_vmax_no3 = 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, + fates_cnp_vmax_no3 = 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08 ; - fates_eca_vmax_p = 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, + fates_cnp_vmax_p = 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09 ; - fates_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, - 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + fates_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, 0.95, 1, + 1, 1 ; + + fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01 ; + + fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; + + fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, + 5.5, 5.5 ; + + fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, + 0.67, 0.67 ; fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 ; @@ -1000,9 +1018,6 @@ data: fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775 ; - fates_fnrt_adapt_tscale = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100 ; - fates_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; fates_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; @@ -1217,13 +1232,6 @@ data: fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6 ; - fates_nfix1 = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_nfix2 = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5 ; - fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; @@ -1238,9 +1246,6 @@ data: fates_phenflush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5 ; - fates_prescribed_mortality_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; @@ -1253,10 +1258,6 @@ data: fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; - fates_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_prescribed_recruitment = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02 ; @@ -1432,6 +1433,8 @@ data: fates_canopy_closure_thresh = 0.8 ; + fates_cnp_eca_plant_escalar = 1.25e-05 ; + fates_cohort_age_fusion_tol = 0.08 ; fates_cohort_size_fusion_tol = 0.08 ; @@ -1444,8 +1447,6 @@ data: fates_dev_arbitrary = _ ; - fates_eca_plant_escalar = 1.25e-05 ; - fates_fire_active_crown_fire = 0 ; fates_fire_cg_strikes = 0.2 ; From f64861e84988f8b189ee336c8957a7527ed76891 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 29 Apr 2022 18:31:49 -0400 Subject: [PATCH 185/852] Added maxpatch to parameter file, updated damage bin widths for history --- main/EDParamsMod.F90 | 27 ++++++++++++++++++++++++ parameter_files/fates_params_default.cdl | 4 ++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index d6cd69b3db..3e9ff9bac0 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -170,7 +170,18 @@ module EDParamsMod ! Switch designating whether to use net or gross assimilation in the stomata model integer, protected, public :: stomatal_assim_model character(len=param_string_length), parameter, public :: stomatal_assim_name = "fates_stomatal_assim" + + + ! Maximum allowable primary and secondary patches + ! These values are USED FOR ALLOCATIONS IN BOTH FATES AND CLM/ELM!!!! + integer, protected, public :: maxpatch_primary + character(len=param_string_length), parameter, public :: maxpatch_primary_name = "fates_maxpatch_primary" + + integer, protected, public :: maxpatch_secondary + character(len=param_string_length), parameter, public :: maxpatch_secondary_name = "fates_maxpatch_secondary" + + ! Logging Control Parameters (ONLY RELEVANT WHEN USE_FATES_LOGGING = TRUE) ! ---------------------------------------------------------------------------------------------- @@ -258,6 +269,8 @@ subroutine FatesParamsInit() ED_val_canopy_closure_thresh = nan stomatal_model = -9 stomatal_assim_model = -9 + maxpatch_primary = -9 + maxpatch_secondary = -9 hydr_kmax_rsurf1 = nan hydr_kmax_rsurf2 = nan hydr_psi0 = nan @@ -395,6 +408,12 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=stomatal_assim_name, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) + + call fates_params%RegisterParameter(name=maxpatch_primary_name, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + + call fates_params%RegisterParameter(name=maxpatch_secondary_name, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) call fates_params%RegisterParameter(name=hydr_name_kmax_rsurf1, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -576,6 +595,14 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetreiveParameter(name=stomatal_assim_name, & data=tmpreal) stomatal_assim_model = nint(tmpreal) + + call fates_params%RetreiveParameter(name=maxpatch_primary_name, & + data=tmpreal) + maxpatch_primary = nint(tmpreal) + + call fates_params%RetreiveParameter(name=maxpatch_secondary_name, & + data=tmpreal) + maxpatch_secondary = nint(tmpreal) call fates_params%RetreiveParameter(name=hydr_name_kmax_rsurf1, & data=hydr_kmax_rsurf1) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 6743ce2e1b..61f441e9d8 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -5,7 +5,7 @@ dimensions: fates_history_height_bins = 6 ; fates_history_size_bins = 13 ; fates_history_coage_bins = 2 ; - fates_history_damage_bins = 6 ; + fates_history_damage_bins = 3 ; fates_hydr_organs = 4 ; fates_leafage_class = 1 ; fates_litterclass = 6 ; @@ -809,7 +809,7 @@ data: fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; - fates_history_damage_bin_edges = 0, 20, 40, 60, 80, 100 ; + fates_history_damage_bin_edges = 0, 80, 100 ; fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100 ; From c4d96b58038c51a4f52cdd2e4f0d5050c0b3ab36 Mon Sep 17 00:00:00 2001 From: Marcos Longo Date: Tue, 3 May 2022 11:54:38 -0700 Subject: [PATCH 186/852] Revised the carbon allocation routine to ensure allocation to fine roots and leaves are truly proportional to demand. Description: 1. Bug fix in DailyPRTAllometricCarbon (parteh/PRTAllometricCarbonMod.F90). When allocating to different tissues, the code was subtracting allocation of tissues before calculating the amount for the next tissue, potentially under-allocating carbon to fine roots. 2. Minor code updates to simplify allocation calculations. It now uses a single allocation factor based on availability and total need, which is applied to all tissues. 3. Replaced a few if statements with select case, which simplifies adding other hypotheses in the future (and it's safer for selecting cases). This pull request addresses the bug discussed in #784 and supersedes pull request #800. Additional minor changes in former PR #800 will be added as subsequent pull requests. --- biogeochem/FatesSoilBGCFluxMod.F90 | 5 +- biogeophys/FatesPlantRespPhotosynthMod.F90 | 1 + main/EDPftvarcon.F90 | 11 +- parteh/PRTAllometricCarbonMod.F90 | 150 +++++++++++---------- parteh/PRTParamsFATESMod.F90 | 43 +++--- 5 files changed, 113 insertions(+), 97 deletions(-) diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index d14ce7b005..cebab25728 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -219,7 +219,8 @@ subroutine UnPackNutrientAquisitionBCs(sites, bc_in) end do ! We can exit if this is a c-only simulation - if(hlm_parteh_mode.eq.prt_carbon_allom_hyp) then + select case (hlm_parteh_mode) + case (prt_carbon_allom_hyp) ! These can now be zero'd do s = 1, nsites bc_in(s)%plant_nh4_uptake_flux(:,:) = 0._r8 @@ -227,7 +228,7 @@ subroutine UnPackNutrientAquisitionBCs(sites, bc_in) bc_in(s)%plant_p_uptake_flux(:,:) = 0._r8 end do return - end if + end select do s = 1, nsites diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index adffe67d85..08607ec9f2 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -500,6 +500,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) end select + ! MLO - Shouldn't these numbers be parameters too? lmr25top = 2.525e-6_r8 * (1.5_r8 ** ((25._r8 - 20._r8)/10._r8)) lmr25top = lmr25top * lnc_top / (umolC_to_kgC * g_per_kg) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index a149132a8d..b65cad5cc1 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1502,7 +1502,8 @@ subroutine FatesCheckParams(is_master) if(.not.is_master) return - if (hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) then + select case (hlm_parteh_mode) + case (prt_cnp_flex_allom_hyp) ! Check to see if either RD/ECA/MIC is turned on @@ -1538,14 +1539,18 @@ subroutine FatesCheckParams(is_master) end if end if - elseif (hlm_parteh_mode .ne. prt_carbon_allom_hyp) then + case (prt_carbon_allom_hyp) + ! No additional checks needed for now. + continue + + case default write(fates_log(),*) 'FATES Plant Allocation and Reactive Transport has' write(fates_log(),*) 'only 2 modules supported, allometric carbon and CNP.' write(fates_log(),*) 'fates_parteh_mode must be set to 1 or 2 in the namelist' write(fates_log(),*) 'Aborting' call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + end select ! If any PFTs are specified as either prescribed N or P uptake ! then they all must be ! diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 5bdf624502..814d3daa36 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -51,6 +51,9 @@ module PRTAllometricCarbonMod use PRTParametersMod , only : prt_params + use EDTypesMod , only : leaves_on + use EDTypesMod , only : leaves_off + implicit none private @@ -114,7 +117,7 @@ module PRTAllometricCarbonMod ! ------------------------------------------------------------------------------------- - type, public, extends(prt_vartypes) :: callom_prt_vartypes + type, public, extends(prt_vartypes) :: callom_prt_vartypes contains @@ -144,7 +147,7 @@ module PRTAllometricCarbonMod public :: InitPRTGlobalAllometricCarbon -contains + contains subroutine InitPRTGlobalAllometricCarbon() @@ -313,6 +316,9 @@ subroutine DailyPRTAllometricCarbon(this) real(r8) :: struct_below_target ! dead (structural) biomass below target amount [kgC] real(r8) :: total_below_target ! total biomass below the allometric target [kgC] + real(r8) :: allocation_factor ! allocation factor (relative to demand) to + ! reconstruct tissues + real(r8) :: flux_adj ! adjustment made to growth flux term to minimize error [kgC] real(r8) :: store_target_fraction ! ratio between storage and leaf biomass when on allometry [kgC] @@ -451,12 +457,13 @@ subroutine DailyPRTAllometricCarbon(this) call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, ipft, target_struct_c) ! Target leaf biomass according to allometry and trimming - if(leaf_status==2) then + select case (leaf_status) + case (leaves_on) call bleaf(dbh,ipft,canopy_trim,target_leaf_c) - else + case (leaves_off) target_leaf_c = 0._r8 - end if - + end select + ! Target fine-root biomass and deriv. according to allometry and trimming [kgC, kgC/cm] call bfineroot(dbh,ipft,canopy_trim,target_fnrt_c) @@ -466,43 +473,42 @@ subroutine DailyPRTAllometricCarbon(this) ! ----------------------------------------------------------------------------------- ! III. Prioritize some amount of carbon to replace leaf/root turnover - ! Make sure it isnt a negative payment, and either pay what is available + ! Make sure it isn't a negative payment, and either pay what is available ! or forcefully pay from storage. ! ----------------------------------------------------------------------------------- - if( prt_params%evergreen(ipft) ==1 ) then + if( prt_params%evergreen(ipft) == itrue ) then leaf_c_demand = max(0.0_r8, & prt_params%leaf_stor_priority(ipft)*sum(this%variables(leaf_c_id)%turnover(:))) else leaf_c_demand = 0.0_r8 end if - fnrt_c_demand = max(0.0_r8, & + fnrt_c_demand = max(0.0_r8, & prt_params%leaf_stor_priority(ipft)*this%variables(fnrt_c_id)%turnover(icd)) total_c_demand = leaf_c_demand + fnrt_c_demand - - if (total_c_demand> nearzero ) then + + if (total_c_demand > nearzero) then ! We pay this even if we don't have the carbon ! Just don't pay so much carbon that storage+carbon_balance can't pay for it + allocation_factor = max(0.0_r8,min(1.0_r8,(store_c+carbon_balance)/total_c_demand)) - leaf_c_flux = min(leaf_c_demand, & - max(0.0_r8,(store_c+carbon_balance)* & - (leaf_c_demand/total_c_demand))) - - ! Add carbon to the youngest age pool (i.e iexp_leaf = index 1) - carbon_balance = carbon_balance - leaf_c_flux - leaf_c(iexp_leaf) = leaf_c(iexp_leaf) + leaf_c_flux - - ! If we are testing b4b, then we pay this even if we don't have the carbon - fnrt_c_flux = min(fnrt_c_demand, & - max(0.0_r8, (store_c+carbon_balance)* & - (fnrt_c_demand/total_c_demand))) + ! MLO. Edited the code to switch the order of operations. The previous code would + ! subtract leaf flux from carbon balance before estimating the fine root flux, + ! potentially allowing less fluxes to fine roots than possible. + leaf_c_flux = leaf_c_demand * allocation_factor + fnrt_c_flux = fnrt_c_demand * allocation_factor - carbon_balance = carbon_balance - fnrt_c_flux - fnrt_c = fnrt_c + fnrt_c_flux + ! Add carbon to the youngest age pool (i.e iexp_leaf = index 1) and fine roots + leaf_c(iexp_leaf) = leaf_c(iexp_leaf) + leaf_c_flux + fnrt_c = fnrt_c + fnrt_c_flux + ! Remove fluxes from carbon balance. In case we may have drawn carbon from storage, + ! carbon_balance will become negative, in which case we will deplete carbon from + ! storage in the next step. + carbon_balance = carbon_balance - ( leaf_c_flux + fnrt_c_flux ) end if ! ----------------------------------------------------------------------------------- @@ -511,19 +517,24 @@ subroutine DailyPRTAllometricCarbon(this) ! ----------------------------------------------------------------------------------- if( carbon_balance < 0.0_r8 ) then - + + ! Store_c_flux will be negative, so store_c will be depleted store_c_flux = carbon_balance carbon_balance = carbon_balance - store_c_flux store_c = store_c + store_c_flux else - store_below_target = max(target_store_c - store_c,0.0_r8) + ! Accumulate some carbon in storage. If storage is completely depleted, aim to + ! increase storage, but not to replenish completely so we can still use some + ! carbon for growth. + store_below_target = max(0.0_r8,target_store_c - store_c) store_target_fraction = max(0.0_r8, store_c/target_store_c ) store_c_flux = min(store_below_target,carbon_balance * & max(exp(-1.*store_target_fraction**4._r8) - exp( -1.0_r8 ),0.0_r8)) + ! Move carbon from carbon balance to storage carbon_balance = carbon_balance - store_c_flux store_c = store_c + store_c_flux @@ -533,24 +544,29 @@ subroutine DailyPRTAllometricCarbon(this) ! V. If carbon is still available, prioritize some allocation to replace ! the rest of the leaf/fineroot deficit ! carbon balance is guaranteed to be >=0 beyond this point + ! MLO. Renamed demand with below target to make it consistent with the + ! definitions at the variable declaration part. ! ----------------------------------------------------------------------------------- - - leaf_c_demand = max(0.0_r8,(target_leaf_c - sum(leaf_c(1:nleafage)))) - fnrt_c_demand = max(0.0_r8,(target_fnrt_c - fnrt_c)) - total_c_demand = leaf_c_demand + fnrt_c_demand - - if( (carbon_balance > nearzero ) .and. (total_c_demand>nearzero)) then + leaf_below_target = max(0.0_r8,target_leaf_c - sum(leaf_c(1:nleafage))) + fnrt_below_target = max(0.0_r8,target_fnrt_c - fnrt_c) + + total_below_target = leaf_below_target + fnrt_below_target + + if ( (carbon_balance > nearzero) .and. (total_below_target > nearzero) ) then + ! Find fraction of carbon to be allocated to leaves and fine roots + allocation_factor = min(1.0_r8, carbon_balance / total_below_target) + + ! MLO. Edited the code to switch the order of operations. The previous code would + ! subtract leaf flux from carbon balance before estimating the fine root flux, + ! potentially allowing less fluxes to fine roots than possible. + leaf_c_flux = leaf_below_target * allocation_factor + fnrt_c_flux = fnrt_below_target * allocation_factor - leaf_c_flux = min(leaf_c_demand, & - carbon_balance*(leaf_c_demand/total_c_demand)) - carbon_balance = carbon_balance - leaf_c_flux leaf_c(iexp_leaf) = leaf_c(iexp_leaf) + leaf_c_flux - - fnrt_c_flux = min(fnrt_c_demand, & - carbon_balance*(fnrt_c_demand/total_c_demand)) - carbon_balance = carbon_balance - fnrt_c_flux - fnrt_c = fnrt_c + fnrt_c_flux + fnrt_c = fnrt_c + fnrt_c_flux + + carbon_balance = carbon_balance - ( leaf_c_flux + fnrt_c_flux ) end if @@ -571,31 +587,22 @@ subroutine DailyPRTAllometricCarbon(this) sapw_below_target + store_below_target if ( total_below_target > nearzero ) then - - if( total_below_target > carbon_balance) then - leaf_c_flux = carbon_balance * leaf_below_target/total_below_target - fnrt_c_flux = carbon_balance * fnrt_below_target/total_below_target - sapw_c_flux = carbon_balance * sapw_below_target/total_below_target - store_c_flux = carbon_balance * store_below_target/total_below_target - else - leaf_c_flux = leaf_below_target - fnrt_c_flux = fnrt_below_target - sapw_c_flux = sapw_below_target - store_c_flux = store_below_target - end if - - carbon_balance = carbon_balance - leaf_c_flux - leaf_c(iexp_leaf) = leaf_c(iexp_leaf) + leaf_c_flux - - carbon_balance = carbon_balance - fnrt_c_flux - fnrt_c = fnrt_c + fnrt_c_flux - - carbon_balance = carbon_balance - sapw_c_flux - sapw_c = sapw_c + sapw_c_flux - - carbon_balance = carbon_balance - store_c_flux - store_c = store_c + store_c_flux - + ! Find allocation factor based on available carbon and total demand to meet target. + allocation_factor = min(1.0_r8, carbon_balance / total_below_target) + + ! Find fluxes to individual pools + leaf_c_flux = leaf_below_target * allocation_factor + fnrt_c_flux = fnrt_below_target * allocation_factor + sapw_c_flux = sapw_below_target * allocation_factor + store_c_flux = store_below_target * allocation_factor + + leaf_c(iexp_leaf) = leaf_c(iexp_leaf) + leaf_c_flux + fnrt_c = fnrt_c + fnrt_c_flux + sapw_c = sapw_c + sapw_c_flux + store_c = store_c + store_c_flux + + carbon_balance = carbon_balance - & + ( leaf_c_flux + fnrt_c_flux + sapw_c_flux + store_c_flux ) end if end if @@ -690,11 +697,12 @@ subroutine DailyPRTAllometricCarbon(this) c_pool(dbh_id) = dbh ! Only grow leaves if we are in a "leaf-on" status - if(leaf_status==2) then - c_mask(leaf_c_id) = grow_leaf - else - c_mask(leaf_c_id) = .false. - end if + select case (leaf_status) + case (leaves_on) + c_mask(leaf_c_id) = grow_leaf + case default + c_mask(leaf_c_id) = .false. + end select c_mask(fnrt_c_id) = grow_fnrt c_mask(sapw_c_id) = grow_sapw c_mask(store_c_id) = grow_store diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index 208ff848fb..c017b4e138 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -1014,12 +1014,12 @@ subroutine PRTCheckParams(is_master) ! Check to make sure the organ ids are valid if this is the ! cnp_flex_allom_hypothesis - if ((hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) .or. & - (hlm_parteh_mode .eq. prt_carbon_allom_hyp) ) then + select case (hlm_parteh_mode) + case (prt_carbon_allom_hyp,prt_cnp_flex_allom_hyp) do io = 1,norgans if(prt_params%organ_id(io) == repro_organ) then - write(fates_log(),*) 'with flexible cnp or c-only alloc hypothesese' + write(fates_log(),*) 'with flexible cnp or c-only alloc hypotheses' write(fates_log(),*) 'reproductive tissues are a special case' write(fates_log(),*) 'and therefore should not be included in' write(fates_log(),*) 'the parameter file organ list' @@ -1027,16 +1027,16 @@ subroutine PRTCheckParams(is_master) write(fates_log(),*) 'Aborting' end if if(prt_params%organ_id(io) == store_organ) then - write(fates_log(),*) 'with flexible cnp or c-only alloc hypothesese' + write(fates_log(),*) 'with flexible cnp or c-only alloc hypotheses' write(fates_log(),*) 'storage is a special case' write(fates_log(),*) 'and therefore should not be included in' write(fates_log(),*) 'the parameter file organ list' write(fates_log(),*) 'fates_prt_organ_id: ',prt_params%organ_id(:) write(fates_log(),*) 'Aborting' end if - + end do - end if + end select pftloop: do ipft = 1,npft @@ -1128,9 +1128,8 @@ subroutine PRTCheckParams(is_master) ! should not be re-translocating mass upon turnover. ! Note to advanced users. Feel free to remove these checks... ! ------------------------------------------------------------------- - - if ((hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) .or. & - (hlm_parteh_mode .eq. prt_carbon_allom_hyp) ) then + select case (hlm_parteh_mode) + case (prt_carbon_allom_hyp,prt_cnp_flex_allom_hyp) do i = 1,norgans io = prt_params%organ_id(i) @@ -1165,10 +1164,11 @@ subroutine PRTCheckParams(is_master) end if end do - end if - - if (hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) then - + end select + + select case (hlm_parteh_mode) + case (prt_cnp_flex_allom_hyp) + ! Make sure nutrient storage fractions are positive if( prt_params%nitr_store_ratio(ipft) < 0._r8 ) then write(fates_log(),*) 'With parteh allometric CNP hypothesis' @@ -1235,9 +1235,9 @@ subroutine PRTCheckParams(is_master) end if end do - - end if - + + end select + ! Growth respiration ! if (parteh_mode .eq. prt_carbon_allom_hyp) then @@ -1258,8 +1258,8 @@ subroutine PRTCheckParams(is_master) ! end if ! end if - if ((hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) .or. & - (hlm_parteh_mode .eq. prt_carbon_allom_hyp) ) then + select case (hlm_parteh_mode) + case (prt_carbon_allom_hyp,prt_cnp_flex_allom_hyp) ! The first nitrogen stoichiometry is used in all cases if ( (any(prt_params%nitr_stoich_p1(ipft,:) < 0.0_r8)) .or. & (any(prt_params%nitr_stoich_p1(ipft,:) >= 1.0_r8))) then @@ -1269,9 +1269,10 @@ subroutine PRTCheckParams(is_master) write(fates_log(),*) ' Aborting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if - end if + end select - if(hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) then + select case (hlm_parteh_mode) + case (prt_cnp_flex_allom_hyp) do i = 1,norgans if ( (prt_params%nitr_stoich_p1(ipft,i) < 0._r8) .or. & @@ -1309,7 +1310,7 @@ subroutine PRTCheckParams(is_master) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - end if + end select ! Check turnover time-scales From e1b3bf89a03ddfaf7e8ba57a3f194cfe255f2e62 Mon Sep 17 00:00:00 2001 From: Marcos Longo Date: Tue, 3 May 2022 13:44:44 -0700 Subject: [PATCH 187/852] Make parameter woody integer. Parameter prt_params%woody is used to decide whether a PFT is woody or not. Instead of converting it to integer whenever a logical test is to be performed, I turned the parameter integer. --- biogeochem/EDCanopyStructureMod.F90 | 4 ++-- biogeochem/EDCohortDynamicsMod.F90 | 2 +- biogeochem/EDLoggingMortalityMod.F90 | 4 ++-- biogeochem/EDPatchDynamicsMod.F90 | 8 ++++---- biogeochem/FatesAllometryMod.F90 | 4 ++-- fire/SFMainMod.F90 | 14 +++++++------- main/FatesHistoryInterfaceMod.F90 | 2 +- parteh/PRTParametersMod.F90 | 2 +- parteh/PRTParamsFATESMod.F90 | 16 ++++++++++------ 9 files changed, 30 insertions(+), 26 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index c12ec2edda..5bd85cb5a1 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1235,7 +1235,7 @@ subroutine canopy_spread( currentSite ) do while (associated(currentCohort)) call carea_allom(currentCohort%dbh,currentCohort%n, & currentSite%spread,currentCohort%pft,currentCohort%c_area) - if( ( int(prt_params%woody(currentCohort%pft)) .eq. itrue ) .and. & + if( ( prt_params%woody(currentCohort%pft) .eq. itrue ) .and. & (currentCohort%canopy_layer .eq. 1 ) ) then sitelevel_canopyarea = sitelevel_canopyarea + currentCohort%c_area endif @@ -1346,7 +1346,7 @@ subroutine canopy_summarization( nsites, sites, bc_in ) if(currentCohort%canopy_layer==1)then currentPatch%total_canopy_area = currentPatch%total_canopy_area + currentCohort%c_area - if( int(prt_params%woody(ft))==itrue)then + if( prt_params%woody(ft) == itrue)then currentPatch%total_tree_area = currentPatch%total_tree_area + currentCohort%c_area endif endif diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 4318ee469f..8c6f589c04 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -2107,7 +2107,7 @@ subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) delta_dbh = 0._r8 delta_hite = 0._r8 - if( int(prt_params%woody(currentCohort%pft)) == itrue) then + if( prt_params%woody(currentCohort%pft) == itrue) then struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index f1f23d9f33..74f21d8bc2 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -258,7 +258,7 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & ! transfer of area to secondary land is based on overall area affected, not just logged crown area ! l_degrad accounts for the affected area between logged crowns - if(int(prt_params%woody(pft_i)) == 1)then ! only set logging rates for trees + if(prt_params%woody(pft_i) == itrue)then ! only set logging rates for trees ! direct logging rates, based on dbh min and max criteria if (dbh >= logging_dbhmin .and. .not. & @@ -542,7 +542,7 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site ! plants that were impacted. Thus, no direct dead can occur ! here, and indirect are impacts. - if(int(prt_params%woody(pft)) == itrue) then + if(prt_params%woody(pft) == itrue) then direct_dead = 0.0_r8 indirect_dead = logging_coll_under_frac * & (1._r8-currentPatch%fract_ldist_not_harvested) * currentCohort%n * & diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 537e74824d..487318fa9d 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -777,7 +777,7 @@ subroutine spawn_patches( currentSite, bc_in) else ! small trees - if( int(prt_params%woody(currentCohort%pft)) == itrue)then + if( prt_params%woody(currentCohort%pft) == itrue)then ! Survivorship of undestory woody plants. Two step process. @@ -917,7 +917,7 @@ subroutine spawn_patches( currentSite, bc_in) ! burned off. Here, we remove that mass, and ! tally it in the flux we sent to the atmosphere - if(int(prt_params%woody(currentCohort%pft)) == itrue)then + if(prt_params%woody(currentCohort%pft) == itrue)then leaf_burn_frac = currentCohort%fraction_crown_burned else @@ -995,7 +995,7 @@ subroutine spawn_patches( currentSite, bc_in) ! WHat to do with cohorts in the understory of a logging generated ! disturbance patch? - if(int(prt_params%woody(currentCohort%pft)) == itrue)then + if(prt_params%woody(currentCohort%pft) == itrue)then ! Survivorship of undestory woody plants. Two step process. @@ -1905,7 +1905,7 @@ subroutine mortality_litter_fluxes(currentSite, currentPatch, & num_dead = currentCohort%n * min(1.0_r8,currentCohort%dmort * & hlm_freq_day * fates_mortality_disturbance_fraction) - elseif(int(prt_params%woody(pft)) == itrue) then + elseif(prt_params%woody(pft) == itrue) then ! Understorey trees. The total dead is based on their survivorship ! function, and the total area of disturbance. diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index 42264ca776..ef3c58495b 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -2370,7 +2370,7 @@ subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl ) integer, parameter :: max_counter = 200 ! Do reduce "if" calls, we break this call into two parts - if ( int(prt_params%woody(ipft)) == itrue ) then + if ( prt_params%woody(ipft) == itrue ) then if(.not.present(bdead)) then write(fates_log(),*) 'woody plants must use structure for dbh reset' @@ -2456,7 +2456,7 @@ subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl ) call h_allom(d,ipft,h) if(counter>10)then write(fates_log(),*) 'dbh counter: ',counter,' is woody: ',& - int(prt_params%woody(ipft))==itrue + (prt_params%woody(ipft) == itrue) end if diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index aedcb4aa7c..ee8e4c2400 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -192,7 +192,7 @@ subroutine charecteristics_of_fuel ( currentSite ) currentPatch%livegrass = 0.0_r8 currentCohort => currentPatch%tallest do while(associated(currentCohort)) - if( int(prt_params%woody(currentCohort%pft)) == ifalse)then + if( prt_params%woody(currentCohort%pft) == ifalse)then currentPatch%livegrass = currentPatch%livegrass + & currentCohort%prt%GetState(leaf_organ, all_carbon_elements) * & @@ -374,7 +374,7 @@ subroutine wind_effect ( currentSite, bc_in) do while(associated(currentCohort)) if (debug) write(fates_log(),*) 'SF currentCohort%c_area ',currentCohort%c_area - if( int(prt_params%woody(currentCohort%pft)) == itrue)then + if( prt_params%woody(currentCohort%pft) == itrue)then currentPatch%total_tree_area = currentPatch%total_tree_area + currentCohort%c_area else total_grass_area = total_grass_area + currentCohort%c_area @@ -864,7 +864,7 @@ subroutine crown_scorching ( currentSite ) if (currentPatch%fire == 1) then currentCohort => currentPatch%tallest; do while(associated(currentCohort)) - if ( int(prt_params%woody(currentCohort%pft)) == itrue) then !trees only + if ( prt_params%woody(currentCohort%pft) == itrue) then !trees only leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) @@ -878,7 +878,7 @@ subroutine crown_scorching ( currentSite ) enddo !end cohort loop do i_pft=1,numpft - if (tree_ag_biomass > 0.0_r8 .and. int(prt_params%woody(i_pft)) == itrue) then + if (tree_ag_biomass > 0.0_r8 .and. prt_params%woody(i_pft) == itrue) then !Equation 16 in Thonicke et al. 2010 !Van Wagner 1973 EQ8 !2/3 Byram (1959) currentPatch%Scorch_ht(i_pft) = EDPftvarcon_inst%fire_alpha_SH(i_pft) * (currentPatch%FI**0.667_r8) @@ -920,7 +920,7 @@ subroutine crown_damage ( currentSite ) do while(associated(currentCohort)) currentCohort%fraction_crown_burned = 0.0_r8 - if ( int(prt_params%woody(currentCohort%pft)) == itrue) then !trees only + if ( prt_params%woody(currentCohort%pft) == itrue) then !trees only ! Flames lower than bottom of canopy. ! c%hite is height of cohort @@ -984,7 +984,7 @@ subroutine cambial_damage_kill ( currentSite ) if (currentPatch%fire == 1) then currentCohort => currentPatch%tallest; do while(associated(currentCohort)) - if ( int(prt_params%woody(currentCohort%pft)) == itrue) then !trees only + if ( prt_params%woody(currentCohort%pft) == itrue) then !trees only ! Equation 21 in Thonicke et al 2010 bt = EDPftvarcon_inst%bark_scaler(currentCohort%pft)*currentCohort%dbh ! bark thickness. ! Equation 20 in Thonicke et al. 2010. @@ -1036,7 +1036,7 @@ subroutine post_fire_mortality ( currentSite ) do while(associated(currentCohort)) currentCohort%fire_mort = 0.0_r8 currentCohort%crownfire_mort = 0.0_r8 - if ( int(prt_params%woody(currentCohort%pft)) == itrue) then + if ( prt_params%woody(currentCohort%pft) == itrue) then ! Equation 22 in Thonicke et al. 2010. currentCohort%crownfire_mort = EDPftvarcon_inst%crown_kill(currentCohort%pft)*currentCohort%fraction_crown_burned**3.0_r8 ! Equation 18 in Thonicke et al. 2010. diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index f43289da15..af02d730a3 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2506,7 +2506,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) store_m_net_alloc*n_perm2 / days_per_year / sec_per_day ! Woody State Variables (basal area growth increment) - if ( int(prt_params%woody(ft)) == itrue) then + if ( prt_params%woody(ft) == itrue) then ! basal area [m2/m2] hio_ba_si_scpf(io_si,scpf) = hio_ba_si_scpf(io_si,scpf) + & diff --git a/parteh/PRTParametersMod.F90 b/parteh/PRTParametersMod.F90 index 04a0f5dda0..a0b6cbb44e 100644 --- a/parteh/PRTParametersMod.F90 +++ b/parteh/PRTParametersMod.F90 @@ -100,7 +100,7 @@ module PRTParametersMod real(r8), allocatable :: c2b(:) ! Carbon to biomass multiplier [kg/kgC] real(r8), allocatable :: wood_density(:) ! wood density g cm^-3 ... - real(r8), allocatable :: woody(:) ! Does the plant have wood? (1=yes, 0=no) + integer , allocatable :: woody(:) ! Does the plant have wood? (1=yes, 0=no) real(r8), allocatable :: crown(:) ! fraction of the height of the plant ! that is occupied by crown real(r8), allocatable :: slamax(:) ! Maximum specific leaf area of plant (at bottom) [m2/gC] diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index 208ff848fb..16c05cb2b0 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -441,8 +441,12 @@ subroutine PRTReceivePFT(fates_params) name = 'fates_woody' call fates_params%RetreiveParameterAllocate(name=name, & - data=prt_params%woody) - + data=tmpreal) + allocate(prt_params%woody(size(tmpreal,dim=1))) + call ArrayNint(tmpreal,prt_params%woody) + deallocate(tmpreal) + + name = 'fates_wood_density' call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%wood_density) @@ -1076,13 +1080,13 @@ subroutine PRTCheckParams(is_master) ! Check if woody plants have a structural biomass (agb) intercept ! ---------------------------------------------------------------------------------- if ( ( prt_params%allom_agb1(ipft) <= tiny(prt_params%allom_agb1(ipft)) ) .and. & - ( int(prt_params%woody(ipft)) .eq. 1 ) ) then + ( prt_params%woody(ipft) .eq. 1 ) ) then write(fates_log(),*) 'Woody plants are expected to have a non-zero intercept' write(fates_log(),*) ' in the diameter to AGB allometry equations' write(fates_log(),*) ' PFT#: ',ipft write(fates_log(),*) ' allom_agb1: ',prt_params%allom_agb1(ipft) - write(fates_log(),*) ' woody: ',int(prt_params%woody(ipft)) + write(fates_log(),*) ' woody: ',prt_params%woody(ipft) write(fates_log(),*) ' Aborting' call endrun(msg=errMsg(sourcefile, __LINE__)) @@ -1091,7 +1095,7 @@ subroutine PRTCheckParams(is_master) ! Check if non-woody plants have structural biomass (agb) intercept ! ---------------------------------------------------------------------------------- ! if ( ( prt_params%allom_agb1(ipft) > tiny(prt_params%allom_agb1(ipft)) ) .and. & -! ( int(prt_params%woody(ipft)) .ne. 1 ) ) then +! ( iprt_params%woody(ipft) .ne. 1 ) ) then ! ! write(fates_log(),*) 'Non-woody plants are expected to have a zero intercept' ! write(fates_log(),*) ' in the diameter to AGB allometry equations' @@ -1100,7 +1104,7 @@ subroutine PRTCheckParams(is_master) ! write(fates_log(),*) ' woody tissues (sap and structural dead wood).' ! write(fates_log(),*) ' PFT#: ',ipft ! write(fates_log(),*) ' allom_agb1: ',prt_params%allom_agb1(ipft) -! write(fates_log(),*) ' woody: ',int(prt_params%woody(ipft)) +! write(fates_log(),*) ' woody: ',prt_params%woody(ipft) ! write(fates_log(),*) ' Aborting' ! call endrun(msg=errMsg(sourcefile, __LINE__)) ! From 3d63f877ff60769339dbcf4cf9286c0bd77565a0 Mon Sep 17 00:00:00 2001 From: Marcos Longo Date: Tue, 3 May 2022 15:57:33 -0700 Subject: [PATCH 188/852] Replaced variable laimemory with leafmemory. Rationale: "laimemory" was a misnomer, as we were tracking leaf biomass. I renamed it leafmemory to be consistent with the memory term for other tissues. --- biogeochem/EDCohortDynamicsMod.F90 | 26 +++++++------- biogeochem/EDPhysiologyMod.F90 | 56 +++++++++++++++--------------- main/EDInitMod.F90 | 28 +++++++-------- main/EDTypesMod.F90 | 4 +-- main/FatesInventoryInitMod.F90 | 8 ++--- main/FatesRestartInterfaceMod.F90 | 16 ++++----- 6 files changed, 69 insertions(+), 69 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 4318ee469f..8e4698f5ea 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -147,7 +147,7 @@ module EDCohortDynamicsMod subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & - prt, laimemory, sapwmemory, structmemory, & + prt, leafmemory, sapwmemory, structmemory, & status, recruitstatus,ctrim, carea, clayer, spread, bc_in) ! ! !DESCRIPTION: @@ -181,7 +181,7 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & real(r8), intent(in) :: dbh ! dbh: cm class(prt_vartypes),target :: prt ! The allocated PARTEH ! object - real(r8), intent(in) :: laimemory ! target leaf biomass- set from + real(r8), intent(in) :: leafmemory ! target leaf biomass- set from ! previous year: kGC per indiv real(r8), intent(in) :: sapwmemory ! target sapwood biomass- set from ! previous year: kGC per indiv @@ -237,7 +237,7 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & new_cohort%canopy_trim = ctrim new_cohort%canopy_layer = clayer new_cohort%canopy_layer_yesterday = real(clayer, r8) - new_cohort%laimemory = laimemory + new_cohort%leafmemory = leafmemory new_cohort%sapwmemory = sapwmemory new_cohort%structmemory = structmemory @@ -541,7 +541,7 @@ subroutine nan_cohort(cc_p) currentCohort%dbh = nan ! 'diameter at breast height' in cm currentCohort%coage = nan ! age of the cohort in years currentCohort%hite = nan ! height: meters - currentCohort%laimemory = nan ! target leaf biomass- set from previous year: kGC per indiv + currentCohort%leafmemory = nan ! target leaf biomass- set from previous year: kGC per indiv currentCohort%sapwmemory = nan ! target sapwood biomass- set from previous year: kGC per indiv currentCohort%structmemory = nan ! target structural biomass- set from previous year: kGC per indiv currentCohort%lai = nan ! leaf area index of cohort m2/m2 @@ -765,7 +765,7 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_ if (currentcohort%n < min_n_safemath .and. level == 1) then terminate = itrue if ( debug ) then - write(fates_log(),*) 'terminating cohorts 0',currentCohort%n/currentPatch%area,currentCohort%dbh,call_index + write(fates_log(),*) 'terminating cohorts 0',currentCohort%n/currentPatch%area,currentCohort%dbh,currentCohort%pft,call_index endif endif @@ -778,7 +778,7 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_ (currentCohort%dbh < 0.00001_r8 .and. store_c < 0._r8) ) then terminate = itrue if ( debug ) then - write(fates_log(),*) 'terminating cohorts 1',currentCohort%n/currentPatch%area,currentCohort%dbh,call_index + write(fates_log(),*) 'terminating cohorts 1',currentCohort%n/currentPatch%area,currentCohort%dbh,currentCohort%pft,call_index endif endif @@ -786,7 +786,7 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_ if (currentCohort%canopy_layer > nclmax ) then terminate = itrue if ( debug ) then - write(fates_log(),*) 'terminating cohorts 2', currentCohort%canopy_layer,call_index + write(fates_log(),*) 'terminating cohorts 2', currentCohort%canopy_layer,currentCohort%pft,call_index endif endif @@ -796,7 +796,7 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_ terminate = itrue if ( debug ) then write(fates_log(),*) 'terminating cohorts 3', & - sapw_c,leaf_c,fnrt_c,store_c,call_index + sapw_c,leaf_c,fnrt_c,store_c,currentCohort%pft,call_index endif endif @@ -805,7 +805,7 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_ terminate = itrue if ( debug ) then write(fates_log(),*) 'terminating cohorts 4', & - struct_c,sapw_c,leaf_c,fnrt_c,store_c,call_index + struct_c,sapw_c,leaf_c,fnrt_c,store_c,currentCohort%pft,call_index endif endif @@ -1196,7 +1196,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) write(fates_log(),*) 'Cohort I, Cohort II' write(fates_log(),*) 'n:',currentCohort%n,nextc%n write(fates_log(),*) 'isnew:',currentCohort%isnew,nextc%isnew - write(fates_log(),*) 'laimemory:',currentCohort%laimemory,nextc%laimemory + write(fates_log(),*) 'leafmemory:',currentCohort%leafmemory,nextc%leafmemory write(fates_log(),*) 'hite:',currentCohort%hite,nextc%hite write(fates_log(),*) 'coage:',currentCohort%coage,nextc%coage write(fates_log(),*) 'dbh:',currentCohort%dbh,nextc%dbh @@ -1234,8 +1234,8 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) ! ----------------------------------------------------------------- call UpdateCohortBioPhysRates(currentCohort) - currentCohort%laimemory = (currentCohort%n*currentCohort%laimemory & - + nextc%n*nextc%laimemory)/newn + currentCohort%leafmemory = (currentCohort%n*currentCohort%leafmemory & + + nextc%n*nextc%leafmemory)/newn currentCohort%sapwmemory = (currentCohort%n*currentCohort%sapwmemory & + nextc%n*nextc%sapwmemory)/newn @@ -1828,7 +1828,7 @@ subroutine copy_cohort( currentCohort,copyc ) n%dbh = o%dbh n%coage = o%coage n%hite = o%hite - n%laimemory = o%laimemory + n%leafmemory = o%leafmemory n%sapwmemory = o%sapwmemory n%structmemory = o%structmemory n%lai = o%lai diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 5d66f56d39..72959ddf21 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -425,8 +425,8 @@ subroutine trim_canopy( currentSite ) real(r8) :: initial_trim ! Initial trim real(r8) :: optimum_trim ! Optimum trim value - real(r8) :: initial_laimem ! Initial laimemory - real(r8) :: optimum_laimem ! Optimum laimemory + real(r8) :: initial_leafmem ! Initial leafmemory + real(r8) :: optimum_leafmem ! Optimum leafmemory !---------------------------------------------------------------------- @@ -446,15 +446,15 @@ subroutine trim_canopy( currentSite ) currentCohort => currentPatch%tallest do while (associated(currentCohort)) - ! Save off the incoming trim and laimemory + ! Save off the incoming trim and leafmemory initial_trim = currentCohort%canopy_trim - initial_laimem = currentCohort%laimemory + initial_leafmem = currentCohort%leafmemory ! Add debug diagnstic output to determine which cohort if (debug) then write(fates_log(),*) 'Current cohort:', icohort write(fates_log(),*) 'Starting canopy trim:', initial_trim - write(fates_log(),*) 'Starting laimemory:', currentCohort%laimemory + write(fates_log(),*) 'Starting leafmemory:', currentCohort%leafmemory endif trimmed = .false. @@ -601,7 +601,7 @@ subroutine trim_canopy( currentSite ) currentCohort%canopy_trim = currentCohort%canopy_trim - & EDPftvarcon_inst%trim_inc(ipft) if (prt_params%evergreen(ipft) /= 1)then - currentCohort%laimemory = currentCohort%laimemory * & + currentCohort%leafmemory = currentCohort%leafmemory * & (1.0_r8 - EDPftvarcon_inst%trim_inc(ipft)) endif @@ -649,15 +649,15 @@ subroutine trim_canopy( currentSite ) ! optimum_trim = (nnu_clai_b(1,1) / cumulative_lai_cohort) * initial_trim - optimum_laimem = (nnu_clai_b(1,1) / cumulative_lai_cohort) * initial_laimem + optimum_leafmem = (nnu_clai_b(1,1) / cumulative_lai_cohort) * initial_leafmem ! Determine if the optimum trim value makes sense. The smallest cohorts tend to have unrealistic fits. if (optimum_trim > 0. .and. optimum_trim < 1.) then currentCohort%canopy_trim = optimum_trim - ! If the cohort pft is not evergreen we reduce the laimemory as well + ! If the cohort pft is not evergreen we reduce the leafmemory as well if (prt_params%evergreen(ipft) /= 1) then - currentCohort%laimemory = optimum_laimem + currentCohort%leafmemory = optimum_leafmem endif trimmed = .true. @@ -1123,14 +1123,14 @@ subroutine phenology_leafonoff(currentSite) ! stop flow of carbon out of bstore. if(store_c>nearzero) then - ! flush either the amount required from the laimemory, or -most- of the storage pool + ! flush either the amount required from the leafmemory, or -most- of the storage pool ! RF: added a criterion to stop the entire store pool emptying and triggering termination mortality ! n.b. this might not be necessary if we adopted a more gradual approach to leaf flushing... store_c_transfer_frac = min((EDPftvarcon_inst%phenflush_fraction(ipft)* & - currentCohort%laimemory)/store_c,(1.0_r8-carbon_store_buffer)) + currentCohort%leafmemory)/store_c,(1.0_r8-carbon_store_buffer)) if(prt_params%woody(ipft).ne.itrue)then - totalmemory=currentCohort%laimemory+currentCohort%sapwmemory+currentCohort%structmemory + totalmemory=currentCohort%leafmemory+currentCohort%sapwmemory+currentCohort%structmemory store_c_transfer_frac = min((EDPftvarcon_inst%phenflush_fraction(ipft)* & totalmemory)/store_c, (1.0_r8-carbon_store_buffer)) endif @@ -1144,7 +1144,7 @@ subroutine phenology_leafonoff(currentSite) if(prt_params%woody(ipft) == itrue) then call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, store_c_transfer_frac) - currentCohort%laimemory = 0.0_r8 + currentCohort%leafmemory = 0.0_r8 else @@ -1152,7 +1152,7 @@ subroutine phenology_leafonoff(currentSite) if (stem_drop_fraction .gt. 0.0_r8) then call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & - store_c_transfer_frac*currentCohort%laimemory/totalmemory) + store_c_transfer_frac*currentCohort%leafmemory/totalmemory) call PRTPhenologyFlush(currentCohort%prt, ipft, sapw_organ, & store_c_transfer_frac*currentCohort%sapwmemory/totalmemory) @@ -1167,7 +1167,7 @@ subroutine phenology_leafonoff(currentSite) end if - currentCohort%laimemory = 0.0_r8 + currentCohort%leafmemory = 0.0_r8 currentCohort%structmemory = 0.0_r8 currentCohort%sapwmemory = 0.0_r8 @@ -1188,10 +1188,10 @@ subroutine phenology_leafonoff(currentSite) ! This sets the cohort to the "leaves off" flag currentCohort%status_coh = leaves_off - ! Remember what the lai was (leaf mass actually) was for next year + ! Remember what the leaf mass was for next year ! the same amount back on in the spring... - currentCohort%laimemory = leaf_c + currentCohort%leafmemory = leaf_c ! Drop Leaves (this routine will update the leaf state variables, ! for carbon and any other element that are prognostic. It will @@ -1238,12 +1238,12 @@ subroutine phenology_leafonoff(currentSite) if(store_c>nearzero) then store_c_transfer_frac = & - min((EDPftvarcon_inst%phenflush_fraction(ipft)*currentCohort%laimemory)/store_c, & + min((EDPftvarcon_inst%phenflush_fraction(ipft)*currentCohort%leafmemory)/store_c, & (1.0_r8-carbon_store_buffer)) if(prt_params%woody(ipft).ne.itrue)then - totalmemory=currentCohort%laimemory+currentCohort%sapwmemory+currentCohort%structmemory + totalmemory=currentCohort%leafmemory+currentCohort%sapwmemory+currentCohort%structmemory store_c_transfer_frac = min(EDPftvarcon_inst%phenflush_fraction(ipft)*totalmemory/store_c, & (1.0_r8-carbon_store_buffer)) @@ -1260,7 +1260,7 @@ subroutine phenology_leafonoff(currentSite) call PRTPhenologyFlush(currentCohort%prt, ipft, & leaf_organ, store_c_transfer_frac) - currentCohort%laimemory = 0.0_r8 + currentCohort%leafmemory = 0.0_r8 else @@ -1268,7 +1268,7 @@ subroutine phenology_leafonoff(currentSite) if (stem_drop_fraction .gt. 0.0_r8) then call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & - store_c_transfer_frac*currentCohort%laimemory/totalmemory) + store_c_transfer_frac*currentCohort%leafmemory/totalmemory) call PRTPhenologyFlush(currentCohort%prt, ipft, sapw_organ, & store_c_transfer_frac*currentCohort%sapwmemory/totalmemory) @@ -1283,7 +1283,7 @@ subroutine phenology_leafonoff(currentSite) end if - currentCohort%laimemory = 0.0_r8 + currentCohort%leafmemory = 0.0_r8 currentCohort%structmemory = 0.0_r8 currentCohort%sapwmemory = 0.0_r8 @@ -1300,8 +1300,8 @@ subroutine phenology_leafonoff(currentSite) ! This sets the cohort to the "leaves off" flag currentCohort%status_coh = leaves_off - ! Remember what the lai (leaf mass actually) was for next year - currentCohort%laimemory = leaf_c + ! Remember what the leaf mass was for next year + currentCohort%leafmemory = leaf_c call PRTDeciduousTurnover(currentCohort%prt,ipft, & leaf_organ, leaf_drop_fraction) @@ -1890,7 +1890,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) ! Default assumption is that leaves are on cohortstatus = leaves_on - temp_cohort%laimemory = 0.0_r8 + temp_cohort%leafmemory = 0.0_r8 temp_cohort%sapwmemory = 0.0_r8 temp_cohort%structmemory = 0.0_r8 @@ -1899,7 +1899,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) ! as "cold", then set the cohort's status to leaves_off, and remember the leaf biomass if ((prt_params%season_decid(ft) == itrue) .and. & (any(currentSite%cstatus == [phen_cstat_nevercold,phen_cstat_iscold]))) then - temp_cohort%laimemory = c_leaf + temp_cohort%leafmemory = c_leaf c_leaf = 0.0_r8 ! If plant is not woody then set sapwood and structural biomass as well @@ -1917,7 +1917,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) ! biomass if ((prt_params%stress_decid(ft) == itrue) .and. & (any(currentSite%dstatus == [phen_dstat_timeoff,phen_dstat_moistoff]))) then - temp_cohort%laimemory = c_leaf + temp_cohort%leafmemory = c_leaf c_leaf = 0.0_r8 ! If plant is not woody then set sapwood and structural biomass as well @@ -2103,7 +2103,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) ! This initializes the cohort call create_cohort(currentSite,currentPatch, temp_cohort%pft, temp_cohort%n, & temp_cohort%hite, temp_cohort%coage, temp_cohort%dbh, prt, & - temp_cohort%laimemory, temp_cohort%sapwmemory, temp_cohort%structmemory, & + temp_cohort%leafmemory, temp_cohort%sapwmemory, temp_cohort%structmemory, & cohortstatus, recruitstatus, & temp_cohort%canopy_trim,temp_cohort%c_area, & currentPatch%NCL_p, currentSite%spread, bc_in) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 06bcd1858a..3b6074d643 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -787,7 +787,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) call bstore_allom(temp_cohort%dbh, pft, temp_cohort%canopy_trim, c_store) - temp_cohort%laimemory = 0._r8 + temp_cohort%leafmemory = 0._r8 temp_cohort%sapwmemory = 0._r8 temp_cohort%structmemory = 0._r8 cstatus = leaves_on @@ -798,7 +798,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) if( prt_params%season_decid(pft) == itrue .and. & any(site_in%cstatus == [phen_cstat_nevercold,phen_cstat_iscold])) then - temp_cohort%laimemory = c_leaf + temp_cohort%leafmemory = c_leaf temp_cohort%sapwmemory = c_sapw * stem_drop_fraction temp_cohort%structmemory = c_struct * stem_drop_fraction c_leaf = 0._r8 @@ -809,7 +809,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) if ( prt_params%stress_decid(pft) == itrue .and. & any(site_in%dstatus == [phen_dstat_timeoff,phen_dstat_moistoff])) then - temp_cohort%laimemory = c_leaf + temp_cohort%leafmemory = c_leaf temp_cohort%sapwmemory = c_sapw * stem_drop_fraction temp_cohort%structmemory = c_struct * stem_drop_fraction c_leaf = 0._r8 @@ -850,21 +850,21 @@ subroutine init_cohorts( site_in, patch_in, bc_in) case(nitrogen_element) - m_struct = c_struct*prt_params%nitr_stoich_p2(pft,prt_params%organ_param_id(struct_organ)) - m_leaf = c_leaf*prt_params%nitr_stoich_p2(pft,prt_params%organ_param_id(leaf_organ)) - m_fnrt = c_fnrt*prt_params%nitr_stoich_p2(pft,prt_params%organ_param_id(fnrt_organ)) - m_sapw = c_sapw*prt_params%nitr_stoich_p2(pft,prt_params%organ_param_id(sapw_organ)) + m_struct = c_struct*prt_params%nitr_stoich_p2(pft,prt_params%organ_param_id(struct_organ)) + m_leaf = c_leaf*prt_params%nitr_stoich_p2(pft,prt_params%organ_param_id(leaf_organ)) + m_fnrt = c_fnrt*prt_params%nitr_stoich_p2(pft,prt_params%organ_param_id(fnrt_organ)) + m_sapw = c_sapw*prt_params%nitr_stoich_p2(pft,prt_params%organ_param_id(sapw_organ)) m_repro = 0._r8 - m_store = StorageNutrientTarget(pft,element_id,m_leaf,m_fnrt,m_sapw,m_struct) + m_store = StorageNutrientTarget(pft,element_id,m_leaf,m_fnrt,m_sapw,m_struct) case(phosphorus_element) - m_struct = c_struct*prt_params%phos_stoich_p2(pft,prt_params%organ_param_id(struct_organ)) - m_leaf = c_leaf*prt_params%phos_stoich_p2(pft,prt_params%organ_param_id(leaf_organ)) - m_fnrt = c_fnrt*prt_params%phos_stoich_p2(pft,prt_params%organ_param_id(fnrt_organ)) - m_sapw = c_sapw*prt_params%phos_stoich_p2(pft,prt_params%organ_param_id(sapw_organ)) + m_struct = c_struct*prt_params%phos_stoich_p2(pft,prt_params%organ_param_id(struct_organ)) + m_leaf = c_leaf*prt_params%phos_stoich_p2(pft,prt_params%organ_param_id(leaf_organ)) + m_fnrt = c_fnrt*prt_params%phos_stoich_p2(pft,prt_params%organ_param_id(fnrt_organ)) + m_sapw = c_sapw*prt_params%phos_stoich_p2(pft,prt_params%organ_param_id(sapw_organ)) m_repro = 0._r8 - m_store = StorageNutrientTarget(pft,element_id,m_leaf,m_fnrt,m_sapw,m_struct) + m_store = StorageNutrientTarget(pft,element_id,m_leaf,m_fnrt,m_sapw,m_struct) end select @@ -893,7 +893,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) call prt_obj%CheckInitialConditions() call create_cohort(site_in, patch_in, pft, temp_cohort%n, temp_cohort%hite, & - temp_cohort%coage, temp_cohort%dbh, prt_obj, temp_cohort%laimemory, & + temp_cohort%coage, temp_cohort%dbh, prt_obj, temp_cohort%leafmemory, & temp_cohort%sapwmemory, temp_cohort%structmemory, cstatus, rstatus, & temp_cohort%canopy_trim, temp_cohort%c_area,1, site_in%spread, bc_in) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 9ce4d5fe44..d377002aa3 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -219,7 +219,7 @@ module EDTypesMod real(r8) :: coage ! cohort age in years real(r8) :: hite ! height: meters integer :: indexnumber ! unique number for each cohort. (within clump?) - real(r8) :: laimemory ! target leaf biomass- set from previous year: kGC per indiv + real(r8) :: leafmemory ! target leaf biomass- set from previous year: kGC per indiv real(r8) :: sapwmemory ! target sapwood biomass- set from previous year: kGC per indiv real(r8) :: structmemory ! target structural biomass- set from previous year: kGC per indiv integer :: canopy_layer ! canopy status of cohort (1 = canopy, 2 = understorey, etc.) @@ -1049,7 +1049,7 @@ subroutine dump_cohort(ccohort) write(fates_log(),*) 'co%dbh = ', ccohort%dbh write(fates_log(),*) 'co%hite = ', ccohort%hite write(fates_log(),*) 'co%coage = ', ccohort%coage - write(fates_log(),*) 'co%laimemory = ', ccohort%laimemory + write(fates_log(),*) 'co%leafmemory = ', ccohort%leafmemory write(fates_log(),*) 'co%sapwmemory = ', ccohort%sapwmemory write(fates_log(),*) 'co%structmemory = ', ccohort%structmemory diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index 507f01dbee..07da027056 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -1039,7 +1039,7 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & call bstore_allom(temp_cohort%dbh, temp_cohort%pft, temp_cohort%canopy_trim, c_store) - temp_cohort%laimemory = 0._r8 + temp_cohort%leafmemory = 0._r8 temp_cohort%sapwmemory = 0._r8 temp_cohort%structmemory = 0._r8 cstatus = leaves_on @@ -1048,7 +1048,7 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & if( prt_params%season_decid(temp_cohort%pft) == itrue .and. & any(csite%cstatus == [phen_cstat_nevercold,phen_cstat_iscold])) then - temp_cohort%laimemory = c_leaf + temp_cohort%leafmemory = c_leaf temp_cohort%sapwmemory = c_sapw * stem_drop_fraction temp_cohort%structmemory = c_struct * stem_drop_fraction c_leaf = 0._r8 @@ -1059,7 +1059,7 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & if ( prt_params%stress_decid(temp_cohort%pft) == itrue .and. & any(csite%dstatus == [phen_dstat_timeoff,phen_dstat_moistoff])) then - temp_cohort%laimemory = c_leaf + temp_cohort%leafmemory = c_leaf temp_cohort%sapwmemory = c_sapw * stem_drop_fraction temp_cohort%structmemory = c_struct * stem_drop_fraction c_leaf = 0._r8 @@ -1167,7 +1167,7 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & call create_cohort(csite, cpatch, temp_cohort%pft, temp_cohort%n, temp_cohort%hite, & temp_cohort%coage, temp_cohort%dbh, & - prt_obj, temp_cohort%laimemory,temp_cohort%sapwmemory, temp_cohort%structmemory, & + prt_obj, temp_cohort%leafmemory,temp_cohort%sapwmemory, temp_cohort%structmemory, & cstatus, rstatus, temp_cohort%canopy_trim,temp_cohort%c_area, & 1, csite%spread, bc_in) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 0605767cd6..a2b8fc425e 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -100,7 +100,7 @@ module FatesRestartInterfaceMod integer :: ir_coage_co integer :: ir_g_sb_laweight_co integer :: ir_height_co - integer :: ir_laimemory_co + integer :: ir_leafmemory_co integer :: ir_sapwmemory_co integer :: ir_structmemory_co integer :: ir_nplant_co @@ -714,10 +714,10 @@ subroutine define_restart_vars(this, initialize_variables) long_name='ed cohort - plant height', units='m', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_height_co ) - call this%set_restart_var(vname='fates_laimemory', vtype=cohort_r8, & + call this%set_restart_var(vname='fates_leafmemory', vtype=cohort_r8, & long_name='ed cohort - target leaf biomass set from prev year', & units='kgC/indiv', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_laimemory_co ) + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_leafmemory_co ) call this%set_restart_var(vname='fates_sapwmemory', vtype=cohort_r8, & long_name='ed cohort - target sapwood biomass set from prev year', & @@ -1769,7 +1769,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_coage_co => this%rvars(ir_coage_co)%r81d, & rio_g_sb_laweight_co => this%rvars(ir_g_sb_laweight_co)%r81d, & rio_height_co => this%rvars(ir_height_co)%r81d, & - rio_laimemory_co => this%rvars(ir_laimemory_co)%r81d, & + rio_leafmemory_co => this%rvars(ir_leafmemory_co)%r81d, & rio_sapwmemory_co => this%rvars(ir_sapwmemory_co)%r81d, & rio_structmemory_co => this%rvars(ir_structmemory_co)%r81d, & rio_nplant_co => this%rvars(ir_nplant_co)%r81d, & @@ -1997,7 +1997,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_dbh_co(io_idx_co) = ccohort%dbh rio_coage_co(io_idx_co) = ccohort%coage rio_height_co(io_idx_co) = ccohort%hite - rio_laimemory_co(io_idx_co) = ccohort%laimemory + rio_leafmemory_co(io_idx_co) = ccohort%leafmemory rio_sapwmemory_co(io_idx_co) = ccohort%sapwmemory rio_structmemory_co(io_idx_co) = ccohort%structmemory rio_g_sb_laweight_co(io_idx_co)= ccohort%g_sb_laweight @@ -2600,7 +2600,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_coage_co => this%rvars(ir_coage_co)%r81d, & rio_g_sb_laweight_co => this%rvars(ir_g_sb_laweight_co)%r81d, & rio_height_co => this%rvars(ir_height_co)%r81d, & - rio_laimemory_co => this%rvars(ir_laimemory_co)%r81d, & + rio_leafmemory_co => this%rvars(ir_leafmemory_co)%r81d, & rio_sapwmemory_co => this%rvars(ir_sapwmemory_co)%r81d, & rio_structmemory_co => this%rvars(ir_structmemory_co)%r81d, & rio_nplant_co => this%rvars(ir_nplant_co)%r81d, & @@ -2802,9 +2802,9 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ccohort%coage = rio_coage_co(io_idx_co) ccohort%g_sb_laweight= rio_g_sb_laweight_co(io_idx_co) ccohort%hite = rio_height_co(io_idx_co) - ccohort%laimemory = rio_laimemory_co(io_idx_co) + ccohort%leafmemory = rio_leafmemory_co(io_idx_co) ccohort%sapwmemory = rio_sapwmemory_co(io_idx_co) - ccohort%structmemory= rio_structmemory_co(io_idx_co) + ccohort%structmemory = rio_structmemory_co(io_idx_co) ccohort%n = rio_nplant_co(io_idx_co) ccohort%gpp_acc = rio_gpp_acc_co(io_idx_co) ccohort%npp_acc = rio_npp_acc_co(io_idx_co) From 03fc6392cee1f34f180dab492675b263a827ca7c Mon Sep 17 00:00:00 2001 From: Marcos Longo Date: Tue, 3 May 2022 16:19:07 -0700 Subject: [PATCH 189/852] Added two history files (default inactive) with LAI by size and PFT (canopy/understory). --- main/FatesHistoryInterfaceMod.F90 | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index f43289da15..c461baa658 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -220,6 +220,9 @@ module FatesHistoryInterfaceMod integer :: ih_bstor_understory_si_scpf integer :: ih_bleaf_canopy_si_scpf integer :: ih_bleaf_understory_si_scpf + ! Size-class x PFT LAI states + integer :: ih_lai_canopy_si_scpf + integer :: ih_lai_understory_si_scpf @@ -1861,6 +1864,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_bstor_understory_si_scpf => this%hvars(ih_bstor_understory_si_scpf)%r82d, & hio_bleaf_canopy_si_scpf => this%hvars(ih_bleaf_canopy_si_scpf)%r82d, & hio_bleaf_understory_si_scpf => this%hvars(ih_bleaf_understory_si_scpf)%r82d, & + hio_lai_canopy_si_scpf => this%hvars(ih_lai_canopy_si_scpf)%r82d, & + hio_lai_understory_si_scpf => this%hvars(ih_lai_understory_si_scpf)%r82d, & hio_mortality_canopy_si_scpf => this%hvars(ih_mortality_canopy_si_scpf)%r82d, & hio_mortality_understory_si_scpf => this%hvars(ih_mortality_understory_si_scpf)%r82d, & hio_nplant_canopy_si_scpf => this%hvars(ih_nplant_canopy_si_scpf)%r82d, & @@ -2633,6 +2638,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) store_m * ccohort%n / m2_per_ha hio_bleaf_canopy_si_scpf(io_si,scpf) = hio_bleaf_canopy_si_scpf(io_si,scpf) + & leaf_m * ccohort%n / m2_per_ha + hio_lai_canopy_si_scpf(io_si,scpf) = hio_lai_canopy_si_scpf(io_si,scpf) + & + ccohort%treelai*ccohort%c_area * AREA_INV hio_canopy_biomass_si(io_si) = hio_canopy_biomass_si(io_si) + n_perm2 * total_m @@ -2726,6 +2733,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) leaf_m * ccohort%n / m2_per_ha hio_understory_biomass_si(io_si) = hio_understory_biomass_si(io_si) + & n_perm2 * total_m + hio_lai_understory_si_scpf(io_si,scpf) = hio_lai_understory_si_scpf(io_si,scpf) + & + ccohort%treelai*ccohort%c_area * AREA_INV !hio_mortality_understory_si_scpf(io_si,scpf) = hio_mortality_understory_si_scpf(io_si,scpf)+ & ! (ccohort%bmort + ccohort%hmort + ccohort%cmort + @@ -4044,7 +4053,7 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) do j_bc = j_t,j_b vwc = bc_in(s)%h2o_liqvol_sl(j_bc) - psi = site_hydr%wrf_soil(j)%p%psi_from_th(vwc) + psi = site_hydr%wrf_soil(j)%p%psi_from_th(vwc) ! MLO: Any reason for not using smp_sl? ! cap capillary pressure ! psi = max(-1e5_r8,psi) Removing cap as that is inconstistent ! with model internals and physics. Should @@ -5793,6 +5802,14 @@ subroutine define_history_vars(this, initialize_variables) ivar=ivar, initialize=initialize_variables, & index = ih_bleaf_canopy_si_scpf) + call this%set_history_var(vname='FATES_LAI_CANOPY_SZPF', & + units = 'm2 m-2', & + long='Leaf area index (LAI) of canopy plants by pft/size', & + use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, & + index = ih_lai_canopy_si_scpf ) + call this%set_history_var(vname='FATES_NPLANT_CANOPY_SZPF', units = 'm-2', & long='number of canopy plants by size/pft per m2', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & @@ -5821,6 +5838,13 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index = ih_bleaf_understory_si_scpf) + call this%set_history_var(vname='FATES_LAI_USTORY_SZPF', & + units = 'm2 m-2', & + long='Leaf area index (LAI) of understory plants by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_lai_understory_si_scpf ) + call this%set_history_var(vname='FATES_NPLANT_USTORY_SZPF', & units = 'm-2', & long='density of understory plants by pft/size in number of plants per m2', & From c9e6df7de0746a065ae3328073256c6cf5b26a63 Mon Sep 17 00:00:00 2001 From: Marcos Longo Date: Tue, 3 May 2022 16:47:23 -0700 Subject: [PATCH 190/852] Updates to target carbon sub-routine to improve readability. Rationale: I rewrote sub-routine TargetAllometryCheck. Instead of using if statements to set logical variables, I assigned the logical variables directly. Also, I added more information to the error message in case the sub-routine fails, which may be useful for debugging. None of the changes should have impacts on FATES results. --- parteh/PRTAllometricCNPMod.F90 | 150 +++++++++++-------- parteh/PRTAllometricCarbonMod.F90 | 234 ++++++++++++++++-------------- 2 files changed, 211 insertions(+), 173 deletions(-) diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 5617d71e5d..d1fd48c7ed 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -2222,72 +2222,94 @@ end function AllomCNPGrowthDeriv ! ==================================================================================== - subroutine TargetAllometryCheck(bleaf,bfroot,bsap,bstore,bdead, & - bt_leaf,bt_froot,bt_sap,bt_store,bt_dead, & - grow_leaf,grow_froot,grow_sapw,grow_store) - - ! Arguments - real(r8),intent(in) :: bleaf !actual - real(r8),intent(in) :: bfroot - real(r8),intent(in) :: bsap - real(r8),intent(in) :: bstore - real(r8),intent(in) :: bdead - real(r8),intent(in) :: bt_leaf !target - real(r8),intent(in) :: bt_froot - real(r8),intent(in) :: bt_sap - real(r8),intent(in) :: bt_store - real(r8),intent(in) :: bt_dead - logical,intent(out) :: grow_leaf !growth flag - logical,intent(out) :: grow_froot - logical,intent(out) :: grow_sapw - logical,intent(out) :: grow_store - - if( (bt_leaf - bleaf)>calloc_abs_error) then - write(fates_log(),*) 'leaves are not on-allometry at the growth step' - write(fates_log(),*) 'exiting',bleaf,bt_leaf - call endrun(msg=errMsg(sourcefile, __LINE__)) - elseif( (bleaf - bt_leaf)>calloc_abs_error) then - ! leaf is above allometry, ignore - grow_leaf = .false. - else - grow_leaf = .true. - end if - - if( (bt_froot - bfroot)>calloc_abs_error) then - write(fates_log(),*) 'fineroots are not on-allometry at the growth step' - write(fates_log(),*) 'exiting',bfroot, bt_froot - call endrun(msg=errMsg(sourcefile, __LINE__)) - elseif( ( bfroot-bt_froot)>calloc_abs_error ) then - grow_froot = .false. - else - grow_froot = .true. - end if - - if( (bt_sap - bsap)>calloc_abs_error) then - write(fates_log(),*) 'sapwood is not on-allometry at the growth step' - write(fates_log(),*) 'exiting',bsap, bt_sap - call endrun(msg=errMsg(sourcefile, __LINE__)) - elseif( ( bsap-bt_sap)>calloc_abs_error ) then - grow_sapw = .false. - else - grow_sapw = .true. - end if + subroutine TargetAllometryCheck(b0_leaf,b0_fnrt,b0_sapw,b0_store,b0_struct, & + bleaf,bfnrt,bsapw,bstore,bstruct, & + bt_leaf,bt_fnrt,bt_sapw,bt_store,bt_struct, & + carbon_balance,ipft,leaf_status, & + grow_leaf,grow_fnrt,grow_sapw,grow_store,grow_struct) - if( (bt_store - bstore)>calloc_abs_error) then - write(fates_log(),*) 'storage is not on-allometry at the growth step' - write(fates_log(),*) 'exiting',bstore,bt_store - call endrun(msg=errMsg(sourcefile, __LINE__)) - elseif( ( bstore-bt_store)>calloc_abs_error ) then - grow_store = .false. - else - grow_store = .true. - end if + ! Arguments + real(r8),intent(in) :: b0_leaf !initial + real(r8),intent(in) :: b0_fnrt + real(r8),intent(in) :: b0_sapw + real(r8),intent(in) :: b0_store + real(r8),intent(in) :: b0_struct + real(r8),intent(in) :: bleaf !actual + real(r8),intent(in) :: bfnrt + real(r8),intent(in) :: bsapw + real(r8),intent(in) :: bstore + real(r8),intent(in) :: bstruct + real(r8),intent(in) :: bt_leaf !target + real(r8),intent(in) :: bt_fnrt + real(r8),intent(in) :: bt_sapw + real(r8),intent(in) :: bt_store + real(r8),intent(in) :: bt_struct + real(r8),intent(in) :: carbon_balance !remaining carbon balance + integer,intent(in) :: ipft !Plant functional type + integer,intent(in) :: leaf_status !Phenology status + logical,intent(out) :: grow_leaf !growth flag + logical,intent(out) :: grow_fnrt + logical,intent(out) :: grow_sapw + logical,intent(out) :: grow_store + logical,intent(out) :: grow_struct + ! Local variables + logical :: fine_leaf + logical :: fine_fnrt + logical :: fine_sapw + logical :: fine_store + logical :: fine_struct + logical :: all_fine + ! Local constants + character(len= 3), parameter :: fmth = '(a)' + character(len=27), parameter :: fmtb = '(a,3(1x,es12.5,1x,a),1x,l1)' + character(len=13), parameter :: fmte = '(a,1x,es12.5)' + character(len=10), parameter :: fmti = '(a,1x,i12)' + + + ! First test whether or not each pool looks reasonable. + fine_leaf = (bt_leaf - bleaf ) <= calloc_abs_error + fine_fnrt = (bt_fnrt - bfnrt ) <= calloc_abs_error + fine_sapw = (bt_sapw - bsapw ) <= calloc_abs_error + fine_store = (bt_store - bstore ) <= calloc_abs_error + fine_struct = (bt_struct - bstruct) <= calloc_abs_error + all_fine = fine_leaf .and. fine_fnrt .and. fine_sapw .and. & + fine_store .and. fine_struct + + ! Decide whether or not to grow tissues (but only if all tissues look fine). + ! We grow only when biomass is less than target biomass (with tolerance). + if (all_fine) then + grow_leaf = ( bleaf - bt_leaf ) <= calloc_abs_error + grow_fnrt = ( bfnrt - bt_fnrt ) <= calloc_abs_error + grow_sapw = ( bsapw - bt_sapw ) <= calloc_abs_error + grow_store = ( bstore - bt_store ) <= calloc_abs_error + grow_struct = ( bstruct - bt_struct ) <= calloc_abs_error + else + ! If anything looks not fine, write a detailed report + write(fates_log(),fmt=fmth) '======' + write(fates_log(),fmt=fmth) ' At least one tissue is not on-allometry at the growth step' + write(fates_log(),fmt=fmth) '======' + write(fates_log(),fmt=fmth) '' + write(fates_log(),fmt=fmth) ' Biomass and on-allometry test (''F'' means problem)' + write(fates_log(),fmt=fmth) '------' + write(fates_log(),fmt=fmth) ' Tissue | Initial | Current | Target | On-allometry' + write(fates_log(),fmt=fmtb) ' Leaf |',b0_leaf ,'|',bleaf ,'|',bt_leaf ,'|',fine_leaf + write(fates_log(),fmt=fmtb) ' Fine root |',b0_fnrt ,'|',bfnrt ,'|',bt_fnrt ,'|',fine_fnrt + write(fates_log(),fmt=fmtb) ' Sap wood |',b0_sapw ,'|',bsapw ,'|',bt_sapw ,'|',fine_sapw + write(fates_log(),fmt=fmtb) ' Storage |',b0_store ,'|',bstore ,'|',bt_store ,'|',fine_store + write(fates_log(),fmt=fmtb) ' Structural |',b0_struct ,'|',bstruct ,'|',bt_struct ,'|',fine_struct + write(fates_log(),fmt=fmth) '' + write(fates_log(),fmt=fmth) ' Ancillary information' + write(fates_log(),fmt=fmth) '------' + write(fates_log(),fmt=fmti) ' PFT = ',ipft + write(fates_log(),fmt=fmti) ' leaf_status = ',leaf_status + write(fates_log(),fmt=fmte) ' carbon_balance = ',carbon_balance + write(fates_log(),fmt=fmte) ' calloc_abs_error = ',calloc_abs_error + write(fates_log(),fmt=fmth) '' + write(fates_log(),fmt=fmth) '======' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if - if( (bt_dead - bdead)>calloc_abs_error) then - write(fates_log(),*) 'structure not on-allometry at the growth step' - write(fates_log(),*) 'exiting',bdead,bt_dead - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + return end subroutine TargetAllometryCheck diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 5bdf624502..c2cd84a7fc 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -376,6 +376,10 @@ subroutine DailyPRTAllometricCarbon(this) integer, parameter :: iexp_leaf = 1 ! index 1 is the expanding (i.e. youngest) ! leaf age class, and therefore ! all new allocation goes into that pool + character(len= 9), parameter :: fmti = '(a,1x,i5)' + character(len=13), parameter :: fmt0 = '(a,1x,es12.5)' + character(len=19), parameter :: fmth = '(a,1x,a5,3(1x,a12))' + character(len=22), parameter :: fmtg = '(a,5x,l1,3(1x,es12.5))' real(r8) :: intgr_params(num_bc_in) ! The boundary conditions to this routine, ! are pressed into an array that is also @@ -639,24 +643,15 @@ subroutine DailyPRTAllometricCarbon(this) ! allow actual pools to be above the target, and in these cases, it sends ! a false on the "grow_<>" flag, allowing the plant to grow into these pools. ! It also checks to make sure that structural biomass is not above the target. + ! ( MLO. Removed the check for storage because the same test is done inside + ! sub-routine TargetAllometryCheck.) - if( (target_store_c - store_c)>calloc_abs_error) then - write(fates_log(),*) 'storage is not on-allometry at the growth step' - write(fates_log(),*) 'exiting' - write(fates_log(),*) 'cbal: ',carbon_balance - write(fates_log(),*) 'near-zero',nearzero - write(fates_log(),*) 'store_c: ',store_c - write(fates_log(),*) 'target c: ',target_store_c - write(fates_log(),*) 'store_c0:', store_c0 - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - - call TargetAllometryCheck(sum(leaf_c(1:nleafage)), fnrt_c, sapw_c, & - store_c, struct_c, & - target_leaf_c, target_fnrt_c, & - target_sapw_c, target_store_c, target_struct_c, & - grow_struct, grow_leaf, grow_fnrt, grow_sapw, grow_store) + call TargetAllometryCheck(sum(leaf_c0(1:nleafage)),fnrt_c0,sapw_c0,store_c0,struct_c0, & + sum(leaf_c(1:nleafage)), fnrt_c, sapw_c,store_c, struct_c, & + target_leaf_c, target_fnrt_c, target_sapw_c, & + target_store_c, target_struct_c, & + carbon_balance,ipft,leaf_status, & + grow_leaf, grow_fnrt, grow_sapw, grow_store, grow_struct) ! -------------------------------------------------------------------------------- ! The numerical integration of growth requires that the instantaneous state @@ -697,28 +692,30 @@ subroutine DailyPRTAllometricCarbon(this) end if c_mask(fnrt_c_id) = grow_fnrt c_mask(sapw_c_id) = grow_sapw - c_mask(store_c_id) = grow_store c_mask(struct_c_id) = grow_struct + c_mask(store_c_id) = grow_store c_mask(repro_c_id) = .true. ! Always calculate reproduction on growth c_mask(dbh_id) = .true. ! Always increment dbh on growth step - + ! When using the Euler method, we keep things simple. We always try ! to make the first integration step to span the entirety of the integration ! window for the independent variable (available carbon) - if(ODESolve == 2) then + select case (ODESolve) + case (2) this%ode_opt_step = totalC - end if + end select do_solve_check: do while( ierr .ne. 0 ) deltaC = min(totalC,this%ode_opt_step) - if(ODESolve == 1) then + select_ODESolve: select case (ODESolve) + case (1) call RKF45(AllomCGrowthDeriv,c_pool,c_mask,deltaC,totalC, & max_trunc_error,intgr_params,c_pool_out,this%ode_opt_step,step_pass) - elseif(ODESolve == 2) then + case (2) call Euler(AllomCGrowthDeriv,c_pool,c_mask,deltaC,totalC,intgr_params,c_pool_out) ! step_pass = .true. @@ -741,11 +738,11 @@ subroutine DailyPRTAllometricCarbon(this) else this%ode_opt_step = 0.5*deltaC end if - else + case default write(fates_log(),*) 'An integrator was chosen that does not exist' write(fates_log(),*) 'ODESolve = ',ODESolve call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + end select select_ODESolve nsteps = nsteps + 1 @@ -755,17 +752,22 @@ subroutine DailyPRTAllometricCarbon(this) end if if(nsteps > max_substeps ) then - write(fates_log(),*) 'Plant Growth Integrator could not find' - write(fates_log(),*) 'a solution in less than ',max_substeps,' tries' - write(fates_log(),*) 'Aborting' - write(fates_log(),*) 'carbon_balance',carbon_balance - write(fates_log(),*) 'deltaC',deltaC - write(fates_log(),*) 'totalC',totalC - write(fates_log(),*) 'leaf:',grow_leaf,target_leaf_c,target_leaf_c - sum(leaf_c(:)) - write(fates_log(),*) 'fnrt:',grow_fnrt,target_fnrt_c,target_fnrt_c - fnrt_c - write(fates_log(),*) 'sap:',grow_sapw,target_sapw_c, target_sapw_c - sapw_c - write(fates_log(),*) 'store:',grow_store,target_store_c,target_store_c - store_c - write(fates_log(),*) 'dead:',target_struct_c,target_struct_c - struct_c + write(fates_log(),fmt=*) '---~---' + write(fates_log(),fmt=*) 'Plant Growth Integrator could not find' + write(fates_log(),fmt=*) 'a solution in less than ',max_substeps,' tries.' + write(fates_log(),fmt=*) 'Aborting!' + write(fates_log(),fmt=*) '---~---' + write(fates_log(),fmt=fmti) 'Leaf status =',leaf_status + write(fates_log(),fmt=fmt0) 'Carbon_balance =',carbon_balance + write(fates_log(),fmt=fmt0) 'deltaC =',deltaC + write(fates_log(),fmt=fmt0) 'totalC =',totalC + write(fates_log(),fmt=fmth) ' Tissue |', ' Grow',' Current',' Target' ,' Deficit' + write(fates_log(),fmt=fmtg) ' Leaf |', grow_leaf , sum(leaf_c(:)),target_leaf_c , target_leaf_c - sum(leaf_c(:)) + write(fates_log(),fmt=fmtg) ' Fine root |', grow_fnrt , fnrt_c,target_fnrt_c , target_fnrt_c - fnrt_c + write(fates_log(),fmt=fmtg) ' Sapwood |', grow_sapw , sapw_c,target_sapw_c , target_sapw_c - sapw_c + write(fates_log(),fmt=fmtg) ' Storage |', grow_store , store_c,target_store_c , target_store_c - store_c + write(fates_log(),fmt=fmtg) ' Structural |', grow_struct , struct_c,target_struct_c, target_struct_c - struct_c + write(fates_log(),fmt=*) '---~---' call endrun(msg=errMsg(sourcefile, __LINE__)) end if @@ -1008,80 +1010,94 @@ end function AllomCGrowthDeriv ! ==================================================================================== - subroutine TargetAllometryCheck(bleaf,bfroot,bsap,bstore,bdead, & - bt_leaf,bt_froot,bt_sap,bt_store,bt_dead, & - grow_dead,grow_leaf,grow_froot,grow_sapw,grow_store) - - ! Arguments - real(r8),intent(in) :: bleaf !actual - real(r8),intent(in) :: bfroot - real(r8),intent(in) :: bsap - real(r8),intent(in) :: bstore - real(r8),intent(in) :: bdead - real(r8),intent(in) :: bt_leaf !target - real(r8),intent(in) :: bt_froot - real(r8),intent(in) :: bt_sap - real(r8),intent(in) :: bt_store - real(r8),intent(in) :: bt_dead - logical,intent(out) :: grow_leaf !growth flag - logical,intent(out) :: grow_froot - logical,intent(out) :: grow_sapw - logical,intent(out) :: grow_store - logical,intent(out) :: grow_dead - - if( (bt_leaf - bleaf)>calloc_abs_error) then - write(fates_log(),*) 'leaves are not on-allometry at the growth step' - write(fates_log(),*) 'exiting',bleaf,bt_leaf - call endrun(msg=errMsg(sourcefile, __LINE__)) - elseif( (bleaf - bt_leaf)>calloc_abs_error) then - ! leaf is above allometry, ignore - grow_leaf = .false. - else - grow_leaf = .true. - end if - - if( (bt_froot - bfroot)>calloc_abs_error) then - write(fates_log(),*) 'fineroots are not on-allometry at the growth step' - write(fates_log(),*) 'exiting',bfroot, bt_froot - call endrun(msg=errMsg(sourcefile, __LINE__)) - elseif( ( bfroot-bt_froot)>calloc_abs_error ) then - grow_froot = .false. - else - grow_froot = .true. - end if - - if( (bt_sap - bsap)>calloc_abs_error) then - write(fates_log(),*) 'sapwood is not on-allometry at the growth step' - write(fates_log(),*) 'exiting',bsap, bt_sap - call endrun(msg=errMsg(sourcefile, __LINE__)) - elseif( ( bsap-bt_sap)>calloc_abs_error ) then - grow_sapw = .false. - else - grow_sapw = .true. - end if - - if( (bt_store - bstore)>calloc_abs_error) then - write(fates_log(),*) 'storage is not on-allometry at the growth step' - write(fates_log(),*) 'exiting',bstore,bt_store - call endrun(msg=errMsg(sourcefile, __LINE__)) - elseif( ( bstore-bt_store)>calloc_abs_error ) then - grow_store = .false. - else - grow_store = .true. - end if - - if( (bt_dead - bdead)>calloc_abs_error) then - write(fates_log(),*) 'structure not on-allometry at the growth step' - write(fates_log(),*) 'exiting',bdead,bt_dead - call endrun(msg=errMsg(sourcefile, __LINE__)) - elseif( (bdead-bt_dead)> calloc_abs_error) then - grow_dead = .false. - else - grow_dead = .true. - end if - + subroutine TargetAllometryCheck(b0_leaf,b0_fnrt,b0_sapw,b0_store,b0_struct, & + bleaf,bfnrt,bsapw,bstore,bstruct, & + bt_leaf,bt_fnrt,bt_sapw,bt_store,bt_struct, & + carbon_balance,ipft,leaf_status, & + grow_leaf,grow_fnrt,grow_sapw,grow_store,grow_struct) - return + ! Arguments + real(r8),intent(in) :: b0_leaf !initial + real(r8),intent(in) :: b0_fnrt + real(r8),intent(in) :: b0_sapw + real(r8),intent(in) :: b0_store + real(r8),intent(in) :: b0_struct + real(r8),intent(in) :: bleaf !actual + real(r8),intent(in) :: bfnrt + real(r8),intent(in) :: bsapw + real(r8),intent(in) :: bstore + real(r8),intent(in) :: bstruct + real(r8),intent(in) :: bt_leaf !target + real(r8),intent(in) :: bt_fnrt + real(r8),intent(in) :: bt_sapw + real(r8),intent(in) :: bt_store + real(r8),intent(in) :: bt_struct + real(r8),intent(in) :: carbon_balance !remaining carbon balance + integer,intent(in) :: ipft !Plant functional type + integer,intent(in) :: leaf_status !Phenology status + logical,intent(out) :: grow_leaf !growth flag + logical,intent(out) :: grow_fnrt + logical,intent(out) :: grow_sapw + logical,intent(out) :: grow_store + logical,intent(out) :: grow_struct + ! Local variables + logical :: fine_leaf + logical :: fine_fnrt + logical :: fine_sapw + logical :: fine_store + logical :: fine_struct + logical :: all_fine + ! Local constants + character(len= 3), parameter :: fmth = '(a)' + character(len=27), parameter :: fmtb = '(a,3(1x,es12.5,1x,a),1x,l1)' + character(len=13), parameter :: fmte = '(a,1x,es12.5)' + character(len=10), parameter :: fmti = '(a,1x,i12)' + + + ! First test whether or not each pool looks reasonable. + fine_leaf = (bt_leaf - bleaf ) <= calloc_abs_error + fine_fnrt = (bt_fnrt - bfnrt ) <= calloc_abs_error + fine_sapw = (bt_sapw - bsapw ) <= calloc_abs_error + fine_store = (bt_store - bstore ) <= calloc_abs_error + fine_struct = (bt_struct - bstruct) <= calloc_abs_error + all_fine = fine_leaf .and. fine_fnrt .and. fine_sapw .and. & + fine_store .and. fine_struct + + ! Decide whether or not to grow tissues (but only if all tissues look fine). + ! We grow only when biomass is less than target biomass (with tolerance). + if (all_fine) then + grow_leaf = ( bleaf - bt_leaf ) <= calloc_abs_error + grow_fnrt = ( bfnrt - bt_fnrt ) <= calloc_abs_error + grow_sapw = ( bsapw - bt_sapw ) <= calloc_abs_error + grow_store = ( bstore - bt_store ) <= calloc_abs_error + grow_struct = ( bstruct - bt_struct ) <= calloc_abs_error + else + ! If anything looks not fine, write a detailed report + write(fates_log(),fmt=fmth) '======' + write(fates_log(),fmt=fmth) ' At least one tissue is not on-allometry at the growth step' + write(fates_log(),fmt=fmth) '======' + write(fates_log(),fmt=fmth) '' + write(fates_log(),fmt=fmth) ' Biomass and on-allometry test (''F'' means problem)' + write(fates_log(),fmt=fmth) '------' + write(fates_log(),fmt=fmth) ' Tissue | Initial | Current | Target | On-allometry' + write(fates_log(),fmt=fmtb) ' Leaf |',b0_leaf ,'|',bleaf ,'|',bt_leaf ,'|',fine_leaf + write(fates_log(),fmt=fmtb) ' Fine root |',b0_fnrt ,'|',bfnrt ,'|',bt_fnrt ,'|',fine_fnrt + write(fates_log(),fmt=fmtb) ' Sap wood |',b0_sapw ,'|',bsapw ,'|',bt_sapw ,'|',fine_sapw + write(fates_log(),fmt=fmtb) ' Storage |',b0_store ,'|',bstore ,'|',bt_store ,'|',fine_store + write(fates_log(),fmt=fmtb) ' Structural |',b0_struct ,'|',bstruct ,'|',bt_struct ,'|',fine_struct + write(fates_log(),fmt=fmth) '' + write(fates_log(),fmt=fmth) ' Ancillary information' + write(fates_log(),fmt=fmth) '------' + write(fates_log(),fmt=fmti) ' PFT = ',ipft + write(fates_log(),fmt=fmti) ' leaf_status = ',leaf_status + write(fates_log(),fmt=fmte) ' carbon_balance = ',carbon_balance + write(fates_log(),fmt=fmte) ' calloc_abs_error = ',calloc_abs_error + write(fates_log(),fmt=fmth) '' + write(fates_log(),fmt=fmth) '======' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + return end subroutine TargetAllometryCheck ! ===================================================================================== From 6529a175df4ce05bc80d9591de015d3a0b95a303 Mon Sep 17 00:00:00 2001 From: Marcos Longo Date: Tue, 3 May 2022 17:04:36 -0700 Subject: [PATCH 191/852] Rename subroutines that have the word retrieve misspelt. No actual change in functionality. --- fire/SFParamsMod.F90 | 42 +++--- main/EDParamsMod.F90 | 108 +++++++-------- main/EDPftvarcon.F90 | 214 +++++++++++++++--------------- main/FatesParametersInterface.F90 | 38 +++--- parteh/PRTParamsFATESMod.F90 | 132 +++++++++--------- 5 files changed, 267 insertions(+), 267 deletions(-) diff --git a/fire/SFParamsMod.F90 b/fire/SFParamsMod.F90 index 02c0ce7756..3d903397bc 100644 --- a/fire/SFParamsMod.F90 +++ b/fire/SFParamsMod.F90 @@ -260,37 +260,37 @@ subroutine SpitFireReceiveScalars(fates_params) real(r8) :: tmp_real - call fates_params%RetreiveParameter(name=SF_name_fdi_a, & + call fates_params%RetrieveParameter(name=SF_name_fdi_a, & data=SF_val_fdi_a) - call fates_params%RetreiveParameter(name=SF_name_fdi_b, & + call fates_params%RetrieveParameter(name=SF_name_fdi_b, & data=SF_val_fdi_b) - call fates_params%RetreiveParameter(name=SF_name_fdi_alpha, & + call fates_params%RetrieveParameter(name=SF_name_fdi_alpha, & data=SF_val_fdi_alpha) - call fates_params%RetreiveParameter(name=SF_name_miner_total, & + call fates_params%RetrieveParameter(name=SF_name_miner_total, & data=SF_val_miner_total) - call fates_params%RetreiveParameter(name=SF_name_fuel_energy, & + call fates_params%RetrieveParameter(name=SF_name_fuel_energy, & data=SF_val_fuel_energy) - call fates_params%RetreiveParameter(name=SF_name_part_dens, & + call fates_params%RetrieveParameter(name=SF_name_part_dens, & data=SF_val_part_dens) - call fates_params%RetreiveParameter(name=SF_name_miner_damp, & + call fates_params%RetrieveParameter(name=SF_name_miner_damp, & data=SF_val_miner_damp) - call fates_params%RetreiveParameter(name=SF_name_max_durat, & + call fates_params%RetrieveParameter(name=SF_name_max_durat, & data=SF_val_max_durat) - call fates_params%RetreiveParameter(name=SF_name_durat_slope, & + call fates_params%RetrieveParameter(name=SF_name_durat_slope, & data=SF_val_durat_slope) - call fates_params%RetreiveParameter(name=SF_name_drying_ratio, & + call fates_params%RetrieveParameter(name=SF_name_drying_ratio, & data=SF_val_drying_ratio) - call fates_params%RetreiveParameter(name=SF_name_fire_threshold, & + call fates_params%RetrieveParameter(name=SF_name_fire_threshold, & data=SF_val_fire_threshold) @@ -323,7 +323,7 @@ subroutine SpitFireReceiveNCWD(fates_params) class(fates_parameters_type), intent(inout) :: fates_params - call fates_params%RetreiveParameter(name=SF_name_CWD_frac, & + call fates_params%RetrieveParameter(name=SF_name_CWD_frac, & data=SF_val_CWD_frac) @@ -380,31 +380,31 @@ subroutine SpitFireReceiveNFSC(fates_params) class(fates_parameters_type), intent(inout) :: fates_params - call fates_params%RetreiveParameter(name=SF_name_SAV, & + call fates_params%RetrieveParameter(name=SF_name_SAV, & data=SF_val_SAV) - call fates_params%RetreiveParameter(name=SF_name_FBD, & + call fates_params%RetrieveParameter(name=SF_name_FBD, & data=SF_val_FBD) - call fates_params%RetreiveParameter(name=SF_name_min_moisture, & + call fates_params%RetrieveParameter(name=SF_name_min_moisture, & data=SF_val_min_moisture) - call fates_params%RetreiveParameter(name=SF_name_mid_moisture, & + call fates_params%RetrieveParameter(name=SF_name_mid_moisture, & data=SF_val_mid_moisture) - call fates_params%RetreiveParameter(name=SF_name_low_moisture_Coeff, & + call fates_params%RetrieveParameter(name=SF_name_low_moisture_Coeff, & data=SF_val_low_moisture_Coeff) - call fates_params%RetreiveParameter(name=SF_name_low_moisture_Slope, & + call fates_params%RetrieveParameter(name=SF_name_low_moisture_Slope, & data=SF_val_low_moisture_Slope) - call fates_params%RetreiveParameter(name=SF_name_mid_moisture_Coeff, & + call fates_params%RetrieveParameter(name=SF_name_mid_moisture_Coeff, & data=SF_val_mid_moisture_Coeff) - call fates_params%RetreiveParameter(name=SF_name_mid_moisture_Slope, & + call fates_params%RetrieveParameter(name=SF_name_mid_moisture_Slope, & data=SF_val_mid_moisture_Slope) - call fates_params%RetreiveParameter(name=SF_name_max_decomp, & + call fates_params%RetrieveParameter(name=SF_name_max_decomp, & data=SF_val_max_decomp) end subroutine SpitFireReceiveNFSC diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 51926d275a..c0d14bf208 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -477,171 +477,171 @@ subroutine FatesReceiveParams(fates_params) real(r8) :: tmpreal ! local real variable for changing type on read real(r8), allocatable :: hydr_htftype_real(:) - call fates_params%RetreiveParameter(name=ED_name_photo_temp_acclim_timescale, & + call fates_params%RetrieveParameter(name=ED_name_photo_temp_acclim_timescale, & data=photo_temp_acclim_timescale) - call fates_params%RetreiveParameter(name=name_photo_tempsens_model, & + call fates_params%RetrieveParameter(name=name_photo_tempsens_model, & data=tmpreal) photo_tempsens_model = nint(tmpreal) - call fates_params%RetreiveParameter(name=name_maintresp_model, & + call fates_params%RetrieveParameter(name=name_maintresp_model, & data=tmpreal) maintresp_model = nint(tmpreal) - call fates_params%RetreiveParameter(name=ED_name_mort_disturb_frac, & + call fates_params%RetrieveParameter(name=ED_name_mort_disturb_frac, & data=fates_mortality_disturbance_fraction) - call fates_params%RetreiveParameter(name=ED_name_comp_excln, & + call fates_params%RetrieveParameter(name=ED_name_comp_excln, & data=ED_val_comp_excln) - call fates_params%RetreiveParameter(name=ED_name_vai_top_bin_width, & + call fates_params%RetrieveParameter(name=ED_name_vai_top_bin_width, & data=ED_val_vai_top_bin_width) - call fates_params%RetreiveParameter(name=ED_name_vai_width_increase_factor, & + call fates_params%RetrieveParameter(name=ED_name_vai_width_increase_factor, & data=ED_val_vai_width_increase_factor) - call fates_params%RetreiveParameter(name=ED_name_init_litter, & + call fates_params%RetrieveParameter(name=ED_name_init_litter, & data=ED_val_init_litter) - call fates_params%RetreiveParameter(name=ED_name_nignitions, & + call fates_params%RetrieveParameter(name=ED_name_nignitions, & data=ED_val_nignitions) - call fates_params%RetreiveParameter(name=ED_name_understorey_death, & + call fates_params%RetrieveParameter(name=ED_name_understorey_death, & data=ED_val_understorey_death) - call fates_params%RetreiveParameter(name=ED_name_cwd_fcel, & + call fates_params%RetrieveParameter(name=ED_name_cwd_fcel, & data=ED_val_cwd_fcel) - call fates_params%RetreiveParameter(name=ED_name_cwd_flig, & + call fates_params%RetrieveParameter(name=ED_name_cwd_flig, & data=ED_val_cwd_flig) - call fates_params%RetreiveParameter(name=ED_name_base_mr_20, & + call fates_params%RetrieveParameter(name=ED_name_base_mr_20, & data=ED_val_base_mr_20) - call fates_params%RetreiveParameter(name=ED_name_phen_drought_threshold, & + call fates_params%RetrieveParameter(name=ED_name_phen_drought_threshold, & data=ED_val_phen_drought_threshold) - call fates_params%RetreiveParameter(name=ED_name_phen_doff_time, & + call fates_params%RetrieveParameter(name=ED_name_phen_doff_time, & data=ED_val_phen_doff_time) - call fates_params%RetreiveParameter(name=ED_name_phen_a, & + call fates_params%RetrieveParameter(name=ED_name_phen_a, & data=ED_val_phen_a) - call fates_params%RetreiveParameter(name=ED_name_phen_b, & + call fates_params%RetrieveParameter(name=ED_name_phen_b, & data=ED_val_phen_b) - call fates_params%RetreiveParameter(name=ED_name_phen_c, & + call fates_params%RetrieveParameter(name=ED_name_phen_c, & data=ED_val_phen_c) - call fates_params%RetreiveParameter(name=ED_name_phen_chiltemp, & + call fates_params%RetrieveParameter(name=ED_name_phen_chiltemp, & data=ED_val_phen_chiltemp) - call fates_params%RetreiveParameter(name=ED_name_phen_mindayson, & + call fates_params%RetrieveParameter(name=ED_name_phen_mindayson, & data=ED_val_phen_mindayson) - call fates_params%RetreiveParameter(name=ED_name_phen_ncolddayslim, & + call fates_params%RetrieveParameter(name=ED_name_phen_ncolddayslim, & data=ED_val_phen_ncolddayslim) - call fates_params%RetreiveParameter(name=ED_name_phen_coldtemp, & + call fates_params%RetrieveParameter(name=ED_name_phen_coldtemp, & data=ED_val_phen_coldtemp) - call fates_params%RetreiveParameter(name=ED_name_cohort_size_fusion_tol, & + call fates_params%RetrieveParameter(name=ED_name_cohort_size_fusion_tol, & data=ED_val_cohort_size_fusion_tol) - call fates_params%RetreiveParameter(name=ED_name_cohort_age_fusion_tol, & + call fates_params%RetrieveParameter(name=ED_name_cohort_age_fusion_tol, & data=ED_val_cohort_age_fusion_tol) - call fates_params%RetreiveParameter(name=ED_name_patch_fusion_tol, & + call fates_params%RetrieveParameter(name=ED_name_patch_fusion_tol, & data=ED_val_patch_fusion_tol) - call fates_params%RetreiveParameter(name=ED_name_canopy_closure_thresh, & + call fates_params%RetrieveParameter(name=ED_name_canopy_closure_thresh, & data=ED_val_canopy_closure_thresh) - call fates_params%RetreiveParameter(name=ED_name_stomatal_model, & + call fates_params%RetrieveParameter(name=ED_name_stomatal_model, & data=tmpreal) stomatal_model = nint(tmpreal) - call fates_params%RetreiveParameter(name=hydr_name_kmax_rsurf1, & + call fates_params%RetrieveParameter(name=hydr_name_kmax_rsurf1, & data=hydr_kmax_rsurf1) - call fates_params%RetreiveParameter(name=hydr_name_kmax_rsurf2, & + call fates_params%RetrieveParameter(name=hydr_name_kmax_rsurf2, & data=hydr_kmax_rsurf2) - call fates_params%RetreiveParameter(name=hydr_name_psi0, & + call fates_params%RetrieveParameter(name=hydr_name_psi0, & data=hydr_psi0) - call fates_params%RetreiveParameter(name=hydr_name_psicap, & + call fates_params%RetrieveParameter(name=hydr_name_psicap, & data=hydr_psicap) - call fates_params%RetreiveParameter(name=bgc_name_soil_salinity, & + call fates_params%RetrieveParameter(name=bgc_name_soil_salinity, & data=bgc_soil_salinity) - call fates_params%RetreiveParameter(name=logging_name_dbhmin, & + call fates_params%RetrieveParameter(name=logging_name_dbhmin, & data=logging_dbhmin) - call fates_params%RetreiveParameter(name=logging_name_dbhmax, & + call fates_params%RetrieveParameter(name=logging_name_dbhmax, & data=logging_dbhmax) - call fates_params%RetreiveParameter(name=logging_name_collateral_frac, & + call fates_params%RetrieveParameter(name=logging_name_collateral_frac, & data=logging_collateral_frac) - call fates_params%RetreiveParameter(name=logging_name_coll_under_frac, & + call fates_params%RetrieveParameter(name=logging_name_coll_under_frac, & data=logging_coll_under_frac) - call fates_params%RetreiveParameter(name=logging_name_direct_frac, & + call fates_params%RetrieveParameter(name=logging_name_direct_frac, & data=logging_direct_frac) - call fates_params%RetreiveParameter(name=logging_name_mechanical_frac, & + call fates_params%RetrieveParameter(name=logging_name_mechanical_frac, & data=logging_mechanical_frac) - call fates_params%RetreiveParameter(name=logging_name_event_code, & + call fates_params%RetrieveParameter(name=logging_name_event_code, & data=logging_event_code) - call fates_params%RetreiveParameter(name=logging_name_dbhmax_infra, & + call fates_params%RetrieveParameter(name=logging_name_dbhmax_infra, & data=logging_dbhmax_infra) - call fates_params%RetreiveParameter(name=logging_name_export_frac, & + call fates_params%RetrieveParameter(name=logging_name_export_frac, & data=logging_export_frac) - call fates_params%RetreiveParameter(name=eca_name_plant_escalar, & + call fates_params%RetrieveParameter(name=eca_name_plant_escalar, & data=eca_plant_escalar) - call fates_params%RetreiveParameter(name=name_theta_cj_c3, & + call fates_params%RetrieveParameter(name=name_theta_cj_c3, & data=theta_cj_c3) - call fates_params%RetreiveParameter(name=name_theta_cj_c4, & + call fates_params%RetrieveParameter(name=name_theta_cj_c4, & data=theta_cj_c4) - call fates_params%RetreiveParameter(name=fates_name_q10_mr, & + call fates_params%RetrieveParameter(name=fates_name_q10_mr, & data=q10_mr) - call fates_params%RetreiveParameter(name=fates_name_q10_froz, & + call fates_params%RetrieveParameter(name=fates_name_q10_froz, & data=q10_froz) - call fates_params%RetreiveParameter(name=name_dev_arbitrary, & + call fates_params%RetrieveParameter(name=name_dev_arbitrary, & data=dev_arbitrary) - call fates_params%RetreiveParameter(name=fates_name_active_crown_fire, & + call fates_params%RetrieveParameter(name=fates_name_active_crown_fire, & data=tmpreal) active_crown_fire = (abs(tmpreal-1.0_r8) RetreiveParameterScalar, RetreiveParameter1D, RetreiveParameter2D - generic :: RetreiveParameterAllocate => RetreiveParameter1DAllocate, RetreiveParameter2DAllocate + generic :: RetrieveParameter => RetrieveParameterScalar, RetrieveParameter1D, RetrieveParameter2D + generic :: RetrieveParameterAllocate => RetrieveParameter1DAllocate, RetrieveParameter2DAllocate generic :: SetData => SetDataScalar, SetData1D, SetData2D procedure :: GetUsedDimensions procedure :: SetDimensionSizes @@ -70,11 +70,11 @@ module FatesParametersInterface procedure :: FindIndex ! Private functions - procedure, private :: RetreiveParameterScalar - procedure, private :: RetreiveParameter1D - procedure, private :: RetreiveParameter2D - procedure, private :: RetreiveParameter1DAllocate - procedure, private :: RetreiveParameter2DAllocate + procedure, private :: RetrieveParameterScalar + procedure, private :: RetrieveParameter1D + procedure, private :: RetrieveParameter2D + procedure, private :: RetrieveParameter1DAllocate + procedure, private :: RetrieveParameter2DAllocate procedure, private :: SetDataScalar procedure, private :: SetData1D procedure, private :: SetData2D @@ -151,7 +151,7 @@ subroutine RegisterParameter(this, name, dimension_shape, dimension_names, & end subroutine RegisterParameter !----------------------------------------------------------------------- - subroutine RetreiveParameterScalar(this, name, data) + subroutine RetrieveParameterScalar(this, name, data) implicit none @@ -165,10 +165,10 @@ subroutine RetreiveParameterScalar(this, name, data) ! assert(size(data) == size(this%parameters(i)%data)) data = this%parameters(i)%data(1, 1) - end subroutine RetreiveParameterScalar + end subroutine RetrieveParameterScalar !----------------------------------------------------------------------- - subroutine RetreiveParameter1D(this, name, data) + subroutine RetrieveParameter1D(this, name, data) use abortutils, only : endrun @@ -182,7 +182,7 @@ subroutine RetreiveParameter1D(this, name, data) i = this%FindIndex(name) if (size(data) /= size(this%parameters(i)%data(:, 1))) then - write(fates_log(), *) 'ERROR : retreiveparameter1d : ', name, ' size inconsistent.' + write(fates_log(), *) 'ERROR : RetrieveParameter1d : ', name, ' size inconsistent.' write(fates_log(), *) 'ERROR : expected size = ', size(data) write(fates_log(), *) 'ERROR : data size received from file = ', size(this%parameters(i)%data(:, 1)) write(fates_log(), *) 'ERROR : dimesions received from file' @@ -194,10 +194,10 @@ subroutine RetreiveParameter1D(this, name, data) end if data = this%parameters(i)%data(:, 1) - end subroutine RetreiveParameter1D + end subroutine RetrieveParameter1D !----------------------------------------------------------------------- - subroutine RetreiveParameter2D(this, name, data) + subroutine RetrieveParameter2D(this, name, data) use abortutils, only : endrun @@ -212,7 +212,7 @@ subroutine RetreiveParameter2D(this, name, data) i = this%FindIndex(name) if (size(data, 1) /= size(this%parameters(i)%data, 1) .and. & size(data, 2) /= size(this%parameters(i)%data, 2)) then - write(fates_log(), *) 'ERROR : retreiveparameter2d : ', name, ' size inconsistent.' + write(fates_log(), *) 'ERROR : RetrieveParameter2d : ', name, ' size inconsistent.' write(fates_log(), *) 'ERROR : expected shape = ', shape(data) write(fates_log(), *) 'ERROR : dim 1 expected size = ', size(data, 1) write(fates_log(), *) 'ERROR : dim 2 expected size = ', size(data, 2) @@ -227,10 +227,10 @@ subroutine RetreiveParameter2D(this, name, data) end if data = this%parameters(i)%data - end subroutine RetreiveParameter2D + end subroutine RetrieveParameter2D !----------------------------------------------------------------------- - subroutine RetreiveParameter1DAllocate(this, name, data) + subroutine RetrieveParameter1DAllocate(this, name, data) use abortutils, only : endrun @@ -248,10 +248,10 @@ subroutine RetreiveParameter1DAllocate(this, name, data) allocate(data(lower_bound:upper_bound)) data(lower_bound:upper_bound) = this%parameters(i)%data(:, 1) - end subroutine RetreiveParameter1DAllocate + end subroutine RetrieveParameter1DAllocate !----------------------------------------------------------------------- - subroutine RetreiveParameter2DAllocate(this, name, data) + subroutine RetrieveParameter2DAllocate(this, name, data) use abortutils, only : endrun @@ -271,7 +271,7 @@ subroutine RetreiveParameter2DAllocate(this, name, data) allocate(data(lb_1:ub_1, lb_2:ub_2)) data(lb_1:ub_1, lb_2:ub_2) = this%parameters(i)%data - end subroutine RetreiveParameter2DAllocate + end subroutine RetrieveParameter2DAllocate !----------------------------------------------------------------------- function FindIndex(this, name) result(i) diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index 208ff848fb..a88bb2c570 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -127,7 +127,7 @@ subroutine PRTReceiveOrgan(fates_params) real(r8), allocatable :: tmpreal(:) ! Temporary variable to hold floats name = 'fates_prt_organ_id' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=tmpreal) allocate(prt_params%organ_id(size(tmpreal,dim=1))) call ArrayNint(tmpreal,prt_params%organ_id) @@ -391,232 +391,232 @@ subroutine PRTReceivePFT(fates_params) ! that are converted to ints name = 'fates_phen_stress_decid' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=tmpreal) allocate(prt_params%stress_decid(size(tmpreal,dim=1))) call ArrayNint(tmpreal,prt_params%stress_decid) deallocate(tmpreal) name = 'fates_phen_season_decid' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=tmpreal) allocate(prt_params%season_decid(size(tmpreal,dim=1))) call ArrayNint(tmpreal,prt_params%season_decid) deallocate(tmpreal) name = 'fates_phen_evergreen' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=tmpreal) allocate(prt_params%evergreen(size(tmpreal,dim=1))) call ArrayNint(tmpreal,prt_params%evergreen) deallocate(tmpreal) name = 'fates_leaf_slamax' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%slamax) name = 'fates_leaf_slatop' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%slatop) name = 'fates_allom_sai_scaler' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_sai_scaler) name = 'fates_fnrt_prof_a' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%fnrt_prof_a) name = 'fates_fnrt_prof_b' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%fnrt_prof_b) name = 'fates_fnrt_prof_mode' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%fnrt_prof_mode) name = 'fates_fire_crown_depth_frac' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%crown) name = 'fates_woody' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%woody) name = 'fates_wood_density' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%wood_density) name = 'fates_seed_dbh_repro_threshold' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%dbh_repro_threshold) name = 'fates_alloc_storage_cushion' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%cushion) name = 'fates_leaf_stor_priority' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%leaf_stor_priority) name = 'fates_senleaf_long_fdrought' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%senleaf_long_fdrought) name = 'fates_root_long' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%root_long) name = 'fates_seed_alloc_mature' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%seed_alloc_mature) name = 'fates_seed_alloc' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%seed_alloc) name = 'fates_c2b' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%c2b) name = 'fates_grperc' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%grperc) name = 'fates_allom_dbh_maxheight' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_dbh_maxheight) name = 'fates_allom_hmode' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_hmode) name = 'fates_allom_lmode' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_lmode) name = 'fates_allom_fmode' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_fmode) name = 'fates_allom_amode' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_amode) name = 'fates_allom_stmode' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_stmode) name = 'fates_allom_cmode' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_cmode) name = 'fates_allom_smode' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_smode) name = 'fates_allom_la_per_sa_int' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_la_per_sa_int) name = 'fates_allom_la_per_sa_slp' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_la_per_sa_slp) name = 'fates_allom_l2fr' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_l2fr) name = 'fates_allom_agb_frac' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_agb_frac) name = 'fates_allom_d2h1' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_d2h1) name = 'fates_allom_d2h2' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_d2h2) name = 'fates_allom_d2h3' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_d2h3) name = 'fates_allom_d2bl1' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_d2bl1) name = 'fates_allom_d2bl2' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_d2bl2) name = 'fates_allom_d2bl3' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_d2bl3) name = 'fates_allom_blca_expnt_diff' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_blca_expnt_diff) name = 'fates_allom_d2ca_coefficient_max' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_d2ca_coefficient_max) name = 'fates_allom_d2ca_coefficient_min' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_d2ca_coefficient_min) name = 'fates_allom_agb1' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_agb1) name = 'fates_allom_agb2' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_agb2) name = 'fates_allom_agb3' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_agb3) name = 'fates_allom_agb4' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_agb4) name = 'fates_allom_zroot_max_dbh' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_zroot_max_dbh) name = 'fates_allom_zroot_max_z' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_zroot_max_z) name = 'fates_allom_zroot_min_dbh' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_zroot_min_dbh) name = 'fates_allom_zroot_min_z' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_zroot_min_z) name = 'fates_allom_zroot_k' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_zroot_k) name = 'fates_branch_turnover' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%branch_long) name = 'fates_turnover_retrans_mode' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%turnover_retrans_mode) name = 'fates_nitr_store_ratio' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%nitr_store_ratio) name = 'fates_phos_store_ratio' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%phos_store_ratio) @@ -703,7 +703,7 @@ subroutine Receive_PFT_nvariants(fates_params) character(len=param_string_length) :: name !X! name = '' - !X! call fates_params%RetreiveParameter(name=name, & + !X! call fates_params%RetrieveParameter(name=name, & !X! data=this%) end subroutine Receive_PFT_nvariants @@ -722,7 +722,7 @@ subroutine PRTReceivePFTLeafAge(fates_params) character(len=param_string_length) :: name name = 'fates_leaf_long' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%leaf_long) return @@ -799,35 +799,35 @@ subroutine PRTReceivePFTOrgans(fates_params) character(len=param_string_length) :: name name = 'fates_prt_nitr_stoich_p1' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%nitr_stoich_p1) name = 'fates_prt_nitr_stoich_p2' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%nitr_stoich_p2) name = 'fates_prt_phos_stoich_p1' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%phos_stoich_p1) name = 'fates_prt_phos_stoich_p2' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%phos_stoich_p2) name = 'fates_prt_alloc_priority' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%alloc_priority) name = 'fates_turnover_carb_retrans' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%turnover_carb_retrans) name = 'fates_turnover_nitr_retrans' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%turnover_nitr_retrans) name = 'fates_turnover_phos_retrans' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%turnover_phos_retrans) end subroutine PRTReceivePFTOrgans From b95ec13aef8d9bc6c25a14118247d288e1bd0d68 Mon Sep 17 00:00:00 2001 From: Marcos Longo Date: Tue, 3 May 2022 17:31:16 -0700 Subject: [PATCH 192/852] A few additional misspellings, all in commented lines. --- main/FatesSynchronizedParamsMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main/FatesSynchronizedParamsMod.F90 b/main/FatesSynchronizedParamsMod.F90 index 7f35b8eeec..8cbda3fdb1 100644 --- a/main/FatesSynchronizedParamsMod.F90 +++ b/main/FatesSynchronizedParamsMod.F90 @@ -126,11 +126,11 @@ subroutine ReceiveParamsScalar(this, fates_params) character(len=param_string_length) :: name ! name = 'q10_mr' -! call fates_params%RetreiveParameter(name=name, & +! call fates_params%RetrieveParameter(name=name, & ! data=this%Q10) ! name = 'froz_q10' -! call fates_params%RetreiveParameter(name=name, & +! call fates_params%RetrieveParameter(name=name, & ! data=this%froz_q10) end subroutine ReceiveParamsScalar From c7d048c66ea68886bcc81bdcd81d488302d1a947 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 5 May 2022 12:37:06 -0400 Subject: [PATCH 193/852] First version of the parameter API updater --- parameter_files/apichange_23to24.xml | 44 ++ parameter_files/fates_params_default.cdl | 522 ++++++++++------------- tools/UpdateParamAPI.py | 358 ++++++++++++++++ tools/ncvarsort.py | 28 +- 4 files changed, 645 insertions(+), 307 deletions(-) create mode 100644 parameter_files/apichange_23to24.xml create mode 100755 tools/UpdateParamAPI.py diff --git a/parameter_files/apichange_23to24.xml b/parameter_files/apichange_23to24.xml new file mode 100644 index 0000000000..4d54c947c8 --- /dev/null +++ b/parameter_files/apichange_23to24.xml @@ -0,0 +1,44 @@ + + + + + + + + + + fates_params_default.cdl + fates_params_default_api24.cdl + 1,2,3,4,5,6,7,8,9,10,11,12 + + + fates_history_damage_bins + 6 + + + fates_cnp_eca_alpha_ptase + + + fates_history_damage_bin_edges + fates_history_damage_bins + % crown loss + Lower edges for damage class bins used in cohort history output + damage + 0, 80, 100 + + + fates_damage_frac + fates_pft + fraction + fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine) + damage + 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 + + + diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 61f441e9d8..45e4a3509c 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1,11 +1,10 @@ -netcdf fates_params_default.c220425_sorted { +netcdf fates_params_default.c210629_sorted { dimensions: fates_NCWD = 4 ; fates_history_age_bins = 7 ; fates_history_height_bins = 6 ; fates_history_size_bins = 13 ; fates_history_coage_bins = 2 ; - fates_history_damage_bins = 3 ; fates_hydr_organs = 4 ; fates_leafage_class = 1 ; fates_litterclass = 6 ; @@ -23,9 +22,6 @@ variables: double fates_history_height_bin_edges(fates_history_height_bins) ; fates_history_height_bin_edges:units = "m" ; fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; - double fates_history_damage_bin_edges(fates_history_damage_bins) ; - fates_history_damage_bin_edges:units = "% crown loss" ; - fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; fates_history_sizeclass_bin_edges:units = "cm" ; fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; @@ -117,7 +113,7 @@ variables: fates_allom_hmode:possible_values = "1: OBrien 1995; 2: Poorter 2006; 3: 2 parameter power law; 4: Chave 2014; 5: Martinez-Cano 2019." ; double fates_allom_l2fr(fates_pft) ; fates_allom_l2fr:units = "gC/gC" ; - fates_allom_l2fr:long_name = "target fine root C per leaf C. for C-only: constant, for CNP: recruit initial value" ; + fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; double fates_allom_la_per_sa_int(fates_pft) ; fates_allom_la_per_sa_int:units = "m2/cm2" ; fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; @@ -160,87 +156,54 @@ variables: double fates_c2b(fates_pft) ; fates_c2b:units = "ratio" ; fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; - double fates_cnp_eca_alpha_ptase(fates_pft) ; - fates_cnp_eca_alpha_ptase:units = "g/m3" ; - fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; - double fates_cnp_eca_decompmicc(fates_pft) ; - fates_cnp_eca_decompmicc:units = "gC/m3" ; - fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; - double fates_cnp_eca_km_nh4(fates_pft) ; - fates_cnp_eca_km_nh4:units = "gN/m3" ; - fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; - double fates_cnp_eca_km_no3(fates_pft) ; - fates_cnp_eca_km_no3:units = "gN/m3" ; - fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; - double fates_cnp_eca_km_p(fates_pft) ; - fates_cnp_eca_km_p:units = "gP/m3" ; - fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; - double fates_cnp_eca_km_ptase(fates_pft) ; - fates_cnp_eca_km_ptase:units = "gP/m3" ; - fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; - double fates_cnp_eca_lambda_ptase(fates_pft) ; - fates_cnp_eca_lambda_ptase:units = "g/m3" ; - fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; - double fates_cnp_eca_vmax_ptase(fates_pft) ; - fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; - fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; - double fates_cnp_fnrt_adapt_tscale(fates_pft) ; - fates_cnp_fnrt_adapt_tscale:units = "days" ; - fates_cnp_fnrt_adapt_tscale:long_name = "Number of days that is the shortest possible doubling period for fine-root adaptation (CNP only)" ; - double fates_cnp_nfix1(fates_pft) ; - fates_cnp_nfix1:units = "NA" ; - fates_cnp_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; - double fates_cnp_nfix2(fates_pft) ; - fates_cnp_nfix2:units = "NA" ; - fates_cnp_nfix2:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; - double fates_cnp_nitr_store_ratio(fates_pft) ; - fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; - fates_cnp_nitr_store_ratio:long_name = "ratio of storeable N, to functional N bound in cell structures of leaf,root,sap" ; - double fates_cnp_phos_store_ratio(fates_pft) ; - fates_cnp_phos_store_ratio:units = "(gP/gP)" ; - fates_cnp_phos_store_ratio:long_name = "ratio of storeable P, to functional P bound in cell structures of leaf,root,sap" ; - double fates_cnp_prescribed_nuptake(fates_pft) ; - fates_cnp_prescribed_nuptake:units = "fraction" ; - fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; - double fates_cnp_prescribed_puptake(fates_pft) ; - fates_cnp_prescribed_puptake:units = "fraction" ; - fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; - double fates_cnp_vmax_nh4(fates_pft) ; - fates_cnp_vmax_nh4:units = "gN/gC/s" ; - fates_cnp_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA & RD)" ; - double fates_cnp_vmax_no3(fates_pft) ; - fates_cnp_vmax_no3:units = "gN/gC/s" ; - fates_cnp_vmax_no3:long_name = "maximum production rate for plant no3 uptake (ECA & RD)" ; - double fates_cnp_vmax_p(fates_pft) ; - fates_cnp_vmax_p:units = "gP/gC/s" ; - fates_cnp_vmax_p:long_name = "maximum production rate for plant p uptake (ECA & RD)" ; - double fates_crown_depth_frac(fates_pft) ; - fates_crown_depth_frac:units = "fraction" ; - fates_crown_depth_frac:long_name = "the depth of a cohorts crown as a fraction of its height" ; - double fates_damage_frac(fates_pft) ; - fates_damage_frac:units = "fraction" ; - fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; - double fates_damage_mort_p1(fates_pft) ; - fates_damage_mort_p1:units = "fraction crown loss - a value of 0.8 means 50% mortality with 80% loss of crown" ; - fates_damage_mort_p1:long_name = "inflection point of damage mortality function - to turn off damage mortality set this to a large number" ; - double fates_damage_mort_p2(fates_pft) ; - fates_damage_mort_p2:units = "unitless" ; - fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; - double fates_damage_recovery_scalar(fates_pft) ; - fates_damage_recovery_scalar:units = "unitless" ; - fates_damage_recovery_scalar:long_name = "fraction of cohort that recovers from damage" ; 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" ; double fates_displar(fates_pft) ; fates_displar:units = "unitless" ; fates_displar:long_name = "Ratio of displacement height to canopy top height" ; + double fates_eca_alpha_ptase(fates_pft) ; + fates_eca_alpha_ptase:units = "g/m3" ; + fates_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; + double fates_eca_decompmicc(fates_pft) ; + fates_eca_decompmicc:units = "gC/m3" ; + fates_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; + double fates_eca_km_nh4(fates_pft) ; + fates_eca_km_nh4:units = "gN/m3" ; + fates_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; + double fates_eca_km_no3(fates_pft) ; + fates_eca_km_no3:units = "gN/m3" ; + fates_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; + double fates_eca_km_p(fates_pft) ; + fates_eca_km_p:units = "gP/m3" ; + fates_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; + double fates_eca_km_ptase(fates_pft) ; + fates_eca_km_ptase:units = "gP/m3" ; + fates_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; + double fates_eca_lambda_ptase(fates_pft) ; + fates_eca_lambda_ptase:units = "g/m3" ; + fates_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; + double fates_eca_vmax_nh4(fates_pft) ; + fates_eca_vmax_nh4:units = "gN/gC/s" ; + fates_eca_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA)" ; + double fates_eca_vmax_no3(fates_pft) ; + fates_eca_vmax_no3:units = "gN/gC/s" ; + fates_eca_vmax_no3:long_name = "maximum production rate for plant no3 uptake (ECA)" ; + double fates_eca_vmax_p(fates_pft) ; + fates_eca_vmax_p:units = "gP/gC/s" ; + fates_eca_vmax_p:long_name = "maximum production rate for plant p uptake (ECA)" ; + double fates_eca_vmax_ptase(fates_pft) ; + fates_eca_vmax_ptase:units = "gP/m2/s" ; + fates_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; double fates_fire_alpha_SH(fates_pft) ; fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; double fates_fire_bark_scaler(fates_pft) ; fates_fire_bark_scaler:units = "fraction" ; fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; + double fates_fire_crown_depth_frac(fates_pft) ; + fates_fire_crown_depth_frac:units = "fraction" ; + fates_fire_crown_depth_frac:long_name = "the depth of a cohorts crown as a fraction of its height" ; double fates_fire_crown_kill(fates_pft) ; fates_fire_crown_kill:units = "NA" ; fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; @@ -425,15 +388,21 @@ variables: double fates_mort_scalar_hydrfailure(fates_pft) ; fates_mort_scalar_hydrfailure:units = "1/yr" ; fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; + double fates_nfix1(fates_pft) ; + fates_nfix1:units = "NA" ; + fates_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; + double fates_nfix2(fates_pft) ; + fates_nfix2:units = "NA" ; + fates_nfix2:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; + double fates_nitr_store_ratio(fates_pft) ; + fates_nitr_store_ratio:units = "(gN/gN)" ; + fates_nitr_store_ratio:long_name = "ratio of storeable N, to functional N bound in cell structures of leaf,root,sap" ; double fates_phen_cold_size_threshold(fates_pft) ; fates_phen_cold_size_threshold:units = "cm" ; fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; double fates_phen_evergreen(fates_pft) ; fates_phen_evergreen:units = "logical flag" ; fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; - double fates_phen_fnrt_drop_fraction(fates_pft) ; - fates_phen_fnrt_drop_fraction:units = "fraction" ; - fates_phen_fnrt_drop_fraction:long_name = "fraction of fine roots to drop during drought/cold" ; double fates_phen_season_decid(fates_pft) ; fates_phen_season_decid:units = "logical flag" ; fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; @@ -446,6 +415,9 @@ variables: double fates_phenflush_fraction(fates_pft) ; fates_phenflush_fraction:units = "fraction" ; fates_phenflush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; + double fates_phos_store_ratio(fates_pft) ; + fates_phos_store_ratio:units = "(gP/gP)" ; + fates_phos_store_ratio:long_name = "ratio of storeable P, to functional P bound in cell structures of leaf,root,sap" ; double fates_prescribed_mortality_canopy(fates_pft) ; fates_prescribed_mortality_canopy:units = "1/yr" ; fates_prescribed_mortality_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; @@ -458,6 +430,12 @@ variables: double fates_prescribed_npp_understory(fates_pft) ; fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; + double fates_prescribed_nuptake(fates_pft) ; + fates_prescribed_nuptake:units = "fraction" ; + fates_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; + double fates_prescribed_puptake(fates_pft) ; + fates_prescribed_puptake:units = "fraction" ; + fates_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; double fates_prescribed_recruitment(fates_pft) ; fates_prescribed_recruitment:units = "n/yr" ; fates_prescribed_recruitment:long_name = "recruitment rate for prescribed physiology mode" ; @@ -564,9 +542,9 @@ variables: double fates_z0mr(fates_pft) ; fates_z0mr:units = "unitless" ; fates_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; - double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; - fates_hlm_pft_map:units = "area fraction" ; - fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; double fates_fire_FBD(fates_litterclass) ; fates_fire_FBD:units = "kg Biomass/m3" ; fates_fire_FBD:long_name = "fuel bulk density" ; @@ -603,9 +581,6 @@ variables: 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" ; - double fates_cnp_eca_plant_escalar ; - fates_cnp_eca_plant_escalar:units = "" ; - fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; double fates_cohort_age_fusion_tol ; fates_cohort_age_fusion_tol:units = "unitless" ; fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; @@ -624,6 +599,9 @@ variables: double fates_dev_arbitrary ; fates_dev_arbitrary:units = "unknown" ; fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; + double fates_eca_plant_escalar ; + fates_eca_plant_escalar:units = "" ; + fates_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; double fates_fire_active_crown_fire ; fates_fire_active_crown_fire:units = "0 or 1" ; fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; @@ -678,9 +656,6 @@ variables: double fates_hydr_psicap ; fates_hydr_psicap:units = "MPa" ; fates_hydr_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; - double fates_hydr_solver ; - fates_hydr_solver:units = "unitless" ; - fates_hydr_solver:long_name = "switch designating which numerical solver for plant hydraulics, 1 = 1D taylor, 2 = 2D Picard" ; double fates_init_litter ; fates_init_litter:units = "NA" ; fates_init_litter:long_name = "Initialization value for litter pool in cold-start (NOT USED)" ; @@ -717,12 +692,6 @@ variables: double fates_maintresp_model ; fates_maintresp_model:units = "unitless" ; fates_maintresp_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991) (NOT USED)" ; - double fates_maxpatch_primary ; - fates_maxpatch_primary:units = "unitless" ; - fates_maxpatch_primary:long_name = "maximum number of primary vegetation patches per site" ; - double fates_maxpatch_secondary ; - fates_maxpatch_secondary:units = "unitless" ; - fates_maxpatch_secondary:long_name = "maximum number of secondary vegetation patches per site" ; double fates_mort_disturb_frac ; fates_mort_disturb_frac:units = "fraction" ; fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; @@ -750,18 +719,12 @@ variables: double fates_phen_doff_time ; fates_phen_doff_time:units = "days" ; fates_phen_doff_time:long_name = "day threshold compared against days since leaves became off-allometry" ; - double fates_phen_drought_model ; - fates_phen_drought_model:units = "none" ; - fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; double fates_phen_drought_threshold ; - fates_phen_drought_threshold:units = "m3/m3 or mm" ; - fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)." ; + fates_phen_drought_threshold:units = "m3/m3" ; + fates_phen_drought_threshold:long_name = "liquid volume in soil layer, threashold for drought phenology" ; double fates_phen_mindayson ; fates_phen_mindayson:units = "days" ; fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; - double fates_phen_moist_threshold ; - fates_phen_moist_threshold:units = "m3/m3 or mm" ; - fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)." ; double fates_phen_ncolddayslim ; fates_phen_ncolddayslim:units = "days" ; fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; @@ -771,9 +734,6 @@ variables: double fates_photo_tempsens_model ; fates_photo_tempsens_model:units = "unitless" ; fates_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; - double fates_pprodharv10_forest_mean ; - fates_pprodharv10_forest_mean:units = "fraction" ; - fates_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types." ; double fates_q10_froz ; fates_q10_froz:units = "unitless" ; fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; @@ -783,9 +743,6 @@ variables: double fates_soil_salinity ; fates_soil_salinity:units = "ppt" ; fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; - double fates_stomatal_assim ; - fates_stomatal_assim:units = "unitless" ; - fates_stomatal_assim:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; double fates_theta_cj_c3 ; fates_theta_cj_c3:units = "unitless" ; fates_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; @@ -794,10 +751,10 @@ variables: fates_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; double fates_vai_top_bin_width ; fates_vai_top_bin_width:units = "m2/m2" ; - fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; + fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer (NOT USED)" ; double fates_vai_width_increase_factor ; fates_vai_width_increase_factor:units = "unitless" ; - fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; + fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing) (NOT USED)" ; // global attributes: :history = "This parameter file is maintained in version control\nSee https://github.com/NGEET/fates/blob/master/parameter_files/fates_params_default.cdl \nFor changes, use git blame \n" ; @@ -809,9 +766,7 @@ data: fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; - fates_history_damage_bin_edges = 0, 80, 100 ; - - fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, + fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100 ; fates_hydr_htftype_node = 1, 1, 1, 1 ; @@ -852,22 +807,22 @@ data: "sapwood ", "structure " ; - fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 ; - fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, + fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; - fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, + fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572 ; - fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, + fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94 ; - fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, + fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931 ; - fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6 ; fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -876,30 +831,30 @@ data: fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07 ; - fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, + fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3 ; - fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, + fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55 ; - fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, + fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464 ; - fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, + fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119 ; - fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, + fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64 ; - fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, + fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37 ; - fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, + fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 ; fates_allom_dbh_maxheight = 90, 90, 90, 90, 90, 90, 3, 3, 2, 0.35, 0.35, 0.35 ; @@ -912,14 +867,14 @@ data: fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 ; fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -930,92 +885,64 @@ data: fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; - fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 ; - fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, + fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; - fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 ; fates_branch_turnover = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; - fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5 ; + fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, + 0.67, 0.67 ; + + fates_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; - fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + fates_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280 ; - fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, + fates_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14 ; - fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, + fates_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27 ; - fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1 ; - - fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, - 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - - fates_cnp_fnrt_adapt_tscale = 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100, 100 ; - - fates_cnp_nfix1 = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_cnp_nfix2 = _, _, _, _, _, _, _, _, _, _, _, _ ; + fates_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; - fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5, 1.5 ; + fates_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5, 1.5 ; + fates_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_vmax_nh4 = 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, + fates_eca_vmax_nh4 = 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07 ; - fates_cnp_vmax_no3 = 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, + fates_eca_vmax_no3 = 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08 ; - fates_cnp_vmax_p = 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, + fates_eca_vmax_p = 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09 ; - fates_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, 0.95, 1, - 1, 1 ; - - fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, - 0.01, 0.01, 0.01 ; - - fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; - - fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, - 5.5, 5.5 ; - - fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, - 0.67, 0.67 ; + fates_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 ; - fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07 ; - fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, + fates_fire_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, + 0.95, 1, 1, 1 ; + + fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775 ; fates_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; @@ -1026,16 +953,16 @@ data: fates_fr_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_fr_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + fates_fr_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25 ; - fates_fr_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + fates_fr_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25 ; - fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, + fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - fates_hydr_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + fates_hydr_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5 ; fates_hydr_avuln_node = @@ -1064,34 +991,34 @@ data: -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; - fates_hydr_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + fates_hydr_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5 ; fates_hydr_p50_node = - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25 ; - fates_hydr_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, + fates_hydr_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333 ; fates_hydr_pinot_node = - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; fates_hydr_pitlp_node = - -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, @@ -1103,10 +1030,10 @@ data: 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - fates_hydr_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + fates_hydr_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625 ; - fates_hydr_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, + fates_hydr_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; fates_hydr_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; @@ -1118,13 +1045,13 @@ data: 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; fates_hydr_vg_alpha_node = - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005 ; fates_hydr_vg_m_node = @@ -1141,79 +1068,79 @@ data: fates_leaf_c3psn = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ; - fates_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, + fates_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, 0.9, 0.75, 0.75, 0.75 ; - fates_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, + fates_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04 ; - fates_leaf_jmaxha = 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, + fates_leaf_jmaxha = 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540 ; - fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, + fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040 ; - fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, + fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495 ; fates_leaf_long = 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, + fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, 0.03, 0.03, 0.03, 0.03, 0.03 ; - fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, + fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, 0.03, 0.03, 0.03, 0.03 ; - fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, + fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 40000 ; fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, + fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, 4.7, 2.2, 5.3, 1.6 ; - fates_leaf_stor_priority = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + fates_leaf_stor_priority = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 ; fates_leaf_vcmax25top = 50, 65, 39, 62, 41, 58, 62, 54, 54, 78, 78, 78 ; - fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, + fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330 ; - fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, + fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250 ; - fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, + fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485 ; - fates_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, -0.23, + fates_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, -0.23, -0.23, -0.23 ; fates_lf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_lf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + fates_lf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25 ; - fates_lf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + fates_lf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25 ; - fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, + fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014 ; - fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -60, -10, -80, -80, + fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -60, -10, -80, -80, -20, 2.5 ; - fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, + fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; @@ -1226,18 +1153,23 @@ data: fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6 ; - fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6 ; + fates_nfix1 = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_nfix2 = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5 ; + fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; - fates_phen_fnrt_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; @@ -1246,19 +1178,26 @@ data: fates_phenflush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_prescribed_mortality_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, + fates_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5 ; + + fates_prescribed_mortality_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; - fates_prescribed_mortality_understory = 0.025, 0.025, 0.025, 0.025, 0.025, + fates_prescribed_mortality_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; - fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, + fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4 ; - fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, + fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; - fates_prescribed_recruitment = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, + fates_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_prescribed_recruitment = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02 ; fates_prt_alloc_priority = @@ -1269,58 +1208,57 @@ data: fates_prt_nitr_stoich_p1 = 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047 ; fates_prt_nitr_stoich_p2 = 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047 ; fates_prt_phos_stoich_p1 = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047 ; fates_prt_phos_stoich_p2 = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047 ; - fates_recruit_hgt_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, + fates_recruit_hgt_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, 0.125, 0.125, 0.125 ; - fates_recruit_initd = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + fates_recruit_initd = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 ; - fates_rholnir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, 0.41, 0.28, + fates_rholnir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, 0.41, 0.28, 0.28, 0.28 ; - fates_rholvis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, 0.08, 0.05, - 0.05, 0.05 ; + fates_rholvis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, 0.08, 0.05, 0.05, 0.05 ; - fates_rhosnir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, 0.49, 0.53, + fates_rhosnir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, 0.49, 0.53, 0.53, 0.53 ; - fates_rhosvis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.31, + fates_rhosvis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.31, 0.31, 0.31 ; fates_root_long = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; @@ -1329,38 +1267,38 @@ data: fates_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9 ; - fates_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, 1.47, + fates_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, 1.47, 1.47, 1.47 ; - fates_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, + fates_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51 ; - fates_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + fates_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; fates_seed_suppl = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_senleaf_long_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, -255000, + fates_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, -255000, -255000, -255000, -255000, -255000, -255000 ; - fates_smpso = -66000, -66000, -66000, -66000, -66000, -66000, -66000, + fates_smpso = -66000, -66000, -66000, -66000, -66000, -66000, -66000, -66000, -66000, -66000, -66000, -66000 ; - fates_taulnir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, 0.43, 0.4, + fates_taulnir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, 0.43, 0.4, 0.4, 0.4 ; - fates_taulvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.05, + fates_taulvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.05, 0.05, 0.05 ; - fates_tausnir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + fates_tausnir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.25, 0.25, 0.25 ; - fates_tausvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + fates_tausvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.12, 0.12, 0.12 ; - fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, + fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03 ; fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; @@ -1385,29 +1323,29 @@ data: fates_turnover_retrans_mode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, + fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7 ; fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; - fates_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, + fates_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055 ; fates_hlm_pft_map = - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; @@ -1433,8 +1371,6 @@ data: fates_canopy_closure_thresh = 0.8 ; - fates_cnp_eca_plant_escalar = 1.25e-05 ; - fates_cohort_age_fusion_tol = 0.08 ; fates_cohort_size_fusion_tol = 0.08 ; @@ -1447,6 +1383,8 @@ data: fates_dev_arbitrary = _ ; + fates_eca_plant_escalar = 1.25e-05 ; + fates_fire_active_crown_fire = 0 ; fates_fire_cg_strikes = 0.2 ; @@ -1483,8 +1421,6 @@ data: fates_hydr_psicap = -0.6 ; - fates_hydr_solver = 1 ; - fates_init_litter = 0.05 ; fates_leaf_stomatal_model = 1 ; @@ -1509,10 +1445,6 @@ data: fates_maintresp_model = 1 ; - fates_maxpatch_primary = 10 ; - - fates_maxpatch_secondary = 4 ; - fates_mort_disturb_frac = 1 ; fates_mort_understorey_death = 0.55983 ; @@ -1531,30 +1463,22 @@ data: fates_phen_doff_time = 100 ; - fates_phen_drought_model = 0 ; - fates_phen_drought_threshold = 0.15 ; fates_phen_mindayson = 90 ; - fates_phen_moist_threshold = 0.18 ; - fates_phen_ncolddayslim = 5 ; fates_photo_temp_acclim_timescale = 30 ; fates_photo_tempsens_model = 1 ; - fates_pprodharv10_forest_mean = 0.8125 ; - fates_q10_froz = 1.5 ; fates_q10_mr = 1.5 ; fates_soil_salinity = 0.4 ; - fates_stomatal_assim = 1 ; - fates_theta_cj_c3 = 0.999 ; fates_theta_cj_c4 = 0.999 ; diff --git a/tools/UpdateParamAPI.py b/tools/UpdateParamAPI.py new file mode 100755 index 0000000000..91272bb20d --- /dev/null +++ b/tools/UpdateParamAPI.py @@ -0,0 +1,358 @@ +#!/usr/bin/env python + +# ======================================================================================= +# This script modifies any FATES parameter file to update it to a new API spec. +# It can change variable names +# It can add new variables +# It can add attributes +# It can update attributes +# It can add new dimensions +# ======================================================================================= + +import os +import argparse +import code # For development: code.interact(local=dict(globals(), **locals())) +from scipy.io import netcdf +import xml.etree.ElementTree as et + +# ======================================================================================= + +def load_xml(xmlfile): + + # This routine parses the XML tree + + xmlroot = et.parse(xmlfile).getroot() + print("\nOpened: {}\n".format(xmlfile)) + + base_cdl = xmlroot.find('base_file').text + new_cdl = xmlroot.find('new_file').text + + pft_list = xmlroot.find('pft_list').text.replace(" ","") + + modroot = xmlroot.find('mods') + + return(base_cdl,new_cdl,pft_list,modroot) + +# ======================================================================================= + +def str2fvec(numstr): + + # Convert a list of strings into floating point numbers + + numvec = [float(i) for i in numstr.split(',')] + return(numvec) + +# ======================================================================================= + +def str2ivec(numstr): + + # Convert a list of strings into integer numbers + + intvec = [int(i) for i in numstr.split(',')] + return(intvec) + +# ======================================================================================= + +def createvar(ncfile,paramname,dimnames,units,longname,usecase,sel_values): + + # Create a new netcdf variable inside an existing netcdf dataset (append) + + ncvar = ncfile.createVariable(paramname,'d',dimnames) + ncvar.units = units + ncvar.long_name = longname + ncvar.use_case = usecase + ncvar[:] = sel_values + ncfile.flush() + + return(ncfile,ncvar) + +# ======================================================================================= + +def selectvalues(ncfile,dimnames,ipft_list,values): + + # Reduce a list of values so that onlythe chosen pft values are left. This + # only works on float arrays currently. We need to pass in a file + # so that we can get the dimension sizes associated with the dimension names. + + if(len(ipft_list) != ncfile.dimensions['fates_pft']): + print('you list of pfts in the xml file must be') + print('the same size as the fates_pft dimension') + print('in your destination file. exiting') + print('len(ipft_list) = {}'.format(len(ipft_list))) + print('fates_pft dim = {}'.format(ncfile.dimensions['fates_pft'])) + exit(2) + + pft_dim = -1 + dim2_size = 1 + for idim,name in enumerate(list(dimnames)): + if(name=='fates_pft'): + pft_dim = idim + pft_dim_size = ncfile.dimensions['fates_pft'] + else: + dim2_size = ncfile.dimensions[name] + + sel_values = [] + if(pft_dim==0): + for j in range(dim2_size): + i0 = j*pft_dim_size + for i in ipft_list: + sel_values.append(values[i-1+i0]) + elif(pft_dim==1): + for i in ipft_list: + i0 = i*dim2_size + for j in range(dim2_size): + sel_values.append(values[j-1+i0]) + else: + sel_values = values + + return(sel_values) + +# ======================================================================================= + +def removevar(base_nc,varname): + + # Remove a variable from a dataset. This is actually the hardest thing to do! + # The trick here, is to copy the whole file, minus the variable of interest + # into a temp file. Then completely remove the old file, and + + fp_base = netcdf.netcdf_file(base_nc, 'r',mmap=False) + + new_nc = os.popen('mktemp').read().rstrip('\n') + fp_new = netcdf.netcdf_file(new_nc, 'w',mmap=False) + + for key, value in sorted(fp_base.dimensions.items()): + fp_new.createDimension(key,int(value)) + + found = False + for key, value in fp_base.variables.items(): + + if(key == varname): + found = True + else: + datatype = value.typecode() + new_var = fp_new.createVariable(key,datatype,value.dimensions) + if(value.data.size == 1): + new_var.assignValue(float(value.data)) + else: + new_var[:] = value[:].copy() + + new_var.units = value.units + new_var.long_name = value.long_name + try: + new_var.use_case = value.use_case + except: + new_var.use_case = "undefined" + + fp_new.history = fp_base.history + + if(not found): + print("was not able to find variable: ()".format(varname)) + exit(2) + + fp_new.flush() + fp_base.close() + fp_new.close() + + mvcmd = "(rm -f "+base_nc+";mv "+new_nc+" "+base_nc+")" + os.system(mvcmd) + + +# ======================================================================================= + +def main(): + + # Parse arguments + parser = argparse.ArgumentParser(description='Parse command line arguments to this script.') + parser.add_argument('--f', dest='xmlfile', type=str, help="XML control file Required.", required=True) + args = parser.parse_args() + + + # Load the xml file, which contains the base cdl, the output cdl, + # and the parameters to be modified + [base_cdl,new_cdl,pft_list,modroot] = load_xml(args.xmlfile) + + ipft_list = str2ivec(pft_list) + + + # Convert the base cdl file into a temp nc binary + base_nc = os.popen('mktemp').read().rstrip('\n') + gencmd = "ncgen -o "+base_nc+" "+base_cdl + os.system(gencmd) + + modlist = [] + for mod in modroot: + if(not('type' in mod.attrib.keys())): + print("mod tag must have attribute type") + print("exiting") + exit(2) + + if(mod.attrib['type'].strip() == 'dimension_add'): + + try: + dimname = mod.find('di').text.strip() + except: + print("{}, no dimension (di), exiting".format(mod.attrib['type']));exit(2) + + try: + values = str2fvec(mod.find('val').text.strip()) + except: + print("no values (val), exiting");exit(2) + + if(len(values)>1): + print("The dimension size should be a scalar") + exit(2) + + ncfile = netcdf.netcdf_file(base_nc,"a",mmap=False) + ncfile.createDimension(dimname, values[0]) + ncfile.flush() + ncfile.close() + + print("dimension: {}, size: {}, added".format(dimname,values[0])) + + + elif(mod.attrib['type'].strip() == 'variable_add'): + + try: + paramname = mod.find('na').text.strip() + except: + print("no name (na), exiting");exit(2) + + try: + dimnames = tuple([mod.find('di').text.strip()]) + except: + print("no dimension (di), exiting");exit(2) + + try: + units = mod.find('un').text.strip() + except: + print("no units (un), exiting");exit(2) + + try: + longname = mod.find('ln').text.strip() + except: + print("no long-name (ln), exiting");exit(2) + + try: + usecase = mod.find('uc').text.strip() + except: + print("no use case (uc), exiting");exit(2) + + try: + values = str2fvec(mod.find('val').text.strip()) + except: + print("no values (val), exiting");exit(2) + + sel_values = selectvalues(ncfile,list(dimnames),ipft_list,values) + + ncfile = netcdf.netcdf_file(base_nc,"a",mmap=False) + [ncfile,ncvar] = createvar(ncfile,paramname,dimnames,units,longname,usecase,sel_values) + ncfile.flush() + ncfile.close() + + print("parameter: {}, added".format(paramname)) + + + elif(mod.attrib['type'] == 'variable_del'): + try: + paramname = mod.attrib['name'] + except: + print('must define the parameter name to delete, using ') + exit(2) + removevar(base_nc,paramname) + print("parameter: {}, removed".format(paramname)) + + + elif(mod.attrib['type'] == 'variable_change'): + + try: + paramname_o = mod.attrib['name'].strip() + except: + print("to change a parameter, the field must have a name attribute") + exit(2) + + ncfile = netcdf.netcdf_file(base_nc,"a",mmap=False) + ncvar_o = ncfile.variables[paramname_o] + dims_o = ncvar_o.dimensions + units_o = ncvar_o.units.decode("utf-8") + longname_o = ncvar_o.long_name.decode("utf-8") + try: + usecase_o = ncvar_o.use_case.decode("utf-8") + except: + usecase_o = 'undefined' + + try: + paramname = mod.find('na').text.strip() + except: + paramname = None + + # Change the parameter's name + if(not isinstance(paramname,type(None))): + [ncfile,ncvar] = createvar(ncfile,paramname,dims_o,units_o,longname_o,usecase_o,ncvar_o[:].copy()) + else: + ncvar = ncvar_o + + # Change the metadata: + try: + units = mod.find('un').text.strip() + except: + units = None + if(not isinstance(units,type(None))): + ncvar.units = units + + try: + longname = mod.find('ln').text.strip() + except: + longname = None + if(not isinstance(longname,type(None))): + ncvar.long_name = longname + + try: + usecase = mod.find('uc').text.strip() + except: + usecase = None + if(not isinstance(usecase,type(None))): + ncvar.use_case = use_case + + try: + values = str2fvec(mod.find('val').text.strip()) + except: + values = None + + if(not isinstance(values,type(None))): + sel_values = selectvalues(ncfile,list(dims_o),ipft_list,values) + + # Scalars have their own thing + if(ncvar.data.size == 1): + ncvar.assignValue(float(sel_values[0])) + else: + ncvar[:] = sel_values[:] + + + ncfile.flush() + ncfile.close() + + # Finally, if we did perform a re-name, and + # created a new variable. We need to delete the + # old one + if(not isinstance(paramname,type(None))): + removevar(base_nc,paramname_o) + + print("parameter: {}, modified".format(paramname)) + + + # Sort the new file + new_nc = os.popen('mktemp').read().rstrip('\n') + os.system("../tools/ncvarsort.py --silent --fin "+base_nc+" --fout "+new_nc+" --overwrite") + + # Dump the new file to the cdl + os.system("ncdump "+new_nc+" > "+new_cdl) + + + + print("\nAPI update complete, see file: {}\n".format(new_cdl)) + + +# This is the actual call to main + +if __name__ == "__main__": + main() diff --git a/tools/ncvarsort.py b/tools/ncvarsort.py index 84b4212726..7f56ab62fa 100755 --- a/tools/ncvarsort.py +++ b/tools/ncvarsort.py @@ -20,6 +20,7 @@ def main(): parser.add_argument('--fout','--output', dest='fnameout', type=str, help="Output filename. Required.", required=True) parser.add_argument('--O','--overwrite', dest='overwrite', help="If present, automatically overwrite the output file.", action="store_true") parser.add_argument('--debug', dest='debug', help="If present, output more diagnostics", action="store_true") + parser.add_argument('--silent', dest='silent', help="If present, prevents printing messages", action="store_true") # args = parser.parse_args() # @@ -65,17 +66,28 @@ def main(): for i in range(len(varnames_list)): varnames_list[i] = sorted(varnames_list[i], key=lambda L: (L.lower(), L)) varnames_list_sorted.extend(varnames_list[i]) - # + + if args.silent: + verbose = False + else: + verbose = True + # write list of variables in ourput order if args.debug: - print(varnames_list_sorted) - # + if (not verbose): + print("cant run debug and silent in ncvarsort") + exit(2) + else: + print(varnames_list_sorted) + + + # open the output filename, deleting it if it exists already. if os.path.isfile(args.fnameout): if args.fnameout == args.fnamein: raise ValueError('Error: output file name is the same as the input file name.') elif args.overwrite: - print('replacing file: '+args.fnameout) + if (verbose): print('replacing file: '+args.fnameout) os.remove(args.fnameout) else: raise ValueError('Output file already exists and overwrite flag not specified for filename: '+args.fnameout) @@ -85,15 +97,15 @@ def main(): #Copy dimensions for dname, the_dim in dsin.dimensions.items(): if args.debug: - print(dname, the_dim.size) + if (verbose): print(dname, the_dim.size) dsout.createDimension(dname, the_dim.size ) # - print() + if (verbose): print() # try: dsout.history = dsin.history except: - print('no history!') + if (verbose): print('no history!') # # # go through each variable in the order of the sorted master list, and copy the variable @@ -103,7 +115,7 @@ def main(): varin = dsin.variables[v_name] outVar = dsout.createVariable(v_name, varin.datatype, varin.dimensions) if args.debug: - print(v_name) + if (verbose): print(v_name) # outVar.setncatts({k: varin.getncattr(k) for k in varin.ncattrs()}) outVar[:] = varin[:] From 32684f746213a9d7d3b512ac8658572b4ed3b748 Mon Sep 17 00:00:00 2001 From: Jacquelyn Shuman Date: Thu, 5 May 2022 16:46:49 -0600 Subject: [PATCH 194/852] Update wind calculation for crown_frac_burnt --- biogeochem/EDPatchDynamicsMod.F90 | 5 +++- fire/SFMainMod.F90 | 38 ++++++++++++++++--------------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 0236e91f08..6bd6153915 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -2123,7 +2123,8 @@ subroutine create_patch(currentSite, new_patch, age, areap, label,nocomp_pft) new_patch%fabi_sun_z(:,:,:) = 0._r8 new_patch%fabi_sha_z(:,:,:) = 0._r8 new_patch%scorch_ht(:) = 0._r8 - new_patch%frac_burnt = 0._r8 + new_patch%frac_burnt = 0._r8 + new_patch%canopy_bulk_density = 0._r8 new_patch%litter_moisture(:) = 0._r8 new_patch%fuel_eff_moist = 0._r8 new_patch%livegrass = 0._r8 @@ -2240,6 +2241,7 @@ subroutine zero_patch(cp_p) currentPatch%ros_back = nan ! backward ros (m/min) currentPatch%scorch_ht(:) = nan ! scorch height of flames on a given PFT currentPatch%frac_burnt = nan ! fraction burnt daily + currentPatch%canopy_bulk_density = nan ! available canopy fuel bulk density in patch (kg biomass/m3) currentPatch%burnt_frac_litter(:) = nan currentPatch%btran_ft(:) = 0.0_r8 @@ -2659,6 +2661,7 @@ subroutine fuse_2_patches(csite, dp, rp) rp%ros_back = (dp%ros_back*dp%area + rp%ros_back*rp%area) * inv_sum_area rp%scorch_ht(:) = (dp%scorch_ht(:)*dp%area + rp%scorch_ht(:)*rp%area) * inv_sum_area rp%frac_burnt = (dp%frac_burnt*dp%area + rp%frac_burnt*rp%area) * inv_sum_area + rp%canopy_bulk_density = (dp%canopy_bulk_density*dp%area + rp%canopy_bulk_density*rp%area) * inv_sum_area rp%burnt_frac_litter(:) = (dp%burnt_frac_litter(:)*dp%area + rp%burnt_frac_litter(:)*rp%area) * inv_sum_area rp%btran_ft(:) = (dp%btran_ft(:)*dp%area + rp%btran_ft(:)*rp%area) * inv_sum_area rp%zstar = (dp%zstar*dp%area + rp%zstar*rp%area) * inv_sum_area diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index af38d24ea3..79ebe87dfc 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -380,7 +380,6 @@ subroutine characteristics_of_crown ( currentSite, canopy_fuel_load, passive_cr real(r8) :: crown_fuel_biomass ! biomass of crown fuel in cohort (kg biomass) real(r8) :: crown_fuel_per_m ! crown fuel per 1m section in cohort real(r8) :: height_base_canopy ! lowest height of fuels in patch to carry fire in crown - real(r8) :: canopy_bulk_density ! density of canopy fuel on patch integer :: ih ! counter @@ -403,6 +402,7 @@ subroutine characteristics_of_crown ( currentSite, canopy_fuel_load, passive_cr height_base_canopy = 0.0_r8 canopy_fuel_load = 0.0_r8 passive_crown_FI = 0.0_r8 + currentPatch%canopy_bulk_density = 0.0_r8 ! if (currentPatch%active_crown_fire == 1) then @@ -472,8 +472,8 @@ subroutine characteristics_of_crown ( currentSite, canopy_fuel_load, passive_cr end if end do - !canopy_bulk_denisty (kg/m3) for Patch - canopy_bulk_density = sum(biom_matrix) / (max_height - height_base_canopy) + !canopy_bulk_density (kg/m3) for Patch + currentPatch%canopy_bulk_density = sum(biom_matrix) / (max_height - height_base_canopy) ! Note: crown_ignition_energy to be calculated based on PFT foliar moisture content from FATES-Hydro ! or create foliar moisture % based on BTRAN @@ -1092,9 +1092,9 @@ subroutine active_crown_fire ( currentSite, canopy_fuel_load, ROS_torch, & real(r8) size_of_fire ! in m2 real(r8) ROS_active ! actual rate of spread (m/min) using FM 10 fuels real(r8) ROS_active_min ! minimum rate of spread to ignite active crown fire - real(r8) phi_wind_ROS_SA ! phi_wind for ROS_active_min, use to find open wind for ROS_SA - real(r8) wind_ROS_SA ! open windspeed for ROS surface fire where ROS_SA = ROS_active_min - real(r8) ROS_SA ! rate of spread for surface fire with wind_ROS_SA + real(r8) CI_temp ! temporary variable to calculate wind_active_min + real(r8) wind_active_min ! open windspeed to sustain active crown fire where ROS_SA = ROS_active_min + real(r8) ROS_SA ! rate of spread for surface fire with wind_active_min real(r8) canopy_frac_burnt ! fraction of canopy fuels consumed (0, surface fire to 1,active crown fire) real(r8) ROS_final ! final rate of spread for combined surface and canopy spread (m/min) real(r8) FI_final ! final fireline intensity (kW/m or kJ/m/sec) with canopy consumption @@ -1168,7 +1168,7 @@ subroutine active_crown_fire ( currentSite, canopy_fuel_load, ROS_torch, & beta_ratio = beta/beta_op ! -- heat of pre-ignition -- - q_ig = q_dry + 2594.0 * fuel_eff_moist + q_ig = q_dry + 2594.0_r8 * fuel_eff_moist ! ---effective heating number--- ! Eq A3 in Thonicke et al. 2010. @@ -1215,14 +1215,15 @@ subroutine active_crown_fire ( currentSite, canopy_fuel_load, ROS_torch, & ir = reaction_v_opt*(net_fuel)*SF_val_fuel_energy*moist_damp*SF_val_miner_damp ! actual ROS (m/min) for FM 10 fuels for open windspeed, Eq 8 Scott & Reinhardt 2001 - ROS_active = 3.34*((ir*xi*(1.0_r8+phi_wind)) / (fuel_bd * eps * q_ig)) + ROS_active = 3.34_r8*((ir*xi*(1.0_r8+phi_wind)) / (fuel_bd * eps * q_ig)) ! critical min rate of spread (m/min) for active crowning - ROS_active_min = (critical_mass_flow_rate / fuel_bd) * 60.0 + ROS_active_min = (critical_mass_flow_rate / fuel_bd) * 60.0_r8 ! check threshold intensity and rate of spread if (currentPatch%FI >= passive_crown_FI .and. ROS_active >= ROS_active_min) then currentPatch%active_crown_fire_flg = 1 ! active crown fire ignited + !ROS_final = ROS_surface+CFB(ROS_active - ROS_surface), Eq 21 Scott & Reinhardt 2001 !with active crown fire CFB (canopy fraction burned) = 100% canopy_frac_burnt = 1.0_r8 @@ -1230,19 +1231,20 @@ subroutine active_crown_fire ( currentSite, canopy_fuel_load, ROS_torch, & else currentPatch%active_crown_fire_flg = 0 ! only passive crown fire with partial crown burnt - ! calculate canopy fraction burnt, Eq 28 Scott & Reinhardt App A - ! using wind at which ROS_active = ROS_active_min - ! solve for phi_wind associated with ROS_active_min - phi_wind_ROS_SA = (ROS_active_min * fuel_bd * eps * q_ig - 3.34 * ir * xi) & - /(3.34 * ir * xi) - ! solve for open wind for that phi_wind - wind_ROS_SA = log(b)*(phi_wind_ROS_SA/(c*beta_ratio**(-e)))/log(b)*(3.28*0.4) - ! use this phi_wind for potential surface ROS for canopy_frac_burnt calculation - ROS_SA = (ir * xi * (1.0_r8 + wind_ROS_SA)) / (fuel_bd * eps * q_ig) + + ! phi_slope is not used yet. consider adding with later development + ! calculate open wind speed critical to sustain active crown fire Eq 20 Scott & Reinhardt + CI_temp = ((164.8_r8 * eps * q_ig)/(ir * currentPatch%canopy_bulk_density)) - 1.0_r8 + + wind_active_min = 0.0457_r8 (CI_temp/0.001612_r8)**0.7_r8 + + ! use open wind speed "wind_active_min" for ROS surface fire where ROS_SA=ROS_active_min + ROS_SA = (ir * xi * (1.0_r8 + wind_active_min)) / (fuel_bd * eps * q_ig) ! canopy fraction burnt, Eq 28 Scott & Reinhardt Appendix A canopy_frac_burnt = (min(1.0_r8, ((currentPatch%ROS_front - ROS_active_min) & /(ROS_SA - ROS_active_min)))) + !ROS_final = ROS_surface+CFB(ROS_active - ROS_surface), Eq 21 Scott & Reinhardt 2001 ROS_final = currentPatch%ROS_front + canopy_frac_burnt*(ROS_active-currentPatch%ROS_front) From 7a1178f31b37a1475b30cde0dc58abc1cd6919ec Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 6 May 2022 12:07:59 -0400 Subject: [PATCH 195/852] CNP updates, small modifications to things like root trimming and limiters on growth. --- main/EDTypesMod.F90 | 4 +- main/FatesHistoryInterfaceMod.F90 | 34 ++++-- parteh/PRTAllometricCNPMod.F90 | 168 +++++++++++++++++++++--------- parteh/PRTGenericMod.F90 | 48 +++++++-- 4 files changed, 184 insertions(+), 70 deletions(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 4ae673d5aa..b76408c787 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -28,9 +28,9 @@ module EDTypesMod private ! By default everything is private save - integer, parameter, public :: maxPatchesPerSite = 6 ! maximum number of patches to live on a site + integer, parameter, public :: maxPatchesPerSite = 11 ! maximum number of patches to live on a site integer, parameter, public :: maxPatchesPerSite_by_disttype(n_anthro_disturbance_categories) = & - (/ 5, 1 /) !!! MUST SUM TO maxPatchesPerSite !!! + (/ 10, 1 /) !!! MUST SUM TO maxPatchesPerSite !!! integer, public :: maxCohortsPerPatch ! maximum number of cohorts per patch integer, parameter, public :: nclmax = 3 ! Maximum number of canopy layers diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 987b8ad87d..9f645c81c4 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -1987,6 +1987,14 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) real(r8), parameter :: tiny = 1.e-5_r8 ! some small number real(r8), parameter :: reallytalltrees = 1000. ! some large number (m) + + ! Set this to true if you want the size-pft l2fr variables to + ! take a mean over the site, otherwise it just tracks the oldest patch + + logical, parameter :: do_site_l2fr_scpf = .false. + + + integer :: tmp associate( hio_npatches_si => this%hvars(ih_npatches_si)%r81d, & @@ -2238,6 +2246,11 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) model_day_int = nint(hlm_model_day) + + + + + ! --------------------------------------------------------------------------------- ! Loop through the FATES scale hierarchy and fill the history IO arrays ! --------------------------------------------------------------------------------- @@ -2546,16 +2559,19 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_l2fr_scpf(io_si,i_scpf) = & hio_l2fr_scpf(io_si,i_scpf) + ccohort%n*fnrt_m/m2_per_ha*ccohort%l2fr - if (ccohort%canopy_layer .eq. 1) then - hio_l2fr_canopy_scpf(io_si,i_scpf) = & - hio_l2fr_canopy_scpf(io_si,i_scpf) + ccohort%n*fnrt_m *ccohort%l2fr - fnrtc_canopy_scpf(i_scpf) = fnrtc_canopy_scpf(i_scpf) + ccohort%n*fnrt_m - else - hio_l2fr_understory_scpf(io_si,i_scpf) = & - hio_l2fr_understory_scpf(io_si,i_scpf) + ccohort%n*fnrt_m*ccohort%l2fr - fnrtc_understory_scpf(i_scpf) = fnrtc_understory_scpf(i_scpf) + ccohort%n*fnrt_m + ! Constrain L2FR to oldest patch? + if(do_site_l2fr_scpf .or. associated(cpatch,sites(s)%oldest_patch)) then + if (ccohort%canopy_layer .eq. 1) then + hio_l2fr_canopy_scpf(io_si,i_scpf) = & + hio_l2fr_canopy_scpf(io_si,i_scpf) + ccohort%n*fnrt_m *ccohort%l2fr + fnrtc_canopy_scpf(i_scpf) = fnrtc_canopy_scpf(i_scpf) + ccohort%n*fnrt_m + else + hio_l2fr_understory_scpf(io_si,i_scpf) = & + hio_l2fr_understory_scpf(io_si,i_scpf) + ccohort%n*fnrt_m*ccohort%l2fr + fnrtc_understory_scpf(i_scpf) = fnrtc_understory_scpf(i_scpf) + ccohort%n*fnrt_m + end if end if - + call bstore_allom(ccohort%dbh,ccohort%pft,ccohort%canopy_trim, store_max) this%hvars(ih_storectfrac_si)%r81d(io_si) = & this%hvars(ih_storectfrac_si)%r81d(io_si) + ccohort%n * store_max/m2_per_ha diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 064eec22a1..e729a4f33c 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -203,7 +203,9 @@ module PRTAllometricCNPMod integer, parameter :: regulate_CN_logi = 3 ! almost deprecated integer, parameter :: regulate_CN_dfdd = 4 - + logical, parameter :: use_gains_in_regulator = .true. + logical, parameter :: use_unrestricted_contraction = .true. + ! ------------------------------------------------------------------------------------- ! This is the core type that holds this specific ! plant reactive transport (PRT) module @@ -226,6 +228,7 @@ module PRTAllometricCNPMod procedure :: CNPAllocateRemainder procedure :: GetDeficit procedure :: StorageRegulator + procedure :: TrimFineRoot end type cnp_allom_prt_vartypes @@ -454,10 +457,8 @@ subroutine DailyPRTAllometricCNP(this) ! =================================================================================== ! This routine updates the l2fr (leaf 2 fine-root multiplier) variable + ! It will also update target_c(fnrt_organ) call this%CNPAdjustFRootTargets(target_c) - - - c_gain0 = c_gain n_gain0 = n_gain @@ -654,9 +655,16 @@ subroutine DailyPRTAllometricCNP(this) else p_gain = p_gain0 end if - + + + + ! If fine-roots are allocated above their + ! target (perhaps with some buffer, but perhaps not) + ! then + call this%TrimFineRoot() + return end subroutine DailyPRTAllometricCNP @@ -680,10 +688,8 @@ subroutine CNPAdjustFRootTargets(this, target_c) ! remain after a day of root turnover without ! replacement real(r8) :: fnrt_frac ! fine-root's current fraction of the target - real(r8) :: loss_flux_c - real(r8) :: loss_flux_n - real(r8) :: loss_flux_p - real(r8) :: fnrt_c_above_target + + integer, parameter :: regulate_type = regulate_CN_dfdd @@ -705,7 +711,7 @@ subroutine CNPAdjustFRootTargets(this, target_c) else call this%StorageRegulator(phosphorus_element, regulate_type,target_c,p_regulator) end if - + ! We take the maximum here, because the maximum is reflective of the ! element with the lowest storage, which is the limiting element if(n_uptake_mode.eq.prescribed_n_uptake)then @@ -738,44 +744,82 @@ subroutine CNPAdjustFRootTargets(this, target_c) ! Find the updated target fineroot biomass call bfineroot(dbh,ipft,canopy_trim, l2fr, target_c(fnrt_organ)) + + end associate - ! The following section allows forceful turnover of fine-roots if a new L2FR is generated - ! that is lower than the previous l2fr. The maintenance turnover (background) rate - ! will automatically accomodate a lower l2fr, but if the change is large it will - ! not keep pace. Note 1: however, that the algorithm in StorageRegulator() will prevent - ! large drops in l2fr (unless that safegaurd is removed). Note 2: this section may also - ! generate mass check errors in the main CNPAllocation routine, this is because the "val" is - ! changing but the net_allocated is not reciprocating, which is expected. + return + end subroutine CNPAdjustFRootTargets + + ! ===================================================================================== - ! Don't remove roots that will be gone due to natural turnover - - store_c = this%GetState(fnrt_organ, carbon12_element)*(1._r8-(years_per_day / prt_params%root_long(ipft))) - - fnrt_c_above_target = max(0._r8,store_c - target_c(fnrt_organ)) + subroutine TrimFineRoot(this) + + ! The following section allows forceful turnover of fine-roots if a new L2FR is generated + ! that is lower than the previous l2fr. The maintenance turnover (background) rate + ! will automatically accomodate a lower l2fr, but if the change is large it will + ! not keep pace. Note 1: however, that the algorithm in StorageRegulator() will prevent + ! large drops in l2fr (unless that safegaurd is removed). Note 2: this section may also + ! generate mass check errors in the main CNPAllocation routine, this is because the "val" is + ! changing but the net_allocated is not reciprocating, which is expected. + + ! Keep a buffer above the L2FR in the hopes that natural turnover will catch + ! up. + class(cnp_allom_prt_vartypes) :: this + + real(r8) :: fnrt_flux_c + real(r8) :: turn_flux_c + real(r8) :: store_flux_c + real(r8) :: nc_fnrt + real(r8) :: pc_fnrt + real(r8) :: target_fnrt_c + real(r8),parameter :: nday_buffer = 0._r8 + real(r8),parameter :: fnrt_opt_eff = 0._r8 ! If we want to transfer resources to storage + + if(.not.use_unrestricted_contraction)return + + associate( ipft => this%bc_in(acnp_bc_in_id_pft)%ival, & + l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval, & + dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval, & + canopy_trim => this%bc_in(acnp_bc_in_id_ctrim)%rval) - loss_flux_c = 0._r8 - - !loss_flux_c = fnrt_c_above_target*max(fnrt_c_above_target/fnrt_c_target-0.1_r8,0._r8) - - - loss_flux_n = loss_flux_c*this%variables(fnrt_n_id)%val(1)/this%variables(fnrt_c_id)%val(1) - this%variables(fnrt_n_id)%val(1) = this%variables(fnrt_n_id)%val(1) - loss_flux_n - this%variables(fnrt_n_id)%turnover(1) = this%variables(fnrt_n_id)%turnover(1) + loss_flux_n + ! Find the updated target fineroot biomass + call bfineroot(dbh,ipft,canopy_trim, l2fr, target_fnrt_c) - loss_flux_p = loss_flux_c*this%variables(fnrt_p_id)%val(1)/this%variables(fnrt_c_id)%val(1) - this%variables(fnrt_p_id)%val(1) = this%variables(fnrt_p_id)%val(1) - loss_flux_p - this%variables(fnrt_p_id)%turnover(1) = this%variables(fnrt_p_id)%turnover(1) + loss_flux_p - - this%variables(fnrt_c_id)%val(1) = this%variables(fnrt_c_id)%val(1) - loss_flux_c - this%variables(fnrt_c_id)%turnover(1) = this%variables(fnrt_c_id)%turnover(1) + loss_flux_c + fnrt_flux_c = max(0._r8,this%variables(fnrt_c_id)%val(1)*(1._r8-nday_buffer*(years_per_day / prt_params%root_long(ipft))) - target_fnrt_c ) - + if(fnrt_flux_c>nearzero) then - end associate + !EDPftvarcon_inst%dev_arbitrary_pft(ipft) - return - end subroutine CNPAdjustFRootTargets + turn_flux_c = (1._r8 - fnrt_opt_eff)*fnrt_flux_c + store_flux_c = fnrt_opt_eff*fnrt_flux_c + nc_fnrt = this%variables(fnrt_n_id)%val(1)/this%variables(fnrt_c_id)%val(1) + pc_fnrt = this%variables(fnrt_p_id)%val(1)/this%variables(fnrt_c_id)%val(1) + + this%variables(fnrt_c_id)%val(1) = this%variables(fnrt_c_id)%val(1) - fnrt_flux_c + this%variables(fnrt_c_id)%turnover(1) = this%variables(fnrt_c_id)%turnover(1) + turn_flux_c + this%variables(fnrt_c_id)%net_alloc(1) = this%variables(fnrt_c_id)%net_alloc(1) - store_flux_c + this%variables(store_c_id)%val(1) = this%variables(store_c_id)%val(1) + store_flux_c + this%variables(store_c_id)%net_alloc(1) = this%variables(store_c_id)%net_alloc(1) + store_flux_c + + this%variables(fnrt_n_id)%val(1) = this%variables(fnrt_n_id)%val(1) - fnrt_flux_c * nc_fnrt + this%variables(fnrt_n_id)%turnover(1) = this%variables(fnrt_n_id)%turnover(1) + turn_flux_c * nc_fnrt + this%variables(fnrt_n_id)%net_alloc(1) = this%variables(fnrt_n_id)%net_alloc(1) - store_flux_c * nc_fnrt + this%variables(store_n_id)%val(1) = this%variables(store_n_id)%val(1) + store_flux_c * nc_fnrt + this%variables(store_n_id)%net_alloc(1) = this%variables(store_n_id)%net_alloc(1) + store_flux_c * nc_fnrt + + this%variables(fnrt_p_id)%val(1) = this%variables(fnrt_p_id)%val(1) - fnrt_flux_c * pc_fnrt + this%variables(fnrt_p_id)%turnover(1) = this%variables(fnrt_p_id)%turnover(1) + turn_flux_c * pc_fnrt + this%variables(fnrt_p_id)%net_alloc(1) = this%variables(fnrt_p_id)%net_alloc(1) - store_flux_c * pc_fnrt + this%variables(store_p_id)%val(1) = this%variables(store_p_id)%val(1) + store_flux_c * pc_fnrt + this%variables(store_p_id)%net_alloc(1) = this%variables(store_p_id)%net_alloc(1) + store_flux_c * pc_fnrt + + end if + end associate + return + end subroutine TrimFineRoot + ! ===================================================================================== subroutine CNPPrioritizedReplacement(this,c_gain, n_gain, p_gain, target_c) @@ -2257,7 +2301,10 @@ subroutine StorageRegulator(this,element_id,regulate_type,target_c,c_scalar) real(r8) :: c_gain real(r8) :: c_fnrt_expand ! predicted carbon available to expand fine-roots ! after replacement of turnover - + real(r8) :: gain + real(r8) :: store_act + real(r8) :: store_c_act + ! This fraction governs ! how much carbon from daily gains + storage overflow, is allowed to ! be spent on growing out roots. This inludes getting roots @@ -2266,20 +2313,22 @@ subroutine StorageRegulator(this,element_id,regulate_type,target_c,c_scalar) integer, parameter :: limit_lf = 2 integer, parameter :: lim_l2fr_max_type = limit_all - real(r8), parameter :: max_l2fr_cgain_frac = 0.95_r8 + real(r8), parameter :: max_l2fr_cgain_frac = 0.99_r8 real(r8), parameter :: nc_frac_offset = 1.0_r8 ! This shifts the center-point ! of the N:C or P:C storage equlibrium ! by multiplying the N term. - associate(dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval, & - canopy_trim => this%bc_in(acnp_bc_in_id_ctrim)%rval, & - ipft => this%bc_in(acnp_bc_in_id_pft)%ival, & - l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval) + + + associate(dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval, & + canopy_trim => this%bc_in(acnp_bc_in_id_ctrim)%rval, & + ipft => this%bc_in(acnp_bc_in_id_pft)%ival, & + l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval) - logi_k = EDPftvarcon_inst%dev_arbitrary_pft(ipft) !2._r8 + logi_k = EDPftvarcon_inst%dev_arbitrary_pft(ipft) store_x0 = 0.0_r8 logi_min = 0.0_r8 @@ -2300,14 +2349,27 @@ subroutine StorageRegulator(this,element_id,regulate_type,target_c,c_scalar) elseif(regulate_type == regulate_CN_dfdd) then - store_max = this%GetNutrientTarget(element_id,store_organ,stoich_growth_min) ! Storage fractions could be more than the target, depending on the ! hypothesis and functions involved, but should typically be 0-1 ! The cap of 5 is for numerics and preventing weird math - store_frac = max(0.01_r8,min(5.0_r8,this%GetState(store_organ, element_id)/store_max)) + if(element_id.eq.nitrogen_element)then + gain = this%bc_inout(acnp_bc_inout_id_netdn)%rval + else + gain = this%bc_inout(acnp_bc_inout_id_netdp)%rval + end if + + if(use_gains_in_regulator)then + store_act = this%GetState(store_organ, element_id) + gain + store_c_act = this%GetState(store_organ, carbon12_element) + this%bc_in(acnp_bc_in_id_netdc)%rval + else + store_act = this%GetState(store_organ, element_id) + store_c_act = this%GetState(store_organ, carbon12_element) + end if + + store_frac = max(0.01_r8,min(5.0_r8,store_act/store_max)) ! Since we don't dump storage carbon ! these stores can actually get pretty large, so the cap of 10x is numerically @@ -2315,7 +2377,7 @@ subroutine StorageRegulator(this,element_id,regulate_type,target_c,c_scalar) store_c_max = target_c(store_organ) - store_c_frac = max(0.01_r8,min(5.0_r8,this%GetState(store_organ, carbon12_element)/store_c_max )) + store_c_frac = max(0.01_r8,min(5.0_r8,store_c_act/store_c_max)) ! ----------------------------------------------------------------------------- ! To decide the upper limit on expanding root growth, we perform a carbon @@ -2396,7 +2458,10 @@ subroutine StorageRegulator(this,element_id,regulate_type,target_c,c_scalar) if(c_scalar>1.0_r8)then c_scalar = min(c_scalar,l2fr_delta_max) else - c_scalar = max(c_scalar,l2fr_delta_min) + ! Remove the min function temporarily + if(.not.use_unrestricted_contraction)then + c_scalar = max(c_scalar,l2fr_delta_min) + end if end if @@ -2404,7 +2469,6 @@ subroutine StorageRegulator(this,element_id,regulate_type,target_c,c_scalar) end associate - end subroutine StorageRegulator ! ==================================================================================== diff --git a/parteh/PRTGenericMod.F90 b/parteh/PRTGenericMod.F90 index b92a1e14a7..d3538b528d 100644 --- a/parteh/PRTGenericMod.F90 +++ b/parteh/PRTGenericMod.F90 @@ -1334,10 +1334,12 @@ function StorageNutrientTarget(pft, element_id, leaf_target, fnrt_target, sapw_t ! total nitrogen content of 1 or more sets of organs ! ------------------------------------------------------------------------------------- - integer, parameter :: lfs_store_prop = 1 ! leaf-sapwood proportional storage - integer, parameter :: lfss_store_prop = 2 ! leaf-fnrt-sapw-struct proportional storage - integer, parameter :: fnrt_store_prop = 3 ! fineroot proportional storage - integer, parameter :: store_prop = lfs_store_prop + integer, parameter :: lfs_store_prop = 1 ! leaf-sapwood proportional storage + integer, parameter :: lfss_store_prop = 2 ! leaf-fnrt-sapw-struct proportional storage + integer, parameter :: fnrt_store_prop = 3 ! fineroot proportional storage + integer, parameter :: cstore_store_prop = 4 ! As a proportion to carbon storage times mean CN + integer, parameter :: lf_store_prop = 5 ! leaf proportional storage + integer, parameter :: store_prop = lf_store_prop select case(element_id) @@ -1352,6 +1354,10 @@ function StorageNutrientTarget(pft, element_id, leaf_target, fnrt_target, sapw_t store_target = prt_params%nitr_store_ratio(pft) * (leaf_target + sapw_target) + elseif (store_prop == lf_store_prop) then + + store_target = prt_params%nitr_store_ratio(pft) * leaf_target + elseif(store_prop==lfss_store_prop) then store_target = prt_params%nitr_store_ratio(pft) * (leaf_target + fnrt_target + sapw_target + struct_target) @@ -1360,6 +1366,30 @@ function StorageNutrientTarget(pft, element_id, leaf_target, fnrt_target, sapw_t store_target = prt_params%nitr_store_ratio(pft) * fnrt_target + elseif(store_prop==cstore_store_prop) then + + !call bsap_allom(dbh,ipft,canopy_trim,sapw_area,target_sapw_c) + !call bagw_allom(dbh,ipft,agw_c_target) + !call bbgw_allom(dbh,ipft,bgw_c_target) + !call bdead_allom(agw_c_target,bgw_c_target,target_sapw_c,ipft,target_struct_c) + !call bleaf(dbh,ipft,canopy_trim, target_leaf_c) + !call bfineroot(dbh,ipft,canopy_trim, l2fr, target_fnrt_c) + !call bstore_allom(dbh,ipft,canopy_trim, target_store_c) + + ! Strategy, store as much nutrient as needed to match carbon's growth potential + ! ie, nutrient storage is proportional to carbon storage times plant NC ratio + + ! N_so = a * C_so * NC_p + ! NC_p = ( (N_so + N_lf + N_fr + N_sa + N_de)/C_tot ) + ! N_so = a * C_so * ( N_so/C_tot) + a * C_so * (N_lf + N_fr + N_sa + N_de)/C_tot ) + ! N_so = (a * C_so * (N_lf + N_fr + N_sa + N_de)/C_tot ) / ( 1 - a * C_so/C_tot) + + !store_target = (target_store_c * prt_params%nitr_store_ratio(pft) * & + ! (leaf_target + fnrt_target + sapw_target + struct_target)/total_c_target) / & + ! ( 1._r8 - target_store_c * prt_params%nitr_store_ratio(pft) / total_c_target ) + write(fates_log(),*)'cstore_store_prop method of calculating target nutrient stores not available' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if @@ -1369,15 +1399,19 @@ function StorageNutrientTarget(pft, element_id, leaf_target, fnrt_target, sapw_t store_target = prt_params%phos_store_ratio(pft) * (leaf_target + fnrt_target + sapw_target) + elseif (store_prop == lf_store_prop) then + + store_target = prt_params%phos_store_ratio(pft) * leaf_target + elseif(store_prop==lfss_store_prop) then - store_target = prt_params%nitr_store_ratio(pft) * (leaf_target + fnrt_target + sapw_target + struct_target) + store_target = prt_params%phos_store_ratio(pft) * (leaf_target + fnrt_target + sapw_target + struct_target) elseif(store_prop==fnrt_store_prop) then store_target = prt_params%phos_store_ratio(pft) * fnrt_target - - end if + + end if end select From 5cb79fe5fa529c47e9e520e030524c4b78fba9ca Mon Sep 17 00:00:00 2001 From: Jacquelyn Shuman Date: Fri, 6 May 2022 13:56:37 -0600 Subject: [PATCH 196/852] Include conversion FM10 fuels ton/acre to kg/m2 --- fire/SFMainMod.F90 | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index 79ebe87dfc..0ba9f8e9e2 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -1101,11 +1101,11 @@ subroutine active_crown_fire ( currentSite, canopy_fuel_load, ROS_torch, & real(r8),parameter :: q_dry = 581.0_r8 !heat of pre-ignition of dry fuels (kJ/kg) ! fuel loading, MEF, and depth from Anderson 1982 Aids to determining fuel models for fire behavior - ! SAV values from BEHAVE model Burgan & Rothermel 1984) - real(r8),parameter :: fuel_1hr = 3.01_r8 ! FM 10 1-hr fuel loading (US tons/acre) - real(r8),parameter :: fuel_10hr = 2.0_r8 ! FM 10 10-hr fuel loading (US tons/acre) - real(r8),parameter :: fuel_100hr = 5.01_r8 ! FM 10 100-hr fuel loading (US tons/acre) - real(r8),parameter :: fuel_live = 2.0_r8 ! FM 10 live fuel loading (US tons/acre) + ! SAV values from BEHAVE model Burgan & Rothermel (1984) + real(r8),parameter :: fuel_1hr_ton = 3.01_r8 ! FM 10 1-hr fuel loading (US tons/acre) + real(r8),parameter :: fuel_10hr_ton = 2.0_r8 ! FM 10 10-hr fuel loading (US tons/acre) + real(r8),parameter :: fuel_100hr_ton = 5.01_r8 ! FM 10 100-hr fuel loading (US tons/acre) + real(r8),parameter :: fuel_live_ton = 2.0_r8 ! FM 10 live fuel loading (US tons/acre) real(r8),parameter :: fuel_mef = 0.25_r8 ! FM 10 moisture of extinction (volumetric) real(r8),parameter :: fuel_depth_ft= 1.0_r8 ! FM 10 fuel depth (ft) real(r8),parameter :: sav_1hr_ft = 2000.0_r8 ! FM 10 1-hr SAV (ft2/ft3) @@ -1137,7 +1137,12 @@ subroutine active_crown_fire ( currentSite, canopy_fuel_load, ROS_torch, & ! Calculate rate of spread using FM 10 as in Rothermel 1977 ! fuel characteristics - total_fuel = (fuel_1hr + fuel_10hr + fuel_100hr + fuel_live) * tonnes_acre_to_kg_m2 + fuel_1hr = fuel_1hr_ton * tonnes_acre_to_kg_m2 + fuel_10hr = fuel_10hr_ton * tonnes_acre_to_kg_m2 + fuel_100hr = fuel_100hr_ton * tonnes_acre_to_kg_m2 + fuel_live = fuel_live_ton * tonnes_acre_to_kg_m2 + + total_fuel = (fuel_1hr + fuel_10hr + fuel_100hr + fuel_live) !total fuel (kg/m2) SAV_1hr = sav_1hr_ft * sqft_cubicft_to_sqm_cubicm SAV_10hr = sav_10hr_ft * sqft_cubicft_to_sqm_cubicm @@ -1150,7 +1155,7 @@ subroutine active_crown_fire ( currentSite, canopy_fuel_load, ROS_torch, & fuel_moistlive = exp(-1.0_r8 * ((SAV_live/SF_val_drying_ratio) * currentSite%acc_NI)) fuel_depth = fuel_depth_ft *0.3048 !convert to meters - fuel_bd = total_fuel/fuel_depth + fuel_bd = total_fuel/fuel_depth !fuel bulk density (kg/m3) fuel_sav = SAV_1hr *(fuel_1hr/total_fuel) + SAV_10hr*(fuel_10hr/total_fuel) + & SAV_100hr*(fuel_100hr/total_fuel) + SAV_live*(fuel_live/total_fuel) @@ -1183,7 +1188,7 @@ subroutine active_crown_fire ( currentSite, canopy_fuel_load, ROS_torch, & midflame_wind = currentSite%wind *0.40_r8 !Scott & Reinhardt 2001 40% open wind speed ! Eq A5 in Thonicke et al. 2010 - ! convert current_wspeed (wind at elev relevant to fire) from m/min to ft/min for Rothermel ROS eqn + ! include convert wind from m/min to ft/min for Rothermel ROS eqn phi_wind = c * ((3.281_r8*midflame_wind)**b)*(beta_ratio**(-e)) !unitless ! ---propagating flux = xi (unitless) From 7912585bb006b514a0ee97cf8de7e829a63ce17f Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 13 May 2022 14:26:13 -0400 Subject: [PATCH 197/852] Parameter file API updater script is nearly final, incremental progress on the API 23-24 xml file. Updates to ncvarsort --- parameter_files/apichange_23to24.xml | 343 ++++++++++++++++++++++++++- tools/UpdateParamAPI.py | 184 +++++++++++--- tools/ncvarsort.py | 3 + 3 files changed, 493 insertions(+), 37 deletions(-) diff --git a/parameter_files/apichange_23to24.xml b/parameter_files/apichange_23to24.xml index 4d54c947c8..6952fca426 100644 --- a/parameter_files/apichange_23to24.xml +++ b/parameter_files/apichange_23to24.xml @@ -19,11 +19,105 @@ fates_history_damage_bins - 6 + 3 fates_cnp_eca_alpha_ptase + + fates_cnp_eca_decompmicc + + + fates_cnp_eca_km_nh4 + + + fates_cnp_eca_km_no3 + + + fates_cnp_eca_km_p + + + fates_cnp_eca_km_ptase + + + fates_cnp_eca_lambda_ptase + + + fates_cnp_eca_vmax_ptase + + + fates_cnp_fnrt_adapt_tscale + fates_pft + days + Number of days that is shortest possible doubling period for fine-root adaptation to C/N/P balance + cnp + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 + + + fates_cnp_nfix1 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + + + fates_cnp_nfix2 + + + fates_cnp_nitr_store_ratio + storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code) + + + fates_cnp_phos_store_ratio + storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code) + + + fates_cnp_prescribed_nuptake + + + fates_cnp_prescribed_puptake + + + fates_cnp_eca_vmax_nh4 + 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9 + + + fates_cnp_eca_vmax_no3 + 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9 + + + fates_cnp_rd_vmax_n + fates_pft + gN/gC/s + maximum production rate for compbined (NH4+NO3) uptake (RD) + cnp + 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9 + + + fates_cnp_vmax_p + maximum production rate for phosphorus (ECA and RD) + 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10 + + + fates_allom_crown_depth_frac + the depth of a cohort crown as a fraction of its height + + + fates_phen_fnrt_drop_frac + fates_pft + fraction + phenology + fraction of fine roots to drop during drought or cold + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + + + fates_cnp_eca_plant_escalar + + + fates_hydro_solver + scalar + unitless + hydro + switch designating which numerical solver for plant hydraulics, 1 = 1D taylor, 2 = 2D Picard + 1 + fates_history_damage_bin_edges fates_history_damage_bins @@ -40,5 +134,252 @@ damage 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 + + fates_damage_mort_p1 + fates_pft + fraction + inflection point of damage mortality function, a value of 0.8 means 50% mortality with 80% loss of crown, turn off with a large number + damage + 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0 + + + fates_damage_mort_p2 + fates_pft + unitless + rate of mortality increase with damage + damage + 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5 + + + fates_damage_recovery_scalar + fates_pft + unitless + fraction of the cohort that recovers from damage + damage + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + + + fates_maxpatch_primary + scalar + count + advanced + maximum number of primary vegetation patches per site + 10 + + + fates_maxpatch_secondary + scalar + count + advanced + maximum number of secondary vegetation patches per site + 1 + + + fates_phen_drought_model + scalar + unitless + phenology + which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like) + 0 + + + fates_phen_drought_threshold + scalar + m3/m3 or mm + phenology + threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm) + 0.15 + + + fates_phen_moist_threshold + scalar + m3/m3 or mm + phenology + upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm) + 0.18 + + + fates_lu_pprodharv10_forest_mean + scalar + fraction + landuse + mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types + 0.8125 + + + fates_stomatal_assim_model + scalar + unitless + stomata + a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model + 1 + + + width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer + + + factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing) + + + factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing) + + + fates_prt_organs + + + fates_plant_organs + 4 + + + fates_alloc_organ_priority + fates_plant_organs, fates_pft + index + Priority level for allocation, 1: replaces turnover from storage, 2: same priority as storage use/replacement, 3: ascending in order of least importance + allocation + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 + + + fates_alloc_organ_name + fates_plant_organs, fates_string_length + unitless - string + allocation + Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90) + leaf, fine root, sapwood,structure + + + fates_alloc_nitr_stoich_p1 + fates_plant_organs, fates_pft + gN/gC + allocation + target nitrogen concentration (ratio with carbon) of organs + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047 + + + fates_alloc_organ_id + fates_plant_organs + unitless + allocation + This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90 + 1, 2, 3, 6 + + + fates_alloc_phos_stoich_p1 + fates_plant_organs, fates_pft + gP/gC + allocation + target phosphorus concentration (ratio with carbon) of organs + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, 0.004, 0.004, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047 + + + fates_turnover_carb_retrans + fates_plant_organs, fates_pft + fraction + allocation + retranslocation (reabsorbtion) fraction of carbon in turnover of scenescing tissues + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + + + fates_turnover_nitr_retrans + fates_plant_organs, fates_pft + fraction + cnp + retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + + + fates_turnover_phos_retrans + fates_plant_organs, fates_pft + fraction + cnp + retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + + + fates_hydro_organ_name + + + + fates_mort_prescribed_canopy + + + fates_mort_prescribed_understory + + + fates_phen_flushfrac + + + fates_mindaysoff + + + fates_turb_leaf_diameter + + + fates_turb_displar + + + fates_turb_z0mr + + + fates_lu_logging_coll_under_frac + + + fates_lu_logging_collateral_frac + + + fates_lu_logging_dbhmax + + + fates_lu_logging_dbhmax_infra + + + fates_lu_logging_dbhmin + + + fates_lu_logging_direct_frac + + + fates_lu_logging_event_code + + + fates_lu_logging_export_frac + + + fates_lu_logging_mechanical_frac + + + fates_leaf_photo_temp_acclim_timescale + + + fates_leaf_theta_cj_c3 + + + fates_leaf_theta_cj_c4 + + + fates_leaf_photo_tempsens_model + + + fates_nonhydro_smpsc + + + fates_nonhydro_smpso + + + fates_ + + + + + + + + + + + fates_ + + + + diff --git a/tools/UpdateParamAPI.py b/tools/UpdateParamAPI.py index 91272bb20d..0d757fd0d0 100755 --- a/tools/UpdateParamAPI.py +++ b/tools/UpdateParamAPI.py @@ -14,6 +14,7 @@ import code # For development: code.interact(local=dict(globals(), **locals())) from scipy.io import netcdf import xml.etree.ElementTree as et +import numpy as np # ======================================================================================= @@ -53,22 +54,25 @@ def str2ivec(numstr): # ======================================================================================= -def createvar(ncfile,paramname,dimnames,units,longname,usecase,sel_values): +def createvar(ncfile,paramname,dimnames,units,longname,usecase,dcode,sel_values): # Create a new netcdf variable inside an existing netcdf dataset (append) - - ncvar = ncfile.createVariable(paramname,'d',dimnames) + + ncvar = ncfile.createVariable(paramname,dcode,dimnames) ncvar.units = units ncvar.long_name = longname ncvar.use_case = usecase - ncvar[:] = sel_values + if( not dimnames): + ncvar.assignValue(sel_values) + else: + ncvar[:] = sel_values ncfile.flush() return(ncfile,ncvar) # ======================================================================================= -def selectvalues(ncfile,dimnames,ipft_list,values): +def selectvalues(ncfile,dimnames,ipft_list,values,dtype): # Reduce a list of values so that onlythe chosen pft values are left. This # only works on float arrays currently. We need to pass in a file @@ -81,29 +85,72 @@ def selectvalues(ncfile,dimnames,ipft_list,values): print('len(ipft_list) = {}'.format(len(ipft_list))) print('fates_pft dim = {}'.format(ncfile.dimensions['fates_pft'])) exit(2) - + + # shift the pft list to a base of 0 instead of 1 + pft_dim = -1 - dim2_size = 1 - for idim,name in enumerate(list(dimnames)): + dim_size = [0 for i in range(0,len(dimnames))] + + for idim, name in enumerate(dimnames): + dim_size[idim] = ncfile.dimensions[name] if(name=='fates_pft'): pft_dim = idim pft_dim_size = ncfile.dimensions['fates_pft'] + + if(len(dimnames) == 1): + + if(pft_dim==0): + dim1_list = ipft_list else: - dim2_size = ncfile.dimensions[name] - - sel_values = [] - if(pft_dim==0): - for j in range(dim2_size): - i0 = j*pft_dim_size - for i in ipft_list: - sel_values.append(values[i-1+i0]) - elif(pft_dim==1): - for i in ipft_list: - i0 = i*dim2_size - for j in range(dim2_size): - sel_values.append(values[j-1+i0]) + dim1_list = range(0,dim_size[0]) + + sel_values = np.zeros([len(dim1_list)]) + for i,ipft in enumerate(dim1_list): + sel_values[i] = values[ipft] + + elif(len(dimnames) == 2 ): + + if(dtype=="c"): + + if(pft_dim>0): + print("problem with pft_dim: {},{}".format(dimnames[0],dimnames[1]));exit(2) + + if(pft_dim==0): + dim1_list = ipft_list + else: + dim1_list = range(0,dim_size[0]) + + #code.interact(local=dict(globals(), **locals())) + #sel_values = np.empty([len(dim1_list),dim_size[1]], dtype="S{}".format(dim_size[1])) + #sel_values = np.empty(len(dim1_list), dtype='S60') + sel_values = np.chararray([len(dim1_list),dim_size[1]]) + sel_values[:] + for i,ipft in enumerate(dim1_list): + for j,cc in enumerate(values[ipft]): + sel_values[i][j] = cc + + + elif(dtype=="d"): + + if(pft_dim==0): + print("problem with pft_dim: {},{}".format(dimnames[0],dimnames[1]));exit(2) + + if(pft_dim==1): + dim1_list = ipft_list + else: + dim1_list = range(0,dim_size[1]) + + sel_values = np.zeros([dim_size[0],len(dim1_list)]) + for i,ipft in enumerate(dim1_list): + for i2 in range(0,dim_size[0]): + id = i2*len(dim1_list)+ipft + sel_values[i2,i] = values[id] + else: - sel_values = values + + # Scalar + #code.interact(local=dict(globals(), **locals())) + sel_values = float(values[0]) return(sel_values) @@ -120,10 +167,13 @@ def removevar(base_nc,varname): new_nc = os.popen('mktemp').read().rstrip('\n') fp_new = netcdf.netcdf_file(new_nc, 'w',mmap=False) + found = False for key, value in sorted(fp_base.dimensions.items()): - fp_new.createDimension(key,int(value)) + if( key == varname ): + found = True + else: + fp_new.createDimension(key,int(value)) - found = False for key, value in fp_base.variables.items(): if(key == varname): @@ -172,7 +222,9 @@ def main(): [base_cdl,new_cdl,pft_list,modroot] = load_xml(args.xmlfile) ipft_list = str2ivec(pft_list) - + + for i,ipft in enumerate(ipft_list): + ipft_list[i] = ipft_list[i]-1 # Convert the base cdl file into a temp nc binary base_nc = os.popen('mktemp').read().rstrip('\n') @@ -194,7 +246,7 @@ def main(): print("{}, no dimension (di), exiting".format(mod.attrib['type']));exit(2) try: - values = str2fvec(mod.find('val').text.strip()) + values = str2ivec(mod.find('val').text.strip()) except: print("no values (val), exiting");exit(2) @@ -209,6 +261,35 @@ def main(): print("dimension: {}, size: {}, added".format(dimname,values[0])) + elif(mod.attrib['type'].strip() == 'dimension_del'): + + try: + dimname = mod.find('di').text.strip() + except: + print('define the dimension name to delete using a tag') + exit(2) + + # Find which parameters use this dimension + ncfile = netcdf.netcdf_file(base_nc,"r",mmap=False) + found = False + for key, value in sorted(ncfile.dimensions.items()): + if(key==dimname): + found=True + + if(not found): + print("could not find {} for deletion".format(dimname));exit(2) + + for key, value in sorted(ncfile.variables.items()): + hasdim = any([dim == dimname for dim in list(value.dimensions) ]) + + if (hasdim): + print("parameter: {}, removed (to accomodate dimension removal)".format(key)) + removevar(base_nc,key) + + ncfile.close() + + removevar(base_nc,dimname) + print("dimension: {}, removed".format(dimname)) elif(mod.attrib['type'].strip() == 'variable_add'): @@ -217,10 +298,15 @@ def main(): except: print("no name (na), exiting");exit(2) + #try: + # dtype = mod.find('dt').text.strip() + #except: + # print("no data type (dt), exiting");exit(2) + try: - dimnames = tuple([mod.find('di').text.strip()]) + dimnames = tuple(mod.find('di').text.replace(" ","").split(',')) except: - print("no dimension (di), exiting");exit(2) + print("no data type (di), exiting");exit(2) try: units = mod.find('un').text.strip() @@ -240,12 +326,31 @@ def main(): try: values = str2fvec(mod.find('val').text.strip()) except: - print("no values (val), exiting");exit(2) + try: + values = mod.find('val').text.strip() + except: + print("no values (val), exiting");exit(2) - sel_values = selectvalues(ncfile,list(dimnames),ipft_list,values) - + #code.interact(local=dict(globals(), **locals())) + + if(dimnames[0]=='scalar' or dimnames[0]=='none' or dimnames[0]==''): + dimnames = () + + if(isinstance(values[0],str)): + dcode = "c" + values = values.split(',') + for i,val in enumerate(values): + values[i] = val.strip() + elif(isinstance(values[0],float)): + dcode = "d" + else: + print("Unknown value type: {} {}".format(type(values[0]),paramname));exit(2) + + + sel_values = selectvalues(ncfile,list(dimnames),ipft_list,values,dcode) + ncfile = netcdf.netcdf_file(base_nc,"a",mmap=False) - [ncfile,ncvar] = createvar(ncfile,paramname,dimnames,units,longname,usecase,sel_values) + [ncfile,ncvar] = createvar(ncfile,paramname,dimnames,units,longname,usecase,dcode,sel_values) ncfile.flush() ncfile.close() @@ -273,6 +378,7 @@ def main(): ncfile = netcdf.netcdf_file(base_nc,"a",mmap=False) ncvar_o = ncfile.variables[paramname_o] dims_o = ncvar_o.dimensions + dtype_o = ncvar_o.typecode() units_o = ncvar_o.units.decode("utf-8") longname_o = ncvar_o.long_name.decode("utf-8") try: @@ -280,6 +386,8 @@ def main(): except: usecase_o = 'undefined' + + try: paramname = mod.find('na').text.strip() except: @@ -287,7 +395,10 @@ def main(): # Change the parameter's name if(not isinstance(paramname,type(None))): - [ncfile,ncvar] = createvar(ncfile,paramname,dims_o,units_o,longname_o,usecase_o,ncvar_o[:].copy()) + if not dims_o: + [ncfile,ncvar] = createvar(ncfile,paramname,dims_o,units_o,longname_o,usecase_o,dtype_o,float(ncvar_o.data)) + else: + [ncfile,ncvar] = createvar(ncfile,paramname,dims_o,units_o,longname_o,usecase_o,dtype_o,ncvar_o[:].copy()) else: ncvar = ncvar_o @@ -319,11 +430,11 @@ def main(): values = None if(not isinstance(values,type(None))): - sel_values = selectvalues(ncfile,list(dims_o),ipft_list,values) + sel_values = selectvalues(ncfile,list(dims_o),ipft_list,values,dtype_o) # Scalars have their own thing if(ncvar.data.size == 1): - ncvar.assignValue(float(sel_values[0])) + ncvar.assignValue(sel_values) else: ncvar[:] = sel_values[:] @@ -336,7 +447,8 @@ def main(): # old one if(not isinstance(paramname,type(None))): removevar(base_nc,paramname_o) - + paramname = paramname_o + print("parameter: {}, modified".format(paramname)) diff --git a/tools/ncvarsort.py b/tools/ncvarsort.py index 7f56ab62fa..327dd84a96 100755 --- a/tools/ncvarsort.py +++ b/tools/ncvarsort.py @@ -42,14 +42,17 @@ def main(): (u'fates_history_damage_bins',):3, (u'fates_hydr_organs',):4, (u'fates_prt_organs',):4, + (u'fates_plant_organs',):4, (u'fates_pft', u'fates_string_length'):5, (u'fates_hydr_organs', u'fates_string_length'):6, (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_pft',):8, (u'fates_hydr_organs', u'fates_pft'):8, (u'fates_leafage_class', u'fates_pft'):8, (u'fates_prt_organs', u'fates_pft'):8, + (u'fates_plant_organs', u'fates_pft'):8, (u'fates_hlm_pftno', u'fates_pft'):9, (u'fates_litterclass',):10, (u'fates_NCWD',):11, From d321625ab3591efbff81572aff7d300a7a8d1826 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 13 May 2022 17:26:00 -0400 Subject: [PATCH 198/852] tweaks to parameter api change couplet --- parameter_files/apichange_23to24.xml | 396 ++++++++++++++++++--------- tools/UpdateParamAPI.py | 39 ++- 2 files changed, 284 insertions(+), 151 deletions(-) diff --git a/parameter_files/apichange_23to24.xml b/parameter_files/apichange_23to24.xml index 6952fca426..fb0012deaa 100644 --- a/parameter_files/apichange_23to24.xml +++ b/parameter_files/apichange_23to24.xml @@ -21,80 +21,6 @@ fates_history_damage_bins 3 - - fates_cnp_eca_alpha_ptase - - - fates_cnp_eca_decompmicc - - - fates_cnp_eca_km_nh4 - - - fates_cnp_eca_km_no3 - - - fates_cnp_eca_km_p - - - fates_cnp_eca_km_ptase - - - fates_cnp_eca_lambda_ptase - - - fates_cnp_eca_vmax_ptase - - - fates_cnp_fnrt_adapt_tscale - fates_pft - days - Number of days that is shortest possible doubling period for fine-root adaptation to C/N/P balance - cnp - 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 - - - fates_cnp_nfix1 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - - - fates_cnp_nfix2 - - - fates_cnp_nitr_store_ratio - storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code) - - - fates_cnp_phos_store_ratio - storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code) - - - fates_cnp_prescribed_nuptake - - - fates_cnp_prescribed_puptake - - - fates_cnp_eca_vmax_nh4 - 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9 - - - fates_cnp_eca_vmax_no3 - 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9 - - - fates_cnp_rd_vmax_n - fates_pft - gN/gC/s - maximum production rate for compbined (NH4+NO3) uptake (RD) - cnp - 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9 - - - fates_cnp_vmax_p - maximum production rate for phosphorus (ECA and RD) - 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10 - fates_allom_crown_depth_frac the depth of a cohort crown as a fraction of its height @@ -103,18 +29,13 @@ fates_phen_fnrt_drop_frac fates_pft fraction - phenology fraction of fine roots to drop during drought or cold 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - - fates_cnp_eca_plant_escalar - fates_hydro_solver scalar unitless - hydro switch designating which numerical solver for plant hydraulics, 1 = 1D taylor, 2 = 2D Picard 1 @@ -123,7 +44,6 @@ fates_history_damage_bins % crown loss Lower edges for damage class bins used in cohort history output - damage 0, 80, 100 @@ -131,7 +51,6 @@ fates_pft fraction fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine) - damage 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 @@ -139,7 +58,6 @@ fates_pft fraction inflection point of damage mortality function, a value of 0.8 means 50% mortality with 80% loss of crown, turn off with a large number - damage 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0 @@ -147,7 +65,6 @@ fates_pft unitless rate of mortality increase with damage - damage 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5 @@ -155,14 +72,12 @@ fates_pft unitless fraction of the cohort that recovers from damage - damage 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 fates_maxpatch_primary scalar count - advanced maximum number of primary vegetation patches per site 10 @@ -170,7 +85,6 @@ fates_maxpatch_secondary scalar count - advanced maximum number of secondary vegetation patches per site 1 @@ -178,7 +92,6 @@ fates_phen_drought_model scalar unitless - phenology which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like) 0 @@ -186,7 +99,6 @@ fates_phen_drought_threshold scalar m3/m3 or mm - phenology threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm) 0.15 @@ -194,7 +106,6 @@ fates_phen_moist_threshold scalar m3/m3 or mm - phenology upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm) 0.18 @@ -202,7 +113,6 @@ fates_lu_pprodharv10_forest_mean scalar fraction - landuse mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types 0.8125 @@ -210,7 +120,6 @@ fates_stomatal_assim_model scalar unitless - stomata a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model 1 @@ -235,22 +144,19 @@ fates_plant_organs, fates_pft index Priority level for allocation, 1: replaces turnover from storage, 2: same priority as storage use/replacement, 3: ascending in order of least importance - allocation 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 fates_alloc_organ_name fates_plant_organs, fates_string_length unitless - string - allocation Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90) leaf, fine root, sapwood,structure - fates_alloc_nitr_stoich_p1 + fates_stoich_nitr fates_plant_organs, fates_pft gN/gC - allocation target nitrogen concentration (ratio with carbon) of organs 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047 @@ -258,46 +164,36 @@ fates_alloc_organ_id fates_plant_organs unitless - allocation This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90 1, 2, 3, 6 - fates_alloc_phos_stoich_p1 + fates_stoich_phos fates_plant_organs, fates_pft gP/gC - allocation target phosphorus concentration (ratio with carbon) of organs 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, 0.004, 0.004, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047 - fates_turnover_carb_retrans + fates_cnp_turnover_nitr_retrans fates_plant_organs, fates_pft fraction - allocation - retranslocation (reabsorbtion) fraction of carbon in turnover of scenescing tissues - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - - - fates_turnover_nitr_retrans - fates_plant_organs, fates_pft - fraction - cnp retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - fates_turnover_phos_retrans + fates_cnp_turnover_phos_retrans fates_plant_organs, fates_pft fraction - cnp retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 fates_hydro_organ_name - + + fates_init_litter + fates_mort_prescribed_canopy @@ -308,7 +204,7 @@ fates_phen_flushfrac - fates_mindaysoff + fates_phen_mindaysoff fates_turb_leaf_diameter @@ -364,22 +260,264 @@ fates_nonhydro_smpso - - fates_ - - - - - - - - - - - fates_ - - - - + + fates_hydro_kmax_rsurf1 + + + fates_hydro_hydr_kmax_rsurf2 + + + fates_hydro_psi0 + + + fates_hydro_psicap + + + fates_hydro_avuln_gs + + + fates_hydro_avuln_node + + + fates_hydro_epsil_node + + + fates_hydro_fcap_node + + + fates_hydro_k_lwp + + + fates_hydro_kmax_node + + + fates_hydro_p50_gs + + + fates_hydro_p50_node + + + fates_hydro_p_taper + + + fates_hydro_pinot_node + + + fates_hydro_pitlp_node + + + fates_hydro_resid_node + + + fates_hydro_rfrac_stem + + + fates_hydro_rs2 + + + fates_hydro_srl + + + fates_hydro_thetas_node + + + fates_hydro_vg_alpha_node + + + fates_hydro_vg_m_node + + + fates_hydro_vg_n_node + + + fates_cnp_eca_alpha_ptase + + + fates_cnp_eca_decompmicc + + + fates_cnp_eca_km_nh4 + + + fates_cnp_eca_km_no3 + + + fates_cnp_eca_km_p + + + fates_cnp_eca_km_ptase + + + fates_cnp_eca_lambda_ptase + + + fates_cnp_eca_vmax_ptase + + + fates_cnp_fnrt_adapt_tscale + fates_pft + days + Number of days that is shortest possible doubling period for fine-root adaptation to C/N/P balance + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 + + + fates_cnp_nfix1 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + + + fates_nfix2 + + + fates_cnp_nitr_store_ratio + storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code) + + + fates_cnp_phos_store_ratio + storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code) + + + fates_cnp_prescribed_nuptake + + + fates_cnp_prescribed_puptake + + + fates_cnp_eca_vmax_nh4 + 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9 + + + fates_cnp_eca_vmax_no3 + 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9 + + + fates_cnp_rd_vmax_n + fates_pft + gN/gC/s + maximum production rate for compbined (NH4+NO3) uptake (RD) + 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9 + + + fates_cnp_vmax_p + maximum production rate for phosphorus (ECA and RD) + 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10 + + + fates_turnover_retrans_mode + + + fates_cnp_eca_plant_escalar + + + fates_alloc_stor_priority_frac + for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage + + + fates_turnover_leaf + + + fates_turnover_fnrt + + + fates_turnover_senleaf_fdrought + + + fates_turnover_branch + + + fates_allom_fnrt_prof_a + + + fates_allom_fnrt_prof_b + + + fates_allom_fnrt_prof_mode + + + fates_frag_maxdecomp + + + fates_frag_cwd_frac + + + fates_frag_fnrt_fcel + + + fates_frag_fnrt_flab + + + fates_frag_fnrt_flig + + + fates_frag_leaf_fcel + + + fates_frag_leaf_flab + + + fates_frag_leaf_flig + + + fates_frag_seed_decay + + + fates_frag_cwd_fcel + + + fates_frag_cwd_flig + + + fates_recruit_seed_alloc + + + fates_recruit_seed_alloc_mature + + + fates_recruit_seed_dbh_repro_threshold + + + fates_recruit_seed_germination_rate + + + fates_recruit_seed_supplement + + + fates_recruit_prescribed_rate + + + fates_recruit_height_min + + + fates_recruit_init_density + + + fates_rad_leaf_clumping_index + + + fates_rad_leaf_xl + + + fates_rad_leaf_rhonir + + + fates_rad_leaf_rhovis + + + fates_rad_stem_rhonir + + + fates_rad_stem_rhovis + + + fates_rad_leaf_taunir + + + fates_rad_leaf_tauvis + + + fates_rad_stem_taunir + + + fates_rad_stem_tauvis + diff --git a/tools/UpdateParamAPI.py b/tools/UpdateParamAPI.py index 0d757fd0d0..fe35d6a0c9 100755 --- a/tools/UpdateParamAPI.py +++ b/tools/UpdateParamAPI.py @@ -120,11 +120,8 @@ def selectvalues(ncfile,dimnames,ipft_list,values,dtype): else: dim1_list = range(0,dim_size[0]) - #code.interact(local=dict(globals(), **locals())) - #sel_values = np.empty([len(dim1_list),dim_size[1]], dtype="S{}".format(dim_size[1])) - #sel_values = np.empty(len(dim1_list), dtype='S60') sel_values = np.chararray([len(dim1_list),dim_size[1]]) - sel_values[:] + sel_values[:] = "" for i,ipft in enumerate(dim1_list): for j,cc in enumerate(values[ipft]): sel_values[i][j] = cc @@ -188,10 +185,10 @@ def removevar(base_nc,varname): new_var.units = value.units new_var.long_name = value.long_name - try: - new_var.use_case = value.use_case - except: - new_var.use_case = "undefined" + #try: + # new_var.use_case = value.use_case + #except: + # new_var.use_case = "undefined" fp_new.history = fp_base.history @@ -318,10 +315,10 @@ def main(): except: print("no long-name (ln), exiting");exit(2) - try: - usecase = mod.find('uc').text.strip() - except: - print("no use case (uc), exiting");exit(2) + #try: + # usecase = mod.find('uc').text.strip() + #except: + # print("no use case (uc), exiting");exit(2) try: values = str2fvec(mod.find('val').text.strip()) @@ -359,9 +356,9 @@ def main(): elif(mod.attrib['type'] == 'variable_del'): try: - paramname = mod.attrib['name'] + paramname = mod.find('na').text.strip() except: - print('must define the parameter name to delete, using ') + print('must define the parameter name to delete, using name attribute') exit(2) removevar(base_nc,paramname) print("parameter: {}, removed".format(paramname)) @@ -385,8 +382,6 @@ def main(): usecase_o = ncvar_o.use_case.decode("utf-8") except: usecase_o = 'undefined' - - try: paramname = mod.find('na').text.strip() @@ -417,12 +412,12 @@ def main(): if(not isinstance(longname,type(None))): ncvar.long_name = longname - try: - usecase = mod.find('uc').text.strip() - except: - usecase = None - if(not isinstance(usecase,type(None))): - ncvar.use_case = use_case + #try: + # usecase = mod.find('uc').text.strip() + #except: + usecase = None + #if(not isinstance(usecase,type(None))): + # ncvar.use_case = use_case try: values = str2fvec(mod.find('val').text.strip()) From 954e343f6fba91767307ff8d8cb8ae413ecbf81b Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 13 May 2022 19:09:18 -0400 Subject: [PATCH 199/852] minor updates to fates default parameters api24 --- parameter_files/apichange_23to24.xml | 2 +- .../fates_params_default_api24.cdl | 1516 ++++++++++++++++ .../fates_params_default_api24_v1.cdl | 1565 +++++++++++++++++ 3 files changed, 3082 insertions(+), 1 deletion(-) create mode 100644 parameter_files/fates_params_default_api24.cdl create mode 100644 parameter_files/fates_params_default_api24_v1.cdl diff --git a/parameter_files/apichange_23to24.xml b/parameter_files/apichange_23to24.xml index fb0012deaa..40055180f8 100644 --- a/parameter_files/apichange_23to24.xml +++ b/parameter_files/apichange_23to24.xml @@ -117,7 +117,7 @@ 0.8125 - fates_stomatal_assim_model + fates_leaf_stomatal_assim_model scalar unitless a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model diff --git a/parameter_files/fates_params_default_api24.cdl b/parameter_files/fates_params_default_api24.cdl new file mode 100644 index 0000000000..178226df04 --- /dev/null +++ b/parameter_files/fates_params_default_api24.cdl @@ -0,0 +1,1516 @@ +netcdf tmp { +dimensions: + fates_NCWD = 4 ; + fates_history_age_bins = 7 ; + fates_history_coage_bins = 2 ; + fates_history_damage_bins = 3 ; + fates_history_height_bins = 6 ; + fates_history_size_bins = 13 ; + fates_hlm_pftno = 14 ; + fates_hydr_organs = 4 ; + fates_leafage_class = 1 ; + fates_litterclass = 6 ; + fates_pft = 12 ; + fates_plant_organs = 4 ; + fates_string_length = 60 ; +variables: + double fates_history_ageclass_bin_edges(fates_history_age_bins) ; + fates_history_ageclass_bin_edges:units = "yr" ; + fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; + double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; + fates_history_coageclass_bin_edges:units = "years" ; + fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; + double fates_history_height_bin_edges(fates_history_height_bins) ; + fates_history_height_bin_edges:units = "m" ; + fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; + double fates_history_damage_bin_edges(fates_history_damage_bins) ; + fates_history_damage_bin_edges:units = "% crown loss" ; + fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; + double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; + fates_history_sizeclass_bin_edges:units = "cm" ; + fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; + double fates_alloc_organ_id(fates_plant_organs) ; + fates_alloc_organ_id:units = "unitless" ; + fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; + double fates_hydr_htftype_node(fates_hydr_organs) ; + fates_hydr_htftype_node:units = "unitless" ; + fates_hydr_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; + char fates_pftname(fates_pft, fates_string_length) ; + fates_pftname:units = "unitless - string" ; + fates_pftname:long_name = "Description of plant type" ; + char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; + fates_hydro_organ_name:units = "unitless - string" ; + fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; + char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; + fates_alloc_organ_name:units = "unitless - string" ; + fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; + 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" ; + 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" ; + double fates_alloc_stor_priority_frac(fates_pft) ; + fates_alloc_stor_priority_frac:units = "unitless" ; + fates_alloc_stor_priority_frac:long_name = "for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage" ; + double fates_alloc_storage_cushion(fates_pft) ; + fates_alloc_storage_cushion:units = "fraction" ; + fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; + double fates_allom_agb1(fates_pft) ; + fates_allom_agb1:units = "variable" ; + fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; + double fates_allom_agb2(fates_pft) ; + fates_allom_agb2:units = "variable" ; + fates_allom_agb2:long_name = "Parameter 2 for agb allometry" ; + double fates_allom_agb3(fates_pft) ; + fates_allom_agb3:units = "variable" ; + fates_allom_agb3:long_name = "Parameter 3 for agb allometry" ; + double fates_allom_agb4(fates_pft) ; + fates_allom_agb4:units = "variable" ; + fates_allom_agb4:long_name = "Parameter 4 for agb allometry" ; + double fates_allom_agb_frac(fates_pft) ; + fates_allom_agb_frac:units = "fraction" ; + fates_allom_agb_frac:long_name = "Fraction of woody biomass that is above ground" ; + double fates_allom_amode(fates_pft) ; + fates_allom_amode:units = "index" ; + fates_allom_amode:long_name = "AGB allometry function index." ; + double fates_allom_blca_expnt_diff(fates_pft) ; + fates_allom_blca_expnt_diff:units = "unitless" ; + fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; + double fates_allom_cmode(fates_pft) ; + fates_allom_cmode:units = "index" ; + fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; + double fates_allom_crown_depth_frac(fates_pft) ; + fates_allom_crown_depth_frac:units = "fraction" ; + fates_allom_crown_depth_frac:long_name = "the depth of a cohort crown as a fraction of its height" ; + double fates_allom_d2bl1(fates_pft) ; + fates_allom_d2bl1:units = "variable" ; + fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; + double fates_allom_d2bl2(fates_pft) ; + fates_allom_d2bl2:units = "variable" ; + fates_allom_d2bl2:long_name = "Parameter 2 for d2bl allometry" ; + double fates_allom_d2bl3(fates_pft) ; + fates_allom_d2bl3:units = "unitless" ; + fates_allom_d2bl3:long_name = "Parameter 3 for d2bl allometry" ; + double fates_allom_d2ca_coefficient_max(fates_pft) ; + fates_allom_d2ca_coefficient_max:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_max:long_name = "max (savanna) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2ca_coefficient_min(fates_pft) ; + fates_allom_d2ca_coefficient_min:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_min:long_name = "min (forest) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2h1(fates_pft) ; + fates_allom_d2h1:units = "variable" ; + fates_allom_d2h1:long_name = "Parameter 1 for d2h allometry (intercept, or c)" ; + double fates_allom_d2h2(fates_pft) ; + fates_allom_d2h2:units = "variable" ; + fates_allom_d2h2:long_name = "Parameter 2 for d2h allometry (slope, or m)" ; + double fates_allom_d2h3(fates_pft) ; + fates_allom_d2h3:units = "variable" ; + fates_allom_d2h3:long_name = "Parameter 3 for d2h allometry (optional)" ; + double fates_allom_dbh_maxheight(fates_pft) ; + fates_allom_dbh_maxheight:units = "cm" ; + fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; + double fates_allom_fmode(fates_pft) ; + fates_allom_fmode:units = "index" ; + fates_allom_fmode:long_name = "fine root biomass allometry function index." ; + double fates_allom_fnrt_prof_a(fates_pft) ; + fates_allom_fnrt_prof_a:units = "unitless" ; + fates_allom_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; + double fates_allom_fnrt_prof_b(fates_pft) ; + fates_allom_fnrt_prof_b:units = "unitless" ; + fates_allom_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; + double fates_allom_fnrt_prof_mode(fates_pft) ; + fates_allom_fnrt_prof_mode:units = "index" ; + fates_allom_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; + double fates_allom_frbstor_repro(fates_pft) ; + fates_allom_frbstor_repro:units = "fraction" ; + fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; + double fates_allom_hmode(fates_pft) ; + fates_allom_hmode:units = "index" ; + fates_allom_hmode:long_name = "height allometry function index." ; + double fates_allom_l2fr(fates_pft) ; + fates_allom_l2fr:units = "gC/gC" ; + fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; + double fates_allom_la_per_sa_int(fates_pft) ; + fates_allom_la_per_sa_int:units = "m2/cm2" ; + fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; + double fates_allom_la_per_sa_slp(fates_pft) ; + fates_allom_la_per_sa_slp:units = "m2/cm2/m" ; + fates_allom_la_per_sa_slp:long_name = "Leaf area per sapwood area rate of change with height, slope (optional)" ; + double fates_allom_lmode(fates_pft) ; + fates_allom_lmode:units = "index" ; + fates_allom_lmode:long_name = "leaf biomass allometry function index." ; + double fates_allom_sai_scaler(fates_pft) ; + fates_allom_sai_scaler:units = "m2/m2" ; + fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; + double fates_allom_smode(fates_pft) ; + fates_allom_smode:units = "index" ; + fates_allom_smode:long_name = "sapwood allometry function index." ; + double fates_allom_stmode(fates_pft) ; + fates_allom_stmode:units = "index" ; + fates_allom_stmode:long_name = "storage allometry function index." ; + double fates_allom_zroot_k(fates_pft) ; + fates_allom_zroot_k:units = "unitless" ; + fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; + double fates_allom_zroot_max_dbh(fates_pft) ; + fates_allom_zroot_max_dbh:units = "cm" ; + fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; + double fates_allom_zroot_max_z(fates_pft) ; + fates_allom_zroot_max_z:units = "m" ; + fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_allom_zroot_min_dbh(fates_pft) ; + fates_allom_zroot_min_dbh:units = "cm" ; + fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; + double fates_allom_zroot_min_z(fates_pft) ; + fates_allom_zroot_min_z:units = "m" ; + fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_c2b(fates_pft) ; + fates_c2b:units = "ratio" ; + fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; + double fates_cnp_eca_alpha_ptase(fates_pft) ; + fates_cnp_eca_alpha_ptase:units = "g/m3" ; + fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; + double fates_cnp_eca_decompmicc(fates_pft) ; + fates_cnp_eca_decompmicc:units = "gC/m3" ; + fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; + double fates_cnp_eca_km_nh4(fates_pft) ; + fates_cnp_eca_km_nh4:units = "gN/m3" ; + fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; + double fates_cnp_eca_km_no3(fates_pft) ; + fates_cnp_eca_km_no3:units = "gN/m3" ; + fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; + double fates_cnp_eca_km_p(fates_pft) ; + fates_cnp_eca_km_p:units = "gP/m3" ; + fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; + double fates_cnp_eca_km_ptase(fates_pft) ; + fates_cnp_eca_km_ptase:units = "gP/m3" ; + fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; + double fates_cnp_eca_lambda_ptase(fates_pft) ; + fates_cnp_eca_lambda_ptase:units = "g/m3" ; + fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; + double fates_cnp_eca_vmax_nh4(fates_pft) ; + fates_cnp_eca_vmax_nh4:units = "gN/gC/s" ; + fates_cnp_eca_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA)" ; + double fates_cnp_eca_vmax_no3(fates_pft) ; + fates_cnp_eca_vmax_no3:units = "gN/gC/s" ; + fates_cnp_eca_vmax_no3:long_name = "maximum production rate for plant no3 uptake (ECA)" ; + double fates_cnp_eca_vmax_ptase(fates_pft) ; + fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; + fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; + double fates_cnp_fnrt_adapt_tscale(fates_pft) ; + fates_cnp_fnrt_adapt_tscale:units = "days" ; + fates_cnp_fnrt_adapt_tscale:long_name = "Number of days that is shortest possible doubling period for fine-root adaptation to C/N/P balance" ; + double fates_cnp_nfix1(fates_pft) ; + fates_cnp_nfix1:units = "NA" ; + fates_cnp_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; + double fates_cnp_nitr_store_ratio(fates_pft) ; + fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; + fates_cnp_nitr_store_ratio:long_name = "storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code)" ; + double fates_cnp_phos_store_ratio(fates_pft) ; + fates_cnp_phos_store_ratio:units = "(gP/gP)" ; + fates_cnp_phos_store_ratio:long_name = "storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code)" ; + double fates_cnp_prescribed_nuptake(fates_pft) ; + fates_cnp_prescribed_nuptake:units = "fraction" ; + fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; + double fates_cnp_prescribed_puptake(fates_pft) ; + fates_cnp_prescribed_puptake:units = "fraction" ; + fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; + double fates_cnp_rd_vmax_n(fates_pft) ; + fates_cnp_rd_vmax_n:units = "gN/gC/s" ; + fates_cnp_rd_vmax_n:long_name = "maximum production rate for compbined (NH4+NO3) uptake (RD)" ; + double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_nitr_retrans:units = "fraction" ; + fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; + double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_phos_retrans:units = "fraction" ; + fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; + double fates_cnp_vmax_p(fates_pft) ; + fates_cnp_vmax_p:units = "gP/gC/s" ; + fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; + double fates_damage_frac(fates_pft) ; + fates_damage_frac:units = "fraction" ; + fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; + double fates_damage_mort_p1(fates_pft) ; + fates_damage_mort_p1:units = "fraction" ; + fates_damage_mort_p1:long_name = "inflection point of damage mortality function, a value of 0.8 means 50% mortality with 80% loss of crown, turn off with a large number" ; + double fates_damage_mort_p2(fates_pft) ; + fates_damage_mort_p2:units = "unitless" ; + fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; + 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_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" ; + double fates_fire_alpha_SH(fates_pft) ; + fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; + fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; + double fates_fire_bark_scaler(fates_pft) ; + fates_fire_bark_scaler:units = "fraction" ; + fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; + double fates_fire_crown_kill(fates_pft) ; + fates_fire_crown_kill:units = "NA" ; + fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; + double fates_frag_fnrt_fcel(fates_pft) ; + fates_frag_fnrt_fcel:units = "fraction" ; + fates_frag_fnrt_fcel:long_name = "Fine root litter cellulose fraction" ; + double fates_frag_fnrt_flab(fates_pft) ; + fates_frag_fnrt_flab:units = "fraction" ; + fates_frag_fnrt_flab:long_name = "Fine root litter labile fraction" ; + double fates_frag_fnrt_flig(fates_pft) ; + fates_frag_fnrt_flig:units = "fraction" ; + fates_frag_fnrt_flig:long_name = "Fine root litter lignin fraction" ; + double fates_frag_leaf_fcel(fates_pft) ; + fates_frag_leaf_fcel:units = "fraction" ; + fates_frag_leaf_fcel:long_name = "Leaf litter cellulose fraction" ; + double fates_frag_leaf_flab(fates_pft) ; + fates_frag_leaf_flab:units = "fraction" ; + fates_frag_leaf_flab:long_name = "Leaf litter labile fraction" ; + double fates_frag_leaf_flig(fates_pft) ; + fates_frag_leaf_flig:units = "fraction" ; + fates_frag_leaf_flig:long_name = "Leaf litter lignin fraction" ; + double fates_frag_seed_decay(fates_pft) ; + fates_frag_seed_decay:units = "yr-1" ; + fates_frag_seed_decay:long_name = "fraction of seeds that decay per year" ; + double fates_grperc(fates_pft) ; + fates_grperc:units = "unitless" ; + fates_grperc:long_name = "Growth respiration factor" ; + double fates_hydro_avuln_gs(fates_pft) ; + fates_hydro_avuln_gs:units = "unitless" ; + fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; + double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; + fates_hydro_avuln_node:units = "unitless" ; + fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; + double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; + fates_hydro_epsil_node:units = "MPa" ; + fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; + double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; + fates_hydro_fcap_node:units = "unitless" ; + fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; + double fates_hydro_k_lwp(fates_pft) ; + fates_hydro_k_lwp:units = "unitless" ; + fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; + double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; + fates_hydro_kmax_node:units = "kg/MPa/m/s" ; + fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; + double fates_hydro_p50_gs(fates_pft) ; + fates_hydro_p50_gs:units = "MPa" ; + fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; + double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; + fates_hydro_p50_node:units = "MPa" ; + fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; + double fates_hydro_p_taper(fates_pft) ; + fates_hydro_p_taper:units = "unitless" ; + fates_hydro_p_taper:long_name = "xylem taper exponent" ; + double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pinot_node:units = "MPa" ; + fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; + double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pitlp_node:units = "MPa" ; + fates_hydro_pitlp_node:long_name = "turgor loss point" ; + double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; + fates_hydro_resid_node:units = "cm3/cm3" ; + fates_hydro_resid_node:long_name = "residual water conent" ; + double fates_hydro_rfrac_stem(fates_pft) ; + fates_hydro_rfrac_stem:units = "fraction" ; + fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; + double fates_hydro_rs2(fates_pft) ; + fates_hydro_rs2:units = "m" ; + fates_hydro_rs2:long_name = "absorbing root radius" ; + double fates_hydro_srl(fates_pft) ; + fates_hydro_srl:units = "m g-1" ; + fates_hydro_srl:long_name = "specific root length" ; + double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; + fates_hydro_thetas_node:units = "cm3/cm3" ; + fates_hydro_thetas_node:long_name = "saturated water content" ; + double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_alpha_node:units = "MPa-1" ; + fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; + double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_m_node:units = "unitless" ; + fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; + 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_leaf_c3psn(fates_pft) ; + fates_leaf_c3psn:units = "flag" ; + fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; + double fates_leaf_jmaxha(fates_pft) ; + fates_leaf_jmaxha:units = "J/mol" ; + fates_leaf_jmaxha:long_name = "activation energy for jmax" ; + double fates_leaf_jmaxhd(fates_pft) ; + fates_leaf_jmaxhd:units = "J/mol" ; + fates_leaf_jmaxhd:long_name = "deactivation energy for jmax" ; + double fates_leaf_jmaxse(fates_pft) ; + fates_leaf_jmaxse:units = "J/mol/K" ; + fates_leaf_jmaxse:long_name = "entropy term for jmax" ; + double fates_leaf_slamax(fates_pft) ; + fates_leaf_slamax:units = "m^2/gC" ; + fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; + double fates_leaf_slatop(fates_pft) ; + fates_leaf_slatop:units = "m^2/gC" ; + fates_leaf_slatop:long_name = "Specific Leaf Area (SLA) at top of canopy, projected area basis" ; + double fates_leaf_stomatal_intercept(fates_pft) ; + fates_leaf_stomatal_intercept:units = "umol H2O/m**2/s" ; + fates_leaf_stomatal_intercept:long_name = "Minimum unstressed stomatal conductance for Ball-Berry model and Medlyn model" ; + double fates_leaf_stomatal_slope_ballberry(fates_pft) ; + fates_leaf_stomatal_slope_ballberry:units = "unitless" ; + fates_leaf_stomatal_slope_ballberry:long_name = "stomatal slope parameter, as per Ball-Berry" ; + double fates_leaf_stomatal_slope_medlyn(fates_pft) ; + fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; + fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; + double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; + fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; + fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; + double fates_leaf_vcmaxha(fates_pft) ; + fates_leaf_vcmaxha:units = "J/mol" ; + fates_leaf_vcmaxha:long_name = "activation energy for vcmax" ; + double fates_leaf_vcmaxhd(fates_pft) ; + fates_leaf_vcmaxhd:units = "J/mol" ; + fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax" ; + double fates_leaf_vcmaxse(fates_pft) ; + fates_leaf_vcmaxse:units = "J/mol/K" ; + fates_leaf_vcmaxse:long_name = "entropy term for vcmax" ; + double fates_maintresp_reduction_curvature(fates_pft) ; + fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; + fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; + double fates_maintresp_reduction_intercept(fates_pft) ; + fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; + fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; + double fates_mort_bmort(fates_pft) ; + fates_mort_bmort:units = "1/yr" ; + fates_mort_bmort:long_name = "background mortality rate" ; + double fates_mort_freezetol(fates_pft) ; + fates_mort_freezetol:units = "degrees C" ; + fates_mort_freezetol:long_name = "minimum temperature tolerance" ; + double fates_mort_hf_flc_threshold(fates_pft) ; + fates_mort_hf_flc_threshold:units = "fraction" ; + fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; + double fates_mort_hf_sm_threshold(fates_pft) ; + fates_mort_hf_sm_threshold:units = "unitless" ; + fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; + double fates_mort_ip_age_senescence(fates_pft) ; + fates_mort_ip_age_senescence:units = "years" ; + fates_mort_ip_age_senescence:long_name = "Mortality cohort age senescence inflection point. If _ this mortality term is off. Setting this value turns on age dependent mortality. " ; + double fates_mort_ip_size_senescence(fates_pft) ; + fates_mort_ip_size_senescence:units = "dbh cm" ; + fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; + double fates_mort_prescribed_canopy(fates_pft) ; + fates_mort_prescribed_canopy:units = "1/yr" ; + fates_mort_prescribed_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; + double fates_mort_prescribed_understory(fates_pft) ; + fates_mort_prescribed_understory:units = "1/yr" ; + fates_mort_prescribed_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; + double fates_mort_r_age_senescence(fates_pft) ; + fates_mort_r_age_senescence:units = "mortality rate year^-1" ; + fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; + double fates_mort_r_size_senescence(fates_pft) ; + fates_mort_r_size_senescence:units = "mortality rate dbh^-1" ; + fates_mort_r_size_senescence:long_name = "Mortality dbh senescence rate of change. Sensible range is around 0.03-0.06. Larger values give steeper mortality curves." ; + double fates_mort_scalar_coldstress(fates_pft) ; + fates_mort_scalar_coldstress:units = "1/yr" ; + fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; + double fates_mort_scalar_cstarvation(fates_pft) ; + fates_mort_scalar_cstarvation:units = "1/yr" ; + fates_mort_scalar_cstarvation:long_name = "maximum mortality rate from carbon starvation" ; + double fates_mort_scalar_hydrfailure(fates_pft) ; + fates_mort_scalar_hydrfailure:units = "1/yr" ; + fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; + double fates_nonhydro_smpsc(fates_pft) ; + fates_nonhydro_smpsc:units = "mm" ; + fates_nonhydro_smpsc:long_name = "Soil water potential at full stomatal closure" ; + double fates_nonhydro_smpso(fates_pft) ; + fates_nonhydro_smpso:units = "mm" ; + fates_nonhydro_smpso:long_name = "Soil water potential at full stomatal opening" ; + double fates_phen_cold_size_threshold(fates_pft) ; + fates_phen_cold_size_threshold:units = "cm" ; + fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; + double fates_phen_evergreen(fates_pft) ; + fates_phen_evergreen:units = "logical flag" ; + fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; + double fates_phen_flushfrac(fates_pft) ; + fates_phen_flushfrac:units = "fraction" ; + fates_phen_flushfrac:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; + double fates_phen_fnrt_drop_frac(fates_pft) ; + fates_phen_fnrt_drop_frac:units = "fraction" ; + fates_phen_fnrt_drop_frac:long_name = "fraction of fine roots to drop during drought or cold" ; + double fates_phen_season_decid(fates_pft) ; + fates_phen_season_decid:units = "logical flag" ; + fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; + double fates_phen_stem_drop_fraction(fates_pft) ; + fates_phen_stem_drop_fraction:units = "fraction" ; + fates_phen_stem_drop_fraction:long_name = "fraction of stems to drop for non-woody species during drought/cold" ; + double fates_phen_stress_decid(fates_pft) ; + fates_phen_stress_decid:units = "logical flag" ; + fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; + double fates_prescribed_npp_canopy(fates_pft) ; + fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; + double fates_prescribed_npp_understory(fates_pft) ; + fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; + double fates_rad_leaf_clumping_index(fates_pft) ; + fates_rad_leaf_clumping_index:units = "fraction (0-1)" ; + fates_rad_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; + double fates_rad_leaf_rhonir(fates_pft) ; + fates_rad_leaf_rhonir:units = "fraction" ; + fates_rad_leaf_rhonir:long_name = "Leaf reflectance: near-IR" ; + double fates_rad_leaf_rhovis(fates_pft) ; + fates_rad_leaf_rhovis:units = "fraction" ; + fates_rad_leaf_rhovis:long_name = "Leaf reflectance: visible" ; + double fates_rad_leaf_taunir(fates_pft) ; + fates_rad_leaf_taunir:units = "fraction" ; + fates_rad_leaf_taunir:long_name = "Leaf transmittance: near-IR" ; + double fates_rad_leaf_tauvis(fates_pft) ; + fates_rad_leaf_tauvis:units = "fraction" ; + fates_rad_leaf_tauvis:long_name = "Leaf transmittance: visible" ; + double fates_rad_leaf_xl(fates_pft) ; + fates_rad_leaf_xl:units = "unitless" ; + fates_rad_leaf_xl:long_name = "Leaf/stem orientation index" ; + double fates_rad_stem_rhonir(fates_pft) ; + fates_rad_stem_rhonir:units = "fraction" ; + fates_rad_stem_rhonir:long_name = "Stem reflectance: near-IR" ; + double fates_rad_stem_rhovis(fates_pft) ; + fates_rad_stem_rhovis:units = "fraction" ; + fates_rad_stem_rhovis:long_name = "Stem reflectance: visible" ; + double fates_rad_stem_taunir(fates_pft) ; + fates_rad_stem_taunir:units = "fraction" ; + fates_rad_stem_taunir:long_name = "Stem transmittance: near-IR" ; + double fates_rad_stem_tauvis(fates_pft) ; + fates_rad_stem_tauvis:units = "fraction" ; + fates_rad_stem_tauvis:long_name = "Stem transmittance: visible" ; + double fates_recruit_height_min(fates_pft) ; + fates_recruit_height_min:units = "m" ; + fates_recruit_height_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; + double fates_recruit_init_density(fates_pft) ; + fates_recruit_init_density:units = "stems/m2" ; + fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation" ; + double fates_recruit_prescribed_rate(fates_pft) ; + fates_recruit_prescribed_rate:units = "n/yr" ; + fates_recruit_prescribed_rate:long_name = "recruitment rate for prescribed physiology mode" ; + double fates_recruit_seed_alloc(fates_pft) ; + fates_recruit_seed_alloc:units = "fraction" ; + fates_recruit_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; + double fates_recruit_seed_alloc_mature(fates_pft) ; + fates_recruit_seed_alloc_mature:units = "fraction" ; + fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; + double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; + fates_recruit_seed_dbh_repro_threshold:units = "cm" ; + fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter (if any) where the plant will start extra clonal allocation to the seed pool" ; + double fates_recruit_seed_germination_rate(fates_pft) ; + fates_recruit_seed_germination_rate:units = "yr-1" ; + fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; + double fates_recruit_seed_supplement(fates_pft) ; + fates_recruit_seed_supplement:units = "KgC/m2/yr" ; + fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; + double fates_stoich_nitr(fates_plant_organs, fates_pft) ; + fates_stoich_nitr:units = "gN/gC" ; + fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; + double fates_stoich_phos(fates_plant_organs, fates_pft) ; + fates_stoich_phos:units = "gP/gC" ; + fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; + double fates_trim_inc(fates_pft) ; + fates_trim_inc:units = "m2/m2" ; + fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; + double fates_trim_limit(fates_pft) ; + fates_trim_limit:units = "m2/m2" ; + fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; + double fates_turb_displar(fates_pft) ; + fates_turb_displar:units = "unitless" ; + fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; + double fates_turb_leaf_diameter(fates_pft) ; + fates_turb_leaf_diameter:units = "m" ; + fates_turb_leaf_diameter:long_name = "Characteristic leaf dimension" ; + double fates_turb_z0mr(fates_pft) ; + fates_turb_z0mr:units = "unitless" ; + fates_turb_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; + double fates_turnover_branch(fates_pft) ; + fates_turnover_branch:units = "yr" ; + fates_turnover_branch:long_name = "turnover time of branches" ; + double fates_turnover_fnrt(fates_pft) ; + fates_turnover_fnrt:units = "yr" ; + fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; + double fates_turnover_leaf(fates_leafage_class, fates_pft) ; + fates_turnover_leaf:units = "yr" ; + fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; + double fates_turnover_senleaf_fdrought(fates_pft) ; + fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; + fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; + double fates_wood_density(fates_pft) ; + fates_wood_density:units = "g/cm3" ; + fates_wood_density:long_name = "mean density of woody tissue in plant" ; + double fates_woody(fates_pft) ; + fates_woody:units = "logical flag" ; + fates_woody:long_name = "Binary woody lifeform flag" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_fire_FBD(fates_litterclass) ; + fates_fire_FBD:units = "kg Biomass/m3" ; + fates_fire_FBD:long_name = "fuel bulk density" ; + double fates_fire_low_moisture_Coeff(fates_litterclass) ; + fates_fire_low_moisture_Coeff:units = "NA" ; + fates_fire_low_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_low_moisture_Slope(fates_litterclass) ; + fates_fire_low_moisture_Slope:units = "NA" ; + fates_fire_low_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture(fates_litterclass) ; + fates_fire_mid_moisture:units = "NA" ; + fates_fire_mid_moisture:long_name = "spitfire litter moisture threshold to be considered medium dry" ; + double fates_fire_mid_moisture_Coeff(fates_litterclass) ; + fates_fire_mid_moisture_Coeff:units = "NA" ; + fates_fire_mid_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture_Slope(fates_litterclass) ; + fates_fire_mid_moisture_Slope:units = "NA" ; + fates_fire_mid_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_min_moisture(fates_litterclass) ; + fates_fire_min_moisture:units = "NA" ; + fates_fire_min_moisture:long_name = "spitfire litter moisture threshold to be considered very dry" ; + double fates_fire_SAV(fates_litterclass) ; + fates_fire_SAV:units = "cm-1" ; + fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; + double fates_frag_maxdecomp(fates_litterclass) ; + fates_frag_maxdecomp:units = "yr-1" ; + fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; + 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_base_mr_20 ; + fates_base_mr_20:units = "gC/gN/s" ; + fates_base_mr_20:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; + 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" ; + double fates_cnp_eca_plant_escalar ; + fates_cnp_eca_plant_escalar:units = "" ; + fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; + double fates_cohort_age_fusion_tol ; + fates_cohort_age_fusion_tol:units = "unitless" ; + fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; + double fates_cohort_size_fusion_tol ; + fates_cohort_size_fusion_tol:units = "unitless" ; + fates_cohort_size_fusion_tol:long_name = "minimum fraction in difference in dbh between cohorts" ; + double fates_comp_excln ; + fates_comp_excln:units = "none" ; + fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; + double fates_dev_arbitrary ; + fates_dev_arbitrary:units = "unknown" ; + fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; + double fates_fire_active_crown_fire ; + fates_fire_active_crown_fire:units = "0 or 1" ; + fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; + double fates_fire_cg_strikes ; + fates_fire_cg_strikes:units = "fraction (0-1)" ; + fates_fire_cg_strikes:long_name = "fraction of cloud to ground lightning strikes" ; + double fates_fire_drying_ratio ; + fates_fire_drying_ratio:units = "NA" ; + fates_fire_drying_ratio:long_name = "spitfire parameter, fire drying ratio for fuel moisture, alpha_FMC EQ 6 Thonicke et al 2010" ; + double fates_fire_durat_slope ; + fates_fire_durat_slope:units = "NA" ; + fates_fire_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; + double fates_fire_fdi_a ; + fates_fire_fdi_a:units = "NA" ; + fates_fire_fdi_a:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010" ; + double fates_fire_fdi_alpha ; + fates_fire_fdi_alpha:units = "NA" ; + fates_fire_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; + double fates_fire_fdi_b ; + fates_fire_fdi_b:units = "NA" ; + fates_fire_fdi_b:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010 " ; + double fates_fire_fuel_energy ; + fates_fire_fuel_energy:units = "kJ/kg" ; + fates_fire_fuel_energy:long_name = "spitfire parameter, heat content of fuel" ; + double fates_fire_max_durat ; + fates_fire_max_durat:units = "minutes" ; + fates_fire_max_durat:long_name = "spitfire parameter, fire maximum duration, Equation 14 Thonicke et al 2010" ; + double fates_fire_miner_damp ; + fates_fire_miner_damp:units = "NA" ; + fates_fire_miner_damp:long_name = "spitfire parameter, mineral-dampening coefficient EQ A1 Thonicke et al 2010 " ; + double fates_fire_miner_total ; + fates_fire_miner_total:units = "fraction" ; + fates_fire_miner_total:long_name = "spitfire parameter, total mineral content, Table A1 Thonicke et al 2010" ; + double fates_fire_nignitions ; + fates_fire_nignitions:units = "ignitions per year per km2" ; + fates_fire_nignitions:long_name = "number of annual ignitions per square km" ; + double fates_fire_part_dens ; + fates_fire_part_dens:units = "kg/m2" ; + fates_fire_part_dens:long_name = "spitfire parameter, oven dry particle density, Table A1 Thonicke et al 2010" ; + double fates_fire_threshold ; + fates_fire_threshold:units = "kW/m" ; + fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; + double fates_frag_cwd_fcel ; + fates_frag_cwd_fcel:units = "unitless" ; + fates_frag_cwd_fcel:long_name = "Cellulose fraction for CWD" ; + double fates_frag_cwd_flig ; + fates_frag_cwd_flig:units = "unitless" ; + fates_frag_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; + double fates_hydro_hydr_kmax_rsurf2 ; + fates_hydro_hydr_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_hydr_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; + double fates_hydro_kmax_rsurf1 ; + fates_hydro_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; + double fates_hydro_psi0 ; + fates_hydro_psi0:units = "MPa" ; + fates_hydro_psi0:long_name = "sapwood water potential at saturation" ; + double fates_hydro_psicap ; + fates_hydro_psicap:units = "MPa" ; + fates_hydro_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; + 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" ; + double fates_leaf_photo_temp_acclim_timescale ; + fates_leaf_photo_temp_acclim_timescale:units = "days" ; + fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; + double fates_leaf_photo_tempsens_model ; + fates_leaf_photo_tempsens_model:units = "unitless" ; + fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; + double fates_leaf_stomatal_assim_model ; + fates_leaf_stomatal_assim_model:units = "unitless" ; + fates_leaf_stomatal_assim_model:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; + double fates_leaf_stomatal_model ; + fates_leaf_stomatal_model:units = "unitless" ; + fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; + double fates_leaf_theta_cj_c3 ; + fates_leaf_theta_cj_c3:units = "unitless" ; + fates_leaf_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; + double fates_leaf_theta_cj_c4 ; + fates_leaf_theta_cj_c4:units = "unitless" ; + fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; + double fates_lu_logging_coll_under_frac ; + fates_lu_logging_coll_under_frac:units = "fraction" ; + fates_lu_logging_coll_under_frac:long_name = "Fraction of stems killed in the understory when logging generates disturbance" ; + double fates_lu_logging_collateral_frac ; + fates_lu_logging_collateral_frac:units = "fraction" ; + fates_lu_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; + double fates_lu_logging_dbhmax ; + fates_lu_logging_dbhmax:units = "cm" ; + fates_lu_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; + double fates_lu_logging_dbhmax_infra ; + fates_lu_logging_dbhmax_infra:units = "cm" ; + fates_lu_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; + double fates_lu_logging_dbhmin ; + fates_lu_logging_dbhmin:units = "cm" ; + fates_lu_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; + double fates_lu_logging_direct_frac ; + fates_lu_logging_direct_frac:units = "fraction" ; + fates_lu_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; + double fates_lu_logging_event_code ; + fates_lu_logging_event_code:units = "unitless" ; + fates_lu_logging_event_code:long_name = "Integer code that options how logging events are structured" ; + double fates_lu_logging_export_frac ; + fates_lu_logging_export_frac:units = "fraction" ; + fates_lu_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; + double fates_lu_logging_mechanical_frac ; + fates_lu_logging_mechanical_frac:units = "fraction" ; + fates_lu_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; + double fates_lu_pprodharv10_forest_mean ; + fates_lu_pprodharv10_forest_mean:units = "fraction" ; + fates_lu_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; + double fates_maintresp_model ; + fates_maintresp_model:units = "unitless" ; + fates_maintresp_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991) (NOT USED)" ; + double fates_maxpatch_primary ; + fates_maxpatch_primary:units = "count" ; + fates_maxpatch_primary:long_name = "maximum number of primary vegetation patches per site" ; + double fates_maxpatch_secondary ; + fates_maxpatch_secondary:units = "count" ; + fates_maxpatch_secondary:long_name = "maximum number of secondary vegetation patches per site" ; + double fates_mort_disturb_frac ; + fates_mort_disturb_frac:units = "fraction" ; + fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; + double fates_mort_understorey_death ; + fates_mort_understorey_death:units = "fraction" ; + fates_mort_understorey_death:long_name = "fraction of plants in understorey cohort impacted by overstorey tree-fall" ; + double fates_patch_fusion_tol ; + fates_patch_fusion_tol:units = "unitless" ; + fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; + double fates_phen_a ; + fates_phen_a:units = "none" ; + fates_phen_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_b ; + fates_phen_b:units = "none" ; + fates_phen_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_c ; + fates_phen_c:units = "none" ; + fates_phen_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_chiltemp ; + fates_phen_chiltemp:units = "degrees C" ; + fates_phen_chiltemp:long_name = "chilling day counting threshold for vegetation" ; + double fates_phen_coldtemp ; + fates_phen_coldtemp:units = "degrees C" ; + fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; + double fates_phen_drought_model ; + fates_phen_drought_model:units = "unitless" ; + fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; + double fates_phen_drought_threshold ; + fates_phen_drought_threshold:units = "m3/m3 or mm" ; + fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_mindaysoff ; + fates_phen_mindaysoff:units = "days" ; + fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves became off-allometry" ; + double fates_phen_mindayson ; + fates_phen_mindayson:units = "days" ; + fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; + double fates_phen_moist_threshold ; + fates_phen_moist_threshold:units = "m3/m3 or mm" ; + fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_ncolddayslim ; + fates_phen_ncolddayslim:units = "days" ; + fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; + double fates_q10_froz ; + fates_q10_froz:units = "unitless" ; + fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; + double fates_q10_mr ; + fates_q10_mr:units = "unitless" ; + fates_q10_mr:long_name = "Q10 for maintenance respiration" ; + double fates_soil_salinity ; + fates_soil_salinity:units = "ppt" ; + fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; + double fates_vai_top_bin_width ; + fates_vai_top_bin_width:units = "m2/m2" ; + fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; + double fates_vai_width_increase_factor ; + fates_vai_width_increase_factor:units = "unitless" ; + fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; + +// global attributes: + :history = "This parameter file is maintained in version control\nSee https://github.com/NGEET/fates/blob/master/parameter_files/fates_params_default.cdl \nFor changes, use git blame \n" ; +data: + + fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; + + fates_history_coageclass_bin_edges = 0, 5 ; + + fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; + + fates_history_damage_bin_edges = 0, 80, 100 ; + + fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, + 80, 90, 100 ; + + fates_alloc_organ_id = 1, 2, 3, 6 ; + + fates_hydr_htftype_node = 1, 1, 1, 1 ; + + fates_pftname = + "broadleaf_evergreen_tropical_tree ", + "needleleaf_evergreen_extratrop_tree ", + "needleleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_tree ", + "broadleaf_hydrodecid_tropical_tree ", + "broadleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_shrub ", + "broadleaf_hydrodecid_extratrop_shrub ", + "broadleaf_colddecid_extratrop_shrub ", + "arctic_c3_grass ", + "cool_c3_grass ", + "c4_grass " ; + + fates_hydro_organ_name = + "leaf ", + "stem ", + "transporting root ", + "absorbing root " ; + + fates_alloc_organ_name = + "leaf", + "fine root", + "sapwood", + "structure" ; + + fates_litterclass_name = + "twig ", + "small branch ", + "large branch ", + "trunk ", + "dead leaves ", + "live grass " ; + + fates_alloc_organ_priority = + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; + + fates_alloc_stor_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8, 0.8 ; + + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + 1.2, 1.2, 1.2 ; + + fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, + 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; + + fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, + 0.572, 0.572, 0.572, 0.572 ; + + fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, + 1.94, 1.94, 1.94 ; + + fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, + 0.931, 0.931, 0.931, 0.931 ; + + fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6 ; + + fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, + 0.95, 1, 1, 1 ; + + fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07 ; + + fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, + 1.3 ; + + fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, + 0.55, 0.55, 0.55 ; + + fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464 ; + + fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119 ; + + fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, + 0.64, 0.64, 0.64 ; + + fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, + 0.37, 0.37, 0.37 ; + + fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, + -999.9, -999.9, -999.9, -999.9, -999.9 ; + + fates_allom_dbh_maxheight = 90, 90, 90, 90, 90, 90, 3, 3, 2, 0.35, 0.35, 0.35 ; + + fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; + + fates_allom_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; + + fates_allom_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8 ; + + fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_zroot_k = 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 ; + + fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; + + fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + + fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 280, 280 ; + + fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, + 0.14, 0.14, 0.14 ; + + fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, + 0.27, 0.27, 0.27 ; + + fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_vmax_nh4 = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_eca_vmax_no3 = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_fnrt_adapt_tscale = 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100 ; + + fates_cnp_nfix1 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_rd_vmax_n = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_turnover_nitr_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_turnover_phos_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, + 5e-10, 5e-10, 5e-10, 5e-10 ; + + fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01 ; + + fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; + + fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, + 5.5, 5.5 ; + + fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2 ; + + fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07, 0.07 ; + + fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, + 0.775, 0.775, 0.775, 0.775, 0.775 ; + + fates_frag_fnrt_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_fnrt_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_fnrt_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_leaf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_seed_decay = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, + 0.51, 0.51, 0.51, 0.51 ; + + fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, + 0.11, 0.11 ; + + fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + 2.5, 2.5 ; + + fates_hydro_avuln_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_hydro_epsil_node = + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_hydro_fcap_node = + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_kmax_node = + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; + + fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + -1.5, -1.5, -1.5 ; + + fates_hydro_p50_node = + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25 ; + + fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, + 0.333, 0.333, 0.333, 0.333, 0.333 ; + + fates_hydro_pinot_node = + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; + + fates_hydro_pitlp_node = + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + -1.67, -1.67, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; + + fates_hydro_resid_node = + 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; + + fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + 0.625, 0.625, 0.625, 0.625, 0.625 ; + + fates_hydro_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, + 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; + + fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; + + fates_hydro_thetas_node = + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; + + fates_hydro_vg_alpha_node = + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005 ; + + fates_hydro_vg_m_node = + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_hydro_vg_n_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_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, + 43540, 43540, 43540, 43540 ; + + fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, + 152040, 152040, 152040, 152040, 152040 ; + + fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, + 495 ; + + fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, + 0.03, 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, + 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, + 10000, 10000, 10000, 10000, 10000, 40000 ; + + fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, + 4.7, 2.2, 5.3, 1.6 ; + + fates_leaf_vcmax25top = + 50, 65, 39, 62, 41, 58, 62, 54, 54, 78, 78, 78 ; + + fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, + 65330, 65330, 65330, 65330 ; + + fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, + 149250, 149250, 149250, 149250, 149250 ; + + fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, + 485 ; + + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; + + fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, + 0.014, 0.014, 0.014, 0.014 ; + + fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -60, -10, -80, -80, + -20, 2.5 ; + + fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, + 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; + + fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_prescribed_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, + 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; + + fates_mort_prescribed_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, + 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; + + fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_nonhydro_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, + -255000, -255000, -255000, -255000, -255000, -255000 ; + + fates_nonhydro_smpso = -66000, -66000, -66000, -66000, -66000, -66000, + -66000, -66000, -66000, -66000, -66000, -66000 ; + + fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; + + fates_phen_flushfrac = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_phen_fnrt_drop_frac = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; + + fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; + + fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, + 0.4, 0.4, 0.4 ; + + fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, + 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; + + fates_rad_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, + 0.9, 0.75, 0.75, 0.75 ; + + fates_rad_leaf_rhonir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, + 0.41, 0.28, 0.28, 0.28 ; + + fates_rad_leaf_rhovis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, + 0.08, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_taunir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, + 0.43, 0.4, 0.4, 0.4 ; + + fates_rad_leaf_tauvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, + 0.06, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, + -0.23, -0.23, -0.23 ; + + fates_rad_stem_rhonir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, + 0.49, 0.53, 0.53, 0.53 ; + + fates_rad_stem_rhovis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.31, 0.31, 0.31 ; + + fates_rad_stem_taunir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.25, 0.25, 0.25 ; + + fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.12, 0.12, 0.12 ; + + fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, + 0.125, 0.125, 0.125 ; + + fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2, 0.2, 0.2 ; + + fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, + 0.02, 0.02, 0.02, 0.02, 0.02 ; + + fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, + 0.9 ; + + fates_recruit_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, + 1.47, 1.47, 1.47 ; + + fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_stoich_nitr = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; + + fates_stoich_phos = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; + + fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, + 0.03, 0.03 ; + + fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; + + fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, + 0.67, 0.67, 0.67 ; + + fates_turb_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.04, 0.04, 0.04, 0.04 ; + + fates_turb_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, + 0.055, 0.055, 0.055, 0.055 ; + + fates_turnover_branch = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; + + fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_leaf = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, + 0.7 ; + + fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; + + fates_hlm_pft_map = + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + + fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; + + fates_fire_low_moisture_Coeff = 1.12, 1.09, 0.98, 0.8, 1.15, 1.15 ; + + fates_fire_low_moisture_Slope = 0.62, 0.72, 0.85, 0.8, 0.62, 0.62 ; + + fates_fire_mid_moisture = 0.72, 0.51, 0.38, 1, 0.8, 0.8 ; + + fates_fire_mid_moisture_Coeff = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_mid_moisture_Slope = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_min_moisture = 0.18, 0.12, 0, 0, 0.24, 0.24 ; + + fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; + + fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; + + fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; + + fates_base_mr_20 = 2.52e-06 ; + + fates_canopy_closure_thresh = 0.8 ; + + fates_cnp_eca_plant_escalar = 1.25e-05 ; + + fates_cohort_age_fusion_tol = 0.08 ; + + fates_cohort_size_fusion_tol = 0.08 ; + + fates_comp_excln = 3 ; + + fates_dev_arbitrary = _ ; + + fates_fire_active_crown_fire = 0 ; + + fates_fire_cg_strikes = 0.2 ; + + fates_fire_drying_ratio = 66000 ; + + fates_fire_durat_slope = -11.06 ; + + fates_fire_fdi_a = 17.62 ; + + fates_fire_fdi_alpha = 0.00037 ; + + fates_fire_fdi_b = 243.12 ; + + fates_fire_fuel_energy = 18000 ; + + fates_fire_max_durat = 240 ; + + fates_fire_miner_damp = 0.41739 ; + + fates_fire_miner_total = 0.055 ; + + fates_fire_nignitions = 15 ; + + fates_fire_part_dens = 513 ; + + fates_fire_threshold = 50 ; + + fates_frag_cwd_fcel = 0.76 ; + + fates_frag_cwd_flig = 0.24 ; + + fates_hydro_hydr_kmax_rsurf2 = 0.0001 ; + + fates_hydro_kmax_rsurf1 = 20 ; + + fates_hydro_psi0 = 0 ; + + fates_hydro_psicap = -0.6 ; + + fates_hydro_solver = 1 ; + + fates_leaf_photo_temp_acclim_timescale = 30 ; + + fates_leaf_photo_tempsens_model = 1 ; + + fates_leaf_stomatal_assim_model = 1 ; + + fates_leaf_stomatal_model = 1 ; + + fates_leaf_theta_cj_c3 = 0.999 ; + + fates_leaf_theta_cj_c4 = 0.999 ; + + fates_lu_logging_coll_under_frac = 0.55983 ; + + fates_lu_logging_collateral_frac = 0.05 ; + + fates_lu_logging_dbhmax = _ ; + + fates_lu_logging_dbhmax_infra = 35 ; + + fates_lu_logging_dbhmin = 50 ; + + fates_lu_logging_direct_frac = 0.15 ; + + fates_lu_logging_event_code = -30 ; + + fates_lu_logging_export_frac = 0.8 ; + + fates_lu_logging_mechanical_frac = 0.05 ; + + fates_lu_pprodharv10_forest_mean = 0.8125 ; + + fates_maintresp_model = 1 ; + + fates_maxpatch_primary = 10 ; + + fates_maxpatch_secondary = 1 ; + + fates_mort_disturb_frac = 1 ; + + fates_mort_understorey_death = 0.55983 ; + + fates_patch_fusion_tol = 0.05 ; + + fates_phen_a = -68 ; + + fates_phen_b = 638 ; + + fates_phen_c = -0.01 ; + + fates_phen_chiltemp = 5 ; + + fates_phen_coldtemp = 7.5 ; + + fates_phen_drought_model = 0 ; + + fates_phen_drought_threshold = 0.15 ; + + fates_phen_mindaysoff = 100 ; + + fates_phen_mindayson = 90 ; + + fates_phen_moist_threshold = 0.18 ; + + fates_phen_ncolddayslim = 5 ; + + fates_q10_froz = 1.5 ; + + fates_q10_mr = 1.5 ; + + fates_soil_salinity = 0.4 ; + + fates_vai_top_bin_width = 1 ; + + fates_vai_width_increase_factor = 1 ; +} diff --git a/parameter_files/fates_params_default_api24_v1.cdl b/parameter_files/fates_params_default_api24_v1.cdl new file mode 100644 index 0000000000..3e2e82edfb --- /dev/null +++ b/parameter_files/fates_params_default_api24_v1.cdl @@ -0,0 +1,1565 @@ +netcdf fates_params_default.c220425_sorted { +dimensions: + fates_NCWD = 4 ; + fates_history_age_bins = 7 ; + fates_history_height_bins = 6 ; + fates_history_size_bins = 13 ; + fates_history_coage_bins = 2 ; + fates_history_damage_bins = 3 ; + fates_hydr_organs = 4 ; + fates_leafage_class = 1 ; + fates_litterclass = 6 ; + fates_pft = 12 ; + fates_prt_organs = 4 ; + fates_string_length = 60 ; + fates_hlm_pftno = 14 ; +variables: + double fates_history_ageclass_bin_edges(fates_history_age_bins) ; + fates_history_ageclass_bin_edges:units = "yr" ; + fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; + double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; + fates_history_coageclass_bin_edges:units = "years" ; + fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; + double fates_history_height_bin_edges(fates_history_height_bins) ; + fates_history_height_bin_edges:units = "m" ; + fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; + double fates_history_damage_bin_edges(fates_history_damage_bins) ; + fates_history_damage_bin_edges:units = "% crown loss" ; + fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; + double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; + fates_history_sizeclass_bin_edges:units = "cm" ; + fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; + double fates_hydr_htftype_node(fates_hydr_organs) ; + fates_hydr_htftype_node:units = "unitless" ; + fates_hydr_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; + fates_hydr_htftype_node:possible_values = "1: Christofferson et al. 2016 (TFS); 2: Van Genuchten 1980" ; + double fates_prt_organ_id(fates_prt_organs) ; + fates_prt_organ_id:units = "index, unitless" ; + fates_prt_organ_id:long_name = "This is the global index the organ in this file is associated with in PRTGenericMod.F90" ; + char fates_pftname(fates_pft, fates_string_length) ; + fates_pftname:units = "unitless - string" ; + fates_pftname:long_name = "Description of plant type" ; + char fates_hydr_organname_node(fates_hydr_organs, fates_string_length) ; + fates_hydr_organname_node:units = "unitless - string" ; + fates_hydr_organname_node:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; + 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_prt_organ_name(fates_prt_organs, fates_string_length) ; + fates_prt_organ_name:units = "unitless - string" ; + fates_prt_organ_name:long_name = "Name of plant organs (order must match PRTGenericMod.F90)" ; + double fates_alloc_storage_cushion(fates_pft) ; + fates_alloc_storage_cushion:units = "fraction" ; + fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; + double fates_allom_agb1(fates_pft) ; + fates_allom_agb1:units = "variable" ; + fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; + double fates_allom_agb2(fates_pft) ; + fates_allom_agb2:units = "variable" ; + fates_allom_agb2:long_name = "Parameter 2 for agb allometry" ; + double fates_allom_agb3(fates_pft) ; + fates_allom_agb3:units = "variable" ; + fates_allom_agb3:long_name = "Parameter 3 for agb allometry" ; + double fates_allom_agb4(fates_pft) ; + fates_allom_agb4:units = "variable" ; + fates_allom_agb4:long_name = "Parameter 4 for agb allometry" ; + double fates_allom_agb_frac(fates_pft) ; + fates_allom_agb_frac:units = "fraction" ; + fates_allom_agb_frac:long_name = "Fraction of woody biomass that is above ground" ; + double fates_allom_amode(fates_pft) ; + fates_allom_amode:units = "index" ; + fates_allom_amode:long_name = "AGB allometry function index." ; + fates_allom_amode:possible_values = "1: Saldarriaga 1998; 2: 2 parameter power law; 3: Chave 2014" ; + double fates_allom_blca_expnt_diff(fates_pft) ; + fates_allom_blca_expnt_diff:units = "unitless" ; + fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; + double fates_allom_cmode(fates_pft) ; + fates_allom_cmode:units = "index" ; + fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; + fates_allom_cmode:possible_values = "1: Constant fraction on AGB" ; + double fates_allom_d2bl1(fates_pft) ; + fates_allom_d2bl1:units = "variable" ; + fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; + double fates_allom_d2bl2(fates_pft) ; + fates_allom_d2bl2:units = "variable" ; + fates_allom_d2bl2:long_name = "Parameter 2 for d2bl allometry" ; + double fates_allom_d2bl3(fates_pft) ; + fates_allom_d2bl3:units = "unitless" ; + fates_allom_d2bl3:long_name = "Parameter 3 for d2bl allometry" ; + double fates_allom_d2ca_coefficient_max(fates_pft) ; + fates_allom_d2ca_coefficient_max:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_max:long_name = "max (savanna) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2ca_coefficient_min(fates_pft) ; + fates_allom_d2ca_coefficient_min:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_min:long_name = "min (forest) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2h1(fates_pft) ; + fates_allom_d2h1:units = "variable" ; + fates_allom_d2h1:long_name = "Parameter 1 for d2h allometry (intercept, or c)" ; + double fates_allom_d2h2(fates_pft) ; + fates_allom_d2h2:units = "variable" ; + fates_allom_d2h2:long_name = "Parameter 2 for d2h allometry (slope, or m)" ; + double fates_allom_d2h3(fates_pft) ; + fates_allom_d2h3:units = "variable" ; + fates_allom_d2h3:long_name = "Parameter 3 for d2h allometry (optional)" ; + double fates_allom_dbh_maxheight(fates_pft) ; + fates_allom_dbh_maxheight:units = "cm" ; + fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; + double fates_allom_fmode(fates_pft) ; + fates_allom_fmode:units = "index" ; + fates_allom_fmode:long_name = "fine root biomass allometry function index." ; + fates_allom_fmode:possible_values = "1: constant fraction of trimmed bleaf; 2: constant fraction of untrimmed bleaf." ; + double fates_allom_frbstor_repro(fates_pft) ; + fates_allom_frbstor_repro:units = "fraction" ; + fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; + double fates_allom_hmode(fates_pft) ; + fates_allom_hmode:units = "index" ; + fates_allom_hmode:long_name = "height allometry function index." ; + fates_allom_hmode:possible_values = "1: OBrien 1995; 2: Poorter 2006; 3: 2 parameter power law; 4: Chave 2014; 5: Martinez-Cano 2019." ; + double fates_allom_l2fr(fates_pft) ; + fates_allom_l2fr:units = "gC/gC" ; + fates_allom_l2fr:long_name = "target fine root C per leaf C. for C-only: constant, for CNP: recruit initial value" ; + double fates_allom_la_per_sa_int(fates_pft) ; + fates_allom_la_per_sa_int:units = "m2/cm2" ; + fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; + double fates_allom_la_per_sa_slp(fates_pft) ; + fates_allom_la_per_sa_slp:units = "m2/cm2/m" ; + fates_allom_la_per_sa_slp:long_name = "Leaf area per sapwood area rate of change with height, slope (optional)" ; + double fates_allom_lmode(fates_pft) ; + fates_allom_lmode:units = "index" ; + fates_allom_lmode:long_name = "leaf biomass allometry function index." ; + fates_allom_lmode:possible_values = "1: Saldarriaga 1998 (capped-dbh power law); 2: generic power law; 3: generic capped-dbh power law." ; + double fates_allom_sai_scaler(fates_pft) ; + fates_allom_sai_scaler:units = "m2/m2" ; + fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; + double fates_allom_smode(fates_pft) ; + fates_allom_smode:units = "index" ; + fates_allom_smode:long_name = "sapwood allometry function index." ; + fates_allom_smode:possible_values = "1: sapwood area proportional to leaf area based on target leaf biomass" ; + double fates_allom_stmode(fates_pft) ; + fates_allom_stmode:units = "index" ; + fates_allom_stmode:long_name = "storage allometry function index." ; + fates_allom_stmode:possible_values = "1: target storage proportional to trimmed maximum leaf biomass." ; + double fates_allom_zroot_k(fates_pft) ; + fates_allom_zroot_k:units = "unitless" ; + fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; + double fates_allom_zroot_max_dbh(fates_pft) ; + fates_allom_zroot_max_dbh:units = "cm" ; + fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; + double fates_allom_zroot_max_z(fates_pft) ; + fates_allom_zroot_max_z:units = "m" ; + fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_allom_zroot_min_dbh(fates_pft) ; + fates_allom_zroot_min_dbh:units = "cm" ; + fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; + double fates_allom_zroot_min_z(fates_pft) ; + fates_allom_zroot_min_z:units = "m" ; + fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_branch_turnover(fates_pft) ; + fates_branch_turnover:units = "yr" ; + fates_branch_turnover:long_name = "turnover time of branches" ; + double fates_c2b(fates_pft) ; + fates_c2b:units = "ratio" ; + fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; + double fates_cnp_eca_alpha_ptase(fates_pft) ; + fates_cnp_eca_alpha_ptase:units = "g/m3" ; + fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; + double fates_cnp_eca_decompmicc(fates_pft) ; + fates_cnp_eca_decompmicc:units = "gC/m3" ; + fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; + double fates_cnp_eca_km_nh4(fates_pft) ; + fates_cnp_eca_km_nh4:units = "gN/m3" ; + fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; + double fates_cnp_eca_km_no3(fates_pft) ; + fates_cnp_eca_km_no3:units = "gN/m3" ; + fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; + double fates_cnp_eca_km_p(fates_pft) ; + fates_cnp_eca_km_p:units = "gP/m3" ; + fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; + double fates_cnp_eca_km_ptase(fates_pft) ; + fates_cnp_eca_km_ptase:units = "gP/m3" ; + fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; + double fates_cnp_eca_lambda_ptase(fates_pft) ; + fates_cnp_eca_lambda_ptase:units = "g/m3" ; + fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; + double fates_cnp_eca_vmax_ptase(fates_pft) ; + fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; + fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; + double fates_cnp_fnrt_adapt_tscale(fates_pft) ; + fates_cnp_fnrt_adapt_tscale:units = "days" ; + fates_cnp_fnrt_adapt_tscale:long_name = "Number of days that is the shortest possible doubling period for fine-root adaptation (CNP only)" ; + double fates_cnp_nfix1(fates_pft) ; + fates_cnp_nfix1:units = "NA" ; + fates_cnp_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; + double fates_cnp_nfix2(fates_pft) ; + fates_cnp_nfix2:units = "NA" ; + fates_cnp_nfix2:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; + double fates_cnp_nitr_store_ratio(fates_pft) ; + fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; + fates_cnp_nitr_store_ratio:long_name = "ratio of storeable N, to functional N bound in cell structures of leaf,root,sap" ; + double fates_cnp_phos_store_ratio(fates_pft) ; + fates_cnp_phos_store_ratio:units = "(gP/gP)" ; + fates_cnp_phos_store_ratio:long_name = "ratio of storeable P, to functional P bound in cell structures of leaf,root,sap" ; + double fates_cnp_prescribed_nuptake(fates_pft) ; + fates_cnp_prescribed_nuptake:units = "fraction" ; + fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; + double fates_cnp_prescribed_puptake(fates_pft) ; + fates_cnp_prescribed_puptake:units = "fraction" ; + fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; + double fates_cnp_vmax_nh4(fates_pft) ; + fates_cnp_vmax_nh4:units = "gN/gC/s" ; + fates_cnp_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA & RD)" ; + double fates_cnp_vmax_no3(fates_pft) ; + fates_cnp_vmax_no3:units = "gN/gC/s" ; + fates_cnp_vmax_no3:long_name = "maximum production rate for plant no3 uptake (ECA & RD)" ; + double fates_cnp_vmax_p(fates_pft) ; + fates_cnp_vmax_p:units = "gP/gC/s" ; + fates_cnp_vmax_p:long_name = "maximum production rate for plant p uptake (ECA & RD)" ; + double fates_allom_crown_depthfrac(fates_pft) ; + fates_allom_crown_depthfrac:units = "fraction" ; + fates_allom_crown_depthfrac:long_name = "the depth of a cohorts crown as a fraction of its height" ; + double fates_damage_frac(fates_pft) ; + fates_damage_frac:units = "fraction" ; + fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; + double fates_damage_mort_p1(fates_pft) ; + fates_damage_mort_p1:units = "fraction crown loss - a value of 0.8 means 50% mortality with 80% loss of crown" ; + fates_damage_mort_p1:long_name = "inflection point of damage mortality function - to turn off damage mortality set this to a large number" ; + double fates_damage_mort_p2(fates_pft) ; + fates_damage_mort_p2:units = "unitless" ; + fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; + double fates_damage_recovery_scalar(fates_pft) ; + fates_damage_recovery_scalar:units = "unitless" ; + fates_damage_recovery_scalar:long_name = "fraction of cohort that recovers from damage" ; + 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" ; + double fates_displar(fates_pft) ; + fates_displar:units = "unitless" ; + fates_displar:long_name = "Ratio of displacement height to canopy top height" ; + double fates_fire_alpha_SH(fates_pft) ; + fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; + fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; + double fates_fire_bark_scaler(fates_pft) ; + fates_fire_bark_scaler:units = "fraction" ; + fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; + double fates_fire_crown_kill(fates_pft) ; + fates_fire_crown_kill:units = "NA" ; + fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; + double fates_fnrt_prof_a(fates_pft) ; + fates_fnrt_prof_a:units = "unitless" ; + fates_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; + double fates_fnrt_prof_b(fates_pft) ; + fates_fnrt_prof_b:units = "unitless" ; + fates_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; + double fates_fnrt_prof_mode(fates_pft) ; + fates_fnrt_prof_mode:units = "index" ; + fates_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; + double fates_fr_fcel(fates_pft) ; + fates_fr_fcel:units = "fraction" ; + fates_fr_fcel:long_name = "Fine root litter cellulose fraction" ; + double fates_fr_flab(fates_pft) ; + fates_fr_flab:units = "fraction" ; + fates_fr_flab:long_name = "Fine root litter labile fraction" ; + double fates_fr_flig(fates_pft) ; + fates_fr_flig:units = "fraction" ; + fates_fr_flig:long_name = "Fine root litter lignin fraction" ; + double fates_grperc(fates_pft) ; + fates_grperc:units = "unitless" ; + fates_grperc:long_name = "Growth respiration factor" ; + double fates_hydr_avuln_gs(fates_pft) ; + fates_hydr_avuln_gs:units = "unitless" ; + fates_hydr_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; + double fates_hydr_avuln_node(fates_hydr_organs, fates_pft) ; + fates_hydr_avuln_node:units = "unitless" ; + fates_hydr_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; + double fates_hydr_epsil_node(fates_hydr_organs, fates_pft) ; + fates_hydr_epsil_node:units = "MPa" ; + fates_hydr_epsil_node:long_name = "bulk elastic modulus" ; + double fates_hydr_fcap_node(fates_hydr_organs, fates_pft) ; + fates_hydr_fcap_node:units = "unitless" ; + fates_hydr_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; + double fates_hydr_k_lwp(fates_pft) ; + fates_hydr_k_lwp:units = "unitless" ; + fates_hydr_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; + fates_hydr_k_lwp:possible_values = "0: turns off leaf humidity effects on conductance. 1-10 activates humidity effects" ; + double fates_hydr_kmax_node(fates_hydr_organs, fates_pft) ; + fates_hydr_kmax_node:units = "kg/MPa/m/s" ; + fates_hydr_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; + double fates_hydr_p50_gs(fates_pft) ; + fates_hydr_p50_gs:units = "MPa" ; + fates_hydr_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; + double fates_hydr_p50_node(fates_hydr_organs, fates_pft) ; + fates_hydr_p50_node:units = "MPa" ; + fates_hydr_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; + double fates_hydr_p_taper(fates_pft) ; + fates_hydr_p_taper:units = "unitless" ; + fates_hydr_p_taper:long_name = "xylem taper exponent" ; + double fates_hydr_pinot_node(fates_hydr_organs, fates_pft) ; + fates_hydr_pinot_node:units = "MPa" ; + fates_hydr_pinot_node:long_name = "osmotic potential at full turgor" ; + double fates_hydr_pitlp_node(fates_hydr_organs, fates_pft) ; + fates_hydr_pitlp_node:units = "MPa" ; + fates_hydr_pitlp_node:long_name = "turgor loss point" ; + double fates_hydr_resid_node(fates_hydr_organs, fates_pft) ; + fates_hydr_resid_node:units = "cm3/cm3" ; + fates_hydr_resid_node:long_name = "residual water conent" ; + double fates_hydr_rfrac_stem(fates_pft) ; + fates_hydr_rfrac_stem:units = "fraction" ; + fates_hydr_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; + double fates_hydr_rs2(fates_pft) ; + fates_hydr_rs2:units = "m" ; + fates_hydr_rs2:long_name = "absorbing root radius" ; + double fates_hydr_srl(fates_pft) ; + fates_hydr_srl:units = "m g-1" ; + fates_hydr_srl:long_name = "specific root length" ; + double fates_hydr_thetas_node(fates_hydr_organs, fates_pft) ; + fates_hydr_thetas_node:units = "cm3/cm3" ; + fates_hydr_thetas_node:long_name = "saturated water content" ; + double fates_hydr_vg_alpha_node(fates_hydr_organs, fates_pft) ; + fates_hydr_vg_alpha_node:units = "MPa-1" ; + fates_hydr_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; + double fates_hydr_vg_m_node(fates_hydr_organs, fates_pft) ; + fates_hydr_vg_m_node:units = "unitless" ; + fates_hydr_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; + double fates_hydr_vg_n_node(fates_hydr_organs, fates_pft) ; + fates_hydr_vg_n_node:units = "unitless" ; + fates_hydr_vg_n_node:long_name = "(used if hydr_htftype_node = 2),n in van Genuchten 1980 model, pore size distribution parameter" ; + double fates_leaf_c3psn(fates_pft) ; + fates_leaf_c3psn:units = "flag" ; + fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; + double fates_leaf_clumping_index(fates_pft) ; + fates_leaf_clumping_index:units = "fraction (0-1)" ; + fates_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; + double fates_leaf_diameter(fates_pft) ; + fates_leaf_diameter:units = "m" ; + fates_leaf_diameter:long_name = "Characteristic leaf dimension" ; + double fates_leaf_jmaxha(fates_pft) ; + fates_leaf_jmaxha:units = "J/mol" ; + fates_leaf_jmaxha:long_name = "activation energy for jmax" ; + double fates_leaf_jmaxhd(fates_pft) ; + fates_leaf_jmaxhd:units = "J/mol" ; + fates_leaf_jmaxhd:long_name = "deactivation energy for jmax" ; + double fates_leaf_jmaxse(fates_pft) ; + fates_leaf_jmaxse:units = "J/mol/K" ; + fates_leaf_jmaxse:long_name = "entropy term for jmax" ; + double fates_leaf_long(fates_leafage_class, fates_pft) ; + fates_leaf_long:units = "yr" ; + fates_leaf_long:long_name = "Leaf longevity (ie turnover timescale)" ; + double fates_leaf_slamax(fates_pft) ; + fates_leaf_slamax:units = "m^2/gC" ; + fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; + double fates_leaf_slatop(fates_pft) ; + fates_leaf_slatop:units = "m^2/gC" ; + fates_leaf_slatop:long_name = "Specific Leaf Area (SLA) at top of canopy, projected area basis" ; + double fates_leaf_stomatal_intercept(fates_pft) ; + fates_leaf_stomatal_intercept:units = "umol H2O/m**2/s" ; + fates_leaf_stomatal_intercept:long_name = "Minimum unstressed stomatal conductance for Ball-Berry model and Medlyn model" ; + double fates_leaf_stomatal_slope_ballberry(fates_pft) ; + fates_leaf_stomatal_slope_ballberry:units = "unitless" ; + fates_leaf_stomatal_slope_ballberry:long_name = "stomatal slope parameter, as per Ball-Berry" ; + double fates_leaf_stomatal_slope_medlyn(fates_pft) ; + fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; + fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; + double fates_leaf_stor_priority(fates_pft) ; + fates_leaf_stor_priority:units = "unitless" ; + fates_leaf_stor_priority:long_name = "factor governing priority of replacing storage with NPP" ; + double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; + fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; + fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; + double fates_leaf_vcmaxha(fates_pft) ; + fates_leaf_vcmaxha:units = "J/mol" ; + fates_leaf_vcmaxha:long_name = "activation energy for vcmax" ; + double fates_leaf_vcmaxhd(fates_pft) ; + fates_leaf_vcmaxhd:units = "J/mol" ; + fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax" ; + double fates_leaf_vcmaxse(fates_pft) ; + fates_leaf_vcmaxse:units = "J/mol/K" ; + fates_leaf_vcmaxse:long_name = "entropy term for vcmax" ; + double fates_leaf_xl(fates_pft) ; + fates_leaf_xl:units = "unitless" ; + fates_leaf_xl:long_name = "Leaf/stem orientation index" ; + double fates_lf_fcel(fates_pft) ; + fates_lf_fcel:units = "fraction" ; + fates_lf_fcel:long_name = "Leaf litter cellulose fraction" ; + double fates_lf_flab(fates_pft) ; + fates_lf_flab:units = "fraction" ; + fates_lf_flab:long_name = "Leaf litter labile fraction" ; + double fates_lf_flig(fates_pft) ; + fates_lf_flig:units = "fraction" ; + fates_lf_flig:long_name = "Leaf litter lignin fraction" ; + double fates_maintresp_reduction_curvature(fates_pft) ; + fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; + fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; + double fates_maintresp_reduction_intercept(fates_pft) ; + fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; + fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; + double fates_mort_bmort(fates_pft) ; + fates_mort_bmort:units = "1/yr" ; + fates_mort_bmort:long_name = "background mortality rate" ; + double fates_mort_freezetol(fates_pft) ; + fates_mort_freezetol:units = "degrees C" ; + fates_mort_freezetol:long_name = "minimum temperature tolerance" ; + double fates_mort_hf_flc_threshold(fates_pft) ; + fates_mort_hf_flc_threshold:units = "fraction" ; + fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; + double fates_mort_hf_sm_threshold(fates_pft) ; + fates_mort_hf_sm_threshold:units = "unitless" ; + fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; + double fates_mort_ip_age_senescence(fates_pft) ; + fates_mort_ip_age_senescence:units = "years" ; + fates_mort_ip_age_senescence:long_name = "Mortality cohort age senescence inflection point. If _ this mortality term is off. Setting this value turns on age dependent mortality. " ; + double fates_mort_ip_size_senescence(fates_pft) ; + fates_mort_ip_size_senescence:units = "dbh cm" ; + fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; + double fates_mort_r_age_senescence(fates_pft) ; + fates_mort_r_age_senescence:units = "mortality rate year^-1" ; + fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; + double fates_mort_r_size_senescence(fates_pft) ; + fates_mort_r_size_senescence:units = "mortality rate dbh^-1" ; + fates_mort_r_size_senescence:long_name = "Mortality dbh senescence rate of change. Sensible range is around 0.03-0.06. Larger values give steeper mortality curves." ; + double fates_mort_scalar_coldstress(fates_pft) ; + fates_mort_scalar_coldstress:units = "1/yr" ; + fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; + double fates_mort_scalar_cstarvation(fates_pft) ; + fates_mort_scalar_cstarvation:units = "1/yr" ; + fates_mort_scalar_cstarvation:long_name = "maximum mortality rate from carbon starvation" ; + double fates_mort_scalar_hydrfailure(fates_pft) ; + fates_mort_scalar_hydrfailure:units = "1/yr" ; + fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; + double fates_phen_cold_size_threshold(fates_pft) ; + fates_phen_cold_size_threshold:units = "cm" ; + fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; + double fates_phen_evergreen(fates_pft) ; + fates_phen_evergreen:units = "logical flag" ; + fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; + double fates_phen_fnrt_drop_fraction(fates_pft) ; + fates_phen_fnrt_drop_fraction:units = "fraction" ; + fates_phen_fnrt_drop_fraction:long_name = "fraction of fine roots to drop during drought/cold" ; + double fates_phen_season_decid(fates_pft) ; + fates_phen_season_decid:units = "logical flag" ; + fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; + double fates_phen_stem_drop_fraction(fates_pft) ; + fates_phen_stem_drop_fraction:units = "fraction" ; + fates_phen_stem_drop_fraction:long_name = "fraction of stems to drop for non-woody species during drought/cold" ; + double fates_phen_stress_decid(fates_pft) ; + fates_phen_stress_decid:units = "logical flag" ; + fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; + double fates_phen_flush_fraction(fates_pft) ; + fates_phen_flush_fraction:units = "fraction" ; + fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; + double fates_prescribed_mortality_canopy(fates_pft) ; + fates_prescribed_mortality_canopy:units = "1/yr" ; + fates_prescribed_mortality_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; + double fates_prescribed_mortality_understory(fates_pft) ; + fates_prescribed_mortality_understory:units = "1/yr" ; + fates_prescribed_mortality_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; + double fates_prescribed_npp_canopy(fates_pft) ; + fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; + double fates_prescribed_npp_understory(fates_pft) ; + fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; + double fates_prescribed_recruitment(fates_pft) ; + fates_prescribed_recruitment:units = "n/yr" ; + fates_prescribed_recruitment:long_name = "recruitment rate for prescribed physiology mode" ; + double fates_prt_alloc_priority(fates_prt_organs, fates_pft) ; + fates_prt_alloc_priority:units = "index (0-fates_prt_organs)" ; + fates_prt_alloc_priority:long_name = "Priority order for allocation (C storage=2)" ; + double fates_prt_nitr_stoich_p1(fates_prt_organs, fates_pft) ; + fates_prt_nitr_stoich_p1:units = "(gN/gC)" ; + fates_prt_nitr_stoich_p1:long_name = "nitrogen stoichiometry, parameter 1" ; + double fates_prt_nitr_stoich_p2(fates_prt_organs, fates_pft) ; + fates_prt_nitr_stoich_p2:units = "(gN/gC)" ; + fates_prt_nitr_stoich_p2:long_name = "nitrogen stoichiometry, parameter 2" ; + double fates_prt_phos_stoich_p1(fates_prt_organs, fates_pft) ; + fates_prt_phos_stoich_p1:units = "(gP/gC)" ; + fates_prt_phos_stoich_p1:long_name = "phosphorous stoichiometry, parameter 1" ; + double fates_prt_phos_stoich_p2(fates_prt_organs, fates_pft) ; + fates_prt_phos_stoich_p2:units = "(gP/gC)" ; + fates_prt_phos_stoich_p2:long_name = "phosphorous stoichiometry, parameter 2" ; + double fates_recruit_hgt_min(fates_pft) ; + fates_recruit_hgt_min:units = "m" ; + fates_recruit_hgt_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; + double fates_recruit_initd(fates_pft) ; + fates_recruit_initd:units = "stems/m2" ; + fates_recruit_initd:long_name = "initial seedling density for a cold-start near-bare-ground simulation" ; + double fates_rholnir(fates_pft) ; + fates_rholnir:units = "fraction" ; + fates_rholnir:long_name = "Leaf reflectance: near-IR" ; + double fates_rholvis(fates_pft) ; + fates_rholvis:units = "fraction" ; + fates_rholvis:long_name = "Leaf reflectance: visible" ; + double fates_rhosnir(fates_pft) ; + fates_rhosnir:units = "fraction" ; + fates_rhosnir:long_name = "Stem reflectance: near-IR" ; + double fates_rhosvis(fates_pft) ; + fates_rhosvis:units = "fraction" ; + fates_rhosvis:long_name = "Stem reflectance: visible" ; + double fates_root_long(fates_pft) ; + fates_root_long:units = "yr" ; + fates_root_long:long_name = "root longevity (alternatively, turnover time)" ; + double fates_seed_alloc(fates_pft) ; + fates_seed_alloc:units = "fraction" ; + fates_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; + double fates_seed_alloc_mature(fates_pft) ; + fates_seed_alloc_mature:units = "fraction" ; + fates_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; + double fates_seed_dbh_repro_threshold(fates_pft) ; + fates_seed_dbh_repro_threshold:units = "cm" ; + fates_seed_dbh_repro_threshold:long_name = "the diameter (if any) where the plant will start extra clonal allocation to the seed pool" ; + double fates_seed_decay_rate(fates_pft) ; + fates_seed_decay_rate:units = "yr-1" ; + fates_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; + double fates_seed_germination_rate(fates_pft) ; + fates_seed_germination_rate:units = "yr-1" ; + fates_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; + double fates_seed_suppl(fates_pft) ; + fates_seed_suppl:units = "KgC/m2/yr" ; + fates_seed_suppl:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; + double fates_senleaf_long_fdrought(fates_pft) ; + fates_senleaf_long_fdrought:units = "unitless[0-1]" ; + fates_senleaf_long_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; + double fates_smpsc(fates_pft) ; + fates_smpsc:units = "mm" ; + fates_smpsc:long_name = "Soil water potential at full stomatal closure" ; + double fates_smpso(fates_pft) ; + fates_smpso:units = "mm" ; + fates_smpso:long_name = "Soil water potential at full stomatal opening" ; + double fates_taulnir(fates_pft) ; + fates_taulnir:units = "fraction" ; + fates_taulnir:long_name = "Leaf transmittance: near-IR" ; + double fates_taulvis(fates_pft) ; + fates_taulvis:units = "fraction" ; + fates_taulvis:long_name = "Leaf transmittance: visible" ; + double fates_tausnir(fates_pft) ; + fates_tausnir:units = "fraction" ; + fates_tausnir:long_name = "Stem transmittance: near-IR" ; + double fates_tausvis(fates_pft) ; + fates_tausvis:units = "fraction" ; + fates_tausvis:long_name = "Stem transmittance: visible" ; + double fates_trim_inc(fates_pft) ; + fates_trim_inc:units = "m2/m2" ; + fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; + double fates_trim_limit(fates_pft) ; + fates_trim_limit:units = "m2/m2" ; + fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; + double fates_turnover_carb_retrans(fates_prt_organs, fates_pft) ; + fates_turnover_carb_retrans:units = "-" ; + fates_turnover_carb_retrans:long_name = "retranslocation fraction of carbon in turnover" ; + double fates_turnover_nitr_retrans(fates_prt_organs, fates_pft) ; + fates_turnover_nitr_retrans:units = "-" ; + fates_turnover_nitr_retrans:long_name = "retranslocation fraction of nitrogen in turnover" ; + double fates_turnover_phos_retrans(fates_prt_organs, fates_pft) ; + fates_turnover_phos_retrans:units = "-" ; + fates_turnover_phos_retrans:long_name = "retranslocation fraction of phosphorous in turnover, parameter 1" ; + double fates_turnover_retrans_mode(fates_pft) ; + fates_turnover_retrans_mode:units = "index" ; + fates_turnover_retrans_mode:long_name = "retranslocation method for leaf/fineroot turnover." ; + fates_turnover_retrans_mode:possible_values = "1: constant fraction." ; + double fates_wood_density(fates_pft) ; + fates_wood_density:units = "g/cm3" ; + fates_wood_density:long_name = "mean density of woody tissue in plant" ; + double fates_woody(fates_pft) ; + fates_woody:units = "logical flag" ; + fates_woody:long_name = "Binary woody lifeform flag" ; + double fates_z0mr(fates_pft) ; + fates_z0mr:units = "unitless" ; + fates_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_fire_FBD(fates_litterclass) ; + fates_fire_FBD:units = "kg Biomass/m3" ; + fates_fire_FBD:long_name = "fuel bulk density" ; + double fates_fire_low_moisture_Coeff(fates_litterclass) ; + fates_fire_low_moisture_Coeff:units = "NA" ; + fates_fire_low_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_low_moisture_Slope(fates_litterclass) ; + fates_fire_low_moisture_Slope:units = "NA" ; + fates_fire_low_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture(fates_litterclass) ; + fates_fire_mid_moisture:units = "NA" ; + fates_fire_mid_moisture:long_name = "spitfire litter moisture threshold to be considered medium dry" ; + double fates_fire_mid_moisture_Coeff(fates_litterclass) ; + fates_fire_mid_moisture_Coeff:units = "NA" ; + fates_fire_mid_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture_Slope(fates_litterclass) ; + fates_fire_mid_moisture_Slope:units = "NA" ; + fates_fire_mid_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_min_moisture(fates_litterclass) ; + fates_fire_min_moisture:units = "NA" ; + fates_fire_min_moisture:long_name = "spitfire litter moisture threshold to be considered very dry" ; + double fates_fire_SAV(fates_litterclass) ; + fates_fire_SAV:units = "cm-1" ; + fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; + double fates_max_decomp(fates_litterclass) ; + fates_max_decomp:units = "yr-1" ; + fates_max_decomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; + double fates_CWD_frac(fates_NCWD) ; + fates_CWD_frac:units = "fraction" ; + fates_CWD_frac:long_name = "fraction of woody (bdead+bsw) biomass destined for CWD pool" ; + double fates_base_mr_20 ; + fates_base_mr_20:units = "gC/gN/s" ; + fates_base_mr_20:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; + 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" ; + double fates_cnp_eca_plant_escalar ; + fates_cnp_eca_plant_escalar:units = "" ; + fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; + double fates_cohort_age_fusion_tol ; + fates_cohort_age_fusion_tol:units = "unitless" ; + fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; + double fates_cohort_size_fusion_tol ; + fates_cohort_size_fusion_tol:units = "unitless" ; + fates_cohort_size_fusion_tol:long_name = "minimum fraction in difference in dbh between cohorts" ; + double fates_comp_excln ; + fates_comp_excln:units = "none" ; + fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; + double fates_cwd_fcel ; + fates_cwd_fcel:units = "unitless" ; + fates_cwd_fcel:long_name = "Cellulose fraction for CWD" ; + double fates_cwd_flig ; + fates_cwd_flig:units = "unitless" ; + fates_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; + double fates_dev_arbitrary ; + fates_dev_arbitrary:units = "unknown" ; + fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; + double fates_fire_active_crown_fire ; + fates_fire_active_crown_fire:units = "0 or 1" ; + fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; + double fates_fire_cg_strikes ; + fates_fire_cg_strikes:units = "fraction (0-1)" ; + fates_fire_cg_strikes:long_name = "fraction of cloud to ground lightning strikes" ; + double fates_fire_drying_ratio ; + fates_fire_drying_ratio:units = "NA" ; + fates_fire_drying_ratio:long_name = "spitfire parameter, fire drying ratio for fuel moisture, alpha_FMC EQ 6 Thonicke et al 2010" ; + double fates_fire_durat_slope ; + fates_fire_durat_slope:units = "NA" ; + fates_fire_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; + double fates_fire_fdi_a ; + fates_fire_fdi_a:units = "NA" ; + fates_fire_fdi_a:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010" ; + double fates_fire_fdi_alpha ; + fates_fire_fdi_alpha:units = "NA" ; + fates_fire_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; + double fates_fire_fdi_b ; + fates_fire_fdi_b:units = "NA" ; + fates_fire_fdi_b:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010 " ; + double fates_fire_fuel_energy ; + fates_fire_fuel_energy:units = "kJ/kg" ; + fates_fire_fuel_energy:long_name = "spitfire parameter, heat content of fuel" ; + double fates_fire_max_durat ; + fates_fire_max_durat:units = "minutes" ; + fates_fire_max_durat:long_name = "spitfire parameter, fire maximum duration, Equation 14 Thonicke et al 2010" ; + double fates_fire_miner_damp ; + fates_fire_miner_damp:units = "NA" ; + fates_fire_miner_damp:long_name = "spitfire parameter, mineral-dampening coefficient EQ A1 Thonicke et al 2010 " ; + double fates_fire_miner_total ; + fates_fire_miner_total:units = "fraction" ; + fates_fire_miner_total:long_name = "spitfire parameter, total mineral content, Table A1 Thonicke et al 2010" ; + double fates_fire_nignitions ; + fates_fire_nignitions:units = "ignitions per year per km2" ; + fates_fire_nignitions:long_name = "number of annual ignitions per square km" ; + double fates_fire_part_dens ; + fates_fire_part_dens:units = "kg/m2" ; + fates_fire_part_dens:long_name = "spitfire parameter, oven dry particle density, Table A1 Thonicke et al 2010" ; + double fates_fire_threshold ; + fates_fire_threshold:units = "kW/m" ; + fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; + double fates_hydr_kmax_rsurf1 ; + fates_hydr_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; + fates_hydr_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; + double fates_hydr_kmax_rsurf2 ; + fates_hydr_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; + fates_hydr_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; + double fates_hydr_psi0 ; + fates_hydr_psi0:units = "MPa" ; + fates_hydr_psi0:long_name = "sapwood water potential at saturation" ; + double fates_hydr_psicap ; + fates_hydr_psicap:units = "MPa" ; + fates_hydr_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; + double fates_hydr_solver ; + fates_hydr_solver:units = "unitless" ; + fates_hydr_solver:long_name = "switch designating which numerical solver for plant hydraulics, 1 = 1D taylor, 2 = 2D Picard" ; + double fates_init_litter ; + fates_init_litter:units = "NA" ; + fates_init_litter:long_name = "Initialization value for litter pool in cold-start (NOT USED)" ; + double fates_leaf_stomatal_model ; + fates_leaf_stomatal_model:units = "unitless" ; + fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; + double fates_logging_coll_under_frac ; + fates_logging_coll_under_frac:units = "fraction" ; + fates_logging_coll_under_frac:long_name = "Fraction of stems killed in the understory when logging generates disturbance" ; + double fates_logging_collateral_frac ; + fates_logging_collateral_frac:units = "fraction" ; + fates_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; + double fates_logging_dbhmax ; + fates_logging_dbhmax:units = "cm" ; + fates_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; + double fates_logging_dbhmax_infra ; + fates_logging_dbhmax_infra:units = "cm" ; + fates_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; + double fates_logging_dbhmin ; + fates_logging_dbhmin:units = "cm" ; + fates_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; + double fates_logging_direct_frac ; + fates_logging_direct_frac:units = "fraction" ; + fates_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; + double fates_logging_event_code ; + fates_logging_event_code:units = "unitless" ; + fates_logging_event_code:long_name = "Integer code that options how logging events are structured" ; + double fates_logging_export_frac ; + fates_logging_export_frac:units = "fraction" ; + fates_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; + double fates_logging_mechanical_frac ; + fates_logging_mechanical_frac:units = "fraction" ; + fates_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; + double fates_maintresp_model ; + fates_maintresp_model:units = "unitless" ; + fates_maintresp_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991) (NOT USED)" ; + double fates_maxpatch_primary ; + fates_maxpatch_primary:units = "unitless" ; + fates_maxpatch_primary:long_name = "maximum number of primary vegetation patches per site" ; + double fates_maxpatch_secondary ; + fates_maxpatch_secondary:units = "unitless" ; + fates_maxpatch_secondary:long_name = "maximum number of secondary vegetation patches per site" ; + double fates_mort_disturb_frac ; + fates_mort_disturb_frac:units = "fraction" ; + fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; + double fates_mort_understorey_death ; + fates_mort_understorey_death:units = "fraction" ; + fates_mort_understorey_death:long_name = "fraction of plants in understorey cohort impacted by overstorey tree-fall" ; + double fates_patch_fusion_tol ; + fates_patch_fusion_tol:units = "unitless" ; + fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; + double fates_phen_a ; + fates_phen_a:units = "none" ; + fates_phen_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_b ; + fates_phen_b:units = "none" ; + fates_phen_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_c ; + fates_phen_c:units = "none" ; + fates_phen_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_chiltemp ; + fates_phen_chiltemp:units = "degrees C" ; + fates_phen_chiltemp:long_name = "chilling day counting threshold for vegetation" ; + double fates_phen_coldtemp ; + fates_phen_coldtemp:units = "degrees C" ; + fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; + double fates_phen_doff_time ; + fates_phen_doff_time:units = "days" ; + fates_phen_doff_time:long_name = "day threshold compared against days since leaves became off-allometry" ; + double fates_phen_drought_model ; + fates_phen_drought_model:units = "none" ; + fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; + double fates_phen_drought_threshold ; + fates_phen_drought_threshold:units = "m3/m3 or mm" ; + fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)." ; + double fates_phen_mindayson ; + fates_phen_mindayson:units = "days" ; + fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; + double fates_phen_moist_threshold ; + fates_phen_moist_threshold:units = "m3/m3 or mm" ; + fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)." ; + double fates_phen_ncolddayslim ; + fates_phen_ncolddayslim:units = "days" ; + fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; + double fates_photo_temp_acclim_timescale ; + fates_photo_temp_acclim_timescale:units = "days" ; + fates_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; + double fates_photo_tempsens_model ; + fates_photo_tempsens_model:units = "unitless" ; + fates_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; + double fates_pprodharv10_forest_mean ; + fates_pprodharv10_forest_mean:units = "fraction" ; + fates_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types." ; + double fates_q10_froz ; + fates_q10_froz:units = "unitless" ; + fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; + double fates_q10_mr ; + fates_q10_mr:units = "unitless" ; + fates_q10_mr:long_name = "Q10 for maintenance respiration" ; + double fates_soil_salinity ; + fates_soil_salinity:units = "ppt" ; + fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; + double fates_stomatal_assim ; + fates_stomatal_assim:units = "unitless" ; + fates_stomatal_assim:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; + double fates_theta_cj_c3 ; + fates_theta_cj_c3:units = "unitless" ; + fates_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; + double fates_theta_cj_c4 ; + fates_theta_cj_c4:units = "unitless" ; + fates_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; + double fates_vai_top_bin_width ; + fates_vai_top_bin_width:units = "m2/m2" ; + fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; + double fates_vai_width_increase_factor ; + fates_vai_width_increase_factor:units = "unitless" ; + fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; + +// global attributes: + :history = "This parameter file is maintained in version control\nSee https://github.com/NGEET/fates/blob/master/parameter_files/fates_params_default.cdl \nFor changes, use git blame \n" ; +data: + + fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; + + fates_history_coageclass_bin_edges = 0, 5 ; + + fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; + + fates_history_damage_bin_edges = 0, 80, 100 ; + + fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, + 80, 90, 100 ; + + fates_hydr_htftype_node = 1, 1, 1, 1 ; + + fates_prt_organ_id = 1, 2, 3, 6 ; + + fates_pftname = + "broadleaf_evergreen_tropical_tree ", + "needleleaf_evergreen_extratrop_tree ", + "needleleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_tree ", + "broadleaf_hydrodecid_tropical_tree ", + "broadleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_shrub ", + "broadleaf_hydrodecid_extratrop_shrub ", + "broadleaf_colddecid_extratrop_shrub ", + "arctic_c3_grass ", + "cool_c3_grass ", + "c4_grass " ; + + fates_hydr_organname_node = + "leaf ", + "stem ", + "transporting root ", + "absorbing root " ; + + fates_litterclass_name = + "twig ", + "small branch ", + "large branch ", + "trunk ", + "dead leaves ", + "live grass " ; + + fates_prt_organ_name = + "leaf ", + "fine root ", + "sapwood ", + "structure " ; + + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + 1.2, 1.2, 1.2 ; + + fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, + 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; + + fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, + 0.572, 0.572, 0.572, 0.572 ; + + fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, + 1.94, 1.94, 1.94 ; + + fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, + 0.931, 0.931, 0.931, 0.931 ; + + fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6 ; + + fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07 ; + + fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, + 1.3 ; + + fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, + 0.55, 0.55, 0.55 ; + + fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464 ; + + fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119 ; + + fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, + 0.64, 0.64, 0.64 ; + + fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, + 0.37, 0.37, 0.37 ; + + fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, + -999.9, -999.9, -999.9, -999.9, -999.9 ; + + fates_allom_dbh_maxheight = 90, 90, 90, 90, 90, 90, 3, 3, 2, 0.35, 0.35, 0.35 ; + + fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8 ; + + fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_zroot_k = 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 ; + + fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; + + fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_branch_turnover = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; + + fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + + fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 280, 280 ; + + fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, + 0.14, 0.14, 0.14 ; + + fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, + 0.27, 0.27, 0.27 ; + + fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_fnrt_adapt_tscale = 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100 ; + + fates_cnp_nfix1 = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_cnp_nfix2 = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_vmax_nh4 = 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, + 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07 ; + + fates_cnp_vmax_no3 = 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, + 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08 ; + + fates_cnp_vmax_p = 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, + 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09 ; + + fates_allom_crown_depthfrac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, 0.95, 1, + 1, 1 ; + + fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01 ; + + fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; + + fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, + 5.5, 5.5 ; + + fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, + 0.67, 0.67 ; + + fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2 ; + + fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07, 0.07 ; + + fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, + 0.775, 0.775, 0.775, 0.775, 0.775 ; + + fates_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; + + fates_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; + + fates_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_fr_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_fr_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25 ; + + fates_fr_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25 ; + + fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, + 0.11, 0.11 ; + + fates_hydr_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + 2.5 ; + + fates_hydr_avuln_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_hydr_epsil_node = + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_hydr_fcap_node = + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydr_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydr_kmax_node = + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; + + fates_hydr_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + -1.5, -1.5, -1.5 ; + + fates_hydr_p50_node = + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25 ; + + fates_hydr_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, + 0.333, 0.333, 0.333, 0.333 ; + + fates_hydr_pinot_node = + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; + + fates_hydr_pitlp_node = + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + -1.67, -1.67, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; + + fates_hydr_resid_node = + 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; + + fates_hydr_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + 0.625, 0.625, 0.625, 0.625, 0.625 ; + + fates_hydr_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, + 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; + + fates_hydr_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; + + fates_hydr_thetas_node = + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; + + fates_hydr_vg_alpha_node = + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005 ; + + fates_hydr_vg_m_node = + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_hydr_vg_n_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_leaf_c3psn = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ; + + fates_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, + 0.9, 0.75, 0.75, 0.75 ; + + fates_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.04, 0.04, 0.04 ; + + fates_leaf_jmaxha = 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, + 43540, 43540, 43540, 43540 ; + + fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, + 152040, 152040, 152040, 152040, 152040 ; + + fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, + 495 ; + + fates_leaf_long = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, + 0.03, 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, + 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, + 10000, 10000, 10000, 10000, 10000, 40000 ; + + fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, + 4.7, 2.2, 5.3, 1.6 ; + + fates_leaf_stor_priority = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8 ; + + fates_leaf_vcmax25top = + 50, 65, 39, 62, 41, 58, 62, 54, 54, 78, 78, 78 ; + + fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, + 65330, 65330, 65330, 65330 ; + + fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, + 149250, 149250, 149250, 149250, 149250 ; + + fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, + 485 ; + + fates_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, -0.23, + -0.23, -0.23 ; + + fates_lf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_lf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25 ; + + fates_lf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25 ; + + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; + + fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, + 0.014, 0.014, 0.014, 0.014 ; + + fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -60, -10, -80, -80, + -20, 2.5 ; + + fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, + 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; + + fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; + + fates_phen_fnrt_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; + + fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; + + fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_prescribed_mortality_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, + 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; + + fates_prescribed_mortality_understory = 0.025, 0.025, 0.025, 0.025, 0.025, + 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; + + fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, + 0.4, 0.4, 0.4 ; + + fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, + 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; + + fates_prescribed_recruitment = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, + 0.02, 0.02, 0.02, 0.02, 0.02 ; + + fates_prt_alloc_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, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; + + fates_prt_nitr_stoich_p1 = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; + + fates_prt_nitr_stoich_p2 = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; + + fates_prt_phos_stoich_p1 = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; + + fates_prt_phos_stoich_p2 = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; + + fates_recruit_hgt_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, + 0.125, 0.125, 0.125 ; + + fates_recruit_initd = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2 ; + + fates_rholnir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, 0.41, 0.28, + 0.28, 0.28 ; + + fates_rholvis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, 0.08, 0.05, + 0.05, 0.05 ; + + fates_rhosnir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, 0.49, 0.53, + 0.53, 0.53 ; + + fates_rhosvis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.31, + 0.31, 0.31 ; + + fates_root_long = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; + + fates_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9 ; + + fates_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, 1.47, + 1.47, 1.47 ; + + fates_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, + 0.51, 0.51, 0.51, 0.51 ; + + fates_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_seed_suppl = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_senleaf_long_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, -255000, + -255000, -255000, -255000, -255000, -255000 ; + + fates_smpso = -66000, -66000, -66000, -66000, -66000, -66000, -66000, + -66000, -66000, -66000, -66000, -66000 ; + + fates_taulnir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, 0.43, 0.4, + 0.4, 0.4 ; + + fates_taulvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.05, + 0.05, 0.05 ; + + fates_tausnir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.25, 0.25, 0.25 ; + + fates_tausvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.12, 0.12, 0.12 ; + + fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, + 0.03, 0.03 ; + + fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; + + fates_turnover_carb_retrans = + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_turnover_nitr_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_turnover_phos_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_turnover_retrans_mode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, + 0.7 ; + + fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; + + fates_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, + 0.055, 0.055, 0.055 ; + + fates_hlm_pft_map = + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + + fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; + + fates_fire_low_moisture_Coeff = 1.12, 1.09, 0.98, 0.8, 1.15, 1.15 ; + + fates_fire_low_moisture_Slope = 0.62, 0.72, 0.85, 0.8, 0.62, 0.62 ; + + fates_fire_mid_moisture = 0.72, 0.51, 0.38, 1, 0.8, 0.8 ; + + fates_fire_mid_moisture_Coeff = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_mid_moisture_Slope = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_min_moisture = 0.18, 0.12, 0, 0, 0.24, 0.24 ; + + fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; + + fates_max_decomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; + + fates_CWD_frac = 0.045, 0.075, 0.21, 0.67 ; + + fates_base_mr_20 = 2.52e-06 ; + + fates_canopy_closure_thresh = 0.8 ; + + fates_cnp_eca_plant_escalar = 1.25e-05 ; + + fates_cohort_age_fusion_tol = 0.08 ; + + fates_cohort_size_fusion_tol = 0.08 ; + + fates_comp_excln = 3 ; + + fates_cwd_fcel = 0.76 ; + + fates_cwd_flig = 0.24 ; + + fates_dev_arbitrary = _ ; + + fates_fire_active_crown_fire = 0 ; + + fates_fire_cg_strikes = 0.2 ; + + fates_fire_drying_ratio = 66000 ; + + fates_fire_durat_slope = -11.06 ; + + fates_fire_fdi_a = 17.62 ; + + fates_fire_fdi_alpha = 0.00037 ; + + fates_fire_fdi_b = 243.12 ; + + fates_fire_fuel_energy = 18000 ; + + fates_fire_max_durat = 240 ; + + fates_fire_miner_damp = 0.41739 ; + + fates_fire_miner_total = 0.055 ; + + fates_fire_nignitions = 15 ; + + fates_fire_part_dens = 513 ; + + fates_fire_threshold = 50 ; + + fates_hydr_kmax_rsurf1 = 20 ; + + fates_hydr_kmax_rsurf2 = 0.0001 ; + + fates_hydr_psi0 = 0 ; + + fates_hydr_psicap = -0.6 ; + + fates_hydr_solver = 1 ; + + fates_init_litter = 0.05 ; + + fates_leaf_stomatal_model = 1 ; + + fates_logging_coll_under_frac = 0.55983 ; + + fates_logging_collateral_frac = 0.05 ; + + fates_logging_dbhmax = _ ; + + fates_logging_dbhmax_infra = 35 ; + + fates_logging_dbhmin = 50 ; + + fates_logging_direct_frac = 0.15 ; + + fates_logging_event_code = -30 ; + + fates_logging_export_frac = 0.8 ; + + fates_logging_mechanical_frac = 0.05 ; + + fates_maintresp_model = 1 ; + + fates_maxpatch_primary = 10 ; + + fates_maxpatch_secondary = 4 ; + + fates_mort_disturb_frac = 1 ; + + fates_mort_understorey_death = 0.55983 ; + + fates_patch_fusion_tol = 0.05 ; + + fates_phen_a = -68 ; + + fates_phen_b = 638 ; + + fates_phen_c = -0.01 ; + + fates_phen_chiltemp = 5 ; + + fates_phen_coldtemp = 7.5 ; + + fates_phen_doff_time = 100 ; + + fates_phen_drought_model = 0 ; + + fates_phen_drought_threshold = 0.15 ; + + fates_phen_mindayson = 90 ; + + fates_phen_moist_threshold = 0.18 ; + + fates_phen_ncolddayslim = 5 ; + + fates_photo_temp_acclim_timescale = 30 ; + + fates_photo_tempsens_model = 1 ; + + fates_pprodharv10_forest_mean = 0.8125 ; + + fates_q10_froz = 1.5 ; + + fates_q10_mr = 1.5 ; + + fates_soil_salinity = 0.4 ; + + fates_stomatal_assim = 1 ; + + fates_theta_cj_c3 = 0.999 ; + + fates_theta_cj_c4 = 0.999 ; + + fates_vai_top_bin_width = 1 ; + + fates_vai_width_increase_factor = 1 ; +} From d14ae29438e09f199230a31279b7691cdcb630a3 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 13 May 2022 19:10:43 -0400 Subject: [PATCH 200/852] Removing parameter file api24 default v1 --- .../fates_params_default_api24_v1.cdl | 1565 ----------------- 1 file changed, 1565 deletions(-) delete mode 100644 parameter_files/fates_params_default_api24_v1.cdl diff --git a/parameter_files/fates_params_default_api24_v1.cdl b/parameter_files/fates_params_default_api24_v1.cdl deleted file mode 100644 index 3e2e82edfb..0000000000 --- a/parameter_files/fates_params_default_api24_v1.cdl +++ /dev/null @@ -1,1565 +0,0 @@ -netcdf fates_params_default.c220425_sorted { -dimensions: - fates_NCWD = 4 ; - fates_history_age_bins = 7 ; - fates_history_height_bins = 6 ; - fates_history_size_bins = 13 ; - fates_history_coage_bins = 2 ; - fates_history_damage_bins = 3 ; - fates_hydr_organs = 4 ; - fates_leafage_class = 1 ; - fates_litterclass = 6 ; - fates_pft = 12 ; - fates_prt_organs = 4 ; - fates_string_length = 60 ; - fates_hlm_pftno = 14 ; -variables: - double fates_history_ageclass_bin_edges(fates_history_age_bins) ; - fates_history_ageclass_bin_edges:units = "yr" ; - fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; - double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; - fates_history_coageclass_bin_edges:units = "years" ; - fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; - double fates_history_height_bin_edges(fates_history_height_bins) ; - fates_history_height_bin_edges:units = "m" ; - fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; - double fates_history_damage_bin_edges(fates_history_damage_bins) ; - fates_history_damage_bin_edges:units = "% crown loss" ; - fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; - double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; - fates_history_sizeclass_bin_edges:units = "cm" ; - fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; - double fates_hydr_htftype_node(fates_hydr_organs) ; - fates_hydr_htftype_node:units = "unitless" ; - fates_hydr_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; - fates_hydr_htftype_node:possible_values = "1: Christofferson et al. 2016 (TFS); 2: Van Genuchten 1980" ; - double fates_prt_organ_id(fates_prt_organs) ; - fates_prt_organ_id:units = "index, unitless" ; - fates_prt_organ_id:long_name = "This is the global index the organ in this file is associated with in PRTGenericMod.F90" ; - char fates_pftname(fates_pft, fates_string_length) ; - fates_pftname:units = "unitless - string" ; - fates_pftname:long_name = "Description of plant type" ; - char fates_hydr_organname_node(fates_hydr_organs, fates_string_length) ; - fates_hydr_organname_node:units = "unitless - string" ; - fates_hydr_organname_node:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; - 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_prt_organ_name(fates_prt_organs, fates_string_length) ; - fates_prt_organ_name:units = "unitless - string" ; - fates_prt_organ_name:long_name = "Name of plant organs (order must match PRTGenericMod.F90)" ; - double fates_alloc_storage_cushion(fates_pft) ; - fates_alloc_storage_cushion:units = "fraction" ; - fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; - double fates_allom_agb1(fates_pft) ; - fates_allom_agb1:units = "variable" ; - fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; - double fates_allom_agb2(fates_pft) ; - fates_allom_agb2:units = "variable" ; - fates_allom_agb2:long_name = "Parameter 2 for agb allometry" ; - double fates_allom_agb3(fates_pft) ; - fates_allom_agb3:units = "variable" ; - fates_allom_agb3:long_name = "Parameter 3 for agb allometry" ; - double fates_allom_agb4(fates_pft) ; - fates_allom_agb4:units = "variable" ; - fates_allom_agb4:long_name = "Parameter 4 for agb allometry" ; - double fates_allom_agb_frac(fates_pft) ; - fates_allom_agb_frac:units = "fraction" ; - fates_allom_agb_frac:long_name = "Fraction of woody biomass that is above ground" ; - double fates_allom_amode(fates_pft) ; - fates_allom_amode:units = "index" ; - fates_allom_amode:long_name = "AGB allometry function index." ; - fates_allom_amode:possible_values = "1: Saldarriaga 1998; 2: 2 parameter power law; 3: Chave 2014" ; - double fates_allom_blca_expnt_diff(fates_pft) ; - fates_allom_blca_expnt_diff:units = "unitless" ; - fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; - double fates_allom_cmode(fates_pft) ; - fates_allom_cmode:units = "index" ; - fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; - fates_allom_cmode:possible_values = "1: Constant fraction on AGB" ; - double fates_allom_d2bl1(fates_pft) ; - fates_allom_d2bl1:units = "variable" ; - fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; - double fates_allom_d2bl2(fates_pft) ; - fates_allom_d2bl2:units = "variable" ; - fates_allom_d2bl2:long_name = "Parameter 2 for d2bl allometry" ; - double fates_allom_d2bl3(fates_pft) ; - fates_allom_d2bl3:units = "unitless" ; - fates_allom_d2bl3:long_name = "Parameter 3 for d2bl allometry" ; - double fates_allom_d2ca_coefficient_max(fates_pft) ; - fates_allom_d2ca_coefficient_max:units = "m2 cm^(-1/beta)" ; - fates_allom_d2ca_coefficient_max:long_name = "max (savanna) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; - double fates_allom_d2ca_coefficient_min(fates_pft) ; - fates_allom_d2ca_coefficient_min:units = "m2 cm^(-1/beta)" ; - fates_allom_d2ca_coefficient_min:long_name = "min (forest) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; - double fates_allom_d2h1(fates_pft) ; - fates_allom_d2h1:units = "variable" ; - fates_allom_d2h1:long_name = "Parameter 1 for d2h allometry (intercept, or c)" ; - double fates_allom_d2h2(fates_pft) ; - fates_allom_d2h2:units = "variable" ; - fates_allom_d2h2:long_name = "Parameter 2 for d2h allometry (slope, or m)" ; - double fates_allom_d2h3(fates_pft) ; - fates_allom_d2h3:units = "variable" ; - fates_allom_d2h3:long_name = "Parameter 3 for d2h allometry (optional)" ; - double fates_allom_dbh_maxheight(fates_pft) ; - fates_allom_dbh_maxheight:units = "cm" ; - fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; - double fates_allom_fmode(fates_pft) ; - fates_allom_fmode:units = "index" ; - fates_allom_fmode:long_name = "fine root biomass allometry function index." ; - fates_allom_fmode:possible_values = "1: constant fraction of trimmed bleaf; 2: constant fraction of untrimmed bleaf." ; - double fates_allom_frbstor_repro(fates_pft) ; - fates_allom_frbstor_repro:units = "fraction" ; - fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; - double fates_allom_hmode(fates_pft) ; - fates_allom_hmode:units = "index" ; - fates_allom_hmode:long_name = "height allometry function index." ; - fates_allom_hmode:possible_values = "1: OBrien 1995; 2: Poorter 2006; 3: 2 parameter power law; 4: Chave 2014; 5: Martinez-Cano 2019." ; - double fates_allom_l2fr(fates_pft) ; - fates_allom_l2fr:units = "gC/gC" ; - fates_allom_l2fr:long_name = "target fine root C per leaf C. for C-only: constant, for CNP: recruit initial value" ; - double fates_allom_la_per_sa_int(fates_pft) ; - fates_allom_la_per_sa_int:units = "m2/cm2" ; - fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; - double fates_allom_la_per_sa_slp(fates_pft) ; - fates_allom_la_per_sa_slp:units = "m2/cm2/m" ; - fates_allom_la_per_sa_slp:long_name = "Leaf area per sapwood area rate of change with height, slope (optional)" ; - double fates_allom_lmode(fates_pft) ; - fates_allom_lmode:units = "index" ; - fates_allom_lmode:long_name = "leaf biomass allometry function index." ; - fates_allom_lmode:possible_values = "1: Saldarriaga 1998 (capped-dbh power law); 2: generic power law; 3: generic capped-dbh power law." ; - double fates_allom_sai_scaler(fates_pft) ; - fates_allom_sai_scaler:units = "m2/m2" ; - fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; - double fates_allom_smode(fates_pft) ; - fates_allom_smode:units = "index" ; - fates_allom_smode:long_name = "sapwood allometry function index." ; - fates_allom_smode:possible_values = "1: sapwood area proportional to leaf area based on target leaf biomass" ; - double fates_allom_stmode(fates_pft) ; - fates_allom_stmode:units = "index" ; - fates_allom_stmode:long_name = "storage allometry function index." ; - fates_allom_stmode:possible_values = "1: target storage proportional to trimmed maximum leaf biomass." ; - double fates_allom_zroot_k(fates_pft) ; - fates_allom_zroot_k:units = "unitless" ; - fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; - double fates_allom_zroot_max_dbh(fates_pft) ; - fates_allom_zroot_max_dbh:units = "cm" ; - fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; - double fates_allom_zroot_max_z(fates_pft) ; - fates_allom_zroot_max_z:units = "m" ; - fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; - double fates_allom_zroot_min_dbh(fates_pft) ; - fates_allom_zroot_min_dbh:units = "cm" ; - fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; - double fates_allom_zroot_min_z(fates_pft) ; - fates_allom_zroot_min_z:units = "m" ; - fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; - double fates_branch_turnover(fates_pft) ; - fates_branch_turnover:units = "yr" ; - fates_branch_turnover:long_name = "turnover time of branches" ; - double fates_c2b(fates_pft) ; - fates_c2b:units = "ratio" ; - fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; - double fates_cnp_eca_alpha_ptase(fates_pft) ; - fates_cnp_eca_alpha_ptase:units = "g/m3" ; - fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; - double fates_cnp_eca_decompmicc(fates_pft) ; - fates_cnp_eca_decompmicc:units = "gC/m3" ; - fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; - double fates_cnp_eca_km_nh4(fates_pft) ; - fates_cnp_eca_km_nh4:units = "gN/m3" ; - fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; - double fates_cnp_eca_km_no3(fates_pft) ; - fates_cnp_eca_km_no3:units = "gN/m3" ; - fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; - double fates_cnp_eca_km_p(fates_pft) ; - fates_cnp_eca_km_p:units = "gP/m3" ; - fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; - double fates_cnp_eca_km_ptase(fates_pft) ; - fates_cnp_eca_km_ptase:units = "gP/m3" ; - fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; - double fates_cnp_eca_lambda_ptase(fates_pft) ; - fates_cnp_eca_lambda_ptase:units = "g/m3" ; - fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; - double fates_cnp_eca_vmax_ptase(fates_pft) ; - fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; - fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; - double fates_cnp_fnrt_adapt_tscale(fates_pft) ; - fates_cnp_fnrt_adapt_tscale:units = "days" ; - fates_cnp_fnrt_adapt_tscale:long_name = "Number of days that is the shortest possible doubling period for fine-root adaptation (CNP only)" ; - double fates_cnp_nfix1(fates_pft) ; - fates_cnp_nfix1:units = "NA" ; - fates_cnp_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; - double fates_cnp_nfix2(fates_pft) ; - fates_cnp_nfix2:units = "NA" ; - fates_cnp_nfix2:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; - double fates_cnp_nitr_store_ratio(fates_pft) ; - fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; - fates_cnp_nitr_store_ratio:long_name = "ratio of storeable N, to functional N bound in cell structures of leaf,root,sap" ; - double fates_cnp_phos_store_ratio(fates_pft) ; - fates_cnp_phos_store_ratio:units = "(gP/gP)" ; - fates_cnp_phos_store_ratio:long_name = "ratio of storeable P, to functional P bound in cell structures of leaf,root,sap" ; - double fates_cnp_prescribed_nuptake(fates_pft) ; - fates_cnp_prescribed_nuptake:units = "fraction" ; - fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; - double fates_cnp_prescribed_puptake(fates_pft) ; - fates_cnp_prescribed_puptake:units = "fraction" ; - fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; - double fates_cnp_vmax_nh4(fates_pft) ; - fates_cnp_vmax_nh4:units = "gN/gC/s" ; - fates_cnp_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA & RD)" ; - double fates_cnp_vmax_no3(fates_pft) ; - fates_cnp_vmax_no3:units = "gN/gC/s" ; - fates_cnp_vmax_no3:long_name = "maximum production rate for plant no3 uptake (ECA & RD)" ; - double fates_cnp_vmax_p(fates_pft) ; - fates_cnp_vmax_p:units = "gP/gC/s" ; - fates_cnp_vmax_p:long_name = "maximum production rate for plant p uptake (ECA & RD)" ; - double fates_allom_crown_depthfrac(fates_pft) ; - fates_allom_crown_depthfrac:units = "fraction" ; - fates_allom_crown_depthfrac:long_name = "the depth of a cohorts crown as a fraction of its height" ; - double fates_damage_frac(fates_pft) ; - fates_damage_frac:units = "fraction" ; - fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; - double fates_damage_mort_p1(fates_pft) ; - fates_damage_mort_p1:units = "fraction crown loss - a value of 0.8 means 50% mortality with 80% loss of crown" ; - fates_damage_mort_p1:long_name = "inflection point of damage mortality function - to turn off damage mortality set this to a large number" ; - double fates_damage_mort_p2(fates_pft) ; - fates_damage_mort_p2:units = "unitless" ; - fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; - double fates_damage_recovery_scalar(fates_pft) ; - fates_damage_recovery_scalar:units = "unitless" ; - fates_damage_recovery_scalar:long_name = "fraction of cohort that recovers from damage" ; - 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" ; - double fates_displar(fates_pft) ; - fates_displar:units = "unitless" ; - fates_displar:long_name = "Ratio of displacement height to canopy top height" ; - double fates_fire_alpha_SH(fates_pft) ; - fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; - fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; - double fates_fire_bark_scaler(fates_pft) ; - fates_fire_bark_scaler:units = "fraction" ; - fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; - double fates_fire_crown_kill(fates_pft) ; - fates_fire_crown_kill:units = "NA" ; - fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; - double fates_fnrt_prof_a(fates_pft) ; - fates_fnrt_prof_a:units = "unitless" ; - fates_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; - double fates_fnrt_prof_b(fates_pft) ; - fates_fnrt_prof_b:units = "unitless" ; - fates_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; - double fates_fnrt_prof_mode(fates_pft) ; - fates_fnrt_prof_mode:units = "index" ; - fates_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; - double fates_fr_fcel(fates_pft) ; - fates_fr_fcel:units = "fraction" ; - fates_fr_fcel:long_name = "Fine root litter cellulose fraction" ; - double fates_fr_flab(fates_pft) ; - fates_fr_flab:units = "fraction" ; - fates_fr_flab:long_name = "Fine root litter labile fraction" ; - double fates_fr_flig(fates_pft) ; - fates_fr_flig:units = "fraction" ; - fates_fr_flig:long_name = "Fine root litter lignin fraction" ; - double fates_grperc(fates_pft) ; - fates_grperc:units = "unitless" ; - fates_grperc:long_name = "Growth respiration factor" ; - double fates_hydr_avuln_gs(fates_pft) ; - fates_hydr_avuln_gs:units = "unitless" ; - fates_hydr_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; - double fates_hydr_avuln_node(fates_hydr_organs, fates_pft) ; - fates_hydr_avuln_node:units = "unitless" ; - fates_hydr_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; - double fates_hydr_epsil_node(fates_hydr_organs, fates_pft) ; - fates_hydr_epsil_node:units = "MPa" ; - fates_hydr_epsil_node:long_name = "bulk elastic modulus" ; - double fates_hydr_fcap_node(fates_hydr_organs, fates_pft) ; - fates_hydr_fcap_node:units = "unitless" ; - fates_hydr_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; - double fates_hydr_k_lwp(fates_pft) ; - fates_hydr_k_lwp:units = "unitless" ; - fates_hydr_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; - fates_hydr_k_lwp:possible_values = "0: turns off leaf humidity effects on conductance. 1-10 activates humidity effects" ; - double fates_hydr_kmax_node(fates_hydr_organs, fates_pft) ; - fates_hydr_kmax_node:units = "kg/MPa/m/s" ; - fates_hydr_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; - double fates_hydr_p50_gs(fates_pft) ; - fates_hydr_p50_gs:units = "MPa" ; - fates_hydr_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; - double fates_hydr_p50_node(fates_hydr_organs, fates_pft) ; - fates_hydr_p50_node:units = "MPa" ; - fates_hydr_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; - double fates_hydr_p_taper(fates_pft) ; - fates_hydr_p_taper:units = "unitless" ; - fates_hydr_p_taper:long_name = "xylem taper exponent" ; - double fates_hydr_pinot_node(fates_hydr_organs, fates_pft) ; - fates_hydr_pinot_node:units = "MPa" ; - fates_hydr_pinot_node:long_name = "osmotic potential at full turgor" ; - double fates_hydr_pitlp_node(fates_hydr_organs, fates_pft) ; - fates_hydr_pitlp_node:units = "MPa" ; - fates_hydr_pitlp_node:long_name = "turgor loss point" ; - double fates_hydr_resid_node(fates_hydr_organs, fates_pft) ; - fates_hydr_resid_node:units = "cm3/cm3" ; - fates_hydr_resid_node:long_name = "residual water conent" ; - double fates_hydr_rfrac_stem(fates_pft) ; - fates_hydr_rfrac_stem:units = "fraction" ; - fates_hydr_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; - double fates_hydr_rs2(fates_pft) ; - fates_hydr_rs2:units = "m" ; - fates_hydr_rs2:long_name = "absorbing root radius" ; - double fates_hydr_srl(fates_pft) ; - fates_hydr_srl:units = "m g-1" ; - fates_hydr_srl:long_name = "specific root length" ; - double fates_hydr_thetas_node(fates_hydr_organs, fates_pft) ; - fates_hydr_thetas_node:units = "cm3/cm3" ; - fates_hydr_thetas_node:long_name = "saturated water content" ; - double fates_hydr_vg_alpha_node(fates_hydr_organs, fates_pft) ; - fates_hydr_vg_alpha_node:units = "MPa-1" ; - fates_hydr_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; - double fates_hydr_vg_m_node(fates_hydr_organs, fates_pft) ; - fates_hydr_vg_m_node:units = "unitless" ; - fates_hydr_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; - double fates_hydr_vg_n_node(fates_hydr_organs, fates_pft) ; - fates_hydr_vg_n_node:units = "unitless" ; - fates_hydr_vg_n_node:long_name = "(used if hydr_htftype_node = 2),n in van Genuchten 1980 model, pore size distribution parameter" ; - double fates_leaf_c3psn(fates_pft) ; - fates_leaf_c3psn:units = "flag" ; - fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; - double fates_leaf_clumping_index(fates_pft) ; - fates_leaf_clumping_index:units = "fraction (0-1)" ; - fates_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; - double fates_leaf_diameter(fates_pft) ; - fates_leaf_diameter:units = "m" ; - fates_leaf_diameter:long_name = "Characteristic leaf dimension" ; - double fates_leaf_jmaxha(fates_pft) ; - fates_leaf_jmaxha:units = "J/mol" ; - fates_leaf_jmaxha:long_name = "activation energy for jmax" ; - double fates_leaf_jmaxhd(fates_pft) ; - fates_leaf_jmaxhd:units = "J/mol" ; - fates_leaf_jmaxhd:long_name = "deactivation energy for jmax" ; - double fates_leaf_jmaxse(fates_pft) ; - fates_leaf_jmaxse:units = "J/mol/K" ; - fates_leaf_jmaxse:long_name = "entropy term for jmax" ; - double fates_leaf_long(fates_leafage_class, fates_pft) ; - fates_leaf_long:units = "yr" ; - fates_leaf_long:long_name = "Leaf longevity (ie turnover timescale)" ; - double fates_leaf_slamax(fates_pft) ; - fates_leaf_slamax:units = "m^2/gC" ; - fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; - double fates_leaf_slatop(fates_pft) ; - fates_leaf_slatop:units = "m^2/gC" ; - fates_leaf_slatop:long_name = "Specific Leaf Area (SLA) at top of canopy, projected area basis" ; - double fates_leaf_stomatal_intercept(fates_pft) ; - fates_leaf_stomatal_intercept:units = "umol H2O/m**2/s" ; - fates_leaf_stomatal_intercept:long_name = "Minimum unstressed stomatal conductance for Ball-Berry model and Medlyn model" ; - double fates_leaf_stomatal_slope_ballberry(fates_pft) ; - fates_leaf_stomatal_slope_ballberry:units = "unitless" ; - fates_leaf_stomatal_slope_ballberry:long_name = "stomatal slope parameter, as per Ball-Berry" ; - double fates_leaf_stomatal_slope_medlyn(fates_pft) ; - fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; - fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; - double fates_leaf_stor_priority(fates_pft) ; - fates_leaf_stor_priority:units = "unitless" ; - fates_leaf_stor_priority:long_name = "factor governing priority of replacing storage with NPP" ; - double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; - fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; - fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; - double fates_leaf_vcmaxha(fates_pft) ; - fates_leaf_vcmaxha:units = "J/mol" ; - fates_leaf_vcmaxha:long_name = "activation energy for vcmax" ; - double fates_leaf_vcmaxhd(fates_pft) ; - fates_leaf_vcmaxhd:units = "J/mol" ; - fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax" ; - double fates_leaf_vcmaxse(fates_pft) ; - fates_leaf_vcmaxse:units = "J/mol/K" ; - fates_leaf_vcmaxse:long_name = "entropy term for vcmax" ; - double fates_leaf_xl(fates_pft) ; - fates_leaf_xl:units = "unitless" ; - fates_leaf_xl:long_name = "Leaf/stem orientation index" ; - double fates_lf_fcel(fates_pft) ; - fates_lf_fcel:units = "fraction" ; - fates_lf_fcel:long_name = "Leaf litter cellulose fraction" ; - double fates_lf_flab(fates_pft) ; - fates_lf_flab:units = "fraction" ; - fates_lf_flab:long_name = "Leaf litter labile fraction" ; - double fates_lf_flig(fates_pft) ; - fates_lf_flig:units = "fraction" ; - fates_lf_flig:long_name = "Leaf litter lignin fraction" ; - double fates_maintresp_reduction_curvature(fates_pft) ; - fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; - fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; - double fates_maintresp_reduction_intercept(fates_pft) ; - fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; - fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; - double fates_mort_bmort(fates_pft) ; - fates_mort_bmort:units = "1/yr" ; - fates_mort_bmort:long_name = "background mortality rate" ; - double fates_mort_freezetol(fates_pft) ; - fates_mort_freezetol:units = "degrees C" ; - fates_mort_freezetol:long_name = "minimum temperature tolerance" ; - double fates_mort_hf_flc_threshold(fates_pft) ; - fates_mort_hf_flc_threshold:units = "fraction" ; - fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; - double fates_mort_hf_sm_threshold(fates_pft) ; - fates_mort_hf_sm_threshold:units = "unitless" ; - fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; - double fates_mort_ip_age_senescence(fates_pft) ; - fates_mort_ip_age_senescence:units = "years" ; - fates_mort_ip_age_senescence:long_name = "Mortality cohort age senescence inflection point. If _ this mortality term is off. Setting this value turns on age dependent mortality. " ; - double fates_mort_ip_size_senescence(fates_pft) ; - fates_mort_ip_size_senescence:units = "dbh cm" ; - fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; - double fates_mort_r_age_senescence(fates_pft) ; - fates_mort_r_age_senescence:units = "mortality rate year^-1" ; - fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; - double fates_mort_r_size_senescence(fates_pft) ; - fates_mort_r_size_senescence:units = "mortality rate dbh^-1" ; - fates_mort_r_size_senescence:long_name = "Mortality dbh senescence rate of change. Sensible range is around 0.03-0.06. Larger values give steeper mortality curves." ; - double fates_mort_scalar_coldstress(fates_pft) ; - fates_mort_scalar_coldstress:units = "1/yr" ; - fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; - double fates_mort_scalar_cstarvation(fates_pft) ; - fates_mort_scalar_cstarvation:units = "1/yr" ; - fates_mort_scalar_cstarvation:long_name = "maximum mortality rate from carbon starvation" ; - double fates_mort_scalar_hydrfailure(fates_pft) ; - fates_mort_scalar_hydrfailure:units = "1/yr" ; - fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; - double fates_phen_cold_size_threshold(fates_pft) ; - fates_phen_cold_size_threshold:units = "cm" ; - fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; - double fates_phen_evergreen(fates_pft) ; - fates_phen_evergreen:units = "logical flag" ; - fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; - double fates_phen_fnrt_drop_fraction(fates_pft) ; - fates_phen_fnrt_drop_fraction:units = "fraction" ; - fates_phen_fnrt_drop_fraction:long_name = "fraction of fine roots to drop during drought/cold" ; - double fates_phen_season_decid(fates_pft) ; - fates_phen_season_decid:units = "logical flag" ; - fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; - double fates_phen_stem_drop_fraction(fates_pft) ; - fates_phen_stem_drop_fraction:units = "fraction" ; - fates_phen_stem_drop_fraction:long_name = "fraction of stems to drop for non-woody species during drought/cold" ; - double fates_phen_stress_decid(fates_pft) ; - fates_phen_stress_decid:units = "logical flag" ; - fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; - double fates_phen_flush_fraction(fates_pft) ; - fates_phen_flush_fraction:units = "fraction" ; - fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; - double fates_prescribed_mortality_canopy(fates_pft) ; - fates_prescribed_mortality_canopy:units = "1/yr" ; - fates_prescribed_mortality_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; - double fates_prescribed_mortality_understory(fates_pft) ; - fates_prescribed_mortality_understory:units = "1/yr" ; - fates_prescribed_mortality_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; - double fates_prescribed_npp_canopy(fates_pft) ; - fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; - fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; - double fates_prescribed_npp_understory(fates_pft) ; - fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; - fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; - double fates_prescribed_recruitment(fates_pft) ; - fates_prescribed_recruitment:units = "n/yr" ; - fates_prescribed_recruitment:long_name = "recruitment rate for prescribed physiology mode" ; - double fates_prt_alloc_priority(fates_prt_organs, fates_pft) ; - fates_prt_alloc_priority:units = "index (0-fates_prt_organs)" ; - fates_prt_alloc_priority:long_name = "Priority order for allocation (C storage=2)" ; - double fates_prt_nitr_stoich_p1(fates_prt_organs, fates_pft) ; - fates_prt_nitr_stoich_p1:units = "(gN/gC)" ; - fates_prt_nitr_stoich_p1:long_name = "nitrogen stoichiometry, parameter 1" ; - double fates_prt_nitr_stoich_p2(fates_prt_organs, fates_pft) ; - fates_prt_nitr_stoich_p2:units = "(gN/gC)" ; - fates_prt_nitr_stoich_p2:long_name = "nitrogen stoichiometry, parameter 2" ; - double fates_prt_phos_stoich_p1(fates_prt_organs, fates_pft) ; - fates_prt_phos_stoich_p1:units = "(gP/gC)" ; - fates_prt_phos_stoich_p1:long_name = "phosphorous stoichiometry, parameter 1" ; - double fates_prt_phos_stoich_p2(fates_prt_organs, fates_pft) ; - fates_prt_phos_stoich_p2:units = "(gP/gC)" ; - fates_prt_phos_stoich_p2:long_name = "phosphorous stoichiometry, parameter 2" ; - double fates_recruit_hgt_min(fates_pft) ; - fates_recruit_hgt_min:units = "m" ; - fates_recruit_hgt_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; - double fates_recruit_initd(fates_pft) ; - fates_recruit_initd:units = "stems/m2" ; - fates_recruit_initd:long_name = "initial seedling density for a cold-start near-bare-ground simulation" ; - double fates_rholnir(fates_pft) ; - fates_rholnir:units = "fraction" ; - fates_rholnir:long_name = "Leaf reflectance: near-IR" ; - double fates_rholvis(fates_pft) ; - fates_rholvis:units = "fraction" ; - fates_rholvis:long_name = "Leaf reflectance: visible" ; - double fates_rhosnir(fates_pft) ; - fates_rhosnir:units = "fraction" ; - fates_rhosnir:long_name = "Stem reflectance: near-IR" ; - double fates_rhosvis(fates_pft) ; - fates_rhosvis:units = "fraction" ; - fates_rhosvis:long_name = "Stem reflectance: visible" ; - double fates_root_long(fates_pft) ; - fates_root_long:units = "yr" ; - fates_root_long:long_name = "root longevity (alternatively, turnover time)" ; - double fates_seed_alloc(fates_pft) ; - fates_seed_alloc:units = "fraction" ; - fates_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; - double fates_seed_alloc_mature(fates_pft) ; - fates_seed_alloc_mature:units = "fraction" ; - fates_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; - double fates_seed_dbh_repro_threshold(fates_pft) ; - fates_seed_dbh_repro_threshold:units = "cm" ; - fates_seed_dbh_repro_threshold:long_name = "the diameter (if any) where the plant will start extra clonal allocation to the seed pool" ; - double fates_seed_decay_rate(fates_pft) ; - fates_seed_decay_rate:units = "yr-1" ; - fates_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; - double fates_seed_germination_rate(fates_pft) ; - fates_seed_germination_rate:units = "yr-1" ; - fates_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; - double fates_seed_suppl(fates_pft) ; - fates_seed_suppl:units = "KgC/m2/yr" ; - fates_seed_suppl:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; - double fates_senleaf_long_fdrought(fates_pft) ; - fates_senleaf_long_fdrought:units = "unitless[0-1]" ; - fates_senleaf_long_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; - double fates_smpsc(fates_pft) ; - fates_smpsc:units = "mm" ; - fates_smpsc:long_name = "Soil water potential at full stomatal closure" ; - double fates_smpso(fates_pft) ; - fates_smpso:units = "mm" ; - fates_smpso:long_name = "Soil water potential at full stomatal opening" ; - double fates_taulnir(fates_pft) ; - fates_taulnir:units = "fraction" ; - fates_taulnir:long_name = "Leaf transmittance: near-IR" ; - double fates_taulvis(fates_pft) ; - fates_taulvis:units = "fraction" ; - fates_taulvis:long_name = "Leaf transmittance: visible" ; - double fates_tausnir(fates_pft) ; - fates_tausnir:units = "fraction" ; - fates_tausnir:long_name = "Stem transmittance: near-IR" ; - double fates_tausvis(fates_pft) ; - fates_tausvis:units = "fraction" ; - fates_tausvis:long_name = "Stem transmittance: visible" ; - double fates_trim_inc(fates_pft) ; - fates_trim_inc:units = "m2/m2" ; - fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; - double fates_trim_limit(fates_pft) ; - fates_trim_limit:units = "m2/m2" ; - fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; - double fates_turnover_carb_retrans(fates_prt_organs, fates_pft) ; - fates_turnover_carb_retrans:units = "-" ; - fates_turnover_carb_retrans:long_name = "retranslocation fraction of carbon in turnover" ; - double fates_turnover_nitr_retrans(fates_prt_organs, fates_pft) ; - fates_turnover_nitr_retrans:units = "-" ; - fates_turnover_nitr_retrans:long_name = "retranslocation fraction of nitrogen in turnover" ; - double fates_turnover_phos_retrans(fates_prt_organs, fates_pft) ; - fates_turnover_phos_retrans:units = "-" ; - fates_turnover_phos_retrans:long_name = "retranslocation fraction of phosphorous in turnover, parameter 1" ; - double fates_turnover_retrans_mode(fates_pft) ; - fates_turnover_retrans_mode:units = "index" ; - fates_turnover_retrans_mode:long_name = "retranslocation method for leaf/fineroot turnover." ; - fates_turnover_retrans_mode:possible_values = "1: constant fraction." ; - double fates_wood_density(fates_pft) ; - fates_wood_density:units = "g/cm3" ; - fates_wood_density:long_name = "mean density of woody tissue in plant" ; - double fates_woody(fates_pft) ; - fates_woody:units = "logical flag" ; - fates_woody:long_name = "Binary woody lifeform flag" ; - double fates_z0mr(fates_pft) ; - fates_z0mr:units = "unitless" ; - fates_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; - double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; - fates_hlm_pft_map:units = "area fraction" ; - fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; - double fates_fire_FBD(fates_litterclass) ; - fates_fire_FBD:units = "kg Biomass/m3" ; - fates_fire_FBD:long_name = "fuel bulk density" ; - double fates_fire_low_moisture_Coeff(fates_litterclass) ; - fates_fire_low_moisture_Coeff:units = "NA" ; - fates_fire_low_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_low_moisture_Slope(fates_litterclass) ; - fates_fire_low_moisture_Slope:units = "NA" ; - fates_fire_low_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_mid_moisture(fates_litterclass) ; - fates_fire_mid_moisture:units = "NA" ; - fates_fire_mid_moisture:long_name = "spitfire litter moisture threshold to be considered medium dry" ; - double fates_fire_mid_moisture_Coeff(fates_litterclass) ; - fates_fire_mid_moisture_Coeff:units = "NA" ; - fates_fire_mid_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_mid_moisture_Slope(fates_litterclass) ; - fates_fire_mid_moisture_Slope:units = "NA" ; - fates_fire_mid_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_min_moisture(fates_litterclass) ; - fates_fire_min_moisture:units = "NA" ; - fates_fire_min_moisture:long_name = "spitfire litter moisture threshold to be considered very dry" ; - double fates_fire_SAV(fates_litterclass) ; - fates_fire_SAV:units = "cm-1" ; - fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; - double fates_max_decomp(fates_litterclass) ; - fates_max_decomp:units = "yr-1" ; - fates_max_decomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; - double fates_CWD_frac(fates_NCWD) ; - fates_CWD_frac:units = "fraction" ; - fates_CWD_frac:long_name = "fraction of woody (bdead+bsw) biomass destined for CWD pool" ; - double fates_base_mr_20 ; - fates_base_mr_20:units = "gC/gN/s" ; - fates_base_mr_20:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; - 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" ; - double fates_cnp_eca_plant_escalar ; - fates_cnp_eca_plant_escalar:units = "" ; - fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; - double fates_cohort_age_fusion_tol ; - fates_cohort_age_fusion_tol:units = "unitless" ; - fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; - double fates_cohort_size_fusion_tol ; - fates_cohort_size_fusion_tol:units = "unitless" ; - fates_cohort_size_fusion_tol:long_name = "minimum fraction in difference in dbh between cohorts" ; - double fates_comp_excln ; - fates_comp_excln:units = "none" ; - fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; - double fates_cwd_fcel ; - fates_cwd_fcel:units = "unitless" ; - fates_cwd_fcel:long_name = "Cellulose fraction for CWD" ; - double fates_cwd_flig ; - fates_cwd_flig:units = "unitless" ; - fates_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; - double fates_dev_arbitrary ; - fates_dev_arbitrary:units = "unknown" ; - fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; - double fates_fire_active_crown_fire ; - fates_fire_active_crown_fire:units = "0 or 1" ; - fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; - double fates_fire_cg_strikes ; - fates_fire_cg_strikes:units = "fraction (0-1)" ; - fates_fire_cg_strikes:long_name = "fraction of cloud to ground lightning strikes" ; - double fates_fire_drying_ratio ; - fates_fire_drying_ratio:units = "NA" ; - fates_fire_drying_ratio:long_name = "spitfire parameter, fire drying ratio for fuel moisture, alpha_FMC EQ 6 Thonicke et al 2010" ; - double fates_fire_durat_slope ; - fates_fire_durat_slope:units = "NA" ; - fates_fire_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; - double fates_fire_fdi_a ; - fates_fire_fdi_a:units = "NA" ; - fates_fire_fdi_a:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010" ; - double fates_fire_fdi_alpha ; - fates_fire_fdi_alpha:units = "NA" ; - fates_fire_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; - double fates_fire_fdi_b ; - fates_fire_fdi_b:units = "NA" ; - fates_fire_fdi_b:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010 " ; - double fates_fire_fuel_energy ; - fates_fire_fuel_energy:units = "kJ/kg" ; - fates_fire_fuel_energy:long_name = "spitfire parameter, heat content of fuel" ; - double fates_fire_max_durat ; - fates_fire_max_durat:units = "minutes" ; - fates_fire_max_durat:long_name = "spitfire parameter, fire maximum duration, Equation 14 Thonicke et al 2010" ; - double fates_fire_miner_damp ; - fates_fire_miner_damp:units = "NA" ; - fates_fire_miner_damp:long_name = "spitfire parameter, mineral-dampening coefficient EQ A1 Thonicke et al 2010 " ; - double fates_fire_miner_total ; - fates_fire_miner_total:units = "fraction" ; - fates_fire_miner_total:long_name = "spitfire parameter, total mineral content, Table A1 Thonicke et al 2010" ; - double fates_fire_nignitions ; - fates_fire_nignitions:units = "ignitions per year per km2" ; - fates_fire_nignitions:long_name = "number of annual ignitions per square km" ; - double fates_fire_part_dens ; - fates_fire_part_dens:units = "kg/m2" ; - fates_fire_part_dens:long_name = "spitfire parameter, oven dry particle density, Table A1 Thonicke et al 2010" ; - double fates_fire_threshold ; - fates_fire_threshold:units = "kW/m" ; - fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; - double fates_hydr_kmax_rsurf1 ; - fates_hydr_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; - fates_hydr_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; - double fates_hydr_kmax_rsurf2 ; - fates_hydr_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; - fates_hydr_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; - double fates_hydr_psi0 ; - fates_hydr_psi0:units = "MPa" ; - fates_hydr_psi0:long_name = "sapwood water potential at saturation" ; - double fates_hydr_psicap ; - fates_hydr_psicap:units = "MPa" ; - fates_hydr_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; - double fates_hydr_solver ; - fates_hydr_solver:units = "unitless" ; - fates_hydr_solver:long_name = "switch designating which numerical solver for plant hydraulics, 1 = 1D taylor, 2 = 2D Picard" ; - double fates_init_litter ; - fates_init_litter:units = "NA" ; - fates_init_litter:long_name = "Initialization value for litter pool in cold-start (NOT USED)" ; - double fates_leaf_stomatal_model ; - fates_leaf_stomatal_model:units = "unitless" ; - fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; - double fates_logging_coll_under_frac ; - fates_logging_coll_under_frac:units = "fraction" ; - fates_logging_coll_under_frac:long_name = "Fraction of stems killed in the understory when logging generates disturbance" ; - double fates_logging_collateral_frac ; - fates_logging_collateral_frac:units = "fraction" ; - fates_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; - double fates_logging_dbhmax ; - fates_logging_dbhmax:units = "cm" ; - fates_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; - double fates_logging_dbhmax_infra ; - fates_logging_dbhmax_infra:units = "cm" ; - fates_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; - double fates_logging_dbhmin ; - fates_logging_dbhmin:units = "cm" ; - fates_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; - double fates_logging_direct_frac ; - fates_logging_direct_frac:units = "fraction" ; - fates_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; - double fates_logging_event_code ; - fates_logging_event_code:units = "unitless" ; - fates_logging_event_code:long_name = "Integer code that options how logging events are structured" ; - double fates_logging_export_frac ; - fates_logging_export_frac:units = "fraction" ; - fates_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; - double fates_logging_mechanical_frac ; - fates_logging_mechanical_frac:units = "fraction" ; - fates_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; - double fates_maintresp_model ; - fates_maintresp_model:units = "unitless" ; - fates_maintresp_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991) (NOT USED)" ; - double fates_maxpatch_primary ; - fates_maxpatch_primary:units = "unitless" ; - fates_maxpatch_primary:long_name = "maximum number of primary vegetation patches per site" ; - double fates_maxpatch_secondary ; - fates_maxpatch_secondary:units = "unitless" ; - fates_maxpatch_secondary:long_name = "maximum number of secondary vegetation patches per site" ; - double fates_mort_disturb_frac ; - fates_mort_disturb_frac:units = "fraction" ; - fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; - double fates_mort_understorey_death ; - fates_mort_understorey_death:units = "fraction" ; - fates_mort_understorey_death:long_name = "fraction of plants in understorey cohort impacted by overstorey tree-fall" ; - double fates_patch_fusion_tol ; - fates_patch_fusion_tol:units = "unitless" ; - fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; - double fates_phen_a ; - fates_phen_a:units = "none" ; - fates_phen_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_b ; - fates_phen_b:units = "none" ; - fates_phen_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_c ; - fates_phen_c:units = "none" ; - fates_phen_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_chiltemp ; - fates_phen_chiltemp:units = "degrees C" ; - fates_phen_chiltemp:long_name = "chilling day counting threshold for vegetation" ; - double fates_phen_coldtemp ; - fates_phen_coldtemp:units = "degrees C" ; - fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; - double fates_phen_doff_time ; - fates_phen_doff_time:units = "days" ; - fates_phen_doff_time:long_name = "day threshold compared against days since leaves became off-allometry" ; - double fates_phen_drought_model ; - fates_phen_drought_model:units = "none" ; - fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; - double fates_phen_drought_threshold ; - fates_phen_drought_threshold:units = "m3/m3 or mm" ; - fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)." ; - double fates_phen_mindayson ; - fates_phen_mindayson:units = "days" ; - fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; - double fates_phen_moist_threshold ; - fates_phen_moist_threshold:units = "m3/m3 or mm" ; - fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)." ; - double fates_phen_ncolddayslim ; - fates_phen_ncolddayslim:units = "days" ; - fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; - double fates_photo_temp_acclim_timescale ; - fates_photo_temp_acclim_timescale:units = "days" ; - fates_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; - double fates_photo_tempsens_model ; - fates_photo_tempsens_model:units = "unitless" ; - fates_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; - double fates_pprodharv10_forest_mean ; - fates_pprodharv10_forest_mean:units = "fraction" ; - fates_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types." ; - double fates_q10_froz ; - fates_q10_froz:units = "unitless" ; - fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; - double fates_q10_mr ; - fates_q10_mr:units = "unitless" ; - fates_q10_mr:long_name = "Q10 for maintenance respiration" ; - double fates_soil_salinity ; - fates_soil_salinity:units = "ppt" ; - fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; - double fates_stomatal_assim ; - fates_stomatal_assim:units = "unitless" ; - fates_stomatal_assim:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; - double fates_theta_cj_c3 ; - fates_theta_cj_c3:units = "unitless" ; - fates_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; - double fates_theta_cj_c4 ; - fates_theta_cj_c4:units = "unitless" ; - fates_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; - double fates_vai_top_bin_width ; - fates_vai_top_bin_width:units = "m2/m2" ; - fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; - double fates_vai_width_increase_factor ; - fates_vai_width_increase_factor:units = "unitless" ; - fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; - -// global attributes: - :history = "This parameter file is maintained in version control\nSee https://github.com/NGEET/fates/blob/master/parameter_files/fates_params_default.cdl \nFor changes, use git blame \n" ; -data: - - fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; - - fates_history_coageclass_bin_edges = 0, 5 ; - - fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; - - fates_history_damage_bin_edges = 0, 80, 100 ; - - fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, - 80, 90, 100 ; - - fates_hydr_htftype_node = 1, 1, 1, 1 ; - - fates_prt_organ_id = 1, 2, 3, 6 ; - - fates_pftname = - "broadleaf_evergreen_tropical_tree ", - "needleleaf_evergreen_extratrop_tree ", - "needleleaf_colddecid_extratrop_tree ", - "broadleaf_evergreen_extratrop_tree ", - "broadleaf_hydrodecid_tropical_tree ", - "broadleaf_colddecid_extratrop_tree ", - "broadleaf_evergreen_extratrop_shrub ", - "broadleaf_hydrodecid_extratrop_shrub ", - "broadleaf_colddecid_extratrop_shrub ", - "arctic_c3_grass ", - "cool_c3_grass ", - "c4_grass " ; - - fates_hydr_organname_node = - "leaf ", - "stem ", - "transporting root ", - "absorbing root " ; - - fates_litterclass_name = - "twig ", - "small branch ", - "large branch ", - "trunk ", - "dead leaves ", - "live grass " ; - - fates_prt_organ_name = - "leaf ", - "fine root ", - "sapwood ", - "structure " ; - - fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, - 1.2, 1.2, 1.2 ; - - fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, - 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; - - fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, - 0.572, 0.572, 0.572, 0.572 ; - - fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, - 1.94, 1.94, 1.94 ; - - fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, - 0.931, 0.931, 0.931, 0.931 ; - - fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6 ; - - fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, - 0.07, 0.07, 0.07 ; - - fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, - 1.3 ; - - fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, - 0.55, 0.55, 0.55 ; - - fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464 ; - - fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119 ; - - fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, - 0.64, 0.64, 0.64 ; - - fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, - 0.37, 0.37, 0.37 ; - - fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, - -999.9, -999.9, -999.9, -999.9, -999.9 ; - - fates_allom_dbh_maxheight = 90, 90, 90, 90, 90, 90, 3, 3, 2, 0.35, 0.35, 0.35 ; - - fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, - 0.8, 0.8, 0.8 ; - - fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1, 0.1 ; - - fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_zroot_k = 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 ; - - fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; - - fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100 ; - - fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1 ; - - fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100 ; - - fates_branch_turnover = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; - - fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; - - fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5 ; - - fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, - 280, 280 ; - - fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, - 0.14, 0.14, 0.14 ; - - fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, - 0.27, 0.27, 0.27 ; - - fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1 ; - - fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, - 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - - fates_cnp_fnrt_adapt_tscale = 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100, 100 ; - - fates_cnp_nfix1 = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_cnp_nfix2 = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5, 1.5 ; - - fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5, 1.5 ; - - fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_vmax_nh4 = 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, - 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07 ; - - fates_cnp_vmax_no3 = 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, - 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08 ; - - fates_cnp_vmax_p = 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, - 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09 ; - - fates_allom_crown_depthfrac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, 0.95, 1, - 1, 1 ; - - fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, - 0.01, 0.01, 0.01 ; - - fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; - - fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, - 5.5, 5.5 ; - - fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, - 0.67, 0.67 ; - - fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, - 0.2 ; - - fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, - 0.07, 0.07, 0.07, 0.07 ; - - fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, - 0.775, 0.775, 0.775, 0.775, 0.775 ; - - fates_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; - - fates_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; - - fates_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - - fates_fr_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_fr_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25 ; - - fates_fr_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25 ; - - fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, - 0.11, 0.11 ; - - fates_hydr_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, - 2.5 ; - - fates_hydr_avuln_node = - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 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_hydr_epsil_node = - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - - fates_hydr_fcap_node = - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, - 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_hydr_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_hydr_kmax_node = - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; - - fates_hydr_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, - -1.5, -1.5, -1.5 ; - - fates_hydr_p50_node = - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25 ; - - fates_hydr_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, - 0.333, 0.333, 0.333, 0.333 ; - - fates_hydr_pinot_node = - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; - - fates_hydr_pitlp_node = - -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, - -1.67, -1.67, - -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, - -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, - -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; - - fates_hydr_resid_node = - 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, - 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - - fates_hydr_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, - 0.625, 0.625, 0.625, 0.625, 0.625 ; - - fates_hydr_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, - 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; - - fates_hydr_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; - - fates_hydr_thetas_node = - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; - - fates_hydr_vg_alpha_node = - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005 ; - - fates_hydr_vg_m_node = - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_hydr_vg_n_node = - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 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_leaf_c3psn = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ; - - fates_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, - 0.9, 0.75, 0.75, 0.75 ; - - fates_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.04, 0.04, 0.04 ; - - fates_leaf_jmaxha = 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, - 43540, 43540, 43540, 43540 ; - - fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, - 152040, 152040, 152040, 152040, 152040 ; - - fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, - 495 ; - - fates_leaf_long = - 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - - fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, - 0.03, 0.03, 0.03, 0.03, 0.03 ; - - fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, - 0.03, 0.03, 0.03, 0.03 ; - - fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, - 10000, 10000, 10000, 10000, 10000, 40000 ; - - fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - - fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, - 4.7, 2.2, 5.3, 1.6 ; - - fates_leaf_stor_priority = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, - 0.8, 0.8 ; - - fates_leaf_vcmax25top = - 50, 65, 39, 62, 41, 58, 62, 54, 54, 78, 78, 78 ; - - fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, - 65330, 65330, 65330, 65330 ; - - fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, - 149250, 149250, 149250, 149250, 149250 ; - - fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, - 485 ; - - fates_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, -0.23, - -0.23, -0.23 ; - - fates_lf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_lf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25 ; - - fates_lf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25 ; - - fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, - 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; - - fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, - 0.014, 0.014, 0.014, 0.014 ; - - fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -60, -10, -80, -80, - -20, 2.5 ; - - fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5 ; - - fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, - 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; - - fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - - fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6, 0.6 ; - - fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6, 0.6 ; - - fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; - - fates_phen_fnrt_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; - - fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; - - fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_prescribed_mortality_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, - 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; - - fates_prescribed_mortality_understory = 0.025, 0.025, 0.025, 0.025, 0.025, - 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; - - fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, - 0.4, 0.4, 0.4 ; - - fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, - 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; - - fates_prescribed_recruitment = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, - 0.02, 0.02, 0.02, 0.02, 0.02 ; - - fates_prt_alloc_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, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; - - fates_prt_nitr_stoich_p1 = - 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, - 0.0047, 0.0047, 0.0047 ; - - fates_prt_nitr_stoich_p2 = - 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, - 0.0047, 0.0047, 0.0047 ; - - fates_prt_phos_stoich_p1 = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, - 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, - 0.00047, 0.00047, 0.00047, 0.00047 ; - - fates_prt_phos_stoich_p2 = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, - 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, - 0.00047, 0.00047, 0.00047, 0.00047 ; - - fates_recruit_hgt_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, - 0.125, 0.125, 0.125 ; - - fates_recruit_initd = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, - 0.2 ; - - fates_rholnir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, 0.41, 0.28, - 0.28, 0.28 ; - - fates_rholvis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, 0.08, 0.05, - 0.05, 0.05 ; - - fates_rhosnir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, 0.49, 0.53, - 0.53, 0.53 ; - - fates_rhosvis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.31, - 0.31, 0.31 ; - - fates_root_long = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - - fates_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; - - fates_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9 ; - - fates_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, 1.47, - 1.47, 1.47 ; - - fates_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, - 0.51, 0.51, 0.51, 0.51 ; - - fates_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5 ; - - fates_seed_suppl = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_senleaf_long_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, -255000, - -255000, -255000, -255000, -255000, -255000 ; - - fates_smpso = -66000, -66000, -66000, -66000, -66000, -66000, -66000, - -66000, -66000, -66000, -66000, -66000 ; - - fates_taulnir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, 0.43, 0.4, - 0.4, 0.4 ; - - fates_taulvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.05, - 0.05, 0.05 ; - - fates_tausnir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, - 0.001, 0.25, 0.25, 0.25 ; - - fates_tausvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, - 0.001, 0.12, 0.12, 0.12 ; - - fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, - 0.03, 0.03 ; - - fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; - - fates_turnover_carb_retrans = - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_turnover_nitr_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_turnover_phos_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_turnover_retrans_mode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, - 0.7 ; - - fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; - - fates_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, - 0.055, 0.055, 0.055 ; - - fates_hlm_pft_map = - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; - - fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; - - fates_fire_low_moisture_Coeff = 1.12, 1.09, 0.98, 0.8, 1.15, 1.15 ; - - fates_fire_low_moisture_Slope = 0.62, 0.72, 0.85, 0.8, 0.62, 0.62 ; - - fates_fire_mid_moisture = 0.72, 0.51, 0.38, 1, 0.8, 0.8 ; - - fates_fire_mid_moisture_Coeff = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; - - fates_fire_mid_moisture_Slope = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; - - fates_fire_min_moisture = 0.18, 0.12, 0, 0, 0.24, 0.24 ; - - fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; - - fates_max_decomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; - - fates_CWD_frac = 0.045, 0.075, 0.21, 0.67 ; - - fates_base_mr_20 = 2.52e-06 ; - - fates_canopy_closure_thresh = 0.8 ; - - fates_cnp_eca_plant_escalar = 1.25e-05 ; - - fates_cohort_age_fusion_tol = 0.08 ; - - fates_cohort_size_fusion_tol = 0.08 ; - - fates_comp_excln = 3 ; - - fates_cwd_fcel = 0.76 ; - - fates_cwd_flig = 0.24 ; - - fates_dev_arbitrary = _ ; - - fates_fire_active_crown_fire = 0 ; - - fates_fire_cg_strikes = 0.2 ; - - fates_fire_drying_ratio = 66000 ; - - fates_fire_durat_slope = -11.06 ; - - fates_fire_fdi_a = 17.62 ; - - fates_fire_fdi_alpha = 0.00037 ; - - fates_fire_fdi_b = 243.12 ; - - fates_fire_fuel_energy = 18000 ; - - fates_fire_max_durat = 240 ; - - fates_fire_miner_damp = 0.41739 ; - - fates_fire_miner_total = 0.055 ; - - fates_fire_nignitions = 15 ; - - fates_fire_part_dens = 513 ; - - fates_fire_threshold = 50 ; - - fates_hydr_kmax_rsurf1 = 20 ; - - fates_hydr_kmax_rsurf2 = 0.0001 ; - - fates_hydr_psi0 = 0 ; - - fates_hydr_psicap = -0.6 ; - - fates_hydr_solver = 1 ; - - fates_init_litter = 0.05 ; - - fates_leaf_stomatal_model = 1 ; - - fates_logging_coll_under_frac = 0.55983 ; - - fates_logging_collateral_frac = 0.05 ; - - fates_logging_dbhmax = _ ; - - fates_logging_dbhmax_infra = 35 ; - - fates_logging_dbhmin = 50 ; - - fates_logging_direct_frac = 0.15 ; - - fates_logging_event_code = -30 ; - - fates_logging_export_frac = 0.8 ; - - fates_logging_mechanical_frac = 0.05 ; - - fates_maintresp_model = 1 ; - - fates_maxpatch_primary = 10 ; - - fates_maxpatch_secondary = 4 ; - - fates_mort_disturb_frac = 1 ; - - fates_mort_understorey_death = 0.55983 ; - - fates_patch_fusion_tol = 0.05 ; - - fates_phen_a = -68 ; - - fates_phen_b = 638 ; - - fates_phen_c = -0.01 ; - - fates_phen_chiltemp = 5 ; - - fates_phen_coldtemp = 7.5 ; - - fates_phen_doff_time = 100 ; - - fates_phen_drought_model = 0 ; - - fates_phen_drought_threshold = 0.15 ; - - fates_phen_mindayson = 90 ; - - fates_phen_moist_threshold = 0.18 ; - - fates_phen_ncolddayslim = 5 ; - - fates_photo_temp_acclim_timescale = 30 ; - - fates_photo_tempsens_model = 1 ; - - fates_pprodharv10_forest_mean = 0.8125 ; - - fates_q10_froz = 1.5 ; - - fates_q10_mr = 1.5 ; - - fates_soil_salinity = 0.4 ; - - fates_stomatal_assim = 1 ; - - fates_theta_cj_c3 = 0.999 ; - - fates_theta_cj_c4 = 0.999 ; - - fates_vai_top_bin_width = 1 ; - - fates_vai_width_increase_factor = 1 ; -} From f28f532d23e6c1e72500e2572f2f092a08e28b22 Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Fri, 13 May 2022 16:42:36 -0700 Subject: [PATCH 201/852] [ make damage timings be controlled by event_code as in the logging module ] [ copy the logging code IsItLoggingTime so that damage timings can be controlled by a code in the parameter file. ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary: no testing --- biogeochem/DamageMainMod.F90 | 98 +++++++++++++++++++++--- main/EDParamsMod.F90 | 15 +++- main/FatesInterfaceMod.F90 | 1 + parameter_files/fates_params_default.cdl | 9 ++- 4 files changed, 111 insertions(+), 12 deletions(-) diff --git a/biogeochem/DamageMainMod.F90 b/biogeochem/DamageMainMod.F90 index 20c9358a28..987a90993e 100644 --- a/biogeochem/DamageMainMod.F90 +++ b/biogeochem/DamageMainMod.F90 @@ -5,14 +5,14 @@ module DamageMainMod use FatesConstantsMod , only : itrue, ifalse use FatesConstantsMod , only : years_per_day use FatesGlobals , only : fates_log - + use FatesGlobals , only : endrun => fates_endrun + use shr_log_mod , only : errMsg => shr_log_errMsg use EDPftvarcon , only : EDPftvarcon_inst - + use EDParamsMod , only : damage_event_code use EDtypesMod , only : ed_site_type use EDtypesMod , only : ed_patch_type use EDtypesMod , only : ed_cohort_type use EDtypesMod , only : AREA - use PRTGenericMod, only : leaf_organ use PRTGenericMod, only : carbon12_element use PRTGenericMod, only : all_carbon_elements @@ -23,12 +23,24 @@ module DamageMainMod use PRTGenericMod, only : repro_organ use PRTGenericMod, only : struct_organ use PRTGenericMod, only : SetState - + use FatesInterfaceTypesMod, only : hlm_current_day + use FatesInterfaceTypesMod, only : hlm_current_month + use FatesInterfaceTypesMod, only : hlm_current_year + use FatesInterfaceTypesMod, only : hlm_model_day + use FatesInterfaceTypesMod , only : hlm_day_of_year + use FatesInterfaceTypesMod, only : hlm_use_canopy_damage + use FatesInterfaceTypesMod, only : hlm_use_understory_damage + + + implicit none private logical, protected :: damage_time ! if true then damage occurs during current time step + character(len=*), parameter, private :: sourcefile = & + __FILE__ + public :: get_crown_reduction public :: get_damage_frac public :: is_it_damage_time @@ -47,20 +59,88 @@ subroutine is_it_damage_time(is_master, currentSite) !---------------------------------------------------------------------------- ! This subroutine determines whether damage should occur (it is called daily) + ! This is almost an exact replica of the IsItLoggingTime subroutine !----------------------------------------------------------------------------- - use FatesInterfaceTypesMod , only : hlm_day_of_year integer, intent(in) :: is_master type(ed_site_type), intent(inout), target :: currentSite - - + + integer :: icode ! Integer equivalent of the event code (parameter file only allows reals) + integer :: damage_date ! Day of month for damage extracted from event code + integer :: damage_month ! Month of year for damage extracted from event code + integer :: damage_year ! Year for damage extracted from event code + character(len=64) :: fmt = '(a,i2.2,a,i2.2,a,i4,4)' + damage_time = .false. + icode = int(damage_event_code) + + if(hlm_use_canopy_damage .eq. ifalse .or. hlm_use_understory_damage .eq. ifalse) return - if (hlm_day_of_year .eq. 1) then + if(icode .eq. 1) then + ! Damage is turned off + damage_time = .false. + + else if(icode .eq. 2) then + ! Damage event on first time step + if(hlm_model_day .eq.1) then + damage_time = .true. + end if + + else if(icode .eq. 3) then + ! Damage event every day - not sure this is recommended as it will result in a very large + ! number of cohorts damage_time = .true. + + else if(icode .eq. 4) then + ! Damage event once a month + if(hlm_current_day.eq.1 ) then + damage_time = .true. + end if + + else if(icode < 0 .and. icode > -366) then + ! Damage event every year on a specific day of the year + if(hlm_day_of_year .eq. abs(icode) ) then + damage_time = .true. + end if + + else if(icode > 10000 ) then + ! Specific Event: YYYYMMDD + damage_date = icode - int(100* floor(real(icode)/100)) + damage_year = floor(real(icode)/10000) + damage_month = floor(real(icode)/100) - damage_year*100 + + if(hlm_current_day .eq. damage_date .and. & + hlm_current_month .eq. damage_month .and. & + hlm_current_year .eq. damage_year ) then + damage_time = .true. + end if + + else + ! Bad damage event flag + write(fates_log(),*) 'An invalid damage code was specified in fates_params' + write(fates_log(),*) 'Check DamageMainMod.F90:is_it_damage_time()' + write(fates_log(),*) 'for a breakdown of the valide codes and change' + write(fates_log(),*) 'fates_damage_event_code in the file accordingly.' + write(fates_log(),*) 'exiting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + if(damage_time .and. (is_master.eq.itrue) ) then + write(fates_log(),fmt) 'Damage Event Enacted on date: ', & + hlm_current_month,'-', hlm_current_day,'-',hlm_current_year end if - + + !if (hlm_day_of_year .eq. 1) then + ! damage_time = .true. + !end if + + write(fates_log(),fmt) 'JN date: ', & + hlm_current_month,'-', hlm_current_day,'-',hlm_current_year + write(fates_log(),*) 'JN damage_time: ', damage_time + + return + end subroutine is_it_damage_time !---------------------------------------------------------------------------- diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index f474a20cab..aa51356339 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -209,6 +209,11 @@ module EDParamsMod character(len=param_string_length),parameter,public :: eca_name_plant_escalar = "fates_eca_plant_escalar" + ! Damage Control Parameters (ONLY RELEVANT WHEN USE_FATES_CANOPY_DAMAGE OR USE_FATES_UNDERSTORY_DAMAGE = TRUE) + !--------------------------------------------------------------------------------------------------------------- + real(r8),protected,public :: damage_event_code ! Code that options how damage events are structured + character(len=param_string_length),parameter,public :: damage_name_event_code = "fates_damage_event_code" + public :: FatesParamsInit public :: FatesRegisterParams public :: FatesReceiveParams @@ -273,6 +278,7 @@ subroutine FatesParamsInit() theta_cj_c3 = nan theta_cj_c4 = nan dev_arbitrary = nan + damage_event_code = nan end subroutine FatesParamsInit !----------------------------------------------------------------------- @@ -441,7 +447,10 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=name_dev_arbitrary, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) - + + call fates_params%RegisterParameter(name=damage_name_event_code, 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, & @@ -635,6 +644,9 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetreiveParameter(name=fates_name_cg_strikes, & data=cg_strikes) + call fates_params%RetreiveParameter(name=damage_name_event_code, & + data=damage_event_code) + ! parameters that are arrays of size defined within the params file and thus need allocating as well call fates_params%RetreiveParameterAllocate(name=ED_name_history_sizeclass_bin_edges, & data=ED_val_history_sizeclass_bin_edges) @@ -718,6 +730,7 @@ subroutine FatesReportParams(is_master) write(fates_log(),fmt0) 'q10_froz = ',q10_froz write(fates_log(),fmt0) 'cg_strikes = ',cg_strikes write(fates_log(),'(a,L2)') 'active_crown_fire = ',active_crown_fire + write(fates_log(),fmt0) 'damage_event_code = ',damage_event_code write(fates_log(),*) '------------------------------------------------------' end if diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index a76c036ca7..64a8d54a91 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1842,6 +1842,7 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) hlm_use_canopy_damage = ival if (fates_global_verbose()) then write(fates_log(),*) 'Transfering hlm_use_canopy_damage= ',ival,' to FATES' + write(fates_log(),*) 'JN FatesInterfaceMod hlm_use_canopy_damage : ', hlm_use_canopy_damage end if case('use_logging') diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 4df45c465d..42b37dd27d 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -157,6 +157,9 @@ variables: double fates_branch_turnover(fates_pft) ; fates_branch_turnover:units = "yr" ; fates_branch_turnover:long_name = "turnover time of branches" ; + double fates_damage_event_code ; + fates_damage_event_code:units = "unitless" ; + fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; double fates_damage_frac(fates_pft) ; fates_damage_frac:units = "fraction"; fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)"; @@ -780,7 +783,7 @@ data: fates_history_coageclass_bin_edges = 0, 5 ; - fates_history_damage_bin_edges = 0, 20, 40, 60, 80 100 ; + fates_history_damage_bin_edges = 0, 20, 40, 60, 80, 100 ; fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; @@ -916,7 +919,9 @@ data: fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; - + + fates_damage_event_code = 1 ; + fates_damage_mort_p1 = 9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0 ; fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, From 261358210a3c9b9632b2e03972e67bfd92846992 Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Fri, 13 May 2022 20:05:17 -0700 Subject: [PATCH 202/852] [ Fixing damage event codes ] [Fix how is_it_damage_time is called. ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary: no testing --- biogeochem/DamageMainMod.F90 | 20 +++++++------------- main/EDMainMod.F90 | 6 ++---- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/biogeochem/DamageMainMod.F90 b/biogeochem/DamageMainMod.F90 index 987a90993e..8d57224f2b 100644 --- a/biogeochem/DamageMainMod.F90 +++ b/biogeochem/DamageMainMod.F90 @@ -70,20 +70,22 @@ subroutine is_it_damage_time(is_master, currentSite) integer :: damage_date ! Day of month for damage extracted from event code integer :: damage_month ! Month of year for damage extracted from event code integer :: damage_year ! Year for damage extracted from event code - character(len=64) :: fmt = '(a,i2.2,a,i2.2,a,i4,4)' + integer :: model_day_int ! Model day + + character(len=64) :: fmt = '(a,i2.2,a,i2.2,a,i4.4)' damage_time = .false. icode = int(damage_event_code) - if(hlm_use_canopy_damage .eq. ifalse .or. hlm_use_understory_damage .eq. ifalse) return - + model_day_int = nint(hlm_model_day) + if(icode .eq. 1) then ! Damage is turned off damage_time = .false. else if(icode .eq. 2) then ! Damage event on first time step - if(hlm_model_day .eq.1) then + if(model_day_int .eq.1) then damage_time = .true. end if @@ -130,15 +132,7 @@ subroutine is_it_damage_time(is_master, currentSite) write(fates_log(),fmt) 'Damage Event Enacted on date: ', & hlm_current_month,'-', hlm_current_day,'-',hlm_current_year end if - - !if (hlm_day_of_year .eq. 1) then - ! damage_time = .true. - !end if - - write(fates_log(),fmt) 'JN date: ', & - hlm_current_month,'-', hlm_current_day,'-',hlm_current_year - write(fates_log(),*) 'JN damage_time: ', damage_time - + return end subroutine is_it_damage_time diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index ce5a2dda76..2470b2c678 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -173,10 +173,8 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) call IsItLoggingTime(hlm_masterproc,currentSite) ! Call a routine that identifies if damage should occur - if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then - call is_it_damage_time(hlm_masterproc, currentSite) - end if - + call is_it_damage_time(hlm_masterproc, currentSite) + !************************************************************************** ! Fire, growth, biogeochemistry. !************************************************************************** From 6ae65be520bfbfcdc07810eabde04a61fc881f8b Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 16 May 2022 11:40:15 -0700 Subject: [PATCH 203/852] removing redundant call to tree_lai --- biogeochem/EDCohortDynamicsMod.F90 | 7 ------- 1 file changed, 7 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index c8e7e8eaf5..277f91b2c6 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -1533,13 +1533,6 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) ! update hydraulics quantities that are functions of hite & biomasses ! deallocate the hydro structure of nextc if (hlm_use_planthydro.eq.itrue) then - call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread, & - currentCohort%pft,currentCohort%c_area) - leaf_c = currentCohort%prt%GetState(leaf_organ, carbon12_element) - currentCohort%treelai = tree_lai(leaf_c, & - currentCohort%pft, currentCohort%c_area, currentCohort%n, & - currentCohort%canopy_layer, currentPatch%canopy_layer_tlai, & - currentCohort%vcmax25top ) call UpdateSizeDepPlantHydProps(currentSite,currentCohort, bc_in) endif From 428d679652d740769b52be1fafd65679c9fa40d0 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 16 May 2022 11:44:13 -0700 Subject: [PATCH 204/852] removing unnecessary calls to tree_lai --- biogeochem/EDCohortDynamicsMod.F90 | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 277f91b2c6..866fac5a81 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -1353,21 +1353,9 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) call endrun(msg=errMsg(sourcefile, __LINE__)) end select - leaf_c = currentCohort%prt%GetState(leaf_organ,all_carbon_elements) - - currentCohort%treelai = tree_lai(leaf_c, currentCohort%pft, currentCohort%c_area, newn, & - currentCohort%canopy_layer, currentPatch%canopy_layer_tlai, & - currentCohort%vcmax25top) - - ! We don't need check on sp mode here since we don't fuse_cohorts with sp mode - currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_trim, & - currentCohort%c_area, newn, currentCohort%canopy_layer, & - currentPatch%canopy_layer_tlai, currentCohort%treelai,currentCohort%vcmax25top,1 ) - call sizetype_class_index(currentCohort%dbh,currentCohort%pft, & currentCohort%size_class,currentCohort%size_by_pft_class) - if(hlm_use_planthydro.eq.itrue) then call FuseCohortHydraulics(currentSite,currentCohort,nextc,bc_in,newn) endif From d1d15d7573d3ff9b483b8c9676d18857ce0d6eb2 Mon Sep 17 00:00:00 2001 From: YanlanLiu Date: Tue, 17 May 2022 20:33:19 -0700 Subject: [PATCH 205/852] added bc%seed_in to seed_external --- biogeochem/EDPhysiologyMod.F90 | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index c287076354..a258a040f1 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1486,9 +1486,17 @@ subroutine SeedIn( currentSite, bc_in, bc_out) end select ! Seed input from external sources (user param seed rain, or dispersal model) + + !YL, include both prescribed seed_suppl and seed_in dispersed from neighbouring gridcells --------- - seed_in_external = seed_stoich*EDPftvarcon_inst%seed_suppl(pft)*years_per_day ![kg/m2/day] + !seed_in_external = seed_stoich*EDPftvarcon_inst%seed_suppl(pft)*years_per_day ![kg/m2/day] + + ! bc%seed_in(pft) in [kg/site/day] + seed_in_external = bc_in%seed_in(pft)/currentPatch%area + seed_stoich*EDPftvarcon_inst%seed_suppl(pft)*years_per_day ![kg/m2/day] + + write(fates_log(),*) 'pft, bc_in%seed_in(pft),bc_in%seed_in(pft)/currentPatch%area, seed_in_external: ', pft, bc_in%seed_in(pft), bc_in%seed_in(pft)/currentPatch%area, seed_in_external + !-------------------------------------------------------------------------------------------------- litt%seed_in_extern(pft) = litt%seed_in_extern(pft) + seed_in_external ! Seeds entering externally [kg/site/day] From 1fbd6d0fac621536cef6a8a54234a7e9ef0f3770 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 18 May 2022 14:09:05 -0400 Subject: [PATCH 206/852] Updated some parameter names to be more verbose --- parameter_files/apichange_23to24.xml | 20 ++-- .../fates_params_default_api24.cdl | 92 +++++++++---------- 2 files changed, 56 insertions(+), 56 deletions(-) diff --git a/parameter_files/apichange_23to24.xml b/parameter_files/apichange_23to24.xml index 40055180f8..8fbe0280fe 100644 --- a/parameter_files/apichange_23to24.xml +++ b/parameter_files/apichange_23to24.xml @@ -110,7 +110,7 @@ 0.18 - fates_lu_pprodharv10_forest_mean + fates_landuse_pprodharv10_forest_mean scalar fraction mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types @@ -216,31 +216,31 @@ fates_turb_z0mr - fates_lu_logging_coll_under_frac + fates_landuse_logging_coll_under_frac - fates_lu_logging_collateral_frac + fates_landuse_logging_collateral_frac - fates_lu_logging_dbhmax + fates_landuse_logging_dbhmax - fates_lu_logging_dbhmax_infra + fates_landuse_logging_dbhmax_infra - fates_lu_logging_dbhmin + fates_landuse_logging_dbhmin - fates_lu_logging_direct_frac + fates_landuse_logging_direct_frac - fates_lu_logging_event_code + fates_landuse_logging_event_code - fates_lu_logging_export_frac + fates_landuse_logging_export_frac - fates_lu_logging_mechanical_frac + fates_landuse_logging_mechanical_frac fates_leaf_photo_temp_acclim_timescale diff --git a/parameter_files/fates_params_default_api24.cdl b/parameter_files/fates_params_default_api24.cdl index 178226df04..85724166bd 100644 --- a/parameter_files/fates_params_default_api24.cdl +++ b/parameter_files/fates_params_default_api24.cdl @@ -659,6 +659,36 @@ 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" ; + 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" ; + double fates_landuse_logging_collateral_frac ; + fates_landuse_logging_collateral_frac:units = "fraction" ; + fates_landuse_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; + double fates_landuse_logging_dbhmax ; + fates_landuse_logging_dbhmax:units = "cm" ; + fates_landuse_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; + double fates_landuse_logging_dbhmax_infra ; + fates_landuse_logging_dbhmax_infra:units = "cm" ; + fates_landuse_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; + double fates_landuse_logging_dbhmin ; + fates_landuse_logging_dbhmin:units = "cm" ; + fates_landuse_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; + double fates_landuse_logging_direct_frac ; + fates_landuse_logging_direct_frac:units = "fraction" ; + fates_landuse_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; + double fates_landuse_logging_event_code ; + fates_landuse_logging_event_code:units = "unitless" ; + fates_landuse_logging_event_code:long_name = "Integer code that options how logging events are structured" ; + double fates_landuse_logging_export_frac ; + fates_landuse_logging_export_frac:units = "fraction" ; + fates_landuse_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; + double fates_landuse_logging_mechanical_frac ; + fates_landuse_logging_mechanical_frac:units = "fraction" ; + fates_landuse_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; + double fates_landuse_pprodharv10_forest_mean ; + fates_landuse_pprodharv10_forest_mean:units = "fraction" ; + fates_landuse_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; double fates_leaf_photo_temp_acclim_timescale ; fates_leaf_photo_temp_acclim_timescale:units = "days" ; fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; @@ -677,36 +707,6 @@ variables: double fates_leaf_theta_cj_c4 ; fates_leaf_theta_cj_c4:units = "unitless" ; fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; - double fates_lu_logging_coll_under_frac ; - fates_lu_logging_coll_under_frac:units = "fraction" ; - fates_lu_logging_coll_under_frac:long_name = "Fraction of stems killed in the understory when logging generates disturbance" ; - double fates_lu_logging_collateral_frac ; - fates_lu_logging_collateral_frac:units = "fraction" ; - fates_lu_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; - double fates_lu_logging_dbhmax ; - fates_lu_logging_dbhmax:units = "cm" ; - fates_lu_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; - double fates_lu_logging_dbhmax_infra ; - fates_lu_logging_dbhmax_infra:units = "cm" ; - fates_lu_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; - double fates_lu_logging_dbhmin ; - fates_lu_logging_dbhmin:units = "cm" ; - fates_lu_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; - double fates_lu_logging_direct_frac ; - fates_lu_logging_direct_frac:units = "fraction" ; - fates_lu_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; - double fates_lu_logging_event_code ; - fates_lu_logging_event_code:units = "unitless" ; - fates_lu_logging_event_code:long_name = "Integer code that options how logging events are structured" ; - double fates_lu_logging_export_frac ; - fates_lu_logging_export_frac:units = "fraction" ; - fates_lu_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; - double fates_lu_logging_mechanical_frac ; - fates_lu_logging_mechanical_frac:units = "fraction" ; - fates_lu_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; - double fates_lu_pprodharv10_forest_mean ; - fates_lu_pprodharv10_forest_mean:units = "fraction" ; - fates_lu_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; double fates_maintresp_model ; fates_maintresp_model:units = "unitless" ; fates_maintresp_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991) (NOT USED)" ; @@ -1438,37 +1438,37 @@ data: fates_hydro_solver = 1 ; - fates_leaf_photo_temp_acclim_timescale = 30 ; + fates_landuse_logging_coll_under_frac = 0.55983 ; - fates_leaf_photo_tempsens_model = 1 ; + fates_landuse_logging_collateral_frac = 0.05 ; - fates_leaf_stomatal_assim_model = 1 ; + fates_landuse_logging_dbhmax = _ ; - fates_leaf_stomatal_model = 1 ; + fates_landuse_logging_dbhmax_infra = 35 ; - fates_leaf_theta_cj_c3 = 0.999 ; + fates_landuse_logging_dbhmin = 50 ; - fates_leaf_theta_cj_c4 = 0.999 ; + fates_landuse_logging_direct_frac = 0.15 ; - fates_lu_logging_coll_under_frac = 0.55983 ; + fates_landuse_logging_event_code = -30 ; - fates_lu_logging_collateral_frac = 0.05 ; + fates_landuse_logging_export_frac = 0.8 ; - fates_lu_logging_dbhmax = _ ; + fates_landuse_logging_mechanical_frac = 0.05 ; - fates_lu_logging_dbhmax_infra = 35 ; + fates_landuse_pprodharv10_forest_mean = 0.8125 ; - fates_lu_logging_dbhmin = 50 ; + fates_leaf_photo_temp_acclim_timescale = 30 ; - fates_lu_logging_direct_frac = 0.15 ; + fates_leaf_photo_tempsens_model = 1 ; - fates_lu_logging_event_code = -30 ; + fates_leaf_stomatal_assim_model = 1 ; - fates_lu_logging_export_frac = 0.8 ; + fates_leaf_stomatal_model = 1 ; - fates_lu_logging_mechanical_frac = 0.05 ; + fates_leaf_theta_cj_c3 = 0.999 ; - fates_lu_pprodharv10_forest_mean = 0.8125 ; + fates_leaf_theta_cj_c4 = 0.999 ; fates_maintresp_model = 1 ; From bf1568c2b2ccc749da10d86344f75acead98b884 Mon Sep 17 00:00:00 2001 From: YanlanLiu Date: Thu, 19 May 2022 19:05:14 -0700 Subject: [PATCH 207/852] cleaned printouts --- biogeochem/EDPhysiologyMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index a258a040f1..b793c965c8 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1494,7 +1494,7 @@ subroutine SeedIn( currentSite, bc_in, bc_out) ! bc%seed_in(pft) in [kg/site/day] seed_in_external = bc_in%seed_in(pft)/currentPatch%area + seed_stoich*EDPftvarcon_inst%seed_suppl(pft)*years_per_day ![kg/m2/day] - write(fates_log(),*) 'pft, bc_in%seed_in(pft),bc_in%seed_in(pft)/currentPatch%area, seed_in_external: ', pft, bc_in%seed_in(pft), bc_in%seed_in(pft)/currentPatch%area, seed_in_external + !write(fates_log(),*) 'pft, bc_in%seed_in(pft),bc_in%seed_in(pft)/currentPatch%area, seed_in_external: ', pft, bc_in%seed_in(pft), bc_in%seed_in(pft)/currentPatch%area, seed_in_external !-------------------------------------------------------------------------------------------------- litt%seed_in_extern(pft) = litt%seed_in_extern(pft) + seed_in_external From 10ee77bee0be3a20a8e45e29dc60180045ce6508 Mon Sep 17 00:00:00 2001 From: ckoven Date: Mon, 23 May 2022 17:27:13 -0600 Subject: [PATCH 208/852] first attempt to make disturbance rates happen in parallel --- biogeochem/EDPatchDynamicsMod.F90 | 129 ++++++++---------------------- 1 file changed, 34 insertions(+), 95 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 13552c899a..d2e612fd74 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -187,6 +187,7 @@ subroutine disturbance_rates( site_in, bc_in) integer :: i_dist real(r8) :: frac_site_primary real(r8) :: harvest_rate + real(r8) :: tempsum !---------------------------------------------------------------------------------------------- ! Calculate Mortality Rates (these were previously calculated during growth derivatives) @@ -343,90 +344,12 @@ subroutine disturbance_rates( site_in, bc_in) call FatesWarn(msg,index=2) endif - - - - ! ------------------------------------------------------------------------------------------ - ! Determine which disturbance is dominant, and force mortality diagnostics in the upper - ! canopy to be zero for the non-dominant mode. Note: upper-canopy tree-fall mortality is - ! not always disturbance generating, so when tree-fall mort is non-dominant, make sure - ! to still diagnose and track the non-disturbance rate - ! ------------------------------------------------------------------------------------------ - - ! DISTURBANCE IS LOGGING - if (currentPatch%disturbance_rates(dtype_ilog) > currentPatch%disturbance_rates(dtype_ifall) .and. & - currentPatch%disturbance_rates(dtype_ilog) > currentPatch%disturbance_rates(dtype_ifire) ) then - - currentPatch%disturbance_rate = currentPatch%disturbance_rates(dtype_ilog) - currentPatch%disturbance_mode = dtype_ilog - - ! Update diagnostics - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - if(currentCohort%canopy_layer == 1)then - currentCohort%cmort = currentCohort%cmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%hmort = currentCohort%hmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%bmort = currentCohort%bmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%dmort = currentCohort%dmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%frmort = currentCohort%frmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%smort = currentCohort%smort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%asmort = currentCohort%asmort*(1.0_r8 - fates_mortality_disturbance_fraction) - end if - currentCohort => currentCohort%taller - enddo !currentCohort - - ! DISTURBANCE IS FIRE - elseif (currentPatch%disturbance_rates(dtype_ifire) > currentPatch%disturbance_rates(dtype_ifall) .and. & - currentPatch%disturbance_rates(dtype_ifire) > currentPatch%disturbance_rates(dtype_ilog) ) then - - currentPatch%disturbance_rate = currentPatch%disturbance_rates(dtype_ifire) - currentPatch%disturbance_mode = dtype_ifire - - ! Update diagnostics, zero non-fire mortality rates - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - if(currentCohort%canopy_layer == 1)then - currentCohort%cmort = currentCohort%cmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%hmort = currentCohort%hmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%bmort = currentCohort%bmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%dmort = currentCohort%dmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%frmort = currentCohort%frmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%smort = currentCohort%smort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%asmort = currentCohort%asmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%lmort_direct = 0.0_r8 - currentCohort%lmort_collateral = 0.0_r8 - currentCohort%lmort_infra = 0.0_r8 - currentCohort%l_degrad = 0.0_r8 - end if - - ! This may be counter-intuitive, but the diagnostic fire-mortality rate - ! will stay zero in the patch that undergoes fire, this is because - ! the actual cohorts who experience the fire are only those in the - ! newly created patch so currentCohort%fmort = 0.0_r8 - ! Don't worry, the cohorts in the newly created patch will reflect burn - - currentCohort => currentCohort%taller - enddo !currentCohort - - else ! If fire and logging are not greater than treefall, just set disturbance rate to tree-fall - ! which is most likely a 0.0 - - currentPatch%disturbance_rate = currentPatch%disturbance_rates(dtype_ifall) - currentPatch%disturbance_mode = dtype_ifall - - ! Update diagnostics, zero non-treefall mortality rates - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - if(currentCohort%canopy_layer == 1)then - currentCohort%lmort_direct = 0.0_r8 - currentCohort%lmort_collateral = 0.0_r8 - currentCohort%lmort_infra = 0.0_r8 - currentCohort%l_degrad = 0.0_r8 - end if - currentCohort => currentCohort%taller - enddo !currentCohort - - + ! if the sum of all disturbance rates is such that they will exceed total patch area on this day, then reduce them all proportionally. + if ( sum(currentPatch%disturbance_rates(:)) .gt. 1.0_r8 ) then + tempsum = sum(currentPatch%disturbance_rates(:)) + do i_dist = 1,N_DIST_TYPES + currentPatch%disturbance_rates(i_dist) = currentPatch%disturbance_rates(i_dist) / tempsum + end do endif currentPatch => currentPatch%younger @@ -491,6 +414,7 @@ subroutine spawn_patches( currentSite, bc_in) real(r8) :: leaf_m ! leaf mass during partial burn calculations logical :: found_youngest_primary ! logical for finding the first primary forest patch integer :: min_nocomp_pft, max_nocomp_pft, i_nocomp_pft + integer :: i_dist, i_dist2 !--------------------------------------------------------------------- storesmallcohort => null() ! storage of the smallest cohort for insertion routine @@ -515,6 +439,8 @@ subroutine spawn_patches( currentSite, bc_in) ! If nocomp is not enabled, then this is not much of a loop, it only passes through once. nocomp_pft_loop: do i_nocomp_pft = min_nocomp_pft,max_nocomp_pft + disturbance_type_loop: do i_dist = 1,N_DIST_TYPES + ! calculate area of disturbed land, in this timestep, by summing contributions from each existing patch. currentPatch => currentSite%youngest_patch @@ -532,12 +458,8 @@ subroutine spawn_patches( currentSite, bc_in) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - ! Check to make sure that the disturbance mode of the patch is set - if( .not.any(currentPatch%disturbance_mode == [dtype_ilog,dtype_ifall,dtype_ifire])) then - write(fates_log(),*) 'undefined disturbance mode? : ',currentPatch%disturbance_mode - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - + currentPatch%disturbance_mode = i_dist + currentPatch%disturbance_rate = currentPatch%disturbance_rates(i_dist) ! Only create new patches that have non-negligible amount of land if((currentPatch%area*currentPatch%disturbance_rate) > nearzero ) then @@ -1118,8 +1040,18 @@ subroutine spawn_patches( currentSite, bc_in) call sort_cohorts(currentPatch) !update area of donor patch + oldarea = currentPatch%area currentPatch%area = currentPatch%area - patch_site_areadis + ! for all disturbance rates that haven't been resolved yet, increase their amount so that + ! they are the same amount of gridcell-scale disturbance relative to the original patch size + if (i_dist .ne. N_DIST_TYPES) then + do i_dist2 = i_dist+1,N_DIST_TYPES + currentPatch%disturbance_rates(i_dist2) = currentPatch%disturbance_rates(i_dist2) & + * oldarea / currentPatch%area + end do + end if + ! sort out the cohorts, since some of them may be so small as to need removing. ! the first call to terminate cohorts removes sparse number densities, ! the second call removes for all other reasons (sparse culling must happen @@ -1131,11 +1063,6 @@ subroutine spawn_patches( currentSite, bc_in) end if ! if ( new_patch%area > nearzero ) then - !zero disturbance rate trackers - currentPatch%disturbance_rate = 0._r8 - currentPatch%disturbance_rates = 0._r8 - currentPatch%fract_ldist_not_harvested = 0._r8 - end if cp_nocomp_matches_2_if currentPatch => currentPatch%younger @@ -1218,7 +1145,19 @@ subroutine spawn_patches( currentSite, bc_in) call check_patch_area(currentSite) call set_patchno(currentSite) + end do disturbance_type_loop + end do nocomp_pft_loop + + !zero disturbance rate trackers on all patches + currentPatch => currentSite%oldest_patch + do while(associated(currentPatch)) + currentPatch%disturbance_rate = 0._r8 + currentPatch%disturbance_rates = 0._r8 + currentPatch%fract_ldist_not_harvested = 0._r8 + currentPatch => currentPatch%younger + end do + return end subroutine spawn_patches From 6ac7604f1037fa863a3b2e10a624713fac9bd20c Mon Sep 17 00:00:00 2001 From: ckoven Date: Mon, 23 May 2022 17:30:22 -0600 Subject: [PATCH 209/852] bugfix --- biogeochem/EDPatchDynamicsMod.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index d2e612fd74..66e01ca95c 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -415,6 +415,7 @@ subroutine spawn_patches( currentSite, bc_in) logical :: found_youngest_primary ! logical for finding the first primary forest patch integer :: min_nocomp_pft, max_nocomp_pft, i_nocomp_pft integer :: i_dist, i_dist2 + real(r8) :: oldarea !--------------------------------------------------------------------- storesmallcohort => null() ! storage of the smallest cohort for insertion routine From f8ff1056b1c81e1d01311d252f0686ddcccf8641 Mon Sep 17 00:00:00 2001 From: ckoven Date: Mon, 23 May 2022 15:23:07 -0600 Subject: [PATCH 210/852] made it so that grasses don't contribute to treefall disturbance --- biogeochem/EDPatchDynamicsMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 13552c899a..c195ec6ba9 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -282,7 +282,7 @@ subroutine disturbance_rates( site_in, bc_in) currentCohort => currentPatch%shortest do while(associated(currentCohort)) - if(currentCohort%canopy_layer == 1)then + if(currentCohort%canopy_layer == 1 .and. int(prt_params%woody(currentCohort%pft)) == itrue )then ! Treefall Disturbance Rate currentPatch%disturbance_rates(dtype_ifall) = currentPatch%disturbance_rates(dtype_ifall) + & From f9613f17af32f17e4c1201302fa0ac6e80700d32 Mon Sep 17 00:00:00 2001 From: ckoven Date: Mon, 23 May 2022 16:04:32 -0600 Subject: [PATCH 211/852] slightly changed logic so that logging degradation / disturbance still happens with respect to canopy grasses if there are any. --- biogeochem/EDPatchDynamicsMod.F90 | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index c195ec6ba9..5319001d3f 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -282,12 +282,14 @@ subroutine disturbance_rates( site_in, bc_in) currentCohort => currentPatch%shortest do while(associated(currentCohort)) - if(currentCohort%canopy_layer == 1 .and. int(prt_params%woody(currentCohort%pft)) == itrue )then + if(currentCohort%canopy_layer == 1)then - ! Treefall Disturbance Rate - currentPatch%disturbance_rates(dtype_ifall) = currentPatch%disturbance_rates(dtype_ifall) + & - fates_mortality_disturbance_fraction * & - min(1.0_r8,currentCohort%dmort)*hlm_freq_day*currentCohort%c_area/currentPatch%area + ! Treefall Disturbance Rate. Only count this for trees, not grasses + if ( int(prt_params%woody(currentCohort%pft)) == itrue ) then + currentPatch%disturbance_rates(dtype_ifall) = currentPatch%disturbance_rates(dtype_ifall) + & + fates_mortality_disturbance_fraction * & + min(1.0_r8,currentCohort%dmort)*hlm_freq_day*currentCohort%c_area/currentPatch%area + end if ! Logging Disturbance Rate currentPatch%disturbance_rates(dtype_ilog) = currentPatch%disturbance_rates(dtype_ilog) + & From d77e7b8a703f865a5653d71f69ff54b7e754ba06 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 24 May 2022 13:25:06 -0400 Subject: [PATCH 212/852] Adding model-side changes to the parameter file parameter names. Changes to initialization sequence to handle fates patch number control. --- biogeochem/EDCanopyStructureMod.F90 | 2 +- biogeochem/EDCohortDynamicsMod.F90 | 7 +- biogeochem/EDPatchDynamicsMod.F90 | 24 +- biogeophys/EDSurfaceAlbedoMod.F90 | 1 - fire/SFParamsMod.F90 | 4 +- main/EDParamsMod.F90 | 94 +++--- main/EDPftvarcon.F90 | 312 +++++++++--------- main/EDTypesMod.F90 | 9 +- main/FatesHistoryInterfaceMod.F90 | 8 +- main/FatesInterfaceMod.F90 | 245 +++++++------- main/FatesInterfaceTypesMod.F90 | 20 +- main/FatesParametersInterface.F90 | 3 +- parameter_files/apichange_23to24.xml | 20 +- .../fates_params_default_api24.cdl | 52 +-- parteh/PRTLossFluxesMod.F90 | 27 +- parteh/PRTParametersMod.F90 | 3 +- parteh/PRTParamsFATESMod.F90 | 211 ++++-------- tools/FatesPFTIndexSwapper.py | 2 +- 18 files changed, 496 insertions(+), 548 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index f981ba5102..e4123fbc05 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -14,6 +14,7 @@ module EDCanopyStructureMod use EDPftvarcon , only : EDPftvarcon_inst use PRTParametersMod , only : prt_params use FatesAllometryMod , only : carea_allom + use FatesAllometryMod , only : CrownDepth use EDCohortDynamicsMod , only : copy_cohort, terminate_cohorts, terminate_cohort, fuse_cohorts use EDCohortDynamicsMod , only : InitPRTObject use EDCohortDynamicsMod , only : InitPRTBoundaryConditions @@ -31,7 +32,6 @@ module EDCanopyStructureMod use FatesInterfaceTypesMod , only : numpft use FatesInterfaceTypesMod, only : bc_in_type use FatesPlantHydraulicsMod, only : UpdateH2OVeg,InitHydrCohort, RecruitWaterStorage - use EDTypesMod , only : maxCohortsPerPatch use PRTGenericMod, only : leaf_organ use PRTGenericMod, only : all_carbon_elements use PRTGenericMod, only : leaf_organ diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 732c1d5307..b8edbde816 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -32,7 +32,7 @@ module EDCohortDynamicsMod use FatesLitterMod , only : ncwd use FatesLitterMod , only : ndcmpy use FatesLitterMod , only : litter_type - use EDTypesMod , only : maxCohortsPerPatch + use EDParamsMod , only : max_cohort_per_patch use EDTypesMod , only : AREA use EDTypesMod , only : min_npm2, min_nppatch use EDTypesMod , only : min_n_safemath @@ -1072,7 +1072,6 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) use FatesInterfaceTypesMod , only : hlm_use_cohort_age_tracking use FatesConstantsMod , only : itrue use FatesConstantsMod, only : days_per_year - use EDTypesMod , only : maxCohortsPerPatch ! ! !ARGUMENTS @@ -1583,7 +1582,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) if ( hlm_use_cohort_age_tracking .eq.itrue) then - if ( nocohorts > maxCohortsPerPatch ) then + if ( nocohorts > max_cohort_per_patch ) then iterate = 1 !---------------------------------------------------------------------! ! Making profile tolerance larger means that more fusion will happen ! @@ -1598,7 +1597,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) else - if (nocohorts > maxCohortsPerPatch) then + if (nocohorts > max_cohort_per_patch) then iterate = 1 !---------------------------------------------------------------------! ! Making profile tolerance larger means that more fusion will happen ! diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 13552c899a..42ca027ff8 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -19,8 +19,6 @@ module EDPatchDynamicsMod use EDTypesMod , only : homogenize_seed_pfts use EDTypesMod , only : n_dbh_bins, area, patchfusion_dbhbin_loweredges use EDtypesMod , only : force_patchfuse_min_biomass - use EDTypesMod , only : maxPatchesPerSite - use EDTypesMod , only : maxPatchesPerSite_by_disttype use EDTypesMod , only : ed_site_type, ed_patch_type, ed_cohort_type use EDTypesMod , only : site_massbal_type use EDTypesMod , only : site_fluxdiags_type @@ -90,6 +88,9 @@ module EDPatchDynamicsMod use SFParamsMod, only : SF_VAL_CWD_FRAC use EDParamsMod, only : logging_event_code use EDParamsMod, only : logging_export_frac + use EDParamsMod, only : maxpatch_primary + use EDParamsMod, only : maxpatch_secondary + use EDParamsMod, only : maxpatch_total use FatesRunningMeanMod, only : ema_24hr, fixed_24hr, ema_lpa ! CIME globals @@ -2315,15 +2316,16 @@ subroutine fuse_patches( csite, bc_in ) ! to let there be one for each type of nocomp PFT on the site. this is likely to lead to problems ! if anthropogenic disturance is enabled. if (hlm_use_nocomp.eq.itrue) then - maxpatches(primaryforest) = max(maxPatchesPerSite_by_disttype(primaryforest), sum(csite%use_this_pft)) - maxpatches(secondaryforest) = maxPatchesPerSite - maxpatches(primaryforest) - if (maxPatchesPerSite .lt. maxpatches(primaryforest)) then + maxpatches(primaryforest) = max(maxpatch_primary, sum(csite%use_this_pft)) + maxpatches(secondaryforest) = maxpatch_total - maxpatches(primaryforest) + if (maxpatch_total .lt. maxpatches(primaryforest)) then write(fates_log(),*) 'too many PFTs and not enough patches for nocomp w/o fixed biogeog' - write(fates_log(),*) 'maxPatchesPerSite,numpft',maxPatchesPerSite,numpft, sum(csite%use_this_pft) + write(fates_log(),*) 'maxpatch_total,numpft',maxpatch_total,numpft, sum(csite%use_this_pft) call endrun(msg=errMsg(sourcefile, __LINE__)) endif else - maxpatches(:) = maxPatchesPerSite_by_disttype(:) + maxpatches(1) = maxpatch_primary + maxpatches(2) = maxpatch_secondary endif currentPatch => currentSite%youngest_patch @@ -2359,7 +2361,7 @@ subroutine fuse_patches( csite, bc_in ) iterate = 1 !---------------------------------------------------------------------! - ! Keep doing this until nopatches <= maxPatchesPerSite ! + ! Keep doing this until nopatches <= maxpatch_total ! !---------------------------------------------------------------------! iterate_eq_1_loop: do while(iterate == 1) @@ -2501,10 +2503,10 @@ subroutine fuse_patches( csite, bc_in ) ! a patch x patch loop, reset the patch fusion tolerance to the starting ! ! value so that any subsequent fusions in this loop are done with that ! ! value. otherwise we can end up in a situation where we've loosened the ! - ! fusion tolerance to get nopatches <= maxPatchesPerSite, but then, ! + ! fusion tolerance to get nopatches <= maxpatch_total, but then, ! ! having accomplished that, we continue through all the patch x patch ! ! combinations and then all the patches get fused, ending up with ! - ! nopatches << maxPatchesPerSite and losing all heterogeneity. ! + ! nopatches << maxpatch_total and losing all heterogeneity. ! !------------------------------------------------------------------------! profiletol = ED_val_patch_fusion_tol @@ -2563,7 +2565,7 @@ subroutine fuse_patches( csite, bc_in ) iterate = 0 endif - enddo iterate_eq_1_loop ! iterate .eq. 1 ==> nopatches>maxPatchesPerSite + enddo iterate_eq_1_loop ! iterate .eq. 1 ==> nopatches>maxpatch_total end do disttype_loop diff --git a/biogeophys/EDSurfaceAlbedoMod.F90 b/biogeophys/EDSurfaceAlbedoMod.F90 index 66bd88a4eb..ddb25f08a4 100644 --- a/biogeophys/EDSurfaceAlbedoMod.F90 +++ b/biogeophys/EDSurfaceAlbedoMod.F90 @@ -11,7 +11,6 @@ module EDSurfaceRadiationMod #include "shr_assert.h" use EDTypesMod , only : ed_patch_type, ed_site_type - use EDTypesMod , only : maxPatchesPerSite use EDTypesMod , only : maxpft use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : itrue diff --git a/fire/SFParamsMod.F90 b/fire/SFParamsMod.F90 index 02c0ce7756..900befe175 100644 --- a/fire/SFParamsMod.F90 +++ b/fire/SFParamsMod.F90 @@ -52,8 +52,8 @@ module SFParamsMod character(len=param_string_length),parameter :: SF_name_durat_slope = "fates_fire_durat_slope" character(len=param_string_length),parameter :: SF_name_drying_ratio = "fates_fire_drying_ratio" character(len=param_string_length),parameter :: SF_name_fire_threshold = "fates_fire_threshold" - character(len=param_string_length),parameter :: SF_name_CWD_frac = "fates_CWD_frac" - character(len=param_string_length),parameter :: SF_name_max_decomp = "fates_max_decomp" + character(len=param_string_length),parameter :: SF_name_CWD_frac = "fates_frag_cwd_frac" + character(len=param_string_length),parameter :: SF_name_max_decomp = "fates_frag_maxdecomp" character(len=param_string_length),parameter :: SF_name_SAV = "fates_fire_SAV" character(len=param_string_length),parameter :: SF_name_FBD = "fates_fire_FBD" character(len=param_string_length),parameter :: SF_name_min_moisture = "fates_fire_min_moisture" diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 3e9ff9bac0..7ed2ee19c4 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -41,7 +41,6 @@ module EDParamsMod real(r8),protected, public :: ED_val_comp_excln real(r8),protected, public :: ED_val_vai_top_bin_width real(r8),protected, public :: ED_val_vai_width_increase_factor - real(r8),protected, public :: ED_val_init_litter real(r8),protected, public :: ED_val_nignitions real(r8),protected, public :: ED_val_understorey_death real(r8),protected, public :: ED_val_cwd_fcel @@ -93,22 +92,21 @@ module EDParamsMod ! 1 = Christofferson et al. 2016 (TFS), 2 = Van Genuchten 1980 integer, protected,allocatable,public :: hydr_htftype_node(:) - character(len=param_string_length),parameter,public :: ED_name_photo_temp_acclim_timescale = "fates_photo_temp_acclim_timescale" - character(len=param_string_length),parameter,public :: name_photo_tempsens_model = "fates_photo_tempsens_model" + character(len=param_string_length),parameter,public :: ED_name_photo_temp_acclim_timescale = "fates_leaf_photo_temp_acclim_timescale" + character(len=param_string_length),parameter,public :: name_photo_tempsens_model = "fates_leaf_photo_tempsens_model" character(len=param_string_length),parameter,public :: name_maintresp_model = "fates_maintresp_model" - character(len=param_string_length),parameter,public :: ED_name_hydr_htftype_node = "fates_hydr_htftype_node" + character(len=param_string_length),parameter,public :: ED_name_hydr_htftype_node = "fates_hydro_htftype_node" character(len=param_string_length),parameter,public :: ED_name_mort_disturb_frac = "fates_mort_disturb_frac" character(len=param_string_length),parameter,public :: ED_name_comp_excln = "fates_comp_excln" character(len=param_string_length),parameter,public :: ED_name_vai_top_bin_width = "fates_vai_top_bin_width" character(len=param_string_length),parameter,public :: ED_name_vai_width_increase_factor = "fates_vai_width_increase_factor" - character(len=param_string_length),parameter,public :: ED_name_init_litter = "fates_init_litter" character(len=param_string_length),parameter,public :: ED_name_nignitions = "fates_fire_nignitions" character(len=param_string_length),parameter,public :: ED_name_understorey_death = "fates_mort_understorey_death" - character(len=param_string_length),parameter,public :: ED_name_cwd_fcel= "fates_cwd_fcel" - character(len=param_string_length),parameter,public :: ED_name_cwd_flig= "fates_cwd_flig" + character(len=param_string_length),parameter,public :: ED_name_cwd_fcel= "fates_frag_cwd_fcel" + character(len=param_string_length),parameter,public :: ED_name_cwd_flig= "fates_frag_cwd_flig" character(len=param_string_length),parameter,public :: ED_name_base_mr_20= "fates_base_mr_20" character(len=param_string_length),parameter,public :: ED_name_phen_drought_threshold= "fates_phen_drought_threshold" - character(len=param_string_length),parameter,public :: ED_name_phen_doff_time= "fates_phen_doff_time" + character(len=param_string_length),parameter,public :: ED_name_phen_doff_time= "fates_phen_mindaysoff" character(len=param_string_length),parameter,public :: ED_name_phen_a= "fates_phen_a" character(len=param_string_length),parameter,public :: ED_name_phen_b= "fates_phen_b" character(len=param_string_length),parameter,public :: ED_name_phen_c= "fates_phen_c" @@ -122,8 +120,8 @@ module EDParamsMod 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 :: name_theta_cj_c3 = "fates_theta_cj_c3" - character(len=param_string_length),parameter,public :: name_theta_cj_c4 = "fates_theta_cj_c4" + character(len=param_string_length),parameter,public :: name_theta_cj_c3 = "fates_leaf_theta_cj_c3" + character(len=param_string_length),parameter,public :: name_theta_cj_c4 = "fates_leaf_theta_cj_c4" character(len=param_string_length),parameter :: fates_name_q10_mr="fates_q10_mr" character(len=param_string_length),parameter :: fates_name_q10_froz="fates_q10_froz" @@ -138,17 +136,17 @@ module EDParamsMod ! ---------------------------------------------------------------------------------------------- real(r8),protected,public :: hydr_kmax_rsurf1 ! maximum conducitivity for unit root surface ! soil to root direction (kg water/m2 root area/Mpa/s) - character(len=param_string_length),parameter,public :: hydr_name_kmax_rsurf1 = "fates_hydr_kmax_rsurf1" + character(len=param_string_length),parameter,public :: hydr_name_kmax_rsurf1 = "fates_hydro_kmax_rsurf1" real(r8),protected,public :: hydr_kmax_rsurf2 ! maximum conducitivity for unit root surface ! root to soil direciton (kg water/m2 root area/Mpa/s) - character(len=param_string_length),parameter,public :: hydr_name_kmax_rsurf2 = "fates_hydr_kmax_rsurf2" + character(len=param_string_length),parameter,public :: hydr_name_kmax_rsurf2 = "fates_hydro_kmax_rsurf2" real(r8),protected,public :: hydr_psi0 ! sapwood water potential at saturation (MPa) - character(len=param_string_length),parameter,public :: hydr_name_psi0 = "fates_hydr_psi0" + character(len=param_string_length),parameter,public :: hydr_name_psi0 = "fates_hydro_psi0" real(r8),protected,public :: hydr_psicap ! sapwood water potential at which capillary reserves exhausted (MPa) - character(len=param_string_length),parameter,public :: hydr_name_psicap = "fates_hydr_psicap" + character(len=param_string_length),parameter,public :: hydr_name_psicap = "fates_hydro_psicap" ! Switch that defines which hydraulic solver to use @@ -160,7 +158,7 @@ module EDParamsMod ! the soil simultaneously, 2D: soil x (root + shell) integer,protected,public :: hydr_solver ! switch designating hydraulics numerical solver - character(len=param_string_length),parameter,public :: hydr_name_solver = "fates_hydr_solver" + character(len=param_string_length),parameter,public :: hydr_name_solver = "fates_hydro_solver" !Soil BGC parameters, mostly used for testing FATES when not coupled to the dynamics bgc hlm ! ---------------------------------------------------------------------------------------------- @@ -169,59 +167,68 @@ module EDParamsMod ! Switch designating whether to use net or gross assimilation in the stomata model integer, protected, public :: stomatal_assim_model - character(len=param_string_length), parameter, public :: stomatal_assim_name = "fates_stomatal_assim" + character(len=param_string_length), parameter, public :: stomatal_assim_name = "fates_leaf_stomatal_assim_model" ! Maximum allowable primary and secondary patches ! These values are USED FOR ALLOCATIONS IN BOTH FATES AND CLM/ELM!!!! + ! The number of patches specified in the parameter file may be over-written. + ! For instance, in SP mode, we want the same number of primary patches as the number of PFTs + ! in the fates parameter file, and zero secondary. - integer, protected, public :: maxpatch_primary + integer, public :: maxpatch_primary character(len=param_string_length), parameter, public :: maxpatch_primary_name = "fates_maxpatch_primary" - integer, protected, public :: maxpatch_secondary + integer, public :: maxpatch_secondary character(len=param_string_length), parameter, public :: maxpatch_secondary_name = "fates_maxpatch_secondary" + integer, public :: maxpatch_total + ! Maximum allowable cohorts per patch + integer, protected, public :: max_cohort_per_patch + character(len=param_string_length), parameter, public :: maxcohort_name = "fates_maxcohort" + + ! Logging Control Parameters (ONLY RELEVANT WHEN USE_FATES_LOGGING = TRUE) ! ---------------------------------------------------------------------------------------------- real(r8),protected,public :: logging_dbhmin ! Minimum dbh at which logging is applied (cm) ! Typically associated with harvesting - character(len=param_string_length),parameter,public :: logging_name_dbhmin = "fates_logging_dbhmin" + character(len=param_string_length),parameter,public :: logging_name_dbhmin = "fates_landuse_logging_dbhmin" real(r8),protected,public :: logging_dbhmax ! Maximum dbh at which logging is applied (cm) ! Typically associated with fire suppression - character(len=param_string_length),parameter,public :: logging_name_dbhmax = "fates_logging_dbhmax" + character(len=param_string_length),parameter,public :: logging_name_dbhmax = "fates_landuse_logging_dbhmax" real(r8),protected,public :: logging_collateral_frac ! Ratio of collateral mortality to direct logging mortality - character(len=param_string_length),parameter,public :: logging_name_collateral_frac = "fates_logging_collateral_frac" + character(len=param_string_length),parameter,public :: logging_name_collateral_frac = "fates_landuse_logging_collateral_frac" real(r8),protected,public :: logging_coll_under_frac ! Fraction of understory plants that die when logging disturbance ! is generated - character(len=param_string_length),parameter,public :: logging_name_coll_under_frac = "fates_logging_coll_under_frac" + character(len=param_string_length),parameter,public :: logging_name_coll_under_frac = "fates_landuse_logging_coll_under_frac" real(r8),protected,public :: logging_direct_frac ! Fraction of stems logged per event - character(len=param_string_length),parameter,public :: logging_name_direct_frac = "fates_logging_direct_frac" + character(len=param_string_length),parameter,public :: logging_name_direct_frac = "fates_landuse_logging_direct_frac" real(r8),protected,public :: logging_mechanical_frac ! Fraction of stems logged per event - character(len=param_string_length),parameter,public :: logging_name_mechanical_frac = "fates_logging_mechanical_frac" + character(len=param_string_length),parameter,public :: logging_name_mechanical_frac = "fates_landuse_logging_mechanical_frac" real(r8),protected,public :: logging_event_code ! Code that options how logging events are structured - character(len=param_string_length),parameter,public :: logging_name_event_code = "fates_logging_event_code" + character(len=param_string_length),parameter,public :: logging_name_event_code = "fates_landuse_logging_event_code" real(r8),protected,public :: logging_dbhmax_infra ! "Tree diameter, above which infrastructure from logging does not impact damage or mortality. - character(len=param_string_length),parameter,public :: logging_name_dbhmax_infra = "fates_logging_dbhmax_infra" + character(len=param_string_length),parameter,public :: logging_name_dbhmax_infra = "fates_landuse_logging_dbhmax_infra" real(r8),protected,public :: logging_export_frac ! "fraction of trunk product being shipped offsite, the ! leftovers will be left onsite as large CWD - character(len=param_string_length),parameter,public :: logging_name_export_frac ="fates_logging_export_frac" + character(len=param_string_length),parameter,public :: logging_name_export_frac ="fates_landuse_logging_export_frac" real(r8),protected,public :: eca_plant_escalar ! scaling factor for plant fine root biomass to ! calculate nutrient carrier enzyme abundance (ECA) - character(len=param_string_length),parameter,public :: eca_name_plant_escalar = "fates_eca_plant_escalar" + character(len=param_string_length),parameter,public :: eca_name_plant_escalar = "fates_cnp_eca_plant_escalar" public :: FatesParamsInit public :: FatesRegisterParams @@ -248,7 +255,6 @@ subroutine FatesParamsInit() ED_val_comp_excln = nan ED_val_vai_top_bin_width = nan ED_val_vai_width_increase_factor = nan - ED_val_init_litter = nan ED_val_nignitions = nan ED_val_understorey_death = nan ED_val_cwd_fcel = nan @@ -271,6 +277,7 @@ subroutine FatesParamsInit() stomatal_assim_model = -9 maxpatch_primary = -9 maxpatch_secondary = -9 + max_cohort_per_patch = -9 hydr_kmax_rsurf1 = nan hydr_kmax_rsurf2 = nan hydr_psi0 = nan @@ -346,9 +353,6 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=ED_name_vai_width_increase_factor, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) - call fates_params%RegisterParameter(name=ED_name_init_litter, dimension_shape=dimension_shape_scalar, & - dimension_names=dim_names_scalar) - call fates_params%RegisterParameter(name=ED_name_nignitions, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -414,6 +418,12 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=maxpatch_secondary_name, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) + + call fates_params%RegisterParameter(name=maxcohort_name, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + + call fates_params%RegisterParameter(name=hydr_name_solver, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) call fates_params%RegisterParameter(name=hydr_name_kmax_rsurf1, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -531,9 +541,6 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetreiveParameter(name=ED_name_vai_width_increase_factor, & data=ED_val_vai_width_increase_factor) - call fates_params%RetreiveParameter(name=ED_name_init_litter, & - data=ED_val_init_litter) - call fates_params%RetreiveParameter(name=ED_name_nignitions, & data=ED_val_nignitions) @@ -603,6 +610,12 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetreiveParameter(name=maxpatch_secondary_name, & data=tmpreal) maxpatch_secondary = nint(tmpreal) + + maxpatch_total = maxpatch_primary+maxpatch_secondary + + call fates_params%RetreiveParameter(name=maxcohort_name, & + data=tmpreal) + max_cohort_per_patch = nint(tmpreal) call fates_params%RetreiveParameter(name=hydr_name_kmax_rsurf1, & data=hydr_kmax_rsurf1) @@ -717,7 +730,6 @@ subroutine FatesReportParams(is_master) write(fates_log(),fmt0) 'ED_val_comp_excln = ',ED_val_comp_excln write(fates_log(),fmt0) 'ED_val_vai_top_bin_width = ',ED_val_vai_top_bin_width write(fates_log(),fmt0) 'ED_val_vai_width_increase_factor = ',ED_val_vai_width_increase_factor - write(fates_log(),fmt0) 'ED_val_init_litter = ',ED_val_init_litter write(fates_log(),fmt0) 'ED_val_nignitions = ',ED_val_nignitions write(fates_log(),fmt0) 'ED_val_understorey_death = ',ED_val_understorey_death write(fates_log(),fmt0) 'ED_val_cwd_fcel = ',ED_val_cwd_fcel @@ -738,11 +750,11 @@ subroutine FatesReportParams(is_master) write(fates_log(),fmt0) 'ED_val_canopy_closure_thresh = ',ED_val_canopy_closure_thresh write(fates_log(),fmt0) 'stomatal_model = ',stomatal_model write(fates_log(),fmt0) 'stomatal_assim_model = ',stomatal_assim_model - write(fates_log(),fmt0) 'hydr_kmax_rsurf1 = ',hydr_kmax_rsurf1 - write(fates_log(),fmt0) 'hydr_kmax_rsurf2 = ',hydr_kmax_rsurf2 - write(fates_log(),fmt0) 'hydr_psi0 = ',hydr_psi0 - write(fates_log(),fmt0) 'hydr_psicap = ',hydr_psicap - write(fates_log(),fmt0) 'hydr_solver = ',hydr_solver + write(fates_log(),fmt0) 'hydro_kmax_rsurf1 = ',hydr_kmax_rsurf1 + write(fates_log(),fmt0) 'hydro_kmax_rsurf2 = ',hydr_kmax_rsurf2 + write(fates_log(),fmt0) 'hydro_psi0 = ',hydr_psi0 + write(fates_log(),fmt0) 'hydro_psicap = ',hydr_psicap + write(fates_log(),fmt0) 'hydro_solver = ',hydr_solver write(fates_log(),fmt0) 'bgc_soil_salinity = ', bgc_soil_salinity write(fates_log(),fmt0) 'logging_dbhmin = ',logging_dbhmin write(fates_log(),fmt0) 'logging_dbhmax = ',logging_dbhmax diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 7678fb719e..6f738f6498 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -132,6 +132,9 @@ module EDPftvarcon ! prescribed_physiology_mode ! Nutrient Aquisition (ECA & RD) + + + !real(r8), allocatable :: rd_vmax_n(:) ! maximum production rate for plant n uptake [gN/gC/s] real(r8), allocatable :: decompmicc(:) ! microbial decomposer biomass gC/m3 ! on root surface @@ -158,7 +161,6 @@ module EDPftvarcon ! more in need a plant is for P versus N [/] !real(r8), allocatable :: nfix1(:) ! nitrogen fixation parameter 1 - !real(r8), allocatable :: nfix2(:) ! nitrogen fixation parameter 2 ! Turnover related things @@ -325,7 +327,7 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_recruit_hgt_min' + name = 'fates_recruit_height_min' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -337,11 +339,11 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_recruit_initd' + name = 'fates_recruit_init_density' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_seed_suppl' + name = 'fates_recruit_seed_supplement' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -357,36 +359,35 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_lf_flab' + name = 'fates_frag_leaf_flab' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_lf_fcel' + name = 'fates_frag_leaf_fcel' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_lf_flig' + name = 'fates_frag_leaf_flig' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_fr_flab' + name = 'fates_frag_fnrt_flab' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_fr_fcel' + name = 'fates_frag_fnrt_fcel' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_fr_flig' + name = 'fates_frag_fnrt_flig' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_leaf_xl' + name = 'fates_rad_leaf_xl' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - - name = 'fates_leaf_clumping_index' + name = 'fates_rad_leaf_clumping_index' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -394,11 +395,11 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_smpso' + name = 'fates_nonhydro_smpso' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_smpsc' + name = 'fates_nonhydro_smpsc' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -418,15 +419,15 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_prescribed_mortality_canopy' + name = 'fates_mort_prescribed_canopy' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_prescribed_mortality_understory' + name = 'fates_mort_prescribed_understory' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_prescribed_recruitment' + name = 'fates_recruit_prescribed_rate' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -438,31 +439,31 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_hydr_p_taper' + name = 'fates_hydro_p_taper' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_hydr_rs2' + name = 'fates_hydro_rs2' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_hydr_srl' + name = 'fates_hydro_srl' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_hydr_rfrac_stem' + name = 'fates_hydro_rfrac_stem' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_hydr_avuln_gs' + name = 'fates_hydro_avuln_gs' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_hydr_p50_gs' + name = 'fates_hydro_p50_gs' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_hydr_k_lwp' + name = 'fates_hydro_k_lwp' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -530,11 +531,11 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_seed_germination_rate' + name = 'fates_recruit_seed_germination_rate' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_seed_decay_rate' + name = 'fates_frag_seed_decay_rate' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -546,19 +547,19 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_leaf_diameter' + name = 'fates_turb_leaf_diameter' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_z0mr' + name = 'fates_turb_z0mr' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_displar' + name = 'fates_turb_displar' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_phenflush_fraction' + name = 'fates_phen_flush_fraction' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -573,55 +574,55 @@ subroutine Register_PFT(this, fates_params) ! Nutrient competition parameters - name = 'fates_eca_decompmicc' + name = 'fates_cnp_eca_decompmicc' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_eca_km_nh4' + name = 'fates_cnp_eca_km_nh4' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_eca_vmax_nh4' + name = 'fates_cnp_eca_vmax_nh4' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_eca_km_no3' + name = 'fates_cnp_eca_km_no3' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_eca_vmax_no3' + name = 'fates_cnp_eca_vmax_no3' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_eca_km_p' + name = 'fates_cnp_eca_km_p' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_eca_vmax_p' + name = 'fates_cnp_vmax_p' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_eca_km_ptase' + name = 'fates_cnp_eca_km_ptase' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_eca_vmax_ptase' + name = 'fates_cnp_eca_vmax_ptase' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_eca_alpha_ptase' + name = 'fates_cnp_eca_alpha_ptase' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_eca_lambda_ptase' + name = 'fates_cnp_eca_lambda_ptase' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_prescribed_nuptake' + name = 'fates_cnp_prescribed_nuptake' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_prescribed_puptake' + name = 'fates_cnp_prescribed_puptake' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -659,7 +660,7 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=this%freezetol) - name = 'fates_recruit_hgt_min' + name = 'fates_recruit_height_min' call fates_params%RetreiveParameterAllocate(name=name, & data=this%hgt_min) @@ -671,11 +672,11 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=this%crown_kill) - name = 'fates_recruit_initd' + name = 'fates_recruit_init_density' call fates_params%RetreiveParameterAllocate(name=name, & data=this%initd) - name = 'fates_seed_suppl' + name = 'fates_recruit_seed_supplement' call fates_params%RetreiveParameterAllocate(name=name, & data=this%seed_suppl) @@ -691,35 +692,35 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=this%stomatal_intercept) - name = 'fates_lf_flab' + name = 'fates_frag_leaf_flab' call fates_params%RetreiveParameterAllocate(name=name, & data=this%lf_flab) - name = 'fates_lf_fcel' + name = 'fates_frag_leaf_fcel' call fates_params%RetreiveParameterAllocate(name=name, & data=this%lf_fcel) - name = 'fates_lf_flig' + name = 'fates_frag_leaf_flig' call fates_params%RetreiveParameterAllocate(name=name, & data=this%lf_flig) - name = 'fates_fr_flab' + name = 'fates_frag_fnrt_flab' call fates_params%RetreiveParameterAllocate(name=name, & data=this%fr_flab) - name = 'fates_fr_fcel' + name = 'fates_frag_fnrt_fcel' call fates_params%RetreiveParameterAllocate(name=name, & data=this%fr_fcel) - name = 'fates_fr_flig' + name = 'fates_frag_fnrt_flig' call fates_params%RetreiveParameterAllocate(name=name, & data=this%fr_flig) - name = 'fates_leaf_xl' + name = 'fates_rad_leaf_xl' call fates_params%RetreiveParameterAllocate(name=name, & data=this%xl) - name = 'fates_leaf_clumping_index' + name = 'fates_rad_leaf_clumping_index' call fates_params%RetreiveParameterAllocate(name=name, & data=this%clumping_index) @@ -727,11 +728,11 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=this%c3psn) - name = 'fates_smpso' + name = 'fates_nonhydro_smpso' call fates_params%RetreiveParameterAllocate(name=name, & data=this%smpso) - name = 'fates_smpsc' + name = 'fates_nonhydro_smpsc' call fates_params%RetreiveParameterAllocate(name=name, & data=this%smpsc) @@ -751,15 +752,15 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=this%prescribed_npp_understory) - name = 'fates_prescribed_mortality_canopy' + name = 'fates_mort_prescribed_canopy' call fates_params%RetreiveParameterAllocate(name=name, & data=this%prescribed_mortality_canopy) - name = 'fates_prescribed_mortality_understory' + name = 'fates_mort_prescribed_understory' call fates_params%RetreiveParameterAllocate(name=name, & data=this%prescribed_mortality_understory) - name = 'fates_prescribed_recruitment' + name = 'fates_recruit_prescribed_rate' call fates_params%RetreiveParameterAllocate(name=name, & data=this%prescribed_recruitment) @@ -771,35 +772,31 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=this%allom_frbstor_repro) - name = 'fates_hydr_p_taper' + name = 'fates_hydro_p_taper' call fates_params%RetreiveParameterAllocate(name=name, & data=this%hydr_p_taper) - name = 'fates_hydr_rs2' + name = 'fates_hydro_rs2' call fates_params%RetreiveParameterAllocate(name=name, & data=this%hydr_rs2) - name = 'fates_hydr_srl' + name = 'fates_hydro_srl' call fates_params%RetreiveParameterAllocate(name=name, & data=this%hydr_srl) - name = 'fates_hydr_rfrac_stem' + name = 'fates_hydro_rfrac_stem' call fates_params%RetreiveParameterAllocate(name=name, & data=this%hydr_rfrac_stem) - name = 'fates_hydr_k_lwp' - call fates_params%RetreiveParameterAllocate(name=name, & - data=this%hydr_k_lwp) - - name = 'fates_hydr_avuln_gs' + name = 'fates_hydro_avuln_gs' call fates_params%RetreiveParameterAllocate(name=name, & data=this%hydr_avuln_gs) - name = 'fates_hydr_p50_gs' + name = 'fates_hydro_p50_gs' call fates_params%RetreiveParameterAllocate(name=name, & data=this%hydr_p50_gs) - name = 'fates_hydr_k_lwp' + name = 'fates_hydro_k_lwp' call fates_params%RetreiveParameterAllocate(name=name, & data=this%hydr_k_lwp) @@ -877,11 +874,11 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=this%jmaxse) - name = 'fates_seed_germination_rate' + name = 'fates_recruit_seed_germination_rate' call fates_params%RetreiveParameterAllocate(name=name, & data=this%germination_rate) - name = 'fates_seed_decay_rate' + name = 'fates_frag_seed_decay_rate' call fates_params%RetreiveParameterAllocate(name=name, & data=this%seed_decay_rate) @@ -893,19 +890,19 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=this%trim_inc) - name = 'fates_leaf_diameter' + name = 'fates_turb_leaf_diameter' call fates_params%RetreiveParameterAllocate(name=name, & data=this%dleaf) - name = 'fates_z0mr' + name = 'fates_turb_z0mr' call fates_params%RetreiveParameterAllocate(name=name, & data=this%z0mr) - name = 'fates_displar' + name = 'fates_turb_displar' call fates_params%RetreiveParameterAllocate(name=name, & data=this%displar) - name = 'fates_phenflush_fraction' + name = 'fates_phen_flush_fraction' call fates_params%RetreiveParameterAllocate(name=name, & data=this%phenflush_fraction) @@ -917,11 +914,11 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=this%phen_stem_drop_fraction) - name = 'fates_prescribed_nuptake' + name = 'fates_cnp_prescribed_nuptake' call fates_params%RetreiveParameterAllocate(name=name, & data=this%prescribed_nuptake) - name = 'fates_prescribed_puptake' + name = 'fates_cnp_prescribed_puptake' call fates_params%RetreiveParameterAllocate(name=name, & data=this%prescribed_puptake) @@ -929,47 +926,47 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=this%dev_arbitrary_pft) - name = 'fates_eca_decompmicc' + name = 'fates_cnp_eca_decompmicc' call fates_params%RetreiveParameterAllocate(name=name, & data=this%decompmicc) - name = 'fates_eca_km_nh4' + name = 'fates_cnp_eca_km_nh4' call fates_params%RetreiveParameterAllocate(name=name, & data=this%eca_km_nh4) - name = 'fates_eca_vmax_nh4' + name = 'fates_cnp_eca_vmax_nh4' call fates_params%RetreiveParameterAllocate(name=name, & data=this%eca_vmax_nh4) - name = 'fates_eca_km_no3' + name = 'fates_cnp_eca_km_no3' call fates_params%RetreiveParameterAllocate(name=name, & data=this%eca_km_no3) - name = 'fates_eca_vmax_no3' + name = 'fates_cnp_eca_vmax_no3' call fates_params%RetreiveParameterAllocate(name=name, & data=this%eca_vmax_no3) - name = 'fates_eca_km_p' + name = 'fates_cnp_eca_km_p' call fates_params%RetreiveParameterAllocate(name=name, & data=this%eca_km_p) - name = 'fates_eca_vmax_p' + name = 'fates_cnp_vmax_p' call fates_params%RetreiveParameterAllocate(name=name, & data=this%eca_vmax_p) - name = 'fates_eca_km_ptase' + name = 'fates_cnp_eca_km_ptase' call fates_params%RetreiveParameterAllocate(name=name, & data=this%eca_km_ptase) - name = 'fates_eca_vmax_ptase' + name = 'fates_cnp_eca_vmax_ptase' call fates_params%RetreiveParameterAllocate(name=name, & data=this%eca_vmax_ptase) - name = 'fates_eca_alpha_ptase' + name = 'fates_cnp_eca_alpha_ptase' call fates_params%RetreiveParameterAllocate(name=name, & data=this%eca_alpha_ptase) - name = 'fates_eca_lambda_ptase' + name = 'fates_cnp_eca_lambda_ptase' call fates_params%RetreiveParameterAllocate(name=name, & data=this%eca_lambda_ptase) @@ -1001,35 +998,35 @@ subroutine Register_PFT_numrad(this, fates_params) !X! call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & !X! dimension_names=dim_names) - name = 'fates_rholvis' + name = 'fates_rad_leaf_rhovis' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names) - name = 'fates_rholnir' + name = 'fates_rad_leaf_rhonir' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names) - name = 'fates_rhosvis' + name = 'fates_rad_stem_rhovis' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names) - name = 'fates_rhosnir' + name = 'fates_rad_stem_rhonir' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names) - name = 'fates_taulvis' + name = 'fates_rad_leaf_tauvis' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names) - name = 'fates_taulnir' + name = 'fates_rad_leaf_taunir' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names) - name = 'fates_tausvis' + name = 'fates_rad_stem_tauvis' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names) - name = 'fates_tausnir' + name = 'fates_rad_stem_taunir' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names) @@ -1071,7 +1068,7 @@ subroutine Receive_PFT_numrad(this, fates_params) ! Fetch metadata from a representative variable. All variables ! called by this subroutine must be dimensioned the same way! - name = 'fates_rholvis' + name = 'fates_rad_leaf_rhovis' index = fates_params%FindIndex(name) call fates_params%GetMetaData(index, name, dimension_shape, dimension_sizes, dimension_names, is_host_param) lower_bound_1 = lower_bound_pft @@ -1088,12 +1085,12 @@ subroutine Receive_PFT_numrad(this, fates_params) ! allocate(this%rhol(lower_bound_1:upper_bound_1, lower_bound_2:upper_bound_2)) - name = 'fates_rholvis' + name = 'fates_rad_leaf_rhovis' call fates_params%RetreiveParameter(name=name, & data=dummy_data) this%rhol(lower_bound_1:upper_bound_1, ivis) = dummy_data - name = 'fates_rholnir' + name = 'fates_rad_leaf_rhonir' call fates_params%RetreiveParameter(name=name, & data=dummy_data) this%rhol(lower_bound_1:upper_bound_1, inir) = dummy_data @@ -1103,12 +1100,12 @@ subroutine Receive_PFT_numrad(this, fates_params) ! allocate(this%rhos(lower_bound_1:upper_bound_1, lower_bound_2:upper_bound_2)) - name = 'fates_rhosvis' + name = 'fates_rad_stem_rhovis' call fates_params%RetreiveParameter(name=name, & data=dummy_data) this%rhos(lower_bound_1:upper_bound_1, ivis) = dummy_data - name = 'fates_rhosnir' + name = 'fates_rad_stem_rhonir' call fates_params%RetreiveParameter(name=name, & data=dummy_data) this%rhos(lower_bound_1:upper_bound_1, inir) = dummy_data @@ -1118,12 +1115,12 @@ subroutine Receive_PFT_numrad(this, fates_params) ! allocate(this%taul(lower_bound_1:upper_bound_1, lower_bound_2:upper_bound_2)) - name = 'fates_taulvis' + name = 'fates_rad_leaf_tauvis' call fates_params%RetreiveParameter(name=name, & data=dummy_data) this%taul(lower_bound_1:upper_bound_1, ivis) = dummy_data - name = 'fates_taulnir' + name = 'fates_rad_leaf_taunir' call fates_params%RetreiveParameter(name=name, & data=dummy_data) this%taul(lower_bound_1:upper_bound_1, inir) = dummy_data @@ -1133,12 +1130,12 @@ subroutine Receive_PFT_numrad(this, fates_params) ! allocate(this%taus(lower_bound_1:upper_bound_1, lower_bound_2:upper_bound_2)) - name = 'fates_tausvis' + name = 'fates_rad_stem_tauvis' call fates_params%RetreiveParameter(name=name, & data=dummy_data) this%taus(lower_bound_1:upper_bound_1, ivis) = dummy_data - name = 'fates_tausnir' + name = 'fates_rad_stem_taunir' call fates_params%RetreiveParameter(name=name, & data=dummy_data) this%taus(lower_bound_1:upper_bound_1, inir) = dummy_data @@ -1220,63 +1217,63 @@ subroutine Register_PFT_hydr_organs(this, fates_params) dim_names(1) = dimension_name_pft dim_names(2) = dimension_name_hydr_organs - name = 'fates_hydr_vg_alpha_node' + name = 'fates_hydro_vg_alpha_node' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_hydr_vg_m_node' + name = 'fates_hydro_vg_m_node' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_hydr_vg_n_node' + name = 'fates_hydro_vg_n_node' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_hydr_avuln_node' + name = 'fates_hydro_avuln_node' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_hydr_p50_node' + name = 'fates_hydro_p50_node' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_hydr_thetas_node' + name = 'fates_hydro_thetas_node' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_hydr_epsil_node' + name = 'fates_hydro_epsil_node' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_hydr_pitlp_node' + name = 'fates_hydro_pitlp_node' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_hydr_resid_node' + name = 'fates_hydro_resid_node' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_hydr_fcap_node' + name = 'fates_hydro_fcap_node' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_hydr_pinot_node' + name = 'fates_hydro_pinot_node' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_hydr_kmax_node' + name = 'fates_hydro_kmax_node' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_hydr_vg_alpha_node' + name = 'fates_hydro_vg_alpha_node' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_hydr_vg_m_node' + name = 'fates_hydro_vg_m_node' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_hydr_vg_n_node' + name = 'fates_hydro_vg_n_node' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -1297,63 +1294,63 @@ subroutine Receive_PFT_hydr_organs(this, fates_params) character(len=param_string_length) :: name - name = 'fates_hydr_vg_alpha_node' + name = 'fates_hydro_vg_alpha_node' call fates_params%RetreiveParameterAllocate(name=name, & data=this%hydr_vg_alpha_node) - name = 'fates_hydr_vg_m_node' + name = 'fates_hydro_vg_m_node' call fates_params%RetreiveParameterAllocate(name=name, & data=this%hydr_vg_m_node) - name = 'fates_hydr_vg_n_node' + name = 'fates_hydro_vg_n_node' call fates_params%RetreiveParameterAllocate(name=name, & data=this%hydr_vg_n_node) - name = 'fates_hydr_avuln_node' + name = 'fates_hydro_avuln_node' call fates_params%RetreiveParameterAllocate(name=name, & data=this%hydr_avuln_node) - name = 'fates_hydr_p50_node' + name = 'fates_hydro_p50_node' call fates_params%RetreiveParameterAllocate(name=name, & data=this%hydr_p50_node) - name = 'fates_hydr_thetas_node' + name = 'fates_hydro_thetas_node' call fates_params%RetreiveParameterAllocate(name=name, & data=this%hydr_thetas_node) - name = 'fates_hydr_epsil_node' + name = 'fates_hydro_epsil_node' call fates_params%RetreiveParameterAllocate(name=name, & data=this%hydr_epsil_node) - name = 'fates_hydr_pitlp_node' + name = 'fates_hydro_pitlp_node' call fates_params%RetreiveParameterAllocate(name=name, & data=this%hydr_pitlp_node) - name = 'fates_hydr_resid_node' + name = 'fates_hydro_resid_node' call fates_params%RetreiveParameterAllocate(name=name, & data=this%hydr_resid_node) - name = 'fates_hydr_fcap_node' + name = 'fates_hydro_fcap_node' call fates_params%RetreiveParameterAllocate(name=name, & data=this%hydr_fcap_node) - name = 'fates_hydr_pinot_node' + name = 'fates_hydro_pinot_node' call fates_params%RetreiveParameterAllocate(name=name, & data=this%hydr_pinot_node) - name = 'fates_hydr_kmax_node' + name = 'fates_hydro_kmax_node' call fates_params%RetreiveParameterAllocate(name=name, & data=this%hydr_kmax_node) - name = 'fates_hydr_vg_alpha_node' + name = 'fates_hydro_vg_alpha_node' call fates_params%RetreiveParameterAllocate(name=name, & data=this%hydr_vg_alpha_node) - name = 'fates_hydr_vg_m_node' + name = 'fates_hydro_vg_m_node' call fates_params%RetreiveParameterAllocate(name=name, & data=this%hydr_vg_m_node) - name = 'fates_hydr_vg_n_node' + name = 'fates_hydro_vg_n_node' call fates_params%RetreiveParameterAllocate(name=name, & data=this%hydr_vg_n_node) @@ -1431,32 +1428,31 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'rhos = ',EDPftvarcon_inst%rhos write(fates_log(),fmt0) 'taul = ',EDPftvarcon_inst%taul write(fates_log(),fmt0) 'taus = ',EDPftvarcon_inst%taus - write(fates_log(),fmt0) 'phenflush_fraction',EDpftvarcon_inst%phenflush_fraction + write(fates_log(),fmt0) 'phen_flush_fraction',EDpftvarcon_inst%phenflush_fraction write(fates_log(),fmt0) 'phen_cold_size_threshold = ',EDPftvarcon_inst%phen_cold_size_threshold write(fates_log(),fmt0) 'phen_stem_drop_fraction',EDpftvarcon_inst%phen_stem_drop_fraction write(fates_log(),fmt0) 'fire_alpha_SH = ',EDPftvarcon_inst%fire_alpha_SH write(fates_log(),fmt0) 'allom_frbstor_repro = ',EDPftvarcon_inst%allom_frbstor_repro - write(fates_log(),fmt0) 'hydr_p_taper = ',EDPftvarcon_inst%hydr_p_taper - write(fates_log(),fmt0) 'hydr_rs2 = ',EDPftvarcon_inst%hydr_rs2 - write(fates_log(),fmt0) 'hydr_srl = ',EDPftvarcon_inst%hydr_srl - write(fates_log(),fmt0) 'hydr_rfrac_stem = ',EDPftvarcon_inst%hydr_rfrac_stem - write(fates_log(),fmt0) 'hydr_avuln_gs = ',EDPftvarcon_inst%hydr_avuln_gs - write(fates_log(),fmt0) 'hydr_k_lwp = ',EDPftvarcon_inst%hydr_k_lwp - write(fates_log(),fmt0) 'hydr_p50_gs = ',EDPftvarcon_inst%hydr_p50_gs - write(fates_log(),fmt0) 'hydr_k_lwp = ',EDPftvarcon_inst%hydr_k_lwp - write(fates_log(),fmt0) 'hydr_avuln_node = ',EDPftvarcon_inst%hydr_avuln_node - write(fates_log(),fmt0) 'hydr_p50_node = ',EDPftvarcon_inst%hydr_p50_node - write(fates_log(),fmt0) 'hydr_thetas_node = ',EDPftvarcon_inst%hydr_thetas_node - write(fates_log(),fmt0) 'hydr_epsil_node = ',EDPftvarcon_inst%hydr_epsil_node - write(fates_log(),fmt0) 'hydr_pitlp_node = ',EDPftvarcon_inst%hydr_pitlp_node - write(fates_log(),fmt0) 'hydr_resid_node = ',EDPftvarcon_inst%hydr_resid_node - write(fates_log(),fmt0) 'hydr_fcap_node = ',EDPftvarcon_inst%hydr_fcap_node - write(fates_log(),fmt0) 'hydr_pinot_node = ',EDPftvarcon_inst%hydr_pinot_node - write(fates_log(),fmt0) 'hydr_kmax_node = ',EDPftvarcon_inst%hydr_kmax_node + write(fates_log(),fmt0) 'hydro_p_taper = ',EDPftvarcon_inst%hydr_p_taper + write(fates_log(),fmt0) 'hydro_rs2 = ',EDPftvarcon_inst%hydr_rs2 + write(fates_log(),fmt0) 'hydro_srl = ',EDPftvarcon_inst%hydr_srl + write(fates_log(),fmt0) 'hydro_rfrac_stem = ',EDPftvarcon_inst%hydr_rfrac_stem + write(fates_log(),fmt0) 'hydro_avuln_gs = ',EDPftvarcon_inst%hydr_avuln_gs + write(fates_log(),fmt0) 'hydro_k_lwp = ',EDPftvarcon_inst%hydr_k_lwp + write(fates_log(),fmt0) 'hydro_p50_gs = ',EDPftvarcon_inst%hydr_p50_gs + write(fates_log(),fmt0) 'hydro_avuln_node = ',EDPftvarcon_inst%hydr_avuln_node + write(fates_log(),fmt0) 'hydro_p50_node = ',EDPftvarcon_inst%hydr_p50_node + write(fates_log(),fmt0) 'hydro_thetas_node = ',EDPftvarcon_inst%hydr_thetas_node + write(fates_log(),fmt0) 'hydro_epsil_node = ',EDPftvarcon_inst%hydr_epsil_node + write(fates_log(),fmt0) 'hydro_pitlp_node = ',EDPftvarcon_inst%hydr_pitlp_node + write(fates_log(),fmt0) 'hydro_resid_node = ',EDPftvarcon_inst%hydr_resid_node + write(fates_log(),fmt0) 'hydro_fcap_node = ',EDPftvarcon_inst%hydr_fcap_node + write(fates_log(),fmt0) 'hydro_pinot_node = ',EDPftvarcon_inst%hydr_pinot_node + write(fates_log(),fmt0) 'hydro_kmax_node = ',EDPftvarcon_inst%hydr_kmax_node write(fates_log(),fmt0) 'hlm_pft_map = ', EDPftvarcon_inst%hlm_pft_map - write(fates_log(),fmt0) 'hydr_vg_alpha_node = ',EDPftvarcon_inst%hydr_vg_alpha_node - write(fates_log(),fmt0) 'hydr_vg_m_node = ',EDPftvarcon_inst%hydr_vg_m_node - write(fates_log(),fmt0) 'hydr_vg_n_node = ',EDPftvarcon_inst%hydr_vg_n_node + write(fates_log(),fmt0) 'hydro_vg_alpha_node = ',EDPftvarcon_inst%hydr_vg_alpha_node + write(fates_log(),fmt0) 'hydro_vg_m_node = ',EDPftvarcon_inst%hydr_vg_m_node + write(fates_log(),fmt0) 'hydro_vg_n_node = ',EDPftvarcon_inst%hydr_vg_n_node write(fates_log(),*) '-------------------------------------------------' end if diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 9ce4d5fe44..12915df7aa 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -28,10 +28,9 @@ module EDTypesMod private ! By default everything is private save - integer, parameter, public :: maxPatchesPerSite = 14 ! maximum number of patches to live on a site - integer, parameter, public :: maxPatchesPerSite_by_disttype(n_anthro_disturbance_categories) = & - (/ 10, 4 /) !!! MUST SUM TO maxPatchesPerSite !!! - integer, public :: maxCohortsPerPatch = 100 ! maximum number of cohorts per patch +! integer, parameter, public :: maxPatchesPerSite = 14 ! maximum number of patches to live on a site +! integer, parameter, public :: maxPatchesPerSite_by_disttype(n_anthro_disturbance_categories) = & +! (/ 10, 4 /) !!! MUST SUM TO maxPatchesPerSite !!! integer, parameter, public :: nclmax = 2 ! Maximum number of canopy layers integer, parameter, public :: ican_upper = 1 ! Nominal index for the upper canopy @@ -429,7 +428,7 @@ module EDTypesMod class(rmean_type), pointer :: tveg24 ! 24-hour mean vegetation temperature (K) class(rmean_type), pointer :: tveg_lpa ! Running mean of vegetation temperature at the ! leaf photosynthesis acclimation timescale [K] - integer :: nocomp_pft_label ! where nocomp is active, use this label for patch ID. + integer :: nocomp_pft_label ! where nocomp is active, use this label for patch ID. ! LEAF ORGANIZATION real(r8) :: pft_agb_profile(maxpft,n_dbh_bins) ! binned above ground biomass, for patch fusion: KgC/m2 diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index d3f7bcfae1..3169d459f1 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -3614,10 +3614,12 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) hio_rad_error_si(io_si) = hio_rad_error_si(io_si) + & cpatch%radiation_error * cpatch%area * AREA_INV + + if(cpatch%patchno.ne.0)then + hio_tveg(io_si) = hio_tveg(io_si) + & + (bc_in(s)%t_veg_pa(cpatch%patchno) - t_water_freeze_k_1atm)*cpatch%area*area_inv + end if - hio_tveg(io_si) = hio_tveg(io_si) + & - (bc_in(s)%t_veg_pa(cpatch%patchno) - t_water_freeze_k_1atm)*cpatch%area*area_inv - ccohort => cpatch%shortest do while(associated(ccohort)) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index da72c4697c..927365356b 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -10,12 +10,14 @@ module FatesInterfaceMod ! ------------------------------------------------------------------------------------ use EDTypesMod , only : ed_site_type - use EDTypesMod , only : maxPatchesPerSite - use EDTypesMod , only : maxCohortsPerPatch use EDTypesMod , only : dinc_vai use EDTypesMod , only : dlower_vai use EDParamsMod , only : ED_val_vai_top_bin_width use EDParamsMod , only : ED_val_vai_width_increase_factor + use EDParamsMod , only : maxpatch_total + use EDParamsMod , only : maxpatch_primary + use EDParamsMod , only : maxpatch_secondary + use EDParamsMod , only : max_cohort_per_patch use EDTypesMod , only : maxSWb use EDTypesMod , only : ivis use EDTypesMod , only : inir @@ -143,7 +145,8 @@ module FatesInterfaceMod public :: FatesInterfaceInit public :: set_fates_ctrlparms public :: SetFatesTime - public :: SetFatesGlobalElements + public :: SetFatesGlobalElements1 + public :: SetFatesGlobalElements2 public :: FatesReportParameters public :: allocate_bcin public :: allocate_bcout @@ -375,7 +378,7 @@ end subroutine zero_bcs ! =========================================================================== - subroutine allocate_bcin(bc_in, nlevsoil_in, nlevdecomp_in, num_lu_harvest_cats) + subroutine allocate_bcin(bc_in, nlevsoil_in, nlevdecomp_in, num_lu_harvest_cats,natpft_lb,natpft_ub) ! --------------------------------------------------------------------------------- ! Allocate and Initialze the FATES boundary condition vectors @@ -386,6 +389,7 @@ subroutine allocate_bcin(bc_in, nlevsoil_in, nlevdecomp_in, num_lu_harvest_cats) integer,intent(in) :: nlevsoil_in integer,intent(in) :: nlevdecomp_in integer,intent(in) :: num_lu_harvest_cats + integer,intent(in) :: natpft_lb,natpft_ub ! dimension bounds of the array holding surface file pft data ! Allocate input boundaries @@ -471,15 +475,15 @@ subroutine allocate_bcin(bc_in, nlevsoil_in, nlevdecomp_in, num_lu_harvest_cats) ! Lightning (or successful ignitions) and population density ! Fire related variables - allocate(bc_in%lightning24(maxPatchesPerSite)) - allocate(bc_in%pop_density(maxPatchesPerSite)) - allocate(bc_in%wind24_pa(maxPatchesPerSite)) - allocate(bc_in%relhumid24_pa(maxPatchesPerSite)) - allocate(bc_in%precip24_pa(maxPatchesPerSite)) + allocate(bc_in%lightning24(maxpatch_total)) + allocate(bc_in%pop_density(maxpatch_total)) + allocate(bc_in%wind24_pa(maxpatch_total)) + allocate(bc_in%relhumid24_pa(maxpatch_total)) + allocate(bc_in%precip24_pa(maxpatch_total)) ! Radiation - allocate(bc_in%solad_parb(maxPatchesPerSite,hlm_numSWb)) - allocate(bc_in%solai_parb(maxPatchesPerSite,hlm_numSWb)) + allocate(bc_in%solad_parb(maxpatch_total,hlm_numSWb)) + allocate(bc_in%solai_parb(maxpatch_total,hlm_numSWb)) ! Hydrology allocate(bc_in%smp_sl(nlevsoil_in)) @@ -496,30 +500,30 @@ subroutine allocate_bcin(bc_in, nlevsoil_in, nlevdecomp_in, num_lu_harvest_cats) ! Photosynthesis - allocate(bc_in%filter_photo_pa(maxPatchesPerSite)) - allocate(bc_in%dayl_factor_pa(maxPatchesPerSite)) - allocate(bc_in%esat_tv_pa(maxPatchesPerSite)) - allocate(bc_in%eair_pa(maxPatchesPerSite)) - allocate(bc_in%oair_pa(maxPatchesPerSite)) - allocate(bc_in%cair_pa(maxPatchesPerSite)) - allocate(bc_in%rb_pa(maxPatchesPerSite)) - allocate(bc_in%t_veg_pa(maxPatchesPerSite)) - allocate(bc_in%tgcm_pa(maxPatchesPerSite)) + allocate(bc_in%filter_photo_pa(maxpatch_total)) + allocate(bc_in%dayl_factor_pa(maxpatch_total)) + allocate(bc_in%esat_tv_pa(maxpatch_total)) + allocate(bc_in%eair_pa(maxpatch_total)) + allocate(bc_in%oair_pa(maxpatch_total)) + allocate(bc_in%cair_pa(maxpatch_total)) + allocate(bc_in%rb_pa(maxpatch_total)) + allocate(bc_in%t_veg_pa(maxpatch_total)) + allocate(bc_in%tgcm_pa(maxpatch_total)) allocate(bc_in%t_soisno_sl(nlevsoil_in)) ! Canopy Radiation - allocate(bc_in%filter_vegzen_pa(maxPatchesPerSite)) - allocate(bc_in%coszen_pa(maxPatchesPerSite)) - allocate(bc_in%fcansno_pa(maxPatchesPerSite)) + allocate(bc_in%filter_vegzen_pa(maxpatch_total)) + allocate(bc_in%coszen_pa(maxpatch_total)) + allocate(bc_in%fcansno_pa(maxpatch_total)) allocate(bc_in%albgr_dir_rb(hlm_numSWb)) allocate(bc_in%albgr_dif_rb(hlm_numSWb)) ! Plant-Hydro BC's if (hlm_use_planthydro.eq.itrue) then - allocate(bc_in%qflx_transp_pa(maxPatchesPerSite)) - allocate(bc_in%swrad_net_pa(maxPatchesPerSite)) - allocate(bc_in%lwrad_net_pa(maxPatchesPerSite)) + allocate(bc_in%qflx_transp_pa(maxpatch_total)) + allocate(bc_in%swrad_net_pa(maxpatch_total)) + allocate(bc_in%lwrad_net_pa(maxpatch_total)) allocate(bc_in%watsat_sisl(nlevsoil_in)) allocate(bc_in%watres_sisl(nlevsoil_in)) @@ -541,13 +545,13 @@ subroutine allocate_bcin(bc_in, nlevsoil_in, nlevdecomp_in, num_lu_harvest_cats) allocate(bc_in%hlm_harvest_catnames(0)) end if - allocate(bc_in%pft_areafrac(0:maxpft)) + allocate(bc_in%pft_areafrac(natpft_lb:natpft_ub)) ! Variables for SP mode. if(hlm_use_sp.eq.itrue) then - allocate(bc_in%hlm_sp_tlai(0:maxpft)) - allocate(bc_in%hlm_sp_tsai(0:maxpft)) - allocate(bc_in%hlm_sp_htop(0:maxpft)) + allocate(bc_in%hlm_sp_tlai(natpft_lb:natpft_ub)) + allocate(bc_in%hlm_sp_tsai(natpft_lb:natpft_ub)) + allocate(bc_in%hlm_sp_htop(natpft_lb:natpft_ub)) end if return end subroutine allocate_bcin @@ -566,28 +570,28 @@ subroutine allocate_bcout(bc_out, nlevsoil_in, nlevdecomp_in) integer,intent(in) :: nlevdecomp_in ! Radiation - allocate(bc_out%fsun_pa(maxPatchesPerSite)) - allocate(bc_out%laisun_pa(maxPatchesPerSite)) - allocate(bc_out%laisha_pa(maxPatchesPerSite)) + allocate(bc_out%fsun_pa(maxpatch_total)) + allocate(bc_out%laisun_pa(maxpatch_total)) + allocate(bc_out%laisha_pa(maxpatch_total)) ! Hydrology allocate(bc_out%active_suction_sl(nlevsoil_in)) - allocate(bc_out%rootr_pasl(maxPatchesPerSite,nlevsoil_in)) - allocate(bc_out%btran_pa(maxPatchesPerSite)) + allocate(bc_out%rootr_pasl(maxpatch_total,nlevsoil_in)) + allocate(bc_out%btran_pa(maxpatch_total)) ! Photosynthesis - allocate(bc_out%rssun_pa(maxPatchesPerSite)) - allocate(bc_out%rssha_pa(maxPatchesPerSite)) + allocate(bc_out%rssun_pa(maxpatch_total)) + allocate(bc_out%rssha_pa(maxpatch_total)) ! Canopy Radiation - allocate(bc_out%albd_parb(maxPatchesPerSite,hlm_numSWb)) - allocate(bc_out%albi_parb(maxPatchesPerSite,hlm_numSWb)) - allocate(bc_out%fabd_parb(maxPatchesPerSite,hlm_numSWb)) - allocate(bc_out%fabi_parb(maxPatchesPerSite,hlm_numSWb)) - allocate(bc_out%ftdd_parb(maxPatchesPerSite,hlm_numSWb)) - allocate(bc_out%ftid_parb(maxPatchesPerSite,hlm_numSWb)) - allocate(bc_out%ftii_parb(maxPatchesPerSite,hlm_numSWb)) + allocate(bc_out%albd_parb(maxpatch_total,hlm_numSWb)) + allocate(bc_out%albi_parb(maxpatch_total,hlm_numSWb)) + allocate(bc_out%fabd_parb(maxpatch_total,hlm_numSWb)) + allocate(bc_out%fabi_parb(maxpatch_total,hlm_numSWb)) + allocate(bc_out%ftdd_parb(maxpatch_total,hlm_numSWb)) + allocate(bc_out%ftid_parb(maxpatch_total,hlm_numSWb)) + allocate(bc_out%ftii_parb(maxpatch_total,hlm_numSWb)) ! We allocate the boundary conditions to the BGC @@ -616,13 +620,13 @@ subroutine allocate_bcout(bc_out, nlevsoil_in, nlevdecomp_in) ! Include the bare-ground patch for these patch-level boundary conditions ! (it will always be zero for all of these) if(hlm_use_ch4.eq.itrue) then - allocate(bc_out%annavg_agnpp_pa(0:maxPatchesPerSite));bc_out%annavg_agnpp_pa(:)=nan - allocate(bc_out%annavg_bgnpp_pa(0:maxPatchesPerSite));bc_out%annavg_bgnpp_pa(:)=nan - allocate(bc_out%annsum_npp_pa(0:maxPatchesPerSite));bc_out%annsum_npp_pa(:)=nan - allocate(bc_out%frootc_pa(0:maxPatchesPerSite));bc_out%frootc_pa(:)=nan + allocate(bc_out%annavg_agnpp_pa(0:maxpatch_total));bc_out%annavg_agnpp_pa(:)=nan + allocate(bc_out%annavg_bgnpp_pa(0:maxpatch_total));bc_out%annavg_bgnpp_pa(:)=nan + allocate(bc_out%annsum_npp_pa(0:maxpatch_total));bc_out%annsum_npp_pa(:)=nan + allocate(bc_out%frootc_pa(0:maxpatch_total));bc_out%frootc_pa(:)=nan allocate(bc_out%root_resp(nlevsoil_in));bc_out%root_resp(:)=nan - allocate(bc_out%woody_frac_aere_pa(0:maxPatchesPerSite));bc_out%woody_frac_aere_pa(:)=nan - allocate(bc_out%rootfr_pa(0:maxPatchesPerSite,nlevsoil_in)) + allocate(bc_out%woody_frac_aere_pa(0:maxpatch_total));bc_out%woody_frac_aere_pa(:)=nan + allocate(bc_out%rootfr_pa(0:maxpatch_total,nlevsoil_in)) bc_out%rootfr_pa(:,:)=nan ! Give the bare-ground root fractions a nominal fraction of unity over depth @@ -659,21 +663,21 @@ subroutine allocate_bcout(bc_out, nlevsoil_in, nlevdecomp_in) ! Canopy Structure - allocate(bc_out%elai_pa(maxPatchesPerSite)) - allocate(bc_out%esai_pa(maxPatchesPerSite)) - allocate(bc_out%tlai_pa(maxPatchesPerSite)) - allocate(bc_out%tsai_pa(maxPatchesPerSite)) - allocate(bc_out%htop_pa(maxPatchesPerSite)) - allocate(bc_out%hbot_pa(maxPatchesPerSite)) - allocate(bc_out%dleaf_pa(maxPatchesPerSite)) + allocate(bc_out%elai_pa(maxpatch_total)) + allocate(bc_out%esai_pa(maxpatch_total)) + allocate(bc_out%tlai_pa(maxpatch_total)) + allocate(bc_out%tsai_pa(maxpatch_total)) + allocate(bc_out%htop_pa(maxpatch_total)) + allocate(bc_out%hbot_pa(maxpatch_total)) + allocate(bc_out%dleaf_pa(maxpatch_total)) - allocate(bc_out%displa_pa(maxPatchesPerSite)) - allocate(bc_out%z0m_pa(maxPatchesPerSite)) + allocate(bc_out%displa_pa(maxpatch_total)) + allocate(bc_out%z0m_pa(maxpatch_total)) - allocate(bc_out%canopy_fraction_pa(maxPatchesPerSite)) - allocate(bc_out%frac_veg_nosno_alb_pa(maxPatchesPerSite)) + allocate(bc_out%canopy_fraction_pa(maxpatch_total)) + allocate(bc_out%frac_veg_nosno_alb_pa(maxpatch_total)) - allocate(bc_out%nocomp_pft_label_pa(maxPatchesPerSite)) + allocate(bc_out%nocomp_pft_label_pa(maxpatch_total)) ! Plant-Hydro BC's if (hlm_use_planthydro.eq.itrue) then @@ -715,37 +719,86 @@ end subroutine set_bcs ! =================================================================================== - subroutine SetFatesGlobalElements(use_fates) + subroutine SetFatesGlobalElements1(use_fates,surf_numpft,surf_numcft) ! -------------------------------------------------------------------------------- ! ! This is the first FATES routine that is called. ! - ! This subroutine MUST BE CALLED AFTER the FATES PFT parameter file has been read in, - ! and the EDPftvarcon_inst structure has been made. - ! This subroutine MUST BE CALLED AFTER NL VARIABLES ARE READ (ie hlm_parteh_mode,etc) - ! This subroutine must ALSO BE CALLED BEFORE the history file dimensions - ! are set. - ! - ! This routine requires no information from the HLM. This routine is responsible - ! for generating the globals that are required by the HLM that are entirely - ! FATES derived. - ! + ! spmode,biogeog and nocomp mode flags have been passed prior to this call ! -------------------------------------------------------------------------------- implicit none logical,intent(in) :: use_fates ! Is fates turned on? - integer :: i + integer,intent(in) :: surf_numpft ! Number of PFTs in surface dataset + integer,intent(in) :: surf_numcft ! Number of CFTs in surface dataset + + integer :: fates_numpft ! Number of PFTs tracked in FATES if (use_fates) then ! Self explanatory, read the fates parameter file call FatesReadParameters() - ! Identify the number of PFTs by evaluating a pft array - ! Using wood density as that is not expected to be deprecated any time soon + fates_numpft = size(prt_params%wood_density,dim=1) + + if(hlm_use_sp==itrue)then + + ! For an SP run we also just use the primary patches + ! to hold all PFTs. So create the same number of + ! patches as the number of PFTs + + maxpatch_primary = fates_numpft + maxpatch_secondary = 0 + maxpatch_total = fates_numpft + + ! If this is an SP run, we actually need enough patches on the + ! CLM/ELM side of the code to hold the LAI data. This + ! number may be larger than what fates requires. Of course + ! we may have multiple PFTs in the surface datafile mapping + ! to FATES. The surf_numpft includes the bare ground. + ! maxpatch_total does not include the bare ground (so add 1) + + fates_maxPatchesPerSite = max(surf_numpft+surf_numcft,maxpatch_total+1) + + else + + ! If we are using fixed biogeography or no-comp then we + ! can also apply those constraints to maxpatch_primary and secondary + ! and that value will match fates_maxPatchesPerSite + + if(hlm_use_nocomp==itrue) then + if(maxpatch_primary maximum number of secondary vegetation patches per site 1 + + + fates_maxcohort + scalar + count + maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances + 100 + + fates_phen_drought_model scalar @@ -201,7 +210,7 @@ fates_mort_prescribed_understory - fates_phen_flushfrac + fates_phen_flush_fraction fates_phen_mindaysoff @@ -260,11 +269,14 @@ fates_nonhydro_smpso + + fates_hydro_htftype_node + fates_hydro_kmax_rsurf1 - fates_hydro_hydr_kmax_rsurf2 + fates_hydro_kmax_rsurf2 fates_hydro_psi0 @@ -408,7 +420,7 @@ fates_cnp_eca_plant_escalar - fates_alloc_stor_priority_frac + fates_alloc_store_priority_frac for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage @@ -457,7 +469,7 @@ fates_frag_leaf_flig - fates_frag_seed_decay + fates_frag_seed_decay_rate fates_frag_cwd_fcel diff --git a/parameter_files/fates_params_default_api24.cdl b/parameter_files/fates_params_default_api24.cdl index 85724166bd..948d6f4224 100644 --- a/parameter_files/fates_params_default_api24.cdl +++ b/parameter_files/fates_params_default_api24.cdl @@ -32,9 +32,9 @@ variables: double fates_alloc_organ_id(fates_plant_organs) ; fates_alloc_organ_id:units = "unitless" ; fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; - double fates_hydr_htftype_node(fates_hydr_organs) ; - fates_hydr_htftype_node:units = "unitless" ; - fates_hydr_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; + double fates_hydro_htftype_node(fates_hydr_organs) ; + fates_hydro_htftype_node:units = "unitless" ; + fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; char fates_pftname(fates_pft, fates_string_length) ; fates_pftname:units = "unitless - string" ; fates_pftname:long_name = "Description of plant type" ; @@ -50,12 +50,12 @@ variables: 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" ; - double fates_alloc_stor_priority_frac(fates_pft) ; - fates_alloc_stor_priority_frac:units = "unitless" ; - fates_alloc_stor_priority_frac:long_name = "for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage" ; double fates_alloc_storage_cushion(fates_pft) ; fates_alloc_storage_cushion:units = "fraction" ; fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; + double fates_alloc_store_priority_frac(fates_pft) ; + fates_alloc_store_priority_frac:units = "unitless" ; + fates_alloc_store_priority_frac:long_name = "for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage" ; double fates_allom_agb1(fates_pft) ; fates_allom_agb1:units = "variable" ; fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; @@ -269,9 +269,9 @@ variables: double fates_frag_leaf_flig(fates_pft) ; fates_frag_leaf_flig:units = "fraction" ; fates_frag_leaf_flig:long_name = "Leaf litter lignin fraction" ; - double fates_frag_seed_decay(fates_pft) ; - fates_frag_seed_decay:units = "yr-1" ; - fates_frag_seed_decay:long_name = "fraction of seeds that decay per year" ; + double fates_frag_seed_decay_rate(fates_pft) ; + fates_frag_seed_decay_rate:units = "yr-1" ; + fates_frag_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; double fates_grperc(fates_pft) ; fates_grperc:units = "unitless" ; fates_grperc:long_name = "Growth respiration factor" ; @@ -428,9 +428,9 @@ variables: double fates_phen_evergreen(fates_pft) ; fates_phen_evergreen:units = "logical flag" ; fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; - double fates_phen_flushfrac(fates_pft) ; - fates_phen_flushfrac:units = "fraction" ; - fates_phen_flushfrac:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; + double fates_phen_flush_fraction(fates_pft) ; + fates_phen_flush_fraction:units = "fraction" ; + fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; double fates_phen_fnrt_drop_frac(fates_pft) ; fates_phen_fnrt_drop_frac:units = "fraction" ; fates_phen_fnrt_drop_frac:long_name = "fraction of fine roots to drop during drought or cold" ; @@ -644,12 +644,12 @@ variables: double fates_frag_cwd_flig ; fates_frag_cwd_flig:units = "unitless" ; fates_frag_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; - double fates_hydro_hydr_kmax_rsurf2 ; - fates_hydro_hydr_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; - fates_hydro_hydr_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; double fates_hydro_kmax_rsurf1 ; fates_hydro_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; fates_hydro_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; + double fates_hydro_kmax_rsurf2 ; + fates_hydro_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; double fates_hydro_psi0 ; fates_hydro_psi0:units = "MPa" ; fates_hydro_psi0:long_name = "sapwood water potential at saturation" ; @@ -710,6 +710,9 @@ variables: double fates_maintresp_model ; fates_maintresp_model:units = "unitless" ; fates_maintresp_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991) (NOT USED)" ; + double fates_maxcohort ; + fates_maxcohort:units = "count" ; + fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; double fates_maxpatch_primary ; fates_maxpatch_primary:units = "count" ; fates_maxpatch_primary:long_name = "maximum number of primary vegetation patches per site" ; @@ -791,7 +794,7 @@ data: fates_alloc_organ_id = 1, 2, 3, 6 ; - fates_hydr_htftype_node = 1, 1, 1, 1 ; + fates_hydro_htftype_node = 1, 1, 1, 1 ; fates_pftname = "broadleaf_evergreen_tropical_tree ", @@ -833,12 +836,12 @@ data: 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; - fates_alloc_stor_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, - 0.8, 0.8, 0.8, 0.8 ; - fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 ; + fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8, 0.8 ; + fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; @@ -1034,7 +1037,7 @@ data: fates_frag_leaf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25 ; - fates_frag_seed_decay = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, + fates_frag_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51 ; fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, @@ -1230,7 +1233,8 @@ data: fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; - fates_phen_flushfrac = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, 0.5 ; + fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, + 0.5 ; fates_phen_fnrt_drop_frac = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; @@ -1428,10 +1432,10 @@ data: fates_frag_cwd_flig = 0.24 ; - fates_hydro_hydr_kmax_rsurf2 = 0.0001 ; - fates_hydro_kmax_rsurf1 = 20 ; + fates_hydro_kmax_rsurf2 = 0.0001 ; + fates_hydro_psi0 = 0 ; fates_hydro_psicap = -0.6 ; @@ -1472,6 +1476,8 @@ data: fates_maintresp_model = 1 ; + fates_maxcohort = 100 ; + fates_maxpatch_primary = 10 ; fates_maxpatch_secondary = 1 ; diff --git a/parteh/PRTLossFluxesMod.F90 b/parteh/PRTLossFluxesMod.F90 index 13b09b2e37..6f23924d48 100644 --- a/parteh/PRTLossFluxesMod.F90 +++ b/parteh/PRTLossFluxesMod.F90 @@ -433,16 +433,8 @@ subroutine PRTDeciduousTurnover(prt,ipft,organ_id,mass_fraction) end if - if ( int(prt_params%turnover_retrans_mode(ipft)) == 1 ) then - call DeciduousTurnoverSimpleRetranslocation(prt,ipft,organ_id,mass_fraction) - else - write(fates_log(),*) 'A retranslocation mode was specified for deciduous drop' - write(fates_log(),*) 'that is unknown.' - write(fates_log(),*) 'turnover_retrans_mode= ',prt_params%turnover_retrans_mode(ipft) - write(fates_log(),*) 'pft = ',ipft - call endrun(msg=errMsg(__FILE__, __LINE__)) - end if - + call DeciduousTurnoverSimpleRetranslocation(prt,ipft,organ_id,mass_fraction) + return end subroutine PRTDeciduousTurnover @@ -518,7 +510,7 @@ subroutine DeciduousTurnoverSimpleRetranslocation(prt,ipft,organ_id,mass_fractio retrans = 0._r8 else if ( any(element_id == carbon_elements_list) ) then - retrans = prt_params%turnover_carb_retrans(ipft,prt_params%organ_param_id(organ_id)) + retrans = 0._r8 else if( element_id == nitrogen_element ) then retrans = prt_params%turnover_nitr_retrans(ipft,prt_params%organ_param_id(organ_id)) else if( element_id == phosphorus_element ) then @@ -587,15 +579,8 @@ subroutine PRTMaintTurnover(prt,ipft,is_drought) logical,intent(in) :: is_drought ! Is this plant/cohort operating in a drought ! stress context? - if ( int(prt_params%turnover_retrans_mode(ipft)) == 1 ) then - call MaintTurnoverSimpleRetranslocation(prt,ipft,is_drought) - else - write(fates_log(),*) 'A maintenance/retranslocation mode was specified' - write(fates_log(),*) 'that is unknown.' - write(fates_log(),*) 'turnover_retrans_mode= ',prt_params%turnover_retrans_mode(ipft) - write(fates_log(),*) 'pft = ',ipft - call endrun(msg=errMsg(__FILE__, __LINE__)) - end if + call MaintTurnoverSimpleRetranslocation(prt,ipft,is_drought) + return end subroutine PRTMaintTurnover @@ -729,7 +714,7 @@ subroutine MaintTurnoverSimpleRetranslocation(prt,ipft,is_drought) retrans_frac = 0._r8 else if ( any(element_id == carbon_elements_list) ) then - retrans_frac = prt_params%turnover_carb_retrans(ipft,prt_params%organ_param_id(organ_id)) + retrans_frac = 0._r8 else if( element_id == nitrogen_element ) then retrans_frac = prt_params%turnover_nitr_retrans(ipft,prt_params%organ_param_id(organ_id)) else if( element_id == phosphorus_element ) then diff --git a/parteh/PRTParametersMod.F90 b/parteh/PRTParametersMod.F90 index ec41595486..40d19de50b 100644 --- a/parteh/PRTParametersMod.F90 +++ b/parteh/PRTParametersMod.F90 @@ -26,8 +26,7 @@ module PRTParametersMod ! one class to the next [yr] real(r8), allocatable :: root_long(:) ! root turnover time (longevity) (pft) [yr] real(r8), allocatable :: branch_long(:) ! Turnover time for branchfall on live trees (pft) [yr] - real(r8), allocatable :: turnover_retrans_mode(:) ! Retranslocation method (pft) - real(r8), allocatable :: turnover_carb_retrans(:,:) ! carbon re-translocation fraction (pft x organ) + !real(r8), allocatable :: turnover_retrans_mode(:) ! Retranslocation method (pft) (NOT USED) real(r8), allocatable :: turnover_nitr_retrans(:,:) ! nitrogen re-translocation fraction (pft x organ) real(r8), allocatable :: turnover_phos_retrans(:,:) ! phosphorus re-translocation fraction (pft x organ) ! Parameters dimensioned by PFT and leaf age diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index 2f1762dd5b..e3a785706d 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -104,7 +104,7 @@ subroutine PRTRegisterOrgan(fates_params) integer, parameter :: dim_lower_bound(1) = (/ lower_bound_general /) character(len=param_string_length) :: name - name = 'fates_prt_organ_id' + name = 'fates_alloc_organ_id' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -126,7 +126,7 @@ subroutine PRTReceiveOrgan(fates_params) real(r8), allocatable :: tmpreal(:) ! Temporary variable to hold floats - name = 'fates_prt_organ_id' + name = 'fates_alloc_organ_id' call fates_params%RetreiveParameterAllocate(name=name, & data=tmpreal) allocate(prt_params%organ_id(size(tmpreal,dim=1))) @@ -163,15 +163,15 @@ subroutine PRTRegisterPFT(fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_fnrt_prof_a' + name = 'fates_allom_fnrt_prof_a' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_fnrt_prof_b' + name = 'fates_allom_fnrt_prof_b' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_fnrt_prof_mode' + name = 'fates_allom_fnrt_prof_mode' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -179,7 +179,7 @@ subroutine PRTRegisterPFT(fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_crown_depth_frac' + name = 'fates_allom_crown_depth_frac' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -199,7 +199,7 @@ subroutine PRTRegisterPFT(fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_seed_dbh_repro_threshold' + name = 'fates_recruit_seed_dbh_repro_threshold' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -207,23 +207,23 @@ subroutine PRTRegisterPFT(fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_leaf_stor_priority' + name = 'fates_alloc_store_priority_frac' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_senleaf_long_fdrought' + name = 'fates_turnover_senleaf_fdrought' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_root_long' + name = 'fates_turnover_fnrt' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_seed_alloc_mature' + name = 'fates_recruit_seed_alloc_mature' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_seed_alloc' + name = 'fates_recruit_seed_alloc' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -355,21 +355,17 @@ subroutine PRTRegisterPFT(fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_turnover_retrans_mode' - call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & - dimension_names=dim_names, lower_bounds=dim_lower_bound) - - name = 'fates_branch_turnover' + name = 'fates_turnover_branch' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_nitr_store_ratio' + name = 'fates_cnp_nitr_store_ratio' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_phos_store_ratio' + name = 'fates_cnp_phos_store_ratio' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -423,19 +419,19 @@ subroutine PRTReceivePFT(fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%allom_sai_scaler) - name = 'fates_fnrt_prof_a' + name = 'fates_allom_fnrt_prof_a' call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%fnrt_prof_a) - name = 'fates_fnrt_prof_b' + name = 'fates_allom_fnrt_prof_b' call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%fnrt_prof_b) - name = 'fates_fnrt_prof_mode' + name = 'fates_allom_fnrt_prof_mode' call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%fnrt_prof_mode) - name = 'fates_crown_depth_frac' + name = 'fates_allom_crown_depth_frac' call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%crown_depth_frac) @@ -447,7 +443,7 @@ subroutine PRTReceivePFT(fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%wood_density) - name = 'fates_seed_dbh_repro_threshold' + name = 'fates_recruit_seed_dbh_repro_threshold' call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%dbh_repro_threshold) @@ -455,23 +451,23 @@ subroutine PRTReceivePFT(fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%cushion) - name = 'fates_leaf_stor_priority' + name = 'fates_alloc_store_priority_frac' call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%leaf_stor_priority) - name = 'fates_senleaf_long_fdrought' + name = 'fates_turnover_senleaf_fdrought' call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%senleaf_long_fdrought) - name = 'fates_root_long' + name = 'fates_turnover_fnrt' call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%root_long) - name = 'fates_seed_alloc_mature' + name = 'fates_recruit_seed_alloc_mature' call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%seed_alloc_mature) - name = 'fates_seed_alloc' + name = 'fates_recruit_seed_alloc' call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%seed_alloc) @@ -603,19 +599,15 @@ subroutine PRTReceivePFT(fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%allom_zroot_k) - name = 'fates_branch_turnover' + name = 'fates_turnover_branch' call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%branch_long) - name = 'fates_turnover_retrans_mode' - call fates_params%RetreiveParameterAllocate(name=name, & - data=prt_params%turnover_retrans_mode) - - name = 'fates_nitr_store_ratio' + name = 'fates_cnp_nitr_store_ratio' call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%nitr_store_ratio) - name = 'fates_phos_store_ratio' + name = 'fates_cnp_phos_store_ratio' call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%phos_store_ratio) @@ -641,7 +633,7 @@ subroutine PRTRegisterPFTLeafAge(fates_params) dim_names(1) = dimension_name_pft dim_names(2) = dimension_name_leaf_age - name = 'fates_leaf_long' + name = 'fates_turnover_leaf' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -721,7 +713,7 @@ subroutine PRTReceivePFTLeafAge(fates_params) character(len=param_string_length) :: name - name = 'fates_leaf_long' + name = 'fates_turnover_leaf' call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%leaf_long) @@ -750,35 +742,23 @@ subroutine PRTRegisterPFTOrgans(fates_params) dim_names(1) = dimension_name_pft dim_names(2) = dimension_name_prt_organs - name = 'fates_prt_nitr_stoich_p1' + name = 'fates_stoich_nitr' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_prt_nitr_stoich_p2' + name = 'fates_stoich_phos' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_prt_phos_stoich_p1' + name = 'fates_alloc_organ_priority' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_prt_phos_stoich_p2' - call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & - dimension_names=dim_names, lower_bounds=dim_lower_bound) - - name = 'fates_prt_alloc_priority' - call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & - dimension_names=dim_names, lower_bounds=dim_lower_bound) - - name = 'fates_turnover_carb_retrans' - call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & - dimension_names=dim_names, lower_bounds=dim_lower_bound) - - name = 'fates_turnover_nitr_retrans' + name = 'fates_cnp_turnover_nitr_retrans' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_turnover_phos_retrans' + name = 'fates_cnp_turnover_phos_retrans' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -798,35 +778,23 @@ subroutine PRTReceivePFTOrgans(fates_params) character(len=param_string_length) :: name - name = 'fates_prt_nitr_stoich_p1' + name = 'fates_stoich_nitr' call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%nitr_stoich_p1) - name = 'fates_prt_nitr_stoich_p2' - call fates_params%RetreiveParameterAllocate(name=name, & - data=prt_params%nitr_stoich_p2) - - name = 'fates_prt_phos_stoich_p1' + name = 'fates_stoich_phos' call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%phos_stoich_p1) - name = 'fates_prt_phos_stoich_p2' - call fates_params%RetreiveParameterAllocate(name=name, & - data=prt_params%phos_stoich_p2) - - name = 'fates_prt_alloc_priority' + name = 'fates_alloc_organ_priority' call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%alloc_priority) - name = 'fates_turnover_carb_retrans' - call fates_params%RetreiveParameterAllocate(name=name, & - data=prt_params%turnover_carb_retrans) - - name = 'fates_turnover_nitr_retrans' + name = 'fates_cnp_turnover_nitr_retrans' call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%turnover_nitr_retrans) - name = 'fates_turnover_phos_retrans' + name = 'fates_cnp_turnover_phos_retrans' call fates_params%RetreiveParameterAllocate(name=name, & data=prt_params%turnover_phos_retrans) @@ -905,17 +873,14 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'allom_zroot_min_z = ',prt_params%allom_zroot_min_z write(fates_log(),fmt0) 'allom_zroot_k = ',prt_params%allom_zroot_k - write(fates_log(),fmt0) 'prt_nitr_stoich_p1 = ',prt_params%nitr_stoich_p1 - write(fates_log(),fmt0) 'prt_nitr_stoich_p2 = ',prt_params%nitr_stoich_p2 - write(fates_log(),fmt0) 'prt_phos_stoich_p1 = ',prt_params%phos_stoich_p1 - write(fates_log(),fmt0) 'prt_phos_stoich_p2 = ',prt_params%phos_stoich_p2 - write(fates_log(),fmt0) 'prt_alloc_priority = ',prt_params%alloc_priority + write(fates_log(),fmt0) 'stoich_nitr = ',prt_params%nitr_stoich_p1 + write(fates_log(),fmt0) 'stoich_phos = ',prt_params%phos_stoich_p1 + write(fates_log(),fmt0) 'alloc_organ_priority = ',prt_params%alloc_priority write(fates_log(),fmt0) 'woody = ',prt_params%woody write(fates_log(),fmt0) 'crown_depth_frac = ',prt_params%crown_depth_frac write(fates_log(),fmt0) 'roota_par = ',prt_params%fnrt_prof_a write(fates_log(),fmt0) 'rootb_par = ',prt_params%fnrt_prof_b write(fates_log(),fmt0) 'fnrt_prof_mode = ',prt_params%fnrt_prof_mode - write(fates_log(),fmt0) 'turnover_carb_retrans = ',prt_params%turnover_carb_retrans write(fates_log(),fmt0) 'turnover_nitr_retrans = ',prt_params%turnover_nitr_retrans write(fates_log(),fmt0) 'turnover_phos_retrans = ',prt_params%turnover_phos_retrans write(fates_log(),fmt0) 'organ_id = ',prt_params%organ_id @@ -1124,50 +1089,6 @@ subroutine PRTCheckParams(is_master) end if - - ! Check re-translocations - ! Seems reasonable to assume that sapwood, structure and reproduction - ! should not be re-translocating mass upon turnover. - ! Note to advanced users. Feel free to remove these checks... - ! ------------------------------------------------------------------- - - if ((hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) .or. & - (hlm_parteh_mode .eq. prt_carbon_allom_hyp) ) then - - do i = 1,norgans - io = prt_params%organ_id(i) - - if(io == sapw_organ) then - if ((prt_params%turnover_carb_retrans(ipft,i) > nearzero)) then - write(fates_log(),*) ' Retranslocation of sapwood tissues should be zero.' - write(fates_log(),*) ' PFT#: ',ipft - write(fates_log(),*) ' carbon retrans: ',prt_params%turnover_carb_retrans(ipft,i) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - elseif(io == struct_organ) then - if ((prt_params%turnover_carb_retrans(ipft,i) > nearzero)) then - write(fates_log(),*) ' Retranslocation of structural tissues should be zero.' - write(fates_log(),*) ' PFT#: ',ipft - write(fates_log(),*) ' carbon retrans: ',prt_params%turnover_carb_retrans(ipft,i) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - end if - - ! Otherwise, all other retranslocations should be between 0 and 1 - if ( (prt_params%turnover_carb_retrans(ipft,i) > 1.0_r8) .or. & - (prt_params%turnover_carb_retrans(ipft,i) < 0.0_r8) ) then - write(fates_log(),*) ' Retranslocation rates should be between 0 and 1.' - write(fates_log(),*) ' PFT#: ',ipft - write(fates_log(),*) ' parameter file index: ',i,' global index: ',io - write(fates_log(),*) ' retranslocation rate: ',prt_params%turnover_carb_retrans(ipft,i) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - end do - end if if (hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) then @@ -1277,26 +1198,18 @@ subroutine PRTCheckParams(is_master) do i = 1,norgans if ( (prt_params%nitr_stoich_p1(ipft,i) < 0._r8) .or. & - (prt_params%nitr_stoich_p2(ipft,i) < 0._r8) .or. & (prt_params%phos_stoich_p1(ipft,i) < 0._r8) .or. & - (prt_params%phos_stoich_p2(ipft,i) < 0._r8) .or. & (prt_params%nitr_stoich_p1(ipft,i) > 1._r8) .or. & - (prt_params%nitr_stoich_p2(ipft,i) > 1._r8) .or. & - (prt_params%phos_stoich_p1(ipft,i) > 1._r8) .or. & - (prt_params%phos_stoich_p2(ipft,i) > 1._r8) ) then + (prt_params%phos_stoich_p1(ipft,i) > 1._r8) ) then write(fates_log(),*) 'When the C,N,P allocation hypothesis with flexible' write(fates_log(),*) 'stoichiometry is turned on (prt_cnp_flex_allom_hyp),' write(fates_log(),*) 'all stoichiometries must be greater than or equal to zero,' write(fates_log(),*) 'and less than 1 (probably way less than 1).' - write(fates_log(),*) 'Setting both p1 and p2 parameters to zero will turn' - write(fates_log(),*) 'off nutrient dynamics for the given species.' write(fates_log(),*) 'You specified an organ/pft less than zero.' write(fates_log(),*) 'PFT: ',ipft write(fates_log(),*) 'organ index (see head of PRTGenericMod): ',io - write(fates_log(),*) 'nitr_stoich_p1: ',prt_params%nitr_stoich_p1(ipft,i) - write(fates_log(),*) 'nitr_stoich_p2: ',prt_params%phos_stoich_p1(ipft,i) - write(fates_log(),*) 'phos_stoich_p1: ',prt_params%nitr_stoich_p2(ipft,i) - write(fates_log(),*) 'phos_stoich_p2: ',prt_params%phos_stoich_p2(ipft,i) + write(fates_log(),*) 'nitr_stoich: ',prt_params%nitr_stoich_p1(ipft,i) + write(fates_log(),*) 'phos_stoich: ',prt_params%phos_stoich_p1(ipft,i) write(fates_log(),*) 'Aborting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if @@ -1478,28 +1391,28 @@ function NewRecruitTotalStoichiometry(ft,element_id) result(recruit_stoich) case(nitrogen_element) nutr_total = & - c_struct*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(struct_organ)) + & - c_leaf*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)) + & - c_fnrt*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)) + & - c_sapw*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)) + & + c_struct*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(struct_organ)) + & + c_leaf*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)) + & + c_fnrt*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)) + & + c_sapw*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) + & StorageNutrientTarget(ft, element_id, & - c_leaf*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)), & - c_fnrt*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)), & - c_sapw*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)), & - c_struct*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(struct_organ))) + c_leaf*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)), & + c_fnrt*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)), & + c_sapw*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)), & + c_struct*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(struct_organ))) case(phosphorus_element) nutr_total = & - c_struct*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(struct_organ)) + & - c_leaf*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)) + & - c_fnrt*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)) + & - c_sapw*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)) + & + c_struct*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(struct_organ)) + & + c_leaf*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)) + & + c_fnrt*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)) + & + c_sapw*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) + & StorageNutrientTarget(ft, element_id, & - c_leaf*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)), & - c_fnrt*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)), & - c_sapw*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)), & - c_struct*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(struct_organ))) + c_leaf*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)), & + c_fnrt*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)), & + c_sapw*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)), & + c_struct*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(struct_organ))) end select diff --git a/tools/FatesPFTIndexSwapper.py b/tools/FatesPFTIndexSwapper.py index 7e39056fa8..e1a71d4334 100755 --- a/tools/FatesPFTIndexSwapper.py +++ b/tools/FatesPFTIndexSwapper.py @@ -24,7 +24,7 @@ # ======================================================================================= pft_dim_name = 'fates_pft' -prt_dim_name = 'fates_prt_organs' +prt_dim_name = 'fates_plant_organs' hydro_dim_name = 'fates_hydr_organs' litt_dim_name = 'fates_litterclass' string_dim_name = 'fates_string_length' From 87620937b992d268df8333beb1a582c7c01950ac Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 24 May 2022 13:45:36 -0400 Subject: [PATCH 213/852] cleaning up the cnp version 2 allocation code, adding in a diagnostic that tracks which speciens (CNP) limits growth --- biogeochem/EDCohortDynamicsMod.F90 | 16 +- main/EDMainMod.F90 | 2 +- main/EDTypesMod.F90 | 8 +- parteh/PRTAllometricCNPMod.F90 | 466 +++++++++++------------------ 4 files changed, 197 insertions(+), 295 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index c1bffe6313..da2f4ad256 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -99,7 +99,7 @@ module EDCohortDynamicsMod use PRTAllometricCNPMod, only : acnp_bc_inout_id_resp_excess, acnp_bc_in_id_netdc use PRTAllometricCNPMod, only : acnp_bc_inout_id_netdn, acnp_bc_inout_id_netdp use PRTAllometricCNPMod, only : acnp_bc_out_id_cefflux, acnp_bc_out_id_nefflux - use PRTAllometricCNPMod, only : acnp_bc_out_id_pefflux + use PRTAllometricCNPMod, only : acnp_bc_out_id_pefflux, acnp_bc_out_id_limiter use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) @@ -431,13 +431,15 @@ subroutine InitPRTBoundaryConditions(new_cohort) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_dbh,bc_rval = new_cohort%dbh) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_resp_excess,bc_rval = new_cohort%resp_excess) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_l2fr,bc_rval = new_cohort%l2fr) + call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_netdn, bc_rval = new_cohort%daily_n_gain) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_netdp, bc_rval = new_cohort%daily_p_uptake) call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_cefflux, bc_rval = new_cohort%daily_c_efflux) call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_nefflux, bc_rval = new_cohort%daily_n_efflux) call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_pefflux, bc_rval = new_cohort%daily_p_efflux) - + call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_limiter, bc_ival = new_cohort%cnp_limiter) + case DEFAULT write(fates_log(),*) 'You specified an unknown PRT module' @@ -717,7 +719,6 @@ subroutine zero_cohort(cc_p) ! resource allocation currentCohort%daily_n_fixation = 0._r8 - end subroutine zero_cohort !-------------------------------------------------------------------------------------! @@ -1213,9 +1214,9 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) ! ----------------------------------------------------------------- call UpdateCohortBioPhysRates(currentCohort) - currentCohort%l2fr = (currentCohort%n*currentCohort%l2fr& + currentCohort%l2fr = (currentCohort%n*currentCohort%l2fr & + nextc%n*nextc%l2fr)/newn - + currentCohort%laimemory = (currentCohort%n*currentCohort%laimemory & + nextc%n*nextc%laimemory)/newn @@ -1830,7 +1831,7 @@ subroutine copy_cohort( currentCohort,copyc ) ! This transfers the PRT objects over. call n%prt%CopyPRTVartypes(o%prt) - n%l2fr = o%l2fr + n%l2fr = o%l2fr ! Leaf biophysical rates n%vcmax25top = o%vcmax25top @@ -1939,6 +1940,9 @@ subroutine copy_cohort( currentCohort,copyc ) n%shorter => NULL() ! pointer to next shorter cohort n%patchptr => o%patchptr ! pointer to patch that cohort is in + + + end subroutine copy_cohort !-------------------------------------------------------------------------------------! diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index d866ca0c2e..28fefe9da2 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -452,7 +452,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentCohort%resp_excess = 0._r8 call currentCohort%prt%DailyPRT() - + ! Send any efflux/exudates to the labile litter pools in the HLM ! ----------------------------------------------------------------------------- diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index b76408c787..0a9d46eb30 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -214,14 +214,15 @@ module EDTypesMod class(prt_vartypes), pointer :: prt real(r8) :: l2fr ! leaf to fineroot biomass ratio (this is constant - ! in carbon only simulations, and is set by the + ! in carbon only simulationss, and is set by the ! allom_l2fr_min parameter. In nutrient ! enabled simulations, this is dynamic, will ! vary between allom_l2fr_min and allom_l2fr_max ! parameters, with a tendency driven by ! nutrient storage) - + integer :: cnp_limiter ! Which species is limiting growth? ! 0=none,1=C,2=N,3=P + !!class(rmean_type), pointer :: l2fr_ema ! Exponential moving average of the L2FR ! VEGETATION STRUCTURE @@ -382,6 +383,9 @@ module EDTypesMod real(r8) :: ddbhdt ! time derivative of dbh : cm/year real(r8) :: dbdeaddt ! time derivative of dead biomass : KgC/year + + + ! FIRE real(r8) :: fraction_crown_burned ! proportion of crown affected by fire:- real(r8) :: cambial_mort ! probability that trees dies due to cambial char diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index e729a4f33c..5115a602b5 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -170,8 +170,9 @@ module PRTAllometricCNPMod integer, public, parameter :: acnp_bc_out_id_cefflux = 1 ! Daily exudation of C [kg] integer, public, parameter :: acnp_bc_out_id_nefflux = 2 ! Daily exudation of N [kg] integer, public, parameter :: acnp_bc_out_id_pefflux = 3 ! Daily exudation of P [kg] + integer, public, parameter :: acnp_bc_out_id_limiter = 4 ! The minimum of the Nutrient ratio over c ratio - integer, parameter :: num_bc_out = 3 ! Total number of + integer, parameter :: num_bc_out = 4 ! Total number of ! Indices for parameters passed to the integrator @@ -227,7 +228,6 @@ module PRTAllometricCNPMod procedure :: CNPAdjustFRootTargets procedure :: CNPAllocateRemainder procedure :: GetDeficit - procedure :: StorageRegulator procedure :: TrimFineRoot end type cnp_allom_prt_vartypes @@ -673,79 +673,163 @@ subroutine CNPAdjustFRootTargets(this, target_c) class(cnp_allom_prt_vartypes) :: this real(r8) :: target_c(:) - + real(r8), pointer :: l2fr ! leaf to fineroot target biomass scaler integer :: ipft ! PFT index real(r8), pointer :: dbh real(r8) :: canopy_trim - !!real(r8) :: l2fr_ema ! Moving average L2FR (EMA) - - real(r8) :: l2fr_actual - real(r8) :: n_regulator ! Nitrogen storage regulation function scaler - real(r8) :: p_regulator ! Phosphorus storage regulation function scaler - real(r8) :: np_regulator ! Combined NP storage regulation function scaler - real(r8) :: turnfrac ! The factional amount of root biomass that may - ! remain after a day of root turnover without - ! replacement - real(r8) :: fnrt_frac ! fine-root's current fraction of the target + real(r8) :: cnp_store_ratio - + real(r8) :: store_c_max, store_c_act + real(r8) :: store_nut_max, store_nut_act + real(r8) :: n_ratio, p_ratio, np_ratio + real(r8) :: fnrt_c,leaf_c,store_c,struct_c,sapw_c,c_gain,c_fnrt_expand + real(r8) :: l2fr_delta_max + real(r8) :: l2fr_delta_scale + real(r8) :: logi_k + real(r8) :: l2fr_mult - integer, parameter :: regulate_type = regulate_CN_dfdd + real(r8), parameter :: max_l2fr_cgain_frac = 0.99_r8 ipft = this%bc_in(acnp_bc_in_id_pft)%ival l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval - canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval + canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval + - associate( l2fr_min => prt_params%allom_l2fr(ipft) ) + ! Step 1: Determine the nutrient to carbon ratio (aka relative health factor) + ! ----------------------------------------------------------------------------------- - if(n_uptake_mode.eq.prescribed_n_uptake)then - n_regulator = 1._r8 - else - call this%StorageRegulator(nitrogen_element, regulate_type,target_c,n_regulator) - end if + store_c_max = target_c(store_organ) - if(p_uptake_mode.eq.prescribed_p_uptake)then - p_regulator = 1._r8 - else - call this%StorageRegulator(phosphorus_element, regulate_type,target_c,p_regulator) - end if + store_c_act = this%GetState(store_organ, carbon12_element) + & + this%bc_in(acnp_bc_in_id_netdc)%rval - ! We take the maximum here, because the maximum is reflective of the - ! element with the lowest storage, which is the limiting element - if(n_uptake_mode.eq.prescribed_n_uptake)then - np_regulator = p_regulator - else - if(p_uptake_mode.eq.prescribed_p_uptake)then - np_regulator = n_regulator - else - np_regulator = max(n_regulator,p_regulator) - end if - end if - - - ! Update the leaf-to-fineroot ratio used - ! to set fine-root biomass allometry + if(n_uptake_mode.ne.prescribed_n_uptake)then - if(regulate_type == regulate_CN_logi)then + ! Calculate the relative nitrogen storage fraction, + ! over the relative carbon storage fraction. - l2fr = l2fr_min + max(0._r8,min(1.0_r8,np_regulator))*(10._r8*l2fr_min-l2fr_min) + store_nut_max = this%GetNutrientTarget(nitrogen_element,store_organ,stoich_growth_min) - elseif(regulate_type == regulate_CN_dfdd) then + store_nut_act = this%GetState(store_organ, nitrogen_element) + & + this%bc_inout(acnp_bc_inout_id_netdn)%rval - ! Only update L2FR if some leaves are out - if(this%GetState(leaf_organ, carbon12_element)/target_c(leaf_organ) >0.5_r8) then - l2fr = l2fr * np_regulator - end if - - end if - - ! Find the updated target fineroot biomass - call bfineroot(dbh,ipft,canopy_trim, l2fr, target_c(fnrt_organ)) + n_ratio = min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max)/(store_c_act/store_c_max))) + + end if + if(p_uptake_mode.ne.prescribed_p_uptake)then + + ! Calculate the relative phosphorus storage fraction, + ! over the relative carbon storage fraction. + + store_nut_max = this%GetNutrientTarget(phosphorus_element,store_organ,stoich_growth_min) + + store_nut_act = this%GetState(store_organ, phosphorus_element) + this%bc_inout(acnp_bc_inout_id_netdp)%rval + + p_ratio = min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max)/(store_c_act/store_c_max))) + + end if + + ! Use the limiting nutrient species + + if(n_uptake_mode.eq.prescribed_n_uptake)then + if(p_uptake_mode.eq.prescribed_p_uptake)then + cnp_store_ratio = 1._r8 + return + else + cnp_store_ratio = p_ratio + end if + else + if(p_uptake_mode.eq.prescribed_p_uptake)then + cnp_store_ratio = n_ratio + else + cnp_store_ratio = min(n_ratio, p_ratio) + end if + end if - end associate + ! ----------------------------------------------------------------------------- + ! To decide the upper limit on expanding root growth, we perform a carbon + ! balance. Note that if we are growing roots out more, than we have proportionaly + ! more C compared to other resources. Specifically, we want to limit root growth + ! such that allocation to roots can't exceed a certain fraction of the daily + ! available carbon. This fraction is "max_l2fr_cgain_frac". + ! Additional notes. When calculating the "allocation to roots", we consider + ! both the carbon necessary to get the roots "on allometry" plux the carbon + ! necessary to expand them. + ! + ! l2fr_delta_max*target_fnrt_c - target_fnrt_c < + ! c_gain - (target_fnrt_c-actual_fnrt_c) - + ! (target_leaf_c-actual_leaf_c) - + ! (target_sapw_c-actual_sapw_c) - + ! (target_dead_c-actual_dead_c) - + ! (target_stor_c-actual_stor_c) + ! + ! ------------------------------------------------------------------------------ + + fnrt_c = this%GetState(fnrt_organ, carbon12_element) + leaf_c = this%GetState(leaf_organ, carbon12_element) + store_c = this%GetState(store_organ, carbon12_element) + struct_c = this%GetState(struct_organ, carbon12_element) + sapw_c = this%GetState(sapw_organ, carbon12_element) + + ! If there is overflow storage, add this to the gain + c_gain = this%bc_in(acnp_bc_in_id_netdc)%rval + max(0._r8,store_c-target_c(store_organ)) + + c_fnrt_expand = max_l2fr_cgain_frac* ( c_gain - & + max(0._r8,target_c(fnrt_organ)-fnrt_c) - & + max(0._r8,target_c(leaf_organ)-leaf_c) - & + max(0._r8,target_c(sapw_organ)-sapw_c) - & + max(0._r8,target_c(struct_organ)-struct_c) - & + max(0._r8,target_c(store_organ)-store_c)) + + l2fr_delta_max = (c_fnrt_expand + target_c(fnrt_organ))/target_c(fnrt_organ) + + ! This value could be negative if there is no gain, or less gain + ! than what can replace tissues, just ensure the multiplier is GT 1 + + l2fr_delta_max = max(1._r8,l2fr_delta_max) + + ! Determine the max change for the doubling timescale + ! 2.0 = l2fr_delta_max^frnt_adapt_tscl + + l2fr_delta_scale = 2._r8**(1._r8/prt_params%fnrt_adapt_tscale(ipft))-1.0_r8 + + ! Calculate the un-regulated l2fr multiplier + + logi_k = EDPftvarcon_inst%dev_arbitrary_pft(ipft) + l2fr_mult = l2fr_delta_scale*(2.0_r8/(1.0_r8 + cnp_store_ratio**logi_k)-1.0_r8)+1.0_r8 + + if(l2fr_mult>1.0_r8)then + l2fr_mult = min(l2fr_mult,l2fr_delta_max) + end if + + ! Use the derivative approach + ! ----------------------------------------------------------------------------------- + + ! gamma = log(np_ratio) + + ! Calculate how close the change in gamma was to what was predicted + + !gamma_del = gamma - dlambda_dgamma*gamma_prev + + + !l2fr_deriv = gamma * dlambda_dgamma + + + + ! Only update L2FR if some leaves are out + if(this%GetState(leaf_organ, carbon12_element)/target_c(leaf_organ) > 0.5_r8) then + + !l2fr = (1._r8-err_beta)*(l2fr * l2fr_mult) + err_beta*l2fr_deriv + l2fr = l2fr * l2fr_mult + + end if + + + ! Find the updated target fineroot biomass + call bfineroot(dbh,ipft,canopy_trim, l2fr, target_c(fnrt_organ)) return end subroutine CNPAdjustFRootTargets @@ -757,7 +841,7 @@ subroutine TrimFineRoot(this) ! The following section allows forceful turnover of fine-roots if a new L2FR is generated ! that is lower than the previous l2fr. The maintenance turnover (background) rate ! will automatically accomodate a lower l2fr, but if the change is large it will - ! not keep pace. Note 1: however, that the algorithm in StorageRegulator() will prevent + ! not keep pace. Note 1: however, that the algorithm for calculating l2fr will prevent ! large drops in l2fr (unless that safegaurd is removed). Note 2: this section may also ! generate mass check errors in the main CNPAllocation routine, this is because the "val" is ! changing but the net_allocated is not reciprocating, which is expected. @@ -1178,6 +1262,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & real(r8), pointer :: dbh integer :: ipft + integer, pointer :: limiter real(r8) :: canopy_trim real(r8) :: leaf_status real(r8) :: l2fr @@ -1256,9 +1341,8 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & integer, parameter :: grow_lim_estNP = 2 ! Estimate equivalent C from N and P integer, parameter :: grow_lim_type = grow_lim_estNP - - - + real :: neq_cgain, peq_cgain ! N and P equivalent c_gain spent on growth + real :: cnp_gain ! used as a check to see efficiency of limited growth integer, parameter :: c_limited = 1 integer, parameter :: n_limited = 2 integer, parameter :: p_limited = 3 @@ -1267,9 +1351,12 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & leaf_status = this%bc_in(acnp_bc_in_id_lstat)%ival dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival + limiter => this%bc_out(acnp_bc_out_id_limiter)%ival canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval l2fr = this%bc_inout(acnp_bc_inout_id_l2fr)%rval ! This variable is not updated in this ! routine, and is therefore not a pointer + + ! If any of these resources is essentially tapped out, ! then there is no point in performing growth ! It also seems impossible that we would be in a leaf-off status @@ -1283,6 +1370,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & leaf_status.eq.leaves_off .or. & n_gain <= 0.1_r8*calloc_abs_error .or. & p_gain <= 0.02_r8*calloc_abs_error ) then + limiter = 0 return end if @@ -1412,8 +1500,33 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & call EstimateGrowthNC(this,target_c,target_dcdd,state_mask,avg_nc,avg_pc) - c_gstature = min(c_gain,n_gain/avg_nc) - c_gstature = min(c_gstature,p_gain/avg_pc) + neq_cgain = n_gain/avg_nc + peq_cgain = p_gain/avg_pc + + if(c_gain this%bc_inout(acnp_bc_inout_id_dbh)%rval, & - canopy_trim => this%bc_in(acnp_bc_in_id_ctrim)%rval, & - ipft => this%bc_in(acnp_bc_in_id_pft)%ival, & - l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval) - - - logi_k = EDPftvarcon_inst%dev_arbitrary_pft(ipft) - store_x0 = 0.0_r8 - logi_min = 0.0_r8 - - ! TEMPORARY OVERRIDE - - if(regulate_type == regulate_CN_logi) then - - store_c = this%GetState(store_organ, carbon12_element) - - ! Fraction of N per fraction of C - ! If this is greater than 1, then we have more N in storage than - ! we have C, so we downregulate. If this is less than 1, then - ! we have less N in storage than we have C, so up-regulate - - store_frac = log(max(0.01_r8,store_frac) / max(0.01_r8,(store_c/target_c(store_organ)))) - - c_scalar = max(0._r8,min(1._r8,logi_min + (1._r8-logi_min)/(1.0 + exp(logi_k*(store_frac-store_x0))))) - - elseif(regulate_type == regulate_CN_dfdd) then - - store_max = this%GetNutrientTarget(element_id,store_organ,stoich_growth_min) - - ! Storage fractions could be more than the target, depending on the - ! hypothesis and functions involved, but should typically be 0-1 - ! The cap of 5 is for numerics and preventing weird math - - if(element_id.eq.nitrogen_element)then - gain = this%bc_inout(acnp_bc_inout_id_netdn)%rval - else - gain = this%bc_inout(acnp_bc_inout_id_netdp)%rval - end if - - if(use_gains_in_regulator)then - store_act = this%GetState(store_organ, element_id) + gain - store_c_act = this%GetState(store_organ, carbon12_element) + this%bc_in(acnp_bc_in_id_netdc)%rval - else - store_act = this%GetState(store_organ, element_id) - store_c_act = this%GetState(store_organ, carbon12_element) - end if - - store_frac = max(0.01_r8,min(5.0_r8,store_act/store_max)) - - ! Since we don't dump storage carbon - ! these stores can actually get pretty large, so the cap of 10x is numerically - ! feasable, and should also minimize stress on the logistic function - - store_c_max = target_c(store_organ) - - store_c_frac = max(0.01_r8,min(5.0_r8,store_c_act/store_c_max)) - - ! ----------------------------------------------------------------------------- - ! To decide the upper limit on expanding root growth, we perform a carbon - ! balance. Note that if we are growing roots out more, than we have proportionaly - ! more C compared to other resources. Specifically, we want to limit root growth - ! such that allocation to roots can't exceed a certain fraction of the daily - ! available carbon. This fraction is "max_l2fr_cgain_frac". - ! Additional notes. When calculating the "allocation to roots", we consider - ! both the carbon necessary to get the roots "on allometry" plux the carbon - ! necessary to expand them. - ! - ! (l2fr_delta_max*target_fnrt_c + target_fnrt_c-actual_fnrt_c )/c_gain - ! < max_l2fr_cgain_frac - ! - ! or - ! - ! l2fr_delta_max*target_fnrt_c < max_l2fr_cgain_frac * (c_gain - - ! (target_fnrt_c-actual_fnrt_c) - - ! (target_leaf_c-actual_leaf_c)) - ! - ! or - ! as much as you like as long as turnover is replaced - ! - ! l2fr_delta_max*target_fnrt_c - target_fnrt_c < - ! c_gain - (target_fnrt_c-actual_fnrt_c) - - ! (target_leaf_c-actual_leaf_c) - - ! (target_sapw_c-actual_sapw_c) - - ! (target_dead_c-actual_dead_c) - - ! (target_stor_c-actual_stor_c) - ! - ! ------------------------------------------------------------------------------ - - fnrt_c = this%GetState(fnrt_organ, carbon12_element) - leaf_c = this%GetState(leaf_organ, carbon12_element) - store_c = this%GetState(store_organ, carbon12_element) - struct_c = this%GetState(struct_organ, carbon12_element) - sapw_c = this%GetState(sapw_organ, carbon12_element) - - ! If there is overflow storage, add this to the gain - c_gain = this%bc_in(acnp_bc_in_id_netdc)%rval + max(0._r8,store_c-target_c(store_organ)) - - - if(lim_l2fr_max_type == limit_lf)then - l2fr_delta_max = max_l2fr_cgain_frac / target_c(fnrt_organ) * & - (c_gain - max(0._r8,target_c(fnrt_organ)-fnrt_c) - max(0._r8,target_c(leaf_organ)-leaf_c)) - - elseif(lim_l2fr_max_type ==limit_all)then - - c_fnrt_expand = max_l2fr_cgain_frac* ( c_gain - & - max(0._r8,target_c(fnrt_organ)-fnrt_c) - & - max(0._r8,target_c(leaf_organ)-leaf_c) - & - max(0._r8,target_c(sapw_organ)-sapw_c) - & - max(0._r8,target_c(struct_organ)-struct_c) - & - max(0._r8,target_c(store_organ)-store_c)) - - l2fr_delta_max = (c_fnrt_expand + target_c(fnrt_organ))/target_c(fnrt_organ) - - - end if - - ! This value could be negative if there is no gain, or less gain - ! than what can replace leaf/root, just ensure the multiplier is GT 1 - - l2fr_delta_max = max(1._r8,l2fr_delta_max) - - ! Constrain change in l2fr minimum to be no more than what is lost - ! in turnover for a day - l2fr_delta_min = 1._r8-(years_per_day / prt_params%root_long(ipft)) - - ! Determine the max change for the doubling timescale - ! 2.0 = l2fr_delta_max^frnt_adapt_tscl - l2fr_delta_scale = 2._r8**(1._r8/prt_params%fnrt_adapt_tscale(ipft))-1.0_r8 - - nc_frac = nc_frac_offset * store_frac / store_c_frac - - c_scalar = l2fr_delta_scale*(2.0_r8/(1.0_r8 + nc_frac**logi_k)-1.0_r8)+1.0_r8 - - if(c_scalar>1.0_r8)then - c_scalar = min(c_scalar,l2fr_delta_max) - else - ! Remove the min function temporarily - if(.not.use_unrestricted_contraction)then - c_scalar = max(c_scalar,l2fr_delta_min) - end if - end if - - - end if - - end associate - - end subroutine StorageRegulator - - ! ==================================================================================== - subroutine EstimateGrowthNC(this,target_c,target_dcdd,state_mask,avg_nc,avg_pc) ! This routine predicts the effective nutrient/carbon allocation ratio @@ -2521,7 +2415,7 @@ subroutine EstimateGrowthNC(this,target_c,target_dcdd,state_mask,avg_nc,avg_pc) fnrt_w = target_dcdd(fnrt_organ) * (1._r8 - repro_c_frac) total_w = total_w + fnrt_w avg_nc = avg_nc + fnrt_w * prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(fnrt_organ)) - avg_pc = avg_nc + fnrt_w * prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(fnrt_organ)) + avg_pc = avg_pc + fnrt_w * prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(fnrt_organ)) end if if(state_mask(sapw_id)) then sapw_w = target_dcdd(sapw_organ) * (1._r8 - repro_c_frac) From 4004259ee095bc2476fa708a94ee2173b7c7ed01 Mon Sep 17 00:00:00 2001 From: ckoven Date: Tue, 24 May 2022 23:52:29 -0600 Subject: [PATCH 214/852] removed patch%disturbance_rate and patch%disturbance_mode as no longer accurate --- biogeochem/EDPatchDynamicsMod.F90 | 89 +++++++++++++++---------------- main/EDMainMod.F90 | 1 - main/EDTypesMod.F90 | 4 -- 3 files changed, 43 insertions(+), 51 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 66e01ca95c..8f2b5e5fad 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -246,7 +246,6 @@ subroutine disturbance_rates( site_in, bc_in) currentCohort => currentCohort%taller end do - currentPatch%disturbance_mode = fates_unset_int currentPatch => currentPatch%younger end do @@ -414,7 +413,8 @@ subroutine spawn_patches( currentSite, bc_in) real(r8) :: leaf_m ! leaf mass during partial burn calculations logical :: found_youngest_primary ! logical for finding the first primary forest patch integer :: min_nocomp_pft, max_nocomp_pft, i_nocomp_pft - integer :: i_dist, i_dist2 + integer :: i_disturbance_type, i_dist2 + real(r8) :: disturbance_rate real(r8) :: oldarea !--------------------------------------------------------------------- @@ -440,7 +440,7 @@ subroutine spawn_patches( currentSite, bc_in) ! If nocomp is not enabled, then this is not much of a loop, it only passes through once. nocomp_pft_loop: do i_nocomp_pft = min_nocomp_pft,max_nocomp_pft - disturbance_type_loop: do i_dist = 1,N_DIST_TYPES + disturbance_type_loop: do i_disturbance_type = 1,N_DIST_TYPES ! calculate area of disturbed land, in this timestep, by summing contributions from each existing patch. currentPatch => currentSite%youngest_patch @@ -453,42 +453,41 @@ subroutine spawn_patches( currentSite, bc_in) cp_nocomp_matches_1_if: if ( hlm_use_nocomp .eq. ifalse .or. & currentPatch%nocomp_pft_label .eq. i_nocomp_pft ) then - if(currentPatch%disturbance_rate > (1.0_r8 + rsnbl_math_prec)) then - write(fates_log(),*) 'patch disturbance rate > 1 ?',currentPatch%disturbance_rate + disturbance_rate = currentPatch%disturbance_rates(i_disturbance_type) + + if(disturbance_rate > (1.0_r8 + rsnbl_math_prec)) then + write(fates_log(),*) 'patch disturbance rate > 1 ?',disturbance_rate call dump_patch(currentPatch) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - currentPatch%disturbance_mode = i_dist - currentPatch%disturbance_rate = currentPatch%disturbance_rates(i_dist) - ! Only create new patches that have non-negligible amount of land - if((currentPatch%area*currentPatch%disturbance_rate) > nearzero ) then + if((currentPatch%area*disturbance_rate) > nearzero ) then ! figure out whether the receiver patch for disturbance from this patch will be ! primary or secondary land receiver patch is primary forest only if both the - ! donor patch is primary forest and the dominant disturbance type is not logging + ! donor patch is primary forest and the current disturbance type is not logging if ( currentPatch%anthro_disturbance_label .eq. primaryforest .and. & - (currentPatch%disturbance_mode .ne. dtype_ilog) ) then + (i_disturbance_type .ne. dtype_ilog) ) then - site_areadis_primary = site_areadis_primary + currentPatch%area * currentPatch%disturbance_rate + site_areadis_primary = site_areadis_primary + currentPatch%area * disturbance_rate ! track disturbance rates to output to history - currentSite%disturbance_rates_primary_to_primary(currentPatch%disturbance_mode) = & - currentSite%disturbance_rates_primary_to_primary(currentPatch%disturbance_mode) + & - currentPatch%area * currentPatch%disturbance_rate * AREA_INV + currentSite%disturbance_rates_primary_to_primary(i_disturbance_type) = & + currentSite%disturbance_rates_primary_to_primary(i_disturbance_type) + & + currentPatch%area * disturbance_rate * AREA_INV else - site_areadis_secondary = site_areadis_secondary + currentPatch%area * currentPatch%disturbance_rate + site_areadis_secondary = site_areadis_secondary + currentPatch%area * disturbance_rate ! track disturbance rates to output to history if (currentPatch%anthro_disturbance_label .eq. secondaryforest) then - currentSite%disturbance_rates_secondary_to_secondary(currentPatch%disturbance_mode) = & - currentSite%disturbance_rates_secondary_to_secondary(currentPatch%disturbance_mode) + & - currentPatch%area * currentPatch%disturbance_rate * AREA_INV + currentSite%disturbance_rates_secondary_to_secondary(i_disturbance_type) = & + currentSite%disturbance_rates_secondary_to_secondary(i_disturbance_type) + & + currentPatch%area * disturbance_rate * AREA_INV else - currentSite%disturbance_rates_primary_to_secondary(currentPatch%disturbance_mode) = & - currentSite%disturbance_rates_primary_to_secondary(currentPatch%disturbance_mode) + & - currentPatch%area * currentPatch%disturbance_rate * AREA_INV + currentSite%disturbance_rates_primary_to_secondary(i_disturbance_type) = & + currentSite%disturbance_rates_primary_to_secondary(i_disturbance_type) + & + currentPatch%area * disturbance_rate * AREA_INV endif endif @@ -562,17 +561,18 @@ subroutine spawn_patches( currentSite, bc_in) currentPatch%nocomp_pft_label .eq. i_nocomp_pft ) then ! This is the amount of patch area that is disturbed, and donated by the donor - patch_site_areadis = currentPatch%area * currentPatch%disturbance_rate + disturbance_rate = currentPatch%disturbance_rates(i_disturbance_type) + patch_site_areadis = currentPatch%area * disturbance_rate if ( patch_site_areadis > nearzero ) then ! figure out whether the receiver patch for disturbance from this patch ! will be primary or secondary land receiver patch is primary forest - ! only if both the donor patch is primary forest and the dominant + ! only if both the donor patch is primary forest and the current ! disturbance type is not logging if (currentPatch%anthro_disturbance_label .eq. primaryforest .and. & - (currentPatch%disturbance_mode .ne. dtype_ilog)) then + (i_disturbance_type .ne. dtype_ilog)) then new_patch => new_patch_primary else new_patch => new_patch_secondary @@ -585,11 +585,11 @@ subroutine spawn_patches( currentSite, bc_in) end if ! for the case where the donating patch is secondary forest, if - ! the dominant disturbance from this patch is non-anthropogenic, + ! the current disturbance from this patch is non-anthropogenic, ! we need to average in the time-since-anthropogenic-disturbance ! from the donor patch into that of the receiver patch if ( currentPatch%anthro_disturbance_label .eq. secondaryforest .and. & - (currentPatch%disturbance_mode .ne. dtype_ilog) ) then + (i_disturbance_type .ne. dtype_ilog) ) then new_patch%age_since_anthro_disturbance = new_patch%age_since_anthro_disturbance + & currentPatch%age_since_anthro_disturbance * (patch_site_areadis / site_areadis_secondary) @@ -600,9 +600,9 @@ subroutine spawn_patches( currentSite, bc_in) ! Transfer the litter existing already in the donor patch to the new patch ! This call will only transfer non-burned litter to new patch ! and burned litter to atmosphere. Thus it is important to zero burnt_frac_litter when - ! fire is not the dominant disturbance regime. + ! fire is not the current disturbance regime. - if(currentPatch%disturbance_mode .ne. dtype_ifire) then + if(i_disturbance_type .ne. dtype_ifire) then currentPatch%burnt_frac_litter(:) = 0._r8 end if @@ -610,10 +610,10 @@ subroutine spawn_patches( currentSite, bc_in) ! Transfer in litter fluxes from plants in various contexts of death and destruction - if(currentPatch%disturbance_mode .eq. dtype_ilog) then + if(i_disturbance_type .eq. dtype_ilog) then call logging_litter_fluxes(currentSite, currentPatch, & new_patch, patch_site_areadis,bc_in) - elseif(currentPatch%disturbance_mode .eq. dtype_ifire) then + elseif(i_disturbance_type .eq. dtype_ifire) then call fire_litter_fluxes(currentSite, currentPatch, & new_patch, patch_site_areadis,bc_in) else @@ -672,8 +672,8 @@ subroutine spawn_patches( currentSite, bc_in) store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) total_c = sapw_c + struct_c + leaf_c + fnrt_c + store_c - ! treefall mortality is the dominant disturbance - if(currentPatch%disturbance_mode .eq. dtype_ifall) then + ! treefall mortality is the current disturbance + if(i_disturbance_type .eq. dtype_ifall) then if(currentCohort%canopy_layer == 1)then @@ -782,8 +782,8 @@ subroutine spawn_patches( currentSite, bc_in) endif endif - ! Fire is the dominant disturbance - elseif (currentPatch%disturbance_mode .eq. dtype_ifire ) then + ! Fire is the current disturbance + elseif (i_disturbance_type .eq. dtype_ifire ) then ! Number of members in the new patch, before we impose fire survivorship nc%n = currentCohort%n * patch_site_areadis/currentPatch%area @@ -881,8 +881,8 @@ subroutine spawn_patches( currentSite, bc_in) - ! Logging is the dominant disturbance - elseif (currentPatch%disturbance_mode .eq. dtype_ilog ) then + ! Logging is the current disturbance + elseif (i_disturbance_type .eq. dtype_ilog ) then ! If this cohort is in the upper canopy. It generated if(currentCohort%canopy_layer == 1)then @@ -916,7 +916,7 @@ subroutine spawn_patches( currentSite, bc_in) else - ! WHat to do with cohorts in the understory of a logging generated + ! What to do with cohorts in the understory of a logging generated ! disturbance patch? if(int(prt_params%woody(currentCohort%pft)) == itrue)then @@ -1000,7 +1000,7 @@ subroutine spawn_patches( currentSite, bc_in) else write(fates_log(),*) 'unknown disturbance mode?' - write(fates_log(),*) 'disturbance_mode: ',currentPatch%disturbance_mode + write(fates_log(),*) 'i_disturbance_type: ',i_disturbance_type call endrun(msg=errMsg(sourcefile, __LINE__)) end if ! Select disturbance mode @@ -1046,8 +1046,8 @@ subroutine spawn_patches( currentSite, bc_in) ! for all disturbance rates that haven't been resolved yet, increase their amount so that ! they are the same amount of gridcell-scale disturbance relative to the original patch size - if (i_dist .ne. N_DIST_TYPES) then - do i_dist2 = i_dist+1,N_DIST_TYPES + if (i_disturbance_type .ne. N_DIST_TYPES) then + do i_dist2 = i_disturbance_type+1,N_DIST_TYPES currentPatch%disturbance_rates(i_dist2) = currentPatch%disturbance_rates(i_dist2) & * oldarea / currentPatch%area end do @@ -1153,8 +1153,7 @@ subroutine spawn_patches( currentSite, bc_in) !zero disturbance rate trackers on all patches currentPatch => currentSite%oldest_patch do while(associated(currentPatch)) - currentPatch%disturbance_rate = 0._r8 - currentPatch%disturbance_rates = 0._r8 + currentPatch%disturbance_rates(:) = 0._r8 currentPatch%fract_ldist_not_harvested = 0._r8 currentPatch => currentPatch%younger end do @@ -2047,7 +2046,6 @@ subroutine create_patch(currentSite, new_patch, age, areap, label,nocomp_pft) ! This new value will be generated when the calculate disturbance ! rates routine is called. This does not need to be remembered or in the restart file. - new_patch%disturbance_mode = fates_unset_int new_patch%f_sun = 0._r8 new_patch%ed_laisun_z(:,:,:) = 0._r8 @@ -2150,8 +2148,7 @@ subroutine zero_patch(cp_p) currentPatch%pft_agb_profile(:,:) = nan ! DISTURBANCE - currentPatch%disturbance_rates = 0._r8 - currentPatch%disturbance_rate = 0._r8 + currentPatch%disturbance_rates(:) = 0._r8 currentPatch%fract_ldist_not_harvested = 0._r8 diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index d05966ef14..7b9d623413 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -847,7 +847,6 @@ subroutine TotalBalanceCheck (currentSite, call_index ) write(fates_log(),*) 'BG CWD (by layer): ', sum(litt%bg_cwd,dim=1) write(fates_log(),*) 'leaf litter:',sum(litt%leaf_fines) write(fates_log(),*) 'root litter (by layer): ',sum(litt%root_fines,dim=1) - write(fates_log(),*) 'dist mode: ',currentPatch%disturbance_mode write(fates_log(),*) 'anthro_disturbance_label: ',currentPatch%anthro_disturbance_label write(fates_log(),*) 'use_this_pft: ', currentSite%use_this_pft(:) if(print_cohorts)then diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 9ce4d5fe44..d108081045 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -537,9 +537,6 @@ module EDTypesMod real(r8) :: disturbance_rates(n_dist_types) ! disturbance rate from 1) mortality ! 2) fire: fraction/day ! 3) logging mortatliy - real(r8) :: disturbance_rate ! larger effective disturbance rate: fraction/day - integer :: disturbance_mode ! index identifying which disturbance was applied - ! can be one of: dtype_ifall, dtype_ilog or dtype_ifire real(r8) :: fract_ldist_not_harvested ! fraction of logged area that is canopy trees that weren't harvested @@ -1016,7 +1013,6 @@ subroutine dump_patch(cpatch) write(fates_log(),*) 'pa%gnd_alb_dir = ',cpatch%gnd_alb_dir(:) write(fates_log(),*) 'pa%c_stomata = ',cpatch%c_stomata write(fates_log(),*) 'pa%c_lblayer = ',cpatch%c_lblayer - write(fates_log(),*) 'pa%disturbance_rate = ',cpatch%disturbance_rate write(fates_log(),*) 'pa%disturbance_rates = ',cpatch%disturbance_rates(:) write(fates_log(),*) 'pa%anthro_disturbance_label = ',cpatch%anthro_disturbance_label write(fates_log(),*) '----------------------------------------' From 7dbe7538fead5d973cac2ab7ebaaf02d030b4063 Mon Sep 17 00:00:00 2001 From: ckoven Date: Tue, 24 May 2022 23:58:36 -0600 Subject: [PATCH 215/852] added variable descriptions --- biogeochem/EDPatchDynamicsMod.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 8f2b5e5fad..b3bab06bcb 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -413,9 +413,9 @@ subroutine spawn_patches( currentSite, bc_in) real(r8) :: leaf_m ! leaf mass during partial burn calculations logical :: found_youngest_primary ! logical for finding the first primary forest patch integer :: min_nocomp_pft, max_nocomp_pft, i_nocomp_pft - integer :: i_disturbance_type, i_dist2 - real(r8) :: disturbance_rate - real(r8) :: oldarea + integer :: i_disturbance_type, i_dist2 ! iterators for looping over disturbance types + real(r8) :: disturbance_rate ! rate of disturbance being resolved [fraction of patch area / day] + real(r8) :: oldarea ! old patch area prior to disturbance !--------------------------------------------------------------------- storesmallcohort => null() ! storage of the smallest cohort for insertion routine From a14a31f53779bf04da4c6c18d2d2293ae44cfe01 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 25 May 2022 14:16:00 -0400 Subject: [PATCH 216/852] Changing some phen parameters to pft level, adding damage codes --- biogeochem/EDPhysiologyMod.F90 | 7 +- main/EDParamsMod.F90 | 104 ++++++++++++++------------- main/EDPftvarcon.F90 | 60 +++++++++++++++- parameter_files/apichange_23to24.xml | 80 ++++++++++++++++++++- 4 files changed, 196 insertions(+), 55 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 33700fef3d..23271f794e 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -688,9 +688,10 @@ subroutine phenology( currentSite, bc_in ) ! !USES: use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm use EDParamsMod, only : ED_val_phen_drought_threshold, ED_val_phen_doff_time - use EDParamsMod, only : ED_val_phen_a, ED_val_phen_b, ED_val_phen_c, ED_val_phen_chiltemp - use EDParamsMod, only : ED_val_phen_mindayson, ED_val_phen_ncolddayslim, ED_val_phen_coldtemp - + !use EDParamsMod, only : ED_val_phen_a, ED_val_phen_b, ED_val_phen_c, ED_val_phen_chiltemp + use EDParamsMod, only : ED_val_phen_mindayson !, ED_val_phen_ncolddayslim, ED_val_phen_coldtemp + use EDPftvarcon, only : phen_gddthresh_a,phen_gddthresh_b,phen_gddthresh_c + use EDPftvarcon, only : phen_chiltemp,phen_coldtemp,phen_ncolddayslim ! ! !ARGUMENTS: diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 7ed2ee19c4..7b8e183adc 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -48,13 +48,13 @@ module EDParamsMod real(r8),protected, public :: ED_val_base_mr_20 real(r8),protected, public :: ED_val_phen_drought_threshold real(r8),protected, public :: ED_val_phen_doff_time - real(r8),protected, public :: ED_val_phen_a - real(r8),protected, public :: ED_val_phen_b - real(r8),protected, public :: ED_val_phen_c - real(r8),protected, public :: ED_val_phen_chiltemp + !real(r8),protected, public :: ED_val_phen_a + !real(r8),protected, public :: ED_val_phen_b + !real(r8),protected, public :: ED_val_phen_c + !real(r8),protected, public :: ED_val_phen_chiltemp real(r8),protected, public :: ED_val_phen_mindayson - real(r8),protected, public :: ED_val_phen_ncolddayslim - real(r8),protected, public :: ED_val_phen_coldtemp + !real(r8),protected, public :: ED_val_phen_ncolddayslim + !real(r8),protected, public :: ED_val_phen_coldtemp real(r8),protected, public :: ED_val_cohort_size_fusion_tol real(r8),protected, public :: ED_val_cohort_age_fusion_tol real(r8),protected, public :: ED_val_patch_fusion_tol @@ -107,13 +107,13 @@ module EDParamsMod character(len=param_string_length),parameter,public :: ED_name_base_mr_20= "fates_base_mr_20" character(len=param_string_length),parameter,public :: ED_name_phen_drought_threshold= "fates_phen_drought_threshold" character(len=param_string_length),parameter,public :: ED_name_phen_doff_time= "fates_phen_mindaysoff" - character(len=param_string_length),parameter,public :: ED_name_phen_a= "fates_phen_a" - character(len=param_string_length),parameter,public :: ED_name_phen_b= "fates_phen_b" - character(len=param_string_length),parameter,public :: ED_name_phen_c= "fates_phen_c" - character(len=param_string_length),parameter,public :: ED_name_phen_chiltemp= "fates_phen_chiltemp" + !character(len=param_string_length),parameter,public :: ED_name_phen_a= "fates_phen_a" + !character(len=param_string_length),parameter,public :: ED_name_phen_b= "fates_phen_b" + !character(len=param_string_length),parameter,public :: ED_name_phen_c= "fates_phen_c" + !character(len=param_string_length),parameter,public :: ED_name_phen_chiltemp= "fates_phen_chiltemp" character(len=param_string_length),parameter,public :: ED_name_phen_mindayson= "fates_phen_mindayson" - character(len=param_string_length),parameter,public :: ED_name_phen_ncolddayslim= "fates_phen_ncolddayslim" - character(len=param_string_length),parameter,public :: ED_name_phen_coldtemp= "fates_phen_coldtemp" + !character(len=param_string_length),parameter,public :: ED_name_phen_ncolddayslim= "fates_phen_ncolddayslim" + !character(len=param_string_length),parameter,public :: ED_name_phen_coldtemp= "fates_phen_coldtemp" character(len=param_string_length),parameter,public :: ED_name_cohort_size_fusion_tol= "fates_cohort_size_fusion_tol" character(len=param_string_length),parameter,public :: ED_name_cohort_age_fusion_tol = "fates_cohort_age_fusion_tol" character(len=param_string_length),parameter,public :: ED_name_patch_fusion_tol= "fates_patch_fusion_tol" @@ -169,7 +169,10 @@ module EDParamsMod integer, protected, public :: stomatal_assim_model character(len=param_string_length), parameter, public :: stomatal_assim_name = "fates_leaf_stomatal_assim_model" - + ! Integer code that options how damage events are structured + integer, protected, public :: damage_event_code + character(len=param_string_length), parameter, public :: damage_event_code_name = "fates_damage_event_code" + ! Maximum allowable primary and secondary patches ! These values are USED FOR ALLOCATIONS IN BOTH FATES AND CLM/ELM!!!! ! The number of patches specified in the parameter file may be over-written. @@ -228,6 +231,9 @@ module EDParamsMod real(r8),protected,public :: eca_plant_escalar ! scaling factor for plant fine root biomass to ! calculate nutrient carrier enzyme abundance (ECA) + + + character(len=param_string_length),parameter,public :: eca_name_plant_escalar = "fates_cnp_eca_plant_escalar" public :: FatesParamsInit @@ -262,13 +268,13 @@ subroutine FatesParamsInit() ED_val_base_mr_20 = nan ED_val_phen_drought_threshold = nan ED_val_phen_doff_time = nan - ED_val_phen_a = nan - ED_val_phen_b = nan - ED_val_phen_c = nan - ED_val_phen_chiltemp = nan + !ED_val_phen_a = nan + !ED_val_phen_b = nan + !ED_val_phen_c = nan + !ED_val_phen_chiltemp = nan ED_val_phen_mindayson = nan - ED_val_phen_ncolddayslim = nan - ED_val_phen_coldtemp = nan + !ED_val_phen_ncolddayslim = nan + !ED_val_phen_coldtemp = nan ED_val_cohort_size_fusion_tol = nan ED_val_cohort_age_fusion_tol = nan ED_val_patch_fusion_tol = nan @@ -374,26 +380,26 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=ED_name_phen_doff_time, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) - call fates_params%RegisterParameter(name=ED_name_phen_a, dimension_shape=dimension_shape_scalar, & - dimension_names=dim_names_scalar) + !call fates_params%RegisterParameter(name=ED_name_phen_a, dimension_shape=dimension_shape_scalar, & + ! dimension_names=dim_names_scalar) - call fates_params%RegisterParameter(name=ED_name_phen_b, dimension_shape=dimension_shape_scalar, & - dimension_names=dim_names_scalar) + !call fates_params%RegisterParameter(name=ED_name_phen_b, dimension_shape=dimension_shape_scalar, & + ! dimension_names=dim_names_scalar) - call fates_params%RegisterParameter(name=ED_name_phen_c, dimension_shape=dimension_shape_scalar, & - dimension_names=dim_names_scalar) + !call fates_params%RegisterParameter(name=ED_name_phen_c, dimension_shape=dimension_shape_scalar, & + ! dimension_names=dim_names_scalar) - call fates_params%RegisterParameter(name=ED_name_phen_chiltemp, dimension_shape=dimension_shape_scalar, & - dimension_names=dim_names_scalar) + !call fates_params%RegisterParameter(name=ED_name_phen_chiltemp, dimension_shape=dimension_shape_scalar, & + ! dimension_names=dim_names_scalar) call fates_params%RegisterParameter(name=ED_name_phen_mindayson, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) - call fates_params%RegisterParameter(name=ED_name_phen_ncolddayslim, dimension_shape=dimension_shape_scalar, & - dimension_names=dim_names_scalar) + !call fates_params%RegisterParameter(name=ED_name_phen_ncolddayslim, dimension_shape=dimension_shape_scalar, & + ! dimension_names=dim_names_scalar) - call fates_params%RegisterParameter(name=ED_name_phen_coldtemp, dimension_shape=dimension_shape_scalar, & - dimension_names=dim_names_scalar) + !call fates_params%RegisterParameter(name=ED_name_phen_coldtemp, dimension_shape=dimension_shape_scalar, & + ! dimension_names=dim_names_scalar) call fates_params%RegisterParameter(name=ED_name_cohort_size_fusion_tol, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -562,26 +568,26 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetreiveParameter(name=ED_name_phen_doff_time, & data=ED_val_phen_doff_time) - call fates_params%RetreiveParameter(name=ED_name_phen_a, & - data=ED_val_phen_a) + !call fates_params%RetreiveParameter(name=ED_name_phen_a, & + ! data=ED_val_phen_a) - call fates_params%RetreiveParameter(name=ED_name_phen_b, & - data=ED_val_phen_b) + !call fates_params%RetreiveParameter(name=ED_name_phen_b, & + ! data=ED_val_phen_b) - call fates_params%RetreiveParameter(name=ED_name_phen_c, & - data=ED_val_phen_c) + !call fates_params%RetreiveParameter(name=ED_name_phen_c, & + ! data=ED_val_phen_c) - call fates_params%RetreiveParameter(name=ED_name_phen_chiltemp, & - data=ED_val_phen_chiltemp) + !call fates_params%RetreiveParameter(name=ED_name_phen_chiltemp, & + ! data=ED_val_phen_chiltemp) call fates_params%RetreiveParameter(name=ED_name_phen_mindayson, & data=ED_val_phen_mindayson) - call fates_params%RetreiveParameter(name=ED_name_phen_ncolddayslim, & - data=ED_val_phen_ncolddayslim) + !call fates_params%RetreiveParameter(name=ED_name_phen_ncolddayslim, & + ! data=ED_val_phen_ncolddayslim) - call fates_params%RetreiveParameter(name=ED_name_phen_coldtemp, & - data=ED_val_phen_coldtemp) + !call fates_params%RetreiveParameter(name=ED_name_phen_coldtemp, & + ! data=ED_val_phen_coldtemp) call fates_params%RetreiveParameter(name=ED_name_cohort_size_fusion_tol, & data=ED_val_cohort_size_fusion_tol) @@ -737,13 +743,13 @@ subroutine FatesReportParams(is_master) write(fates_log(),fmt0) 'ED_val_base_mr_20 = ', ED_val_base_mr_20 write(fates_log(),fmt0) 'ED_val_phen_drought_threshold = ',ED_val_phen_drought_threshold write(fates_log(),fmt0) 'ED_val_phen_doff_time = ',ED_val_phen_doff_time - write(fates_log(),fmt0) 'ED_val_phen_a = ',ED_val_phen_a - write(fates_log(),fmt0) 'ED_val_phen_b = ',ED_val_phen_b - write(fates_log(),fmt0) 'ED_val_phen_c = ',ED_val_phen_c - write(fates_log(),fmt0) 'ED_val_phen_chiltemp = ',ED_val_phen_chiltemp + !write(fates_log(),fmt0) 'ED_val_phen_a = ',ED_val_phen_a + !write(fates_log(),fmt0) 'ED_val_phen_b = ',ED_val_phen_b + !write(fates_log(),fmt0) 'ED_val_phen_c = ',ED_val_phen_c + !write(fates_log(),fmt0) 'ED_val_phen_chiltemp = ',ED_val_phen_chiltemp write(fates_log(),fmt0) 'ED_val_phen_mindayson = ',ED_val_phen_mindayson - write(fates_log(),fmt0) 'ED_val_phen_ncolddayslim = ',ED_val_phen_ncolddayslim - write(fates_log(),fmt0) 'ED_val_phen_coldtemp = ',ED_val_phen_coldtemp + !write(fates_log(),fmt0) 'ED_val_phen_ncolddayslim = ',ED_val_phen_ncolddayslim + !write(fates_log(),fmt0) 'ED_val_phen_coldtemp = ',ED_val_phen_coldtemp write(fates_log(),fmt0) 'ED_val_cohort_size_fusion_tol = ',ED_val_cohort_size_fusion_tol 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 diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 6f738f6498..fabe95c38b 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -180,7 +180,17 @@ module EDPftvarcon ! prescribe an uptake rate for phosphorus ! This is the fraction of plant demand - + ! GDD accumulation function, intercept parameters: gdd_thesh = a + b exp(c*ncd) + !real(r8), allocatable :: phen_gddthresh_a + !real(r8), allocatable :: phen_gddthresh_b + !real(r8), allocatable :: phen_gddthresh_c + !chilling day counting threshold for vegetation (deg C) + !real(r8), allocatable :: phen_chiltemp + ! vegetation temperature exceedance that flags a cold-day for leaf-drop (deg C) + !real(r8), allocatable :: phen_coldtemp + ! day threshold exceedance for temperature leaf-drop (days) + !real(r8), allocatable :: phen_ncolddayslim + ! Unassociated pft dimensioned free parameter that ! developers can use for testing arbitrary new hypothese real(r8), allocatable :: dev_arbitrary_pft(:) @@ -559,6 +569,30 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_phen_gddthresh_a' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_phen_gddthresh_b' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_phen_gddthresh_c' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_phen_chilltemp' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_phen_coldtemp' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_phen_ncolddayslim' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_phen_flush_fraction' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -902,6 +936,30 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=this%displar) + name = 'fates_phen_gddthresh_a' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%phen_gddthresh_a) + + name = 'fates_phen_gddthresh_b' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%phen_gddthresh_b) + + name = 'fates_phen_gddthresh_c' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%phen_gddthresh_c) + + name = 'fates_phen_chilltemp' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%phen_chilltemp) + + name = 'fates_phen_coldtemp' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%phen_coldtemp) + + name = 'fates_phen_ncolddayslim' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%phen_ncolddayslim) + name = 'fates_phen_flush_fraction' call fates_params%RetreiveParameterAllocate(name=name, & data=this%phenflush_fraction) diff --git a/parameter_files/apichange_23to24.xml b/parameter_files/apichange_23to24.xml index ce5856b4a7..6a3b62dfac 100644 --- a/parameter_files/apichange_23to24.xml +++ b/parameter_files/apichange_23to24.xml @@ -106,10 +106,10 @@ fates_phen_drought_threshold - scalar + fates_pft m3/m3 or mm threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm) - 0.15 + 0.15,0.15,0.15,0.15,0.15,0.15,0.15,0.15,0.15,0.15,0.15,0.15 fates_phen_moist_threshold @@ -531,5 +531,81 @@ fates_rad_stem_tauvis + + fates_damage_event_code + scalar + unitless + Integer code that options how damage events are structured + 1 + + + fates_phen_gddthresh_a + + + fates_phen_gddthresh_a + fates_pft + unitless + GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd) + -68,-68,-68,-68,-68,-68,-68,-68,-68,-68,-68,-68 + + + fates_phen_b + + + fates_phen_gddthresh_b + fates_pft + unitless + GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd) + 638,638,638,638,638,638,638,638,638,638,638,638 + + + fates_phen_c + + + fates_phen_gddthresh_c + fates_pft + unitless + GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd) + -0.01,-0.01,-0.01,-0.01,-0.01,-0.01,-0.01,-0.01,-0.01,-0.01,-0.01,-0.01, + + + fates_phen_chiltemp + + + fates_phen_chilltemp + fates_pft + degrees C + chilling day counting threshold for vegetation + 5,5,5,5,5,5,5,5,5,5,5,5 + + + fates_phen_coldtemp + + + fates_phen_coldtemp + fates_pft + degrees C + vegetation temperature exceedance that flags a cold-day for leaf-drop + 7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5, + + + fates_phen_ncolddayslim + + + fates_phen_ncolddayslim + fates_pft + days + day threshold exceedance for temperature leaf-drop + + + + fates_cnp_store_ovrflw_frac + fates_pft + fraction + size of overflow storage (for excess C,N or P) as a fraction of storage target + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 + + + From 5c8c58b6bf1403be3f9f06160a50d2dcbe3cb3dc Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 25 May 2022 16:13:26 -0400 Subject: [PATCH 217/852] Reverted pft-scale phen parameters back to scalar because the phenology routine is site level and thus out of scope for this PR --- biogeochem/EDPhysiologyMod.F90 | 6 +- main/EDParamsMod.F90 | 96 +++++++++---------- main/EDPftvarcon.F90 | 59 ------------ parameter_files/apichange_23to24.xml | 60 +----------- .../fates_params_default_api24.cdl | 49 ++++++---- 5 files changed, 85 insertions(+), 185 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 23271f794e..cad0c81560 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -688,10 +688,8 @@ subroutine phenology( currentSite, bc_in ) ! !USES: use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm use EDParamsMod, only : ED_val_phen_drought_threshold, ED_val_phen_doff_time - !use EDParamsMod, only : ED_val_phen_a, ED_val_phen_b, ED_val_phen_c, ED_val_phen_chiltemp - use EDParamsMod, only : ED_val_phen_mindayson !, ED_val_phen_ncolddayslim, ED_val_phen_coldtemp - use EDPftvarcon, only : phen_gddthresh_a,phen_gddthresh_b,phen_gddthresh_c - use EDPftvarcon, only : phen_chiltemp,phen_coldtemp,phen_ncolddayslim + use EDParamsMod, only : ED_val_phen_a, ED_val_phen_b, ED_val_phen_c, ED_val_phen_chiltemp + use EDParamsMod, only : ED_val_phen_mindayson, ED_val_phen_ncolddayslim, ED_val_phen_coldtemp ! ! !ARGUMENTS: diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 7b8e183adc..b28ab877b8 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -48,13 +48,13 @@ module EDParamsMod real(r8),protected, public :: ED_val_base_mr_20 real(r8),protected, public :: ED_val_phen_drought_threshold real(r8),protected, public :: ED_val_phen_doff_time - !real(r8),protected, public :: ED_val_phen_a - !real(r8),protected, public :: ED_val_phen_b - !real(r8),protected, public :: ED_val_phen_c - !real(r8),protected, public :: ED_val_phen_chiltemp + real(r8),protected, public :: ED_val_phen_a + real(r8),protected, public :: ED_val_phen_b + real(r8),protected, public :: ED_val_phen_c + real(r8),protected, public :: ED_val_phen_chiltemp real(r8),protected, public :: ED_val_phen_mindayson - !real(r8),protected, public :: ED_val_phen_ncolddayslim - !real(r8),protected, public :: ED_val_phen_coldtemp + real(r8),protected, public :: ED_val_phen_ncolddayslim + real(r8),protected, public :: ED_val_phen_coldtemp real(r8),protected, public :: ED_val_cohort_size_fusion_tol real(r8),protected, public :: ED_val_cohort_age_fusion_tol real(r8),protected, public :: ED_val_patch_fusion_tol @@ -107,13 +107,13 @@ module EDParamsMod character(len=param_string_length),parameter,public :: ED_name_base_mr_20= "fates_base_mr_20" character(len=param_string_length),parameter,public :: ED_name_phen_drought_threshold= "fates_phen_drought_threshold" character(len=param_string_length),parameter,public :: ED_name_phen_doff_time= "fates_phen_mindaysoff" - !character(len=param_string_length),parameter,public :: ED_name_phen_a= "fates_phen_a" - !character(len=param_string_length),parameter,public :: ED_name_phen_b= "fates_phen_b" - !character(len=param_string_length),parameter,public :: ED_name_phen_c= "fates_phen_c" - !character(len=param_string_length),parameter,public :: ED_name_phen_chiltemp= "fates_phen_chiltemp" + character(len=param_string_length),parameter,public :: ED_name_phen_a= "fates_phen_gddthresh_a" + character(len=param_string_length),parameter,public :: ED_name_phen_b= "fates_phen_gddthresh_b" + character(len=param_string_length),parameter,public :: ED_name_phen_c= "fates_phen_gddthresh_c" + character(len=param_string_length),parameter,public :: ED_name_phen_chiltemp= "fates_phen_chilltemp" character(len=param_string_length),parameter,public :: ED_name_phen_mindayson= "fates_phen_mindayson" - !character(len=param_string_length),parameter,public :: ED_name_phen_ncolddayslim= "fates_phen_ncolddayslim" - !character(len=param_string_length),parameter,public :: ED_name_phen_coldtemp= "fates_phen_coldtemp" + character(len=param_string_length),parameter,public :: ED_name_phen_ncolddayslim= "fates_phen_ncolddayslim" + character(len=param_string_length),parameter,public :: ED_name_phen_coldtemp= "fates_phen_coldtemp" character(len=param_string_length),parameter,public :: ED_name_cohort_size_fusion_tol= "fates_cohort_size_fusion_tol" character(len=param_string_length),parameter,public :: ED_name_cohort_age_fusion_tol = "fates_cohort_age_fusion_tol" character(len=param_string_length),parameter,public :: ED_name_patch_fusion_tol= "fates_patch_fusion_tol" @@ -268,13 +268,13 @@ subroutine FatesParamsInit() ED_val_base_mr_20 = nan ED_val_phen_drought_threshold = nan ED_val_phen_doff_time = nan - !ED_val_phen_a = nan - !ED_val_phen_b = nan - !ED_val_phen_c = nan - !ED_val_phen_chiltemp = nan + ED_val_phen_a = nan + ED_val_phen_b = nan + ED_val_phen_c = nan + ED_val_phen_chiltemp = nan ED_val_phen_mindayson = nan - !ED_val_phen_ncolddayslim = nan - !ED_val_phen_coldtemp = nan + ED_val_phen_ncolddayslim = nan + ED_val_phen_coldtemp = nan ED_val_cohort_size_fusion_tol = nan ED_val_cohort_age_fusion_tol = nan ED_val_patch_fusion_tol = nan @@ -380,26 +380,26 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=ED_name_phen_doff_time, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) - !call fates_params%RegisterParameter(name=ED_name_phen_a, dimension_shape=dimension_shape_scalar, & - ! dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=ED_name_phen_a, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) - !call fates_params%RegisterParameter(name=ED_name_phen_b, dimension_shape=dimension_shape_scalar, & - ! dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=ED_name_phen_b, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) - !call fates_params%RegisterParameter(name=ED_name_phen_c, dimension_shape=dimension_shape_scalar, & - ! dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=ED_name_phen_c, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) - !call fates_params%RegisterParameter(name=ED_name_phen_chiltemp, dimension_shape=dimension_shape_scalar, & - ! dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=ED_name_phen_chiltemp, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) call fates_params%RegisterParameter(name=ED_name_phen_mindayson, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) - !call fates_params%RegisterParameter(name=ED_name_phen_ncolddayslim, dimension_shape=dimension_shape_scalar, & - ! dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=ED_name_phen_ncolddayslim, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) - !call fates_params%RegisterParameter(name=ED_name_phen_coldtemp, dimension_shape=dimension_shape_scalar, & - ! dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=ED_name_phen_coldtemp, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) call fates_params%RegisterParameter(name=ED_name_cohort_size_fusion_tol, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -568,26 +568,26 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetreiveParameter(name=ED_name_phen_doff_time, & data=ED_val_phen_doff_time) - !call fates_params%RetreiveParameter(name=ED_name_phen_a, & - ! data=ED_val_phen_a) + call fates_params%RetreiveParameter(name=ED_name_phen_a, & + data=ED_val_phen_a) - !call fates_params%RetreiveParameter(name=ED_name_phen_b, & - ! data=ED_val_phen_b) + call fates_params%RetreiveParameter(name=ED_name_phen_b, & + data=ED_val_phen_b) - !call fates_params%RetreiveParameter(name=ED_name_phen_c, & - ! data=ED_val_phen_c) + call fates_params%RetreiveParameter(name=ED_name_phen_c, & + data=ED_val_phen_c) - !call fates_params%RetreiveParameter(name=ED_name_phen_chiltemp, & - ! data=ED_val_phen_chiltemp) + call fates_params%RetreiveParameter(name=ED_name_phen_chiltemp, & + data=ED_val_phen_chiltemp) call fates_params%RetreiveParameter(name=ED_name_phen_mindayson, & data=ED_val_phen_mindayson) - !call fates_params%RetreiveParameter(name=ED_name_phen_ncolddayslim, & - ! data=ED_val_phen_ncolddayslim) + call fates_params%RetreiveParameter(name=ED_name_phen_ncolddayslim, & + data=ED_val_phen_ncolddayslim) - !call fates_params%RetreiveParameter(name=ED_name_phen_coldtemp, & - ! data=ED_val_phen_coldtemp) + call fates_params%RetreiveParameter(name=ED_name_phen_coldtemp, & + data=ED_val_phen_coldtemp) call fates_params%RetreiveParameter(name=ED_name_cohort_size_fusion_tol, & data=ED_val_cohort_size_fusion_tol) @@ -743,13 +743,13 @@ subroutine FatesReportParams(is_master) write(fates_log(),fmt0) 'ED_val_base_mr_20 = ', ED_val_base_mr_20 write(fates_log(),fmt0) 'ED_val_phen_drought_threshold = ',ED_val_phen_drought_threshold write(fates_log(),fmt0) 'ED_val_phen_doff_time = ',ED_val_phen_doff_time - !write(fates_log(),fmt0) 'ED_val_phen_a = ',ED_val_phen_a - !write(fates_log(),fmt0) 'ED_val_phen_b = ',ED_val_phen_b - !write(fates_log(),fmt0) 'ED_val_phen_c = ',ED_val_phen_c - !write(fates_log(),fmt0) 'ED_val_phen_chiltemp = ',ED_val_phen_chiltemp + write(fates_log(),fmt0) 'ED_val_phen_a = ',ED_val_phen_a + write(fates_log(),fmt0) 'ED_val_phen_b = ',ED_val_phen_b + write(fates_log(),fmt0) 'ED_val_phen_c = ',ED_val_phen_c + write(fates_log(),fmt0) 'ED_val_phen_chiltemp = ',ED_val_phen_chiltemp write(fates_log(),fmt0) 'ED_val_phen_mindayson = ',ED_val_phen_mindayson - !write(fates_log(),fmt0) 'ED_val_phen_ncolddayslim = ',ED_val_phen_ncolddayslim - !write(fates_log(),fmt0) 'ED_val_phen_coldtemp = ',ED_val_phen_coldtemp + write(fates_log(),fmt0) 'ED_val_phen_ncolddayslim = ',ED_val_phen_ncolddayslim + write(fates_log(),fmt0) 'ED_val_phen_coldtemp = ',ED_val_phen_coldtemp write(fates_log(),fmt0) 'ED_val_cohort_size_fusion_tol = ',ED_val_cohort_size_fusion_tol 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 diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index fabe95c38b..cbf9d2f42c 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -180,17 +180,6 @@ module EDPftvarcon ! prescribe an uptake rate for phosphorus ! This is the fraction of plant demand - ! GDD accumulation function, intercept parameters: gdd_thesh = a + b exp(c*ncd) - !real(r8), allocatable :: phen_gddthresh_a - !real(r8), allocatable :: phen_gddthresh_b - !real(r8), allocatable :: phen_gddthresh_c - !chilling day counting threshold for vegetation (deg C) - !real(r8), allocatable :: phen_chiltemp - ! vegetation temperature exceedance that flags a cold-day for leaf-drop (deg C) - !real(r8), allocatable :: phen_coldtemp - ! day threshold exceedance for temperature leaf-drop (days) - !real(r8), allocatable :: phen_ncolddayslim - ! Unassociated pft dimensioned free parameter that ! developers can use for testing arbitrary new hypothese real(r8), allocatable :: dev_arbitrary_pft(:) @@ -569,30 +558,6 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_phen_gddthresh_a' - call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & - dimension_names=dim_names, lower_bounds=dim_lower_bound) - - name = 'fates_phen_gddthresh_b' - call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & - dimension_names=dim_names, lower_bounds=dim_lower_bound) - - name = 'fates_phen_gddthresh_c' - call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & - dimension_names=dim_names, lower_bounds=dim_lower_bound) - - name = 'fates_phen_chilltemp' - call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & - dimension_names=dim_names, lower_bounds=dim_lower_bound) - - name = 'fates_phen_coldtemp' - call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & - dimension_names=dim_names, lower_bounds=dim_lower_bound) - - name = 'fates_phen_ncolddayslim' - call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & - dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_phen_flush_fraction' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -936,30 +901,6 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=this%displar) - name = 'fates_phen_gddthresh_a' - call fates_params%RetreiveParameterAllocate(name=name, & - data=this%phen_gddthresh_a) - - name = 'fates_phen_gddthresh_b' - call fates_params%RetreiveParameterAllocate(name=name, & - data=this%phen_gddthresh_b) - - name = 'fates_phen_gddthresh_c' - call fates_params%RetreiveParameterAllocate(name=name, & - data=this%phen_gddthresh_c) - - name = 'fates_phen_chilltemp' - call fates_params%RetreiveParameterAllocate(name=name, & - data=this%phen_chilltemp) - - name = 'fates_phen_coldtemp' - call fates_params%RetreiveParameterAllocate(name=name, & - data=this%phen_coldtemp) - - name = 'fates_phen_ncolddayslim' - call fates_params%RetreiveParameterAllocate(name=name, & - data=this%phen_ncolddayslim) - name = 'fates_phen_flush_fraction' call fates_params%RetreiveParameterAllocate(name=name, & data=this%phenflush_fraction) diff --git a/parameter_files/apichange_23to24.xml b/parameter_files/apichange_23to24.xml index 6a3b62dfac..53440050d9 100644 --- a/parameter_files/apichange_23to24.xml +++ b/parameter_files/apichange_23to24.xml @@ -106,10 +106,10 @@ fates_phen_drought_threshold - fates_pft + scalar m3/m3 or mm threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm) - 0.15,0.15,0.15,0.15,0.15,0.15,0.15,0.15,0.15,0.15,0.15,0.15 + 0.15 fates_phen_moist_threshold @@ -541,62 +541,14 @@ fates_phen_gddthresh_a - - fates_phen_gddthresh_a - fates_pft - unitless - GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd) - -68,-68,-68,-68,-68,-68,-68,-68,-68,-68,-68,-68 - - - fates_phen_b - - + fates_phen_gddthresh_b - fates_pft - unitless - GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd) - 638,638,638,638,638,638,638,638,638,638,638,638 - - - fates_phen_c - + fates_phen_gddthresh_c - fates_pft - unitless - GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd) - -0.01,-0.01,-0.01,-0.01,-0.01,-0.01,-0.01,-0.01,-0.01,-0.01,-0.01,-0.01, - - fates_phen_chiltemp - - + fates_phen_chilltemp - fates_pft - degrees C - chilling day counting threshold for vegetation - 5,5,5,5,5,5,5,5,5,5,5,5 - - - fates_phen_coldtemp - - - fates_phen_coldtemp - fates_pft - degrees C - vegetation temperature exceedance that flags a cold-day for leaf-drop - 7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5, - - - fates_phen_ncolddayslim - - - fates_phen_ncolddayslim - fates_pft - days - day threshold exceedance for temperature leaf-drop - fates_cnp_store_ovrflw_frac @@ -605,7 +557,5 @@ size of overflow storage (for excess C,N or P) as a fraction of storage target 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 - - diff --git a/parameter_files/fates_params_default_api24.cdl b/parameter_files/fates_params_default_api24.cdl index 948d6f4224..2aa81200e2 100644 --- a/parameter_files/fates_params_default_api24.cdl +++ b/parameter_files/fates_params_default_api24.cdl @@ -218,6 +218,10 @@ variables: double fates_cnp_rd_vmax_n(fates_pft) ; fates_cnp_rd_vmax_n:units = "gN/gC/s" ; fates_cnp_rd_vmax_n:long_name = "maximum production rate for compbined (NH4+NO3) uptake (RD)" ; + double fates_cnp_store_ovrflw_frac(fates_pft) ; + fates_cnp_store_ovrflw_frac:units = "fraction" ; + fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; + fates_cnp_store_ovrflw_frac:use_case = "None" ; double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; fates_cnp_turnover_nitr_retrans:units = "fraction" ; fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; @@ -593,6 +597,9 @@ variables: double fates_comp_excln ; fates_comp_excln:units = "none" ; fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; + double fates_damage_event_code ; + fates_damage_event_code:units = "unitless" ; + fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; double fates_dev_arbitrary ; fates_dev_arbitrary:units = "unknown" ; fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; @@ -728,18 +735,9 @@ variables: double fates_patch_fusion_tol ; fates_patch_fusion_tol:units = "unitless" ; fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; - double fates_phen_a ; - fates_phen_a:units = "none" ; - fates_phen_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_b ; - fates_phen_b:units = "none" ; - fates_phen_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_c ; - fates_phen_c:units = "none" ; - fates_phen_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_chiltemp ; - fates_phen_chiltemp:units = "degrees C" ; - fates_phen_chiltemp:long_name = "chilling day counting threshold for vegetation" ; + double fates_phen_chilltemp ; + fates_phen_chilltemp:units = "degrees C" ; + fates_phen_chilltemp:long_name = "chilling day counting threshold for vegetation" ; double fates_phen_coldtemp ; fates_phen_coldtemp:units = "degrees C" ; fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; @@ -749,6 +747,15 @@ variables: double fates_phen_drought_threshold ; fates_phen_drought_threshold:units = "m3/m3 or mm" ; fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_gddthresh_a ; + fates_phen_gddthresh_a:units = "none" ; + fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_b ; + fates_phen_gddthresh_b:units = "none" ; + fates_phen_gddthresh_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_c ; + fates_phen_gddthresh_c:units = "none" ; + fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; double fates_phen_mindaysoff ; fates_phen_mindaysoff:units = "days" ; fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves became off-allometry" ; @@ -983,6 +990,8 @@ data: fates_cnp_rd_vmax_n = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_cnp_turnover_nitr_retrans = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, @@ -1398,6 +1407,8 @@ data: fates_comp_excln = 3 ; + fates_damage_event_code = 1 ; + fates_dev_arbitrary = _ ; fates_fire_active_crown_fire = 0 ; @@ -1488,13 +1499,7 @@ data: fates_patch_fusion_tol = 0.05 ; - fates_phen_a = -68 ; - - fates_phen_b = 638 ; - - fates_phen_c = -0.01 ; - - fates_phen_chiltemp = 5 ; + fates_phen_chilltemp = 5 ; fates_phen_coldtemp = 7.5 ; @@ -1502,6 +1507,12 @@ data: fates_phen_drought_threshold = 0.15 ; + fates_phen_gddthresh_a = -68 ; + + fates_phen_gddthresh_b = 638 ; + + fates_phen_gddthresh_c = -0.01 ; + fates_phen_mindaysoff = 100 ; fates_phen_mindayson = 90 ; From 758d902706f5ba0efe6b81fa40394455be31b3d6 Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Wed, 25 May 2022 18:07:53 -0700 Subject: [PATCH 218/852] [ create a single hlm_use_crown_damage switch and make a parameter to signal which canaopy layer of trees gets damaged ] [ Single switch for turning on the module and parameters to modify the module's behaviour. ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes - single namelist option now hlm_use_crown_damage and a new parameter fates_damage_canopy_layer_code 1 for canopy and 2 for understory] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary:no testing --- biogeochem/DamageMainMod.F90 | 2 - biogeochem/EDCohortDynamicsMod.F90 | 3 +- biogeochem/EDMortalityFunctionsMod.F90 | 5 +-- biogeochem/EDPatchDynamicsMod.F90 | 49 +++++++++++++--------- biogeophys/FatesPlantRespPhotosynthMod.F90 | 5 +-- main/EDInitMod.F90 | 5 +-- main/EDMainMod.F90 | 5 +-- main/EDParamsMod.F90 | 17 ++++++-- main/EDTypesMod.F90 | 1 - main/FatesHistoryInterfaceMod.F90 | 18 ++++---- main/FatesInterfaceMod.F90 | 30 ++++--------- main/FatesInterfaceTypesMod.F90 | 7 +--- main/FatesRestartInterfaceMod.F90 | 12 +++--- parameter_files/fates_params_default.cdl | 5 +++ 14 files changed, 79 insertions(+), 85 deletions(-) diff --git a/biogeochem/DamageMainMod.F90 b/biogeochem/DamageMainMod.F90 index 8d57224f2b..8e8748692f 100644 --- a/biogeochem/DamageMainMod.F90 +++ b/biogeochem/DamageMainMod.F90 @@ -28,8 +28,6 @@ module DamageMainMod use FatesInterfaceTypesMod, only : hlm_current_year use FatesInterfaceTypesMod, only : hlm_model_day use FatesInterfaceTypesMod , only : hlm_day_of_year - use FatesInterfaceTypesMod, only : hlm_use_canopy_damage - use FatesInterfaceTypesMod, only : hlm_use_understory_damage diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 7d04ce2f07..bf6614f25f 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -11,6 +11,7 @@ Module EDCohortDynamicsMod use FatesInterfaceTypesMod , only : hlm_use_planthydro use FatesInterfaceTypesMod , only : hlm_use_sp use FatesInterfaceTypesMod , only : hlm_use_cohort_age_tracking + use FatesInterfaceTypesMod , only : hlm_use_crown_damage use FatesInterfaceTypesMod , only : hlm_is_restart use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : fates_unset_int @@ -723,8 +724,6 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_ ! terminates all cohorts when they get too small ! ! !USES: - use FatesInterfaceTypesMod , only : hlm_use_canopy_damage - use FatesInterfaceTypesMod , only : hlm_use_understory_damage ! ! !ARGUMENTS diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index 443035b7ca..46a88d5fec 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -17,8 +17,7 @@ module EDMortalityFunctionsMod use FatesInterfaceTypesMod , only : hlm_use_ed_prescribed_phys use FatesInterfaceTypesMod , only : hlm_freq_day use FatesInterfaceTypesMod , only : hlm_use_planthydro - use FatesInterfaceTypesMod , only : hlm_use_canopy_damage - use FatesInterfaceTypesMod , only : hlm_use_understory_damage + use FatesInterfaceTypesMod , only : hlm_use_crown_damage use EDLoggingMortalityMod , only : LoggingMortality_frac use EDParamsMod , only : fates_mortality_disturbance_fraction @@ -116,7 +115,7 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmor end if ! Damage dependent mortality - if (hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + if (hlm_use_crown_damage .eq. itrue) then call get_damage_mortality(cohort_in%crowndamage, cohort_in%pft, dgmort) else dgmort = 0.0_r8 diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 546e2727cc..2d2c3d8ff9 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -472,10 +472,10 @@ subroutine spawn_patches( currentSite, bc_in) use PRTLossFluxesMod , only : PRTDamageLosses use PRTGenericMod , only : leaf_organ use ChecksBalancesMod , only : SiteMassStock - use FatesInterfaceTypesMod, only : hlm_use_canopy_damage - use FatesInterfaceTypesMod, only : hlm_use_understory_damage + use FatesInterfaceTypesMod, only : hlm_use_crown_damage use FatesInterfaceTypesMod, only : nlevdamage use FatesParameterDerivedMod, only : param_derived + use EDParamsMod , only : damage_canopy_layer_code ! ! !ARGUMENTS: @@ -539,11 +539,14 @@ subroutine spawn_patches( currentSite, bc_in) logical :: found_youngest_primary ! logical for finding the first primary forest patch integer :: min_nocomp_pft, max_nocomp_pft, i_nocomp_pft + integer :: i_damage_code !--------------------------------------------------------------------- real(r8), parameter :: damage_error_fail = 1.0e-6_r8 !--------------------------------------------------------------------- + + i_damage_code = int(damage_canopy_layer_code) total_litter_d = 0.0_r8 @@ -760,7 +763,7 @@ subroutine spawn_patches( currentSite, bc_in) ! and the damaged trees - if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + if(hlm_use_crown_damage .eq. itrue) then if( damage_time ) then call damage_litter_fluxes(currentSite, currentPatch, & @@ -905,7 +908,7 @@ subroutine spawn_patches( currentSite, bc_in) total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 - if (hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + if (hlm_use_crown_damage .eq. itrue) then currentSite%imort_rate_damage(currentCohort%crowndamage, & currentCohort%size_class, currentCohort%pft) = & @@ -1017,7 +1020,7 @@ subroutine spawn_patches( currentSite, bc_in) end if ! also track fire damage mortality and cflux along size x damage axis - if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + if(hlm_use_crown_damage .eq. itrue) then if(levcan==ican_upper) then currentSite%fmort_rate_canopy_damage(currentCohort%crowndamage, currentCohort%size_class, & currentCohort%pft) = & @@ -1178,7 +1181,7 @@ subroutine spawn_patches( currentSite, bc_in) logging_coll_under_frac/ hlm_freq_day ) * & total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 - if (hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + if (hlm_use_crown_damage .eq. itrue) then currentSite%imort_rate_damage(currentCohort%crowndamage,& currentCohort%size_class, currentCohort%pft) = & currentSite%imort_rate_damage(currentCohort%crowndamage,& @@ -1253,7 +1256,7 @@ subroutine spawn_patches( currentSite, bc_in) ! Regardless of disturbance type, reduce mass of damaged trees - if(hlm_use_canopy_damage .eq.itrue .or. hlm_use_understory_damage .eq. itrue) then + if(hlm_use_crown_damage .eq. itrue) then if(damage_time) then ! if woody @@ -1269,9 +1272,9 @@ subroutine spawn_patches( currentSite, bc_in) call get_damage_frac(currentCohort%crowndamage, cd, currentCohort%pft, cd_frac) - if(hlm_use_canopy_damage .eq. itrue .and. currentCohort%canopy_layer == 1) then + if(i_damage_code .eq. 1 .and. currentCohort%canopy_layer == 1) then cd_n = currentCohort%n * cd_frac - else if(hlm_use_understory_damage .eq. itrue .and. currentCohort%canopy_layer > 1) then + else if(i_damage_code .eq. 2 .and. currentCohort%canopy_layer > 1) then cd_n = nc%n * cd_frac else cd_n = 0._r8 @@ -1346,12 +1349,12 @@ subroutine spawn_patches( currentSite, bc_in) fnrt_c = nc_d%prt%GetState(fnrt_organ, all_carbon_elements) - if(hlm_use_canopy_damage .eq. itrue) then + if(i_damage_code .eq. 1 ) then currentSite%crownarea_canopy_damage = currentSite%crownarea_canopy_damage + & (currentCohort%c_area/currentCohort%n - nc_d%c_area/nc_d%n) * nc_d%n end if - if(hlm_use_understory_damage .eq. itrue) then + if(i_damage_code .eq. 2 ) then currentSite%crownarea_ustory_damage = currentSite%crownarea_ustory_damage + & (currentCohort%c_area/currentCohort%n - nc_d%c_area/nc_d%n) * nc_d%n end if @@ -1387,14 +1390,14 @@ subroutine spawn_patches( currentSite, bc_in) ! Reduce currentCohort%n now based on sum of all new damage classes ! And update c_area of the undamaged cohort (since number density has changed) - if(hlm_use_canopy_damage .eq. itrue) then + if(i_damage_code .eq. 1 ) then currentCohort%n = currentCohort%n - cd_n_total call carea_allom(currentCohort%dbh, currentCohort%n, currentSite%spread,& currentCohort%pft, currentCohort%crowndamage, currentCohort%c_area) - else if(hlm_use_understory_damage .eq. itrue) then + else if(i_damage_code .eq. 2 ) then nc%n = nc%n - cd_n_total call carea_allom(nc%dbh, nc%n, currentSite%spread,& - nc%pft, nc%crowndamage, nc%c_area) + nc%pft, nc%crowndamage, nc%c_area) end if @@ -2383,8 +2386,8 @@ subroutine damage_litter_fluxes(currentSite, currentPatch, newPatch,patch_site_a use SFParamsMod , only : SF_val_cwd_frac use FatesInterfaceTypesMod , only : nlevdamage use EDParamsMod , only : ED_val_understorey_death - use FatesInterfaceTypesMod, only : hlm_use_canopy_damage - use FatesInterfaceTypesMod, only : hlm_use_understory_damage + use EDParamsMod , only : damage_canopy_layer_code + use FatesInterfaceTypesMod, only : hlm_use_crown_damage use FatesConstantsMod, only : itrue use FatesParameterDerivedMod, only : param_derived ! @@ -2437,7 +2440,11 @@ subroutine damage_litter_fluxes(currentSite, currentPatch, newPatch,patch_site_a integer :: ncwd_no_trunk real(r8), allocatable :: SF_val_CWD_frac_canopy(:) real(r8) :: cd_n_tot + integer :: i_damage_code + !--------------------------------------------------------------------- + i_damage_code = int(damage_canopy_layer_code) + total_damage_litter = 0.0_r8 cd_n_tot = 0.0_r8 ncwd_no_trunk = ncwd - 1 @@ -2495,15 +2502,17 @@ subroutine damage_litter_fluxes(currentSite, currentPatch, newPatch,patch_site_a if(prt_params%woody(currentCohort%pft)==1) then - if( hlm_use_canopy_damage .eq.itrue .and. & - currentCohort%canopy_layer ==1 .and. .not. currentCohort%isnew) then + if( hlm_use_crown_damage .eq.itrue .and. & + currentCohort%canopy_layer ==1 .and. i_damage_code .eq. 1 .and. & + .not. currentCohort%isnew) then ! litter is called before damage - so we need to account for mortality here too num_trees = currentCohort%n * (1.0_r8 - fates_mortality_disturbance_fraction * & min(1.0_r8, currentCohort%dmort* hlm_freq_day)) - else if( hlm_use_understory_damage .eq.itrue .and. & - currentCohort%canopy_layer > 1 .and. .not. currentCohort%isnew) then + else if( hlm_use_crown_damage .eq.itrue .and. & + currentCohort%canopy_layer > 1 .and. i_damage_code .eq. 2 .and. & + .not. currentCohort%isnew) then ! for trees in new patch to be damaged num_trees = currentCohort%n * (patch_site_areadis/currentPatch%area) * & diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 3bf35c6849..3d9e005154 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -136,8 +136,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) use DamageMainMod, only : get_crown_reduction - use FatesInterfaceTypesMod, only : hlm_use_canopy_damage - use FatesInterfaceTypesMod, only : hlm_use_understory_damage + use FatesInterfaceTypesMod, only : hlm_use_crown_damage ! ARGUMENTS: ! ----------------------------------------------------------------------------------- @@ -651,7 +650,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) - if (hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + if (hlm_use_crown_damage .eq. itrue) then agb_frac = prt_params%allom_agb_frac(currentCohort%pft) branch_frac = param_derived%branch_frac(currentCohort%pft) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index b49c757e3c..4ace6c87f1 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -43,8 +43,7 @@ module EDInitMod use FatesInterfaceTypesMod , only : hlm_use_planthydro use FatesInterfaceTypesMod , only : hlm_use_inventory_init use FatesInterfaceTypesMod , only : hlm_use_fixed_biogeog - use FatesInterfaceTypesMod , only : hlm_use_canopy_damage - use FatesInterfaceTypesMod , only : hlm_use_understory_damage + use FatesInterfaceTypesMod , only : hlm_use_crown_damage use FatesInterfaceTypesMod , only : hlm_use_sp use FatesInterfaceTypesMod , only : numpft use FatesInterfaceTypesMod , only : nleafage @@ -131,7 +130,7 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) allocate(site_in%mass_balance(1:num_elements)) allocate(site_in%flux_diags(1:num_elements)) - if (hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + if (hlm_use_crown_damage .eq. itrue) then allocate(site_in%term_nindivs_canopy_damage(1:nlevdamage, 1:nlevsclass, 1:numpft)) allocate(site_in%term_nindivs_ustory_damage(1:nlevdamage, 1:nlevsclass, 1:numpft)) allocate(site_in%imort_rate_damage(1:nlevdamage, 1:nlevsclass, 1:numpft)) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 2470b2c678..85ef572163 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -19,8 +19,7 @@ module EDMainMod use FatesInterfaceTypesMod , only : hlm_use_cohort_age_tracking use FatesInterfaceTypesMod , only : hlm_reference_date use FatesInterfaceTypesMod , only : hlm_use_ed_prescribed_phys - use FatesInterfaceTypesMod , only : hlm_use_canopy_damage - use FatesInterfaceTypesMod , only : hlm_use_understory_damage + use FatesInterfaceTypesMod , only : hlm_use_crown_damage use FatesInterfaceTypesMod , only : hlm_use_ed_st3 use FatesInterfaceTypesMod , only : hlm_use_sp use FatesInterfaceTypesMod , only : bc_in_type @@ -523,7 +522,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) call currentCohort%prt%DailyPRT() - if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + if(hlm_use_crown_damage .eq. itrue) then if(currentCohort%crowndamage > 1) then diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index aa51356339..199bf42445 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -209,10 +209,13 @@ module EDParamsMod character(len=param_string_length),parameter,public :: eca_name_plant_escalar = "fates_eca_plant_escalar" - ! Damage Control Parameters (ONLY RELEVANT WHEN USE_FATES_CANOPY_DAMAGE OR USE_FATES_UNDERSTORY_DAMAGE = TRUE) + ! Damage Control Parameters (ONLY RELEVANT WHEN USE_FATES_DAMAGE = TRUE) !--------------------------------------------------------------------------------------------------------------- - real(r8),protected,public :: damage_event_code ! Code that options how damage events are structured + real(r8),protected,public :: damage_event_code ! Code that options how damage events are structured character(len=param_string_length),parameter,public :: damage_name_event_code = "fates_damage_event_code" + + real(r8),protected,public :: damage_canopy_layer_code ! Code that changes whether damage affects canopy trees (1), understory trees (2) + character(len=param_string_length),parameter,public :: damage_name_canopy_layer_code = "fates_damage_canopy_layer_code" public :: FatesParamsInit public :: FatesRegisterParams @@ -279,6 +282,7 @@ subroutine FatesParamsInit() theta_cj_c4 = nan dev_arbitrary = nan damage_event_code = nan + damage_canopy_layer_code = nan end subroutine FatesParamsInit !----------------------------------------------------------------------- @@ -448,7 +452,10 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=name_dev_arbitrary, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) - call fates_params%RegisterParameter(name=damage_name_event_code, dimension_shape=dimension_shape_scalar, & + call fates_params%RegisterParameter(name=damage_name_event_code, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + + call fates_params%RegisterParameter(name=damage_name_canopy_layer_code, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) ! non-scalar parameters @@ -647,6 +654,9 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetreiveParameter(name=damage_name_event_code, & data=damage_event_code) + call fates_params%RetreiveParameter(name=damage_name_canopy_layer_code, & + data=damage_canopy_layer_code) + ! parameters that are arrays of size defined within the params file and thus need allocating as well call fates_params%RetreiveParameterAllocate(name=ED_name_history_sizeclass_bin_edges, & data=ED_val_history_sizeclass_bin_edges) @@ -731,6 +741,7 @@ subroutine FatesReportParams(is_master) write(fates_log(),fmt0) 'cg_strikes = ',cg_strikes 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(),*) '------------------------------------------------------' end if diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 8f367f78de..2e4a13a309 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -22,7 +22,6 @@ module EDTypesMod use FatesRunningMeanMod, only : rmean_type use FatesInterfaceTypesMod,only : bc_in_type use FatesInterfaceTypesMod,only : bc_out_type - use FatesInterfaceTypesMod,only : hlm_use_canopy_damage, hlm_use_understory_damage implicit none private ! By default everything is private diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 0ce2ee34c9..f9dd8f0621 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -38,8 +38,7 @@ Module FatesHistoryInterfaceMod use FatesInterfaceTypesMod , only : hlm_use_planthydro use FatesInterfaceTypesMod , only : hlm_use_ed_st3 use FatesInterfaceTypesMod , only : hlm_use_cohort_age_tracking - use FatesInterfaceTypesMod , only : hlm_use_canopy_damage - use FatesInterfaceTypesMod , only : hlm_use_understory_damage + use FatesInterfaceTypesMod , only : hlm_use_crown_damage use FatesInterfaceTypesMod , only : numpft use FatesInterfaceTypesMod , only : hlm_freq_day use FatesInterfaceTypesMod , only : hlm_parteh_mode @@ -2208,7 +2207,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) end do ! damage variables - site level - this needs to be OUT of the patch loop - if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + if(hlm_use_crown_damage .eq. itrue) then this%hvars(ih_crownarea_canopy_damage_si)%r81d(io_si) = & this%hvars(ih_crownarea_canopy_damage_si)%r81d(io_si) + & @@ -2741,7 +2740,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) end if ! damage variables - cohort level - if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + if(hlm_use_crown_damage .eq. itrue) then cdpf = get_cdamagesizepft_class_index(ccohort%dbh, ccohort%crowndamage, ccohort%pft) @@ -2891,7 +2890,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! damage variables - canopy - if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + if(hlm_use_crown_damage .eq. itrue) then ! carbon starvation mortality in the canopy by size x damage x pft this%hvars(ih_m3_mortality_canopy_si_cdpf)%r82d(io_si,cdpf) = & @@ -3023,7 +3022,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! damage variables - understory - if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + if(hlm_use_crown_damage .eq. itrue) then ! carbon mortality in the understory by damage x size x pft this%hvars(ih_m3_mortality_understory_si_cdpf)%r82d(io_si,cdpf) = & @@ -3300,8 +3299,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) end do end do - if(hlm_use_canopy_damage .eq. itrue .or. & - hlm_use_understory_damage .eq. itrue ) then + if(hlm_use_crown_damage .eq. itrue) then do i_pft = 1, numpft do icdam = 1, nlevdamage @@ -3384,7 +3382,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_m9_si_scpf(io_si,i_scpf) + & hio_m10_si_scpf(io_si,i_scpf) - if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + if(hlm_use_crown_damage .eq. itrue) then hio_mortality_si_pft(io_si, i_pft) = hio_mortality_si_pft(io_si,i_pft) + & this%hvars(ih_m11_si_scpf)%r82d(io_si,i_scpf) end if @@ -6842,7 +6840,7 @@ subroutine define_history_vars(this, initialize_variables) index = ih_resp_m_understory_si_scls) ! CROWN DAMAGE VARIABLES - if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + if(hlm_use_crown_damage .eq. itrue) then call this%set_history_var(vname='FATES_CROWNAREA_CANOPY_CD', units = 'm2 m-2 yr-1', & long='crownarea lost to damage each year', use_default='inactive', & diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 64a8d54a91..8a729c6bef 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -778,8 +778,7 @@ subroutine SetFatesGlobalElements(use_fates) ! These values are used to define the restart file allocations and general structure ! of memory for the cohort arrays - if ( hlm_use_cohort_age_tracking .eq. itrue .or. & - hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + if ( hlm_use_cohort_age_tracking .eq. itrue .or. hlm_use_crown_damage .eq. itrue) then maxCohortsPerPatch = 300 else maxCohortsPerPatch = 100 @@ -1331,8 +1330,7 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) hlm_use_lu_harvest = unset_int hlm_num_lu_harvest_cats = unset_int hlm_use_cohort_age_tracking = unset_int - hlm_use_understory_damage = unset_int - hlm_use_canopy_damage = unset_int + hlm_use_crown_damage = unset_int hlm_use_logging = unset_int hlm_use_ed_st3 = unset_int hlm_use_ed_prescribed_phys = unset_int @@ -1645,16 +1643,9 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if(hlm_use_understory_damage .eq. unset_int) then + if(hlm_use_crown_damage .eq. unset_int) then if (fates_global_verbose()) then - write(fates_log(), *) 'switch for understory damage unset: hlm_use_understory_damage, exiting' - end if - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - if(hlm_use_canopy_damage .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'switch for canopy damage unset: hlm_use_canopy_damage, exiting' + write(fates_log(), *) 'switch for crown damage unset: hlm_use_crown_damage, exiting' end if call endrun(msg=errMsg(sourcefile, __LINE__)) end if @@ -1832,17 +1823,10 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) write(fates_log(),*) 'Transfering hlm_use_cohort_age_tracking= ',ival,' to FATES' end if - case('use_understory_damage') - hlm_use_understory_damage = ival - if (fates_global_verbose()) then - write(fates_log(),*) 'Transfering hlm_use_understory_damage= ',ival,' to FATES' - end if - - case('use_canopy_damage') - hlm_use_canopy_damage = ival + case('use_crown_damage') + hlm_use_crown_damage = ival if (fates_global_verbose()) then - write(fates_log(),*) 'Transfering hlm_use_canopy_damage= ',ival,' to FATES' - write(fates_log(),*) 'JN FatesInterfaceMod hlm_use_canopy_damage : ', hlm_use_canopy_damage + write(fates_log(),*) 'Transfering hlm_use_crown_damage= ',ival,' to FATES' end if case('use_logging') diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 26d36f62fa..806dd386e7 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -151,11 +151,8 @@ module FatesInterfaceTypesMod ! cohort age tracking. 1 = TRUE, 0 = FALSE - integer, public :: hlm_use_canopy_damage ! This flag signals whether or not to use - ! the canopy damage module. 1 = TRUE, 0 = FALSE - - integer, public :: hlm_use_understory_damage ! This flag signals whether or not to use - ! understory damage. 1 = TRUE, 0 = FALSE + integer, public :: hlm_use_crown_damage ! This flag signals whether or not to use + ! the crown damage module. 1 = TRUE, 0 = FALSE integer, public :: hlm_use_ed_st3 ! This flag signals whether or not to use diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 41bc8e58f0..d0b2ea3d5d 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -1786,8 +1786,7 @@ end subroutine set_restart_var subroutine set_restart_vectors(this,nc,nsites,sites) - use FatesInterfaceTypesMod, only : hlm_use_canopy_damage - use FatesInterfaceTypesMod, only : hlm_use_understory_damage + use FatesInterfaceTypesMod, only : hlm_use_crown_damage use FatesInterfaceTypesMod, only : fates_maxElementsPerPatch use FatesInterfaceTypesMod, only : numpft use EDTypesMod, only : ed_site_type @@ -2369,7 +2368,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) ! this only copies live portions of transitions - but that's ok because the mortality ! bit only needs to be added for history outputs - if(hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + if(hlm_use_crown_damage .eq. itrue) then do i_scls = 1, nlevsclass do i_cdam = 1, nlevdamage @@ -2694,9 +2693,8 @@ subroutine get_restart_vectors(this, nc, nsites, sites) use EDTypesMod, only : numWaterMem use EDTypesMod, only : num_vegtemp_mem use FatesSizeAgeTypeIndicesMod, only : get_age_class_index - use FatesInterfaceTypesMod, only : hlm_use_canopy_damage - use FatesInterfaceTypesMod, only : hlm_use_understory_damage - + use FatesInterfaceTypesMod, only : hlm_use_crown_damage + ! !ARGUMENTS: class(fates_restart_interface_type) , intent(inout) :: this @@ -3296,7 +3294,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) io_idx_si_sc = io_idx_si_sc + 1 end do - if (hlm_use_canopy_damage .eq. itrue .or. hlm_use_understory_damage .eq. itrue) then + if (hlm_use_crown_damage .eq. itrue) then do i_cdam = 1, nlevdamage do i_pft = 1, numpft do i_scls = 1, nlevsclass diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 42b37dd27d..7c9fefaf8f 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -157,6 +157,9 @@ variables: double fates_branch_turnover(fates_pft) ; fates_branch_turnover:units = "yr" ; fates_branch_turnover:long_name = "turnover time of branches" ; + double fates_damage_canopy_layer_code ; + fates_damage_canopy_layer_code:units = "unitless" ; + fates_damage_canopy_layer_code:long_name = "Integer code that decides whether damage affects canopy trees (1), understory trees (2)" ; double fates_damage_event_code ; fates_damage_event_code:units = "unitless" ; fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; @@ -920,6 +923,8 @@ data: fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; + fates_damage_canopy_layer_code = 1 ; + fates_damage_event_code = 1 ; fates_damage_mort_p1 = 9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0 ; From ece0c714e7f2996dea4decd7cca178f74ea49762 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 26 May 2022 11:38:42 -0700 Subject: [PATCH 219/852] converting new procedures to CamelCase --- biogeochem/DamageMainMod.F90 | 50 +++++++++++----------- biogeochem/EDCohortDynamicsMod.F90 | 4 +- biogeochem/EDMortalityFunctionsMod.F90 | 4 +- biogeochem/EDPatchDynamicsMod.F90 | 24 +++++------ biogeochem/FatesAllometryMod.F90 | 18 ++++---- biogeophys/FatesPlantRespPhotosynthMod.F90 | 4 +- main/EDMainMod.F90 | 6 +-- main/FatesHistoryInterfaceMod.F90 | 2 +- parameter_files/fates_params_default.cdl | 2 +- 9 files changed, 57 insertions(+), 57 deletions(-) diff --git a/biogeochem/DamageMainMod.F90 b/biogeochem/DamageMainMod.F90 index 8e8748692f..1609edf64d 100644 --- a/biogeochem/DamageMainMod.F90 +++ b/biogeochem/DamageMainMod.F90 @@ -5,8 +5,8 @@ module DamageMainMod use FatesConstantsMod , only : itrue, ifalse use FatesConstantsMod , only : years_per_day use FatesGlobals , only : fates_log - use FatesGlobals , only : endrun => fates_endrun - use shr_log_mod , only : errMsg => shr_log_errMsg + use FatesGlobals , only : endrun => fates_endrun + use shr_log_mod , only : errMsg => shr_log_errMsg use EDPftvarcon , only : EDPftvarcon_inst use EDParamsMod , only : damage_event_code use EDtypesMod , only : ed_site_type @@ -34,16 +34,16 @@ module DamageMainMod implicit none private - logical, protected :: damage_time ! if true then damage occurs during current time step + logical, protected :: DamageTime ! if true then damage occurs during current time step character(len=*), parameter, private :: sourcefile = & __FILE__ - public :: get_crown_reduction - public :: get_damage_frac - public :: is_it_damage_time - public :: damage_time - public :: get_damage_mortality + public :: GetCrownReduction + public :: GetDamageFrac + public :: IsItDamageTime + public :: DamageTime + public :: GetDamageMortality logical :: debug = .false. ! for debugging @@ -53,7 +53,7 @@ module DamageMainMod contains - subroutine is_it_damage_time(is_master, currentSite) + subroutine IsItDamageTime(is_master, currentSite) !---------------------------------------------------------------------------- ! This subroutine determines whether damage should occur (it is called daily) @@ -72,36 +72,36 @@ subroutine is_it_damage_time(is_master, currentSite) character(len=64) :: fmt = '(a,i2.2,a,i2.2,a,i4.4)' - damage_time = .false. + DamageTime = .false. icode = int(damage_event_code) model_day_int = nint(hlm_model_day) if(icode .eq. 1) then ! Damage is turned off - damage_time = .false. + DamageTime = .false. else if(icode .eq. 2) then ! Damage event on first time step if(model_day_int .eq.1) then - damage_time = .true. + DamageTime = .true. end if else if(icode .eq. 3) then ! Damage event every day - not sure this is recommended as it will result in a very large ! number of cohorts - damage_time = .true. + DamageTime = .true. else if(icode .eq. 4) then ! Damage event once a month if(hlm_current_day.eq.1 ) then - damage_time = .true. + DamageTime = .true. end if else if(icode < 0 .and. icode > -366) then ! Damage event every year on a specific day of the year if(hlm_day_of_year .eq. abs(icode) ) then - damage_time = .true. + DamageTime = .true. end if else if(icode > 10000 ) then @@ -113,31 +113,31 @@ subroutine is_it_damage_time(is_master, currentSite) if(hlm_current_day .eq. damage_date .and. & hlm_current_month .eq. damage_month .and. & hlm_current_year .eq. damage_year ) then - damage_time = .true. + DamageTime = .true. end if else ! Bad damage event flag write(fates_log(),*) 'An invalid damage code was specified in fates_params' - write(fates_log(),*) 'Check DamageMainMod.F90:is_it_damage_time()' + write(fates_log(),*) 'Check DamageMainMod.F90:IsItDamageTime()' write(fates_log(),*) 'for a breakdown of the valide codes and change' write(fates_log(),*) 'fates_damage_event_code in the file accordingly.' write(fates_log(),*) 'exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if(damage_time .and. (is_master.eq.itrue) ) then + if(DamageTime .and. (is_master.eq.itrue) ) then write(fates_log(),fmt) 'Damage Event Enacted on date: ', & hlm_current_month,'-', hlm_current_day,'-',hlm_current_year end if return - end subroutine is_it_damage_time + end subroutine IsItDamageTime !---------------------------------------------------------------------------- - subroutine get_damage_frac(cc_cd, nc_cd, pft, dist_frac) + subroutine GetDamageFrac(cc_cd, nc_cd, pft, dist_frac) ! given current cohort damage class find the fraction of individuals @@ -160,11 +160,11 @@ subroutine get_damage_frac(cc_cd, nc_cd, pft, dist_frac) ! (if damage is occuring annually don't do this) - end subroutine get_damage_frac + end subroutine GetDamageFrac !------------------------------------------------------- - subroutine get_crown_reduction(crowndamage, crown_reduction) + subroutine GetCrownReduction(crowndamage, crown_reduction) !------------------------------------------------------------------ ! This function takes the crown damage class of a cohort (integer) @@ -185,13 +185,13 @@ subroutine get_crown_reduction(crowndamage, crown_reduction) crown_reduction = min(1.0_r8, (real(crowndamage) - 1.0_r8) * class_width) return - end subroutine get_crown_reduction + end subroutine GetCrownReduction !---------------------------------------------------------------------------------------- - subroutine get_damage_mortality(crowndamage,pft, dgmort) + subroutine GetDamageMortality(crowndamage,pft, dgmort) use FatesInterfaceTypesMod , only : nlevdamage use EDPftvarcon , only : EDPftvarcon_inst @@ -226,7 +226,7 @@ subroutine get_damage_mortality(crowndamage,pft, dgmort) end if return - end subroutine get_damage_mortality + end subroutine GetDamageMortality !---------------------------------------------------------------------------------------- diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 519b47e3bb..03ee146b3f 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -1081,7 +1081,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) use FatesConstantsMod , only : itrue use FatesConstantsMod, only : days_per_year use EDTypesMod , only : maxCohortsPerPatch - use DamageMainMod, only : get_crown_reduction + use DamageMainMod, only : GetCrownReduction ! ! !ARGUMENTS type (ed_site_type), intent(inout), target :: currentSite @@ -2084,7 +2084,7 @@ subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) ! consistent with stuctural biomass (or, in the case of grasses, leaf biomass) ! then correct (increase) the dbh to match that. ! ----------------------------------------------------------------------------------- - use DamageMainMod, only : get_crown_reduction + use DamageMainMod, only : GetCrownReduction ! argument type(ed_cohort_type),intent(inout) :: currentCohort diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index 69c7d5070a..13082cf910 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -59,7 +59,7 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmor use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm use FatesInterfaceTypesMod , only : hlm_hio_ignore_val use FatesConstantsMod, only : fates_check_param_set - use DamageMainMod, only : get_damage_mortality + use DamageMainMod, only : GetDamageMortality type (ed_cohort_type), intent(in) :: cohort_in type (bc_in_type), intent(in) :: bc_in @@ -123,7 +123,7 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmor ! Damage dependent mortality if (hlm_use_crown_damage .eq. itrue) then - call get_damage_mortality(cohort_in%crowndamage, cohort_in%pft, dgmort) + call GetDamageMortality(cohort_in%crowndamage, cohort_in%pft, dgmort) else dgmort = 0.0_r8 end if diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index da1b48cb2a..6fc1281434 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -62,7 +62,7 @@ module EDPatchDynamicsMod use EDLoggingMortalityMod, only : logging_time use EDLoggingMortalityMod, only : get_harvest_rate_area use EDParamsMod , only : fates_mortality_disturbance_fraction - use DamageMainMod , only : damage_time + use DamageMainMod , only : DamageTime use FatesAllometryMod , only : carea_allom use FatesAllometryMod , only : set_root_fraction use FatesConstantsMod , only : g_per_kg @@ -469,8 +469,8 @@ subroutine spawn_patches( currentSite, bc_in) use EDParamsMod , only : ED_val_understorey_death, logging_coll_under_frac use EDCohortDynamicsMod , only : zero_cohort, copy_cohort, terminate_cohorts use FatesConstantsMod , only : rsnbl_math_prec - use DamageMainMod , only : get_crown_reduction - use DamageMainMod , only : get_damage_frac + use DamageMainMod , only : GetCrownReduction + use DamageMainMod , only : GetDamageFrac use PRTLossFluxesMod , only : PRTDamageLosses use PRTGenericMod , only : leaf_organ use ChecksBalancesMod , only : SiteMassStock @@ -766,7 +766,7 @@ subroutine spawn_patches( currentSite, bc_in) ! and the damaged trees if(hlm_use_crown_damage .eq. itrue) then - if( damage_time ) then + if( DamageTime ) then call damage_litter_fluxes(currentSite, currentPatch, & new_patch, patch_site_areadis, patch_damage_litter) @@ -1259,7 +1259,7 @@ subroutine spawn_patches( currentSite, bc_in) ! Regardless of disturbance type, reduce mass of damaged trees if(hlm_use_crown_damage .eq. itrue) then - if(damage_time) then + if(DamageTime) then ! if woody if (prt_params%woody(currentCohort%pft)==1 ) then @@ -1272,7 +1272,7 @@ subroutine spawn_patches( currentSite, bc_in) ! for each damage class find the number density and if big enough allocate a new cohort do cd = currentCohort%crowndamage+1, nlevdamage - call get_damage_frac(currentCohort%crowndamage, cd, currentCohort%pft, cd_frac) + call GetDamageFrac(currentCohort%crowndamage, cd, currentCohort%pft, cd_frac) if(i_damage_code .eq. 1 .and. currentCohort%canopy_layer == 1) then cd_n = currentCohort%n * cd_frac @@ -1315,7 +1315,7 @@ subroutine spawn_patches( currentSite, bc_in) call carea_allom(nc_d%dbh, nc_d%n, currentSite%spread,& nc_d%pft, nc_d%crowndamage, nc_d%c_area) - call get_crown_reduction(nc_d%crowndamage, mass_frac) + call GetCrownReduction(nc_d%crowndamage, mass_frac) leaf_m_pre = nc_d%prt%GetState(leaf_organ, all_carbon_elements) + & @@ -1560,7 +1560,7 @@ subroutine spawn_patches( currentSite, bc_in) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if (damage_time) then + if (DamageTime) then write(fates_log(),*) 'Damage to litter: ',total_litter_d @@ -2383,8 +2383,8 @@ subroutine damage_litter_fluxes(currentSite, currentPatch, newPatch,patch_site_a ! !DESCRIPTION: ! ! !USES: - use DamageMainMod, only : get_crown_reduction - use DamageMainMod , only : get_damage_frac + use DamageMainMod, only : GetCrownReduction + use DamageMainMod , only : GetDamageFrac use SFParamsMod , only : SF_val_cwd_frac use FatesInterfaceTypesMod , only : nlevdamage use EDParamsMod , only : ED_val_understorey_death @@ -2528,7 +2528,7 @@ subroutine damage_litter_fluxes(currentSite, currentPatch, newPatch,patch_site_a do cd = currentCohort%crowndamage+1, nlevdamage - call get_damage_frac(currentCohort%crowndamage, cd, currentCohort%pft, cd_frac) + call GetDamageFrac(currentCohort%crowndamage, cd, currentCohort%pft, cd_frac) ! now to get the number of damaged trees we multiply by damage frac num_trees_cd = num_trees * cd_frac @@ -2538,7 +2538,7 @@ subroutine damage_litter_fluxes(currentSite, currentPatch, newPatch,patch_site_a ! if non negligable get litter if (num_trees_cd > nearzero ) then - call get_crown_reduction(cd, crown_reduction) + call GetCrownReduction(cd, crown_reduction) ! leaf loss in kg diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index 446312571d..7574950860 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -98,7 +98,7 @@ module FatesAllometryMod use FatesGlobals , only : FatesWarn,N2S,A2S,I2S use EDTypesMod , only : nlevleaf, dinc_vai use EDTypesMod , only : nclmax - use DamageMainMod , only : get_crown_reduction + use DamageMainMod , only : GetCrownReduction implicit none @@ -365,7 +365,7 @@ end subroutine h_allom subroutine bagw_allom(d,ipft,crowndamage, bagw,dbagwdd) - use DamageMainMod, only : get_crown_reduction + use DamageMainMod, only : GetCrownReduction use FatesParameterDerivedMod, only : param_derived real(r8),intent(in) :: d ! plant diameter [cm] @@ -407,7 +407,7 @@ subroutine bagw_allom(d,ipft,crowndamage, bagw,dbagwdd) end select if(crowndamage > 1) then - call get_crown_reduction(crowndamage, crown_reduction) + call GetCrownReduction(crowndamage, crown_reduction) bagw = bagw - (bagw * branch_frac * crown_reduction) if(present(dbagwdd))then dbagwdd = dbagwdd - (dbagwdd * branch_frac * crown_reduction) @@ -546,7 +546,7 @@ subroutine bleaf(d,ipft,crowndamage,canopy_trim,bl,dbldd) ! this routine is not name-spaced with allom_ ! ------------------------------------------------------------------------- - use DamageMainMod , only : get_crown_reduction + use DamageMainMod , only : GetCrownReduction real(r8),intent(in) :: d ! plant diameter [cm] integer(i4),intent(in) :: ipft ! PFT index @@ -577,7 +577,7 @@ subroutine bleaf(d,ipft,crowndamage,canopy_trim,bl,dbldd) if ( crowndamage > 1 ) then - call get_crown_reduction(crowndamage, crown_reduction) + call GetCrownReduction(crowndamage, crown_reduction) bl = bl * (1.0_r8 - crown_reduction) if(present(dbldd))then dbldd = dblmaxdd * canopy_trim * (1.0_r8 - crown_reduction) @@ -896,7 +896,7 @@ end function leafc_from_treelai subroutine bsap_allom(d,ipft,crowndamage,canopy_trim,sapw_area,bsap,dbsapdd) - use DamageMainMod , only : get_crown_reduction + use DamageMainMod , only : GetCrownReduction use FatesParameterDerivedMod, only : param_derived real(r8),intent(in) :: d ! plant diameter [cm] @@ -949,7 +949,7 @@ subroutine bsap_allom(d,ipft,crowndamage,canopy_trim,sapw_area,bsap,dbsapdd) ! fraction of biomass that would be in branches (pft specific) if(crowndamage > 1)then - call get_crown_reduction(crowndamage, crown_reduction) + call GetCrownReduction(crowndamage, crown_reduction) bsap = bsap - (bsap * agb_frac * branch_frac * crown_reduction) if(present(dbsapdd))then dbsapdd = dbsapdd - (dbsapdd * agb_frac * branch_frac * crown_reduction) @@ -2128,13 +2128,13 @@ subroutine carea_2pwr(dbh,spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max,c_area,inv c_area = spreadterm * dbh ** crown_area_to_dbh_exponent if(crowndamage > 1) then - call get_crown_reduction(crowndamage, crown_reduction) + call GetCrownReduction(crowndamage, crown_reduction) c_area = c_area * (1.0_r8 - crown_reduction) end if else if(crowndamage > 1) then - call get_crown_reduction(crowndamage, crown_reduction) + call GetCrownReduction(crowndamage, crown_reduction) c_area = c_area/(1.0_r8 - crown_reduction) end if dbh = (c_area / spreadterm) ** (1./crown_area_to_dbh_exponent) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 843866878d..27613cf355 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -139,7 +139,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) use FatesAllometryMod, only : set_root_fraction use FatesAllometryMod, only : decay_coeff_kn - use DamageMainMod, only : get_crown_reduction + use DamageMainMod, only : GetCrownReduction use FatesInterfaceTypesMod, only : hlm_use_crown_damage @@ -659,7 +659,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) agb_frac = prt_params%allom_agb_frac(currentCohort%pft) branch_frac = param_derived%branch_frac(currentCohort%pft) - call get_crown_reduction(currentCohort%crowndamage, crown_reduction) + call GetCrownReduction(currentCohort%crowndamage, crown_reduction) ! need the undamaged version if using ratios with roots sapw_c = sapw_c / & diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index d083f7fd1c..6bde3c2af7 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -81,7 +81,7 @@ module EDMainMod use FatesPlantHydraulicsMod , only : AccumulateMortalityWaterStorage use FatesAllometryMod , only : h_allom,tree_sai,tree_lai use EDLoggingMortalityMod , only : IsItLoggingTime - use DamageMainMod , only : is_it_damage_time + use DamageMainMod , only : IsItDamageTime use EDPatchDynamicsMod , only : get_frac_site_primary use FatesGlobals , only : endrun => fates_endrun use ChecksBalancesMod , only : SiteMassStock @@ -171,7 +171,7 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) call IsItLoggingTime(hlm_masterproc,currentSite) ! Call a routine that identifies if damage should occur - call is_it_damage_time(hlm_masterproc, currentSite) + call IsItDamageTime(hlm_masterproc, currentSite) !************************************************************************** ! Fire, growth, biogeochemistry. @@ -320,7 +320,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) use FatesInterfaceTypesMod, only : hlm_use_cohort_age_tracking use FatesConstantsMod, only : itrue use PRTGenericMod , only : all_carbon_elements - use DamageMainMod , only : damage_time + use DamageMainMod , only : DamageTime use EDCohortDynamicsMod , only : zero_cohort, copy_cohort, insert_cohort use EDCohortDynamicsMod , only : DeallocateCohort use FatesPlantHydraulicsMod, only : InitHydrCohort diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index c590dac7b6..deb4571b92 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -1839,7 +1839,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) use EDTypesMod , only : nlevleaf use EDParamsMod, only : ED_val_history_height_bin_edges use FatesInterfaceTypesMod, only : nlevdamage - use DamageMainMod , only : damage_time + use DamageMainMod , only : DamageTime ! Arguments class(fates_history_interface_type) :: this diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index fba1e186e6..c33d9683b3 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -165,7 +165,7 @@ variables: fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; double fates_damage_frac(fates_pft) ; fates_damage_frac:units = "fraction"; - fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)"; + fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the IsItDamageTime subroutine)"; double fates_damage_mort_p1(fates_pft) ; fates_damage_mort_p1:units = "fraction crown loss - a value of 0.8 means 50% mortality with 80% loss of crown"; fates_damage_mort_p1:long_name = "inflection point of damage mortality function - to turn off damage mortality set this to a large number" ; From f73d65d2dde128a99bb925d8dde63bae45653ca9 Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Thu, 26 May 2022 13:04:49 -0700 Subject: [PATCH 220/852] [ change damage bin edges ] [ remove upper bin edge of 100 ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary: no testing --- main/FatesInterfaceMod.F90 | 2 +- parameter_files/fates_params_default.cdl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 8a729c6bef..f33fa0c6a2 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -834,7 +834,7 @@ subroutine SetFatesGlobalElements(use_fates) nlevage = size(ED_val_history_ageclass_bin_edges,dim=1) nlevheight = size(ED_val_history_height_bin_edges,dim=1) nlevcoage = size(ED_val_history_coageclass_bin_edges,dim=1) - nlevdamage = size(ED_val_history_damage_bin_edges, dim=1) - 1 + nlevdamage = size(ED_val_history_damage_bin_edges, dim=1) ! do some checks on the size, age, and height bin arrays to make sure they make sense: ! make sure that all start at zero, and that both are monotonically increasing diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 7c9fefaf8f..161842b1b3 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -5,7 +5,7 @@ dimensions: fates_history_height_bins = 6 ; fates_history_size_bins = 13 ; fates_history_coage_bins = 2 ; - fates_history_damage_bins = 6 ; + fates_history_damage_bins = 2 ; fates_hydr_organs = 4 ; fates_leafage_class = 1 ; fates_litterclass = 6 ; @@ -786,7 +786,7 @@ data: fates_history_coageclass_bin_edges = 0, 5 ; - fates_history_damage_bin_edges = 0, 20, 40, 60, 80, 100 ; + fates_history_damage_bin_edges = 0, 80 ; fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; From 59d43572177341cbbf48f5779316338d3aa017a5 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 26 May 2022 13:48:27 -0700 Subject: [PATCH 221/852] converting logical from CamelCase back to original format --- biogeochem/DamageMainMod.F90 | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/biogeochem/DamageMainMod.F90 b/biogeochem/DamageMainMod.F90 index 1609edf64d..6ab8bcb66d 100644 --- a/biogeochem/DamageMainMod.F90 +++ b/biogeochem/DamageMainMod.F90 @@ -34,7 +34,7 @@ module DamageMainMod implicit none private - logical, protected :: DamageTime ! if true then damage occurs during current time step + logical, protected :: damage_time ! if true then damage occurs during current time step character(len=*), parameter, private :: sourcefile = & __FILE__ @@ -42,7 +42,7 @@ module DamageMainMod public :: GetCrownReduction public :: GetDamageFrac public :: IsItDamageTime - public :: DamageTime + public :: damage_time public :: GetDamageMortality logical :: debug = .false. ! for debugging @@ -72,36 +72,36 @@ subroutine IsItDamageTime(is_master, currentSite) character(len=64) :: fmt = '(a,i2.2,a,i2.2,a,i4.4)' - DamageTime = .false. + damage_time = .false. icode = int(damage_event_code) model_day_int = nint(hlm_model_day) if(icode .eq. 1) then ! Damage is turned off - DamageTime = .false. + damage_time = .false. else if(icode .eq. 2) then ! Damage event on first time step if(model_day_int .eq.1) then - DamageTime = .true. + damage_time = .true. end if else if(icode .eq. 3) then ! Damage event every day - not sure this is recommended as it will result in a very large ! number of cohorts - DamageTime = .true. + damage_time = .true. else if(icode .eq. 4) then ! Damage event once a month if(hlm_current_day.eq.1 ) then - DamageTime = .true. + damage_time = .true. end if else if(icode < 0 .and. icode > -366) then ! Damage event every year on a specific day of the year if(hlm_day_of_year .eq. abs(icode) ) then - DamageTime = .true. + damage_time = .true. end if else if(icode > 10000 ) then @@ -113,7 +113,7 @@ subroutine IsItDamageTime(is_master, currentSite) if(hlm_current_day .eq. damage_date .and. & hlm_current_month .eq. damage_month .and. & hlm_current_year .eq. damage_year ) then - DamageTime = .true. + damage_time = .true. end if else From 657ba0ab3ed4a5f2f5662c4593cae31dc9d14a1d Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 26 May 2022 13:51:33 -0700 Subject: [PATCH 222/852] adding target_c_area local to UpdateCohortLAI --- biogeochem/EDCanopyStructureMod.F90 | 4 ++-- biogeochem/EDCohortDynamicsMod.F90 | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index ec2a1a628e..e4a84db206 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1886,7 +1886,6 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) real(r8) :: total_canopy_area real(r8) :: total_patch_leaf_stem_area real(r8) :: weight ! Weighting for cohort variables in patch - real(r8) :: target_c_area do s = 1,nsites @@ -2249,7 +2248,8 @@ subroutine UpdateCohortLAI(currentCohort, canopy_layer_tlai, patcharea) ! Local variables real(r8) :: leaf_c ! leaf carbon [kg] - + real(r8) :: target_c_area + ! Obtain the leaf carbon leaf_c = currentCohort%prt%GetState(leaf_organ,all_carbon_elements) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 03ee146b3f..78328e2bdc 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -1111,7 +1111,6 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) real(r8) :: dynamic_age_fusion_tolerance real(r8) :: dbh real(r8) :: leaf_c ! leaf carbon [kg] - real(r8) :: target_c_area integer :: largersc, smallersc, sc_i ! indices for tracking the growth flux caused by fusion real(r8) :: larger_n, smaller_n From 735b33fe7f1f84e5193d5f22d4ab21fab5809526 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 27 May 2022 11:47:16 -0400 Subject: [PATCH 223/852] Addition of damage history dimensioning, and module flag --- main/EDParamsMod.F90 | 39 ++++++++++-- main/EDPftvarcon.F90 | 13 +++- main/FatesIODimensionsMod.F90 | 17 ++++++ main/FatesIOVariableKindMod.F90 | 3 + main/FatesInterfaceMod.F90 | 59 +++++++++++++++++-- main/FatesInterfaceTypesMod.F90 | 42 +++++++++---- main/FatesParametersInterface.F90 | 3 +- parameter_files/apichange_23to24.xml | 11 +++- .../fates_params_default_api24.cdl | 9 ++- 9 files changed, 167 insertions(+), 29 deletions(-) diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index b28ab877b8..209d48490b 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -86,7 +86,8 @@ module EDParamsMod real(r8),protected,allocatable,public :: ED_val_history_ageclass_bin_edges(:) real(r8),protected,allocatable,public :: ED_val_history_height_bin_edges(:) real(r8),protected,allocatable,public :: ED_val_history_coageclass_bin_edges(:) - + real(r8),protected,allocatable,public :: ED_val_history_damage_bin_edges(:) + ! Switch that defines the current pressure-volume and pressure-conductivity model ! to be used at each node (compartment/organ) ! 1 = Christofferson et al. 2016 (TFS), 2 = Van Genuchten 1980 @@ -131,6 +132,7 @@ module EDParamsMod character(len=param_string_length),parameter,public :: ED_name_history_ageclass_bin_edges= "fates_history_ageclass_bin_edges" character(len=param_string_length),parameter,public :: ED_name_history_height_bin_edges= "fates_history_height_bin_edges" 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) ! ---------------------------------------------------------------------------------------------- @@ -148,7 +150,7 @@ module EDParamsMod real(r8),protected,public :: hydr_psicap ! sapwood water potential at which capillary reserves exhausted (MPa) character(len=param_string_length),parameter,public :: hydr_name_psicap = "fates_hydro_psicap" - + ! Switch that defines which hydraulic solver to use ! 1 = Taylor solution that solves plant fluxes with 1 layer ! sequentially placing solution on top of previous layer solves @@ -171,7 +173,10 @@ module EDParamsMod ! Integer code that options how damage events are structured integer, protected, public :: damage_event_code - character(len=param_string_length), parameter, public :: damage_event_code_name = "fates_damage_event_code" + character(len=param_string_length), parameter, public :: damage_name_event_code = "fates_damage_event_code" + + integer,protected,public :: damage_canopy_layer_code ! Code that changes whether damage affects canopy trees (1), understory trees (2) + character(len=param_string_length),parameter,public :: damage_name_canopy_layer_code = "fates_damage_canopy_layer_code" ! Maximum allowable primary and secondary patches ! These values are USED FOR ALLOCATIONS IN BOTH FATES AND CLM/ELM!!!! @@ -304,6 +309,8 @@ subroutine FatesParamsInit() theta_cj_c3 = nan theta_cj_c4 = nan dev_arbitrary = nan + damage_event_code = -9 + damage_canopy_layer_code = -9 end subroutine FatesParamsInit !----------------------------------------------------------------------- @@ -315,7 +322,7 @@ subroutine FatesRegisterParams(fates_params) use FatesParametersInterface, only : fates_parameters_type, dimension_name_scalar, dimension_shape_1d use FatesParametersInterface, only : dimension_name_history_size_bins, dimension_name_history_age_bins use FatesParametersInterface, only : dimension_name_history_height_bins, dimension_name_hydr_organs - use FatesParametersInterface, only : dimension_name_history_coage_bins + use FatesParametersInterface, only : dimension_name_history_coage_bins, dimension_name_history_damage_bins use FatesParametersInterface, only : dimension_shape_scalar @@ -329,7 +336,8 @@ subroutine FatesRegisterParams(fates_params) character(len=param_string_length), parameter :: dim_names_height(1) = (/dimension_name_history_height_bins/) character(len=param_string_length), parameter :: dim_names_coageclass(1) = (/dimension_name_history_coage_bins/) character(len=param_string_length), parameter :: dim_names_hydro_organs(1) = (/dimension_name_hydr_organs/) - + character(len=param_string_length), parameter :: dim_names_damageclass(1)= (/dimension_name_history_damage_bins/) + call FatesParamsInit() call fates_params%RegisterParameter(name=ED_name_photo_temp_acclim_timescale, dimension_shape=dimension_shape_scalar, & @@ -484,6 +492,12 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=name_dev_arbitrary, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) + + call fates_params%RegisterParameter(name=damage_name_event_code, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + + call fates_params%RegisterParameter(name=damage_name_canopy_layer_code, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) ! non-scalar parameters @@ -508,6 +522,8 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=ED_name_history_coageclass_bin_edges, dimension_shape=dimension_shape_1d, & dimension_names=dim_names_coageclass) + call fates_params%RegisterParameter(name=ED_name_history_damage_bin_edges, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names_damageclass) end subroutine FatesRegisterParams @@ -694,6 +710,14 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetreiveParameter(name=fates_name_cg_strikes, & data=cg_strikes) + call fates_params%RetreiveParameter(name=damage_name_event_code, & + data=tmpreal) + damage_event_code = nint(tmpreal) + + call fates_params%RetreiveParameter(name=damage_name_canopy_layer_code, & + data=tmpreal) + damage_canopy_layer_code = nint(tmpreal) + ! parameters that are arrays of size defined within the params file and thus need allocating as well call fates_params%RetreiveParameterAllocate(name=ED_name_history_sizeclass_bin_edges, & data=ED_val_history_sizeclass_bin_edges) @@ -707,6 +731,9 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetreiveParameterAllocate(name=ED_name_history_coageclass_bin_edges, & data=ED_val_history_coageclass_bin_edges) + call fates_params%RetreiveParameterAllocate(name=ED_name_history_damage_bin_edges, & + data=ED_val_history_damage_bin_edges) + call fates_params%RetreiveParameterAllocate(name=ED_name_hydr_htftype_node, & data=hydr_htftype_real) allocate(hydr_htftype_node(size(hydr_htftype_real))) @@ -775,6 +802,8 @@ subroutine FatesReportParams(is_master) write(fates_log(),fmt0) 'q10_froz = ',q10_froz write(fates_log(),fmt0) 'cg_strikes = ',cg_strikes 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(),*) '------------------------------------------------------' end if diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index cbf9d2f42c..e6ee23e66a 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1474,8 +1474,9 @@ subroutine FatesCheckParams(is_master) ! ----------------------------------------------------------------------------------- use FatesConstantsMod , only : fates_check_param_set use FatesConstantsMod , only : itrue, ifalse - use EDParamsMod , only : logging_mechanical_frac, logging_collateral_frac, logging_direct_frac - use FatesInterfaceTypesMod , only : hlm_use_fixed_biogeog,hlm_use_sp + use EDParamsMod , only : logging_mechanical_frac, logging_collateral_frac + use EDParamsMod , only : logging_direct_frac,logging_export_frac + use FatesInterfaceTypesMod, only : hlm_use_fixed_biogeog,hlm_use_sp, hlm_name ! Argument logical, intent(in) :: is_master ! Only log if this is the master proc @@ -1576,6 +1577,14 @@ subroutine FatesCheckParams(is_master) call endrun(msg=errMsg(sourcefile, __LINE__)) endif + ! logging export turned off in CLM until the interface is included + if(logging_export_frac>nearzero .and. hlm_name .eq. 'CLM') then + write(fates_log(),*) 'The harvest to wood-product interface with CLM is not yet operational' + write(fates_log(),*) 'This feature is only available in ELM at the time being' + write(fates_log(),*) 'Please make sure the parameter fates_lu_logging_export_frac = 0' + call endrun(msg=errMsg(sourcefile, __LINE__)) + + ! Same for phosphorus if (any(EDPftvarcon_inst%prescribed_puptake(:) < -nearzero ) .or. & any(EDPftvarcon_inst%prescribed_puptake(:) > 10._r8 )) then diff --git a/main/FatesIODimensionsMod.F90 b/main/FatesIODimensionsMod.F90 index 6760bf0dbe..c8d4c17b85 100644 --- a/main/FatesIODimensionsMod.F90 +++ b/main/FatesIODimensionsMod.F90 @@ -27,6 +27,9 @@ module FatesIODimensionsMod character(*), parameter, public :: levcnlf = 'fates_levcnlf' ! matches histFileMod character(*), parameter, public :: levcnlfpft = 'fates_levcnlfpf' ! matches histFileMod character(*), parameter, public :: levagefuel = 'fates_levagefuel' ! matches histFileMod + character(*), parameter, public :: levcdsc = 'fates_levcdsc' ! matches histFileMod + character(*), parameter, public :: levcdpf = 'fates_levcdpf' ! matches histFileMod + character(*), parameter, public :: levcdam = 'fates_levcdam' ! matches histFileMod character(*), parameter, public :: levelem = 'fates_levelem' character(*), parameter, public :: levelpft = 'fates_levelpft' @@ -93,7 +96,15 @@ module FatesIODimensionsMod ! levelcwd = This records the boundaries for element x cwd ! levelage = This records the boundaries for element x age + ! levcdsc = This is a structure that records the boundaries for the + ! number of crown damage x size classes dimension + ! levcdpf = This is a structure that records the boundaries for the + ! number of crown damage x size classes x pft dimension + + ! levcdam = This is the structure that records the boundaries for the + ! number of crown damage classes dimension + type, public :: fates_bounds_type integer :: cohort_begin integer :: cohort_end @@ -131,6 +142,12 @@ module FatesIODimensionsMod integer :: cnlf_end integer :: cnlfpft_begin integer :: cnlfpft_end + integer :: cdsc_begin + integer :: cdsc_end + integer :: cdpf_begin + integer :: cdpf_end + integer :: cdam_begin + integer :: cdam_end integer :: elem_begin integer :: elem_end integer :: elpft_begin diff --git a/main/FatesIOVariableKindMod.F90 b/main/FatesIOVariableKindMod.F90 index 2d2dc4b716..853122730e 100644 --- a/main/FatesIOVariableKindMod.F90 +++ b/main/FatesIOVariableKindMod.F90 @@ -32,6 +32,9 @@ module FatesIOVariableKindMod character(*), parameter, public :: site_cwdsc_r8 = 'SI_CWDSC_R8' character(*), parameter, public :: site_can_r8 = 'SI_CAN_R8' character(*), parameter, public :: site_cnlf_r8 = 'SI_CNLF_R8' + character(*), parameter, public :: site_cdpf_r8 = 'SI_CDPF_R8' + character(*), parameter, public :: site_cdsc_r8 = 'SI_CDSC_R8' + character(*), parameter, public :: site_cdam_r8 = 'SI_CDAM_R8' character(*), parameter, public :: site_cnlfpft_r8 = 'SI_CNLFPFT_R8' character(*), parameter, public :: site_scag_r8 = 'SI_SCAG_R8' character(*), parameter, public :: site_scagpft_r8 = 'SI_SCAGPFT_R8' diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 927365356b..ed08cc5fc8 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -14,6 +14,7 @@ module FatesInterfaceMod use EDTypesMod , only : dlower_vai use EDParamsMod , only : ED_val_vai_top_bin_width use EDParamsMod , only : ED_val_vai_width_increase_factor + use EDParamsMod , only : ED_val_history_damage_bin_edges use EDParamsMod , only : maxpatch_total use EDParamsMod , only : maxpatch_primary use EDParamsMod , only : maxpatch_secondary @@ -373,6 +374,10 @@ subroutine zero_bcs(fates,s) end if fates%bc_out(s)%plant_stored_h2o_si = 0.0_r8 + + fates%bc_out(s)%hrv_deadstemc_to_prod10c = 0.0_r8 + fates%bc_out(s)%hrv_deadstemc_to_prod100c = 0.0_r8 + return end subroutine zero_bcs @@ -879,7 +884,8 @@ subroutine SetFatesGlobalElements2(use_fates) nlevage = size(ED_val_history_ageclass_bin_edges,dim=1) nlevheight = size(ED_val_history_height_bin_edges,dim=1) nlevcoage = size(ED_val_history_coageclass_bin_edges,dim=1) - + nlevdamage = size(ED_val_history_damage_bin_edges, dim=1) + ! do some checks on the size, age, and height bin arrays to make sure they make sense: ! make sure that all start at zero, and that both are monotonically increasing if ( ED_val_history_sizeclass_bin_edges(1) .ne. 0._r8 ) then @@ -1047,6 +1053,7 @@ subroutine fates_history_maps integer :: icwd integer :: ifuel integer :: ican + integer :: icdam integer :: ileaf integer :: iage integer :: iheight @@ -1090,14 +1097,21 @@ subroutine fates_history_maps allocate( fates_hdim_cwdmap_levelcwd(num_elements*ncwd)) allocate( fates_hdim_agemap_levelage(num_elements*nlevage)) - + allocate( fates_hdim_levdamage(1:nlevdamage )) + allocate( fates_hdim_scmap_levcdsc(nlevsclass*nlevdamage)) + allocate( fates_hdim_cdmap_levcdsc(nlevsclass*nlevdamage)) + allocate( fates_hdim_scmap_levcdpf(nlevsclass*nlevdamage * numpft)) + allocate( fates_hdim_cdmap_levcdpf(nlevsclass*nlevdamage * numpft)) + allocate( fates_hdim_pftmap_levcdpf(nlevsclass*nlevdamage * numpft)) + ! Fill the IO array of plant size classes fates_hdim_levsclass(:) = ED_val_history_sizeclass_bin_edges(:) fates_hdim_levage(:) = ED_val_history_ageclass_bin_edges(:) fates_hdim_levheight(:) = ED_val_history_height_bin_edges(:) fates_hdim_levcoage(:) = ED_val_history_coageclass_bin_edges(:) fates_hdim_levleaf(:) = dlower_vai(:) - + fates_hdim_levdamage(:) = ED_val_history_damage_bin_edges(:) + ! make pft array do ipft=1,numpft fates_hdim_levpft(ipft) = ipft @@ -1188,6 +1202,27 @@ subroutine fates_history_maps end do end do + i=0 + do icdam=1,nlevdamage + do isc=1,nlevsclass + i=i+1 + fates_hdim_scmap_levcdsc(i) = isc + fates_hdim_cdmap_levcdsc(i) = icdam + end do + end do + + i=0 + do ipft=1,numpft + do icdam=1,nlevdamage + do isc=1,nlevsclass + i=i+1 + fates_hdim_scmap_levcdpf(i) = isc + fates_hdim_cdmap_levcdpf(i) = icdam + fates_hdim_pftmap_levcdpf(i) = ipft + end do + end do + end do + i=0 do ipft=1,numpft do ican=1,nclmax @@ -1324,6 +1359,7 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) hlm_nu_com = 'unset' hlm_decomp = 'unset' hlm_nitrogen_spec = unset_int + hlm_use_tree_damage = unset_int hlm_phosphorus_spec = unset_int hlm_use_ch4 = unset_int hlm_use_vertsoilc = unset_int @@ -1494,7 +1530,16 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) write(fates_log(),*) 'FATES dimension/parameter unset: hlm_nu_com, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if - + + if(hlm_use_tree_damage .eq. unset_int .or. hlm_use_tree_damage .eq. itrue) then + write(fates_log(),*) 'FATES dimension/parameter unset: hlm_use_tree_damage, exiting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + if(hlm_use_tree_damage .eq. itrue) then + write(fates_log(),*) 'hlm_use_tree_damage is not available yet, value: ',hlm_use_tree_damage,' ,set to false' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if if(hlm_nitrogen_spec .eq. unset_int) then write(fates_log(),*) 'FATES parameters unset: hlm_nitrogen_spec, exiting' @@ -1645,6 +1690,12 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) write(fates_log(),*) 'Transfering hlm_ipedof = ',ival,' to FATES' end if + case('use_tree_damage') + hlm_use_tree_damage = ival + if (fates_global_verbose()) then + write(fates_log(),*) 'Transfering hlm_use_tree_damage = ',ival,' to FATES' + end if + case('nitrogen_spec') hlm_nitrogen_spec = ival if (fates_global_verbose()) then diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 8a68bef9d3..faea30da38 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -143,17 +143,21 @@ module FatesInterfaceTypesMod ! THIS IS CURRENTLY NOT SUPPORTED integer, public :: hlm_use_cohort_age_tracking ! This flag signals whether or not to use - ! cohort age tracking. 1 = TRUE, 0 = FALSE - - integer, public :: hlm_use_ed_st3 ! This flag signals whether or not to use - ! (ST)atic (ST)and (ST)ructure mode (ST3) - ! Essentially, this gives us the ability - ! to turn off "dynamics", ie growth, disturbance - ! recruitment and mortality. - ! (EXPERIMENTAL!!!!! - RGK 07-2017) - ! 1 = TRUE, 0 = FALSE - ! default should be FALSE (dynamics on) - ! cannot be true with prescribed_phys + ! cohort age tracking. 1 = TRUE, 0 = FALSE + + + integer, public :: hlm_use_tree_damage ! This flag signals whehter or not to turn on the + ! tree damage module + + integer, public :: hlm_use_ed_st3 ! This flag signals whether or not to use + ! (ST)atic (ST)and (ST)ructure mode (ST3) + ! Essentially, this gives us the ability + ! to turn off "dynamics", ie growth, disturbance + ! recruitment and mortality. + ! (EXPERIMENTAL!!!!! - RGK 07-2017) + ! 1 = TRUE, 0 = FALSE + ! default should be FALSE (dynamics on) + ! cannot be true with prescribed_phys integer, public :: hlm_use_ed_prescribed_phys ! This flag signals whether or not to use ! prescribed physiology, somewhat the opposite @@ -264,7 +268,14 @@ module FatesInterfaceTypesMod integer , public, allocatable :: fates_hdim_pftmap_levelpft(:) ! map of pfts in the element x pft dimension integer , public, allocatable :: fates_hdim_cwdmap_levelcwd(:) ! map of cwds in the element x cwd dimension integer , public, allocatable :: fates_hdim_agemap_levelage(:) ! map of ages in the element x age dimension - + + integer , public, allocatable :: fates_hdim_pftmap_levcdpf(:) ! map of pfts into size x crowndamage x pft dimension + integer , public, allocatable :: fates_hdim_cdmap_levcdpf(:) ! map of crowndamage into size x crowndamage x pft + integer , public, allocatable :: fates_hdim_scmap_levcdpf(:) ! map of size into size x crowndamage x pft + integer , public, allocatable :: fates_hdim_cdmap_levcdsc(:) ! map of crowndamage into size x crowndamage + integer , public, allocatable :: fates_hdim_scmap_levcdsc(:) ! map of size into size x crowndamage + integer , public, allocatable :: fates_hdim_levdamage(:) ! plant damage class lower bound dimension + ! ------------------------------------------------------------------------------------ ! DYNAMIC BOUNDARY CONDITIONS ! ------------------------------------------------------------------------------------ @@ -301,7 +312,8 @@ module FatesInterfaceTypesMod integer, public :: nlevheight ! The total number of height bins output to history integer, public :: nlevcoage ! The total number of cohort age bins output to history integer, public :: nleafage ! The total number of leaf age classes - + integer, public :: nlevdamage ! The total number of damage classes + ! ------------------------------------------------------------------------------------- ! Structured Boundary Conditions (SITE/PATCH SCALE) ! For floating point arrays, it is sometimes the convention to define the arrays as @@ -711,6 +723,10 @@ module FatesInterfaceTypesMod ! [mm H2O/s] + ! FATES LULCC + real(r8) :: hrv_deadstemc_to_prod10c ! Harvested C flux to 10-yr wood product pool [Site-Level, gC m-2 s-1] + real(r8) :: hrv_deadstemc_to_prod100c ! Harvested C flux to 100-yr wood product pool [Site-Level, gC m-2 s-1] + end type bc_out_type diff --git a/main/FatesParametersInterface.F90 b/main/FatesParametersInterface.F90 index 9000fc85bc..bbdac19be5 100644 --- a/main/FatesParametersInterface.F90 +++ b/main/FatesParametersInterface.F90 @@ -36,7 +36,8 @@ module FatesParametersInterface character(len=*), parameter, public :: dimension_name_history_height_bins = 'fates_history_height_bins' character(len=*), parameter, public :: dimension_name_history_coage_bins = 'fates_history_coage_bins' character(len=*), parameter, public :: dimension_name_hlm_pftno = 'fates_hlm_pftno' - character(len=*), parameter, public :: dimension_name_damage_bins = 'fates_history_damage_bins' + character(len=*), parameter, public :: dimension_name_history_damage_bins = 'fates_history_damage_bins' + character(len=*), parameter, public :: dimension_name_damage = 'fates_damage_class' ! Dimensions in the host namespace: character(len=*), parameter, public :: dimension_name_host_allpfts = 'allpfts' diff --git a/parameter_files/apichange_23to24.xml b/parameter_files/apichange_23to24.xml index 53440050d9..a634ecc212 100644 --- a/parameter_files/apichange_23to24.xml +++ b/parameter_files/apichange_23to24.xml @@ -19,7 +19,7 @@ fates_history_damage_bins - 3 + 2 fates_allom_crown_depth_frac @@ -44,7 +44,7 @@ fates_history_damage_bins % crown loss Lower edges for damage class bins used in cohort history output - 0, 80, 100 + 0, 80 fates_damage_frac @@ -538,6 +538,13 @@ Integer code that options how damage events are structured 1 + + fates_damage_canopy_layer_code + scalar + unitless + Integer code that decides whether damage affects canopy trees (1), understory trees (2) + 1 + fates_phen_gddthresh_a diff --git a/parameter_files/fates_params_default_api24.cdl b/parameter_files/fates_params_default_api24.cdl index 2aa81200e2..24494dcc37 100644 --- a/parameter_files/fates_params_default_api24.cdl +++ b/parameter_files/fates_params_default_api24.cdl @@ -3,7 +3,7 @@ dimensions: fates_NCWD = 4 ; fates_history_age_bins = 7 ; fates_history_coage_bins = 2 ; - fates_history_damage_bins = 3 ; + fates_history_damage_bins = 2 ; fates_history_height_bins = 6 ; fates_history_size_bins = 13 ; fates_hlm_pftno = 14 ; @@ -597,6 +597,9 @@ variables: double fates_comp_excln ; fates_comp_excln:units = "none" ; fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; + double fates_damage_canopy_layer_code ; + fates_damage_canopy_layer_code:units = "unitless" ; + fates_damage_canopy_layer_code:long_name = "Integer code that decides whether damage affects canopy trees (1), understory trees (2)" ; double fates_damage_event_code ; fates_damage_event_code:units = "unitless" ; fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; @@ -794,7 +797,7 @@ data: fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; - fates_history_damage_bin_edges = 0, 80, 100 ; + fates_history_damage_bin_edges = 0, 80 ; fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100 ; @@ -1407,6 +1410,8 @@ data: fates_comp_excln = 3 ; + fates_damage_canopy_layer_code = 1 ; + fates_damage_event_code = 1 ; fates_dev_arbitrary = _ ; From 64f6c719f94f28d9ab9138363dde2ee4f7124600 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 27 May 2022 13:19:45 -0400 Subject: [PATCH 224/852] Removing export frac check --- main/EDPftvarcon.F90 | 8 -------- 1 file changed, 8 deletions(-) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index e6ee23e66a..b2bd3fe2f3 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1577,14 +1577,6 @@ subroutine FatesCheckParams(is_master) call endrun(msg=errMsg(sourcefile, __LINE__)) endif - ! logging export turned off in CLM until the interface is included - if(logging_export_frac>nearzero .and. hlm_name .eq. 'CLM') then - write(fates_log(),*) 'The harvest to wood-product interface with CLM is not yet operational' - write(fates_log(),*) 'This feature is only available in ELM at the time being' - write(fates_log(),*) 'Please make sure the parameter fates_lu_logging_export_frac = 0' - call endrun(msg=errMsg(sourcefile, __LINE__)) - - ! Same for phosphorus if (any(EDPftvarcon_inst%prescribed_puptake(:) < -nearzero ) .or. & any(EDPftvarcon_inst%prescribed_puptake(:) > 10._r8 )) then From 401cb25cbbae54031162fb8c65e497f38c30aab9 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 27 May 2022 15:20:59 -0400 Subject: [PATCH 225/852] Minor syntax updates --- main/EDTypesMod.F90 | 4 ---- main/FatesInterfaceTypesMod.F90 | 2 +- parameter_files/apichange_23to24.xml | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 12915df7aa..3ca3764338 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -28,10 +28,6 @@ module EDTypesMod private ! By default everything is private save -! integer, parameter, public :: maxPatchesPerSite = 14 ! maximum number of patches to live on a site -! integer, parameter, public :: maxPatchesPerSite_by_disttype(n_anthro_disturbance_categories) = & -! (/ 10, 4 /) !!! MUST SUM TO maxPatchesPerSite !!! - integer, parameter, public :: nclmax = 2 ! Maximum number of canopy layers integer, parameter, public :: ican_upper = 1 ! Nominal index for the upper canopy integer, parameter, public :: ican_ustory = 2 ! Nominal index for diagnostics that refer diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index faea30da38..5df7fd7abf 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -146,7 +146,7 @@ module FatesInterfaceTypesMod ! cohort age tracking. 1 = TRUE, 0 = FALSE - integer, public :: hlm_use_tree_damage ! This flag signals whehter or not to turn on the + integer, public :: hlm_use_tree_damage ! This flag signals whether or not to turn on the ! tree damage module integer, public :: hlm_use_ed_st3 ! This flag signals whether or not to use diff --git a/parameter_files/apichange_23to24.xml b/parameter_files/apichange_23to24.xml index a634ecc212..4c9c7aced4 100644 --- a/parameter_files/apichange_23to24.xml +++ b/parameter_files/apichange_23to24.xml @@ -36,7 +36,7 @@ fates_hydro_solver scalar unitless - switch designating which numerical solver for plant hydraulics, 1 = 1D taylor, 2 = 2D Picard + switch designating which numerical solver for plant hydraulics, 1 = 1D taylor, 2 = 2D Picard, 3 = 2D Newton (deprecated) 1 From dbd00f4745c99708cb4af6ff0c28939eba5ce7b7 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 27 May 2022 15:29:02 -0400 Subject: [PATCH 226/852] Syntax changes, minor --- parteh/PRTParametersMod.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/parteh/PRTParametersMod.F90 b/parteh/PRTParametersMod.F90 index 40d19de50b..06704b7cfd 100644 --- a/parteh/PRTParametersMod.F90 +++ b/parteh/PRTParametersMod.F90 @@ -26,7 +26,6 @@ module PRTParametersMod ! one class to the next [yr] real(r8), allocatable :: root_long(:) ! root turnover time (longevity) (pft) [yr] real(r8), allocatable :: branch_long(:) ! Turnover time for branchfall on live trees (pft) [yr] - !real(r8), allocatable :: turnover_retrans_mode(:) ! Retranslocation method (pft) (NOT USED) real(r8), allocatable :: turnover_nitr_retrans(:,:) ! nitrogen re-translocation fraction (pft x organ) real(r8), allocatable :: turnover_phos_retrans(:,:) ! phosphorus re-translocation fraction (pft x organ) ! Parameters dimensioned by PFT and leaf age From cc2d5f88fb86c7631703e1b2218e19acc6170f41 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 27 May 2022 15:19:57 -0700 Subject: [PATCH 227/852] fixing erroneous damage_time name changes --- biogeochem/DamageMainMod.F90 | 2 +- biogeochem/EDPatchDynamicsMod.F90 | 8 ++++---- main/EDMainMod.F90 | 1 - main/FatesHistoryInterfaceMod.F90 | 1 - 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/biogeochem/DamageMainMod.F90 b/biogeochem/DamageMainMod.F90 index 6ab8bcb66d..2d0a94dc06 100644 --- a/biogeochem/DamageMainMod.F90 +++ b/biogeochem/DamageMainMod.F90 @@ -126,7 +126,7 @@ subroutine IsItDamageTime(is_master, currentSite) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if(DamageTime .and. (is_master.eq.itrue) ) then + if(damage_time .and. (is_master.eq.itrue) ) then write(fates_log(),fmt) 'Damage Event Enacted on date: ', & hlm_current_month,'-', hlm_current_day,'-',hlm_current_year end if diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 6fc1281434..5fca8b5d11 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -62,7 +62,7 @@ module EDPatchDynamicsMod use EDLoggingMortalityMod, only : logging_time use EDLoggingMortalityMod, only : get_harvest_rate_area use EDParamsMod , only : fates_mortality_disturbance_fraction - use DamageMainMod , only : DamageTime + use DamageMainMod , only : damage_time use FatesAllometryMod , only : carea_allom use FatesAllometryMod , only : set_root_fraction use FatesConstantsMod , only : g_per_kg @@ -766,7 +766,7 @@ subroutine spawn_patches( currentSite, bc_in) ! and the damaged trees if(hlm_use_crown_damage .eq. itrue) then - if( DamageTime ) then + if(damage_time) then call damage_litter_fluxes(currentSite, currentPatch, & new_patch, patch_site_areadis, patch_damage_litter) @@ -1259,7 +1259,7 @@ subroutine spawn_patches( currentSite, bc_in) ! Regardless of disturbance type, reduce mass of damaged trees if(hlm_use_crown_damage .eq. itrue) then - if(DamageTime) then + if(damage_time) then ! if woody if (prt_params%woody(currentCohort%pft)==1 ) then @@ -1560,7 +1560,7 @@ subroutine spawn_patches( currentSite, bc_in) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if (DamageTime) then + if (damage_time) then write(fates_log(),*) 'Damage to litter: ',total_litter_d diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 6bde3c2af7..06b4a3593d 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -320,7 +320,6 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) use FatesInterfaceTypesMod, only : hlm_use_cohort_age_tracking use FatesConstantsMod, only : itrue use PRTGenericMod , only : all_carbon_elements - use DamageMainMod , only : DamageTime use EDCohortDynamicsMod , only : zero_cohort, copy_cohort, insert_cohort use EDCohortDynamicsMod , only : DeallocateCohort use FatesPlantHydraulicsMod, only : InitHydrCohort diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index deb4571b92..3c76123408 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -1839,7 +1839,6 @@ subroutine update_history_dyn(this,nc,nsites,sites) use EDTypesMod , only : nlevleaf use EDParamsMod, only : ED_val_history_height_bin_edges use FatesInterfaceTypesMod, only : nlevdamage - use DamageMainMod , only : DamageTime ! Arguments class(fates_history_interface_type) :: this From 6b21b533ef9bee1942658d14a6a437b6afd1fb35 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 27 May 2022 15:26:35 -0700 Subject: [PATCH 228/852] fixing bad merge --- biogeochem/EDMortalityFunctionsMod.F90 | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index 13082cf910..a7df37e5df 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -178,6 +178,7 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmor else write(fates_log(),*) 'dbh problem in mortality_rates', & cohort_in%dbh,cohort_in%pft,cohort_in%n,cohort_in%canopy_layer + call endrun(msg=errMsg(sourcefile, __LINE__)) endif !-------------------------------------------------------------------------------- ! Mortality due to cold and freezing stress (frmort), based on ED2 and: @@ -186,18 +187,6 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmor ! Eastern US carbon sink. Glob. Change Biol., 12, 2370-2390, ! doi: 10.1111/j.1365-2486.2006.01254.x - else - write(fates_log(),*) 'dbh problem in mortality_rates', & - cohort_in%dbh,cohort_in%pft,cohort_in%n,cohort_in%canopy_layer - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - !-------------------------------------------------------------------------------- - ! Mortality due to cold and freezing stress (frmort), based on ED2 and: - ! Albani, M.; D. Medvigy; G. C. Hurtt; P. R. Moorcroft, 2006: The contributions - ! of land-use change, CO2 fertilization, and climate variability to the - ! Eastern US carbon sink. Glob. Change Biol., 12, 2370-2390, - ! doi: 10.1111/j.1365-2486.2006.01254.x - temp_in_C = cohort_in%patchptr%tveg24%GetMean() - tfrz temp_dep_fraction = max(0.0_r8, min(1.0_r8, 1.0_r8 - (temp_in_C - & From a76d62f91edcffdcfa0bd3f57c4ed263a4da3ad5 Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Fri, 27 May 2022 15:28:42 -0700 Subject: [PATCH 229/852] [ update UpdateCohortLAI to accommodate extra arguments needed for damage ] [ site%spread needed in calculating target_carea for trees that are damaged ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary:no testing --- biogeochem/DamageMainMod.F90 | 2 +- biogeochem/EDCanopyStructureMod.F90 | 24 ++++++++++++++---------- biogeochem/EDMortalityFunctionsMod.F90 | 22 ++++++---------------- biogeochem/EDPatchDynamicsMod.F90 | 8 ++++---- main/EDMainMod.F90 | 2 +- main/FatesHistoryInterfaceMod.F90 | 2 +- 6 files changed, 27 insertions(+), 33 deletions(-) diff --git a/biogeochem/DamageMainMod.F90 b/biogeochem/DamageMainMod.F90 index 6ab8bcb66d..2d0a94dc06 100644 --- a/biogeochem/DamageMainMod.F90 +++ b/biogeochem/DamageMainMod.F90 @@ -126,7 +126,7 @@ subroutine IsItDamageTime(is_master, currentSite) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if(DamageTime .and. (is_master.eq.itrue) ) then + if(damage_time .and. (is_master.eq.itrue) ) then write(fates_log(),fmt) 'Damage Event Enacted on date: ', & hlm_current_month,'-', hlm_current_day,'-',hlm_current_year end if diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index e4a84db206..662b75c65d 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1547,7 +1547,7 @@ subroutine leaf_area_profile( currentSite ) if (currentPatch%total_canopy_area > nearzero ) then - call UpdatePatchLAI(currentPatch, patch_lai) + call UpdatePatchLAI(currentPatch, patch_lai, CurrentSite) if(smooth_leaf_distribution == 1)then @@ -2181,7 +2181,7 @@ end subroutine CanopyLayerArea ! =============================================================================================== - subroutine UpdatePatchLAI(currentPatch, patch_lai) + subroutine UpdatePatchLAI(currentPatch, patch_lai, currentSite) ! -------------------------------------------------------------------------------------------- ! This subroutine works through the current patch cohorts and updates the canopy_layer_tlai @@ -2193,6 +2193,7 @@ subroutine UpdatePatchLAI(currentPatch, patch_lai) ! Arguments type(ed_patch_type),intent(inout), target :: currentPatch + type(ed_site_type),intent(inout), target :: currentSite real(r8), intent(inout) :: patch_lai ! Local Variables @@ -2215,7 +2216,8 @@ subroutine UpdatePatchLAI(currentPatch, patch_lai) ft = currentCohort%pft ! Update the cohort level lai and related variables - call UpdateCohortLAI(currentCohort,currentPatch%canopy_layer_tlai,currentPatch%total_canopy_area) + call UpdateCohortLAI(currentCohort,currentPatch%canopy_layer_tlai, & + currentPatch%total_canopy_area, currentSite%spread) ! Update the number of number of vegetation layers currentPatch%ncan(cl,ft) = max(currentPatch%ncan(cl,ft),currentCohort%NV) @@ -2234,7 +2236,7 @@ subroutine UpdatePatchLAI(currentPatch, patch_lai) end subroutine UpdatePatchLAI ! =============================================================================================== - subroutine UpdateCohortLAI(currentCohort, canopy_layer_tlai, patcharea) + subroutine UpdateCohortLAI(currentCohort, canopy_layer_tlai, patcharea, spread) ! Update LAI and related variables for a given cohort @@ -2245,26 +2247,28 @@ subroutine UpdateCohortLAI(currentCohort, canopy_layer_tlai, patcharea) type(ed_cohort_type),intent(inout), target :: currentCohort real(r8), intent(in) :: canopy_layer_tlai(nclmax) ! total leaf area index of each canopy layer real(r8), intent(in) :: patcharea ! either patch%total_canopy_area or patch%area - + real(r8), intent(in) :: spread ! currentSite%spread + ! Local variables real(r8) :: leaf_c ! leaf carbon [kg] - real(r8) :: target_c_area + real(r8) :: target_c_area ! target c_area - as if not damaged ! Obtain the leaf carbon leaf_c = currentCohort%prt%GetState(leaf_organ,all_carbon_elements) + ! Note that tree_lai has an internal check on the canopy locatoin currentCohort%treelai = tree_lai(leaf_c, currentCohort%pft, currentCohort%c_area, & currentCohort%n, currentCohort%canopy_layer, & canopy_layer_tlai,currentCohort%vcmax25top ) - call carea_allom(currentCohort%dbh, currentCohort%n, currentSite%spread, currentCohort%pft, & - 1, target_c_area) - + call carea_allom(currentCohort%dbh, currentCohort%n, spread, currentCohort%pft, & + 1, target_c_area) + if (hlm_use_sp .eq. ifalse) then currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_trim, & target_c_area, currentCohort%n, currentCohort%canopy_layer, & - currentPatch%canopy_layer_tlai, currentCohort%treelai , & + canopy_layer_tlai, currentCohort%treelai , & currentCohort%vcmax25top,4) end if diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index 13082cf910..6b006d90e9 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -175,22 +175,12 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmor cmort = 0.0_r8 endif + else write(fates_log(),*) 'dbh problem in mortality_rates', & cohort_in%dbh,cohort_in%pft,cohort_in%n,cohort_in%canopy_layer + call endrun(msg=errMsg(sourcefile, __LINE__)) endif - !-------------------------------------------------------------------------------- - ! Mortality due to cold and freezing stress (frmort), based on ED2 and: - ! Albani, M.; D. Medvigy; G. C. Hurtt; P. R. Moorcroft, 2006: The contributions - ! of land-use change, CO2 fertilization, and climate variability to the - ! Eastern US carbon sink. Glob. Change Biol., 12, 2370-2390, - ! doi: 10.1111/j.1365-2486.2006.01254.x - - else - write(fates_log(),*) 'dbh problem in mortality_rates', & - cohort_in%dbh,cohort_in%pft,cohort_in%n,cohort_in%canopy_layer - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif !-------------------------------------------------------------------------------- ! Mortality due to cold and freezing stress (frmort), based on ED2 and: ! Albani, M.; D. Medvigy; G. C. Hurtt; P. R. Moorcroft, 2006: The contributions @@ -198,11 +188,11 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmor ! Eastern US carbon sink. Glob. Change Biol., 12, 2370-2390, ! doi: 10.1111/j.1365-2486.2006.01254.x - temp_in_C = cohort_in%patchptr%tveg24%GetMean() - tfrz + temp_in_C = cohort_in%patchptr%tveg24%GetMean() - tfrz - temp_dep_fraction = max(0.0_r8, min(1.0_r8, 1.0_r8 - (temp_in_C - & - EDPftvarcon_inst%freezetol(cohort_in%pft))/frost_mort_buffer) ) - frmort = EDPftvarcon_inst%mort_scalar_coldstress(cohort_in%pft) * temp_dep_fraction + temp_dep_fraction = max(0.0_r8, min(1.0_r8, 1.0_r8 - (temp_in_C - & + EDPftvarcon_inst%freezetol(cohort_in%pft))/frost_mort_buffer) ) + frmort = EDPftvarcon_inst%mort_scalar_coldstress(cohort_in%pft) * temp_dep_fraction !mortality_rates = bmort + hmort + cmort diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 6fc1281434..5e38a3ab0d 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -62,7 +62,7 @@ module EDPatchDynamicsMod use EDLoggingMortalityMod, only : logging_time use EDLoggingMortalityMod, only : get_harvest_rate_area use EDParamsMod , only : fates_mortality_disturbance_fraction - use DamageMainMod , only : DamageTime + use DamageMainMod , only : damage_time use FatesAllometryMod , only : carea_allom use FatesAllometryMod , only : set_root_fraction use FatesConstantsMod , only : g_per_kg @@ -766,7 +766,7 @@ subroutine spawn_patches( currentSite, bc_in) ! and the damaged trees if(hlm_use_crown_damage .eq. itrue) then - if( DamageTime ) then + if( damage_time ) then call damage_litter_fluxes(currentSite, currentPatch, & new_patch, patch_site_areadis, patch_damage_litter) @@ -1259,7 +1259,7 @@ subroutine spawn_patches( currentSite, bc_in) ! Regardless of disturbance type, reduce mass of damaged trees if(hlm_use_crown_damage .eq. itrue) then - if(DamageTime) then + if(damage_time) then ! if woody if (prt_params%woody(currentCohort%pft)==1 ) then @@ -1560,7 +1560,7 @@ subroutine spawn_patches( currentSite, bc_in) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if (DamageTime) then + if (damage_time) then write(fates_log(),*) 'Damage to litter: ',total_litter_d diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 6bde3c2af7..5ee8372873 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -320,7 +320,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) use FatesInterfaceTypesMod, only : hlm_use_cohort_age_tracking use FatesConstantsMod, only : itrue use PRTGenericMod , only : all_carbon_elements - use DamageMainMod , only : DamageTime + use DamageMainMod , only : damage_time use EDCohortDynamicsMod , only : zero_cohort, copy_cohort, insert_cohort use EDCohortDynamicsMod , only : DeallocateCohort use FatesPlantHydraulicsMod, only : InitHydrCohort diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index deb4571b92..c590dac7b6 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -1839,7 +1839,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) use EDTypesMod , only : nlevleaf use EDParamsMod, only : ED_val_history_height_bin_edges use FatesInterfaceTypesMod, only : nlevdamage - use DamageMainMod , only : DamageTime + use DamageMainMod , only : damage_time ! Arguments class(fates_history_interface_type) :: this From 8040e3c53875853ff159587434a4db7dd0bef3dc Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 31 May 2022 10:23:17 -0700 Subject: [PATCH 230/852] first cut at updated tveg calculation --- main/FatesHistoryInterfaceMod.F90 | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index d3f7bcfae1..89ee555a9a 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -3584,11 +3584,31 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) hio_hr_si(io_si) = bc_in(s)%tot_het_resp / g_per_kg ipa = 0 - cpatch => sites(s)%oldest_patch - + patch_area_by_age(1:nlevage) = 0._r8 canopy_area_by_age(1:nlevage) = 0._r8 + site_area_veg = 0._r8 + + ! Calculate the site-level total vegetated area (i.e. non-bareground) + cpatch => sites(s)%oldest_patch + do while(associated(cpatch)) + if (nocomp_pft_label .ne. 0) then + site_area_veg = site_area_veg + cpatch%area + endif + cpatch => cpatch%younger + end do + ! Only calculate the instantaneous vegetation temperature for vegetated sites + cpatch => sites(s)%oldest_patch + do while(associated(cpatch)) + if (nocomp_pft_label .ne. 0) then + hio_tveg(io_si) = hio_tveg(io_si) + & + (bc_in(s)%t_veg_pa(cpatch%patchno) - t_water_freeze_k_1atm) * cpatch%area / site_area_veg + end if + cpatch => cpatch%younger + end do + + cpatch => sites(s)%oldest_patch do while(associated(cpatch)) patch_area_by_age(cpatch%age_class) = & @@ -3615,9 +3635,6 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) hio_rad_error_si(io_si) = hio_rad_error_si(io_si) + & cpatch%radiation_error * cpatch%area * AREA_INV - hio_tveg(io_si) = hio_tveg(io_si) + & - (bc_in(s)%t_veg_pa(cpatch%patchno) - t_water_freeze_k_1atm)*cpatch%area*area_inv - ccohort => cpatch%shortest do while(associated(ccohort)) From bf34299c3ff998cffb413154b79ce9f20ecb18d3 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 31 May 2022 10:49:57 -0700 Subject: [PATCH 231/852] updating with simpler version --- main/FatesHistoryInterfaceMod.F90 | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 89ee555a9a..07a65666ed 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -3488,8 +3488,9 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) real(r8) :: npp ! npp for this time-step (adjusted for g resp) [kgC/indiv/step] real(r8) :: aresp ! autotrophic respiration (adjusted for g resp) [kgC/indiv/step] real(r8) :: n_perm2 ! individuals per m2 for the whole column - real(r8) :: patch_area_by_age(nlevage) ! patch area in each bin for normalizing purposes + real(r8) :: patch_area_by_age(nlevage) ! patch area in each bin for normalizing purposes real(r8) :: canopy_area_by_age(nlevage) ! canopy area in each bin for normalizing purposes + real(r8) :: site_area_veg ! area of the site that is not bare-ground real(r8), parameter :: tiny = 1.e-5_r8 ! some small number integer :: ipa2 ! patch incrementer integer :: cnlfpft_indx, cnlf_indx, ipft, ican, ileaf ! more iterators and indices @@ -3587,27 +3588,17 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) patch_area_by_age(1:nlevage) = 0._r8 canopy_area_by_age(1:nlevage) = 0._r8 - site_area_veg = 0._r8 + site_area_veg = area ! Calculate the site-level total vegetated area (i.e. non-bareground) cpatch => sites(s)%oldest_patch do while(associated(cpatch)) - if (nocomp_pft_label .ne. 0) then - site_area_veg = site_area_veg + cpatch%area + if (nocomp_pft_label .eq. 0) then + site_area_veg = site_area_veg - cpatch%area endif cpatch => cpatch%younger end do - ! Only calculate the instantaneous vegetation temperature for vegetated sites - cpatch => sites(s)%oldest_patch - do while(associated(cpatch)) - if (nocomp_pft_label .ne. 0) then - hio_tveg(io_si) = hio_tveg(io_si) + & - (bc_in(s)%t_veg_pa(cpatch%patchno) - t_water_freeze_k_1atm) * cpatch%area / site_area_veg - end if - cpatch => cpatch%younger - end do - cpatch => sites(s)%oldest_patch do while(associated(cpatch)) @@ -3634,6 +3625,12 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) hio_rad_error_si(io_si) = hio_rad_error_si(io_si) + & cpatch%radiation_error * cpatch%area * AREA_INV + + ! Only accumulate the instantaneous vegetation temperature for vegetated patches + if (nocomp_pft_label .ne. 0) then + hio_tveg(io_si) = hio_tveg(io_si) + & + (bc_in(s)%t_veg_pa(cpatch%patchno) - t_water_freeze_k_1atm) * cpatch%area / site_area_veg + end if ccohort => cpatch%shortest do while(associated(ccohort)) From d597f4117c4bbae5fc22fd5dcb9bc2a091573219 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 31 May 2022 10:56:32 -0700 Subject: [PATCH 232/852] fixed missing type call --- main/FatesHistoryInterfaceMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 07a65666ed..bb511461cf 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -3593,7 +3593,7 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) ! Calculate the site-level total vegetated area (i.e. non-bareground) cpatch => sites(s)%oldest_patch do while(associated(cpatch)) - if (nocomp_pft_label .eq. 0) then + if (cpatch%nocomp_pft_label .eq. 0) then site_area_veg = site_area_veg - cpatch%area endif cpatch => cpatch%younger @@ -3627,7 +3627,7 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) cpatch%radiation_error * cpatch%area * AREA_INV ! Only accumulate the instantaneous vegetation temperature for vegetated patches - if (nocomp_pft_label .ne. 0) then + if (cpatch%nocomp_pft_label .ne. 0) then hio_tveg(io_si) = hio_tveg(io_si) + & (bc_in(s)%t_veg_pa(cpatch%patchno) - t_water_freeze_k_1atm) * cpatch%area / site_area_veg end if From 8c85f902285fa1923ffc23454dd226a75883d9bb Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 31 May 2022 13:53:00 -0600 Subject: [PATCH 233/852] Removing stoich_p2 variables --- biogeochem/EDCanopyStructureMod.F90 | 6 ++-- biogeochem/EDPhysiologyMod.F90 | 48 ++++++++++++++--------------- main/EDInitMod.F90 | 20 ++++++------ main/FatesInterfaceMod.F90 | 11 ++++--- main/FatesInventoryInitMod.F90 | 42 ++++++++++--------------- parteh/PRTAllometricCNPMod.F90 | 40 ++++++++++++++---------- parteh/PRTParametersMod.F90 | 4 +-- 7 files changed, 87 insertions(+), 84 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 75d23f9985..649b96c1e5 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1810,8 +1810,8 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) c = fcolumn(s) do while(associated(currentPatch)) - if(currentPatch%nocomp_pft_label.ne.0)then ! ignore the bare-ground-PFT patch entirely for these BC outs - + if_nocomp_notbare: if(currentPatch%nocomp_pft_label.ne.0)then ! ignore the bare-ground-PFT patch entirely for these BC outs + ifp = ifp+1 if ( currentPatch%total_canopy_area-currentPatch%area > 0.000001_r8 ) then @@ -1931,7 +1931,7 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) total_patch_area = total_patch_area + currentPatch%area/AREA - end if + end if if_nocomp_notbare currentPatch => currentPatch%younger end do diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 3a8a939bb1..ff0d171466 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1941,28 +1941,28 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) case(nitrogen_element) mass_demand = & - c_struct*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(struct_organ)) + & - c_leaf*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)) + & - c_fnrt*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)) + & - c_sapw*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)) + & + c_struct*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(struct_organ)) + & + c_leaf*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)) + & + c_fnrt*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)) + & + c_sapw*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) + & StorageNutrientTarget(ft, element_id, & - c_leaf*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)), & - c_fnrt*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)), & - c_sapw*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)), & - c_struct*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(struct_organ))) + c_leaf*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)), & + c_fnrt*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)), & + c_sapw*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)), & + c_struct*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(struct_organ))) case(phosphorus_element) mass_demand = & - c_struct*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(struct_organ)) + & - c_leaf*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)) + & - c_fnrt*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)) + & - c_sapw*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)) + & + c_struct*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(struct_organ)) + & + c_leaf*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)) + & + c_fnrt*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)) + & + c_sapw*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) + & StorageNutrientTarget(ft, element_id, & - c_leaf*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)), & - c_fnrt*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)), & - c_sapw*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)), & - c_struct*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(struct_organ))) + c_leaf*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)), & + c_fnrt*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)), & + c_sapw*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)), & + c_struct*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(struct_organ))) case default write(fates_log(),*) 'Undefined element type in recruitment' @@ -2016,19 +2016,19 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) case(nitrogen_element) - m_struct = c_struct*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(struct_organ)) - m_leaf = c_leaf*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)) - m_fnrt = c_fnrt*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)) - m_sapw = c_sapw*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)) + m_struct = c_struct*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(struct_organ)) + m_leaf = c_leaf*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)) + m_fnrt = c_fnrt*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)) + m_sapw = c_sapw*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) m_store = StorageNutrientTarget(ft, element_id, m_leaf, m_fnrt, m_sapw, m_struct ) m_repro = 0._r8 case(phosphorus_element) - m_struct = c_struct*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(struct_organ)) - m_leaf = c_leaf*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)) - m_fnrt = c_fnrt*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)) - m_sapw = c_sapw*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)) + m_struct = c_struct*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(struct_organ)) + m_leaf = c_leaf*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)) + m_fnrt = c_fnrt*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)) + m_sapw = c_sapw*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) m_store = StorageNutrientTarget(ft, element_id, m_leaf, m_fnrt, m_sapw, m_struct ) m_repro = 0._r8 diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index d129e8567e..4d4bb27dbb 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -377,7 +377,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) end do !ft else ! for sp and nocomp mode, assert a bare ground patch if needed sumarea = sum(sites(s)%area_pft(1:numpft)) - + ! In all the other FATES modes, bareground is the area in which plants ! do not grow of their own accord. In SP mode we assert that the canopy is full for ! each PFT patch. Thus, we also need to assert a bare ground area in @@ -397,6 +397,8 @@ subroutine set_site_properties( nsites, sites,bc_in ) end if !fixed biogeog do ft = 1,numpft + ! Setting this to true ensures that all pfts + ! are used for nocomp with no biogeog sites(s)%use_this_pft(ft) = itrue if(hlm_use_fixed_biogeog.eq.itrue)then if(sites(s)%area_pft(ft).gt.0.0_r8)then @@ -850,19 +852,19 @@ subroutine init_cohorts( site_in, patch_in, bc_in) case(nitrogen_element) - m_struct = c_struct*prt_params%nitr_stoich_p2(pft,prt_params%organ_param_id(struct_organ)) - m_leaf = c_leaf*prt_params%nitr_stoich_p2(pft,prt_params%organ_param_id(leaf_organ)) - m_fnrt = c_fnrt*prt_params%nitr_stoich_p2(pft,prt_params%organ_param_id(fnrt_organ)) - m_sapw = c_sapw*prt_params%nitr_stoich_p2(pft,prt_params%organ_param_id(sapw_organ)) + m_struct = c_struct*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(struct_organ)) + m_leaf = c_leaf*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(leaf_organ)) + m_fnrt = c_fnrt*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(fnrt_organ)) + m_sapw = c_sapw*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(sapw_organ)) m_repro = 0._r8 m_store = StorageNutrientTarget(pft,element_id,m_leaf,m_fnrt,m_sapw,m_struct) case(phosphorus_element) - m_struct = c_struct*prt_params%phos_stoich_p2(pft,prt_params%organ_param_id(struct_organ)) - m_leaf = c_leaf*prt_params%phos_stoich_p2(pft,prt_params%organ_param_id(leaf_organ)) - m_fnrt = c_fnrt*prt_params%phos_stoich_p2(pft,prt_params%organ_param_id(fnrt_organ)) - m_sapw = c_sapw*prt_params%phos_stoich_p2(pft,prt_params%organ_param_id(sapw_organ)) + m_struct = c_struct*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(struct_organ)) + m_leaf = c_leaf*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(leaf_organ)) + m_fnrt = c_fnrt*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(fnrt_organ)) + m_sapw = c_sapw*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(sapw_organ)) m_repro = 0._r8 m_store = StorageNutrientTarget(pft,element_id,m_leaf,m_fnrt,m_sapw,m_struct) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index ed08cc5fc8..9b72b0332b 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -775,10 +775,13 @@ subroutine SetFatesGlobalElements1(use_fates,surf_numpft,surf_numcft) ! and that value will match fates_maxPatchesPerSite if(hlm_use_nocomp==itrue) then - if(maxpatch_primary Date: Tue, 31 May 2022 17:06:40 -0400 Subject: [PATCH 234/852] Small adjustments to parameter update pr, including setting secondary patches to 4 in the xml update file. --- parameter_files/apichange_23to24.xml | 4 ++-- parameter_files/fates_params_default_api24.cdl | 6 +++--- parteh/PRTParametersMod.F90 | 2 -- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/parameter_files/apichange_23to24.xml b/parameter_files/apichange_23to24.xml index 4c9c7aced4..0bddd6940d 100644 --- a/parameter_files/apichange_23to24.xml +++ b/parameter_files/apichange_23to24.xml @@ -86,7 +86,7 @@ scalar count maximum number of secondary vegetation patches per site - 1 + 4 @@ -153,7 +153,7 @@ fates_plant_organs, fates_pft index Priority level for allocation, 1: replaces turnover from storage, 2: same priority as storage use/replacement, 3: ascending in order of least importance - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 fates_alloc_organ_name diff --git a/parameter_files/fates_params_default_api24.cdl b/parameter_files/fates_params_default_api24.cdl index 24494dcc37..b45f3249ef 100644 --- a/parameter_files/fates_params_default_api24.cdl +++ b/parameter_files/fates_params_default_api24.cdl @@ -668,7 +668,7 @@ variables: fates_hydro_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; 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" ; + 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_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" ; @@ -842,7 +842,7 @@ data: fates_alloc_organ_priority = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; @@ -1496,7 +1496,7 @@ data: fates_maxpatch_primary = 10 ; - fates_maxpatch_secondary = 1 ; + fates_maxpatch_secondary = 4 ; fates_mort_disturb_frac = 1 ; diff --git a/parteh/PRTParametersMod.F90 b/parteh/PRTParametersMod.F90 index 06704b7cfd..f5895ef56a 100644 --- a/parteh/PRTParametersMod.F90 +++ b/parteh/PRTParametersMod.F90 @@ -44,9 +44,7 @@ module PRTParametersMod ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! real(r8), allocatable :: nitr_stoich_p1(:,:) ! Parameter 1 for nitrogen stoichiometry (pft x organ) - real(r8), allocatable :: nitr_stoich_p2(:,:) ! Parameter 2 for nitrogen stoichiometry (pft x organ) real(r8), allocatable :: phos_stoich_p1(:,:) ! Parameter 1 for phosphorus stoichiometry (pft x organ) - real(r8), allocatable :: phos_stoich_p2(:,:) ! Parameter 2 for phosphorus stoichiometry (pft x organ) real(r8), allocatable :: nitr_store_ratio(:) ! This is the ratio of the target nitrogen stored per ! target nitrogen that is bound into the tissues From adcaa0639a8534188629ca8ac43c990e7828ba42 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 31 May 2022 14:49:28 -0700 Subject: [PATCH 235/852] simplifying further --- main/FatesHistoryInterfaceMod.F90 | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 07a65666ed..59c19ff533 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -3588,16 +3588,13 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) patch_area_by_age(1:nlevage) = 0._r8 canopy_area_by_age(1:nlevage) = 0._r8 - site_area_veg = area ! Calculate the site-level total vegetated area (i.e. non-bareground) - cpatch => sites(s)%oldest_patch - do while(associated(cpatch)) - if (nocomp_pft_label .eq. 0) then - site_area_veg = site_area_veg - cpatch%area - endif - cpatch => cpatch%younger - end do + if (hlm_use_nocomp .eq. itrue) then + site_area_veg = area - sites(s)%area_pft(0) + else + site_area_veg = area + end if cpatch => sites(s)%oldest_patch do while(associated(cpatch)) @@ -3627,9 +3624,10 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) cpatch%radiation_error * cpatch%area * AREA_INV ! Only accumulate the instantaneous vegetation temperature for vegetated patches - if (nocomp_pft_label .ne. 0) then + if (cpatch%patchno .ne. 0) then hio_tveg(io_si) = hio_tveg(io_si) + & - (bc_in(s)%t_veg_pa(cpatch%patchno) - t_water_freeze_k_1atm) * cpatch%area / site_area_veg + (bc_in(s)%t_veg_pa(cpatch%patchno) - t_water_freeze_k_1atm) * & + cpatch%area / site_area_veg end if ccohort => cpatch%shortest From 11b393cb7b45e8854b1d69bd32e056742f97cf34 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 1 Jun 2022 11:20:21 -0400 Subject: [PATCH 236/852] Updating the default parameter file to api 24 --- parameter_files/fates_params_default.cdl | 1433 +++++++++++----------- 1 file changed, 741 insertions(+), 692 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 45e4a3509c..b45f3249ef 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1,17 +1,18 @@ -netcdf fates_params_default.c210629_sorted { +netcdf tmp { dimensions: fates_NCWD = 4 ; fates_history_age_bins = 7 ; + fates_history_coage_bins = 2 ; + fates_history_damage_bins = 2 ; fates_history_height_bins = 6 ; fates_history_size_bins = 13 ; - fates_history_coage_bins = 2 ; + fates_hlm_pftno = 14 ; fates_hydr_organs = 4 ; fates_leafage_class = 1 ; fates_litterclass = 6 ; fates_pft = 12 ; - fates_prt_organs = 4 ; + fates_plant_organs = 4 ; fates_string_length = 60 ; - fates_hlm_pftno = 14 ; variables: double fates_history_ageclass_bin_edges(fates_history_age_bins) ; fates_history_ageclass_bin_edges:units = "yr" ; @@ -22,31 +23,39 @@ variables: double fates_history_height_bin_edges(fates_history_height_bins) ; fates_history_height_bin_edges:units = "m" ; fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; + double fates_history_damage_bin_edges(fates_history_damage_bins) ; + fates_history_damage_bin_edges:units = "% crown loss" ; + fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; fates_history_sizeclass_bin_edges:units = "cm" ; fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; - double fates_hydr_htftype_node(fates_hydr_organs) ; - fates_hydr_htftype_node:units = "unitless" ; - fates_hydr_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; - fates_hydr_htftype_node:possible_values = "1: Christofferson et al. 2016 (TFS); 2: Van Genuchten 1980" ; - double fates_prt_organ_id(fates_prt_organs) ; - fates_prt_organ_id:units = "index, unitless" ; - fates_prt_organ_id:long_name = "This is the global index the organ in this file is associated with in PRTGenericMod.F90" ; + double fates_alloc_organ_id(fates_plant_organs) ; + fates_alloc_organ_id:units = "unitless" ; + fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; + double fates_hydro_htftype_node(fates_hydr_organs) ; + fates_hydro_htftype_node:units = "unitless" ; + fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; char fates_pftname(fates_pft, fates_string_length) ; fates_pftname:units = "unitless - string" ; fates_pftname:long_name = "Description of plant type" ; - char fates_hydr_organname_node(fates_hydr_organs, fates_string_length) ; - fates_hydr_organname_node:units = "unitless - string" ; - fates_hydr_organname_node:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; + char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; + fates_hydro_organ_name:units = "unitless - string" ; + fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; + char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; + fates_alloc_organ_name:units = "unitless - string" ; + fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; 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_prt_organ_name(fates_prt_organs, fates_string_length) ; - fates_prt_organ_name:units = "unitless - string" ; - fates_prt_organ_name:long_name = "Name of plant organs (order must match PRTGenericMod.F90)" ; + 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" ; double fates_alloc_storage_cushion(fates_pft) ; fates_alloc_storage_cushion:units = "fraction" ; fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; + double fates_alloc_store_priority_frac(fates_pft) ; + fates_alloc_store_priority_frac:units = "unitless" ; + fates_alloc_store_priority_frac:long_name = "for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage" ; double fates_allom_agb1(fates_pft) ; fates_allom_agb1:units = "variable" ; fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; @@ -65,14 +74,15 @@ variables: double fates_allom_amode(fates_pft) ; fates_allom_amode:units = "index" ; fates_allom_amode:long_name = "AGB allometry function index." ; - fates_allom_amode:possible_values = "1: Saldarriaga 1998; 2: 2 parameter power law; 3: Chave 2014" ; double fates_allom_blca_expnt_diff(fates_pft) ; fates_allom_blca_expnt_diff:units = "unitless" ; fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; double fates_allom_cmode(fates_pft) ; fates_allom_cmode:units = "index" ; fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; - fates_allom_cmode:possible_values = "1: Constant fraction on AGB" ; + double fates_allom_crown_depth_frac(fates_pft) ; + fates_allom_crown_depth_frac:units = "fraction" ; + fates_allom_crown_depth_frac:long_name = "the depth of a cohort crown as a fraction of its height" ; double fates_allom_d2bl1(fates_pft) ; fates_allom_d2bl1:units = "variable" ; fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; @@ -103,14 +113,21 @@ variables: double fates_allom_fmode(fates_pft) ; fates_allom_fmode:units = "index" ; fates_allom_fmode:long_name = "fine root biomass allometry function index." ; - fates_allom_fmode:possible_values = "1: constant fraction of trimmed bleaf; 2: constant fraction of untrimmed bleaf." ; + double fates_allom_fnrt_prof_a(fates_pft) ; + fates_allom_fnrt_prof_a:units = "unitless" ; + fates_allom_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; + double fates_allom_fnrt_prof_b(fates_pft) ; + fates_allom_fnrt_prof_b:units = "unitless" ; + fates_allom_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; + double fates_allom_fnrt_prof_mode(fates_pft) ; + fates_allom_fnrt_prof_mode:units = "index" ; + fates_allom_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; double fates_allom_frbstor_repro(fates_pft) ; fates_allom_frbstor_repro:units = "fraction" ; fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; double fates_allom_hmode(fates_pft) ; fates_allom_hmode:units = "index" ; fates_allom_hmode:long_name = "height allometry function index." ; - fates_allom_hmode:possible_values = "1: OBrien 1995; 2: Poorter 2006; 3: 2 parameter power law; 4: Chave 2014; 5: Martinez-Cano 2019." ; double fates_allom_l2fr(fates_pft) ; fates_allom_l2fr:units = "gC/gC" ; fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; @@ -123,18 +140,15 @@ variables: double fates_allom_lmode(fates_pft) ; fates_allom_lmode:units = "index" ; fates_allom_lmode:long_name = "leaf biomass allometry function index." ; - fates_allom_lmode:possible_values = "1: Saldarriaga 1998 (capped-dbh power law); 2: generic power law; 3: generic capped-dbh power law." ; double fates_allom_sai_scaler(fates_pft) ; fates_allom_sai_scaler:units = "m2/m2" ; fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; double fates_allom_smode(fates_pft) ; fates_allom_smode:units = "index" ; fates_allom_smode:long_name = "sapwood allometry function index." ; - fates_allom_smode:possible_values = "1: sapwood area proportional to leaf area based on target leaf biomass" ; double fates_allom_stmode(fates_pft) ; fates_allom_stmode:units = "index" ; fates_allom_stmode:long_name = "storage allometry function index." ; - fates_allom_stmode:possible_values = "1: target storage proportional to trimmed maximum leaf biomass." ; double fates_allom_zroot_k(fates_pft) ; fates_allom_zroot_k:units = "unitless" ; fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; @@ -150,151 +164,181 @@ variables: double fates_allom_zroot_min_z(fates_pft) ; fates_allom_zroot_min_z:units = "m" ; fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; - double fates_branch_turnover(fates_pft) ; - fates_branch_turnover:units = "yr" ; - fates_branch_turnover:long_name = "turnover time of branches" ; double fates_c2b(fates_pft) ; fates_c2b:units = "ratio" ; fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; + double fates_cnp_eca_alpha_ptase(fates_pft) ; + fates_cnp_eca_alpha_ptase:units = "g/m3" ; + fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; + double fates_cnp_eca_decompmicc(fates_pft) ; + fates_cnp_eca_decompmicc:units = "gC/m3" ; + fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; + double fates_cnp_eca_km_nh4(fates_pft) ; + fates_cnp_eca_km_nh4:units = "gN/m3" ; + fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; + double fates_cnp_eca_km_no3(fates_pft) ; + fates_cnp_eca_km_no3:units = "gN/m3" ; + fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; + double fates_cnp_eca_km_p(fates_pft) ; + fates_cnp_eca_km_p:units = "gP/m3" ; + fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; + double fates_cnp_eca_km_ptase(fates_pft) ; + fates_cnp_eca_km_ptase:units = "gP/m3" ; + fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; + double fates_cnp_eca_lambda_ptase(fates_pft) ; + fates_cnp_eca_lambda_ptase:units = "g/m3" ; + fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; + double fates_cnp_eca_vmax_nh4(fates_pft) ; + fates_cnp_eca_vmax_nh4:units = "gN/gC/s" ; + fates_cnp_eca_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA)" ; + double fates_cnp_eca_vmax_no3(fates_pft) ; + fates_cnp_eca_vmax_no3:units = "gN/gC/s" ; + fates_cnp_eca_vmax_no3:long_name = "maximum production rate for plant no3 uptake (ECA)" ; + double fates_cnp_eca_vmax_ptase(fates_pft) ; + fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; + fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; + double fates_cnp_fnrt_adapt_tscale(fates_pft) ; + fates_cnp_fnrt_adapt_tscale:units = "days" ; + fates_cnp_fnrt_adapt_tscale:long_name = "Number of days that is shortest possible doubling period for fine-root adaptation to C/N/P balance" ; + double fates_cnp_nfix1(fates_pft) ; + fates_cnp_nfix1:units = "NA" ; + fates_cnp_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; + double fates_cnp_nitr_store_ratio(fates_pft) ; + fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; + fates_cnp_nitr_store_ratio:long_name = "storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code)" ; + double fates_cnp_phos_store_ratio(fates_pft) ; + fates_cnp_phos_store_ratio:units = "(gP/gP)" ; + fates_cnp_phos_store_ratio:long_name = "storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code)" ; + double fates_cnp_prescribed_nuptake(fates_pft) ; + fates_cnp_prescribed_nuptake:units = "fraction" ; + fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; + double fates_cnp_prescribed_puptake(fates_pft) ; + fates_cnp_prescribed_puptake:units = "fraction" ; + fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; + double fates_cnp_rd_vmax_n(fates_pft) ; + fates_cnp_rd_vmax_n:units = "gN/gC/s" ; + fates_cnp_rd_vmax_n:long_name = "maximum production rate for compbined (NH4+NO3) uptake (RD)" ; + double fates_cnp_store_ovrflw_frac(fates_pft) ; + fates_cnp_store_ovrflw_frac:units = "fraction" ; + fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; + fates_cnp_store_ovrflw_frac:use_case = "None" ; + double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_nitr_retrans:units = "fraction" ; + fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; + double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_phos_retrans:units = "fraction" ; + fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; + double fates_cnp_vmax_p(fates_pft) ; + fates_cnp_vmax_p:units = "gP/gC/s" ; + fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; + double fates_damage_frac(fates_pft) ; + fates_damage_frac:units = "fraction" ; + fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; + double fates_damage_mort_p1(fates_pft) ; + fates_damage_mort_p1:units = "fraction" ; + fates_damage_mort_p1:long_name = "inflection point of damage mortality function, a value of 0.8 means 50% mortality with 80% loss of crown, turn off with a large number" ; + double fates_damage_mort_p2(fates_pft) ; + fates_damage_mort_p2:units = "unitless" ; + fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; + 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_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" ; - double fates_displar(fates_pft) ; - fates_displar:units = "unitless" ; - fates_displar:long_name = "Ratio of displacement height to canopy top height" ; - double fates_eca_alpha_ptase(fates_pft) ; - fates_eca_alpha_ptase:units = "g/m3" ; - fates_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; - double fates_eca_decompmicc(fates_pft) ; - fates_eca_decompmicc:units = "gC/m3" ; - fates_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; - double fates_eca_km_nh4(fates_pft) ; - fates_eca_km_nh4:units = "gN/m3" ; - fates_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; - double fates_eca_km_no3(fates_pft) ; - fates_eca_km_no3:units = "gN/m3" ; - fates_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; - double fates_eca_km_p(fates_pft) ; - fates_eca_km_p:units = "gP/m3" ; - fates_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; - double fates_eca_km_ptase(fates_pft) ; - fates_eca_km_ptase:units = "gP/m3" ; - fates_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; - double fates_eca_lambda_ptase(fates_pft) ; - fates_eca_lambda_ptase:units = "g/m3" ; - fates_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; - double fates_eca_vmax_nh4(fates_pft) ; - fates_eca_vmax_nh4:units = "gN/gC/s" ; - fates_eca_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA)" ; - double fates_eca_vmax_no3(fates_pft) ; - fates_eca_vmax_no3:units = "gN/gC/s" ; - fates_eca_vmax_no3:long_name = "maximum production rate for plant no3 uptake (ECA)" ; - double fates_eca_vmax_p(fates_pft) ; - fates_eca_vmax_p:units = "gP/gC/s" ; - fates_eca_vmax_p:long_name = "maximum production rate for plant p uptake (ECA)" ; - double fates_eca_vmax_ptase(fates_pft) ; - fates_eca_vmax_ptase:units = "gP/m2/s" ; - fates_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; double fates_fire_alpha_SH(fates_pft) ; fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; double fates_fire_bark_scaler(fates_pft) ; fates_fire_bark_scaler:units = "fraction" ; fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; - double fates_fire_crown_depth_frac(fates_pft) ; - fates_fire_crown_depth_frac:units = "fraction" ; - fates_fire_crown_depth_frac:long_name = "the depth of a cohorts crown as a fraction of its height" ; double fates_fire_crown_kill(fates_pft) ; fates_fire_crown_kill:units = "NA" ; fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; - double fates_fnrt_prof_a(fates_pft) ; - fates_fnrt_prof_a:units = "unitless" ; - fates_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; - double fates_fnrt_prof_b(fates_pft) ; - fates_fnrt_prof_b:units = "unitless" ; - fates_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; - double fates_fnrt_prof_mode(fates_pft) ; - fates_fnrt_prof_mode:units = "index" ; - fates_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; - double fates_fr_fcel(fates_pft) ; - fates_fr_fcel:units = "fraction" ; - fates_fr_fcel:long_name = "Fine root litter cellulose fraction" ; - double fates_fr_flab(fates_pft) ; - fates_fr_flab:units = "fraction" ; - fates_fr_flab:long_name = "Fine root litter labile fraction" ; - double fates_fr_flig(fates_pft) ; - fates_fr_flig:units = "fraction" ; - fates_fr_flig:long_name = "Fine root litter lignin fraction" ; + double fates_frag_fnrt_fcel(fates_pft) ; + fates_frag_fnrt_fcel:units = "fraction" ; + fates_frag_fnrt_fcel:long_name = "Fine root litter cellulose fraction" ; + double fates_frag_fnrt_flab(fates_pft) ; + fates_frag_fnrt_flab:units = "fraction" ; + fates_frag_fnrt_flab:long_name = "Fine root litter labile fraction" ; + double fates_frag_fnrt_flig(fates_pft) ; + fates_frag_fnrt_flig:units = "fraction" ; + fates_frag_fnrt_flig:long_name = "Fine root litter lignin fraction" ; + double fates_frag_leaf_fcel(fates_pft) ; + fates_frag_leaf_fcel:units = "fraction" ; + fates_frag_leaf_fcel:long_name = "Leaf litter cellulose fraction" ; + double fates_frag_leaf_flab(fates_pft) ; + fates_frag_leaf_flab:units = "fraction" ; + fates_frag_leaf_flab:long_name = "Leaf litter labile fraction" ; + double fates_frag_leaf_flig(fates_pft) ; + fates_frag_leaf_flig:units = "fraction" ; + fates_frag_leaf_flig:long_name = "Leaf litter lignin fraction" ; + double fates_frag_seed_decay_rate(fates_pft) ; + fates_frag_seed_decay_rate:units = "yr-1" ; + fates_frag_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; double fates_grperc(fates_pft) ; fates_grperc:units = "unitless" ; fates_grperc:long_name = "Growth respiration factor" ; - double fates_hydr_avuln_gs(fates_pft) ; - fates_hydr_avuln_gs:units = "unitless" ; - fates_hydr_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; - double fates_hydr_avuln_node(fates_hydr_organs, fates_pft) ; - fates_hydr_avuln_node:units = "unitless" ; - fates_hydr_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; - double fates_hydr_epsil_node(fates_hydr_organs, fates_pft) ; - fates_hydr_epsil_node:units = "MPa" ; - fates_hydr_epsil_node:long_name = "bulk elastic modulus" ; - double fates_hydr_fcap_node(fates_hydr_organs, fates_pft) ; - fates_hydr_fcap_node:units = "unitless" ; - fates_hydr_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; - double fates_hydr_k_lwp(fates_pft) ; - fates_hydr_k_lwp:units = "unitless" ; - fates_hydr_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; - fates_hydr_k_lwp:possible_values = "0: turns off leaf humidity effects on conductance. 1-10 activates humidity effects" ; - double fates_hydr_kmax_node(fates_hydr_organs, fates_pft) ; - fates_hydr_kmax_node:units = "kg/MPa/m/s" ; - fates_hydr_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; - double fates_hydr_p50_gs(fates_pft) ; - fates_hydr_p50_gs:units = "MPa" ; - fates_hydr_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; - double fates_hydr_p50_node(fates_hydr_organs, fates_pft) ; - fates_hydr_p50_node:units = "MPa" ; - fates_hydr_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; - double fates_hydr_p_taper(fates_pft) ; - fates_hydr_p_taper:units = "unitless" ; - fates_hydr_p_taper:long_name = "xylem taper exponent" ; - double fates_hydr_pinot_node(fates_hydr_organs, fates_pft) ; - fates_hydr_pinot_node:units = "MPa" ; - fates_hydr_pinot_node:long_name = "osmotic potential at full turgor" ; - double fates_hydr_pitlp_node(fates_hydr_organs, fates_pft) ; - fates_hydr_pitlp_node:units = "MPa" ; - fates_hydr_pitlp_node:long_name = "turgor loss point" ; - double fates_hydr_resid_node(fates_hydr_organs, fates_pft) ; - fates_hydr_resid_node:units = "cm3/cm3" ; - fates_hydr_resid_node:long_name = "residual water conent" ; - double fates_hydr_rfrac_stem(fates_pft) ; - fates_hydr_rfrac_stem:units = "fraction" ; - fates_hydr_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; - double fates_hydr_rs2(fates_pft) ; - fates_hydr_rs2:units = "m" ; - fates_hydr_rs2:long_name = "absorbing root radius" ; - double fates_hydr_srl(fates_pft) ; - fates_hydr_srl:units = "m g-1" ; - fates_hydr_srl:long_name = "specific root length" ; - double fates_hydr_thetas_node(fates_hydr_organs, fates_pft) ; - fates_hydr_thetas_node:units = "cm3/cm3" ; - fates_hydr_thetas_node:long_name = "saturated water content" ; - double fates_hydr_vg_alpha_node(fates_hydr_organs, fates_pft) ; - fates_hydr_vg_alpha_node:units = "MPa-1" ; - fates_hydr_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; - double fates_hydr_vg_m_node(fates_hydr_organs, fates_pft) ; - fates_hydr_vg_m_node:units = "unitless" ; - fates_hydr_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; - double fates_hydr_vg_n_node(fates_hydr_organs, fates_pft) ; - fates_hydr_vg_n_node:units = "unitless" ; - fates_hydr_vg_n_node:long_name = "(used if hydr_htftype_node = 2),n in van Genuchten 1980 model, pore size distribution parameter" ; + double fates_hydro_avuln_gs(fates_pft) ; + fates_hydro_avuln_gs:units = "unitless" ; + fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; + double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; + fates_hydro_avuln_node:units = "unitless" ; + fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; + double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; + fates_hydro_epsil_node:units = "MPa" ; + fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; + double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; + fates_hydro_fcap_node:units = "unitless" ; + fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; + double fates_hydro_k_lwp(fates_pft) ; + fates_hydro_k_lwp:units = "unitless" ; + fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; + double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; + fates_hydro_kmax_node:units = "kg/MPa/m/s" ; + fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; + double fates_hydro_p50_gs(fates_pft) ; + fates_hydro_p50_gs:units = "MPa" ; + fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; + double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; + fates_hydro_p50_node:units = "MPa" ; + fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; + double fates_hydro_p_taper(fates_pft) ; + fates_hydro_p_taper:units = "unitless" ; + fates_hydro_p_taper:long_name = "xylem taper exponent" ; + double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pinot_node:units = "MPa" ; + fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; + double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pitlp_node:units = "MPa" ; + fates_hydro_pitlp_node:long_name = "turgor loss point" ; + double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; + fates_hydro_resid_node:units = "cm3/cm3" ; + fates_hydro_resid_node:long_name = "residual water conent" ; + double fates_hydro_rfrac_stem(fates_pft) ; + fates_hydro_rfrac_stem:units = "fraction" ; + fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; + double fates_hydro_rs2(fates_pft) ; + fates_hydro_rs2:units = "m" ; + fates_hydro_rs2:long_name = "absorbing root radius" ; + double fates_hydro_srl(fates_pft) ; + fates_hydro_srl:units = "m g-1" ; + fates_hydro_srl:long_name = "specific root length" ; + double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; + fates_hydro_thetas_node:units = "cm3/cm3" ; + fates_hydro_thetas_node:long_name = "saturated water content" ; + double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_alpha_node:units = "MPa-1" ; + fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; + double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_m_node:units = "unitless" ; + fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; + 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_leaf_c3psn(fates_pft) ; fates_leaf_c3psn:units = "flag" ; fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; - double fates_leaf_clumping_index(fates_pft) ; - fates_leaf_clumping_index:units = "fraction (0-1)" ; - fates_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; - double fates_leaf_diameter(fates_pft) ; - fates_leaf_diameter:units = "m" ; - fates_leaf_diameter:long_name = "Characteristic leaf dimension" ; double fates_leaf_jmaxha(fates_pft) ; fates_leaf_jmaxha:units = "J/mol" ; fates_leaf_jmaxha:long_name = "activation energy for jmax" ; @@ -304,9 +348,6 @@ variables: double fates_leaf_jmaxse(fates_pft) ; fates_leaf_jmaxse:units = "J/mol/K" ; fates_leaf_jmaxse:long_name = "entropy term for jmax" ; - double fates_leaf_long(fates_leafage_class, fates_pft) ; - fates_leaf_long:units = "yr" ; - fates_leaf_long:long_name = "Leaf longevity (ie turnover timescale)" ; double fates_leaf_slamax(fates_pft) ; fates_leaf_slamax:units = "m^2/gC" ; fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; @@ -322,9 +363,6 @@ variables: double fates_leaf_stomatal_slope_medlyn(fates_pft) ; fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; - double fates_leaf_stor_priority(fates_pft) ; - fates_leaf_stor_priority:units = "unitless" ; - fates_leaf_stor_priority:long_name = "factor governing priority of replacing storage with NPP" ; double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; @@ -337,18 +375,6 @@ variables: double fates_leaf_vcmaxse(fates_pft) ; fates_leaf_vcmaxse:units = "J/mol/K" ; fates_leaf_vcmaxse:long_name = "entropy term for vcmax" ; - double fates_leaf_xl(fates_pft) ; - fates_leaf_xl:units = "unitless" ; - fates_leaf_xl:long_name = "Leaf/stem orientation index" ; - double fates_lf_fcel(fates_pft) ; - fates_lf_fcel:units = "fraction" ; - fates_lf_fcel:long_name = "Leaf litter cellulose fraction" ; - double fates_lf_flab(fates_pft) ; - fates_lf_flab:units = "fraction" ; - fates_lf_flab:long_name = "Leaf litter labile fraction" ; - double fates_lf_flig(fates_pft) ; - fates_lf_flig:units = "fraction" ; - fates_lf_flig:long_name = "Leaf litter lignin fraction" ; double fates_maintresp_reduction_curvature(fates_pft) ; fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; @@ -373,6 +399,12 @@ variables: double fates_mort_ip_size_senescence(fates_pft) ; fates_mort_ip_size_senescence:units = "dbh cm" ; fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; + double fates_mort_prescribed_canopy(fates_pft) ; + fates_mort_prescribed_canopy:units = "1/yr" ; + fates_mort_prescribed_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; + double fates_mort_prescribed_understory(fates_pft) ; + fates_mort_prescribed_understory:units = "1/yr" ; + fates_mort_prescribed_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; double fates_mort_r_age_senescence(fates_pft) ; fates_mort_r_age_senescence:units = "mortality rate year^-1" ; fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; @@ -388,21 +420,24 @@ variables: double fates_mort_scalar_hydrfailure(fates_pft) ; fates_mort_scalar_hydrfailure:units = "1/yr" ; fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; - double fates_nfix1(fates_pft) ; - fates_nfix1:units = "NA" ; - fates_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; - double fates_nfix2(fates_pft) ; - fates_nfix2:units = "NA" ; - fates_nfix2:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; - double fates_nitr_store_ratio(fates_pft) ; - fates_nitr_store_ratio:units = "(gN/gN)" ; - fates_nitr_store_ratio:long_name = "ratio of storeable N, to functional N bound in cell structures of leaf,root,sap" ; + double fates_nonhydro_smpsc(fates_pft) ; + fates_nonhydro_smpsc:units = "mm" ; + fates_nonhydro_smpsc:long_name = "Soil water potential at full stomatal closure" ; + double fates_nonhydro_smpso(fates_pft) ; + fates_nonhydro_smpso:units = "mm" ; + fates_nonhydro_smpso:long_name = "Soil water potential at full stomatal opening" ; double fates_phen_cold_size_threshold(fates_pft) ; fates_phen_cold_size_threshold:units = "cm" ; fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; double fates_phen_evergreen(fates_pft) ; fates_phen_evergreen:units = "logical flag" ; fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; + double fates_phen_flush_fraction(fates_pft) ; + fates_phen_flush_fraction:units = "fraction" ; + fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; + double fates_phen_fnrt_drop_frac(fates_pft) ; + fates_phen_fnrt_drop_frac:units = "fraction" ; + fates_phen_fnrt_drop_frac:long_name = "fraction of fine roots to drop during drought or cold" ; double fates_phen_season_decid(fates_pft) ; fates_phen_season_decid:units = "logical flag" ; fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; @@ -412,139 +447,108 @@ variables: double fates_phen_stress_decid(fates_pft) ; fates_phen_stress_decid:units = "logical flag" ; fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; - double fates_phenflush_fraction(fates_pft) ; - fates_phenflush_fraction:units = "fraction" ; - fates_phenflush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; - double fates_phos_store_ratio(fates_pft) ; - fates_phos_store_ratio:units = "(gP/gP)" ; - fates_phos_store_ratio:long_name = "ratio of storeable P, to functional P bound in cell structures of leaf,root,sap" ; - double fates_prescribed_mortality_canopy(fates_pft) ; - fates_prescribed_mortality_canopy:units = "1/yr" ; - fates_prescribed_mortality_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; - double fates_prescribed_mortality_understory(fates_pft) ; - fates_prescribed_mortality_understory:units = "1/yr" ; - fates_prescribed_mortality_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; double fates_prescribed_npp_canopy(fates_pft) ; fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; double fates_prescribed_npp_understory(fates_pft) ; fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; - double fates_prescribed_nuptake(fates_pft) ; - fates_prescribed_nuptake:units = "fraction" ; - fates_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; - double fates_prescribed_puptake(fates_pft) ; - fates_prescribed_puptake:units = "fraction" ; - fates_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; - double fates_prescribed_recruitment(fates_pft) ; - fates_prescribed_recruitment:units = "n/yr" ; - fates_prescribed_recruitment:long_name = "recruitment rate for prescribed physiology mode" ; - double fates_prt_alloc_priority(fates_prt_organs, fates_pft) ; - fates_prt_alloc_priority:units = "index (0-fates_prt_organs)" ; - fates_prt_alloc_priority:long_name = "Priority order for allocation (C storage=2)" ; - double fates_prt_nitr_stoich_p1(fates_prt_organs, fates_pft) ; - fates_prt_nitr_stoich_p1:units = "(gN/gC)" ; - fates_prt_nitr_stoich_p1:long_name = "nitrogen stoichiometry, parameter 1" ; - double fates_prt_nitr_stoich_p2(fates_prt_organs, fates_pft) ; - fates_prt_nitr_stoich_p2:units = "(gN/gC)" ; - fates_prt_nitr_stoich_p2:long_name = "nitrogen stoichiometry, parameter 2" ; - double fates_prt_phos_stoich_p1(fates_prt_organs, fates_pft) ; - fates_prt_phos_stoich_p1:units = "(gP/gC)" ; - fates_prt_phos_stoich_p1:long_name = "phosphorous stoichiometry, parameter 1" ; - double fates_prt_phos_stoich_p2(fates_prt_organs, fates_pft) ; - fates_prt_phos_stoich_p2:units = "(gP/gC)" ; - fates_prt_phos_stoich_p2:long_name = "phosphorous stoichiometry, parameter 2" ; - double fates_recruit_hgt_min(fates_pft) ; - fates_recruit_hgt_min:units = "m" ; - fates_recruit_hgt_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; - double fates_recruit_initd(fates_pft) ; - fates_recruit_initd:units = "stems/m2" ; - fates_recruit_initd:long_name = "initial seedling density for a cold-start near-bare-ground simulation" ; - double fates_rholnir(fates_pft) ; - fates_rholnir:units = "fraction" ; - fates_rholnir:long_name = "Leaf reflectance: near-IR" ; - double fates_rholvis(fates_pft) ; - fates_rholvis:units = "fraction" ; - fates_rholvis:long_name = "Leaf reflectance: visible" ; - double fates_rhosnir(fates_pft) ; - fates_rhosnir:units = "fraction" ; - fates_rhosnir:long_name = "Stem reflectance: near-IR" ; - double fates_rhosvis(fates_pft) ; - fates_rhosvis:units = "fraction" ; - fates_rhosvis:long_name = "Stem reflectance: visible" ; - double fates_root_long(fates_pft) ; - fates_root_long:units = "yr" ; - fates_root_long:long_name = "root longevity (alternatively, turnover time)" ; - double fates_seed_alloc(fates_pft) ; - fates_seed_alloc:units = "fraction" ; - fates_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; - double fates_seed_alloc_mature(fates_pft) ; - fates_seed_alloc_mature:units = "fraction" ; - fates_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; - double fates_seed_dbh_repro_threshold(fates_pft) ; - fates_seed_dbh_repro_threshold:units = "cm" ; - fates_seed_dbh_repro_threshold:long_name = "the diameter (if any) where the plant will start extra clonal allocation to the seed pool" ; - double fates_seed_decay_rate(fates_pft) ; - fates_seed_decay_rate:units = "yr-1" ; - fates_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; - double fates_seed_germination_rate(fates_pft) ; - fates_seed_germination_rate:units = "yr-1" ; - fates_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; - double fates_seed_suppl(fates_pft) ; - fates_seed_suppl:units = "KgC/m2/yr" ; - fates_seed_suppl:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; - double fates_senleaf_long_fdrought(fates_pft) ; - fates_senleaf_long_fdrought:units = "unitless[0-1]" ; - fates_senleaf_long_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; - double fates_smpsc(fates_pft) ; - fates_smpsc:units = "mm" ; - fates_smpsc:long_name = "Soil water potential at full stomatal closure" ; - double fates_smpso(fates_pft) ; - fates_smpso:units = "mm" ; - fates_smpso:long_name = "Soil water potential at full stomatal opening" ; - double fates_taulnir(fates_pft) ; - fates_taulnir:units = "fraction" ; - fates_taulnir:long_name = "Leaf transmittance: near-IR" ; - double fates_taulvis(fates_pft) ; - fates_taulvis:units = "fraction" ; - fates_taulvis:long_name = "Leaf transmittance: visible" ; - double fates_tausnir(fates_pft) ; - fates_tausnir:units = "fraction" ; - fates_tausnir:long_name = "Stem transmittance: near-IR" ; - double fates_tausvis(fates_pft) ; - fates_tausvis:units = "fraction" ; - fates_tausvis:long_name = "Stem transmittance: visible" ; + double fates_rad_leaf_clumping_index(fates_pft) ; + fates_rad_leaf_clumping_index:units = "fraction (0-1)" ; + fates_rad_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; + double fates_rad_leaf_rhonir(fates_pft) ; + fates_rad_leaf_rhonir:units = "fraction" ; + fates_rad_leaf_rhonir:long_name = "Leaf reflectance: near-IR" ; + double fates_rad_leaf_rhovis(fates_pft) ; + fates_rad_leaf_rhovis:units = "fraction" ; + fates_rad_leaf_rhovis:long_name = "Leaf reflectance: visible" ; + double fates_rad_leaf_taunir(fates_pft) ; + fates_rad_leaf_taunir:units = "fraction" ; + fates_rad_leaf_taunir:long_name = "Leaf transmittance: near-IR" ; + double fates_rad_leaf_tauvis(fates_pft) ; + fates_rad_leaf_tauvis:units = "fraction" ; + fates_rad_leaf_tauvis:long_name = "Leaf transmittance: visible" ; + double fates_rad_leaf_xl(fates_pft) ; + fates_rad_leaf_xl:units = "unitless" ; + fates_rad_leaf_xl:long_name = "Leaf/stem orientation index" ; + double fates_rad_stem_rhonir(fates_pft) ; + fates_rad_stem_rhonir:units = "fraction" ; + fates_rad_stem_rhonir:long_name = "Stem reflectance: near-IR" ; + double fates_rad_stem_rhovis(fates_pft) ; + fates_rad_stem_rhovis:units = "fraction" ; + fates_rad_stem_rhovis:long_name = "Stem reflectance: visible" ; + double fates_rad_stem_taunir(fates_pft) ; + fates_rad_stem_taunir:units = "fraction" ; + fates_rad_stem_taunir:long_name = "Stem transmittance: near-IR" ; + double fates_rad_stem_tauvis(fates_pft) ; + fates_rad_stem_tauvis:units = "fraction" ; + fates_rad_stem_tauvis:long_name = "Stem transmittance: visible" ; + double fates_recruit_height_min(fates_pft) ; + fates_recruit_height_min:units = "m" ; + fates_recruit_height_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; + double fates_recruit_init_density(fates_pft) ; + fates_recruit_init_density:units = "stems/m2" ; + fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation" ; + double fates_recruit_prescribed_rate(fates_pft) ; + fates_recruit_prescribed_rate:units = "n/yr" ; + fates_recruit_prescribed_rate:long_name = "recruitment rate for prescribed physiology mode" ; + double fates_recruit_seed_alloc(fates_pft) ; + fates_recruit_seed_alloc:units = "fraction" ; + fates_recruit_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; + double fates_recruit_seed_alloc_mature(fates_pft) ; + fates_recruit_seed_alloc_mature:units = "fraction" ; + fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; + double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; + fates_recruit_seed_dbh_repro_threshold:units = "cm" ; + fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter (if any) where the plant will start extra clonal allocation to the seed pool" ; + double fates_recruit_seed_germination_rate(fates_pft) ; + fates_recruit_seed_germination_rate:units = "yr-1" ; + fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; + double fates_recruit_seed_supplement(fates_pft) ; + fates_recruit_seed_supplement:units = "KgC/m2/yr" ; + fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; + double fates_stoich_nitr(fates_plant_organs, fates_pft) ; + fates_stoich_nitr:units = "gN/gC" ; + fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; + double fates_stoich_phos(fates_plant_organs, fates_pft) ; + fates_stoich_phos:units = "gP/gC" ; + fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; double fates_trim_inc(fates_pft) ; fates_trim_inc:units = "m2/m2" ; fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; double fates_trim_limit(fates_pft) ; fates_trim_limit:units = "m2/m2" ; fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; - double fates_turnover_carb_retrans(fates_prt_organs, fates_pft) ; - fates_turnover_carb_retrans:units = "-" ; - fates_turnover_carb_retrans:long_name = "retranslocation fraction of carbon in turnover" ; - double fates_turnover_nitr_retrans(fates_prt_organs, fates_pft) ; - fates_turnover_nitr_retrans:units = "-" ; - fates_turnover_nitr_retrans:long_name = "retranslocation fraction of nitrogen in turnover" ; - double fates_turnover_phos_retrans(fates_prt_organs, fates_pft) ; - fates_turnover_phos_retrans:units = "-" ; - fates_turnover_phos_retrans:long_name = "retranslocation fraction of phosphorous in turnover, parameter 1" ; - double fates_turnover_retrans_mode(fates_pft) ; - fates_turnover_retrans_mode:units = "index" ; - fates_turnover_retrans_mode:long_name = "retranslocation method for leaf/fineroot turnover." ; - fates_turnover_retrans_mode:possible_values = "1: constant fraction." ; + double fates_turb_displar(fates_pft) ; + fates_turb_displar:units = "unitless" ; + fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; + double fates_turb_leaf_diameter(fates_pft) ; + fates_turb_leaf_diameter:units = "m" ; + fates_turb_leaf_diameter:long_name = "Characteristic leaf dimension" ; + double fates_turb_z0mr(fates_pft) ; + fates_turb_z0mr:units = "unitless" ; + fates_turb_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; + double fates_turnover_branch(fates_pft) ; + fates_turnover_branch:units = "yr" ; + fates_turnover_branch:long_name = "turnover time of branches" ; + double fates_turnover_fnrt(fates_pft) ; + fates_turnover_fnrt:units = "yr" ; + fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; + double fates_turnover_leaf(fates_leafage_class, fates_pft) ; + fates_turnover_leaf:units = "yr" ; + fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; + double fates_turnover_senleaf_fdrought(fates_pft) ; + fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; + fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; double fates_wood_density(fates_pft) ; fates_wood_density:units = "g/cm3" ; fates_wood_density:long_name = "mean density of woody tissue in plant" ; double fates_woody(fates_pft) ; fates_woody:units = "logical flag" ; fates_woody:long_name = "Binary woody lifeform flag" ; - double fates_z0mr(fates_pft) ; - fates_z0mr:units = "unitless" ; - fates_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; - double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; - fates_hlm_pft_map:units = "area fraction" ; - fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; double fates_fire_FBD(fates_litterclass) ; fates_fire_FBD:units = "kg Biomass/m3" ; fates_fire_FBD:long_name = "fuel bulk density" ; @@ -569,18 +573,21 @@ variables: double fates_fire_SAV(fates_litterclass) ; fates_fire_SAV:units = "cm-1" ; fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; - double fates_max_decomp(fates_litterclass) ; - fates_max_decomp:units = "yr-1" ; - fates_max_decomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; - double fates_CWD_frac(fates_NCWD) ; - fates_CWD_frac:units = "fraction" ; - fates_CWD_frac:long_name = "fraction of woody (bdead+bsw) biomass destined for CWD pool" ; + double fates_frag_maxdecomp(fates_litterclass) ; + fates_frag_maxdecomp:units = "yr-1" ; + fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; + 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_base_mr_20 ; fates_base_mr_20:units = "gC/gN/s" ; fates_base_mr_20:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; 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" ; + double fates_cnp_eca_plant_escalar ; + fates_cnp_eca_plant_escalar:units = "" ; + fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; double fates_cohort_age_fusion_tol ; fates_cohort_age_fusion_tol:units = "unitless" ; fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; @@ -590,18 +597,15 @@ variables: double fates_comp_excln ; fates_comp_excln:units = "none" ; fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; - double fates_cwd_fcel ; - fates_cwd_fcel:units = "unitless" ; - fates_cwd_fcel:long_name = "Cellulose fraction for CWD" ; - double fates_cwd_flig ; - fates_cwd_flig:units = "unitless" ; - fates_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; + double fates_damage_canopy_layer_code ; + fates_damage_canopy_layer_code:units = "unitless" ; + fates_damage_canopy_layer_code:long_name = "Integer code that decides whether damage affects canopy trees (1), understory trees (2)" ; + double fates_damage_event_code ; + fates_damage_event_code:units = "unitless" ; + fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; double fates_dev_arbitrary ; fates_dev_arbitrary:units = "unknown" ; fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; - double fates_eca_plant_escalar ; - fates_eca_plant_escalar:units = "" ; - fates_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; double fates_fire_active_crown_fire ; fates_fire_active_crown_fire:units = "0 or 1" ; fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; @@ -644,54 +648,87 @@ variables: double fates_fire_threshold ; fates_fire_threshold:units = "kW/m" ; fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; - double fates_hydr_kmax_rsurf1 ; - fates_hydr_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; - fates_hydr_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; - double fates_hydr_kmax_rsurf2 ; - fates_hydr_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; - fates_hydr_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; - double fates_hydr_psi0 ; - fates_hydr_psi0:units = "MPa" ; - fates_hydr_psi0:long_name = "sapwood water potential at saturation" ; - double fates_hydr_psicap ; - fates_hydr_psicap:units = "MPa" ; - fates_hydr_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; - double fates_init_litter ; - fates_init_litter:units = "NA" ; - fates_init_litter:long_name = "Initialization value for litter pool in cold-start (NOT USED)" ; + double fates_frag_cwd_fcel ; + fates_frag_cwd_fcel:units = "unitless" ; + fates_frag_cwd_fcel:long_name = "Cellulose fraction for CWD" ; + double fates_frag_cwd_flig ; + fates_frag_cwd_flig:units = "unitless" ; + fates_frag_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; + double fates_hydro_kmax_rsurf1 ; + fates_hydro_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; + double fates_hydro_kmax_rsurf2 ; + fates_hydro_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; + double fates_hydro_psi0 ; + fates_hydro_psi0:units = "MPa" ; + fates_hydro_psi0:long_name = "sapwood water potential at saturation" ; + double fates_hydro_psicap ; + fates_hydro_psicap:units = "MPa" ; + fates_hydro_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; + 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_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" ; + double fates_landuse_logging_collateral_frac ; + fates_landuse_logging_collateral_frac:units = "fraction" ; + fates_landuse_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; + double fates_landuse_logging_dbhmax ; + fates_landuse_logging_dbhmax:units = "cm" ; + fates_landuse_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; + double fates_landuse_logging_dbhmax_infra ; + fates_landuse_logging_dbhmax_infra:units = "cm" ; + fates_landuse_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; + double fates_landuse_logging_dbhmin ; + fates_landuse_logging_dbhmin:units = "cm" ; + fates_landuse_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; + double fates_landuse_logging_direct_frac ; + fates_landuse_logging_direct_frac:units = "fraction" ; + fates_landuse_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; + double fates_landuse_logging_event_code ; + fates_landuse_logging_event_code:units = "unitless" ; + fates_landuse_logging_event_code:long_name = "Integer code that options how logging events are structured" ; + double fates_landuse_logging_export_frac ; + fates_landuse_logging_export_frac:units = "fraction" ; + fates_landuse_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; + double fates_landuse_logging_mechanical_frac ; + fates_landuse_logging_mechanical_frac:units = "fraction" ; + fates_landuse_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; + double fates_landuse_pprodharv10_forest_mean ; + fates_landuse_pprodharv10_forest_mean:units = "fraction" ; + fates_landuse_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; + double fates_leaf_photo_temp_acclim_timescale ; + fates_leaf_photo_temp_acclim_timescale:units = "days" ; + fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; + double fates_leaf_photo_tempsens_model ; + fates_leaf_photo_tempsens_model:units = "unitless" ; + fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; + double fates_leaf_stomatal_assim_model ; + fates_leaf_stomatal_assim_model:units = "unitless" ; + fates_leaf_stomatal_assim_model:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; double fates_leaf_stomatal_model ; fates_leaf_stomatal_model:units = "unitless" ; fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; - double fates_logging_coll_under_frac ; - fates_logging_coll_under_frac:units = "fraction" ; - fates_logging_coll_under_frac:long_name = "Fraction of stems killed in the understory when logging generates disturbance" ; - double fates_logging_collateral_frac ; - fates_logging_collateral_frac:units = "fraction" ; - fates_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; - double fates_logging_dbhmax ; - fates_logging_dbhmax:units = "cm" ; - fates_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; - double fates_logging_dbhmax_infra ; - fates_logging_dbhmax_infra:units = "cm" ; - fates_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; - double fates_logging_dbhmin ; - fates_logging_dbhmin:units = "cm" ; - fates_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; - double fates_logging_direct_frac ; - fates_logging_direct_frac:units = "fraction" ; - fates_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; - double fates_logging_event_code ; - fates_logging_event_code:units = "unitless" ; - fates_logging_event_code:long_name = "Integer code that options how logging events are structured" ; - double fates_logging_export_frac ; - fates_logging_export_frac:units = "fraction" ; - fates_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; - double fates_logging_mechanical_frac ; - fates_logging_mechanical_frac:units = "fraction" ; - fates_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; + double fates_leaf_theta_cj_c3 ; + fates_leaf_theta_cj_c3:units = "unitless" ; + fates_leaf_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; + double fates_leaf_theta_cj_c4 ; + fates_leaf_theta_cj_c4:units = "unitless" ; + fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; double fates_maintresp_model ; fates_maintresp_model:units = "unitless" ; fates_maintresp_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991) (NOT USED)" ; + double fates_maxcohort ; + fates_maxcohort:units = "count" ; + fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; + double fates_maxpatch_primary ; + fates_maxpatch_primary:units = "count" ; + fates_maxpatch_primary:long_name = "maximum number of primary vegetation patches per site" ; + double fates_maxpatch_secondary ; + fates_maxpatch_secondary:units = "count" ; + fates_maxpatch_secondary:long_name = "maximum number of secondary vegetation patches per site" ; double fates_mort_disturb_frac ; fates_mort_disturb_frac:units = "fraction" ; fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; @@ -701,39 +738,39 @@ variables: double fates_patch_fusion_tol ; fates_patch_fusion_tol:units = "unitless" ; fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; - double fates_phen_a ; - fates_phen_a:units = "none" ; - fates_phen_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_b ; - fates_phen_b:units = "none" ; - fates_phen_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_c ; - fates_phen_c:units = "none" ; - fates_phen_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_chiltemp ; - fates_phen_chiltemp:units = "degrees C" ; - fates_phen_chiltemp:long_name = "chilling day counting threshold for vegetation" ; + double fates_phen_chilltemp ; + fates_phen_chilltemp:units = "degrees C" ; + fates_phen_chilltemp:long_name = "chilling day counting threshold for vegetation" ; double fates_phen_coldtemp ; fates_phen_coldtemp:units = "degrees C" ; fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; - double fates_phen_doff_time ; - fates_phen_doff_time:units = "days" ; - fates_phen_doff_time:long_name = "day threshold compared against days since leaves became off-allometry" ; + double fates_phen_drought_model ; + fates_phen_drought_model:units = "unitless" ; + fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; double fates_phen_drought_threshold ; - fates_phen_drought_threshold:units = "m3/m3" ; - fates_phen_drought_threshold:long_name = "liquid volume in soil layer, threashold for drought phenology" ; + fates_phen_drought_threshold:units = "m3/m3 or mm" ; + fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_gddthresh_a ; + fates_phen_gddthresh_a:units = "none" ; + fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_b ; + fates_phen_gddthresh_b:units = "none" ; + fates_phen_gddthresh_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_c ; + fates_phen_gddthresh_c:units = "none" ; + fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_mindaysoff ; + fates_phen_mindaysoff:units = "days" ; + fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves became off-allometry" ; double fates_phen_mindayson ; fates_phen_mindayson:units = "days" ; fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; + double fates_phen_moist_threshold ; + fates_phen_moist_threshold:units = "m3/m3 or mm" ; + fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; double fates_phen_ncolddayslim ; fates_phen_ncolddayslim:units = "days" ; fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; - double fates_photo_temp_acclim_timescale ; - fates_photo_temp_acclim_timescale:units = "days" ; - fates_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; - double fates_photo_tempsens_model ; - fates_photo_tempsens_model:units = "unitless" ; - fates_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; double fates_q10_froz ; fates_q10_froz:units = "unitless" ; fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; @@ -743,18 +780,12 @@ variables: double fates_soil_salinity ; fates_soil_salinity:units = "ppt" ; fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; - double fates_theta_cj_c3 ; - fates_theta_cj_c3:units = "unitless" ; - fates_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; - double fates_theta_cj_c4 ; - fates_theta_cj_c4:units = "unitless" ; - fates_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; double fates_vai_top_bin_width ; fates_vai_top_bin_width:units = "m2/m2" ; - fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer (NOT USED)" ; + fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; double fates_vai_width_increase_factor ; fates_vai_width_increase_factor:units = "unitless" ; - fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing) (NOT USED)" ; + fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; // global attributes: :history = "This parameter file is maintained in version control\nSee https://github.com/NGEET/fates/blob/master/parameter_files/fates_params_default.cdl \nFor changes, use git blame \n" ; @@ -766,12 +797,14 @@ data: fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; - fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, + fates_history_damage_bin_edges = 0, 80 ; + + fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100 ; - fates_hydr_htftype_node = 1, 1, 1, 1 ; + fates_alloc_organ_id = 1, 2, 3, 6 ; - fates_prt_organ_id = 1, 2, 3, 6 ; + fates_hydro_htftype_node = 1, 1, 1, 1 ; fates_pftname = "broadleaf_evergreen_tropical_tree ", @@ -787,12 +820,18 @@ data: "cool_c3_grass ", "c4_grass " ; - fates_hydr_organname_node = + fates_hydro_organ_name = "leaf ", "stem ", "transporting root ", "absorbing root " ; + fates_alloc_organ_name = + "leaf", + "fine root", + "sapwood", + "structure" ; + fates_litterclass_name = "twig ", "small branch ", @@ -801,28 +840,31 @@ data: "dead leaves ", "live grass " ; - fates_prt_organ_name = - "leaf ", - "fine root ", - "sapwood ", - "structure " ; + 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, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; - fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 ; - fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, + fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8, 0.8 ; + + fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; - fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, + fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572 ; - fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, + fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94 ; - fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, + fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931 ; - fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6 ; fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -831,50 +873,59 @@ data: fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, + 0.95, 1, 1, 1 ; + + fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07 ; - fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, + fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3 ; - fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, + fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55 ; - fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, + fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464 ; - fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, + fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119 ; - fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, + fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64 ; - fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, + fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37 ; - fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, + fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 ; fates_allom_dbh_maxheight = 90, 90, 90, 90, 90, 90, 3, 3, 2, 0.35, 0.35, 0.35 ; fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_allom_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; + + fates_allom_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; + + fates_allom_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 ; fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -885,182 +936,224 @@ data: fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; - fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 ; - fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, + fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; - fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 ; - fates_branch_turnover = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; - fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; - fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, - 0.67, 0.67 ; - - fates_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5 ; + fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; - fates_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280 ; - fates_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, + fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14 ; - fates_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, + fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27 ; - fates_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; + fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_vmax_nh4 = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_eca_vmax_no3 = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_fnrt_adapt_tscale = 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100 ; - fates_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_cnp_nfix1 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; - fates_eca_vmax_nh4 = 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, - 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07 ; + fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; - fates_eca_vmax_no3 = 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, - 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08 ; + fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_eca_vmax_p = 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, - 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09 ; + fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + fates_cnp_rd_vmax_n = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_turnover_nitr_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_turnover_phos_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, + 5e-10, 5e-10, 5e-10, 5e-10 ; + + fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01 ; + + fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; + + fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, + 5.5, 5.5 ; + + fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 ; - fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07 ; - fates_fire_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, - 0.95, 1, 1, 1 ; - - fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, + fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775 ; - fates_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; + fates_frag_fnrt_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; - fates_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; + fates_frag_fnrt_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; - fates_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + fates_frag_fnrt_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; - fates_fr_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + fates_frag_leaf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; - fates_fr_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25 ; + fates_frag_leaf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; - fates_fr_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25 ; + fates_frag_leaf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, + 0.51, 0.51, 0.51, 0.51 ; - fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, + fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - fates_hydr_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, - 2.5 ; + fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + 2.5, 2.5 ; - fates_hydr_avuln_node = + fates_hydro_avuln_node = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 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_hydr_epsil_node = + fates_hydro_epsil_node = 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - fates_hydr_fcap_node = + fates_hydro_fcap_node = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_hydr_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_hydr_kmax_node = + fates_hydro_kmax_node = -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; - fates_hydr_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5 ; - fates_hydr_p50_node = - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + fates_hydro_p50_node = + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25 ; - fates_hydr_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, - 0.333, 0.333, 0.333, 0.333 ; + fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, + 0.333, 0.333, 0.333, 0.333, 0.333 ; - fates_hydr_pinot_node = - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + fates_hydro_pinot_node = + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; - fates_hydr_pitlp_node = - -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + fates_hydro_pitlp_node = + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; - fates_hydr_resid_node = + fates_hydro_resid_node = 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - fates_hydr_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625 ; - fates_hydr_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, + fates_hydro_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; - fates_hydr_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; + fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; - fates_hydr_thetas_node = + fates_hydro_thetas_node = 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; - fates_hydr_vg_alpha_node = - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + fates_hydro_vg_alpha_node = + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005 ; - fates_hydr_vg_m_node = + fates_hydro_vg_m_node = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_hydr_vg_n_node = + fates_hydro_vg_n_node = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -1068,284 +1161,222 @@ data: fates_leaf_c3psn = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ; - fates_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, - 0.9, 0.75, 0.75, 0.75 ; - - fates_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.04, 0.04, 0.04 ; - - fates_leaf_jmaxha = 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, + fates_leaf_jmaxha = 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540 ; - fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, + fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040 ; - fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, + fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495 ; - fates_leaf_long = - 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - - fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, + fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, 0.03, 0.03, 0.03, 0.03, 0.03 ; - fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, + fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, 0.03, 0.03, 0.03, 0.03 ; - fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, + fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 40000 ; fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, + fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, 4.7, 2.2, 5.3, 1.6 ; - fates_leaf_stor_priority = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, - 0.8, 0.8 ; - fates_leaf_vcmax25top = 50, 65, 39, 62, 41, 58, 62, 54, 54, 78, 78, 78 ; - fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, + fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330 ; - fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, + fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250 ; - fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, + fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485 ; - fates_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, -0.23, - -0.23, -0.23 ; - - fates_lf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_lf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25 ; - - fates_lf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25 ; - - fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, + fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014 ; - fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -60, -10, -80, -80, + fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -60, -10, -80, -80, -20, 2.5 ; - fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, + fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + fates_mort_prescribed_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, + 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; + + fates_mort_prescribed_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, + 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; + fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6 ; - fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6 ; - fates_nfix1 = _, _, _, _, _, _, _, _, _, _, _, _ ; + fates_nonhydro_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, + -255000, -255000, -255000, -255000, -255000, -255000 ; - fates_nfix2 = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5 ; + fates_nonhydro_smpso = -66000, -66000, -66000, -66000, -66000, -66000, + -66000, -66000, -66000, -66000, -66000, -66000 ; fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; + fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, + 0.5 ; + + fates_phen_fnrt_drop_frac = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; - fates_phenflush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5 ; - - fates_prescribed_mortality_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, - 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; - - fates_prescribed_mortality_understory = 0.025, 0.025, 0.025, 0.025, 0.025, - 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; - - fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, + fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4 ; - fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, + fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; - fates_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_prescribed_recruitment = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, - 0.02, 0.02, 0.02, 0.02, 0.02 ; - - fates_prt_alloc_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, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; + fates_rad_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, + 0.9, 0.75, 0.75, 0.75 ; - fates_prt_nitr_stoich_p1 = - 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, - 0.0047, 0.0047, 0.0047 ; + fates_rad_leaf_rhonir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, + 0.41, 0.28, 0.28, 0.28 ; - fates_prt_nitr_stoich_p2 = - 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, - 0.0047, 0.0047, 0.0047 ; + fates_rad_leaf_rhovis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, + 0.08, 0.05, 0.05, 0.05 ; - fates_prt_phos_stoich_p1 = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, - 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, - 0.00047, 0.00047, 0.00047, 0.00047 ; + fates_rad_leaf_taunir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, + 0.43, 0.4, 0.4, 0.4 ; - fates_prt_phos_stoich_p2 = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, - 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, - 0.00047, 0.00047, 0.00047, 0.00047 ; + fates_rad_leaf_tauvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, + 0.06, 0.05, 0.05, 0.05 ; - fates_recruit_hgt_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, - 0.125, 0.125, 0.125 ; + fates_rad_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, + -0.23, -0.23, -0.23 ; - fates_recruit_initd = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, - 0.2 ; + fates_rad_stem_rhonir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, + 0.49, 0.53, 0.53, 0.53 ; - fates_rholnir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, 0.41, 0.28, - 0.28, 0.28 ; + fates_rad_stem_rhovis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.31, 0.31, 0.31 ; - fates_rholvis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, 0.08, 0.05, 0.05, 0.05 ; + fates_rad_stem_taunir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.25, 0.25, 0.25 ; - fates_rhosnir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, 0.49, 0.53, - 0.53, 0.53 ; + fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.12, 0.12, 0.12 ; - fates_rhosvis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.31, - 0.31, 0.31 ; + fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, + 0.125, 0.125, 0.125 ; - fates_root_long = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2, 0.2, 0.2 ; - fates_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; + fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, + 0.02, 0.02, 0.02, 0.02, 0.02 ; - fates_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9 ; + fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; - fates_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, 1.47, - 1.47, 1.47 ; + fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, + 0.9 ; - fates_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, - 0.51, 0.51, 0.51, 0.51 ; + fates_recruit_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, + 1.47, 1.47, 1.47 ; - fates_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5 ; + fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_seed_suppl = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_senleaf_long_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_stoich_nitr = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; - fates_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, -255000, - -255000, -255000, -255000, -255000, -255000 ; + fates_stoich_phos = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; - fates_smpso = -66000, -66000, -66000, -66000, -66000, -66000, -66000, - -66000, -66000, -66000, -66000, -66000 ; + fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, + 0.03, 0.03 ; - fates_taulnir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, 0.43, 0.4, - 0.4, 0.4 ; + fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; - fates_taulvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.05, - 0.05, 0.05 ; + fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, + 0.67, 0.67, 0.67 ; - fates_tausnir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, - 0.001, 0.25, 0.25, 0.25 ; + fates_turb_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.04, 0.04, 0.04, 0.04 ; - fates_tausvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, - 0.001, 0.12, 0.12, 0.12 ; + fates_turb_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, + 0.055, 0.055, 0.055, 0.055 ; - fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, - 0.03, 0.03 ; + fates_turnover_branch = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; - fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; + fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - fates_turnover_carb_retrans = - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_turnover_nitr_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_turnover_phos_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_turnover_leaf = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - fates_turnover_retrans_mode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, + fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7 ; fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; - fates_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, - 0.055, 0.055, 0.055 ; - fates_hlm_pft_map = - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; @@ -1363,28 +1394,28 @@ data: fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; - fates_max_decomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; + fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; - fates_CWD_frac = 0.045, 0.075, 0.21, 0.67 ; + fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; fates_base_mr_20 = 2.52e-06 ; fates_canopy_closure_thresh = 0.8 ; + fates_cnp_eca_plant_escalar = 1.25e-05 ; + fates_cohort_age_fusion_tol = 0.08 ; fates_cohort_size_fusion_tol = 0.08 ; fates_comp_excln = 3 ; - fates_cwd_fcel = 0.76 ; + fates_damage_canopy_layer_code = 1 ; - fates_cwd_flig = 0.24 ; + fates_damage_event_code = 1 ; fates_dev_arbitrary = _ ; - fates_eca_plant_escalar = 1.25e-05 ; - fates_fire_active_crown_fire = 0 ; fates_fire_cg_strikes = 0.2 ; @@ -1413,65 +1444,87 @@ data: fates_fire_threshold = 50 ; - fates_hydr_kmax_rsurf1 = 20 ; + fates_frag_cwd_fcel = 0.76 ; - fates_hydr_kmax_rsurf2 = 0.0001 ; + fates_frag_cwd_flig = 0.24 ; - fates_hydr_psi0 = 0 ; + fates_hydro_kmax_rsurf1 = 20 ; - fates_hydr_psicap = -0.6 ; + fates_hydro_kmax_rsurf2 = 0.0001 ; - fates_init_litter = 0.05 ; + fates_hydro_psi0 = 0 ; - fates_leaf_stomatal_model = 1 ; + fates_hydro_psicap = -0.6 ; + + fates_hydro_solver = 1 ; + + fates_landuse_logging_coll_under_frac = 0.55983 ; - fates_logging_coll_under_frac = 0.55983 ; + fates_landuse_logging_collateral_frac = 0.05 ; - fates_logging_collateral_frac = 0.05 ; + fates_landuse_logging_dbhmax = _ ; - fates_logging_dbhmax = _ ; + fates_landuse_logging_dbhmax_infra = 35 ; - fates_logging_dbhmax_infra = 35 ; + fates_landuse_logging_dbhmin = 50 ; - fates_logging_dbhmin = 50 ; + fates_landuse_logging_direct_frac = 0.15 ; - fates_logging_direct_frac = 0.15 ; + fates_landuse_logging_event_code = -30 ; - fates_logging_event_code = -30 ; + fates_landuse_logging_export_frac = 0.8 ; - fates_logging_export_frac = 0.8 ; + fates_landuse_logging_mechanical_frac = 0.05 ; - fates_logging_mechanical_frac = 0.05 ; + fates_landuse_pprodharv10_forest_mean = 0.8125 ; + + fates_leaf_photo_temp_acclim_timescale = 30 ; + + fates_leaf_photo_tempsens_model = 1 ; + + fates_leaf_stomatal_assim_model = 1 ; + + fates_leaf_stomatal_model = 1 ; + + fates_leaf_theta_cj_c3 = 0.999 ; + + fates_leaf_theta_cj_c4 = 0.999 ; fates_maintresp_model = 1 ; + fates_maxcohort = 100 ; + + fates_maxpatch_primary = 10 ; + + fates_maxpatch_secondary = 4 ; + fates_mort_disturb_frac = 1 ; fates_mort_understorey_death = 0.55983 ; fates_patch_fusion_tol = 0.05 ; - fates_phen_a = -68 ; + fates_phen_chilltemp = 5 ; - fates_phen_b = 638 ; + fates_phen_coldtemp = 7.5 ; - fates_phen_c = -0.01 ; + fates_phen_drought_model = 0 ; - fates_phen_chiltemp = 5 ; + fates_phen_drought_threshold = 0.15 ; - fates_phen_coldtemp = 7.5 ; + fates_phen_gddthresh_a = -68 ; - fates_phen_doff_time = 100 ; + fates_phen_gddthresh_b = 638 ; - fates_phen_drought_threshold = 0.15 ; + fates_phen_gddthresh_c = -0.01 ; - fates_phen_mindayson = 90 ; + fates_phen_mindaysoff = 100 ; - fates_phen_ncolddayslim = 5 ; + fates_phen_mindayson = 90 ; - fates_photo_temp_acclim_timescale = 30 ; + fates_phen_moist_threshold = 0.18 ; - fates_photo_tempsens_model = 1 ; + fates_phen_ncolddayslim = 5 ; fates_q10_froz = 1.5 ; @@ -1479,10 +1532,6 @@ data: fates_soil_salinity = 0.4 ; - fates_theta_cj_c3 = 0.999 ; - - fates_theta_cj_c4 = 0.999 ; - fates_vai_top_bin_width = 1 ; fates_vai_width_increase_factor = 1 ; From 8078b3a44e83800bf994f18bf4251e2ca174b2c8 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 1 Jun 2022 10:56:19 -0600 Subject: [PATCH 237/852] adjusting check to avoid segfault if flush_to_zero is not present --- main/FatesHistoryInterfaceMod.F90 | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 0c8cbb4ee0..35237630f4 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -1538,10 +1538,11 @@ subroutine set_history_var(this, vname, units, long, use_default, avgflag, vtype ! We make one exception to this rule, for the fates_fraction variable. That way ! we can always know what fraction of the gridcell FATES is occupying. - if (present(flush_to_zero) .and. flush_to_zero) then - flushval = 0.0_r8 - else - flushval = hlm_hio_ignore_val + flushval = hlm_hio_ignore_val + if (present(flush_to_zero)) then + if (flush_to_zero) then + flushval = 0.0_r8 + endif endif write_var = check_hlm_list(trim(hlms), trim(hlm_name)) From 380b298a06c127871487225c91c269db2cb0eafa Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 2 Jun 2022 12:27:04 -0400 Subject: [PATCH 238/852] Update the default parameter file --- parameter_files/fates_params_default.cdl | 1433 +++++++++++----------- 1 file changed, 692 insertions(+), 741 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index b45f3249ef..45e4a3509c 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1,18 +1,17 @@ -netcdf tmp { +netcdf fates_params_default.c210629_sorted { dimensions: fates_NCWD = 4 ; fates_history_age_bins = 7 ; - fates_history_coage_bins = 2 ; - fates_history_damage_bins = 2 ; fates_history_height_bins = 6 ; fates_history_size_bins = 13 ; - fates_hlm_pftno = 14 ; + fates_history_coage_bins = 2 ; fates_hydr_organs = 4 ; fates_leafage_class = 1 ; fates_litterclass = 6 ; fates_pft = 12 ; - fates_plant_organs = 4 ; + fates_prt_organs = 4 ; fates_string_length = 60 ; + fates_hlm_pftno = 14 ; variables: double fates_history_ageclass_bin_edges(fates_history_age_bins) ; fates_history_ageclass_bin_edges:units = "yr" ; @@ -23,39 +22,31 @@ variables: double fates_history_height_bin_edges(fates_history_height_bins) ; fates_history_height_bin_edges:units = "m" ; fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; - double fates_history_damage_bin_edges(fates_history_damage_bins) ; - fates_history_damage_bin_edges:units = "% crown loss" ; - fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; fates_history_sizeclass_bin_edges:units = "cm" ; fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; - double fates_alloc_organ_id(fates_plant_organs) ; - fates_alloc_organ_id:units = "unitless" ; - fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; - double fates_hydro_htftype_node(fates_hydr_organs) ; - fates_hydro_htftype_node:units = "unitless" ; - fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; + double fates_hydr_htftype_node(fates_hydr_organs) ; + fates_hydr_htftype_node:units = "unitless" ; + fates_hydr_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; + fates_hydr_htftype_node:possible_values = "1: Christofferson et al. 2016 (TFS); 2: Van Genuchten 1980" ; + double fates_prt_organ_id(fates_prt_organs) ; + fates_prt_organ_id:units = "index, unitless" ; + fates_prt_organ_id:long_name = "This is the global index the organ in this file is associated with in PRTGenericMod.F90" ; char fates_pftname(fates_pft, fates_string_length) ; fates_pftname:units = "unitless - string" ; fates_pftname:long_name = "Description of plant type" ; - char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; - fates_hydro_organ_name:units = "unitless - string" ; - fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; - char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; - fates_alloc_organ_name:units = "unitless - string" ; - fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; + char fates_hydr_organname_node(fates_hydr_organs, fates_string_length) ; + fates_hydr_organname_node:units = "unitless - string" ; + fates_hydr_organname_node:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; 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" ; - 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" ; + char fates_prt_organ_name(fates_prt_organs, fates_string_length) ; + fates_prt_organ_name:units = "unitless - string" ; + fates_prt_organ_name:long_name = "Name of plant organs (order must match PRTGenericMod.F90)" ; double fates_alloc_storage_cushion(fates_pft) ; fates_alloc_storage_cushion:units = "fraction" ; fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; - double fates_alloc_store_priority_frac(fates_pft) ; - fates_alloc_store_priority_frac:units = "unitless" ; - fates_alloc_store_priority_frac:long_name = "for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage" ; double fates_allom_agb1(fates_pft) ; fates_allom_agb1:units = "variable" ; fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; @@ -74,15 +65,14 @@ variables: double fates_allom_amode(fates_pft) ; fates_allom_amode:units = "index" ; fates_allom_amode:long_name = "AGB allometry function index." ; + fates_allom_amode:possible_values = "1: Saldarriaga 1998; 2: 2 parameter power law; 3: Chave 2014" ; double fates_allom_blca_expnt_diff(fates_pft) ; fates_allom_blca_expnt_diff:units = "unitless" ; fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; double fates_allom_cmode(fates_pft) ; fates_allom_cmode:units = "index" ; fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; - double fates_allom_crown_depth_frac(fates_pft) ; - fates_allom_crown_depth_frac:units = "fraction" ; - fates_allom_crown_depth_frac:long_name = "the depth of a cohort crown as a fraction of its height" ; + fates_allom_cmode:possible_values = "1: Constant fraction on AGB" ; double fates_allom_d2bl1(fates_pft) ; fates_allom_d2bl1:units = "variable" ; fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; @@ -113,21 +103,14 @@ variables: double fates_allom_fmode(fates_pft) ; fates_allom_fmode:units = "index" ; fates_allom_fmode:long_name = "fine root biomass allometry function index." ; - double fates_allom_fnrt_prof_a(fates_pft) ; - fates_allom_fnrt_prof_a:units = "unitless" ; - fates_allom_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; - double fates_allom_fnrt_prof_b(fates_pft) ; - fates_allom_fnrt_prof_b:units = "unitless" ; - fates_allom_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; - double fates_allom_fnrt_prof_mode(fates_pft) ; - fates_allom_fnrt_prof_mode:units = "index" ; - fates_allom_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; + fates_allom_fmode:possible_values = "1: constant fraction of trimmed bleaf; 2: constant fraction of untrimmed bleaf." ; double fates_allom_frbstor_repro(fates_pft) ; fates_allom_frbstor_repro:units = "fraction" ; fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; double fates_allom_hmode(fates_pft) ; fates_allom_hmode:units = "index" ; fates_allom_hmode:long_name = "height allometry function index." ; + fates_allom_hmode:possible_values = "1: OBrien 1995; 2: Poorter 2006; 3: 2 parameter power law; 4: Chave 2014; 5: Martinez-Cano 2019." ; double fates_allom_l2fr(fates_pft) ; fates_allom_l2fr:units = "gC/gC" ; fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; @@ -140,15 +123,18 @@ variables: double fates_allom_lmode(fates_pft) ; fates_allom_lmode:units = "index" ; fates_allom_lmode:long_name = "leaf biomass allometry function index." ; + fates_allom_lmode:possible_values = "1: Saldarriaga 1998 (capped-dbh power law); 2: generic power law; 3: generic capped-dbh power law." ; double fates_allom_sai_scaler(fates_pft) ; fates_allom_sai_scaler:units = "m2/m2" ; fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; double fates_allom_smode(fates_pft) ; fates_allom_smode:units = "index" ; fates_allom_smode:long_name = "sapwood allometry function index." ; + fates_allom_smode:possible_values = "1: sapwood area proportional to leaf area based on target leaf biomass" ; double fates_allom_stmode(fates_pft) ; fates_allom_stmode:units = "index" ; fates_allom_stmode:long_name = "storage allometry function index." ; + fates_allom_stmode:possible_values = "1: target storage proportional to trimmed maximum leaf biomass." ; double fates_allom_zroot_k(fates_pft) ; fates_allom_zroot_k:units = "unitless" ; fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; @@ -164,181 +150,151 @@ variables: double fates_allom_zroot_min_z(fates_pft) ; fates_allom_zroot_min_z:units = "m" ; fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_branch_turnover(fates_pft) ; + fates_branch_turnover:units = "yr" ; + fates_branch_turnover:long_name = "turnover time of branches" ; double fates_c2b(fates_pft) ; fates_c2b:units = "ratio" ; fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; - double fates_cnp_eca_alpha_ptase(fates_pft) ; - fates_cnp_eca_alpha_ptase:units = "g/m3" ; - fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; - double fates_cnp_eca_decompmicc(fates_pft) ; - fates_cnp_eca_decompmicc:units = "gC/m3" ; - fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; - double fates_cnp_eca_km_nh4(fates_pft) ; - fates_cnp_eca_km_nh4:units = "gN/m3" ; - fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; - double fates_cnp_eca_km_no3(fates_pft) ; - fates_cnp_eca_km_no3:units = "gN/m3" ; - fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; - double fates_cnp_eca_km_p(fates_pft) ; - fates_cnp_eca_km_p:units = "gP/m3" ; - fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; - double fates_cnp_eca_km_ptase(fates_pft) ; - fates_cnp_eca_km_ptase:units = "gP/m3" ; - fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; - double fates_cnp_eca_lambda_ptase(fates_pft) ; - fates_cnp_eca_lambda_ptase:units = "g/m3" ; - fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; - double fates_cnp_eca_vmax_nh4(fates_pft) ; - fates_cnp_eca_vmax_nh4:units = "gN/gC/s" ; - fates_cnp_eca_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA)" ; - double fates_cnp_eca_vmax_no3(fates_pft) ; - fates_cnp_eca_vmax_no3:units = "gN/gC/s" ; - fates_cnp_eca_vmax_no3:long_name = "maximum production rate for plant no3 uptake (ECA)" ; - double fates_cnp_eca_vmax_ptase(fates_pft) ; - fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; - fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; - double fates_cnp_fnrt_adapt_tscale(fates_pft) ; - fates_cnp_fnrt_adapt_tscale:units = "days" ; - fates_cnp_fnrt_adapt_tscale:long_name = "Number of days that is shortest possible doubling period for fine-root adaptation to C/N/P balance" ; - double fates_cnp_nfix1(fates_pft) ; - fates_cnp_nfix1:units = "NA" ; - fates_cnp_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; - double fates_cnp_nitr_store_ratio(fates_pft) ; - fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; - fates_cnp_nitr_store_ratio:long_name = "storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code)" ; - double fates_cnp_phos_store_ratio(fates_pft) ; - fates_cnp_phos_store_ratio:units = "(gP/gP)" ; - fates_cnp_phos_store_ratio:long_name = "storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code)" ; - double fates_cnp_prescribed_nuptake(fates_pft) ; - fates_cnp_prescribed_nuptake:units = "fraction" ; - fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; - double fates_cnp_prescribed_puptake(fates_pft) ; - fates_cnp_prescribed_puptake:units = "fraction" ; - fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; - double fates_cnp_rd_vmax_n(fates_pft) ; - fates_cnp_rd_vmax_n:units = "gN/gC/s" ; - fates_cnp_rd_vmax_n:long_name = "maximum production rate for compbined (NH4+NO3) uptake (RD)" ; - double fates_cnp_store_ovrflw_frac(fates_pft) ; - fates_cnp_store_ovrflw_frac:units = "fraction" ; - fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; - fates_cnp_store_ovrflw_frac:use_case = "None" ; - double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; - fates_cnp_turnover_nitr_retrans:units = "fraction" ; - fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; - double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; - fates_cnp_turnover_phos_retrans:units = "fraction" ; - fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; - double fates_cnp_vmax_p(fates_pft) ; - fates_cnp_vmax_p:units = "gP/gC/s" ; - fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; - double fates_damage_frac(fates_pft) ; - fates_damage_frac:units = "fraction" ; - fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; - double fates_damage_mort_p1(fates_pft) ; - fates_damage_mort_p1:units = "fraction" ; - fates_damage_mort_p1:long_name = "inflection point of damage mortality function, a value of 0.8 means 50% mortality with 80% loss of crown, turn off with a large number" ; - double fates_damage_mort_p2(fates_pft) ; - fates_damage_mort_p2:units = "unitless" ; - fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; - 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_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" ; + double fates_displar(fates_pft) ; + fates_displar:units = "unitless" ; + fates_displar:long_name = "Ratio of displacement height to canopy top height" ; + double fates_eca_alpha_ptase(fates_pft) ; + fates_eca_alpha_ptase:units = "g/m3" ; + fates_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; + double fates_eca_decompmicc(fates_pft) ; + fates_eca_decompmicc:units = "gC/m3" ; + fates_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; + double fates_eca_km_nh4(fates_pft) ; + fates_eca_km_nh4:units = "gN/m3" ; + fates_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; + double fates_eca_km_no3(fates_pft) ; + fates_eca_km_no3:units = "gN/m3" ; + fates_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; + double fates_eca_km_p(fates_pft) ; + fates_eca_km_p:units = "gP/m3" ; + fates_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; + double fates_eca_km_ptase(fates_pft) ; + fates_eca_km_ptase:units = "gP/m3" ; + fates_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; + double fates_eca_lambda_ptase(fates_pft) ; + fates_eca_lambda_ptase:units = "g/m3" ; + fates_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; + double fates_eca_vmax_nh4(fates_pft) ; + fates_eca_vmax_nh4:units = "gN/gC/s" ; + fates_eca_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA)" ; + double fates_eca_vmax_no3(fates_pft) ; + fates_eca_vmax_no3:units = "gN/gC/s" ; + fates_eca_vmax_no3:long_name = "maximum production rate for plant no3 uptake (ECA)" ; + double fates_eca_vmax_p(fates_pft) ; + fates_eca_vmax_p:units = "gP/gC/s" ; + fates_eca_vmax_p:long_name = "maximum production rate for plant p uptake (ECA)" ; + double fates_eca_vmax_ptase(fates_pft) ; + fates_eca_vmax_ptase:units = "gP/m2/s" ; + fates_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; double fates_fire_alpha_SH(fates_pft) ; fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; double fates_fire_bark_scaler(fates_pft) ; fates_fire_bark_scaler:units = "fraction" ; fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; + double fates_fire_crown_depth_frac(fates_pft) ; + fates_fire_crown_depth_frac:units = "fraction" ; + fates_fire_crown_depth_frac:long_name = "the depth of a cohorts crown as a fraction of its height" ; double fates_fire_crown_kill(fates_pft) ; fates_fire_crown_kill:units = "NA" ; fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; - double fates_frag_fnrt_fcel(fates_pft) ; - fates_frag_fnrt_fcel:units = "fraction" ; - fates_frag_fnrt_fcel:long_name = "Fine root litter cellulose fraction" ; - double fates_frag_fnrt_flab(fates_pft) ; - fates_frag_fnrt_flab:units = "fraction" ; - fates_frag_fnrt_flab:long_name = "Fine root litter labile fraction" ; - double fates_frag_fnrt_flig(fates_pft) ; - fates_frag_fnrt_flig:units = "fraction" ; - fates_frag_fnrt_flig:long_name = "Fine root litter lignin fraction" ; - double fates_frag_leaf_fcel(fates_pft) ; - fates_frag_leaf_fcel:units = "fraction" ; - fates_frag_leaf_fcel:long_name = "Leaf litter cellulose fraction" ; - double fates_frag_leaf_flab(fates_pft) ; - fates_frag_leaf_flab:units = "fraction" ; - fates_frag_leaf_flab:long_name = "Leaf litter labile fraction" ; - double fates_frag_leaf_flig(fates_pft) ; - fates_frag_leaf_flig:units = "fraction" ; - fates_frag_leaf_flig:long_name = "Leaf litter lignin fraction" ; - double fates_frag_seed_decay_rate(fates_pft) ; - fates_frag_seed_decay_rate:units = "yr-1" ; - fates_frag_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; + double fates_fnrt_prof_a(fates_pft) ; + fates_fnrt_prof_a:units = "unitless" ; + fates_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; + double fates_fnrt_prof_b(fates_pft) ; + fates_fnrt_prof_b:units = "unitless" ; + fates_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; + double fates_fnrt_prof_mode(fates_pft) ; + fates_fnrt_prof_mode:units = "index" ; + fates_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; + double fates_fr_fcel(fates_pft) ; + fates_fr_fcel:units = "fraction" ; + fates_fr_fcel:long_name = "Fine root litter cellulose fraction" ; + double fates_fr_flab(fates_pft) ; + fates_fr_flab:units = "fraction" ; + fates_fr_flab:long_name = "Fine root litter labile fraction" ; + double fates_fr_flig(fates_pft) ; + fates_fr_flig:units = "fraction" ; + fates_fr_flig:long_name = "Fine root litter lignin fraction" ; double fates_grperc(fates_pft) ; fates_grperc:units = "unitless" ; fates_grperc:long_name = "Growth respiration factor" ; - double fates_hydro_avuln_gs(fates_pft) ; - fates_hydro_avuln_gs:units = "unitless" ; - fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; - double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; - fates_hydro_avuln_node:units = "unitless" ; - fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; - double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; - fates_hydro_epsil_node:units = "MPa" ; - fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; - double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; - fates_hydro_fcap_node:units = "unitless" ; - fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; - double fates_hydro_k_lwp(fates_pft) ; - fates_hydro_k_lwp:units = "unitless" ; - fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; - double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; - fates_hydro_kmax_node:units = "kg/MPa/m/s" ; - fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; - double fates_hydro_p50_gs(fates_pft) ; - fates_hydro_p50_gs:units = "MPa" ; - fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; - double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; - fates_hydro_p50_node:units = "MPa" ; - fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; - double fates_hydro_p_taper(fates_pft) ; - fates_hydro_p_taper:units = "unitless" ; - fates_hydro_p_taper:long_name = "xylem taper exponent" ; - double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; - fates_hydro_pinot_node:units = "MPa" ; - fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; - double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; - fates_hydro_pitlp_node:units = "MPa" ; - fates_hydro_pitlp_node:long_name = "turgor loss point" ; - double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; - fates_hydro_resid_node:units = "cm3/cm3" ; - fates_hydro_resid_node:long_name = "residual water conent" ; - double fates_hydro_rfrac_stem(fates_pft) ; - fates_hydro_rfrac_stem:units = "fraction" ; - fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; - double fates_hydro_rs2(fates_pft) ; - fates_hydro_rs2:units = "m" ; - fates_hydro_rs2:long_name = "absorbing root radius" ; - double fates_hydro_srl(fates_pft) ; - fates_hydro_srl:units = "m g-1" ; - fates_hydro_srl:long_name = "specific root length" ; - double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; - fates_hydro_thetas_node:units = "cm3/cm3" ; - fates_hydro_thetas_node:long_name = "saturated water content" ; - double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; - fates_hydro_vg_alpha_node:units = "MPa-1" ; - fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; - double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; - fates_hydro_vg_m_node:units = "unitless" ; - fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; - 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_hydr_avuln_gs(fates_pft) ; + fates_hydr_avuln_gs:units = "unitless" ; + fates_hydr_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; + double fates_hydr_avuln_node(fates_hydr_organs, fates_pft) ; + fates_hydr_avuln_node:units = "unitless" ; + fates_hydr_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; + double fates_hydr_epsil_node(fates_hydr_organs, fates_pft) ; + fates_hydr_epsil_node:units = "MPa" ; + fates_hydr_epsil_node:long_name = "bulk elastic modulus" ; + double fates_hydr_fcap_node(fates_hydr_organs, fates_pft) ; + fates_hydr_fcap_node:units = "unitless" ; + fates_hydr_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; + double fates_hydr_k_lwp(fates_pft) ; + fates_hydr_k_lwp:units = "unitless" ; + fates_hydr_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; + fates_hydr_k_lwp:possible_values = "0: turns off leaf humidity effects on conductance. 1-10 activates humidity effects" ; + double fates_hydr_kmax_node(fates_hydr_organs, fates_pft) ; + fates_hydr_kmax_node:units = "kg/MPa/m/s" ; + fates_hydr_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; + double fates_hydr_p50_gs(fates_pft) ; + fates_hydr_p50_gs:units = "MPa" ; + fates_hydr_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; + double fates_hydr_p50_node(fates_hydr_organs, fates_pft) ; + fates_hydr_p50_node:units = "MPa" ; + fates_hydr_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; + double fates_hydr_p_taper(fates_pft) ; + fates_hydr_p_taper:units = "unitless" ; + fates_hydr_p_taper:long_name = "xylem taper exponent" ; + double fates_hydr_pinot_node(fates_hydr_organs, fates_pft) ; + fates_hydr_pinot_node:units = "MPa" ; + fates_hydr_pinot_node:long_name = "osmotic potential at full turgor" ; + double fates_hydr_pitlp_node(fates_hydr_organs, fates_pft) ; + fates_hydr_pitlp_node:units = "MPa" ; + fates_hydr_pitlp_node:long_name = "turgor loss point" ; + double fates_hydr_resid_node(fates_hydr_organs, fates_pft) ; + fates_hydr_resid_node:units = "cm3/cm3" ; + fates_hydr_resid_node:long_name = "residual water conent" ; + double fates_hydr_rfrac_stem(fates_pft) ; + fates_hydr_rfrac_stem:units = "fraction" ; + fates_hydr_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; + double fates_hydr_rs2(fates_pft) ; + fates_hydr_rs2:units = "m" ; + fates_hydr_rs2:long_name = "absorbing root radius" ; + double fates_hydr_srl(fates_pft) ; + fates_hydr_srl:units = "m g-1" ; + fates_hydr_srl:long_name = "specific root length" ; + double fates_hydr_thetas_node(fates_hydr_organs, fates_pft) ; + fates_hydr_thetas_node:units = "cm3/cm3" ; + fates_hydr_thetas_node:long_name = "saturated water content" ; + double fates_hydr_vg_alpha_node(fates_hydr_organs, fates_pft) ; + fates_hydr_vg_alpha_node:units = "MPa-1" ; + fates_hydr_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; + double fates_hydr_vg_m_node(fates_hydr_organs, fates_pft) ; + fates_hydr_vg_m_node:units = "unitless" ; + fates_hydr_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; + double fates_hydr_vg_n_node(fates_hydr_organs, fates_pft) ; + fates_hydr_vg_n_node:units = "unitless" ; + fates_hydr_vg_n_node:long_name = "(used if hydr_htftype_node = 2),n in van Genuchten 1980 model, pore size distribution parameter" ; double fates_leaf_c3psn(fates_pft) ; fates_leaf_c3psn:units = "flag" ; fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; + double fates_leaf_clumping_index(fates_pft) ; + fates_leaf_clumping_index:units = "fraction (0-1)" ; + fates_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; + double fates_leaf_diameter(fates_pft) ; + fates_leaf_diameter:units = "m" ; + fates_leaf_diameter:long_name = "Characteristic leaf dimension" ; double fates_leaf_jmaxha(fates_pft) ; fates_leaf_jmaxha:units = "J/mol" ; fates_leaf_jmaxha:long_name = "activation energy for jmax" ; @@ -348,6 +304,9 @@ variables: double fates_leaf_jmaxse(fates_pft) ; fates_leaf_jmaxse:units = "J/mol/K" ; fates_leaf_jmaxse:long_name = "entropy term for jmax" ; + double fates_leaf_long(fates_leafage_class, fates_pft) ; + fates_leaf_long:units = "yr" ; + fates_leaf_long:long_name = "Leaf longevity (ie turnover timescale)" ; double fates_leaf_slamax(fates_pft) ; fates_leaf_slamax:units = "m^2/gC" ; fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; @@ -363,6 +322,9 @@ variables: double fates_leaf_stomatal_slope_medlyn(fates_pft) ; fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; + double fates_leaf_stor_priority(fates_pft) ; + fates_leaf_stor_priority:units = "unitless" ; + fates_leaf_stor_priority:long_name = "factor governing priority of replacing storage with NPP" ; double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; @@ -375,6 +337,18 @@ variables: double fates_leaf_vcmaxse(fates_pft) ; fates_leaf_vcmaxse:units = "J/mol/K" ; fates_leaf_vcmaxse:long_name = "entropy term for vcmax" ; + double fates_leaf_xl(fates_pft) ; + fates_leaf_xl:units = "unitless" ; + fates_leaf_xl:long_name = "Leaf/stem orientation index" ; + double fates_lf_fcel(fates_pft) ; + fates_lf_fcel:units = "fraction" ; + fates_lf_fcel:long_name = "Leaf litter cellulose fraction" ; + double fates_lf_flab(fates_pft) ; + fates_lf_flab:units = "fraction" ; + fates_lf_flab:long_name = "Leaf litter labile fraction" ; + double fates_lf_flig(fates_pft) ; + fates_lf_flig:units = "fraction" ; + fates_lf_flig:long_name = "Leaf litter lignin fraction" ; double fates_maintresp_reduction_curvature(fates_pft) ; fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; @@ -399,12 +373,6 @@ variables: double fates_mort_ip_size_senescence(fates_pft) ; fates_mort_ip_size_senescence:units = "dbh cm" ; fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; - double fates_mort_prescribed_canopy(fates_pft) ; - fates_mort_prescribed_canopy:units = "1/yr" ; - fates_mort_prescribed_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; - double fates_mort_prescribed_understory(fates_pft) ; - fates_mort_prescribed_understory:units = "1/yr" ; - fates_mort_prescribed_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; double fates_mort_r_age_senescence(fates_pft) ; fates_mort_r_age_senescence:units = "mortality rate year^-1" ; fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; @@ -420,24 +388,21 @@ variables: double fates_mort_scalar_hydrfailure(fates_pft) ; fates_mort_scalar_hydrfailure:units = "1/yr" ; fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; - double fates_nonhydro_smpsc(fates_pft) ; - fates_nonhydro_smpsc:units = "mm" ; - fates_nonhydro_smpsc:long_name = "Soil water potential at full stomatal closure" ; - double fates_nonhydro_smpso(fates_pft) ; - fates_nonhydro_smpso:units = "mm" ; - fates_nonhydro_smpso:long_name = "Soil water potential at full stomatal opening" ; + double fates_nfix1(fates_pft) ; + fates_nfix1:units = "NA" ; + fates_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; + double fates_nfix2(fates_pft) ; + fates_nfix2:units = "NA" ; + fates_nfix2:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; + double fates_nitr_store_ratio(fates_pft) ; + fates_nitr_store_ratio:units = "(gN/gN)" ; + fates_nitr_store_ratio:long_name = "ratio of storeable N, to functional N bound in cell structures of leaf,root,sap" ; double fates_phen_cold_size_threshold(fates_pft) ; fates_phen_cold_size_threshold:units = "cm" ; fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; double fates_phen_evergreen(fates_pft) ; fates_phen_evergreen:units = "logical flag" ; fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; - double fates_phen_flush_fraction(fates_pft) ; - fates_phen_flush_fraction:units = "fraction" ; - fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; - double fates_phen_fnrt_drop_frac(fates_pft) ; - fates_phen_fnrt_drop_frac:units = "fraction" ; - fates_phen_fnrt_drop_frac:long_name = "fraction of fine roots to drop during drought or cold" ; double fates_phen_season_decid(fates_pft) ; fates_phen_season_decid:units = "logical flag" ; fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; @@ -447,108 +412,139 @@ variables: double fates_phen_stress_decid(fates_pft) ; fates_phen_stress_decid:units = "logical flag" ; fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; + double fates_phenflush_fraction(fates_pft) ; + fates_phenflush_fraction:units = "fraction" ; + fates_phenflush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; + double fates_phos_store_ratio(fates_pft) ; + fates_phos_store_ratio:units = "(gP/gP)" ; + fates_phos_store_ratio:long_name = "ratio of storeable P, to functional P bound in cell structures of leaf,root,sap" ; + double fates_prescribed_mortality_canopy(fates_pft) ; + fates_prescribed_mortality_canopy:units = "1/yr" ; + fates_prescribed_mortality_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; + double fates_prescribed_mortality_understory(fates_pft) ; + fates_prescribed_mortality_understory:units = "1/yr" ; + fates_prescribed_mortality_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; double fates_prescribed_npp_canopy(fates_pft) ; fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; double fates_prescribed_npp_understory(fates_pft) ; fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; - double fates_rad_leaf_clumping_index(fates_pft) ; - fates_rad_leaf_clumping_index:units = "fraction (0-1)" ; - fates_rad_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; - double fates_rad_leaf_rhonir(fates_pft) ; - fates_rad_leaf_rhonir:units = "fraction" ; - fates_rad_leaf_rhonir:long_name = "Leaf reflectance: near-IR" ; - double fates_rad_leaf_rhovis(fates_pft) ; - fates_rad_leaf_rhovis:units = "fraction" ; - fates_rad_leaf_rhovis:long_name = "Leaf reflectance: visible" ; - double fates_rad_leaf_taunir(fates_pft) ; - fates_rad_leaf_taunir:units = "fraction" ; - fates_rad_leaf_taunir:long_name = "Leaf transmittance: near-IR" ; - double fates_rad_leaf_tauvis(fates_pft) ; - fates_rad_leaf_tauvis:units = "fraction" ; - fates_rad_leaf_tauvis:long_name = "Leaf transmittance: visible" ; - double fates_rad_leaf_xl(fates_pft) ; - fates_rad_leaf_xl:units = "unitless" ; - fates_rad_leaf_xl:long_name = "Leaf/stem orientation index" ; - double fates_rad_stem_rhonir(fates_pft) ; - fates_rad_stem_rhonir:units = "fraction" ; - fates_rad_stem_rhonir:long_name = "Stem reflectance: near-IR" ; - double fates_rad_stem_rhovis(fates_pft) ; - fates_rad_stem_rhovis:units = "fraction" ; - fates_rad_stem_rhovis:long_name = "Stem reflectance: visible" ; - double fates_rad_stem_taunir(fates_pft) ; - fates_rad_stem_taunir:units = "fraction" ; - fates_rad_stem_taunir:long_name = "Stem transmittance: near-IR" ; - double fates_rad_stem_tauvis(fates_pft) ; - fates_rad_stem_tauvis:units = "fraction" ; - fates_rad_stem_tauvis:long_name = "Stem transmittance: visible" ; - double fates_recruit_height_min(fates_pft) ; - fates_recruit_height_min:units = "m" ; - fates_recruit_height_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; - double fates_recruit_init_density(fates_pft) ; - fates_recruit_init_density:units = "stems/m2" ; - fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation" ; - double fates_recruit_prescribed_rate(fates_pft) ; - fates_recruit_prescribed_rate:units = "n/yr" ; - fates_recruit_prescribed_rate:long_name = "recruitment rate for prescribed physiology mode" ; - double fates_recruit_seed_alloc(fates_pft) ; - fates_recruit_seed_alloc:units = "fraction" ; - fates_recruit_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; - double fates_recruit_seed_alloc_mature(fates_pft) ; - fates_recruit_seed_alloc_mature:units = "fraction" ; - fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; - double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; - fates_recruit_seed_dbh_repro_threshold:units = "cm" ; - fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter (if any) where the plant will start extra clonal allocation to the seed pool" ; - double fates_recruit_seed_germination_rate(fates_pft) ; - fates_recruit_seed_germination_rate:units = "yr-1" ; - fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; - double fates_recruit_seed_supplement(fates_pft) ; - fates_recruit_seed_supplement:units = "KgC/m2/yr" ; - fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; - double fates_stoich_nitr(fates_plant_organs, fates_pft) ; - fates_stoich_nitr:units = "gN/gC" ; - fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; - double fates_stoich_phos(fates_plant_organs, fates_pft) ; - fates_stoich_phos:units = "gP/gC" ; - fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; + double fates_prescribed_nuptake(fates_pft) ; + fates_prescribed_nuptake:units = "fraction" ; + fates_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; + double fates_prescribed_puptake(fates_pft) ; + fates_prescribed_puptake:units = "fraction" ; + fates_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; + double fates_prescribed_recruitment(fates_pft) ; + fates_prescribed_recruitment:units = "n/yr" ; + fates_prescribed_recruitment:long_name = "recruitment rate for prescribed physiology mode" ; + double fates_prt_alloc_priority(fates_prt_organs, fates_pft) ; + fates_prt_alloc_priority:units = "index (0-fates_prt_organs)" ; + fates_prt_alloc_priority:long_name = "Priority order for allocation (C storage=2)" ; + double fates_prt_nitr_stoich_p1(fates_prt_organs, fates_pft) ; + fates_prt_nitr_stoich_p1:units = "(gN/gC)" ; + fates_prt_nitr_stoich_p1:long_name = "nitrogen stoichiometry, parameter 1" ; + double fates_prt_nitr_stoich_p2(fates_prt_organs, fates_pft) ; + fates_prt_nitr_stoich_p2:units = "(gN/gC)" ; + fates_prt_nitr_stoich_p2:long_name = "nitrogen stoichiometry, parameter 2" ; + double fates_prt_phos_stoich_p1(fates_prt_organs, fates_pft) ; + fates_prt_phos_stoich_p1:units = "(gP/gC)" ; + fates_prt_phos_stoich_p1:long_name = "phosphorous stoichiometry, parameter 1" ; + double fates_prt_phos_stoich_p2(fates_prt_organs, fates_pft) ; + fates_prt_phos_stoich_p2:units = "(gP/gC)" ; + fates_prt_phos_stoich_p2:long_name = "phosphorous stoichiometry, parameter 2" ; + double fates_recruit_hgt_min(fates_pft) ; + fates_recruit_hgt_min:units = "m" ; + fates_recruit_hgt_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; + double fates_recruit_initd(fates_pft) ; + fates_recruit_initd:units = "stems/m2" ; + fates_recruit_initd:long_name = "initial seedling density for a cold-start near-bare-ground simulation" ; + double fates_rholnir(fates_pft) ; + fates_rholnir:units = "fraction" ; + fates_rholnir:long_name = "Leaf reflectance: near-IR" ; + double fates_rholvis(fates_pft) ; + fates_rholvis:units = "fraction" ; + fates_rholvis:long_name = "Leaf reflectance: visible" ; + double fates_rhosnir(fates_pft) ; + fates_rhosnir:units = "fraction" ; + fates_rhosnir:long_name = "Stem reflectance: near-IR" ; + double fates_rhosvis(fates_pft) ; + fates_rhosvis:units = "fraction" ; + fates_rhosvis:long_name = "Stem reflectance: visible" ; + double fates_root_long(fates_pft) ; + fates_root_long:units = "yr" ; + fates_root_long:long_name = "root longevity (alternatively, turnover time)" ; + double fates_seed_alloc(fates_pft) ; + fates_seed_alloc:units = "fraction" ; + fates_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; + double fates_seed_alloc_mature(fates_pft) ; + fates_seed_alloc_mature:units = "fraction" ; + fates_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; + double fates_seed_dbh_repro_threshold(fates_pft) ; + fates_seed_dbh_repro_threshold:units = "cm" ; + fates_seed_dbh_repro_threshold:long_name = "the diameter (if any) where the plant will start extra clonal allocation to the seed pool" ; + double fates_seed_decay_rate(fates_pft) ; + fates_seed_decay_rate:units = "yr-1" ; + fates_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; + double fates_seed_germination_rate(fates_pft) ; + fates_seed_germination_rate:units = "yr-1" ; + fates_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; + double fates_seed_suppl(fates_pft) ; + fates_seed_suppl:units = "KgC/m2/yr" ; + fates_seed_suppl:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; + double fates_senleaf_long_fdrought(fates_pft) ; + fates_senleaf_long_fdrought:units = "unitless[0-1]" ; + fates_senleaf_long_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; + double fates_smpsc(fates_pft) ; + fates_smpsc:units = "mm" ; + fates_smpsc:long_name = "Soil water potential at full stomatal closure" ; + double fates_smpso(fates_pft) ; + fates_smpso:units = "mm" ; + fates_smpso:long_name = "Soil water potential at full stomatal opening" ; + double fates_taulnir(fates_pft) ; + fates_taulnir:units = "fraction" ; + fates_taulnir:long_name = "Leaf transmittance: near-IR" ; + double fates_taulvis(fates_pft) ; + fates_taulvis:units = "fraction" ; + fates_taulvis:long_name = "Leaf transmittance: visible" ; + double fates_tausnir(fates_pft) ; + fates_tausnir:units = "fraction" ; + fates_tausnir:long_name = "Stem transmittance: near-IR" ; + double fates_tausvis(fates_pft) ; + fates_tausvis:units = "fraction" ; + fates_tausvis:long_name = "Stem transmittance: visible" ; double fates_trim_inc(fates_pft) ; fates_trim_inc:units = "m2/m2" ; fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; double fates_trim_limit(fates_pft) ; fates_trim_limit:units = "m2/m2" ; fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; - double fates_turb_displar(fates_pft) ; - fates_turb_displar:units = "unitless" ; - fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; - double fates_turb_leaf_diameter(fates_pft) ; - fates_turb_leaf_diameter:units = "m" ; - fates_turb_leaf_diameter:long_name = "Characteristic leaf dimension" ; - double fates_turb_z0mr(fates_pft) ; - fates_turb_z0mr:units = "unitless" ; - fates_turb_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; - double fates_turnover_branch(fates_pft) ; - fates_turnover_branch:units = "yr" ; - fates_turnover_branch:long_name = "turnover time of branches" ; - double fates_turnover_fnrt(fates_pft) ; - fates_turnover_fnrt:units = "yr" ; - fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; - double fates_turnover_leaf(fates_leafage_class, fates_pft) ; - fates_turnover_leaf:units = "yr" ; - fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; - double fates_turnover_senleaf_fdrought(fates_pft) ; - fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; - fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; + double fates_turnover_carb_retrans(fates_prt_organs, fates_pft) ; + fates_turnover_carb_retrans:units = "-" ; + fates_turnover_carb_retrans:long_name = "retranslocation fraction of carbon in turnover" ; + double fates_turnover_nitr_retrans(fates_prt_organs, fates_pft) ; + fates_turnover_nitr_retrans:units = "-" ; + fates_turnover_nitr_retrans:long_name = "retranslocation fraction of nitrogen in turnover" ; + double fates_turnover_phos_retrans(fates_prt_organs, fates_pft) ; + fates_turnover_phos_retrans:units = "-" ; + fates_turnover_phos_retrans:long_name = "retranslocation fraction of phosphorous in turnover, parameter 1" ; + double fates_turnover_retrans_mode(fates_pft) ; + fates_turnover_retrans_mode:units = "index" ; + fates_turnover_retrans_mode:long_name = "retranslocation method for leaf/fineroot turnover." ; + fates_turnover_retrans_mode:possible_values = "1: constant fraction." ; double fates_wood_density(fates_pft) ; fates_wood_density:units = "g/cm3" ; fates_wood_density:long_name = "mean density of woody tissue in plant" ; double fates_woody(fates_pft) ; fates_woody:units = "logical flag" ; fates_woody:long_name = "Binary woody lifeform flag" ; - double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; - fates_hlm_pft_map:units = "area fraction" ; - fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_z0mr(fates_pft) ; + fates_z0mr:units = "unitless" ; + fates_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; double fates_fire_FBD(fates_litterclass) ; fates_fire_FBD:units = "kg Biomass/m3" ; fates_fire_FBD:long_name = "fuel bulk density" ; @@ -573,21 +569,18 @@ variables: double fates_fire_SAV(fates_litterclass) ; fates_fire_SAV:units = "cm-1" ; fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; - double fates_frag_maxdecomp(fates_litterclass) ; - fates_frag_maxdecomp:units = "yr-1" ; - fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; - 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_max_decomp(fates_litterclass) ; + fates_max_decomp:units = "yr-1" ; + fates_max_decomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; + double fates_CWD_frac(fates_NCWD) ; + fates_CWD_frac:units = "fraction" ; + fates_CWD_frac:long_name = "fraction of woody (bdead+bsw) biomass destined for CWD pool" ; double fates_base_mr_20 ; fates_base_mr_20:units = "gC/gN/s" ; fates_base_mr_20:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; 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" ; - double fates_cnp_eca_plant_escalar ; - fates_cnp_eca_plant_escalar:units = "" ; - fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; double fates_cohort_age_fusion_tol ; fates_cohort_age_fusion_tol:units = "unitless" ; fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; @@ -597,15 +590,18 @@ variables: double fates_comp_excln ; fates_comp_excln:units = "none" ; fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; - double fates_damage_canopy_layer_code ; - fates_damage_canopy_layer_code:units = "unitless" ; - fates_damage_canopy_layer_code:long_name = "Integer code that decides whether damage affects canopy trees (1), understory trees (2)" ; - double fates_damage_event_code ; - fates_damage_event_code:units = "unitless" ; - fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; + double fates_cwd_fcel ; + fates_cwd_fcel:units = "unitless" ; + fates_cwd_fcel:long_name = "Cellulose fraction for CWD" ; + double fates_cwd_flig ; + fates_cwd_flig:units = "unitless" ; + fates_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; double fates_dev_arbitrary ; fates_dev_arbitrary:units = "unknown" ; fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; + double fates_eca_plant_escalar ; + fates_eca_plant_escalar:units = "" ; + fates_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; double fates_fire_active_crown_fire ; fates_fire_active_crown_fire:units = "0 or 1" ; fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; @@ -648,87 +644,54 @@ variables: double fates_fire_threshold ; fates_fire_threshold:units = "kW/m" ; fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; - double fates_frag_cwd_fcel ; - fates_frag_cwd_fcel:units = "unitless" ; - fates_frag_cwd_fcel:long_name = "Cellulose fraction for CWD" ; - double fates_frag_cwd_flig ; - fates_frag_cwd_flig:units = "unitless" ; - fates_frag_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; - double fates_hydro_kmax_rsurf1 ; - fates_hydro_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; - fates_hydro_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; - double fates_hydro_kmax_rsurf2 ; - fates_hydro_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; - fates_hydro_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; - double fates_hydro_psi0 ; - fates_hydro_psi0:units = "MPa" ; - fates_hydro_psi0:long_name = "sapwood water potential at saturation" ; - double fates_hydro_psicap ; - fates_hydro_psicap:units = "MPa" ; - fates_hydro_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; - 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_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" ; - double fates_landuse_logging_collateral_frac ; - fates_landuse_logging_collateral_frac:units = "fraction" ; - fates_landuse_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; - double fates_landuse_logging_dbhmax ; - fates_landuse_logging_dbhmax:units = "cm" ; - fates_landuse_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; - double fates_landuse_logging_dbhmax_infra ; - fates_landuse_logging_dbhmax_infra:units = "cm" ; - fates_landuse_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; - double fates_landuse_logging_dbhmin ; - fates_landuse_logging_dbhmin:units = "cm" ; - fates_landuse_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; - double fates_landuse_logging_direct_frac ; - fates_landuse_logging_direct_frac:units = "fraction" ; - fates_landuse_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; - double fates_landuse_logging_event_code ; - fates_landuse_logging_event_code:units = "unitless" ; - fates_landuse_logging_event_code:long_name = "Integer code that options how logging events are structured" ; - double fates_landuse_logging_export_frac ; - fates_landuse_logging_export_frac:units = "fraction" ; - fates_landuse_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; - double fates_landuse_logging_mechanical_frac ; - fates_landuse_logging_mechanical_frac:units = "fraction" ; - fates_landuse_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; - double fates_landuse_pprodharv10_forest_mean ; - fates_landuse_pprodharv10_forest_mean:units = "fraction" ; - fates_landuse_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; - double fates_leaf_photo_temp_acclim_timescale ; - fates_leaf_photo_temp_acclim_timescale:units = "days" ; - fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; - double fates_leaf_photo_tempsens_model ; - fates_leaf_photo_tempsens_model:units = "unitless" ; - fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; - double fates_leaf_stomatal_assim_model ; - fates_leaf_stomatal_assim_model:units = "unitless" ; - fates_leaf_stomatal_assim_model:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; + double fates_hydr_kmax_rsurf1 ; + fates_hydr_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; + fates_hydr_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; + double fates_hydr_kmax_rsurf2 ; + fates_hydr_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; + fates_hydr_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; + double fates_hydr_psi0 ; + fates_hydr_psi0:units = "MPa" ; + fates_hydr_psi0:long_name = "sapwood water potential at saturation" ; + double fates_hydr_psicap ; + fates_hydr_psicap:units = "MPa" ; + fates_hydr_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; + double fates_init_litter ; + fates_init_litter:units = "NA" ; + fates_init_litter:long_name = "Initialization value for litter pool in cold-start (NOT USED)" ; double fates_leaf_stomatal_model ; fates_leaf_stomatal_model:units = "unitless" ; fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; - double fates_leaf_theta_cj_c3 ; - fates_leaf_theta_cj_c3:units = "unitless" ; - fates_leaf_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; - double fates_leaf_theta_cj_c4 ; - fates_leaf_theta_cj_c4:units = "unitless" ; - fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; + double fates_logging_coll_under_frac ; + fates_logging_coll_under_frac:units = "fraction" ; + fates_logging_coll_under_frac:long_name = "Fraction of stems killed in the understory when logging generates disturbance" ; + double fates_logging_collateral_frac ; + fates_logging_collateral_frac:units = "fraction" ; + fates_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; + double fates_logging_dbhmax ; + fates_logging_dbhmax:units = "cm" ; + fates_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; + double fates_logging_dbhmax_infra ; + fates_logging_dbhmax_infra:units = "cm" ; + fates_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; + double fates_logging_dbhmin ; + fates_logging_dbhmin:units = "cm" ; + fates_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; + double fates_logging_direct_frac ; + fates_logging_direct_frac:units = "fraction" ; + fates_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; + double fates_logging_event_code ; + fates_logging_event_code:units = "unitless" ; + fates_logging_event_code:long_name = "Integer code that options how logging events are structured" ; + double fates_logging_export_frac ; + fates_logging_export_frac:units = "fraction" ; + fates_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; + double fates_logging_mechanical_frac ; + fates_logging_mechanical_frac:units = "fraction" ; + fates_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; double fates_maintresp_model ; fates_maintresp_model:units = "unitless" ; fates_maintresp_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991) (NOT USED)" ; - double fates_maxcohort ; - fates_maxcohort:units = "count" ; - fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; - double fates_maxpatch_primary ; - fates_maxpatch_primary:units = "count" ; - fates_maxpatch_primary:long_name = "maximum number of primary vegetation patches per site" ; - double fates_maxpatch_secondary ; - fates_maxpatch_secondary:units = "count" ; - fates_maxpatch_secondary:long_name = "maximum number of secondary vegetation patches per site" ; double fates_mort_disturb_frac ; fates_mort_disturb_frac:units = "fraction" ; fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; @@ -738,39 +701,39 @@ variables: double fates_patch_fusion_tol ; fates_patch_fusion_tol:units = "unitless" ; fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; - double fates_phen_chilltemp ; - fates_phen_chilltemp:units = "degrees C" ; - fates_phen_chilltemp:long_name = "chilling day counting threshold for vegetation" ; + double fates_phen_a ; + fates_phen_a:units = "none" ; + fates_phen_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_b ; + fates_phen_b:units = "none" ; + fates_phen_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_c ; + fates_phen_c:units = "none" ; + fates_phen_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_chiltemp ; + fates_phen_chiltemp:units = "degrees C" ; + fates_phen_chiltemp:long_name = "chilling day counting threshold for vegetation" ; double fates_phen_coldtemp ; fates_phen_coldtemp:units = "degrees C" ; fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; - double fates_phen_drought_model ; - fates_phen_drought_model:units = "unitless" ; - fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; + double fates_phen_doff_time ; + fates_phen_doff_time:units = "days" ; + fates_phen_doff_time:long_name = "day threshold compared against days since leaves became off-allometry" ; double fates_phen_drought_threshold ; - fates_phen_drought_threshold:units = "m3/m3 or mm" ; - fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; - double fates_phen_gddthresh_a ; - fates_phen_gddthresh_a:units = "none" ; - fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_gddthresh_b ; - fates_phen_gddthresh_b:units = "none" ; - fates_phen_gddthresh_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_gddthresh_c ; - fates_phen_gddthresh_c:units = "none" ; - fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_mindaysoff ; - fates_phen_mindaysoff:units = "days" ; - fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves became off-allometry" ; + fates_phen_drought_threshold:units = "m3/m3" ; + fates_phen_drought_threshold:long_name = "liquid volume in soil layer, threashold for drought phenology" ; double fates_phen_mindayson ; fates_phen_mindayson:units = "days" ; fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; - double fates_phen_moist_threshold ; - fates_phen_moist_threshold:units = "m3/m3 or mm" ; - fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; double fates_phen_ncolddayslim ; fates_phen_ncolddayslim:units = "days" ; fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; + double fates_photo_temp_acclim_timescale ; + fates_photo_temp_acclim_timescale:units = "days" ; + fates_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; + double fates_photo_tempsens_model ; + fates_photo_tempsens_model:units = "unitless" ; + fates_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; double fates_q10_froz ; fates_q10_froz:units = "unitless" ; fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; @@ -780,12 +743,18 @@ variables: double fates_soil_salinity ; fates_soil_salinity:units = "ppt" ; fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; + double fates_theta_cj_c3 ; + fates_theta_cj_c3:units = "unitless" ; + fates_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; + double fates_theta_cj_c4 ; + fates_theta_cj_c4:units = "unitless" ; + fates_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; double fates_vai_top_bin_width ; fates_vai_top_bin_width:units = "m2/m2" ; - fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; + fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer (NOT USED)" ; double fates_vai_width_increase_factor ; fates_vai_width_increase_factor:units = "unitless" ; - fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; + fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing) (NOT USED)" ; // global attributes: :history = "This parameter file is maintained in version control\nSee https://github.com/NGEET/fates/blob/master/parameter_files/fates_params_default.cdl \nFor changes, use git blame \n" ; @@ -797,14 +766,12 @@ data: fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; - fates_history_damage_bin_edges = 0, 80 ; - - fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, + fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100 ; - fates_alloc_organ_id = 1, 2, 3, 6 ; + fates_hydr_htftype_node = 1, 1, 1, 1 ; - fates_hydro_htftype_node = 1, 1, 1, 1 ; + fates_prt_organ_id = 1, 2, 3, 6 ; fates_pftname = "broadleaf_evergreen_tropical_tree ", @@ -820,18 +787,12 @@ data: "cool_c3_grass ", "c4_grass " ; - fates_hydro_organ_name = + fates_hydr_organname_node = "leaf ", "stem ", "transporting root ", "absorbing root " ; - fates_alloc_organ_name = - "leaf", - "fine root", - "sapwood", - "structure" ; - fates_litterclass_name = "twig ", "small branch ", @@ -840,31 +801,28 @@ data: "dead leaves ", "live grass " ; - 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, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; + fates_prt_organ_name = + "leaf ", + "fine root ", + "sapwood ", + "structure " ; - fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 ; - fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, - 0.8, 0.8, 0.8, 0.8 ; - - fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, + fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; - fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, + fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572 ; - fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, + fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94 ; - fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, + fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931 ; - fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6 ; fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -873,59 +831,50 @@ data: fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, - 0.95, 1, 1, 1 ; - - fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07 ; - fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, + fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3 ; - fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, + fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55 ; - fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, + fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464 ; - fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, + fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119 ; - fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, + fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64 ; - fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, + fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37 ; - fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, + fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 ; fates_allom_dbh_maxheight = 90, 90, 90, 90, 90, 90, 3, 3, 2, 0.35, 0.35, 0.35 ; fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; - - fates_allom_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; - - fates_allom_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 ; fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -936,224 +885,182 @@ data: fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; - fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 ; - fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, + fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; - fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 ; + fates_branch_turnover = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; + fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; - fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5 ; + fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, + 0.67, 0.67 ; - fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + fates_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280 ; - fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, + fates_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14 ; - fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, + fates_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27 ; - fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1 ; - - fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_eca_vmax_nh4 = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, - 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - - fates_cnp_eca_vmax_no3 = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, - 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - - fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, - 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - - fates_cnp_fnrt_adapt_tscale = 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100, 100 ; + fates_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; - fates_cnp_nfix1 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5, 1.5 ; + fates_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5, 1.5 ; + fates_eca_vmax_nh4 = 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, + 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07 ; - fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_eca_vmax_no3 = 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, + 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08 ; - fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_eca_vmax_p = 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, + 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09 ; - fates_cnp_rd_vmax_n = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + fates_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_turnover_nitr_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_turnover_phos_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, - 5e-10, 5e-10, 5e-10, 5e-10 ; - - fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, - 0.01, 0.01, 0.01 ; - - fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; - - fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, - 5.5, 5.5 ; - - fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 ; - fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07 ; - fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, - 0.775, 0.775, 0.775, 0.775, 0.775 ; + fates_fire_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, + 0.95, 1, 1, 1 ; - fates_frag_fnrt_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5 ; + fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, + 0.775, 0.775, 0.775, 0.775, 0.775 ; - fates_frag_fnrt_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; + fates_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; - fates_frag_fnrt_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; + fates_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; - fates_frag_leaf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5 ; + fates_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - fates_frag_leaf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; + fates_fr_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_frag_leaf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; + fates_fr_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25 ; - fates_frag_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, - 0.51, 0.51, 0.51, 0.51 ; + fates_fr_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25 ; - fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, + fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, - 2.5, 2.5 ; + fates_hydr_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + 2.5 ; - fates_hydro_avuln_node = + fates_hydr_avuln_node = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 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_hydro_epsil_node = + fates_hydr_epsil_node = 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - fates_hydro_fcap_node = + fates_hydr_fcap_node = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_hydr_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_hydro_kmax_node = + fates_hydr_kmax_node = -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; - fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + fates_hydr_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5 ; - fates_hydro_p50_node = - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + fates_hydr_p50_node = + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25 ; - fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, - 0.333, 0.333, 0.333, 0.333, 0.333 ; + fates_hydr_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, + 0.333, 0.333, 0.333, 0.333 ; - fates_hydro_pinot_node = - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + fates_hydr_pinot_node = + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; - fates_hydro_pitlp_node = - -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + fates_hydr_pitlp_node = + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; - fates_hydro_resid_node = + fates_hydr_resid_node = 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + fates_hydr_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625 ; - fates_hydro_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, + fates_hydr_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; - fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; + fates_hydr_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; - fates_hydro_thetas_node = + fates_hydr_thetas_node = 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; - fates_hydro_vg_alpha_node = - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + fates_hydr_vg_alpha_node = + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005 ; - fates_hydro_vg_m_node = + fates_hydr_vg_m_node = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_hydro_vg_n_node = + fates_hydr_vg_n_node = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -1161,222 +1068,284 @@ data: 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, + fates_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, + 0.9, 0.75, 0.75, 0.75 ; + + fates_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.04, 0.04, 0.04 ; + + fates_leaf_jmaxha = 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540 ; - fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, + fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040 ; - fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, + fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495 ; - fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, + fates_leaf_long = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, 0.03, 0.03, 0.03, 0.03, 0.03 ; - fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, + fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, 0.03, 0.03, 0.03, 0.03 ; - fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, + fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 40000 ; fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, + fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, 4.7, 2.2, 5.3, 1.6 ; + fates_leaf_stor_priority = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8 ; + fates_leaf_vcmax25top = 50, 65, 39, 62, 41, 58, 62, 54, 54, 78, 78, 78 ; - fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, + fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330 ; - fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, + fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250 ; - fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, + fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485 ; - fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + fates_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, -0.23, + -0.23, -0.23 ; + + fates_lf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_lf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25 ; + + fates_lf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25 ; + + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, + fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014 ; - fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -60, -10, -80, -80, + fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -60, -10, -80, -80, -20, 2.5 ; - fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, + fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - fates_mort_prescribed_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, - 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; - - fates_mort_prescribed_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, - 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; - fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6 ; - fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6 ; - fates_nonhydro_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, - -255000, -255000, -255000, -255000, -255000, -255000 ; + fates_nfix1 = _, _, _, _, _, _, _, _, _, _, _, _ ; - fates_nonhydro_smpso = -66000, -66000, -66000, -66000, -66000, -66000, - -66000, -66000, -66000, -66000, -66000, -66000 ; + fates_nfix2 = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5 ; fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; - fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, - 0.5 ; - - fates_phen_fnrt_drop_frac = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; - fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, + fates_phenflush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5 ; + + fates_prescribed_mortality_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, + 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; + + fates_prescribed_mortality_understory = 0.025, 0.025, 0.025, 0.025, 0.025, + 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; + + fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4 ; - fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, + fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; - fates_rad_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, - 0.9, 0.75, 0.75, 0.75 ; + fates_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_rad_leaf_rhonir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, - 0.41, 0.28, 0.28, 0.28 ; + fates_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_rad_leaf_rhovis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, - 0.08, 0.05, 0.05, 0.05 ; + fates_prescribed_recruitment = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, + 0.02, 0.02, 0.02, 0.02, 0.02 ; - fates_rad_leaf_taunir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, - 0.43, 0.4, 0.4, 0.4 ; + fates_prt_alloc_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, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; - fates_rad_leaf_tauvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, - 0.06, 0.05, 0.05, 0.05 ; + fates_prt_nitr_stoich_p1 = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; - fates_rad_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, - -0.23, -0.23, -0.23 ; + fates_prt_nitr_stoich_p2 = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; - fates_rad_stem_rhonir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, - 0.49, 0.53, 0.53, 0.53 ; + fates_prt_phos_stoich_p1 = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; - fates_rad_stem_rhovis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.21, 0.31, 0.31, 0.31 ; + fates_prt_phos_stoich_p2 = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; - fates_rad_stem_taunir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, - 0.001, 0.001, 0.25, 0.25, 0.25 ; + fates_recruit_hgt_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, + 0.125, 0.125, 0.125 ; - fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, - 0.001, 0.001, 0.12, 0.12, 0.12 ; + fates_recruit_initd = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2 ; - fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, - 0.125, 0.125, 0.125 ; + fates_rholnir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, 0.41, 0.28, + 0.28, 0.28 ; - fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, - 0.2, 0.2, 0.2 ; + fates_rholvis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, 0.08, 0.05, 0.05, 0.05 ; - fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, - 0.02, 0.02, 0.02, 0.02, 0.02 ; + fates_rhosnir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, 0.49, 0.53, + 0.53, 0.53 ; - fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1, 0.1 ; + fates_rhosvis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.31, + 0.31, 0.31 ; - fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, - 0.9 ; + fates_root_long = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - fates_recruit_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, - 1.47, 1.47, 1.47 ; + fates_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; - fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5 ; + fates_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9 ; - fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, 1.47, + 1.47, 1.47 ; - fates_stoich_nitr = - 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, - 0.0047, 0.0047, 0.0047 ; + fates_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, + 0.51, 0.51, 0.51, 0.51 ; - fates_stoich_phos = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, - 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, - 0.00047, 0.00047, 0.00047, 0.00047 ; + fates_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; - fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, - 0.03, 0.03 ; + fates_seed_suppl = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; + fates_senleaf_long_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, - 0.67, 0.67, 0.67 ; + fates_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, -255000, + -255000, -255000, -255000, -255000, -255000 ; - fates_turb_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.04, 0.04, 0.04, 0.04 ; + fates_smpso = -66000, -66000, -66000, -66000, -66000, -66000, -66000, + -66000, -66000, -66000, -66000, -66000 ; - fates_turb_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, - 0.055, 0.055, 0.055, 0.055 ; + fates_taulnir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, 0.43, 0.4, + 0.4, 0.4 ; - fates_turnover_branch = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; + fates_taulvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.05, + 0.05, 0.05 ; - fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + fates_tausnir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.25, 0.25, 0.25 ; - fates_turnover_leaf = - 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + fates_tausvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.12, 0.12, 0.12 ; - fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, + 0.03, 0.03 ; + + fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; - fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, + fates_turnover_carb_retrans = + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_turnover_nitr_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_turnover_phos_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_turnover_retrans_mode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7 ; fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; + fates_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, + 0.055, 0.055, 0.055 ; + fates_hlm_pft_map = - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; @@ -1394,28 +1363,28 @@ data: fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; - fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; + fates_max_decomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; - fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; + fates_CWD_frac = 0.045, 0.075, 0.21, 0.67 ; fates_base_mr_20 = 2.52e-06 ; fates_canopy_closure_thresh = 0.8 ; - fates_cnp_eca_plant_escalar = 1.25e-05 ; - fates_cohort_age_fusion_tol = 0.08 ; fates_cohort_size_fusion_tol = 0.08 ; fates_comp_excln = 3 ; - fates_damage_canopy_layer_code = 1 ; + fates_cwd_fcel = 0.76 ; - fates_damage_event_code = 1 ; + fates_cwd_flig = 0.24 ; fates_dev_arbitrary = _ ; + fates_eca_plant_escalar = 1.25e-05 ; + fates_fire_active_crown_fire = 0 ; fates_fire_cg_strikes = 0.2 ; @@ -1444,94 +1413,76 @@ data: fates_fire_threshold = 50 ; - fates_frag_cwd_fcel = 0.76 ; - - fates_frag_cwd_flig = 0.24 ; - - fates_hydro_kmax_rsurf1 = 20 ; - - fates_hydro_kmax_rsurf2 = 0.0001 ; + fates_hydr_kmax_rsurf1 = 20 ; - fates_hydro_psi0 = 0 ; + fates_hydr_kmax_rsurf2 = 0.0001 ; - fates_hydro_psicap = -0.6 ; + fates_hydr_psi0 = 0 ; - fates_hydro_solver = 1 ; + fates_hydr_psicap = -0.6 ; - fates_landuse_logging_coll_under_frac = 0.55983 ; + fates_init_litter = 0.05 ; - fates_landuse_logging_collateral_frac = 0.05 ; - - fates_landuse_logging_dbhmax = _ ; - - fates_landuse_logging_dbhmax_infra = 35 ; - - fates_landuse_logging_dbhmin = 50 ; - - fates_landuse_logging_direct_frac = 0.15 ; - - fates_landuse_logging_event_code = -30 ; + fates_leaf_stomatal_model = 1 ; - fates_landuse_logging_export_frac = 0.8 ; + fates_logging_coll_under_frac = 0.55983 ; - fates_landuse_logging_mechanical_frac = 0.05 ; + fates_logging_collateral_frac = 0.05 ; - fates_landuse_pprodharv10_forest_mean = 0.8125 ; + fates_logging_dbhmax = _ ; - fates_leaf_photo_temp_acclim_timescale = 30 ; + fates_logging_dbhmax_infra = 35 ; - fates_leaf_photo_tempsens_model = 1 ; + fates_logging_dbhmin = 50 ; - fates_leaf_stomatal_assim_model = 1 ; + fates_logging_direct_frac = 0.15 ; - fates_leaf_stomatal_model = 1 ; + fates_logging_event_code = -30 ; - fates_leaf_theta_cj_c3 = 0.999 ; + fates_logging_export_frac = 0.8 ; - fates_leaf_theta_cj_c4 = 0.999 ; + fates_logging_mechanical_frac = 0.05 ; fates_maintresp_model = 1 ; - fates_maxcohort = 100 ; - - fates_maxpatch_primary = 10 ; - - fates_maxpatch_secondary = 4 ; - fates_mort_disturb_frac = 1 ; fates_mort_understorey_death = 0.55983 ; fates_patch_fusion_tol = 0.05 ; - fates_phen_chilltemp = 5 ; + fates_phen_a = -68 ; - fates_phen_coldtemp = 7.5 ; - - fates_phen_drought_model = 0 ; + fates_phen_b = 638 ; - fates_phen_drought_threshold = 0.15 ; + fates_phen_c = -0.01 ; - fates_phen_gddthresh_a = -68 ; + fates_phen_chiltemp = 5 ; - fates_phen_gddthresh_b = 638 ; + fates_phen_coldtemp = 7.5 ; - fates_phen_gddthresh_c = -0.01 ; + fates_phen_doff_time = 100 ; - fates_phen_mindaysoff = 100 ; + fates_phen_drought_threshold = 0.15 ; fates_phen_mindayson = 90 ; - fates_phen_moist_threshold = 0.18 ; - fates_phen_ncolddayslim = 5 ; + fates_photo_temp_acclim_timescale = 30 ; + + fates_photo_tempsens_model = 1 ; + fates_q10_froz = 1.5 ; fates_q10_mr = 1.5 ; fates_soil_salinity = 0.4 ; + fates_theta_cj_c3 = 0.999 ; + + fates_theta_cj_c4 = 0.999 ; + fates_vai_top_bin_width = 1 ; fates_vai_width_increase_factor = 1 ; From b3845dc5a888fe279213b4cf2176a586ecb11186 Mon Sep 17 00:00:00 2001 From: YanlanLiu Date: Thu, 2 Jun 2022 09:41:03 -0700 Subject: [PATCH 239/852] pring out seed_in --- biogeochem/EDPhysiologyMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index b793c965c8..4a0a8ed9db 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1521,7 +1521,7 @@ subroutine SeedIn( currentSite, bc_in, bc_out) !YL--------- do pft = 1,numpft bc_out%seed_out(pft) = bc_out%seed_out(pft) + site_seed_rain(pft)*disp_frac(pft) ![kg/site/day] - !write(fates_log(),*) 'pft, site_seed_rain(pft), bc_out%seed_out(pft): ', pft, site_seed_rain(pft), bc_out%seed_out(pft) + write(fates_log(),*) 'pft, bc_in%seed_in(pft), bc_out%seed_out(pft): ', pft, bc_in%seed_in(pft), bc_out%seed_out(pft) end do !----------- From 808e38f04630b5f43d0635d6f96e877f756e157e Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 6 Jun 2022 10:02:35 -0600 Subject: [PATCH 240/852] changed array indices to use names indices --- biogeochem/EDPatchDynamicsMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 53f99827f9..6b4bf0f93f 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -2324,8 +2324,8 @@ subroutine fuse_patches( csite, bc_in ) call endrun(msg=errMsg(sourcefile, __LINE__)) endif else - maxpatches(1) = maxpatch_primary - maxpatches(2) = maxpatch_secondary + maxpatches(primaryforest) = maxpatch_primary + maxpatches(secondaryforest) = maxpatch_secondary endif currentPatch => currentSite%youngest_patch From 8078435e026330b24d63e9097e7160e22e5148cd Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 6 Jun 2022 15:17:02 -0600 Subject: [PATCH 241/852] Reverting changes to EDCanopyStructureMod for b4b --- biogeochem/EDCanopyStructureMod.F90 | 428 +++++++++++++++++----------- 1 file changed, 257 insertions(+), 171 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 975d177d31..888b36586b 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -14,7 +14,6 @@ module EDCanopyStructureMod use EDPftvarcon , only : EDPftvarcon_inst use PRTParametersMod , only : prt_params use FatesAllometryMod , only : carea_allom - use FatesAllometryMod , only : CrownDepth use EDCohortDynamicsMod , only : copy_cohort, terminate_cohorts, terminate_cohort, fuse_cohorts use EDCohortDynamicsMod , only : InitPRTObject use EDCohortDynamicsMod , only : InitPRTBoundaryConditions @@ -32,6 +31,7 @@ module EDCanopyStructureMod use FatesInterfaceTypesMod , only : numpft use FatesInterfaceTypesMod, only : bc_in_type use FatesPlantHydraulicsMod, only : UpdateH2OVeg,InitHydrCohort, RecruitWaterStorage + use EDTypesMod , only : maxCohortsPerPatch use PRTGenericMod, only : leaf_organ use PRTGenericMod, only : all_carbon_elements use PRTGenericMod, only : leaf_organ @@ -1495,6 +1495,7 @@ subroutine leaf_area_profile( currentSite ) real(r8) :: fraction_exposed ! how much of this layer is not covered by snow? real(r8) :: layer_top_hite ! notional top height of this canopy layer (m) real(r8) :: layer_bottom_hite ! notional bottom height of this canopy layer (m) + integer :: smooth_leaf_distribution ! is the leaf distribution this option (1) or not (0) real(r8) :: frac_canopy(N_HITE_BINS) ! amount of canopy in each height class real(r8) :: patch_lai ! LAI summed over the patch in m2/m2 of canopy area real(r8) :: minh(N_HITE_BINS) ! minimum height in height class (m) @@ -1503,10 +1504,11 @@ subroutine leaf_area_profile( currentSite ) real(r8) :: min_chite ! bottom of cohort canopy (m) real(r8) :: max_chite ! top of cohort canopy (m) real(r8) :: lai ! summed lai for checking m2 m-2 - real(r8) :: crown_depth ! Vertical depth of the crown [m] !---------------------------------------------------------------------- + smooth_leaf_distribution = 0 + ! Here we are trying to generate a profile of leaf area, indexed by 'z' and by pft ! We assume that each point in the canopy recieved the light attenuated by the average ! leaf area index above it, irrespective of PFT identity... @@ -1541,221 +1543,305 @@ subroutine leaf_area_profile( currentSite ) call UpdatePatchLAI(currentPatch, patch_lai) - ! ----------------------------------------------------------------------------- - ! Standard canopy layering model. - ! Go through all cohorts and add their leaf area - ! and canopy area to the accumulators. - ! ----------------------------------------------------------------------------- + if(smooth_leaf_distribution == 1)then + ! ----------------------------------------------------------------------------- + ! we are going to ignore the concept of canopy layers, and put all of the leaf + ! area into height banded bins. using the same domains as we had before, except + ! that CL always = 1 + ! ----------------------------------------------------------------------------- - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - ft = currentCohort%pft - cl = currentCohort%canopy_layer + ! this is a crude way of dividing up the bins. Should it be a function of actual maximum height? + dh = 1.0_r8*(HITEMAX/N_HITE_BINS) + do iv = 1,N_HITE_BINS + if (iv == 1) then + minh(iv) = 0.0_r8 + maxh(iv) = dh + else + minh(iv) = (iv-1)*dh + maxh(iv) = (iv)*dh + endif + enddo - ! ---------------------------------------------------------------- - ! How much of each tree is stem area index? Assuming that there is - ! This may indeed be zero if there is a sensecent grass - ! ---------------------------------------------------------------- + currentCohort => currentPatch%shortest + do while(associated(currentCohort)) + ft = currentCohort%pft + min_chite = currentCohort%hite - currentCohort%hite * prt_params%crown_depth_frac(ft) + max_chite = currentCohort%hite + do iv = 1,N_HITE_BINS + frac_canopy(iv) = 0.0_r8 + ! this layer is in the middle of the canopy + if(max_chite > maxh(iv).and.min_chite < minh(iv))then + frac_canopy(iv)= min(1.0_r8,dh / (currentCohort%hite*prt_params%crown_depth_frac(ft) )) + ! this is the layer with the bottom of the canopy in it. + elseif(min_chite < maxh(iv).and.min_chite > minh(iv).and.max_chite > maxh(iv))then + frac_canopy(iv) = (maxh(iv) -min_chite ) / (currentCohort%hite*prt_params%crown_depth_frac(ft) ) + ! this is the layer with the top of the canopy in it. + elseif(max_chite > minh(iv).and.max_chite < maxh(iv).and.min_chite < minh(iv))then + frac_canopy(iv) = (max_chite - minh(iv)) / (currentCohort%hite*prt_params%crown_depth_frac(ft)) + elseif(max_chite < maxh(iv).and.min_chite > minh(iv))then !the whole cohort is within this layer. + frac_canopy(iv) = 1.0_r8 + endif - if( (currentCohort%treelai+currentCohort%treesai) > 0._r8)then - fleaf = currentCohort%lai / (currentCohort%lai + currentCohort%sai) - else - fleaf = 0._r8 - endif + ! no m2 of leaf per m2 of ground in each height class + currentPatch%tlai_profile(1,ft,iv) = currentPatch%tlai_profile(1,ft,iv) + frac_canopy(iv) * & + currentCohort%lai + currentPatch%tsai_profile(1,ft,iv) = currentPatch%tsai_profile(1,ft,iv) + frac_canopy(iv) * & + currentCohort%sai - currentPatch%nrad(cl,ft) = currentPatch%ncan(cl,ft) + !snow burial + if(currentSite%snow_depth > maxh(iv))then + fraction_exposed = 0._r8 + endif + if(currentSite%snow_depth < minh(iv))then + fraction_exposed = 1._r8 + endif + if(currentSite%snow_depth >= minh(iv) .and. currentSite%snow_depth <= maxh(iv)) then !only partly hidden... + fraction_exposed = 1._r8 - max(0._r8,(min(1.0_r8,(currentSite%snow_depth-minh(iv))/dh))) + endif + + currentPatch%elai_profile(1,ft,iv) = currentPatch%tlai_profile(1,ft,iv) * fraction_exposed + currentPatch%esai_profile(1,ft,iv) = currentPatch%tsai_profile(1,ft,iv) * fraction_exposed + + enddo ! (iv) hite bins + + currentCohort => currentCohort%taller + + enddo !currentCohort + + ! ----------------------------------------------------------------------------- + ! Perform a leaf area conservation check on the LAI profile + lai = 0.0_r8 + do ft = 1,numpft + lai = lai+ sum(currentPatch%tlai_profile(1,ft,:)) + enddo - if (currentPatch%nrad(cl,ft) > nlevleaf ) then - write(fates_log(), *) 'Number of radiative leaf layers is larger' - write(fates_log(), *) ' than the maximum allowed.' - write(fates_log(), *) ' cl: ',cl - write(fates_log(), *) ' ft: ',ft - write(fates_log(), *) ' nlevleaf: ',nlevleaf - write(fates_log(), *) ' currentPatch%nrad(cl,ft): ', currentPatch%nrad(cl,ft) + if(lai > patch_lai)then + write(fates_log(), *) 'FATES: problem with lai assignments' call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + endif - call CrownDepth(currentCohort%hite,currentCohort%pft,crown_depth) - - ! -------------------------------------------------------------------------- - ! Whole layers. Make a weighted average of the leaf area in each layer - ! before dividing it by the total area. Fill up layer for whole layers. - ! -------------------------------------------------------------------------- - do iv = 1,currentCohort%NV + else ! smooth leaf distribution - ! This loop builds the arrays that define the effective (not snow covered) - ! and total (includes snow covered) area indices for leaves and stems - ! We calculate the absolute elevation of each layer to help determine if the layer - ! is obscured by snow. - - layer_top_hite = currentCohort%hite - & - ( real(iv-1,r8)/currentCohort%NV * crown_depth ) + ! ----------------------------------------------------------------------------- + ! Standard canopy layering model. + ! Go through all cohorts and add their leaf area + ! and canopy area to the accumulators. + ! ----------------------------------------------------------------------------- - layer_bottom_hite = currentCohort%hite - & - ( real(iv,r8)/currentCohort%NV * crown_depth ) - fraction_exposed = 1.0_r8 - if(currentSite%snow_depth > layer_top_hite)then - fraction_exposed = 0._r8 - endif - if(currentSite%snow_depth < layer_bottom_hite)then - fraction_exposed = 1._r8 - endif - if(currentSite%snow_depth >= layer_bottom_hite .and. & - currentSite%snow_depth <= layer_top_hite) then !only partly hidden... - fraction_exposed = 1._r8 - max(0._r8,(min(1.0_r8,(currentSite%snow_depth -layer_bottom_hite)/ & - (layer_top_hite-layer_bottom_hite )))) - endif + currentCohort => currentPatch%shortest + do while(associated(currentCohort)) + ft = currentCohort%pft + cl = currentCohort%canopy_layer - if(iv==currentCohort%NV) then - remainder = (currentCohort%treelai + currentCohort%treesai) - & - (dlower_vai(iv) - dinc_vai(iv)) - if(remainder > dinc_vai(iv) )then - write(fates_log(), *)'ED: issue with remainder', & - currentCohort%treelai,currentCohort%treesai,dinc_vai(iv), & - currentCohort%NV,remainder + ! ---------------------------------------------------------------- + ! How much of each tree is stem area index? Assuming that there is + ! This may indeed be zero if there is a sensecent grass + ! ---------------------------------------------------------------- - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif + if( (currentCohort%treelai+currentCohort%treesai) > 0._r8)then + fleaf = currentCohort%lai / (currentCohort%lai + currentCohort%sai) else - remainder = dinc_vai(iv) + fleaf = 0._r8 + endif + + currentPatch%nrad(cl,ft) = currentPatch%ncan(cl,ft) + + if (currentPatch%nrad(cl,ft) > nlevleaf ) then + write(fates_log(), *) 'Number of radiative leaf layers is larger' + write(fates_log(), *) ' than the maximum allowed.' + write(fates_log(), *) ' cl: ',cl + write(fates_log(), *) ' ft: ',ft + write(fates_log(), *) ' nlevleaf: ',nlevleaf + write(fates_log(), *) ' currentPatch%nrad(cl,ft): ', currentPatch%nrad(cl,ft) + call endrun(msg=errMsg(sourcefile, __LINE__)) end if - currentPatch%tlai_profile(cl,ft,iv) = currentPatch%tlai_profile(cl,ft,iv) + & - remainder * fleaf * currentCohort%c_area/currentPatch%total_canopy_area - currentPatch%elai_profile(cl,ft,iv) = currentPatch%elai_profile(cl,ft,iv) + & - remainder * fleaf * currentCohort%c_area/currentPatch%total_canopy_area * & - fraction_exposed + ! -------------------------------------------------------------------------- + ! Whole layers. Make a weighted average of the leaf area in each layer + ! before dividing it by the total area. Fill up layer for whole layers. + ! -------------------------------------------------------------------------- - currentPatch%tsai_profile(cl,ft,iv) = currentPatch%tsai_profile(cl,ft,iv) + & - remainder * (1._r8 - fleaf) * currentCohort%c_area/currentPatch%total_canopy_area + do iv = 1,currentCohort%NV - currentPatch%esai_profile(cl,ft,iv) = currentPatch%esai_profile(cl,ft,iv) + & - remainder * (1._r8 - fleaf) * currentCohort%c_area/currentPatch%total_canopy_area * & - fraction_exposed + ! This loop builds the arrays that define the effective (not snow covered) + ! and total (includes snow covered) area indices for leaves and stems + ! We calculate the absolute elevation of each layer to help determine if the layer + ! is obscured by snow. - currentPatch%canopy_area_profile(cl,ft,iv) = currentPatch%canopy_area_profile(cl,ft,iv) + & - currentCohort%c_area/currentPatch%total_canopy_area + layer_top_hite = currentCohort%hite - & + ( real(iv-1,r8)/currentCohort%NV * currentCohort%hite * & + prt_params%crown_depth_frac(currentCohort%pft) ) - currentPatch%layer_height_profile(cl,ft,iv) = currentPatch%layer_height_profile(cl,ft,iv) + & - (remainder * fleaf * currentCohort%c_area/currentPatch%total_canopy_area * & - (layer_top_hite+layer_bottom_hite)/2.0_r8) !average height of layer. + layer_bottom_hite = currentCohort%hite - & + ( real(iv,r8)/currentCohort%NV * currentCohort%hite * & + prt_params%crown_depth_frac(currentCohort%pft) ) - end do + fraction_exposed = 1.0_r8 + if(currentSite%snow_depth > layer_top_hite)then + fraction_exposed = 0._r8 + endif + if(currentSite%snow_depth < layer_bottom_hite)then + fraction_exposed = 1._r8 + endif + if(currentSite%snow_depth >= layer_bottom_hite .and. & + currentSite%snow_depth <= layer_top_hite) then !only partly hidden... + fraction_exposed = 1._r8 - max(0._r8,(min(1.0_r8,(currentSite%snow_depth -layer_bottom_hite)/ & + (layer_top_hite-layer_bottom_hite )))) + endif - currentCohort => currentCohort%taller + if(iv==currentCohort%NV) then + remainder = (currentCohort%treelai + currentCohort%treesai) - & + (dlower_vai(iv) - dinc_vai(iv)) + if(remainder > dinc_vai(iv) )then + write(fates_log(), *)'ED: issue with remainder', & + currentCohort%treelai,currentCohort%treesai,dinc_vai(iv), & + currentCohort%NV,remainder + + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + else + remainder = dinc_vai(iv) + end if - enddo !cohort + currentPatch%tlai_profile(cl,ft,iv) = currentPatch%tlai_profile(cl,ft,iv) + & + remainder * fleaf * currentCohort%c_area/currentPatch%total_canopy_area - ! -------------------------------------------------------------------------- + currentPatch%elai_profile(cl,ft,iv) = currentPatch%elai_profile(cl,ft,iv) + & + remainder * fleaf * currentCohort%c_area/currentPatch%total_canopy_area * & + fraction_exposed - ! If there is an upper-story, the top canopy layer - ! should have a value of exactly 1.0 in its top leaf layer - ! -------------------------------------------------------------------------- + currentPatch%tsai_profile(cl,ft,iv) = currentPatch%tsai_profile(cl,ft,iv) + & + remainder * (1._r8 - fleaf) * currentCohort%c_area/currentPatch%total_canopy_area - if ( (currentPatch%NCL_p > 1) .and. & - (sum(currentPatch%canopy_area_profile(1,:,1)) < 0.9999 )) then - write(fates_log(), *) 'FATES: canopy_area_profile was less than 1 at the canopy top' - write(fates_log(), *) 'cl: ',1 - write(fates_log(), *) 'iv: ',1 - write(fates_log(), *) 'sum(cpatch%canopy_area_profile(1,:,1)): ', & - sum(currentPatch%canopy_area_profile(1,:,1)) - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - if(currentCohort%canopy_layer==1)then - write(fates_log(), *) 'FATES: cohorts',currentCohort%dbh,currentCohort%c_area, & - currentPatch%total_canopy_area,currentPatch%area - write(fates_log(), *) 'ED: fracarea', currentCohort%pft, & + currentPatch%esai_profile(cl,ft,iv) = currentPatch%esai_profile(cl,ft,iv) + & + remainder * (1._r8 - fleaf) * currentCohort%c_area/currentPatch%total_canopy_area * & + fraction_exposed + + currentPatch%canopy_area_profile(cl,ft,iv) = currentPatch%canopy_area_profile(cl,ft,iv) + & currentCohort%c_area/currentPatch%total_canopy_area - endif + + currentPatch%layer_height_profile(cl,ft,iv) = currentPatch%layer_height_profile(cl,ft,iv) + & + (remainder * fleaf * currentCohort%c_area/currentPatch%total_canopy_area * & + (layer_top_hite+layer_bottom_hite)/2.0_r8) !average height of layer. + + end do + currentCohort => currentCohort%taller - enddo !currentCohort - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + enddo !cohort + ! -------------------------------------------------------------------------- - ! -------------------------------------------------------------------------- - ! In the following loop we are now normalizing the effective and - ! total area profiles to convert from units of leaf/stem area per vegetated - ! canopy area, into leaf/stem area per area of their own radiative column - ! which is typically the footprint of all cohorts contained in the canopy - ! layer x pft bins. - ! Also perform some checks on area normalization. - ! Check the area of each leaf layer, across pfts. - ! It should never be larger than 1 or less than 0. - ! -------------------------------------------------------------------------- + ! If there is an upper-story, the top canopy layer + ! should have a value of exactly 1.0 in its top leaf layer + ! -------------------------------------------------------------------------- - do cl = 1,currentPatch%NCL_p - do iv = 1,currentPatch%ncan(cl,ft) + if ( (currentPatch%NCL_p > 1) .and. & + (sum(currentPatch%canopy_area_profile(1,:,1)) < 0.9999 )) then + write(fates_log(), *) 'FATES: canopy_area_profile was less than 1 at the canopy top' + write(fates_log(), *) 'cl: ',1 + write(fates_log(), *) 'iv: ',1 + write(fates_log(), *) 'sum(cpatch%canopy_area_profile(1,:,1)): ', & + sum(currentPatch%canopy_area_profile(1,:,1)) + currentCohort => currentPatch%shortest + do while(associated(currentCohort)) + if(currentCohort%canopy_layer==1)then + write(fates_log(), *) 'FATES: cohorts',currentCohort%dbh,currentCohort%c_area, & + currentPatch%total_canopy_area,currentPatch%area + write(fates_log(), *) 'ED: fracarea', currentCohort%pft, & + currentCohort%c_area/currentPatch%total_canopy_area + endif + currentCohort => currentCohort%taller + enddo !currentCohort + call endrun(msg=errMsg(sourcefile, __LINE__)) - if( debug .and. sum(currentPatch%canopy_area_profile(cl,:,iv)) > 1.0001_r8 ) then + end if - write(fates_log(), *) 'FATES: A canopy_area_profile exceeded 1.0' - write(fates_log(), *) 'cl: ',cl - write(fates_log(), *) 'iv: ',iv - write(fates_log(), *) 'sum(cpatch%canopy_area_profile(cl,:,iv)): ', & - sum(currentPatch%canopy_area_profile(cl,:,iv)) - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - if(currentCohort%canopy_layer==cl)then - write(fates_log(), *) 'FATES: cohorts in layer cl = ',cl, & - currentCohort%dbh,currentCohort%c_area, & - currentPatch%total_canopy_area,currentPatch%area - write(fates_log(), *) 'ED: fracarea', currentCohort%pft, & - currentCohort%c_area/currentPatch%total_canopy_area - endif - currentCohort => currentCohort%taller - enddo !currentCohort - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - end do - do ft = 1,numpft + ! -------------------------------------------------------------------------- + ! In the following loop we are now normalizing the effective and + ! total area profiles to convert from units of leaf/stem area per vegetated + ! canopy area, into leaf/stem area per area of their own radiative column + ! which is typically the footprint of all cohorts contained in the canopy + ! layer x pft bins. + ! Also perform some checks on area normalization. + ! Check the area of each leaf layer, across pfts. + ! It should never be larger than 1 or less than 0. + ! -------------------------------------------------------------------------- + + do cl = 1,currentPatch%NCL_p do iv = 1,currentPatch%ncan(cl,ft) - if( currentPatch%canopy_area_profile(cl,ft,iv) > nearzero ) then + if( debug .and. sum(currentPatch%canopy_area_profile(cl,:,iv)) > 1.0001_r8 ) then + + write(fates_log(), *) 'FATES: A canopy_area_profile exceeded 1.0' + write(fates_log(), *) 'cl: ',cl + write(fates_log(), *) 'iv: ',iv + write(fates_log(), *) 'sum(cpatch%canopy_area_profile(cl,:,iv)): ', & + sum(currentPatch%canopy_area_profile(cl,:,iv)) + currentCohort => currentPatch%shortest + do while(associated(currentCohort)) + if(currentCohort%canopy_layer==cl)then + write(fates_log(), *) 'FATES: cohorts in layer cl = ',cl, & + currentCohort%dbh,currentCohort%c_area, & + currentPatch%total_canopy_area,currentPatch%area + write(fates_log(), *) 'ED: fracarea', currentCohort%pft, & + currentCohort%c_area/currentPatch%total_canopy_area + endif + currentCohort => currentCohort%taller + enddo !currentCohort + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + end do - currentPatch%tlai_profile(cl,ft,iv) = currentPatch%tlai_profile(cl,ft,iv) / & - currentPatch%canopy_area_profile(cl,ft,iv) + do ft = 1,numpft + do iv = 1,currentPatch%ncan(cl,ft) - currentPatch%tsai_profile(cl,ft,iv) = currentPatch%tsai_profile(cl,ft,iv) / & - currentPatch%canopy_area_profile(cl,ft,iv) + if( currentPatch%canopy_area_profile(cl,ft,iv) > nearzero ) then - currentPatch%elai_profile(cl,ft,iv) = currentPatch%elai_profile(cl,ft,iv) / & - currentPatch%canopy_area_profile(cl,ft,iv) + currentPatch%tlai_profile(cl,ft,iv) = currentPatch%tlai_profile(cl,ft,iv) / & + currentPatch%canopy_area_profile(cl,ft,iv) - currentPatch%esai_profile(cl,ft,iv) = currentPatch%esai_profile(cl,ft,iv) / & - currentPatch%canopy_area_profile(cl,ft,iv) - end if + currentPatch%tsai_profile(cl,ft,iv) = currentPatch%tsai_profile(cl,ft,iv) / & + currentPatch%canopy_area_profile(cl,ft,iv) - if(currentPatch%tlai_profile(cl,ft,iv)>nearzero )then - currentPatch%layer_height_profile(cl,ft,iv) = currentPatch%layer_height_profile(cl,ft,iv) & - /currentPatch%tlai_profile(cl,ft,iv) - end if + currentPatch%elai_profile(cl,ft,iv) = currentPatch%elai_profile(cl,ft,iv) / & + currentPatch%canopy_area_profile(cl,ft,iv) - enddo + currentPatch%esai_profile(cl,ft,iv) = currentPatch%esai_profile(cl,ft,iv) / & + currentPatch%canopy_area_profile(cl,ft,iv) + end if + if(currentPatch%tlai_profile(cl,ft,iv)>nearzero )then + currentPatch%layer_height_profile(cl,ft,iv) = currentPatch%layer_height_profile(cl,ft,iv) & + /currentPatch%tlai_profile(cl,ft,iv) + end if + + enddo + + enddo enddo - enddo - ! -------------------------------------------------------------------------- - ! Set the mask that identifies which PFT x can-layer combinations have - ! scattering elements in them. - ! -------------------------------------------------------------------------- + ! -------------------------------------------------------------------------- + ! Set the mask that identifies which PFT x can-layer combinations have + ! scattering elements in them. + ! -------------------------------------------------------------------------- - do cl = 1,currentPatch%NCL_p - do ft = 1,numpft - do iv = 1, currentPatch%nrad(cl,ft) - if(currentPatch%canopy_area_profile(cl,ft,iv) > 0._r8)then - currentPatch%canopy_mask(cl,ft) = 1 - endif - end do !iv - enddo !ft - enddo ! loop over cl + do cl = 1,currentPatch%NCL_p + do ft = 1,numpft + do iv = 1, currentPatch%nrad(cl,ft) + if(currentPatch%canopy_area_profile(cl,ft,iv) > 0._r8)then + currentPatch%canopy_mask(cl,ft) = 1 + endif + end do !iv + enddo !ft + enddo ! loop over cl + + endif !leaf distribution end if @@ -1810,8 +1896,8 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) c = fcolumn(s) do while(associated(currentPatch)) - if_nocomp_notbare: if(currentPatch%nocomp_pft_label.ne.0)then ! ignore the bare-ground-PFT patch entirely for these BC outs - + if(currentPatch%nocomp_pft_label.ne.0)then ! ignore the bare-ground-PFT patch entirely for these BC outs + ifp = ifp+1 if ( currentPatch%total_canopy_area-currentPatch%area > 0.000001_r8 ) then @@ -1931,7 +2017,7 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) total_patch_area = total_patch_area + currentPatch%area/AREA - end if if_nocomp_notbare + end if currentPatch => currentPatch%younger end do From 7182c2c073b257f0c06ac24d83d23491969275e1 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 6 Jun 2022 15:36:29 -0600 Subject: [PATCH 242/852] minor fix, removed old maxcohort declaration --- biogeochem/EDCanopyStructureMod.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 888b36586b..fc24a44e53 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -31,7 +31,6 @@ module EDCanopyStructureMod use FatesInterfaceTypesMod , only : numpft use FatesInterfaceTypesMod, only : bc_in_type use FatesPlantHydraulicsMod, only : UpdateH2OVeg,InitHydrCohort, RecruitWaterStorage - use EDTypesMod , only : maxCohortsPerPatch use PRTGenericMod, only : leaf_organ use PRTGenericMod, only : all_carbon_elements use PRTGenericMod, only : leaf_organ From a1ec3b2786537a3a9340e189cce24466de79f937 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 7 Jun 2022 16:49:05 -0400 Subject: [PATCH 243/852] fixed maxCohorts --- biogeochem/EDCanopyStructureMod.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 888b36586b..fc24a44e53 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -31,7 +31,6 @@ module EDCanopyStructureMod use FatesInterfaceTypesMod , only : numpft use FatesInterfaceTypesMod, only : bc_in_type use FatesPlantHydraulicsMod, only : UpdateH2OVeg,InitHydrCohort, RecruitWaterStorage - use EDTypesMod , only : maxCohortsPerPatch use PRTGenericMod, only : leaf_organ use PRTGenericMod, only : all_carbon_elements use PRTGenericMod, only : leaf_organ From d3d5b836c958d76e000c0f03b67da3ad1de4fc25 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 8 Jun 2022 10:32:59 -0600 Subject: [PATCH 244/852] Copied fates_params_default_api24.cdl over to the default file --- parameter_files/fates_params_default.cdl | 1433 +++++++++++----------- 1 file changed, 741 insertions(+), 692 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 45e4a3509c..569e6a1ab6 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1,17 +1,18 @@ -netcdf fates_params_default.c210629_sorted { +netcdf fates_params_default_api24 { dimensions: fates_NCWD = 4 ; fates_history_age_bins = 7 ; + fates_history_coage_bins = 2 ; + fates_history_damage_bins = 2 ; fates_history_height_bins = 6 ; fates_history_size_bins = 13 ; - fates_history_coage_bins = 2 ; + fates_hlm_pftno = 14 ; fates_hydr_organs = 4 ; fates_leafage_class = 1 ; fates_litterclass = 6 ; fates_pft = 12 ; - fates_prt_organs = 4 ; + fates_plant_organs = 4 ; fates_string_length = 60 ; - fates_hlm_pftno = 14 ; variables: double fates_history_ageclass_bin_edges(fates_history_age_bins) ; fates_history_ageclass_bin_edges:units = "yr" ; @@ -22,31 +23,39 @@ variables: double fates_history_height_bin_edges(fates_history_height_bins) ; fates_history_height_bin_edges:units = "m" ; fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; + double fates_history_damage_bin_edges(fates_history_damage_bins) ; + fates_history_damage_bin_edges:units = "% crown loss" ; + fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; fates_history_sizeclass_bin_edges:units = "cm" ; fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; - double fates_hydr_htftype_node(fates_hydr_organs) ; - fates_hydr_htftype_node:units = "unitless" ; - fates_hydr_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; - fates_hydr_htftype_node:possible_values = "1: Christofferson et al. 2016 (TFS); 2: Van Genuchten 1980" ; - double fates_prt_organ_id(fates_prt_organs) ; - fates_prt_organ_id:units = "index, unitless" ; - fates_prt_organ_id:long_name = "This is the global index the organ in this file is associated with in PRTGenericMod.F90" ; + double fates_alloc_organ_id(fates_plant_organs) ; + fates_alloc_organ_id:units = "unitless" ; + fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; + double fates_hydro_htftype_node(fates_hydr_organs) ; + fates_hydro_htftype_node:units = "unitless" ; + fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; char fates_pftname(fates_pft, fates_string_length) ; fates_pftname:units = "unitless - string" ; fates_pftname:long_name = "Description of plant type" ; - char fates_hydr_organname_node(fates_hydr_organs, fates_string_length) ; - fates_hydr_organname_node:units = "unitless - string" ; - fates_hydr_organname_node:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; + char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; + fates_hydro_organ_name:units = "unitless - string" ; + fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; + char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; + fates_alloc_organ_name:units = "unitless - string" ; + fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; 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_prt_organ_name(fates_prt_organs, fates_string_length) ; - fates_prt_organ_name:units = "unitless - string" ; - fates_prt_organ_name:long_name = "Name of plant organs (order must match PRTGenericMod.F90)" ; + 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" ; double fates_alloc_storage_cushion(fates_pft) ; fates_alloc_storage_cushion:units = "fraction" ; fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; + double fates_alloc_store_priority_frac(fates_pft) ; + fates_alloc_store_priority_frac:units = "unitless" ; + fates_alloc_store_priority_frac:long_name = "for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage" ; double fates_allom_agb1(fates_pft) ; fates_allom_agb1:units = "variable" ; fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; @@ -65,14 +74,15 @@ variables: double fates_allom_amode(fates_pft) ; fates_allom_amode:units = "index" ; fates_allom_amode:long_name = "AGB allometry function index." ; - fates_allom_amode:possible_values = "1: Saldarriaga 1998; 2: 2 parameter power law; 3: Chave 2014" ; double fates_allom_blca_expnt_diff(fates_pft) ; fates_allom_blca_expnt_diff:units = "unitless" ; fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; double fates_allom_cmode(fates_pft) ; fates_allom_cmode:units = "index" ; fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; - fates_allom_cmode:possible_values = "1: Constant fraction on AGB" ; + double fates_allom_crown_depth_frac(fates_pft) ; + fates_allom_crown_depth_frac:units = "fraction" ; + fates_allom_crown_depth_frac:long_name = "the depth of a cohort crown as a fraction of its height" ; double fates_allom_d2bl1(fates_pft) ; fates_allom_d2bl1:units = "variable" ; fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; @@ -103,14 +113,21 @@ variables: double fates_allom_fmode(fates_pft) ; fates_allom_fmode:units = "index" ; fates_allom_fmode:long_name = "fine root biomass allometry function index." ; - fates_allom_fmode:possible_values = "1: constant fraction of trimmed bleaf; 2: constant fraction of untrimmed bleaf." ; + double fates_allom_fnrt_prof_a(fates_pft) ; + fates_allom_fnrt_prof_a:units = "unitless" ; + fates_allom_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; + double fates_allom_fnrt_prof_b(fates_pft) ; + fates_allom_fnrt_prof_b:units = "unitless" ; + fates_allom_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; + double fates_allom_fnrt_prof_mode(fates_pft) ; + fates_allom_fnrt_prof_mode:units = "index" ; + fates_allom_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; double fates_allom_frbstor_repro(fates_pft) ; fates_allom_frbstor_repro:units = "fraction" ; fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; double fates_allom_hmode(fates_pft) ; fates_allom_hmode:units = "index" ; fates_allom_hmode:long_name = "height allometry function index." ; - fates_allom_hmode:possible_values = "1: OBrien 1995; 2: Poorter 2006; 3: 2 parameter power law; 4: Chave 2014; 5: Martinez-Cano 2019." ; double fates_allom_l2fr(fates_pft) ; fates_allom_l2fr:units = "gC/gC" ; fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; @@ -123,18 +140,15 @@ variables: double fates_allom_lmode(fates_pft) ; fates_allom_lmode:units = "index" ; fates_allom_lmode:long_name = "leaf biomass allometry function index." ; - fates_allom_lmode:possible_values = "1: Saldarriaga 1998 (capped-dbh power law); 2: generic power law; 3: generic capped-dbh power law." ; double fates_allom_sai_scaler(fates_pft) ; fates_allom_sai_scaler:units = "m2/m2" ; fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; double fates_allom_smode(fates_pft) ; fates_allom_smode:units = "index" ; fates_allom_smode:long_name = "sapwood allometry function index." ; - fates_allom_smode:possible_values = "1: sapwood area proportional to leaf area based on target leaf biomass" ; double fates_allom_stmode(fates_pft) ; fates_allom_stmode:units = "index" ; fates_allom_stmode:long_name = "storage allometry function index." ; - fates_allom_stmode:possible_values = "1: target storage proportional to trimmed maximum leaf biomass." ; double fates_allom_zroot_k(fates_pft) ; fates_allom_zroot_k:units = "unitless" ; fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; @@ -150,151 +164,181 @@ variables: double fates_allom_zroot_min_z(fates_pft) ; fates_allom_zroot_min_z:units = "m" ; fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; - double fates_branch_turnover(fates_pft) ; - fates_branch_turnover:units = "yr" ; - fates_branch_turnover:long_name = "turnover time of branches" ; double fates_c2b(fates_pft) ; fates_c2b:units = "ratio" ; fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; + double fates_cnp_eca_alpha_ptase(fates_pft) ; + fates_cnp_eca_alpha_ptase:units = "g/m3" ; + fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; + double fates_cnp_eca_decompmicc(fates_pft) ; + fates_cnp_eca_decompmicc:units = "gC/m3" ; + fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; + double fates_cnp_eca_km_nh4(fates_pft) ; + fates_cnp_eca_km_nh4:units = "gN/m3" ; + fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; + double fates_cnp_eca_km_no3(fates_pft) ; + fates_cnp_eca_km_no3:units = "gN/m3" ; + fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; + double fates_cnp_eca_km_p(fates_pft) ; + fates_cnp_eca_km_p:units = "gP/m3" ; + fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; + double fates_cnp_eca_km_ptase(fates_pft) ; + fates_cnp_eca_km_ptase:units = "gP/m3" ; + fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; + double fates_cnp_eca_lambda_ptase(fates_pft) ; + fates_cnp_eca_lambda_ptase:units = "g/m3" ; + fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; + double fates_cnp_eca_vmax_nh4(fates_pft) ; + fates_cnp_eca_vmax_nh4:units = "gN/gC/s" ; + fates_cnp_eca_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA)" ; + double fates_cnp_eca_vmax_no3(fates_pft) ; + fates_cnp_eca_vmax_no3:units = "gN/gC/s" ; + fates_cnp_eca_vmax_no3:long_name = "maximum production rate for plant no3 uptake (ECA)" ; + double fates_cnp_eca_vmax_ptase(fates_pft) ; + fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; + fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; + double fates_cnp_fnrt_adapt_tscale(fates_pft) ; + fates_cnp_fnrt_adapt_tscale:units = "days" ; + fates_cnp_fnrt_adapt_tscale:long_name = "Number of days that is shortest possible doubling period for fine-root adaptation to C/N/P balance" ; + double fates_cnp_nfix1(fates_pft) ; + fates_cnp_nfix1:units = "NA" ; + fates_cnp_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; + double fates_cnp_nitr_store_ratio(fates_pft) ; + fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; + fates_cnp_nitr_store_ratio:long_name = "storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code)" ; + double fates_cnp_phos_store_ratio(fates_pft) ; + fates_cnp_phos_store_ratio:units = "(gP/gP)" ; + fates_cnp_phos_store_ratio:long_name = "storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code)" ; + double fates_cnp_prescribed_nuptake(fates_pft) ; + fates_cnp_prescribed_nuptake:units = "fraction" ; + fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; + double fates_cnp_prescribed_puptake(fates_pft) ; + fates_cnp_prescribed_puptake:units = "fraction" ; + fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; + double fates_cnp_rd_vmax_n(fates_pft) ; + fates_cnp_rd_vmax_n:units = "gN/gC/s" ; + fates_cnp_rd_vmax_n:long_name = "maximum production rate for compbined (NH4+NO3) uptake (RD)" ; + double fates_cnp_store_ovrflw_frac(fates_pft) ; + fates_cnp_store_ovrflw_frac:units = "fraction" ; + fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; + fates_cnp_store_ovrflw_frac:use_case = "None" ; + double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_nitr_retrans:units = "fraction" ; + fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; + double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_phos_retrans:units = "fraction" ; + fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; + double fates_cnp_vmax_p(fates_pft) ; + fates_cnp_vmax_p:units = "gP/gC/s" ; + fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; + double fates_damage_frac(fates_pft) ; + fates_damage_frac:units = "fraction" ; + fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; + double fates_damage_mort_p1(fates_pft) ; + fates_damage_mort_p1:units = "fraction" ; + fates_damage_mort_p1:long_name = "inflection point of damage mortality function, a value of 0.8 means 50% mortality with 80% loss of crown, turn off with a large number" ; + double fates_damage_mort_p2(fates_pft) ; + fates_damage_mort_p2:units = "unitless" ; + fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; + 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_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" ; - double fates_displar(fates_pft) ; - fates_displar:units = "unitless" ; - fates_displar:long_name = "Ratio of displacement height to canopy top height" ; - double fates_eca_alpha_ptase(fates_pft) ; - fates_eca_alpha_ptase:units = "g/m3" ; - fates_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; - double fates_eca_decompmicc(fates_pft) ; - fates_eca_decompmicc:units = "gC/m3" ; - fates_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; - double fates_eca_km_nh4(fates_pft) ; - fates_eca_km_nh4:units = "gN/m3" ; - fates_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; - double fates_eca_km_no3(fates_pft) ; - fates_eca_km_no3:units = "gN/m3" ; - fates_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; - double fates_eca_km_p(fates_pft) ; - fates_eca_km_p:units = "gP/m3" ; - fates_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; - double fates_eca_km_ptase(fates_pft) ; - fates_eca_km_ptase:units = "gP/m3" ; - fates_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; - double fates_eca_lambda_ptase(fates_pft) ; - fates_eca_lambda_ptase:units = "g/m3" ; - fates_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; - double fates_eca_vmax_nh4(fates_pft) ; - fates_eca_vmax_nh4:units = "gN/gC/s" ; - fates_eca_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA)" ; - double fates_eca_vmax_no3(fates_pft) ; - fates_eca_vmax_no3:units = "gN/gC/s" ; - fates_eca_vmax_no3:long_name = "maximum production rate for plant no3 uptake (ECA)" ; - double fates_eca_vmax_p(fates_pft) ; - fates_eca_vmax_p:units = "gP/gC/s" ; - fates_eca_vmax_p:long_name = "maximum production rate for plant p uptake (ECA)" ; - double fates_eca_vmax_ptase(fates_pft) ; - fates_eca_vmax_ptase:units = "gP/m2/s" ; - fates_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; double fates_fire_alpha_SH(fates_pft) ; fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; double fates_fire_bark_scaler(fates_pft) ; fates_fire_bark_scaler:units = "fraction" ; fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; - double fates_fire_crown_depth_frac(fates_pft) ; - fates_fire_crown_depth_frac:units = "fraction" ; - fates_fire_crown_depth_frac:long_name = "the depth of a cohorts crown as a fraction of its height" ; double fates_fire_crown_kill(fates_pft) ; fates_fire_crown_kill:units = "NA" ; fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; - double fates_fnrt_prof_a(fates_pft) ; - fates_fnrt_prof_a:units = "unitless" ; - fates_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; - double fates_fnrt_prof_b(fates_pft) ; - fates_fnrt_prof_b:units = "unitless" ; - fates_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; - double fates_fnrt_prof_mode(fates_pft) ; - fates_fnrt_prof_mode:units = "index" ; - fates_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; - double fates_fr_fcel(fates_pft) ; - fates_fr_fcel:units = "fraction" ; - fates_fr_fcel:long_name = "Fine root litter cellulose fraction" ; - double fates_fr_flab(fates_pft) ; - fates_fr_flab:units = "fraction" ; - fates_fr_flab:long_name = "Fine root litter labile fraction" ; - double fates_fr_flig(fates_pft) ; - fates_fr_flig:units = "fraction" ; - fates_fr_flig:long_name = "Fine root litter lignin fraction" ; + double fates_frag_fnrt_fcel(fates_pft) ; + fates_frag_fnrt_fcel:units = "fraction" ; + fates_frag_fnrt_fcel:long_name = "Fine root litter cellulose fraction" ; + double fates_frag_fnrt_flab(fates_pft) ; + fates_frag_fnrt_flab:units = "fraction" ; + fates_frag_fnrt_flab:long_name = "Fine root litter labile fraction" ; + double fates_frag_fnrt_flig(fates_pft) ; + fates_frag_fnrt_flig:units = "fraction" ; + fates_frag_fnrt_flig:long_name = "Fine root litter lignin fraction" ; + double fates_frag_leaf_fcel(fates_pft) ; + fates_frag_leaf_fcel:units = "fraction" ; + fates_frag_leaf_fcel:long_name = "Leaf litter cellulose fraction" ; + double fates_frag_leaf_flab(fates_pft) ; + fates_frag_leaf_flab:units = "fraction" ; + fates_frag_leaf_flab:long_name = "Leaf litter labile fraction" ; + double fates_frag_leaf_flig(fates_pft) ; + fates_frag_leaf_flig:units = "fraction" ; + fates_frag_leaf_flig:long_name = "Leaf litter lignin fraction" ; + double fates_frag_seed_decay_rate(fates_pft) ; + fates_frag_seed_decay_rate:units = "yr-1" ; + fates_frag_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; double fates_grperc(fates_pft) ; fates_grperc:units = "unitless" ; fates_grperc:long_name = "Growth respiration factor" ; - double fates_hydr_avuln_gs(fates_pft) ; - fates_hydr_avuln_gs:units = "unitless" ; - fates_hydr_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; - double fates_hydr_avuln_node(fates_hydr_organs, fates_pft) ; - fates_hydr_avuln_node:units = "unitless" ; - fates_hydr_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; - double fates_hydr_epsil_node(fates_hydr_organs, fates_pft) ; - fates_hydr_epsil_node:units = "MPa" ; - fates_hydr_epsil_node:long_name = "bulk elastic modulus" ; - double fates_hydr_fcap_node(fates_hydr_organs, fates_pft) ; - fates_hydr_fcap_node:units = "unitless" ; - fates_hydr_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; - double fates_hydr_k_lwp(fates_pft) ; - fates_hydr_k_lwp:units = "unitless" ; - fates_hydr_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; - fates_hydr_k_lwp:possible_values = "0: turns off leaf humidity effects on conductance. 1-10 activates humidity effects" ; - double fates_hydr_kmax_node(fates_hydr_organs, fates_pft) ; - fates_hydr_kmax_node:units = "kg/MPa/m/s" ; - fates_hydr_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; - double fates_hydr_p50_gs(fates_pft) ; - fates_hydr_p50_gs:units = "MPa" ; - fates_hydr_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; - double fates_hydr_p50_node(fates_hydr_organs, fates_pft) ; - fates_hydr_p50_node:units = "MPa" ; - fates_hydr_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; - double fates_hydr_p_taper(fates_pft) ; - fates_hydr_p_taper:units = "unitless" ; - fates_hydr_p_taper:long_name = "xylem taper exponent" ; - double fates_hydr_pinot_node(fates_hydr_organs, fates_pft) ; - fates_hydr_pinot_node:units = "MPa" ; - fates_hydr_pinot_node:long_name = "osmotic potential at full turgor" ; - double fates_hydr_pitlp_node(fates_hydr_organs, fates_pft) ; - fates_hydr_pitlp_node:units = "MPa" ; - fates_hydr_pitlp_node:long_name = "turgor loss point" ; - double fates_hydr_resid_node(fates_hydr_organs, fates_pft) ; - fates_hydr_resid_node:units = "cm3/cm3" ; - fates_hydr_resid_node:long_name = "residual water conent" ; - double fates_hydr_rfrac_stem(fates_pft) ; - fates_hydr_rfrac_stem:units = "fraction" ; - fates_hydr_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; - double fates_hydr_rs2(fates_pft) ; - fates_hydr_rs2:units = "m" ; - fates_hydr_rs2:long_name = "absorbing root radius" ; - double fates_hydr_srl(fates_pft) ; - fates_hydr_srl:units = "m g-1" ; - fates_hydr_srl:long_name = "specific root length" ; - double fates_hydr_thetas_node(fates_hydr_organs, fates_pft) ; - fates_hydr_thetas_node:units = "cm3/cm3" ; - fates_hydr_thetas_node:long_name = "saturated water content" ; - double fates_hydr_vg_alpha_node(fates_hydr_organs, fates_pft) ; - fates_hydr_vg_alpha_node:units = "MPa-1" ; - fates_hydr_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; - double fates_hydr_vg_m_node(fates_hydr_organs, fates_pft) ; - fates_hydr_vg_m_node:units = "unitless" ; - fates_hydr_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; - double fates_hydr_vg_n_node(fates_hydr_organs, fates_pft) ; - fates_hydr_vg_n_node:units = "unitless" ; - fates_hydr_vg_n_node:long_name = "(used if hydr_htftype_node = 2),n in van Genuchten 1980 model, pore size distribution parameter" ; + double fates_hydro_avuln_gs(fates_pft) ; + fates_hydro_avuln_gs:units = "unitless" ; + fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; + double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; + fates_hydro_avuln_node:units = "unitless" ; + fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; + double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; + fates_hydro_epsil_node:units = "MPa" ; + fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; + double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; + fates_hydro_fcap_node:units = "unitless" ; + fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; + double fates_hydro_k_lwp(fates_pft) ; + fates_hydro_k_lwp:units = "unitless" ; + fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; + double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; + fates_hydro_kmax_node:units = "kg/MPa/m/s" ; + fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; + double fates_hydro_p50_gs(fates_pft) ; + fates_hydro_p50_gs:units = "MPa" ; + fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; + double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; + fates_hydro_p50_node:units = "MPa" ; + fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; + double fates_hydro_p_taper(fates_pft) ; + fates_hydro_p_taper:units = "unitless" ; + fates_hydro_p_taper:long_name = "xylem taper exponent" ; + double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pinot_node:units = "MPa" ; + fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; + double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pitlp_node:units = "MPa" ; + fates_hydro_pitlp_node:long_name = "turgor loss point" ; + double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; + fates_hydro_resid_node:units = "cm3/cm3" ; + fates_hydro_resid_node:long_name = "residual water conent" ; + double fates_hydro_rfrac_stem(fates_pft) ; + fates_hydro_rfrac_stem:units = "fraction" ; + fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; + double fates_hydro_rs2(fates_pft) ; + fates_hydro_rs2:units = "m" ; + fates_hydro_rs2:long_name = "absorbing root radius" ; + double fates_hydro_srl(fates_pft) ; + fates_hydro_srl:units = "m g-1" ; + fates_hydro_srl:long_name = "specific root length" ; + double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; + fates_hydro_thetas_node:units = "cm3/cm3" ; + fates_hydro_thetas_node:long_name = "saturated water content" ; + double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_alpha_node:units = "MPa-1" ; + fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; + double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_m_node:units = "unitless" ; + fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; + 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_leaf_c3psn(fates_pft) ; fates_leaf_c3psn:units = "flag" ; fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; - double fates_leaf_clumping_index(fates_pft) ; - fates_leaf_clumping_index:units = "fraction (0-1)" ; - fates_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; - double fates_leaf_diameter(fates_pft) ; - fates_leaf_diameter:units = "m" ; - fates_leaf_diameter:long_name = "Characteristic leaf dimension" ; double fates_leaf_jmaxha(fates_pft) ; fates_leaf_jmaxha:units = "J/mol" ; fates_leaf_jmaxha:long_name = "activation energy for jmax" ; @@ -304,9 +348,6 @@ variables: double fates_leaf_jmaxse(fates_pft) ; fates_leaf_jmaxse:units = "J/mol/K" ; fates_leaf_jmaxse:long_name = "entropy term for jmax" ; - double fates_leaf_long(fates_leafage_class, fates_pft) ; - fates_leaf_long:units = "yr" ; - fates_leaf_long:long_name = "Leaf longevity (ie turnover timescale)" ; double fates_leaf_slamax(fates_pft) ; fates_leaf_slamax:units = "m^2/gC" ; fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; @@ -322,9 +363,6 @@ variables: double fates_leaf_stomatal_slope_medlyn(fates_pft) ; fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; - double fates_leaf_stor_priority(fates_pft) ; - fates_leaf_stor_priority:units = "unitless" ; - fates_leaf_stor_priority:long_name = "factor governing priority of replacing storage with NPP" ; double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; @@ -337,18 +375,6 @@ variables: double fates_leaf_vcmaxse(fates_pft) ; fates_leaf_vcmaxse:units = "J/mol/K" ; fates_leaf_vcmaxse:long_name = "entropy term for vcmax" ; - double fates_leaf_xl(fates_pft) ; - fates_leaf_xl:units = "unitless" ; - fates_leaf_xl:long_name = "Leaf/stem orientation index" ; - double fates_lf_fcel(fates_pft) ; - fates_lf_fcel:units = "fraction" ; - fates_lf_fcel:long_name = "Leaf litter cellulose fraction" ; - double fates_lf_flab(fates_pft) ; - fates_lf_flab:units = "fraction" ; - fates_lf_flab:long_name = "Leaf litter labile fraction" ; - double fates_lf_flig(fates_pft) ; - fates_lf_flig:units = "fraction" ; - fates_lf_flig:long_name = "Leaf litter lignin fraction" ; double fates_maintresp_reduction_curvature(fates_pft) ; fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; @@ -373,6 +399,12 @@ variables: double fates_mort_ip_size_senescence(fates_pft) ; fates_mort_ip_size_senescence:units = "dbh cm" ; fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; + double fates_mort_prescribed_canopy(fates_pft) ; + fates_mort_prescribed_canopy:units = "1/yr" ; + fates_mort_prescribed_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; + double fates_mort_prescribed_understory(fates_pft) ; + fates_mort_prescribed_understory:units = "1/yr" ; + fates_mort_prescribed_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; double fates_mort_r_age_senescence(fates_pft) ; fates_mort_r_age_senescence:units = "mortality rate year^-1" ; fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; @@ -388,21 +420,24 @@ variables: double fates_mort_scalar_hydrfailure(fates_pft) ; fates_mort_scalar_hydrfailure:units = "1/yr" ; fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; - double fates_nfix1(fates_pft) ; - fates_nfix1:units = "NA" ; - fates_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; - double fates_nfix2(fates_pft) ; - fates_nfix2:units = "NA" ; - fates_nfix2:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; - double fates_nitr_store_ratio(fates_pft) ; - fates_nitr_store_ratio:units = "(gN/gN)" ; - fates_nitr_store_ratio:long_name = "ratio of storeable N, to functional N bound in cell structures of leaf,root,sap" ; + double fates_nonhydro_smpsc(fates_pft) ; + fates_nonhydro_smpsc:units = "mm" ; + fates_nonhydro_smpsc:long_name = "Soil water potential at full stomatal closure" ; + double fates_nonhydro_smpso(fates_pft) ; + fates_nonhydro_smpso:units = "mm" ; + fates_nonhydro_smpso:long_name = "Soil water potential at full stomatal opening" ; double fates_phen_cold_size_threshold(fates_pft) ; fates_phen_cold_size_threshold:units = "cm" ; fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; double fates_phen_evergreen(fates_pft) ; fates_phen_evergreen:units = "logical flag" ; fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; + double fates_phen_flush_fraction(fates_pft) ; + fates_phen_flush_fraction:units = "fraction" ; + fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; + double fates_phen_fnrt_drop_frac(fates_pft) ; + fates_phen_fnrt_drop_frac:units = "fraction" ; + fates_phen_fnrt_drop_frac:long_name = "fraction of fine roots to drop during drought or cold" ; double fates_phen_season_decid(fates_pft) ; fates_phen_season_decid:units = "logical flag" ; fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; @@ -412,139 +447,108 @@ variables: double fates_phen_stress_decid(fates_pft) ; fates_phen_stress_decid:units = "logical flag" ; fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; - double fates_phenflush_fraction(fates_pft) ; - fates_phenflush_fraction:units = "fraction" ; - fates_phenflush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; - double fates_phos_store_ratio(fates_pft) ; - fates_phos_store_ratio:units = "(gP/gP)" ; - fates_phos_store_ratio:long_name = "ratio of storeable P, to functional P bound in cell structures of leaf,root,sap" ; - double fates_prescribed_mortality_canopy(fates_pft) ; - fates_prescribed_mortality_canopy:units = "1/yr" ; - fates_prescribed_mortality_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; - double fates_prescribed_mortality_understory(fates_pft) ; - fates_prescribed_mortality_understory:units = "1/yr" ; - fates_prescribed_mortality_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; double fates_prescribed_npp_canopy(fates_pft) ; fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; double fates_prescribed_npp_understory(fates_pft) ; fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; - double fates_prescribed_nuptake(fates_pft) ; - fates_prescribed_nuptake:units = "fraction" ; - fates_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; - double fates_prescribed_puptake(fates_pft) ; - fates_prescribed_puptake:units = "fraction" ; - fates_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; - double fates_prescribed_recruitment(fates_pft) ; - fates_prescribed_recruitment:units = "n/yr" ; - fates_prescribed_recruitment:long_name = "recruitment rate for prescribed physiology mode" ; - double fates_prt_alloc_priority(fates_prt_organs, fates_pft) ; - fates_prt_alloc_priority:units = "index (0-fates_prt_organs)" ; - fates_prt_alloc_priority:long_name = "Priority order for allocation (C storage=2)" ; - double fates_prt_nitr_stoich_p1(fates_prt_organs, fates_pft) ; - fates_prt_nitr_stoich_p1:units = "(gN/gC)" ; - fates_prt_nitr_stoich_p1:long_name = "nitrogen stoichiometry, parameter 1" ; - double fates_prt_nitr_stoich_p2(fates_prt_organs, fates_pft) ; - fates_prt_nitr_stoich_p2:units = "(gN/gC)" ; - fates_prt_nitr_stoich_p2:long_name = "nitrogen stoichiometry, parameter 2" ; - double fates_prt_phos_stoich_p1(fates_prt_organs, fates_pft) ; - fates_prt_phos_stoich_p1:units = "(gP/gC)" ; - fates_prt_phos_stoich_p1:long_name = "phosphorous stoichiometry, parameter 1" ; - double fates_prt_phos_stoich_p2(fates_prt_organs, fates_pft) ; - fates_prt_phos_stoich_p2:units = "(gP/gC)" ; - fates_prt_phos_stoich_p2:long_name = "phosphorous stoichiometry, parameter 2" ; - double fates_recruit_hgt_min(fates_pft) ; - fates_recruit_hgt_min:units = "m" ; - fates_recruit_hgt_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; - double fates_recruit_initd(fates_pft) ; - fates_recruit_initd:units = "stems/m2" ; - fates_recruit_initd:long_name = "initial seedling density for a cold-start near-bare-ground simulation" ; - double fates_rholnir(fates_pft) ; - fates_rholnir:units = "fraction" ; - fates_rholnir:long_name = "Leaf reflectance: near-IR" ; - double fates_rholvis(fates_pft) ; - fates_rholvis:units = "fraction" ; - fates_rholvis:long_name = "Leaf reflectance: visible" ; - double fates_rhosnir(fates_pft) ; - fates_rhosnir:units = "fraction" ; - fates_rhosnir:long_name = "Stem reflectance: near-IR" ; - double fates_rhosvis(fates_pft) ; - fates_rhosvis:units = "fraction" ; - fates_rhosvis:long_name = "Stem reflectance: visible" ; - double fates_root_long(fates_pft) ; - fates_root_long:units = "yr" ; - fates_root_long:long_name = "root longevity (alternatively, turnover time)" ; - double fates_seed_alloc(fates_pft) ; - fates_seed_alloc:units = "fraction" ; - fates_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; - double fates_seed_alloc_mature(fates_pft) ; - fates_seed_alloc_mature:units = "fraction" ; - fates_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; - double fates_seed_dbh_repro_threshold(fates_pft) ; - fates_seed_dbh_repro_threshold:units = "cm" ; - fates_seed_dbh_repro_threshold:long_name = "the diameter (if any) where the plant will start extra clonal allocation to the seed pool" ; - double fates_seed_decay_rate(fates_pft) ; - fates_seed_decay_rate:units = "yr-1" ; - fates_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; - double fates_seed_germination_rate(fates_pft) ; - fates_seed_germination_rate:units = "yr-1" ; - fates_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; - double fates_seed_suppl(fates_pft) ; - fates_seed_suppl:units = "KgC/m2/yr" ; - fates_seed_suppl:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; - double fates_senleaf_long_fdrought(fates_pft) ; - fates_senleaf_long_fdrought:units = "unitless[0-1]" ; - fates_senleaf_long_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; - double fates_smpsc(fates_pft) ; - fates_smpsc:units = "mm" ; - fates_smpsc:long_name = "Soil water potential at full stomatal closure" ; - double fates_smpso(fates_pft) ; - fates_smpso:units = "mm" ; - fates_smpso:long_name = "Soil water potential at full stomatal opening" ; - double fates_taulnir(fates_pft) ; - fates_taulnir:units = "fraction" ; - fates_taulnir:long_name = "Leaf transmittance: near-IR" ; - double fates_taulvis(fates_pft) ; - fates_taulvis:units = "fraction" ; - fates_taulvis:long_name = "Leaf transmittance: visible" ; - double fates_tausnir(fates_pft) ; - fates_tausnir:units = "fraction" ; - fates_tausnir:long_name = "Stem transmittance: near-IR" ; - double fates_tausvis(fates_pft) ; - fates_tausvis:units = "fraction" ; - fates_tausvis:long_name = "Stem transmittance: visible" ; + double fates_rad_leaf_clumping_index(fates_pft) ; + fates_rad_leaf_clumping_index:units = "fraction (0-1)" ; + fates_rad_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; + double fates_rad_leaf_rhonir(fates_pft) ; + fates_rad_leaf_rhonir:units = "fraction" ; + fates_rad_leaf_rhonir:long_name = "Leaf reflectance: near-IR" ; + double fates_rad_leaf_rhovis(fates_pft) ; + fates_rad_leaf_rhovis:units = "fraction" ; + fates_rad_leaf_rhovis:long_name = "Leaf reflectance: visible" ; + double fates_rad_leaf_taunir(fates_pft) ; + fates_rad_leaf_taunir:units = "fraction" ; + fates_rad_leaf_taunir:long_name = "Leaf transmittance: near-IR" ; + double fates_rad_leaf_tauvis(fates_pft) ; + fates_rad_leaf_tauvis:units = "fraction" ; + fates_rad_leaf_tauvis:long_name = "Leaf transmittance: visible" ; + double fates_rad_leaf_xl(fates_pft) ; + fates_rad_leaf_xl:units = "unitless" ; + fates_rad_leaf_xl:long_name = "Leaf/stem orientation index" ; + double fates_rad_stem_rhonir(fates_pft) ; + fates_rad_stem_rhonir:units = "fraction" ; + fates_rad_stem_rhonir:long_name = "Stem reflectance: near-IR" ; + double fates_rad_stem_rhovis(fates_pft) ; + fates_rad_stem_rhovis:units = "fraction" ; + fates_rad_stem_rhovis:long_name = "Stem reflectance: visible" ; + double fates_rad_stem_taunir(fates_pft) ; + fates_rad_stem_taunir:units = "fraction" ; + fates_rad_stem_taunir:long_name = "Stem transmittance: near-IR" ; + double fates_rad_stem_tauvis(fates_pft) ; + fates_rad_stem_tauvis:units = "fraction" ; + fates_rad_stem_tauvis:long_name = "Stem transmittance: visible" ; + double fates_recruit_height_min(fates_pft) ; + fates_recruit_height_min:units = "m" ; + fates_recruit_height_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; + double fates_recruit_init_density(fates_pft) ; + fates_recruit_init_density:units = "stems/m2" ; + fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation" ; + double fates_recruit_prescribed_rate(fates_pft) ; + fates_recruit_prescribed_rate:units = "n/yr" ; + fates_recruit_prescribed_rate:long_name = "recruitment rate for prescribed physiology mode" ; + double fates_recruit_seed_alloc(fates_pft) ; + fates_recruit_seed_alloc:units = "fraction" ; + fates_recruit_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; + double fates_recruit_seed_alloc_mature(fates_pft) ; + fates_recruit_seed_alloc_mature:units = "fraction" ; + fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; + double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; + fates_recruit_seed_dbh_repro_threshold:units = "cm" ; + fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter (if any) where the plant will start extra clonal allocation to the seed pool" ; + double fates_recruit_seed_germination_rate(fates_pft) ; + fates_recruit_seed_germination_rate:units = "yr-1" ; + fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; + double fates_recruit_seed_supplement(fates_pft) ; + fates_recruit_seed_supplement:units = "KgC/m2/yr" ; + fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; + double fates_stoich_nitr(fates_plant_organs, fates_pft) ; + fates_stoich_nitr:units = "gN/gC" ; + fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; + double fates_stoich_phos(fates_plant_organs, fates_pft) ; + fates_stoich_phos:units = "gP/gC" ; + fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; double fates_trim_inc(fates_pft) ; fates_trim_inc:units = "m2/m2" ; fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; double fates_trim_limit(fates_pft) ; fates_trim_limit:units = "m2/m2" ; fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; - double fates_turnover_carb_retrans(fates_prt_organs, fates_pft) ; - fates_turnover_carb_retrans:units = "-" ; - fates_turnover_carb_retrans:long_name = "retranslocation fraction of carbon in turnover" ; - double fates_turnover_nitr_retrans(fates_prt_organs, fates_pft) ; - fates_turnover_nitr_retrans:units = "-" ; - fates_turnover_nitr_retrans:long_name = "retranslocation fraction of nitrogen in turnover" ; - double fates_turnover_phos_retrans(fates_prt_organs, fates_pft) ; - fates_turnover_phos_retrans:units = "-" ; - fates_turnover_phos_retrans:long_name = "retranslocation fraction of phosphorous in turnover, parameter 1" ; - double fates_turnover_retrans_mode(fates_pft) ; - fates_turnover_retrans_mode:units = "index" ; - fates_turnover_retrans_mode:long_name = "retranslocation method for leaf/fineroot turnover." ; - fates_turnover_retrans_mode:possible_values = "1: constant fraction." ; + double fates_turb_displar(fates_pft) ; + fates_turb_displar:units = "unitless" ; + fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; + double fates_turb_leaf_diameter(fates_pft) ; + fates_turb_leaf_diameter:units = "m" ; + fates_turb_leaf_diameter:long_name = "Characteristic leaf dimension" ; + double fates_turb_z0mr(fates_pft) ; + fates_turb_z0mr:units = "unitless" ; + fates_turb_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; + double fates_turnover_branch(fates_pft) ; + fates_turnover_branch:units = "yr" ; + fates_turnover_branch:long_name = "turnover time of branches" ; + double fates_turnover_fnrt(fates_pft) ; + fates_turnover_fnrt:units = "yr" ; + fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; + double fates_turnover_leaf(fates_leafage_class, fates_pft) ; + fates_turnover_leaf:units = "yr" ; + fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; + double fates_turnover_senleaf_fdrought(fates_pft) ; + fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; + fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; double fates_wood_density(fates_pft) ; fates_wood_density:units = "g/cm3" ; fates_wood_density:long_name = "mean density of woody tissue in plant" ; double fates_woody(fates_pft) ; fates_woody:units = "logical flag" ; fates_woody:long_name = "Binary woody lifeform flag" ; - double fates_z0mr(fates_pft) ; - fates_z0mr:units = "unitless" ; - fates_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; - double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; - fates_hlm_pft_map:units = "area fraction" ; - fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; double fates_fire_FBD(fates_litterclass) ; fates_fire_FBD:units = "kg Biomass/m3" ; fates_fire_FBD:long_name = "fuel bulk density" ; @@ -569,18 +573,21 @@ variables: double fates_fire_SAV(fates_litterclass) ; fates_fire_SAV:units = "cm-1" ; fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; - double fates_max_decomp(fates_litterclass) ; - fates_max_decomp:units = "yr-1" ; - fates_max_decomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; - double fates_CWD_frac(fates_NCWD) ; - fates_CWD_frac:units = "fraction" ; - fates_CWD_frac:long_name = "fraction of woody (bdead+bsw) biomass destined for CWD pool" ; + double fates_frag_maxdecomp(fates_litterclass) ; + fates_frag_maxdecomp:units = "yr-1" ; + fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; + 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_base_mr_20 ; fates_base_mr_20:units = "gC/gN/s" ; fates_base_mr_20:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; 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" ; + double fates_cnp_eca_plant_escalar ; + fates_cnp_eca_plant_escalar:units = "" ; + fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; double fates_cohort_age_fusion_tol ; fates_cohort_age_fusion_tol:units = "unitless" ; fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; @@ -590,18 +597,15 @@ variables: double fates_comp_excln ; fates_comp_excln:units = "none" ; fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; - double fates_cwd_fcel ; - fates_cwd_fcel:units = "unitless" ; - fates_cwd_fcel:long_name = "Cellulose fraction for CWD" ; - double fates_cwd_flig ; - fates_cwd_flig:units = "unitless" ; - fates_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; + double fates_damage_canopy_layer_code ; + fates_damage_canopy_layer_code:units = "unitless" ; + fates_damage_canopy_layer_code:long_name = "Integer code that decides whether damage affects canopy trees (1), understory trees (2)" ; + double fates_damage_event_code ; + fates_damage_event_code:units = "unitless" ; + fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; double fates_dev_arbitrary ; fates_dev_arbitrary:units = "unknown" ; fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; - double fates_eca_plant_escalar ; - fates_eca_plant_escalar:units = "" ; - fates_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; double fates_fire_active_crown_fire ; fates_fire_active_crown_fire:units = "0 or 1" ; fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; @@ -644,54 +648,87 @@ variables: double fates_fire_threshold ; fates_fire_threshold:units = "kW/m" ; fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; - double fates_hydr_kmax_rsurf1 ; - fates_hydr_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; - fates_hydr_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; - double fates_hydr_kmax_rsurf2 ; - fates_hydr_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; - fates_hydr_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; - double fates_hydr_psi0 ; - fates_hydr_psi0:units = "MPa" ; - fates_hydr_psi0:long_name = "sapwood water potential at saturation" ; - double fates_hydr_psicap ; - fates_hydr_psicap:units = "MPa" ; - fates_hydr_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; - double fates_init_litter ; - fates_init_litter:units = "NA" ; - fates_init_litter:long_name = "Initialization value for litter pool in cold-start (NOT USED)" ; + double fates_frag_cwd_fcel ; + fates_frag_cwd_fcel:units = "unitless" ; + fates_frag_cwd_fcel:long_name = "Cellulose fraction for CWD" ; + double fates_frag_cwd_flig ; + fates_frag_cwd_flig:units = "unitless" ; + fates_frag_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; + double fates_hydro_kmax_rsurf1 ; + fates_hydro_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; + double fates_hydro_kmax_rsurf2 ; + fates_hydro_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; + double fates_hydro_psi0 ; + fates_hydro_psi0:units = "MPa" ; + fates_hydro_psi0:long_name = "sapwood water potential at saturation" ; + double fates_hydro_psicap ; + fates_hydro_psicap:units = "MPa" ; + fates_hydro_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; + 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_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" ; + double fates_landuse_logging_collateral_frac ; + fates_landuse_logging_collateral_frac:units = "fraction" ; + fates_landuse_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; + double fates_landuse_logging_dbhmax ; + fates_landuse_logging_dbhmax:units = "cm" ; + fates_landuse_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; + double fates_landuse_logging_dbhmax_infra ; + fates_landuse_logging_dbhmax_infra:units = "cm" ; + fates_landuse_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; + double fates_landuse_logging_dbhmin ; + fates_landuse_logging_dbhmin:units = "cm" ; + fates_landuse_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; + double fates_landuse_logging_direct_frac ; + fates_landuse_logging_direct_frac:units = "fraction" ; + fates_landuse_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; + double fates_landuse_logging_event_code ; + fates_landuse_logging_event_code:units = "unitless" ; + fates_landuse_logging_event_code:long_name = "Integer code that options how logging events are structured" ; + double fates_landuse_logging_export_frac ; + fates_landuse_logging_export_frac:units = "fraction" ; + fates_landuse_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; + double fates_landuse_logging_mechanical_frac ; + fates_landuse_logging_mechanical_frac:units = "fraction" ; + fates_landuse_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; + double fates_landuse_pprodharv10_forest_mean ; + fates_landuse_pprodharv10_forest_mean:units = "fraction" ; + fates_landuse_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; + double fates_leaf_photo_temp_acclim_timescale ; + fates_leaf_photo_temp_acclim_timescale:units = "days" ; + fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; + double fates_leaf_photo_tempsens_model ; + fates_leaf_photo_tempsens_model:units = "unitless" ; + fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; + double fates_leaf_stomatal_assim_model ; + fates_leaf_stomatal_assim_model:units = "unitless" ; + fates_leaf_stomatal_assim_model:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; double fates_leaf_stomatal_model ; fates_leaf_stomatal_model:units = "unitless" ; fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; - double fates_logging_coll_under_frac ; - fates_logging_coll_under_frac:units = "fraction" ; - fates_logging_coll_under_frac:long_name = "Fraction of stems killed in the understory when logging generates disturbance" ; - double fates_logging_collateral_frac ; - fates_logging_collateral_frac:units = "fraction" ; - fates_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; - double fates_logging_dbhmax ; - fates_logging_dbhmax:units = "cm" ; - fates_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; - double fates_logging_dbhmax_infra ; - fates_logging_dbhmax_infra:units = "cm" ; - fates_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; - double fates_logging_dbhmin ; - fates_logging_dbhmin:units = "cm" ; - fates_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; - double fates_logging_direct_frac ; - fates_logging_direct_frac:units = "fraction" ; - fates_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; - double fates_logging_event_code ; - fates_logging_event_code:units = "unitless" ; - fates_logging_event_code:long_name = "Integer code that options how logging events are structured" ; - double fates_logging_export_frac ; - fates_logging_export_frac:units = "fraction" ; - fates_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; - double fates_logging_mechanical_frac ; - fates_logging_mechanical_frac:units = "fraction" ; - fates_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; + double fates_leaf_theta_cj_c3 ; + fates_leaf_theta_cj_c3:units = "unitless" ; + fates_leaf_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; + double fates_leaf_theta_cj_c4 ; + fates_leaf_theta_cj_c4:units = "unitless" ; + fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; double fates_maintresp_model ; fates_maintresp_model:units = "unitless" ; fates_maintresp_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991) (NOT USED)" ; + double fates_maxcohort ; + fates_maxcohort:units = "count" ; + fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; + double fates_maxpatch_primary ; + fates_maxpatch_primary:units = "count" ; + fates_maxpatch_primary:long_name = "maximum number of primary vegetation patches per site" ; + double fates_maxpatch_secondary ; + fates_maxpatch_secondary:units = "count" ; + fates_maxpatch_secondary:long_name = "maximum number of secondary vegetation patches per site" ; double fates_mort_disturb_frac ; fates_mort_disturb_frac:units = "fraction" ; fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; @@ -701,39 +738,39 @@ variables: double fates_patch_fusion_tol ; fates_patch_fusion_tol:units = "unitless" ; fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; - double fates_phen_a ; - fates_phen_a:units = "none" ; - fates_phen_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_b ; - fates_phen_b:units = "none" ; - fates_phen_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_c ; - fates_phen_c:units = "none" ; - fates_phen_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_chiltemp ; - fates_phen_chiltemp:units = "degrees C" ; - fates_phen_chiltemp:long_name = "chilling day counting threshold for vegetation" ; + double fates_phen_chilltemp ; + fates_phen_chilltemp:units = "degrees C" ; + fates_phen_chilltemp:long_name = "chilling day counting threshold for vegetation" ; double fates_phen_coldtemp ; fates_phen_coldtemp:units = "degrees C" ; fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; - double fates_phen_doff_time ; - fates_phen_doff_time:units = "days" ; - fates_phen_doff_time:long_name = "day threshold compared against days since leaves became off-allometry" ; + double fates_phen_drought_model ; + fates_phen_drought_model:units = "unitless" ; + fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; double fates_phen_drought_threshold ; - fates_phen_drought_threshold:units = "m3/m3" ; - fates_phen_drought_threshold:long_name = "liquid volume in soil layer, threashold for drought phenology" ; + fates_phen_drought_threshold:units = "m3/m3 or mm" ; + fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_gddthresh_a ; + fates_phen_gddthresh_a:units = "none" ; + fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_b ; + fates_phen_gddthresh_b:units = "none" ; + fates_phen_gddthresh_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_c ; + fates_phen_gddthresh_c:units = "none" ; + fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_mindaysoff ; + fates_phen_mindaysoff:units = "days" ; + fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves became off-allometry" ; double fates_phen_mindayson ; fates_phen_mindayson:units = "days" ; fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; + double fates_phen_moist_threshold ; + fates_phen_moist_threshold:units = "m3/m3 or mm" ; + fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; double fates_phen_ncolddayslim ; fates_phen_ncolddayslim:units = "days" ; fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; - double fates_photo_temp_acclim_timescale ; - fates_photo_temp_acclim_timescale:units = "days" ; - fates_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; - double fates_photo_tempsens_model ; - fates_photo_tempsens_model:units = "unitless" ; - fates_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; double fates_q10_froz ; fates_q10_froz:units = "unitless" ; fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; @@ -743,18 +780,12 @@ variables: double fates_soil_salinity ; fates_soil_salinity:units = "ppt" ; fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; - double fates_theta_cj_c3 ; - fates_theta_cj_c3:units = "unitless" ; - fates_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; - double fates_theta_cj_c4 ; - fates_theta_cj_c4:units = "unitless" ; - fates_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; double fates_vai_top_bin_width ; fates_vai_top_bin_width:units = "m2/m2" ; - fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer (NOT USED)" ; + fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; double fates_vai_width_increase_factor ; fates_vai_width_increase_factor:units = "unitless" ; - fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing) (NOT USED)" ; + fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; // global attributes: :history = "This parameter file is maintained in version control\nSee https://github.com/NGEET/fates/blob/master/parameter_files/fates_params_default.cdl \nFor changes, use git blame \n" ; @@ -766,12 +797,14 @@ data: fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; - fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, + fates_history_damage_bin_edges = 0, 80 ; + + fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100 ; - fates_hydr_htftype_node = 1, 1, 1, 1 ; + fates_alloc_organ_id = 1, 2, 3, 6 ; - fates_prt_organ_id = 1, 2, 3, 6 ; + fates_hydro_htftype_node = 1, 1, 1, 1 ; fates_pftname = "broadleaf_evergreen_tropical_tree ", @@ -787,12 +820,18 @@ data: "cool_c3_grass ", "c4_grass " ; - fates_hydr_organname_node = + fates_hydro_organ_name = "leaf ", "stem ", "transporting root ", "absorbing root " ; + fates_alloc_organ_name = + "leaf", + "fine root", + "sapwood", + "structure" ; + fates_litterclass_name = "twig ", "small branch ", @@ -801,28 +840,31 @@ data: "dead leaves ", "live grass " ; - fates_prt_organ_name = - "leaf ", - "fine root ", - "sapwood ", - "structure " ; + 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, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; - fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 ; - fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, + fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8, 0.8 ; + + fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; - fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, + fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572 ; - fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, + fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94 ; - fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, + fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931 ; - fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6 ; fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -831,50 +873,59 @@ data: fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, + 0.95, 1, 1, 1 ; + + fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07 ; - fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, + fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3 ; - fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, + fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55 ; - fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, + fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464 ; - fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, + fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119 ; - fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, + fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64 ; - fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, + fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37 ; - fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, + fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 ; fates_allom_dbh_maxheight = 90, 90, 90, 90, 90, 90, 3, 3, 2, 0.35, 0.35, 0.35 ; fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_allom_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; + + fates_allom_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; + + fates_allom_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 ; fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -885,182 +936,224 @@ data: fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; - fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 ; - fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, + fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; - fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 ; - fates_branch_turnover = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; - fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; - fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, - 0.67, 0.67 ; - - fates_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5 ; + fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; - fates_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280 ; - fates_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, + fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14 ; - fates_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, + fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27 ; - fates_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; + fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_vmax_nh4 = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_eca_vmax_no3 = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_fnrt_adapt_tscale = 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100 ; - fates_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_cnp_nfix1 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; - fates_eca_vmax_nh4 = 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, - 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07 ; + fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; - fates_eca_vmax_no3 = 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, - 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08 ; + fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_eca_vmax_p = 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, - 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09 ; + fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + fates_cnp_rd_vmax_n = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_turnover_nitr_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_turnover_phos_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, + 5e-10, 5e-10, 5e-10, 5e-10 ; + + fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01 ; + + fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; + + fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, + 5.5, 5.5 ; + + fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 ; - fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07 ; - fates_fire_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, - 0.95, 1, 1, 1 ; - - fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, + fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775 ; - fates_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; + fates_frag_fnrt_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; - fates_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; + fates_frag_fnrt_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; - fates_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + fates_frag_fnrt_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; - fates_fr_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + fates_frag_leaf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; - fates_fr_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25 ; + fates_frag_leaf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; - fates_fr_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25 ; + fates_frag_leaf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, + 0.51, 0.51, 0.51, 0.51 ; - fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, + fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - fates_hydr_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, - 2.5 ; + fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + 2.5, 2.5 ; - fates_hydr_avuln_node = + fates_hydro_avuln_node = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 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_hydr_epsil_node = + fates_hydro_epsil_node = 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - fates_hydr_fcap_node = + fates_hydro_fcap_node = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_hydr_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_hydr_kmax_node = + fates_hydro_kmax_node = -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; - fates_hydr_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5 ; - fates_hydr_p50_node = - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + fates_hydro_p50_node = + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25 ; - fates_hydr_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, - 0.333, 0.333, 0.333, 0.333 ; + fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, + 0.333, 0.333, 0.333, 0.333, 0.333 ; - fates_hydr_pinot_node = - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + fates_hydro_pinot_node = + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; - fates_hydr_pitlp_node = - -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + fates_hydro_pitlp_node = + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; - fates_hydr_resid_node = + fates_hydro_resid_node = 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - fates_hydr_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625 ; - fates_hydr_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, + fates_hydro_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; - fates_hydr_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; + fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; - fates_hydr_thetas_node = + fates_hydro_thetas_node = 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; - fates_hydr_vg_alpha_node = - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + fates_hydro_vg_alpha_node = + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005 ; - fates_hydr_vg_m_node = + fates_hydro_vg_m_node = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_hydr_vg_n_node = + fates_hydro_vg_n_node = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -1068,284 +1161,222 @@ data: fates_leaf_c3psn = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ; - fates_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, - 0.9, 0.75, 0.75, 0.75 ; - - fates_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.04, 0.04, 0.04 ; - - fates_leaf_jmaxha = 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, + fates_leaf_jmaxha = 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540 ; - fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, + fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040, 152040 ; - fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, + fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495 ; - fates_leaf_long = - 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - - fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, + fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, 0.03, 0.03, 0.03, 0.03, 0.03 ; - fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, + fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, 0.03, 0.03, 0.03, 0.03 ; - fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, + fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 40000 ; fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, + fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, 4.7, 2.2, 5.3, 1.6 ; - fates_leaf_stor_priority = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, - 0.8, 0.8 ; - fates_leaf_vcmax25top = 50, 65, 39, 62, 41, 58, 62, 54, 54, 78, 78, 78 ; - fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, + fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330 ; - fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, + fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250, 149250 ; - fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, + fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485 ; - fates_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, -0.23, - -0.23, -0.23 ; - - fates_lf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_lf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25 ; - - fates_lf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25 ; - - fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, + fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014 ; - fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -60, -10, -80, -80, + fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -60, -10, -80, -80, -20, 2.5 ; - fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, + fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + fates_mort_prescribed_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, + 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; + + fates_mort_prescribed_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, + 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; + fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6 ; - fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6 ; - fates_nfix1 = _, _, _, _, _, _, _, _, _, _, _, _ ; + fates_nonhydro_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, + -255000, -255000, -255000, -255000, -255000, -255000 ; - fates_nfix2 = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5 ; + fates_nonhydro_smpso = -66000, -66000, -66000, -66000, -66000, -66000, + -66000, -66000, -66000, -66000, -66000, -66000 ; fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; + fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, + 0.5 ; + + fates_phen_fnrt_drop_frac = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; - fates_phenflush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5 ; - - fates_prescribed_mortality_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, - 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; - - fates_prescribed_mortality_understory = 0.025, 0.025, 0.025, 0.025, 0.025, - 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; - - fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, + fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4 ; - fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, + fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; - fates_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_prescribed_recruitment = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, - 0.02, 0.02, 0.02, 0.02, 0.02 ; - - fates_prt_alloc_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, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; + fates_rad_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, + 0.9, 0.75, 0.75, 0.75 ; - fates_prt_nitr_stoich_p1 = - 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, - 0.0047, 0.0047, 0.0047 ; + fates_rad_leaf_rhonir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, + 0.41, 0.28, 0.28, 0.28 ; - fates_prt_nitr_stoich_p2 = - 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, - 0.0047, 0.0047, 0.0047 ; + fates_rad_leaf_rhovis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, + 0.08, 0.05, 0.05, 0.05 ; - fates_prt_phos_stoich_p1 = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, - 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, - 0.00047, 0.00047, 0.00047, 0.00047 ; + fates_rad_leaf_taunir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, + 0.43, 0.4, 0.4, 0.4 ; - fates_prt_phos_stoich_p2 = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, - 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, - 0.00047, 0.00047, 0.00047, 0.00047 ; + fates_rad_leaf_tauvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, + 0.06, 0.05, 0.05, 0.05 ; - fates_recruit_hgt_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, - 0.125, 0.125, 0.125 ; + fates_rad_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, + -0.23, -0.23, -0.23 ; - fates_recruit_initd = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, - 0.2 ; + fates_rad_stem_rhonir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, + 0.49, 0.53, 0.53, 0.53 ; - fates_rholnir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, 0.41, 0.28, - 0.28, 0.28 ; + fates_rad_stem_rhovis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.31, 0.31, 0.31 ; - fates_rholvis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, 0.08, 0.05, 0.05, 0.05 ; + fates_rad_stem_taunir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.25, 0.25, 0.25 ; - fates_rhosnir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, 0.49, 0.53, - 0.53, 0.53 ; + fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.12, 0.12, 0.12 ; - fates_rhosvis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.31, - 0.31, 0.31 ; + fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, + 0.125, 0.125, 0.125 ; - fates_root_long = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2, 0.2, 0.2 ; - fates_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; + fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, + 0.02, 0.02, 0.02, 0.02, 0.02 ; - fates_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9 ; + fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; - fates_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, 1.47, - 1.47, 1.47 ; + fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, + 0.9 ; - fates_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, - 0.51, 0.51, 0.51, 0.51 ; + fates_recruit_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, + 1.47, 1.47, 1.47 ; - fates_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5 ; + fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_seed_suppl = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_senleaf_long_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_stoich_nitr = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; - fates_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, -255000, - -255000, -255000, -255000, -255000, -255000 ; + fates_stoich_phos = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; - fates_smpso = -66000, -66000, -66000, -66000, -66000, -66000, -66000, - -66000, -66000, -66000, -66000, -66000 ; + fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, + 0.03, 0.03 ; - fates_taulnir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, 0.43, 0.4, - 0.4, 0.4 ; + fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; - fates_taulvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.05, - 0.05, 0.05 ; + fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, + 0.67, 0.67, 0.67 ; - fates_tausnir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, - 0.001, 0.25, 0.25, 0.25 ; + fates_turb_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.04, 0.04, 0.04, 0.04 ; - fates_tausvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, - 0.001, 0.12, 0.12, 0.12 ; + fates_turb_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, + 0.055, 0.055, 0.055, 0.055 ; - fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, - 0.03, 0.03 ; + fates_turnover_branch = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; - fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; + fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - fates_turnover_carb_retrans = - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_turnover_nitr_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_turnover_phos_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_turnover_leaf = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - fates_turnover_retrans_mode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, + fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7 ; fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; - fates_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, - 0.055, 0.055, 0.055 ; - fates_hlm_pft_map = - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; @@ -1363,28 +1394,28 @@ data: fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; - fates_max_decomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; + fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; - fates_CWD_frac = 0.045, 0.075, 0.21, 0.67 ; + fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; fates_base_mr_20 = 2.52e-06 ; fates_canopy_closure_thresh = 0.8 ; + fates_cnp_eca_plant_escalar = 1.25e-05 ; + fates_cohort_age_fusion_tol = 0.08 ; fates_cohort_size_fusion_tol = 0.08 ; fates_comp_excln = 3 ; - fates_cwd_fcel = 0.76 ; + fates_damage_canopy_layer_code = 1 ; - fates_cwd_flig = 0.24 ; + fates_damage_event_code = 1 ; fates_dev_arbitrary = _ ; - fates_eca_plant_escalar = 1.25e-05 ; - fates_fire_active_crown_fire = 0 ; fates_fire_cg_strikes = 0.2 ; @@ -1413,65 +1444,87 @@ data: fates_fire_threshold = 50 ; - fates_hydr_kmax_rsurf1 = 20 ; + fates_frag_cwd_fcel = 0.76 ; - fates_hydr_kmax_rsurf2 = 0.0001 ; + fates_frag_cwd_flig = 0.24 ; - fates_hydr_psi0 = 0 ; + fates_hydro_kmax_rsurf1 = 20 ; - fates_hydr_psicap = -0.6 ; + fates_hydro_kmax_rsurf2 = 0.0001 ; - fates_init_litter = 0.05 ; + fates_hydro_psi0 = 0 ; - fates_leaf_stomatal_model = 1 ; + fates_hydro_psicap = -0.6 ; + + fates_hydro_solver = 1 ; + + fates_landuse_logging_coll_under_frac = 0.55983 ; - fates_logging_coll_under_frac = 0.55983 ; + fates_landuse_logging_collateral_frac = 0.05 ; - fates_logging_collateral_frac = 0.05 ; + fates_landuse_logging_dbhmax = _ ; - fates_logging_dbhmax = _ ; + fates_landuse_logging_dbhmax_infra = 35 ; - fates_logging_dbhmax_infra = 35 ; + fates_landuse_logging_dbhmin = 50 ; - fates_logging_dbhmin = 50 ; + fates_landuse_logging_direct_frac = 0.15 ; - fates_logging_direct_frac = 0.15 ; + fates_landuse_logging_event_code = -30 ; - fates_logging_event_code = -30 ; + fates_landuse_logging_export_frac = 0.8 ; - fates_logging_export_frac = 0.8 ; + fates_landuse_logging_mechanical_frac = 0.05 ; - fates_logging_mechanical_frac = 0.05 ; + fates_landuse_pprodharv10_forest_mean = 0.8125 ; + + fates_leaf_photo_temp_acclim_timescale = 30 ; + + fates_leaf_photo_tempsens_model = 1 ; + + fates_leaf_stomatal_assim_model = 1 ; + + fates_leaf_stomatal_model = 1 ; + + fates_leaf_theta_cj_c3 = 0.999 ; + + fates_leaf_theta_cj_c4 = 0.999 ; fates_maintresp_model = 1 ; + fates_maxcohort = 100 ; + + fates_maxpatch_primary = 10 ; + + fates_maxpatch_secondary = 4 ; + fates_mort_disturb_frac = 1 ; fates_mort_understorey_death = 0.55983 ; fates_patch_fusion_tol = 0.05 ; - fates_phen_a = -68 ; + fates_phen_chilltemp = 5 ; - fates_phen_b = 638 ; + fates_phen_coldtemp = 7.5 ; - fates_phen_c = -0.01 ; + fates_phen_drought_model = 0 ; - fates_phen_chiltemp = 5 ; + fates_phen_drought_threshold = 0.15 ; - fates_phen_coldtemp = 7.5 ; + fates_phen_gddthresh_a = -68 ; - fates_phen_doff_time = 100 ; + fates_phen_gddthresh_b = 638 ; - fates_phen_drought_threshold = 0.15 ; + fates_phen_gddthresh_c = -0.01 ; - fates_phen_mindayson = 90 ; + fates_phen_mindaysoff = 100 ; - fates_phen_ncolddayslim = 5 ; + fates_phen_mindayson = 90 ; - fates_photo_temp_acclim_timescale = 30 ; + fates_phen_moist_threshold = 0.18 ; - fates_photo_tempsens_model = 1 ; + fates_phen_ncolddayslim = 5 ; fates_q10_froz = 1.5 ; @@ -1479,10 +1532,6 @@ data: fates_soil_salinity = 0.4 ; - fates_theta_cj_c3 = 0.999 ; - - fates_theta_cj_c4 = 0.999 ; - fates_vai_top_bin_width = 1 ; fates_vai_width_increase_factor = 1 ; From 4c01c5a340b8267b8ffd1f9962b9abbf28f9b827 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 8 Jun 2022 10:33:50 -0600 Subject: [PATCH 245/852] Removing the api24 temporary default parameter file --- .../fates_params_default_api24.cdl | 1538 ----------------- 1 file changed, 1538 deletions(-) delete mode 100644 parameter_files/fates_params_default_api24.cdl diff --git a/parameter_files/fates_params_default_api24.cdl b/parameter_files/fates_params_default_api24.cdl deleted file mode 100644 index b45f3249ef..0000000000 --- a/parameter_files/fates_params_default_api24.cdl +++ /dev/null @@ -1,1538 +0,0 @@ -netcdf tmp { -dimensions: - fates_NCWD = 4 ; - fates_history_age_bins = 7 ; - fates_history_coage_bins = 2 ; - fates_history_damage_bins = 2 ; - fates_history_height_bins = 6 ; - fates_history_size_bins = 13 ; - fates_hlm_pftno = 14 ; - fates_hydr_organs = 4 ; - fates_leafage_class = 1 ; - fates_litterclass = 6 ; - fates_pft = 12 ; - fates_plant_organs = 4 ; - fates_string_length = 60 ; -variables: - double fates_history_ageclass_bin_edges(fates_history_age_bins) ; - fates_history_ageclass_bin_edges:units = "yr" ; - fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; - double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; - fates_history_coageclass_bin_edges:units = "years" ; - fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; - double fates_history_height_bin_edges(fates_history_height_bins) ; - fates_history_height_bin_edges:units = "m" ; - fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; - double fates_history_damage_bin_edges(fates_history_damage_bins) ; - fates_history_damage_bin_edges:units = "% crown loss" ; - fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; - double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; - fates_history_sizeclass_bin_edges:units = "cm" ; - fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; - double fates_alloc_organ_id(fates_plant_organs) ; - fates_alloc_organ_id:units = "unitless" ; - fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; - double fates_hydro_htftype_node(fates_hydr_organs) ; - fates_hydro_htftype_node:units = "unitless" ; - fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; - char fates_pftname(fates_pft, fates_string_length) ; - fates_pftname:units = "unitless - string" ; - fates_pftname:long_name = "Description of plant type" ; - char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; - fates_hydro_organ_name:units = "unitless - string" ; - fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; - char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; - fates_alloc_organ_name:units = "unitless - string" ; - fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; - 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" ; - 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" ; - double fates_alloc_storage_cushion(fates_pft) ; - fates_alloc_storage_cushion:units = "fraction" ; - fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; - double fates_alloc_store_priority_frac(fates_pft) ; - fates_alloc_store_priority_frac:units = "unitless" ; - fates_alloc_store_priority_frac:long_name = "for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage" ; - double fates_allom_agb1(fates_pft) ; - fates_allom_agb1:units = "variable" ; - fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; - double fates_allom_agb2(fates_pft) ; - fates_allom_agb2:units = "variable" ; - fates_allom_agb2:long_name = "Parameter 2 for agb allometry" ; - double fates_allom_agb3(fates_pft) ; - fates_allom_agb3:units = "variable" ; - fates_allom_agb3:long_name = "Parameter 3 for agb allometry" ; - double fates_allom_agb4(fates_pft) ; - fates_allom_agb4:units = "variable" ; - fates_allom_agb4:long_name = "Parameter 4 for agb allometry" ; - double fates_allom_agb_frac(fates_pft) ; - fates_allom_agb_frac:units = "fraction" ; - fates_allom_agb_frac:long_name = "Fraction of woody biomass that is above ground" ; - double fates_allom_amode(fates_pft) ; - fates_allom_amode:units = "index" ; - fates_allom_amode:long_name = "AGB allometry function index." ; - double fates_allom_blca_expnt_diff(fates_pft) ; - fates_allom_blca_expnt_diff:units = "unitless" ; - fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; - double fates_allom_cmode(fates_pft) ; - fates_allom_cmode:units = "index" ; - fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; - double fates_allom_crown_depth_frac(fates_pft) ; - fates_allom_crown_depth_frac:units = "fraction" ; - fates_allom_crown_depth_frac:long_name = "the depth of a cohort crown as a fraction of its height" ; - double fates_allom_d2bl1(fates_pft) ; - fates_allom_d2bl1:units = "variable" ; - fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; - double fates_allom_d2bl2(fates_pft) ; - fates_allom_d2bl2:units = "variable" ; - fates_allom_d2bl2:long_name = "Parameter 2 for d2bl allometry" ; - double fates_allom_d2bl3(fates_pft) ; - fates_allom_d2bl3:units = "unitless" ; - fates_allom_d2bl3:long_name = "Parameter 3 for d2bl allometry" ; - double fates_allom_d2ca_coefficient_max(fates_pft) ; - fates_allom_d2ca_coefficient_max:units = "m2 cm^(-1/beta)" ; - fates_allom_d2ca_coefficient_max:long_name = "max (savanna) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; - double fates_allom_d2ca_coefficient_min(fates_pft) ; - fates_allom_d2ca_coefficient_min:units = "m2 cm^(-1/beta)" ; - fates_allom_d2ca_coefficient_min:long_name = "min (forest) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; - double fates_allom_d2h1(fates_pft) ; - fates_allom_d2h1:units = "variable" ; - fates_allom_d2h1:long_name = "Parameter 1 for d2h allometry (intercept, or c)" ; - double fates_allom_d2h2(fates_pft) ; - fates_allom_d2h2:units = "variable" ; - fates_allom_d2h2:long_name = "Parameter 2 for d2h allometry (slope, or m)" ; - double fates_allom_d2h3(fates_pft) ; - fates_allom_d2h3:units = "variable" ; - fates_allom_d2h3:long_name = "Parameter 3 for d2h allometry (optional)" ; - double fates_allom_dbh_maxheight(fates_pft) ; - fates_allom_dbh_maxheight:units = "cm" ; - fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; - double fates_allom_fmode(fates_pft) ; - fates_allom_fmode:units = "index" ; - fates_allom_fmode:long_name = "fine root biomass allometry function index." ; - double fates_allom_fnrt_prof_a(fates_pft) ; - fates_allom_fnrt_prof_a:units = "unitless" ; - fates_allom_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; - double fates_allom_fnrt_prof_b(fates_pft) ; - fates_allom_fnrt_prof_b:units = "unitless" ; - fates_allom_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; - double fates_allom_fnrt_prof_mode(fates_pft) ; - fates_allom_fnrt_prof_mode:units = "index" ; - fates_allom_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; - double fates_allom_frbstor_repro(fates_pft) ; - fates_allom_frbstor_repro:units = "fraction" ; - fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; - double fates_allom_hmode(fates_pft) ; - fates_allom_hmode:units = "index" ; - fates_allom_hmode:long_name = "height allometry function index." ; - double fates_allom_l2fr(fates_pft) ; - fates_allom_l2fr:units = "gC/gC" ; - fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; - double fates_allom_la_per_sa_int(fates_pft) ; - fates_allom_la_per_sa_int:units = "m2/cm2" ; - fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; - double fates_allom_la_per_sa_slp(fates_pft) ; - fates_allom_la_per_sa_slp:units = "m2/cm2/m" ; - fates_allom_la_per_sa_slp:long_name = "Leaf area per sapwood area rate of change with height, slope (optional)" ; - double fates_allom_lmode(fates_pft) ; - fates_allom_lmode:units = "index" ; - fates_allom_lmode:long_name = "leaf biomass allometry function index." ; - double fates_allom_sai_scaler(fates_pft) ; - fates_allom_sai_scaler:units = "m2/m2" ; - fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; - double fates_allom_smode(fates_pft) ; - fates_allom_smode:units = "index" ; - fates_allom_smode:long_name = "sapwood allometry function index." ; - double fates_allom_stmode(fates_pft) ; - fates_allom_stmode:units = "index" ; - fates_allom_stmode:long_name = "storage allometry function index." ; - double fates_allom_zroot_k(fates_pft) ; - fates_allom_zroot_k:units = "unitless" ; - fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; - double fates_allom_zroot_max_dbh(fates_pft) ; - fates_allom_zroot_max_dbh:units = "cm" ; - fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; - double fates_allom_zroot_max_z(fates_pft) ; - fates_allom_zroot_max_z:units = "m" ; - fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; - double fates_allom_zroot_min_dbh(fates_pft) ; - fates_allom_zroot_min_dbh:units = "cm" ; - fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; - double fates_allom_zroot_min_z(fates_pft) ; - fates_allom_zroot_min_z:units = "m" ; - fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; - double fates_c2b(fates_pft) ; - fates_c2b:units = "ratio" ; - fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; - double fates_cnp_eca_alpha_ptase(fates_pft) ; - fates_cnp_eca_alpha_ptase:units = "g/m3" ; - fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; - double fates_cnp_eca_decompmicc(fates_pft) ; - fates_cnp_eca_decompmicc:units = "gC/m3" ; - fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; - double fates_cnp_eca_km_nh4(fates_pft) ; - fates_cnp_eca_km_nh4:units = "gN/m3" ; - fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; - double fates_cnp_eca_km_no3(fates_pft) ; - fates_cnp_eca_km_no3:units = "gN/m3" ; - fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; - double fates_cnp_eca_km_p(fates_pft) ; - fates_cnp_eca_km_p:units = "gP/m3" ; - fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; - double fates_cnp_eca_km_ptase(fates_pft) ; - fates_cnp_eca_km_ptase:units = "gP/m3" ; - fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; - double fates_cnp_eca_lambda_ptase(fates_pft) ; - fates_cnp_eca_lambda_ptase:units = "g/m3" ; - fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; - double fates_cnp_eca_vmax_nh4(fates_pft) ; - fates_cnp_eca_vmax_nh4:units = "gN/gC/s" ; - fates_cnp_eca_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA)" ; - double fates_cnp_eca_vmax_no3(fates_pft) ; - fates_cnp_eca_vmax_no3:units = "gN/gC/s" ; - fates_cnp_eca_vmax_no3:long_name = "maximum production rate for plant no3 uptake (ECA)" ; - double fates_cnp_eca_vmax_ptase(fates_pft) ; - fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; - fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; - double fates_cnp_fnrt_adapt_tscale(fates_pft) ; - fates_cnp_fnrt_adapt_tscale:units = "days" ; - fates_cnp_fnrt_adapt_tscale:long_name = "Number of days that is shortest possible doubling period for fine-root adaptation to C/N/P balance" ; - double fates_cnp_nfix1(fates_pft) ; - fates_cnp_nfix1:units = "NA" ; - fates_cnp_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; - double fates_cnp_nitr_store_ratio(fates_pft) ; - fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; - fates_cnp_nitr_store_ratio:long_name = "storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code)" ; - double fates_cnp_phos_store_ratio(fates_pft) ; - fates_cnp_phos_store_ratio:units = "(gP/gP)" ; - fates_cnp_phos_store_ratio:long_name = "storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code)" ; - double fates_cnp_prescribed_nuptake(fates_pft) ; - fates_cnp_prescribed_nuptake:units = "fraction" ; - fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; - double fates_cnp_prescribed_puptake(fates_pft) ; - fates_cnp_prescribed_puptake:units = "fraction" ; - fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; - double fates_cnp_rd_vmax_n(fates_pft) ; - fates_cnp_rd_vmax_n:units = "gN/gC/s" ; - fates_cnp_rd_vmax_n:long_name = "maximum production rate for compbined (NH4+NO3) uptake (RD)" ; - double fates_cnp_store_ovrflw_frac(fates_pft) ; - fates_cnp_store_ovrflw_frac:units = "fraction" ; - fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; - fates_cnp_store_ovrflw_frac:use_case = "None" ; - double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; - fates_cnp_turnover_nitr_retrans:units = "fraction" ; - fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; - double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; - fates_cnp_turnover_phos_retrans:units = "fraction" ; - fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; - double fates_cnp_vmax_p(fates_pft) ; - fates_cnp_vmax_p:units = "gP/gC/s" ; - fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; - double fates_damage_frac(fates_pft) ; - fates_damage_frac:units = "fraction" ; - fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; - double fates_damage_mort_p1(fates_pft) ; - fates_damage_mort_p1:units = "fraction" ; - fates_damage_mort_p1:long_name = "inflection point of damage mortality function, a value of 0.8 means 50% mortality with 80% loss of crown, turn off with a large number" ; - double fates_damage_mort_p2(fates_pft) ; - fates_damage_mort_p2:units = "unitless" ; - fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; - 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_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" ; - double fates_fire_alpha_SH(fates_pft) ; - fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; - fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; - double fates_fire_bark_scaler(fates_pft) ; - fates_fire_bark_scaler:units = "fraction" ; - fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; - double fates_fire_crown_kill(fates_pft) ; - fates_fire_crown_kill:units = "NA" ; - fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; - double fates_frag_fnrt_fcel(fates_pft) ; - fates_frag_fnrt_fcel:units = "fraction" ; - fates_frag_fnrt_fcel:long_name = "Fine root litter cellulose fraction" ; - double fates_frag_fnrt_flab(fates_pft) ; - fates_frag_fnrt_flab:units = "fraction" ; - fates_frag_fnrt_flab:long_name = "Fine root litter labile fraction" ; - double fates_frag_fnrt_flig(fates_pft) ; - fates_frag_fnrt_flig:units = "fraction" ; - fates_frag_fnrt_flig:long_name = "Fine root litter lignin fraction" ; - double fates_frag_leaf_fcel(fates_pft) ; - fates_frag_leaf_fcel:units = "fraction" ; - fates_frag_leaf_fcel:long_name = "Leaf litter cellulose fraction" ; - double fates_frag_leaf_flab(fates_pft) ; - fates_frag_leaf_flab:units = "fraction" ; - fates_frag_leaf_flab:long_name = "Leaf litter labile fraction" ; - double fates_frag_leaf_flig(fates_pft) ; - fates_frag_leaf_flig:units = "fraction" ; - fates_frag_leaf_flig:long_name = "Leaf litter lignin fraction" ; - double fates_frag_seed_decay_rate(fates_pft) ; - fates_frag_seed_decay_rate:units = "yr-1" ; - fates_frag_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; - double fates_grperc(fates_pft) ; - fates_grperc:units = "unitless" ; - fates_grperc:long_name = "Growth respiration factor" ; - double fates_hydro_avuln_gs(fates_pft) ; - fates_hydro_avuln_gs:units = "unitless" ; - fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; - double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; - fates_hydro_avuln_node:units = "unitless" ; - fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; - double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; - fates_hydro_epsil_node:units = "MPa" ; - fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; - double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; - fates_hydro_fcap_node:units = "unitless" ; - fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; - double fates_hydro_k_lwp(fates_pft) ; - fates_hydro_k_lwp:units = "unitless" ; - fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; - double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; - fates_hydro_kmax_node:units = "kg/MPa/m/s" ; - fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; - double fates_hydro_p50_gs(fates_pft) ; - fates_hydro_p50_gs:units = "MPa" ; - fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; - double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; - fates_hydro_p50_node:units = "MPa" ; - fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; - double fates_hydro_p_taper(fates_pft) ; - fates_hydro_p_taper:units = "unitless" ; - fates_hydro_p_taper:long_name = "xylem taper exponent" ; - double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; - fates_hydro_pinot_node:units = "MPa" ; - fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; - double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; - fates_hydro_pitlp_node:units = "MPa" ; - fates_hydro_pitlp_node:long_name = "turgor loss point" ; - double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; - fates_hydro_resid_node:units = "cm3/cm3" ; - fates_hydro_resid_node:long_name = "residual water conent" ; - double fates_hydro_rfrac_stem(fates_pft) ; - fates_hydro_rfrac_stem:units = "fraction" ; - fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; - double fates_hydro_rs2(fates_pft) ; - fates_hydro_rs2:units = "m" ; - fates_hydro_rs2:long_name = "absorbing root radius" ; - double fates_hydro_srl(fates_pft) ; - fates_hydro_srl:units = "m g-1" ; - fates_hydro_srl:long_name = "specific root length" ; - double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; - fates_hydro_thetas_node:units = "cm3/cm3" ; - fates_hydro_thetas_node:long_name = "saturated water content" ; - double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; - fates_hydro_vg_alpha_node:units = "MPa-1" ; - fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; - double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; - fates_hydro_vg_m_node:units = "unitless" ; - fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; - 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_leaf_c3psn(fates_pft) ; - fates_leaf_c3psn:units = "flag" ; - fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; - double fates_leaf_jmaxha(fates_pft) ; - fates_leaf_jmaxha:units = "J/mol" ; - fates_leaf_jmaxha:long_name = "activation energy for jmax" ; - double fates_leaf_jmaxhd(fates_pft) ; - fates_leaf_jmaxhd:units = "J/mol" ; - fates_leaf_jmaxhd:long_name = "deactivation energy for jmax" ; - double fates_leaf_jmaxse(fates_pft) ; - fates_leaf_jmaxse:units = "J/mol/K" ; - fates_leaf_jmaxse:long_name = "entropy term for jmax" ; - double fates_leaf_slamax(fates_pft) ; - fates_leaf_slamax:units = "m^2/gC" ; - fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; - double fates_leaf_slatop(fates_pft) ; - fates_leaf_slatop:units = "m^2/gC" ; - fates_leaf_slatop:long_name = "Specific Leaf Area (SLA) at top of canopy, projected area basis" ; - double fates_leaf_stomatal_intercept(fates_pft) ; - fates_leaf_stomatal_intercept:units = "umol H2O/m**2/s" ; - fates_leaf_stomatal_intercept:long_name = "Minimum unstressed stomatal conductance for Ball-Berry model and Medlyn model" ; - double fates_leaf_stomatal_slope_ballberry(fates_pft) ; - fates_leaf_stomatal_slope_ballberry:units = "unitless" ; - fates_leaf_stomatal_slope_ballberry:long_name = "stomatal slope parameter, as per Ball-Berry" ; - double fates_leaf_stomatal_slope_medlyn(fates_pft) ; - fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; - fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; - double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; - fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; - fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; - double fates_leaf_vcmaxha(fates_pft) ; - fates_leaf_vcmaxha:units = "J/mol" ; - fates_leaf_vcmaxha:long_name = "activation energy for vcmax" ; - double fates_leaf_vcmaxhd(fates_pft) ; - fates_leaf_vcmaxhd:units = "J/mol" ; - fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax" ; - double fates_leaf_vcmaxse(fates_pft) ; - fates_leaf_vcmaxse:units = "J/mol/K" ; - fates_leaf_vcmaxse:long_name = "entropy term for vcmax" ; - double fates_maintresp_reduction_curvature(fates_pft) ; - fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; - fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; - double fates_maintresp_reduction_intercept(fates_pft) ; - fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; - fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; - double fates_mort_bmort(fates_pft) ; - fates_mort_bmort:units = "1/yr" ; - fates_mort_bmort:long_name = "background mortality rate" ; - double fates_mort_freezetol(fates_pft) ; - fates_mort_freezetol:units = "degrees C" ; - fates_mort_freezetol:long_name = "minimum temperature tolerance" ; - double fates_mort_hf_flc_threshold(fates_pft) ; - fates_mort_hf_flc_threshold:units = "fraction" ; - fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; - double fates_mort_hf_sm_threshold(fates_pft) ; - fates_mort_hf_sm_threshold:units = "unitless" ; - fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; - double fates_mort_ip_age_senescence(fates_pft) ; - fates_mort_ip_age_senescence:units = "years" ; - fates_mort_ip_age_senescence:long_name = "Mortality cohort age senescence inflection point. If _ this mortality term is off. Setting this value turns on age dependent mortality. " ; - double fates_mort_ip_size_senescence(fates_pft) ; - fates_mort_ip_size_senescence:units = "dbh cm" ; - fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; - double fates_mort_prescribed_canopy(fates_pft) ; - fates_mort_prescribed_canopy:units = "1/yr" ; - fates_mort_prescribed_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; - double fates_mort_prescribed_understory(fates_pft) ; - fates_mort_prescribed_understory:units = "1/yr" ; - fates_mort_prescribed_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; - double fates_mort_r_age_senescence(fates_pft) ; - fates_mort_r_age_senescence:units = "mortality rate year^-1" ; - fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; - double fates_mort_r_size_senescence(fates_pft) ; - fates_mort_r_size_senescence:units = "mortality rate dbh^-1" ; - fates_mort_r_size_senescence:long_name = "Mortality dbh senescence rate of change. Sensible range is around 0.03-0.06. Larger values give steeper mortality curves." ; - double fates_mort_scalar_coldstress(fates_pft) ; - fates_mort_scalar_coldstress:units = "1/yr" ; - fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; - double fates_mort_scalar_cstarvation(fates_pft) ; - fates_mort_scalar_cstarvation:units = "1/yr" ; - fates_mort_scalar_cstarvation:long_name = "maximum mortality rate from carbon starvation" ; - double fates_mort_scalar_hydrfailure(fates_pft) ; - fates_mort_scalar_hydrfailure:units = "1/yr" ; - fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; - double fates_nonhydro_smpsc(fates_pft) ; - fates_nonhydro_smpsc:units = "mm" ; - fates_nonhydro_smpsc:long_name = "Soil water potential at full stomatal closure" ; - double fates_nonhydro_smpso(fates_pft) ; - fates_nonhydro_smpso:units = "mm" ; - fates_nonhydro_smpso:long_name = "Soil water potential at full stomatal opening" ; - double fates_phen_cold_size_threshold(fates_pft) ; - fates_phen_cold_size_threshold:units = "cm" ; - fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; - double fates_phen_evergreen(fates_pft) ; - fates_phen_evergreen:units = "logical flag" ; - fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; - double fates_phen_flush_fraction(fates_pft) ; - fates_phen_flush_fraction:units = "fraction" ; - fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; - double fates_phen_fnrt_drop_frac(fates_pft) ; - fates_phen_fnrt_drop_frac:units = "fraction" ; - fates_phen_fnrt_drop_frac:long_name = "fraction of fine roots to drop during drought or cold" ; - double fates_phen_season_decid(fates_pft) ; - fates_phen_season_decid:units = "logical flag" ; - fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; - double fates_phen_stem_drop_fraction(fates_pft) ; - fates_phen_stem_drop_fraction:units = "fraction" ; - fates_phen_stem_drop_fraction:long_name = "fraction of stems to drop for non-woody species during drought/cold" ; - double fates_phen_stress_decid(fates_pft) ; - fates_phen_stress_decid:units = "logical flag" ; - fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; - double fates_prescribed_npp_canopy(fates_pft) ; - fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; - fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; - double fates_prescribed_npp_understory(fates_pft) ; - fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; - fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; - double fates_rad_leaf_clumping_index(fates_pft) ; - fates_rad_leaf_clumping_index:units = "fraction (0-1)" ; - fates_rad_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; - double fates_rad_leaf_rhonir(fates_pft) ; - fates_rad_leaf_rhonir:units = "fraction" ; - fates_rad_leaf_rhonir:long_name = "Leaf reflectance: near-IR" ; - double fates_rad_leaf_rhovis(fates_pft) ; - fates_rad_leaf_rhovis:units = "fraction" ; - fates_rad_leaf_rhovis:long_name = "Leaf reflectance: visible" ; - double fates_rad_leaf_taunir(fates_pft) ; - fates_rad_leaf_taunir:units = "fraction" ; - fates_rad_leaf_taunir:long_name = "Leaf transmittance: near-IR" ; - double fates_rad_leaf_tauvis(fates_pft) ; - fates_rad_leaf_tauvis:units = "fraction" ; - fates_rad_leaf_tauvis:long_name = "Leaf transmittance: visible" ; - double fates_rad_leaf_xl(fates_pft) ; - fates_rad_leaf_xl:units = "unitless" ; - fates_rad_leaf_xl:long_name = "Leaf/stem orientation index" ; - double fates_rad_stem_rhonir(fates_pft) ; - fates_rad_stem_rhonir:units = "fraction" ; - fates_rad_stem_rhonir:long_name = "Stem reflectance: near-IR" ; - double fates_rad_stem_rhovis(fates_pft) ; - fates_rad_stem_rhovis:units = "fraction" ; - fates_rad_stem_rhovis:long_name = "Stem reflectance: visible" ; - double fates_rad_stem_taunir(fates_pft) ; - fates_rad_stem_taunir:units = "fraction" ; - fates_rad_stem_taunir:long_name = "Stem transmittance: near-IR" ; - double fates_rad_stem_tauvis(fates_pft) ; - fates_rad_stem_tauvis:units = "fraction" ; - fates_rad_stem_tauvis:long_name = "Stem transmittance: visible" ; - double fates_recruit_height_min(fates_pft) ; - fates_recruit_height_min:units = "m" ; - fates_recruit_height_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; - double fates_recruit_init_density(fates_pft) ; - fates_recruit_init_density:units = "stems/m2" ; - fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation" ; - double fates_recruit_prescribed_rate(fates_pft) ; - fates_recruit_prescribed_rate:units = "n/yr" ; - fates_recruit_prescribed_rate:long_name = "recruitment rate for prescribed physiology mode" ; - double fates_recruit_seed_alloc(fates_pft) ; - fates_recruit_seed_alloc:units = "fraction" ; - fates_recruit_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; - double fates_recruit_seed_alloc_mature(fates_pft) ; - fates_recruit_seed_alloc_mature:units = "fraction" ; - fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; - double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; - fates_recruit_seed_dbh_repro_threshold:units = "cm" ; - fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter (if any) where the plant will start extra clonal allocation to the seed pool" ; - double fates_recruit_seed_germination_rate(fates_pft) ; - fates_recruit_seed_germination_rate:units = "yr-1" ; - fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; - double fates_recruit_seed_supplement(fates_pft) ; - fates_recruit_seed_supplement:units = "KgC/m2/yr" ; - fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; - double fates_stoich_nitr(fates_plant_organs, fates_pft) ; - fates_stoich_nitr:units = "gN/gC" ; - fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; - double fates_stoich_phos(fates_plant_organs, fates_pft) ; - fates_stoich_phos:units = "gP/gC" ; - fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; - double fates_trim_inc(fates_pft) ; - fates_trim_inc:units = "m2/m2" ; - fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; - double fates_trim_limit(fates_pft) ; - fates_trim_limit:units = "m2/m2" ; - fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; - double fates_turb_displar(fates_pft) ; - fates_turb_displar:units = "unitless" ; - fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; - double fates_turb_leaf_diameter(fates_pft) ; - fates_turb_leaf_diameter:units = "m" ; - fates_turb_leaf_diameter:long_name = "Characteristic leaf dimension" ; - double fates_turb_z0mr(fates_pft) ; - fates_turb_z0mr:units = "unitless" ; - fates_turb_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; - double fates_turnover_branch(fates_pft) ; - fates_turnover_branch:units = "yr" ; - fates_turnover_branch:long_name = "turnover time of branches" ; - double fates_turnover_fnrt(fates_pft) ; - fates_turnover_fnrt:units = "yr" ; - fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; - double fates_turnover_leaf(fates_leafage_class, fates_pft) ; - fates_turnover_leaf:units = "yr" ; - fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; - double fates_turnover_senleaf_fdrought(fates_pft) ; - fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; - fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; - double fates_wood_density(fates_pft) ; - fates_wood_density:units = "g/cm3" ; - fates_wood_density:long_name = "mean density of woody tissue in plant" ; - double fates_woody(fates_pft) ; - fates_woody:units = "logical flag" ; - fates_woody:long_name = "Binary woody lifeform flag" ; - double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; - fates_hlm_pft_map:units = "area fraction" ; - fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; - double fates_fire_FBD(fates_litterclass) ; - fates_fire_FBD:units = "kg Biomass/m3" ; - fates_fire_FBD:long_name = "fuel bulk density" ; - double fates_fire_low_moisture_Coeff(fates_litterclass) ; - fates_fire_low_moisture_Coeff:units = "NA" ; - fates_fire_low_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_low_moisture_Slope(fates_litterclass) ; - fates_fire_low_moisture_Slope:units = "NA" ; - fates_fire_low_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_mid_moisture(fates_litterclass) ; - fates_fire_mid_moisture:units = "NA" ; - fates_fire_mid_moisture:long_name = "spitfire litter moisture threshold to be considered medium dry" ; - double fates_fire_mid_moisture_Coeff(fates_litterclass) ; - fates_fire_mid_moisture_Coeff:units = "NA" ; - fates_fire_mid_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_mid_moisture_Slope(fates_litterclass) ; - fates_fire_mid_moisture_Slope:units = "NA" ; - fates_fire_mid_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_min_moisture(fates_litterclass) ; - fates_fire_min_moisture:units = "NA" ; - fates_fire_min_moisture:long_name = "spitfire litter moisture threshold to be considered very dry" ; - double fates_fire_SAV(fates_litterclass) ; - fates_fire_SAV:units = "cm-1" ; - fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; - double fates_frag_maxdecomp(fates_litterclass) ; - fates_frag_maxdecomp:units = "yr-1" ; - fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; - 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_base_mr_20 ; - fates_base_mr_20:units = "gC/gN/s" ; - fates_base_mr_20:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; - 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" ; - double fates_cnp_eca_plant_escalar ; - fates_cnp_eca_plant_escalar:units = "" ; - fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; - double fates_cohort_age_fusion_tol ; - fates_cohort_age_fusion_tol:units = "unitless" ; - fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; - double fates_cohort_size_fusion_tol ; - fates_cohort_size_fusion_tol:units = "unitless" ; - fates_cohort_size_fusion_tol:long_name = "minimum fraction in difference in dbh between cohorts" ; - double fates_comp_excln ; - fates_comp_excln:units = "none" ; - fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; - double fates_damage_canopy_layer_code ; - fates_damage_canopy_layer_code:units = "unitless" ; - fates_damage_canopy_layer_code:long_name = "Integer code that decides whether damage affects canopy trees (1), understory trees (2)" ; - double fates_damage_event_code ; - fates_damage_event_code:units = "unitless" ; - fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; - double fates_dev_arbitrary ; - fates_dev_arbitrary:units = "unknown" ; - fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; - double fates_fire_active_crown_fire ; - fates_fire_active_crown_fire:units = "0 or 1" ; - fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; - double fates_fire_cg_strikes ; - fates_fire_cg_strikes:units = "fraction (0-1)" ; - fates_fire_cg_strikes:long_name = "fraction of cloud to ground lightning strikes" ; - double fates_fire_drying_ratio ; - fates_fire_drying_ratio:units = "NA" ; - fates_fire_drying_ratio:long_name = "spitfire parameter, fire drying ratio for fuel moisture, alpha_FMC EQ 6 Thonicke et al 2010" ; - double fates_fire_durat_slope ; - fates_fire_durat_slope:units = "NA" ; - fates_fire_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; - double fates_fire_fdi_a ; - fates_fire_fdi_a:units = "NA" ; - fates_fire_fdi_a:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010" ; - double fates_fire_fdi_alpha ; - fates_fire_fdi_alpha:units = "NA" ; - fates_fire_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; - double fates_fire_fdi_b ; - fates_fire_fdi_b:units = "NA" ; - fates_fire_fdi_b:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010 " ; - double fates_fire_fuel_energy ; - fates_fire_fuel_energy:units = "kJ/kg" ; - fates_fire_fuel_energy:long_name = "spitfire parameter, heat content of fuel" ; - double fates_fire_max_durat ; - fates_fire_max_durat:units = "minutes" ; - fates_fire_max_durat:long_name = "spitfire parameter, fire maximum duration, Equation 14 Thonicke et al 2010" ; - double fates_fire_miner_damp ; - fates_fire_miner_damp:units = "NA" ; - fates_fire_miner_damp:long_name = "spitfire parameter, mineral-dampening coefficient EQ A1 Thonicke et al 2010 " ; - double fates_fire_miner_total ; - fates_fire_miner_total:units = "fraction" ; - fates_fire_miner_total:long_name = "spitfire parameter, total mineral content, Table A1 Thonicke et al 2010" ; - double fates_fire_nignitions ; - fates_fire_nignitions:units = "ignitions per year per km2" ; - fates_fire_nignitions:long_name = "number of annual ignitions per square km" ; - double fates_fire_part_dens ; - fates_fire_part_dens:units = "kg/m2" ; - fates_fire_part_dens:long_name = "spitfire parameter, oven dry particle density, Table A1 Thonicke et al 2010" ; - double fates_fire_threshold ; - fates_fire_threshold:units = "kW/m" ; - fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; - double fates_frag_cwd_fcel ; - fates_frag_cwd_fcel:units = "unitless" ; - fates_frag_cwd_fcel:long_name = "Cellulose fraction for CWD" ; - double fates_frag_cwd_flig ; - fates_frag_cwd_flig:units = "unitless" ; - fates_frag_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; - double fates_hydro_kmax_rsurf1 ; - fates_hydro_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; - fates_hydro_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; - double fates_hydro_kmax_rsurf2 ; - fates_hydro_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; - fates_hydro_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; - double fates_hydro_psi0 ; - fates_hydro_psi0:units = "MPa" ; - fates_hydro_psi0:long_name = "sapwood water potential at saturation" ; - double fates_hydro_psicap ; - fates_hydro_psicap:units = "MPa" ; - fates_hydro_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; - 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_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" ; - double fates_landuse_logging_collateral_frac ; - fates_landuse_logging_collateral_frac:units = "fraction" ; - fates_landuse_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; - double fates_landuse_logging_dbhmax ; - fates_landuse_logging_dbhmax:units = "cm" ; - fates_landuse_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; - double fates_landuse_logging_dbhmax_infra ; - fates_landuse_logging_dbhmax_infra:units = "cm" ; - fates_landuse_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; - double fates_landuse_logging_dbhmin ; - fates_landuse_logging_dbhmin:units = "cm" ; - fates_landuse_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; - double fates_landuse_logging_direct_frac ; - fates_landuse_logging_direct_frac:units = "fraction" ; - fates_landuse_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; - double fates_landuse_logging_event_code ; - fates_landuse_logging_event_code:units = "unitless" ; - fates_landuse_logging_event_code:long_name = "Integer code that options how logging events are structured" ; - double fates_landuse_logging_export_frac ; - fates_landuse_logging_export_frac:units = "fraction" ; - fates_landuse_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; - double fates_landuse_logging_mechanical_frac ; - fates_landuse_logging_mechanical_frac:units = "fraction" ; - fates_landuse_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; - double fates_landuse_pprodharv10_forest_mean ; - fates_landuse_pprodharv10_forest_mean:units = "fraction" ; - fates_landuse_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; - double fates_leaf_photo_temp_acclim_timescale ; - fates_leaf_photo_temp_acclim_timescale:units = "days" ; - fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; - double fates_leaf_photo_tempsens_model ; - fates_leaf_photo_tempsens_model:units = "unitless" ; - fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; - double fates_leaf_stomatal_assim_model ; - fates_leaf_stomatal_assim_model:units = "unitless" ; - fates_leaf_stomatal_assim_model:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; - double fates_leaf_stomatal_model ; - fates_leaf_stomatal_model:units = "unitless" ; - fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; - double fates_leaf_theta_cj_c3 ; - fates_leaf_theta_cj_c3:units = "unitless" ; - fates_leaf_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; - double fates_leaf_theta_cj_c4 ; - fates_leaf_theta_cj_c4:units = "unitless" ; - fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; - double fates_maintresp_model ; - fates_maintresp_model:units = "unitless" ; - fates_maintresp_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991) (NOT USED)" ; - double fates_maxcohort ; - fates_maxcohort:units = "count" ; - fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; - double fates_maxpatch_primary ; - fates_maxpatch_primary:units = "count" ; - fates_maxpatch_primary:long_name = "maximum number of primary vegetation patches per site" ; - double fates_maxpatch_secondary ; - fates_maxpatch_secondary:units = "count" ; - fates_maxpatch_secondary:long_name = "maximum number of secondary vegetation patches per site" ; - double fates_mort_disturb_frac ; - fates_mort_disturb_frac:units = "fraction" ; - fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; - double fates_mort_understorey_death ; - fates_mort_understorey_death:units = "fraction" ; - fates_mort_understorey_death:long_name = "fraction of plants in understorey cohort impacted by overstorey tree-fall" ; - double fates_patch_fusion_tol ; - fates_patch_fusion_tol:units = "unitless" ; - fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; - double fates_phen_chilltemp ; - fates_phen_chilltemp:units = "degrees C" ; - fates_phen_chilltemp:long_name = "chilling day counting threshold for vegetation" ; - double fates_phen_coldtemp ; - fates_phen_coldtemp:units = "degrees C" ; - fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; - double fates_phen_drought_model ; - fates_phen_drought_model:units = "unitless" ; - fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; - double fates_phen_drought_threshold ; - fates_phen_drought_threshold:units = "m3/m3 or mm" ; - fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; - double fates_phen_gddthresh_a ; - fates_phen_gddthresh_a:units = "none" ; - fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_gddthresh_b ; - fates_phen_gddthresh_b:units = "none" ; - fates_phen_gddthresh_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_gddthresh_c ; - fates_phen_gddthresh_c:units = "none" ; - fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_mindaysoff ; - fates_phen_mindaysoff:units = "days" ; - fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves became off-allometry" ; - double fates_phen_mindayson ; - fates_phen_mindayson:units = "days" ; - fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; - double fates_phen_moist_threshold ; - fates_phen_moist_threshold:units = "m3/m3 or mm" ; - fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; - double fates_phen_ncolddayslim ; - fates_phen_ncolddayslim:units = "days" ; - fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; - double fates_q10_froz ; - fates_q10_froz:units = "unitless" ; - fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; - double fates_q10_mr ; - fates_q10_mr:units = "unitless" ; - fates_q10_mr:long_name = "Q10 for maintenance respiration" ; - double fates_soil_salinity ; - fates_soil_salinity:units = "ppt" ; - fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; - double fates_vai_top_bin_width ; - fates_vai_top_bin_width:units = "m2/m2" ; - fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; - double fates_vai_width_increase_factor ; - fates_vai_width_increase_factor:units = "unitless" ; - fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; - -// global attributes: - :history = "This parameter file is maintained in version control\nSee https://github.com/NGEET/fates/blob/master/parameter_files/fates_params_default.cdl \nFor changes, use git blame \n" ; -data: - - fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; - - fates_history_coageclass_bin_edges = 0, 5 ; - - fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; - - fates_history_damage_bin_edges = 0, 80 ; - - fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, - 80, 90, 100 ; - - fates_alloc_organ_id = 1, 2, 3, 6 ; - - fates_hydro_htftype_node = 1, 1, 1, 1 ; - - fates_pftname = - "broadleaf_evergreen_tropical_tree ", - "needleleaf_evergreen_extratrop_tree ", - "needleleaf_colddecid_extratrop_tree ", - "broadleaf_evergreen_extratrop_tree ", - "broadleaf_hydrodecid_tropical_tree ", - "broadleaf_colddecid_extratrop_tree ", - "broadleaf_evergreen_extratrop_shrub ", - "broadleaf_hydrodecid_extratrop_shrub ", - "broadleaf_colddecid_extratrop_shrub ", - "arctic_c3_grass ", - "cool_c3_grass ", - "c4_grass " ; - - fates_hydro_organ_name = - "leaf ", - "stem ", - "transporting root ", - "absorbing root " ; - - fates_alloc_organ_name = - "leaf", - "fine root", - "sapwood", - "structure" ; - - fates_litterclass_name = - "twig ", - "small branch ", - "large branch ", - "trunk ", - "dead leaves ", - "live grass " ; - - 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, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; - - fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, - 1.2, 1.2, 1.2 ; - - fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, - 0.8, 0.8, 0.8, 0.8 ; - - fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, - 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; - - fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, - 0.572, 0.572, 0.572, 0.572 ; - - fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, - 1.94, 1.94, 1.94 ; - - fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, - 0.931, 0.931, 0.931, 0.931 ; - - fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6 ; - - fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, - 0.95, 1, 1, 1 ; - - fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, - 0.07, 0.07, 0.07 ; - - fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, - 1.3 ; - - fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, - 0.55, 0.55, 0.55 ; - - fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464 ; - - fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119 ; - - fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, - 0.64, 0.64, 0.64 ; - - fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, - 0.37, 0.37, 0.37 ; - - fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, - -999.9, -999.9, -999.9, -999.9, -999.9 ; - - fates_allom_dbh_maxheight = 90, 90, 90, 90, 90, 90, 3, 3, 2, 0.35, 0.35, 0.35 ; - - fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; - - fates_allom_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; - - fates_allom_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - - fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, - 0.8, 0.8, 0.8 ; - - fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1, 0.1 ; - - fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_zroot_k = 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 ; - - fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; - - fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100 ; - - fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1 ; - - fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100 ; - - fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; - - fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5 ; - - fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, - 280, 280 ; - - fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, - 0.14, 0.14, 0.14 ; - - fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, - 0.27, 0.27, 0.27 ; - - fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1 ; - - fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_eca_vmax_nh4 = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, - 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - - fates_cnp_eca_vmax_no3 = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, - 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - - fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, - 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - - fates_cnp_fnrt_adapt_tscale = 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100, 100 ; - - fates_cnp_nfix1 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5, 1.5 ; - - fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5, 1.5 ; - - fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_rd_vmax_n = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, - 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - - fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_turnover_nitr_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_turnover_phos_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, - 5e-10, 5e-10, 5e-10, 5e-10 ; - - fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, - 0.01, 0.01, 0.01 ; - - fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; - - fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, - 5.5, 5.5 ; - - fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, - 0.2 ; - - fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, - 0.07, 0.07, 0.07, 0.07 ; - - fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, - 0.775, 0.775, 0.775, 0.775, 0.775 ; - - fates_frag_fnrt_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5 ; - - fates_frag_fnrt_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; - - fates_frag_fnrt_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; - - fates_frag_leaf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5 ; - - fates_frag_leaf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; - - fates_frag_leaf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; - - fates_frag_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, - 0.51, 0.51, 0.51, 0.51 ; - - fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, - 0.11, 0.11 ; - - fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, - 2.5, 2.5 ; - - fates_hydro_avuln_node = - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 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_hydro_epsil_node = - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - - fates_hydro_fcap_node = - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, - 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_hydro_kmax_node = - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; - - fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, - -1.5, -1.5, -1.5 ; - - fates_hydro_p50_node = - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25 ; - - fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, - 0.333, 0.333, 0.333, 0.333, 0.333 ; - - fates_hydro_pinot_node = - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; - - fates_hydro_pitlp_node = - -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, - -1.67, -1.67, - -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, - -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, - -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; - - fates_hydro_resid_node = - 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, - 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - - fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, - 0.625, 0.625, 0.625, 0.625, 0.625 ; - - fates_hydro_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, - 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; - - fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; - - fates_hydro_thetas_node = - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; - - fates_hydro_vg_alpha_node = - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005 ; - - fates_hydro_vg_m_node = - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_hydro_vg_n_node = - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 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_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, - 43540, 43540, 43540, 43540 ; - - fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, - 152040, 152040, 152040, 152040, 152040 ; - - fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, - 495 ; - - fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, - 0.03, 0.03, 0.03, 0.03, 0.03 ; - - fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, - 0.03, 0.03, 0.03, 0.03 ; - - fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, - 10000, 10000, 10000, 10000, 10000, 40000 ; - - fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - - fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, - 4.7, 2.2, 5.3, 1.6 ; - - fates_leaf_vcmax25top = - 50, 65, 39, 62, 41, 58, 62, 54, 54, 78, 78, 78 ; - - fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, - 65330, 65330, 65330, 65330 ; - - fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, - 149250, 149250, 149250, 149250, 149250 ; - - fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, - 485 ; - - fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, - 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; - - fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, - 0.014, 0.014, 0.014, 0.014 ; - - fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -60, -10, -80, -80, - -20, 2.5 ; - - fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5 ; - - fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, - 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; - - fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_prescribed_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, - 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; - - fates_mort_prescribed_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, - 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; - - fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - - fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6, 0.6 ; - - fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6, 0.6 ; - - fates_nonhydro_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, - -255000, -255000, -255000, -255000, -255000, -255000 ; - - fates_nonhydro_smpso = -66000, -66000, -66000, -66000, -66000, -66000, - -66000, -66000, -66000, -66000, -66000, -66000 ; - - fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; - - fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, - 0.5 ; - - fates_phen_fnrt_drop_frac = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; - - fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; - - fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, - 0.4, 0.4, 0.4 ; - - fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, - 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; - - fates_rad_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, - 0.9, 0.75, 0.75, 0.75 ; - - fates_rad_leaf_rhonir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, - 0.41, 0.28, 0.28, 0.28 ; - - fates_rad_leaf_rhovis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, - 0.08, 0.05, 0.05, 0.05 ; - - fates_rad_leaf_taunir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, - 0.43, 0.4, 0.4, 0.4 ; - - fates_rad_leaf_tauvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, - 0.06, 0.05, 0.05, 0.05 ; - - fates_rad_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, - -0.23, -0.23, -0.23 ; - - fates_rad_stem_rhonir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, - 0.49, 0.53, 0.53, 0.53 ; - - fates_rad_stem_rhovis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.21, 0.31, 0.31, 0.31 ; - - fates_rad_stem_taunir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, - 0.001, 0.001, 0.25, 0.25, 0.25 ; - - fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, - 0.001, 0.001, 0.12, 0.12, 0.12 ; - - fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, - 0.125, 0.125, 0.125 ; - - fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, - 0.2, 0.2, 0.2 ; - - fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, - 0.02, 0.02, 0.02, 0.02, 0.02 ; - - fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1, 0.1 ; - - fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, - 0.9 ; - - fates_recruit_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, - 1.47, 1.47, 1.47 ; - - fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_stoich_nitr = - 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, - 0.0047, 0.0047, 0.0047 ; - - fates_stoich_phos = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, - 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, - 0.00047, 0.00047, 0.00047, 0.00047 ; - - fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, - 0.03, 0.03 ; - - fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; - - fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, - 0.67, 0.67, 0.67 ; - - fates_turb_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.04, 0.04, 0.04, 0.04 ; - - fates_turb_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, - 0.055, 0.055, 0.055, 0.055 ; - - fates_turnover_branch = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; - - fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - - fates_turnover_leaf = - 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - - fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, - 0.7 ; - - fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; - - fates_hlm_pft_map = - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; - - fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; - - fates_fire_low_moisture_Coeff = 1.12, 1.09, 0.98, 0.8, 1.15, 1.15 ; - - fates_fire_low_moisture_Slope = 0.62, 0.72, 0.85, 0.8, 0.62, 0.62 ; - - fates_fire_mid_moisture = 0.72, 0.51, 0.38, 1, 0.8, 0.8 ; - - fates_fire_mid_moisture_Coeff = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; - - fates_fire_mid_moisture_Slope = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; - - fates_fire_min_moisture = 0.18, 0.12, 0, 0, 0.24, 0.24 ; - - fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; - - fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; - - fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; - - fates_base_mr_20 = 2.52e-06 ; - - fates_canopy_closure_thresh = 0.8 ; - - fates_cnp_eca_plant_escalar = 1.25e-05 ; - - fates_cohort_age_fusion_tol = 0.08 ; - - fates_cohort_size_fusion_tol = 0.08 ; - - fates_comp_excln = 3 ; - - fates_damage_canopy_layer_code = 1 ; - - fates_damage_event_code = 1 ; - - fates_dev_arbitrary = _ ; - - fates_fire_active_crown_fire = 0 ; - - fates_fire_cg_strikes = 0.2 ; - - fates_fire_drying_ratio = 66000 ; - - fates_fire_durat_slope = -11.06 ; - - fates_fire_fdi_a = 17.62 ; - - fates_fire_fdi_alpha = 0.00037 ; - - fates_fire_fdi_b = 243.12 ; - - fates_fire_fuel_energy = 18000 ; - - fates_fire_max_durat = 240 ; - - fates_fire_miner_damp = 0.41739 ; - - fates_fire_miner_total = 0.055 ; - - fates_fire_nignitions = 15 ; - - fates_fire_part_dens = 513 ; - - fates_fire_threshold = 50 ; - - fates_frag_cwd_fcel = 0.76 ; - - fates_frag_cwd_flig = 0.24 ; - - fates_hydro_kmax_rsurf1 = 20 ; - - fates_hydro_kmax_rsurf2 = 0.0001 ; - - fates_hydro_psi0 = 0 ; - - fates_hydro_psicap = -0.6 ; - - fates_hydro_solver = 1 ; - - fates_landuse_logging_coll_under_frac = 0.55983 ; - - fates_landuse_logging_collateral_frac = 0.05 ; - - fates_landuse_logging_dbhmax = _ ; - - fates_landuse_logging_dbhmax_infra = 35 ; - - fates_landuse_logging_dbhmin = 50 ; - - fates_landuse_logging_direct_frac = 0.15 ; - - fates_landuse_logging_event_code = -30 ; - - fates_landuse_logging_export_frac = 0.8 ; - - fates_landuse_logging_mechanical_frac = 0.05 ; - - fates_landuse_pprodharv10_forest_mean = 0.8125 ; - - fates_leaf_photo_temp_acclim_timescale = 30 ; - - fates_leaf_photo_tempsens_model = 1 ; - - fates_leaf_stomatal_assim_model = 1 ; - - fates_leaf_stomatal_model = 1 ; - - fates_leaf_theta_cj_c3 = 0.999 ; - - fates_leaf_theta_cj_c4 = 0.999 ; - - fates_maintresp_model = 1 ; - - fates_maxcohort = 100 ; - - fates_maxpatch_primary = 10 ; - - fates_maxpatch_secondary = 4 ; - - fates_mort_disturb_frac = 1 ; - - fates_mort_understorey_death = 0.55983 ; - - fates_patch_fusion_tol = 0.05 ; - - fates_phen_chilltemp = 5 ; - - fates_phen_coldtemp = 7.5 ; - - fates_phen_drought_model = 0 ; - - fates_phen_drought_threshold = 0.15 ; - - fates_phen_gddthresh_a = -68 ; - - fates_phen_gddthresh_b = 638 ; - - fates_phen_gddthresh_c = -0.01 ; - - fates_phen_mindaysoff = 100 ; - - fates_phen_mindayson = 90 ; - - fates_phen_moist_threshold = 0.18 ; - - fates_phen_ncolddayslim = 5 ; - - fates_q10_froz = 1.5 ; - - fates_q10_mr = 1.5 ; - - fates_soil_salinity = 0.4 ; - - fates_vai_top_bin_width = 1 ; - - fates_vai_width_increase_factor = 1 ; -} From 0bcfd4fc2eb6e5a3b44aff3408fe25e2ee6995b0 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 15 Jun 2022 10:08:22 -0700 Subject: [PATCH 246/852] change flux terms to static allocation by maxpft to dynamic allocation by numpft --- main/EDInitMod.F90 | 8 +++++- main/EDTypesMod.F90 | 63 ++++++++++++++++++++++----------------------- 2 files changed, 38 insertions(+), 33 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index b9f551b5be..34f1f49d20 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -127,7 +127,13 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) allocate(site_in%growthflux_fusion(1:nlevsclass,1:numpft)) allocate(site_in%mass_balance(1:num_elements)) allocate(site_in%flux_diags(1:num_elements)) - + + allocate(site_in%term_carbonflux_canopy(1:numpft)) + allocate(site_in%term_carbonflux_ustory(1:numpft)) + allocate(site_in%imort_carbonflux(1:numpft)) + allocate(site_in%fmort_carbonflux_canopy(1:numpft)) + allocate(site_in%fmort_carbonflux_ustory(1:numpft)) + site_in%nlevsoil = bc_in%nlevsoil allocate(site_in%rootfrac_scr(site_in%nlevsoil)) allocate(site_in%zi_soil(0:site_in%nlevsoil)) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 3c9e44b5b8..8475844c83 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -792,42 +792,41 @@ module EDTypesMod ! TERMINATION, RECRUITMENT, DEMOTION, and DISTURBANCE - real(r8), allocatable :: term_nindivs_canopy(:,:) ! number of canopy individuals that were in cohorts which - ! were terminated this timestep, on size x pft - real(r8), allocatable :: term_nindivs_ustory(:,:) ! number of understory individuals that were in cohorts which - ! were terminated this timestep, on size x pft - - real(r8) :: term_carbonflux_canopy(1:maxpft) ! carbon flux from live to dead pools associated - ! with termination mortality, per canopy level - real(r8) :: term_carbonflux_ustory(1:maxpft) ! carbon flux from live to dead pools associated - ! with termination mortality, per canopy level - real(r8) :: demotion_carbonflux ! biomass of demoted individuals from canopy to understory [kgC/ha/day] - real(r8) :: promotion_carbonflux ! biomass of promoted individuals from understory to canopy [kgC/ha/day] - real(r8) :: imort_carbonflux(1:maxpft) ! biomass of individuals killed due to impact mortality per year. [kgC/ha/day] - real(r8) :: fmort_carbonflux_canopy(1:maxpft) ! biomass of canopy indivs killed due to fire per year. [gC/m2/sec] - real(r8) :: fmort_carbonflux_ustory(1:maxpft) ! biomass of understory indivs killed due to fire per year [gC/m2/sec] - real(r8) :: harvest_carbon_flux ! diagnostic site level flux of carbon as harvested plants [kg C / m2 / day] - - real(r8) :: recruitment_rate(1:maxpft) ! number of individuals that were recruited into new cohorts - real(r8), allocatable :: demotion_rate(:) ! rate of individuals demoted from canopy to understory per FATES timestep - - real(r8), allocatable :: promotion_rate(:) ! rate of individuals promoted from understory to canopy per FATES timestep - - real(r8), allocatable :: imort_rate(:,:) ! rate of individuals killed due to impact mortality per year. on size x pft array + real(r8), allocatable :: term_nindivs_canopy(:,:) ! number of canopy individuals that were in cohorts which + ! were terminated this timestep, on size x pft + real(r8), allocatable :: term_nindivs_ustory(:,:) ! number of understory individuals that were in cohorts which + ! were terminated this timestep, on size x pft + + real(r8), allocatable :: term_carbonflux_canopy(:) ! carbon flux from live to dead pools associated + ! with termination mortality, per canopy level + real(r8), allocatable :: term_carbonflux_ustory(:) ! carbon flux from live to dead pools associated + ! with termination mortality, per canopy level + real(r8), allocatable :: imort_carbonflux(:) ! biomass of individuals killed due to impact mortality per year. [kgC/ha/day] + real(r8), allocatable :: fmort_carbonflux_canopy(:) ! biomass of canopy indivs killed due to fire per year. [gC/m2/sec] + real(r8), allocatable :: fmort_carbonflux_ustory(:) ! biomass of understory indivs killed due to fire per year [gC/m2/sec] + + real(r8) :: demotion_carbonflux ! biomass of demoted individuals from canopy to understory [kgC/ha/day] + real(r8) :: promotion_carbonflux ! biomass of promoted individuals from understory to canopy [kgC/ha/day] + real(r8) :: harvest_carbon_flux ! diagnostic site level flux of carbon as harvested plants [kg C / m2 / day] + + real(r8) :: recruitment_rate(1:maxpft) ! number of individuals that were recruited into new cohorts + real(r8), allocatable :: demotion_rate(:) ! rate of individuals demoted from canopy to understory per FATES timestep + real(r8), allocatable :: promotion_rate(:) ! rate of individuals promoted from understory to canopy per FATES timestep + real(r8), allocatable :: imort_rate(:,:) ! rate of individuals killed due to impact mortality per year. on size x pft array - real(r8), allocatable :: fmort_rate_canopy(:,:) ! rate of canopy individuals killed due to fire mortality per year. - ! on size x pft array (1:nlevsclass,1:numpft) - real(r8), allocatable :: fmort_rate_ustory(:,:) ! rate of understory individuals killed due to fire mortality per year. - ! on size x pft array (1:nlevsclass,1:numpft) + real(r8), allocatable :: fmort_rate_canopy(:,:) ! rate of canopy individuals killed due to fire mortality per year. + ! on size x pft array (1:nlevsclass,1:numpft) + real(r8), allocatable :: fmort_rate_ustory(:,:) ! rate of understory individuals killed due to fire mortality per year. + ! on size x pft array (1:nlevsclass,1:numpft) - real(r8), allocatable :: fmort_rate_cambial(:,:) ! rate of individuals killed due to fire mortality - ! from cambial damage per year. on size x pft array - real(r8), allocatable :: fmort_rate_crown(:,:) ! rate of individuals killed due to fire mortality - ! from crown damage per year. on size x pft array + real(r8), allocatable :: fmort_rate_cambial(:,:) ! rate of individuals killed due to fire mortality + ! from cambial damage per year. on size x pft array + real(r8), allocatable :: fmort_rate_crown(:,:) ! rate of individuals killed due to fire mortality + ! from crown damage per year. on size x pft array - real(r8), allocatable :: growthflux_fusion(:,:) ! rate of individuals moving into a given size class bin - ! due to fusion in a given day. on size x pft array + real(r8), allocatable :: growthflux_fusion(:,:) ! rate of individuals moving into a given size class bin + ! due to fusion in a given day. on size x pft array From b3297509419e721d4d8b9a5430f39ea1bcfec90f Mon Sep 17 00:00:00 2001 From: YanlanLiu Date: Thu, 16 Jun 2022 13:54:32 -0700 Subject: [PATCH 247/852] bug corrected in areal normalization of external seed --- biogeochem/EDPhysiologyMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 4a0a8ed9db..d30b3dd1e2 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1492,9 +1492,9 @@ subroutine SeedIn( currentSite, bc_in, bc_out) !seed_in_external = seed_stoich*EDPftvarcon_inst%seed_suppl(pft)*years_per_day ![kg/m2/day] ! bc%seed_in(pft) in [kg/site/day] - seed_in_external = bc_in%seed_in(pft)/currentPatch%area + seed_stoich*EDPftvarcon_inst%seed_suppl(pft)*years_per_day ![kg/m2/day] + seed_in_external = bc_in%seed_in(pft)/area + seed_stoich*EDPftvarcon_inst%seed_suppl(pft)*years_per_day ![kg/m2/day] - !write(fates_log(),*) 'pft, bc_in%seed_in(pft),bc_in%seed_in(pft)/currentPatch%area, seed_in_external: ', pft, bc_in%seed_in(pft), bc_in%seed_in(pft)/currentPatch%area, seed_in_external + write(fates_log(),*) 'pft, bc_in%seed_in(pft),bc_in%seed_in(pft)/currentPatch%area, seed_in_external: ', pft, bc_in%seed_in(pft), bc_in%seed_in(pft)/currentPatch%area, seed_in_external !-------------------------------------------------------------------------------------------------- litt%seed_in_extern(pft) = litt%seed_in_extern(pft) + seed_in_external From 14c300295f5e5a25029576ba520fcd0c3a42535e Mon Sep 17 00:00:00 2001 From: Shijie Shu Date: Thu, 16 Jun 2022 14:25:03 -0700 Subject: [PATCH 248/852] Added historical outputs of secondary patches. --- biogeochem/EDCanopyStructureMod.F90 | 3 +- biogeochem/EDLoggingMortalityMod.F90 | 19 +- biogeochem/EDPatchDynamicsMod.F90 | 286 ++++++++++++------------ main/EDInitMod.F90 | 1 + main/EDMainMod.F90 | 1 - main/EDTypesMod.F90 | 6 +- main/FatesHistoryInterfaceMod.F90 | 322 ++++++++++++++++++++++++--- 7 files changed, 451 insertions(+), 187 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 1d9d8206fe..694f3c2e46 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1901,13 +1901,14 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_in,bc_out) use EDTypesMod , only : ed_patch_type, ed_cohort_type, & ed_site_type, AREA - use FatesInterfaceTypesMod , only : bc_out_type + use FatesInterfaceTypesMod , only : bc_in_type, bc_out_type ! ! !ARGUMENTS integer, intent(in) :: nsites type(ed_site_type), intent(inout), target :: sites(nsites) integer, intent(in) :: fcolumn(nsites) + type(bc_in_type), intent(inout) :: bc_in(nsites) type(bc_out_type), intent(inout) :: bc_out(nsites) ! Locals diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index bc3c90da0a..d17010a33a 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -374,12 +374,13 @@ subroutine get_harvest_rate_area (patch_anthro_disturbance_label, hlm_harvest_ca integer :: h_index ! for looping over harvest categories integer :: icode ! Integer equivalent of the event code (parameter file only allows reals) - ! Loop around harvest categories to determine the annual hlm harvest rate for the current cohort based on patch history info + ! Loop around harvest categories to determine the annual hlm harvest rate for the current cohort based on patch history info + ! We do account forest only since non-forest harvest has geographical mismatch to LUH2 dataset harvest_rate = 0._r8 do h_index = 1,hlm_num_lu_harvest_cats if (patch_anthro_disturbance_label .eq. primaryforest) then - if(hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1" .or. & - hlm_harvest_catnames(h_index) .eq. "HARVEST_VH2") then + if(hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1") then! .or. & + ! hlm_harvest_catnames(h_index) .eq. "HARVEST_VH2") then harvest_rate = harvest_rate + hlm_harvest_rates(h_index) endif else if (patch_anthro_disturbance_label .eq. secondaryforest .and. & @@ -389,8 +390,8 @@ subroutine get_harvest_rate_area (patch_anthro_disturbance_label, hlm_harvest_ca endif else if (patch_anthro_disturbance_label .eq. secondaryforest .and. & secondary_age < secondary_age_threshold) then - if(hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2" .or. & - hlm_harvest_catnames(h_index) .eq. "HARVEST_SH3") then + if(hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2") then! .or. & + ! hlm_harvest_catnames(h_index) .eq. "HARVEST_SH3") then harvest_rate = harvest_rate + hlm_harvest_rates(h_index) endif endif @@ -594,8 +595,8 @@ subroutine get_harvest_rate_carbon (patch_anthro_disturbance_label, hlm_harvest_ do h_index = 1,hlm_num_lu_harvest_cats if (patch_anthro_disturbance_label .eq. primaryforest) then - if(hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1" .or. & - hlm_harvest_catnames(h_index) .eq. "HARVEST_VH2") then + if(hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1") then! .or. & + ! hlm_harvest_catnames(h_index) .eq. "HARVEST_VH2") then harvest_rate_c = harvest_rate_c + hlm_harvest_rates(h_index) ! Determine the total supply of available C for harvest if(harvestable_forest_c(h_index) >= harvest_rate_c) then @@ -624,8 +625,8 @@ subroutine get_harvest_rate_carbon (patch_anthro_disturbance_label, hlm_harvest_ endif else if (patch_anthro_disturbance_label .eq. secondaryforest .and. & secondary_age < secondary_age_threshold) then - if(hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2" .or. & - hlm_harvest_catnames(h_index) .eq. "HARVEST_SH3") then + if(hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2") then! .or. & + ! hlm_harvest_catnames(h_index) .eq. "HARVEST_SH3") then harvest_rate_c = harvest_rate_c + hlm_harvest_rates(h_index) if(harvestable_forest_c(h_index) >= harvest_rate_c) then harvest_rate_supply = harvest_rate_supply + harvestable_forest_c(h_index) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index cfe719b44b..b1036035a0 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -191,9 +191,13 @@ subroutine disturbance_rates( site_in, bc_in) integer :: h_index real(r8) :: frac_site_primary real(r8) :: harvest_rate + real(r8) :: tempsum real(r8) :: harvestable_forest_c(hlm_num_lu_harvest_cats) real(r8) :: available_forest_c(hlm_num_lu_harvest_cats) integer :: harvest_tag(hlm_num_lu_harvest_cats) + integer :: harvest_debt_primary + integer :: harvest_debt_secondary + integer :: patch_no_secondary !---------------------------------------------------------------------------------------------- ! Calculate Mortality Rates (these were previously calculated during growth derivatives) @@ -208,6 +212,10 @@ subroutine disturbance_rates( site_in, bc_in) site_in%harvest_carbon_flux = 0._r8 + harvest_debt_primary = 0 + harvest_debt_secondary = 0 + patch_no_secondary = 0 + currentPatch => site_in%oldest_patch do while (associated(currentPatch)) @@ -259,21 +267,75 @@ subroutine disturbance_rates( site_in, bc_in) currentCohort => currentCohort%taller end do - currentPatch%disturbance_mode = fates_unset_int - currentPatch => currentPatch%younger - end do - ! Determine harvest debt from all three categories - do h_index = 1, hlm_num_lu_harvest_cats - if (harvest_tag(h_index) == 2 .or. & - (harvest_tag(h_index) == 1 .and. .not. (hlm_harvest_bypass_criteria))) then - if(logging_time) then - site_in%resources_management%harvest_debt = site_in%resources_management%harvest_debt + & - bc_in%hlm_harvest_rates(h_index) - end if + ! Determine harvest debt status from all three categories + ! Each cohort has the same harvest tag but not each patch + ! Hence this part shall be within the patch loop + ! TODO: we can define harvest debt as a fraction of the + ! harvest rate in the future + ! Warning: Non-forest harvest is not accounted for yet + ! Thus the harvest tag for non-forest are not effective + if(logging_time) then + harvest_debt_loop: do h_index = 1, hlm_num_lu_harvest_cats + ! Primary patch: Once a patch has debt, skip the calculation + if (harvest_debt_primary == 0) then + if ( currentPatch%anthro_disturbance_label .eq. primaryforest ) then + if ( harvest_tag(h_index) == 2 .or. & + (harvest_tag(h_index) == 1 .and. .not. (hlm_harvest_bypass_criteria))) then + ! h_index points to primary forest harvest + if((bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1")) then + harvest_debt_primary = 1 + exit harvest_debt_loop + end if + end if + end if + end if + ! Secondary patch + if (harvest_debt_secondary == 0) then + if ( currentPatch%anthro_disturbance_label .eq. secondaryforest ) then + patch_no_secondary = patch_no_secondary + 1 + if ( harvest_tag(h_index) == 2 .or. & + (harvest_tag(h_index) == 1 .and. .not. (hlm_harvest_bypass_criteria))) then + ! h_index points to secondary forest harvest + if((bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH1") .or. & + (bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2")) then + harvest_debt_secondary = 1 + exit harvest_debt_loop + end if + end if + end if + end if + end do harvest_debt_loop end if + + currentPatch => currentPatch%younger end do + ! Obatin actual harvest debt. This shall be outside the patch loop + if(logging_time) then + do h_index = 1, hlm_num_lu_harvest_cats + if ( harvest_debt_primary == 1 ) then + ! Only account for primary forest harvest rate + if((bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1")) then !.or. & + ! (bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_VH2")) then + site_in%resources_management%harvest_debt = site_in%resources_management%harvest_debt + & + bc_in%hlm_harvest_rates(h_index) + end if + end if + if (harvest_debt_secondary == 1 .or. patch_no_secondary == 0) then + ! Only account for secondary forest harvest rate + if((bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH1") .or. & + (bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2")) then !.or. & + ! (bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH3")) then + site_in%resources_management%harvest_debt = site_in%resources_management%harvest_debt + & + bc_in%hlm_harvest_rates(h_index) + site_in%resources_management%harvest_debt_sec = site_in%resources_management%harvest_debt_sec + & + bc_in%hlm_harvest_rates(h_index) + end if + end if + end do + end if + ! --------------------------------------------------------------------------------------------- ! Calculate Disturbance Rates based on the mortality rates just calculated ! --------------------------------------------------------------------------------------------- @@ -381,89 +443,12 @@ subroutine disturbance_rates( site_in, bc_in) endif endif - - - ! ------------------------------------------------------------------------------------------ - ! Determine which disturbance is dominant, and force mortality diagnostics in the upper - ! canopy to be zero for the non-dominant mode. Note: upper-canopy tree-fall mortality is - ! not always disturbance generating, so when tree-fall mort is non-dominant, make sure - ! to still diagnose and track the non-disturbance rate - ! ------------------------------------------------------------------------------------------ - - ! DISTURBANCE IS LOGGING - if (currentPatch%disturbance_rates(dtype_ilog) > currentPatch%disturbance_rates(dtype_ifall) .and. & - currentPatch%disturbance_rates(dtype_ilog) > currentPatch%disturbance_rates(dtype_ifire) ) then - - currentPatch%disturbance_rate = currentPatch%disturbance_rates(dtype_ilog) - currentPatch%disturbance_mode = dtype_ilog - - ! Update diagnostics - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - if(currentCohort%canopy_layer == 1)then - currentCohort%cmort = currentCohort%cmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%hmort = currentCohort%hmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%bmort = currentCohort%bmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%dmort = currentCohort%dmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%frmort = currentCohort%frmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%smort = currentCohort%smort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%asmort = currentCohort%asmort*(1.0_r8 - fates_mortality_disturbance_fraction) - end if - currentCohort => currentCohort%taller - enddo !currentCohort - - ! DISTURBANCE IS FIRE - elseif (currentPatch%disturbance_rates(dtype_ifire) > currentPatch%disturbance_rates(dtype_ifall) .and. & - currentPatch%disturbance_rates(dtype_ifire) > currentPatch%disturbance_rates(dtype_ilog) ) then - - currentPatch%disturbance_rate = currentPatch%disturbance_rates(dtype_ifire) - currentPatch%disturbance_mode = dtype_ifire - - ! Update diagnostics, zero non-fire mortality rates - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - if(currentCohort%canopy_layer == 1)then - currentCohort%cmort = currentCohort%cmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%hmort = currentCohort%hmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%bmort = currentCohort%bmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%dmort = currentCohort%dmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%frmort = currentCohort%frmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%smort = currentCohort%smort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%asmort = currentCohort%asmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%lmort_direct = 0.0_r8 - currentCohort%lmort_collateral = 0.0_r8 - currentCohort%lmort_infra = 0.0_r8 - currentCohort%l_degrad = 0.0_r8 - end if - - ! This may be counter-intuitive, but the diagnostic fire-mortality rate - ! will stay zero in the patch that undergoes fire, this is because - ! the actual cohorts who experience the fire are only those in the - ! newly created patch so currentCohort%fmort = 0.0_r8 - ! Don't worry, the cohorts in the newly created patch will reflect burn - - currentCohort => currentCohort%taller - enddo !currentCohort - - else ! If fire and logging are not greater than treefall, just set disturbance rate to tree-fall - ! which is most likely a 0.0 - - currentPatch%disturbance_rate = currentPatch%disturbance_rates(dtype_ifall) - currentPatch%disturbance_mode = dtype_ifall - - ! Update diagnostics, zero non-treefall mortality rates - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - if(currentCohort%canopy_layer == 1)then - currentCohort%lmort_direct = 0.0_r8 - currentCohort%lmort_collateral = 0.0_r8 - currentCohort%lmort_infra = 0.0_r8 - currentCohort%l_degrad = 0.0_r8 - end if - currentCohort => currentCohort%taller - enddo !currentCohort - - + ! if the sum of all disturbance rates is such that they will exceed total patch area on this day, then reduce them all proportionally. + if ( sum(currentPatch%disturbance_rates(:)) .gt. 1.0_r8 ) then + tempsum = sum(currentPatch%disturbance_rates(:)) + do i_dist = 1,N_DIST_TYPES + currentPatch%disturbance_rates(i_dist) = currentPatch%disturbance_rates(i_dist) / tempsum + end do endif currentPatch => currentPatch%younger @@ -528,6 +513,9 @@ subroutine spawn_patches( currentSite, bc_in) real(r8) :: leaf_m ! leaf mass during partial burn calculations logical :: found_youngest_primary ! logical for finding the first primary forest patch integer :: min_nocomp_pft, max_nocomp_pft, i_nocomp_pft + integer :: i_disturbance_type, i_dist2 ! iterators for looping over disturbance types + real(r8) :: disturbance_rate ! rate of disturbance being resolved [fraction of patch area / day] + real(r8) :: oldarea ! old patch area prior to disturbance !--------------------------------------------------------------------- storesmallcohort => null() ! storage of the smallest cohort for insertion routine @@ -552,6 +540,8 @@ subroutine spawn_patches( currentSite, bc_in) ! If nocomp is not enabled, then this is not much of a loop, it only passes through once. nocomp_pft_loop: do i_nocomp_pft = min_nocomp_pft,max_nocomp_pft + disturbance_type_loop: do i_disturbance_type = 1,N_DIST_TYPES + ! calculate area of disturbed land, in this timestep, by summing contributions from each existing patch. currentPatch => currentSite%youngest_patch @@ -562,47 +552,42 @@ subroutine spawn_patches( currentSite, bc_in) cp_nocomp_matches_1_if: if ( hlm_use_nocomp .eq. ifalse .or. & currentPatch%nocomp_pft_label .eq. i_nocomp_pft ) then - - if(currentPatch%disturbance_rate > (1.0_r8 + rsnbl_math_prec)) then - write(fates_log(),*) 'patch disturbance rate > 1 ?',currentPatch%disturbance_rate + + disturbance_rate = currentPatch%disturbance_rates(i_disturbance_type) + + if(disturbance_rate > (1.0_r8 + rsnbl_math_prec)) then + write(fates_log(),*) 'patch disturbance rate > 1 ?',disturbance_rate call dump_patch(currentPatch) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - ! Check to make sure that the disturbance mode of the patch is set - if( .not.any(currentPatch%disturbance_mode == [dtype_ilog,dtype_ifall,dtype_ifire])) then - write(fates_log(),*) 'undefined disturbance mode? : ',currentPatch%disturbance_mode - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - ! Only create new patches that have non-negligible amount of land - if((currentPatch%area*currentPatch%disturbance_rate) > nearzero ) then + if((currentPatch%area*disturbance_rate) > nearzero ) then ! figure out whether the receiver patch for disturbance from this patch will be ! primary or secondary land receiver patch is primary forest only if both the - ! donor patch is primary forest and the dominant disturbance type is not logging + ! donor patch is primary forest and the current disturbance type is not logging if ( currentPatch%anthro_disturbance_label .eq. primaryforest .and. & - (currentPatch%disturbance_mode .ne. dtype_ilog) ) then + (i_disturbance_type .ne. dtype_ilog) ) then - site_areadis_primary = site_areadis_primary + currentPatch%area * currentPatch%disturbance_rate + site_areadis_primary = site_areadis_primary + currentPatch%area * disturbance_rate ! track disturbance rates to output to history - currentSite%disturbance_rates_primary_to_primary(currentPatch%disturbance_mode) = & - currentSite%disturbance_rates_primary_to_primary(currentPatch%disturbance_mode) + & - currentPatch%area * currentPatch%disturbance_rate * AREA_INV + currentSite%disturbance_rates_primary_to_primary(i_disturbance_type) = & + currentSite%disturbance_rates_primary_to_primary(i_disturbance_type) + & + currentPatch%area * disturbance_rate * AREA_INV else - site_areadis_secondary = site_areadis_secondary + currentPatch%area * currentPatch%disturbance_rate + site_areadis_secondary = site_areadis_secondary + currentPatch%area * disturbance_rate ! track disturbance rates to output to history if (currentPatch%anthro_disturbance_label .eq. secondaryforest) then - currentSite%disturbance_rates_secondary_to_secondary(currentPatch%disturbance_mode) = & - currentSite%disturbance_rates_secondary_to_secondary(currentPatch%disturbance_mode) + & - currentPatch%area * currentPatch%disturbance_rate * AREA_INV + currentSite%disturbance_rates_secondary_to_secondary(i_disturbance_type) = & + currentSite%disturbance_rates_secondary_to_secondary(i_disturbance_type) + & + currentPatch%area * disturbance_rate * AREA_INV else - currentSite%disturbance_rates_primary_to_secondary(currentPatch%disturbance_mode) = & - currentSite%disturbance_rates_primary_to_secondary(currentPatch%disturbance_mode) + & - currentPatch%area * currentPatch%disturbance_rate * AREA_INV + currentSite%disturbance_rates_primary_to_secondary(i_disturbance_type) = & + currentSite%disturbance_rates_primary_to_secondary(i_disturbance_type) + & + currentPatch%area * disturbance_rate * AREA_INV endif endif @@ -676,17 +661,18 @@ subroutine spawn_patches( currentSite, bc_in) currentPatch%nocomp_pft_label .eq. i_nocomp_pft ) then ! This is the amount of patch area that is disturbed, and donated by the donor - patch_site_areadis = currentPatch%area * currentPatch%disturbance_rate + disturbance_rate = currentPatch%disturbance_rates(i_disturbance_type) + patch_site_areadis = currentPatch%area * disturbance_rate if ( patch_site_areadis > nearzero ) then ! figure out whether the receiver patch for disturbance from this patch ! will be primary or secondary land receiver patch is primary forest - ! only if both the donor patch is primary forest and the dominant + ! only if both the donor patch is primary forest and the current ! disturbance type is not logging if (currentPatch%anthro_disturbance_label .eq. primaryforest .and. & - (currentPatch%disturbance_mode .ne. dtype_ilog)) then + (i_disturbance_type .ne. dtype_ilog)) then new_patch => new_patch_primary else new_patch => new_patch_secondary @@ -699,11 +685,11 @@ subroutine spawn_patches( currentSite, bc_in) end if ! for the case where the donating patch is secondary forest, if - ! the dominant disturbance from this patch is non-anthropogenic, + ! the current disturbance from this patch is non-anthropogenic, ! we need to average in the time-since-anthropogenic-disturbance ! from the donor patch into that of the receiver patch if ( currentPatch%anthro_disturbance_label .eq. secondaryforest .and. & - (currentPatch%disturbance_mode .ne. dtype_ilog) ) then + (i_disturbance_type .ne. dtype_ilog) ) then new_patch%age_since_anthro_disturbance = new_patch%age_since_anthro_disturbance + & currentPatch%age_since_anthro_disturbance * (patch_site_areadis / site_areadis_secondary) @@ -714,9 +700,9 @@ subroutine spawn_patches( currentSite, bc_in) ! Transfer the litter existing already in the donor patch to the new patch ! This call will only transfer non-burned litter to new patch ! and burned litter to atmosphere. Thus it is important to zero burnt_frac_litter when - ! fire is not the dominant disturbance regime. + ! fire is not the current disturbance regime. - if(currentPatch%disturbance_mode .ne. dtype_ifire) then + if(i_disturbance_type .ne. dtype_ifire) then currentPatch%burnt_frac_litter(:) = 0._r8 end if @@ -724,10 +710,10 @@ subroutine spawn_patches( currentSite, bc_in) ! Transfer in litter fluxes from plants in various contexts of death and destruction - if(currentPatch%disturbance_mode .eq. dtype_ilog) then + if(i_disturbance_type .eq. dtype_ilog) then call logging_litter_fluxes(currentSite, currentPatch, & new_patch, patch_site_areadis,bc_in) - elseif(currentPatch%disturbance_mode .eq. dtype_ifire) then + elseif(i_disturbance_type .eq. dtype_ifire) then call fire_litter_fluxes(currentSite, currentPatch, & new_patch, patch_site_areadis,bc_in) else @@ -786,8 +772,8 @@ subroutine spawn_patches( currentSite, bc_in) store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) total_c = sapw_c + struct_c + leaf_c + fnrt_c + store_c - ! treefall mortality is the dominant disturbance - if(currentPatch%disturbance_mode .eq. dtype_ifall) then + ! treefall mortality is the current disturbance + if(i_disturbance_type .eq. dtype_ifall) then if(currentCohort%canopy_layer == 1)then @@ -896,8 +882,8 @@ subroutine spawn_patches( currentSite, bc_in) endif endif - ! Fire is the dominant disturbance - elseif (currentPatch%disturbance_mode .eq. dtype_ifire ) then + ! Fire is the current disturbance + elseif (i_disturbance_type .eq. dtype_ifire ) then ! Number of members in the new patch, before we impose fire survivorship nc%n = currentCohort%n * patch_site_areadis/currentPatch%area @@ -995,8 +981,8 @@ subroutine spawn_patches( currentSite, bc_in) - ! Logging is the dominant disturbance - elseif (currentPatch%disturbance_mode .eq. dtype_ilog ) then + ! Logging is the current disturbance + elseif (i_disturbance_type .eq. dtype_ilog ) then ! If this cohort is in the upper canopy. It generated if(currentCohort%canopy_layer == 1)then @@ -1114,7 +1100,7 @@ subroutine spawn_patches( currentSite, bc_in) else write(fates_log(),*) 'unknown disturbance mode?' - write(fates_log(),*) 'disturbance_mode: ',currentPatch%disturbance_mode + write(fates_log(),*) 'i_disturbance_type: ', i_disturbance_type call endrun(msg=errMsg(sourcefile, __LINE__)) end if ! Select disturbance mode @@ -1155,8 +1141,18 @@ subroutine spawn_patches( currentSite, bc_in) call sort_cohorts(currentPatch) !update area of donor patch + oldarea = currentPatch%area currentPatch%area = currentPatch%area - patch_site_areadis + ! for all disturbance rates that haven't been resolved yet, increase their amount so that + ! they are the same amount of gridcell-scale disturbance relative to the original patch size + if (i_disturbance_type .ne. N_DIST_TYPES) then + do i_dist2 = i_disturbance_type+1,N_DIST_TYPES + currentPatch%disturbance_rates(i_dist2) = currentPatch%disturbance_rates(i_dist2) & + * oldarea / currentPatch%area + end do + end if + ! sort out the cohorts, since some of them may be so small as to need removing. ! the first call to terminate cohorts removes sparse number densities, ! the second call removes for all other reasons (sparse culling must happen @@ -1168,11 +1164,6 @@ subroutine spawn_patches( currentSite, bc_in) end if ! if ( new_patch%area > nearzero ) then - !zero disturbance rate trackers - currentPatch%disturbance_rate = 0._r8 - currentPatch%disturbance_rates = 0._r8 - currentPatch%fract_ldist_not_harvested = 0._r8 - end if cp_nocomp_matches_2_if currentPatch => currentPatch%younger @@ -1254,8 +1245,19 @@ subroutine spawn_patches( currentSite, bc_in) call check_patch_area(currentSite) call set_patchno(currentSite) - + + end do disturbance_type_loop + end do nocomp_pft_loop + + !zero disturbance rate trackers on all patches + currentPatch => currentSite%oldest_patch + do while(associated(currentPatch)) + currentPatch%disturbance_rates(:) = 0._r8 + currentPatch%fract_ldist_not_harvested = 0._r8 + currentPatch => currentPatch%younger + end do + return end subroutine spawn_patches @@ -2144,7 +2146,6 @@ subroutine create_patch(currentSite, new_patch, age, areap, label,nocomp_pft) ! This new value will be generated when the calculate disturbance ! rates routine is called. This does not need to be remembered or in the restart file. - new_patch%disturbance_mode = fates_unset_int new_patch%f_sun = 0._r8 new_patch%ed_laisun_z(:,:,:) = 0._r8 @@ -2247,8 +2248,7 @@ subroutine zero_patch(cp_p) currentPatch%pft_agb_profile(:,:) = nan ! DISTURBANCE - currentPatch%disturbance_rates = 0._r8 - currentPatch%disturbance_rate = 0._r8 + currentPatch%disturbance_rates(:) = 0._r8 currentPatch%fract_ldist_not_harvested = 0._r8 diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index dabdfb84f6..ac0b80a182 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -249,6 +249,7 @@ subroutine zero_site( site_in ) ! Resources management (logging/harvesting, etc) site_in%resources_management%harvest_debt = 0.0_r8 + site_in%resources_management%harvest_debt_sec = 0.0_r8 site_in%resources_management%trunk_product_site = 0.0_r8 ! canopy spread diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 8b749cb17c..b1c9ebb511 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -855,7 +855,6 @@ subroutine TotalBalanceCheck (currentSite, call_index ) write(fates_log(),*) 'BG CWD (by layer): ', sum(litt%bg_cwd,dim=1) write(fates_log(),*) 'leaf litter:',sum(litt%leaf_fines) write(fates_log(),*) 'root litter (by layer): ',sum(litt%root_fines,dim=1) - write(fates_log(),*) 'dist mode: ',currentPatch%disturbance_mode write(fates_log(),*) 'anthro_disturbance_label: ',currentPatch%anthro_disturbance_label write(fates_log(),*) 'use_this_pft: ', currentSite%use_this_pft(:) if(print_cohorts)then diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index bd51a29746..ba32b647b1 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -537,9 +537,6 @@ module EDTypesMod real(r8) :: disturbance_rates(n_dist_types) ! disturbance rate from 1) mortality ! 2) fire: fraction/day ! 3) logging mortatliy - real(r8) :: disturbance_rate ! larger effective disturbance rate: fraction/day - integer :: disturbance_mode ! index identifying which disturbance was applied - ! can be one of: dtype_ifall, dtype_ilog or dtype_ifire real(r8) :: fract_ldist_not_harvested ! fraction of logged area that is canopy trees that weren't harvested @@ -594,6 +591,8 @@ module EDTypesMod real(r8) :: trunk_product_site ! Actual trunk product at site level KgC/site real(r8) :: harvest_debt ! the amount of kgC per site that did not successfully harvested + real(r8) :: harvest_debt_sec ! the amount of kgC per site from secondary patches that did + ! not successfully harvested !debug variables real(r8) :: delta_litter_stock ! kgC/site = kgC/ha @@ -1017,7 +1016,6 @@ subroutine dump_patch(cpatch) write(fates_log(),*) 'pa%gnd_alb_dir = ',cpatch%gnd_alb_dir(:) write(fates_log(),*) 'pa%c_stomata = ',cpatch%c_stomata write(fates_log(),*) 'pa%c_lblayer = ',cpatch%c_lblayer - write(fates_log(),*) 'pa%disturbance_rate = ',cpatch%disturbance_rate write(fates_log(),*) 'pa%disturbance_rates = ',cpatch%disturbance_rates(:) write(fates_log(),*) 'pa%anthro_disturbance_label = ',cpatch%anthro_disturbance_label write(fates_log(),*) '----------------------------------------' diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 5e89cd4c27..da508d8f2e 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -271,6 +271,12 @@ module FatesHistoryInterfaceMod integer :: ih_canopy_biomass_si integer :: ih_understory_biomass_si + integer :: ih_npp_secondary_si + integer :: ih_gpp_secondary_si + integer :: ih_aresp_secondary_si + integer :: ih_maint_resp_secondary_si + integer :: ih_growth_resp_secondary_si + integer :: ih_primaryland_fusion_error_si integer :: ih_disturbance_rate_p2p_si integer :: ih_disturbance_rate_p2s_si @@ -281,6 +287,7 @@ module FatesHistoryInterfaceMod integer :: ih_potential_disturbance_rate_si integer :: ih_harvest_carbonflux_si integer :: ih_harvest_debt_si + integer :: ih_harvest_debt_sec_si ! Indices to site by size-class by age variables integer :: ih_nplant_si_scag @@ -316,7 +323,9 @@ module FatesHistoryInterfaceMod integer :: ih_err_fates_si integer :: ih_npatches_si + integer :: ih_npatches_sec_si integer :: ih_ncohorts_si + integer :: ih_ncohorts_sec_si integer :: ih_demotion_carbonflux_si integer :: ih_promotion_carbonflux_si integer :: ih_canopy_mortality_carbonflux_si @@ -444,6 +453,7 @@ module FatesHistoryInterfaceMod integer :: ih_ddbh_understory_si_scls integer :: ih_agb_si_scls integer :: ih_biomass_si_scls + integer :: ih_mortality_canopy_secondary_si_scls ! mortality vars integer :: ih_m1_si_scls @@ -457,6 +467,14 @@ module FatesHistoryInterfaceMod integer :: ih_m9_si_scls integer :: ih_m10_si_scls + integer :: ih_m1_sec_si_scls + integer :: ih_m2_sec_si_scls + integer :: ih_m3_sec_si_scls + integer :: ih_m7_sec_si_scls + integer :: ih_m8_sec_si_scls + integer :: ih_m9_sec_si_scls + integer :: ih_m10_sec_si_scls + integer :: ih_m10_si_cacls integer :: ih_nplant_si_cacls @@ -506,15 +524,19 @@ module FatesHistoryInterfaceMod ! indices to (site x pft) variables integer :: ih_biomass_si_pft + integer :: ih_biomass_sec_si_pft integer :: ih_leafbiomass_si_pft integer :: ih_storebiomass_si_pft integer :: ih_nindivs_si_pft + integer :: ih_nindivs_sec_si_pft integer :: ih_recruitment_si_pft integer :: ih_mortality_si_pft integer :: ih_crownarea_si_pft integer :: ih_canopycrownarea_si_pft integer :: ih_gpp_si_pft + integer :: ih_gpp_sec_si_pft integer :: ih_npp_si_pft + integer :: ih_npp_sec_si_pft integer :: ih_nocomp_pftpatchfraction_si_pft integer :: ih_nocomp_pftnpatches_si_pft integer :: ih_nocomp_pftburnedarea_si_pft @@ -538,6 +560,8 @@ module FatesHistoryInterfaceMod integer :: ih_fire_intensity_si_age integer :: ih_fire_sum_fuel_si_age + integer :: ih_lai_secondary_si + ! indices to (site x height) variables integer :: ih_canopy_height_dist_si_height integer :: ih_leaf_height_dist_si_height @@ -1753,6 +1777,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) real(r8) :: binbottom,bintop ! edges of height bins real(r8) :: gpp_cached ! variable used to cache gpp value in previous time step; for C13 discrimination + real(r8) :: lai_patch_cached ! temporary variable to cache mean lai of current patch ! The following are all carbon states, turnover and net allocation flux variables ! the organs of relevance should be self explanatory @@ -1787,21 +1812,27 @@ subroutine update_history_dyn(this,nc,nsites,sites) integer :: tmp associate( hio_npatches_si => this%hvars(ih_npatches_si)%r81d, & + hio_npatches_sec_si => this%hvars(ih_npatches_sec_si)%r81d, & hio_ncohorts_si => this%hvars(ih_ncohorts_si)%r81d, & + hio_ncohorts_sec_si => this%hvars(ih_ncohorts_sec_si)%r81d, & hio_trimming_si => this%hvars(ih_trimming_si)%r81d, & hio_area_plant_si => this%hvars(ih_area_plant_si)%r81d, & hio_area_trees_si => this%hvars(ih_area_trees_si)%r81d, & hio_canopy_spread_si => this%hvars(ih_canopy_spread_si)%r81d, & hio_biomass_si_pft => this%hvars(ih_biomass_si_pft)%r82d, & + hio_biomass_sec_si_pft => this%hvars(ih_biomass_sec_si_pft)%r82d, & hio_leafbiomass_si_pft => this%hvars(ih_leafbiomass_si_pft)%r82d, & hio_storebiomass_si_pft => this%hvars(ih_storebiomass_si_pft)%r82d, & hio_nindivs_si_pft => this%hvars(ih_nindivs_si_pft)%r82d, & + hio_nindivs_sec_si_pft => this%hvars(ih_nindivs_sec_si_pft)%r82d, & hio_recruitment_si_pft => this%hvars(ih_recruitment_si_pft)%r82d, & hio_mortality_si_pft => this%hvars(ih_mortality_si_pft)%r82d, & hio_crownarea_si_pft => this%hvars(ih_crownarea_si_pft)%r82d, & hio_canopycrownarea_si_pft => this%hvars(ih_canopycrownarea_si_pft)%r82d, & hio_gpp_si_pft => this%hvars(ih_gpp_si_pft)%r82d, & + hio_gpp_sec_si_pft => this%hvars(ih_gpp_sec_si_pft)%r82d, & hio_npp_si_pft => this%hvars(ih_npp_si_pft)%r82d, & + hio_npp_sec_si_pft => this%hvars(ih_npp_sec_si_pft)%r82d, & hio_nesterov_fire_danger_si => this%hvars(ih_nesterov_fire_danger_si)%r81d, & hio_fire_nignitions_si => this%hvars(ih_fire_nignitions_si)%r81d, & hio_fire_fdi_si => this%hvars(ih_fire_fdi_si)%r81d, & @@ -1843,6 +1874,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_potential_disturbance_rate_si => this%hvars(ih_potential_disturbance_rate_si)%r81d, & hio_harvest_carbonflux_si => this%hvars(ih_harvest_carbonflux_si)%r81d, & hio_harvest_debt_si => this%hvars(ih_harvest_debt_si)%r81d, & + hio_harvest_debt_sec_si => this%hvars(ih_harvest_debt_sec_si)%r81d, & hio_gpp_si_scpf => this%hvars(ih_gpp_si_scpf)%r82d, & hio_npp_totl_si_scpf => this%hvars(ih_npp_totl_si_scpf)%r82d, & hio_npp_leaf_si_scpf => this%hvars(ih_npp_leaf_si_scpf)%r82d, & @@ -1864,6 +1896,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_bleaf_canopy_si_scpf => this%hvars(ih_bleaf_canopy_si_scpf)%r82d, & hio_bleaf_understory_si_scpf => this%hvars(ih_bleaf_understory_si_scpf)%r82d, & hio_mortality_canopy_si_scpf => this%hvars(ih_mortality_canopy_si_scpf)%r82d, & + hio_mortality_canopy_secondary_si_scls => this%hvars(ih_mortality_canopy_secondary_si_scls)%r82d, & hio_mortality_understory_si_scpf => this%hvars(ih_mortality_understory_si_scpf)%r82d, & hio_nplant_canopy_si_scpf => this%hvars(ih_nplant_canopy_si_scpf)%r82d, & hio_nplant_understory_si_scpf => this%hvars(ih_nplant_understory_si_scpf)%r82d, & @@ -1913,6 +1946,14 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_m10_si_scls => this%hvars(ih_m10_si_scls)%r82d, & hio_m10_si_cacls => this%hvars(ih_m10_si_cacls)%r82d, & + hio_m1_sec_si_scls => this%hvars(ih_m1_sec_si_scls)%r82d, & + hio_m2_sec_si_scls => this%hvars(ih_m2_sec_si_scls)%r82d, & + hio_m3_sec_si_scls => this%hvars(ih_m3_sec_si_scls)%r82d, & + hio_m7_sec_si_scls => this%hvars(ih_m7_sec_si_scls)%r82d, & + hio_m8_sec_si_scls => this%hvars(ih_m8_sec_si_scls)%r82d, & + hio_m9_sec_si_scls => this%hvars(ih_m9_sec_si_scls)%r82d, & + hio_m10_sec_si_scls => this%hvars(ih_m10_sec_si_scls)%r82d, & + hio_c13disc_si_scpf => this%hvars(ih_c13disc_si_scpf)%r82d, & hio_cwd_elcwd => this%hvars(ih_cwd_elcwd)%r82d, & @@ -1977,6 +2018,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_yesterdaycanopylevel_understory_si_scls => this%hvars(ih_yesterdaycanopylevel_understory_si_scls)%r82d, & hio_area_si_age => this%hvars(ih_area_si_age)%r82d, & hio_lai_si_age => this%hvars(ih_lai_si_age)%r82d, & + hio_lai_secondary_si => this%hvars(ih_lai_secondary_si)%r81d, & hio_canopy_area_si_age => this%hvars(ih_canopy_area_si_age)%r82d, & hio_ncl_si_age => this%hvars(ih_ncl_si_age)%r82d, & hio_npatches_si_age => this%hvars(ih_npatches_si_age)%r82d, & @@ -2112,6 +2154,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) end if hio_harvest_carbonflux_si(io_si) = sites(s)%harvest_carbon_flux hio_harvest_debt_si(io_si) = sites(s)%resources_management%harvest_debt + hio_harvest_debt_sec_si(io_si) = sites(s)%resources_management%harvest_debt_sec ! error in primary lands from patch fusion [m2 m-2 day-1] -> [m2 m-2 yr-1] hio_primaryland_fusion_error_si(io_si) = sites(s)%primary_land_patchfusion_error * days_per_year @@ -2149,6 +2192,9 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! Increment the number of patches per site hio_npatches_si(io_si) = hio_npatches_si(io_si) + 1._r8 + if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + hio_npatches_sec_si(io_si) = hio_npatches_sec_si(io_si) + 1._r8 + end if cpatch%age_class = get_age_class_index(cpatch%age) @@ -2161,9 +2207,9 @@ subroutine update_history_dyn(this,nc,nsites,sites) (cpatch%tveg24%GetMean()- t_water_freeze_k_1atm)*cpatch%area*AREA_INV ! Increment some patch-age-resolved diagnostics - hio_lai_si_age(io_si,cpatch%age_class) = hio_lai_si_age(io_si,cpatch%age_class) & + sum(cpatch%tlai_profile(:,:,:)) * cpatch%area + hio_ncl_si_age(io_si,cpatch%age_class) = hio_ncl_si_age(io_si,cpatch%age_class) & + cpatch%ncl_p * cpatch%area hio_npatches_si_age(io_si,cpatch%age_class) = hio_npatches_si_age(io_si,cpatch%age_class) + 1._r8 @@ -2189,6 +2235,19 @@ subroutine update_history_dyn(this,nc,nsites,sites) + cpatch%area * AREA_INV endif + ! Secondary forest mean LAI + if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + lai_patch_cached = 0._r8 + do ican = 1, cpatch%NCL_p + do i_pft = 1, numpft + lai_patch_cached = lai_patch_cached + sum(cpatch%canopy_area_profile(ican,i_pft,1:cpatch%nrad(ican,i_pft)) * & + cpatch%tlai_profile(ican,i_pft,1:cpatch%nrad(ican,i_pft))) + end do + end do + hio_lai_secondary_si(io_si) = hio_lai_secondary_si(io_si) & + + lai_patch_cached * min(1.0_r8, (cpatch%total_canopy_area/cpatch%area)) * cpatch%area * AREA_INV + end if + ! patch-age-resolved fire variables do i_pft = 1,numpft ! for scorch height, weight the value by patch area within any @@ -2254,6 +2313,10 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! Increment the number of cohorts per site hio_ncohorts_si(io_si) = hio_ncohorts_si(io_si) + 1._r8 + if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + hio_ncohorts_sec_si(io_si) = hio_ncohorts_sec_si(io_si) + 1._r8 + end if + n_perm2 = ccohort%n * AREA_INV hio_canopy_area_si_age(io_si,cpatch%age_class) = hio_canopy_area_si_age(io_si,cpatch%age_class) & @@ -2346,9 +2409,19 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_nindivs_si_pft(io_si,ft) = hio_nindivs_si_pft(io_si,ft) + & ccohort%n * AREA_INV + if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + hio_nindivs_sec_si_pft(io_si,ft) = hio_nindivs_sec_si_pft(io_si,ft) + & + ccohort%n * AREA_INV + end if + hio_biomass_si_pft(io_si, ft) = hio_biomass_si_pft(io_si, ft) + & (ccohort%n * AREA_INV) * total_m + if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + hio_biomass_sec_si_pft(io_si, ft) = hio_biomass_sec_si_pft(io_si, ft) + & + (ccohort%n * AREA_INV) * total_m + end if + ! update total biomass per age bin hio_biomass_si_age(io_si,cpatch%age_class) = hio_biomass_si_age(io_si,cpatch%age_class) & + total_m * ccohort%n * AREA_INV @@ -2431,6 +2504,14 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_npp_si_pft(io_si, ft) = hio_npp_si_pft(io_si, ft) + & ccohort%npp_acc_hold * n_perm2 / days_per_year / sec_per_day + if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + hio_gpp_sec_si_pft(io_si, ft) = hio_gpp_sec_si_pft(io_si, ft) + & + ccohort%gpp_acc_hold * n_perm2 / days_per_year / sec_per_day + hio_npp_sec_si_pft(io_si, ft) = hio_npp_sec_si_pft(io_si, ft) + & + ccohort%npp_acc_hold * n_perm2 / days_per_year / sec_per_day + end if + + ! Site by Size-Class x PFT (SCPF) ! ------------------------------------------------------------------------ @@ -2564,6 +2645,25 @@ subroutine update_history_dyn(this,nc,nsites,sites) ccohort%frmort*ccohort%n / m2_per_ha hio_m9_si_scls(io_si,scls) = hio_m9_si_scls(io_si,scls) + ccohort%smort*ccohort%n / m2_per_ha + ! Examine secondary forest mortality and mortality rates + + if(cpatch%anthro_disturbance_label .eq. secondaryforest) then + + if (hlm_use_cohort_age_tracking .eq.itrue) then + hio_m10_sec_si_scls(io_si,scls) = hio_m10_sec_si_scls(io_si,scls) + & + ccohort%asmort*ccohort%n / m2_per_ha + end if + + hio_m1_sec_si_scls(io_si,scls) = hio_m1_sec_si_scls(io_si,scls) + ccohort%bmort*ccohort%n / m2_per_ha + hio_m2_sec_si_scls(io_si,scls) = hio_m2_sec_si_scls(io_si,scls) + ccohort%hmort*ccohort%n / m2_per_ha + hio_m3_sec_si_scls(io_si,scls) = hio_m3_sec_si_scls(io_si,scls) + ccohort%cmort*ccohort%n / m2_per_ha + hio_m7_sec_si_scls(io_si,scls) = hio_m7_sec_si_scls(io_si,scls) + & + (ccohort%lmort_direct+ccohort%lmort_collateral+ccohort%lmort_infra) * ccohort%n / m2_per_ha + hio_m8_sec_si_scls(io_si,scls) = hio_m8_sec_si_scls(io_si,scls) + & + ccohort%frmort*ccohort%n / m2_per_ha + hio_m9_sec_si_scls(io_si,scls) = hio_m9_sec_si_scls(io_si,scls) + ccohort%smort*ccohort%n / m2_per_ha + end if + !C13 discrimination if(gpp_cached + ccohort%gpp_acc_hold > 0.0_r8)then hio_c13disc_si_scpf(io_si,scpf) = ((hio_c13disc_si_scpf(io_si,scpf) * gpp_cached) + & @@ -2741,6 +2841,15 @@ subroutine update_history_dyn(this,nc,nsites,sites) (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & ccohort%n * sec_per_day * days_per_year / m2_per_ha + if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + hio_mortality_canopy_secondary_si_scls(io_si,scls) = hio_mortality_canopy_secondary_si_scls(io_si,scls) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort) * ccohort%n / m2_per_ha + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & + ccohort%n * sec_per_day * days_per_year / m2_per_ha + end if + + hio_nplant_understory_si_scpf(io_si,scpf) = hio_nplant_understory_si_scpf(io_si,scpf) + ccohort%n / m2_per_ha hio_nplant_understory_si_scls(io_si,scls) = hio_nplant_understory_si_scls(io_si,scls) + ccohort%n / m2_per_ha hio_lai_understory_si_scls(io_si,scls) = hio_lai_understory_si_scls(io_si,scls) + & @@ -2994,6 +3103,12 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_mortality_canopy_si_scls(io_si,i_scls) = hio_mortality_canopy_si_scls(io_si,i_scls) + & sites(s)%fmort_rate_canopy(i_scls, i_pft) / m2_per_ha + ! Shijie: Think about how to add later? + !if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + ! hio_mortality_canopy_secondary_si_scls(io_si,i_scls) = hio_mortality_canopy_secondary_si_scls(io_si,i_scls) + & + ! sites(s)%term_nindivs_canopy(i_scls,i_pft) * days_per_year / m2_per_ha + !end if + ! the fire mortality rates for each layer are total dead, since the usable ! output will then normalize by the counts, we are allowed to sum over layers hio_mortality_understory_si_scpf(io_si,i_scpf) = hio_mortality_understory_si_scpf(io_si,i_scpf) + & @@ -3503,10 +3618,15 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) real(r8) :: per_dt_tstep ! Time step in frequency units (/s) associate( hio_gpp_si => this%hvars(ih_gpp_si)%r81d, & + hio_gpp_secondary_si => this%hvars(ih_gpp_secondary_si)%r81d, & hio_npp_si => this%hvars(ih_npp_si)%r81d, & + hio_npp_secondary_si => this%hvars(ih_npp_secondary_si)%r81d, & hio_aresp_si => this%hvars(ih_aresp_si)%r81d, & + hio_aresp_secondary_si => this%hvars(ih_aresp_secondary_si)%r81d, & hio_maint_resp_si => this%hvars(ih_maint_resp_si)%r81d, & + hio_maint_resp_secondary_si => this%hvars(ih_maint_resp_secondary_si)%r81d, & hio_growth_resp_si => this%hvars(ih_growth_resp_si)%r81d, & + hio_growth_resp_secondary_si => this%hvars(ih_growth_resp_secondary_si)%r81d, & hio_c_stomata_si => this%hvars(ih_c_stomata_si)%r81d, & hio_c_lblayer_si => this%hvars(ih_c_lblayer_si)%r81d, & hio_rad_error_si => this%hvars(ih_rad_error_si)%r81d, & @@ -3651,6 +3771,20 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) hio_maint_resp_si(io_si) = hio_maint_resp_si(io_si) + & ccohort%resp_m * n_perm2 * per_dt_tstep + ! Secondary forest only + if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + hio_npp_secondary_si(io_si) = hio_npp_secondary_si(io_si) + & + npp * n_perm2 * per_dt_tstep + hio_gpp_secondary_si(io_si) = hio_gpp_secondary_si(io_si) + & + ccohort%gpp_tstep * n_perm2 * per_dt_tstep + hio_aresp_secondary_si(io_si) = hio_aresp_secondary_si(io_si) + & + aresp * n_perm2 * per_dt_tstep + hio_growth_resp_secondary_si(io_si) = hio_growth_resp_secondary_si(io_si) + & + resp_g * n_perm2 * per_dt_tstep + hio_maint_resp_secondary_si(io_si) = hio_maint_resp_secondary_si(io_si) + & + ccohort%resp_m * n_perm2 * per_dt_tstep + end if + ! Add up the total Net Ecosystem Production ! for this timestep. [kgC/m2/s] hio_nep_si(io_si) = hio_nep_si(io_si) + & @@ -4377,6 +4511,18 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_ncohorts_si) + call this%set_history_var(vname='FATES_NPATCHES_SECONDARY', units='', & + long='total number of patches per site', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_npatches_sec_si) + + call this%set_history_var(vname='FATES_NCOHORTS_SECONDARY', units='', & + long='total number of cohorts per site', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_ncohorts_sec_si) + ! Patch variables call this%set_history_var(vname='FATES_TRIMMING', units='1', & long='degree to which canopy expansion is limited by leaf economics (0-1)', & @@ -4469,6 +4615,12 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_biomass_si_pft) + call this%set_history_var(vname='FATES_VEGC_SE_PF', units='kg m-2', & + long='total PFT-level biomass in kg of carbon per land area, secondary patches', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_biomass_sec_si_pft) + call this%set_history_var(vname='FATES_LEAFC_PF', units='kg m-2', & long='total PFT-level leaf biomass in kg carbon per m2 land area', & use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & @@ -4505,12 +4657,30 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_npp_si_pft) + call this%set_history_var(vname='FATES_GPP_SE_PF', units='kg m-2 s-1', & + long='total PFT-level GPP in kg carbon per m2 land area per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_gpp_sec_si_pft) + + call this%set_history_var(vname='FATES_NPP_SE_PF', units='kg m-2 yr-1', & + long='total PFT-level NPP in kg carbon per m2 land area per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_npp_sec_si_pft) + call this%set_history_var(vname='FATES_NPLANT_PF', units='m-2', & long='total PFT-level number of individuals per m2 land area', & use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_nindivs_si_pft) + call this%set_history_var(vname='FATES_NPLANT_SEC_PF', units='m-2', & + long='total PFT-level number of individuals per m2 land area, secondary patches', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_nindivs_sec_si_pft) + call this%set_history_var(vname='FATES_RECRUITMENT_PF', & units='m-2 yr-1', & long='PFT-level recruitment rate in number of individuals per m2 land area per year', & @@ -4556,6 +4726,12 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_lai_si_age) + call this%set_history_var(vname='FATES_LAI_SECONDARY', units='m2 m-2', & + long='leaf area index per m2 land area, secondary patches', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_lai_secondary_si) + call this%set_history_var(vname='FATES_CANOPYAREA_AP', units='m2 m-2', & long='canopy area by age bin per m2 land area', use_default='active', & avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & @@ -5144,64 +5320,69 @@ subroutine define_history_vars(this, initialize_variables) ! disturbance rates call this%set_history_var(vname='PRIMARYLAND_PATCHFUSION_ERROR', units='m2 m-2 d-1', & long='Error in total primary lands associated with patch fusion', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_primaryland_fusion_error_si ) call this%set_history_var(vname='DISTURBANCE_RATE_P2P', units='m2 m-2 d-1', & long='Disturbance rate from primary to primary lands', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_disturbance_rate_p2p_si ) call this%set_history_var(vname='DISTURBANCE_RATE_P2S', units='m2 m-2 d-1', & long='Disturbance rate from primary to secondary lands', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_disturbance_rate_p2s_si ) call this%set_history_var(vname='DISTURBANCE_RATE_S2S', units='m2 m-2 d-1', & long='Disturbance rate from secondary to secondary lands', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_disturbance_rate_s2s_si ) - call this%set_history_var(vname='DISTURBANCE_RATE_FIRE', units='m2 m-2 d-1', & - long='Disturbance rate from fire', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_fire_disturbance_rate_si ) - - call this%set_history_var(vname='DISTURBANCE_RATE_LOGGING', units='m2 m-2 d-1', & - long='Disturbance rate from logging', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_logging_disturbance_rate_si ) - - call this%set_history_var(vname='DISTURBANCE_RATE_TREEFALL', units='m2 m-2 d-1', & - long='Disturbance rate from treefall', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_fall_disturbance_rate_si ) - - call this%set_history_var(vname='DISTURBANCE_RATE_POTENTIAL', units='m2 m-2 d-1', & - long='Potential (i.e., including unresolved) disturbance rate', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_potential_disturbance_rate_si ) +! call this%set_history_var(vname='DISTURBANCE_RATE_FIRE', units='m2 m-2 d-1', & +! long='Disturbance rate from fire', use_default='active', & +! avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & +! ivar=ivar, initialize=initialize_variables, index = ih_fire_disturbance_rate_si ) +! +! call this%set_history_var(vname='DISTURBANCE_RATE_LOGGING', units='m2 m-2 d-1', & +! long='Disturbance rate from logging', use_default='active', & +! avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & +! ivar=ivar, initialize=initialize_variables, index = ih_logging_disturbance_rate_si ) +! +! call this%set_history_var(vname='DISTURBANCE_RATE_TREEFALL', units='m2 m-2 d-1', & +! long='Disturbance rate from treefall', use_default='active', & +! avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & +! ivar=ivar, initialize=initialize_variables, index = ih_fall_disturbance_rate_si ) +! +! call this%set_history_var(vname='DISTURBANCE_RATE_POTENTIAL', units='m2 m-2 d-1', & +! long='Potential (i.e., including unresolved) disturbance rate', use_default='active', & +! avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & +! ivar=ivar, initialize=initialize_variables, index = ih_potential_disturbance_rate_si ) call this%set_history_var(vname='HARVEST_CARBON_FLUX', units='kg C m-2 d-1', & long='Harvest carbon flux', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_harvest_carbonflux_si ) call this%set_history_var(vname='HARVEST_DEBT', units='kg C', & long='Accumulated carbon failed to be harvested', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_harvest_debt_si ) + call this%set_history_var(vname='HARVEST_DEBT_SEC', units='kg C', & + long='Accumulated carbon failed to be harvested from secondary patches', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_harvest_debt_sec_si ) + ! Canopy Resistance call this%set_history_var(vname='C_STOMATA', units='umol m-2 s-1', & long='mean stomatal conductance', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=2, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & ivar=ivar, initialize=initialize_variables, index = ih_c_stomata_si ) call this%set_history_var(vname='C_LBLAYER', units='umol m-2 s-1', & long='mean leaf boundary layer conductance', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=2, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & ivar=ivar, initialize=initialize_variables, index = ih_c_lblayer_si ) @@ -5212,28 +5393,55 @@ subroutine define_history_vars(this, initialize_variables) use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_npp_si) + call this%set_history_var(vname='FATES_NPP_SECONDARY', units='kg m-2 s-1', & + long='net primary production in kg carbon per m2 per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_npp_secondary_si) + call this%set_history_var(vname='FATES_GPP', units='kg m-2 s-1', & long='gross primary production in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_gpp_si) + call this%set_history_var(vname='FATES_GPP_SECONDARY', units='kg m-2 s-1', & + long='gross primary production in kg carbon per m2 per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_gpp_secondary_si) + call this%set_history_var(vname='FATES_AUTORESP', units='kg m-2 s-1', & long='autotrophic respiration in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_aresp_si) + call this%set_history_var(vname='FATES_AUTORESP_SECONDARY', units='kg m-2 s-1', & + long='autotrophic respiration in kg carbon per m2 per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_aresp_secondary_si) + call this%set_history_var(vname='FATES_GROWTH_RESP', units='kg m-2 s-1', & long='growth respiration in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=2, ivar=ivar, initialize=initialize_variables, & index = ih_growth_resp_si) + call this%set_history_var(vname='FATES_GROWTH_RESP_SECONDARY', units='kg m-2 s-1', & + long='growth respiration in kg carbon per m2 per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, & + index = ih_growth_resp_secondary_si) + call this%set_history_var(vname='FATES_MAINT_RESP', units='kg m-2 s-1', & - long='maintenance respiration in kg carbon per m2 land area per second', & + long='maintenance respiration in kg carbon per m2 land area per second, secondary patches', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=2, ivar=ivar, initialize=initialize_variables, & index = ih_maint_resp_si) + call this%set_history_var(vname='FATES_MAINT_RESP_SECONDARY', units='kg m-2 s-1', & + long='maintenance respiration in kg carbon per m2 land area per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, & + index = ih_maint_resp_secondary_si) + ! Canopy resistance call this%set_history_var(vname='FATES_STOMATAL_COND_AP', & @@ -6074,6 +6282,13 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index = ih_mortality_canopy_si_scls) + call this%set_history_var(vname='FATES_MORTALITY_CANOPY_SE_SZ', & + units = 'm-2 yr-1', & + long='total mortality of canopy trees by size class in number of plants per m2, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_mortality_canopy_secondary_si_scls) + call this%set_history_var(vname='FATES_NPLANT_USTORY_SZ', & units = 'm-2', & long='number of understory plants per m2 by size class', & @@ -6127,6 +6342,27 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index = ih_m3_si_scls) + call this%set_history_var(vname='FATES_MORTALITY_BACKGROUND_SE_SZ', & + units = 'm-2 yr-1', & + long='background mortality by size in number of plants per m2 per year, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m1_sec_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_HYDRAULIC_SE_SZ', & + units = 'm-2 yr-1', & + long='hydraulic mortality by size in number of plants per m2 per year, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m2_sec_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_CSTARV_SE_SZ', & + units = 'm-2 yr-1', & + long='carbon starvation mortality by size in number of plants per m2 per year, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m3_sec_si_scls) + call this%set_history_var(vname='FATES_MORTALITY_IMPACT_SZ', & units = 'm-2 yr-1', & long='impact mortality by size in number of plants per m2 per year', & @@ -6183,6 +6419,34 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index = ih_m10_si_cacls) + call this%set_history_var(vname='FATES_MORTALITY_LOGGING_SE_SZ', & + units = 'm-2 yr-1', & + long='logging mortality by size in number of plants per m2 per event, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m7_sec_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_FREEZING_SE_SZ', & + units = 'm-2 event-1', & + long='freezing mortality by size in number of plants per m2 per event, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m8_sec_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_SENESCENCE_SE_SZ', & + units = 'm-2 yr-1', & + long='senescence mortality by size in number of plants per m2 per event, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m9_sec_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_AGESCEN_SE_SZ', & + units = 'm-2 yr-1', & + long='age senescence mortality by size in number of plants per m2 per year, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m10_sec_si_scls) + call this%set_history_var(vname='FATES_NPP_CANOPY_SZ', units = 'kg m-2 s-1', & long='NPP of canopy plants by size class in kg carbon per m2 per second', & use_default='inactive', avgflag='A', vtype=site_size_r8, & From 4b075c8a92a421864676a1f3890301b0166af023 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 23 Jun 2022 10:31:35 -0400 Subject: [PATCH 249/852] Updating new parameter file name for pprodhvar10 --- main/EDParamsMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 08c64db383..2923f59d06 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -235,7 +235,7 @@ module EDParamsMod real(r8),protected,public :: pprodharv10_forest_mean ! "mean harvest mortality proportion of deadstem to 10-yr ! product pool (pprodharv10) of all woody PFT types - character(len=param_string_length),parameter,public :: logging_name_pprodharv10="fates_pprodharv10_forest_mean" + character(len=param_string_length),parameter,public :: logging_name_pprodharv10="fates_landuse_pprodharv10_forest_mean" real(r8),protected,public :: eca_plant_escalar ! scaling factor for plant fine root biomass to ! calculate nutrient carrier enzyme abundance (ECA) From acc05e6ed82bab526be9f1a6ee0751527c6322a0 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 23 Jun 2022 10:38:01 -0400 Subject: [PATCH 250/852] Re-removing harvest_carbon_flux --- main/EDTypesMod.F90 | 2 -- 1 file changed, 2 deletions(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index a2223d6d76..1c76f44a54 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -802,8 +802,6 @@ module EDTypesMod real(r8) :: demotion_carbonflux ! biomass of demoted individuals from canopy to understory [kgC/ha/day] real(r8) :: promotion_carbonflux ! biomass of promoted individuals from understory to canopy [kgC/ha/day] - real(r8) :: harvest_carbon_flux ! diagnostic site level flux of carbon as harvested plants [kg C / m2 / day] - real(r8) :: recruitment_rate(1:maxpft) ! number of individuals that were recruited into new cohorts real(r8), allocatable :: demotion_rate(:) ! rate of individuals demoted from canopy to understory per FATES timestep real(r8), allocatable :: promotion_rate(:) ! rate of individuals promoted from understory to canopy per FATES timestep From 1bb4423b38b221eff548ef016147968b0fdb3601 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 23 Jun 2022 10:41:23 -0400 Subject: [PATCH 251/852] Removed duplicate entry of the interface variables hrv_deadstemc_to_prodc --- main/FatesInterfaceTypesMod.F90 | 4 ---- 1 file changed, 4 deletions(-) diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index df43414a6b..f08fba4ce8 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -725,10 +725,6 @@ module FatesInterfaceTypesMod ! FATES LULCC real(r8) :: hrv_deadstemc_to_prod10c ! Harvested C flux to 10-yr wood product pool [Site-Level, gC m-2 s-1] real(r8) :: hrv_deadstemc_to_prod100c ! Harvested C flux to 100-yr wood product pool [Site-Level, gC m-2 s-1] - - ! FATES LULCC - real(r8) :: hrv_deadstemc_to_prod10c ! Harvested C flux to 10-yr wood product pool [Site-Level, gC m-2 s-1] - real(r8) :: hrv_deadstemc_to_prod100c ! Harvested C flux to 100-yr wood product pool [Site-Level, gC m-2 s-1] end type bc_out_type From b061711ad9f4e946fae6de2bced1dcc3cdcfc9f1 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 23 Jun 2022 10:52:55 -0400 Subject: [PATCH 252/852] Removed unused bc_in in update_hlm_dynamics --- biogeochem/EDCanopyStructureMod.F90 | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 46fd15b383..f195f59f0a 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1854,7 +1854,7 @@ end subroutine leaf_area_profile ! ====================================================================================== - subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_in,bc_out) + subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) ! ---------------------------------------------------------------------------------- ! The purpose of this routine is to package output boundary conditions related @@ -1863,14 +1863,13 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_in,bc_out) use EDTypesMod , only : ed_patch_type, ed_cohort_type, & ed_site_type, AREA - use FatesInterfaceTypesMod , only : bc_in_type, bc_out_type + use FatesInterfaceTypesMod , only : bc_out_type ! ! !ARGUMENTS integer, intent(in) :: nsites type(ed_site_type), intent(inout), target :: sites(nsites) integer, intent(in) :: fcolumn(nsites) - type(bc_in_type), intent(in) :: bc_in(nsites) type(bc_out_type), intent(inout) :: bc_out(nsites) ! Locals From 53ca295e84cdb6b0a0fe99ba937161dc19d76987 Mon Sep 17 00:00:00 2001 From: ckoven Date: Thu, 23 Jun 2022 14:55:45 -0600 Subject: [PATCH 253/852] auto-indented spawn_patches --- biogeochem/EDPatchDynamicsMod.F90 | 1326 ++++++++++++++--------------- 1 file changed, 663 insertions(+), 663 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index b3bab06bcb..dc3cfa373e 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -436,717 +436,717 @@ subroutine spawn_patches( currentSite, bc_in) ! in the nocomp cases, since every patch has a PFT identity, it can only receive patch area from patches ! that have the same identity. In order to allow this, we have this very high level loop over nocomp PFTs - ! and only do the disturbance for any patches that have that nocomp PFT identity. + ! and only do the disturbance for any patches that have that nocomp PFT identity. ! If nocomp is not enabled, then this is not much of a loop, it only passes through once. nocomp_pft_loop: do i_nocomp_pft = min_nocomp_pft,max_nocomp_pft - disturbance_type_loop: do i_disturbance_type = 1,N_DIST_TYPES + disturbance_type_loop: do i_disturbance_type = 1,N_DIST_TYPES - ! calculate area of disturbed land, in this timestep, by summing contributions from each existing patch. - currentPatch => currentSite%youngest_patch + ! calculate area of disturbed land, in this timestep, by summing contributions from each existing patch. + currentPatch => currentSite%youngest_patch - site_areadis_primary = 0.0_r8 - site_areadis_secondary = 0.0_r8 + site_areadis_primary = 0.0_r8 + site_areadis_secondary = 0.0_r8 - do while(associated(currentPatch)) + do while(associated(currentPatch)) - cp_nocomp_matches_1_if: if ( hlm_use_nocomp .eq. ifalse .or. & - currentPatch%nocomp_pft_label .eq. i_nocomp_pft ) then - - disturbance_rate = currentPatch%disturbance_rates(i_disturbance_type) + cp_nocomp_matches_1_if: if ( hlm_use_nocomp .eq. ifalse .or. & + currentPatch%nocomp_pft_label .eq. i_nocomp_pft ) then - if(disturbance_rate > (1.0_r8 + rsnbl_math_prec)) then - write(fates_log(),*) 'patch disturbance rate > 1 ?',disturbance_rate - call dump_patch(currentPatch) - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + disturbance_rate = currentPatch%disturbance_rates(i_disturbance_type) - ! Only create new patches that have non-negligible amount of land - if((currentPatch%area*disturbance_rate) > nearzero ) then - - ! figure out whether the receiver patch for disturbance from this patch will be - ! primary or secondary land receiver patch is primary forest only if both the - ! donor patch is primary forest and the current disturbance type is not logging - if ( currentPatch%anthro_disturbance_label .eq. primaryforest .and. & - (i_disturbance_type .ne. dtype_ilog) ) then - - site_areadis_primary = site_areadis_primary + currentPatch%area * disturbance_rate + if(disturbance_rate > (1.0_r8 + rsnbl_math_prec)) then + write(fates_log(),*) 'patch disturbance rate > 1 ?',disturbance_rate + call dump_patch(currentPatch) + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if - ! track disturbance rates to output to history - currentSite%disturbance_rates_primary_to_primary(i_disturbance_type) = & - currentSite%disturbance_rates_primary_to_primary(i_disturbance_type) + & - currentPatch%area * disturbance_rate * AREA_INV - else - site_areadis_secondary = site_areadis_secondary + currentPatch%area * disturbance_rate + ! Only create new patches that have non-negligible amount of land + if((currentPatch%area*disturbance_rate) > nearzero ) then - ! track disturbance rates to output to history - if (currentPatch%anthro_disturbance_label .eq. secondaryforest) then - currentSite%disturbance_rates_secondary_to_secondary(i_disturbance_type) = & - currentSite%disturbance_rates_secondary_to_secondary(i_disturbance_type) + & - currentPatch%area * disturbance_rate * AREA_INV - else - currentSite%disturbance_rates_primary_to_secondary(i_disturbance_type) = & - currentSite%disturbance_rates_primary_to_secondary(i_disturbance_type) + & - currentPatch%area * disturbance_rate * AREA_INV - endif + ! figure out whether the receiver patch for disturbance from this patch will be + ! primary or secondary land receiver patch is primary forest only if both the + ! donor patch is primary forest and the current disturbance type is not logging + if ( currentPatch%anthro_disturbance_label .eq. primaryforest .and. & + (i_disturbance_type .ne. dtype_ilog) ) then - endif - - end if - - end if cp_nocomp_matches_1_if - currentPatch => currentPatch%older - enddo ! end loop over patches. sum area disturbed for all patches. + site_areadis_primary = site_areadis_primary + currentPatch%area * disturbance_rate - ! It is possible that no disturbance area was generated - if ( (site_areadis_primary + site_areadis_secondary) > nearzero) then - - age = 0.0_r8 + ! track disturbance rates to output to history + currentSite%disturbance_rates_primary_to_primary(i_disturbance_type) = & + currentSite%disturbance_rates_primary_to_primary(i_disturbance_type) + & + currentPatch%area * disturbance_rate * AREA_INV + else + site_areadis_secondary = site_areadis_secondary + currentPatch%area * disturbance_rate - ! create two empty patches, to absorb newly disturbed primary and secondary forest area - ! first create patch to receive primary forest area - if ( site_areadis_primary .gt. nearzero ) then - allocate(new_patch_primary) + ! track disturbance rates to output to history + if (currentPatch%anthro_disturbance_label .eq. secondaryforest) then + currentSite%disturbance_rates_secondary_to_secondary(i_disturbance_type) = & + currentSite%disturbance_rates_secondary_to_secondary(i_disturbance_type) + & + currentPatch%area * disturbance_rate * AREA_INV + else + currentSite%disturbance_rates_primary_to_secondary(i_disturbance_type) = & + currentSite%disturbance_rates_primary_to_secondary(i_disturbance_type) + & + currentPatch%area * disturbance_rate * AREA_INV + endif - call create_patch(currentSite, new_patch_primary, age, & - site_areadis_primary, primaryforest, i_nocomp_pft) - - ! Initialize the litter pools to zero, these - ! pools will be populated by looping over the existing patches - ! and transfering in mass - do el=1,num_elements - call new_patch_primary%litter(el)%InitConditions(init_leaf_fines=0._r8, & - init_root_fines=0._r8, & - init_ag_cwd=0._r8, & - init_bg_cwd=0._r8, & - init_seed=0._r8, & - init_seed_germ=0._r8) - end do - new_patch_primary%tallest => null() - new_patch_primary%shortest => null() + endif - endif + end if - ! next create patch to receive secondary forest area - if ( site_areadis_secondary .gt. nearzero) then - allocate(new_patch_secondary) - call create_patch(currentSite, new_patch_secondary, age, & - site_areadis_secondary, secondaryforest,i_nocomp_pft) - - ! Initialize the litter pools to zero, these - ! pools will be populated by looping over the existing patches - ! and transfering in mass - do el=1,num_elements - call new_patch_secondary%litter(el)%InitConditions(init_leaf_fines=0._r8, & - init_root_fines=0._r8, & - init_ag_cwd=0._r8, & - init_bg_cwd=0._r8, & - init_seed=0._r8, & - init_seed_germ=0._r8) - end do - new_patch_secondary%tallest => null() - new_patch_secondary%shortest => null() + end if cp_nocomp_matches_1_if + currentPatch => currentPatch%older + enddo ! end loop over patches. sum area disturbed for all patches. + + ! It is possible that no disturbance area was generated + if ( (site_areadis_primary + site_areadis_secondary) > nearzero) then + + age = 0.0_r8 + + ! create two empty patches, to absorb newly disturbed primary and secondary forest area + ! first create patch to receive primary forest area + if ( site_areadis_primary .gt. nearzero ) then + allocate(new_patch_primary) + + call create_patch(currentSite, new_patch_primary, age, & + site_areadis_primary, primaryforest, i_nocomp_pft) + + ! Initialize the litter pools to zero, these + ! pools will be populated by looping over the existing patches + ! and transfering in mass + do el=1,num_elements + call new_patch_primary%litter(el)%InitConditions(init_leaf_fines=0._r8, & + init_root_fines=0._r8, & + init_ag_cwd=0._r8, & + init_bg_cwd=0._r8, & + init_seed=0._r8, & + init_seed_germ=0._r8) + end do + new_patch_primary%tallest => null() + new_patch_primary%shortest => null() - endif - - ! loop round all the patches that contribute surviving indivduals and litter - ! pools to the new patch. We only loop the pre-existing patches, so - ! quit the loop if the current patch is either null, or matches the - ! two new pointers. + endif - currentPatch => currentSite%oldest_patch - do while(associated(currentPatch)) + ! next create patch to receive secondary forest area + if ( site_areadis_secondary .gt. nearzero) then + allocate(new_patch_secondary) + call create_patch(currentSite, new_patch_secondary, age, & + site_areadis_secondary, secondaryforest,i_nocomp_pft) + + ! Initialize the litter pools to zero, these + ! pools will be populated by looping over the existing patches + ! and transfering in mass + do el=1,num_elements + call new_patch_secondary%litter(el)%InitConditions(init_leaf_fines=0._r8, & + init_root_fines=0._r8, & + init_ag_cwd=0._r8, & + init_bg_cwd=0._r8, & + init_seed=0._r8, & + init_seed_germ=0._r8) + end do + new_patch_secondary%tallest => null() + new_patch_secondary%shortest => null() - cp_nocomp_matches_2_if: if ( hlm_use_nocomp .eq. ifalse .or. & - currentPatch%nocomp_pft_label .eq. i_nocomp_pft ) then + endif - ! This is the amount of patch area that is disturbed, and donated by the donor - disturbance_rate = currentPatch%disturbance_rates(i_disturbance_type) - patch_site_areadis = currentPatch%area * disturbance_rate + ! loop round all the patches that contribute surviving indivduals and litter + ! pools to the new patch. We only loop the pre-existing patches, so + ! quit the loop if the current patch is either null, or matches the + ! two new pointers. - - if ( patch_site_areadis > nearzero ) then - - ! figure out whether the receiver patch for disturbance from this patch - ! will be primary or secondary land receiver patch is primary forest - ! only if both the donor patch is primary forest and the current - ! disturbance type is not logging - if (currentPatch%anthro_disturbance_label .eq. primaryforest .and. & - (i_disturbance_type .ne. dtype_ilog)) then - new_patch => new_patch_primary - else - new_patch => new_patch_secondary - endif - - if(.not.associated(new_patch))then - write(fates_log(),*) 'Patch spawning has attempted to point to' - write(fates_log(),*) 'an un-allocated patch' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - ! for the case where the donating patch is secondary forest, if - ! the current disturbance from this patch is non-anthropogenic, - ! we need to average in the time-since-anthropogenic-disturbance - ! from the donor patch into that of the receiver patch - if ( currentPatch%anthro_disturbance_label .eq. secondaryforest .and. & - (i_disturbance_type .ne. dtype_ilog) ) then - - new_patch%age_since_anthro_disturbance = new_patch%age_since_anthro_disturbance + & - currentPatch%age_since_anthro_disturbance * (patch_site_areadis / site_areadis_secondary) + currentPatch => currentSite%oldest_patch + do while(associated(currentPatch)) - endif - - - ! Transfer the litter existing already in the donor patch to the new patch - ! This call will only transfer non-burned litter to new patch - ! and burned litter to atmosphere. Thus it is important to zero burnt_frac_litter when - ! fire is not the current disturbance regime. + cp_nocomp_matches_2_if: if ( hlm_use_nocomp .eq. ifalse .or. & + currentPatch%nocomp_pft_label .eq. i_nocomp_pft ) then - if(i_disturbance_type .ne. dtype_ifire) then - currentPatch%burnt_frac_litter(:) = 0._r8 - end if + ! This is the amount of patch area that is disturbed, and donated by the donor + disturbance_rate = currentPatch%disturbance_rates(i_disturbance_type) + patch_site_areadis = currentPatch%area * disturbance_rate - call TransLitterNewPatch( currentSite, currentPatch, new_patch, patch_site_areadis) - ! Transfer in litter fluxes from plants in various contexts of death and destruction + if ( patch_site_areadis > nearzero ) then - if(i_disturbance_type .eq. dtype_ilog) then - call logging_litter_fluxes(currentSite, currentPatch, & - new_patch, patch_site_areadis,bc_in) - elseif(i_disturbance_type .eq. dtype_ifire) then - call fire_litter_fluxes(currentSite, currentPatch, & - new_patch, patch_site_areadis,bc_in) - else - call mortality_litter_fluxes(currentSite, currentPatch, & - new_patch, patch_site_areadis,bc_in) - endif + ! figure out whether the receiver patch for disturbance from this patch + ! will be primary or secondary land receiver patch is primary forest + ! only if both the donor patch is primary forest and the current + ! disturbance type is not logging + if (currentPatch%anthro_disturbance_label .eq. primaryforest .and. & + (i_disturbance_type .ne. dtype_ilog)) then + new_patch => new_patch_primary + else + new_patch => new_patch_secondary + endif + if(.not.associated(new_patch))then + write(fates_log(),*) 'Patch spawning has attempted to point to' + write(fates_log(),*) 'an un-allocated patch' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if - ! Copy any means or timers from the original patch to the new patch - ! These values will inherit all info from the original patch - ! -------------------------------------------------------------------------- - call new_patch%tveg24%CopyFromDonor(currentPatch%tveg24) - call new_patch%tveg_lpa%CopyFromDonor(currentPatch%tveg_lpa) - - - ! -------------------------------------------------------------------------- - ! The newly formed patch from disturbance (new_patch), has now been given - ! some litter from dead plants and pre-existing litter from the donor patches. - ! - ! Next, we loop through the cohorts in the donor patch, copy them with - ! area modified number density into the new-patch, and apply survivorship. - ! ------------------------------------------------------------------------- - - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - - allocate(nc) - if(hlm_use_planthydro.eq.itrue) call InitHydrCohort(CurrentSite,nc) - - ! Initialize the PARTEH object and point to the - ! correct boundary condition fields - nc%prt => null() - call InitPRTObject(nc%prt) - call InitPRTBoundaryConditions(nc) - - ! (Keeping as an example) - ! Allocate running mean functions - !allocate(nc%tveg_lpa) - !call nc%tveg_lpa%InitRMean(ema_lpa,init_value=new_patch%tveg_lpa%GetMean()) - - call zero_cohort(nc) - - ! nc is the new cohort that goes in the disturbed patch (new_patch)... currentCohort - ! is the curent cohort that stays in the donor patch (currentPatch) - call copy_cohort(currentCohort, nc) - - !this is the case as the new patch probably doesn't have a closed canopy, and - ! even if it does, that will be sorted out in canopy_structure. - nc%canopy_layer = 1 - nc%canopy_layer_yesterday = 1._r8 - - sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) - struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) - leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) - fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) - store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) - total_c = sapw_c + struct_c + leaf_c + fnrt_c + store_c - - ! treefall mortality is the current disturbance - if(i_disturbance_type .eq. dtype_ifall) then - - if(currentCohort%canopy_layer == 1)then - - ! In the donor patch we are left with fewer trees because the area has decreased - ! the plant density for large trees does not actually decrease in the donor patch - ! because this is the part of the original patch where no trees have actually fallen - ! The diagnostic cmort,bmort,hmort, and frmort rates have already been saved - - currentCohort%n = currentCohort%n * (1.0_r8 - fates_mortality_disturbance_fraction * & - min(1.0_r8,currentCohort%dmort * hlm_freq_day)) - - nc%n = 0.0_r8 ! kill all of the trees who caused the disturbance. - - nc%cmort = nan ! The mortality diagnostics are set to nan - ! because the cohort should dissappear - nc%hmort = nan - nc%bmort = nan - nc%frmort = nan - nc%smort = nan - nc%asmort = nan - nc%lmort_direct = nan - nc%lmort_collateral = nan - nc%lmort_infra = nan - nc%l_degrad = nan - - else - ! small trees - if( int(prt_params%woody(currentCohort%pft)) == itrue)then - - - ! Survivorship of undestory woody plants. Two step process. - ! Step 1: Reduce current number of plants to reflect the - ! change in area. - ! The number density per square are doesn't change, - ! but since the patch is smaller and cohort counts - ! are absolute, reduce this number. - - nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - - ! because the mortality rate due to impact for the cohorts which - ! had been in the understory and are now in the newly- - ! disturbed patch is very high, passing the imort directly to history - ! results in large numerical errors, on account of the sharply - ! reduced number densities. so instead pass this info via a - ! site-level diagnostic variable before reducing the number density. - - currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) = & - currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) + & - nc%n * ED_val_understorey_death / hlm_freq_day - - - currentSite%imort_carbonflux = currentSite%imort_carbonflux + & - (nc%n * ED_val_understorey_death / hlm_freq_day ) * & - total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 - - ! Step 2: Apply survivor ship function based on the understory death fraction - ! remaining of understory plants of those that are knocked over - ! by the overstorey trees dying... - nc%n = nc%n * (1.0_r8 - ED_val_understorey_death) - - ! since the donor patch split and sent a fraction of its members - ! to the new patch and a fraction to be preserved in itself, - ! when reporting diagnostic rates, we must carry over the mortality rates from - ! the donor that were applied before the patch split. Remember this is only - ! for diagnostics. But think of it this way, the rates are weighted by - ! number density in EDCLMLink, and the number density of this new patch is donated - ! so with the number density must come the effective mortality rates. - - nc%cmort = currentCohort%cmort - nc%hmort = currentCohort%hmort - nc%bmort = currentCohort%bmort - nc%frmort = currentCohort%frmort - nc%smort = currentCohort%smort - nc%asmort = currentCohort%asmort - nc%dmort = currentCohort%dmort - nc%lmort_direct = currentCohort%lmort_direct - nc%lmort_collateral = currentCohort%lmort_collateral - nc%lmort_infra = currentCohort%lmort_infra - - ! understory trees that might potentially be knocked over in the disturbance. - ! The existing (donor) patch should not have any impact mortality, it should - ! only lose cohorts due to the decrease in area. This is not mortality. - ! Besides, the current and newly created patch sum to unity - - currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - - else - ! grass is not killed by mortality disturbance events. Just move it into the new patch area. - ! Just split the grass into the existing and new patch structures - nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - - ! Those remaining in the existing - currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - - nc%cmort = currentCohort%cmort - nc%hmort = currentCohort%hmort - nc%bmort = currentCohort%bmort - nc%frmort = currentCohort%frmort - nc%smort = currentCohort%smort - nc%asmort = currentCohort%asmort - nc%dmort = currentCohort%dmort - nc%lmort_direct = currentCohort%lmort_direct - nc%lmort_collateral = currentCohort%lmort_collateral - nc%lmort_infra = currentCohort%lmort_infra - - endif - endif - - ! Fire is the current disturbance - elseif (i_disturbance_type .eq. dtype_ifire ) then - - ! Number of members in the new patch, before we impose fire survivorship - nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - - ! loss of individuals from source patch due to area shrinking - currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - - levcan = currentCohort%canopy_layer - - if(levcan==ican_upper) then - - ! before changing number densities, track total rate of trees that died - ! due to fire, as well as from each fire mortality term - currentSite%fmort_rate_canopy(currentCohort%size_class, currentCohort%pft) = & - currentSite%fmort_rate_canopy(currentCohort%size_class, currentCohort%pft) + & - nc%n * currentCohort%fire_mort / hlm_freq_day - - currentSite%fmort_carbonflux_canopy = currentSite%fmort_carbonflux_canopy + & - (nc%n * currentCohort%fire_mort) * & - total_c * g_per_kg * days_per_sec * ha_per_m2 - - else - currentSite%fmort_rate_ustory(currentCohort%size_class, currentCohort%pft) = & - currentSite%fmort_rate_ustory(currentCohort%size_class, currentCohort%pft) + & - nc%n * currentCohort%fire_mort / hlm_freq_day - - currentSite%fmort_carbonflux_ustory = currentSite%fmort_carbonflux_ustory + & - (nc%n * currentCohort%fire_mort) * & - total_c * g_per_kg * days_per_sec * ha_per_m2 - end if - - currentSite%fmort_rate_cambial(currentCohort%size_class, currentCohort%pft) = & - currentSite%fmort_rate_cambial(currentCohort%size_class, currentCohort%pft) + & - nc%n * currentCohort%cambial_mort / hlm_freq_day - currentSite%fmort_rate_crown(currentCohort%size_class, currentCohort%pft) = & - currentSite%fmort_rate_crown(currentCohort%size_class, currentCohort%pft) + & - nc%n * currentCohort%crownfire_mort / hlm_freq_day - - ! loss of individual from fire in new patch. - nc%n = nc%n * (1.0_r8 - currentCohort%fire_mort) - - nc%cmort = currentCohort%cmort - nc%hmort = currentCohort%hmort - nc%bmort = currentCohort%bmort - nc%frmort = currentCohort%frmort - nc%smort = currentCohort%smort - nc%asmort = currentCohort%asmort - nc%dmort = currentCohort%dmort - nc%lmort_direct = currentCohort%lmort_direct - nc%lmort_collateral = currentCohort%lmort_collateral - nc%lmort_infra = currentCohort%lmort_infra - - - ! Some of of the leaf mass from living plants has been - ! burned off. Here, we remove that mass, and - ! tally it in the flux we sent to the atmosphere - - if(int(prt_params%woody(currentCohort%pft)) == itrue)then - leaf_burn_frac = currentCohort%fraction_crown_burned - else + ! for the case where the donating patch is secondary forest, if + ! the current disturbance from this patch is non-anthropogenic, + ! we need to average in the time-since-anthropogenic-disturbance + ! from the donor patch into that of the receiver patch + if ( currentPatch%anthro_disturbance_label .eq. secondaryforest .and. & + (i_disturbance_type .ne. dtype_ilog) ) then - ! Grasses determine their fraction of leaves burned here + new_patch%age_since_anthro_disturbance = new_patch%age_since_anthro_disturbance + & + currentPatch%age_since_anthro_disturbance * (patch_site_areadis / site_areadis_secondary) - leaf_burn_frac = currentPatch%burnt_frac_litter(lg_sf) - endif - - ! Perform a check to make sure that spitfire gave - ! us reasonable mortality and burn fraction rates - - if( (leaf_burn_frac < 0._r8) .or. & - (leaf_burn_frac > 1._r8) .or. & - (currentCohort%fire_mort < 0._r8) .or. & - (currentCohort%fire_mort > 1._r8)) then - write(fates_log(),*) 'unexpected fire fractions' - write(fates_log(),*) prt_params%woody(currentCohort%pft) - write(fates_log(),*) leaf_burn_frac - write(fates_log(),*) currentCohort%fire_mort - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - do el = 1,num_elements - - leaf_m = nc%prt%GetState(leaf_organ, element_list(el)) - - currentSite%mass_balance(el)%burn_flux_to_atm = & - currentSite%mass_balance(el)%burn_flux_to_atm + & - leaf_burn_frac * leaf_m * nc%n - end do + endif - ! Here the mass is removed from the plant - call PRTBurnLosses(nc%prt, leaf_organ, leaf_burn_frac) - currentCohort%fraction_crown_burned = 0.0_r8 - nc%fraction_crown_burned = 0.0_r8 + ! Transfer the litter existing already in the donor patch to the new patch + ! This call will only transfer non-burned litter to new patch + ! and burned litter to atmosphere. Thus it is important to zero burnt_frac_litter when + ! fire is not the current disturbance regime. + if(i_disturbance_type .ne. dtype_ifire) then + currentPatch%burnt_frac_litter(:) = 0._r8 + end if + call TransLitterNewPatch( currentSite, currentPatch, new_patch, patch_site_areadis) - ! Logging is the current disturbance - elseif (i_disturbance_type .eq. dtype_ilog ) then - - ! If this cohort is in the upper canopy. It generated - if(currentCohort%canopy_layer == 1)then - - ! calculate the survivorship of disturbed trees because non-harvested - nc%n = currentCohort%n * currentCohort%l_degrad - ! nc%n = (currentCohort%l_degrad / (currentCohort%l_degrad + & - ! currentCohort%lmort_direct + currentCohort%lmort_collateral + - ! currentCohort%lmort_infra) ) * & - ! currentCohort%n * patch_site_areadis/currentPatch%area - - ! Reduce counts in the existing/donor patch according to the logging rate - currentCohort%n = currentCohort%n * & - (1.0_r8 - min(1.0_r8,(currentCohort%lmort_direct + & - currentCohort%lmort_collateral + & - currentCohort%lmort_infra + currentCohort%l_degrad))) - - nc%cmort = currentCohort%cmort - nc%hmort = currentCohort%hmort - nc%bmort = currentCohort%bmort - nc%frmort = currentCohort%frmort - nc%smort = currentCohort%smort - nc%asmort = currentCohort%asmort - nc%dmort = currentCohort%dmort - - ! since these are the ones that weren't logged, - ! set the logging mortality rates as zero - nc%lmort_direct = 0._r8 - nc%lmort_collateral = 0._r8 - nc%lmort_infra = 0._r8 - - else - - ! What to do with cohorts in the understory of a logging generated - ! disturbance patch? - - if(int(prt_params%woody(currentCohort%pft)) == itrue)then - - - ! Survivorship of undestory woody plants. Two step process. - ! Step 1: Reduce current number of plants to reflect the - ! change in area. - ! The number density per square are doesn't change, - ! but since the patch is smaller - ! and cohort counts are absolute, reduce this number. - nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - - ! because the mortality rate due to impact for the cohorts which had - ! been in the understory and are now in the newly- - ! disturbed patch is very high, passing the imort directly to - ! history results in large numerical errors, on account - ! of the sharply reduced number densities. so instead pass this info - ! via a site-level diagnostic variable before reducing - ! the number density. - currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) = & - currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) + & - nc%n * currentPatch%fract_ldist_not_harvested * & - logging_coll_under_frac / hlm_freq_day - - currentSite%imort_carbonflux = currentSite%imort_carbonflux + & - (nc%n * currentPatch%fract_ldist_not_harvested * & - logging_coll_under_frac/ hlm_freq_day ) * & - total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 - - - ! Step 2: Apply survivor ship function based on the understory death fraction - - ! remaining of understory plants of those that are knocked - ! over by the overstorey trees dying... - ! LOGGING SURVIVORSHIP OF UNDERSTORY PLANTS IS SET AS A NEW PARAMETER - ! in the fatesparameter files - nc%n = nc%n * (1.0_r8 - & - (1.0_r8-currentPatch%fract_ldist_not_harvested) * logging_coll_under_frac) - - ! Step 3: Reduce the number count of cohorts in the - ! original/donor/non-disturbed patch to reflect the area change - currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - - nc%cmort = currentCohort%cmort - nc%hmort = currentCohort%hmort - nc%bmort = currentCohort%bmort - nc%frmort = currentCohort%frmort - nc%smort = currentCohort%smort - nc%asmort = currentCohort%asmort - nc%dmort = currentCohort%dmort - nc%lmort_direct = currentCohort%lmort_direct - nc%lmort_collateral = currentCohort%lmort_collateral - nc%lmort_infra = currentCohort%lmort_infra - + ! Transfer in litter fluxes from plants in various contexts of death and destruction + + if(i_disturbance_type .eq. dtype_ilog) then + call logging_litter_fluxes(currentSite, currentPatch, & + new_patch, patch_site_areadis,bc_in) + elseif(i_disturbance_type .eq. dtype_ifire) then + call fire_litter_fluxes(currentSite, currentPatch, & + new_patch, patch_site_areadis,bc_in) else - - ! grass is not killed by mortality disturbance events. - ! Just move it into the new patch area. - ! Just split the grass into the existing and new patch structures - nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - - ! Those remaining in the existing - currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - - ! No grass impact mortality imposed on the newly created patch - nc%cmort = currentCohort%cmort - nc%hmort = currentCohort%hmort - nc%bmort = currentCohort%bmort - nc%frmort = currentCohort%frmort - nc%smort = currentCohort%smort - nc%asmort = currentCohort%asmort - nc%dmort = currentCohort%dmort - nc%lmort_direct = currentCohort%lmort_direct - nc%lmort_collateral = currentCohort%lmort_collateral - nc%lmort_infra = currentCohort%lmort_infra - - endif ! is/is-not woody - - endif ! Select canopy layer - - else - write(fates_log(),*) 'unknown disturbance mode?' - write(fates_log(),*) 'i_disturbance_type: ',i_disturbance_type - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if ! Select disturbance mode - - if (nc%n > 0.0_r8) then - storebigcohort => new_patch%tallest - storesmallcohort => new_patch%shortest - if(associated(new_patch%tallest))then - tnull = 0 - else - tnull = 1 - new_patch%tallest => nc - nc%taller => null() - endif - - if(associated(new_patch%shortest))then - snull = 0 + call mortality_litter_fluxes(currentSite, currentPatch, & + new_patch, patch_site_areadis,bc_in) + endif + + + ! Copy any means or timers from the original patch to the new patch + ! These values will inherit all info from the original patch + ! -------------------------------------------------------------------------- + call new_patch%tveg24%CopyFromDonor(currentPatch%tveg24) + call new_patch%tveg_lpa%CopyFromDonor(currentPatch%tveg_lpa) + + + ! -------------------------------------------------------------------------- + ! The newly formed patch from disturbance (new_patch), has now been given + ! some litter from dead plants and pre-existing litter from the donor patches. + ! + ! Next, we loop through the cohorts in the donor patch, copy them with + ! area modified number density into the new-patch, and apply survivorship. + ! ------------------------------------------------------------------------- + + currentCohort => currentPatch%shortest + do while(associated(currentCohort)) + + allocate(nc) + if(hlm_use_planthydro.eq.itrue) call InitHydrCohort(CurrentSite,nc) + + ! Initialize the PARTEH object and point to the + ! correct boundary condition fields + nc%prt => null() + call InitPRTObject(nc%prt) + call InitPRTBoundaryConditions(nc) + + ! (Keeping as an example) + ! Allocate running mean functions + !allocate(nc%tveg_lpa) + !call nc%tveg_lpa%InitRMean(ema_lpa,init_value=new_patch%tveg_lpa%GetMean()) + + call zero_cohort(nc) + + ! nc is the new cohort that goes in the disturbed patch (new_patch)... currentCohort + ! is the curent cohort that stays in the donor patch (currentPatch) + call copy_cohort(currentCohort, nc) + + !this is the case as the new patch probably doesn't have a closed canopy, and + ! even if it does, that will be sorted out in canopy_structure. + nc%canopy_layer = 1 + nc%canopy_layer_yesterday = 1._r8 + + sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) + struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) + leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) + fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) + store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) + total_c = sapw_c + struct_c + leaf_c + fnrt_c + store_c + + ! treefall mortality is the current disturbance + if(i_disturbance_type .eq. dtype_ifall) then + + if(currentCohort%canopy_layer == 1)then + + ! In the donor patch we are left with fewer trees because the area has decreased + ! the plant density for large trees does not actually decrease in the donor patch + ! because this is the part of the original patch where no trees have actually fallen + ! The diagnostic cmort,bmort,hmort, and frmort rates have already been saved + + currentCohort%n = currentCohort%n * (1.0_r8 - fates_mortality_disturbance_fraction * & + min(1.0_r8,currentCohort%dmort * hlm_freq_day)) + + nc%n = 0.0_r8 ! kill all of the trees who caused the disturbance. + + nc%cmort = nan ! The mortality diagnostics are set to nan + ! because the cohort should dissappear + nc%hmort = nan + nc%bmort = nan + nc%frmort = nan + nc%smort = nan + nc%asmort = nan + nc%lmort_direct = nan + nc%lmort_collateral = nan + nc%lmort_infra = nan + nc%l_degrad = nan + + else + ! small trees + if( int(prt_params%woody(currentCohort%pft)) == itrue)then + + + ! Survivorship of undestory woody plants. Two step process. + ! Step 1: Reduce current number of plants to reflect the + ! change in area. + ! The number density per square are doesn't change, + ! but since the patch is smaller and cohort counts + ! are absolute, reduce this number. + + nc%n = currentCohort%n * patch_site_areadis/currentPatch%area + + ! because the mortality rate due to impact for the cohorts which + ! had been in the understory and are now in the newly- + ! disturbed patch is very high, passing the imort directly to history + ! results in large numerical errors, on account of the sharply + ! reduced number densities. so instead pass this info via a + ! site-level diagnostic variable before reducing the number density. + + currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) = & + currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) + & + nc%n * ED_val_understorey_death / hlm_freq_day + + + currentSite%imort_carbonflux = currentSite%imort_carbonflux + & + (nc%n * ED_val_understorey_death / hlm_freq_day ) * & + total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 + + ! Step 2: Apply survivor ship function based on the understory death fraction + ! remaining of understory plants of those that are knocked over + ! by the overstorey trees dying... + nc%n = nc%n * (1.0_r8 - ED_val_understorey_death) + + ! since the donor patch split and sent a fraction of its members + ! to the new patch and a fraction to be preserved in itself, + ! when reporting diagnostic rates, we must carry over the mortality rates from + ! the donor that were applied before the patch split. Remember this is only + ! for diagnostics. But think of it this way, the rates are weighted by + ! number density in EDCLMLink, and the number density of this new patch is donated + ! so with the number density must come the effective mortality rates. + + nc%cmort = currentCohort%cmort + nc%hmort = currentCohort%hmort + nc%bmort = currentCohort%bmort + nc%frmort = currentCohort%frmort + nc%smort = currentCohort%smort + nc%asmort = currentCohort%asmort + nc%dmort = currentCohort%dmort + nc%lmort_direct = currentCohort%lmort_direct + nc%lmort_collateral = currentCohort%lmort_collateral + nc%lmort_infra = currentCohort%lmort_infra + + ! understory trees that might potentially be knocked over in the disturbance. + ! The existing (donor) patch should not have any impact mortality, it should + ! only lose cohorts due to the decrease in area. This is not mortality. + ! Besides, the current and newly created patch sum to unity + + currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) + + else + ! grass is not killed by mortality disturbance events. Just move it into the new patch area. + ! Just split the grass into the existing and new patch structures + nc%n = currentCohort%n * patch_site_areadis/currentPatch%area + + ! Those remaining in the existing + currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) + + nc%cmort = currentCohort%cmort + nc%hmort = currentCohort%hmort + nc%bmort = currentCohort%bmort + nc%frmort = currentCohort%frmort + nc%smort = currentCohort%smort + nc%asmort = currentCohort%asmort + nc%dmort = currentCohort%dmort + nc%lmort_direct = currentCohort%lmort_direct + nc%lmort_collateral = currentCohort%lmort_collateral + nc%lmort_infra = currentCohort%lmort_infra + + endif + endif + + ! Fire is the current disturbance + elseif (i_disturbance_type .eq. dtype_ifire ) then + + ! Number of members in the new patch, before we impose fire survivorship + nc%n = currentCohort%n * patch_site_areadis/currentPatch%area + + ! loss of individuals from source patch due to area shrinking + currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) + + levcan = currentCohort%canopy_layer + + if(levcan==ican_upper) then + + ! before changing number densities, track total rate of trees that died + ! due to fire, as well as from each fire mortality term + currentSite%fmort_rate_canopy(currentCohort%size_class, currentCohort%pft) = & + currentSite%fmort_rate_canopy(currentCohort%size_class, currentCohort%pft) + & + nc%n * currentCohort%fire_mort / hlm_freq_day + + currentSite%fmort_carbonflux_canopy = currentSite%fmort_carbonflux_canopy + & + (nc%n * currentCohort%fire_mort) * & + total_c * g_per_kg * days_per_sec * ha_per_m2 + + else + currentSite%fmort_rate_ustory(currentCohort%size_class, currentCohort%pft) = & + currentSite%fmort_rate_ustory(currentCohort%size_class, currentCohort%pft) + & + nc%n * currentCohort%fire_mort / hlm_freq_day + + currentSite%fmort_carbonflux_ustory = currentSite%fmort_carbonflux_ustory + & + (nc%n * currentCohort%fire_mort) * & + total_c * g_per_kg * days_per_sec * ha_per_m2 + end if + + currentSite%fmort_rate_cambial(currentCohort%size_class, currentCohort%pft) = & + currentSite%fmort_rate_cambial(currentCohort%size_class, currentCohort%pft) + & + nc%n * currentCohort%cambial_mort / hlm_freq_day + currentSite%fmort_rate_crown(currentCohort%size_class, currentCohort%pft) = & + currentSite%fmort_rate_crown(currentCohort%size_class, currentCohort%pft) + & + nc%n * currentCohort%crownfire_mort / hlm_freq_day + + ! loss of individual from fire in new patch. + nc%n = nc%n * (1.0_r8 - currentCohort%fire_mort) + + nc%cmort = currentCohort%cmort + nc%hmort = currentCohort%hmort + nc%bmort = currentCohort%bmort + nc%frmort = currentCohort%frmort + nc%smort = currentCohort%smort + nc%asmort = currentCohort%asmort + nc%dmort = currentCohort%dmort + nc%lmort_direct = currentCohort%lmort_direct + nc%lmort_collateral = currentCohort%lmort_collateral + nc%lmort_infra = currentCohort%lmort_infra + + + ! Some of of the leaf mass from living plants has been + ! burned off. Here, we remove that mass, and + ! tally it in the flux we sent to the atmosphere + + if(int(prt_params%woody(currentCohort%pft)) == itrue)then + leaf_burn_frac = currentCohort%fraction_crown_burned + else + + ! Grasses determine their fraction of leaves burned here + + leaf_burn_frac = currentPatch%burnt_frac_litter(lg_sf) + endif + + ! Perform a check to make sure that spitfire gave + ! us reasonable mortality and burn fraction rates + + if( (leaf_burn_frac < 0._r8) .or. & + (leaf_burn_frac > 1._r8) .or. & + (currentCohort%fire_mort < 0._r8) .or. & + (currentCohort%fire_mort > 1._r8)) then + write(fates_log(),*) 'unexpected fire fractions' + write(fates_log(),*) prt_params%woody(currentCohort%pft) + write(fates_log(),*) leaf_burn_frac + write(fates_log(),*) currentCohort%fire_mort + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + do el = 1,num_elements + + leaf_m = nc%prt%GetState(leaf_organ, element_list(el)) + + currentSite%mass_balance(el)%burn_flux_to_atm = & + currentSite%mass_balance(el)%burn_flux_to_atm + & + leaf_burn_frac * leaf_m * nc%n + end do + + ! Here the mass is removed from the plant + + call PRTBurnLosses(nc%prt, leaf_organ, leaf_burn_frac) + currentCohort%fraction_crown_burned = 0.0_r8 + nc%fraction_crown_burned = 0.0_r8 + + + + ! Logging is the current disturbance + elseif (i_disturbance_type .eq. dtype_ilog ) then + + ! If this cohort is in the upper canopy. It generated + if(currentCohort%canopy_layer == 1)then + + ! calculate the survivorship of disturbed trees because non-harvested + nc%n = currentCohort%n * currentCohort%l_degrad + ! nc%n = (currentCohort%l_degrad / (currentCohort%l_degrad + & + ! currentCohort%lmort_direct + currentCohort%lmort_collateral + + ! currentCohort%lmort_infra) ) * & + ! currentCohort%n * patch_site_areadis/currentPatch%area + + ! Reduce counts in the existing/donor patch according to the logging rate + currentCohort%n = currentCohort%n * & + (1.0_r8 - min(1.0_r8,(currentCohort%lmort_direct + & + currentCohort%lmort_collateral + & + currentCohort%lmort_infra + currentCohort%l_degrad))) + + nc%cmort = currentCohort%cmort + nc%hmort = currentCohort%hmort + nc%bmort = currentCohort%bmort + nc%frmort = currentCohort%frmort + nc%smort = currentCohort%smort + nc%asmort = currentCohort%asmort + nc%dmort = currentCohort%dmort + + ! since these are the ones that weren't logged, + ! set the logging mortality rates as zero + nc%lmort_direct = 0._r8 + nc%lmort_collateral = 0._r8 + nc%lmort_infra = 0._r8 + + else + + ! What to do with cohorts in the understory of a logging generated + ! disturbance patch? + + if(int(prt_params%woody(currentCohort%pft)) == itrue)then + + + ! Survivorship of undestory woody plants. Two step process. + ! Step 1: Reduce current number of plants to reflect the + ! change in area. + ! The number density per square are doesn't change, + ! but since the patch is smaller + ! and cohort counts are absolute, reduce this number. + nc%n = currentCohort%n * patch_site_areadis/currentPatch%area + + ! because the mortality rate due to impact for the cohorts which had + ! been in the understory and are now in the newly- + ! disturbed patch is very high, passing the imort directly to + ! history results in large numerical errors, on account + ! of the sharply reduced number densities. so instead pass this info + ! via a site-level diagnostic variable before reducing + ! the number density. + currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) = & + currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) + & + nc%n * currentPatch%fract_ldist_not_harvested * & + logging_coll_under_frac / hlm_freq_day + + currentSite%imort_carbonflux = currentSite%imort_carbonflux + & + (nc%n * currentPatch%fract_ldist_not_harvested * & + logging_coll_under_frac/ hlm_freq_day ) * & + total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 + + + ! Step 2: Apply survivor ship function based on the understory death fraction + + ! remaining of understory plants of those that are knocked + ! over by the overstorey trees dying... + ! LOGGING SURVIVORSHIP OF UNDERSTORY PLANTS IS SET AS A NEW PARAMETER + ! in the fatesparameter files + nc%n = nc%n * (1.0_r8 - & + (1.0_r8-currentPatch%fract_ldist_not_harvested) * logging_coll_under_frac) + + ! Step 3: Reduce the number count of cohorts in the + ! original/donor/non-disturbed patch to reflect the area change + currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) + + nc%cmort = currentCohort%cmort + nc%hmort = currentCohort%hmort + nc%bmort = currentCohort%bmort + nc%frmort = currentCohort%frmort + nc%smort = currentCohort%smort + nc%asmort = currentCohort%asmort + nc%dmort = currentCohort%dmort + nc%lmort_direct = currentCohort%lmort_direct + nc%lmort_collateral = currentCohort%lmort_collateral + nc%lmort_infra = currentCohort%lmort_infra + + else + + ! grass is not killed by mortality disturbance events. + ! Just move it into the new patch area. + ! Just split the grass into the existing and new patch structures + nc%n = currentCohort%n * patch_site_areadis/currentPatch%area + + ! Those remaining in the existing + currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) + + ! No grass impact mortality imposed on the newly created patch + nc%cmort = currentCohort%cmort + nc%hmort = currentCohort%hmort + nc%bmort = currentCohort%bmort + nc%frmort = currentCohort%frmort + nc%smort = currentCohort%smort + nc%asmort = currentCohort%asmort + nc%dmort = currentCohort%dmort + nc%lmort_direct = currentCohort%lmort_direct + nc%lmort_collateral = currentCohort%lmort_collateral + nc%lmort_infra = currentCohort%lmort_infra + + endif ! is/is-not woody + + endif ! Select canopy layer + + else + write(fates_log(),*) 'unknown disturbance mode?' + write(fates_log(),*) 'i_disturbance_type: ',i_disturbance_type + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if ! Select disturbance mode + + if (nc%n > 0.0_r8) then + storebigcohort => new_patch%tallest + storesmallcohort => new_patch%shortest + if(associated(new_patch%tallest))then + tnull = 0 + else + tnull = 1 + new_patch%tallest => nc + nc%taller => null() + endif + + if(associated(new_patch%shortest))then + snull = 0 + else + snull = 1 + new_patch%shortest => nc + nc%shorter => null() + endif + nc%patchptr => new_patch + call insert_cohort(nc, new_patch%tallest, new_patch%shortest, & + tnull, snull, storebigcohort, storesmallcohort) + + new_patch%tallest => storebigcohort + new_patch%shortest => storesmallcohort + else + + ! Get rid of the new temporary cohort + call DeallocateCohort(nc) + deallocate(nc) + + endif + + currentCohort => currentCohort%taller + enddo ! currentCohort + call sort_cohorts(currentPatch) + + !update area of donor patch + oldarea = currentPatch%area + currentPatch%area = currentPatch%area - patch_site_areadis + + ! for all disturbance rates that haven't been resolved yet, increase their amount so that + ! they are the same amount of gridcell-scale disturbance relative to the original patch size + if (i_disturbance_type .ne. N_DIST_TYPES) then + do i_dist2 = i_disturbance_type+1,N_DIST_TYPES + currentPatch%disturbance_rates(i_dist2) = currentPatch%disturbance_rates(i_dist2) & + * oldarea / currentPatch%area + end do + end if + + ! sort out the cohorts, since some of them may be so small as to need removing. + ! the first call to terminate cohorts removes sparse number densities, + ! the second call removes for all other reasons (sparse culling must happen + ! before fusion) + call terminate_cohorts(currentSite, currentPatch, 1,16,bc_in) + call fuse_cohorts(currentSite,currentPatch, bc_in) + call terminate_cohorts(currentSite, currentPatch, 2,16,bc_in) + call sort_cohorts(currentPatch) + + end if ! if ( new_patch%area > nearzero ) then + + end if cp_nocomp_matches_2_if + currentPatch => currentPatch%younger + + enddo ! currentPatch patch loop. + + !*************************/ + !** INSERT NEW PATCH(ES) INTO LINKED LIST + !*************************/ + + if ( site_areadis_primary .gt. nearzero) then + currentPatch => currentSite%youngest_patch + ! insert new youngest primary patch after all the secondary patches, if there are any. + ! this requires first finding the current youngest primary to insert the new one ahead of + if (currentPatch%anthro_disturbance_label .eq. secondaryforest ) then + found_youngest_primary = .false. + do while(associated(currentPatch) .and. .not. found_youngest_primary) + currentPatch => currentPatch%older + if (associated(currentPatch)) then + if (currentPatch%anthro_disturbance_label .eq. primaryforest) then + found_youngest_primary = .true. + endif + endif + end do + if (associated(currentPatch)) then + ! the case where we've found a youngest primary patch + new_patch_primary%older => currentPatch + new_patch_primary%younger => currentPatch%younger + currentPatch%younger%older => new_patch_primary + currentPatch%younger => new_patch_primary else - snull = 1 - new_patch%shortest => nc - nc%shorter => null() + ! the case where we haven't, because the patches are all secondaary, + ! and are putting a primary patch at the oldest end of the + ! linked list (not sure how this could happen, but who knows...) + new_patch_primary%older => null() + new_patch_primary%younger => currentSite%oldest_patch + currentSite%oldest_patch%older => new_patch_primary + currentSite%oldest_patch => new_patch_primary endif - nc%patchptr => new_patch - call insert_cohort(nc, new_patch%tallest, new_patch%shortest, & - tnull, snull, storebigcohort, storesmallcohort) - - new_patch%tallest => storebigcohort - new_patch%shortest => storesmallcohort else - - ! Get rid of the new temporary cohort - call DeallocateCohort(nc) - deallocate(nc) - + ! the case where there are no secondary patches at the start of the linked list (prior logic) + new_patch_primary%older => currentPatch + new_patch_primary%younger => null() + currentPatch%younger => new_patch_primary + currentSite%youngest_patch => new_patch_primary endif - - currentCohort => currentCohort%taller - enddo ! currentCohort - call sort_cohorts(currentPatch) - - !update area of donor patch - oldarea = currentPatch%area - currentPatch%area = currentPatch%area - patch_site_areadis - - ! for all disturbance rates that haven't been resolved yet, increase their amount so that - ! they are the same amount of gridcell-scale disturbance relative to the original patch size - if (i_disturbance_type .ne. N_DIST_TYPES) then - do i_dist2 = i_disturbance_type+1,N_DIST_TYPES - currentPatch%disturbance_rates(i_dist2) = currentPatch%disturbance_rates(i_dist2) & - * oldarea / currentPatch%area - end do - end if + endif - ! sort out the cohorts, since some of them may be so small as to need removing. + ! insert first secondary at the start of the list + if ( site_areadis_secondary .gt. nearzero) then + currentPatch => currentSite%youngest_patch + new_patch_secondary%older => currentPatch + new_patch_secondary%younger=> null() + currentPatch%younger => new_patch_secondary + currentSite%youngest_patch => new_patch_secondary + endif + + + ! sort out the cohorts, since some of them may be so small as to need removing. ! the first call to terminate cohorts removes sparse number densities, ! the second call removes for all other reasons (sparse culling must happen ! before fusion) - call terminate_cohorts(currentSite, currentPatch, 1,16,bc_in) - call fuse_cohorts(currentSite,currentPatch, bc_in) - call terminate_cohorts(currentSite, currentPatch, 2,16,bc_in) - call sort_cohorts(currentPatch) - end if ! if ( new_patch%area > nearzero ) then - - end if cp_nocomp_matches_2_if - currentPatch => currentPatch%younger - - enddo ! currentPatch patch loop. + if ( site_areadis_primary .gt. nearzero) then + call terminate_cohorts(currentSite, new_patch_primary, 1,17, bc_in) + call fuse_cohorts(currentSite,new_patch_primary, bc_in) + call terminate_cohorts(currentSite, new_patch_primary, 2,17, bc_in) + call sort_cohorts(new_patch_primary) + endif - !*************************/ - !** INSERT NEW PATCH(ES) INTO LINKED LIST - !*************************/ - - if ( site_areadis_primary .gt. nearzero) then - currentPatch => currentSite%youngest_patch - ! insert new youngest primary patch after all the secondary patches, if there are any. - ! this requires first finding the current youngest primary to insert the new one ahead of - if (currentPatch%anthro_disturbance_label .eq. secondaryforest ) then - found_youngest_primary = .false. - do while(associated(currentPatch) .and. .not. found_youngest_primary) - currentPatch => currentPatch%older - if (associated(currentPatch)) then - if (currentPatch%anthro_disturbance_label .eq. primaryforest) then - found_youngest_primary = .true. - endif - endif - end do - if (associated(currentPatch)) then - ! the case where we've found a youngest primary patch - new_patch_primary%older => currentPatch - new_patch_primary%younger => currentPatch%younger - currentPatch%younger%older => new_patch_primary - currentPatch%younger => new_patch_primary - else - ! the case where we haven't, because the patches are all secondaary, - ! and are putting a primary patch at the oldest end of the - ! linked list (not sure how this could happen, but who knows...) - new_patch_primary%older => null() - new_patch_primary%younger => currentSite%oldest_patch - currentSite%oldest_patch%older => new_patch_primary - currentSite%oldest_patch => new_patch_primary + if ( site_areadis_secondary .gt. nearzero) then + call terminate_cohorts(currentSite, new_patch_secondary, 1,18,bc_in) + call fuse_cohorts(currentSite,new_patch_secondary, bc_in) + call terminate_cohorts(currentSite, new_patch_secondary, 2,18,bc_in) + call sort_cohorts(new_patch_secondary) endif - else - ! the case where there are no secondary patches at the start of the linked list (prior logic) - new_patch_primary%older => currentPatch - new_patch_primary%younger => null() - currentPatch%younger => new_patch_primary - currentSite%youngest_patch => new_patch_primary - endif - endif - - ! insert first secondary at the start of the list - if ( site_areadis_secondary .gt. nearzero) then - currentPatch => currentSite%youngest_patch - new_patch_secondary%older => currentPatch - new_patch_secondary%younger=> null() - currentPatch%younger => new_patch_secondary - currentSite%youngest_patch => new_patch_secondary - endif - - - ! sort out the cohorts, since some of them may be so small as to need removing. - ! the first call to terminate cohorts removes sparse number densities, - ! the second call removes for all other reasons (sparse culling must happen - ! before fusion) - - if ( site_areadis_primary .gt. nearzero) then - call terminate_cohorts(currentSite, new_patch_primary, 1,17, bc_in) - call fuse_cohorts(currentSite,new_patch_primary, bc_in) - call terminate_cohorts(currentSite, new_patch_primary, 2,17, bc_in) - call sort_cohorts(new_patch_primary) - endif - - if ( site_areadis_secondary .gt. nearzero) then - call terminate_cohorts(currentSite, new_patch_secondary, 1,18,bc_in) - call fuse_cohorts(currentSite,new_patch_secondary, bc_in) - call terminate_cohorts(currentSite, new_patch_secondary, 2,18,bc_in) - call sort_cohorts(new_patch_secondary) - endif - - endif !end new_patch area - - - call check_patch_area(currentSite) - call set_patchno(currentSite) - - end do disturbance_type_loop + + endif !end new_patch area + + + call check_patch_area(currentSite) + call set_patchno(currentSite) + + end do disturbance_type_loop end do nocomp_pft_loop From 485fe8373256d356db22e62f9b74f8f460af9128 Mon Sep 17 00:00:00 2001 From: ckoven Date: Thu, 23 Jun 2022 15:06:01 -0600 Subject: [PATCH 254/852] Revert "auto-indented spawn_patches" This reverts commit 53ca295e84cdb6b0a0fe99ba937161dc19d76987. --- biogeochem/EDPatchDynamicsMod.F90 | 1326 ++++++++++++++--------------- 1 file changed, 663 insertions(+), 663 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index dc3cfa373e..b3bab06bcb 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -436,717 +436,717 @@ subroutine spawn_patches( currentSite, bc_in) ! in the nocomp cases, since every patch has a PFT identity, it can only receive patch area from patches ! that have the same identity. In order to allow this, we have this very high level loop over nocomp PFTs - ! and only do the disturbance for any patches that have that nocomp PFT identity. + ! and only do the disturbance for any patches that have that nocomp PFT identity. ! If nocomp is not enabled, then this is not much of a loop, it only passes through once. nocomp_pft_loop: do i_nocomp_pft = min_nocomp_pft,max_nocomp_pft - disturbance_type_loop: do i_disturbance_type = 1,N_DIST_TYPES + disturbance_type_loop: do i_disturbance_type = 1,N_DIST_TYPES - ! calculate area of disturbed land, in this timestep, by summing contributions from each existing patch. - currentPatch => currentSite%youngest_patch - - site_areadis_primary = 0.0_r8 - site_areadis_secondary = 0.0_r8 - - do while(associated(currentPatch)) + ! calculate area of disturbed land, in this timestep, by summing contributions from each existing patch. + currentPatch => currentSite%youngest_patch - cp_nocomp_matches_1_if: if ( hlm_use_nocomp .eq. ifalse .or. & - currentPatch%nocomp_pft_label .eq. i_nocomp_pft ) then + site_areadis_primary = 0.0_r8 + site_areadis_secondary = 0.0_r8 - disturbance_rate = currentPatch%disturbance_rates(i_disturbance_type) + do while(associated(currentPatch)) - if(disturbance_rate > (1.0_r8 + rsnbl_math_prec)) then - write(fates_log(),*) 'patch disturbance rate > 1 ?',disturbance_rate - call dump_patch(currentPatch) - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + cp_nocomp_matches_1_if: if ( hlm_use_nocomp .eq. ifalse .or. & + currentPatch%nocomp_pft_label .eq. i_nocomp_pft ) then + + disturbance_rate = currentPatch%disturbance_rates(i_disturbance_type) - ! Only create new patches that have non-negligible amount of land - if((currentPatch%area*disturbance_rate) > nearzero ) then + if(disturbance_rate > (1.0_r8 + rsnbl_math_prec)) then + write(fates_log(),*) 'patch disturbance rate > 1 ?',disturbance_rate + call dump_patch(currentPatch) + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if - ! figure out whether the receiver patch for disturbance from this patch will be - ! primary or secondary land receiver patch is primary forest only if both the - ! donor patch is primary forest and the current disturbance type is not logging - if ( currentPatch%anthro_disturbance_label .eq. primaryforest .and. & - (i_disturbance_type .ne. dtype_ilog) ) then + ! Only create new patches that have non-negligible amount of land + if((currentPatch%area*disturbance_rate) > nearzero ) then + + ! figure out whether the receiver patch for disturbance from this patch will be + ! primary or secondary land receiver patch is primary forest only if both the + ! donor patch is primary forest and the current disturbance type is not logging + if ( currentPatch%anthro_disturbance_label .eq. primaryforest .and. & + (i_disturbance_type .ne. dtype_ilog) ) then + + site_areadis_primary = site_areadis_primary + currentPatch%area * disturbance_rate - site_areadis_primary = site_areadis_primary + currentPatch%area * disturbance_rate + ! track disturbance rates to output to history + currentSite%disturbance_rates_primary_to_primary(i_disturbance_type) = & + currentSite%disturbance_rates_primary_to_primary(i_disturbance_type) + & + currentPatch%area * disturbance_rate * AREA_INV + else + site_areadis_secondary = site_areadis_secondary + currentPatch%area * disturbance_rate - ! track disturbance rates to output to history - currentSite%disturbance_rates_primary_to_primary(i_disturbance_type) = & - currentSite%disturbance_rates_primary_to_primary(i_disturbance_type) + & - currentPatch%area * disturbance_rate * AREA_INV - else - site_areadis_secondary = site_areadis_secondary + currentPatch%area * disturbance_rate + ! track disturbance rates to output to history + if (currentPatch%anthro_disturbance_label .eq. secondaryforest) then + currentSite%disturbance_rates_secondary_to_secondary(i_disturbance_type) = & + currentSite%disturbance_rates_secondary_to_secondary(i_disturbance_type) + & + currentPatch%area * disturbance_rate * AREA_INV + else + currentSite%disturbance_rates_primary_to_secondary(i_disturbance_type) = & + currentSite%disturbance_rates_primary_to_secondary(i_disturbance_type) + & + currentPatch%area * disturbance_rate * AREA_INV + endif - ! track disturbance rates to output to history - if (currentPatch%anthro_disturbance_label .eq. secondaryforest) then - currentSite%disturbance_rates_secondary_to_secondary(i_disturbance_type) = & - currentSite%disturbance_rates_secondary_to_secondary(i_disturbance_type) + & - currentPatch%area * disturbance_rate * AREA_INV - else - currentSite%disturbance_rates_primary_to_secondary(i_disturbance_type) = & - currentSite%disturbance_rates_primary_to_secondary(i_disturbance_type) + & - currentPatch%area * disturbance_rate * AREA_INV - endif + endif + + end if + + end if cp_nocomp_matches_1_if + currentPatch => currentPatch%older + enddo ! end loop over patches. sum area disturbed for all patches. - endif + ! It is possible that no disturbance area was generated + if ( (site_areadis_primary + site_areadis_secondary) > nearzero) then + + age = 0.0_r8 - end if + ! create two empty patches, to absorb newly disturbed primary and secondary forest area + ! first create patch to receive primary forest area + if ( site_areadis_primary .gt. nearzero ) then + allocate(new_patch_primary) - end if cp_nocomp_matches_1_if - currentPatch => currentPatch%older - enddo ! end loop over patches. sum area disturbed for all patches. - - ! It is possible that no disturbance area was generated - if ( (site_areadis_primary + site_areadis_secondary) > nearzero) then - - age = 0.0_r8 - - ! create two empty patches, to absorb newly disturbed primary and secondary forest area - ! first create patch to receive primary forest area - if ( site_areadis_primary .gt. nearzero ) then - allocate(new_patch_primary) - - call create_patch(currentSite, new_patch_primary, age, & - site_areadis_primary, primaryforest, i_nocomp_pft) - - ! Initialize the litter pools to zero, these - ! pools will be populated by looping over the existing patches - ! and transfering in mass - do el=1,num_elements - call new_patch_primary%litter(el)%InitConditions(init_leaf_fines=0._r8, & - init_root_fines=0._r8, & - init_ag_cwd=0._r8, & - init_bg_cwd=0._r8, & - init_seed=0._r8, & - init_seed_germ=0._r8) - end do - new_patch_primary%tallest => null() - new_patch_primary%shortest => null() + call create_patch(currentSite, new_patch_primary, age, & + site_areadis_primary, primaryforest, i_nocomp_pft) + + ! Initialize the litter pools to zero, these + ! pools will be populated by looping over the existing patches + ! and transfering in mass + do el=1,num_elements + call new_patch_primary%litter(el)%InitConditions(init_leaf_fines=0._r8, & + init_root_fines=0._r8, & + init_ag_cwd=0._r8, & + init_bg_cwd=0._r8, & + init_seed=0._r8, & + init_seed_germ=0._r8) + end do + new_patch_primary%tallest => null() + new_patch_primary%shortest => null() - endif + endif - ! next create patch to receive secondary forest area - if ( site_areadis_secondary .gt. nearzero) then - allocate(new_patch_secondary) - call create_patch(currentSite, new_patch_secondary, age, & - site_areadis_secondary, secondaryforest,i_nocomp_pft) - - ! Initialize the litter pools to zero, these - ! pools will be populated by looping over the existing patches - ! and transfering in mass - do el=1,num_elements - call new_patch_secondary%litter(el)%InitConditions(init_leaf_fines=0._r8, & - init_root_fines=0._r8, & - init_ag_cwd=0._r8, & - init_bg_cwd=0._r8, & - init_seed=0._r8, & - init_seed_germ=0._r8) - end do - new_patch_secondary%tallest => null() - new_patch_secondary%shortest => null() + ! next create patch to receive secondary forest area + if ( site_areadis_secondary .gt. nearzero) then + allocate(new_patch_secondary) + call create_patch(currentSite, new_patch_secondary, age, & + site_areadis_secondary, secondaryforest,i_nocomp_pft) + + ! Initialize the litter pools to zero, these + ! pools will be populated by looping over the existing patches + ! and transfering in mass + do el=1,num_elements + call new_patch_secondary%litter(el)%InitConditions(init_leaf_fines=0._r8, & + init_root_fines=0._r8, & + init_ag_cwd=0._r8, & + init_bg_cwd=0._r8, & + init_seed=0._r8, & + init_seed_germ=0._r8) + end do + new_patch_secondary%tallest => null() + new_patch_secondary%shortest => null() - endif + endif + + ! loop round all the patches that contribute surviving indivduals and litter + ! pools to the new patch. We only loop the pre-existing patches, so + ! quit the loop if the current patch is either null, or matches the + ! two new pointers. - ! loop round all the patches that contribute surviving indivduals and litter - ! pools to the new patch. We only loop the pre-existing patches, so - ! quit the loop if the current patch is either null, or matches the - ! two new pointers. + currentPatch => currentSite%oldest_patch + do while(associated(currentPatch)) - currentPatch => currentSite%oldest_patch - do while(associated(currentPatch)) + cp_nocomp_matches_2_if: if ( hlm_use_nocomp .eq. ifalse .or. & + currentPatch%nocomp_pft_label .eq. i_nocomp_pft ) then - cp_nocomp_matches_2_if: if ( hlm_use_nocomp .eq. ifalse .or. & - currentPatch%nocomp_pft_label .eq. i_nocomp_pft ) then + ! This is the amount of patch area that is disturbed, and donated by the donor + disturbance_rate = currentPatch%disturbance_rates(i_disturbance_type) + patch_site_areadis = currentPatch%area * disturbance_rate - ! This is the amount of patch area that is disturbed, and donated by the donor - disturbance_rate = currentPatch%disturbance_rates(i_disturbance_type) - patch_site_areadis = currentPatch%area * disturbance_rate + + if ( patch_site_areadis > nearzero ) then + + ! figure out whether the receiver patch for disturbance from this patch + ! will be primary or secondary land receiver patch is primary forest + ! only if both the donor patch is primary forest and the current + ! disturbance type is not logging + if (currentPatch%anthro_disturbance_label .eq. primaryforest .and. & + (i_disturbance_type .ne. dtype_ilog)) then + new_patch => new_patch_primary + else + new_patch => new_patch_secondary + endif + + if(.not.associated(new_patch))then + write(fates_log(),*) 'Patch spawning has attempted to point to' + write(fates_log(),*) 'an un-allocated patch' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + ! for the case where the donating patch is secondary forest, if + ! the current disturbance from this patch is non-anthropogenic, + ! we need to average in the time-since-anthropogenic-disturbance + ! from the donor patch into that of the receiver patch + if ( currentPatch%anthro_disturbance_label .eq. secondaryforest .and. & + (i_disturbance_type .ne. dtype_ilog) ) then + + new_patch%age_since_anthro_disturbance = new_patch%age_since_anthro_disturbance + & + currentPatch%age_since_anthro_disturbance * (patch_site_areadis / site_areadis_secondary) + endif + + + ! Transfer the litter existing already in the donor patch to the new patch + ! This call will only transfer non-burned litter to new patch + ! and burned litter to atmosphere. Thus it is important to zero burnt_frac_litter when + ! fire is not the current disturbance regime. - if ( patch_site_areadis > nearzero ) then + if(i_disturbance_type .ne. dtype_ifire) then + currentPatch%burnt_frac_litter(:) = 0._r8 + end if - ! figure out whether the receiver patch for disturbance from this patch - ! will be primary or secondary land receiver patch is primary forest - ! only if both the donor patch is primary forest and the current - ! disturbance type is not logging - if (currentPatch%anthro_disturbance_label .eq. primaryforest .and. & - (i_disturbance_type .ne. dtype_ilog)) then - new_patch => new_patch_primary - else - new_patch => new_patch_secondary - endif + call TransLitterNewPatch( currentSite, currentPatch, new_patch, patch_site_areadis) - if(.not.associated(new_patch))then - write(fates_log(),*) 'Patch spawning has attempted to point to' - write(fates_log(),*) 'an un-allocated patch' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + ! Transfer in litter fluxes from plants in various contexts of death and destruction - ! for the case where the donating patch is secondary forest, if - ! the current disturbance from this patch is non-anthropogenic, - ! we need to average in the time-since-anthropogenic-disturbance - ! from the donor patch into that of the receiver patch - if ( currentPatch%anthro_disturbance_label .eq. secondaryforest .and. & - (i_disturbance_type .ne. dtype_ilog) ) then + if(i_disturbance_type .eq. dtype_ilog) then + call logging_litter_fluxes(currentSite, currentPatch, & + new_patch, patch_site_areadis,bc_in) + elseif(i_disturbance_type .eq. dtype_ifire) then + call fire_litter_fluxes(currentSite, currentPatch, & + new_patch, patch_site_areadis,bc_in) + else + call mortality_litter_fluxes(currentSite, currentPatch, & + new_patch, patch_site_areadis,bc_in) + endif - new_patch%age_since_anthro_disturbance = new_patch%age_since_anthro_disturbance + & - currentPatch%age_since_anthro_disturbance * (patch_site_areadis / site_areadis_secondary) + ! Copy any means or timers from the original patch to the new patch + ! These values will inherit all info from the original patch + ! -------------------------------------------------------------------------- + call new_patch%tveg24%CopyFromDonor(currentPatch%tveg24) + call new_patch%tveg_lpa%CopyFromDonor(currentPatch%tveg_lpa) + + + ! -------------------------------------------------------------------------- + ! The newly formed patch from disturbance (new_patch), has now been given + ! some litter from dead plants and pre-existing litter from the donor patches. + ! + ! Next, we loop through the cohorts in the donor patch, copy them with + ! area modified number density into the new-patch, and apply survivorship. + ! ------------------------------------------------------------------------- + + currentCohort => currentPatch%shortest + do while(associated(currentCohort)) + + allocate(nc) + if(hlm_use_planthydro.eq.itrue) call InitHydrCohort(CurrentSite,nc) + + ! Initialize the PARTEH object and point to the + ! correct boundary condition fields + nc%prt => null() + call InitPRTObject(nc%prt) + call InitPRTBoundaryConditions(nc) + + ! (Keeping as an example) + ! Allocate running mean functions + !allocate(nc%tveg_lpa) + !call nc%tveg_lpa%InitRMean(ema_lpa,init_value=new_patch%tveg_lpa%GetMean()) + + call zero_cohort(nc) + + ! nc is the new cohort that goes in the disturbed patch (new_patch)... currentCohort + ! is the curent cohort that stays in the donor patch (currentPatch) + call copy_cohort(currentCohort, nc) + + !this is the case as the new patch probably doesn't have a closed canopy, and + ! even if it does, that will be sorted out in canopy_structure. + nc%canopy_layer = 1 + nc%canopy_layer_yesterday = 1._r8 + + sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) + struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) + leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) + fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) + store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) + total_c = sapw_c + struct_c + leaf_c + fnrt_c + store_c + + ! treefall mortality is the current disturbance + if(i_disturbance_type .eq. dtype_ifall) then + + if(currentCohort%canopy_layer == 1)then + + ! In the donor patch we are left with fewer trees because the area has decreased + ! the plant density for large trees does not actually decrease in the donor patch + ! because this is the part of the original patch where no trees have actually fallen + ! The diagnostic cmort,bmort,hmort, and frmort rates have already been saved + + currentCohort%n = currentCohort%n * (1.0_r8 - fates_mortality_disturbance_fraction * & + min(1.0_r8,currentCohort%dmort * hlm_freq_day)) + + nc%n = 0.0_r8 ! kill all of the trees who caused the disturbance. + + nc%cmort = nan ! The mortality diagnostics are set to nan + ! because the cohort should dissappear + nc%hmort = nan + nc%bmort = nan + nc%frmort = nan + nc%smort = nan + nc%asmort = nan + nc%lmort_direct = nan + nc%lmort_collateral = nan + nc%lmort_infra = nan + nc%l_degrad = nan + + else + ! small trees + if( int(prt_params%woody(currentCohort%pft)) == itrue)then + + + ! Survivorship of undestory woody plants. Two step process. + ! Step 1: Reduce current number of plants to reflect the + ! change in area. + ! The number density per square are doesn't change, + ! but since the patch is smaller and cohort counts + ! are absolute, reduce this number. + + nc%n = currentCohort%n * patch_site_areadis/currentPatch%area + + ! because the mortality rate due to impact for the cohorts which + ! had been in the understory and are now in the newly- + ! disturbed patch is very high, passing the imort directly to history + ! results in large numerical errors, on account of the sharply + ! reduced number densities. so instead pass this info via a + ! site-level diagnostic variable before reducing the number density. + + currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) = & + currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) + & + nc%n * ED_val_understorey_death / hlm_freq_day + + + currentSite%imort_carbonflux = currentSite%imort_carbonflux + & + (nc%n * ED_val_understorey_death / hlm_freq_day ) * & + total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 + + ! Step 2: Apply survivor ship function based on the understory death fraction + ! remaining of understory plants of those that are knocked over + ! by the overstorey trees dying... + nc%n = nc%n * (1.0_r8 - ED_val_understorey_death) + + ! since the donor patch split and sent a fraction of its members + ! to the new patch and a fraction to be preserved in itself, + ! when reporting diagnostic rates, we must carry over the mortality rates from + ! the donor that were applied before the patch split. Remember this is only + ! for diagnostics. But think of it this way, the rates are weighted by + ! number density in EDCLMLink, and the number density of this new patch is donated + ! so with the number density must come the effective mortality rates. + + nc%cmort = currentCohort%cmort + nc%hmort = currentCohort%hmort + nc%bmort = currentCohort%bmort + nc%frmort = currentCohort%frmort + nc%smort = currentCohort%smort + nc%asmort = currentCohort%asmort + nc%dmort = currentCohort%dmort + nc%lmort_direct = currentCohort%lmort_direct + nc%lmort_collateral = currentCohort%lmort_collateral + nc%lmort_infra = currentCohort%lmort_infra + + ! understory trees that might potentially be knocked over in the disturbance. + ! The existing (donor) patch should not have any impact mortality, it should + ! only lose cohorts due to the decrease in area. This is not mortality. + ! Besides, the current and newly created patch sum to unity + + currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) + + else + ! grass is not killed by mortality disturbance events. Just move it into the new patch area. + ! Just split the grass into the existing and new patch structures + nc%n = currentCohort%n * patch_site_areadis/currentPatch%area + + ! Those remaining in the existing + currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) + + nc%cmort = currentCohort%cmort + nc%hmort = currentCohort%hmort + nc%bmort = currentCohort%bmort + nc%frmort = currentCohort%frmort + nc%smort = currentCohort%smort + nc%asmort = currentCohort%asmort + nc%dmort = currentCohort%dmort + nc%lmort_direct = currentCohort%lmort_direct + nc%lmort_collateral = currentCohort%lmort_collateral + nc%lmort_infra = currentCohort%lmort_infra + endif + endif + + ! Fire is the current disturbance + elseif (i_disturbance_type .eq. dtype_ifire ) then + + ! Number of members in the new patch, before we impose fire survivorship + nc%n = currentCohort%n * patch_site_areadis/currentPatch%area + + ! loss of individuals from source patch due to area shrinking + currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) + + levcan = currentCohort%canopy_layer + + if(levcan==ican_upper) then + + ! before changing number densities, track total rate of trees that died + ! due to fire, as well as from each fire mortality term + currentSite%fmort_rate_canopy(currentCohort%size_class, currentCohort%pft) = & + currentSite%fmort_rate_canopy(currentCohort%size_class, currentCohort%pft) + & + nc%n * currentCohort%fire_mort / hlm_freq_day + + currentSite%fmort_carbonflux_canopy = currentSite%fmort_carbonflux_canopy + & + (nc%n * currentCohort%fire_mort) * & + total_c * g_per_kg * days_per_sec * ha_per_m2 + + else + currentSite%fmort_rate_ustory(currentCohort%size_class, currentCohort%pft) = & + currentSite%fmort_rate_ustory(currentCohort%size_class, currentCohort%pft) + & + nc%n * currentCohort%fire_mort / hlm_freq_day + + currentSite%fmort_carbonflux_ustory = currentSite%fmort_carbonflux_ustory + & + (nc%n * currentCohort%fire_mort) * & + total_c * g_per_kg * days_per_sec * ha_per_m2 + end if + + currentSite%fmort_rate_cambial(currentCohort%size_class, currentCohort%pft) = & + currentSite%fmort_rate_cambial(currentCohort%size_class, currentCohort%pft) + & + nc%n * currentCohort%cambial_mort / hlm_freq_day + currentSite%fmort_rate_crown(currentCohort%size_class, currentCohort%pft) = & + currentSite%fmort_rate_crown(currentCohort%size_class, currentCohort%pft) + & + nc%n * currentCohort%crownfire_mort / hlm_freq_day + + ! loss of individual from fire in new patch. + nc%n = nc%n * (1.0_r8 - currentCohort%fire_mort) + + nc%cmort = currentCohort%cmort + nc%hmort = currentCohort%hmort + nc%bmort = currentCohort%bmort + nc%frmort = currentCohort%frmort + nc%smort = currentCohort%smort + nc%asmort = currentCohort%asmort + nc%dmort = currentCohort%dmort + nc%lmort_direct = currentCohort%lmort_direct + nc%lmort_collateral = currentCohort%lmort_collateral + nc%lmort_infra = currentCohort%lmort_infra + + + ! Some of of the leaf mass from living plants has been + ! burned off. Here, we remove that mass, and + ! tally it in the flux we sent to the atmosphere + + if(int(prt_params%woody(currentCohort%pft)) == itrue)then + leaf_burn_frac = currentCohort%fraction_crown_burned + else + ! Grasses determine their fraction of leaves burned here - ! Transfer the litter existing already in the donor patch to the new patch - ! This call will only transfer non-burned litter to new patch - ! and burned litter to atmosphere. Thus it is important to zero burnt_frac_litter when - ! fire is not the current disturbance regime. - - if(i_disturbance_type .ne. dtype_ifire) then - currentPatch%burnt_frac_litter(:) = 0._r8 - end if - - call TransLitterNewPatch( currentSite, currentPatch, new_patch, patch_site_areadis) + leaf_burn_frac = currentPatch%burnt_frac_litter(lg_sf) + endif + + ! Perform a check to make sure that spitfire gave + ! us reasonable mortality and burn fraction rates + + if( (leaf_burn_frac < 0._r8) .or. & + (leaf_burn_frac > 1._r8) .or. & + (currentCohort%fire_mort < 0._r8) .or. & + (currentCohort%fire_mort > 1._r8)) then + write(fates_log(),*) 'unexpected fire fractions' + write(fates_log(),*) prt_params%woody(currentCohort%pft) + write(fates_log(),*) leaf_burn_frac + write(fates_log(),*) currentCohort%fire_mort + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + do el = 1,num_elements + + leaf_m = nc%prt%GetState(leaf_organ, element_list(el)) + + currentSite%mass_balance(el)%burn_flux_to_atm = & + currentSite%mass_balance(el)%burn_flux_to_atm + & + leaf_burn_frac * leaf_m * nc%n + end do - ! Transfer in litter fluxes from plants in various contexts of death and destruction + ! Here the mass is removed from the plant - if(i_disturbance_type .eq. dtype_ilog) then - call logging_litter_fluxes(currentSite, currentPatch, & - new_patch, patch_site_areadis,bc_in) - elseif(i_disturbance_type .eq. dtype_ifire) then - call fire_litter_fluxes(currentSite, currentPatch, & - new_patch, patch_site_areadis,bc_in) - else - call mortality_litter_fluxes(currentSite, currentPatch, & - new_patch, patch_site_areadis,bc_in) - endif + call PRTBurnLosses(nc%prt, leaf_organ, leaf_burn_frac) + currentCohort%fraction_crown_burned = 0.0_r8 + nc%fraction_crown_burned = 0.0_r8 - ! Copy any means or timers from the original patch to the new patch - ! These values will inherit all info from the original patch - ! -------------------------------------------------------------------------- - call new_patch%tveg24%CopyFromDonor(currentPatch%tveg24) - call new_patch%tveg_lpa%CopyFromDonor(currentPatch%tveg_lpa) - - ! -------------------------------------------------------------------------- - ! The newly formed patch from disturbance (new_patch), has now been given - ! some litter from dead plants and pre-existing litter from the donor patches. - ! - ! Next, we loop through the cohorts in the donor patch, copy them with - ! area modified number density into the new-patch, and apply survivorship. - ! ------------------------------------------------------------------------- - - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - - allocate(nc) - if(hlm_use_planthydro.eq.itrue) call InitHydrCohort(CurrentSite,nc) - - ! Initialize the PARTEH object and point to the - ! correct boundary condition fields - nc%prt => null() - call InitPRTObject(nc%prt) - call InitPRTBoundaryConditions(nc) - - ! (Keeping as an example) - ! Allocate running mean functions - !allocate(nc%tveg_lpa) - !call nc%tveg_lpa%InitRMean(ema_lpa,init_value=new_patch%tveg_lpa%GetMean()) - - call zero_cohort(nc) - - ! nc is the new cohort that goes in the disturbed patch (new_patch)... currentCohort - ! is the curent cohort that stays in the donor patch (currentPatch) - call copy_cohort(currentCohort, nc) - - !this is the case as the new patch probably doesn't have a closed canopy, and - ! even if it does, that will be sorted out in canopy_structure. - nc%canopy_layer = 1 - nc%canopy_layer_yesterday = 1._r8 - - sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) - struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) - leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) - fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) - store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) - total_c = sapw_c + struct_c + leaf_c + fnrt_c + store_c - - ! treefall mortality is the current disturbance - if(i_disturbance_type .eq. dtype_ifall) then - - if(currentCohort%canopy_layer == 1)then - - ! In the donor patch we are left with fewer trees because the area has decreased - ! the plant density for large trees does not actually decrease in the donor patch - ! because this is the part of the original patch where no trees have actually fallen - ! The diagnostic cmort,bmort,hmort, and frmort rates have already been saved - - currentCohort%n = currentCohort%n * (1.0_r8 - fates_mortality_disturbance_fraction * & - min(1.0_r8,currentCohort%dmort * hlm_freq_day)) - - nc%n = 0.0_r8 ! kill all of the trees who caused the disturbance. - - nc%cmort = nan ! The mortality diagnostics are set to nan - ! because the cohort should dissappear - nc%hmort = nan - nc%bmort = nan - nc%frmort = nan - nc%smort = nan - nc%asmort = nan - nc%lmort_direct = nan - nc%lmort_collateral = nan - nc%lmort_infra = nan - nc%l_degrad = nan - - else - ! small trees - if( int(prt_params%woody(currentCohort%pft)) == itrue)then - - - ! Survivorship of undestory woody plants. Two step process. - ! Step 1: Reduce current number of plants to reflect the - ! change in area. - ! The number density per square are doesn't change, - ! but since the patch is smaller and cohort counts - ! are absolute, reduce this number. - - nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - - ! because the mortality rate due to impact for the cohorts which - ! had been in the understory and are now in the newly- - ! disturbed patch is very high, passing the imort directly to history - ! results in large numerical errors, on account of the sharply - ! reduced number densities. so instead pass this info via a - ! site-level diagnostic variable before reducing the number density. - - currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) = & - currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) + & - nc%n * ED_val_understorey_death / hlm_freq_day - - - currentSite%imort_carbonflux = currentSite%imort_carbonflux + & - (nc%n * ED_val_understorey_death / hlm_freq_day ) * & - total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 - - ! Step 2: Apply survivor ship function based on the understory death fraction - ! remaining of understory plants of those that are knocked over - ! by the overstorey trees dying... - nc%n = nc%n * (1.0_r8 - ED_val_understorey_death) - - ! since the donor patch split and sent a fraction of its members - ! to the new patch and a fraction to be preserved in itself, - ! when reporting diagnostic rates, we must carry over the mortality rates from - ! the donor that were applied before the patch split. Remember this is only - ! for diagnostics. But think of it this way, the rates are weighted by - ! number density in EDCLMLink, and the number density of this new patch is donated - ! so with the number density must come the effective mortality rates. - - nc%cmort = currentCohort%cmort - nc%hmort = currentCohort%hmort - nc%bmort = currentCohort%bmort - nc%frmort = currentCohort%frmort - nc%smort = currentCohort%smort - nc%asmort = currentCohort%asmort - nc%dmort = currentCohort%dmort - nc%lmort_direct = currentCohort%lmort_direct - nc%lmort_collateral = currentCohort%lmort_collateral - nc%lmort_infra = currentCohort%lmort_infra - - ! understory trees that might potentially be knocked over in the disturbance. - ! The existing (donor) patch should not have any impact mortality, it should - ! only lose cohorts due to the decrease in area. This is not mortality. - ! Besides, the current and newly created patch sum to unity - - currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - - else - ! grass is not killed by mortality disturbance events. Just move it into the new patch area. - ! Just split the grass into the existing and new patch structures - nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - - ! Those remaining in the existing - currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - - nc%cmort = currentCohort%cmort - nc%hmort = currentCohort%hmort - nc%bmort = currentCohort%bmort - nc%frmort = currentCohort%frmort - nc%smort = currentCohort%smort - nc%asmort = currentCohort%asmort - nc%dmort = currentCohort%dmort - nc%lmort_direct = currentCohort%lmort_direct - nc%lmort_collateral = currentCohort%lmort_collateral - nc%lmort_infra = currentCohort%lmort_infra - - endif - endif - - ! Fire is the current disturbance - elseif (i_disturbance_type .eq. dtype_ifire ) then - - ! Number of members in the new patch, before we impose fire survivorship - nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - - ! loss of individuals from source patch due to area shrinking - currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - - levcan = currentCohort%canopy_layer - - if(levcan==ican_upper) then - - ! before changing number densities, track total rate of trees that died - ! due to fire, as well as from each fire mortality term - currentSite%fmort_rate_canopy(currentCohort%size_class, currentCohort%pft) = & - currentSite%fmort_rate_canopy(currentCohort%size_class, currentCohort%pft) + & - nc%n * currentCohort%fire_mort / hlm_freq_day - - currentSite%fmort_carbonflux_canopy = currentSite%fmort_carbonflux_canopy + & - (nc%n * currentCohort%fire_mort) * & - total_c * g_per_kg * days_per_sec * ha_per_m2 - - else - currentSite%fmort_rate_ustory(currentCohort%size_class, currentCohort%pft) = & - currentSite%fmort_rate_ustory(currentCohort%size_class, currentCohort%pft) + & - nc%n * currentCohort%fire_mort / hlm_freq_day - - currentSite%fmort_carbonflux_ustory = currentSite%fmort_carbonflux_ustory + & - (nc%n * currentCohort%fire_mort) * & - total_c * g_per_kg * days_per_sec * ha_per_m2 - end if - - currentSite%fmort_rate_cambial(currentCohort%size_class, currentCohort%pft) = & - currentSite%fmort_rate_cambial(currentCohort%size_class, currentCohort%pft) + & - nc%n * currentCohort%cambial_mort / hlm_freq_day - currentSite%fmort_rate_crown(currentCohort%size_class, currentCohort%pft) = & - currentSite%fmort_rate_crown(currentCohort%size_class, currentCohort%pft) + & - nc%n * currentCohort%crownfire_mort / hlm_freq_day - - ! loss of individual from fire in new patch. - nc%n = nc%n * (1.0_r8 - currentCohort%fire_mort) - - nc%cmort = currentCohort%cmort - nc%hmort = currentCohort%hmort - nc%bmort = currentCohort%bmort - nc%frmort = currentCohort%frmort - nc%smort = currentCohort%smort - nc%asmort = currentCohort%asmort - nc%dmort = currentCohort%dmort - nc%lmort_direct = currentCohort%lmort_direct - nc%lmort_collateral = currentCohort%lmort_collateral - nc%lmort_infra = currentCohort%lmort_infra - - - ! Some of of the leaf mass from living plants has been - ! burned off. Here, we remove that mass, and - ! tally it in the flux we sent to the atmosphere - - if(int(prt_params%woody(currentCohort%pft)) == itrue)then - leaf_burn_frac = currentCohort%fraction_crown_burned - else - - ! Grasses determine their fraction of leaves burned here - - leaf_burn_frac = currentPatch%burnt_frac_litter(lg_sf) - endif - - ! Perform a check to make sure that spitfire gave - ! us reasonable mortality and burn fraction rates - - if( (leaf_burn_frac < 0._r8) .or. & - (leaf_burn_frac > 1._r8) .or. & - (currentCohort%fire_mort < 0._r8) .or. & - (currentCohort%fire_mort > 1._r8)) then - write(fates_log(),*) 'unexpected fire fractions' - write(fates_log(),*) prt_params%woody(currentCohort%pft) - write(fates_log(),*) leaf_burn_frac - write(fates_log(),*) currentCohort%fire_mort - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - do el = 1,num_elements - - leaf_m = nc%prt%GetState(leaf_organ, element_list(el)) - - currentSite%mass_balance(el)%burn_flux_to_atm = & - currentSite%mass_balance(el)%burn_flux_to_atm + & - leaf_burn_frac * leaf_m * nc%n - end do - - ! Here the mass is removed from the plant - - call PRTBurnLosses(nc%prt, leaf_organ, leaf_burn_frac) - currentCohort%fraction_crown_burned = 0.0_r8 - nc%fraction_crown_burned = 0.0_r8 - - - - ! Logging is the current disturbance - elseif (i_disturbance_type .eq. dtype_ilog ) then - - ! If this cohort is in the upper canopy. It generated - if(currentCohort%canopy_layer == 1)then - - ! calculate the survivorship of disturbed trees because non-harvested - nc%n = currentCohort%n * currentCohort%l_degrad - ! nc%n = (currentCohort%l_degrad / (currentCohort%l_degrad + & - ! currentCohort%lmort_direct + currentCohort%lmort_collateral + - ! currentCohort%lmort_infra) ) * & - ! currentCohort%n * patch_site_areadis/currentPatch%area - - ! Reduce counts in the existing/donor patch according to the logging rate - currentCohort%n = currentCohort%n * & - (1.0_r8 - min(1.0_r8,(currentCohort%lmort_direct + & - currentCohort%lmort_collateral + & - currentCohort%lmort_infra + currentCohort%l_degrad))) - - nc%cmort = currentCohort%cmort - nc%hmort = currentCohort%hmort - nc%bmort = currentCohort%bmort - nc%frmort = currentCohort%frmort - nc%smort = currentCohort%smort - nc%asmort = currentCohort%asmort - nc%dmort = currentCohort%dmort - - ! since these are the ones that weren't logged, - ! set the logging mortality rates as zero - nc%lmort_direct = 0._r8 - nc%lmort_collateral = 0._r8 - nc%lmort_infra = 0._r8 - - else - - ! What to do with cohorts in the understory of a logging generated - ! disturbance patch? - - if(int(prt_params%woody(currentCohort%pft)) == itrue)then - - - ! Survivorship of undestory woody plants. Two step process. - ! Step 1: Reduce current number of plants to reflect the - ! change in area. - ! The number density per square are doesn't change, - ! but since the patch is smaller - ! and cohort counts are absolute, reduce this number. - nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - - ! because the mortality rate due to impact for the cohorts which had - ! been in the understory and are now in the newly- - ! disturbed patch is very high, passing the imort directly to - ! history results in large numerical errors, on account - ! of the sharply reduced number densities. so instead pass this info - ! via a site-level diagnostic variable before reducing - ! the number density. - currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) = & - currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) + & - nc%n * currentPatch%fract_ldist_not_harvested * & - logging_coll_under_frac / hlm_freq_day - - currentSite%imort_carbonflux = currentSite%imort_carbonflux + & - (nc%n * currentPatch%fract_ldist_not_harvested * & - logging_coll_under_frac/ hlm_freq_day ) * & - total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 - - - ! Step 2: Apply survivor ship function based on the understory death fraction - - ! remaining of understory plants of those that are knocked - ! over by the overstorey trees dying... - ! LOGGING SURVIVORSHIP OF UNDERSTORY PLANTS IS SET AS A NEW PARAMETER - ! in the fatesparameter files - nc%n = nc%n * (1.0_r8 - & - (1.0_r8-currentPatch%fract_ldist_not_harvested) * logging_coll_under_frac) - - ! Step 3: Reduce the number count of cohorts in the - ! original/donor/non-disturbed patch to reflect the area change - currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - - nc%cmort = currentCohort%cmort - nc%hmort = currentCohort%hmort - nc%bmort = currentCohort%bmort - nc%frmort = currentCohort%frmort - nc%smort = currentCohort%smort - nc%asmort = currentCohort%asmort - nc%dmort = currentCohort%dmort - nc%lmort_direct = currentCohort%lmort_direct - nc%lmort_collateral = currentCohort%lmort_collateral - nc%lmort_infra = currentCohort%lmort_infra - - else - - ! grass is not killed by mortality disturbance events. - ! Just move it into the new patch area. - ! Just split the grass into the existing and new patch structures - nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - - ! Those remaining in the existing - currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - - ! No grass impact mortality imposed on the newly created patch - nc%cmort = currentCohort%cmort - nc%hmort = currentCohort%hmort - nc%bmort = currentCohort%bmort - nc%frmort = currentCohort%frmort - nc%smort = currentCohort%smort - nc%asmort = currentCohort%asmort - nc%dmort = currentCohort%dmort - nc%lmort_direct = currentCohort%lmort_direct - nc%lmort_collateral = currentCohort%lmort_collateral - nc%lmort_infra = currentCohort%lmort_infra - - endif ! is/is-not woody - - endif ! Select canopy layer - - else - write(fates_log(),*) 'unknown disturbance mode?' - write(fates_log(),*) 'i_disturbance_type: ',i_disturbance_type - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if ! Select disturbance mode - - if (nc%n > 0.0_r8) then - storebigcohort => new_patch%tallest - storesmallcohort => new_patch%shortest - if(associated(new_patch%tallest))then - tnull = 0 - else - tnull = 1 - new_patch%tallest => nc - nc%taller => null() - endif - - if(associated(new_patch%shortest))then - snull = 0 - else - snull = 1 - new_patch%shortest => nc - nc%shorter => null() - endif - nc%patchptr => new_patch - call insert_cohort(nc, new_patch%tallest, new_patch%shortest, & - tnull, snull, storebigcohort, storesmallcohort) - - new_patch%tallest => storebigcohort - new_patch%shortest => storesmallcohort - else - - ! Get rid of the new temporary cohort - call DeallocateCohort(nc) - deallocate(nc) - - endif - - currentCohort => currentCohort%taller - enddo ! currentCohort - call sort_cohorts(currentPatch) - - !update area of donor patch - oldarea = currentPatch%area - currentPatch%area = currentPatch%area - patch_site_areadis - - ! for all disturbance rates that haven't been resolved yet, increase their amount so that - ! they are the same amount of gridcell-scale disturbance relative to the original patch size - if (i_disturbance_type .ne. N_DIST_TYPES) then - do i_dist2 = i_disturbance_type+1,N_DIST_TYPES - currentPatch%disturbance_rates(i_dist2) = currentPatch%disturbance_rates(i_dist2) & - * oldarea / currentPatch%area - end do - end if - - ! sort out the cohorts, since some of them may be so small as to need removing. - ! the first call to terminate cohorts removes sparse number densities, - ! the second call removes for all other reasons (sparse culling must happen - ! before fusion) - call terminate_cohorts(currentSite, currentPatch, 1,16,bc_in) - call fuse_cohorts(currentSite,currentPatch, bc_in) - call terminate_cohorts(currentSite, currentPatch, 2,16,bc_in) - call sort_cohorts(currentPatch) - - end if ! if ( new_patch%area > nearzero ) then - - end if cp_nocomp_matches_2_if - currentPatch => currentPatch%younger - - enddo ! currentPatch patch loop. - - !*************************/ - !** INSERT NEW PATCH(ES) INTO LINKED LIST - !*************************/ - - if ( site_areadis_primary .gt. nearzero) then - currentPatch => currentSite%youngest_patch - ! insert new youngest primary patch after all the secondary patches, if there are any. - ! this requires first finding the current youngest primary to insert the new one ahead of - if (currentPatch%anthro_disturbance_label .eq. secondaryforest ) then - found_youngest_primary = .false. - do while(associated(currentPatch) .and. .not. found_youngest_primary) - currentPatch => currentPatch%older - if (associated(currentPatch)) then - if (currentPatch%anthro_disturbance_label .eq. primaryforest) then - found_youngest_primary = .true. - endif - endif - end do - if (associated(currentPatch)) then - ! the case where we've found a youngest primary patch - new_patch_primary%older => currentPatch - new_patch_primary%younger => currentPatch%younger - currentPatch%younger%older => new_patch_primary - currentPatch%younger => new_patch_primary + ! Logging is the current disturbance + elseif (i_disturbance_type .eq. dtype_ilog ) then + + ! If this cohort is in the upper canopy. It generated + if(currentCohort%canopy_layer == 1)then + + ! calculate the survivorship of disturbed trees because non-harvested + nc%n = currentCohort%n * currentCohort%l_degrad + ! nc%n = (currentCohort%l_degrad / (currentCohort%l_degrad + & + ! currentCohort%lmort_direct + currentCohort%lmort_collateral + + ! currentCohort%lmort_infra) ) * & + ! currentCohort%n * patch_site_areadis/currentPatch%area + + ! Reduce counts in the existing/donor patch according to the logging rate + currentCohort%n = currentCohort%n * & + (1.0_r8 - min(1.0_r8,(currentCohort%lmort_direct + & + currentCohort%lmort_collateral + & + currentCohort%lmort_infra + currentCohort%l_degrad))) + + nc%cmort = currentCohort%cmort + nc%hmort = currentCohort%hmort + nc%bmort = currentCohort%bmort + nc%frmort = currentCohort%frmort + nc%smort = currentCohort%smort + nc%asmort = currentCohort%asmort + nc%dmort = currentCohort%dmort + + ! since these are the ones that weren't logged, + ! set the logging mortality rates as zero + nc%lmort_direct = 0._r8 + nc%lmort_collateral = 0._r8 + nc%lmort_infra = 0._r8 + else - ! the case where we haven't, because the patches are all secondaary, - ! and are putting a primary patch at the oldest end of the - ! linked list (not sure how this could happen, but who knows...) - new_patch_primary%older => null() - new_patch_primary%younger => currentSite%oldest_patch - currentSite%oldest_patch%older => new_patch_primary - currentSite%oldest_patch => new_patch_primary + + ! What to do with cohorts in the understory of a logging generated + ! disturbance patch? + + if(int(prt_params%woody(currentCohort%pft)) == itrue)then + + + ! Survivorship of undestory woody plants. Two step process. + ! Step 1: Reduce current number of plants to reflect the + ! change in area. + ! The number density per square are doesn't change, + ! but since the patch is smaller + ! and cohort counts are absolute, reduce this number. + nc%n = currentCohort%n * patch_site_areadis/currentPatch%area + + ! because the mortality rate due to impact for the cohorts which had + ! been in the understory and are now in the newly- + ! disturbed patch is very high, passing the imort directly to + ! history results in large numerical errors, on account + ! of the sharply reduced number densities. so instead pass this info + ! via a site-level diagnostic variable before reducing + ! the number density. + currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) = & + currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) + & + nc%n * currentPatch%fract_ldist_not_harvested * & + logging_coll_under_frac / hlm_freq_day + + currentSite%imort_carbonflux = currentSite%imort_carbonflux + & + (nc%n * currentPatch%fract_ldist_not_harvested * & + logging_coll_under_frac/ hlm_freq_day ) * & + total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 + + + ! Step 2: Apply survivor ship function based on the understory death fraction + + ! remaining of understory plants of those that are knocked + ! over by the overstorey trees dying... + ! LOGGING SURVIVORSHIP OF UNDERSTORY PLANTS IS SET AS A NEW PARAMETER + ! in the fatesparameter files + nc%n = nc%n * (1.0_r8 - & + (1.0_r8-currentPatch%fract_ldist_not_harvested) * logging_coll_under_frac) + + ! Step 3: Reduce the number count of cohorts in the + ! original/donor/non-disturbed patch to reflect the area change + currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) + + nc%cmort = currentCohort%cmort + nc%hmort = currentCohort%hmort + nc%bmort = currentCohort%bmort + nc%frmort = currentCohort%frmort + nc%smort = currentCohort%smort + nc%asmort = currentCohort%asmort + nc%dmort = currentCohort%dmort + nc%lmort_direct = currentCohort%lmort_direct + nc%lmort_collateral = currentCohort%lmort_collateral + nc%lmort_infra = currentCohort%lmort_infra + + else + + ! grass is not killed by mortality disturbance events. + ! Just move it into the new patch area. + ! Just split the grass into the existing and new patch structures + nc%n = currentCohort%n * patch_site_areadis/currentPatch%area + + ! Those remaining in the existing + currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) + + ! No grass impact mortality imposed on the newly created patch + nc%cmort = currentCohort%cmort + nc%hmort = currentCohort%hmort + nc%bmort = currentCohort%bmort + nc%frmort = currentCohort%frmort + nc%smort = currentCohort%smort + nc%asmort = currentCohort%asmort + nc%dmort = currentCohort%dmort + nc%lmort_direct = currentCohort%lmort_direct + nc%lmort_collateral = currentCohort%lmort_collateral + nc%lmort_infra = currentCohort%lmort_infra + + endif ! is/is-not woody + + endif ! Select canopy layer + + else + write(fates_log(),*) 'unknown disturbance mode?' + write(fates_log(),*) 'i_disturbance_type: ',i_disturbance_type + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if ! Select disturbance mode + + if (nc%n > 0.0_r8) then + storebigcohort => new_patch%tallest + storesmallcohort => new_patch%shortest + if(associated(new_patch%tallest))then + tnull = 0 + else + tnull = 1 + new_patch%tallest => nc + nc%taller => null() endif + + if(associated(new_patch%shortest))then + snull = 0 + else + snull = 1 + new_patch%shortest => nc + nc%shorter => null() + endif + nc%patchptr => new_patch + call insert_cohort(nc, new_patch%tallest, new_patch%shortest, & + tnull, snull, storebigcohort, storesmallcohort) + + new_patch%tallest => storebigcohort + new_patch%shortest => storesmallcohort else - ! the case where there are no secondary patches at the start of the linked list (prior logic) - new_patch_primary%older => currentPatch - new_patch_primary%younger => null() - currentPatch%younger => new_patch_primary - currentSite%youngest_patch => new_patch_primary + + ! Get rid of the new temporary cohort + call DeallocateCohort(nc) + deallocate(nc) + endif - endif - - ! insert first secondary at the start of the list - if ( site_areadis_secondary .gt. nearzero) then - currentPatch => currentSite%youngest_patch - new_patch_secondary%older => currentPatch - new_patch_secondary%younger=> null() - currentPatch%younger => new_patch_secondary - currentSite%youngest_patch => new_patch_secondary - endif - + + currentCohort => currentCohort%taller + enddo ! currentCohort + call sort_cohorts(currentPatch) + + !update area of donor patch + oldarea = currentPatch%area + currentPatch%area = currentPatch%area - patch_site_areadis + + ! for all disturbance rates that haven't been resolved yet, increase their amount so that + ! they are the same amount of gridcell-scale disturbance relative to the original patch size + if (i_disturbance_type .ne. N_DIST_TYPES) then + do i_dist2 = i_disturbance_type+1,N_DIST_TYPES + currentPatch%disturbance_rates(i_dist2) = currentPatch%disturbance_rates(i_dist2) & + * oldarea / currentPatch%area + end do + end if - ! sort out the cohorts, since some of them may be so small as to need removing. + ! sort out the cohorts, since some of them may be so small as to need removing. ! the first call to terminate cohorts removes sparse number densities, ! the second call removes for all other reasons (sparse culling must happen ! before fusion) + call terminate_cohorts(currentSite, currentPatch, 1,16,bc_in) + call fuse_cohorts(currentSite,currentPatch, bc_in) + call terminate_cohorts(currentSite, currentPatch, 2,16,bc_in) + call sort_cohorts(currentPatch) - if ( site_areadis_primary .gt. nearzero) then - call terminate_cohorts(currentSite, new_patch_primary, 1,17, bc_in) - call fuse_cohorts(currentSite,new_patch_primary, bc_in) - call terminate_cohorts(currentSite, new_patch_primary, 2,17, bc_in) - call sort_cohorts(new_patch_primary) - endif + end if ! if ( new_patch%area > nearzero ) then + + end if cp_nocomp_matches_2_if + currentPatch => currentPatch%younger + + enddo ! currentPatch patch loop. - if ( site_areadis_secondary .gt. nearzero) then - call terminate_cohorts(currentSite, new_patch_secondary, 1,18,bc_in) - call fuse_cohorts(currentSite,new_patch_secondary, bc_in) - call terminate_cohorts(currentSite, new_patch_secondary, 2,18,bc_in) - call sort_cohorts(new_patch_secondary) + !*************************/ + !** INSERT NEW PATCH(ES) INTO LINKED LIST + !*************************/ + + if ( site_areadis_primary .gt. nearzero) then + currentPatch => currentSite%youngest_patch + ! insert new youngest primary patch after all the secondary patches, if there are any. + ! this requires first finding the current youngest primary to insert the new one ahead of + if (currentPatch%anthro_disturbance_label .eq. secondaryforest ) then + found_youngest_primary = .false. + do while(associated(currentPatch) .and. .not. found_youngest_primary) + currentPatch => currentPatch%older + if (associated(currentPatch)) then + if (currentPatch%anthro_disturbance_label .eq. primaryforest) then + found_youngest_primary = .true. + endif + endif + end do + if (associated(currentPatch)) then + ! the case where we've found a youngest primary patch + new_patch_primary%older => currentPatch + new_patch_primary%younger => currentPatch%younger + currentPatch%younger%older => new_patch_primary + currentPatch%younger => new_patch_primary + else + ! the case where we haven't, because the patches are all secondaary, + ! and are putting a primary patch at the oldest end of the + ! linked list (not sure how this could happen, but who knows...) + new_patch_primary%older => null() + new_patch_primary%younger => currentSite%oldest_patch + currentSite%oldest_patch%older => new_patch_primary + currentSite%oldest_patch => new_patch_primary endif - - endif !end new_patch area - - - call check_patch_area(currentSite) - call set_patchno(currentSite) - - end do disturbance_type_loop + else + ! the case where there are no secondary patches at the start of the linked list (prior logic) + new_patch_primary%older => currentPatch + new_patch_primary%younger => null() + currentPatch%younger => new_patch_primary + currentSite%youngest_patch => new_patch_primary + endif + endif + + ! insert first secondary at the start of the list + if ( site_areadis_secondary .gt. nearzero) then + currentPatch => currentSite%youngest_patch + new_patch_secondary%older => currentPatch + new_patch_secondary%younger=> null() + currentPatch%younger => new_patch_secondary + currentSite%youngest_patch => new_patch_secondary + endif + + + ! sort out the cohorts, since some of them may be so small as to need removing. + ! the first call to terminate cohorts removes sparse number densities, + ! the second call removes for all other reasons (sparse culling must happen + ! before fusion) + + if ( site_areadis_primary .gt. nearzero) then + call terminate_cohorts(currentSite, new_patch_primary, 1,17, bc_in) + call fuse_cohorts(currentSite,new_patch_primary, bc_in) + call terminate_cohorts(currentSite, new_patch_primary, 2,17, bc_in) + call sort_cohorts(new_patch_primary) + endif + + if ( site_areadis_secondary .gt. nearzero) then + call terminate_cohorts(currentSite, new_patch_secondary, 1,18,bc_in) + call fuse_cohorts(currentSite,new_patch_secondary, bc_in) + call terminate_cohorts(currentSite, new_patch_secondary, 2,18,bc_in) + call sort_cohorts(new_patch_secondary) + endif + + endif !end new_patch area + + + call check_patch_area(currentSite) + call set_patchno(currentSite) + + end do disturbance_type_loop end do nocomp_pft_loop From bd994a1c548d9c13e1bcc9a40657de2f670515c4 Mon Sep 17 00:00:00 2001 From: ckoven Date: Thu, 23 Jun 2022 15:09:28 -0600 Subject: [PATCH 255/852] re-auto-indented spawn_patches (after merging main branch) --- biogeochem/EDPatchDynamicsMod.F90 | 1334 ++++++++++++++--------------- 1 file changed, 667 insertions(+), 667 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 584494de8b..d837ed737a 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -437,721 +437,721 @@ subroutine spawn_patches( currentSite, bc_in) ! in the nocomp cases, since every patch has a PFT identity, it can only receive patch area from patches ! that have the same identity. In order to allow this, we have this very high level loop over nocomp PFTs - ! and only do the disturbance for any patches that have that nocomp PFT identity. + ! and only do the disturbance for any patches that have that nocomp PFT identity. ! If nocomp is not enabled, then this is not much of a loop, it only passes through once. nocomp_pft_loop: do i_nocomp_pft = min_nocomp_pft,max_nocomp_pft - disturbance_type_loop: do i_disturbance_type = 1,N_DIST_TYPES + disturbance_type_loop: do i_disturbance_type = 1,N_DIST_TYPES - ! calculate area of disturbed land, in this timestep, by summing contributions from each existing patch. - currentPatch => currentSite%youngest_patch + ! calculate area of disturbed land, in this timestep, by summing contributions from each existing patch. + currentPatch => currentSite%youngest_patch - site_areadis_primary = 0.0_r8 - site_areadis_secondary = 0.0_r8 + site_areadis_primary = 0.0_r8 + site_areadis_secondary = 0.0_r8 - do while(associated(currentPatch)) + do while(associated(currentPatch)) - cp_nocomp_matches_1_if: if ( hlm_use_nocomp .eq. ifalse .or. & - currentPatch%nocomp_pft_label .eq. i_nocomp_pft ) then - - disturbance_rate = currentPatch%disturbance_rates(i_disturbance_type) + cp_nocomp_matches_1_if: if ( hlm_use_nocomp .eq. ifalse .or. & + currentPatch%nocomp_pft_label .eq. i_nocomp_pft ) then - if(disturbance_rate > (1.0_r8 + rsnbl_math_prec)) then - write(fates_log(),*) 'patch disturbance rate > 1 ?',disturbance_rate - call dump_patch(currentPatch) - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + disturbance_rate = currentPatch%disturbance_rates(i_disturbance_type) - ! Only create new patches that have non-negligible amount of land - if((currentPatch%area*disturbance_rate) > nearzero ) then - - ! figure out whether the receiver patch for disturbance from this patch will be - ! primary or secondary land receiver patch is primary forest only if both the - ! donor patch is primary forest and the current disturbance type is not logging - if ( currentPatch%anthro_disturbance_label .eq. primaryforest .and. & - (i_disturbance_type .ne. dtype_ilog) ) then - - site_areadis_primary = site_areadis_primary + currentPatch%area * disturbance_rate + if(disturbance_rate > (1.0_r8 + rsnbl_math_prec)) then + write(fates_log(),*) 'patch disturbance rate > 1 ?',disturbance_rate + call dump_patch(currentPatch) + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if - ! track disturbance rates to output to history - currentSite%disturbance_rates_primary_to_primary(i_disturbance_type) = & - currentSite%disturbance_rates_primary_to_primary(i_disturbance_type) + & - currentPatch%area * disturbance_rate * AREA_INV - else - site_areadis_secondary = site_areadis_secondary + currentPatch%area * disturbance_rate + ! Only create new patches that have non-negligible amount of land + if((currentPatch%area*disturbance_rate) > nearzero ) then - ! track disturbance rates to output to history - if (currentPatch%anthro_disturbance_label .eq. secondaryforest) then - currentSite%disturbance_rates_secondary_to_secondary(i_disturbance_type) = & - currentSite%disturbance_rates_secondary_to_secondary(i_disturbance_type) + & - currentPatch%area * disturbance_rate * AREA_INV - else - currentSite%disturbance_rates_primary_to_secondary(i_disturbance_type) = & - currentSite%disturbance_rates_primary_to_secondary(i_disturbance_type) + & - currentPatch%area * disturbance_rate * AREA_INV - endif + ! figure out whether the receiver patch for disturbance from this patch will be + ! primary or secondary land receiver patch is primary forest only if both the + ! donor patch is primary forest and the current disturbance type is not logging + if ( currentPatch%anthro_disturbance_label .eq. primaryforest .and. & + (i_disturbance_type .ne. dtype_ilog) ) then - endif - - end if - - end if cp_nocomp_matches_1_if - currentPatch => currentPatch%older - enddo ! end loop over patches. sum area disturbed for all patches. + site_areadis_primary = site_areadis_primary + currentPatch%area * disturbance_rate - ! It is possible that no disturbance area was generated - if ( (site_areadis_primary + site_areadis_secondary) > nearzero) then - - age = 0.0_r8 + ! track disturbance rates to output to history + currentSite%disturbance_rates_primary_to_primary(i_disturbance_type) = & + currentSite%disturbance_rates_primary_to_primary(i_disturbance_type) + & + currentPatch%area * disturbance_rate * AREA_INV + else + site_areadis_secondary = site_areadis_secondary + currentPatch%area * disturbance_rate - ! create two empty patches, to absorb newly disturbed primary and secondary forest area - ! first create patch to receive primary forest area - if ( site_areadis_primary .gt. nearzero ) then - allocate(new_patch_primary) + ! track disturbance rates to output to history + if (currentPatch%anthro_disturbance_label .eq. secondaryforest) then + currentSite%disturbance_rates_secondary_to_secondary(i_disturbance_type) = & + currentSite%disturbance_rates_secondary_to_secondary(i_disturbance_type) + & + currentPatch%area * disturbance_rate * AREA_INV + else + currentSite%disturbance_rates_primary_to_secondary(i_disturbance_type) = & + currentSite%disturbance_rates_primary_to_secondary(i_disturbance_type) + & + currentPatch%area * disturbance_rate * AREA_INV + endif - call create_patch(currentSite, new_patch_primary, age, & - site_areadis_primary, primaryforest, i_nocomp_pft) - - ! Initialize the litter pools to zero, these - ! pools will be populated by looping over the existing patches - ! and transfering in mass - do el=1,num_elements - call new_patch_primary%litter(el)%InitConditions(init_leaf_fines=0._r8, & - init_root_fines=0._r8, & - init_ag_cwd=0._r8, & - init_bg_cwd=0._r8, & - init_seed=0._r8, & - init_seed_germ=0._r8) - end do - new_patch_primary%tallest => null() - new_patch_primary%shortest => null() + endif - endif + end if - ! next create patch to receive secondary forest area - if ( site_areadis_secondary .gt. nearzero) then - allocate(new_patch_secondary) - call create_patch(currentSite, new_patch_secondary, age, & - site_areadis_secondary, secondaryforest,i_nocomp_pft) - - ! Initialize the litter pools to zero, these - ! pools will be populated by looping over the existing patches - ! and transfering in mass - do el=1,num_elements - call new_patch_secondary%litter(el)%InitConditions(init_leaf_fines=0._r8, & - init_root_fines=0._r8, & - init_ag_cwd=0._r8, & - init_bg_cwd=0._r8, & - init_seed=0._r8, & - init_seed_germ=0._r8) - end do - new_patch_secondary%tallest => null() - new_patch_secondary%shortest => null() + end if cp_nocomp_matches_1_if + currentPatch => currentPatch%older + enddo ! end loop over patches. sum area disturbed for all patches. + + ! It is possible that no disturbance area was generated + if ( (site_areadis_primary + site_areadis_secondary) > nearzero) then + + age = 0.0_r8 + + ! create two empty patches, to absorb newly disturbed primary and secondary forest area + ! first create patch to receive primary forest area + if ( site_areadis_primary .gt. nearzero ) then + allocate(new_patch_primary) + + call create_patch(currentSite, new_patch_primary, age, & + site_areadis_primary, primaryforest, i_nocomp_pft) + + ! Initialize the litter pools to zero, these + ! pools will be populated by looping over the existing patches + ! and transfering in mass + do el=1,num_elements + call new_patch_primary%litter(el)%InitConditions(init_leaf_fines=0._r8, & + init_root_fines=0._r8, & + init_ag_cwd=0._r8, & + init_bg_cwd=0._r8, & + init_seed=0._r8, & + init_seed_germ=0._r8) + end do + new_patch_primary%tallest => null() + new_patch_primary%shortest => null() - endif - - ! loop round all the patches that contribute surviving indivduals and litter - ! pools to the new patch. We only loop the pre-existing patches, so - ! quit the loop if the current patch is either null, or matches the - ! two new pointers. + endif - currentPatch => currentSite%oldest_patch - do while(associated(currentPatch)) + ! next create patch to receive secondary forest area + if ( site_areadis_secondary .gt. nearzero) then + allocate(new_patch_secondary) + call create_patch(currentSite, new_patch_secondary, age, & + site_areadis_secondary, secondaryforest,i_nocomp_pft) + + ! Initialize the litter pools to zero, these + ! pools will be populated by looping over the existing patches + ! and transfering in mass + do el=1,num_elements + call new_patch_secondary%litter(el)%InitConditions(init_leaf_fines=0._r8, & + init_root_fines=0._r8, & + init_ag_cwd=0._r8, & + init_bg_cwd=0._r8, & + init_seed=0._r8, & + init_seed_germ=0._r8) + end do + new_patch_secondary%tallest => null() + new_patch_secondary%shortest => null() - cp_nocomp_matches_2_if: if ( hlm_use_nocomp .eq. ifalse .or. & - currentPatch%nocomp_pft_label .eq. i_nocomp_pft ) then + endif - ! This is the amount of patch area that is disturbed, and donated by the donor - disturbance_rate = currentPatch%disturbance_rates(i_disturbance_type) - patch_site_areadis = currentPatch%area * disturbance_rate + ! loop round all the patches that contribute surviving indivduals and litter + ! pools to the new patch. We only loop the pre-existing patches, so + ! quit the loop if the current patch is either null, or matches the + ! two new pointers. - - if ( patch_site_areadis > nearzero ) then - - ! figure out whether the receiver patch for disturbance from this patch - ! will be primary or secondary land receiver patch is primary forest - ! only if both the donor patch is primary forest and the current - ! disturbance type is not logging - if (currentPatch%anthro_disturbance_label .eq. primaryforest .and. & - (i_disturbance_type .ne. dtype_ilog)) then - new_patch => new_patch_primary - else - new_patch => new_patch_secondary - endif - - if(.not.associated(new_patch))then - write(fates_log(),*) 'Patch spawning has attempted to point to' - write(fates_log(),*) 'an un-allocated patch' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - ! for the case where the donating patch is secondary forest, if - ! the current disturbance from this patch is non-anthropogenic, - ! we need to average in the time-since-anthropogenic-disturbance - ! from the donor patch into that of the receiver patch - if ( currentPatch%anthro_disturbance_label .eq. secondaryforest .and. & - (i_disturbance_type .ne. dtype_ilog) ) then - - new_patch%age_since_anthro_disturbance = new_patch%age_since_anthro_disturbance + & - currentPatch%age_since_anthro_disturbance * (patch_site_areadis / site_areadis_secondary) + currentPatch => currentSite%oldest_patch + do while(associated(currentPatch)) - endif - - - ! Transfer the litter existing already in the donor patch to the new patch - ! This call will only transfer non-burned litter to new patch - ! and burned litter to atmosphere. Thus it is important to zero burnt_frac_litter when - ! fire is not the current disturbance regime. + cp_nocomp_matches_2_if: if ( hlm_use_nocomp .eq. ifalse .or. & + currentPatch%nocomp_pft_label .eq. i_nocomp_pft ) then - if(i_disturbance_type .ne. dtype_ifire) then - currentPatch%burnt_frac_litter(:) = 0._r8 - end if + ! This is the amount of patch area that is disturbed, and donated by the donor + disturbance_rate = currentPatch%disturbance_rates(i_disturbance_type) + patch_site_areadis = currentPatch%area * disturbance_rate - call TransLitterNewPatch( currentSite, currentPatch, new_patch, patch_site_areadis) - ! Transfer in litter fluxes from plants in various contexts of death and destruction + if ( patch_site_areadis > nearzero ) then - if(i_disturbance_type .eq. dtype_ilog) then - call logging_litter_fluxes(currentSite, currentPatch, & - new_patch, patch_site_areadis,bc_in) - elseif(i_disturbance_type .eq. dtype_ifire) then - call fire_litter_fluxes(currentSite, currentPatch, & - new_patch, patch_site_areadis,bc_in) - else - call mortality_litter_fluxes(currentSite, currentPatch, & - new_patch, patch_site_areadis,bc_in) - endif + ! figure out whether the receiver patch for disturbance from this patch + ! will be primary or secondary land receiver patch is primary forest + ! only if both the donor patch is primary forest and the current + ! disturbance type is not logging + if (currentPatch%anthro_disturbance_label .eq. primaryforest .and. & + (i_disturbance_type .ne. dtype_ilog)) then + new_patch => new_patch_primary + else + new_patch => new_patch_secondary + endif + if(.not.associated(new_patch))then + write(fates_log(),*) 'Patch spawning has attempted to point to' + write(fates_log(),*) 'an un-allocated patch' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if - ! Copy any means or timers from the original patch to the new patch - ! These values will inherit all info from the original patch - ! -------------------------------------------------------------------------- - call new_patch%tveg24%CopyFromDonor(currentPatch%tveg24) - call new_patch%tveg_lpa%CopyFromDonor(currentPatch%tveg_lpa) - - - ! -------------------------------------------------------------------------- - ! The newly formed patch from disturbance (new_patch), has now been given - ! some litter from dead plants and pre-existing litter from the donor patches. - ! - ! Next, we loop through the cohorts in the donor patch, copy them with - ! area modified number density into the new-patch, and apply survivorship. - ! ------------------------------------------------------------------------- - - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - - allocate(nc) - if(hlm_use_planthydro.eq.itrue) call InitHydrCohort(CurrentSite,nc) - - ! Initialize the PARTEH object and point to the - ! correct boundary condition fields - nc%prt => null() - call InitPRTObject(nc%prt) - call InitPRTBoundaryConditions(nc) - - ! (Keeping as an example) - ! Allocate running mean functions - !allocate(nc%tveg_lpa) - !call nc%tveg_lpa%InitRMean(ema_lpa,init_value=new_patch%tveg_lpa%GetMean()) - - call zero_cohort(nc) - - ! nc is the new cohort that goes in the disturbed patch (new_patch)... currentCohort - ! is the curent cohort that stays in the donor patch (currentPatch) - call copy_cohort(currentCohort, nc) - - !this is the case as the new patch probably doesn't have a closed canopy, and - ! even if it does, that will be sorted out in canopy_structure. - nc%canopy_layer = 1 - nc%canopy_layer_yesterday = 1._r8 - - sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) - struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) - leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) - fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) - store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) - total_c = sapw_c + struct_c + leaf_c + fnrt_c + store_c - - ! treefall mortality is the current disturbance - if(i_disturbance_type .eq. dtype_ifall) then - - if(currentCohort%canopy_layer == 1)then - - ! In the donor patch we are left with fewer trees because the area has decreased - ! the plant density for large trees does not actually decrease in the donor patch - ! because this is the part of the original patch where no trees have actually fallen - ! The diagnostic cmort,bmort,hmort, and frmort rates have already been saved - - currentCohort%n = currentCohort%n * (1.0_r8 - fates_mortality_disturbance_fraction * & - min(1.0_r8,currentCohort%dmort * hlm_freq_day)) - - nc%n = 0.0_r8 ! kill all of the trees who caused the disturbance. - - nc%cmort = nan ! The mortality diagnostics are set to nan - ! because the cohort should dissappear - nc%hmort = nan - nc%bmort = nan - nc%frmort = nan - nc%smort = nan - nc%asmort = nan - nc%lmort_direct = nan - nc%lmort_collateral = nan - nc%lmort_infra = nan - nc%l_degrad = nan - - else - ! small trees - if( prt_params%woody(currentCohort%pft) == itrue)then - - - ! Survivorship of undestory woody plants. Two step process. - ! Step 1: Reduce current number of plants to reflect the - ! change in area. - ! The number density per square are doesn't change, - ! but since the patch is smaller and cohort counts - ! are absolute, reduce this number. - - nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - - ! because the mortality rate due to impact for the cohorts which - ! had been in the understory and are now in the newly- - ! disturbed patch is very high, passing the imort directly to history - ! results in large numerical errors, on account of the sharply - ! reduced number densities. so instead pass this info via a - ! site-level diagnostic variable before reducing the number density. - - currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) = & - currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) + & - nc%n * ED_val_understorey_death / hlm_freq_day - - - currentSite%imort_carbonflux(currentCohort%pft) = & - currentSite%imort_carbonflux(currentCohort%pft) + & - (nc%n * ED_val_understorey_death / hlm_freq_day ) * & - total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 - - ! Step 2: Apply survivor ship function based on the understory death fraction - ! remaining of understory plants of those that are knocked over - ! by the overstorey trees dying... - nc%n = nc%n * (1.0_r8 - ED_val_understorey_death) - - ! since the donor patch split and sent a fraction of its members - ! to the new patch and a fraction to be preserved in itself, - ! when reporting diagnostic rates, we must carry over the mortality rates from - ! the donor that were applied before the patch split. Remember this is only - ! for diagnostics. But think of it this way, the rates are weighted by - ! number density in EDCLMLink, and the number density of this new patch is donated - ! so with the number density must come the effective mortality rates. - - nc%cmort = currentCohort%cmort - nc%hmort = currentCohort%hmort - nc%bmort = currentCohort%bmort - nc%frmort = currentCohort%frmort - nc%smort = currentCohort%smort - nc%asmort = currentCohort%asmort - nc%dmort = currentCohort%dmort - nc%lmort_direct = currentCohort%lmort_direct - nc%lmort_collateral = currentCohort%lmort_collateral - nc%lmort_infra = currentCohort%lmort_infra - - ! understory trees that might potentially be knocked over in the disturbance. - ! The existing (donor) patch should not have any impact mortality, it should - ! only lose cohorts due to the decrease in area. This is not mortality. - ! Besides, the current and newly created patch sum to unity - - currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - - else - ! grass is not killed by mortality disturbance events. Just move it into the new patch area. - ! Just split the grass into the existing and new patch structures - nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - - ! Those remaining in the existing - currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - - nc%cmort = currentCohort%cmort - nc%hmort = currentCohort%hmort - nc%bmort = currentCohort%bmort - nc%frmort = currentCohort%frmort - nc%smort = currentCohort%smort - nc%asmort = currentCohort%asmort - nc%dmort = currentCohort%dmort - nc%lmort_direct = currentCohort%lmort_direct - nc%lmort_collateral = currentCohort%lmort_collateral - nc%lmort_infra = currentCohort%lmort_infra - - endif - endif - - ! Fire is the current disturbance - elseif (i_disturbance_type .eq. dtype_ifire ) then - - ! Number of members in the new patch, before we impose fire survivorship - nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - - ! loss of individuals from source patch due to area shrinking - currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - - levcan = currentCohort%canopy_layer - - if(levcan==ican_upper) then - - ! before changing number densities, track total rate of trees that died - ! due to fire, as well as from each fire mortality term - currentSite%fmort_rate_canopy(currentCohort%size_class, currentCohort%pft) = & - currentSite%fmort_rate_canopy(currentCohort%size_class, currentCohort%pft) + & - nc%n * currentCohort%fire_mort / hlm_freq_day - - currentSite%fmort_carbonflux_canopy(currentCohort%pft) = & - currentSite%fmort_carbonflux_canopy(currentCohort%pft) + & - (nc%n * currentCohort%fire_mort) * & - total_c * g_per_kg * days_per_sec * ha_per_m2 - - else - currentSite%fmort_rate_ustory(currentCohort%size_class, currentCohort%pft) = & - currentSite%fmort_rate_ustory(currentCohort%size_class, currentCohort%pft) + & - nc%n * currentCohort%fire_mort / hlm_freq_day - - currentSite%fmort_carbonflux_ustory(currentCohort%pft) = & - currentSite%fmort_carbonflux_ustory(currentCohort%pft) + & - (nc%n * currentCohort%fire_mort) * & - total_c * g_per_kg * days_per_sec * ha_per_m2 - end if - - currentSite%fmort_rate_cambial(currentCohort%size_class, currentCohort%pft) = & - currentSite%fmort_rate_cambial(currentCohort%size_class, currentCohort%pft) + & - nc%n * currentCohort%cambial_mort / hlm_freq_day - currentSite%fmort_rate_crown(currentCohort%size_class, currentCohort%pft) = & - currentSite%fmort_rate_crown(currentCohort%size_class, currentCohort%pft) + & - nc%n * currentCohort%crownfire_mort / hlm_freq_day - - ! loss of individual from fire in new patch. - nc%n = nc%n * (1.0_r8 - currentCohort%fire_mort) - - nc%cmort = currentCohort%cmort - nc%hmort = currentCohort%hmort - nc%bmort = currentCohort%bmort - nc%frmort = currentCohort%frmort - nc%smort = currentCohort%smort - nc%asmort = currentCohort%asmort - nc%dmort = currentCohort%dmort - nc%lmort_direct = currentCohort%lmort_direct - nc%lmort_collateral = currentCohort%lmort_collateral - nc%lmort_infra = currentCohort%lmort_infra - - - ! Some of of the leaf mass from living plants has been - ! burned off. Here, we remove that mass, and - ! tally it in the flux we sent to the atmosphere - - if(prt_params%woody(currentCohort%pft) == itrue)then - leaf_burn_frac = currentCohort%fraction_crown_burned - else + ! for the case where the donating patch is secondary forest, if + ! the current disturbance from this patch is non-anthropogenic, + ! we need to average in the time-since-anthropogenic-disturbance + ! from the donor patch into that of the receiver patch + if ( currentPatch%anthro_disturbance_label .eq. secondaryforest .and. & + (i_disturbance_type .ne. dtype_ilog) ) then - ! Grasses determine their fraction of leaves burned here + new_patch%age_since_anthro_disturbance = new_patch%age_since_anthro_disturbance + & + currentPatch%age_since_anthro_disturbance * (patch_site_areadis / site_areadis_secondary) - leaf_burn_frac = currentPatch%burnt_frac_litter(lg_sf) - endif - - ! Perform a check to make sure that spitfire gave - ! us reasonable mortality and burn fraction rates - - if( (leaf_burn_frac < 0._r8) .or. & - (leaf_burn_frac > 1._r8) .or. & - (currentCohort%fire_mort < 0._r8) .or. & - (currentCohort%fire_mort > 1._r8)) then - write(fates_log(),*) 'unexpected fire fractions' - write(fates_log(),*) prt_params%woody(currentCohort%pft) - write(fates_log(),*) leaf_burn_frac - write(fates_log(),*) currentCohort%fire_mort - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - do el = 1,num_elements - - leaf_m = nc%prt%GetState(leaf_organ, element_list(el)) - - currentSite%mass_balance(el)%burn_flux_to_atm = & - currentSite%mass_balance(el)%burn_flux_to_atm + & - leaf_burn_frac * leaf_m * nc%n - end do + endif - ! Here the mass is removed from the plant - call PRTBurnLosses(nc%prt, leaf_organ, leaf_burn_frac) - currentCohort%fraction_crown_burned = 0.0_r8 - nc%fraction_crown_burned = 0.0_r8 + ! Transfer the litter existing already in the donor patch to the new patch + ! This call will only transfer non-burned litter to new patch + ! and burned litter to atmosphere. Thus it is important to zero burnt_frac_litter when + ! fire is not the current disturbance regime. + if(i_disturbance_type .ne. dtype_ifire) then + currentPatch%burnt_frac_litter(:) = 0._r8 + end if + call TransLitterNewPatch( currentSite, currentPatch, new_patch, patch_site_areadis) - ! Logging is the current disturbance - elseif (i_disturbance_type .eq. dtype_ilog ) then - - ! If this cohort is in the upper canopy. It generated - if(currentCohort%canopy_layer == 1)then - - ! calculate the survivorship of disturbed trees because non-harvested - nc%n = currentCohort%n * currentCohort%l_degrad - ! nc%n = (currentCohort%l_degrad / (currentCohort%l_degrad + & - ! currentCohort%lmort_direct + currentCohort%lmort_collateral + - ! currentCohort%lmort_infra) ) * & - ! currentCohort%n * patch_site_areadis/currentPatch%area - - ! Reduce counts in the existing/donor patch according to the logging rate - currentCohort%n = currentCohort%n * & - (1.0_r8 - min(1.0_r8,(currentCohort%lmort_direct + & - currentCohort%lmort_collateral + & - currentCohort%lmort_infra + currentCohort%l_degrad))) - - nc%cmort = currentCohort%cmort - nc%hmort = currentCohort%hmort - nc%bmort = currentCohort%bmort - nc%frmort = currentCohort%frmort - nc%smort = currentCohort%smort - nc%asmort = currentCohort%asmort - nc%dmort = currentCohort%dmort - - ! since these are the ones that weren't logged, - ! set the logging mortality rates as zero - nc%lmort_direct = 0._r8 - nc%lmort_collateral = 0._r8 - nc%lmort_infra = 0._r8 - - else - - ! What to do with cohorts in the understory of a logging generated - ! disturbance patch? - - if(prt_params%woody(currentCohort%pft) == itrue)then - - - ! Survivorship of undestory woody plants. Two step process. - ! Step 1: Reduce current number of plants to reflect the - ! change in area. - ! The number density per square are doesn't change, - ! but since the patch is smaller - ! and cohort counts are absolute, reduce this number. - nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - - ! because the mortality rate due to impact for the cohorts which had - ! been in the understory and are now in the newly- - ! disturbed patch is very high, passing the imort directly to - ! history results in large numerical errors, on account - ! of the sharply reduced number densities. so instead pass this info - ! via a site-level diagnostic variable before reducing - ! the number density. - currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) = & - currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) + & - nc%n * currentPatch%fract_ldist_not_harvested * & - logging_coll_under_frac / hlm_freq_day - - currentSite%imort_carbonflux(currentCohort%pft) = & - currentSite%imort_carbonflux(currentCohort%pft) + & - (nc%n * currentPatch%fract_ldist_not_harvested * & - logging_coll_under_frac/ hlm_freq_day ) * & - total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 - - - ! Step 2: Apply survivor ship function based on the understory death fraction - - ! remaining of understory plants of those that are knocked - ! over by the overstorey trees dying... - ! LOGGING SURVIVORSHIP OF UNDERSTORY PLANTS IS SET AS A NEW PARAMETER - ! in the fatesparameter files - nc%n = nc%n * (1.0_r8 - & - (1.0_r8-currentPatch%fract_ldist_not_harvested) * logging_coll_under_frac) - - ! Step 3: Reduce the number count of cohorts in the - ! original/donor/non-disturbed patch to reflect the area change - currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - - nc%cmort = currentCohort%cmort - nc%hmort = currentCohort%hmort - nc%bmort = currentCohort%bmort - nc%frmort = currentCohort%frmort - nc%smort = currentCohort%smort - nc%asmort = currentCohort%asmort - nc%dmort = currentCohort%dmort - nc%lmort_direct = currentCohort%lmort_direct - nc%lmort_collateral = currentCohort%lmort_collateral - nc%lmort_infra = currentCohort%lmort_infra - + ! Transfer in litter fluxes from plants in various contexts of death and destruction + + if(i_disturbance_type .eq. dtype_ilog) then + call logging_litter_fluxes(currentSite, currentPatch, & + new_patch, patch_site_areadis,bc_in) + elseif(i_disturbance_type .eq. dtype_ifire) then + call fire_litter_fluxes(currentSite, currentPatch, & + new_patch, patch_site_areadis,bc_in) else - - ! grass is not killed by mortality disturbance events. - ! Just move it into the new patch area. - ! Just split the grass into the existing and new patch structures - nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - - ! Those remaining in the existing - currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - - ! No grass impact mortality imposed on the newly created patch - nc%cmort = currentCohort%cmort - nc%hmort = currentCohort%hmort - nc%bmort = currentCohort%bmort - nc%frmort = currentCohort%frmort - nc%smort = currentCohort%smort - nc%asmort = currentCohort%asmort - nc%dmort = currentCohort%dmort - nc%lmort_direct = currentCohort%lmort_direct - nc%lmort_collateral = currentCohort%lmort_collateral - nc%lmort_infra = currentCohort%lmort_infra - - endif ! is/is-not woody - - endif ! Select canopy layer - - else - write(fates_log(),*) 'unknown disturbance mode?' - write(fates_log(),*) 'i_disturbance_type: ',i_disturbance_type - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if ! Select disturbance mode - - if (nc%n > 0.0_r8) then - storebigcohort => new_patch%tallest - storesmallcohort => new_patch%shortest - if(associated(new_patch%tallest))then - tnull = 0 - else - tnull = 1 - new_patch%tallest => nc - nc%taller => null() - endif - - if(associated(new_patch%shortest))then - snull = 0 + call mortality_litter_fluxes(currentSite, currentPatch, & + new_patch, patch_site_areadis,bc_in) + endif + + + ! Copy any means or timers from the original patch to the new patch + ! These values will inherit all info from the original patch + ! -------------------------------------------------------------------------- + call new_patch%tveg24%CopyFromDonor(currentPatch%tveg24) + call new_patch%tveg_lpa%CopyFromDonor(currentPatch%tveg_lpa) + + + ! -------------------------------------------------------------------------- + ! The newly formed patch from disturbance (new_patch), has now been given + ! some litter from dead plants and pre-existing litter from the donor patches. + ! + ! Next, we loop through the cohorts in the donor patch, copy them with + ! area modified number density into the new-patch, and apply survivorship. + ! ------------------------------------------------------------------------- + + currentCohort => currentPatch%shortest + do while(associated(currentCohort)) + + allocate(nc) + if(hlm_use_planthydro.eq.itrue) call InitHydrCohort(CurrentSite,nc) + + ! Initialize the PARTEH object and point to the + ! correct boundary condition fields + nc%prt => null() + call InitPRTObject(nc%prt) + call InitPRTBoundaryConditions(nc) + + ! (Keeping as an example) + ! Allocate running mean functions + !allocate(nc%tveg_lpa) + !call nc%tveg_lpa%InitRMean(ema_lpa,init_value=new_patch%tveg_lpa%GetMean()) + + call zero_cohort(nc) + + ! nc is the new cohort that goes in the disturbed patch (new_patch)... currentCohort + ! is the curent cohort that stays in the donor patch (currentPatch) + call copy_cohort(currentCohort, nc) + + !this is the case as the new patch probably doesn't have a closed canopy, and + ! even if it does, that will be sorted out in canopy_structure. + nc%canopy_layer = 1 + nc%canopy_layer_yesterday = 1._r8 + + sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) + struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) + leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) + fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) + store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) + total_c = sapw_c + struct_c + leaf_c + fnrt_c + store_c + + ! treefall mortality is the current disturbance + if(i_disturbance_type .eq. dtype_ifall) then + + if(currentCohort%canopy_layer == 1)then + + ! In the donor patch we are left with fewer trees because the area has decreased + ! the plant density for large trees does not actually decrease in the donor patch + ! because this is the part of the original patch where no trees have actually fallen + ! The diagnostic cmort,bmort,hmort, and frmort rates have already been saved + + currentCohort%n = currentCohort%n * (1.0_r8 - fates_mortality_disturbance_fraction * & + min(1.0_r8,currentCohort%dmort * hlm_freq_day)) + + nc%n = 0.0_r8 ! kill all of the trees who caused the disturbance. + + nc%cmort = nan ! The mortality diagnostics are set to nan + ! because the cohort should dissappear + nc%hmort = nan + nc%bmort = nan + nc%frmort = nan + nc%smort = nan + nc%asmort = nan + nc%lmort_direct = nan + nc%lmort_collateral = nan + nc%lmort_infra = nan + nc%l_degrad = nan + + else + ! small trees + if( prt_params%woody(currentCohort%pft) == itrue)then + + + ! Survivorship of undestory woody plants. Two step process. + ! Step 1: Reduce current number of plants to reflect the + ! change in area. + ! The number density per square are doesn't change, + ! but since the patch is smaller and cohort counts + ! are absolute, reduce this number. + + nc%n = currentCohort%n * patch_site_areadis/currentPatch%area + + ! because the mortality rate due to impact for the cohorts which + ! had been in the understory and are now in the newly- + ! disturbed patch is very high, passing the imort directly to history + ! results in large numerical errors, on account of the sharply + ! reduced number densities. so instead pass this info via a + ! site-level diagnostic variable before reducing the number density. + + currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) = & + currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) + & + nc%n * ED_val_understorey_death / hlm_freq_day + + + currentSite%imort_carbonflux(currentCohort%pft) = & + currentSite%imort_carbonflux(currentCohort%pft) + & + (nc%n * ED_val_understorey_death / hlm_freq_day ) * & + total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 + + ! Step 2: Apply survivor ship function based on the understory death fraction + ! remaining of understory plants of those that are knocked over + ! by the overstorey trees dying... + nc%n = nc%n * (1.0_r8 - ED_val_understorey_death) + + ! since the donor patch split and sent a fraction of its members + ! to the new patch and a fraction to be preserved in itself, + ! when reporting diagnostic rates, we must carry over the mortality rates from + ! the donor that were applied before the patch split. Remember this is only + ! for diagnostics. But think of it this way, the rates are weighted by + ! number density in EDCLMLink, and the number density of this new patch is donated + ! so with the number density must come the effective mortality rates. + + nc%cmort = currentCohort%cmort + nc%hmort = currentCohort%hmort + nc%bmort = currentCohort%bmort + nc%frmort = currentCohort%frmort + nc%smort = currentCohort%smort + nc%asmort = currentCohort%asmort + nc%dmort = currentCohort%dmort + nc%lmort_direct = currentCohort%lmort_direct + nc%lmort_collateral = currentCohort%lmort_collateral + nc%lmort_infra = currentCohort%lmort_infra + + ! understory trees that might potentially be knocked over in the disturbance. + ! The existing (donor) patch should not have any impact mortality, it should + ! only lose cohorts due to the decrease in area. This is not mortality. + ! Besides, the current and newly created patch sum to unity + + currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) + + else + ! grass is not killed by mortality disturbance events. Just move it into the new patch area. + ! Just split the grass into the existing and new patch structures + nc%n = currentCohort%n * patch_site_areadis/currentPatch%area + + ! Those remaining in the existing + currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) + + nc%cmort = currentCohort%cmort + nc%hmort = currentCohort%hmort + nc%bmort = currentCohort%bmort + nc%frmort = currentCohort%frmort + nc%smort = currentCohort%smort + nc%asmort = currentCohort%asmort + nc%dmort = currentCohort%dmort + nc%lmort_direct = currentCohort%lmort_direct + nc%lmort_collateral = currentCohort%lmort_collateral + nc%lmort_infra = currentCohort%lmort_infra + + endif + endif + + ! Fire is the current disturbance + elseif (i_disturbance_type .eq. dtype_ifire ) then + + ! Number of members in the new patch, before we impose fire survivorship + nc%n = currentCohort%n * patch_site_areadis/currentPatch%area + + ! loss of individuals from source patch due to area shrinking + currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) + + levcan = currentCohort%canopy_layer + + if(levcan==ican_upper) then + + ! before changing number densities, track total rate of trees that died + ! due to fire, as well as from each fire mortality term + currentSite%fmort_rate_canopy(currentCohort%size_class, currentCohort%pft) = & + currentSite%fmort_rate_canopy(currentCohort%size_class, currentCohort%pft) + & + nc%n * currentCohort%fire_mort / hlm_freq_day + + currentSite%fmort_carbonflux_canopy(currentCohort%pft) = & + currentSite%fmort_carbonflux_canopy(currentCohort%pft) + & + (nc%n * currentCohort%fire_mort) * & + total_c * g_per_kg * days_per_sec * ha_per_m2 + + else + currentSite%fmort_rate_ustory(currentCohort%size_class, currentCohort%pft) = & + currentSite%fmort_rate_ustory(currentCohort%size_class, currentCohort%pft) + & + nc%n * currentCohort%fire_mort / hlm_freq_day + + currentSite%fmort_carbonflux_ustory(currentCohort%pft) = & + currentSite%fmort_carbonflux_ustory(currentCohort%pft) + & + (nc%n * currentCohort%fire_mort) * & + total_c * g_per_kg * days_per_sec * ha_per_m2 + end if + + currentSite%fmort_rate_cambial(currentCohort%size_class, currentCohort%pft) = & + currentSite%fmort_rate_cambial(currentCohort%size_class, currentCohort%pft) + & + nc%n * currentCohort%cambial_mort / hlm_freq_day + currentSite%fmort_rate_crown(currentCohort%size_class, currentCohort%pft) = & + currentSite%fmort_rate_crown(currentCohort%size_class, currentCohort%pft) + & + nc%n * currentCohort%crownfire_mort / hlm_freq_day + + ! loss of individual from fire in new patch. + nc%n = nc%n * (1.0_r8 - currentCohort%fire_mort) + + nc%cmort = currentCohort%cmort + nc%hmort = currentCohort%hmort + nc%bmort = currentCohort%bmort + nc%frmort = currentCohort%frmort + nc%smort = currentCohort%smort + nc%asmort = currentCohort%asmort + nc%dmort = currentCohort%dmort + nc%lmort_direct = currentCohort%lmort_direct + nc%lmort_collateral = currentCohort%lmort_collateral + nc%lmort_infra = currentCohort%lmort_infra + + + ! Some of of the leaf mass from living plants has been + ! burned off. Here, we remove that mass, and + ! tally it in the flux we sent to the atmosphere + + if(prt_params%woody(currentCohort%pft) == itrue)then + leaf_burn_frac = currentCohort%fraction_crown_burned + else + + ! Grasses determine their fraction of leaves burned here + + leaf_burn_frac = currentPatch%burnt_frac_litter(lg_sf) + endif + + ! Perform a check to make sure that spitfire gave + ! us reasonable mortality and burn fraction rates + + if( (leaf_burn_frac < 0._r8) .or. & + (leaf_burn_frac > 1._r8) .or. & + (currentCohort%fire_mort < 0._r8) .or. & + (currentCohort%fire_mort > 1._r8)) then + write(fates_log(),*) 'unexpected fire fractions' + write(fates_log(),*) prt_params%woody(currentCohort%pft) + write(fates_log(),*) leaf_burn_frac + write(fates_log(),*) currentCohort%fire_mort + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + do el = 1,num_elements + + leaf_m = nc%prt%GetState(leaf_organ, element_list(el)) + + currentSite%mass_balance(el)%burn_flux_to_atm = & + currentSite%mass_balance(el)%burn_flux_to_atm + & + leaf_burn_frac * leaf_m * nc%n + end do + + ! Here the mass is removed from the plant + + call PRTBurnLosses(nc%prt, leaf_organ, leaf_burn_frac) + currentCohort%fraction_crown_burned = 0.0_r8 + nc%fraction_crown_burned = 0.0_r8 + + + + ! Logging is the current disturbance + elseif (i_disturbance_type .eq. dtype_ilog ) then + + ! If this cohort is in the upper canopy. It generated + if(currentCohort%canopy_layer == 1)then + + ! calculate the survivorship of disturbed trees because non-harvested + nc%n = currentCohort%n * currentCohort%l_degrad + ! nc%n = (currentCohort%l_degrad / (currentCohort%l_degrad + & + ! currentCohort%lmort_direct + currentCohort%lmort_collateral + + ! currentCohort%lmort_infra) ) * & + ! currentCohort%n * patch_site_areadis/currentPatch%area + + ! Reduce counts in the existing/donor patch according to the logging rate + currentCohort%n = currentCohort%n * & + (1.0_r8 - min(1.0_r8,(currentCohort%lmort_direct + & + currentCohort%lmort_collateral + & + currentCohort%lmort_infra + currentCohort%l_degrad))) + + nc%cmort = currentCohort%cmort + nc%hmort = currentCohort%hmort + nc%bmort = currentCohort%bmort + nc%frmort = currentCohort%frmort + nc%smort = currentCohort%smort + nc%asmort = currentCohort%asmort + nc%dmort = currentCohort%dmort + + ! since these are the ones that weren't logged, + ! set the logging mortality rates as zero + nc%lmort_direct = 0._r8 + nc%lmort_collateral = 0._r8 + nc%lmort_infra = 0._r8 + + else + + ! What to do with cohorts in the understory of a logging generated + ! disturbance patch? + + if(prt_params%woody(currentCohort%pft) == itrue)then + + + ! Survivorship of undestory woody plants. Two step process. + ! Step 1: Reduce current number of plants to reflect the + ! change in area. + ! The number density per square are doesn't change, + ! but since the patch is smaller + ! and cohort counts are absolute, reduce this number. + nc%n = currentCohort%n * patch_site_areadis/currentPatch%area + + ! because the mortality rate due to impact for the cohorts which had + ! been in the understory and are now in the newly- + ! disturbed patch is very high, passing the imort directly to + ! history results in large numerical errors, on account + ! of the sharply reduced number densities. so instead pass this info + ! via a site-level diagnostic variable before reducing + ! the number density. + currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) = & + currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) + & + nc%n * currentPatch%fract_ldist_not_harvested * & + logging_coll_under_frac / hlm_freq_day + + currentSite%imort_carbonflux(currentCohort%pft) = & + currentSite%imort_carbonflux(currentCohort%pft) + & + (nc%n * currentPatch%fract_ldist_not_harvested * & + logging_coll_under_frac/ hlm_freq_day ) * & + total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 + + + ! Step 2: Apply survivor ship function based on the understory death fraction + + ! remaining of understory plants of those that are knocked + ! over by the overstorey trees dying... + ! LOGGING SURVIVORSHIP OF UNDERSTORY PLANTS IS SET AS A NEW PARAMETER + ! in the fatesparameter files + nc%n = nc%n * (1.0_r8 - & + (1.0_r8-currentPatch%fract_ldist_not_harvested) * logging_coll_under_frac) + + ! Step 3: Reduce the number count of cohorts in the + ! original/donor/non-disturbed patch to reflect the area change + currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) + + nc%cmort = currentCohort%cmort + nc%hmort = currentCohort%hmort + nc%bmort = currentCohort%bmort + nc%frmort = currentCohort%frmort + nc%smort = currentCohort%smort + nc%asmort = currentCohort%asmort + nc%dmort = currentCohort%dmort + nc%lmort_direct = currentCohort%lmort_direct + nc%lmort_collateral = currentCohort%lmort_collateral + nc%lmort_infra = currentCohort%lmort_infra + + else + + ! grass is not killed by mortality disturbance events. + ! Just move it into the new patch area. + ! Just split the grass into the existing and new patch structures + nc%n = currentCohort%n * patch_site_areadis/currentPatch%area + + ! Those remaining in the existing + currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) + + ! No grass impact mortality imposed on the newly created patch + nc%cmort = currentCohort%cmort + nc%hmort = currentCohort%hmort + nc%bmort = currentCohort%bmort + nc%frmort = currentCohort%frmort + nc%smort = currentCohort%smort + nc%asmort = currentCohort%asmort + nc%dmort = currentCohort%dmort + nc%lmort_direct = currentCohort%lmort_direct + nc%lmort_collateral = currentCohort%lmort_collateral + nc%lmort_infra = currentCohort%lmort_infra + + endif ! is/is-not woody + + endif ! Select canopy layer + + else + write(fates_log(),*) 'unknown disturbance mode?' + write(fates_log(),*) 'i_disturbance_type: ',i_disturbance_type + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if ! Select disturbance mode + + if (nc%n > 0.0_r8) then + storebigcohort => new_patch%tallest + storesmallcohort => new_patch%shortest + if(associated(new_patch%tallest))then + tnull = 0 + else + tnull = 1 + new_patch%tallest => nc + nc%taller => null() + endif + + if(associated(new_patch%shortest))then + snull = 0 + else + snull = 1 + new_patch%shortest => nc + nc%shorter => null() + endif + nc%patchptr => new_patch + call insert_cohort(nc, new_patch%tallest, new_patch%shortest, & + tnull, snull, storebigcohort, storesmallcohort) + + new_patch%tallest => storebigcohort + new_patch%shortest => storesmallcohort + else + + ! Get rid of the new temporary cohort + call DeallocateCohort(nc) + deallocate(nc) + + endif + + currentCohort => currentCohort%taller + enddo ! currentCohort + call sort_cohorts(currentPatch) + + !update area of donor patch + oldarea = currentPatch%area + currentPatch%area = currentPatch%area - patch_site_areadis + + ! for all disturbance rates that haven't been resolved yet, increase their amount so that + ! they are the same amount of gridcell-scale disturbance relative to the original patch size + if (i_disturbance_type .ne. N_DIST_TYPES) then + do i_dist2 = i_disturbance_type+1,N_DIST_TYPES + currentPatch%disturbance_rates(i_dist2) = currentPatch%disturbance_rates(i_dist2) & + * oldarea / currentPatch%area + end do + end if + + ! sort out the cohorts, since some of them may be so small as to need removing. + ! the first call to terminate cohorts removes sparse number densities, + ! the second call removes for all other reasons (sparse culling must happen + ! before fusion) + call terminate_cohorts(currentSite, currentPatch, 1,16,bc_in) + call fuse_cohorts(currentSite,currentPatch, bc_in) + call terminate_cohorts(currentSite, currentPatch, 2,16,bc_in) + call sort_cohorts(currentPatch) + + end if ! if ( new_patch%area > nearzero ) then + + end if cp_nocomp_matches_2_if + currentPatch => currentPatch%younger + + enddo ! currentPatch patch loop. + + !*************************/ + !** INSERT NEW PATCH(ES) INTO LINKED LIST + !*************************/ + + if ( site_areadis_primary .gt. nearzero) then + currentPatch => currentSite%youngest_patch + ! insert new youngest primary patch after all the secondary patches, if there are any. + ! this requires first finding the current youngest primary to insert the new one ahead of + if (currentPatch%anthro_disturbance_label .eq. secondaryforest ) then + found_youngest_primary = .false. + do while(associated(currentPatch) .and. .not. found_youngest_primary) + currentPatch => currentPatch%older + if (associated(currentPatch)) then + if (currentPatch%anthro_disturbance_label .eq. primaryforest) then + found_youngest_primary = .true. + endif + endif + end do + if (associated(currentPatch)) then + ! the case where we've found a youngest primary patch + new_patch_primary%older => currentPatch + new_patch_primary%younger => currentPatch%younger + currentPatch%younger%older => new_patch_primary + currentPatch%younger => new_patch_primary else - snull = 1 - new_patch%shortest => nc - nc%shorter => null() + ! the case where we haven't, because the patches are all secondaary, + ! and are putting a primary patch at the oldest end of the + ! linked list (not sure how this could happen, but who knows...) + new_patch_primary%older => null() + new_patch_primary%younger => currentSite%oldest_patch + currentSite%oldest_patch%older => new_patch_primary + currentSite%oldest_patch => new_patch_primary endif - nc%patchptr => new_patch - call insert_cohort(nc, new_patch%tallest, new_patch%shortest, & - tnull, snull, storebigcohort, storesmallcohort) - - new_patch%tallest => storebigcohort - new_patch%shortest => storesmallcohort else - - ! Get rid of the new temporary cohort - call DeallocateCohort(nc) - deallocate(nc) - + ! the case where there are no secondary patches at the start of the linked list (prior logic) + new_patch_primary%older => currentPatch + new_patch_primary%younger => null() + currentPatch%younger => new_patch_primary + currentSite%youngest_patch => new_patch_primary endif - - currentCohort => currentCohort%taller - enddo ! currentCohort - call sort_cohorts(currentPatch) - - !update area of donor patch - oldarea = currentPatch%area - currentPatch%area = currentPatch%area - patch_site_areadis - - ! for all disturbance rates that haven't been resolved yet, increase their amount so that - ! they are the same amount of gridcell-scale disturbance relative to the original patch size - if (i_disturbance_type .ne. N_DIST_TYPES) then - do i_dist2 = i_disturbance_type+1,N_DIST_TYPES - currentPatch%disturbance_rates(i_dist2) = currentPatch%disturbance_rates(i_dist2) & - * oldarea / currentPatch%area - end do - end if + endif - ! sort out the cohorts, since some of them may be so small as to need removing. + ! insert first secondary at the start of the list + if ( site_areadis_secondary .gt. nearzero) then + currentPatch => currentSite%youngest_patch + new_patch_secondary%older => currentPatch + new_patch_secondary%younger=> null() + currentPatch%younger => new_patch_secondary + currentSite%youngest_patch => new_patch_secondary + endif + + + ! sort out the cohorts, since some of them may be so small as to need removing. ! the first call to terminate cohorts removes sparse number densities, ! the second call removes for all other reasons (sparse culling must happen ! before fusion) - call terminate_cohorts(currentSite, currentPatch, 1,16,bc_in) - call fuse_cohorts(currentSite,currentPatch, bc_in) - call terminate_cohorts(currentSite, currentPatch, 2,16,bc_in) - call sort_cohorts(currentPatch) - end if ! if ( new_patch%area > nearzero ) then - - end if cp_nocomp_matches_2_if - currentPatch => currentPatch%younger - - enddo ! currentPatch patch loop. + if ( site_areadis_primary .gt. nearzero) then + call terminate_cohorts(currentSite, new_patch_primary, 1,17, bc_in) + call fuse_cohorts(currentSite,new_patch_primary, bc_in) + call terminate_cohorts(currentSite, new_patch_primary, 2,17, bc_in) + call sort_cohorts(new_patch_primary) + endif - !*************************/ - !** INSERT NEW PATCH(ES) INTO LINKED LIST - !*************************/ - - if ( site_areadis_primary .gt. nearzero) then - currentPatch => currentSite%youngest_patch - ! insert new youngest primary patch after all the secondary patches, if there are any. - ! this requires first finding the current youngest primary to insert the new one ahead of - if (currentPatch%anthro_disturbance_label .eq. secondaryforest ) then - found_youngest_primary = .false. - do while(associated(currentPatch) .and. .not. found_youngest_primary) - currentPatch => currentPatch%older - if (associated(currentPatch)) then - if (currentPatch%anthro_disturbance_label .eq. primaryforest) then - found_youngest_primary = .true. - endif - endif - end do - if (associated(currentPatch)) then - ! the case where we've found a youngest primary patch - new_patch_primary%older => currentPatch - new_patch_primary%younger => currentPatch%younger - currentPatch%younger%older => new_patch_primary - currentPatch%younger => new_patch_primary - else - ! the case where we haven't, because the patches are all secondaary, - ! and are putting a primary patch at the oldest end of the - ! linked list (not sure how this could happen, but who knows...) - new_patch_primary%older => null() - new_patch_primary%younger => currentSite%oldest_patch - currentSite%oldest_patch%older => new_patch_primary - currentSite%oldest_patch => new_patch_primary + if ( site_areadis_secondary .gt. nearzero) then + call terminate_cohorts(currentSite, new_patch_secondary, 1,18,bc_in) + call fuse_cohorts(currentSite,new_patch_secondary, bc_in) + call terminate_cohorts(currentSite, new_patch_secondary, 2,18,bc_in) + call sort_cohorts(new_patch_secondary) endif - else - ! the case where there are no secondary patches at the start of the linked list (prior logic) - new_patch_primary%older => currentPatch - new_patch_primary%younger => null() - currentPatch%younger => new_patch_primary - currentSite%youngest_patch => new_patch_primary - endif - endif - - ! insert first secondary at the start of the list - if ( site_areadis_secondary .gt. nearzero) then - currentPatch => currentSite%youngest_patch - new_patch_secondary%older => currentPatch - new_patch_secondary%younger=> null() - currentPatch%younger => new_patch_secondary - currentSite%youngest_patch => new_patch_secondary - endif - - - ! sort out the cohorts, since some of them may be so small as to need removing. - ! the first call to terminate cohorts removes sparse number densities, - ! the second call removes for all other reasons (sparse culling must happen - ! before fusion) - - if ( site_areadis_primary .gt. nearzero) then - call terminate_cohorts(currentSite, new_patch_primary, 1,17, bc_in) - call fuse_cohorts(currentSite,new_patch_primary, bc_in) - call terminate_cohorts(currentSite, new_patch_primary, 2,17, bc_in) - call sort_cohorts(new_patch_primary) - endif - - if ( site_areadis_secondary .gt. nearzero) then - call terminate_cohorts(currentSite, new_patch_secondary, 1,18,bc_in) - call fuse_cohorts(currentSite,new_patch_secondary, bc_in) - call terminate_cohorts(currentSite, new_patch_secondary, 2,18,bc_in) - call sort_cohorts(new_patch_secondary) - endif - - endif !end new_patch area - - - call check_patch_area(currentSite) - call set_patchno(currentSite) - - end do disturbance_type_loop + + endif !end new_patch area + + + call check_patch_area(currentSite) + call set_patchno(currentSite) + + end do disturbance_type_loop end do nocomp_pft_loop From 19c74846d7e06708c34911cc7ed7a18c5e50cbee Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Sun, 26 Jun 2022 10:43:40 -0400 Subject: [PATCH 256/852] Re-introduced gracefull crash when tring to perform carbon based (mass) harvest rates, updated a hard-coded constant to a named constant --- biogeochem/EDLoggingMortalityMod.F90 | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index ca3ba26f03..b03e9485f5 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -273,8 +273,10 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & ! if (fates_global_verbose()) then ! write(fates_log(), *) 'Successfully Read Harvest Rate from HLM.', hlm_harvest_rates(:), harvest_rate ! end if - !write(fates_log(),*) 'HLM harvest carbon data not implemented yet. Exiting.' - !call endrun(msg=errMsg(sourcefile, __LINE__)) + + write(fates_log(),*) 'HLM harvest carbon data not implemented yet. Exiting.' + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif ! transfer of area to secondary land is based on overall area affected, not just logged crown area @@ -846,14 +848,14 @@ subroutine UpdateHarvestC(currentSite,bc_out) bc_out%hrv_deadstemc_to_prod100c = 0._r8 ! Calculate the unit transfer factor (from kgC m-2 day-1 to gC m-2 s-1) - unit_trans_factor = 1000._r8 * days_per_sec + unit_trans_factor = g_per_kg * days_per_sec bc_out%hrv_deadstemc_to_prod10c = bc_out%hrv_deadstemc_to_prod10c + & currentSite%mass_balance(element_pos(carbon12_element))%wood_product * & AREA_INV * pprodharv10_forest_mean * unit_trans_factor bc_out%hrv_deadstemc_to_prod100c = bc_out%hrv_deadstemc_to_prod100c + & currentSite%mass_balance(element_pos(carbon12_element))%wood_product * & - AREA_INV * (1 - pprodharv10_forest_mean) * unit_trans_factor + AREA_INV * (1._r8 - pprodharv10_forest_mean) * unit_trans_factor return end subroutine UpdateHarvestC From 83f2fcb004f4cca6cb5fda2a6c69c3edf7612c69 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Sun, 26 Jun 2022 10:45:32 -0400 Subject: [PATCH 257/852] Adding in restart info for wood products --- main/FatesRestartInterfaceMod.F90 | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 0c88d90986..c61c87fd4b 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -219,6 +219,7 @@ module FatesRestartInterfaceMod integer :: ir_uptake_flxdg integer :: ir_oldstock_mbal integer :: ir_errfates_mbal + integer :: ir_woodprod_mbal integer :: ir_prt_base ! Base index for all PRT variables ! Hydraulic indices @@ -1056,7 +1057,11 @@ subroutine define_restart_vars(this, initialize_variables) units='kg/ha', veclength=num_elements, flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_errfates_mbal) - + call this%RegisterCohortVector(symbol_base='fates_woodproduct', vtype=site_r8, & + long_name_base='Current wood product flux', & + units='kg/m2/day', veclength=num_elements, flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_woodprod_mbal) + ! Only register satellite phenology related restart variables if it is turned on! if(hlm_use_sp .eq. itrue) then @@ -1910,7 +1915,8 @@ subroutine set_restart_vectors(this,nc,nsites,sites) this%rvars(ir_oldstock_mbal+el-1)%r81d(io_idx_si) = sites(s)%mass_balance(el)%old_stock this%rvars(ir_errfates_mbal+el-1)%r81d(io_idx_si) = sites(s)%mass_balance(el)%err_fates - + this%rvars(ir_woodprod_mbal+el-1)%r81d(io_idx_si) = sites(s)%mass_balance(el)%wood_product + end do @@ -2738,7 +2744,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%mass_balance(el)%old_stock = this%rvars(ir_oldstock_mbal+el-1)%r81d(io_idx_si) sites(s)%mass_balance(el)%err_fates = this%rvars(ir_errfates_mbal+el-1)%r81d(io_idx_si) - + sites(s)%mass_balance(el)%wood_product = this%rvars(ir_woodprod_mbal+el-1)%r81d(io_idx_si) end do sites(s)%spread = rio_spread_si(io_idx_si) From fc472cfb9f9b8a3097f6bb131dff1cf11f7c790e Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 28 Jun 2022 15:17:38 -0700 Subject: [PATCH 258/852] wholesale copy of @mpaiao version of the vincety algorithm --- main/FatesUtilsMod.F90 | 47 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/main/FatesUtilsMod.F90 b/main/FatesUtilsMod.F90 index 20416e16d6..a36261cc76 100644 --- a/main/FatesUtilsMod.F90 +++ b/main/FatesUtilsMod.F90 @@ -74,6 +74,53 @@ subroutine check_var_real(r8_var, var_name, return_code) end subroutine check_var_real + + !==========================================================================================! + ! Function to compute the great circle distance between two points: the s suffix denotes ! + ! source point, and f denotes the destination - "forepoint"). The results are given in ! + ! metres. The formula is intended to be accurate for both small and large distances and ! + ! uses double precision to avoid ill-conditioned behaviour of sin and cos for numbers ! + ! close to the n*pi/2. ! + !------------------------------------------------------------------------------------------! + real function dist_gc(slons,slonf,slats,slatf) + use consts_coms, only : erad & ! intent(in) + , pio1808 ! ! intent(in) + implicit none + !----- Local variables. ----------------------------------------------------------------! + real, intent(in) :: slons + real, intent(in) :: slonf + real, intent(in) :: slats + real, intent(in) :: slatf + !----- Local variables. ----------------------------------------------------------------! + real(kind=8) :: lons + real(kind=8) :: lonf + real(kind=8) :: lats + real(kind=8) :: latf + real(kind=8) :: dlon + real(kind=8) :: dlat + real(kind=8) :: x + real(kind=8) :: y + !---------------------------------------------------------------------------------------! + + !----- Convert the co-ordinates to double precision and to radians. --------------------! + lons = dble(slons) * pio1808 + lonf = dble(slonf) * pio1808 + lats = dble(slats) * pio1808 + latf = dble(slatf) * pio1808 + dlon = lonf - lons + dlat = latf - lats + + !----- Find the arcs. ------------------------------------------------------------------! + x = dsin(lats) * dsin(latf) + dcos(lats) * dcos(latf) * dcos(dlon) + y = dsqrt( (dcos(latf)*dsin(dlon)) * (dcos(latf)*dsin(dlon)) & + + (dcos(lats)*dsin(latf)-dsin(lats)*dcos(latf)*dcos(dlon)) & + * (dcos(lats)*dsin(latf)-dsin(lats)*dcos(latf)*dcos(dlon)) ) + + !----- Convert the arcs to actual distance. --------------------------------------------! + dist_gc = erad*sngl(datan2(y,x)) + + return + end function dist_gc end module FatesUtilsMod From ef30ae81583b61dbd14c45d9d5623e27a20f2f83 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 28 Jun 2022 15:43:31 -0700 Subject: [PATCH 259/852] updating gcd import code with fates constants. Adding new constant params --- main/FatesConstantsMod.F90 | 5 +++ main/FatesUtilsMod.F90 | 84 ++++++++++++++++++++------------------ 2 files changed, 50 insertions(+), 39 deletions(-) diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index 726100a37b..11d209865a 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -223,6 +223,11 @@ module FatesConstantsMod real(fates_r8), parameter, public :: fates_huge = huge(g_per_kg) real(fates_r8), parameter, public :: fates_tiny = tiny(g_per_kg) + + ! Geodesy constants (WGS 84) + real(fates_r8), parameter, public :: earth_radius_eq = 6378137_fates_r8 ! equitorial radius, earth [m] + real(fates_r8), parameter, public :: earth_flattening = 1.0_fates_r8 / 298.257223563_fates_r8 ! flattening [non-dimensional] + ! Geometric Constants diff --git a/main/FatesUtilsMod.F90 b/main/FatesUtilsMod.F90 index a36261cc76..13176ddec8 100644 --- a/main/FatesUtilsMod.F90 +++ b/main/FatesUtilsMod.F90 @@ -82,45 +82,51 @@ end subroutine check_var_real ! uses double precision to avoid ill-conditioned behaviour of sin and cos for numbers ! ! close to the n*pi/2. ! !------------------------------------------------------------------------------------------! - real function dist_gc(slons,slonf,slats,slatf) - use consts_coms, only : erad & ! intent(in) - , pio1808 ! ! intent(in) - implicit none - !----- Local variables. ----------------------------------------------------------------! - real, intent(in) :: slons - real, intent(in) :: slonf - real, intent(in) :: slats - real, intent(in) :: slatf - !----- Local variables. ----------------------------------------------------------------! - real(kind=8) :: lons - real(kind=8) :: lonf - real(kind=8) :: lats - real(kind=8) :: latf - real(kind=8) :: dlon - real(kind=8) :: dlat - real(kind=8) :: x - real(kind=8) :: y - !---------------------------------------------------------------------------------------! - - !----- Convert the co-ordinates to double precision and to radians. --------------------! - lons = dble(slons) * pio1808 - lonf = dble(slonf) * pio1808 - lats = dble(slats) * pio1808 - latf = dble(slatf) * pio1808 - dlon = lonf - lons - dlat = latf - lats - - !----- Find the arcs. ------------------------------------------------------------------! - x = dsin(lats) * dsin(latf) + dcos(lats) * dcos(latf) * dcos(dlon) - y = dsqrt( (dcos(latf)*dsin(dlon)) * (dcos(latf)*dsin(dlon)) & - + (dcos(lats)*dsin(latf)-dsin(lats)*dcos(latf)*dcos(dlon)) & - * (dcos(lats)*dsin(latf)-dsin(lats)*dcos(latf)*dcos(dlon)) ) - - !----- Convert the arcs to actual distance. --------------------------------------------! - dist_gc = erad*sngl(datan2(y,x)) - - return - end function dist_gc + real(r8) function GreatCircleDist(slons,slonf,slats,slatf) + + use FatesConstantsMod, only : earth_radius_eq & + , pi_const + implicit none + + !----- Local variables. ----------------------------------------------------------------! + real(r8), intent(in) :: slons + real(r8), intent(in) :: slonf + real(r8), intent(in) :: slats + real(r8), intent(in) :: slatf + + !----- Local variables. ----------------------------------------------------------------! + real(r8) :: lons + real(r8) :: lonf + real(r8) :: lats + real(r8) :: latf + real(r8) :: dlon + real(r8) :: dlat + real(r8) :: x + real(r8) :: y + !---------------------------------------------------------------------------------------! + + !----- Convert the co-ordinates to double precision and to radians. --------------------! + lons = slons * pi_const + lonf = slonf * pi_const + lats = slats * pi_const + latf = slatf * pi_const + dlon = lonf - lons + dlat = latf - lats + + !----- Find the arcs. ------------------------------------------------------------------! + x = dsin(lats) * dsin(latf) + dcos(lats) * dcos(latf) * dcos(dlon) + y = dsqrt( (dcos(latf)*dsin(dlon)) * (dcos(latf)*dsin(dlon)) & + + (dcos(lats)*dsin(latf)-dsin(lats)*dcos(latf)*dcos(dlon)) & + * (dcos(lats)*dsin(latf)-dsin(lats)*dcos(latf)*dcos(dlon)) ) + + !----- Convert the arcs to actual distance. --------------------------------------------! + GreatCircleDist = earth_radius_eq*datan2(y,x) + + return + + end function GreatCircleDist + + end module FatesUtilsMod From e85d1f4d459d163af532da8aae3f419a50cfca8c Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 29 Jun 2022 10:29:16 -0400 Subject: [PATCH 260/852] Updated argument name in UpdateCohortLai --- biogeochem/EDCanopyStructureMod.F90 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 85aa880829..611d6fad19 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -2238,7 +2238,7 @@ subroutine UpdatePatchLAI(currentPatch, patch_lai, currentSite) end subroutine UpdatePatchLAI ! =============================================================================================== - subroutine UpdateCohortLAI(currentCohort, canopy_layer_tlai, patcharea, spread) + subroutine UpdateCohortLAI(currentCohort, canopy_layer_tlai, total_canopy_area, spread) ! Update LAI and related variables for a given cohort @@ -2248,7 +2248,7 @@ subroutine UpdateCohortLAI(currentCohort, canopy_layer_tlai, patcharea, spread) ! Arguments type(ed_cohort_type),intent(inout), target :: currentCohort real(r8), intent(in) :: canopy_layer_tlai(nclmax) ! total leaf area index of each canopy layer - real(r8), intent(in) :: patcharea ! either patch%total_canopy_area or patch%area + real(r8), intent(in) :: total_canopy_area ! either patch%total_canopy_area or patch%area real(r8), intent(in) :: spread ! currentSite%spread ! Local variables @@ -2275,8 +2275,8 @@ subroutine UpdateCohortLAI(currentCohort, canopy_layer_tlai, patcharea, spread) end if ! Update the cohort lai and sai - currentCohort%lai = currentCohort%treelai *currentCohort%c_area/patcharea - currentCohort%sai = currentCohort%treesai *currentCohort%c_area/patcharea + currentCohort%lai = currentCohort%treelai *currentCohort%c_area/total_canopy_area + currentCohort%sai = currentCohort%treesai *currentCohort%c_area/total_canopy_area ! Number of actual vegetation layers in this cohort's crown currentCohort%nv = count((currentCohort%treelai+currentCohort%treesai) .gt. dlower_vai(:)) + 1 From bb345fc0bc37428aa30b1356b705abb1ad51d683 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 29 Jun 2022 12:47:57 -0400 Subject: [PATCH 261/852] Added the undamaged class named constant --- biogeochem/DamageMainMod.F90 | 8 ++++++++ biogeochem/EDCohortDynamicsMod.F90 | 4 ++-- main/EDInitMod.F90 | 5 +++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/biogeochem/DamageMainMod.F90 b/biogeochem/DamageMainMod.F90 index 2d0a94dc06..6ea408dd82 100644 --- a/biogeochem/DamageMainMod.F90 +++ b/biogeochem/DamageMainMod.F90 @@ -47,6 +47,14 @@ module DamageMainMod logical :: debug = .false. ! for debugging + + ! The following is the special classification for undamaged plants + ! and is used in contexts where cohort%damageclass is used. This is + ! to flag to the user that an undamaged plant is assumed in those contexts + + integer, parameter, public :: undamaged_class = 1 + + ! ============================================================================ ! ============================================================================ diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 230b8c28fe..75a06f3ddd 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -102,7 +102,7 @@ Module EDCohortDynamicsMod use PRTAllometricCNPMod, only : acnp_bc_out_id_pefflux use PRTAllometricCNPMod, only : acnp_bc_out_id_nneed use PRTAllometricCNPMod, only : acnp_bc_out_id_pneed - + use DamageMainMod, only : GetCrownReduction use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) @@ -1080,7 +1080,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) use FatesInterfaceTypesMod , only : hlm_use_cohort_age_tracking use FatesConstantsMod , only : itrue use FatesConstantsMod, only : days_per_year - use DamageMainMod, only : GetCrownReduction + ! ! !ARGUMENTS diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index c1dd2dfda8..22e9203ef4 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -77,6 +77,7 @@ module EDInitMod use PRTGenericMod, only : phosphorus_element use PRTGenericMod, only : SetState use FatesSizeAgeTypeIndicesMod,only : get_age_class_index + use DamageMainMod, only : undamaged_class ! CIME GLOBALS use shr_log_mod , only : errMsg => shr_log_errMsg @@ -956,8 +957,8 @@ subroutine init_cohorts( site_in, patch_in, bc_in) call create_cohort(site_in, patch_in, pft, temp_cohort%n, temp_cohort%hite, & temp_cohort%coage, temp_cohort%dbh, prt_obj, temp_cohort%leafmemory,& temp_cohort%sapwmemory, temp_cohort%structmemory, cstatus, rstatus, & - temp_cohort%canopy_trim, temp_cohort%c_area, 1, temp_cohort%crowndamage,& - site_in%spread, bc_in) + temp_cohort%canopy_trim, temp_cohort%c_area, undamaged_class, & + temp_cohort%crowndamage, site_in%spread, bc_in) deallocate(temp_cohort) ! get rid of temporary cohort From ce6f93b1ba7bd3662c7248fa6227b416d53b4e63 Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Wed, 29 Jun 2022 11:05:05 -0700 Subject: [PATCH 262/852] [ Change tree_sai so that it is affected by damage ] [ Was using undamaged target lai to calculate tree_sai but it should actually be damaged lai. ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary: no testing --- biogeochem/EDCanopyStructureMod.F90 | 14 +++++--------- biogeochem/EDCohortDynamicsMod.F90 | 2 +- biogeochem/EDPhysiologyMod.F90 | 2 +- biogeochem/FatesAllometryMod.F90 | 6 +++--- 4 files changed, 10 insertions(+), 14 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 611d6fad19..9fc30b478b 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -2238,7 +2238,7 @@ subroutine UpdatePatchLAI(currentPatch, patch_lai, currentSite) end subroutine UpdatePatchLAI ! =============================================================================================== - subroutine UpdateCohortLAI(currentCohort, canopy_layer_tlai, total_canopy_area, spread) + subroutine UpdateCohortLAI(currentCohort, canopy_layer_tlai, total_canopy_area) ! Update LAI and related variables for a given cohort @@ -2249,11 +2249,9 @@ subroutine UpdateCohortLAI(currentCohort, canopy_layer_tlai, total_canopy_area, type(ed_cohort_type),intent(inout), target :: currentCohort real(r8), intent(in) :: canopy_layer_tlai(nclmax) ! total leaf area index of each canopy layer real(r8), intent(in) :: total_canopy_area ! either patch%total_canopy_area or patch%area - real(r8), intent(in) :: spread ! currentSite%spread ! Local variables real(r8) :: leaf_c ! leaf carbon [kg] - real(r8) :: target_c_area ! target c_area - as if not damaged ! Obtain the leaf carbon leaf_c = currentCohort%prt%GetState(leaf_organ,all_carbon_elements) @@ -2263,13 +2261,11 @@ subroutine UpdateCohortLAI(currentCohort, canopy_layer_tlai, total_canopy_area, currentCohort%treelai = tree_lai(leaf_c, currentCohort%pft, currentCohort%c_area, & currentCohort%n, currentCohort%canopy_layer, & canopy_layer_tlai,currentCohort%vcmax25top ) - - call carea_allom(currentCohort%dbh, currentCohort%n, spread, currentCohort%pft, & - 1, target_c_area) - + if (hlm_use_sp .eq. ifalse) then - currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_trim, & - target_c_area, currentCohort%n, currentCohort%canopy_layer, & + currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%crowndamage, & + currentCohort%canopy_trim, & + currentCohort%c_area, currentCohort%n, currentCohort%canopy_layer, & canopy_layer_tlai, currentCohort%treelai , & currentCohort%vcmax25top,4) end if diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 75a06f3ddd..c690bf898f 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -287,7 +287,7 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & if(hlm_use_sp.eq.ifalse)then new_cohort%treesai = tree_sai(new_cohort%pft, new_cohort%dbh, & - new_cohort%canopy_trim, & + new_cohort%crowndamage, new_cohort%canopy_trim, & new_cohort%c_area, new_cohort%n, new_cohort%canopy_layer, & patchptr%canopy_layer_tlai, new_cohort%treelai,new_cohort%vcmax25top,2 ) end if diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index af846de2e6..0c13806859 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -475,7 +475,7 @@ subroutine trim_canopy( currentSite ) ! We don't need check on sp mode here since we don't trim_canopy with sp mode currentCohort%treesai = tree_sai(currentCohort%pft, & - currentCohort%dbh, & + currentCohort%dbh, currentCohort%crowndamage, & currentCohort%canopy_trim, & target_c_area, currentCohort%n,currentCohort%canopy_layer,& currentPatch%canopy_layer_tlai, currentCohort%treelai, & diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index 29f08e58ae..a537be5af3 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -740,7 +740,7 @@ end function tree_lai ! ============================================================================ - real(r8) function tree_sai(pft, dbh, canopy_trim, c_area, nplant, cl, & + real(r8) function tree_sai(pft, dbh, crowndamage, canopy_trim, c_area, nplant, cl, & canopy_lai, treelai, vcmax25top, call_id ) ! ============================================================================ @@ -749,6 +749,7 @@ real(r8) function tree_sai(pft, dbh, canopy_trim, c_area, nplant, cl, & integer, intent(in) :: pft real(r8), intent(in) :: dbh + integer, intent(in) :: crowndamage real(r8), intent(in) :: canopy_trim ! trimming function (0-1) real(r8), intent(in) :: c_area ! crown area (m2) real(r8), intent(in) :: nplant ! number of plants @@ -763,8 +764,7 @@ real(r8) function tree_sai(pft, dbh, canopy_trim, c_area, nplant, cl, & real(r8) :: target_lai real(r8) :: target_bleaf - ! target undamaged bleaf - call bleaf(dbh, pft, 1, canopy_trim, target_bleaf) + call bleaf(dbh, pft, crowndamage, canopy_trim, target_bleaf) target_lai = tree_lai(target_bleaf, pft, c_area, nplant, cl,& canopy_lai, vcmax25top) From d2dfb732953d8f94c5a0146d0cca300a3bb3a52d Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 30 Jun 2022 10:01:27 -0400 Subject: [PATCH 263/852] Minor variable name change for readability --- biogeochem/EDMortalityFunctionsMod.F90 | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index f64d2b6901..d745f468d5 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -72,7 +72,8 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmor real(r8),intent(out) :: dgmort ! damage dependent mortality real(r8) :: frac ! relativised stored carbohydrate - real(r8) :: leaf_c ! leaf biomass kgC + real(r8) :: target_leaf_c ! target leaf biomass for the current trim status and + ! damage class [kgC] real(r8) :: store_c real(r8) :: hf_sm_threshold ! hydraulic failure soil moisture threshold real(r8) :: hf_flc_threshold ! hydraulic failure fractional loss of conductivity threshold @@ -164,10 +165,10 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmor ! Carbon Starvation induced mortality. if ( cohort_in%dbh > 0._r8 ) then - call bleaf(cohort_in%dbh,cohort_in%pft,cohort_in%crowndamage,cohort_in%canopy_trim,leaf_c) + call bleaf(cohort_in%dbh,cohort_in%pft,cohort_in%crowndamage,cohort_in%canopy_trim,target_leaf_c) store_c = cohort_in%prt%GetState(store_organ,all_carbon_elements) - call storage_fraction_of_target(leaf_c, store_c, frac) + call storage_fraction_of_target(target_leaf_c, store_c, frac) if( frac .lt. 1._r8) then cmort = max(0.0_r8,EDPftvarcon_inst%mort_scalar_cstarvation(cohort_in%pft) * & (1.0_r8 - frac)) From 71c56b190bf0225fff908a281c21ad11b4c9cecf Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 30 Jun 2022 10:24:50 -0400 Subject: [PATCH 264/852] Inremental change towards damage recovery refactor --- biogeochem/DamageMainMod.F90 | 184 ++++++++++++++++++++++++++++++ main/EDMainMod.F90 | 107 +++++------------ parteh/PRTAllometricCarbonMod.F90 | 84 -------------- 3 files changed, 211 insertions(+), 164 deletions(-) diff --git a/biogeochem/DamageMainMod.F90 b/biogeochem/DamageMainMod.F90 index 6ea408dd82..2330c2ebc0 100644 --- a/biogeochem/DamageMainMod.F90 +++ b/biogeochem/DamageMainMod.F90 @@ -44,6 +44,7 @@ module DamageMainMod public :: IsItDamageTime public :: damage_time public :: GetDamageMortality + public :: DamageRecovery logical :: debug = .false. ! for debugging @@ -60,6 +61,189 @@ module DamageMainMod contains + subroutine DamageRecovery(currentCohort,recoveryCohort) + + !--------------------------------------------------------------------------- + ! JN March 2021 + ! At this point it is possible that damaged cohorts have reached their + ! target allometries. There is a choice now - if they have excess carbon, + ! they can use it to grow along their reduced allometric targets - i.e. + ! dbh and all carbon pools grow out together. OR they can use excess carbon to + ! jump to a lower damage class by changing their target allometry and growing + ! to meet new C pools for same dbh. + ! + ! d = damage class + ! -------------------------------------------------------------------------- + + type(ed_cohort_type) :: currentCohort + type(ed_cohort_type), pointer :: recoveryCohort + + + + if (crowndamage > 1 .and. carbon_balance > calloc_abs_error) then + + if(damage_recovery_scalar > 0.0_r8) then + ! 1. What is excess carbon? + ! carbon_balance + + ! 2. What is biomass required to go from current damage level to next damage level? + + ! mass of this damage class + mass_d = (sum(leaf_c(1:nleafage)) + fnrt_c + store_c + sapw_c + struct_c ) + + ! Target sapwood biomass according to allometry and trimming [kgC] + call bsap_allom(dbh,ipft, crowndamage-1, canopy_trim,sapw_area,targetn_sapw_c) + ! Target total above ground biomass in woody/fibrous tissues [kgC] + call bagw_allom(dbh,ipft, crowndamage-1, targetn_agw_c) + ! Target total below ground biomass in woody/fibrous tissues [kgC] + call bbgw_allom(dbh,ipft,targetn_bgw_c) + ! Target total dead (structrual) biomass [kgC] + call bdead_allom( targetn_agw_c, targetn_bgw_c, targetn_sapw_c, ipft, targetn_struct_c) + ! Target fine-root biomass and deriv. according to allometry and trimming [kgC, kgC/cm] + call bfineroot(dbh,ipft,canopy_trim,targetn_fnrt_c) + ! Target storage carbon [kgC,kgC/cm] + call bstore_allom(dbh,ipft,crowndamage-1, canopy_trim,targetn_store_c) + ! Target leaf biomass according to allometry and trimming + if(leaf_status==2) then + call bleaf(dbh,ipft,crowndamage-1, canopy_trim,targetn_leaf_c) + else + targetn_leaf_c = 0._r8 + end if + + + mass_dminus1 = (max(sum(leaf_c), targetn_leaf_c) + max(fnrt_c, targetn_fnrt_c) + & + max(store_c, targetn_store_c) + max(sapw_c, targetn_sapw_c) + & + max(struct_c, targetn_struct_c)) + + ! Carbon needed to get from current mass to allometric target mass of next damage class up + recovery_demand = mass_dminus1 - mass_d + + ! 3. How many trees can get there with excess carbon? + max_recover_n = carbon_balance * n / recovery_demand + + ! 4. Use the scalar to decide how many to recover + n_recover = max_recover_n * damage_recovery_scalar + + ! carbon balance needs to be updated + + ! there is a special case where damage_recovery_scalar = 1, but + ! max_recover_n > n (i.e. there is more carbon than needed for all + ! individuals to recover to the next damage class. + ! in this case we can cheat, by making n_recover 0 and simply + ! allowing the donor cohort to recover and then go through + ! prt - will this work though? if they are not anywhere near allometry? + + + if(damage_recovery_scalar .eq. 1.0_r8 .and. max_recover_n > n) then + n_recover = 0.0_r8 + crowndamage = crowndamage - 1 + ! call prt from within itself here? + else + carbon_balance = (n * carbon_balance - (recovery_demand * n_recover)) /(n-n_recover) + end if + + ! we reduce number density here and continue on with daily prt for the + ! part of the cohort that is not recovering - staying fixed on its + ! current reduced allometries + n = n - n_recover + + ! Outside of parteh we will copy the cohort and allow the + ! recovery portion to change allometric targets. + + end if ! end if some recovery is permited + end if ! end if crowndamage + !------------------------------------------------------------------------------------ + + + + + + if(currentCohort%crowndamage > 1) then + + ! N is inout boundary condition so has now been updated. The difference must + ! go to a new cohort + n_recover = n_old - currentCohort%n + + if(n_recover > nearzero) then + + allocate(nc) + if(hlm_use_planthydro .eq. itrue) call InitHydrCohort(CurrentSite,nc) + ! Initialize the PARTEH object and point to the + ! correct boundary condition fields + nc%prt => null() + call InitPRTObject(nc%prt) + call InitPRTBoundaryConditions(nc) + ! call zero_cohort(nc) + call copy_cohort(currentCohort, nc) + + nc%n = n_recover + nc%crowndamage = currentCohort%crowndamage - 1 + + ! Need to adjust the crown area which is NOT on a per individual basis + nc%c_area = nc%n/n_old * currentCohort%c_area + currentCohort%c_area = currentCohort%c_area - nc%c_area + + ! This new cohort spends carbon balance on growing out pools + ! (but not dbh) to reach new allometric targets + ! This was already calculated within parteh - this cohort should just + ! be able to hit allometric targets of one damage class down + call nc%prt%DamageRecovery() + + ! at this point we need to update fluxes or this cohort will + ! fail its mass conservation checks + + sapw_c = nc%prt%GetState(sapw_organ, all_carbon_elements) + struct_c = nc%prt%GetState(struct_organ, all_carbon_elements) + leaf_c = nc%prt%GetState(leaf_organ, all_carbon_elements) + fnrt_c = nc%prt%GetState(fnrt_organ, all_carbon_elements) + store_c = nc%prt%GetState(store_organ, all_carbon_elements) + repro_c = nc%prt%GetState(repro_organ, all_carbon_elements) + nc_carbon = sapw_c + struct_c + leaf_c + fnrt_c + store_c + repro_c + + cc_sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) + cc_struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) + cc_leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) + cc_fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) + cc_store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) + cc_repro_c = currentCohort%prt%GetState(repro_organ, all_carbon_elements) + cc_carbon = cc_sapw_c + cc_struct_c + cc_leaf_c + cc_fnrt_c + cc_store_c + cc_repro_c + + + call PRTDamageRecoveryFluxes(nc%prt, leaf_organ, leaf_c0, leaf_c, cc_leaf_c) + call PRTDamageRecoveryFluxes(nc%prt, repro_organ, repro_c0, repro_c, cc_repro_c) + call PRTDamageRecoveryFluxes(nc%prt, sapw_organ, sapw_c0, sapw_c, cc_sapw_c) + call PRTDamageRecoveryFluxes(nc%prt, struct_organ, struct_c0, struct_c, cc_struct_c) + call PRTDamageRecoveryFluxes(nc%prt, store_organ, store_c0, store_c, cc_store_c) + call PRTDamageRecoveryFluxes(nc%prt, fnrt_organ, fnrt_c0, fnrt_c, cc_fnrt_c) + + ! update crown area + call carea_allom(nc%dbh, nc%n, currentSite%spread, nc%pft, nc%crowndamage, nc%c_area) + call carea_allom(currentCohort%dbh, currentCohort%n, currentSite%spread, & + currentCohort%pft, currentCohort%crowndamage, currentCohort%c_area) + + + + !----------- Insert copy into linked list ----------------------! + nc%shorter => currentCohort + if(associated(currentCohort%taller))then + nc%taller => currentCohort%taller + currentCohort%taller%shorter => nc + else + currentPatch%tallest => nc + nc%taller => null() + endif + currentCohort%taller => nc + + end if ! end if greater than nearzero + + end if ! end if crowndamage > 1 + + + + + return + end subroutine DamageRecovery + subroutine IsItDamageTime(is_master, currentSite) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 06b4a3593d..dce23895ae 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -517,91 +517,38 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) total_c0 = sapw_c0 + struct_c0 + leaf_c0 + fnrt_c0 + store_c0 + repro_c0 cc_carbon = 0.0_r8 ! need to set it here to avoid nan errors if conditions aren't met below + + ! We split the allocation into phases (currently for all hypotheses) + ! In phase 1, allocation gets the mass of organs to match targets + ! In phase 2, allocation increases the mass of organs along with stature growth (dbh) + ! The reason why we split is to accomodate the damage code. Following phase 1, + ! we will allow the damage status of the cohorts to potentially recover, if they + ! have any left-over C/N/P resources. In this process, the cohort will be split + ! into two, each having a number count summing to the original. Where one cohort + ! will remain in the original damage class proceed with allocation, and the other + ! will reduce its damage class with new mass tarets. The latter will have to re-play + ! The first phase of allocation. Both cohorts have the opportunity (if resources remain) + ! to grow in stature (phase 2) - call currentCohort%prt%DailyPRT() + call currentCohort%prt%DailyPRT(phase=1) + if(hlm_use_crown_damage .eq. itrue) then + ! The loop order is shortest to tallest + ! The recovered cohort (ie one with larger targets) + ! is newly created in DamageRecovery(), and + ! is inserted into the next position, following the + ! original and current (unrecovered) cohort. + ! we pass it back here in case the pointer is + ! needed for diagnostics + call DamageRecovery(currentCohort,recoveredCohort) + end if + + call currentCohort%prt%DailyPRT(phase=2) + if(hlm_use_crown_damage .eq. itrue) then - if(currentCohort%crowndamage > 1) then - - ! N is inout boundary condition so has now been updated. The difference must - ! go to a new cohort - n_recover = n_old - currentCohort%n - - if(n_recover > nearzero) then - - allocate(nc) - if(hlm_use_planthydro .eq. itrue) call InitHydrCohort(CurrentSite,nc) - ! Initialize the PARTEH object and point to the - ! correct boundary condition fields - nc%prt => null() - call InitPRTObject(nc%prt) - call InitPRTBoundaryConditions(nc) - ! call zero_cohort(nc) - call copy_cohort(currentCohort, nc) - - nc%n = n_recover - nc%crowndamage = currentCohort%crowndamage - 1 - - ! Need to adjust the crown area which is NOT on a per individual basis - nc%c_area = nc%n/n_old * currentCohort%c_area - currentCohort%c_area = currentCohort%c_area - nc%c_area - - ! This new cohort spends carbon balance on growing out pools - ! (but not dbh) to reach new allometric targets - ! This was already calculated within parteh - this cohort should just - ! be able to hit allometric targets of one damage class down - call nc%prt%DamageRecovery() - - ! at this point we need to update fluxes or this cohort will - ! fail its mass conservation checks - - sapw_c = nc%prt%GetState(sapw_organ, all_carbon_elements) - struct_c = nc%prt%GetState(struct_organ, all_carbon_elements) - leaf_c = nc%prt%GetState(leaf_organ, all_carbon_elements) - fnrt_c = nc%prt%GetState(fnrt_organ, all_carbon_elements) - store_c = nc%prt%GetState(store_organ, all_carbon_elements) - repro_c = nc%prt%GetState(repro_organ, all_carbon_elements) - nc_carbon = sapw_c + struct_c + leaf_c + fnrt_c + store_c + repro_c - - cc_sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) - cc_struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) - cc_leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) - cc_fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) - cc_store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) - cc_repro_c = currentCohort%prt%GetState(repro_organ, all_carbon_elements) - cc_carbon = cc_sapw_c + cc_struct_c + cc_leaf_c + cc_fnrt_c + cc_store_c + cc_repro_c - - - call PRTDamageRecoveryFluxes(nc%prt, leaf_organ, leaf_c0, leaf_c, cc_leaf_c) - call PRTDamageRecoveryFluxes(nc%prt, repro_organ, repro_c0, repro_c, cc_repro_c) - call PRTDamageRecoveryFluxes(nc%prt, sapw_organ, sapw_c0, sapw_c, cc_sapw_c) - call PRTDamageRecoveryFluxes(nc%prt, struct_organ, struct_c0, struct_c, cc_struct_c) - call PRTDamageRecoveryFluxes(nc%prt, store_organ, store_c0, store_c, cc_store_c) - call PRTDamageRecoveryFluxes(nc%prt, fnrt_organ, fnrt_c0, fnrt_c, cc_fnrt_c) - - ! update crown area - call carea_allom(nc%dbh, nc%n, currentSite%spread, nc%pft, nc%crowndamage, nc%c_area) - call carea_allom(currentCohort%dbh, currentCohort%n, currentSite%spread, & - currentCohort%pft, currentCohort%crowndamage, currentCohort%c_area) - - - - !----------- Insert copy into linked list ----------------------! - nc%shorter => currentCohort - if(associated(currentCohort%taller))then - nc%taller => currentCohort%taller - currentCohort%taller%shorter => nc - else - currentPatch%tallest => nc - nc%taller => null() - endif - currentCohort%taller => nc - - end if ! end if greater than nearzero - - end if ! end if crowndamage > 1 + end if ! end if crowndamage is on diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index c7f4f449bf..b4194919db 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -670,90 +670,6 @@ subroutine DailyPRTAllometricCarbon(this) ! left to allocate, and thus it must be on allometry when its not. ! ----------------------------------------------------------------------------------- - !----------------------------------------------------------------------------------- - ! JN March 2021 - ! At this point it is possible that damaged cohorts have reached their - ! target allometries. There is a choice now - if they have excess carbon, - ! they can use it to grow along their reduced allometric targets - i.e. - ! dbh and all carbon pools grow out together. OR they can use excess carbon to - ! jump to a lower damage class by changing their target allometry and growing - ! to meet new C pools for same dbh. - ! - ! d = damage class - - if (crowndamage > 1 .and. carbon_balance > calloc_abs_error) then - - if(damage_recovery_scalar > 0.0_r8) then - ! 1. What is excess carbon? - ! carbon_balance - - ! 2. What is biomass required to go from current damage level to next damage level? - - ! mass of this damage class - mass_d = (sum(leaf_c(1:nleafage)) + fnrt_c + store_c + sapw_c + struct_c ) - - ! Target sapwood biomass according to allometry and trimming [kgC] - call bsap_allom(dbh,ipft, crowndamage-1, canopy_trim,sapw_area,targetn_sapw_c) - ! Target total above ground biomass in woody/fibrous tissues [kgC] - call bagw_allom(dbh,ipft, crowndamage-1, targetn_agw_c) - ! Target total below ground biomass in woody/fibrous tissues [kgC] - call bbgw_allom(dbh,ipft,targetn_bgw_c) - ! Target total dead (structrual) biomass [kgC] - call bdead_allom( targetn_agw_c, targetn_bgw_c, targetn_sapw_c, ipft, targetn_struct_c) - ! Target fine-root biomass and deriv. according to allometry and trimming [kgC, kgC/cm] - call bfineroot(dbh,ipft,canopy_trim,targetn_fnrt_c) - ! Target storage carbon [kgC,kgC/cm] - call bstore_allom(dbh,ipft,crowndamage-1, canopy_trim,targetn_store_c) - ! Target leaf biomass according to allometry and trimming - if(leaf_status==2) then - call bleaf(dbh,ipft,crowndamage-1, canopy_trim,targetn_leaf_c) - else - targetn_leaf_c = 0._r8 - end if - - - mass_dminus1 = (max(sum(leaf_c), targetn_leaf_c) + max(fnrt_c, targetn_fnrt_c) + & - max(store_c, targetn_store_c) + max(sapw_c, targetn_sapw_c) + & - max(struct_c, targetn_struct_c)) - - ! Carbon needed to get from current mass to allometric target mass of next damage class up - recovery_demand = mass_dminus1 - mass_d - - ! 3. How many trees can get there with excess carbon? - max_recover_n = carbon_balance * n / recovery_demand - - ! 4. Use the scalar to decide how many to recover - n_recover = max_recover_n * damage_recovery_scalar - - ! carbon balance needs to be updated - - ! there is a special case where damage_recovery_scalar = 1, but - ! max_recover_n > n (i.e. there is more carbon than needed for all - ! individuals to recover to the next damage class. - ! in this case we can cheat, by making n_recover 0 and simply - ! allowing the donor cohort to recover and then go through - ! prt - will this work though? if they are not anywhere near allometry? - - - if(damage_recovery_scalar .eq. 1.0_r8 .and. max_recover_n > n) then - n_recover = 0.0_r8 - crowndamage = crowndamage - 1 - ! call prt from within itself here? - else - carbon_balance = (n * carbon_balance - (recovery_demand * n_recover)) /(n-n_recover) - end if - - ! we reduce number density here and continue on with daily prt for the - ! part of the cohort that is not recovering - staying fixed on its - ! current reduced allometries - n = n - n_recover - - ! Outside of parteh we will copy the cohort and allow the - ! recovery portion to change allometric targets. - - end if ! end if some recovery is permited - end if ! end if crowndamage - !------------------------------------------------------------------------------------ if_stature_growth: if( carbon_balance > calloc_abs_error ) then From 010a95fd300cf9cfde0c5d7574e4f318feb820fe Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 30 Jun 2022 14:38:10 -0400 Subject: [PATCH 265/852] Second pass through splitting allocation and modularizing the recovery code. --- biogeochem/DamageMainMod.F90 | 376 ++++++++++++++++------------- biogeochem/EDCohortDynamicsMod.F90 | 2 - biogeochem/FatesAllometryMod.F90 | 1 - main/EDMainMod.F90 | 185 +++++++------- parteh/PRTAllometricCarbonMod.F90 | 70 +----- 5 files changed, 305 insertions(+), 329 deletions(-) diff --git a/biogeochem/DamageMainMod.F90 b/biogeochem/DamageMainMod.F90 index 2330c2ebc0..650d0f8ddd 100644 --- a/biogeochem/DamageMainMod.F90 +++ b/biogeochem/DamageMainMod.F90 @@ -61,7 +61,7 @@ module DamageMainMod contains - subroutine DamageRecovery(currentCohort,recoveryCohort) + subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) !--------------------------------------------------------------------------- ! JN March 2021 @@ -74,173 +74,219 @@ subroutine DamageRecovery(currentCohort,recoveryCohort) ! ! d = damage class ! -------------------------------------------------------------------------- - - type(ed_cohort_type) :: currentCohort - type(ed_cohort_type), pointer :: recoveryCohort - - - if (crowndamage > 1 .and. carbon_balance > calloc_abs_error) then - - if(damage_recovery_scalar > 0.0_r8) then - ! 1. What is excess carbon? - ! carbon_balance + type(ed_site_type) :: csite ! Site of the current cohort + type(ed_patch_type) :: cpatch ! patch of the current cohort + type(ed_cohort_type) :: ccohort ! Current (damaged) cohort + logical :: newly_recovered ! true if we create a new cohort + + ! locals + type(ed_cohort_type), pointer :: rcohort ! New cohort that recovers by + ! having an lower damage class + real(r8) :: sapw_area + real(r8) :: target_sapw_c,target_sapw_m + real(r8) :: target_agw_c + real(r8) :: target_bgw_c + real(r8) :: target_struct_c,target_struct_m + real(r8) :: target_fnrt_c,target_fnrt_m + real(r8) :: target_leaf_c,target_leaf_m + real(r8) :: target_store_c,target_store_m + real(r8) :: target_repro_m + real(r8) :: mass_d + real(r8) :: mass_dminus1 + real(r8) :: recovery_demand + real(r8) :: max_recover_nplant + real(r8) :: nplant_recover + + associate(dbh => ccohort%dbh, & + ipft => ccohort%pft, & + canopy_trim => ccohort%canopy_trim) + + ! If we are currently undamaged, no recovery + ! necessary, do nothing and return a null pointer + ! If the damage_recovery_scalar is zero, which + ! would be an unusual testing case, but possible, + ! then no recovery is possible, do nothing and + ! return a null pointer + if ((ccohort%crowndamage == undamaged_class) .or. & + (damage_recovery_scalar < nearzero) ) then + newly_recovered = .false. + return + end if + + cpatch => ccohort%patchptr + + + ! If we have not returned, then this cohort both has + ! a damaged status, and the ability to recover from that damage + ! ----------------------------------------------------------------- + + ! To determine recovery, the first priority is to determine how much + ! resources (C,N,P) are required to recover the plant to the target + ! pool sizes of the next (less) damage class + + ! Target sapwood biomass according to allometry and trimming [kgC] + call bsap_allom(dbh,ipft, ccohort%crowndamage-1, canopy_trim,sapw_area,target_sapw_c) + ! Target total above ground biomass in woody/fibrous tissues [kgC] + call bagw_allom(dbh,ipft, ccohort%crowndamage-1, target_agw_c) + ! Target total below ground biomass in woody/fibrous tissues [kgC] + call bbgw_allom(dbh,ipft,target_bgw_c) + ! Target total dead (structrual) biomass [kgC] + call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, ipft, target_struct_c) + ! Target fine-root biomass and deriv. according to allometry and trimming [kgC, kgC/cm] + call bfineroot(dbh,ipft,canopy_trim,target_fnrt_c) + ! Target storage carbon [kgC,kgC/cm] + call bstore_allom(dbh,ipft,crowndamage-1, canopy_trim,target_store_c) + ! Target leaf biomass according to allometry and trimming + if(ccohort%status_coh==leaves_on) then + call bleaf(dbh,ipft,crowndamage-1, canopy_trim,target_leaf_c) + else + target_leaf_c = 0._r8 + end if + + ! We will be taking the number of recovering plants + ! based on minimum of available resources for C/N/P (initialize high) + nplant_recover = 1.e10_r8 + + do el=1,num_elements + + ! Actual mass of chemical species in the organs + leaf_m = ccohort%prt%GetState(leaf_organ, element_list(el)) + store_m = ccohort%prt%GetState(store_organ, element_list(el)) + sapw_m = ccohort%prt%GetState(sapw_organ, element_list(el)) + fnrt_m = ccohort%prt%GetState(fnrt_organ, element_list(el)) + struct_m = ccohort%prt%GetState(struct_organ, element_list(el)) + repro_m = ccohort%prt%GetState(repro_organ, element_list(el)) + + ! Target mass of chemical species in organs, based on stature, + ! allometry and stoichiometry parameters + select case (element_list(el)) + case (carbon12_element) + target_store_m = target_store_c + target_leaf_m = target_leaf_c + target_fnrt_m = target_fnrt_c + target_struct_m = target_struct_c + target_sapw_m = target_sapw_c + target_repro_m = 0._r8 + available_m = ccohort%npp_acc + case (nitrogen_element) + target_struct_m = target_struct_c * & + prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(struct_organ)) + target_leaf_m = target_leaf_c * & + prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(leaf_organ)) + target_fnrt_m = target_fnrt_c * & + prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(fnrt_organ)) + target_sapw_m = target_sapw_c * & + prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(sapw_organ)) + target_repro_m = 0._r8 + target_store_m = StorageNutrientTarget(ipft, element_list(el), & + leaf_target_m, fnrt_target_m, sapw_target_m, struct_target_m) + ! For nutrients, all uptake is immediately put into storage, so just swap + ! them and assume storage is what is available, but needs to be filled up + available_m = store_m + store_m = 0._r8 + case (phosphorus_element) + target_struct_m = target_struct_c * & + prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(struct_organ)) + target_leaf_m = target_leaf_c * & + prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(leaf_organ)) + target_fnrt_m = target_fnrt_c * & + prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(fnrt_organ)) + target_sapw_m = target_sapw_c * & + prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(sapw_organ)) + target_repro_m = 0._r8 + target_store_m = StorageNutrientTarget(ipft, element_list(el), & + leaf_target_m, fnrt_target_m, sapw_target_m, struct_target_m) + end select + + ! 1. What is excess carbon? + ! carbon_balance + + ! 2. What is biomass required to go from current + ! damage level to next damage level? + + ! mass of this damage class + mass_d = leaf_m + store_m + sapw_m + fnrt_m + struct_m + repro_m + + mass_dminus1 = max(leaf_m, target_leaf_m) + max(fnrt_m, target_fnrt_m) + & + max(store_m, target_store_m) + max(sapw_m, target_sapw_m) + & + max(struct_m, target_struct_m)) + + ! Mass needed to get from current mass to allometric + ! target mass of next damage class up + recovery_demand = mass_dminus1 - mass_d + + ! 3. How many trees can get there with excess carbon? + max_recover_nplant = available_m * ccohort%n / recovery_demand + + ! 4. Use the scalar to decide how many to recover + nplant_recover = min(nplant_recover,max(0._r8,max_recover_nplant * damage_recovery_scalar)) + + end do - ! 2. What is biomass required to go from current damage level to next damage level? - - ! mass of this damage class - mass_d = (sum(leaf_c(1:nleafage)) + fnrt_c + store_c + sapw_c + struct_c ) - - ! Target sapwood biomass according to allometry and trimming [kgC] - call bsap_allom(dbh,ipft, crowndamage-1, canopy_trim,sapw_area,targetn_sapw_c) - ! Target total above ground biomass in woody/fibrous tissues [kgC] - call bagw_allom(dbh,ipft, crowndamage-1, targetn_agw_c) - ! Target total below ground biomass in woody/fibrous tissues [kgC] - call bbgw_allom(dbh,ipft,targetn_bgw_c) - ! Target total dead (structrual) biomass [kgC] - call bdead_allom( targetn_agw_c, targetn_bgw_c, targetn_sapw_c, ipft, targetn_struct_c) - ! Target fine-root biomass and deriv. according to allometry and trimming [kgC, kgC/cm] - call bfineroot(dbh,ipft,canopy_trim,targetn_fnrt_c) - ! Target storage carbon [kgC,kgC/cm] - call bstore_allom(dbh,ipft,crowndamage-1, canopy_trim,targetn_store_c) - ! Target leaf biomass according to allometry and trimming - if(leaf_status==2) then - call bleaf(dbh,ipft,crowndamage-1, canopy_trim,targetn_leaf_c) - else - targetn_leaf_c = 0._r8 - end if - - - mass_dminus1 = (max(sum(leaf_c), targetn_leaf_c) + max(fnrt_c, targetn_fnrt_c) + & - max(store_c, targetn_store_c) + max(sapw_c, targetn_sapw_c) + & - max(struct_c, targetn_struct_c)) - - ! Carbon needed to get from current mass to allometric target mass of next damage class up - recovery_demand = mass_dminus1 - mass_d - - ! 3. How many trees can get there with excess carbon? - max_recover_n = carbon_balance * n / recovery_demand - - ! 4. Use the scalar to decide how many to recover - n_recover = max_recover_n * damage_recovery_scalar - - ! carbon balance needs to be updated - - ! there is a special case where damage_recovery_scalar = 1, but - ! max_recover_n > n (i.e. there is more carbon than needed for all - ! individuals to recover to the next damage class. - ! in this case we can cheat, by making n_recover 0 and simply - ! allowing the donor cohort to recover and then go through - ! prt - will this work though? if they are not anywhere near allometry? - - - if(damage_recovery_scalar .eq. 1.0_r8 .and. max_recover_n > n) then - n_recover = 0.0_r8 - crowndamage = crowndamage - 1 - ! call prt from within itself here? - else - carbon_balance = (n * carbon_balance - (recovery_demand * n_recover)) /(n-n_recover) - end if - - ! we reduce number density here and continue on with daily prt for the - ! part of the cohort that is not recovering - staying fixed on its - ! current reduced allometries - n = n - n_recover - - ! Outside of parteh we will copy the cohort and allow the - ! recovery portion to change allometric targets. - - end if ! end if some recovery is permited - end if ! end if crowndamage - !------------------------------------------------------------------------------------ - - - - + ! there is a special case where damage_recovery_scalar = 1, but + ! max_recover_nplant > n (i.e. there is more carbon than needed for all + ! individuals to recover to the next damage class. + ! in this case we can cheat, by making n_recover 0 and simply + ! allowing the donor cohort to recover and then go through + ! prt - will this work though? if they are not anywhere near allometry? + + if( abs(damage_recovery_scalar-1._r8) < nearzero .and. & + nplant_recover > ccohort%n) then + nplant_recover = 0.0_r8 + crowndamage = crowndamage - 1 + end if + + if(nplant_recover < nearzero) then + + newly_recovered = .false. + return + + else + newly_recovered = .true. + allocate(rcohort) + if(hlm_use_planthydro .eq. itrue) call InitHydrCohort(csite,rcohort) + ! Initialize the PARTEH object and point to the + ! correct boundary condition fields + rcohort%prt => null() + call InitPRTObject(rcohort%prt) + call InitPRTBoundaryConditions(rcohort) + call copy_cohort(ccohort, rcohort) + + rcohort%n = nplant_recover + + rcohort%crowndamage = ccohort%crowndamage - 1 + + ! Need to adjust the crown area which is NOT on a per individual basis + call carea_allom(dbh,rcohort%n,site_spread,ipft,rcohort%crowndamage,c_area) + !rcohort%n/n_old * ccohort%c_area + !ccohort%c_area = ccohort%c_area - rcohort%c_area + + ! Update properties of the un-recovered (donor) cohort + ccohort%n = ccohort%n - rcohort%n + ccohort%c_area = ccohort%c_area * ccohort%n / (ccohort%n+rcohort%n) + + !----------- Insert copy into linked list ----------------------! + ! This subroutine is called within a loop in EDMain that + ! proceeds short to tall. We want the newly created cohort + ! to have an opportunity to experience the list, so we add + ! it in the list in a position taller than the current cohort + ! --------------------------------------------------------------! + + rcohort%shorter => ccohort + if(associated(ccohort%taller))then + rcohort%taller => ccohort%taller + ccohort%taller%shorter => rcohort + else + cpatch%tallest => rcohort + rcohort%taller => null() + endif + ccohort%taller => rcohort + + end if ! end if greater than nearzero + + end associate - if(currentCohort%crowndamage > 1) then - - ! N is inout boundary condition so has now been updated. The difference must - ! go to a new cohort - n_recover = n_old - currentCohort%n - - if(n_recover > nearzero) then - - allocate(nc) - if(hlm_use_planthydro .eq. itrue) call InitHydrCohort(CurrentSite,nc) - ! Initialize the PARTEH object and point to the - ! correct boundary condition fields - nc%prt => null() - call InitPRTObject(nc%prt) - call InitPRTBoundaryConditions(nc) - ! call zero_cohort(nc) - call copy_cohort(currentCohort, nc) - - nc%n = n_recover - nc%crowndamage = currentCohort%crowndamage - 1 - - ! Need to adjust the crown area which is NOT on a per individual basis - nc%c_area = nc%n/n_old * currentCohort%c_area - currentCohort%c_area = currentCohort%c_area - nc%c_area - - ! This new cohort spends carbon balance on growing out pools - ! (but not dbh) to reach new allometric targets - ! This was already calculated within parteh - this cohort should just - ! be able to hit allometric targets of one damage class down - call nc%prt%DamageRecovery() - - ! at this point we need to update fluxes or this cohort will - ! fail its mass conservation checks - - sapw_c = nc%prt%GetState(sapw_organ, all_carbon_elements) - struct_c = nc%prt%GetState(struct_organ, all_carbon_elements) - leaf_c = nc%prt%GetState(leaf_organ, all_carbon_elements) - fnrt_c = nc%prt%GetState(fnrt_organ, all_carbon_elements) - store_c = nc%prt%GetState(store_organ, all_carbon_elements) - repro_c = nc%prt%GetState(repro_organ, all_carbon_elements) - nc_carbon = sapw_c + struct_c + leaf_c + fnrt_c + store_c + repro_c - - cc_sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) - cc_struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) - cc_leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) - cc_fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) - cc_store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) - cc_repro_c = currentCohort%prt%GetState(repro_organ, all_carbon_elements) - cc_carbon = cc_sapw_c + cc_struct_c + cc_leaf_c + cc_fnrt_c + cc_store_c + cc_repro_c - - - call PRTDamageRecoveryFluxes(nc%prt, leaf_organ, leaf_c0, leaf_c, cc_leaf_c) - call PRTDamageRecoveryFluxes(nc%prt, repro_organ, repro_c0, repro_c, cc_repro_c) - call PRTDamageRecoveryFluxes(nc%prt, sapw_organ, sapw_c0, sapw_c, cc_sapw_c) - call PRTDamageRecoveryFluxes(nc%prt, struct_organ, struct_c0, struct_c, cc_struct_c) - call PRTDamageRecoveryFluxes(nc%prt, store_organ, store_c0, store_c, cc_store_c) - call PRTDamageRecoveryFluxes(nc%prt, fnrt_organ, fnrt_c0, fnrt_c, cc_fnrt_c) - - ! update crown area - call carea_allom(nc%dbh, nc%n, currentSite%spread, nc%pft, nc%crowndamage, nc%c_area) - call carea_allom(currentCohort%dbh, currentCohort%n, currentSite%spread, & - currentCohort%pft, currentCohort%crowndamage, currentCohort%c_area) - - - - !----------- Insert copy into linked list ----------------------! - nc%shorter => currentCohort - if(associated(currentCohort%taller))then - nc%taller => currentCohort%taller - currentCohort%taller%shorter => nc - else - currentPatch%tallest => nc - nc%taller => null() - endif - currentCohort%taller => nc - - end if ! end if greater than nearzero - - end if ! end if crowndamage > 1 - - - - return end subroutine DamageRecovery diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index c690bf898f..bad98c2eb7 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -314,7 +314,6 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & call InitPRTBoundaryConditions(new_cohort) - ! Allocate running mean functions ! (Keeping as an example) @@ -410,7 +409,6 @@ subroutine InitPRTBoundaryConditions(new_cohort) call new_cohort%prt%RegisterBCInOut(ac_bc_inout_id_dbh,bc_rval = new_cohort%dbh) call new_cohort%prt%RegisterBCInOut(ac_bc_inout_id_netdc,bc_rval = new_cohort%npp_acc) - call new_cohort%prt%RegisterBCInOut(ac_bc_inout_id_n,bc_rval = new_cohort%n) call new_cohort%prt%RegisterBCInOut(ac_bc_inout_id_cdamage,bc_ival = new_cohort%crowndamage) call new_cohort%prt%RegisterBCIn(ac_bc_in_id_pft,bc_ival = new_cohort%pft) call new_cohort%prt%RegisterBCIn(ac_bc_in_id_ctrim,bc_rval = new_cohort%canopy_trim) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index a537be5af3..0766ee645a 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -574,7 +574,6 @@ subroutine bleaf(d,ipft,crowndamage,canopy_trim,bl,dbldd) dbldd = dblmaxdd * canopy_trim end if - if ( crowndamage > 1 ) then call GetCrownReduction(crowndamage, crown_reduction) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index dce23895ae..66c2c5a936 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -427,97 +427,95 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentPatch%age_class = get_age_class_index(currentPatch%age) - ! Update Canopy Biomass Pools + ! Within this loop, we may be creating new cohorts, which + ! are copies of pre-existing cohorts with reduced damage classes. + ! If that is true, we want to bypass some of the things in + ! this loop (such as calculation of npp, etc) because they + ! are derived from the donor and have been modified accordingly + newly_recovered = .false. + currentCohort => currentPatch%shortest do while(associated(currentCohort)) ft = currentCohort%pft - - ! Calculate the mortality derivatives - call Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_primary ) - - ! ----------------------------------------------------------------------------- - ! Apply Plant Allocation and Reactive Transport - ! ----------------------------------------------------------------------------- - ! ----------------------------------------------------------------------------- - ! Identify the net carbon gain for this dynamics interval - ! Set the available carbon pool, identify allocation portions, and - ! decrement the available carbon pool to zero. - ! ----------------------------------------------------------------------------- - - - if (hlm_use_ed_prescribed_phys .eq. itrue) then - if (currentCohort%canopy_layer .eq. 1) then - currentCohort%npp_acc = EDPftvarcon_inst%prescribed_npp_canopy(ft) & - * currentCohort%c_area / currentCohort%n / hlm_days_per_year + + ! Some cohorts are created and inserted to the list while + ! the loop is going. These are pointed to the "taller" position + ! of current, and then inherit properties of their donor (current) + ! we don't need to repeat things before allocation for these + ! newly_recovered cohorts + + if_newlyrecovered: if(.not.newly_recovered) then + + ! Calculate the mortality derivatives + call Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_primary ) + + ! ----------------------------------------------------------------------------- + ! Apply Plant Allocation and Reactive Transport + ! ----------------------------------------------------------------------------- + ! ----------------------------------------------------------------------------- + ! Identify the net carbon gain for this dynamics interval + ! Set the available carbon pool, identify allocation portions, and + ! decrement the available carbon pool to zero. + ! ----------------------------------------------------------------------------- + + if (hlm_use_ed_prescribed_phys .eq. itrue) then + if (currentCohort%canopy_layer .eq. 1) then + currentCohort%npp_acc = EDPftvarcon_inst%prescribed_npp_canopy(ft) & + * currentCohort%c_area / currentCohort%n / hlm_days_per_year + else + currentCohort%npp_acc = EDPftvarcon_inst%prescribed_npp_understory(ft) & + * currentCohort%c_area / currentCohort%n / hlm_days_per_year + endif + + ! We don't explicitly define a respiration rate for prescribe phys + ! but we do need to pass mass balance. So we say it is zero respiration + currentCohort%gpp_acc = currentCohort%npp_acc + currentCohort%resp_acc = 0._r8 + + end if + + ! ----------------------------------------------------------------------------- + ! Save NPP/GPP/R in these "hold" style variables. These variables + ! persist after this routine is complete, and used in I/O diagnostics. + ! Whereas the _acc style variables are zero'd because they are key + ! accumulation state variables. + ! + ! convert from kgC/indiv/day into kgC/indiv/year + ! _acc_hold is remembered until the next dynamics step (used for I/O) + ! _acc will be reset soon and will be accumulated on the next leaf + ! photosynthesis step + ! ----------------------------------------------------------------------------- + + currentCohort%npp_acc_hold = currentCohort%npp_acc * real(hlm_days_per_year,r8) + currentCohort%gpp_acc_hold = currentCohort%gpp_acc * real(hlm_days_per_year,r8) + currentCohort%resp_acc_hold = currentCohort%resp_acc * real(hlm_days_per_year,r8) + + ! Conduct Maintenance Turnover (parteh) + if(debug) call currentCohort%prt%CheckMassConservation(ft,3) + if(any(currentSite%dstatus == [phen_dstat_moiston,phen_dstat_timeon])) then + is_drought = .false. else - currentCohort%npp_acc = EDPftvarcon_inst%prescribed_npp_understory(ft) & - * currentCohort%c_area / currentCohort%n / hlm_days_per_year - endif - - ! We don't explicitly define a respiration rate for prescribe phys - ! but we do need to pass mass balance. So we say it is zero respiration - currentCohort%gpp_acc = currentCohort%npp_acc - currentCohort%resp_acc = 0._r8 - - end if - - ! ----------------------------------------------------------------------------- - ! Save NPP/GPP/R in these "hold" style variables. These variables - ! persist after this routine is complete, and used in I/O diagnostics. - ! Whereas the _acc style variables are zero'd because they are key - ! accumulation state variables. - ! - ! convert from kgC/indiv/day into kgC/indiv/year - ! _acc_hold is remembered until the next dynamics step (used for I/O) - ! _acc will be reset soon and will be accumulated on the next leaf - ! photosynthesis step - ! ----------------------------------------------------------------------------- - - currentCohort%npp_acc_hold = currentCohort%npp_acc * real(hlm_days_per_year,r8) - currentCohort%gpp_acc_hold = currentCohort%gpp_acc * real(hlm_days_per_year,r8) - currentCohort%resp_acc_hold = currentCohort%resp_acc * real(hlm_days_per_year,r8) - - - ! Conduct Maintenance Turnover (parteh) - if(debug) call currentCohort%prt%CheckMassConservation(ft,3) - if(any(currentSite%dstatus == [phen_dstat_moiston,phen_dstat_timeon])) then - is_drought = .false. - else - is_drought = .true. - end if - - call PRTMaintTurnover(currentCohort%prt,ft,is_drought) - - ! If the current diameter of a plant is somehow less than what is consistent - ! with what is allometrically consistent with the stuctural biomass, then - ! correct the dbh to match. - + is_drought = .true. + end if + + call PRTMaintTurnover(currentCohort%prt,ft,is_drought) + + ! If the current diameter of a plant is somehow less than what is consistent + ! with what is allometrically consistent with the stuctural biomass, then + ! correct the dbh to match. + + end if if_newlyrecovered + call EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) - + hite_old = currentCohort%hite dbh_old = currentCohort%dbh - + ! ----------------------------------------------------------------------------- ! Growth and Allocation (PARTEH) ! ----------------------------------------------------------------------------- - ! cohorts will be split during this phase to allow some fraction to recover - ! keep track of starting population - n_old = currentCohort%n - - ! track initial carbon pools - - leaf_c0 = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) - fnrt_c0 = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) - sapw_c0 = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) - struct_c0 = currentCohort%prt%GetState(struct_organ, all_carbon_elements) - store_c0 = currentCohort%prt%GetState(store_organ, all_carbon_elements) - repro_c0 = currentCohort%prt%GetState(repro_organ, all_carbon_elements) - - total_c0 = sapw_c0 + struct_c0 + leaf_c0 + fnrt_c0 + store_c0 + repro_c0 - cc_carbon = 0.0_r8 ! need to set it here to avoid nan errors if conditions aren't met below - ! We split the allocation into phases (currently for all hypotheses) ! In phase 1, allocation gets the mass of organs to match targets ! In phase 2, allocation increases the mass of organs along with stature growth (dbh) @@ -531,8 +529,9 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! to grow in stature (phase 2) call currentCohort%prt%DailyPRT(phase=1) - if(hlm_use_crown_damage .eq. itrue) then - + + if((newly_recovered .eq. .false.) .and. & + (hlm_use_crown_damage .eq. itrue) ) then ! The loop order is shortest to tallest ! The recovered cohort (ie one with larger targets) ! is newly created in DamageRecovery(), and @@ -540,19 +539,22 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! original and current (unrecovered) cohort. ! we pass it back here in case the pointer is ! needed for diagnostics - call DamageRecovery(currentCohort,recoveredCohort) + call DamageRecovery(currentSite,currentPatch,currentCohort,newly_recovered) + + ! New targets may have been issued (based on damage status). If so, + ! we need to repeat phase 1 of allocation. This only happens if + ! the cohort is NOT split, and the whole thing graduates to a lesser + ! damage class + if(.not.newly_recovered)then + call currentCohort%prt%DailyPRT(phase=1) + end if + + else + newly_recovered = .false. end if call currentCohort%prt%DailyPRT(phase=2) - - if(hlm_use_crown_damage .eq. itrue) then - - - - end if ! end if crowndamage is on - - ! Update the mass balance tracking for the daily nutrient uptake flux ! Then zero out the daily uptakes, they have been used ! ----------------------------------------------------------------------------- @@ -688,11 +690,8 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) call coagetype_class_index(currentCohort%coage, currentCohort%pft, & currentCohort%coage_class,currentCohort%coage_by_pft_class) end if - currentCohort => currentCohort%taller - - end do currentPatch => currentPatch%older diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index b4194919db..746ca38ebf 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -90,9 +90,8 @@ module PRTAllometricCarbonMod integer, public, parameter :: ac_bc_inout_id_dbh = 1 ! Plant DBH integer, public, parameter :: ac_bc_inout_id_netdc = 2 ! Index for the net daily C input BC - integer, public, parameter :: ac_bc_inout_id_n = 3 ! Number of plants - integer, public, parameter :: ac_bc_inout_id_cdamage = 4 ! Index for the crowndamage input BC - integer, parameter :: num_bc_inout = 4 ! Number of in & output boundary conditions + integer, public, parameter :: ac_bc_inout_id_cdamage = 3 ! Index for the crowndamage input BC + integer, parameter :: num_bc_inout = 3 ! Number of in & output boundary conditions integer, public, parameter :: ac_bc_in_id_pft = 1 ! Index for the PFT input BC @@ -434,7 +433,6 @@ subroutine DailyPRTAllometricCarbon(this) dbh => this%bc_inout(ac_bc_inout_id_dbh)%rval carbon_balance => this%bc_inout(ac_bc_inout_id_netdc)%rval - n => this%bc_inout(ac_bc_inout_id_n)%rval crowndamage => this%bc_inout(ac_bc_inout_id_cdamage)%ival canopy_trim = this%bc_in(ac_bc_in_id_ctrim)%rval @@ -1152,70 +1150,6 @@ subroutine FastPRTAllometricCarbon(this) return end subroutine FastPRTAllometricCarbon - !------------------------------------------------------------------------------- - - subroutine PRTDamageRecovery(this) - ! ---------------------------------------------------------------------------------- - ! We are assigning mass to each organ based on the allometric targets - ! ---------------------------------------------------------------------------------- - class(callom_prt_vartypes) :: this - - - real(r8),pointer :: dbh - integer, pointer :: crowndamage - real(r8) :: canopy_trim - integer :: ipft - real(r8) :: target_leaf_c ! target leaf carbon [kgC] - real(r8) :: target_fnrt_c ! target fine-root carbon [kgC] - real(r8) :: target_sapw_c ! target sapwood carbon [kgC] - real(r8) :: target_store_c ! target storage carbon [kgC] - real(r8) :: target_agw_c ! target above ground carbon in woody tissues [kgC] - real(r8) :: target_bgw_c ! target below ground carbon in woody tissues [kgC] - real(r8) :: target_struct_c ! target structural carbon [kgC] - real(r8) :: sapw_area ! dummy var, x-section area of sapwood [m2] - integer :: leaf_status - real(r8) :: leaf_c_flux - integer, parameter :: iexp_leaf = 1 ! index 1 is the expanding leaf age class and - ! therefore all new carbon goes into that pool - - associate ( & - leaf_c => this%variables(leaf_c_id)%val, & - fnrt_c => this%variables(fnrt_c_id)%val(icd), & - sapw_c => this%variables(sapw_c_id)%val(icd), & - store_c => this%variables(store_c_id)%val(icd), & - repro_c => this%variables(repro_c_id)%val(icd), & - struct_c => this%variables(struct_c_id)%val(icd)) - - dbh => this%bc_inout(ac_bc_inout_id_dbh)%rval - crowndamage => this%bc_inout(ac_bc_inout_id_cdamage)%ival - canopy_trim = this%bc_in(ac_bc_in_id_ctrim)%rval - ipft = this%bc_in(ac_bc_in_id_pft)%ival - leaf_status = this%bc_in(ac_bc_in_id_lstat)%ival - - ! Get allometric targets for this dbh and crown damage class - call bsap_allom(dbh, ipft, crowndamage, canopy_trim, sapw_area, target_sapw_c) - call bagw_allom(dbh, ipft, crowndamage, target_agw_c) - call bbgw_allom(dbh, ipft, target_bgw_c) - call bdead_allom(target_agw_c, target_bgw_c, target_sapw_c, ipft, target_struct_c) - if(leaf_status ==2)then - call bleaf(dbh, ipft, crowndamage, canopy_trim, target_leaf_c) - else - target_leaf_c = 0.0_r8 - end if - call bfineroot(dbh, ipft, canopy_trim, target_fnrt_c) - call bstore_allom(dbh, ipft,crowndamage, canopy_trim, target_store_c) - - ! Now we assign these targets to the actual biomass pools - fnrt_c = max(target_fnrt_c, fnrt_c) - store_c = max(target_store_c, store_c) - sapw_c = max(target_sapw_c, sapw_c) - struct_c = max(target_struct_c, struct_c) - leaf_c_flux = target_leaf_c - sum(leaf_c) - leaf_c(iexp_leaf) = leaf_c(iexp_leaf) + leaf_c_flux - - end associate - end subroutine PRTDamageRecovery - ! ===================================================================================== end module PRTAllometricCarbonMod From 02b661a7254bb57813f247bd4d573ccb304ff014 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 30 Jun 2022 14:45:25 -0400 Subject: [PATCH 266/852] Minor updates to damage recovery --- biogeochem/DamageMainMod.F90 | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/biogeochem/DamageMainMod.F90 b/biogeochem/DamageMainMod.F90 index 650d0f8ddd..d015cc79ea 100644 --- a/biogeochem/DamageMainMod.F90 +++ b/biogeochem/DamageMainMod.F90 @@ -114,8 +114,6 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) return end if - cpatch => ccohort%patchptr - ! If we have not returned, then this cohort both has ! a damaged status, and the ability to recover from that damage @@ -197,6 +195,10 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) target_repro_m = 0._r8 target_store_m = StorageNutrientTarget(ipft, element_list(el), & leaf_target_m, fnrt_target_m, sapw_target_m, struct_target_m) + ! For nutrients, all uptake is immediately put into storage, so just swap + ! them and assume storage is what is available, but needs to be filled up + available_m = store_m + store_m = 0._r8 end select ! 1. What is excess carbon? @@ -258,7 +260,7 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) rcohort%crowndamage = ccohort%crowndamage - 1 ! Need to adjust the crown area which is NOT on a per individual basis - call carea_allom(dbh,rcohort%n,site_spread,ipft,rcohort%crowndamage,c_area) + call carea_allom(dbh,rcohort%n,csite%spread,ipft,rcohort%crowndamage,rcohort%c_area) !rcohort%n/n_old * ccohort%c_area !ccohort%c_area = ccohort%c_area - rcohort%c_area From db144732cef952429a6c2ca3293aeb5f09eb7b8c Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 30 Jun 2022 17:02:52 -0400 Subject: [PATCH 267/852] Applying the phase argument to carbon allocation in parteh --- biogeochem/DamageMainMod.F90 | 12 +- main/EDMainMod.F90 | 21 +- parteh/PRTAllometricCarbonMod.F90 | 954 +++++++++++++++--------------- parteh/PRTGenericMod.F90 | 5 +- 4 files changed, 491 insertions(+), 501 deletions(-) diff --git a/biogeochem/DamageMainMod.F90 b/biogeochem/DamageMainMod.F90 index d015cc79ea..c2cef680e4 100644 --- a/biogeochem/DamageMainMod.F90 +++ b/biogeochem/DamageMainMod.F90 @@ -346,9 +346,9 @@ subroutine IsItDamageTime(is_master, currentSite) else if(icode > 10000 ) then ! Specific Event: YYYYMMDD - damage_date = icode - int(100* floor(real(icode)/100)) - damage_year = floor(real(icode)/10000) - damage_month = floor(real(icode)/100) - damage_year*100 + damage_date = icode - int(100* floor(real(icode,r8)/100._r8)) + damage_year = floor(real(icode,r8)/10000._r8) + damage_month = floor(real(icode,r8)/100._r8) - damage_year*100 if(hlm_current_day .eq. damage_date .and. & hlm_current_month .eq. damage_month .and. & @@ -422,7 +422,7 @@ subroutine GetCrownReduction(crowndamage, crown_reduction) real(r8) :: class_width class_width = 1.0_r8/nlevdamage - crown_reduction = min(1.0_r8, (real(crowndamage) - 1.0_r8) * class_width) + crown_reduction = min(1.0_r8, (real(crowndamage,r8) - 1.0_r8) * class_width) return end subroutine GetCrownReduction @@ -446,7 +446,7 @@ subroutine GetDamageMortality(crowndamage,pft, dgmort) real(r8) :: class_width real(r8) :: crown_loss - class_width = 1.0_r8/real(nlevdamage) + class_width = 1.0_r8/real(nlevdamage,r8) ! parameter to determine slope of exponential damage_mort_p1 = EDPftvarcon_inst%damage_mort_p1(pft) @@ -455,7 +455,7 @@ subroutine GetDamageMortality(crowndamage,pft, dgmort) ! make damage mortality a function of crownloss and not crowndamage ! class so that it doesn't need to be re-parameterised if the number ! of damage classes change. - crown_loss = min(1.0_r8, (real(crowndamage) - 1.0_r8) * class_width) + crown_loss = min(1.0_r8, (real(crowndamage,r8) - 1.0_r8) * class_width) if (crowndamage .eq. 1 ) then dgmort = 0.0_r8 diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 66c2c5a936..03e9903de8 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -445,7 +445,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! we don't need to repeat things before allocation for these ! newly_recovered cohorts - if_newlyrecovered: if(.not.newly_recovered) then + if_not_newlyrecovered: if(.not.newly_recovered) then ! Calculate the mortality derivatives call Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_primary ) @@ -500,13 +500,22 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) end if call PRTMaintTurnover(currentCohort%prt,ft,is_drought) - - ! If the current diameter of a plant is somehow less than what is consistent - ! with what is allometrically consistent with the stuctural biomass, then - ! correct the dbh to match. - end if if_newlyrecovered + + ! ----------------------------------------------------------------------------------- + ! Call the routine that advances leaves in age. + ! This will move a portion of the leaf mass in each + ! age bin, to the next bin. This will not handle movement + ! of mass from the oldest bin into the litter pool, that is something else. + ! ----------------------------------------------------------------------------------- + call currentCohort%prt%AgeLeaves(ft,sec_per_day) + + end if if_not_newlyrecovered + + ! If the current diameter of a plant is somehow less than what is consistent + ! with what is allometrically consistent with the stuctural biomass, then + ! correct the dbh to match. call EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) hite_old = currentCohort%hite diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 746ca38ebf..d2bce65d35 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -125,7 +125,6 @@ module PRTAllometricCarbonMod procedure :: DailyPRT => DailyPRTAllometricCarbon procedure :: FastPRT => FastPRTAllometricCarbon - procedure :: DamageRecovery => PRTDamageRecovery end type callom_prt_vartypes @@ -244,7 +243,7 @@ end subroutine InitPRTGlobalAllometricCarbon ! ===================================================================================== - subroutine DailyPRTAllometricCarbon(this) + subroutine DailyPRTAllometricCarbon(this,phase) ! ----------------------------------------------------------------------------------- ! @@ -286,25 +285,26 @@ subroutine DailyPRTAllometricCarbon(this) ! ! ---------------------------------------------------------------------------------- - - ! The class is the only argument + class(callom_prt_vartypes) :: this ! this class + integer,intent(in) :: phase ! the phase splits the routine into parts + ! ----------------------------------------------------------------------------------- ! These are local copies of the in/out boundary condition structure ! ----------------------------------------------------------------------------------- real(r8),pointer :: dbh ! Diameter at breast height [cm] - ! this local will point to both in and out bc's + ! this local will point to both in and out bc's real(r8),pointer :: carbon_balance ! Daily carbon balance for this cohort [kgC] real(r8), pointer :: n ! number of plants integer, pointer :: crowndamage ! which crown damage class - - + + real(r8) :: canopy_trim ! The canopy trimming function [0-1] integer :: ipft ! Plant Functional Type index - + real(r8) :: target_leaf_c ! target leaf carbon [kgC] real(r8) :: target_fnrt_c ! target fine-root carbon [kgC] real(r8) :: target_sapw_c ! target sapwood carbon [kgC] @@ -323,14 +323,14 @@ subroutine DailyPRTAllometricCarbon(this) real(r8) :: total_below_target ! total biomass below the allometric target [kgC] real(r8) :: allocation_factor ! allocation factor (relative to demand) to - ! reconstruct tissues + ! reconstruct tissues real(r8) :: flux_adj ! adjustment made to growth flux term to minimize error [kgC] real(r8) :: store_target_fraction ! ratio between storage and leaf biomass when on allometry [kgC] real(r8) :: leaf_c_demand ! leaf carbon that is demanded to replace maintenance turnover [kgC] real(r8) :: fnrt_c_demand ! fineroot carbon that is demanded to replace - ! maintenance turnover [kgC] + ! maintenance turnover [kgC] real(r8) :: total_c_demand ! total carbon that is demanded to replace maintenance turnover [kgC] logical :: step_pass ! Did the integration step pass? @@ -343,7 +343,7 @@ subroutine DailyPRTAllometricCarbon(this) real(r8),dimension(max_nleafage) :: leaf_c0 - ! Initial value of carbon used to determine net flux + ! Initial value of carbon used to determine net flux real(r8) :: fnrt_c0 ! during this routine real(r8) :: sapw_c0 ! "" real(r8) :: store_c0 ! "" @@ -356,7 +356,7 @@ subroutine DailyPRTAllometricCarbon(this) logical :: grow_sapw ! Is sapwood at allometric target and should be grown? logical :: grow_store ! Is storage at allometric target and should be grown? - ! integrator variables + ! integrator variables real(r8) :: deltaC ! trial value for substep integer :: ierr ! error flag for allometric growth step integer :: nsteps ! number of sub-steps @@ -370,22 +370,6 @@ subroutine DailyPRTAllometricCarbon(this) integer :: leaf_status ! are leaves on (2) or off (1) real(r8) :: leaf_age_flux ! carbon mass flux between leaf age classification pools - ! for recovery dynamics - real(r8) :: mass_d - real(r8) :: mass_dminus1 - real(r8) :: recovery_demand - real(r8) :: targetn_sapw_c - real(r8) :: targetn_agw_c - real(r8) :: targetn_bgw_c - real(r8) :: targetn_struct_c - real(r8) :: targetn_leaf_c - real(r8) :: targetn_store_c - real(r8) :: targetn_fnrt_c - real(r8) :: max_recover_n - real(r8) :: n_recover - real(r8) :: damage_recovery_scalar - real(r8) :: carbon_balance2 - ! Integegrator variables c_pool is "mostly" carbon variables, it also includes ! dbh... ! ----------------------------------------------------------------------------------- @@ -401,501 +385,497 @@ subroutine DailyPRTAllometricCarbon(this) integer, parameter :: ODESolve = 2 ! 1=RKF45, 2=Euler integer, parameter :: iexp_leaf = 1 ! index 1 is the expanding (i.e. youngest) - ! leaf age class, and therefore - ! all new allocation goes into that pool + ! leaf age class, and therefore + ! all new allocation goes into that pool character(len= 9), parameter :: fmti = '(a,1x,i5)' character(len=13), parameter :: fmt0 = '(a,1x,es12.5)' character(len=19), parameter :: fmth = '(a,1x,a5,3(1x,a12))' character(len=22), parameter :: fmtg = '(a,5x,l1,3(1x,es12.5))' real(r8) :: intgr_params(num_bc_in+1) ! The boundary conditions to this routine, - ! are pressed into an array that is also - ! passed to the integrators - ! add one because we pass crown damage also - ! which is not a bc_in - + ! are pressed into an array that is also + ! passed to the integrators + ! add one because we pass crown damage also + ! which is not a bc_in - associate( & + associate( & + leaf_c => this%variables(leaf_c_id)%val, & - fnrt_c => this%variables(fnrt_c_id)%val(icd), & - sapw_c => this%variables(sapw_c_id)%val(icd), & - store_c => this%variables(store_c_id)%val(icd), & - repro_c => this%variables(repro_c_id)%val(icd), & - struct_c => this%variables(struct_c_id)%val(icd)) + fnrt_c => this%variables(fnrt_c_id)%val(icd), & + sapw_c => this%variables(sapw_c_id)%val(icd), & + store_c => this%variables(store_c_id)%val(icd), & + repro_c => this%variables(repro_c_id)%val(icd), & + struct_c => this%variables(struct_c_id)%val(icd)) - ! ----------------------------------------------------------------------------------- - ! 0. - ! Copy the boundary conditions into readable local variables. - ! We don't use pointers for bc's that ar "in" only, only "in-out" and "out" - ! ----------------------------------------------------------------------------------- + ! ----------------------------------------------------------------------------------- + ! 0. + ! Copy the boundary conditions into readable local variables. + ! We don't use pointers for bc's that ar "in" only, only "in-out" and "out" + ! ----------------------------------------------------------------------------------- + + dbh => this%bc_inout(ac_bc_inout_id_dbh)%rval + carbon_balance => this%bc_inout(ac_bc_inout_id_netdc)%rval + crowndamage => this%bc_inout(ac_bc_inout_id_cdamage)%ival + + canopy_trim = this%bc_in(ac_bc_in_id_ctrim)%rval + ipft = this%bc_in(ac_bc_in_id_pft)%ival + leaf_status = this%bc_in(ac_bc_in_id_lstat)%ival + + nleafage = prt_global%state_descriptor(leaf_c_id)%num_pos ! Number of leaf age class - dbh => this%bc_inout(ac_bc_inout_id_dbh)%rval - carbon_balance => this%bc_inout(ac_bc_inout_id_netdc)%rval - crowndamage => this%bc_inout(ac_bc_inout_id_cdamage)%ival - - canopy_trim = this%bc_in(ac_bc_in_id_ctrim)%rval - ipft = this%bc_in(ac_bc_in_id_pft)%ival - leaf_status = this%bc_in(ac_bc_in_id_lstat)%ival - - intgr_params(:) = un_initialized - intgr_params(ac_bc_in_id_ctrim) = this%bc_in(ac_bc_in_id_ctrim)%rval - intgr_params(ac_bc_in_id_pft) = real(this%bc_in(ac_bc_in_id_pft)%ival) - intgr_params(num_bc_in + 1) = real(this%bc_inout(ac_bc_inout_id_cdamage)%ival) - - nleafage = prt_global%state_descriptor(leaf_c_id)%num_pos ! Number of leaf age class - damage_recovery_scalar = prt_params%damage_recovery_scalar(ipft) - - ! ----------------------------------------------------------------------------------- - ! Call the routine that advances leaves in age. - ! This will move a portion of the leaf mass in each - ! age bin, to the next bin. This will not handle movement - ! of mass from the oldest bin into the litter pool, that is something else. - ! ----------------------------------------------------------------------------------- - call this%AgeLeaves(ipft,sec_per_day) + ! ----------------------------------------------------------------------------------- + ! I. Remember the values for the state variables at the beginning of this + ! routines. We will then use that to determine their net allocation and reactive + ! transport flux "%net_alloc" at the end. + ! ----------------------------------------------------------------------------------- + + leaf_c0(1:nleafage) = leaf_c(1:nleafage) ! Set initial leaf carbon + fnrt_c0 = fnrt_c ! Set initial fine-root carbon + sapw_c0 = sapw_c ! Set initial sapwood carbon + store_c0 = store_c ! Set initial storage carbon + repro_c0 = repro_c ! Set initial reproductive carbon + struct_c0 = struct_c ! Set initial structural carbon + + ! ----------------------------------------------------------------------------------- + ! II. Calculate target size of the biomass compartment for a given dbh. + ! ----------------------------------------------------------------------------------- - ! ----------------------------------------------------------------------------------- - ! I. Remember the values for the state variables at the beginning of this - ! routines. We will then use that to determine their net allocation and reactive - ! transport flux "%net_alloc" at the end. - ! ----------------------------------------------------------------------------------- - - leaf_c0(1:nleafage) = leaf_c(1:nleafage) ! Set initial leaf carbon - fnrt_c0 = fnrt_c ! Set initial fine-root carbon - sapw_c0 = sapw_c ! Set initial sapwood carbon - store_c0 = store_c ! Set initial storage carbon - repro_c0 = repro_c ! Set initial reproductive carbon - struct_c0 = struct_c ! Set initial structural carbon + ! Target sapwood biomass according to allometry and trimming [kgC] + call bsap_allom(dbh,ipft, crowndamage, canopy_trim,sapw_area,target_sapw_c) - ! ----------------------------------------------------------------------------------- - ! II. Calculate target size of the biomass compartment for a given dbh. - ! ----------------------------------------------------------------------------------- - - ! Target sapwood biomass according to allometry and trimming [kgC] - call bsap_allom(dbh,ipft, crowndamage, canopy_trim,sapw_area,target_sapw_c) - - ! Target total above ground biomass in woody/fibrous tissues [kgC] - call bagw_allom(dbh,ipft, crowndamage, target_agw_c) - - ! Target total below ground biomass in woody/fibrous tissues [kgC] - call bbgw_allom(dbh,ipft,target_bgw_c) - - ! Target total dead (structrual) biomass [kgC] - call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, ipft, target_struct_c) - - ! Target leaf biomass according to allometry and trimming - select case (leaf_status) - case (leaves_on) - call bleaf(dbh,ipft,crowndamage,canopy_trim,target_leaf_c) - case (leaves_off) - target_leaf_c = 0._r8 - end select - - ! Target fine-root biomass and deriv. according to allometry and trimming [kgC, kgC/cm] - call bfineroot(dbh,ipft,canopy_trim,target_fnrt_c) - - ! Target storage carbon [kgC,kgC/cm] - call bstore_allom(dbh,ipft,crowndamage,canopy_trim,target_store_c) + ! Target total above ground biomass in woody/fibrous tissues [kgC] + call bagw_allom(dbh,ipft, crowndamage, target_agw_c) + + ! Target total below ground biomass in woody/fibrous tissues [kgC] + call bbgw_allom(dbh,ipft,target_bgw_c) + + ! Target total dead (structrual) biomass [kgC] + call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, ipft, target_struct_c) + + ! Target leaf biomass according to allometry and trimming + select case (leaf_status) + case (leaves_on) + call bleaf(dbh,ipft,crowndamage,canopy_trim,target_leaf_c) + case (leaves_off) + target_leaf_c = 0._r8 + end select + + ! Target fine-root biomass and deriv. according to allometry and trimming [kgC, kgC/cm] + call bfineroot(dbh,ipft,canopy_trim,target_fnrt_c) + ! Target storage carbon [kgC,kgC/cm] + call bstore_allom(dbh,ipft,crowndamage,canopy_trim,target_store_c) - ! ----------------------------------------------------------------------------------- - ! III. Prioritize some amount of carbon to replace leaf/root turnover - ! Make sure it isn't a negative payment, and either pay what is available - ! or forcefully pay from storage. - ! ----------------------------------------------------------------------------------- - - if( prt_params%evergreen(ipft) == itrue ) then - leaf_c_demand = max(0.0_r8, & - prt_params%leaf_stor_priority(ipft)*sum(this%variables(leaf_c_id)%turnover(:))) - else - leaf_c_demand = 0.0_r8 - end if - - fnrt_c_demand = max(0.0_r8, & - prt_params%leaf_stor_priority(ipft)*this%variables(fnrt_c_id)%turnover(icd)) - - total_c_demand = leaf_c_demand + fnrt_c_demand - - if (total_c_demand > nearzero) then - - ! We pay this even if we don't have the carbon - ! Just don't pay so much carbon that storage+carbon_balance can't pay for it - allocation_factor = max(0.0_r8,min(1.0_r8,(store_c+carbon_balance)/total_c_demand)) - - ! MLO. Edited the code to switch the order of operations. The previous code would - ! subtract leaf flux from carbon balance before estimating the fine root flux, - ! potentially allowing less fluxes to fine roots than possible. - leaf_c_flux = leaf_c_demand * allocation_factor - fnrt_c_flux = fnrt_c_demand * allocation_factor - - ! Add carbon to the youngest age pool (i.e iexp_leaf = index 1) and fine roots - leaf_c(iexp_leaf) = leaf_c(iexp_leaf) + leaf_c_flux - fnrt_c = fnrt_c + fnrt_c_flux - - ! Remove fluxes from carbon balance. In case we may have drawn carbon from storage, - ! carbon_balance will become negative, in which case we will deplete carbon from - ! storage in the next step. - carbon_balance = carbon_balance - ( leaf_c_flux + fnrt_c_flux ) - end if + ! ----------------------------------------------------------------------------------- + ! Phase 1: Replace losses, push pools towards targets + ! ----------------------------------------------------------------------------------- - ! ----------------------------------------------------------------------------------- - ! IV. if carbon balance is negative, re-coup the losses from storage - ! if it is positive, give some love to storage carbon - ! ----------------------------------------------------------------------------------- + if_phase: if(phase.eq.1) then - if( carbon_balance < 0.0_r8 ) then + ! III. Prioritize some amount of carbon to replace leaf/root turnover + ! Make sure it isn't a negative payment, and either pay what is available + ! or forcefully pay from storage. + ! ----------------------------------------------------------------------------------- + + if( prt_params%evergreen(ipft) == itrue ) then + leaf_c_demand = max(0.0_r8, & + prt_params%leaf_stor_priority(ipft)*sum(this%variables(leaf_c_id)%turnover(:))) + else + leaf_c_demand = 0.0_r8 + end if + + fnrt_c_demand = max(0.0_r8, & + prt_params%leaf_stor_priority(ipft)*this%variables(fnrt_c_id)%turnover(icd)) - ! Store_c_flux will be negative, so store_c will be depleted - store_c_flux = carbon_balance - carbon_balance = carbon_balance - store_c_flux - store_c = store_c + store_c_flux + total_c_demand = leaf_c_demand + fnrt_c_demand + + if (total_c_demand > nearzero) then - else + ! We pay this even if we don't have the carbon + ! Just don't pay so much carbon that storage+carbon_balance can't pay for it + allocation_factor = max(0.0_r8,min(1.0_r8,(store_c+carbon_balance)/total_c_demand)) + + ! MLO. Edited the code to switch the order of operations. The previous code would + ! subtract leaf flux from carbon balance before estimating the fine root flux, + ! potentially allowing less fluxes to fine roots than possible. + leaf_c_flux = leaf_c_demand * allocation_factor + fnrt_c_flux = fnrt_c_demand * allocation_factor + + ! Add carbon to the youngest age pool (i.e iexp_leaf = index 1) and fine roots + leaf_c(iexp_leaf) = leaf_c(iexp_leaf) + leaf_c_flux + fnrt_c = fnrt_c + fnrt_c_flux + + ! Remove fluxes from carbon balance. In case we may have drawn carbon from storage, + ! carbon_balance will become negative, in which case we will deplete carbon from + ! storage in the next step. + carbon_balance = carbon_balance - ( leaf_c_flux + fnrt_c_flux ) + end if + + ! ----------------------------------------------------------------------------------- + ! IV. if carbon balance is negative, re-coup the losses from storage + ! if it is positive, give some love to storage carbon + ! ----------------------------------------------------------------------------------- - ! Accumulate some carbon in storage. If storage is completely depleted, aim to - ! increase storage, but not to replenish completely so we can still use some - ! carbon for growth. - store_below_target = max(0.0_r8,target_store_c - store_c) - store_target_fraction = max(0.0_r8, store_c/target_store_c ) + if( carbon_balance < 0.0_r8 ) then - store_c_flux = min(store_below_target,carbon_balance * & - max(exp(-1.*store_target_fraction**4._r8) - exp( -1.0_r8 ),0.0_r8)) + ! Store_c_flux will be negative, so store_c will be depleted + store_c_flux = carbon_balance + carbon_balance = carbon_balance - store_c_flux + store_c = store_c + store_c_flux - ! Move carbon from carbon balance to storage - carbon_balance = carbon_balance - store_c_flux - store_c = store_c + store_c_flux + else - end if + ! Accumulate some carbon in storage. If storage is completely depleted, aim to + ! increase storage, but not to replenish completely so we can still use some + ! carbon for growth. + store_below_target = max(0.0_r8,target_store_c - store_c) + store_target_fraction = max(0.0_r8, store_c/target_store_c ) - ! ----------------------------------------------------------------------------------- - ! V. If carbon is still available, prioritize some allocation to replace - ! the rest of the leaf/fineroot deficit - ! carbon balance is guaranteed to be >=0 beyond this point - ! MLO. Renamed demand with below target to make it consistent with the - ! definitions at the variable declaration part. - ! ----------------------------------------------------------------------------------- + store_c_flux = min(store_below_target,carbon_balance * & + max(exp(-1.*store_target_fraction**4._r8) - exp( -1.0_r8 ),0.0_r8)) - leaf_below_target = max(0.0_r8,target_leaf_c - sum(leaf_c(1:nleafage))) - fnrt_below_target = max(0.0_r8,target_fnrt_c - fnrt_c) + ! Move carbon from carbon balance to storage + carbon_balance = carbon_balance - store_c_flux + store_c = store_c + store_c_flux - total_below_target = leaf_below_target + fnrt_below_target + end if - if ( (carbon_balance > nearzero) .and. (total_below_target > nearzero) ) then - ! Find fraction of carbon to be allocated to leaves and fine roots - allocation_factor = min(1.0_r8, carbon_balance / total_below_target) + ! ----------------------------------------------------------------------------------- + ! V. If carbon is still available, prioritize some allocation to replace + ! the rest of the leaf/fineroot deficit + ! carbon balance is guaranteed to be >=0 beyond this point + ! MLO. Renamed demand with below target to make it consistent with the + ! definitions at the variable declaration part. + ! ----------------------------------------------------------------------------------- - ! MLO. Edited the code to switch the order of operations. The previous code would - ! subtract leaf flux from carbon balance before estimating the fine root flux, - ! potentially allowing less fluxes to fine roots than possible. - leaf_c_flux = leaf_below_target * allocation_factor - fnrt_c_flux = fnrt_below_target * allocation_factor + leaf_below_target = max(0.0_r8,target_leaf_c - sum(leaf_c(1:nleafage))) + fnrt_below_target = max(0.0_r8,target_fnrt_c - fnrt_c) - leaf_c(iexp_leaf) = leaf_c(iexp_leaf) + leaf_c_flux - fnrt_c = fnrt_c + fnrt_c_flux + total_below_target = leaf_below_target + fnrt_below_target + + if ( (carbon_balance > nearzero) .and. (total_below_target > nearzero) ) then + ! Find fraction of carbon to be allocated to leaves and fine roots + allocation_factor = min(1.0_r8, carbon_balance / total_below_target) - carbon_balance = carbon_balance - ( leaf_c_flux + fnrt_c_flux ) + ! MLO. Edited the code to switch the order of operations. The previous code would + ! subtract leaf flux from carbon balance before estimating the fine root flux, + ! potentially allowing less fluxes to fine roots than possible. + leaf_c_flux = leaf_below_target * allocation_factor + fnrt_c_flux = fnrt_below_target * allocation_factor - end if + leaf_c(iexp_leaf) = leaf_c(iexp_leaf) + leaf_c_flux + fnrt_c = fnrt_c + fnrt_c_flux + + carbon_balance = carbon_balance - ( leaf_c_flux + fnrt_c_flux ) + + end if + + ! ----------------------------------------------------------------------------------- + ! VI. If carbon is still available, we try to push all live + ! pools back towards allometry. But only upwards, if fusion happened + ! to generate some pools above allometric target, don't reduce the pool, + ! just ignore it until the rest of the plant grows to meet it. + ! ----------------------------------------------------------------------------------- + if( carbon_balance > nearzero ) then + + leaf_below_target = max(target_leaf_c - sum(leaf_c(1:nleafage)),0.0_r8) + fnrt_below_target = max(target_fnrt_c - fnrt_c,0.0_r8) + sapw_below_target = max(target_sapw_c - sapw_c,0.0_r8) + store_below_target = max(target_store_c - store_c,0.0_r8) + + total_below_target = leaf_below_target + fnrt_below_target + & + sapw_below_target + store_below_target + + if ( total_below_target > nearzero ) then + ! Find allocation factor based on available carbon and total demand to meet target. + allocation_factor = min(1.0_r8, carbon_balance / total_below_target) + + ! Find fluxes to individual pools + leaf_c_flux = leaf_below_target * allocation_factor + fnrt_c_flux = fnrt_below_target * allocation_factor + sapw_c_flux = sapw_below_target * allocation_factor + store_c_flux = store_below_target * allocation_factor + + leaf_c(iexp_leaf) = leaf_c(iexp_leaf) + leaf_c_flux + fnrt_c = fnrt_c + fnrt_c_flux + sapw_c = sapw_c + sapw_c_flux + store_c = store_c + store_c_flux + + carbon_balance = carbon_balance - & + ( leaf_c_flux + fnrt_c_flux + sapw_c_flux + store_c_flux ) + end if + end if + + ! ----------------------------------------------------------------------------------- + ! VII. If carbon is still available, replenish the structural pool to get + ! back on allometry + ! ----------------------------------------------------------------------------------- + + if( carbon_balance > nearzero ) then + + struct_below_target = max(target_struct_c - struct_c ,0.0_r8) + + if ( struct_below_target > 0.0_r8) then + + struct_c_flux = min(carbon_balance,struct_below_target) + carbon_balance = carbon_balance - struct_c_flux + struct_c = struct_c + struct_c_flux + + end if + + end if + + elseif( (phase.eq.2) .and. ( carbon_balance > calloc_abs_error ) then + + ! ----------------------------------------------------------------------------------- + ! VIII. If carbon is yet still available ... + ! Our pools are now either on allometry or above (from fusion). + ! We we can increment those pools at or below, + ! including structure and reproduction according to their rates + ! Use an adaptive euler integration. If the error is not nominal, + ! the carbon balance sub-step (deltaC) will be halved and tried again + ! + ! Note that we compare against calloc_abs_error here because it is possible + ! that all the carbon was effectively used up, but a miniscule amount + ! remains due to numerical precision (ie -20 or so), so even though + ! the plant has not been brought to be "on allometry", it thinks it has carbon + ! left to allocate, and thus it must be on allometry when its not. + ! ----------------------------------------------------------------------------------- + + intgr_params(:) = un_initialized + intgr_params(ac_bc_in_id_ctrim) = this%bc_in(ac_bc_in_id_ctrim)%rval + intgr_params(ac_bc_in_id_pft) = real(this%bc_in(ac_bc_in_id_pft)%ival) + intgr_params(num_bc_in + 1) = real(this%bc_inout(ac_bc_inout_id_cdamage)%ival) + + + + ! This routine checks that actual carbon is not below that targets. It does + ! allow actual pools to be above the target, and in these cases, it sends + ! a false on the "grow_<>" flag, allowing the plant to grow into these pools. + ! It also checks to make sure that structural biomass is not above the target. + ! ( MLO. Removed the check for storage because the same test is done inside + ! sub-routine TargetAllometryCheck.) + + call TargetAllometryCheck(sum(leaf_c0(1:nleafage)),fnrt_c0,sapw_c0,store_c0,struct_c0, & + sum(leaf_c(1:nleafage)), fnrt_c, sapw_c,store_c, struct_c, & + target_leaf_c, target_fnrt_c, target_sapw_c, & + target_store_c, target_struct_c, & + carbon_balance,ipft,leaf_status, & + grow_leaf, grow_fnrt, grow_sapw, grow_store, grow_struct) + + ! -------------------------------------------------------------------------------- + ! The numerical integration of growth requires that the instantaneous state + ! variables are passed in as an array. We call it "c_pool". + ! + ! Initialize the adaptive integrator arrays and flags + ! -------------------------------------------------------------------------------- + + ierr = 1 + totalC = carbon_balance + nsteps = 0 + + c_pool(:) = 0.0_r8 ! Zero state variable array + c_mask(:) = .false. ! This mask tells the integrator + ! which indices are active. Its possible + ! that due to fusion, or previous numerical + ! truncation errors, that one of these pools + ! may be larger than its target! We check + ! this, and if true, then we flag that + ! pool to be ignored. c_mask(i) = .false. + ! For grasses, since they don't grow very + ! large and thus won't accumulate such large + ! errors, we always mask as true. + + c_pool(leaf_c_id) = sum(leaf_c(1:nleafage)) + c_pool(fnrt_c_id) = fnrt_c + c_pool(sapw_c_id) = sapw_c + c_pool(store_c_id) = store_c + c_pool(struct_c_id) = struct_c + c_pool(repro_c_id) = repro_c + c_pool(dbh_id) = dbh + + ! Only grow leaves if we are in a "leaf-on" status + select case (leaf_status) + case (leaves_on) + c_mask(leaf_c_id) = grow_leaf + case default + c_mask(leaf_c_id) = .false. + end select + c_mask(fnrt_c_id) = grow_fnrt + c_mask(sapw_c_id) = grow_sapw + c_mask(struct_c_id) = grow_struct + c_mask(store_c_id) = grow_store + c_mask(repro_c_id) = .true. ! Always calculate reproduction on growth + c_mask(dbh_id) = .true. ! Always increment dbh on growth step + + + ! When using the Euler method, we keep things simple. We always try + ! to make the first integration step to span the entirety of the integration + ! window for the independent variable (available carbon) + + select case (ODESolve) + case (2) + this%ode_opt_step = totalC + end select + + do_solve_check: do while( ierr .ne. 0 ) + + deltaC = min(totalC,this%ode_opt_step) + select_ODESolve: select case (ODESolve) + case (1) + call RKF45(AllomCGrowthDeriv,c_pool,c_mask,deltaC,totalC, & + max_trunc_error,intgr_params,c_pool_out,this%ode_opt_step,step_pass) + + case (2) + call Euler(AllomCGrowthDeriv,c_pool,c_mask,deltaC,totalC,intgr_params,c_pool_out) + ! step_pass = .true. + + ! When integrating along the allometric curve, we have the luxury of perfect + ! hindsite. Ie, after we have made our step, we can see if the amount + ! of each carbon we have matches the target associated with the new dbh. + ! The following call evaluates how close we are to the allometically defined + ! targets. If we are too far (governed by max_trunc_error), then we + ! pass back the pass/fail flag (step_pass) as false. If false, then + ! we halve the step-size, and then retry. If that step was fine, then + ! we remember the current step size as a good next guess. + + call CheckIntegratedAllometries(c_pool_out(dbh_id),ipft,& + crowndamage, canopy_trim, & + c_pool_out(leaf_c_id), c_pool_out(fnrt_c_id), c_pool_out(sapw_c_id), & + c_pool_out(store_c_id), c_pool_out(struct_c_id), & + c_mask(leaf_c_id), c_mask(fnrt_c_id), c_mask(sapw_c_id), & + c_mask(store_c_id), c_mask(struct_c_id), max_trunc_error, step_pass) + if(step_pass) then + this%ode_opt_step = deltaC + else + this%ode_opt_step = 0.5*deltaC + end if + case default + write(fates_log(),*) 'An integrator was chosen that does not exist' + write(fates_log(),*) 'ODESolve = ',ODESolve + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select select_ODESolve + + nsteps = nsteps + 1 + + if (step_pass) then ! If true, then step is accepted + totalC = totalC - deltaC + c_pool(:) = c_pool_out(:) + end if + + if(nsteps > max_substeps ) then + write(fates_log(),fmt=*) '---~---' + write(fates_log(),fmt=*) 'Plant Growth Integrator could not find' + write(fates_log(),fmt=*) 'a solution in less than ',max_substeps,' tries.' + write(fates_log(),fmt=*) 'Aborting!' + write(fates_log(),fmt=*) '---~---' + write(fates_log(),fmt=fmti) 'Leaf status =',leaf_status + write(fates_log(),fmt=fmt0) 'Carbon_balance =',carbon_balance + write(fates_log(),fmt=fmt0) 'deltaC =',deltaC + write(fates_log(),fmt=fmt0) 'totalC =',totalC + write(fates_log(),fmt=*) 'crowndamage : ', crowndamage + write(fates_log(),fmt=fmth) ' Tissue |', ' Grow',' Current',' Target' ,' Deficit' + write(fates_log(),fmt=fmtg) ' Leaf |', grow_leaf , sum(leaf_c(:)),target_leaf_c , target_leaf_c - sum(leaf_c(:)) + write(fates_log(),fmt=fmtg) ' Fine root |', grow_fnrt , fnrt_c,target_fnrt_c , target_fnrt_c - fnrt_c + write(fates_log(),fmt=fmtg) ' Sapwood |', grow_sapw , sapw_c,target_sapw_c , target_sapw_c - sapw_c + write(fates_log(),fmt=fmtg) ' Storage |', grow_store , store_c,target_store_c , target_store_c - store_c + write(fates_log(),fmt=fmtg) ' Structural |', grow_struct , struct_c,target_struct_c, target_struct_c - struct_c + write(fates_log(),fmt=*) '---~---' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + ! + ! TotalC should eventually be whittled down to near zero. + ! The solvers are not perfect, so we can't expect it to be perfectly zero. + ! Note that calloc_abs_error is 1e-9, which is really small (1 microgram of carbon) + ! yet also six orders of magnitude greater than typical rounding errors (~1e-15). + + ! At that point, update the actual states + ! -------------------------------------------------------------------------------- + if_step_pass: if( (totalC < calloc_abs_error) .and. (step_pass) )then + + ierr = 0 + leaf_c_flux = c_pool(leaf_c_id) - sum(leaf_c(1:nleafage)) + fnrt_c_flux = c_pool(fnrt_c_id) - fnrt_c + sapw_c_flux = c_pool(sapw_c_id) - sapw_c + store_c_flux = c_pool(store_c_id) - store_c + struct_c_flux = c_pool(struct_c_id) - struct_c + repro_c_flux = c_pool(repro_c_id) - repro_c + + ! Make an adjustment to flux partitions to make it match remaining c balance + flux_adj = carbon_balance/(leaf_c_flux+fnrt_c_flux+sapw_c_flux + & + store_c_flux+struct_c_flux+repro_c_flux) + + + leaf_c_flux = leaf_c_flux*flux_adj + fnrt_c_flux = fnrt_c_flux*flux_adj + sapw_c_flux = sapw_c_flux*flux_adj + store_c_flux = store_c_flux*flux_adj + struct_c_flux = struct_c_flux*flux_adj + repro_c_flux = repro_c_flux*flux_adj + + carbon_balance = carbon_balance - leaf_c_flux + leaf_c(iexp_leaf) = leaf_c(iexp_leaf) + leaf_c_flux + + carbon_balance = carbon_balance - fnrt_c_flux + fnrt_c = fnrt_c + fnrt_c_flux + + carbon_balance = carbon_balance - sapw_c_flux + sapw_c = sapw_c + sapw_c_flux + + carbon_balance = carbon_balance - store_c_flux + store_c = store_c + store_c_flux + + carbon_balance = carbon_balance - struct_c_flux + struct_c = struct_c + struct_c_flux + + carbon_balance = carbon_balance - repro_c_flux + repro_c = repro_c + repro_c_flux + + dbh = c_pool(dbh_id) + + if( abs(carbon_balance)>calloc_abs_error ) then + write(fates_log(),*) 'carbon conservation error while integrating pools' + write(fates_log(),*) 'along alometric curve' + write(fates_log(),*) 'carbon_balance = ',carbon_balance,totalC + write(fates_log(),*) 'exiting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + end if if_step_pass + + end do do_solve_check + + end if if_phase - ! ----------------------------------------------------------------------------------- - ! VI. If carbon is still available, we try to push all live - ! pools back towards allometry. But only upwards, if fusion happened - ! to generate some pools above allometric target, don't reduce the pool, - ! just ignore it until the rest of the plant grows to meet it. - ! ----------------------------------------------------------------------------------- - if( carbon_balance > nearzero ) then + ! Track the net allocations and transport from this routine + ! (the AgeLeaves() routine handled tracking allocation through aging) - leaf_below_target = max(target_leaf_c - sum(leaf_c(1:nleafage)),0.0_r8) - fnrt_below_target = max(target_fnrt_c - fnrt_c,0.0_r8) - sapw_below_target = max(target_sapw_c - sapw_c,0.0_r8) - store_below_target = max(target_store_c - store_c,0.0_r8) - - total_below_target = leaf_below_target + fnrt_below_target + & - sapw_below_target + store_below_target - - if ( total_below_target > nearzero ) then - ! Find allocation factor based on available carbon and total demand to meet target. - allocation_factor = min(1.0_r8, carbon_balance / total_below_target) - - ! Find fluxes to individual pools - leaf_c_flux = leaf_below_target * allocation_factor - fnrt_c_flux = fnrt_below_target * allocation_factor - sapw_c_flux = sapw_below_target * allocation_factor - store_c_flux = store_below_target * allocation_factor - - leaf_c(iexp_leaf) = leaf_c(iexp_leaf) + leaf_c_flux - fnrt_c = fnrt_c + fnrt_c_flux - sapw_c = sapw_c + sapw_c_flux - store_c = store_c + store_c_flux - - carbon_balance = carbon_balance - & - ( leaf_c_flux + fnrt_c_flux + sapw_c_flux + store_c_flux ) - end if - end if - - ! ----------------------------------------------------------------------------------- - ! VII. If carbon is still available, replenish the structural pool to get - ! back on allometry - ! ----------------------------------------------------------------------------------- + this%variables(leaf_c_id)%net_alloc(icd) = & + this%variables(leaf_c_id)%net_alloc(icd) + (leaf_c(icd) - leaf_c0(icd)) - if( carbon_balance > nearzero ) then - - struct_below_target = max(target_struct_c - struct_c ,0.0_r8) - - if ( struct_below_target > 0.0_r8) then - - struct_c_flux = min(carbon_balance,struct_below_target) - carbon_balance = carbon_balance - struct_c_flux - struct_c = struct_c + struct_c_flux - - end if - - end if - - ! ----------------------------------------------------------------------------------- - ! VIII. If carbon is yet still available ... - ! Our pools are now either on allometry or above (from fusion). - ! We we can increment those pools at or below, - ! including structure and reproduction according to their rates - ! Use an adaptive euler integration. If the error is not nominal, - ! the carbon balance sub-step (deltaC) will be halved and tried again - ! - ! Note that we compare against calloc_abs_error here because it is possible - ! that all the carbon was effectively used up, but a miniscule amount - ! remains due to numerical precision (ie -20 or so), so even though - ! the plant has not been brought to be "on allometry", it thinks it has carbon - ! left to allocate, and thus it must be on allometry when its not. - ! ----------------------------------------------------------------------------------- - + this%variables(fnrt_c_id)%net_alloc(icd) = & + this%variables(fnrt_c_id)%net_alloc(icd) + (fnrt_c - fnrt_c0) - if_stature_growth: if( carbon_balance > calloc_abs_error ) then - - ! This routine checks that actual carbon is not below that targets. It does - ! allow actual pools to be above the target, and in these cases, it sends - ! a false on the "grow_<>" flag, allowing the plant to grow into these pools. - ! It also checks to make sure that structural biomass is not above the target. - ! ( MLO. Removed the check for storage because the same test is done inside - ! sub-routine TargetAllometryCheck.) - - call TargetAllometryCheck(sum(leaf_c0(1:nleafage)),fnrt_c0,sapw_c0,store_c0,struct_c0, & - sum(leaf_c(1:nleafage)), fnrt_c, sapw_c,store_c, struct_c, & - target_leaf_c, target_fnrt_c, target_sapw_c, & - target_store_c, target_struct_c, & - carbon_balance,ipft,leaf_status, & - grow_leaf, grow_fnrt, grow_sapw, grow_store, grow_struct) - - ! -------------------------------------------------------------------------------- - ! The numerical integration of growth requires that the instantaneous state - ! variables are passed in as an array. We call it "c_pool". - ! - ! Initialize the adaptive integrator arrays and flags - ! -------------------------------------------------------------------------------- - - ierr = 1 - totalC = carbon_balance - nsteps = 0 - - c_pool(:) = 0.0_r8 ! Zero state variable array - c_mask(:) = .false. ! This mask tells the integrator - ! which indices are active. Its possible - ! that due to fusion, or previous numerical - ! truncation errors, that one of these pools - ! may be larger than its target! We check - ! this, and if true, then we flag that - ! pool to be ignored. c_mask(i) = .false. - ! For grasses, since they don't grow very - ! large and thus won't accumulate such large - ! errors, we always mask as true. - - c_pool(leaf_c_id) = sum(leaf_c(1:nleafage)) - c_pool(fnrt_c_id) = fnrt_c - c_pool(sapw_c_id) = sapw_c - c_pool(store_c_id) = store_c - c_pool(struct_c_id) = struct_c - c_pool(repro_c_id) = repro_c - c_pool(dbh_id) = dbh - - ! Only grow leaves if we are in a "leaf-on" status - select case (leaf_status) - case (leaves_on) - c_mask(leaf_c_id) = grow_leaf - case default - c_mask(leaf_c_id) = .false. - end select - c_mask(fnrt_c_id) = grow_fnrt - c_mask(sapw_c_id) = grow_sapw - c_mask(struct_c_id) = grow_struct - c_mask(store_c_id) = grow_store - c_mask(repro_c_id) = .true. ! Always calculate reproduction on growth - c_mask(dbh_id) = .true. ! Always increment dbh on growth step - - - ! When using the Euler method, we keep things simple. We always try - ! to make the first integration step to span the entirety of the integration - ! window for the independent variable (available carbon) - - select case (ODESolve) - case (2) - this%ode_opt_step = totalC - end select - - do_solve_check: do while( ierr .ne. 0 ) - - deltaC = min(totalC,this%ode_opt_step) - select_ODESolve: select case (ODESolve) - case (1) - call RKF45(AllomCGrowthDeriv,c_pool,c_mask,deltaC,totalC, & - max_trunc_error,intgr_params,c_pool_out,this%ode_opt_step,step_pass) - - case (2) - call Euler(AllomCGrowthDeriv,c_pool,c_mask,deltaC,totalC,intgr_params,c_pool_out) - ! step_pass = .true. - - ! When integrating along the allometric curve, we have the luxury of perfect - ! hindsite. Ie, after we have made our step, we can see if the amount - ! of each carbon we have matches the target associated with the new dbh. - ! The following call evaluates how close we are to the allometically defined - ! targets. If we are too far (governed by max_trunc_error), then we - ! pass back the pass/fail flag (step_pass) as false. If false, then - ! we halve the step-size, and then retry. If that step was fine, then - ! we remember the current step size as a good next guess. - - call CheckIntegratedAllometries(c_pool_out(dbh_id),ipft,& - crowndamage, canopy_trim, & - c_pool_out(leaf_c_id), c_pool_out(fnrt_c_id), c_pool_out(sapw_c_id), & - c_pool_out(store_c_id), c_pool_out(struct_c_id), & - c_mask(leaf_c_id), c_mask(fnrt_c_id), c_mask(sapw_c_id), & - c_mask(store_c_id), c_mask(struct_c_id), max_trunc_error, step_pass) - if(step_pass) then - this%ode_opt_step = deltaC - else - this%ode_opt_step = 0.5*deltaC - end if - case default - write(fates_log(),*) 'An integrator was chosen that does not exist' - write(fates_log(),*) 'ODESolve = ',ODESolve - call endrun(msg=errMsg(sourcefile, __LINE__)) - end select select_ODESolve - - nsteps = nsteps + 1 - - if (step_pass) then ! If true, then step is accepted - totalC = totalC - deltaC - c_pool(:) = c_pool_out(:) - end if - - if(nsteps > max_substeps ) then - write(fates_log(),fmt=*) '---~---' - write(fates_log(),fmt=*) 'Plant Growth Integrator could not find' - write(fates_log(),fmt=*) 'a solution in less than ',max_substeps,' tries.' - write(fates_log(),fmt=*) 'Aborting!' - write(fates_log(),fmt=*) '---~---' - write(fates_log(),fmt=fmti) 'Leaf status =',leaf_status - write(fates_log(),fmt=fmt0) 'Carbon_balance =',carbon_balance - write(fates_log(),fmt=fmt0) 'deltaC =',deltaC - write(fates_log(),fmt=fmt0) 'totalC =',totalC - write(fates_log(),fmt=*) 'crowndamage : ', crowndamage - write(fates_log(),fmt=fmth) ' Tissue |', ' Grow',' Current',' Target' ,' Deficit' - write(fates_log(),fmt=fmtg) ' Leaf |', grow_leaf , sum(leaf_c(:)),target_leaf_c , target_leaf_c - sum(leaf_c(:)) - write(fates_log(),fmt=fmtg) ' Fine root |', grow_fnrt , fnrt_c,target_fnrt_c , target_fnrt_c - fnrt_c - write(fates_log(),fmt=fmtg) ' Sapwood |', grow_sapw , sapw_c,target_sapw_c , target_sapw_c - sapw_c - write(fates_log(),fmt=fmtg) ' Storage |', grow_store , store_c,target_store_c , target_store_c - store_c - write(fates_log(),fmt=fmtg) ' Structural |', grow_struct , struct_c,target_struct_c, target_struct_c - struct_c - write(fates_log(),fmt=*) '---~---' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - ! - ! TotalC should eventually be whittled down to near zero. - ! The solvers are not perfect, so we can't expect it to be perfectly zero. - ! Note that calloc_abs_error is 1e-9, which is really small (1 microgram of carbon) - ! yet also six orders of magnitude greater than typical rounding errors (~1e-15). - - ! At that point, update the actual states - ! -------------------------------------------------------------------------------- - if_step_pass: if( (totalC < calloc_abs_error) .and. (step_pass) )then - - ierr = 0 - leaf_c_flux = c_pool(leaf_c_id) - sum(leaf_c(1:nleafage)) - fnrt_c_flux = c_pool(fnrt_c_id) - fnrt_c - sapw_c_flux = c_pool(sapw_c_id) - sapw_c - store_c_flux = c_pool(store_c_id) - store_c - struct_c_flux = c_pool(struct_c_id) - struct_c - repro_c_flux = c_pool(repro_c_id) - repro_c - - ! Make an adjustment to flux partitions to make it match remaining c balance - flux_adj = carbon_balance/(leaf_c_flux+fnrt_c_flux+sapw_c_flux + & - store_c_flux+struct_c_flux+repro_c_flux) - - - leaf_c_flux = leaf_c_flux*flux_adj - fnrt_c_flux = fnrt_c_flux*flux_adj - sapw_c_flux = sapw_c_flux*flux_adj - store_c_flux = store_c_flux*flux_adj - struct_c_flux = struct_c_flux*flux_adj - repro_c_flux = repro_c_flux*flux_adj - - carbon_balance = carbon_balance - leaf_c_flux - leaf_c(iexp_leaf) = leaf_c(iexp_leaf) + leaf_c_flux - - carbon_balance = carbon_balance - fnrt_c_flux - fnrt_c = fnrt_c + fnrt_c_flux - - carbon_balance = carbon_balance - sapw_c_flux - sapw_c = sapw_c + sapw_c_flux - - carbon_balance = carbon_balance - store_c_flux - store_c = store_c + store_c_flux - - carbon_balance = carbon_balance - struct_c_flux - struct_c = struct_c + struct_c_flux - - carbon_balance = carbon_balance - repro_c_flux - repro_c = repro_c + repro_c_flux - - dbh = c_pool(dbh_id) - - if( abs(carbon_balance)>calloc_abs_error ) then - write(fates_log(),*) 'carbon conservation error while integrating pools' - write(fates_log(),*) 'along alometric curve' - write(fates_log(),*) 'carbon_balance = ',carbon_balance,totalC - write(fates_log(),*) 'exiting' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - end if if_step_pass - - end do do_solve_check - - end if if_stature_growth - - ! Track the net allocations and transport from this routine - ! (the AgeLeaves() routine handled tracking allocation through aging) - - this%variables(leaf_c_id)%net_alloc(icd) = & - this%variables(leaf_c_id)%net_alloc(icd) + (leaf_c(icd) - leaf_c0(icd)) - - this%variables(fnrt_c_id)%net_alloc(icd) = & - this%variables(fnrt_c_id)%net_alloc(icd) + (fnrt_c - fnrt_c0) - - this%variables(sapw_c_id)%net_alloc(icd) = & - this%variables(sapw_c_id)%net_alloc(icd) + (sapw_c - sapw_c0) - - this%variables(store_c_id)%net_alloc(icd) = & - this%variables(store_c_id)%net_alloc(icd) + (store_c - store_c0) - - this%variables(repro_c_id)%net_alloc(icd) = & - this%variables(repro_c_id)%net_alloc(icd) + (repro_c - repro_c0) - - this%variables(struct_c_id)%net_alloc(icd) = & - this%variables(struct_c_id)%net_alloc(icd) + (struct_c - struct_c0) - - - - end associate - - return + this%variables(sapw_c_id)%net_alloc(icd) = & + this%variables(sapw_c_id)%net_alloc(icd) + (sapw_c - sapw_c0) + + this%variables(store_c_id)%net_alloc(icd) = & + this%variables(store_c_id)%net_alloc(icd) + (store_c - store_c0) + + this%variables(repro_c_id)%net_alloc(icd) = & + this%variables(repro_c_id)%net_alloc(icd) + (repro_c - repro_c0) + + this%variables(struct_c_id)%net_alloc(icd) = & + this%variables(struct_c_id)%net_alloc(icd) + (struct_c - struct_c0) + + + + end associate + + return end subroutine DailyPRTAllometricCarbon ! ===================================================================================== diff --git a/parteh/PRTGenericMod.F90 b/parteh/PRTGenericMod.F90 index fb83aebae7..001c617912 100644 --- a/parteh/PRTGenericMod.F90 +++ b/parteh/PRTGenericMod.F90 @@ -1254,9 +1254,10 @@ end function GetCoordVal ! ==================================================================================== - subroutine DailyPRTBase(this) + subroutine DailyPRTBase(this,phase) - class(prt_vartypes) :: this + class(prt_vartypes) :: this + integer,intent(in) :: phase ! We allow this and its children to be broken into phases write(fates_log(),*)'Daily PRT Allocation must be extended' call endrun(msg=errMsg(sourcefile, __LINE__)) From daafba13ba34a36ffbef2c3ec61afdd2d22576b5 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 30 Jun 2022 17:32:30 -0400 Subject: [PATCH 268/852] cleaning up damage boundary condition to parteh, adding in phase hooks to parteh_mode=2, even if its incompatible at the moment --- biogeochem/EDCohortDynamicsMod.F90 | 10 +- parteh/PRTAllometricCNPMod.F90 | 267 ++++++++++++++--------------- parteh/PRTAllometricCarbonMod.F90 | 48 +++--- 3 files changed, 163 insertions(+), 162 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index bad98c2eb7..1f48a1f055 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -88,18 +88,17 @@ Module EDCohortDynamicsMod use PRTAllometricCarbonMod, only : callom_prt_vartypes use PRTAllometricCarbonMod, only : ac_bc_inout_id_netdc use PRTAllometricCarbonMod, only : ac_bc_in_id_pft - use PRTAllometricCarbonMod, only : ac_bc_inout_id_cdamage use PRTAllometricCarbonMod, only : ac_bc_inout_id_n use PRTAllometricCarbonMod, only : ac_bc_in_id_ctrim use PRTAllometricCarbonMod, only : ac_bc_inout_id_dbh - use PRTAllometricCarbonMod, only : ac_bc_in_id_lstat + use PRTAllometricCarbonMod, only : ac_bc_in_id_lstat, ac_bc_in_id_cdamage use PRTAllometricCNPMod, only : cnp_allom_prt_vartypes use PRTAllometricCNPMod, only : acnp_bc_in_id_pft, acnp_bc_in_id_ctrim use PRTAllometricCNPMod, only : acnp_bc_in_id_lstat, acnp_bc_inout_id_dbh use PRTAllometricCNPMod, only : acnp_bc_inout_id_rmaint_def, acnp_bc_in_id_netdc use PRTAllometricCNPMod, only : acnp_bc_in_id_netdnh4, acnp_bc_in_id_netdno3, acnp_bc_in_id_netdp use PRTAllometricCNPMod, only : acnp_bc_out_id_cefflux, acnp_bc_out_id_nefflux - use PRTAllometricCNPMod, only : acnp_bc_out_id_pefflux + use PRTAllometricCNPMod, only : acnp_bc_out_id_pefflux, acnp_bc_in_id_cdamage use PRTAllometricCNPMod, only : acnp_bc_out_id_nneed use PRTAllometricCNPMod, only : acnp_bc_out_id_pneed use DamageMainMod, only : GetCrownReduction @@ -409,7 +408,7 @@ subroutine InitPRTBoundaryConditions(new_cohort) call new_cohort%prt%RegisterBCInOut(ac_bc_inout_id_dbh,bc_rval = new_cohort%dbh) call new_cohort%prt%RegisterBCInOut(ac_bc_inout_id_netdc,bc_rval = new_cohort%npp_acc) - call new_cohort%prt%RegisterBCInOut(ac_bc_inout_id_cdamage,bc_ival = new_cohort%crowndamage) + call new_cohort%prt%RegisterBCIn(ac_bc_in_id_cdamage,bc_ival = new_cohort%crowndamage) call new_cohort%prt%RegisterBCIn(ac_bc_in_id_pft,bc_ival = new_cohort%pft) call new_cohort%prt%RegisterBCIn(ac_bc_in_id_ctrim,bc_rval = new_cohort%canopy_trim) call new_cohort%prt%RegisterBCIn(ac_bc_in_id_lstat,bc_ival = new_cohort%status_coh) @@ -423,7 +422,8 @@ subroutine InitPRTBoundaryConditions(new_cohort) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdnh4, bc_rval = new_cohort%daily_nh4_uptake) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdno3, bc_rval = new_cohort%daily_no3_uptake) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdp, bc_rval = new_cohort%daily_p_uptake) - + call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_cdamage,bc_ival = new_cohort%crowndamage) + call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_dbh,bc_rval = new_cohort%dbh) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_rmaint_def,bc_rval = new_cohort%resp_m_def) diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 1ab310dd32..d9d0b1385d 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -138,11 +138,9 @@ module PRTAllometricCNPMod integer, public, parameter :: acnp_bc_inout_id_dbh = 1 ! Plant DBH integer, public, parameter :: acnp_bc_inout_id_rmaint_def = 2 ! Index for any accumulated - integer, public, parameter :: acnp_bc_inout_id_cdamage = 3 ! Crown damage index - integer, public, parameter :: acnp_bc_inout_id_num = 4 ! Number of plants + ! maintenance respiration deficit - ! maintenance respiration deficit - integer, public, parameter :: num_bc_inout = 4 + integer, public, parameter :: num_bc_inout = 2 ! ------------------------------------------------------------------------------------- ! Input only Boundary Indices (These are public) @@ -155,9 +153,10 @@ module PRTAllometricCNPMod integer, public, parameter :: acnp_bc_in_id_netdnh4 = 5 ! Index for the net daily NH4 input BC integer, public, parameter :: acnp_bc_in_id_netdno3 = 6 ! Index for the net daily NO3 input BC integer, public, parameter :: acnp_bc_in_id_netdp = 7 ! Index for the net daily P input BC + integer, public, parameter :: acnp_bc_in_id_cdamage = 8 ! Index for the crowndamage input BC ! 0=leaf off, 1=leaf on - integer, parameter :: num_bc_in = 7 + integer, parameter :: num_bc_in = 8 ! ------------------------------------------------------------------------------------- ! Output Boundary Indices (These are public) @@ -248,99 +247,100 @@ module PRTAllometricCNPMod subroutine InitPRTGlobalAllometricCNP() - ! ---------------------------------------------------------------------------------- - ! Initialize and populate the general mapping table that - ! organizes the specific variables in this module to - ! pre-ordained groups, so they can be used to inform - ! the rest of the model - ! - ! This routine is not part of the sp_pool_vartypes class - ! because it is the same for all plants and we need not - ! waste memory on it. - ! ----------------------------------------------------------------------------------- + ! ---------------------------------------------------------------------------------- + ! Initialize and populate the general mapping table that + ! organizes the specific variables in this module to + ! pre-ordained groups, so they can be used to inform + ! the rest of the model + ! + ! This routine is not part of the sp_pool_vartypes class + ! because it is the same for all plants and we need not + ! waste memory on it. + ! ----------------------------------------------------------------------------------- - integer :: nleafage + integer :: nleafage - allocate(prt_global_acnp) - allocate(prt_global_acnp%state_descriptor(num_vars)) + allocate(prt_global_acnp) + allocate(prt_global_acnp%state_descriptor(num_vars)) - prt_global_acnp%hyp_name = 'Allometric Flexible C+N+P' + prt_global_acnp%hyp_name = 'Allometric Flexible C+N+P' - prt_global_acnp%hyp_id = prt_cnp_flex_allom_hyp + prt_global_acnp%hyp_id = prt_cnp_flex_allom_hyp - call prt_global_acnp%ZeroGlobal() + call prt_global_acnp%ZeroGlobal() - ! The number of leaf age classes can be determined from the parameter file, - ! notably the size of the leaf-longevity parameter's second dimension. - ! This is the same value in FatesInterfaceMod.F90 + ! The number of leaf age classes can be determined from the parameter file, + ! notably the size of the leaf-longevity parameter's second dimension. + ! This is the same value in FatesInterfaceMod.F90 - nleafage = size(prt_params%leaf_long,dim=2) + nleafage = size(prt_params%leaf_long,dim=2) - if(nleafage>max_nleafage) then - write(fates_log(),*) 'The allometric carbon PARTEH hypothesis' - write(fates_log(),*) 'sets a maximum number of leaf age classes' - write(fates_log(),*) 'used for scratch space. The model wants' - write(fates_log(),*) 'exceed that. Simply increase max_nleafage' - write(fates_log(),*) 'found in parteh/PRTAllometricCarbonMod.F90' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + if(nleafage>max_nleafage) then + write(fates_log(),*) 'The allometric carbon PARTEH hypothesis' + write(fates_log(),*) 'sets a maximum number of leaf age classes' + write(fates_log(),*) 'used for scratch space. The model wants' + write(fates_log(),*) 'exceed that. Simply increase max_nleafage' + write(fates_log(),*) 'found in parteh/PRTAllometricCarbonMod.F90' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if - call prt_global_acnp%RegisterVarInGlobal(leaf_c_id,'Leaf Carbon','leaf_c',leaf_organ,carbon12_element,nleafage) - call prt_global_acnp%RegisterVarInGlobal(fnrt_c_id,'Fine Root Carbon','fnrt_c',fnrt_organ,carbon12_element,icd) - call prt_global_acnp%RegisterVarInGlobal(sapw_c_id,'Sapwood Carbon','sapw_c',sapw_organ,carbon12_element,icd) - call prt_global_acnp%RegisterVarInGlobal(store_c_id,'Storage Carbon','store_c',store_organ,carbon12_element,icd) - call prt_global_acnp%RegisterVarInGlobal(struct_c_id,'Structural Carbon','struct_c',struct_organ,carbon12_element,icd) - call prt_global_acnp%RegisterVarInGlobal(repro_c_id,'Reproductive Carbon','repro_c',repro_organ,carbon12_element,icd) + call prt_global_acnp%RegisterVarInGlobal(leaf_c_id,'Leaf Carbon','leaf_c',leaf_organ,carbon12_element,nleafage) + call prt_global_acnp%RegisterVarInGlobal(fnrt_c_id,'Fine Root Carbon','fnrt_c',fnrt_organ,carbon12_element,icd) + call prt_global_acnp%RegisterVarInGlobal(sapw_c_id,'Sapwood Carbon','sapw_c',sapw_organ,carbon12_element,icd) + call prt_global_acnp%RegisterVarInGlobal(store_c_id,'Storage Carbon','store_c',store_organ,carbon12_element,icd) + call prt_global_acnp%RegisterVarInGlobal(struct_c_id,'Structural Carbon','struct_c',struct_organ,carbon12_element,icd) + call prt_global_acnp%RegisterVarInGlobal(repro_c_id,'Reproductive Carbon','repro_c',repro_organ,carbon12_element,icd) - call prt_global_acnp%RegisterVarInGlobal(leaf_n_id,'Leaf Nitrogen','leaf_n',leaf_organ,nitrogen_element,nleafage) - call prt_global_acnp%RegisterVarInGlobal(fnrt_n_id,'Fine Root Nitrogen','fnrt_n',fnrt_organ,nitrogen_element,icd) - call prt_global_acnp%RegisterVarInGlobal(sapw_n_id,'Sapwood Nitrogen','sapw_n',sapw_organ,nitrogen_element,icd) - call prt_global_acnp%RegisterVarInGlobal(store_n_id,'Storage Nitrogen','store_n',store_organ,nitrogen_element,icd) - call prt_global_acnp%RegisterVarInGlobal(struct_n_id,'Structural Nitrogen','struct_n',struct_organ,nitrogen_element,icd) - call prt_global_acnp%RegisterVarInGlobal(repro_n_id,'Reproductive Nitrogen','repro_n',repro_organ,nitrogen_element,icd) + call prt_global_acnp%RegisterVarInGlobal(leaf_n_id,'Leaf Nitrogen','leaf_n',leaf_organ,nitrogen_element,nleafage) + call prt_global_acnp%RegisterVarInGlobal(fnrt_n_id,'Fine Root Nitrogen','fnrt_n',fnrt_organ,nitrogen_element,icd) + call prt_global_acnp%RegisterVarInGlobal(sapw_n_id,'Sapwood Nitrogen','sapw_n',sapw_organ,nitrogen_element,icd) + call prt_global_acnp%RegisterVarInGlobal(store_n_id,'Storage Nitrogen','store_n',store_organ,nitrogen_element,icd) + call prt_global_acnp%RegisterVarInGlobal(struct_n_id,'Structural Nitrogen','struct_n',struct_organ,nitrogen_element,icd) + call prt_global_acnp%RegisterVarInGlobal(repro_n_id,'Reproductive Nitrogen','repro_n',repro_organ,nitrogen_element,icd) - call prt_global_acnp%RegisterVarInGlobal(leaf_p_id,'Leaf Phosphorus','leaf_p',leaf_organ,phosphorus_element,nleafage) - call prt_global_acnp%RegisterVarInGlobal(fnrt_p_id,'Fine Root Phosphorus','fnrt_p',fnrt_organ,phosphorus_element,icd) - call prt_global_acnp%RegisterVarInGlobal(sapw_p_id,'Sapwood Phosphorus','sapw_p',sapw_organ,phosphorus_element,icd) - call prt_global_acnp%RegisterVarInGlobal(store_p_id,'Storage Phosphorus','store_p',store_organ,phosphorus_element,icd) - call prt_global_acnp%RegisterVarInGlobal(struct_p_id,'Structural Phosphorus','struct_p',struct_organ,phosphorus_element,icd) - call prt_global_acnp%RegisterVarInGlobal(repro_p_id,'Reproductive Phosphorus','repro_p',repro_organ,phosphorus_element,icd) + call prt_global_acnp%RegisterVarInGlobal(leaf_p_id,'Leaf Phosphorus','leaf_p',leaf_organ,phosphorus_element,nleafage) + call prt_global_acnp%RegisterVarInGlobal(fnrt_p_id,'Fine Root Phosphorus','fnrt_p',fnrt_organ,phosphorus_element,icd) + call prt_global_acnp%RegisterVarInGlobal(sapw_p_id,'Sapwood Phosphorus','sapw_p',sapw_organ,phosphorus_element,icd) + call prt_global_acnp%RegisterVarInGlobal(store_p_id,'Storage Phosphorus','store_p',store_organ,phosphorus_element,icd) + call prt_global_acnp%RegisterVarInGlobal(struct_p_id,'Structural Phosphorus','struct_p',struct_organ,phosphorus_element,icd) + call prt_global_acnp%RegisterVarInGlobal(repro_p_id,'Reproductive Phosphorus','repro_p',repro_organ,phosphorus_element,icd) - ! Set some of the array sizes for input and output boundary conditions - prt_global_acnp%num_bc_in = num_bc_in - prt_global_acnp%num_bc_out = num_bc_out - prt_global_acnp%num_bc_inout = num_bc_inout - prt_global_acnp%num_vars = num_vars + ! Set some of the array sizes for input and output boundary conditions + prt_global_acnp%num_bc_in = num_bc_in + prt_global_acnp%num_bc_out = num_bc_out + prt_global_acnp%num_bc_inout = num_bc_inout + prt_global_acnp%num_vars = num_vars - ! Have the global generic pointer, point to this hypothesis' object - prt_global => prt_global_acnp + ! Have the global generic pointer, point to this hypothesis' object + prt_global => prt_global_acnp - return + return end subroutine InitPRTGlobalAllometricCNP ! ===================================================================================== - subroutine DailyPRTAllometricCNP(this) + subroutine DailyPRTAllometricCNP(this,phase) class(cnp_allom_prt_vartypes) :: this - + integer,intent(in) :: phase + ! Pointers to in-out bcs real(r8),pointer :: dbh ! Diameter at breast height [cm] real(r8),pointer :: maint_r_def ! Current maintenance respiration deficit [kgC] - integer ,pointer :: cdamage ! Crown damage - + ! Input only bcs integer :: ipft ! Plant Functional Type index real(r8) :: c_gain ! Daily carbon balance for this cohort [kgC] real(r8) :: n_gain ! Daily nitrogen uptake through fine-roots [kgN] real(r8) :: p_gain ! Daily phosphorus uptake through fine-roots [kgN] real(r8) :: canopy_trim ! The canopy trimming function [0-1] - + integer :: crowndamage ! which crown damage clas + ! Pointers to output bcs real(r8),pointer :: c_efflux ! Total plant efflux of carbon (kgC) real(r8),pointer :: n_efflux ! Total plant efflux of nitrogen (kgN) @@ -379,7 +379,6 @@ subroutine DailyPRTAllometricCNP(this) real(r8) :: n_gain0 real(r8) :: p_gain0 real(r8) :: maint_r_def0 - integer :: cdamage0 ! Used for mass checking, total mass allocated based ! on change in the states, should match gain0's @@ -389,6 +388,13 @@ subroutine DailyPRTAllometricCNP(this) real(r8) :: target_n,target_p real(r8) :: sum_c ! error checking sum + + ! We do not use damage with parteh_mode 2, so just + ! do everything in phase 1 and short-circuit the phase 2 call + ! ---------------------------------------------------------- + if(phase.eq.2) return + + ! integrator variables ! Copy the input only boundary conditions into readable local variables @@ -398,11 +404,12 @@ subroutine DailyPRTAllometricCNP(this) ! ----------------------------------------------------------------------------------- c_gain = this%bc_in(acnp_bc_in_id_netdc)%rval; c_gain0 = c_gain n_gain = this%bc_in(acnp_bc_in_id_netdnh4)%rval + & - this%bc_in(acnp_bc_in_id_netdno3)%rval + this%bc_in(acnp_bc_in_id_netdno3)%rval n_gain0 = n_gain p_gain = this%bc_in(acnp_bc_in_id_netdp)%rval; p_gain0 = p_gain canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival + crowndamage = this%bc_in(acnp_bc_in_id_cdamage)%ival ! Output only boundary conditions c_efflux => this%bc_out(acnp_bc_out_id_cefflux)%rval; c_efflux = 0._r8 @@ -411,42 +418,39 @@ subroutine DailyPRTAllometricCNP(this) n_need => this%bc_out(acnp_bc_out_id_nneed)%rval; n_need = fates_unset_r8 p_need => this%bc_out(acnp_bc_out_id_pneed)%rval; p_need = fates_unset_r8 - + ! In/out boundary conditions maint_r_def => this%bc_inout(acnp_bc_inout_id_rmaint_def)%rval; maint_r_def0 = maint_r_def dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval; dbh0 = dbh - cdamage => this%bc_inout(acnp_bc_inout_id_cdamage)%ival; cdamage0 = cdamage - - - - ! If more than 1 leaf age bin is present, this - ! call advances leaves in their age, but does - ! not actually remove any biomass from the plant - - call this%AgeLeaves(ipft,sec_per_day) - + + if(crowndamage>1)then + write(fates_log(),*) 'The crown damage model is incompatible with' + write(fates_log(),*) 'dynamic nutrients, ie parteh_mode=2' + write(fates_log(),*) 'This feature will be brought in in with CNP v2' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + ! Set all of the per-organ pointer arrays ! Note: Since growth only happens in the 1st leaf bin, we only ! point to that bin. However, we need to account for all bins ! when we calculate the deficit - + allocate(state_c(num_organs)) allocate(state_n(num_organs)) allocate(state_p(num_organs)) - + ! Set carbon targets based on the plant's current stature target_c(:) = fates_unset_r8 target_dcdd(:) = fates_unset_r8 - call bsap_allom(dbh,ipft,cdamage, canopy_trim, & - sapw_area,target_c(sapw_id),target_dcdd(sapw_id) ) - call bagw_allom(dbh,ipft,cdamage, agw_c_target,agw_dcdd_target) + call bsap_allom(dbh,ipft,canopy_trim,sapw_area,target_c(sapw_id),target_dcdd(sapw_id) ) + call bagw_allom(dbh,ipft,agw_c_target,agw_dcdd_target) call bbgw_allom(dbh,ipft,bgw_c_target,bgw_dcdd_target) call bdead_allom(agw_c_target,bgw_c_target, target_c(sapw_id), ipft, target_c(struct_id), & - agw_dcdd_target, bgw_dcdd_target, target_dcdd(sapw_id), target_dcdd(struct_id)) - call bleaf(dbh,ipft,cdamage, canopy_trim, target_c(leaf_id), target_dcdd(leaf_id)) + agw_dcdd_target, bgw_dcdd_target, target_dcdd(sapw_id), target_dcdd(struct_id)) + call bleaf(dbh,ipft,canopy_trim, target_c(leaf_id), target_dcdd(leaf_id)) call bfineroot(dbh,ipft,canopy_trim, target_c(fnrt_id), target_dcdd(fnrt_id)) - call bstore_allom(dbh,ipft,cdamage, canopy_trim, target_c(store_id), target_dcdd(store_id)) + call bstore_allom(dbh,ipft,canopy_trim, target_c(store_id), target_dcdd(store_id)) target_c(repro_id) = 0._r8 target_dcdd(repro_id) = 0._r8 @@ -467,7 +471,7 @@ subroutine DailyPRTAllometricCNP(this) i_var = prt_global%sp_organ_map(organ_list(i_org),phosphorus_element) state_p(i_org)%ptr => this%variables(i_var)%val(1) state_p0(i_org) = this%variables(i_var)%val(1) - + end do ! =================================================================================== @@ -484,21 +488,21 @@ subroutine DailyPRTAllometricCNP(this) i_var = prt_global%sp_organ_map(store_organ,phosphorus_element) p_gain = p_gain + sum(this%variables(i_var)%val(:)) this%variables(i_var)%val(:) = 0._r8 - + ! =================================================================================== ! Step 1. Prioritized allocation to replace tissues from turnover, and/or pay ! any un-paid maintenance respiration from storage. ! =================================================================================== - + call this%CNPPrioritizedReplacement(maint_r_def, c_gain, n_gain, p_gain, & - state_c, state_n, state_p, target_c) + state_c, state_n, state_p, target_c) sum_c = 0._r8 do i_org = 1,num_organs sum_c = sum_c+state_c(i_org)%ptr end do if( abs((c_gain0-c_gain) - & - (sum_c-sum(state_c0(:),dim=1)+(maint_r_def0-maint_r_def))) >calloc_abs_error ) then + (sum_c-sum(state_c0(:),dim=1)+(maint_r_def0-maint_r_def))) >calloc_abs_error ) then write(fates_log(),*) 'Carbon not balancing I' do i_org = 1,num_organs write(fates_log(),*) 'state_c: ',state_c(i_org)%ptr,state_c0(i_org) @@ -506,23 +510,23 @@ subroutine DailyPRTAllometricCNP(this) write(fates_log(),*) maint_r_def0-maint_r_def call endrun(msg=errMsg(sourcefile, __LINE__)) end if - + ! =================================================================================== ! Step 2. Grow out the stature of the plant by allocating to tissues beyond ! current targets. ! Attempts have been made to get all pools and species closest to allometric ! targets based on prioritized relative demand and allometry functions. ! =================================================================================== - + call this%CNPStatureGrowth(c_gain, n_gain, p_gain, & state_c, state_n, state_p, target_c, target_dcdd, cnp_limiter) - + sum_c = 0._r8 do i_org = 1,num_organs sum_c = sum_c+state_c(i_org)%ptr end do if( abs((c_gain0-c_gain) - & - (sum_c-sum(state_c0(:),dim=1)+(maint_r_def0-maint_r_def))) >calloc_abs_error ) then + (sum_c-sum(state_c0(:),dim=1)+(maint_r_def0-maint_r_def))) >calloc_abs_error ) then write(fates_log(),*) 'Carbon not balanceing II' do i_org = 1,num_organs write(fates_log(),*) 'state_c: ',state_c(i_org)%ptr,state_c0(i_org) @@ -536,14 +540,14 @@ subroutine DailyPRTAllometricCNP(this) ! At this point, at least 1 of the 3 resources have been used up. ! Allocate the remaining resources, or as a last resort, efflux them. ! =================================================================================== - + call this%CNPAllocateRemainder(c_gain, n_gain, p_gain, & state_c, state_n, state_p, c_efflux, n_efflux, p_efflux) ! Error Check: Make sure that the mass gains are completely used up if( abs(c_gain) > calloc_abs_error .or. & - abs(n_gain) > 0.1_r8*calloc_abs_error .or. & - abs(p_gain) > 0.02_r8*calloc_abs_error ) then + abs(n_gain) > 0.1_r8*calloc_abs_error .or. & + abs(p_gain) > 0.02_r8*calloc_abs_error ) then write(fates_log(),*) 'Allocation scheme should had used up all mass gain pools' write(fates_log(),*) 'Any mass that cannot be allocated should be effluxed' write(fates_log(),*) 'c_gain: ',c_gain @@ -557,39 +561,40 @@ subroutine DailyPRTAllometricCNP(this) ! Since this is also a check against what was available ! we include maintenance pay-back and efflux to the "allocated" ! pool to make sure everything balances. - + allocated_c = (maint_r_def0-maint_r_def) + c_efflux allocated_n = n_efflux allocated_p = p_efflux - + + ! Update the allocation flux diagnostic arrays for each 3 elements do i_org = 1,num_organs - + i_var = prt_global%sp_organ_map(organ_list(i_org),carbon12_element) this%variables(i_var)%net_alloc(1) = & this%variables(i_var)%net_alloc(1) + (state_c(i_org)%ptr - state_c0(i_org)) allocated_c = allocated_c + (state_c(i_org)%ptr - state_c0(i_org)) - + i_var = prt_global%sp_organ_map(organ_list(i_org),nitrogen_element) this%variables(i_var)%net_alloc(1) = & this%variables(i_var)%net_alloc(1) + (state_n(i_org)%ptr - state_n0(i_org)) allocated_n = allocated_n + (state_n(i_org)%ptr - state_n0(i_org)) - + i_var = prt_global%sp_organ_map(organ_list(i_org),phosphorus_element) this%variables(i_var)%net_alloc(1) = & this%variables(i_var)%net_alloc(1) + (state_p(i_org)%ptr - state_p0(i_org)) allocated_p = allocated_p + (state_p(i_org)%ptr - state_p0(i_org)) - + end do - + if(debug) then ! Error Check: Do a final balance between how much mass ! we had to work with, and how much was allocated - + if ( abs(allocated_c - c_gain0) > calloc_abs_error .or. & abs(allocated_n - n_gain0) > calloc_abs_error .or. & abs(allocated_p - p_gain0) > calloc_abs_error ) then @@ -608,14 +613,14 @@ subroutine DailyPRTAllometricCNP(this) target_n = this%GetNutrientTarget(nitrogen_element,store_organ) target_p = this%GetNutrientTarget(phosphorus_element,store_organ) - + n_need = target_n - state_n(store_id)%ptr p_need = target_p - state_p(store_id)%ptr - + deallocate(state_c) deallocate(state_n) deallocate(state_p) - + return end subroutine DailyPRTAllometricCNP @@ -1019,7 +1024,6 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & integer :: ipft real(r8) :: canopy_trim real(r8) :: leaf_status - integer :: icrowndamage integer :: i, ii ! organ index loops (masked and unmasked) integer :: istep ! outer step iteration loop @@ -1101,8 +1105,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval - icrowndamage = this%bc_inout(acnp_bc_inout_id_cdamage)%ival - + cnp_limiter = 0 ! If any of these resources is essentially tapped out, @@ -1124,7 +1127,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & intgr_params(:) = fates_unset_r8 intgr_params(acnp_bc_in_id_ctrim) = this%bc_in(acnp_bc_in_id_ctrim)%rval intgr_params(acnp_bc_in_id_pft) = real(this%bc_in(acnp_bc_in_id_pft)%ival) - + intgr_params(acnp_bc_in_id_cdamage) = real(this%bc_in(acnp_bc_in_id_cdamage)%ival) state_mask(:) = .false. mask_organs(:) = fates_unset_int @@ -1368,8 +1371,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & leafc_tp1 = leafc_tp1 + this%variables(i_var)%val(i) end do - call CheckIntegratedAllometries(state_array_out(dbh_id),ipft, & - icrowndamage, canopy_trim, & + call CheckIntegratedAllometries(state_array_out(dbh_id),ipft,canopy_trim, & leafc_tp1, state_array_out(fnrt_id), state_array_out(sapw_id), & state_array_out(store_id), state_array_out(struct_id), & state_mask(leaf_id), state_mask(fnrt_id), state_mask(sapw_id), & @@ -1459,13 +1461,13 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & storec_tp1 = state_array_out(store_id) structc_tp1 = state_array_out(struct_id) - call bleaf(dbh_tp1,ipft,icrowndamage, canopy_trim,leaf_c_target_tp1) + call bleaf(dbh_tp1,ipft,canopy_trim,leaf_c_target_tp1) call bfineroot(dbh_tp1,ipft,canopy_trim,fnrt_c_target_tp1) - call bsap_allom(dbh_tp1,ipft,icrowndamage,canopy_trim,sapw_area,sapw_c_target_tp1) - call bagw_allom(dbh_tp1,ipft,icrowndamage, agw_c_target_tp1) + call bsap_allom(dbh_tp1,ipft,canopy_trim,sapw_area,sapw_c_target_tp1) + call bagw_allom(dbh_tp1,ipft,agw_c_target_tp1) call bbgw_allom(dbh_tp1,ipft,bgw_c_target_tp1) call bdead_allom(agw_c_target_tp1,bgw_c_target_tp1, sapw_c_target_tp1, ipft, struct_c_target_tp1) - call bstore_allom(dbh_tp1,ipft,icrowndamage, canopy_trim,store_c_target_tp1) + call bstore_allom(dbh_tp1,ipft,canopy_trim,store_c_target_tp1) write(fates_log(),*) 'leaf_c: ',leafc_tp1, leaf_c_target_tp1,leafc_tp1-leaf_c_target_tp1 write(fates_log(),*) 'fnrt_c: ',fnrtc_tp1, fnrt_c_target_tp1,fnrtc_tp1- fnrt_c_target_tp1 @@ -1573,13 +1575,11 @@ subroutine CNPAllocateRemainder(this,c_gain, n_gain, p_gain, & real(r8), pointer :: dbh integer :: ipft real(r8) :: canopy_trim - integer, pointer :: icrowndamage dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival - icrowndamage => this%bc_inout(acnp_bc_inout_id_cdamage)%ival ! ----------------------------------------------------------------------------------- ! If nutrients are still available, then we can bump up the values in the pools @@ -1631,7 +1631,7 @@ subroutine CNPAllocateRemainder(this,c_gain, n_gain, p_gain, & if(c_gain>calloc_abs_error) then ! Update carbon based allometric targets - call bstore_allom(dbh,ipft,icrowndamage, canopy_trim, store_c_target) + call bstore_allom(dbh,ipft,canopy_trim, store_c_target) ! Estimate the overflow store_c_target = store_c_target * (1.0_r8 + store_overflow_frac) @@ -1717,7 +1717,6 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe real(r8) :: target_c real(r8),pointer :: dbh - integer, pointer :: cdamage real(r8) :: canopy_trim integer :: ipft integer :: i_cvar @@ -1726,13 +1725,13 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe real(r8) :: sapw_c_target,agw_c_target real(r8) :: bgw_c_target,struct_c_target + + dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival i_cvar = prt_global%sp_organ_map(organ_id,carbon12_element) - cdamage => this%bc_inout(acnp_bc_inout_id_cdamage)%ival - ! Storage of nutrients are assumed to have different compartments than ! for carbon, and thus their targets are not associated with a tissue @@ -1741,10 +1740,10 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe if(organ_id == store_organ) then - call bleaf(dbh,ipft,1, canopy_trim,leaf_c_target) + call bleaf(dbh,ipft,canopy_trim,leaf_c_target) call bfineroot(dbh,ipft,canopy_trim,fnrt_c_target) - call bsap_allom(dbh,ipft,1, canopy_trim,sapw_area,sapw_c_target) - call bagw_allom(dbh,ipft,1, agw_c_target) + call bsap_allom(dbh,ipft,canopy_trim,sapw_area,sapw_c_target) + call bagw_allom(dbh,ipft,agw_c_target) call bbgw_allom(dbh,ipft,bgw_c_target) call bdead_allom(agw_c_target,bgw_c_target, sapw_c_target, ipft, struct_c_target) @@ -2102,8 +2101,8 @@ function AllomCNPGrowthDeriv(l_state_array,l_state_mask,cbalance,intgr_params) r ! locals integer :: ipft ! PFT index + integer :: crowndamage ! Damage class real(r8) :: canopy_trim ! Canopy trimming function (boundary condition [0-1] - integer :: icrowndamage ! crown damage index real(r8) :: leaf_c_target ! target leaf biomass, dummy var (kgC) real(r8) :: fnrt_c_target ! target fine-root biomass, dummy var (kgC) real(r8) :: sapw_c_target ! target sapwood biomass, dummy var (kgC) @@ -2142,16 +2141,16 @@ function AllomCNPGrowthDeriv(l_state_array,l_state_mask,cbalance,intgr_params) r canopy_trim = intgr_params(acnp_bc_in_id_ctrim) ipft = int(intgr_params(acnp_bc_in_id_pft)) - icrowndamage = int(intgr_params(acnp_bc_inout_id_cdamage)) - - call bleaf(dbh,ipft,icrowndamage, canopy_trim,leaf_c_target,leaf_dcdd_target) + crowndamage = int(intgr_params(acnp_bc_in_id_cdamage)) + + call bleaf(dbh,ipft,crowndamage,canopy_trim,leaf_c_target,leaf_dcdd_target) call bfineroot(dbh,ipft,canopy_trim,fnrt_c_target,fnrt_dcdd_target) - call bsap_allom(dbh,ipft,icrowndamage, canopy_trim,sapw_area,sapw_c_target,sapw_dcdd_target) - call bagw_allom(dbh,ipft,icrowndamage, agw_c_target,agw_dcdd_target) + call bsap_allom(dbh,ipft,crowndamage,canopy_trim,sapw_area,sapw_c_target,sapw_dcdd_target) + call bagw_allom(dbh,ipft,crowndamage,agw_c_target,agw_dcdd_target) call bbgw_allom(dbh,ipft,bgw_c_target,bgw_dcdd_target) call bdead_allom(agw_c_target,bgw_c_target, sapw_c_target, ipft, struct_c_target, & agw_dcdd_target, bgw_dcdd_target, sapw_dcdd_target, struct_dcdd_target) - call bstore_allom(dbh,ipft,icrowndamage,canopy_trim,store_c_target,store_dcdd_target) + call bstore_allom(dbh,ipft,crowndamage,canopy_trim,store_c_target,store_dcdd_target) if (mask_repro) then ! fraction of carbon going towards reproduction diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index d2bce65d35..2a158aed30 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -90,14 +90,15 @@ module PRTAllometricCarbonMod integer, public, parameter :: ac_bc_inout_id_dbh = 1 ! Plant DBH integer, public, parameter :: ac_bc_inout_id_netdc = 2 ! Index for the net daily C input BC - integer, public, parameter :: ac_bc_inout_id_cdamage = 3 ! Index for the crowndamage input BC - integer, parameter :: num_bc_inout = 3 ! Number of in & output boundary conditions + + integer, parameter :: num_bc_inout = 2 ! Number of in & output boundary conditions integer, public, parameter :: ac_bc_in_id_pft = 1 ! Index for the PFT input BC integer, public, parameter :: ac_bc_in_id_ctrim = 2 ! Index for the canopy trim function integer, public, parameter :: ac_bc_in_id_lstat = 3 ! Leaf status (on or off) - integer, parameter :: num_bc_in = 3 ! Number of input boundary conditions + integer, public, parameter :: ac_bc_in_id_cdamage = 4 ! Index for the crowndamage input BC + integer, parameter :: num_bc_in = 4 ! Number of input boundary conditions ! THere are no purely output boundary conditions @@ -298,8 +299,7 @@ subroutine DailyPRTAllometricCarbon(this,phase) ! this local will point to both in and out bc's real(r8),pointer :: carbon_balance ! Daily carbon balance for this cohort [kgC] - real(r8), pointer :: n ! number of plants - integer, pointer :: crowndamage ! which crown damage class + integer :: crowndamage ! which crown damage class real(r8) :: canopy_trim ! The canopy trimming function [0-1] @@ -392,12 +392,13 @@ subroutine DailyPRTAllometricCarbon(this,phase) character(len=19), parameter :: fmth = '(a,1x,a5,3(1x,a12))' character(len=22), parameter :: fmtg = '(a,5x,l1,3(1x,es12.5))' - real(r8) :: intgr_params(num_bc_in+1) ! The boundary conditions to this routine, + ! The boundary conditions to this routine, ! are pressed into an array that is also ! passed to the integrators ! add one because we pass crown damage also ! which is not a bc_in - + + real(r8) :: intgr_params(num_bc_in) associate( & @@ -417,12 +418,13 @@ subroutine DailyPRTAllometricCarbon(this,phase) dbh => this%bc_inout(ac_bc_inout_id_dbh)%rval carbon_balance => this%bc_inout(ac_bc_inout_id_netdc)%rval - crowndamage => this%bc_inout(ac_bc_inout_id_cdamage)%ival + canopy_trim = this%bc_in(ac_bc_in_id_ctrim)%rval ipft = this%bc_in(ac_bc_in_id_pft)%ival leaf_status = this%bc_in(ac_bc_in_id_lstat)%ival - + crowndamage = this%bc_in(ac_bc_in_id_cdamage)%ival + nleafage = prt_global%state_descriptor(leaf_c_id)%num_pos ! Number of leaf age class ! ----------------------------------------------------------------------------------- @@ -644,10 +646,10 @@ subroutine DailyPRTAllometricCarbon(this,phase) ! left to allocate, and thus it must be on allometry when its not. ! ----------------------------------------------------------------------------------- - intgr_params(:) = un_initialized - intgr_params(ac_bc_in_id_ctrim) = this%bc_in(ac_bc_in_id_ctrim)%rval - intgr_params(ac_bc_in_id_pft) = real(this%bc_in(ac_bc_in_id_pft)%ival) - intgr_params(num_bc_in + 1) = real(this%bc_inout(ac_bc_inout_id_cdamage)%ival) + intgr_params(:) = un_initialized + intgr_params(ac_bc_in_id_ctrim) = this%bc_in(ac_bc_in_id_ctrim)%rval + intgr_params(ac_bc_in_id_pft) = real(this%bc_in(ac_bc_in_id_pft)%ival) + intgr_params(ac_bc_in_id_cdamage) = real(this%bc_in(ac_bc_in_id_cdamage)%ival) @@ -906,16 +908,16 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) real(r8),dimension(lbound(c_pools,dim=1):ubound(c_pools,dim=1)) :: dCdx ! locals - integer :: ipft ! PFT index - integer :: crowndamage + integer :: ipft ! PFT index + integer :: crowndamage ! Damage class real(r8) :: canopy_trim ! Canopy trimming function (boundary condition [0-1] - real(r8) :: ct_leaf ! target leaf biomass, dummy var (kgC) - real(r8) :: ct_fnrt ! target fine-root biomass, dummy var (kgC) - real(r8) :: ct_sap ! target sapwood biomass, dummy var (kgC) - real(r8) :: ct_agw ! target aboveground wood, dummy var (kgC) - real(r8) :: ct_bgw ! target belowground wood, dummy var (kgC) - real(r8) :: ct_store ! target storage, dummy var (kgC) - real(r8) :: ct_dead ! target structural biomas, dummy var (kgC) + real(r8) :: ct_leaf ! target leaf biomass, dummy var (kgC) + real(r8) :: ct_fnrt ! target fine-root biomass, dummy var (kgC) + real(r8) :: ct_sap ! target sapwood biomass, dummy var (kgC) + real(r8) :: ct_agw ! target aboveground wood, dummy var (kgC) + real(r8) :: ct_bgw ! target belowground wood, dummy var (kgC) + real(r8) :: ct_store ! target storage, dummy var (kgC) + real(r8) :: ct_dead ! target structural biomas, dummy var (kgC) real(r8) :: sapw_area ! dummy sapwood area real(r8) :: ct_dleafdd ! target leaf biomass derivative wrt diameter, (kgC/cm) real(r8) :: ct_dfnrtdd ! target fine-root biomass derivative wrt diameter, (kgC/cm) @@ -945,7 +947,7 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) canopy_trim = intgr_params(ac_bc_in_id_ctrim) ipft = int(intgr_params(ac_bc_in_id_pft)) - crowndamage = int(intgr_params(num_bc_in + 1)) + crowndamage = int(intgr_params(ac_bc_in_id_cdamage)) call bleaf(dbh,ipft,crowndamage,canopy_trim,ct_leaf, dbldd=ct_dleafdd) call bfineroot(dbh,ipft,canopy_trim,ct_fnrt,ct_dfnrtdd) From f6bfc64e6f49cb738cea4d92098b01e84236dc0c Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 1 Jul 2022 12:15:46 -0600 Subject: [PATCH 269/852] Various merge resolutions and fixes for new damge recovery scheme --- biogeochem/DamageMainMod.F90 | 90 ++++++++++++++-------- biogeochem/EDCanopyStructureMod.F90 | 2 +- biogeochem/EDCohortDynamicsMod.F90 | 3 +- biogeochem/EDMortalityFunctionsMod.F90 | 4 +- biogeochem/EDPatchDynamicsMod.F90 | 17 ++-- biogeophys/FatesPlantRespPhotosynthMod.F90 | 4 +- main/EDInitMod.F90 | 4 +- main/EDMainMod.F90 | 9 ++- main/EDPftvarcon.F90 | 40 ++++++++++ main/FatesHistoryInterfaceMod.F90 | 18 ++--- main/FatesIOVariableKindMod.F90 | 3 - main/FatesInterfaceTypesMod.F90 | 26 +------ main/FatesParametersInterface.F90 | 2 - main/FatesRestartInterfaceMod.F90 | 18 ++--- parteh/PRTAllometricCNPMod.F90 | 53 +++++++------ parteh/PRTAllometricCarbonMod.F90 | 2 +- parteh/PRTParamsFATESMod.F90 | 10 ++- 17 files changed, 173 insertions(+), 132 deletions(-) diff --git a/biogeochem/DamageMainMod.F90 b/biogeochem/DamageMainMod.F90 index c2cef680e4..290db57225 100644 --- a/biogeochem/DamageMainMod.F90 +++ b/biogeochem/DamageMainMod.F90 @@ -4,15 +4,22 @@ module DamageMainMod use FatesConstantsMod , only : i4 => fates_int use FatesConstantsMod , only : itrue, ifalse use FatesConstantsMod , only : years_per_day + use FatesConstantsMod , only : nearzero use FatesGlobals , only : fates_log use FatesGlobals , only : endrun => fates_endrun use shr_log_mod , only : errMsg => shr_log_errMsg use EDPftvarcon , only : EDPftvarcon_inst use EDParamsMod , only : damage_event_code - use EDtypesMod , only : ed_site_type - use EDtypesMod , only : ed_patch_type - use EDtypesMod , only : ed_cohort_type - use EDtypesMod , only : AREA + use EDTypesMod , only : ed_site_type + use EDTypesMod , only : ed_patch_type + use EDTypesMod , only : ed_cohort_type + use EDTypesMod , only : AREA + use EDTypesMod , only : leaves_on + use PRTGenericMod, only : num_elements + use PRTGenericMod, only : element_list + use PRTGenericMod, only : carbon12_element + use PRTGenericMod, only : nitrogen_element + use PRTGenericMod, only : phosphorus_element use PRTGenericMod, only : leaf_organ use PRTGenericMod, only : carbon12_element use PRTGenericMod, only : all_carbon_elements @@ -23,13 +30,25 @@ module DamageMainMod use PRTGenericMod, only : repro_organ use PRTGenericMod, only : struct_organ use PRTGenericMod, only : SetState + use PRTGenericMod, only : StorageNutrientTarget + use PRTParametersMod, only : prt_params use FatesInterfaceTypesMod, only : hlm_current_day use FatesInterfaceTypesMod, only : hlm_current_month use FatesInterfaceTypesMod, only : hlm_current_year use FatesInterfaceTypesMod, only : hlm_model_day - use FatesInterfaceTypesMod , only : hlm_day_of_year - - + use FatesInterfaceTypesMod, only : hlm_day_of_year + use FatesInterfaceTypesMod, only : hlm_use_planthydro + use FatesAllometryMod, only : bsap_allom + use FatesAllometryMod, only : bagw_allom + use FatesAllometryMod, only : bbgw_allom + use FatesAllometryMod, only : bdead_allom + use FatesAllometryMod, only : bfineroot + use FatesAllometryMod, only : bstore_allom + use FatesAllometryMod, only : bleaf + use EDCohortDynamicsMod, only : copy_cohort + use FatesPlantHydraulicsMod, only : InitHydrCohort + use EDCohortDynamicsMod , only : InitPRTObject + use EDCohortDynamicsMod , only : InitPRTBoundaryConditions implicit none private @@ -77,26 +96,34 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) type(ed_site_type) :: csite ! Site of the current cohort type(ed_patch_type) :: cpatch ! patch of the current cohort - type(ed_cohort_type) :: ccohort ! Current (damaged) cohort + type(ed_cohort_type),pointer :: ccohort ! Current (damaged) cohort logical :: newly_recovered ! true if we create a new cohort ! locals type(ed_cohort_type), pointer :: rcohort ! New cohort that recovers by ! having an lower damage class - real(r8) :: sapw_area - real(r8) :: target_sapw_c,target_sapw_m - real(r8) :: target_agw_c - real(r8) :: target_bgw_c - real(r8) :: target_struct_c,target_struct_m - real(r8) :: target_fnrt_c,target_fnrt_m - real(r8) :: target_leaf_c,target_leaf_m - real(r8) :: target_store_c,target_store_m - real(r8) :: target_repro_m - real(r8) :: mass_d - real(r8) :: mass_dminus1 - real(r8) :: recovery_demand - real(r8) :: max_recover_nplant - real(r8) :: nplant_recover + real(r8) :: sapw_area ! sapwood area + real(r8) :: target_sapw_c,target_sapw_m ! sapwood mass, C and N/P + real(r8) :: target_agw_c ! target above ground wood + real(r8) :: target_bgw_c ! target below ground wood + real(r8) :: target_struct_c,target_struct_m ! target structural C and N/P + real(r8) :: target_fnrt_c,target_fnrt_m ! target fine-root C and N/P + real(r8) :: target_leaf_c,target_leaf_m ! target leaf C and N/P + real(r8) :: target_store_c,target_store_m ! target storage C and N/P + real(r8) :: target_repro_m ! target reproductive C/N/P + real(r8) :: leaf_m,fnrt_m,sapw_m ! actual masses in organs C/N/P + real(r8) :: struct_m,store_m,repro_m ! actual masses in organs C/N/P + real(r8) :: mass_d ! intermediate term for nplant_recover + real(r8) :: mass_dminus1 ! intermediate term for nplant_recover + real(r8) :: available_m ! available mass that can be used to + ! improve damage class + real(r8) :: recovery_demand ! amount of mass needed to get to + ! get to the target of the next damage class + real(r8) :: max_recover_nplant ! max number of plants that could get to + ! target of next class + real(r8) :: nplant_recover ! number of plants in cohort that will + ! recover to the next class + integer :: el ! element loop counter associate(dbh => ccohort%dbh, & ipft => ccohort%pft, & @@ -109,7 +136,7 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) ! then no recovery is possible, do nothing and ! return a null pointer if ((ccohort%crowndamage == undamaged_class) .or. & - (damage_recovery_scalar < nearzero) ) then + (EDPftvarcon_inst%damage_recovery_scalar(ipft) < nearzero) ) then newly_recovered = .false. return end if @@ -134,10 +161,10 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) ! Target fine-root biomass and deriv. according to allometry and trimming [kgC, kgC/cm] call bfineroot(dbh,ipft,canopy_trim,target_fnrt_c) ! Target storage carbon [kgC,kgC/cm] - call bstore_allom(dbh,ipft,crowndamage-1, canopy_trim,target_store_c) + call bstore_allom(dbh,ipft,ccohort%crowndamage-1, canopy_trim,target_store_c) ! Target leaf biomass according to allometry and trimming if(ccohort%status_coh==leaves_on) then - call bleaf(dbh,ipft,crowndamage-1, canopy_trim,target_leaf_c) + call bleaf(dbh,ipft,ccohort%crowndamage-1, canopy_trim,target_leaf_c) else target_leaf_c = 0._r8 end if @@ -178,7 +205,7 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(sapw_organ)) target_repro_m = 0._r8 target_store_m = StorageNutrientTarget(ipft, element_list(el), & - leaf_target_m, fnrt_target_m, sapw_target_m, struct_target_m) + target_leaf_m, target_fnrt_m, target_sapw_m, target_struct_m) ! For nutrients, all uptake is immediately put into storage, so just swap ! them and assume storage is what is available, but needs to be filled up available_m = store_m @@ -194,7 +221,7 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(sapw_organ)) target_repro_m = 0._r8 target_store_m = StorageNutrientTarget(ipft, element_list(el), & - leaf_target_m, fnrt_target_m, sapw_target_m, struct_target_m) + target_leaf_m, target_fnrt_m, target_sapw_m, target_struct_m) ! For nutrients, all uptake is immediately put into storage, so just swap ! them and assume storage is what is available, but needs to be filled up available_m = store_m @@ -212,7 +239,7 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) mass_dminus1 = max(leaf_m, target_leaf_m) + max(fnrt_m, target_fnrt_m) + & max(store_m, target_store_m) + max(sapw_m, target_sapw_m) + & - max(struct_m, target_struct_m)) + max(struct_m, target_struct_m) ! Mass needed to get from current mass to allometric ! target mass of next damage class up @@ -222,7 +249,8 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) max_recover_nplant = available_m * ccohort%n / recovery_demand ! 4. Use the scalar to decide how many to recover - nplant_recover = min(nplant_recover,max(0._r8,max_recover_nplant * damage_recovery_scalar)) + nplant_recover = min(nplant_recover,max(0._r8,max_recover_nplant * & + EDPftvarcon_inst%damage_recovery_scalar(ipft) )) end do @@ -233,10 +261,10 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) ! allowing the donor cohort to recover and then go through ! prt - will this work though? if they are not anywhere near allometry? - if( abs(damage_recovery_scalar-1._r8) < nearzero .and. & + if( abs(EDPftvarcon_inst%damage_recovery_scalar(ipft)-1._r8) < nearzero .and. & nplant_recover > ccohort%n) then nplant_recover = 0.0_r8 - crowndamage = crowndamage - 1 + ccohort%crowndamage = ccohort%crowndamage - 1 end if if(nplant_recover < nearzero) then diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 9fc30b478b..6efbbeee93 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -2219,7 +2219,7 @@ subroutine UpdatePatchLAI(currentPatch, patch_lai, currentSite) ! Update the cohort level lai and related variables call UpdateCohortLAI(currentCohort,currentPatch%canopy_layer_tlai, & - currentPatch%total_canopy_area, currentSite%spread) + currentPatch%total_canopy_area) ! Update the number of number of vegetation layers currentPatch%ncan(cl,ft) = max(currentPatch%ncan(cl,ft),currentCohort%NV) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 1f48a1f055..71aa369b07 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -11,7 +11,7 @@ Module EDCohortDynamicsMod use FatesInterfaceTypesMod , only : hlm_use_planthydro use FatesInterfaceTypesMod , only : hlm_use_sp use FatesInterfaceTypesMod , only : hlm_use_cohort_age_tracking - use FatesInterfaceTypesMod , only : hlm_use_crown_damage + use FatesInterfaceTypesMod , only : hlm_use_tree_damage use FatesInterfaceTypesMod , only : hlm_is_restart use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : fates_unset_int @@ -88,7 +88,6 @@ Module EDCohortDynamicsMod use PRTAllometricCarbonMod, only : callom_prt_vartypes use PRTAllometricCarbonMod, only : ac_bc_inout_id_netdc use PRTAllometricCarbonMod, only : ac_bc_in_id_pft - use PRTAllometricCarbonMod, only : ac_bc_inout_id_n use PRTAllometricCarbonMod, only : ac_bc_in_id_ctrim use PRTAllometricCarbonMod, only : ac_bc_inout_id_dbh use PRTAllometricCarbonMod, only : ac_bc_in_id_lstat, ac_bc_in_id_cdamage diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index d745f468d5..e160703945 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -19,7 +19,7 @@ module EDMortalityFunctionsMod use FatesInterfaceTypesMod , only : hlm_use_ed_prescribed_phys use FatesInterfaceTypesMod , only : hlm_freq_day use FatesInterfaceTypesMod , only : hlm_use_planthydro - use FatesInterfaceTypesMod , only : hlm_use_crown_damage + use FatesInterfaceTypesMod , only : hlm_use_tree_damage use EDLoggingMortalityMod , only : LoggingMortality_frac use EDParamsMod , only : fates_mortality_disturbance_fraction @@ -123,7 +123,7 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmor end if ! Damage dependent mortality - if (hlm_use_crown_damage .eq. itrue) then + if (hlm_use_tree_damage .eq. itrue) then call GetDamageMortality(cohort_in%crowndamage, cohort_in%pft, dgmort) else dgmort = 0.0_r8 diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index ee6b4d2ae4..83c027fdf8 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -7,6 +7,7 @@ module EDPatchDynamicsMod use FatesGlobals , only : FatesWarn,N2S,A2S use FatesInterfaceTypesMod , only : hlm_freq_day use FatesInterfaceTypesMod , only : hlm_days_per_year + use FatesInterfaceTypesMod, only : hlm_use_tree_damage use EDPftvarcon , only : EDPftvarcon_inst use EDPftvarcon , only : GetDecompyFrac use PRTParametersMod , only : prt_params @@ -463,7 +464,6 @@ subroutine spawn_patches( currentSite, bc_in) use PRTLossFluxesMod , only : PRTDamageLosses use PRTGenericMod , only : leaf_organ use ChecksBalancesMod , only : SiteMassStock - use FatesInterfaceTypesMod, only : hlm_use_crown_damage use FatesInterfaceTypesMod, only : nlevdamage use FatesParameterDerivedMod, only : param_derived use EDParamsMod , only : damage_canopy_layer_code @@ -754,7 +754,7 @@ subroutine spawn_patches( currentSite, bc_in) ! and the damaged trees - if(hlm_use_crown_damage .eq. itrue) then + if(hlm_use_tree_damage .eq. itrue) then if(damage_time) then call damage_litter_fluxes(currentSite, currentPatch, & @@ -899,7 +899,7 @@ subroutine spawn_patches( currentSite, bc_in) total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 - if (hlm_use_crown_damage .eq. itrue) then + if (hlm_use_tree_damage .eq. itrue) then currentSite%imort_rate_damage(currentCohort%crowndamage, & currentCohort%size_class, currentCohort%pft) = & @@ -1013,7 +1013,7 @@ subroutine spawn_patches( currentSite, bc_in) end if ! also track fire damage mortality and cflux along size x damage axis - if(hlm_use_crown_damage .eq. itrue) then + if(hlm_use_tree_damage .eq. itrue) then if(levcan==ican_upper) then currentSite%fmort_rate_canopy_damage(currentCohort%crowndamage, currentCohort%size_class, & currentCohort%pft) = & @@ -1172,7 +1172,7 @@ subroutine spawn_patches( currentSite, bc_in) logging_coll_under_frac/ hlm_freq_day ) * & total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 - if (hlm_use_crown_damage .eq. itrue) then + if (hlm_use_tree_damage .eq. itrue) then currentSite%imort_rate_damage(currentCohort%crowndamage,& currentCohort%size_class, currentCohort%pft) = & currentSite%imort_rate_damage(currentCohort%crowndamage,& @@ -1247,7 +1247,7 @@ subroutine spawn_patches( currentSite, bc_in) ! Regardless of disturbance type, reduce mass of damaged trees - if(hlm_use_crown_damage .eq. itrue) then + if(hlm_use_tree_damage .eq. itrue) then if(damage_time) then ! if woody @@ -2378,7 +2378,6 @@ subroutine damage_litter_fluxes(currentSite, currentPatch, newPatch,patch_site_a use FatesInterfaceTypesMod , only : nlevdamage use EDParamsMod , only : ED_val_understorey_death use EDParamsMod , only : damage_canopy_layer_code - use FatesInterfaceTypesMod, only : hlm_use_crown_damage use FatesConstantsMod, only : itrue use FatesParameterDerivedMod, only : param_derived ! @@ -2493,7 +2492,7 @@ subroutine damage_litter_fluxes(currentSite, currentPatch, newPatch,patch_site_a if(prt_params%woody(currentCohort%pft)==1) then - if( hlm_use_crown_damage .eq.itrue .and. & + if( hlm_use_tree_damage .eq.itrue .and. & currentCohort%canopy_layer ==1 .and. i_damage_code .eq. 1 .and. & .not. currentCohort%isnew) then @@ -2501,7 +2500,7 @@ subroutine damage_litter_fluxes(currentSite, currentPatch, newPatch,patch_site_a num_trees = currentCohort%n * (1.0_r8 - fates_mortality_disturbance_fraction * & min(1.0_r8, currentCohort%dmort* hlm_freq_day)) - else if( hlm_use_crown_damage .eq.itrue .and. & + else if( hlm_use_tree_damage .eq.itrue .and. & currentCohort%canopy_layer > 1 .and. i_damage_code .eq. 2 .and. & .not. currentCohort%isnew) then diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index df836bbff4..e3286d7b00 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -138,7 +138,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) use DamageMainMod, only : GetCrownReduction - use FatesInterfaceTypesMod, only : hlm_use_crown_damage + use FatesInterfaceTypesMod, only : hlm_use_tree_damage ! ARGUMENTS: ! ----------------------------------------------------------------------------------- @@ -653,7 +653,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) - if (hlm_use_crown_damage .eq. itrue) then + if (hlm_use_tree_damage .eq. itrue) then agb_frac = prt_params%allom_agb_frac(currentCohort%pft) branch_frac = param_derived%branch_frac(currentCohort%pft) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 22e9203ef4..526f8b0715 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -43,7 +43,7 @@ module EDInitMod use FatesInterfaceTypesMod , only : hlm_use_planthydro use FatesInterfaceTypesMod , only : hlm_use_inventory_init use FatesInterfaceTypesMod , only : hlm_use_fixed_biogeog - use FatesInterfaceTypesMod , only : hlm_use_crown_damage + use FatesInterfaceTypesMod , only : hlm_use_tree_damage use FatesInterfaceTypesMod , only : hlm_use_sp use FatesInterfaceTypesMod , only : numpft use FatesInterfaceTypesMod , only : nleafage @@ -131,7 +131,7 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) allocate(site_in%mass_balance(1:num_elements)) allocate(site_in%flux_diags(1:num_elements)) - if (hlm_use_crown_damage .eq. itrue) then + if (hlm_use_tree_damage .eq. itrue) then allocate(site_in%term_nindivs_canopy_damage(1:nlevdamage, 1:nlevsclass, 1:numpft)) allocate(site_in%term_nindivs_ustory_damage(1:nlevdamage, 1:nlevsclass, 1:numpft)) allocate(site_in%imort_rate_damage(1:nlevdamage, 1:nlevsclass, 1:numpft)) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 03e9903de8..ccdc3e5ae7 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -19,7 +19,7 @@ module EDMainMod use FatesInterfaceTypesMod , only : hlm_use_cohort_age_tracking use FatesInterfaceTypesMod , only : hlm_reference_date use FatesInterfaceTypesMod , only : hlm_use_ed_prescribed_phys - use FatesInterfaceTypesMod , only : hlm_use_crown_damage + use FatesInterfaceTypesMod , only : hlm_use_tree_damage use FatesInterfaceTypesMod , only : hlm_use_ed_st3 use FatesInterfaceTypesMod , only : hlm_use_sp use FatesInterfaceTypesMod , only : bc_in_type @@ -361,7 +361,10 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) real(r8) :: delta_dbh ! correction for dbh real(r8) :: delta_hite ! correction for hite real(r8) :: current_npp ! place holder for calculating npp each year in prescribed physiology mode - + logical :: newly_recovered ! If the current loop is dealing with a newly created cohort, which + ! was created because it is a clone of the previous cohort in + ! a lowered damage state. This cohort should bypass several calculations + ! because it inherited them (such as daily carbon balance) real(r8) :: target_leaf_c real(r8) :: frac_site_primary @@ -540,7 +543,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) call currentCohort%prt%DailyPRT(phase=1) if((newly_recovered .eq. .false.) .and. & - (hlm_use_crown_damage .eq. itrue) ) then + (hlm_use_tree_damage .eq. itrue) ) then ! The loop order is shortest to tallest ! The recovered cohort (ie one with larger targets) ! is newly created in DamageRecovery(), and diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 7d6d4f641b..d7319dfa2c 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -131,6 +131,14 @@ module EDPftvarcon real(r8), allocatable :: prescribed_recruitment(:) ! this is only for the ! prescribed_physiology_mode + + ! Damage Parameters + + real(r8), allocatable :: damage_frac(:) ! Fraction of each cohort damaged per year + real(r8), allocatable :: damage_mort_p1(:) ! Inflection point for damage mortality function + real(r8), allocatable :: damage_mort_p2(:) ! Rate parameter for damage mortality function + real(r8), allocatable :: damage_recovery_scalar(:) ! what fraction of cohort gets to recover + ! Nutrient Aquisition (ECA & RD) @@ -430,6 +438,22 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_damage_frac' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_damage_mort_p1' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_damage_mort_p2' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_damage_recovery_scalar' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_fire_alpha_SH' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -763,6 +787,22 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetrieveParameterAllocate(name=name, & data=this%prescribed_recruitment) + name = 'fates_damage_frac' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%damage_frac) + + name = 'fates_damage_mort_p1' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%damage_mort_p1) + + name = 'fates_damage_mort_p2' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%damage_mort_p2) + + name = 'fates_damage_recovery_scalar' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%damage_recovery_scalar) + name = 'fates_fire_alpha_SH' call fates_params%RetrieveParameterAllocate(name=name, & data=this%fire_alpha_SH) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index abac9921d7..2987c5df56 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -38,7 +38,7 @@ module FatesHistoryInterfaceMod use FatesInterfaceTypesMod , only : hlm_use_planthydro use FatesInterfaceTypesMod , only : hlm_use_ed_st3 use FatesInterfaceTypesMod , only : hlm_use_cohort_age_tracking - use FatesInterfaceTypesMod , only : hlm_use_crown_damage + use FatesInterfaceTypesMod , only : hlm_use_tree_damage use FatesInterfaceTypesMod , only : nlevdamage use FatesInterfaceTypesMod , only : numpft use FatesInterfaceTypesMod , only : hlm_freq_day @@ -2216,7 +2216,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) end do ! damage variables - site level - this needs to be OUT of the patch loop - if(hlm_use_crown_damage .eq. itrue) then + if(hlm_use_tree_damage .eq. itrue) then this%hvars(ih_crownarea_canopy_damage_si)%r81d(io_si) = & this%hvars(ih_crownarea_canopy_damage_si)%r81d(io_si) + & @@ -2643,7 +2643,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) scls => ccohort%size_class, & cacls => ccohort%coage_class, & capf => ccohort%coage_by_pft_class, & - cdam => ccohort%crowndamage)) + cdam => ccohort%crowndamage) gpp_cached = (hio_gpp_si_scpf(io_si,scpf)) * & days_per_year * sec_per_day @@ -2749,7 +2749,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) end if ! damage variables - cohort level - if(hlm_use_crown_damage .eq. itrue) then + if(hlm_use_tree_damage .eq. itrue) then cdpf = get_cdamagesizepft_class_index(ccohort%dbh, ccohort%crowndamage, ccohort%pft) @@ -2912,7 +2912,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) ccohort%n * ccohort%npp_acc_hold / m2_per_ha / days_per_year / sec_per_day ! damage variables - canopy - if(hlm_use_crown_damage .eq. itrue) then + if(hlm_use_tree_damage .eq. itrue) then ! carbon starvation mortality in the canopy by size x damage x pft this%hvars(ih_m3_mortality_canopy_si_cdpf)%r82d(io_si,cdpf) = & @@ -3045,7 +3045,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) ccohort%npp_acc_hold * ccohort%n / m2_per_ha / days_per_year / sec_per_day ! damage variables - understory - if(hlm_use_crown_damage .eq. itrue) then + if(hlm_use_tree_damage .eq. itrue) then ! carbon mortality in the understory by damage x size x pft this%hvars(ih_m3_mortality_understory_si_cdpf)%r82d(io_si,cdpf) = & @@ -3335,7 +3335,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_firemortality_carbonflux_si_pft(io_si,i_pft) = sites(s)%fmort_carbonflux_canopy(i_pft) / g_per_kg end do - if(hlm_use_crown_damage .eq. itrue) then + if(hlm_use_tree_damage .eq. itrue) then do i_pft = 1, numpft do icdam = 1, nlevdamage @@ -3417,7 +3417,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_m9_si_scpf(io_si,i_scpf) + & hio_m10_si_scpf(io_si,i_scpf) - if(hlm_use_crown_damage .eq. itrue) then + if(hlm_use_tree_damage .eq. itrue) then hio_mortality_si_pft(io_si, i_pft) = hio_mortality_si_pft(io_si,i_pft) + & this%hvars(ih_m11_si_scpf)%r82d(io_si,i_scpf) end if @@ -6923,7 +6923,7 @@ subroutine define_history_vars(this, initialize_variables) ! CROWN DAMAGE VARIABLES - if_crowndamage: if(hlm_use_crown_damage .eq. itrue) then + if_crowndamage: if(hlm_use_tree_damage .eq. itrue) then call this%set_history_var(vname='FATES_CROWNAREA_CANOPY_CD', units = 'm2 m-2 yr-1', & long='crownarea lost to damage each year', use_default='inactive', & diff --git a/main/FatesIOVariableKindMod.F90 b/main/FatesIOVariableKindMod.F90 index c311b03de0..853122730e 100644 --- a/main/FatesIOVariableKindMod.F90 +++ b/main/FatesIOVariableKindMod.F90 @@ -36,9 +36,6 @@ module FatesIOVariableKindMod character(*), parameter, public :: site_cdsc_r8 = 'SI_CDSC_R8' character(*), parameter, public :: site_cdam_r8 = 'SI_CDAM_R8' character(*), parameter, public :: site_cnlfpft_r8 = 'SI_CNLFPFT_R8' - character(*), parameter, public :: site_cdpf_r8 = 'SI_CDPF_R8' - character(*), parameter, public :: site_cdsc_r8 = 'SI_CDSC_R8' - character(*), parameter, public :: site_cdam_r8 = 'SI_CDAM_R8' character(*), parameter, public :: site_scag_r8 = 'SI_SCAG_R8' character(*), parameter, public :: site_scagpft_r8 = 'SI_SCAGPFT_R8' character(*), parameter, public :: site_agepft_r8 = 'SI_AGEPFT_R8' diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index ad9020cb65..5df7fd7abf 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -146,21 +146,6 @@ module FatesInterfaceTypesMod ! cohort age tracking. 1 = TRUE, 0 = FALSE -<<<<<<< HEAD - integer, public :: hlm_use_crown_damage ! This flag signals whether or not to use - ! the crown damage module. 1 = TRUE, 0 = FALSE - - - integer, public :: hlm_use_ed_st3 ! This flag signals whether or not to use - ! (ST)atic (ST)and (ST)ructure mode (ST3) - ! Essentially, this gives us the ability - ! to turn off "dynamics", ie growth, disturbance - ! recruitment and mortality. - ! (EXPERIMENTAL!!!!! - RGK 07-2017) - ! 1 = TRUE, 0 = FALSE - ! default should be FALSE (dynamics on) - ! cannot be true with prescribed_phys -======= integer, public :: hlm_use_tree_damage ! This flag signals whether or not to turn on the ! tree damage module @@ -173,7 +158,6 @@ module FatesInterfaceTypesMod ! 1 = TRUE, 0 = FALSE ! default should be FALSE (dynamics on) ! cannot be true with prescribed_phys ->>>>>>> master integer, public :: hlm_use_ed_prescribed_phys ! This flag signals whether or not to use ! prescribed physiology, somewhat the opposite @@ -255,13 +239,6 @@ module FatesInterfaceTypesMod real(r8), public, allocatable :: fates_hdim_levsclass(:) ! plant size class lower bound dimension integer , public, allocatable :: fates_hdim_pfmap_levscpf(:) ! map of pfts into size-class x pft dimension integer , public, allocatable :: fates_hdim_scmap_levscpf(:) ! map of size-class into size-class x pft dimension - integer , public, allocatable :: fates_hdim_pftmap_levcdpf(:) ! map of pfts into size x crowndamage x pft dimension - integer , public, allocatable :: fates_hdim_cdmap_levcdpf(:) ! map of crowndamage into size x crowndamage x pft - integer , public, allocatable :: fates_hdim_scmap_levcdpf(:) ! map of size into size x crowndamage x pft - integer , public, allocatable :: fates_hdim_cdmap_levcdsc(:) ! map of crowndamage into size x crowndamage - integer , public, allocatable :: fates_hdim_scmap_levcdsc(:) ! map of size into size x crowndamage - integer , public, allocatable :: fates_hdim_levdamage(:) ! plant damage class lower bound dimension - real(r8), public, allocatable :: fates_hdim_levage(:) ! patch age lower bound dimension real(r8), public, allocatable :: fates_hdim_levheight(:) ! height lower bound dimension integer , public, allocatable :: fates_hdim_levpft(:) ! plant pft dimension @@ -554,7 +531,7 @@ module FatesInterfaceTypesMod character(len=64), allocatable :: hlm_harvest_catnames(:) ! names of hlm_harvest d1 integer :: hlm_harvest_units ! what units are the harvest rates specified in? [area vs carbon] - + ! Fixed biogeography mode real(r8), allocatable :: pft_areafrac(:) ! Fractional area of the FATES column occupied by each PFT @@ -745,6 +722,7 @@ module FatesInterfaceTypesMod ! small fluxes for various reasons ! [mm H2O/s] + ! FATES LULCC real(r8) :: hrv_deadstemc_to_prod10c ! Harvested C flux to 10-yr wood product pool [Site-Level, gC m-2 s-1] real(r8) :: hrv_deadstemc_to_prod100c ! Harvested C flux to 100-yr wood product pool [Site-Level, gC m-2 s-1] diff --git a/main/FatesParametersInterface.F90 b/main/FatesParametersInterface.F90 index ff44b73cd0..aa13150c4a 100644 --- a/main/FatesParametersInterface.F90 +++ b/main/FatesParametersInterface.F90 @@ -31,12 +31,10 @@ module FatesParametersInterface character(len=*), parameter, public :: dimension_name_hydr_organs = 'fates_hydr_organs' character(len=*), parameter, public :: dimension_name_prt_organs = 'fates_plant_organs' character(len=*), parameter, public :: dimension_name_leaf_age = 'fates_leafage_class' - character(len=*), parameter, public :: dimension_name_damage = 'fates_damage_class' character(len=*), parameter, public :: dimension_name_history_size_bins = 'fates_history_size_bins' character(len=*), parameter, public :: dimension_name_history_age_bins = 'fates_history_age_bins' character(len=*), parameter, public :: dimension_name_history_height_bins = 'fates_history_height_bins' character(len=*), parameter, public :: dimension_name_history_coage_bins = 'fates_history_coage_bins' - character(len=*), parameter, public :: dimension_name_history_damage_bins = 'fates_history_damage_bins' 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' diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 027dd08cfb..a225cce2e8 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -20,6 +20,7 @@ module FatesRestartInterfaceMod use FatesInterfaceTypesMod, only : hlm_use_planthydro use FatesInterfaceTypesMod, only : hlm_use_sp use FatesInterfaceTypesMod, only : fates_maxElementsPerSite + use FatesInterfaceTypesMod, only : hlm_use_tree_damage use EDCohortDynamicsMod, only : UpdateCohortBioPhysRates use FatesHydraulicsMemMod, only : nshell use FatesHydraulicsMemMod, only : n_hypool_ag @@ -1792,7 +1793,6 @@ end subroutine set_restart_var subroutine set_restart_vectors(this,nc,nsites,sites) - use FatesInterfaceTypesMod, only : hlm_use_crown_damage use FatesInterfaceTypesMod, only : fates_maxElementsPerPatch use FatesInterfaceTypesMod, only : numpft use EDTypesMod, only : ed_site_type @@ -1970,9 +1970,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_promcflux_si => this%rvars(ir_promcflux_si)%r81d, & rio_imortcflux_sipft => this%rvars(ir_imortcflux_sipft)%r81d, & rio_fmortcflux_cano_sipft => this%rvars(ir_fmortcflux_cano_sipft)%r81d, & - rio_fmortcflux_usto_sipft => this%rvars(ir_fmortcflux_usto_sipft)%r81d) - - ! damage + rio_fmortcflux_usto_sipft => this%rvars(ir_fmortcflux_usto_sipft)%r81d, & rio_imortrate_sicdpf => this%rvars(ir_imortrate_sicdpf)%r81d, & rio_imortcflux_sicdsc => this%rvars(ir_imortcflux_sicdsc)%r81d, & rio_termcflux_cano_sicdsc => this%rvars(ir_termcflux_cano_sicdsc)%r81d, & @@ -2379,7 +2377,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) ! this only copies live portions of transitions - but that's ok because the mortality ! bit only needs to be added for history outputs - if(hlm_use_crown_damage .eq. itrue) then + if(hlm_use_tree_damage .eq. itrue) then do i_scls = 1, nlevsclass do i_cdam = 1, nlevdamage @@ -2708,8 +2706,6 @@ subroutine get_restart_vectors(this, nc, nsites, sites) use EDTypesMod, only : numWaterMem use EDTypesMod, only : num_vegtemp_mem use FatesSizeAgeTypeIndicesMod, only : get_age_class_index - use FatesInterfaceTypesMod, only : hlm_use_crown_damage - ! !ARGUMENTS: class(fates_restart_interface_type) , intent(inout) :: this @@ -2870,13 +2866,9 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_promcflux_si => this%rvars(ir_promcflux_si)%r81d, & rio_termcarea_cano_si => this%rvars(ir_termcarea_cano_si)%r81d, & rio_termcarea_usto_si => this%rvars(ir_termcarea_usto_si)%r81d, & - rio_imortcarea_si => this%rvars(ir_imortcarea_si)%r81d, & rio_fmortcarea_cano_si => this%rvars(ir_fmortcarea_cano_si)%r81d, & rio_fmortcarea_usto_si => this%rvars(ir_fmortcarea_usto_si)%r81d, & - - - ! Damage rio_imortrate_sicdpf => this%rvars(ir_imortrate_sicdpf)%r81d, & rio_termnindiv_cano_sicdpf => this%rvars(ir_termnindiv_cano_sicdpf)%r81d, & rio_termnindiv_usto_sicdpf => this%rvars(ir_termnindiv_usto_sicdpf)%r81d, & @@ -2888,7 +2880,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_fmortcflux_cano_sicdsc => this%rvars(ir_fmortcflux_cano_sicdsc)%r81d, & rio_fmortcflux_usto_sicdsc => this%rvars(ir_fmortcflux_usto_sicdsc)%r81d, & rio_crownarea_cano_damage_si=> this%rvars(ir_crownarea_cano_si)%r81d, & - rio_crownarea_usto_damage_si=> this%rvars(ir_crownarea_usto_si)%r81d ) + rio_crownarea_usto_damage_si=> this%rvars(ir_crownarea_usto_si)%r81d, & rio_imortcflux_sipft => this%rvars(ir_imortcflux_sipft)%r81d, & rio_fmortcflux_cano_sipft => this%rvars(ir_fmortcflux_cano_sipft)%r81d, & rio_fmortcflux_usto_sipft => this%rvars(ir_fmortcflux_usto_sipft)%r81d) @@ -3308,7 +3300,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) io_idx_si_sc = io_idx_si_sc + 1 end do - if (hlm_use_crown_damage .eq. itrue) then + if (hlm_use_tree_damage .eq. itrue) then do i_cdam = 1, nlevdamage do i_pft = 1, numpft do i_scls = 1, nlevsclass diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index d9d0b1385d..6170a7ae2e 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -339,7 +339,7 @@ subroutine DailyPRTAllometricCNP(this,phase) real(r8) :: n_gain ! Daily nitrogen uptake through fine-roots [kgN] real(r8) :: p_gain ! Daily phosphorus uptake through fine-roots [kgN] real(r8) :: canopy_trim ! The canopy trimming function [0-1] - integer :: crowndamage ! which crown damage clas + integer :: crown_damage ! which crown damage clas ! Pointers to output bcs real(r8),pointer :: c_efflux ! Total plant efflux of carbon (kgC) @@ -409,7 +409,7 @@ subroutine DailyPRTAllometricCNP(this,phase) p_gain = this%bc_in(acnp_bc_in_id_netdp)%rval; p_gain0 = p_gain canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival - crowndamage = this%bc_in(acnp_bc_in_id_cdamage)%ival + crown_damage = this%bc_in(acnp_bc_in_id_cdamage)%ival ! Output only boundary conditions c_efflux => this%bc_out(acnp_bc_out_id_cefflux)%rval; c_efflux = 0._r8 @@ -424,7 +424,7 @@ subroutine DailyPRTAllometricCNP(this,phase) dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval; dbh0 = dbh - if(crowndamage>1)then + if(crown_damage>1)then write(fates_log(),*) 'The crown damage model is incompatible with' write(fates_log(),*) 'dynamic nutrients, ie parteh_mode=2' write(fates_log(),*) 'This feature will be brought in in with CNP v2' @@ -443,14 +443,14 @@ subroutine DailyPRTAllometricCNP(this,phase) ! Set carbon targets based on the plant's current stature target_c(:) = fates_unset_r8 target_dcdd(:) = fates_unset_r8 - call bsap_allom(dbh,ipft,canopy_trim,sapw_area,target_c(sapw_id),target_dcdd(sapw_id) ) - call bagw_allom(dbh,ipft,agw_c_target,agw_dcdd_target) + call bsap_allom(dbh,ipft,crown_damage,canopy_trim,sapw_area,target_c(sapw_id),target_dcdd(sapw_id) ) + call bagw_allom(dbh,ipft,crown_damage,agw_c_target,agw_dcdd_target) call bbgw_allom(dbh,ipft,bgw_c_target,bgw_dcdd_target) call bdead_allom(agw_c_target,bgw_c_target, target_c(sapw_id), ipft, target_c(struct_id), & agw_dcdd_target, bgw_dcdd_target, target_dcdd(sapw_id), target_dcdd(struct_id)) - call bleaf(dbh,ipft,canopy_trim, target_c(leaf_id), target_dcdd(leaf_id)) + call bleaf(dbh,ipft,crown_damage,canopy_trim, target_c(leaf_id), target_dcdd(leaf_id)) call bfineroot(dbh,ipft,canopy_trim, target_c(fnrt_id), target_dcdd(fnrt_id)) - call bstore_allom(dbh,ipft,canopy_trim, target_c(store_id), target_dcdd(store_id)) + call bstore_allom(dbh,ipft,crown_damage,canopy_trim, target_c(store_id), target_dcdd(store_id)) target_c(repro_id) = 0._r8 target_dcdd(repro_id) = 0._r8 @@ -1024,6 +1024,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & integer :: ipft real(r8) :: canopy_trim real(r8) :: leaf_status + integer :: crown_damage ! which crown damage clas integer :: i, ii ! organ index loops (masked and unmasked) integer :: istep ! outer step iteration loop @@ -1104,6 +1105,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & leaf_status = this%bc_in(acnp_bc_in_id_lstat)%ival dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival + crown_damage = this%bc_in(acnp_bc_in_id_cdamage)%ival canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval cnp_limiter = 0 @@ -1371,7 +1373,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & leafc_tp1 = leafc_tp1 + this%variables(i_var)%val(i) end do - call CheckIntegratedAllometries(state_array_out(dbh_id),ipft,canopy_trim, & + call CheckIntegratedAllometries(state_array_out(dbh_id),ipft,crown_damage,canopy_trim, & leafc_tp1, state_array_out(fnrt_id), state_array_out(sapw_id), & state_array_out(store_id), state_array_out(struct_id), & state_mask(leaf_id), state_mask(fnrt_id), state_mask(sapw_id), & @@ -1461,13 +1463,13 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & storec_tp1 = state_array_out(store_id) structc_tp1 = state_array_out(struct_id) - call bleaf(dbh_tp1,ipft,canopy_trim,leaf_c_target_tp1) + call bleaf(dbh_tp1,ipft,crown_damage,canopy_trim,leaf_c_target_tp1) call bfineroot(dbh_tp1,ipft,canopy_trim,fnrt_c_target_tp1) - call bsap_allom(dbh_tp1,ipft,canopy_trim,sapw_area,sapw_c_target_tp1) - call bagw_allom(dbh_tp1,ipft,agw_c_target_tp1) + call bsap_allom(dbh_tp1,ipft,crown_damage,canopy_trim,sapw_area,sapw_c_target_tp1) + call bagw_allom(dbh_tp1,ipft,crown_damage,agw_c_target_tp1) call bbgw_allom(dbh_tp1,ipft,bgw_c_target_tp1) call bdead_allom(agw_c_target_tp1,bgw_c_target_tp1, sapw_c_target_tp1, ipft, struct_c_target_tp1) - call bstore_allom(dbh_tp1,ipft,canopy_trim,store_c_target_tp1) + call bstore_allom(dbh_tp1,ipft,crown_damage,canopy_trim,store_c_target_tp1) write(fates_log(),*) 'leaf_c: ',leafc_tp1, leaf_c_target_tp1,leafc_tp1-leaf_c_target_tp1 write(fates_log(),*) 'fnrt_c: ',fnrtc_tp1, fnrt_c_target_tp1,fnrtc_tp1- fnrt_c_target_tp1 @@ -1575,11 +1577,12 @@ subroutine CNPAllocateRemainder(this,c_gain, n_gain, p_gain, & real(r8), pointer :: dbh integer :: ipft real(r8) :: canopy_trim - + integer :: crown_damage dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival + crown_damage = this%bc_in(acnp_bc_in_id_cdamage)%ival ! ----------------------------------------------------------------------------------- ! If nutrients are still available, then we can bump up the values in the pools @@ -1631,7 +1634,7 @@ subroutine CNPAllocateRemainder(this,c_gain, n_gain, p_gain, & if(c_gain>calloc_abs_error) then ! Update carbon based allometric targets - call bstore_allom(dbh,ipft,canopy_trim, store_c_target) + call bstore_allom(dbh,ipft,crown_damage,canopy_trim, store_c_target) ! Estimate the overflow store_c_target = store_c_target * (1.0_r8 + store_overflow_frac) @@ -1720,6 +1723,7 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe real(r8) :: canopy_trim integer :: ipft integer :: i_cvar + integer :: crown_damage real(r8) :: sapw_area real(r8) :: leaf_c_target,fnrt_c_target real(r8) :: sapw_c_target,agw_c_target @@ -1732,7 +1736,8 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival i_cvar = prt_global%sp_organ_map(organ_id,carbon12_element) - + crown_damage = this%bc_in(acnp_bc_in_id_cdamage)%ival + ! Storage of nutrients are assumed to have different compartments than ! for carbon, and thus their targets are not associated with a tissue ! but is more represented as a fraction of the maximum amount of nutrient @@ -1740,10 +1745,10 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe if(organ_id == store_organ) then - call bleaf(dbh,ipft,canopy_trim,leaf_c_target) + call bleaf(dbh,ipft,crown_damage,canopy_trim,leaf_c_target) call bfineroot(dbh,ipft,canopy_trim,fnrt_c_target) - call bsap_allom(dbh,ipft,canopy_trim,sapw_area,sapw_c_target) - call bagw_allom(dbh,ipft,agw_c_target) + call bsap_allom(dbh,ipft,crown_damage,canopy_trim,sapw_area,sapw_c_target) + call bagw_allom(dbh,ipft,crown_damage,agw_c_target) call bbgw_allom(dbh,ipft,bgw_c_target) call bdead_allom(agw_c_target,bgw_c_target, sapw_c_target, ipft, struct_c_target) @@ -2101,7 +2106,7 @@ function AllomCNPGrowthDeriv(l_state_array,l_state_mask,cbalance,intgr_params) r ! locals integer :: ipft ! PFT index - integer :: crowndamage ! Damage class + integer :: crown_damage ! Damage class real(r8) :: canopy_trim ! Canopy trimming function (boundary condition [0-1] real(r8) :: leaf_c_target ! target leaf biomass, dummy var (kgC) real(r8) :: fnrt_c_target ! target fine-root biomass, dummy var (kgC) @@ -2141,16 +2146,16 @@ function AllomCNPGrowthDeriv(l_state_array,l_state_mask,cbalance,intgr_params) r canopy_trim = intgr_params(acnp_bc_in_id_ctrim) ipft = int(intgr_params(acnp_bc_in_id_pft)) - crowndamage = int(intgr_params(acnp_bc_in_id_cdamage)) + crown_damage = int(intgr_params(acnp_bc_in_id_cdamage)) - call bleaf(dbh,ipft,crowndamage,canopy_trim,leaf_c_target,leaf_dcdd_target) + call bleaf(dbh,ipft,crown_damage,canopy_trim,leaf_c_target,leaf_dcdd_target) call bfineroot(dbh,ipft,canopy_trim,fnrt_c_target,fnrt_dcdd_target) - call bsap_allom(dbh,ipft,crowndamage,canopy_trim,sapw_area,sapw_c_target,sapw_dcdd_target) - call bagw_allom(dbh,ipft,crowndamage,agw_c_target,agw_dcdd_target) + call bsap_allom(dbh,ipft,crown_damage,canopy_trim,sapw_area,sapw_c_target,sapw_dcdd_target) + call bagw_allom(dbh,ipft,crown_damage,agw_c_target,agw_dcdd_target) call bbgw_allom(dbh,ipft,bgw_c_target,bgw_dcdd_target) call bdead_allom(agw_c_target,bgw_c_target, sapw_c_target, ipft, struct_c_target, & agw_dcdd_target, bgw_dcdd_target, sapw_dcdd_target, struct_dcdd_target) - call bstore_allom(dbh,ipft,crowndamage,canopy_trim,store_c_target,store_dcdd_target) + call bstore_allom(dbh,ipft,crown_damage,canopy_trim,store_c_target,store_dcdd_target) if (mask_repro) then ! fraction of carbon going towards reproduction diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 2a158aed30..56f8c8e1f4 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -629,7 +629,7 @@ subroutine DailyPRTAllometricCarbon(this,phase) end if - elseif( (phase.eq.2) .and. ( carbon_balance > calloc_abs_error ) then + elseif( (phase.eq.2) .and. ( carbon_balance > calloc_abs_error )) then ! ----------------------------------------------------------------------------------- ! VIII. If carbon is yet still available ... diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index 66033a3194..76558874b7 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -1378,14 +1378,16 @@ function NewRecruitTotalStoichiometry(ft,element_id) result(recruit_stoich) real(r8) :: c_total ! total target carbon real(r8) :: nutr_total ! total target nutrient + integer, parameter :: not_damaged = 1 ! this is also in MainDamageMod, here for dependency purposes + call h2d_allom(EDPftvarcon_inst%hgt_min(ft),ft,dbh) - call bleaf(dbh,ft,init_recruit_trim,c_leaf) + call bleaf(dbh,ft,not_damaged,init_recruit_trim,c_leaf) call bfineroot(dbh,ft,init_recruit_trim,c_fnrt) - call bsap_allom(dbh,ft,init_recruit_trim,a_sapw, c_sapw) - call bagw_allom(dbh,ft,c_agw) + call bsap_allom(dbh,ft,not_damaged,init_recruit_trim,a_sapw, c_sapw) + call bagw_allom(dbh,ft,not_damaged,c_agw) call bbgw_allom(dbh,ft,c_bgw) call bdead_allom(c_agw,c_bgw,c_sapw,ft,c_struct) - call bstore_allom(dbh,ft,init_recruit_trim,c_store) + call bstore_allom(dbh,ft,not_damaged,init_recruit_trim,c_store) ! Total carbon in a newly recruited plant c_total = c_leaf + c_fnrt + c_sapw + c_struct + c_store From b660f7b65efe791b51d06a789b027b2f5648114a Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 1 Jul 2022 14:42:09 -0400 Subject: [PATCH 270/852] Moving DamageRecovery to cohortdynamics --- biogeochem/DamageMainMod.F90 | 272 +---------------------------- biogeochem/EDCohortDynamicsMod.F90 | 244 +++++++++++++++++++++++++- main/EDMainMod.F90 | 1 + 3 files changed, 246 insertions(+), 271 deletions(-) diff --git a/biogeochem/DamageMainMod.F90 b/biogeochem/DamageMainMod.F90 index 290db57225..41e32ef59d 100644 --- a/biogeochem/DamageMainMod.F90 +++ b/biogeochem/DamageMainMod.F90 @@ -14,41 +14,11 @@ module DamageMainMod use EDTypesMod , only : ed_patch_type use EDTypesMod , only : ed_cohort_type use EDTypesMod , only : AREA - use EDTypesMod , only : leaves_on - use PRTGenericMod, only : num_elements - use PRTGenericMod, only : element_list - use PRTGenericMod, only : carbon12_element - use PRTGenericMod, only : nitrogen_element - use PRTGenericMod, only : phosphorus_element - use PRTGenericMod, only : leaf_organ - use PRTGenericMod, only : carbon12_element - use PRTGenericMod, only : all_carbon_elements - use PRTGenericMod, only : leaf_organ - use PRTGenericMod, only : fnrt_organ - use PRTGenericMod, only : sapw_organ - use PRTGenericMod, only : store_organ - use PRTGenericMod, only : repro_organ - use PRTGenericMod, only : struct_organ - use PRTGenericMod, only : SetState - use PRTGenericMod, only : StorageNutrientTarget - use PRTParametersMod, only : prt_params use FatesInterfaceTypesMod, only : hlm_current_day use FatesInterfaceTypesMod, only : hlm_current_month use FatesInterfaceTypesMod, only : hlm_current_year use FatesInterfaceTypesMod, only : hlm_model_day use FatesInterfaceTypesMod, only : hlm_day_of_year - use FatesInterfaceTypesMod, only : hlm_use_planthydro - use FatesAllometryMod, only : bsap_allom - use FatesAllometryMod, only : bagw_allom - use FatesAllometryMod, only : bbgw_allom - use FatesAllometryMod, only : bdead_allom - use FatesAllometryMod, only : bfineroot - use FatesAllometryMod, only : bstore_allom - use FatesAllometryMod, only : bleaf - use EDCohortDynamicsMod, only : copy_cohort - use FatesPlantHydraulicsMod, only : InitHydrCohort - use EDCohortDynamicsMod , only : InitPRTObject - use EDCohortDynamicsMod , only : InitPRTBoundaryConditions implicit none private @@ -63,7 +33,7 @@ module DamageMainMod public :: IsItDamageTime public :: damage_time public :: GetDamageMortality - public :: DamageRecovery + logical :: debug = .false. ! for debugging @@ -80,245 +50,7 @@ module DamageMainMod contains - subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) - - !--------------------------------------------------------------------------- - ! JN March 2021 - ! At this point it is possible that damaged cohorts have reached their - ! target allometries. There is a choice now - if they have excess carbon, - ! they can use it to grow along their reduced allometric targets - i.e. - ! dbh and all carbon pools grow out together. OR they can use excess carbon to - ! jump to a lower damage class by changing their target allometry and growing - ! to meet new C pools for same dbh. - ! - ! d = damage class - ! -------------------------------------------------------------------------- - - type(ed_site_type) :: csite ! Site of the current cohort - type(ed_patch_type) :: cpatch ! patch of the current cohort - type(ed_cohort_type),pointer :: ccohort ! Current (damaged) cohort - logical :: newly_recovered ! true if we create a new cohort - - ! locals - type(ed_cohort_type), pointer :: rcohort ! New cohort that recovers by - ! having an lower damage class - real(r8) :: sapw_area ! sapwood area - real(r8) :: target_sapw_c,target_sapw_m ! sapwood mass, C and N/P - real(r8) :: target_agw_c ! target above ground wood - real(r8) :: target_bgw_c ! target below ground wood - real(r8) :: target_struct_c,target_struct_m ! target structural C and N/P - real(r8) :: target_fnrt_c,target_fnrt_m ! target fine-root C and N/P - real(r8) :: target_leaf_c,target_leaf_m ! target leaf C and N/P - real(r8) :: target_store_c,target_store_m ! target storage C and N/P - real(r8) :: target_repro_m ! target reproductive C/N/P - real(r8) :: leaf_m,fnrt_m,sapw_m ! actual masses in organs C/N/P - real(r8) :: struct_m,store_m,repro_m ! actual masses in organs C/N/P - real(r8) :: mass_d ! intermediate term for nplant_recover - real(r8) :: mass_dminus1 ! intermediate term for nplant_recover - real(r8) :: available_m ! available mass that can be used to - ! improve damage class - real(r8) :: recovery_demand ! amount of mass needed to get to - ! get to the target of the next damage class - real(r8) :: max_recover_nplant ! max number of plants that could get to - ! target of next class - real(r8) :: nplant_recover ! number of plants in cohort that will - ! recover to the next class - integer :: el ! element loop counter - - associate(dbh => ccohort%dbh, & - ipft => ccohort%pft, & - canopy_trim => ccohort%canopy_trim) - - ! If we are currently undamaged, no recovery - ! necessary, do nothing and return a null pointer - ! If the damage_recovery_scalar is zero, which - ! would be an unusual testing case, but possible, - ! then no recovery is possible, do nothing and - ! return a null pointer - if ((ccohort%crowndamage == undamaged_class) .or. & - (EDPftvarcon_inst%damage_recovery_scalar(ipft) < nearzero) ) then - newly_recovered = .false. - return - end if - - - ! If we have not returned, then this cohort both has - ! a damaged status, and the ability to recover from that damage - ! ----------------------------------------------------------------- - - ! To determine recovery, the first priority is to determine how much - ! resources (C,N,P) are required to recover the plant to the target - ! pool sizes of the next (less) damage class - - ! Target sapwood biomass according to allometry and trimming [kgC] - call bsap_allom(dbh,ipft, ccohort%crowndamage-1, canopy_trim,sapw_area,target_sapw_c) - ! Target total above ground biomass in woody/fibrous tissues [kgC] - call bagw_allom(dbh,ipft, ccohort%crowndamage-1, target_agw_c) - ! Target total below ground biomass in woody/fibrous tissues [kgC] - call bbgw_allom(dbh,ipft,target_bgw_c) - ! Target total dead (structrual) biomass [kgC] - call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, ipft, target_struct_c) - ! Target fine-root biomass and deriv. according to allometry and trimming [kgC, kgC/cm] - call bfineroot(dbh,ipft,canopy_trim,target_fnrt_c) - ! Target storage carbon [kgC,kgC/cm] - call bstore_allom(dbh,ipft,ccohort%crowndamage-1, canopy_trim,target_store_c) - ! Target leaf biomass according to allometry and trimming - if(ccohort%status_coh==leaves_on) then - call bleaf(dbh,ipft,ccohort%crowndamage-1, canopy_trim,target_leaf_c) - else - target_leaf_c = 0._r8 - end if - - ! We will be taking the number of recovering plants - ! based on minimum of available resources for C/N/P (initialize high) - nplant_recover = 1.e10_r8 - - do el=1,num_elements - - ! Actual mass of chemical species in the organs - leaf_m = ccohort%prt%GetState(leaf_organ, element_list(el)) - store_m = ccohort%prt%GetState(store_organ, element_list(el)) - sapw_m = ccohort%prt%GetState(sapw_organ, element_list(el)) - fnrt_m = ccohort%prt%GetState(fnrt_organ, element_list(el)) - struct_m = ccohort%prt%GetState(struct_organ, element_list(el)) - repro_m = ccohort%prt%GetState(repro_organ, element_list(el)) - - ! Target mass of chemical species in organs, based on stature, - ! allometry and stoichiometry parameters - select case (element_list(el)) - case (carbon12_element) - target_store_m = target_store_c - target_leaf_m = target_leaf_c - target_fnrt_m = target_fnrt_c - target_struct_m = target_struct_c - target_sapw_m = target_sapw_c - target_repro_m = 0._r8 - available_m = ccohort%npp_acc - case (nitrogen_element) - target_struct_m = target_struct_c * & - prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(struct_organ)) - target_leaf_m = target_leaf_c * & - prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(leaf_organ)) - target_fnrt_m = target_fnrt_c * & - prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(fnrt_organ)) - target_sapw_m = target_sapw_c * & - prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(sapw_organ)) - target_repro_m = 0._r8 - target_store_m = StorageNutrientTarget(ipft, element_list(el), & - target_leaf_m, target_fnrt_m, target_sapw_m, target_struct_m) - ! For nutrients, all uptake is immediately put into storage, so just swap - ! them and assume storage is what is available, but needs to be filled up - available_m = store_m - store_m = 0._r8 - case (phosphorus_element) - target_struct_m = target_struct_c * & - prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(struct_organ)) - target_leaf_m = target_leaf_c * & - prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(leaf_organ)) - target_fnrt_m = target_fnrt_c * & - prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(fnrt_organ)) - target_sapw_m = target_sapw_c * & - prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(sapw_organ)) - target_repro_m = 0._r8 - target_store_m = StorageNutrientTarget(ipft, element_list(el), & - target_leaf_m, target_fnrt_m, target_sapw_m, target_struct_m) - ! For nutrients, all uptake is immediately put into storage, so just swap - ! them and assume storage is what is available, but needs to be filled up - available_m = store_m - store_m = 0._r8 - end select - - ! 1. What is excess carbon? - ! carbon_balance - - ! 2. What is biomass required to go from current - ! damage level to next damage level? - - ! mass of this damage class - mass_d = leaf_m + store_m + sapw_m + fnrt_m + struct_m + repro_m - - mass_dminus1 = max(leaf_m, target_leaf_m) + max(fnrt_m, target_fnrt_m) + & - max(store_m, target_store_m) + max(sapw_m, target_sapw_m) + & - max(struct_m, target_struct_m) - - ! Mass needed to get from current mass to allometric - ! target mass of next damage class up - recovery_demand = mass_dminus1 - mass_d - - ! 3. How many trees can get there with excess carbon? - max_recover_nplant = available_m * ccohort%n / recovery_demand - - ! 4. Use the scalar to decide how many to recover - nplant_recover = min(nplant_recover,max(0._r8,max_recover_nplant * & - EDPftvarcon_inst%damage_recovery_scalar(ipft) )) - - end do - - ! there is a special case where damage_recovery_scalar = 1, but - ! max_recover_nplant > n (i.e. there is more carbon than needed for all - ! individuals to recover to the next damage class. - ! in this case we can cheat, by making n_recover 0 and simply - ! allowing the donor cohort to recover and then go through - ! prt - will this work though? if they are not anywhere near allometry? - - if( abs(EDPftvarcon_inst%damage_recovery_scalar(ipft)-1._r8) < nearzero .and. & - nplant_recover > ccohort%n) then - nplant_recover = 0.0_r8 - ccohort%crowndamage = ccohort%crowndamage - 1 - end if - - if(nplant_recover < nearzero) then - - newly_recovered = .false. - return - - else - newly_recovered = .true. - allocate(rcohort) - if(hlm_use_planthydro .eq. itrue) call InitHydrCohort(csite,rcohort) - ! Initialize the PARTEH object and point to the - ! correct boundary condition fields - rcohort%prt => null() - call InitPRTObject(rcohort%prt) - call InitPRTBoundaryConditions(rcohort) - call copy_cohort(ccohort, rcohort) - - rcohort%n = nplant_recover - - rcohort%crowndamage = ccohort%crowndamage - 1 - - ! Need to adjust the crown area which is NOT on a per individual basis - call carea_allom(dbh,rcohort%n,csite%spread,ipft,rcohort%crowndamage,rcohort%c_area) - !rcohort%n/n_old * ccohort%c_area - !ccohort%c_area = ccohort%c_area - rcohort%c_area - - ! Update properties of the un-recovered (donor) cohort - ccohort%n = ccohort%n - rcohort%n - ccohort%c_area = ccohort%c_area * ccohort%n / (ccohort%n+rcohort%n) - - !----------- Insert copy into linked list ----------------------! - ! This subroutine is called within a loop in EDMain that - ! proceeds short to tall. We want the newly created cohort - ! to have an opportunity to experience the list, so we add - ! it in the list in a position taller than the current cohort - ! --------------------------------------------------------------! - - rcohort%shorter => ccohort - if(associated(ccohort%taller))then - rcohort%taller => ccohort%taller - ccohort%taller%shorter => rcohort - else - cpatch%tallest => rcohort - rcohort%taller => null() - endif - ccohort%taller => rcohort - - end if ! end if greater than nearzero - - end associate - - return - end subroutine DamageRecovery + subroutine IsItDamageTime(is_master, currentSite) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 71aa369b07..0f2a0b2008 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -42,6 +42,7 @@ Module EDCohortDynamicsMod use EDTypesMod , only : ican_upper use EDTypesMod , only : site_fluxdiags_type use PRTGenericMod , only : num_elements + use EDTypesMod , only : leaves_on use EDParamsMod , only : ED_val_cohort_age_fusion_tol use FatesInterfaceTypesMod , only : hlm_use_planthydro use FatesInterfaceTypesMod , only : hlm_parteh_mode @@ -126,7 +127,8 @@ Module EDCohortDynamicsMod public :: UpdateCohortBioPhysRates public :: DeallocateCohort public :: EvaluateAndCorrectDBH - + public :: DamageRecovery + logical, parameter :: debug = .false. ! local debug flag character(len=*), parameter, private :: sourcefile = & @@ -2166,5 +2168,245 @@ end subroutine EvaluateAndCorrectDBH !------------------------------------------------------------------------------------ + subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) + + !--------------------------------------------------------------------------- + ! JN March 2021 + ! At this point it is possible that damaged cohorts have reached their + ! target allometries. There is a choice now - if they have excess carbon, + ! they can use it to grow along their reduced allometric targets - i.e. + ! dbh and all carbon pools grow out together. OR they can use excess carbon to + ! jump to a lower damage class by changing their target allometry and growing + ! to meet new C pools for same dbh. + ! + ! d = damage class + ! -------------------------------------------------------------------------- + + type(ed_site_type) :: csite ! Site of the current cohort + type(ed_patch_type) :: cpatch ! patch of the current cohort + type(ed_cohort_type),pointer :: ccohort ! Current (damaged) cohort + logical :: newly_recovered ! true if we create a new cohort + + ! locals + type(ed_cohort_type), pointer :: rcohort ! New cohort that recovers by + ! having an lower damage class + real(r8) :: sapw_area ! sapwood area + real(r8) :: target_sapw_c,target_sapw_m ! sapwood mass, C and N/P + real(r8) :: target_agw_c ! target above ground wood + real(r8) :: target_bgw_c ! target below ground wood + real(r8) :: target_struct_c,target_struct_m ! target structural C and N/P + real(r8) :: target_fnrt_c,target_fnrt_m ! target fine-root C and N/P + real(r8) :: target_leaf_c,target_leaf_m ! target leaf C and N/P + real(r8) :: target_store_c,target_store_m ! target storage C and N/P + real(r8) :: target_repro_m ! target reproductive C/N/P + real(r8) :: leaf_m,fnrt_m,sapw_m ! actual masses in organs C/N/P + real(r8) :: struct_m,store_m,repro_m ! actual masses in organs C/N/P + real(r8) :: mass_d ! intermediate term for nplant_recover + real(r8) :: mass_dminus1 ! intermediate term for nplant_recover + real(r8) :: available_m ! available mass that can be used to + ! improve damage class + real(r8) :: recovery_demand ! amount of mass needed to get to + ! get to the target of the next damage class + real(r8) :: max_recover_nplant ! max number of plants that could get to + ! target of next class + real(r8) :: nplant_recover ! number of plants in cohort that will + ! recover to the next class + integer :: el ! element loop counter + + associate(dbh => ccohort%dbh, & + ipft => ccohort%pft, & + canopy_trim => ccohort%canopy_trim) + + ! If we are currently undamaged, no recovery + ! necessary, do nothing and return a null pointer + ! If the damage_recovery_scalar is zero, which + ! would be an unusual testing case, but possible, + ! then no recovery is possible, do nothing and + ! return a null pointer + if ((ccohort%crowndamage == undamaged_class) .or. & + (EDPftvarcon_inst%damage_recovery_scalar(ipft) < nearzero) ) then + newly_recovered = .false. + return + end if + + + ! If we have not returned, then this cohort both has + ! a damaged status, and the ability to recover from that damage + ! ----------------------------------------------------------------- + + ! To determine recovery, the first priority is to determine how much + ! resources (C,N,P) are required to recover the plant to the target + ! pool sizes of the next (less) damage class + + ! Target sapwood biomass according to allometry and trimming [kgC] + call bsap_allom(dbh,ipft, ccohort%crowndamage-1, canopy_trim,sapw_area,target_sapw_c) + ! Target total above ground biomass in woody/fibrous tissues [kgC] + call bagw_allom(dbh,ipft, ccohort%crowndamage-1, target_agw_c) + ! Target total below ground biomass in woody/fibrous tissues [kgC] + call bbgw_allom(dbh,ipft,target_bgw_c) + ! Target total dead (structrual) biomass [kgC] + call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, ipft, target_struct_c) + ! Target fine-root biomass and deriv. according to allometry and trimming [kgC, kgC/cm] + call bfineroot(dbh,ipft,canopy_trim,target_fnrt_c) + ! Target storage carbon [kgC,kgC/cm] + call bstore_allom(dbh,ipft,ccohort%crowndamage-1, canopy_trim,target_store_c) + ! Target leaf biomass according to allometry and trimming + if(ccohort%status_coh==leaves_on) then + call bleaf(dbh,ipft,ccohort%crowndamage-1, canopy_trim,target_leaf_c) + else + target_leaf_c = 0._r8 + end if + + ! We will be taking the number of recovering plants + ! based on minimum of available resources for C/N/P (initialize high) + nplant_recover = 1.e10_r8 + + do el=1,num_elements + + ! Actual mass of chemical species in the organs + leaf_m = ccohort%prt%GetState(leaf_organ, element_list(el)) + store_m = ccohort%prt%GetState(store_organ, element_list(el)) + sapw_m = ccohort%prt%GetState(sapw_organ, element_list(el)) + fnrt_m = ccohort%prt%GetState(fnrt_organ, element_list(el)) + struct_m = ccohort%prt%GetState(struct_organ, element_list(el)) + repro_m = ccohort%prt%GetState(repro_organ, element_list(el)) + + ! Target mass of chemical species in organs, based on stature, + ! allometry and stoichiometry parameters + select case (element_list(el)) + case (carbon12_element) + target_store_m = target_store_c + target_leaf_m = target_leaf_c + target_fnrt_m = target_fnrt_c + target_struct_m = target_struct_c + target_sapw_m = target_sapw_c + target_repro_m = 0._r8 + available_m = ccohort%npp_acc + case (nitrogen_element) + target_struct_m = target_struct_c * & + prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(struct_organ)) + target_leaf_m = target_leaf_c * & + prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(leaf_organ)) + target_fnrt_m = target_fnrt_c * & + prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(fnrt_organ)) + target_sapw_m = target_sapw_c * & + prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(sapw_organ)) + target_repro_m = 0._r8 + target_store_m = StorageNutrientTarget(ipft, element_list(el), & + target_leaf_m, target_fnrt_m, target_sapw_m, target_struct_m) + ! For nutrients, all uptake is immediately put into storage, so just swap + ! them and assume storage is what is available, but needs to be filled up + available_m = store_m + store_m = 0._r8 + case (phosphorus_element) + target_struct_m = target_struct_c * & + prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(struct_organ)) + target_leaf_m = target_leaf_c * & + prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(leaf_organ)) + target_fnrt_m = target_fnrt_c * & + prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(fnrt_organ)) + target_sapw_m = target_sapw_c * & + prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(sapw_organ)) + target_repro_m = 0._r8 + target_store_m = StorageNutrientTarget(ipft, element_list(el), & + target_leaf_m, target_fnrt_m, target_sapw_m, target_struct_m) + ! For nutrients, all uptake is immediately put into storage, so just swap + ! them and assume storage is what is available, but needs to be filled up + available_m = store_m + store_m = 0._r8 + end select + + ! 1. What is excess carbon? + ! carbon_balance + + ! 2. What is biomass required to go from current + ! damage level to next damage level? + + ! mass of this damage class + mass_d = leaf_m + store_m + sapw_m + fnrt_m + struct_m + repro_m + + mass_dminus1 = max(leaf_m, target_leaf_m) + max(fnrt_m, target_fnrt_m) + & + max(store_m, target_store_m) + max(sapw_m, target_sapw_m) + & + max(struct_m, target_struct_m) + + ! Mass needed to get from current mass to allometric + ! target mass of next damage class up + recovery_demand = mass_dminus1 - mass_d + + ! 3. How many trees can get there with excess carbon? + max_recover_nplant = available_m * ccohort%n / recovery_demand + + ! 4. Use the scalar to decide how many to recover + nplant_recover = min(nplant_recover,max(0._r8,max_recover_nplant * & + EDPftvarcon_inst%damage_recovery_scalar(ipft) )) + + end do + + ! there is a special case where damage_recovery_scalar = 1, but + ! max_recover_nplant > n (i.e. there is more carbon than needed for all + ! individuals to recover to the next damage class. + ! in this case we can cheat, by making n_recover 0 and simply + ! allowing the donor cohort to recover and then go through + ! prt - will this work though? if they are not anywhere near allometry? + + if( abs(EDPftvarcon_inst%damage_recovery_scalar(ipft)-1._r8) < nearzero .and. & + nplant_recover > ccohort%n) then + nplant_recover = 0.0_r8 + ccohort%crowndamage = ccohort%crowndamage - 1 + end if + + if(nplant_recover < nearzero) then + + newly_recovered = .false. + return + + else + newly_recovered = .true. + allocate(rcohort) + if(hlm_use_planthydro .eq. itrue) call InitHydrCohort(csite,rcohort) + ! Initialize the PARTEH object and point to the + ! correct boundary condition fields + rcohort%prt => null() + call InitPRTObject(rcohort%prt) + call InitPRTBoundaryConditions(rcohort) + call copy_cohort(ccohort, rcohort) + + rcohort%n = nplant_recover + + rcohort%crowndamage = ccohort%crowndamage - 1 + + ! Need to adjust the crown area which is NOT on a per individual basis + call carea_allom(dbh,rcohort%n,csite%spread,ipft,rcohort%crowndamage,rcohort%c_area) + !rcohort%n/n_old * ccohort%c_area + !ccohort%c_area = ccohort%c_area - rcohort%c_area + + ! Update properties of the un-recovered (donor) cohort + ccohort%n = ccohort%n - rcohort%n + ccohort%c_area = ccohort%c_area * ccohort%n / (ccohort%n+rcohort%n) + + !----------- Insert copy into linked list ----------------------! + ! This subroutine is called within a loop in EDMain that + ! proceeds short to tall. We want the newly created cohort + ! to have an opportunity to experience the list, so we add + ! it in the list in a position taller than the current cohort + ! --------------------------------------------------------------! + + rcohort%shorter => ccohort + if(associated(ccohort%taller))then + rcohort%taller => ccohort%taller + ccohort%taller%shorter => rcohort + else + cpatch%tallest => rcohort + rcohort%taller => null() + endif + ccohort%taller => rcohort + + end if ! end if greater than nearzero + + end associate + + return + end subroutine DamageRecovery + end module EDCohortDynamicsMod diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index ccdc3e5ae7..537381a977 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -36,6 +36,7 @@ module EDMainMod use EDCohortDynamicsMod , only : sort_cohorts use EDCohortDynamicsMod , only : count_cohorts use EDCohortDynamicsMod , only : EvaluateAndCorrectDBH + use EDCohortDynamicsMod , only : DamageRecovery use EDPatchDynamicsMod , only : disturbance_rates use EDPatchDynamicsMod , only : fuse_patches use EDPatchDynamicsMod , only : spawn_patches From bfe205cf8eacb7b4d898aba6fdaa3380d7f15ab6 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 1 Jul 2022 13:17:19 -0600 Subject: [PATCH 271/852] resolution on moving damagerecovery --- biogeochem/EDCohortDynamicsMod.F90 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 0f2a0b2008..9d3f6e4bfe 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -30,6 +30,7 @@ Module EDCohortDynamicsMod use EDTypesMod , only : ed_site_type, ed_patch_type, ed_cohort_type use EDTypesMod , only : nclmax use PRTGenericMod , only : element_list + use PRTGenericMod , only : StorageNutrientTarget use FatesLitterMod , only : ncwd use FatesLitterMod , only : ndcmpy use FatesLitterMod , only : litter_type @@ -68,6 +69,7 @@ Module EDCohortDynamicsMod use FatesAllometryMod , only : bdead_allom use FatesAllometryMod , only : h_allom use FatesAllometryMod , only : carea_allom + use FatesAllometryMod , only : bstore_allom use FatesAllometryMod , only : ForceDBH use FatesAllometryMod , only : tree_lai, tree_sai use FatesAllometryMod , only : set_root_fraction @@ -102,6 +104,7 @@ Module EDCohortDynamicsMod use PRTAllometricCNPMod, only : acnp_bc_out_id_nneed use PRTAllometricCNPMod, only : acnp_bc_out_id_pneed use DamageMainMod, only : GetCrownReduction + use DamageMainMod, only : undamaged_class use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) From 84e84b986569ae0b424fad590ee63d0b0bb9085f Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 1 Jul 2022 13:32:10 -0600 Subject: [PATCH 272/852] Removed check on use_tree_damage, which is allowed now --- main/FatesInterfaceMod.F90 | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 0ca5aafb63..b878219e2f 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1383,6 +1383,7 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) hlm_use_sp = unset_int hlm_use_inventory_init = unset_int hlm_inventory_ctrl_file = 'unset' + hlm_use_tree_damage = unset_int case('check_allset') @@ -1538,11 +1539,6 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if(hlm_use_tree_damage .eq. itrue) then - write(fates_log(),*) 'hlm_use_tree_damage is not available yet, value: ',hlm_use_tree_damage,' ,set to false' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - if(hlm_nitrogen_spec .eq. unset_int) then write(fates_log(),*) 'FATES parameters unset: hlm_nitrogen_spec, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) From 650077a26ae52135c11635f5a17040c08526aba4 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 1 Jul 2022 13:33:58 -0600 Subject: [PATCH 273/852] Fixes to use_tree_damage --- main/FatesInterfaceMod.F90 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index b878219e2f..b73b378aa0 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1383,7 +1383,6 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) hlm_use_sp = unset_int hlm_use_inventory_init = unset_int hlm_inventory_ctrl_file = 'unset' - hlm_use_tree_damage = unset_int case('check_allset') @@ -1534,7 +1533,7 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if(hlm_use_tree_damage .eq. unset_int .or. hlm_use_tree_damage .eq. itrue) then + if(hlm_use_tree_damage .eq. unset_int) then write(fates_log(),*) 'FATES dimension/parameter unset: hlm_use_tree_damage, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if From 71c41c6b7606500c46e895dc99b4984709d2f942 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Sun, 3 Jul 2022 08:56:14 -0600 Subject: [PATCH 274/852] Making tree_sai in canopy_trim use actual area --- biogeochem/EDPhysiologyMod.F90 | 5 +---- biogeochem/FatesAllometryMod.F90 | 13 +++++++------ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 0c13806859..45d9ca38a3 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -470,14 +470,11 @@ subroutine trim_canopy( currentSite ) currentCohort%n, currentCohort%canopy_layer, & currentPatch%canopy_layer_tlai,currentCohort%vcmax25top ) - call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread,currentCohort%pft,& - 1, target_c_area) - ! We don't need check on sp mode here since we don't trim_canopy with sp mode currentCohort%treesai = tree_sai(currentCohort%pft, & currentCohort%dbh, currentCohort%crowndamage, & currentCohort%canopy_trim, & - target_c_area, currentCohort%n,currentCohort%canopy_layer,& + currentCohort%c_area, currentCohort%n,currentCohort%canopy_layer,& currentPatch%canopy_layer_tlai, currentCohort%treelai, & currentCohort%vcmax25top,0 ) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index 0766ee645a..6a15985965 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -497,16 +497,16 @@ subroutine carea_allom(dbh,nplant,site_spread,ipft,crowndamage,c_area,inverse) case(1) dbh_eff = min(dbh,dbh_maxh) call carea_2pwr(dbh_eff,site_spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max, & - c_area,do_inverse, crowndamage) + crowndamage,c_area, do_inverse) capped_allom = .true. case(2) ! "2par_pwr") - call carea_2pwr(dbh,site_spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max,c_area, & - do_inverse, crowndamage) + call carea_2pwr(dbh,site_spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max, & + crowndamage, c_area, do_inverse) capped_allom = .false. case(3) dbh_eff = min(dbh,dbh_maxh) call carea_2pwr(dbh_eff,site_spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max, & - c_area,do_inverse, crowndamage) + crowndamage, c_area, do_inverse) capped_allom = .true. case DEFAULT write(fates_log(),*) 'An undefined leaf allometry was specified: ', & @@ -2083,7 +2083,8 @@ end subroutine CrownDepth ! ============================================================================= - subroutine carea_2pwr(dbh,spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max,c_area,inverse,crowndamage) + subroutine carea_2pwr(dbh,spread,d2bl_p2,d2bl_ediff,d2ca_min, & + d2ca_max,crowndamage,c_area,inverse) ! ============================================================================ ! Calculate area of ground covered by entire cohort. (m2) @@ -2096,9 +2097,9 @@ subroutine carea_2pwr(dbh,spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max,c_area,inv real(r8),intent(in) :: d2bl_ediff ! area difference factor in the diameter-bleaf allometry (exponent) real(r8),intent(in) :: d2ca_min ! minimum diameter to crown area scaling factor real(r8),intent(in) :: d2ca_max ! maximum diameter to crown area scaling factor + integer,intent(in) :: crowndamage ! crowndamage class [1: undamaged, >1: damaged] real(r8),intent(inout) :: c_area ! crown area for one plant [m2] logical,intent(in) :: inverse ! if true, calculate dbh from crown area rather than its reverse - integer,intent(in) :: crowndamage ! crowndamage class [1: undamaged, >1: damaged] real(r8) :: crown_area_to_dbh_exponent real(r8) :: spreadterm ! Effective 2bh to crown area scaling factor From 52f5b8719260a323bbc9878e702446037023bba2 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 5 Jul 2022 13:09:15 -0600 Subject: [PATCH 275/852] argument re-ordering in crowndamage allometry argument and adding in the call to initalize the derived damage parameter --- biogeochem/EDCohortDynamicsMod.F90 | 18 ++++++++---------- biogeochem/FatesAllometryMod.F90 | 8 ++++---- main/FatesParameterDerivedMod.F90 | 9 ++++----- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 9d3f6e4bfe..f81e5df9b4 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -1319,10 +1319,10 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) if( prt_params%woody(currentCohort%pft) == itrue ) then - call ForceDBH( currentCohort%pft, currentCohort%canopy_trim, & + call ForceDBH( currentCohort%pft, currentCohort%crowndamage, & + currentCohort%canopy_trim, & currentCohort%dbh, currentCohort%hite, & - bdead = currentCohort%prt%GetState(struct_organ,all_carbon_elements), & - crowndamage = currentCohort%crowndamage) + bdead = currentCohort%prt%GetState(struct_organ,all_carbon_elements)) end if ! @@ -1357,11 +1357,10 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) ! ----------------------------------------------------------------- ! if( prt_params%woody(currentCohort%pft) == itrue ) then - call ForceDBH( currentCohort%pft, currentCohort%canopy_trim, & + call ForceDBH( currentCohort%pft, currentCohort%crowndamage, & + currentCohort%canopy_trim, & currentCohort%dbh, currentCohort%hite, & - bdead = currentCohort%prt%GetState(struct_organ,all_carbon_elements),& - crowndamage = currentCohort%crowndamage) - + bdead = currentCohort%prt%GetState(struct_organ,all_carbon_elements)) end if ! call carea_allom(currentCohort%dbh,newn,currentSite%spread,currentCohort%pft,& @@ -2140,8 +2139,7 @@ subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) if( (struct_c - target_struct_c ) > calloc_abs_error ) then - call ForceDBH( ipft,canopy_trim, dbh, hite_out, bdead=struct_c, & - crowndamage = icrowndamage) + call ForceDBH( ipft,icrowndamage,canopy_trim, dbh, hite_out, bdead=struct_c) delta_dbh = dbh - currentCohort%dbh delta_hite = hite_out - currentCohort%hite @@ -2158,7 +2156,7 @@ subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) call bleaf(dbh,ipft,icrowndamage, canopy_trim,target_leaf_c) if( ( leaf_c - target_leaf_c ) > calloc_abs_error ) then - call ForceDBH( ipft, canopy_trim, dbh, hite_out, bl=leaf_c ) + call ForceDBH( ipft, icrowndamage, canopy_trim, dbh, hite_out, bl=leaf_c ) delta_dbh = dbh - currentCohort%dbh delta_hite = hite_out - currentCohort%hite currentCohort%dbh = dbh diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index 6a15985965..43497b5b44 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -2404,7 +2404,7 @@ real(r8) function decay_coeff_kn(pft,vcmax25top) end function decay_coeff_kn ! ===================================================================================== -subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl, crowndamage) +subroutine ForceDBH( ipft, crowndamage, canopy_trim, d, h, bdead, bl ) ! ========================================================================= ! This subroutine estimates the diameter based on either the structural biomass @@ -2419,7 +2419,7 @@ subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl, crowndamage) integer(i4),intent(in) :: ipft ! PFT index - integer(i4),intent(in),optional :: crowndamage ! crowndamage [1: undamaged, >1: damaged] + integer(i4),intent(in) :: crowndamage ! crowndamage [1: undamaged, >1: damaged] real(r8),intent(in) :: canopy_trim real(r8),intent(inout) :: d ! plant diameter [cm] real(r8),intent(out) :: h ! plant height @@ -2504,7 +2504,7 @@ subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl, crowndamage) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - call bleaf(d,ipft,1,canopy_trim,bt_leaf,dbt_leaf_dd) + call bleaf(d,ipft,crowndamage,canopy_trim,bt_leaf,dbt_leaf_dd) counter = 0 step_frac = step_frac0 @@ -2513,7 +2513,7 @@ subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl, crowndamage) dd = step_frac*(bl-bt_leaf)/dbt_leaf_dd d_try = d + dd - call bleaf(d_try,ipft,1,canopy_trim,bt_leaf_try,dbt_leaf_dd_try) + call bleaf(d_try,ipft,crowndamage,canopy_trim,bt_leaf_try,dbt_leaf_dd_try) ! Prevent overshooting if(bt_leaf_try > (bl+calloc_abs_error)) then diff --git a/main/FatesParameterDerivedMod.F90 b/main/FatesParameterDerivedMod.F90 index 0214224ee3..e63a361384 100644 --- a/main/FatesParameterDerivedMod.F90 +++ b/main/FatesParameterDerivedMod.F90 @@ -66,10 +66,9 @@ end subroutine InitAllocate ! ===================================================================================== ! =================================================================================== - subroutine InitAllocateDamageTransitions(this,nlevdamage, numpft) + subroutine InitAllocateDamageTransitions(this,numpft) class(param_derived_type), intent(inout) :: this - integer, intent(in) :: nlevdamage integer, intent(in) :: numpft allocate(this%damage_transitions(nlevdamage,nlevdamage, numpft)) @@ -96,6 +95,7 @@ subroutine Init(this,numpft) associate( vcmax25top => EDPftvarcon_inst%vcmax25top ) call this%InitAllocate(numpft) + call this%InitDamageTransitions(numpft) do ft = 1,numpft @@ -129,13 +129,12 @@ end subroutine Init !========================================================================= - subroutine InitDamageTransitions(this, nlevdamage, numpft) + subroutine InitDamageTransitions(this, numpft) use EDPftvarcon, only: EDPftvarcon_inst class(param_derived_type), intent(inout) :: this - integer, intent(in) :: nlevdamage integer, intent(in) :: numpft ! local variables @@ -144,7 +143,7 @@ subroutine InitDamageTransitions(this, nlevdamage, numpft) real(r8) :: damage_frac ! damage fraction - call this%InitAllocateDamageTransitions(nlevdamage, numpft) + call this%InitAllocateDamageTransitions(numpft) do ft = 1, numpft From b26610612625fe0e05b0e57ac3b15ce08875e79e Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 5 Jul 2022 20:26:23 -0600 Subject: [PATCH 276/852] Removed a redundant (double) allocation call --- biogeochem/EDPatchDynamicsMod.F90 | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 83c027fdf8..df27f99d33 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -804,17 +804,6 @@ subroutine spawn_patches( currentSite, bc_in) agb_frac = prt_params%allom_agb_frac(currentCohort%pft) branch_frac = param_derived%branch_frac(currentCohort%pft) - allocate(nc) ! new cohort surviving - if(hlm_use_planthydro.eq.itrue) call InitHydrCohort(CurrentSite,nc) - - ! Initialize the PARTEH object and point to the - ! correct boundary condition fields - nc%prt => null() - - call InitPRTObject(nc%prt) - call InitPRTBoundaryConditions(nc) - call zero_cohort(nc) - ! nc is the new cohort that goes in the disturbed patch (new_patch)... currentCohort ! is the curent cohort that stays in the donor patch (currentPatch) From 34a6fe33d8b12f1156342e00b4bd36ab0cf38012 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 6 Jul 2022 11:55:13 -0400 Subject: [PATCH 277/852] Removed patch level damage code, in preparation for moving it to a pre-disturbance part of the dynamics code. --- biogeochem/EDPatchDynamicsMod.F90 | 817 ++++++------------------------ 1 file changed, 157 insertions(+), 660 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index df27f99d33..7fe99f2ee6 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -6,8 +6,6 @@ module EDPatchDynamicsMod use FatesGlobals , only : fates_log use FatesGlobals , only : FatesWarn,N2S,A2S use FatesInterfaceTypesMod , only : hlm_freq_day - use FatesInterfaceTypesMod , only : hlm_days_per_year - use FatesInterfaceTypesMod, only : hlm_use_tree_damage use EDPftvarcon , only : EDPftvarcon_inst use EDPftvarcon , only : GetDecompyFrac use PRTParametersMod , only : prt_params @@ -44,7 +42,6 @@ module EDPatchDynamicsMod use FatesInterfaceTypesMod , only : hlm_use_planthydro use FatesInterfaceTypesMod , only : hlm_numSWb use FatesInterfaceTypesMod , only : bc_in_type - use FatesInterfaceTypesMod , only : hlm_days_per_year use FatesInterfaceTypesMod , only : numpft use FatesInterfaceTypesMod , only : hlm_stepsize use FatesInterfaceTypesMod , only : hlm_use_sp @@ -61,7 +58,6 @@ module EDPatchDynamicsMod use EDLoggingMortalityMod, only : logging_time use EDLoggingMortalityMod, only : get_harvest_rate_area use EDParamsMod , only : fates_mortality_disturbance_fraction - use DamageMainMod , only : damage_time use FatesAllometryMod , only : carea_allom use FatesAllometryMod , only : set_root_fraction use FatesConstantsMod , only : g_per_kg @@ -139,7 +135,6 @@ module EDPatchDynamicsMod real(r8), parameter :: existing_litt_localization = 1.0_r8 real(r8), parameter :: treefall_localization = 0.0_r8 real(r8), parameter :: burn_localization = 0.0_r8 - real(r8), parameter :: damage_localization = 0.0_r8 character(len=512) :: msg ! Message string for warnings and logging @@ -212,11 +207,9 @@ subroutine disturbance_rates( site_in, bc_in) call mortality_rates(currentCohort,bc_in,cmort,hmort,bmort,frmort,smort,asmort,dgmort) currentCohort%dmort = cmort+hmort+bmort+frmort+smort+asmort+dgmort - call carea_allom(currentCohort%dbh,currentCohort%n,site_in%spread,currentCohort%pft, & currentCohort%crowndamage,currentCohort%c_area) - ! Initialize diagnostic mortality rates currentCohort%cmort = cmort currentCohort%bmort = bmort @@ -225,7 +218,7 @@ subroutine disturbance_rates( site_in, bc_in) currentCohort%smort = smort currentCohort%asmort = asmort currentCohort%dgmort = dgmort - + call LoggingMortality_frac(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_layer, & lmort_direct,lmort_collateral,lmort_infra,l_degrad,& bc_in%hlm_harvest_rates, & @@ -299,8 +292,6 @@ subroutine disturbance_rates( site_in, bc_in) currentCohort%c_area/currentPatch%area endif - - currentCohort => currentCohort%taller enddo !currentCohort @@ -450,7 +441,6 @@ subroutine spawn_patches( currentSite, bc_in) ! 6) For mortality, Plants in new and existing understorey are killed ! 7) For fire, burned plants are killed, and unburned plants are added to new patch. ! 8) New cohorts are added to new patch and sorted. - ! This includes splitting cohorts within the new patch into different damage classes ! 9) New patch is added into linked list ! 10) Area checked, and patchno recalculated. ! @@ -459,31 +449,19 @@ subroutine spawn_patches( currentSite, bc_in) use EDParamsMod , only : ED_val_understorey_death, logging_coll_under_frac use EDCohortDynamicsMod , only : zero_cohort, copy_cohort, terminate_cohorts use FatesConstantsMod , only : rsnbl_math_prec - use DamageMainMod , only : GetCrownReduction - use DamageMainMod , only : GetDamageFrac - use PRTLossFluxesMod , only : PRTDamageLosses - use PRTGenericMod , only : leaf_organ - use ChecksBalancesMod , only : SiteMassStock - use FatesInterfaceTypesMod, only : nlevdamage - use FatesParameterDerivedMod, only : param_derived - use EDParamsMod , only : damage_canopy_layer_code - + ! ! !ARGUMENTS: type (ed_site_type), intent(inout), target :: currentSite type (bc_in_type), intent(in) :: bc_in ! ! !LOCAL VARIABLES: - type(litter_type), pointer :: litt - type(litter_type), pointer :: litt_new - type (ed_patch_type) , pointer :: new_patch type (ed_patch_type) , pointer :: new_patch_primary type (ed_patch_type) , pointer :: new_patch_secondary type (ed_patch_type) , pointer :: currentPatch type (ed_cohort_type), pointer :: currentCohort type (ed_cohort_type), pointer :: nc - type (ed_cohort_type), pointer :: nc_d type (ed_cohort_type), pointer :: storesmallcohort type (ed_cohort_type), pointer :: storebigcohort real(r8) :: site_areadis_primary ! total area disturbed (to primary forest) in m2 per site per day @@ -499,48 +477,14 @@ subroutine spawn_patches( currentSite, bc_in) real(r8) :: sapw_c ! sapwood carbon [kg] real(r8) :: store_c ! storage carbon [kg] real(r8) :: struct_c ! structure carbon [kg] - real(r8) :: repro_c ! reproductive carbon [kg] real(r8) :: total_c ! total carbon of plant [kg] real(r8) :: leaf_burn_frac ! fraction of leaves burned in fire ! for both woody and grass species real(r8) :: leaf_m ! leaf mass during partial burn calculations - - real(r8) :: total_litter_d ! total litter from damage - real(r8) :: patch_damage_litter ! patch level litter from damage - real(r8) :: mass_frac ! mass to remove from damaged cohorts - real(r8) :: leaf_m_pre ! leaf mass pre damage - real(r8) :: leaf_m_post ! leaf mass post damage - real(r8) :: leaf_loss_prt ! leaf mass lost - real(r8) :: sapw_m_pre ! sapw mass pre damage - real(r8) :: sapw_m_post ! sapw mass post damage - real(r8) :: sapw_loss_prt ! sapw mass lost - real(r8) :: struct_m_pre ! struct mass pre damage - real(r8) :: struct_m_post ! struct mass post damage - real(r8) :: struct_loss_prt ! struct mass lost - real(r8) :: store_m_pre ! storage mass pre damage - real(r8) :: store_m_post ! storage mass post damage - real(r8) :: store_loss_prt ! storage mass lost - real(r8) :: cd_n ! number in new damaged cohort - real(r8) :: cd_n_total ! total number damaged - integer :: cd ! crowndamage counter - real(r8) :: cd_frac ! fraction of cohort going to new damage class - real(r8) :: agb_frac ! agoveground biomass fraction of cohort - real(r8) :: branch_frac ! branch fraction of aboveground biomass - logical :: found_youngest_primary ! logical for finding the first primary forest patch integer :: min_nocomp_pft, max_nocomp_pft, i_nocomp_pft - - integer :: i_damage_code !--------------------------------------------------------------------- - real(r8), parameter :: damage_error_fail = 1.0e-6_r8 - - !--------------------------------------------------------------------- - - i_damage_code = int(damage_canopy_layer_code) - - total_litter_d = 0.0_r8 - storesmallcohort => null() ! storage of the smallest cohort for insertion routine storebigcohort => null() ! storage of the largest cohort for insertion routine @@ -552,12 +496,6 @@ subroutine spawn_patches( currentSite, bc_in) max_nocomp_pft = fates_unset_int endif - leaf_loss_prt = 0.0_r8 - sapw_loss_prt = 0.0_r8 - struct_loss_prt = 0.0_r8 - store_loss_prt = 0.0_r8 - patch_damage_litter = 0.0_r8 - ! zero the diagnostic disturbance rate fields currentSite%disturbance_rates_primary_to_primary(1:N_DIST_TYPES) = 0._r8 currentSite%disturbance_rates_primary_to_secondary(1:N_DIST_TYPES) = 0._r8 @@ -632,7 +570,7 @@ subroutine spawn_patches( currentSite, bc_in) ! It is possible that no disturbance area was generated if ( (site_areadis_primary + site_areadis_secondary) > nearzero) then - + age = 0.0_r8 ! create two empty patches, to absorb newly disturbed primary and secondary forest area @@ -647,12 +585,12 @@ subroutine spawn_patches( currentSite, bc_in) ! pools will be populated by looping over the existing patches ! and transfering in mass do el=1,num_elements - call new_patch_primary%litter(el)%InitConditions(init_leaf_fines=0._r8, & - init_root_fines=0._r8, & - init_ag_cwd=0._r8, & - init_bg_cwd=0._r8, & - init_seed=0._r8, & - init_seed_germ=0._r8) + call new_patch_primary%litter(el)%InitConditions(init_leaf_fines=0._r8, & + init_root_fines=0._r8, & + init_ag_cwd=0._r8, & + init_bg_cwd=0._r8, & + init_seed=0._r8, & + init_seed_germ=0._r8) end do new_patch_primary%tallest => null() new_patch_primary%shortest => null() @@ -685,7 +623,7 @@ subroutine spawn_patches( currentSite, bc_in) ! pools to the new patch. We only loop the pre-existing patches, so ! quit the loop if the current patch is either null, or matches the ! two new pointers. - + currentPatch => currentSite%oldest_patch do while(associated(currentPatch)) @@ -695,45 +633,46 @@ subroutine spawn_patches( currentSite, bc_in) ! This is the amount of patch area that is disturbed, and donated by the donor patch_site_areadis = currentPatch%area * currentPatch%disturbance_rate + if ( patch_site_areadis > nearzero ) then - ! figure out whether the receiver patch for disturbance from this patch - ! will be primary or secondary land receiver patch is primary forest - ! only if both the donor patch is primary forest and the dominant - ! disturbance type is not logging - if (currentPatch%anthro_disturbance_label .eq. primaryforest .and. & - (currentPatch%disturbance_mode .ne. dtype_ilog)) then - new_patch => new_patch_primary - else - new_patch => new_patch_secondary - endif - - if(.not.associated(new_patch))then - write(fates_log(),*) 'Patch spawning has attempted to point to' - write(fates_log(),*) 'an un-allocated patch' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + ! figure out whether the receiver patch for disturbance from this patch + ! will be primary or secondary land receiver patch is primary forest + ! only if both the donor patch is primary forest and the dominant + ! disturbance type is not logging + if (currentPatch%anthro_disturbance_label .eq. primaryforest .and. & + (currentPatch%disturbance_mode .ne. dtype_ilog)) then + new_patch => new_patch_primary + else + new_patch => new_patch_secondary + endif + + if(.not.associated(new_patch))then + write(fates_log(),*) 'Patch spawning has attempted to point to' + write(fates_log(),*) 'an un-allocated patch' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if ! for the case where the donating patch is secondary forest, if ! the dominant disturbance from this patch is non-anthropogenic, ! we need to average in the time-since-anthropogenic-disturbance ! from the donor patch into that of the receiver patch if ( currentPatch%anthro_disturbance_label .eq. secondaryforest .and. & - (currentPatch%disturbance_mode .ne. dtype_ilog) ) then + (currentPatch%disturbance_mode .ne. dtype_ilog) ) then new_patch%age_since_anthro_disturbance = new_patch%age_since_anthro_disturbance + & currentPatch%age_since_anthro_disturbance * (patch_site_areadis / site_areadis_secondary) endif - - + + ! Transfer the litter existing already in the donor patch to the new patch ! This call will only transfer non-burned litter to new patch ! and burned litter to atmosphere. Thus it is important to zero burnt_frac_litter when ! fire is not the dominant disturbance regime. if(currentPatch%disturbance_mode .ne. dtype_ifire) then - currentPatch%burnt_frac_litter(:) = 0._r8 + currentPatch%burnt_frac_litter(:) = 0._r8 end if call TransLitterNewPatch( currentSite, currentPatch, new_patch, patch_site_areadis) @@ -747,23 +686,9 @@ subroutine spawn_patches( currentSite, bc_in) call fire_litter_fluxes(currentSite, currentPatch, & new_patch, patch_site_areadis,bc_in) else - call mortality_litter_fluxes(currentSite, currentPatch,& + call mortality_litter_fluxes(currentSite, currentPatch, & new_patch, patch_site_areadis,bc_in) - end if - - - - ! and the damaged trees - if(hlm_use_tree_damage .eq. itrue) then - if(damage_time) then - - call damage_litter_fluxes(currentSite, currentPatch, & - new_patch, patch_site_areadis, patch_damage_litter) - end if - end if - - ! in kg - for mass conservation checking - total_litter_d = total_litter_d + patch_damage_litter + endif ! Copy any means or timers from the original patch to the new patch @@ -779,7 +704,6 @@ subroutine spawn_patches( currentSite, bc_in) ! ! Next, we loop through the cohorts in the donor patch, copy them with ! area modified number density into the new-patch, and apply survivorship. - ! Cohorts in the new patch have to be split into damage and undamaged. ! ------------------------------------------------------------------------- currentCohort => currentPatch%shortest @@ -801,64 +725,54 @@ subroutine spawn_patches( currentSite, bc_in) call zero_cohort(nc) - agb_frac = prt_params%allom_agb_frac(currentCohort%pft) - branch_frac = param_derived%branch_frac(currentCohort%pft) - - - ! nc is the new cohort that goes in the disturbed patch (new_patch)... currentCohort - ! is the curent cohort that stays in the donor patch (currentPatch) - ! nc_d is the new cohort that goes in the disturbed (new) patch and gets damaged - call copy_cohort(currentCohort, nc) - - !this is the case as the new patch probably doesn't have a closed canopy, and - ! even if it does, that will be sorted out in canopy_structure. - nc%canopy_layer = 1 - nc%canopy_layer_yesterday = 1._r8 - - sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) - struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) - leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) - fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) - store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) - total_c = sapw_c + struct_c + leaf_c + fnrt_c + store_c - - - ! As we loop through disturbances we just focus on nc - surviving trees in new patch - ! After this loop we can alter number densities in nc and nc_d and apply damage - - ! if treefall mortality is the dominant disturbance - if(currentPatch%disturbance_mode .eq. dtype_ifall) then + ! nc is the new cohort that goes in the disturbed patch (new_patch)... currentCohort + ! is the curent cohort that stays in the donor patch (currentPatch) + call copy_cohort(currentCohort, nc) - ! if canopy - if(currentCohort%canopy_layer == 1)then + !this is the case as the new patch probably doesn't have a closed canopy, and + ! even if it does, that will be sorted out in canopy_structure. + nc%canopy_layer = 1 + nc%canopy_layer_yesterday = 1._r8 + + sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) + struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) + leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) + fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) + store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) + total_c = sapw_c + struct_c + leaf_c + fnrt_c + store_c + + ! treefall mortality is the dominant disturbance + if(currentPatch%disturbance_mode .eq. dtype_ifall) then + + if(currentCohort%canopy_layer == 1)then ! In the donor patch we are left with fewer trees because the area has decreased ! the plant density for large trees does not actually decrease in the donor patch ! because this is the part of the original patch where no trees have actually fallen ! The diagnostic cmort,bmort,hmort, and frmort rates have already been saved - + currentCohort%n = currentCohort%n * (1.0_r8 - fates_mortality_disturbance_fraction * & - min(1.0_r8,currentCohort%dmort * hlm_freq_day)) - + min(1.0_r8,currentCohort%dmort * hlm_freq_day)) + nc%n = 0.0_r8 ! kill all of the trees who caused the disturbance. - + nc%cmort = nan ! The mortality diagnostics are set to nan - ! because the cohort should dissappear + ! because the cohort should dissappear nc%hmort = nan nc%bmort = nan nc%frmort = nan nc%smort = nan nc%asmort = nan - nc%dgmort = nan nc%lmort_direct = nan nc%lmort_collateral = nan nc%lmort_infra = nan nc%l_degrad = nan - + else ! small trees if( prt_params%woody(currentCohort%pft) == itrue)then - + + ! Survivorship of undestory woody plants. Two step process. ! Step 1: Reduce current number of plants to reflect the ! change in area. @@ -867,7 +781,7 @@ subroutine spawn_patches( currentSite, bc_in) ! are absolute, reduce this number. nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - + ! because the mortality rate due to impact for the cohorts which ! had been in the understory and are now in the newly- ! disturbed patch is very high, passing the imort directly to history @@ -878,7 +792,7 @@ subroutine spawn_patches( currentSite, bc_in) currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) = & currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) + & nc%n * ED_val_understorey_death / hlm_freq_day - + currentSite%imort_crownarea = currentSite%imort_crownarea + & currentCohort%c_area * ED_val_understorey_death / hlm_freq_day @@ -887,8 +801,7 @@ subroutine spawn_patches( currentSite, bc_in) (nc%n * ED_val_understorey_death / hlm_freq_day ) * & total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 - - if (hlm_use_tree_damage .eq. itrue) then + if (hlm_use_crown_damage .eq. itrue) then currentSite%imort_rate_damage(currentCohort%crowndamage, & currentCohort%size_class, currentCohort%pft) = & @@ -902,13 +815,13 @@ subroutine spawn_patches( currentSite, bc_in) total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 end if - - + + ! Step 2: Apply survivor ship function based on the understory death fraction ! remaining of understory plants of those that are knocked over ! by the overstorey trees dying... nc%n = nc%n * (1.0_r8 - ED_val_understorey_death) - + ! since the donor patch split and sent a fraction of its members ! to the new patch and a fraction to be preserved in itself, ! when reporting diagnostic rates, we must carry over the mortality rates from @@ -916,62 +829,62 @@ subroutine spawn_patches( currentSite, bc_in) ! for diagnostics. But think of it this way, the rates are weighted by ! number density in EDCLMLink, and the number density of this new patch is donated ! so with the number density must come the effective mortality rates. - + nc%cmort = currentCohort%cmort nc%hmort = currentCohort%hmort nc%bmort = currentCohort%bmort nc%frmort = currentCohort%frmort nc%smort = currentCohort%smort nc%asmort = currentCohort%asmort - nc%dgmort = currentCohort%dgmort nc%dmort = currentCohort%dmort + nc%dgmort = currentCohort%dgmort nc%lmort_direct = currentCohort%lmort_direct nc%lmort_collateral = currentCohort%lmort_collateral nc%lmort_infra = currentCohort%lmort_infra - + ! understory trees that might potentially be knocked over in the disturbance. ! The existing (donor) patch should not have any impact mortality, it should ! only lose cohorts due to the decrease in area. This is not mortality. ! Besides, the current and newly created patch sum to unity - + currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - - else ! if not woody + + else ! grass is not killed by mortality disturbance events. Just move it into the new patch area. ! Just split the grass into the existing and new patch structures nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - + ! Those remaining in the existing currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - + nc%cmort = currentCohort%cmort nc%hmort = currentCohort%hmort nc%bmort = currentCohort%bmort nc%frmort = currentCohort%frmort nc%smort = currentCohort%smort nc%asmort = currentCohort%asmort - nc%dgmort = currentCohort%dgmort nc%dmort = currentCohort%dmort + nc%dgmort = currentCohort%dgmort nc%lmort_direct = currentCohort%lmort_direct nc%lmort_collateral = currentCohort%lmort_collateral nc%lmort_infra = currentCohort%lmort_infra - + endif - end if - + endif + ! Fire is the dominant disturbance elseif (currentPatch%disturbance_mode .eq. dtype_ifire ) then - + ! Number of members in the new patch, before we impose fire survivorship nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - + ! loss of individuals from source patch due to area shrinking currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - + levcan = currentCohort%canopy_layer - + if(levcan==ican_upper) then - + ! before changing number densities, track total rate of trees that died ! due to fire, as well as from each fire mortality term currentSite%fmort_rate_canopy(currentCohort%size_class, currentCohort%pft) = & @@ -985,12 +898,12 @@ subroutine spawn_patches( currentSite, bc_in) currentSite%fmort_crownarea_canopy = currentSite%fmort_crownarea_canopy + & currentCohort%c_area * currentCohort%fire_mort / hlm_freq_day - + else currentSite%fmort_rate_ustory(currentCohort%size_class, currentCohort%pft) = & currentSite%fmort_rate_ustory(currentCohort%size_class, currentCohort%pft) + & nc%n * currentCohort%fire_mort / hlm_freq_day - + currentSite%fmort_carbonflux_ustory(currentCohort%pft) = & currentSite%fmort_carbonflux_ustory(currentCohort%pft) + & (nc%n * currentCohort%fire_mort) * & @@ -998,11 +911,10 @@ subroutine spawn_patches( currentSite, bc_in) currentSite%fmort_crownarea_ustory = currentSite%fmort_crownarea_ustory + & currentCohort%c_area * currentCohort%fire_mort / hlm_freq_day - end if ! also track fire damage mortality and cflux along size x damage axis - if(hlm_use_tree_damage .eq. itrue) then + if(hlm_use_crown_damage .eq. itrue) then if(levcan==ican_upper) then currentSite%fmort_rate_canopy_damage(currentCohort%crowndamage, currentCohort%size_class, & currentCohort%pft) = & @@ -1025,17 +937,17 @@ subroutine spawn_patches( currentSite, bc_in) total_c * g_per_kg * days_per_sec * ha_per_m2 end if end if - + currentSite%fmort_rate_cambial(currentCohort%size_class, currentCohort%pft) = & currentSite%fmort_rate_cambial(currentCohort%size_class, currentCohort%pft) + & nc%n * currentCohort%cambial_mort / hlm_freq_day currentSite%fmort_rate_crown(currentCohort%size_class, currentCohort%pft) = & currentSite%fmort_rate_crown(currentCohort%size_class, currentCohort%pft) + & nc%n * currentCohort%crownfire_mort / hlm_freq_day - + ! loss of individual from fire in new patch. nc%n = nc%n * (1.0_r8 - currentCohort%fire_mort) - + nc%cmort = currentCohort%cmort nc%hmort = currentCohort%hmort nc%bmort = currentCohort%bmort @@ -1052,36 +964,37 @@ subroutine spawn_patches( currentSite, bc_in) ! Some of of the leaf mass from living plants has been ! burned off. Here, we remove that mass, and ! tally it in the flux we sent to the atmosphere - + if(prt_params%woody(currentCohort%pft) == itrue)then leaf_burn_frac = currentCohort%fraction_crown_burned else - ! Grasses determine their fraction of leaves burned here - leaf_burn_frac = currentPatch%burnt_frac_litter(lg_sf) - endif + ! Grasses determine their fraction of leaves burned here + leaf_burn_frac = currentPatch%burnt_frac_litter(lg_sf) + endif + ! Perform a check to make sure that spitfire gave ! us reasonable mortality and burn fraction rates - + if( (leaf_burn_frac < 0._r8) .or. & - (leaf_burn_frac > 1._r8) .or. & - (currentCohort%fire_mort < 0._r8) .or. & - (currentCohort%fire_mort > 1._r8)) then - write(fates_log(),*) 'unexpected fire fractions' - write(fates_log(),*) prt_params%woody(currentCohort%pft) - write(fates_log(),*) leaf_burn_frac - write(fates_log(),*) currentCohort%fire_mort - call endrun(msg=errMsg(sourcefile, __LINE__)) + (leaf_burn_frac > 1._r8) .or. & + (currentCohort%fire_mort < 0._r8) .or. & + (currentCohort%fire_mort > 1._r8)) then + write(fates_log(),*) 'unexpected fire fractions' + write(fates_log(),*) prt_params%woody(currentCohort%pft) + write(fates_log(),*) leaf_burn_frac + write(fates_log(),*) currentCohort%fire_mort + call endrun(msg=errMsg(sourcefile, __LINE__)) end if do el = 1,num_elements - leaf_m = nc%prt%GetState(leaf_organ, element_list(el)) + leaf_m = nc%prt%GetState(leaf_organ, element_list(el)) - currentSite%mass_balance(el)%burn_flux_to_atm = & - currentSite%mass_balance(el)%burn_flux_to_atm + & - leaf_burn_frac * leaf_m * nc%n + currentSite%mass_balance(el)%burn_flux_to_atm = & + currentSite%mass_balance(el)%burn_flux_to_atm + & + leaf_burn_frac * leaf_m * nc%n end do ! Here the mass is removed from the plant @@ -1090,24 +1003,26 @@ subroutine spawn_patches( currentSite, bc_in) currentCohort%fraction_crown_burned = 0.0_r8 nc%fraction_crown_burned = 0.0_r8 - ! Logging is the dominant disturbance - elseif (currentPatch%disturbance_mode .eq. dtype_ilog ) then + + ! Logging is the dominant disturbance + elseif (currentPatch%disturbance_mode .eq. dtype_ilog ) then + ! If this cohort is in the upper canopy. It generated if(currentCohort%canopy_layer == 1)then - + ! calculate the survivorship of disturbed trees because non-harvested nc%n = currentCohort%n * currentCohort%l_degrad ! nc%n = (currentCohort%l_degrad / (currentCohort%l_degrad + & ! currentCohort%lmort_direct + currentCohort%lmort_collateral + ! currentCohort%lmort_infra) ) * & ! currentCohort%n * patch_site_areadis/currentPatch%area - + ! Reduce counts in the existing/donor patch according to the logging rate currentCohort%n = currentCohort%n * & - (1.0_r8 - min(1.0_r8,(currentCohort%lmort_direct + & - currentCohort%lmort_collateral + & - currentCohort%lmort_infra + currentCohort%l_degrad))) + (1.0_r8 - min(1.0_r8,(currentCohort%lmort_direct + & + currentCohort%lmort_collateral + & + currentCohort%lmort_infra + currentCohort%l_degrad))) nc%cmort = currentCohort%cmort nc%hmort = currentCohort%hmort @@ -1123,13 +1038,15 @@ subroutine spawn_patches( currentSite, bc_in) nc%lmort_direct = 0._r8 nc%lmort_collateral = 0._r8 nc%lmort_infra = 0._r8 - + else - + ! WHat to do with cohorts in the understory of a logging generated ! disturbance patch? + if(prt_params%woody(currentCohort%pft) == itrue)then - + + ! Survivorship of undestory woody plants. Two step process. ! Step 1: Reduce current number of plants to reflect the ! change in area. @@ -1137,8 +1054,7 @@ subroutine spawn_patches( currentSite, bc_in) ! but since the patch is smaller ! and cohort counts are absolute, reduce this number. nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - - + ! because the mortality rate due to impact for the cohorts which had ! been in the understory and are now in the newly- ! disturbed patch is very high, passing the imort directly to @@ -1150,45 +1066,27 @@ subroutine spawn_patches( currentSite, bc_in) currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) + & nc%n * currentPatch%fract_ldist_not_harvested * & logging_coll_under_frac / hlm_freq_day - - currentSite%imort_crownarea = currentSite%imort_crownarea + & - nc%c_area * currentPatch%fract_ldist_not_harvested * & - logging_coll_under_frac / hlm_freq_day currentSite%imort_carbonflux(currentCohort%pft) = & currentSite%imort_carbonflux(currentCohort%pft) + & (nc%n * currentPatch%fract_ldist_not_harvested * & logging_coll_under_frac/ hlm_freq_day ) * & total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 - - if (hlm_use_tree_damage .eq. itrue) then - currentSite%imort_rate_damage(currentCohort%crowndamage,& - currentCohort%size_class, currentCohort%pft) = & - currentSite%imort_rate_damage(currentCohort%crowndamage,& - currentCohort%size_class, currentCohort%pft) + & - nc%n * currentPatch%fract_ldist_not_harvested * & - logging_coll_under_frac / hlm_freq_day - - currentSite%imort_cflux_damage(nc%crowndamage, nc%size_class) = & - currentSite%imort_cflux_damage(nc%crowndamage, nc%size_class) + & - (nc%n * currentPatch%fract_ldist_not_harvested * & - logging_coll_under_frac/ hlm_freq_day ) * & - total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 - end if - + + ! Step 2: Apply survivor ship function based on the understory death fraction - + ! remaining of understory plants of those that are knocked ! over by the overstorey trees dying... ! LOGGING SURVIVORSHIP OF UNDERSTORY PLANTS IS SET AS A NEW PARAMETER ! in the fatesparameter files nc%n = nc%n * (1.0_r8 - & (1.0_r8-currentPatch%fract_ldist_not_harvested) * logging_coll_under_frac) - + ! Step 3: Reduce the number count of cohorts in the ! original/donor/non-disturbed patch to reflect the area change currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - + nc%cmort = currentCohort%cmort nc%hmort = currentCohort%hmort nc%bmort = currentCohort%bmort @@ -1200,17 +1098,17 @@ subroutine spawn_patches( currentSite, bc_in) nc%lmort_direct = currentCohort%lmort_direct nc%lmort_collateral = currentCohort%lmort_collateral nc%lmort_infra = currentCohort%lmort_infra - - else ! if not woody - + + else + ! grass is not killed by mortality disturbance events. ! Just move it into the new patch area. ! Just split the grass into the existing and new patch structures nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - + ! Those remaining in the existing currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - + ! No grass impact mortality imposed on the newly created patch nc%cmort = currentCohort%cmort nc%hmort = currentCohort%hmort @@ -1218,176 +1116,21 @@ subroutine spawn_patches( currentSite, bc_in) nc%frmort = currentCohort%frmort nc%smort = currentCohort%smort nc%asmort = currentCohort%asmort - nc%dgmort = currentCohort%dgmort nc%dmort = currentCohort%dmort nc%lmort_direct = currentCohort%lmort_direct nc%lmort_collateral = currentCohort%lmort_collateral nc%lmort_infra = currentCohort%lmort_infra - + endif ! is/is-not woody - - end if - - else - write(fates_log(),*) 'unknown disturbance mode?' - write(fates_log(),*) 'disturbance_mode: ',currentPatch%disturbance_mode - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if ! Select disturbance mode - - - ! Regardless of disturbance type, reduce mass of damaged trees - if(hlm_use_tree_damage .eq. itrue) then - if(damage_time) then - - ! if woody - if (prt_params%woody(currentCohort%pft)==1 ) then - - if(.not. currentCohort%isnew ) then - - ! to keep track of how much canopy n needs to be reduced by after the loop - cd_n_total = 0.0_r8 - - ! for each damage class find the number density and if big enough allocate a new cohort - do cd = currentCohort%crowndamage+1, nlevdamage - - call GetDamageFrac(currentCohort%crowndamage, cd, currentCohort%pft, cd_frac) - - if(i_damage_code .eq. 1 .and. currentCohort%canopy_layer == 1) then - cd_n = currentCohort%n * cd_frac - else if(i_damage_code .eq. 2 .and. currentCohort%canopy_layer > 1) then - cd_n = nc%n * cd_frac - else - cd_n = 0._r8 - end if - - - if(cd_n > nearzero) then - - cd_n_total = cd_n_total + cd_n - - allocate(nc_d) ! new cohort surviving but damaged - if(hlm_use_planthydro.eq.itrue) call InitHydrCohort(CurrentSite,nc_d) - - ! Initialize the PARTEH object and point to the - ! correct boundary condition fields - nc_d%prt => null() - - call InitPRTObject(nc_d%prt) - call InitPRTBoundaryConditions(nc_d) - call zero_cohort(nc_d) - - ! nc_canopy_d is the new cohort that gets damaged - call copy_cohort(currentCohort, nc_d) - - nc_d%canopy_layer = currentCohort%canopy_layer - nc_d%canopy_layer_yesterday = 1._r8 - - ! new number densities - we just do damaged cohort here - - ! undamaged at the end of the cohort loop once we know how many damaged to - ! subtract - - nc_d%n = cd_n - nc_d%crowndamage = cd - - ! update crown area here - for cohort fusion and canopy organisation below - call carea_allom(nc_d%dbh, nc_d%n, currentSite%spread,& - nc_d%pft, nc_d%crowndamage, nc_d%c_area) - - call GetCrownReduction(nc_d%crowndamage, mass_frac) - - - leaf_m_pre = nc_d%prt%GetState(leaf_organ, all_carbon_elements) + & - nc_d%prt%GetState(repro_organ, all_carbon_elements) - call PRTDamageLosses(nc_d%prt, leaf_organ, mass_frac) - call PRTDamageLosses(nc_d%prt, repro_organ, mass_frac) - leaf_m_post = nc_d%prt%GetState(leaf_organ, all_carbon_elements) + & - nc_d%prt%GetState(repro_organ, all_carbon_elements) - - leaf_loss_prt = leaf_loss_prt + (leaf_m_pre - leaf_m_post)* & - nc_d%n - - sapw_m_pre = nc_d%prt%GetState(sapw_organ, all_carbon_elements) - call PRTDamageLosses(nc_d%prt, sapw_organ, mass_frac * & - branch_frac * agb_frac) - sapw_m_post = nc_d%prt%GetState(sapw_organ, all_carbon_elements) - sapw_loss_prt = sapw_loss_prt + (sapw_m_pre - sapw_m_post)*nc_d%n - - struct_m_pre = nc_d%prt%GetState(struct_organ, all_carbon_elements) - call PRTDamageLosses(nc_d%prt, struct_organ, mass_frac * & - branch_frac * agb_frac) - struct_m_post = nc_d%prt%GetState(struct_organ, all_carbon_elements) - struct_loss_prt = struct_loss_prt + (struct_m_pre - struct_m_post)* & - nc_d%n - - store_m_pre = nc_d%prt%GetState(store_organ, all_carbon_elements) - call PRTDamageLosses(nc_d%prt, store_organ, mass_frac * & - branch_frac * agb_frac) - store_m_post = nc_d%prt%GetState(store_organ, all_carbon_elements) - store_loss_prt = store_loss_prt + (store_m_pre - store_m_post)* & - nc_d%n - - fnrt_c = nc_d%prt%GetState(fnrt_organ, all_carbon_elements) - - - if(i_damage_code .eq. 1 ) then - currentSite%crownarea_canopy_damage = currentSite%crownarea_canopy_damage + & - (currentCohort%c_area/currentCohort%n - nc_d%c_area/nc_d%n) * nc_d%n - end if - - if(i_damage_code .eq. 2 ) then - currentSite%crownarea_ustory_damage = currentSite%crownarea_ustory_damage + & - (currentCohort%c_area/currentCohort%n - nc_d%c_area/nc_d%n) * nc_d%n - end if - - - storebigcohort => currentPatch%tallest - storesmallcohort => currentPatch%shortest - if(associated(currentPatch%tallest))then - tnull = 0 - else - tnull = 1 - currentPatch%tallest => nc_d - nc_d%taller => null() - endif - - if(associated(currentPatch%shortest))then - snull = 0 - else - snull = 1 - currentPatch%shortest => nc_d - nc_d%shorter => null() - endif - - call insert_cohort(nc_d, currentPatch%tallest, currentPatch%shortest, & - tnull, snull, storebigcohort, storesmallcohort) - - currentPatch%tallest => storebigcohort - currentPatch%shortest => storesmallcohort - - end if ! end if new n is large enough - - end do ! end crowndamage loop - - ! Reduce currentCohort%n now based on sum of all new damage classes - ! And update c_area of the undamaged cohort (since number density has changed) - if(i_damage_code .eq. 1 ) then - currentCohort%n = currentCohort%n - cd_n_total - call carea_allom(currentCohort%dbh, currentCohort%n, currentSite%spread,& - currentCohort%pft, currentCohort%crowndamage, currentCohort%c_area) - else if(i_damage_code .eq. 2 ) then - nc%n = nc%n - cd_n_total - call carea_allom(nc%dbh, nc%n, currentSite%spread,& - nc%pft, nc%crowndamage, nc%c_area) - end if - - - end if ! end if not new - end if ! end if canopy and woody - end if ! end if damage time - end if ! end if damage is on - + + endif ! Select canopy layer + + else + write(fates_log(),*) 'unknown disturbance mode?' + write(fates_log(),*) 'disturbance_mode: ',currentPatch%disturbance_mode + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if ! Select disturbance mode - ! Put new undamaged cohorts in the correct place in the linked list if (nc%n > 0.0_r8) then storebigcohort => new_patch%tallest storesmallcohort => new_patch%shortest @@ -1398,7 +1141,7 @@ subroutine spawn_patches( currentSite, bc_in) new_patch%tallest => nc nc%taller => null() endif - + if(associated(new_patch%shortest))then snull = 0 else @@ -1408,24 +1151,22 @@ subroutine spawn_patches( currentSite, bc_in) endif nc%patchptr => new_patch call insert_cohort(nc, new_patch%tallest, new_patch%shortest, & - tnull, snull, storebigcohort, storesmallcohort) - + tnull, snull, storebigcohort, storesmallcohort) + new_patch%tallest => storebigcohort new_patch%shortest => storesmallcohort else - + ! Get rid of the new temporary cohort call DeallocateCohort(nc) deallocate(nc) - + endif - + currentCohort => currentCohort%taller enddo ! currentCohort - - call sort_cohorts(currentPatch) - + !update area of donor patch currentPatch%area = currentPatch%area - patch_site_areadis @@ -1438,20 +1179,19 @@ subroutine spawn_patches( currentSite, bc_in) call terminate_cohorts(currentSite, currentPatch, 2,16,bc_in) call sort_cohorts(currentPatch) - end if ! if ( new_patch%area > nearzero ) then - + !zero disturbance rate trackers currentPatch%disturbance_rate = 0._r8 currentPatch%disturbance_rates = 0._r8 currentPatch%fract_ldist_not_harvested = 0._r8 - end if cp_nocomp_matches_2_if - currentPatch => currentPatch%younger - + end if cp_nocomp_matches_2_if + currentPatch => currentPatch%younger + + enddo ! currentPatch patch loop. - enddo ! currentPatch patch loop. - !*************************/ + !*************************/ !** INSERT NEW PATCH(ES) INTO LINKED LIST !*************************/ @@ -1527,24 +1267,6 @@ subroutine spawn_patches( currentSite, bc_in) call check_patch_area(currentSite) call set_patchno(currentSite) - - ! Stop run if the amount of litter from damage does not match the biomass lost from damaged cohorts - if ( abs(total_litter_d - (leaf_loss_prt + sapw_loss_prt + & - struct_loss_prt + store_loss_prt)) > damage_error_fail ) then - write(fates_log(),*) 'Damage to litter does not match biomass loss' - write(fates_log(),*) 'Damage to litter: ',total_litter_d, & - 'biomass loss: ', (leaf_loss_prt + sapw_loss_prt + struct_loss_prt + store_loss_prt), & - 'error: ',total_litter_d - (leaf_loss_prt + sapw_loss_prt + struct_loss_prt + store_loss_prt) - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - if (damage_time) then - - - write(fates_log(),*) 'Damage to litter: ',total_litter_d - write(fates_log(),*) 'Damage from trees:',leaf_loss_prt+ & - sapw_loss_prt + struct_loss_prt + store_loss_prt - end if end do nocomp_pft_loop return @@ -1572,8 +1294,6 @@ subroutine check_patch_area( currentSite ) real(r8) :: seed_stock real(r8) :: litter_stock real(r8) :: mass_gain - real(r8) :: litter_leaf - real(r8) :: live_leaf real(r8), parameter :: area_error_fail = 1.0e-6_r8 !--------------------------------------------------------------------- @@ -1607,7 +1327,8 @@ subroutine check_patch_area( currentSite ) do el = 1,num_elements ! This returns the total mass on the patch for the current area [kg] - call PatchMassStock(largestPatch,el,live_stock,seed_stock,litter_stock) + call PatchMassStock(largestPatch,el,live_stock,seed_stock,litter_stock) + ! Then we scale the total mass by the added area mass_gain = (seed_stock+litter_stock) * & (area_site-areatot)/largestPatch%area @@ -1749,7 +1470,6 @@ subroutine TransLitterNewPatch(currentSite, & curr_litt => currentPatch%litter(el) new_litt => newPatch%litter(el) - ! Distribute the fragmentation litter flux rates. This is only used for diagnostics ! at this point. Litter fragmentation has already been passed to the output ! boundary flux arrays. @@ -1873,7 +1593,6 @@ subroutine TransLitterNewPatch(currentSite, & end do end do - do pft = 1,numpft @@ -2339,6 +2058,7 @@ subroutine mortality_litter_fluxes(currentSite, currentPatch, & flux_diags%leaf_litter_input(pft) = flux_diags%leaf_litter_input(pft) + & num_dead*(leaf_m + repro_m) + flux_diags%root_litter_input(pft) = flux_diags%root_litter_input(pft) + & num_dead * (fnrt_m + store_m*(1.0_r8-EDPftvarcon_inst%allom_frbstor_repro(pft))) @@ -2353,229 +2073,6 @@ subroutine mortality_litter_fluxes(currentSite, currentPatch, & return end subroutine mortality_litter_fluxes - ! ============================================================================ - - subroutine damage_litter_fluxes(currentSite, currentPatch, newPatch,patch_site_areadis, & - total_damage_litter) - ! - ! !DESCRIPTION: - ! - ! !USES: - use DamageMainMod, only : GetCrownReduction - use DamageMainMod , only : GetDamageFrac - use SFParamsMod , only : SF_val_cwd_frac - use FatesInterfaceTypesMod , only : nlevdamage - use EDParamsMod , only : ED_val_understorey_death - use EDParamsMod , only : damage_canopy_layer_code - use FatesConstantsMod, only : itrue - use FatesParameterDerivedMod, only : param_derived - ! - - ! !ARGUMENTS: - type(ed_site_type) , intent(inout), target :: currentSite - type(ed_patch_type) , intent(inout), target :: currentPatch - type(ed_patch_type) , intent(inout), target :: newPatch - real(r8) , intent(in) :: patch_site_areadis - real(r8), intent(out) :: total_damage_litter - - - ! !LOCAL VARIABLES: - type(ed_cohort_type), pointer :: currentCohort - type(litter_type), pointer :: new_litt - type(litter_type), pointer :: curr_litt - type(site_massbal_type), pointer :: site_mass - type(site_fluxdiags_type), pointer :: flux_diags - - real(r8) :: leaf_donatable_mass ! mass of donatable litter [kg] - real(r8) :: branch_donatable_mass! mass of donatable cwd [kg] - real(r8) :: leaf_m ! leaf mass [kg] - real(r8) :: sapw_m ! sapwood mass [kg] - real(r8) :: struct_m ! structure mass [kg] - real(r8) :: repro_m ! reproductive mass [kg] - real(r8) :: store_m ! storage mass [kg] - real(r8) :: remainder_area ! current patch area after donation [m2] - real(r8) :: retain_frac ! Fraction of mass to be retained - real(r8) :: retain_m2 ! area normalization for litter mass destined to old patch [m-2] - real(r8) :: donate_frac ! Fraction of mass to be donated - real(r8) :: donate_m2 ! area normalization for litter mass destined to new patch [m-2] - integer :: pft ! plant functional type index - integer :: crowndamage ! new increased crown damage class - real(r8) :: crown_reduction ! amount that crown is reduced by (must be same as leaf biomass) - real(r8) :: leaf_loss ! amount of leaf biomass that has been lost - real(r8) :: branch_loss ! amount of branch biomass that has been lost - integer :: dcmpy ! decomposability index - real(r8) :: seed_mass ! Total seed mass generated from storage death [kg] - integer :: c ! coarse woody debris pool index - integer :: el ! element loop index - integer :: sl ! soil layer index - integer :: element_id ! parteh compatible global element index - real(r8) :: dcmpy_frac ! decomposability fraction - real(r8) :: num_trees ! number of trees that were damaged - real(r8) :: num_trees_cd - integer :: cd - real(r8) :: cd_frac - real(r8) :: agb_frac - real(r8) :: branch_frac - integer :: ncwd_no_trunk - real(r8), allocatable :: SF_val_CWD_frac_canopy(:) - real(r8) :: cd_n_tot - integer :: i_damage_code - - !--------------------------------------------------------------------- - i_damage_code = int(damage_canopy_layer_code) - - total_damage_litter = 0.0_r8 - cd_n_tot = 0.0_r8 - ncwd_no_trunk = ncwd - 1 - allocate(SF_val_CWD_frac_canopy(ncwd_no_trunk)) - - ! crown damage is currently not trunks - but we want 100% of - ! damage above to go to litter. We therefore have to - ! renormalise just the first three litter bins - SF_val_CWD_frac_canopy = SF_val_CWD_frac(1:ncwd_no_trunk)/sum(SF_val_CWD_frac(1:ncwd_no_trunk)) - - - ! m2 - remainder_area = currentPatch%area - patch_site_areadis - ! fraction of litter to retain (remain area frac * how much - ! dispersal of litter there is) - retain_frac = (1.0_r8-damage_localization) * & - remainder_area/(newPatch%area+remainder_area) - donate_frac = 1.0_r8-retain_frac - - if(remainder_area > rsnbl_math_prec) then - retain_m2 = retain_frac/remainder_area - donate_m2 = (1.0_r8-retain_frac)/newPatch%area - else - retain_m2 = 0._r8 - donate_m2 = 1._r8/newPatch%area - end if - - - ! loop through elements and spread between retain and donate litter - do el = 1,num_elements - - element_id = element_list(el) - site_mass => currentSite%mass_balance(el) - flux_diags => currentSite%flux_diags(el) - curr_litt => currentPatch%litter(el) ! Litter pool of "current" patch - new_litt => newPatch%litter(el) - - - - currentCohort => currentPatch%shortest - - do while(associated(currentCohort)) - - - pft = currentCohort%pft - agb_frac = prt_params%allom_agb_frac(pft) - branch_frac = param_derived%branch_frac(pft) - - ! Get mass in Kg of the element in the specified organ - sapw_m = currentCohort%prt%GetState(sapw_organ, element_id) - struct_m = currentCohort%prt%GetState(struct_organ, element_id) - leaf_m = currentCohort%prt%GetState(leaf_organ, element_id) !kg - repro_m = currentCohort%prt%GetState(repro_organ, element_id) - store_m = currentCohort%prt%GetState(store_organ, element_id) - - if(prt_params%woody(currentCohort%pft)==1) then - - if( hlm_use_tree_damage .eq.itrue .and. & - currentCohort%canopy_layer ==1 .and. i_damage_code .eq. 1 .and. & - .not. currentCohort%isnew) then - - ! litter is called before damage - so we need to account for mortality here too - num_trees = currentCohort%n * (1.0_r8 - fates_mortality_disturbance_fraction * & - min(1.0_r8, currentCohort%dmort* hlm_freq_day)) - - else if( hlm_use_tree_damage .eq.itrue .and. & - currentCohort%canopy_layer > 1 .and. i_damage_code .eq. 2 .and. & - .not. currentCohort%isnew) then - - ! for trees in new patch to be damaged - num_trees = currentCohort%n * (patch_site_areadis/currentPatch%area) * & - (1.0_r8 - ED_val_understorey_death) - - else - num_trees = 0._r8 - end if - - - - do cd = currentCohort%crowndamage+1, nlevdamage - - call GetDamageFrac(currentCohort%crowndamage, cd, currentCohort%pft, cd_frac) - - ! now to get the number of damaged trees we multiply by damage frac - num_trees_cd = num_trees * cd_frac - - cd_n_tot = cd_n_tot + num_trees_cd - - ! if non negligable get litter - if (num_trees_cd > nearzero ) then - - call GetCrownReduction(cd, crown_reduction) - - - ! leaf loss in kg - leaf_loss = (leaf_m + repro_m) * crown_reduction - leaf_donatable_mass = num_trees_cd * leaf_loss - - do dcmpy=1,ndcmpy - dcmpy_frac = GetDecompyFrac(pft,leaf_organ,dcmpy) - - new_litt%leaf_fines(dcmpy) = new_litt%leaf_fines(dcmpy) + & - leaf_donatable_mass*donate_m2*dcmpy_frac ! kg per m2 - curr_litt%leaf_fines(dcmpy) = curr_litt%leaf_fines(dcmpy) + & - leaf_donatable_mass*retain_m2*dcmpy_frac ! kg per m2 - end do - - flux_diags%leaf_litter_input(pft) = flux_diags%leaf_litter_input(pft) + & - leaf_donatable_mass - - ! branch loss - branch_loss = (sapw_m + struct_m + store_m) * crown_reduction * & - branch_frac * agb_frac * num_trees_cd - - do c=1,(ncwd_no_trunk) - - branch_donatable_mass = branch_loss * SF_val_CWD_frac_canopy(c) - - ! Transfer wood of dying trees to AG CWD pools - new_litt%ag_cwd(c) = new_litt%ag_cwd(c) + branch_donatable_mass * donate_m2 - - curr_litt%ag_cwd(c) = curr_litt%ag_cwd(c) + branch_donatable_mass * retain_m2 - - flux_diags%cwd_ag_input(c) = & - flux_diags%cwd_ag_input(c) + branch_donatable_mass - - end do - - ! should match leaf damage that is printed after PRTDamageLosses is called - total_damage_litter = total_damage_litter + leaf_donatable_mass + & - branch_loss - - end if ! end if non-negligable - end do ! end crown damage loop - - end if ! end if woody - - - - currentCohort => currentCohort%taller - - - enddo !currentCohort - - enddo ! end element - - return - end subroutine damage_litter_fluxes - - - - ! ============================================================================ subroutine create_patch(currentSite, new_patch, age, areap, label,nocomp_pft) From 715f3b52c47ae984c421e8e56dfc3ca426db41a4 Mon Sep 17 00:00:00 2001 From: YanlanLiu Date: Wed, 6 Jul 2022 09:07:12 -0700 Subject: [PATCH 278/852] crossgrid seed exchange for all PFTs --- tools/ModifyParams.sh | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tools/ModifyParams.sh diff --git a/tools/ModifyParams.sh b/tools/ModifyParams.sh new file mode 100644 index 0000000000..bf52a181d2 --- /dev/null +++ b/tools/ModifyParams.sh @@ -0,0 +1,35 @@ +#!/bin/sh +# Put in ~/global/scratch/users/yanlanliu/E3SM/components/elm/src/external_models/fates/tools +cp fates_parameter_default.nc fates_params_seednew_bkp.nc + +./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_recruit_initd --value 0.0 --allPFTs + +./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_recruit_initd --value 0.4 --pft 7 + +./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_recruit_initd --value 0.4 --pft 9 + +./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_recruit_initd --value 0.4 --pft 10 + + +./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_seed_alloc --value 0.3 --pft 7 + +./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_seed_alloc --value 0.3 --pft 9 + +./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_seed_alloc --value 0.3 --pft 10 + +./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_seed_alloc_mature --value 0.7 --pft 7 + +./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_seed_alloc_mature --value 0.7 --pft 9 + +./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_seed_alloc_mature --value 0.7 --pft 10 + +./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_seed_dbh_repro_threshold --value 0.5 --pft 7 + +./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_seed_dbh_repro_threshold --value 0.5 --pft 9 + +./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_seed_dbh_repro_threshold --value 0.5 --pft 10 + +./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_phen_chiltemp --value -2.0 + +./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_phen_coldtemp --value -0.0 + From 33516666a9c543e5f381a3d6cffe3543178f4044 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 6 Jul 2022 11:53:57 -0600 Subject: [PATCH 279/852] Added declaration of global hlm_use_tree_damage --- biogeochem/EDPatchDynamicsMod.F90 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 7fe99f2ee6..345e725b0e 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -47,6 +47,7 @@ module EDPatchDynamicsMod use FatesInterfaceTypesMod , only : hlm_use_sp use FatesInterfaceTypesMod , only : hlm_use_nocomp use FatesInterfaceTypesMod , only : hlm_use_fixed_biogeog + use FatesInterfaceTypesMod , only : hlm_use_tree_damage use FatesGlobals , only : endrun => fates_endrun use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : itrue, ifalse @@ -801,7 +802,7 @@ subroutine spawn_patches( currentSite, bc_in) (nc%n * ED_val_understorey_death / hlm_freq_day ) * & total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 - if (hlm_use_crown_damage .eq. itrue) then + if (hlm_use_tree_damage .eq. itrue) then currentSite%imort_rate_damage(currentCohort%crowndamage, & currentCohort%size_class, currentCohort%pft) = & @@ -914,7 +915,7 @@ subroutine spawn_patches( currentSite, bc_in) end if ! also track fire damage mortality and cflux along size x damage axis - if(hlm_use_crown_damage .eq. itrue) then + if(hlm_use_tree_damage .eq. itrue) then if(levcan==ican_upper) then currentSite%fmort_rate_canopy_damage(currentCohort%crowndamage, currentCohort%size_class, & currentCohort%pft) = & From b9d7b97cdb3068963e379e7edf7afdb2cab8700e Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 6 Jul 2022 15:35:07 -0400 Subject: [PATCH 280/852] First pass at the new damage application routine --- biogeochem/EDPhysiologyMod.F90 | 141 +++++++++++++++++++++++++++++++++ main/EDMainMod.F90 | 3 +- 2 files changed, 143 insertions(+), 1 deletion(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 45d9ca38a3..7ea5344f4e 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -121,6 +121,7 @@ module EDPhysiologyMod public :: ZeroAllocationRates public :: PreDisturbanceLitterFluxes public :: PreDisturbanceIntegrateLitter + public :: GenerateDamageAndLitterFluxes public :: SeedIn logical, parameter :: debug = .false. ! local debug flag @@ -186,6 +187,146 @@ subroutine ZeroAllocationRates( currentSite ) return end subroutine ZeroAllocationRates + ! ============================================================================ + + subroutine GenerateDamageAndLitterFluxes( currentSite, currentPatch, bc_in ) + + if(hlm_use_crown_damage .ne. itrue) return + + if(.not.damage_time) return + + currentCohort => currentPatch%tallest + do while (associated(currentCohort)) + + ! Ignore damage to new plants and non-woody plants + if(prt_params%woody(currentCohort%pft)==ifalse ) cycle + if(currentCohort%isnew ) cycle + + agb_frac = prt_params%allom_agb_frac(currentCohort%pft) + branch_frac = param_derived%branch_frac(currentCohort%pft) + + do_dclass: do cd = currentCohort%crowndamage+1, nlevdamage + + call GetDamageFrac(currentCohort%crowndamage, cd, currentCohort%pft, cd_frac) + + ! now to get the number of damaged trees we multiply by damage frac + num_trees_cd = currentCohort%n * cd_frac + + ! if non negligable lets create a new cohort and generate some litter + if_numtrees: if (num_trees_cd > nearzero ) then + + ! Create a new damaged cohort + allocate(nc_d) ! new cohort surviving but damaged + if(hlm_use_planthydro.eq.itrue) call InitHydrCohort(CurrentSite,nc_d) + + ! Initialize the PARTEH object and point to the + ! correct boundary condition fields + nc_d%prt => null() + + call InitPRTObject(nc_d%prt) + call InitPRTBoundaryConditions(nc_d) + call zero_cohort(nc_d) + + ! nc_canopy_d is the new cohort that gets damaged + call copy_cohort(currentCohort, nc_d) + + ! new number densities - we just do damaged cohort here - + ! undamaged at the end of the cohort loop once we know how many damaged to + ! subtract + + nc_d%n = num_trees_cd + nc_d%crowndamage = cd + + ! Remove these trees from the donor cohort + currentCohort%n = currentCohort%n - num_trees_cd + + ! update crown area here - for cohort fusion and canopy organisation below + call carea_allom(nc_d%dbh, nc_d%n, currentSite%spread,& + nc_d%pft, nc_d%crowndamage, nc_d%c_area) + + call GetCrownReduction(cd, crown_loss_frac) + + do_element: do el = 1, num_elements + + litt => currentPatch%litter(el) + flux_diags => currentSite%flux_diags(el) + + ! Reduce the mass of the newly damaged cohort + ! Fine-roots are not damaged as of yet + ! only above-ground sapwood,structure and storage in + ! branches is damaged/removed + branch_loss_frac = crown_loss_frac * branch_frac * agb_frac + + leaf_loss = nc_d%prt%GetState(leaf_organ,element_id(el))*crown_loss_frac + repro_loss = nc_d%prt%GetState(repro_organ,element_id(el))*crown_loss_frac + sapw_loss = nc_d%prt%GetState(sapw_organ,element_id(el))*branch_loss_frac + store_loss = nc_d%prt%GetState(store_organ,element_id(el))*branch_loss_frac + struct_loss = nc_d%prt%GetState(struct_organ,element_id(el))*branch_loss_frac + + ! ------------------------------------------------------ + ! Transfer the biomass from the cohort's + ! damage to the litter input fluxes + ! ------------------------------------------------------ + + do dcmpy=1,ndcmpy + dcmpy_frac = GetDecompyFrac(pft,leaf_organ,dcmpy) + litt%leaf_fines_in(dcmpy) = litt%leaf_fines_in(dcmpy) + & + (store_loss+leaf_loss+repro_loss) * & + nc_d%n * dcmpy_frac / currentPatch%area + end do + + flux_diags%leaf_litter_input(pft) = & + flux_diags%leaf_litter_input(pft) + & + (store_loss+leaf_loss+repro_loss) * nc_d%n + + do c = 1,ncwd + litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + & + (sapw_loss + struct_loss) * & + SF_val_CWD_frac(c) * nc_d%n / & + currentPatch%area + + flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & + (struct_m_turnover + sapw_m_turnover) * & + SF_val_CWD_frac(c) * nc_d%n + end do + + end do do_element + + ! Applying the damage to the cohort, does not need to happen + ! in the element loop, it will loop inside that call + call PRTDamageLosses(nc_d%prt, leaf_organ, crown_loss_frac) + call PRTDamageLosses(nc_d%prt, repro_organ, crown_loss_frac) + call PRTDamageLosses(nc_d%prt, sapw_organ, branch_loss_frac) + call PRTDamageLosses(nc_d%prt, store_organ, branch_loss_frac) + call PRTDamageLosses(nc_d%prt, struct_organ, branch_loss_frac) + + + !----------- Insert new cohort into the linked list + ! This list is going tall to short, lets add this new + ! cohort into a taller position so we don't hit it again + ! as the loop traverses + ! --------------------------------------------------------------! + + nc_d%shorter => currentCohort + if(associated(currentCohort%taller))then + nc_d%taller => currentCohort%taller + currentCohort%taller%shorter => nc_d + else + cpatch%tallest => nc_d + nc_d%taller => null() + endif + currentCohort%taller => nc_d + + + end if if_numtrees + + end do do_dclass + + currentCohort => currentCohort%shorter + enddo + + return + end subroutine GenerateDamageAndLitterFluxes ! ============================================================================ diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 537381a977..04f71fc615 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -738,10 +738,11 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentPatch => currentSite%youngest_patch do while(associated(currentPatch)) + + call GenerateDamageAndLitterFluxes( currentSite, currentPatch, bc_in) call PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in) - call PreDisturbanceIntegrateLitter(currentPatch ) currentPatch => currentPatch%older From 049c850674253aec2a8c57c6cde18d98debeb992 Mon Sep 17 00:00:00 2001 From: Jun Yan Ding Date: Wed, 6 Jul 2022 14:52:15 -0700 Subject: [PATCH 281/852] fixing hydro grass water balance error --- biogeochem/EDPhysiologyMod.F90 | 9 +++++---- biogeophys/FatesPlantHydraulicsMod.F90 | 10 +++++++++- main/FatesHydraulicsMemMod.F90 | 2 +- parameter_files/fates_params_default.cdl | 2 +- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 6feb039d37..65db791aee 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -815,8 +815,8 @@ subroutine phenology( currentSite, bc_in ) endif ! ! accumulate the GDD using daily mean temperatures - ! Don't accumulate GDD during the growing season (that wouldn't make sense) - if (temp_in_C .gt. 0._r8 .and. currentSite%cstatus == phen_cstat_iscold) then + ! Don't accumulate GDD during the growing season (that wouldn't make sense) Junyan modified to adding nevercold + if (temp_in_C .gt. 0._r8 .and. (currentSite%cstatus == phen_cstat_iscold .or. currentSite%cstatus == phen_cstat_nevercold)) then currentSite%grow_deg_days = currentSite%grow_deg_days + temp_in_C endif @@ -910,9 +910,10 @@ subroutine phenology( currentSite, bc_in ) ! and thus %nchilldays will never go from zero to 1. The following logic ! when coupled with this fact will essentially prevent cold-deciduous ! plants from re-emerging in areas without at least some cold days - + if( (currentSite%cstatus == phen_cstat_notcold) .and. & - (dayssincecleafoff > 400)) then ! remove leaves after a whole year + (dayssincecleafoff > 40000)) then ! remove leaves after a whole year, + !Junyan change dayssincecleafoff > 400 to 40000 to disable this function, so the condition will never be met ! when there is no 'off' period. currentSite%grow_deg_days = 0._r8 diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index bd77528b14..3130a1d43a 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -934,8 +934,16 @@ subroutine UpdatePlantHydrLenVol(ccohort,site_hydr) crown_depth = min(ccohort%hite,0.1_r8) z_stem = ccohort%hite - crown_depth v_sapwood = a_sapwood * z_stem ! + 0.333_r8*a_sapwood*crown_depth - ccohort_hydr%v_ag(n_hypool_leaf+1:n_hypool_ag) = v_sapwood / n_hypool_stem + ! Junyan changed the following code to calculate the above ground node volume + ! foliage donate half of its water volume to xylem for grass + if (prt_params%woody(ft)==1) then + ccohort_hydr%v_ag(n_hypool_leaf+1:n_hypool_ag) = v_sapwood / n_hypool_stem ! original code + else + v_leaf_donate(1:n_hypool_leaf) = ccohort_hydr%v_ag(1:n_hypool_leaf) / l2sap_vol_donate_frac + ccohort_hydr%v_ag(1:n_hypool_leaf) = ccohort_hydr%v_ag(1:n_hypool_leaf) - v_leaf_donate(1:n_hypool_leaf) + ccohort_hydr%v_ag(n_hypool_leaf+1:n_hypool_ag) = (v_sapwood + sum(v_leaf_donate(1:n_hypool_leaf))) / n_hypool_stem + end if ! Determine belowground biomass as a function of total (sapwood, heartwood, ! leaf, fine root) biomass then subtract out the fine root biomass to get diff --git a/main/FatesHydraulicsMemMod.F90 b/main/FatesHydraulicsMemMod.F90 index f971b4f55b..8dbeb8030f 100644 --- a/main/FatesHydraulicsMemMod.F90 +++ b/main/FatesHydraulicsMemMod.F90 @@ -29,7 +29,7 @@ module FatesHydraulicsMemMod integer, parameter, public :: n_hypool_stem = 1 integer, parameter, public :: n_hypool_troot = 1 ! CANNOT BE CHANGED integer, parameter, public :: n_hypool_aroot = 1 ! THIS IS "PER-SOIL-LAYER" - integer, parameter, public :: nshell = 5 + integer, parameter, public :: nshell = 1 ! number of aboveground plant water storage nodes integer, parameter, public :: n_hypool_ag = n_hypool_leaf+n_hypool_stem diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 6d5fa2cb4e..c33aa39485 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -769,7 +769,7 @@ data: fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100 ; - fates_hydr_htftype_node = 1, 1, 1, 1 ; + fates_hydr_htftype_node = 2, 2, 2, 2 ; fates_prt_organ_id = 1, 2, 3, 6 ; From 18317daa7933b3ecf166413d89854d76033abde8 Mon Sep 17 00:00:00 2001 From: Jun Yan Ding Date: Wed, 6 Jul 2022 19:12:19 -0700 Subject: [PATCH 282/852] fix hydro grass --- biogeophys/FatesPlantHydraulicsMod.F90 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 3130a1d43a..06bfd8781f 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -857,7 +857,9 @@ subroutine UpdatePlantHydrLenVol(ccohort,site_hydr) ! roots to help mitigate numerical issues due to very small volumes. This is the ! fraction the transporting roots donate to those layers real(r8), parameter :: t2aroot_vol_donate_frac = 0.65_r8 - + real(r8), parameter :: l2sap_vol_donate_frac = 0.5_r8 ! Junyan added + + real(r8), parameter :: min_leaf_frac = 0.1_r8 ! Fraction of maximum leaf carbon that ! we set as our lower cap on leaf volume real(r8), parameter :: min_trim = 0.1_r8 ! The lower cap on trimming function used From 87f06677e9909ae421e4b22603e790a18198ef39 Mon Sep 17 00:00:00 2001 From: JunyanDing <43835195+JunyanDing@users.noreply.github.com> Date: Wed, 6 Jul 2022 20:51:51 -0700 Subject: [PATCH 283/852] Update FatesPlantHydraulicsMod.F90 --- biogeophys/FatesPlantHydraulicsMod.F90 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 06bfd8781f..cc26852bd0 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -852,13 +852,14 @@ subroutine UpdatePlantHydrLenVol(ccohort,site_hydr) integer :: nlevrhiz ! number of rhizosphere levels real(r8) :: dbh ! the dbh of current cohort [cm] real(r8) :: z_fr ! rooting depth of a cohort [cm] - + real(r8) :: v_leaf_donate(1:n_hypool_leaf) ! the volume that leaf will donate to xylem + ! We allow the transporting root to donate a fraction of its volume to the absorbing ! roots to help mitigate numerical issues due to very small volumes. This is the ! fraction the transporting roots donate to those layers real(r8), parameter :: t2aroot_vol_donate_frac = 0.65_r8 real(r8), parameter :: l2sap_vol_donate_frac = 0.5_r8 ! Junyan added - + real(r8), parameter :: min_leaf_frac = 0.1_r8 ! Fraction of maximum leaf carbon that ! we set as our lower cap on leaf volume From 9d9c192f184431c5f329ac9ed195ee9de10cc952 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 8 Jul 2022 17:03:54 -0600 Subject: [PATCH 284/852] zero cohort water balance error during cohort creation --- biogeochem/EDCohortDynamicsMod.F90 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index ab06f828e7..4948f68129 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -332,6 +332,9 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & ! This allocates array spaces call InitHydrCohort(currentSite,new_cohort) + ! zero out the water balance error + new_cohort%co_hydr%errh2o = 0._r8 + ! This calculates node heights call UpdatePlantHydrNodes(new_cohort,new_cohort%pft, & new_cohort%hite,currentSite%si_hydr) From 3e2aeab861d1fd522c7580e9a99739db6953bf88 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 11 Jul 2022 14:51:45 -0400 Subject: [PATCH 285/852] Adding variable definitions to the damage generation routine --- biogeochem/EDPhysiologyMod.F90 | 152 ++++++++++++++++++++------------- 1 file changed, 92 insertions(+), 60 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 7ea5344f4e..7fff02491a 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -13,12 +13,14 @@ module EDPhysiologyMod use FatesInterfaceTypesMod, only : hlm_day_of_year use FatesInterfaceTypesMod, only : numpft use FatesInterfaceTypesMod, only : nleafage + use FatesInterfaceTypesMod, only : nlevdamage use FatesInterfaceTypesMod, only : hlm_use_planthydro use FatesInterfaceTypesMod, only : hlm_parteh_mode use FatesInterfaceTypesMod, only : hlm_use_fixed_biogeog use FatesInterfaceTypesMod, only : hlm_use_nocomp use FatesInterfaceTypesMod, only : hlm_nitrogen_spec use FatesInterfaceTypesMod, only : hlm_phosphorus_spec + use FatesInterfaceTypesMod, only : hlm_use_tree_damage use FatesConstantsMod, only : r8 => fates_r8 use FatesConstantsMod, only : nearzero use EDPftvarcon , only : EDPftvarcon_inst @@ -103,11 +105,13 @@ module EDPhysiologyMod use PRTGenericMod, only : repro_organ use PRTGenericMod, only : struct_organ use PRTGenericMod, only : SetState - use PRTLossFluxesMod, only : PRTPhenologyFlush - use PRTLossFluxesMod, only : PRTDeciduousTurnover - use PRTLossFluxesMod, only : PRTReproRelease - use PRTGenericMod, only : StorageNutrientTarget - + use PRTLossFluxesMod, only : PRTPhenologyFlush + use PRTLossFluxesMod, only : PRTDeciduousTurnover + use PRTLossFluxesMod, only : PRTReproRelease + use PRTGenericMod, only : StorageNutrientTarget + use DamageMainMod, only : damage_time + use SFParamsMod, only : SF_val_CWD_frac + implicit none private @@ -189,67 +193,96 @@ end subroutine ZeroAllocationRates ! ============================================================================ - subroutine GenerateDamageAndLitterFluxes( currentSite, currentPatch, bc_in ) + subroutine GenerateDamageAndLitterFluxes( csite, cpatch, bc_in ) - if(hlm_use_crown_damage .ne. itrue) return + ! Arguments + type(ed_site_type) :: csite + type(ed_patch_type) :: cpatch + type(bc_in_type), intent(in) :: bc_in + - if(.not.damage_time) return + ! Locals + type(ed_cohort_type), pointer :: ccohort ! Current cohort + type(ed_cohort_type), pointer :: ndcohort ! Newly damage-class cohort + type(litter_type), pointer :: litt ! Points to the litter object + type(site_fluxdiags_type), pointer :: flux_diags ! pointer to site level flux diagnostics object + integer :: cd ! Damage class index + integer :: el ! Element index + integer :: dcmpy ! Decomposition pool index + integer :: c ! CWD pool index + real(r8) :: cd_frac ! Fraction of trees damaged in this class transition + real(r8) :: num_trees_cd ! Number of trees to spawn into the new damage class cohort + real(r8) :: crown_loss_frac ! Fraction of crown lost from one damage class to next + real(r8) :: branch_loss_frac ! Fraction of sap, structure and storage lost in branch + ! fall during damage + real(r8) :: leaf_loss ! Mass lost to each organ during damage [kg] + real(r8) :: repro_loss ! "" [kg] + real(r8) :: sapw_loss ! "" [kg] + real(r8) :: store_loss ! "" [kg] + real(r8) :: struct_loss ! "" [kg] + real(r8) :: dcmpy_frac ! fraction of mass going to each decomposition pool - currentCohort => currentPatch%tallest - do while (associated(currentCohort)) + + if(hlm_use_tree_damage .ne. itrue) return - ! Ignore damage to new plants and non-woody plants - if(prt_params%woody(currentCohort%pft)==ifalse ) cycle - if(currentCohort%isnew ) cycle + if(.not.damage_time) return - agb_frac = prt_params%allom_agb_frac(currentCohort%pft) - branch_frac = param_derived%branch_frac(currentCohort%pft) + ccohort => cpatch%tallest + do while (associated(ccohort)) - do_dclass: do cd = currentCohort%crowndamage+1, nlevdamage + ! Ignore damage to new plants and non-woody plants + if(prt_params%woody(ccohort%pft)==ifalse ) cycle + if(ccohort%isnew ) cycle + + associate( ipft => ccohort%pft, & + agb_frac => prt_params%allom_agb_frac(ccohort%pft), & + branch_frac => param_derived%branch_frac(ccohort%pft)) + + do_dclass: do cd = ccohort%crowndamage+1, nlevdamage - call GetDamageFrac(currentCohort%crowndamage, cd, currentCohort%pft, cd_frac) + call GetDamageFrac(ccohort%crowndamage, cd, ipft, cd_frac) ! now to get the number of damaged trees we multiply by damage frac - num_trees_cd = currentCohort%n * cd_frac + num_trees_cd = ccohort%n * cd_frac ! if non negligable lets create a new cohort and generate some litter if_numtrees: if (num_trees_cd > nearzero ) then ! Create a new damaged cohort - allocate(nc_d) ! new cohort surviving but damaged - if(hlm_use_planthydro.eq.itrue) call InitHydrCohort(CurrentSite,nc_d) + allocate(ndcohort) ! new cohort surviving but damaged + if(hlm_use_planthydro.eq.itrue) call InitHydrCohort(csite,ndcohort) ! Initialize the PARTEH object and point to the ! correct boundary condition fields - nc_d%prt => null() + ndcohort%prt => null() - call InitPRTObject(nc_d%prt) - call InitPRTBoundaryConditions(nc_d) - call zero_cohort(nc_d) + call InitPRTObject(ndcohort%prt) + call InitPRTBoundaryConditions(ndcohort) + call zero_cohort(ndcohort) ! nc_canopy_d is the new cohort that gets damaged - call copy_cohort(currentCohort, nc_d) + call copy_cohort(ccohort, ndcohort) ! new number densities - we just do damaged cohort here - ! undamaged at the end of the cohort loop once we know how many damaged to ! subtract - nc_d%n = num_trees_cd - nc_d%crowndamage = cd + ndcohort%n = num_trees_cd + ndcohort%crowndamage = cd ! Remove these trees from the donor cohort - currentCohort%n = currentCohort%n - num_trees_cd + ccohort%n = ccohort%n - num_trees_cd ! update crown area here - for cohort fusion and canopy organisation below - call carea_allom(nc_d%dbh, nc_d%n, currentSite%spread,& - nc_d%pft, nc_d%crowndamage, nc_d%c_area) + call carea_allom(ndcohort%dbh, ndcohort%n, csite%spread,& + ipft, ndcohort%crowndamage, ndcohort%c_area) call GetCrownReduction(cd, crown_loss_frac) do_element: do el = 1, num_elements - litt => currentPatch%litter(el) - flux_diags => currentSite%flux_diags(el) + litt => cpatch%litter(el) + flux_diags => csite%flux_diags(el) ! Reduce the mass of the newly damaged cohort ! Fine-roots are not damaged as of yet @@ -257,11 +290,11 @@ subroutine GenerateDamageAndLitterFluxes( currentSite, currentPatch, bc_in ) ! branches is damaged/removed branch_loss_frac = crown_loss_frac * branch_frac * agb_frac - leaf_loss = nc_d%prt%GetState(leaf_organ,element_id(el))*crown_loss_frac - repro_loss = nc_d%prt%GetState(repro_organ,element_id(el))*crown_loss_frac - sapw_loss = nc_d%prt%GetState(sapw_organ,element_id(el))*branch_loss_frac - store_loss = nc_d%prt%GetState(store_organ,element_id(el))*branch_loss_frac - struct_loss = nc_d%prt%GetState(struct_organ,element_id(el))*branch_loss_frac + leaf_loss = ndcohort%prt%GetState(leaf_organ,element_id(el))*crown_loss_frac + repro_loss = ndcohort%prt%GetState(repro_organ,element_id(el))*crown_loss_frac + sapw_loss = ndcohort%prt%GetState(sapw_organ,element_id(el))*branch_loss_frac + store_loss = ndcohort%prt%GetState(store_organ,element_id(el))*branch_loss_frac + struct_loss = ndcohort%prt%GetState(struct_organ,element_id(el))*branch_loss_frac ! ------------------------------------------------------ ! Transfer the biomass from the cohort's @@ -272,33 +305,33 @@ subroutine GenerateDamageAndLitterFluxes( currentSite, currentPatch, bc_in ) dcmpy_frac = GetDecompyFrac(pft,leaf_organ,dcmpy) litt%leaf_fines_in(dcmpy) = litt%leaf_fines_in(dcmpy) + & (store_loss+leaf_loss+repro_loss) * & - nc_d%n * dcmpy_frac / currentPatch%area + ndcohort%n * dcmpy_frac / cpatch%area end do flux_diags%leaf_litter_input(pft) = & flux_diags%leaf_litter_input(pft) + & - (store_loss+leaf_loss+repro_loss) * nc_d%n + (store_loss+leaf_loss+repro_loss) * ndcohort%n do c = 1,ncwd litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + & (sapw_loss + struct_loss) * & - SF_val_CWD_frac(c) * nc_d%n / & - currentPatch%area + SF_val_CWD_frac(c) * ndcohort%n / & + cpatch%area flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & - (struct_m_turnover + sapw_m_turnover) * & - SF_val_CWD_frac(c) * nc_d%n + (struct_loss + sapw_loss) * & + SF_val_CWD_frac(c) * ndcohort%n end do end do do_element ! Applying the damage to the cohort, does not need to happen ! in the element loop, it will loop inside that call - call PRTDamageLosses(nc_d%prt, leaf_organ, crown_loss_frac) - call PRTDamageLosses(nc_d%prt, repro_organ, crown_loss_frac) - call PRTDamageLosses(nc_d%prt, sapw_organ, branch_loss_frac) - call PRTDamageLosses(nc_d%prt, store_organ, branch_loss_frac) - call PRTDamageLosses(nc_d%prt, struct_organ, branch_loss_frac) + call PRTDamageLosses(ndcohort%prt, leaf_organ, crown_loss_frac) + call PRTDamageLosses(ndcohort%prt, repro_organ, crown_loss_frac) + call PRTDamageLosses(ndcohort%prt, sapw_organ, branch_loss_frac) + call PRTDamageLosses(ndcohort%prt, store_organ, branch_loss_frac) + call PRTDamageLosses(ndcohort%prt, struct_organ, branch_loss_frac) !----------- Insert new cohort into the linked list @@ -307,22 +340,22 @@ subroutine GenerateDamageAndLitterFluxes( currentSite, currentPatch, bc_in ) ! as the loop traverses ! --------------------------------------------------------------! - nc_d%shorter => currentCohort - if(associated(currentCohort%taller))then - nc_d%taller => currentCohort%taller - currentCohort%taller%shorter => nc_d + ndcohort%shorter => ccohort + if(associated(ccohort%taller))then + ndcohort%taller => ccohort%taller + ccohort%taller%shorter => ndcohort else - cpatch%tallest => nc_d - nc_d%taller => null() + cpatch%tallest => ndcohort + ndcohort%taller => null() endif - currentCohort%taller => nc_d - + ccohort%taller => ndcohort end if if_numtrees end do do_dclass - - currentCohort => currentCohort%shorter + + end associate + ccohort => ccohort%shorter enddo return @@ -1958,7 +1991,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) ! !USES: use FatesInterfaceTypesMod, only : hlm_use_ed_prescribed_phys use FatesLitterMod , only : ncwd - use SFParamsMod , only : SF_val_CWD_frac + ! ! !ARGUMENTS type(ed_site_type), intent(inout), target :: currentSite @@ -2289,7 +2322,6 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) ! and turnover in dying trees. ! ! !USES: - use SFParamsMod , only : SF_val_CWD_frac ! ! !ARGUMENTS From 6e00ae0178f81b563aa6c287b069bab6f8278951 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 12 Jul 2022 14:30:00 -0400 Subject: [PATCH 286/852] Remove endrun --- biogeochem/EDPatchDynamicsMod.F90 | 5 ----- 1 file changed, 5 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index d837ed737a..a25045a58c 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -2330,11 +2330,6 @@ subroutine fuse_patches( csite, bc_in ) tpp => currentSite%youngest_patch tpp_loop: do while(associated(tpp)) - if(.not.associated(currentPatch))then - write(fates_log(),*) 'FATES fuse_patches(): currentPatch is not associated?' - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - both_associated_if: if(associated(tpp).and.associated(currentPatch))then !--------------------------------------------------------------------! ! only fuse patches whose anthropogenic disturbance category matches ! From 85f7e55d2e73c720e6c601fdf80ea624305c8b45 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 12 Jul 2022 13:00:30 -0600 Subject: [PATCH 287/852] Added module use statements to damage and litter generation module --- biogeochem/EDPhysiologyMod.F90 | 24 ++++++++++++++++-------- main/EDMainMod.F90 | 1 + 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 7fff02491a..f1268e5e7a 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -31,6 +31,8 @@ module EDPhysiologyMod use EDCohortDynamicsMod , only : zero_cohort use EDCohortDynamicsMod , only : create_cohort, sort_cohorts use EDCohortDynamicsMod , only : InitPRTObject + use EDCohortDynamicsMod , only : InitPRTBoundaryConditions + use EDCohortDynamicsMod , only : copy_cohort use FatesAllometryMod , only : tree_lai use FatesAllometryMod , only : tree_sai use FatesAllometryMod , only : leafc_from_treelai @@ -108,9 +110,15 @@ module EDPhysiologyMod use PRTLossFluxesMod, only : PRTPhenologyFlush use PRTLossFluxesMod, only : PRTDeciduousTurnover use PRTLossFluxesMod, only : PRTReproRelease + use PRTLossFluxesMod, only : PRTDamageLosses use PRTGenericMod, only : StorageNutrientTarget use DamageMainMod, only : damage_time + use DamageMainMod, only : GetCrownReduction + use DamageMainMod, only : GetDamageFrac use SFParamsMod, only : SF_val_CWD_frac + use FatesParameterDerivedMod, only : param_derived + use FatesPlantHydraulicsMod, only : InitHydrCohort + implicit none private @@ -290,11 +298,11 @@ subroutine GenerateDamageAndLitterFluxes( csite, cpatch, bc_in ) ! branches is damaged/removed branch_loss_frac = crown_loss_frac * branch_frac * agb_frac - leaf_loss = ndcohort%prt%GetState(leaf_organ,element_id(el))*crown_loss_frac - repro_loss = ndcohort%prt%GetState(repro_organ,element_id(el))*crown_loss_frac - sapw_loss = ndcohort%prt%GetState(sapw_organ,element_id(el))*branch_loss_frac - store_loss = ndcohort%prt%GetState(store_organ,element_id(el))*branch_loss_frac - struct_loss = ndcohort%prt%GetState(struct_organ,element_id(el))*branch_loss_frac + leaf_loss = ndcohort%prt%GetState(leaf_organ,element_list(el))*crown_loss_frac + repro_loss = ndcohort%prt%GetState(repro_organ,element_list(el))*crown_loss_frac + sapw_loss = ndcohort%prt%GetState(sapw_organ,element_list(el))*branch_loss_frac + store_loss = ndcohort%prt%GetState(store_organ,element_list(el))*branch_loss_frac + struct_loss = ndcohort%prt%GetState(struct_organ,element_list(el))*branch_loss_frac ! ------------------------------------------------------ ! Transfer the biomass from the cohort's @@ -302,14 +310,14 @@ subroutine GenerateDamageAndLitterFluxes( csite, cpatch, bc_in ) ! ------------------------------------------------------ do dcmpy=1,ndcmpy - dcmpy_frac = GetDecompyFrac(pft,leaf_organ,dcmpy) + dcmpy_frac = GetDecompyFrac(ipft,leaf_organ,dcmpy) litt%leaf_fines_in(dcmpy) = litt%leaf_fines_in(dcmpy) + & (store_loss+leaf_loss+repro_loss) * & ndcohort%n * dcmpy_frac / cpatch%area end do - flux_diags%leaf_litter_input(pft) = & - flux_diags%leaf_litter_input(pft) + & + flux_diags%leaf_litter_input(ipft) = & + flux_diags%leaf_litter_input(ipft) + & (store_loss+leaf_loss+repro_loss) * ndcohort%n do c = 1,ncwd diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 04f71fc615..33bbaff3d4 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -50,6 +50,7 @@ module EDMainMod use EDPhysiologyMod , only : ZeroLitterFluxes use EDPhysiologyMod , only : PreDisturbanceLitterFluxes use EDPhysiologyMod , only : PreDisturbanceIntegrateLitter + use EDPhysiologyMod , only : GenerateDamageAndLitterFluxes use FatesSoilBGCFluxMod , only : FluxIntoLitterPools use EDCohortDynamicsMod , only : UpdateCohortBioPhysRates use FatesSoilBGCFluxMod , only : PrepNutrientAquisitionBCs From 16526de8420a5b2cda1c305a36ef0dd75a2d9c66 Mon Sep 17 00:00:00 2001 From: JunyanDing <43835195+JunyanDing@users.noreply.github.com> Date: Tue, 12 Jul 2022 14:40:56 -0700 Subject: [PATCH 288/852] fix small bug --- biogeophys/FatesPlantHydraulicsMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index cc26852bd0..c626067d39 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -943,7 +943,7 @@ subroutine UpdatePlantHydrLenVol(ccohort,site_hydr) if (prt_params%woody(ft)==1) then ccohort_hydr%v_ag(n_hypool_leaf+1:n_hypool_ag) = v_sapwood / n_hypool_stem ! original code else - v_leaf_donate(1:n_hypool_leaf) = ccohort_hydr%v_ag(1:n_hypool_leaf) / l2sap_vol_donate_frac + v_leaf_donate(1:n_hypool_leaf) = ccohort_hydr%v_ag(1:n_hypool_leaf) * l2sap_vol_donate_frac ccohort_hydr%v_ag(1:n_hypool_leaf) = ccohort_hydr%v_ag(1:n_hypool_leaf) - v_leaf_donate(1:n_hypool_leaf) ccohort_hydr%v_ag(n_hypool_leaf+1:n_hypool_ag) = (v_sapwood + sum(v_leaf_donate(1:n_hypool_leaf))) / n_hypool_stem end if From 78435acc986f9a576b5315ae0057477fe7e85853 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 14 Jul 2022 16:16:26 -0700 Subject: [PATCH 289/852] condensing formula to avoid numerical instability --- biogeophys/FatesPlantHydraulicsMod.F90 | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index b1606e3450..31a50b59b8 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -4629,8 +4629,7 @@ function xylemtaper(pexp, dz) result(chi_tapnotap) real(r8) , intent(in) :: dz ! hydraulic distance from petiole to node of interest[m] ! ! !LOCAL VARIABLES: - real(r8) :: qexp ! total conductance exponent (as in Fig. 2b of Savage et al. (2010) - real(r8) :: qexp_notap ! same as qexp, but without xylem taper; i.e., pexp = 0 + real(r8) :: qexp ! total conductance exponent (as in Fig. 2b of Savage et al. (2010) minus a0 term real(r8) :: lN=0.005_r8 ! petiole length[m] real(r8) :: mu=1.0E-03_r8 ! viscosity[kg m-1 s-1] real(r8) :: rintN=0.00001_r8 ! internal conduit diameter in petiole[m] @@ -4661,16 +4660,15 @@ function xylemtaper(pexp, dz) result(chi_tapnotap) a2 = 1.096488_r8 a1 = 1.844792_r8 a0 = 1.320732_r8 - qexp = a5*pexp**5 + a4*pexp**4 + a3*pexp**3 + a2*pexp**2 + a1*pexp + a0 - qexp_notap = a0 + + qexp = a5*pexp**5 + a4*pexp**4 + a3*pexp**3 + a2*pexp**2 + a1*pexp num = 3._r8*log(1._r8 - dz/lN * (1._r8-n_ext**(1._r8/3._r8))) den = log(n_ext) big_N = num/den - 1._r8 r0rN = n_ext**(big_N/2._r8) - ktap = kN * (r0rN**qexp) - knotap = kN * (r0rN**qexp_notap) - chi_tapnotap = ktap / knotap + + chi_tapnotap = r0rN**qexp return From 928738f76df2bff1da284dc9f3b1ba8e2f9413da Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 14 Jul 2022 16:29:29 -0700 Subject: [PATCH 290/852] further simplification --- biogeophys/FatesPlantHydraulicsMod.F90 | 8 -------- 1 file changed, 8 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 31a50b59b8..2225022e9f 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -4631,15 +4631,9 @@ function xylemtaper(pexp, dz) result(chi_tapnotap) ! !LOCAL VARIABLES: real(r8) :: qexp ! total conductance exponent (as in Fig. 2b of Savage et al. (2010) minus a0 term real(r8) :: lN=0.005_r8 ! petiole length[m] - real(r8) :: mu=1.0E-03_r8 ! viscosity[kg m-1 s-1] - real(r8) :: rintN=0.00001_r8 ! internal conduit diameter in petiole[m] - real(r8) :: NsegintN=200 ! number of conduits in a single terminal twig[-] - real(r8) :: kN ! conductance for laminar flow through all conduits in a terminal twig, according to Hagen-Poiseuille[kg Pa-1 s-1] real(r8) :: n_ext=2._r8 ! number of daughter branches per parent branch, assumed constant throughout tree (self-similarity) [-] real(r8) :: big_n ! number of branching levels (allowed here to take on non-integer values): increases with tree size [-] real(r8) :: r0rN ! ratio of stem radius to terminal twig radius; r.ext0/r.extN (x-axis of Savage et al. (2010) Fig 2a)[-] - real(r8) :: ktap ! hydraulic conductance along the pathway,accounting for xylem taper [kg s-1 MPa-1] - real(r8) :: knotap ! hydraulic conductance along the pathway,not accounting for xylem taper [kg s-1 MPa-1] real(r8) :: num ! temporary real(r8) :: den ! temporary real(r8) :: a5,a4,a3,a2,a1,a0 ! coefficients of 5th-order polynomial fit to Savage et al. Fig. 2b (qexp vs. pexp) @@ -4652,8 +4646,6 @@ function xylemtaper(pexp, dz) result(chi_tapnotap) ! !------------------------------------------------------------------------ - kN = NsegintN*pi*rintN**(4.0_r8)/(8.0_r8*mu*lN) - a5 = -3.555547_r8 a4 = 9.760275_r8 a3 = -8.468005_r8 From 2836b2ae0e576fd7f428e3e609c3b1a787b9a839 Mon Sep 17 00:00:00 2001 From: ckoven Date: Mon, 18 Jul 2022 17:59:09 -0600 Subject: [PATCH 291/852] encapsulated tree/grass logic into function and use to re-add non-disturbance mortality --- biogeochem/EDMortalityFunctionsMod.F90 | 47 +++++++++++++++++++++++--- biogeochem/EDPatchDynamicsMod.F90 | 3 +- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index 605c377508..1368394f22 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -36,6 +36,7 @@ module EDMortalityFunctionsMod public :: mortality_rates public :: Mortality_Derivative + public :: ExemptTreefallDist ! ============================================================================ @@ -275,13 +276,21 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_pr * currentCohort%n else - - ! Mortality from logging in the canopy is ONLY disturbance generating, don't ! update number densities via non-disturbance inducing death - currentCohort%dndt= -(1.0_r8-fates_mortality_disturbance_fraction) & - * (cmort+hmort+bmort+frmort+smort+asmort) * & - currentCohort%n + + ! for plants whose death is not considered disturbance (i.e. grasses), + ! need to include all of their mortality here rather than part of it here + ! and part in disturbance routine. + + if ( .not. ExemptTreefallDist(currentCohort)) then + currentCohort%dndt= -(1.0_r8-fates_mortality_disturbance_fraction) & + * (cmort+hmort+bmort+frmort+smort+asmort) * & + currentCohort%n + else + currentCohort%dndt= - (cmort+hmort+bmort+frmort+smort+asmort) * & + currentCohort%n + endif endif @@ -289,4 +298,32 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_pr end subroutine Mortality_Derivative + ! ============================================================================ + + function ExemptTreefallDist(ccohort) result(is_exempt) + + use PRTParametersMod , only : prt_params + + ! ============================================================================ + ! Determine whether or not to consider some fraction of a cohort's crown + ! area as disturbed patch area when individuals of that cohort die. + ! ============================================================================ + + ! Arguments + type(ed_cohort_type),intent(in), target :: ccohort + + logical :: is_exempt ! if true, then treat all mortality from this cohort as non-disturbance-generating + + !! current logic is only to exempt non-woody plants + + if ( prt_params%woody(ccohort%pft) == ifalse ) then + is_exempt = .true. + else + is_exempt = .false. + endif + + return + + end function ExemptTreefallDist + end module EDMortalityFunctionsMod diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 5319001d3f..8efbee9a4d 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -157,6 +157,7 @@ subroutine disturbance_rates( site_in, bc_in) ! !USES: use EDMortalityFunctionsMod , only : mortality_rates + use EDMortalityFunctionsMod , only : ExemptTreefallDist ! loging flux use EDLoggingMortalityMod , only : LoggingMortality_frac @@ -285,7 +286,7 @@ subroutine disturbance_rates( site_in, bc_in) if(currentCohort%canopy_layer == 1)then ! Treefall Disturbance Rate. Only count this for trees, not grasses - if ( int(prt_params%woody(currentCohort%pft)) == itrue ) then + if ( .not. ExemptTreefallDist(currentCohort) ) then currentPatch%disturbance_rates(dtype_ifall) = currentPatch%disturbance_rates(dtype_ifall) + & fates_mortality_disturbance_fraction * & min(1.0_r8,currentCohort%dmort)*hlm_freq_day*currentCohort%c_area/currentPatch%area From dfe638b5744c604165178cdc1c3a3e39125e0bbc Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Tue, 19 Jul 2022 11:22:06 -0700 Subject: [PATCH 292/852] Update biogeochem/EDMortalityFunctionsMod.F90 Co-authored-by: Gregory Lemieux <7565064+glemieux@users.noreply.github.com> --- biogeochem/EDMortalityFunctionsMod.F90 | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index 1368394f22..22e34e1abc 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -283,13 +283,9 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_pr ! need to include all of their mortality here rather than part of it here ! and part in disturbance routine. + currentCohort%dndt= -(cmort+hmort+bmort+frmort+smort+asmort) * currentCohort%n if ( .not. ExemptTreefallDist(currentCohort)) then - currentCohort%dndt= -(1.0_r8-fates_mortality_disturbance_fraction) & - * (cmort+hmort+bmort+frmort+smort+asmort) * & - currentCohort%n - else - currentCohort%dndt= - (cmort+hmort+bmort+frmort+smort+asmort) * & - currentCohort%n + currentCohort%dndt = (1.0_r8-fates_mortality_disturbance_fraction) * currentCohort%dndt endif endif From 4772c5235217bee346df88a22dadb09a1e216413 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 21 Jul 2022 14:45:33 -0700 Subject: [PATCH 293/852] making great circle distance public --- main/FatesUtilsMod.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/main/FatesUtilsMod.F90 b/main/FatesUtilsMod.F90 index 13176ddec8..6dfd2dbcc0 100644 --- a/main/FatesUtilsMod.F90 +++ b/main/FatesUtilsMod.F90 @@ -12,6 +12,7 @@ module FatesUtilsMod ! Make public necessary subroutines and functions public :: check_hlm_list public :: check_var_real + public :: GreatCircleDist contains From 97ad792be8ee2b984fd0a9a90fb09b15b7f0cab2 Mon Sep 17 00:00:00 2001 From: adamhb Date: Thu, 21 Jul 2022 15:00:34 -0700 Subject: [PATCH 294/852] fixed retrieve spelling --- main/EDParamsMod.F90 | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 1f69977e34..fb07c4a87a 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -467,7 +467,8 @@ subroutine FatesRegisterParams(fates_params) dimension_names=dim_names_scalar) call fates_params%RegisterParameter(name=ED_name_regeneration_model, dimension_shape=dimension_shape_scalar, & - + dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=stomatal_assim_name, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -590,16 +591,16 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetrieveParameter(name=ED_name_photo_temp_acclim_timescale, & data=photo_temp_acclim_timescale) - call fates_params%RetreiveParameter(name=ED_name_sdlng_emerg_h2o_timescale, & + call fates_params%RetrieveParameter(name=ED_name_sdlng_emerg_h2o_timescale, & data=sdlng_emerg_h2o_timescale) - call fates_params%RetreiveParameter(name=ED_name_sdlng_mort_par_timescale, & + call fates_params%RetrieveParameter(name=ED_name_sdlng_mort_par_timescale, & data=sdlng_mort_par_timescale) - call fates_params%RetreiveParameter(name=ED_name_sdlng_mdd_timescale, & + call fates_params%RetrieveParameter(name=ED_name_sdlng_mdd_timescale, & data=sdlng_mdd_timescale) - call fates_params%RetreiveParameter(name=ED_name_sdlng2sap_par_timescale, & + call fates_params%RetrieveParameter(name=ED_name_sdlng2sap_par_timescale, & data=sdlng2sap_par_timescale) call fates_params%RetrieveParameter(name=name_photo_tempsens_model, & From 21a7927237d47f6244244727068c74c75365dc63 Mon Sep 17 00:00:00 2001 From: adamhb Date: Thu, 21 Jul 2022 20:43:56 -0700 Subject: [PATCH 295/852] fixed retrieve spelling in params mod --- main/EDParamsMod.F90 | 2 +- main/EDPftvarcon.F90 | 32 ++++++++++++++++---------------- parteh/PRTParamsFATESMod.F90 | 4 ++-- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index fb07c4a87a..2e56062d91 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -681,7 +681,7 @@ subroutine FatesReceiveParams(fates_params) data=tmpreal) stomatal_model = nint(tmpreal) - call fates_params%RetreiveParameter(name=ED_name_regeneration_model, & + call fates_params%RetrieveParameter(name=ED_name_regeneration_model, & data=tmpreal) regeneration_model = nint(tmpreal) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 04df78b1ea..4b5cc5ac57 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -959,67 +959,67 @@ subroutine Receive_PFT(this, fates_params) data=this%germination_rate) name = 'fates_repro_frac_seed' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=this%repro_frac_seed) name = 'fates_a_emerg' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=this%a_emerg) name = 'fates_b_emerg' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=this%b_emerg) name = 'fates_par_crit_germ' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=this%par_crit_germ) name = 'fates_seedling_psi_emerg' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=this%seedling_psi_emerg) name = 'fates_seedling_psi_crit' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=this%seedling_psi_crit) name = 'fates_seedling_light_rec_a' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=this%seedling_light_rec_a) name = 'fates_seedling_light_rec_b' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=this%seedling_light_rec_b) name = 'fates_seedling_mdd_crit' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=this%seedling_mdd_crit) name = 'fates_seedling_h2o_mort_a' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=this%seedling_h2o_mort_a) name = 'fates_seedling_h2o_mort_b' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=this%seedling_h2o_mort_b) name = 'fates_seedling_h2o_mort_c' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=this%seedling_h2o_mort_c) name = 'fates_seedling_root_depth' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=this%seedling_root_depth) name = 'fates_seedling_light_mort_a' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=this%seedling_light_mort_a) name = 'fates_seedling_light_mort_b' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=this%seedling_light_mort_b) name = 'fates_background_seedling_mort' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=this%background_seedling_mort) name = 'fates_frag_seed_decay_rate' diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index 7591006b73..473b833399 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -487,11 +487,11 @@ subroutine PRTReceivePFT(fates_params) !ahb added the code below !-------------------------------------------------------- name = 'fates_repro_alloc_a' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%repro_alloc_a) name = 'fates_repro_alloc_b' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%repro_alloc_b) !--------------------------------------------------------- From 605062a32871c57f8e65f2bdee57d1e7f4cc1772 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 28 Jul 2022 18:00:56 -0400 Subject: [PATCH 296/852] Simple optimizations to math in hifrq history --- main/FatesConstantsMod.F90 | 3 ++ main/FatesHistoryInterfaceMod.F90 | 64 ++++++++++++++++--------------- 2 files changed, 36 insertions(+), 31 deletions(-) diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index 726100a37b..0ec836fe0f 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -132,6 +132,9 @@ module FatesConstantsMod ! Conversion factor: micromoles per mole real(fates_r8), parameter, public :: umol_per_mol = 1.0E6_fates_r8 + ! Conversion factor: moles per micromole + real(fates_r8), parameter, public :: mol_per_umol = 1.0E-6_fates_r8 + ! Conversion factor: umols per kilomole real(fates_r8), parameter, public :: umol_per_kmol = 1.0E9_fates_r8 diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 3ef7fd14df..acfccf0d65 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -68,7 +68,7 @@ module FatesHistoryInterfaceMod use FatesConstantsMod , only : m2_per_ha use FatesConstantsMod , only : m_per_cm use FatesConstantsMod , only : sec_per_min - use FatesConstantsMod , only : umol_per_mol + use FatesConstantsMod , only : umol_per_mol,mol_per_umol use FatesConstantsMod , only : pa_per_mpa use FatesLitterMod , only : litter_type use FatesConstantsMod , only : secondaryforest @@ -3633,8 +3633,8 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) io_si = sites(s)%h_gid - hio_nep_si(io_si) = -bc_in(s)%tot_het_resp / g_per_kg ! (kgC/m2/s) - hio_hr_si(io_si) = bc_in(s)%tot_het_resp / g_per_kg + hio_nep_si(io_si) = -bc_in(s)%tot_het_resp * kg_per_g + hio_hr_si(io_si) = bc_in(s)%tot_het_resp * kg_per_g ipa = 0 @@ -3660,17 +3660,17 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) ! Canopy resitance terms hio_c_stomata_si_age(io_si,cpatch%age_class) = & hio_c_stomata_si_age(io_si,cpatch%age_class) + & - cpatch%c_stomata * cpatch%total_canopy_area / umol_per_mol + cpatch%c_stomata * cpatch%total_canopy_area * mol_per_umol hio_c_lblayer_si_age(io_si,cpatch%age_class) = & hio_c_lblayer_si_age(io_si,cpatch%age_class) + & - cpatch%c_lblayer * cpatch%total_canopy_area / umol_per_mol + cpatch%c_lblayer * cpatch%total_canopy_area * mol_per_umol hio_c_stomata_si(io_si) = hio_c_stomata_si(io_si) + & - cpatch%c_stomata * cpatch%total_canopy_area / umol_per_mol + cpatch%c_stomata * cpatch%total_canopy_area * mol_per_umol hio_c_lblayer_si(io_si) = hio_c_lblayer_si(io_si) + & - cpatch%c_lblayer * cpatch%total_canopy_area / umol_per_mol + cpatch%c_lblayer * cpatch%total_canopy_area * mol_per_umol hio_rad_error_si(io_si) = hio_rad_error_si(io_si) + & cpatch%radiation_error * cpatch%area * AREA_INV @@ -3727,15 +3727,15 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) ! Total AR (kgC/m2/s) = (kgC/plant/step) / (s/step) * (plant/m2) hio_ar_si_scpf(io_si,scpf) = hio_ar_si_scpf(io_si,scpf) + & - (ccohort%resp_tstep/dt_tstep) * n_perm2 + (ccohort%resp_tstep*per_dt_tstep) * n_perm2 ! Growth AR (kgC/m2/s) hio_ar_grow_si_scpf(io_si,scpf) = hio_ar_grow_si_scpf(io_si,scpf) + & - (resp_g/dt_tstep) * n_perm2 + (resp_g*per_dt_tstep) * n_perm2 ! Maint AR (kgC/m2/s) hio_ar_maint_si_scpf(io_si,scpf) = hio_ar_maint_si_scpf(io_si,scpf) + & - (ccohort%resp_m/dt_tstep) * n_perm2 + (ccohort%resp_m*per_dt_tstep) * n_perm2 ! Maintenance AR partition variables are stored as rates (kgC/plant/s) ! (kgC/m2/s) = (kgC/plant/s) * (plant/m2) @@ -3773,18 +3773,18 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) ! ! size-resolved respiration fluxes are in kg C / m2 / s hio_rdark_canopy_si_scls(io_si,scls) = hio_rdark_canopy_si_scls(io_si,scls) + & - ccohort%rdark * ccohort%n / m2_per_ha + ccohort%rdark * ccohort%n * ha_per_m2 hio_livestem_mr_canopy_si_scls(io_si,scls) = hio_livestem_mr_canopy_si_scls(io_si,scls) + & - ccohort%livestem_mr * ccohort%n / m2_per_ha + ccohort%livestem_mr * ccohort%n * ha_per_m2 hio_livecroot_mr_canopy_si_scls(io_si,scls) = hio_livecroot_mr_canopy_si_scls(io_si,scls) + & - ccohort%livecroot_mr * ccohort%n / m2_per_ha + ccohort%livecroot_mr * ccohort%n * ha_per_m2 hio_froot_mr_canopy_si_scls(io_si,scls) = hio_froot_mr_canopy_si_scls(io_si,scls) + & - ccohort%froot_mr * ccohort%n / m2_per_ha + ccohort%froot_mr * ccohort%n * ha_per_m2 hio_resp_g_canopy_si_scls(io_si,scls) = hio_resp_g_canopy_si_scls(io_si,scls) + & - resp_g * ccohort%n * per_dt_tstep / m2_per_ha + resp_g * ccohort%n * per_dt_tstep * ha_per_m2 hio_resp_m_canopy_si_scls(io_si,scls) = hio_resp_m_canopy_si_scls(io_si,scls) + & - ccohort%resp_m * ccohort%n * per_dt_tstep / m2_per_ha + ccohort%resp_m * ccohort%n * per_dt_tstep * ha_per_m2 else ! ! bulk fluxes are in gC / m2 / s @@ -3796,17 +3796,17 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) ! ! size-resolved respiration fluxes are in kg C / m2 / s hio_rdark_understory_si_scls(io_si,scls) = hio_rdark_understory_si_scls(io_si,scls) + & - ccohort%rdark * ccohort%n / m2_per_ha + ccohort%rdark * ccohort%n * ha_per_m2 hio_livestem_mr_understory_si_scls(io_si,scls) = hio_livestem_mr_understory_si_scls(io_si,scls) + & - ccohort%livestem_mr * ccohort%n / m2_per_ha + ccohort%livestem_mr * ccohort%n * ha_per_m2 hio_livecroot_mr_understory_si_scls(io_si,scls) = hio_livecroot_mr_understory_si_scls(io_si,scls) + & - ccohort%livecroot_mr * ccohort%n / m2_per_ha + ccohort%livecroot_mr * ccohort%n * ha_per_m2 hio_froot_mr_understory_si_scls(io_si,scls) = hio_froot_mr_understory_si_scls(io_si,scls) + & - ccohort%froot_mr * ccohort%n / m2_per_ha + ccohort%froot_mr * ccohort%n * ha_per_m2 hio_resp_g_understory_si_scls(io_si,scls) = hio_resp_g_understory_si_scls(io_si,scls) + & - resp_g * ccohort%n * per_dt_tstep / m2_per_ha + resp_g * ccohort%n * per_dt_tstep * ha_per_m2 hio_resp_m_understory_si_scls(io_si,scls) = hio_resp_m_understory_si_scls(io_si,scls) + & - ccohort%resp_m * ccohort%n * per_dt_tstep / m2_per_ha + ccohort%resp_m * ccohort%n * per_dt_tstep * ha_per_m2 endif end associate endif @@ -3816,7 +3816,7 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) do ileaf=1,ccohort%nv cnlf_indx = ileaf + (ican-1) * nlevleaf hio_ts_net_uptake_si_cnlf(io_si, cnlf_indx) = hio_ts_net_uptake_si_cnlf(io_si, cnlf_indx) + & - ccohort%ts_net_uptake(ileaf) * per_dt_tstep * ccohort%c_area / AREA + ccohort%ts_net_uptake(ileaf) * per_dt_tstep * ccohort%c_area * area_inv end do ccohort => ccohort%taller @@ -4017,7 +4017,7 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) type(ed_cohort_type),pointer :: ccohort type(ed_cohort_hydr_type), pointer :: ccohort_hydr type(ed_site_hydr_type), pointer :: site_hydr - + real(r8) :: per_dt_tstep ! Time step in frequency units (/s) real(r8), parameter :: daysecs = 86400.0_r8 ! What modeler doesn't recognize 86400? real(r8), parameter :: yeardays = 365.0_r8 ! Should this be 365.25? @@ -4070,6 +4070,8 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) ! Flush the relevant history variables call this%flush_hvars(nc,upfreq_in=4) + per_dt_tstep = 1._r8 / dt_tstep + if(print_iterations) then do iscpf = 1,iterh2_nhist iterh2_histx(iscpf) = iterh2_dx*real(iscpf-1,r8) @@ -4181,11 +4183,11 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) do ipft = 1, numpft do iscls = 1,nlevsclass iscpf = (ipft-1)*nlevsclass + iscls - hio_sapflow_scpf(io_si,iscpf) = site_hydr%sapflow_scpf(iscls, ipft) / m2_per_ha - hio_rootuptake0_scpf(io_si,iscpf) = site_hydr%rootuptake0_scpf(iscls,ipft) / m2_per_ha - hio_rootuptake10_scpf(io_si,iscpf) = site_hydr%rootuptake10_scpf(iscls,ipft) / m2_per_ha - hio_rootuptake50_scpf(io_si,iscpf) = site_hydr%rootuptake50_scpf(iscls,ipft) / m2_per_ha - hio_rootuptake100_scpf(io_si,iscpf) = site_hydr%rootuptake100_scpf(iscls,ipft) / m2_per_ha + hio_sapflow_scpf(io_si,iscpf) = site_hydr%sapflow_scpf(iscls, ipft) * ha_per_m2 + hio_rootuptake0_scpf(io_si,iscpf) = site_hydr%rootuptake0_scpf(iscls,ipft) * ha_per_m2 + hio_rootuptake10_scpf(io_si,iscpf) = site_hydr%rootuptake10_scpf(iscls,ipft) * ha_per_m2 + hio_rootuptake50_scpf(io_si,iscpf) = site_hydr%rootuptake50_scpf(iscls,ipft) * ha_per_m2 + hio_rootuptake100_scpf(io_si,iscpf) = site_hydr%rootuptake100_scpf(iscls,ipft) * ha_per_m2 hio_iterh1_scpf(io_si,iscpf) = 0._r8 hio_iterh2_scpf(io_si,iscpf) = 0._r8 end do @@ -4206,7 +4208,7 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) iscpf = ccohort%size_by_pft_class ! scale up cohort fluxes to their sites - number_fraction_rate = (ccohort%n / nplant_scpf(iscpf))/dt_tstep + number_fraction_rate = (ccohort%n / nplant_scpf(iscpf)) * per_dt_tstep ! scale cohorts to mean quantity number_fraction = (ccohort%n / nplant_scpf(iscpf)) @@ -4280,7 +4282,7 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) if(hlm_use_ed_st3.eq.ifalse) then do iscpf=1,nlevsclass*numpft - if ((abs(hio_nplant_si_scpf(io_si, iscpf)-(nplant_scpf(iscpf)/m2_per_ha)) > 1.0E-8_r8) .and. & + if ((abs(hio_nplant_si_scpf(io_si, iscpf)-(nplant_scpf(iscpf)*ha_per_m2)) > 1.0E-8_r8) .and. & (hio_nplant_si_scpf(io_si, iscpf) .ne. hlm_hio_ignore_val)) then write(fates_log(),*) 'numpft:',numpft write(fates_log(),*) 'nlevsclass:',nlevsclass From d0127a8c8d564d56ae87052e86605fa31d40659d Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 28 Jul 2022 18:06:19 -0400 Subject: [PATCH 297/852] added use for kg_per_g --- main/FatesHistoryInterfaceMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index acfccf0d65..7ab5c9c0ca 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -57,7 +57,7 @@ module FatesHistoryInterfaceMod ! CIME Globals use shr_log_mod , only : errMsg => shr_log_errMsg use shr_infnan_mod , only : isnan => shr_infnan_isnan - use FatesConstantsMod , only : g_per_kg + use FatesConstantsMod , only : g_per_kg,kg_per_g use FatesConstantsMod , only : ha_per_m2 use FatesConstantsMod , only : days_per_sec use FatesConstantsMod , only : sec_per_day From ad53cdea7e19c3e2eb9dacefecba29c96406c371 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 28 Jul 2022 22:03:16 -0400 Subject: [PATCH 298/852] Removed laimemory, sapwmemory and structmemory --- biogeochem/EDCohortDynamicsMod.F90 | 28 +----- biogeochem/EDPhysiologyMod.F90 | 138 +++++++++++------------------ main/EDInitMod.F90 | 12 +-- main/EDPftvarcon.F90 | 9 ++ main/EDTypesMod.F90 | 6 -- main/FatesInventoryInitMod.F90 | 21 ++--- main/FatesRestartInterfaceMod.F90 | 31 ------- 7 files changed, 67 insertions(+), 178 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 4948f68129..a7d203da5d 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -147,8 +147,7 @@ module EDCohortDynamicsMod subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & - prt, leafmemory, sapwmemory, structmemory, & - status, recruitstatus,ctrim, carea, clayer, spread, bc_in) + prt, status, recruitstatus,ctrim, carea, clayer, spread, bc_in) ! ! !DESCRIPTION: ! create new cohort @@ -181,12 +180,6 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & real(r8), intent(in) :: dbh ! dbh: cm class(prt_vartypes),target :: prt ! The allocated PARTEH ! object - real(r8), intent(in) :: leafmemory ! target leaf biomass- set from - ! previous year: kGC per indiv - real(r8), intent(in) :: sapwmemory ! target sapwood biomass- set from - ! previous year: kGC per indiv - real(r8), intent(in) :: structmemory ! target structural biomass- set from - ! previous year: kGC per indiv real(r8), intent(in) :: ctrim ! What is the fraction of the maximum ! leaf biomass that we are targeting? real(r8), intent(in) :: spread ! The community assembly effects how @@ -237,9 +230,6 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & new_cohort%canopy_trim = ctrim new_cohort%canopy_layer = clayer new_cohort%canopy_layer_yesterday = real(clayer, r8) - new_cohort%leafmemory = leafmemory - new_cohort%sapwmemory = sapwmemory - new_cohort%structmemory = structmemory ! This sets things like vcmax25top, that depend on the ! leaf age fractions (which are defined by PARTEH) @@ -544,9 +534,6 @@ subroutine nan_cohort(cc_p) currentCohort%dbh = nan ! 'diameter at breast height' in cm currentCohort%coage = nan ! age of the cohort in years currentCohort%hite = nan ! height: meters - currentCohort%leafmemory = nan ! target leaf biomass- set from previous year: kGC per indiv - currentCohort%sapwmemory = nan ! target sapwood biomass- set from previous year: kGC per indiv - currentCohort%structmemory = nan ! target structural biomass- set from previous year: kGC per indiv currentCohort%lai = nan ! leaf area index of cohort m2/m2 currentCohort%sai = nan ! stem area index of cohort m2/m2 currentCohort%g_sb_laweight = nan ! Total leaf conductance of cohort (stomata+blayer) weighted by leaf-area [m/s]*[m2] @@ -1198,7 +1185,6 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) write(fates_log(),*) 'Cohort I, Cohort II' write(fates_log(),*) 'n:',currentCohort%n,nextc%n write(fates_log(),*) 'isnew:',currentCohort%isnew,nextc%isnew - write(fates_log(),*) 'leafmemory:',currentCohort%leafmemory,nextc%leafmemory write(fates_log(),*) 'hite:',currentCohort%hite,nextc%hite write(fates_log(),*) 'coage:',currentCohort%coage,nextc%coage write(fates_log(),*) 'dbh:',currentCohort%dbh,nextc%dbh @@ -1236,15 +1222,6 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) ! ----------------------------------------------------------------- call UpdateCohortBioPhysRates(currentCohort) - currentCohort%leafmemory = (currentCohort%n*currentCohort%leafmemory & - + nextc%n*nextc%leafmemory)/newn - - currentCohort%sapwmemory = (currentCohort%n*currentCohort%sapwmemory & - + nextc%n*nextc%sapwmemory)/newn - - currentCohort%structmemory = (currentCohort%n*currentCohort%structmemory & - + nextc%n*nextc%structmemory)/newn - currentCohort%canopy_trim = (currentCohort%n*currentCohort%canopy_trim & + nextc%n*nextc%canopy_trim)/newn @@ -1810,9 +1787,6 @@ subroutine copy_cohort( currentCohort,copyc ) n%dbh = o%dbh n%coage = o%coage n%hite = o%hite - n%leafmemory = o%leafmemory - n%sapwmemory = o%sapwmemory - n%structmemory = o%structmemory n%lai = o%lai n%sai = o%sai n%g_sb_laweight = o%g_sb_laweight diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 9a43af3226..d3815241fc 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -425,8 +425,6 @@ subroutine trim_canopy( currentSite ) real(r8) :: initial_trim ! Initial trim real(r8) :: optimum_trim ! Optimum trim value - real(r8) :: initial_leafmem ! Initial leafmemory - real(r8) :: optimum_leafmem ! Optimum leafmemory !---------------------------------------------------------------------- @@ -446,15 +444,13 @@ subroutine trim_canopy( currentSite ) currentCohort => currentPatch%tallest do while (associated(currentCohort)) - ! Save off the incoming trim and leafmemory + ! Save off the incoming trim initial_trim = currentCohort%canopy_trim - initial_leafmem = currentCohort%leafmemory ! Add debug diagnstic output to determine which cohort if (debug) then write(fates_log(),*) 'Current cohort:', icohort write(fates_log(),*) 'Starting canopy trim:', initial_trim - write(fates_log(),*) 'Starting leafmemory:', currentCohort%leafmemory endif trimmed = .false. @@ -596,10 +592,6 @@ subroutine trim_canopy( currentSite ) if (currentCohort%hite > EDPftvarcon_inst%hgt_min(ipft)) then currentCohort%canopy_trim = currentCohort%canopy_trim - & EDPftvarcon_inst%trim_inc(ipft) - if (prt_params%evergreen(ipft) /= 1)then - currentCohort%leafmemory = currentCohort%leafmemory * & - (1.0_r8 - EDPftvarcon_inst%trim_inc(ipft)) - endif trimmed = .true. @@ -641,17 +633,11 @@ subroutine trim_canopy( currentSite ) ! optimum_trim = (nnu_clai_b(1,1) / cumulative_lai_cohort) * initial_trim - optimum_leafmem = (nnu_clai_b(1,1) / cumulative_lai_cohort) * initial_leafmem ! Determine if the optimum trim value makes sense. The smallest cohorts tend to have unrealistic fits. if (optimum_trim > 0. .and. optimum_trim < 1.) then currentCohort%canopy_trim = optimum_trim - ! If the cohort pft is not evergreen we reduce the leafmemory as well - if (prt_params%evergreen(ipft) /= 1) then - currentCohort%leafmemory = optimum_leafmem - endif - trimmed = .true. endif @@ -1077,7 +1063,11 @@ subroutine phenology_leafonoff(currentSite) real(r8) :: struct_c ! structural wood carbon [kg] real(r8) :: store_c ! storage carbon [kg] real(r8) :: store_c_transfer_frac ! Fraction of storage carbon used to flush leaves - real(r8) :: totalmemory ! total memory of carbon [kg] + real(r8) :: deficit_c ! Amount of C needed to get flushing pools "on-allometry" + real(r8) :: target_leaf_c + real(r8) :: target_sapw_c + real(r8) :: target_bgw_c, target_agw_c, target_struct_c + real(r8) :: sapw_area integer :: ipft real(r8), parameter :: leaf_drop_fraction = 1.0_r8 real(r8), parameter :: carbon_store_buffer = 0.10_r8 @@ -1096,10 +1086,10 @@ subroutine phenology_leafonoff(currentSite) if(debug) call currentCohort%prt%CheckMassConservation(ipft,0) - store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) - leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) - sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) - struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) + store_c = currentCohort%prt%GetState(store_organ, carbon12_element) + leaf_c = currentCohort%prt%GetState(leaf_organ, carbon12_element) + sapw_c = currentCohort%prt%GetState(sapw_organ, carbon12_element) + struct_c = currentCohort%prt%GetState(struct_organ, carbon12_element) stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(ipft) @@ -1113,18 +1103,24 @@ subroutine phenology_leafonoff(currentSite) currentCohort%status_coh = leaves_on ! Leaves are on, so change status to ! stop flow of carbon out of bstore. + call bleaf(currentCohort%dbh,currentCohort%pft,currentCohort%canopy_trim,target_leaf_c) + call bsap_allom(currentCohort%dbh,currentCohort%pft,currentCohort%canopy_trim,sapw_area,target_sapw_c) + call bbgw_allom(currentCohort%dbh,currentCohort%pft,target_bgw_c) + call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, currentCohort%pft, target_struct_c) + + if(prt_params%woody(ipft) == itrue)then + deficit_c = target_leaf_c + else + deficit_c = target_leaf_c + (target_sapw_c-sapw_c) + (target_struct_c-struct_c) + end if + if(store_c>nearzero) then - ! flush either the amount required from the leafmemory, or -most- of the storage pool + + ! flush either the amount to get to the target, or -most- of the storage pool ! RF: added a criterion to stop the entire store pool emptying and triggering termination mortality ! n.b. this might not be necessary if we adopted a more gradual approach to leaf flushing... - store_c_transfer_frac = min((EDPftvarcon_inst%phenflush_fraction(ipft)* & - currentCohort%leafmemory)/store_c,(1.0_r8-carbon_store_buffer)) - - if(prt_params%woody(ipft).ne.itrue)then - totalmemory=currentCohort%leafmemory+currentCohort%sapwmemory+currentCohort%structmemory - store_c_transfer_frac = min((EDPftvarcon_inst%phenflush_fraction(ipft)* & - totalmemory)/store_c, (1.0_r8-carbon_store_buffer)) - endif + store_c_transfer_frac = min((EDPftvarcon_inst%phenflush_fraction(ipft)*deficit_c)/store_c, & + (1.0_r8-carbon_store_buffer)) else store_c_transfer_frac = 0.0_r8 @@ -1135,21 +1131,21 @@ subroutine phenology_leafonoff(currentSite) if(prt_params%woody(ipft) == itrue) then call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, store_c_transfer_frac) - currentCohort%leafmemory = 0.0_r8 else - ! Check that the stem drop fraction is set to non-zero amount otherwise flush all carbon store to leaves + ! Check that the stem drop fraction is set to non-zero amount + ! otherwise flush all carbon store to leaves if (stem_drop_fraction .gt. 0.0_r8) then call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & - store_c_transfer_frac*currentCohort%leafmemory/totalmemory) + store_c_transfer_frac*target_leaf_c/deficit_c) call PRTPhenologyFlush(currentCohort%prt, ipft, sapw_organ, & - store_c_transfer_frac*currentCohort%sapwmemory/totalmemory) + store_c_transfer_frac*(target_sapw_c-sapw_c)/deficit_c) call PRTPhenologyFlush(currentCohort%prt, ipft, struct_organ, & - store_c_transfer_frac*currentCohort%structmemory/totalmemory) + store_c_transfer_frac*(target_struct_c-struct_c)/deficit_c) else @@ -1158,10 +1154,6 @@ subroutine phenology_leafonoff(currentSite) end if - currentCohort%leafmemory = 0.0_r8 - currentCohort%structmemory = 0.0_r8 - currentCohort%sapwmemory = 0.0_r8 - endif endif !pft phenology endif ! growing season @@ -1179,11 +1171,6 @@ subroutine phenology_leafonoff(currentSite) ! This sets the cohort to the "leaves off" flag currentCohort%status_coh = leaves_off - ! Remember what the leaf mass was for next year - ! the same amount back on in the spring... - - currentCohort%leafmemory = leaf_c - ! Drop Leaves (this routine will update the leaf state variables, ! for carbon and any other element that are prognostic. It will ! also track the turnover masses that will be sent to litter later on) @@ -1193,10 +1180,6 @@ subroutine phenology_leafonoff(currentSite) if(prt_params%woody(ipft).ne.itrue)then - currentCohort%sapwmemory = sapw_c * stem_drop_fraction - - currentCohort%structmemory = struct_c * stem_drop_fraction - call PRTDeciduousTurnover(currentCohort%prt,ipft, & sapw_organ, stem_drop_fraction) @@ -1226,19 +1209,22 @@ subroutine phenology_leafonoff(currentSite) currentCohort%status_coh = leaves_on ! Leaves are on, so change status to ! stop flow of carbon out of bstore. - if(store_c>nearzero) then - - store_c_transfer_frac = & - min((EDPftvarcon_inst%phenflush_fraction(ipft)*currentCohort%leafmemory)/store_c, & - (1.0_r8-carbon_store_buffer)) - - if(prt_params%woody(ipft).ne.itrue)then - - totalmemory=currentCohort%leafmemory+currentCohort%sapwmemory+currentCohort%structmemory - store_c_transfer_frac = min(EDPftvarcon_inst%phenflush_fraction(ipft)*totalmemory/store_c, & - (1.0_r8-carbon_store_buffer)) + call bleaf(currentCohort%dbh,currentCohort%pft,currentCohort%canopy_trim,target_leaf_c) + call bsap_allom(currentCohort%dbh,currentCohort%pft,currentCohort%canopy_trim,sapw_area,target_sapw_c) + call bbgw_allom(currentCohort%dbh,currentCohort%pft,target_bgw_c) + call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, currentCohort%pft, target_struct_c) - endif + if(prt_params%woody(ipft) == itrue)then + deficit_c = target_leaf_c + else + deficit_c = target_leaf_c + (target_sapw_c-sapw_c) + (target_struct_c-struct_c) + end if + + if(store_c>nearzero) then + + store_c_transfer_frac = & + min((EDPftvarcon_inst%phenflush_fraction(ipft)*deficit_c)/store_c, & + (1.0_r8-carbon_store_buffer)) else store_c_transfer_frac = 0.0_r8 @@ -1251,22 +1237,20 @@ subroutine phenology_leafonoff(currentSite) call PRTPhenologyFlush(currentCohort%prt, ipft, & leaf_organ, store_c_transfer_frac) - currentCohort%leafmemory = 0.0_r8 - else ! Check that the stem drop fraction is set to non-zero amount otherwise flush all carbon store to leaves if (stem_drop_fraction .gt. 0.0_r8) then call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & - store_c_transfer_frac*currentCohort%leafmemory/totalmemory) + store_c_transfer_frac*target_leaf_c/deficit_c) call PRTPhenologyFlush(currentCohort%prt, ipft, sapw_organ, & - store_c_transfer_frac*currentCohort%sapwmemory/totalmemory) + store_c_transfer_frac*(target_sapw_c-sapw_c)/deficit_c) call PRTPhenologyFlush(currentCohort%prt, ipft, struct_organ, & - store_c_transfer_frac*currentCohort%structmemory/totalmemory) - + store_c_transfer_frac*(target_struct_c-struct_c)/deficit_c) + else call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & @@ -1274,10 +1258,6 @@ subroutine phenology_leafonoff(currentSite) end if - currentCohort%leafmemory = 0.0_r8 - currentCohort%structmemory = 0.0_r8 - currentCohort%sapwmemory = 0.0_r8 - endif ! woody plant check endif !currentCohort status again? endif !currentSite status @@ -1291,17 +1271,11 @@ subroutine phenology_leafonoff(currentSite) ! This sets the cohort to the "leaves off" flag currentCohort%status_coh = leaves_off - ! Remember what the leaf mass was for next year - currentCohort%leafmemory = leaf_c - call PRTDeciduousTurnover(currentCohort%prt,ipft, & leaf_organ, leaf_drop_fraction) if(prt_params%woody(ipft).ne.itrue)then - currentCohort%sapwmemory = sapw_c * stem_drop_fraction - currentCohort%structmemory = struct_c * stem_drop_fraction - call PRTDeciduousTurnover(currentCohort%prt,ipft, & sapw_organ, stem_drop_fraction) @@ -1881,22 +1855,15 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) ! Default assumption is that leaves are on cohortstatus = leaves_on - temp_cohort%leafmemory = 0.0_r8 - temp_cohort%sapwmemory = 0.0_r8 - temp_cohort%structmemory = 0.0_r8 - ! But if the plant is seasonally (cold) deciduous, and the site status is flagged ! as "cold", then set the cohort's status to leaves_off, and remember the leaf biomass if ((prt_params%season_decid(ft) == itrue) .and. & (any(currentSite%cstatus == [phen_cstat_nevercold,phen_cstat_iscold]))) then - temp_cohort%leafmemory = c_leaf c_leaf = 0.0_r8 ! If plant is not woody then set sapwood and structural biomass as well if (prt_params%woody(ft).ne.itrue) then - temp_cohort%sapwmemory = c_sapw * stem_drop_fraction - temp_cohort%structmemory = c_struct * stem_drop_fraction c_sapw = (1.0_r8 - stem_drop_fraction) * c_sapw c_struct = (1.0_r8 - stem_drop_fraction) * c_struct endif @@ -1908,13 +1875,10 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) ! biomass if ((prt_params%stress_decid(ft) == itrue) .and. & (any(currentSite%dstatus == [phen_dstat_timeoff,phen_dstat_moistoff]))) then - temp_cohort%leafmemory = c_leaf c_leaf = 0.0_r8 ! If plant is not woody then set sapwood and structural biomass as well if(prt_params%woody(ft).ne.itrue)then - temp_cohort%sapwmemory = c_sapw * stem_drop_fraction - temp_cohort%structmemory = c_struct * stem_drop_fraction c_sapw = (1.0_r8 - stem_drop_fraction) * c_sapw c_struct = (1.0_r8 - stem_drop_fraction) * c_struct endif @@ -1988,7 +1952,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) endif ! Only bother allocating a new cohort if there is a reasonable amount of it - any_recruits: if (temp_cohort%n > min_n_safemath )then + any_recruits: if (temp_cohort%n > min_n_safemath )then ! ----------------------------------------------------------------------------- ! PART II. @@ -2091,10 +2055,10 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) ! ----------------------------------------------------------------------------------- call prt%CheckInitialConditions() + ! This initializes the cohort call create_cohort(currentSite,currentPatch, temp_cohort%pft, temp_cohort%n, & temp_cohort%hite, temp_cohort%coage, temp_cohort%dbh, prt, & - temp_cohort%leafmemory, temp_cohort%sapwmemory, temp_cohort%structmemory, & cohortstatus, recruitstatus, & temp_cohort%canopy_trim,temp_cohort%c_area, & currentPatch%NCL_p, currentSite%spread, bc_in) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 451834a9ec..688c07010e 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -794,9 +794,6 @@ subroutine init_cohorts( site_in, patch_in, bc_in) call bstore_allom(temp_cohort%dbh, pft, temp_cohort%canopy_trim, c_store) - temp_cohort%leafmemory = 0._r8 - temp_cohort%sapwmemory = 0._r8 - temp_cohort%structmemory = 0._r8 cstatus = leaves_on stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(temp_cohort%pft) @@ -805,9 +802,6 @@ subroutine init_cohorts( site_in, patch_in, bc_in) if( prt_params%season_decid(pft) == itrue .and. & any(site_in%cstatus == [phen_cstat_nevercold,phen_cstat_iscold])) then - temp_cohort%leafmemory = c_leaf - temp_cohort%sapwmemory = c_sapw * stem_drop_fraction - temp_cohort%structmemory = c_struct * stem_drop_fraction c_leaf = 0._r8 c_sapw = (1.0_r8-stem_drop_fraction) * c_sapw c_struct = (1.0_r8-stem_drop_fraction) * c_struct @@ -816,9 +810,6 @@ subroutine init_cohorts( site_in, patch_in, bc_in) if ( prt_params%stress_decid(pft) == itrue .and. & any(site_in%dstatus == [phen_dstat_timeoff,phen_dstat_moistoff])) then - temp_cohort%leafmemory = c_leaf - temp_cohort%sapwmemory = c_sapw * stem_drop_fraction - temp_cohort%structmemory = c_struct * stem_drop_fraction c_leaf = 0._r8 c_sapw = (1.0_r8-stem_drop_fraction) * c_sapw c_struct = (1.0_r8-stem_drop_fraction) * c_struct @@ -900,8 +891,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) call prt_obj%CheckInitialConditions() call create_cohort(site_in, patch_in, pft, temp_cohort%n, temp_cohort%hite, & - temp_cohort%coage, temp_cohort%dbh, prt_obj, temp_cohort%leafmemory, & - temp_cohort%sapwmemory, temp_cohort%structmemory, cstatus, rstatus, & + temp_cohort%coage, temp_cohort%dbh, prt_obj, cstatus, rstatus, & temp_cohort%canopy_trim, temp_cohort%c_area,1, site_in%spread, bc_in) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 7d6d4f641b..e381ab8bc7 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1690,6 +1690,15 @@ subroutine FatesCheckParams(is_master) end if end if + if( (prt_params%woody(ipft) == itrue) .and. & + (EDPftvarcon_inst%phen_stem_drop_fraction(ipft) > nearzero ) ) then + write(fates_log(),*) ' Non-zero stem-drop fractions are not allowed for woody plants' + write(fates_log(),*) ' PFT#: ',ipft + write(fates_log(),*) ' part_params%woody:',prt_params%woody(ipft) + write(fates_log(),*) ' phen_stem_drop_fraction: ', EDPFtvarcon_inst%phen_stem_drop_fraction(ipft) + write(fates_log(),*) ' Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if ! Check if freezing tolerance is within reasonable bounds ! ---------------------------------------------------------------------------------- diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 39b7c9cbf2..edf9976218 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -214,9 +214,6 @@ module EDTypesMod real(r8) :: coage ! cohort age in years real(r8) :: hite ! height: meters integer :: indexnumber ! unique number for each cohort. (within clump?) - real(r8) :: leafmemory ! target leaf biomass- set from previous year: kGC per indiv - real(r8) :: sapwmemory ! target sapwood biomass- set from previous year: kGC per indiv - real(r8) :: structmemory ! target structural biomass- set from previous year: kGC per indiv integer :: canopy_layer ! canopy status of cohort (1 = canopy, 2 = understorey, etc.) real(r8) :: canopy_layer_yesterday ! recent canopy status of cohort ! (1 = canopy, 2 = understorey, etc.) @@ -1037,9 +1034,6 @@ subroutine dump_cohort(ccohort) write(fates_log(),*) 'co%dbh = ', ccohort%dbh write(fates_log(),*) 'co%hite = ', ccohort%hite write(fates_log(),*) 'co%coage = ', ccohort%coage - write(fates_log(),*) 'co%leafmemory = ', ccohort%leafmemory - write(fates_log(),*) 'co%sapwmemory = ', ccohort%sapwmemory - write(fates_log(),*) 'co%structmemory = ', ccohort%structmemory write(fates_log(),*) 'leaf carbon = ', ccohort%prt%GetState(leaf_organ,all_carbon_elements) write(fates_log(),*) 'fineroot carbon = ', ccohort%prt%GetState(fnrt_organ,all_carbon_elements) diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index e4b5fe4e2b..a76ae9df4f 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -1041,32 +1041,22 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & call bstore_allom(temp_cohort%dbh, temp_cohort%pft, temp_cohort%canopy_trim, c_store) - temp_cohort%leafmemory = 0._r8 - temp_cohort%sapwmemory = 0._r8 - temp_cohort%structmemory = 0._r8 cstatus = leaves_on - stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(temp_cohort%pft) if( prt_params%season_decid(temp_cohort%pft) == itrue .and. & any(csite%cstatus == [phen_cstat_nevercold,phen_cstat_iscold])) then - temp_cohort%leafmemory = c_leaf - temp_cohort%sapwmemory = c_sapw * stem_drop_fraction - temp_cohort%structmemory = c_struct * stem_drop_fraction c_leaf = 0._r8 - c_sapw = (1._r8 - stem_drop_fraction) * c_sapw - c_struct = (1._r8 - stem_drop_fraction) * c_struct + c_sapw = (1._r8 - stem_drop_fraction) * c_sapw + c_struct = (1._r8 - stem_drop_fraction) * c_struct cstatus = leaves_off endif if ( prt_params%stress_decid(temp_cohort%pft) == itrue .and. & any(csite%dstatus == [phen_dstat_timeoff,phen_dstat_moistoff])) then - temp_cohort%leafmemory = c_leaf - temp_cohort%sapwmemory = c_sapw * stem_drop_fraction - temp_cohort%structmemory = c_struct * stem_drop_fraction c_leaf = 0._r8 - c_sapw = (1._r8 - stem_drop_fraction) * c_sapw - c_struct = (1._r8 - stem_drop_fraction) * c_struct + c_sapw = (1._r8 - stem_drop_fraction) * c_sapw + c_struct = (1._r8 - stem_drop_fraction) * c_struct cstatus = leaves_off endif @@ -1161,8 +1151,7 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & call create_cohort(csite, cpatch, temp_cohort%pft, temp_cohort%n, temp_cohort%hite, & temp_cohort%coage, temp_cohort%dbh, & - prt_obj, temp_cohort%leafmemory,temp_cohort%sapwmemory, temp_cohort%structmemory, & - cstatus, rstatus, temp_cohort%canopy_trim,temp_cohort%c_area, & + prt_obj, cstatus, rstatus, temp_cohort%canopy_trim,temp_cohort%c_area, & 1, csite%spread, bc_in) deallocate(temp_cohort) ! get rid of temporary cohort diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index c61c87fd4b..838441be8b 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -100,9 +100,6 @@ module FatesRestartInterfaceMod integer :: ir_coage_co integer :: ir_g_sb_laweight_co integer :: ir_height_co - integer :: ir_leafmemory_co - integer :: ir_sapwmemory_co - integer :: ir_structmemory_co integer :: ir_nplant_co integer :: ir_gpp_acc_co integer :: ir_npp_acc_co @@ -714,21 +711,6 @@ subroutine define_restart_vars(this, initialize_variables) long_name='ed cohort - plant height', units='m', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_height_co ) - call this%set_restart_var(vname='fates_leafmemory', vtype=cohort_r8, & - long_name='ed cohort - target leaf biomass set from prev year', & - units='kgC/indiv', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_leafmemory_co ) - - call this%set_restart_var(vname='fates_sapwmemory', vtype=cohort_r8, & - long_name='ed cohort - target sapwood biomass set from prev year', & - units='kgC/indiv', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_sapwmemory_co ) - - call this%set_restart_var(vname='fates_structmemory', vtype=cohort_r8, & - long_name='ed cohort - target structural biomass set from prev year', & - units='kgC/indiv', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_structmemory_co ) - call this%set_restart_var(vname='fates_nplant', vtype=cohort_r8, & long_name='ed cohort - number of plants in the cohort', & units='/patch', flushval = flushzero, & @@ -1773,9 +1755,6 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_coage_co => this%rvars(ir_coage_co)%r81d, & rio_g_sb_laweight_co => this%rvars(ir_g_sb_laweight_co)%r81d, & rio_height_co => this%rvars(ir_height_co)%r81d, & - rio_leafmemory_co => this%rvars(ir_leafmemory_co)%r81d, & - rio_sapwmemory_co => this%rvars(ir_sapwmemory_co)%r81d, & - rio_structmemory_co => this%rvars(ir_structmemory_co)%r81d, & rio_nplant_co => this%rvars(ir_nplant_co)%r81d, & rio_gpp_acc_co => this%rvars(ir_gpp_acc_co)%r81d, & rio_npp_acc_co => this%rvars(ir_npp_acc_co)%r81d, & @@ -2002,11 +1981,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_dbh_co(io_idx_co) = ccohort%dbh rio_coage_co(io_idx_co) = ccohort%coage rio_height_co(io_idx_co) = ccohort%hite - rio_leafmemory_co(io_idx_co) = ccohort%leafmemory - rio_sapwmemory_co(io_idx_co) = ccohort%sapwmemory - rio_structmemory_co(io_idx_co) = ccohort%structmemory rio_g_sb_laweight_co(io_idx_co)= ccohort%g_sb_laweight - rio_nplant_co(io_idx_co) = ccohort%n rio_gpp_acc_co(io_idx_co) = ccohort%gpp_acc rio_npp_acc_co(io_idx_co) = ccohort%npp_acc @@ -2612,9 +2587,6 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_coage_co => this%rvars(ir_coage_co)%r81d, & rio_g_sb_laweight_co => this%rvars(ir_g_sb_laweight_co)%r81d, & rio_height_co => this%rvars(ir_height_co)%r81d, & - rio_leafmemory_co => this%rvars(ir_leafmemory_co)%r81d, & - rio_sapwmemory_co => this%rvars(ir_sapwmemory_co)%r81d, & - rio_structmemory_co => this%rvars(ir_structmemory_co)%r81d, & rio_nplant_co => this%rvars(ir_nplant_co)%r81d, & rio_gpp_acc_co => this%rvars(ir_gpp_acc_co)%r81d, & rio_npp_acc_co => this%rvars(ir_npp_acc_co)%r81d, & @@ -2814,9 +2786,6 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ccohort%coage = rio_coage_co(io_idx_co) ccohort%g_sb_laweight= rio_g_sb_laweight_co(io_idx_co) ccohort%hite = rio_height_co(io_idx_co) - ccohort%leafmemory = rio_leafmemory_co(io_idx_co) - ccohort%sapwmemory = rio_sapwmemory_co(io_idx_co) - ccohort%structmemory = rio_structmemory_co(io_idx_co) ccohort%n = rio_nplant_co(io_idx_co) ccohort%gpp_acc = rio_gpp_acc_co(io_idx_co) ccohort%npp_acc = rio_npp_acc_co(io_idx_co) From d364757b99c31bbcb7d194696e9b6a50ad0d6148 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 28 Jul 2022 22:18:15 -0400 Subject: [PATCH 299/852] removed %lai and %sai where were redundant with treelai and canopy_area --- biogeochem/EDCanopyStructureMod.F90 | 436 +++++++++++----------------- biogeochem/EDCohortDynamicsMod.F90 | 6 - main/EDTypesMod.F90 | 3 - 3 files changed, 172 insertions(+), 273 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index f195f59f0a..6fb7529bf1 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1449,8 +1449,6 @@ subroutine leaf_area_profile( currentSite ) ! ! currentCohort%treelai ! LAI per unit crown area (m2/m2) ! currentCohort%treesai ! SAI per unit crown area (m2/m2) - ! currentCohort%lai ! LAI per unit canopy area (m2/m2) - ! currentCohort%sai ! SAI per unit canopy area (m2/m2) ! currentCohort%NV ! The number of discrete vegetation ! ! layers needed to describe this crown ! @@ -1477,7 +1475,7 @@ subroutine leaf_area_profile( currentSite ) ! !USES: use EDtypesMod , only : area, dinc_vai, dlower_vai, hitemax, n_hite_bins - + ! ! !ARGUMENTS type(ed_site_type) , intent(inout) :: currentSite @@ -1497,7 +1495,6 @@ subroutine leaf_area_profile( currentSite ) real(r8) :: layer_bottom_hite ! notional bottom height of this canopy layer (m) integer :: smooth_leaf_distribution ! is the leaf distribution this option (1) or not (0) real(r8) :: frac_canopy(N_HITE_BINS) ! amount of canopy in each height class - real(r8) :: patch_lai ! LAI summed over the patch in m2/m2 of canopy area real(r8) :: minh(N_HITE_BINS) ! minimum height in height class (m) real(r8) :: maxh(N_HITE_BINS) ! maximum height in height class (m) real(r8) :: dh ! vertical detph of height class (m) @@ -1525,7 +1522,6 @@ subroutine leaf_area_profile( currentSite ) currentPatch%canopy_layer_tlai(:) = 0._r8 currentPatch%ncan(:,:) = 0 currentPatch%nrad(:,:) = 0 - patch_lai = 0._r8 currentPatch%tlai_profile(:,:,:) = 0._r8 currentPatch%tsai_profile(:,:,:) = 0._r8 currentPatch%elai_profile(:,:,:) = 0._r8 @@ -1541,307 +1537,223 @@ subroutine leaf_area_profile( currentSite ) if (currentPatch%total_canopy_area > nearzero ) then - call UpdatePatchLAI(currentPatch, patch_lai) - - if(smooth_leaf_distribution == 1)then - - ! ----------------------------------------------------------------------------- - ! we are going to ignore the concept of canopy layers, and put all of the leaf - ! area into height banded bins. using the same domains as we had before, except - ! that CL always = 1 - ! ----------------------------------------------------------------------------- - - ! this is a crude way of dividing up the bins. Should it be a function of actual maximum height? - dh = 1.0_r8*(HITEMAX/N_HITE_BINS) - do iv = 1,N_HITE_BINS - if (iv == 1) then - minh(iv) = 0.0_r8 - maxh(iv) = dh - else - minh(iv) = (iv-1)*dh - maxh(iv) = (iv)*dh - endif - enddo - - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - ft = currentCohort%pft - min_chite = currentCohort%hite - currentCohort%hite * prt_params%crown_depth_frac(ft) - max_chite = currentCohort%hite - do iv = 1,N_HITE_BINS - frac_canopy(iv) = 0.0_r8 - ! this layer is in the middle of the canopy - if(max_chite > maxh(iv).and.min_chite < minh(iv))then - frac_canopy(iv)= min(1.0_r8,dh / (currentCohort%hite*prt_params%crown_depth_frac(ft) )) - ! this is the layer with the bottom of the canopy in it. - elseif(min_chite < maxh(iv).and.min_chite > minh(iv).and.max_chite > maxh(iv))then - frac_canopy(iv) = (maxh(iv) -min_chite ) / (currentCohort%hite*prt_params%crown_depth_frac(ft) ) - ! this is the layer with the top of the canopy in it. - elseif(max_chite > minh(iv).and.max_chite < maxh(iv).and.min_chite < minh(iv))then - frac_canopy(iv) = (max_chite - minh(iv)) / (currentCohort%hite*prt_params%crown_depth_frac(ft)) - elseif(max_chite < maxh(iv).and.min_chite > minh(iv))then !the whole cohort is within this layer. - frac_canopy(iv) = 1.0_r8 - endif - - ! no m2 of leaf per m2 of ground in each height class - currentPatch%tlai_profile(1,ft,iv) = currentPatch%tlai_profile(1,ft,iv) + frac_canopy(iv) * & - currentCohort%lai - currentPatch%tsai_profile(1,ft,iv) = currentPatch%tsai_profile(1,ft,iv) + frac_canopy(iv) * & - currentCohort%sai + call UpdatePatchLAI(currentPatch) - !snow burial - if(currentSite%snow_depth > maxh(iv))then - fraction_exposed = 0._r8 - endif - if(currentSite%snow_depth < minh(iv))then - fraction_exposed = 1._r8 - endif - if(currentSite%snow_depth >= minh(iv) .and. currentSite%snow_depth <= maxh(iv)) then !only partly hidden... - fraction_exposed = 1._r8 - max(0._r8,(min(1.0_r8,(currentSite%snow_depth-minh(iv))/dh))) - endif - - currentPatch%elai_profile(1,ft,iv) = currentPatch%tlai_profile(1,ft,iv) * fraction_exposed - currentPatch%esai_profile(1,ft,iv) = currentPatch%tsai_profile(1,ft,iv) * fraction_exposed + ! ----------------------------------------------------------------------------- + ! Standard canopy layering model. + ! Go through all cohorts and add their leaf area + ! and canopy area to the accumulators. + ! ----------------------------------------------------------------------------- - enddo ! (iv) hite bins + currentCohort => currentPatch%shortest + do while(associated(currentCohort)) + ft = currentCohort%pft + cl = currentCohort%canopy_layer - currentCohort => currentCohort%taller + ! ---------------------------------------------------------------- + ! How much of each tree is stem area index? Assuming that there is + ! This may indeed be zero if there is a sensecent grass + ! ---------------------------------------------------------------- - enddo !currentCohort + if( (currentCohort%treelai+currentCohort%treesai) > 0._r8)then + fleaf = currentCohort%treelai / (currentCohort%treelai + currentCohort%treesai) + else + fleaf = 0._r8 + endif - ! ----------------------------------------------------------------------------- - ! Perform a leaf area conservation check on the LAI profile - lai = 0.0_r8 - do ft = 1,numpft - lai = lai+ sum(currentPatch%tlai_profile(1,ft,:)) - enddo + currentPatch%nrad(cl,ft) = currentPatch%ncan(cl,ft) - if(lai > patch_lai)then - write(fates_log(), *) 'FATES: problem with lai assignments' + if (currentPatch%nrad(cl,ft) > nlevleaf ) then + write(fates_log(), *) 'Number of radiative leaf layers is larger' + write(fates_log(), *) ' than the maximum allowed.' + write(fates_log(), *) ' cl: ',cl + write(fates_log(), *) ' ft: ',ft + write(fates_log(), *) ' nlevleaf: ',nlevleaf + write(fates_log(), *) ' currentPatch%nrad(cl,ft): ', currentPatch%nrad(cl,ft) call endrun(msg=errMsg(sourcefile, __LINE__)) - endif + end if - else ! smooth leaf distribution + ! -------------------------------------------------------------------------- + ! Whole layers. Make a weighted average of the leaf area in each layer + ! before dividing it by the total area. Fill up layer for whole layers. + ! -------------------------------------------------------------------------- - ! ----------------------------------------------------------------------------- - ! Standard canopy layering model. - ! Go through all cohorts and add their leaf area - ! and canopy area to the accumulators. - ! ----------------------------------------------------------------------------- + do iv = 1,currentCohort%NV + ! This loop builds the arrays that define the effective (not snow covered) + ! and total (includes snow covered) area indices for leaves and stems + ! We calculate the absolute elevation of each layer to help determine if the layer + ! is obscured by snow. - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - ft = currentCohort%pft - cl = currentCohort%canopy_layer + layer_top_hite = currentCohort%hite - & + ( real(iv-1,r8)/currentCohort%NV * currentCohort%hite * & + prt_params%crown_depth_frac(currentCohort%pft) ) - ! ---------------------------------------------------------------- - ! How much of each tree is stem area index? Assuming that there is - ! This may indeed be zero if there is a sensecent grass - ! ---------------------------------------------------------------- + layer_bottom_hite = currentCohort%hite - & + ( real(iv,r8)/currentCohort%NV * currentCohort%hite * & + prt_params%crown_depth_frac(currentCohort%pft) ) - if( (currentCohort%treelai+currentCohort%treesai) > 0._r8)then - fleaf = currentCohort%lai / (currentCohort%lai + currentCohort%sai) - else - fleaf = 0._r8 + fraction_exposed = 1.0_r8 + if(currentSite%snow_depth > layer_top_hite)then + fraction_exposed = 0._r8 + endif + if(currentSite%snow_depth < layer_bottom_hite)then + fraction_exposed = 1._r8 + endif + if(currentSite%snow_depth >= layer_bottom_hite .and. & + currentSite%snow_depth <= layer_top_hite) then !only partly hidden... + fraction_exposed = 1._r8 - max(0._r8,(min(1.0_r8,(currentSite%snow_depth -layer_bottom_hite)/ & + (layer_top_hite-layer_bottom_hite )))) endif - currentPatch%nrad(cl,ft) = currentPatch%ncan(cl,ft) + if(iv==currentCohort%NV) then + remainder = (currentCohort%treelai + currentCohort%treesai) - & + (dlower_vai(iv) - dinc_vai(iv)) + if(remainder > dinc_vai(iv) )then + write(fates_log(), *)'ED: issue with remainder', & + currentCohort%treelai,currentCohort%treesai,dinc_vai(iv), & + currentCohort%NV,remainder - if (currentPatch%nrad(cl,ft) > nlevleaf ) then - write(fates_log(), *) 'Number of radiative leaf layers is larger' - write(fates_log(), *) ' than the maximum allowed.' - write(fates_log(), *) ' cl: ',cl - write(fates_log(), *) ' ft: ',ft - write(fates_log(), *) ' nlevleaf: ',nlevleaf - write(fates_log(), *) ' currentPatch%nrad(cl,ft): ', currentPatch%nrad(cl,ft) - call endrun(msg=errMsg(sourcefile, __LINE__)) + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + else + remainder = dinc_vai(iv) end if + currentPatch%tlai_profile(cl,ft,iv) = currentPatch%tlai_profile(cl,ft,iv) + & + remainder * fleaf * currentCohort%c_area/currentPatch%total_canopy_area - ! -------------------------------------------------------------------------- - ! Whole layers. Make a weighted average of the leaf area in each layer - ! before dividing it by the total area. Fill up layer for whole layers. - ! -------------------------------------------------------------------------- + currentPatch%elai_profile(cl,ft,iv) = currentPatch%elai_profile(cl,ft,iv) + & + remainder * fleaf * currentCohort%c_area/currentPatch%total_canopy_area * & + fraction_exposed - do iv = 1,currentCohort%NV + currentPatch%tsai_profile(cl,ft,iv) = currentPatch%tsai_profile(cl,ft,iv) + & + remainder * (1._r8 - fleaf) * currentCohort%c_area/currentPatch%total_canopy_area - ! This loop builds the arrays that define the effective (not snow covered) - ! and total (includes snow covered) area indices for leaves and stems - ! We calculate the absolute elevation of each layer to help determine if the layer - ! is obscured by snow. + currentPatch%esai_profile(cl,ft,iv) = currentPatch%esai_profile(cl,ft,iv) + & + remainder * (1._r8 - fleaf) * currentCohort%c_area/currentPatch%total_canopy_area * & + fraction_exposed - layer_top_hite = currentCohort%hite - & - ( real(iv-1,r8)/currentCohort%NV * currentCohort%hite * & - prt_params%crown_depth_frac(currentCohort%pft) ) + currentPatch%canopy_area_profile(cl,ft,iv) = currentPatch%canopy_area_profile(cl,ft,iv) + & + currentCohort%c_area/currentPatch%total_canopy_area - layer_bottom_hite = currentCohort%hite - & - ( real(iv,r8)/currentCohort%NV * currentCohort%hite * & - prt_params%crown_depth_frac(currentCohort%pft) ) + currentPatch%layer_height_profile(cl,ft,iv) = currentPatch%layer_height_profile(cl,ft,iv) + & + (remainder * fleaf * currentCohort%c_area/currentPatch%total_canopy_area * & + (layer_top_hite+layer_bottom_hite)/2.0_r8) !average height of layer. - fraction_exposed = 1.0_r8 - if(currentSite%snow_depth > layer_top_hite)then - fraction_exposed = 0._r8 - endif - if(currentSite%snow_depth < layer_bottom_hite)then - fraction_exposed = 1._r8 - endif - if(currentSite%snow_depth >= layer_bottom_hite .and. & - currentSite%snow_depth <= layer_top_hite) then !only partly hidden... - fraction_exposed = 1._r8 - max(0._r8,(min(1.0_r8,(currentSite%snow_depth -layer_bottom_hite)/ & - (layer_top_hite-layer_bottom_hite )))) - endif - - if(iv==currentCohort%NV) then - remainder = (currentCohort%treelai + currentCohort%treesai) - & - (dlower_vai(iv) - dinc_vai(iv)) - if(remainder > dinc_vai(iv) )then - write(fates_log(), *)'ED: issue with remainder', & - currentCohort%treelai,currentCohort%treesai,dinc_vai(iv), & - currentCohort%NV,remainder - - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - else - remainder = dinc_vai(iv) - end if + end do - currentPatch%tlai_profile(cl,ft,iv) = currentPatch%tlai_profile(cl,ft,iv) + & - remainder * fleaf * currentCohort%c_area/currentPatch%total_canopy_area + currentCohort => currentCohort%taller - currentPatch%elai_profile(cl,ft,iv) = currentPatch%elai_profile(cl,ft,iv) + & - remainder * fleaf * currentCohort%c_area/currentPatch%total_canopy_area * & - fraction_exposed + enddo !cohort - currentPatch%tsai_profile(cl,ft,iv) = currentPatch%tsai_profile(cl,ft,iv) + & - remainder * (1._r8 - fleaf) * currentCohort%c_area/currentPatch%total_canopy_area + ! -------------------------------------------------------------------------- - currentPatch%esai_profile(cl,ft,iv) = currentPatch%esai_profile(cl,ft,iv) + & - remainder * (1._r8 - fleaf) * currentCohort%c_area/currentPatch%total_canopy_area * & - fraction_exposed + ! If there is an upper-story, the top canopy layer + ! should have a value of exactly 1.0 in its top leaf layer + ! -------------------------------------------------------------------------- - currentPatch%canopy_area_profile(cl,ft,iv) = currentPatch%canopy_area_profile(cl,ft,iv) + & + if ( (currentPatch%NCL_p > 1) .and. & + (sum(currentPatch%canopy_area_profile(1,:,1)) < 0.9999 )) then + write(fates_log(), *) 'FATES: canopy_area_profile was less than 1 at the canopy top' + write(fates_log(), *) 'cl: ',1 + write(fates_log(), *) 'iv: ',1 + write(fates_log(), *) 'sum(cpatch%canopy_area_profile(1,:,1)): ', & + sum(currentPatch%canopy_area_profile(1,:,1)) + currentCohort => currentPatch%shortest + do while(associated(currentCohort)) + if(currentCohort%canopy_layer==1)then + write(fates_log(), *) 'FATES: cohorts',currentCohort%dbh,currentCohort%c_area, & + currentPatch%total_canopy_area,currentPatch%area + write(fates_log(), *) 'ED: fracarea', currentCohort%pft, & currentCohort%c_area/currentPatch%total_canopy_area - - currentPatch%layer_height_profile(cl,ft,iv) = currentPatch%layer_height_profile(cl,ft,iv) + & - (remainder * fleaf * currentCohort%c_area/currentPatch%total_canopy_area * & - (layer_top_hite+layer_bottom_hite)/2.0_r8) !average height of layer. - - end do - + endif currentCohort => currentCohort%taller + enddo !currentCohort + call endrun(msg=errMsg(sourcefile, __LINE__)) - enddo !cohort - - ! -------------------------------------------------------------------------- + end if - ! If there is an upper-story, the top canopy layer - ! should have a value of exactly 1.0 in its top leaf layer - ! -------------------------------------------------------------------------- - if ( (currentPatch%NCL_p > 1) .and. & - (sum(currentPatch%canopy_area_profile(1,:,1)) < 0.9999 )) then - write(fates_log(), *) 'FATES: canopy_area_profile was less than 1 at the canopy top' - write(fates_log(), *) 'cl: ',1 - write(fates_log(), *) 'iv: ',1 - write(fates_log(), *) 'sum(cpatch%canopy_area_profile(1,:,1)): ', & - sum(currentPatch%canopy_area_profile(1,:,1)) - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - if(currentCohort%canopy_layer==1)then - write(fates_log(), *) 'FATES: cohorts',currentCohort%dbh,currentCohort%c_area, & - currentPatch%total_canopy_area,currentPatch%area - write(fates_log(), *) 'ED: fracarea', currentCohort%pft, & - currentCohort%c_area/currentPatch%total_canopy_area - endif - currentCohort => currentCohort%taller - enddo !currentCohort - call endrun(msg=errMsg(sourcefile, __LINE__)) + ! -------------------------------------------------------------------------- + ! In the following loop we are now normalizing the effective and + ! total area profiles to convert from units of leaf/stem area per vegetated + ! canopy area, into leaf/stem area per area of their own radiative column + ! which is typically the footprint of all cohorts contained in the canopy + ! layer x pft bins. + ! Also perform some checks on area normalization. + ! Check the area of each leaf layer, across pfts. + ! It should never be larger than 1 or less than 0. + ! -------------------------------------------------------------------------- - end if + do cl = 1,currentPatch%NCL_p + do iv = 1,currentPatch%ncan(cl,ft) + if( debug .and. sum(currentPatch%canopy_area_profile(cl,:,iv)) > 1.0001_r8 ) then - ! -------------------------------------------------------------------------- - ! In the following loop we are now normalizing the effective and - ! total area profiles to convert from units of leaf/stem area per vegetated - ! canopy area, into leaf/stem area per area of their own radiative column - ! which is typically the footprint of all cohorts contained in the canopy - ! layer x pft bins. - ! Also perform some checks on area normalization. - ! Check the area of each leaf layer, across pfts. - ! It should never be larger than 1 or less than 0. - ! -------------------------------------------------------------------------- + write(fates_log(), *) 'FATES: A canopy_area_profile exceeded 1.0' + write(fates_log(), *) 'cl: ',cl + write(fates_log(), *) 'iv: ',iv + write(fates_log(), *) 'sum(cpatch%canopy_area_profile(cl,:,iv)): ', & + sum(currentPatch%canopy_area_profile(cl,:,iv)) + currentCohort => currentPatch%shortest + do while(associated(currentCohort)) + if(currentCohort%canopy_layer==cl)then + write(fates_log(), *) 'FATES: cohorts in layer cl = ',cl, & + currentCohort%dbh,currentCohort%c_area, & + currentPatch%total_canopy_area,currentPatch%area + write(fates_log(), *) 'ED: fracarea', currentCohort%pft, & + currentCohort%c_area/currentPatch%total_canopy_area + endif + currentCohort => currentCohort%taller + enddo !currentCohort + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + end do - do cl = 1,currentPatch%NCL_p + do ft = 1,numpft do iv = 1,currentPatch%ncan(cl,ft) - if( debug .and. sum(currentPatch%canopy_area_profile(cl,:,iv)) > 1.0001_r8 ) then - - write(fates_log(), *) 'FATES: A canopy_area_profile exceeded 1.0' - write(fates_log(), *) 'cl: ',cl - write(fates_log(), *) 'iv: ',iv - write(fates_log(), *) 'sum(cpatch%canopy_area_profile(cl,:,iv)): ', & - sum(currentPatch%canopy_area_profile(cl,:,iv)) - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - if(currentCohort%canopy_layer==cl)then - write(fates_log(), *) 'FATES: cohorts in layer cl = ',cl, & - currentCohort%dbh,currentCohort%c_area, & - currentPatch%total_canopy_area,currentPatch%area - write(fates_log(), *) 'ED: fracarea', currentCohort%pft, & - currentCohort%c_area/currentPatch%total_canopy_area - endif - currentCohort => currentCohort%taller - enddo !currentCohort - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - end do + if( currentPatch%canopy_area_profile(cl,ft,iv) > nearzero ) then - do ft = 1,numpft - do iv = 1,currentPatch%ncan(cl,ft) + currentPatch%tlai_profile(cl,ft,iv) = currentPatch%tlai_profile(cl,ft,iv) / & + currentPatch%canopy_area_profile(cl,ft,iv) - if( currentPatch%canopy_area_profile(cl,ft,iv) > nearzero ) then + currentPatch%tsai_profile(cl,ft,iv) = currentPatch%tsai_profile(cl,ft,iv) / & + currentPatch%canopy_area_profile(cl,ft,iv) - currentPatch%tlai_profile(cl,ft,iv) = currentPatch%tlai_profile(cl,ft,iv) / & - currentPatch%canopy_area_profile(cl,ft,iv) + currentPatch%elai_profile(cl,ft,iv) = currentPatch%elai_profile(cl,ft,iv) / & + currentPatch%canopy_area_profile(cl,ft,iv) - currentPatch%tsai_profile(cl,ft,iv) = currentPatch%tsai_profile(cl,ft,iv) / & - currentPatch%canopy_area_profile(cl,ft,iv) - - currentPatch%elai_profile(cl,ft,iv) = currentPatch%elai_profile(cl,ft,iv) / & - currentPatch%canopy_area_profile(cl,ft,iv) - - currentPatch%esai_profile(cl,ft,iv) = currentPatch%esai_profile(cl,ft,iv) / & - currentPatch%canopy_area_profile(cl,ft,iv) - end if - - if(currentPatch%tlai_profile(cl,ft,iv)>nearzero )then - currentPatch%layer_height_profile(cl,ft,iv) = currentPatch%layer_height_profile(cl,ft,iv) & - /currentPatch%tlai_profile(cl,ft,iv) - end if + currentPatch%esai_profile(cl,ft,iv) = currentPatch%esai_profile(cl,ft,iv) / & + currentPatch%canopy_area_profile(cl,ft,iv) + end if - enddo + if(currentPatch%tlai_profile(cl,ft,iv)>nearzero )then + currentPatch%layer_height_profile(cl,ft,iv) = currentPatch%layer_height_profile(cl,ft,iv) & + /currentPatch%tlai_profile(cl,ft,iv) + end if enddo - enddo - ! -------------------------------------------------------------------------- - ! Set the mask that identifies which PFT x can-layer combinations have - ! scattering elements in them. - ! -------------------------------------------------------------------------- + enddo + enddo - do cl = 1,currentPatch%NCL_p - do ft = 1,numpft - do iv = 1, currentPatch%nrad(cl,ft) - if(currentPatch%canopy_area_profile(cl,ft,iv) > 0._r8)then - currentPatch%canopy_mask(cl,ft) = 1 - endif - end do !iv - enddo !ft - enddo ! loop over cl + ! -------------------------------------------------------------------------- + ! Set the mask that identifies which PFT x can-layer combinations have + ! scattering elements in them. + ! -------------------------------------------------------------------------- - endif !leaf distribution + do cl = 1,currentPatch%NCL_p + do ft = 1,numpft + do iv = 1, currentPatch%nrad(cl,ft) + if(currentPatch%canopy_area_profile(cl,ft,iv) > 0._r8)then + currentPatch%canopy_mask(cl,ft) = 1 + endif + end do !iv + enddo !ft + enddo ! loop over cl end if @@ -2180,7 +2092,7 @@ end subroutine CanopyLayerArea ! =============================================================================================== - subroutine UpdatePatchLAI(currentPatch, patch_lai) + subroutine UpdatePatchLAI(currentPatch) ! -------------------------------------------------------------------------------------------- ! This subroutine works through the current patch cohorts and updates the canopy_layer_tlai @@ -2192,7 +2104,6 @@ subroutine UpdatePatchLAI(currentPatch, patch_lai) ! Arguments type(ed_patch_type),intent(inout), target :: currentPatch - real(r8), intent(inout) :: patch_lai ! Local Variables type(ed_cohort_type), pointer :: currentCohort @@ -2219,11 +2130,10 @@ subroutine UpdatePatchLAI(currentPatch, patch_lai) ! Update the number of number of vegetation layers currentPatch%ncan(cl,ft) = max(currentPatch%ncan(cl,ft),currentCohort%NV) - ! Update the patch canopy layer tlai - currentPatch%canopy_layer_tlai(cl) = currentPatch%canopy_layer_tlai(cl) + currentCohort%lai + ! Update the patch canopy layer tlai (LAI per canopy area) + currentPatch%canopy_layer_tlai(cl) = currentPatch%canopy_layer_tlai(cl) + & + currentCohort%treelai *currentCohort%c_area/currentPatch%total_canopy_area - ! Calculate the total patch lai - patch_lai = patch_lai + currentCohort%lai end if currentCohort => currentCohort%shorter @@ -2263,9 +2173,7 @@ subroutine UpdateCohortLAI(currentCohort, canopy_layer_tlai, patcharea) currentCohort%vcmax25top,4) end if - ! Update the cohort lai and sai - currentCohort%lai = currentCohort%treelai *currentCohort%c_area/patcharea - currentCohort%sai = currentCohort%treesai *currentCohort%c_area/patcharea + ! Number of actual vegetation layers in this cohort's crown currentCohort%nv = count((currentCohort%treelai+currentCohort%treesai) .gt. dlower_vai(:)) + 1 diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index a7d203da5d..2d796a9048 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -277,8 +277,6 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & patchptr%canopy_layer_tlai, new_cohort%treelai,new_cohort%vcmax25top,2 ) end if - new_cohort%lai = new_cohort%treelai * new_cohort%c_area/patchptr%area - ! Put cohort at the right place in the linked list storebigcohort => patchptr%tallest @@ -534,8 +532,6 @@ subroutine nan_cohort(cc_p) currentCohort%dbh = nan ! 'diameter at breast height' in cm currentCohort%coage = nan ! age of the cohort in years currentCohort%hite = nan ! height: meters - currentCohort%lai = nan ! leaf area index of cohort m2/m2 - currentCohort%sai = nan ! stem area index of cohort m2/m2 currentCohort%g_sb_laweight = nan ! Total leaf conductance of cohort (stomata+blayer) weighted by leaf-area [m/s]*[m2] currentCohort%canopy_trim = nan ! What is the fraction of the maximum leaf biomass that we are targeting? :- currentCohort%leaf_cost = nan ! How much does it cost to maintain leaves: kgC/m2/year-1 @@ -1787,8 +1783,6 @@ subroutine copy_cohort( currentCohort,copyc ) n%dbh = o%dbh n%coage = o%coage n%hite = o%hite - n%lai = o%lai - n%sai = o%sai n%g_sb_laweight = o%g_sb_laweight n%leaf_cost = o%leaf_cost n%canopy_layer = o%canopy_layer diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index edf9976218..dfdfcdf43b 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -1041,9 +1041,6 @@ subroutine dump_cohort(ccohort) write(fates_log(),*) 'structural (dead) carbon = ', ccohort%prt%GetState(struct_organ,all_carbon_elements) write(fates_log(),*) 'storage carbon = ', ccohort%prt%GetState(store_organ,all_carbon_elements) write(fates_log(),*) 'reproductive carbon = ', ccohort%prt%GetState(repro_organ,all_carbon_elements) - - write(fates_log(),*) 'co%lai = ', ccohort%lai - write(fates_log(),*) 'co%sai = ', ccohort%sai write(fates_log(),*) 'co%g_sb_laweight = ', ccohort%g_sb_laweight write(fates_log(),*) 'co%leaf_cost = ', ccohort%leaf_cost write(fates_log(),*) 'co%canopy_layer = ', ccohort%canopy_layer From 3c5090d2f8343971f64f652e9305154af982e256 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 28 Jul 2022 22:35:49 -0400 Subject: [PATCH 300/852] Cleaned up logic on flushing for grasses without stemdrop --- biogeochem/EDPhysiologyMod.F90 | 100 +++++++++++++++------------------ 1 file changed, 45 insertions(+), 55 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index d3815241fc..f3072cd4eb 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1108,10 +1108,12 @@ subroutine phenology_leafonoff(currentSite) call bbgw_allom(currentCohort%dbh,currentCohort%pft,target_bgw_c) call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, currentCohort%pft, target_struct_c) - if(prt_params%woody(ipft) == itrue)then - deficit_c = target_leaf_c - else + if (stem_drop_fraction .gt. 0.0_r8) then + ! Note, this is only true for some grasses, woody plants don't + ! have a stem drop fraction deficit_c = target_leaf_c + (target_sapw_c-sapw_c) + (target_struct_c-struct_c) + else + deficit_c = target_leaf_c end if if(store_c>nearzero) then @@ -1128,33 +1130,27 @@ subroutine phenology_leafonoff(currentSite) ! This call will request that storage carbon will be transferred to ! leaf tissues. It is specified as a fraction of the available storage - if(prt_params%woody(ipft) == itrue) then - - call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, store_c_transfer_frac) - + ! Check that the stem drop fraction is set to non-zero amount + ! otherwise flush all carbon store to leaves + if (stem_drop_fraction .gt. 0.0_r8) then + + call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & + store_c_transfer_frac*target_leaf_c/deficit_c) + + call PRTPhenologyFlush(currentCohort%prt, ipft, sapw_organ, & + store_c_transfer_frac*(target_sapw_c-sapw_c)/deficit_c) + + call PRTPhenologyFlush(currentCohort%prt, ipft, struct_organ, & + store_c_transfer_frac*(target_struct_c-struct_c)/deficit_c) + else + + call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & + store_c_transfer_frac) + + end if - ! Check that the stem drop fraction is set to non-zero amount - ! otherwise flush all carbon store to leaves - if (stem_drop_fraction .gt. 0.0_r8) then - - call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & - store_c_transfer_frac*target_leaf_c/deficit_c) - - call PRTPhenologyFlush(currentCohort%prt, ipft, sapw_organ, & - store_c_transfer_frac*(target_sapw_c-sapw_c)/deficit_c) - - call PRTPhenologyFlush(currentCohort%prt, ipft, struct_organ, & - store_c_transfer_frac*(target_struct_c-struct_c)/deficit_c) - - else - - call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & - store_c_transfer_frac) - - end if - - endif + endif endif !pft phenology endif ! growing season @@ -1214,10 +1210,12 @@ subroutine phenology_leafonoff(currentSite) call bbgw_allom(currentCohort%dbh,currentCohort%pft,target_bgw_c) call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, currentCohort%pft, target_struct_c) - if(prt_params%woody(ipft) == itrue)then - deficit_c = target_leaf_c - else + if (stem_drop_fraction .gt. 0.0_r8) then + ! Note, this is only true for some grasses, woody plants don't + ! have a stem drop fraction deficit_c = target_leaf_c + (target_sapw_c-sapw_c) + (target_struct_c-struct_c) + else + deficit_c = target_leaf_c end if if(store_c>nearzero) then @@ -1232,31 +1230,23 @@ subroutine phenology_leafonoff(currentSite) ! This call will request that storage carbon will be transferred to ! leaf tissues. It is specified as a fraction of the available storage - if(prt_params%woody(ipft) == itrue) then - - call PRTPhenologyFlush(currentCohort%prt, ipft, & - leaf_organ, store_c_transfer_frac) - + if (stem_drop_fraction .gt. 0.0_r8) then + + call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & + store_c_transfer_frac*target_leaf_c/deficit_c) + + call PRTPhenologyFlush(currentCohort%prt, ipft, sapw_organ, & + store_c_transfer_frac*(target_sapw_c-sapw_c)/deficit_c) + + call PRTPhenologyFlush(currentCohort%prt, ipft, struct_organ, & + store_c_transfer_frac*(target_struct_c-struct_c)/deficit_c) + else - - ! Check that the stem drop fraction is set to non-zero amount otherwise flush all carbon store to leaves - if (stem_drop_fraction .gt. 0.0_r8) then - - call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & - store_c_transfer_frac*target_leaf_c/deficit_c) - - call PRTPhenologyFlush(currentCohort%prt, ipft, sapw_organ, & - store_c_transfer_frac*(target_sapw_c-sapw_c)/deficit_c) - - call PRTPhenologyFlush(currentCohort%prt, ipft, struct_organ, & - store_c_transfer_frac*(target_struct_c-struct_c)/deficit_c) - - else - - call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & - store_c_transfer_frac) - - end if + + call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & + store_c_transfer_frac) + + end if endif ! woody plant check endif !currentCohort status again? From a37749b814bcb6da824be224ca37fb600082dfd5 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 29 Jul 2022 10:20:09 -0400 Subject: [PATCH 301/852] Added call to bagw during leaf flushing --- biogeochem/EDPhysiologyMod.F90 | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index f3072cd4eb..a47d1fe433 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1066,7 +1066,7 @@ subroutine phenology_leafonoff(currentSite) real(r8) :: deficit_c ! Amount of C needed to get flushing pools "on-allometry" real(r8) :: target_leaf_c real(r8) :: target_sapw_c - real(r8) :: target_bgw_c, target_agw_c, target_struct_c + real(r8) :: target_agw_c, target_bgw_c, target_agw_c, target_struct_c real(r8) :: sapw_area integer :: ipft real(r8), parameter :: leaf_drop_fraction = 1.0_r8 @@ -1104,9 +1104,12 @@ subroutine phenology_leafonoff(currentSite) ! stop flow of carbon out of bstore. call bleaf(currentCohort%dbh,currentCohort%pft,currentCohort%canopy_trim,target_leaf_c) - call bsap_allom(currentCohort%dbh,currentCohort%pft,currentCohort%canopy_trim,sapw_area,target_sapw_c) + call bsap_allom(currentCohort%dbh,currentCohort%pft, & + currentCohort%canopy_trim,sapw_area,target_sapw_c) + call bagw_allom(currentCohort%dbh,currentCohort%pft,target_agw_c) call bbgw_allom(currentCohort%dbh,currentCohort%pft,target_bgw_c) - call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, currentCohort%pft, target_struct_c) + call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, & + currentCohort%pft, target_struct_c) if (stem_drop_fraction .gt. 0.0_r8) then ! Note, this is only true for some grasses, woody plants don't @@ -1205,10 +1208,14 @@ subroutine phenology_leafonoff(currentSite) currentCohort%status_coh = leaves_on ! Leaves are on, so change status to ! stop flow of carbon out of bstore. - call bleaf(currentCohort%dbh,currentCohort%pft,currentCohort%canopy_trim,target_leaf_c) - call bsap_allom(currentCohort%dbh,currentCohort%pft,currentCohort%canopy_trim,sapw_area,target_sapw_c) + call bleaf(currentCohort%dbh,currentCohort%pft,& + currentCohort%canopy_trim,target_leaf_c) + call bsap_allom(currentCohort%dbh,currentCohort%pft, & + currentCohort%canopy_trim,sapw_area,target_sapw_c) + call bagw_allom(currentCohort%dbh,currentCohort%pft,target_agw_c) call bbgw_allom(currentCohort%dbh,currentCohort%pft,target_bgw_c) - call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, currentCohort%pft, target_struct_c) + call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, & + currentCohort%pft, target_struct_c) if (stem_drop_fraction .gt. 0.0_r8) then ! Note, this is only true for some grasses, woody plants don't From 36491b99343f2cc5fc634c736477cc4f13c2525b Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 29 Jul 2022 15:10:01 -0400 Subject: [PATCH 302/852] Adding recruit l2fr and smoothing to the f_cn function --- biogeochem/EDCanopyStructureMod.F90 | 11 +- biogeochem/EDCohortDynamicsMod.F90 | 53 +++++----- biogeochem/EDPatchDynamicsMod.F90 | 3 +- biogeochem/EDPhysiologyMod.F90 | 149 ++++++++++++++++++++++++++-- main/EDInitMod.F90 | 17 ++-- main/EDMainMod.F90 | 19 ++++ main/EDTypesMod.F90 | 43 +++++--- main/FatesHistoryInterfaceMod.F90 | 43 ++++---- main/FatesInterfaceMod.F90 | 2 +- main/FatesRestartInterfaceMod.F90 | 52 +++++++++- main/FatesRunningMeanMod.F90 | 15 +-- parteh/PRTAllometricCNPMod.F90 | 96 +++++++++--------- parteh/PRTGenericMod.F90 | 5 + parteh/PRTParametersMod.F90 | 13 +-- parteh/PRTParamsFATESMod.F90 | 27 ++--- 15 files changed, 370 insertions(+), 178 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 2e0ad6159e..bbca1054e9 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -671,14 +671,14 @@ subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr,bc_in) ! correct boundary condition fields copyc%prt => null() call InitPRTObject(copyc%prt) - call InitPRTBoundaryConditions(copyc) if( hlm_use_planthydro.eq.itrue ) then call InitHydrCohort(currentSite,copyc) endif call copy_cohort(currentCohort, copyc) - + call InitPRTBoundaryConditions(copyc,currentCohort%pft,1) + newarea = currentCohort%c_area - cc_loss copyc%n = currentCohort%n*newarea/currentCohort%c_area currentCohort%n = currentCohort%n - copyc%n @@ -1130,7 +1130,7 @@ subroutine PromoteIntoLayer(currentSite,currentPatch,i_lyr) ! correct boundary condition fields copyc%prt => null() call InitPRTObject(copyc%prt) - call InitPRTBoundaryConditions(copyc) + if( hlm_use_planthydro.eq.itrue ) then call InitHydrCohort(CurrentSite,copyc) @@ -1143,7 +1143,8 @@ subroutine PromoteIntoLayer(currentSite,currentPatch,i_lyr) ! init_value=currentPatch%tveg_lpa%GetMean()) call copy_cohort(currentCohort, copyc) !makes an identical copy... - + call InitPRTBoundaryConditions(copyc,currentCohort%pft,2) + newarea = currentCohort%c_area - cc_gain !new area of existing cohort call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread, & @@ -1331,8 +1332,6 @@ subroutine canopy_summarization( nsites, sites, bc_in ) do while(associated(currentCohort)) ft = currentCohort%pft - - leaf_c = currentCohort%prt%GetState(leaf_organ, carbon12_element) sapw_c = currentCohort%prt%GetState(sapw_organ, carbon12_element) struct_c = currentCohort%prt%GetState(struct_organ, carbon12_element) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index da2f4ad256..234dc1bc9d 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -19,7 +19,7 @@ module EDCohortDynamicsMod use FatesConstantsMod , only : nearzero use FatesConstantsMod , only : calloc_abs_error use FatesConstantsMod , only : sec_per_day - use FatesRunningMeanMod , only : ema_lpa, ema_60day + use FatesRunningMeanMod , only : ema_lpa, ema_60day, ema_storemem use FatesInterfaceTypesMod , only : hlm_days_per_year use FatesInterfaceTypesMod , only : nleafage use SFParamsMod , only : SF_val_CWD_frac @@ -94,8 +94,11 @@ module EDCohortDynamicsMod use PRTAllometricCNPMod, only : cnp_allom_prt_vartypes use PRTAllometricCNPMod, only : acnp_bc_in_id_pft, acnp_bc_in_id_ctrim use PRTAllometricCNPMod, only : acnp_bc_in_id_lstat, acnp_bc_inout_id_dbh - !use PRTAllometricCNPMod, only : acnp_bc_in_id_l2fr_ema + use PRTAllometricCNPMod, only : acnp_bc_inout_id_nc_store + use PRTAllometricCNPMod, only : acnp_bc_inout_id_pc_store use PRTAllometricCNPMod, only : acnp_bc_inout_id_l2fr + use PRTAllometricCNPMod, only : acnp_bc_in_id_nc_repro + use PRTAllometricCNPMod, only : acnp_bc_in_id_pc_repro use PRTAllometricCNPMod, only : acnp_bc_inout_id_resp_excess, acnp_bc_in_id_netdc use PRTAllometricCNPMod, only : acnp_bc_inout_id_netdn, acnp_bc_inout_id_netdp use PRTAllometricCNPMod, only : acnp_bc_out_id_cefflux, acnp_bc_out_id_nefflux @@ -217,8 +220,7 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & ! The PARTEH cohort object should be allocated and already ! initialized in this routine. call new_cohort%prt%CheckInitialConditions() - - + !**********************/ ! Define cohort state variable !**********************/ @@ -250,6 +252,8 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & new_cohort%l2fr = prt_params%allom_l2fr(pft) + new_cohort%nc_store = 1._r8 ! Assume balanced N/C stores + new_cohort%pc_store = 1._r8 ! Assume balanced P/C stores ! This sets things like vcmax25top, that depend on the ! leaf age fractions (which are defined by PARTEH) @@ -324,7 +328,7 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & !! allocate(new_cohort%tveg_lpa) !! call new_cohort%tveg_lpa%InitRMean(ema_lpa,init_value=patchptr%tveg_lpa%GetMean()) - call InitPRTBoundaryConditions(new_cohort) + call InitPRTBoundaryConditions(new_cohort,pft,0) ! Recuits do not have mortality rates, nor have they moved any @@ -385,7 +389,7 @@ end subroutine create_cohort ! ------------------------------------------------------------------------------------- - subroutine InitPRTBoundaryConditions(new_cohort) + subroutine InitPRTBoundaryConditions(new_cohort,ft,call_id) ! Set the boundary conditions that flow in an out of the PARTEH ! allocation hypotheses. Each of these calls to "RegsterBC" are simply @@ -406,8 +410,9 @@ subroutine InitPRTBoundaryConditions(new_cohort) ! value boundary condition. type(ed_cohort_type), intent(inout), target :: new_cohort - - + integer,intent(in) :: ft ! PFT index + integer,intent(in) :: call_id + select case(hlm_parteh_mode) case (prt_carbon_allom_hyp) @@ -425,12 +430,15 @@ subroutine InitPRTBoundaryConditions(new_cohort) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_ctrim,bc_rval = new_cohort%canopy_trim) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_lstat,bc_ival = new_cohort%status_coh) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdc, bc_rval = new_cohort%npp_acc) - - !!call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_l2fr_ema, bc_rval = new_cohort%l2fr_ema%l_mean) + + call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_nc_repro,bc_rval = new_cohort%patchptr%nitr_repro_stoich(ft)) + call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_pc_repro,bc_rval = new_cohort%patchptr%phos_repro_stoich(ft)) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_dbh,bc_rval = new_cohort%dbh) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_resp_excess,bc_rval = new_cohort%resp_excess) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_l2fr,bc_rval = new_cohort%l2fr) + call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_nc_store,bc_rval = new_cohort%nc_store) + call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_pc_store,bc_rval = new_cohort%pc_store) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_netdn, bc_rval = new_cohort%daily_n_gain) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_netdp, bc_rval = new_cohort%daily_p_uptake) @@ -594,8 +602,7 @@ subroutine nan_cohort(cc_p) currentCohort%daily_p_efflux = nan currentCohort%daily_n_demand = nan currentCohort%daily_p_demand = nan - - + currentCohort%c13disc_clm = nan ! C13 discrimination, per mil at indiv/timestep currentCohort%c13disc_acc = nan ! C13 discrimination, per mil at indiv/timestep at indiv/daily at the end of a day @@ -1019,11 +1026,6 @@ subroutine DeallocateCohort(currentCohort) type(ed_cohort_type),intent(inout) :: currentCohort - ! (Keeping as an example) - ! Remove the running mean structure - ! deallocate(currentCohort%tveg_lpa) - !!deallocate(currentCohort%l2fr_ema) - ! At this point, nothing should be pointing to current Cohort if (hlm_use_planthydro.eq.itrue) call DeallocateHydrCohort(currentCohort) @@ -1188,12 +1190,10 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) end do end if - ! (Keeping as an example) - ! Running mean fuses based on number density fraction just - ! like other variables - !!call currentCohort%tveg_lpa%FuseRMean(nextc%tveg_lpa,currentCohort%n/newn) - - !!call currentCohort%l2fr_ema%FuseRMean(nextc%l2fr_ema,currentCohort%n/newn) + currentCohort%nc_store = (currentCohort%n*currentCohort%nc_store & + + nextc%n*nextc%nc_store)/newn + currentCohort%pc_store = (currentCohort%n*currentCohort%pc_store & + + nextc%n*nextc%pc_store)/newn ! new cohort age is weighted mean of two cohorts currentCohort%coage = & @@ -1839,11 +1839,10 @@ subroutine copy_cohort( currentCohort,copyc ) n%tpu25top = o%tpu25top n%kp25top = o%kp25top - ! (Keeping as an example) ! Copy over running means - ! call n%tveg_lpa%CopyFromDonor(o%tveg_lpa) - !!call n%l2fr_ema%CopyFromDonor(o%l2fr_ema) - + n%nc_store = o%nc_store + n%pc_store = o%pc_store + ! CARBON FLUXES n%gpp_acc_hold = o%gpp_acc_hold n%gpp_acc = o%gpp_acc diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 456f49304c..1d24db1896 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -706,7 +706,8 @@ subroutine spawn_patches( currentSite, bc_in) ! correct boundary condition fields nc%prt => null() call InitPRTObject(nc%prt) - call InitPRTBoundaryConditions(nc) + nc%patchptr => new_patch + call InitPRTBoundaryConditions(nc,currentCohort%pft,3) call zero_cohort(nc) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index c55110c266..f381c53347 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -48,6 +48,7 @@ module EDPhysiologyMod use EDTypesMod , only : nlevleaf use EDTypesMod , only : num_vegtemp_mem use EDTypesMod , only : maxpft + use EDTypesMod , only : nclmax use EDTypesMod , only : ed_site_type, ed_patch_type, ed_cohort_type use EDTypesMod , only : leaves_on use EDTypesMod , only : leaves_off @@ -106,6 +107,7 @@ module EDPhysiologyMod use PRTLossFluxesMod, only : PRTDeciduousTurnover use PRTLossFluxesMod, only : PRTReproRelease use PRTGenericMod, only : StorageNutrientTarget + use PRTInitParamsFatesMod, only : NewRecruitTotalStoichiometry implicit none private @@ -116,12 +118,14 @@ module EDPhysiologyMod public :: assign_cohort_SP_properties public :: recruitment public :: ZeroLitterFluxes - public :: ZeroAllocationRates public :: PreDisturbanceLitterFluxes public :: PreDisturbanceIntegrateLitter public :: SeedIn - + public :: UpdateRecruitL2FR + public :: UpdateRecruitStoich + public :: SetRecruitL2FR + logical, parameter :: debug = .false. ! local debug flag character(len=*), parameter, private :: sourcefile = & __FILE__ @@ -1675,15 +1679,16 @@ subroutine SeedIn( currentSite, bc_in ) litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)/area ! If there is forced external seed rain, we calculate the input mass flux - ! from the different elements, usung the seed optimal stoichiometry - ! for non-carbon + ! from the different elements, usung the mean stoichiometry of new + ! recruits for the current patch and lowest canopy position + select case(element_id) case(carbon12_element) seed_stoich = 1._r8 case(nitrogen_element) - seed_stoich = prt_params%nitr_recr_stoich(pft) + seed_stoich = currentPatch%nitr_repro_stoich(pft) case(phosphorus_element) - seed_stoich = prt_params%phos_recr_stoich(pft) + seed_stoich = currentPatch%phos_repro_stoich(pft) case default write(fates_log(), *) 'undefined element specified' write(fates_log(), *) 'while defining forced external seed mass flux' @@ -1866,7 +1871,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) temp_cohort%pft = ft temp_cohort%hite = EDPftvarcon_inst%hgt_min(ft) temp_cohort%coage = 0.0_r8 - temp_cohort%l2fr = prt_params%allom_l2fr(ft) + temp_cohort%l2fr = currentSite%rec_l2fr(ft,currentPatch%NCL_p) stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(ft) call h2d_allom(temp_cohort%hite,ft,temp_cohort%dbh) @@ -2583,4 +2588,134 @@ subroutine CWDOut( litt, fragmentation_scaler, nlev_eff_decomp ) end subroutine CWDOut + ! ====================================================================== + + subroutine UpdateRecruitL2FR(csite) + + type(ed_site_type) :: csite + type(ed_patch_type), pointer :: cpatch + type(ed_cohort_type), pointer :: ccohort + + real(r8) :: rec_n(maxpft,nclmax) ! plant count + real(r8) :: rec_l2fr0(maxpft,nclmax) ! mean l2fr for this day + integer :: rec_count(maxpft,nclmax) ! sample count + integer :: ft ! functional type index + integer :: cl ! canopy layer index + real(r8) :: dbh_min ! the dbh of a recruit + real(r8), parameter :: max_delta = 5.0_r8 ! dbh tolerance, cm, consituting a recruit + real(r8), parameter :: smth_wgt = 1._r8/300.0_r8 + integer, parameter :: max_count = 3 + + ! Difference in dbh (cm) to consider a plant was recruited fairly recently + + rec_n(1:numpft,1:nclmax) = 0._r8 + rec_l2fr0(1:numpft,1:nclmax) = 0._r8 + + cpatch => csite%youngest_patch + do while(associated(cpatch)) + + rec_count(1:numpft,1:nclmax) = 0 + + ccohort => cpatch%shortest + cloop: do while(associated(ccohort)) + + ft = ccohort%pft + cl = ccohort%canopy_layer + call h2d_allom(EDPftvarcon_inst%hgt_min(ft),ft,dbh_min) + + if( .not.ccohort%isnew ) then + + if(rec_count(ft,cl) <= max_count .and. & + ccohort%dbh-dbh_min < max_delta ) then + rec_count(ft,cl) = rec_count(ft,cl) + 1 + rec_n(ft,cl) = rec_n(ft,cl) + ccohort%n + rec_l2fr0(ft,cl) = rec_l2fr0(ft,cl) + ccohort%n*ccohort%l2fr + end if + + end if + + ccohort => ccohort%taller + end do cloop + + cpatch => cpatch%older + end do + + ! Find the daily mean for each PFT weighted by number and add it to the running mean + do cl = 1,nclmax + do ft = 1,numpft + if(rec_n(ft,cl)>nearzero)then + rec_l2fr0(ft,cl) = rec_l2fr0(ft,cl) / rec_n(ft,cl) + csite%rec_l2fr(ft,cl) = & + (1._r8-smth_wgt)*csite%rec_l2fr(ft,cl) + smth_wgt*rec_l2fr0(ft,cl) + + !print*,"REC_L2FR:",cl,csite%rec_l2fr(ft,cl) + end if + end do + end do + + return + end subroutine UpdateRecruitL2FR + + ! ====================================================================== + + subroutine UpdateRecruitStoich(csite) + + type(ed_site_type) :: csite + type(ed_patch_type), pointer :: cpatch + integer :: ft ! functional type index + integer :: cl ! canopy layer index + real(r8) :: rec_l2fr_pft ! Actual l2fr of a pft in it's patch + + ! Update the total plant stoichiometry of a new recruit, based on the updated + ! L2FR values + cpatch => csite%youngest_patch + do while(associated(cpatch)) + cl = cpatch%ncl_p + do ft = 1,numpft + rec_l2fr_pft = csite%rec_l2fr(ft,cl) + cpatch%nitr_repro_stoich(ft) = & + NewRecruitTotalStoichiometry(ft,rec_l2fr_pft,nitrogen_element) + cpatch%phos_repro_stoich(ft) = & + NewRecruitTotalStoichiometry(ft,rec_l2fr_pft,phosphorus_element) + end do + cpatch => cpatch%older + end do + + return + end subroutine UpdateRecruitStoich + + ! ====================================================================== + + subroutine SetRecruitL2FR(csite) + + ! I DONT THINK THIS ROUTINE IS ACTUALLY NEEDED... + ! TURN THIS OFF IN A B4B TEST + + + type(ed_site_type) :: csite + type(ed_patch_type), pointer :: cpatch + type(ed_cohort_type), pointer :: ccohort + integer :: ft,cl + + cpatch => csite%youngest_patch + do while(associated(cpatch)) + ccohort => cpatch%shortest + cloop: do while(associated(ccohort)) + + if( ccohort%isnew ) then + ft = ccohort%pft + cl = ccohort%canopy_layer + ccohort%l2fr = csite%rec_l2fr(ft,cl) + end if + + ccohort => ccohort%taller + end do cloop + + cpatch => cpatch%older + end do + + return + end subroutine SetRecruitL2FR + + end module EDPhysiologyMod diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index e51d506b05..775681f4ee 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -13,7 +13,7 @@ module EDInitMod use FatesGlobals , only : endrun => fates_endrun use EDTypesMod , only : nclmax use FatesGlobals , only : fates_log - use FatesInterfaceTypesMod , only : hlm_is_restart + use FatesInterfaceTypesMod , only : hlm_is_restart use EDPftvarcon , only : EDPftvarcon_inst use PRTParametersMod , only : prt_params use EDCohortDynamicsMod , only : create_cohort, fuse_cohorts, sort_cohorts @@ -143,6 +143,10 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) allocate(site_in%use_this_pft(1:numpft)) allocate(site_in%area_by_age(1:nlevage)) + ! for CNP dynamics, track the mean l2fr of recruits + ! for different pfts and canopy positions + allocate(site_in%rec_l2fr(1:numpft,nclmax)) + ! SP mode allocate(site_in%sp_tlai(1:numpft)) @@ -326,6 +330,10 @@ subroutine set_site_properties( nsites, sites,bc_in ) sites(s)%NF = 0.0_r8 sites(s)%NF_successful = 0.0_r8 + do ft = 1,numpft + sites(s)%rec_l2fr(ft,:) = prt_params%allom_l2fr(ft) + end do + if(hlm_use_fixed_biogeog.eq.itrue)then ! MAPPING OF FATES PFTs on to HLM_PFTs ! add up the area associated with each FATES PFT @@ -417,9 +425,6 @@ subroutine init_patches( nsites, sites, bc_in) ! This may be call a near bare ground initialization, or it may ! load patches from an inventory. - ! - - use FatesPlantHydraulicsMod, only : updateSizeDepRhizHydProps use FatesInventoryInitMod, only : initialize_sites_by_inventory @@ -851,7 +856,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) m_leaf = c_leaf*prt_params%nitr_stoich_p2(pft,prt_params%organ_param_id(leaf_organ)) m_fnrt = c_fnrt*prt_params%nitr_stoich_p2(pft,prt_params%organ_param_id(fnrt_organ)) m_sapw = c_sapw*prt_params%nitr_stoich_p2(pft,prt_params%organ_param_id(sapw_organ)) - m_repro = 0._r8 + m_repro = 0._r8 m_store = StorageNutrientTarget(pft,element_id,m_leaf,m_fnrt,m_sapw,m_struct) case(phosphorus_element) @@ -860,7 +865,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) m_leaf = c_leaf*prt_params%phos_stoich_p2(pft,prt_params%organ_param_id(leaf_organ)) m_fnrt = c_fnrt*prt_params%phos_stoich_p2(pft,prt_params%organ_param_id(fnrt_organ)) m_sapw = c_sapw*prt_params%phos_stoich_p2(pft,prt_params%organ_param_id(sapw_organ)) - m_repro = 0._r8 + m_repro = 0._r8 m_store = StorageNutrientTarget(pft,element_id,m_leaf,m_fnrt,m_sapw,m_struct) end select diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 28fefe9da2..5aaa4f25f2 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -48,6 +48,9 @@ module EDMainMod use EDPhysiologyMod , only : ZeroLitterFluxes use EDPhysiologyMod , only : PreDisturbanceLitterFluxes use EDPhysiologyMod , only : PreDisturbanceIntegrateLitter + use EDPhysiologyMod , only : UpdateRecruitL2FR + use EDPhysiologyMod , only : UpdateRecruitStoich + use EDPhysiologyMod , only : SetRecruitL2FR use FatesSoilBGCFluxMod , only : FluxIntoLitterPools use FatesSoilBGCFluxMod , only : EffluxIntoLitterPools use EDCohortDynamicsMod , only : UpdateCohortBioPhysRates @@ -349,6 +352,13 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! Set a pointer to this sites carbon12 mass balance site_cmass => currentSite%mass_balance(element_pos(carbon12_element)) + ! This call updates the assessment of the total stoichiometry + ! for a new recruit, based on its PFT and the L2FR of + ! a new recruit. This is called here, because it is + ! prior to the growth sequence, where reproductive + ! tissues are allocated + call UpdateRecruitStoich(currentSite) + currentPatch => currentSite%youngest_patch do while(associated(currentPatch)) @@ -542,6 +552,12 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) end do + ! We keep a record of the L2FRs of plants + ! that are near the recruit size, for different + ! pfts and canopy layer. We use this mean to + ! set the L2FRs of newly recruited plants + call UpdateRecruitL2FR(currentSite) + ! When plants die, the water goes with them. This effects ! the water balance. @@ -638,6 +654,9 @@ subroutine ed_update_site( currentSite, bc_in, bc_out ) call TotalBalanceCheck(currentSite,final_check_id) + ! Update recruit L2FRs based on new canopy position + call SetRecruitL2FR(currentSite) + currentSite%area_by_age(:) = 0._r8 currentPatch => currentSite%oldest_patch diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 0a9d46eb30..7adba898a1 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -220,10 +220,13 @@ module EDTypesMod ! vary between allom_l2fr_min and allom_l2fr_max ! parameters, with a tendency driven by ! nutrient storage) - - integer :: cnp_limiter ! Which species is limiting growth? ! 0=none,1=C,2=N,3=P - !!class(rmean_type), pointer :: l2fr_ema ! Exponential moving average of the L2FR + + ! Used for CNP + integer :: cnp_limiter ! Which species is limiting growth? ! 0=none,1=C,2=N,3=P + real(r8) :: nc_store ! Exponential moving average of the log of the N/C storage ratio + real(r8) :: pc_store ! Exponential moving average of the log of the P/C storage ratio + ! VEGETATION STRUCTURE integer :: pft ! pft number @@ -437,6 +440,8 @@ module EDTypesMod class(rmean_type), pointer :: tveg24 ! 24-hour mean vegetation temperature (K) class(rmean_type), pointer :: tveg_lpa ! Running mean of vegetation temperature at the ! leaf photosynthesis acclimation timescale [K] + + integer :: nocomp_pft_label ! where nocomp is active, use this label for patch ID. ! LEAF ORGANIZATION @@ -537,18 +542,25 @@ module EDTypesMod real(r8) :: psn_z(nclmax,maxpft,nlevleaf) ! carbon assimilation in each canopy layer, pft, and leaf layer. umolC/m2/s ! ROOTS - real(r8) :: btran_ft(maxpft) ! btran calculated seperately for each PFT:- - real(r8) :: bstress_sal_ft(maxpft) ! bstress from salinity calculated seperately for each PFT:- - + real(r8) :: btran_ft(maxpft) ! btran calculated seperately for each PFT:- + real(r8) :: bstress_sal_ft(maxpft) ! bstress from salinity calculated seperately for each PFT:- + +! real(r8), pointer :: rec_l2fr_pft(:) ! A pointer array that points + ! to the lowest canopy position of site%rec_l2fr + ! Thus, this is the l2fr of any new recruit in the + ! current patch, according to its PFT + real(r8) :: nitr_repro_stoich(maxpft) ! The NC ratio of a new recruit in this patch + real(r8) :: phos_repro_stoich(maxpft) ! The PC ratio of a new recruit in this patch - ! DISTURBANCE - real(r8) :: disturbance_rates(n_dist_types) ! disturbance rate from 1) mortality - ! 2) fire: fraction/day - ! 3) logging mortatliy - real(r8) :: disturbance_rate ! larger effective disturbance rate: fraction/day - integer :: disturbance_mode ! index identifying which disturbance was applied - ! can be one of: dtype_ifall, dtype_ilog or dtype_ifire - real(r8) :: fract_ldist_not_harvested ! fraction of logged area that is canopy trees that weren't harvested + + ! DISTURBANCE + real(r8) :: disturbance_rates(n_dist_types) ! disturbance rate from 1) mortality + ! 2) fire: fraction/day + ! 3) logging mortatliy + real(r8) :: disturbance_rate ! larger effective disturbance rate: fraction/day + integer :: disturbance_mode ! index identifying which disturbance was applied + ! can be one of: dtype_ifall, dtype_ilog or dtype_ifire + real(r8) :: fract_ldist_not_harvested ! fraction of logged area that is canopy trees that weren't harvested ! Litter and Coarse Woody Debris @@ -720,6 +732,9 @@ module EDTypesMod ! Total area of patches in each age bin [m2] real(r8), allocatable :: area_by_age(:) + real(r8), allocatable :: rec_l2fr(:,:) ! A running mean of the l2fr's for the newly + ! recruited, pft x canopy_layer + ! SP mode target PFT level variables real(r8), allocatable :: sp_tlai(:) ! target TLAI per FATES pft real(r8), allocatable :: sp_tsai(:) ! target TSAI per FATES pft diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 9f645c81c4..c5223c18f5 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -187,11 +187,10 @@ module FatesHistoryInterfaceMod integer :: ih_totvegp_si integer :: ih_l2fr_si - !!integer :: ih_l2fr_ema_si - integer :: ih_l2fr_scpf integer :: ih_l2fr_canopy_scpf integer :: ih_l2fr_understory_scpf - + integer :: ih_recl2fr_canopy_pf + integer :: ih_recl2fr_ustory_pf integer :: ih_nh4uptake_si integer :: ih_no3uptake_si integer :: ih_puptake_si @@ -2001,8 +2000,8 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_ncohorts_si => this%hvars(ih_ncohorts_si)%r81d, & hio_trimming_si => this%hvars(ih_trimming_si)%r81d, & hio_l2fr_si => this%hvars(ih_l2fr_si)%r81d, & - !!hio_l2fr_ema_si => this%hvars(ih_l2fr_ema_si)%r81d, & - hio_l2fr_scpf => this%hvars(ih_l2fr_scpf)%r82d, & + hio_recl2fr_canopy_pf => this%hvars(ih_recl2fr_canopy_pf)%r82d, & + hio_recl2fr_ustory_pf => this%hvars(ih_recl2fr_ustory_pf)%r82d, & hio_l2fr_canopy_scpf => this%hvars(ih_l2fr_canopy_scpf)%r82d, & hio_l2fr_understory_scpf => this%hvars(ih_l2fr_understory_scpf)%r82d, & hio_area_plant_si => this%hvars(ih_area_plant_si)%r81d, & @@ -2278,6 +2277,11 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) sites(s)%mass_balance(element_pos(carbon12_element))%burn_flux_to_atm * & ha_per_m2 * days_per_sec + do ft = 1,numpft + hio_recl2fr_canopy_pf(io_si,ft) = sites(s)%rec_l2fr(ft,1) + hio_recl2fr_ustory_pf(io_si,ft) = sites(s)%rec_l2fr(ft,2) + end do + do el = 1, num_elements ! Total model error [kg/day -> kg/s] (all elements) @@ -2554,11 +2558,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_l2fr_si(io_si) = hio_l2fr_si(io_si) + ccohort%n*fnrt_m/m2_per_ha*ccohort%l2fr - !!hio_l2fr_ema_si(io_si) = hio_l2fr_ema_si(io_si) + ccohort%n*fnrt_m/m2_per_ha*ccohort%l2fr_ema%GetMean() - - hio_l2fr_scpf(io_si,i_scpf) = & - hio_l2fr_scpf(io_si,i_scpf) + ccohort%n*fnrt_m/m2_per_ha*ccohort%l2fr - ! Constrain L2FR to oldest patch? if(do_site_l2fr_scpf .or. associated(cpatch,sites(s)%oldest_patch)) then if (ccohort%canopy_layer .eq. 1) then @@ -3636,10 +3635,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) do i_pft = 1, numpft do i_scls = 1,nlevsclass i_scpf = (i_pft-1)*nlevsclass + i_scls - if(this%hvars(ih_fnrtc_scpf)%r82d(io_si,i_scpf)>nearzero)then - hio_l2fr_scpf(io_si,i_scpf) = hio_l2fr_scpf(io_si,i_scpf) / & - this%hvars(ih_fnrtc_scpf)%r82d(io_si,i_scpf) - end if if(fnrtc_canopy_scpf(i_scpf)>nearzero)then hio_l2fr_canopy_scpf(io_si,i_scpf) = & hio_l2fr_canopy_scpf(io_si,i_scpf)/fnrtc_canopy_scpf(i_scpf) @@ -4631,6 +4626,7 @@ subroutine define_history_vars(this, initialize_variables) ! patch age x pft (site_agepft_r8) : APPF ! canopy layer x leaf layer (site_cnlf_r8) : CLLL ! canopy layer x leaf layer x pft (site_cnlfpft_r8) : CLLLPF + ! canopy layer x pft (site_clpf_r8) : CLPF ! element x cwd size (site_elcwd_r8) : ELDC ! cohort size x patch age (site_scag_r8) : SZAP ! cohort size x patch age x pft (site_scagpft_r8) : SZAPPF @@ -4667,18 +4663,17 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_l2fr_si) - !!call this%set_history_var(vname='FATES_L2FR_EMA', units='kg kg-1', & - !! long='Moving average of the leaf to fineroot biomass multiplier for target allometry', & - !! use_default='active', & - !! avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - !! ivar=ivar, initialize=initialize_variables, index = ih_l2fr_ema_si) + call this%set_history_var(vname='FATES_RECL2FR_CANOPY_PF', units='kg kg-1', & + long='The leaf to fineroot biomass multiplier for recruits (canopy)', & + use_default='active', & + avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_recl2fr_canopy_pf) - - call this%set_history_var(vname='FATES_L2FR_SZPF', units='kg kg-1', & - long='The leaf to fineroot biomass multiplier for target allometry', & + call this%set_history_var(vname='FATES_RECL2FR_USTORY_PF', units='kg kg-1', & + long='The leaf to fineroot biomass multiplier for recruits (understory)', & use_default='active', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_l2fr_scpf) + avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_recl2fr_ustory_pf) call this%set_history_var(vname='FATES_L2FR_CANOPY_SZPF', units='kg kg-1', & long='The leaf to fineroot biomass multiplier for target allometry in canopy plants', & diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index b70d680437..af4c7d2dc0 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -926,7 +926,7 @@ subroutine InitTimeAveragingGlobals() allocate(ema_lpa) call ema_lpa%define(photo_temp_acclim_timescale*sec_per_day, & hlm_stepsize,moving_ema_window) - + !allocate(ema_60day) !call ema_60day%define(prt_params%fnrt_adapt_tscl*sec_per_day,sec_per_day,moving_ema_window) !class(rmean_arr_type), pointer :: ema_fnrt_tscale(:) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 23787241bb..15604aba25 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -96,6 +96,8 @@ module FatesRestartInterfaceMod integer :: ir_canopy_layer_yesterday_co integer :: ir_canopy_trim_co integer :: ir_l2fr_co + integer :: ir_nc_store_co + integer :: ir_pc_store_co integer :: ir_size_class_lasttimestep_co integer :: ir_dbh_co integer :: ir_coage_co @@ -184,6 +186,7 @@ module FatesRestartInterfaceMod integer :: ir_litter_moisture_pa_nfsc ! Site level + integer :: ir_recl2fr_sipfcl integer :: ir_watermem_siwm integer :: ir_vegtempmem_sitm integer :: ir_seed_bank_sift @@ -696,6 +699,14 @@ subroutine define_restart_vars(this, initialize_variables) call this%set_restart_var(vname='fates_l2fr', vtype=cohort_r8, & long_name='ed cohort - l2fr', units='fraction', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_l2fr_co ) + + call this%set_restart_var(vname='fates_nc_store', vtype=cohort_r8, & + long_name='ed cohort - nc_store', units='fraction', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_nc_store_co ) + + call this%set_restart_var(vname='fates_pc_store', vtype=cohort_r8, & + long_name='ed cohort - pc_store', units='fraction', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_pc_store_co ) call this%set_restart_var(vname='fates_size_class_lasttimestep', vtype=cohort_int, & long_name='ed cohort - size-class last timestep', units='index', flushval = flushzero, & @@ -1121,7 +1132,11 @@ subroutine define_restart_vars(this, initialize_variables) ! ! site x time level vars ! - + call this%set_restart_var(vname='fates_recruit_l2fr', vtype=cohort_r8, & + long_name='site-level mean recruit l2frs, by pft x canopy layer', & + units='-', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_recl2fr_sipfcl) + call this%set_restart_var(vname='fates_water_memory', vtype=cohort_r8, & long_name='last 10 days of volumetric soil water, by site x day-index', & units='m3/m3', flushval = flushzero, & @@ -1677,6 +1692,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) integer :: io_idx_pa_dc ! each decomposability index integer :: io_idx_pa_ib ! each SW band (vis/ir) per patch (pa_ib) integer :: io_idx_si_wmem ! each water memory class within each site + integer :: io_idx_si_pfcl ! each pft x canopy layer within each site integer :: io_idx_si_lyr_shell ! site - layer x shell index integer :: io_idx_si_scpf ! each size-class x pft index within site integer :: io_idx_si_sc ! each size-class index within site @@ -1732,6 +1748,8 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_canopy_layer_yesterday_co => this%rvars(ir_canopy_layer_yesterday_co)%r81d, & rio_canopy_trim_co => this%rvars(ir_canopy_trim_co)%r81d, & rio_l2fr_co => this%rvars(ir_l2fr_co)%r81d, & + rio_nc_store_co => this%rvars(ir_nc_store_co)%r81d, & + rio_pc_store_co => this%rvars(ir_pc_store_co)%r81d, & rio_seed_prod_co => this%rvars(ir_seed_prod_co)%r81d, & rio_size_class_lasttimestep => this%rvars(ir_size_class_lasttimestep_co)%int1d, & rio_dbh_co => this%rvars(ir_dbh_co)%r81d, & @@ -1779,6 +1797,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_nocomp_pft_label_pa => this%rvars(ir_nocomp_pft_label_pa)%int1d, & rio_area_pa => this%rvars(ir_area_pa)%r81d, & rio_watermem_siwm => this%rvars(ir_watermem_siwm)%r81d, & + rio_recl2fr_sipfcl => this%rvars(ir_recl2fr_sipfcl)%r81d, & rio_vegtempmem_sitm => this%rvars(ir_vegtempmem_sitm)%r81d, & rio_recrate_sift => this%rvars(ir_recrate_sift)%r81d, & rio_use_this_pft_sift => this%rvars(ir_use_this_pft_sift)%int1d, & @@ -1823,6 +1842,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) io_idx_co = io_idx_co_1st io_idx_pa_ib = io_idx_co_1st io_idx_si_wmem = io_idx_co_1st + io_idx_si_pfcl = io_idx_co_1st io_idx_si_vtmem = io_idx_co_1st io_idx_pa_ncl = io_idx_co_1st @@ -1947,6 +1967,8 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_canopy_layer_yesterday_co(io_idx_co) = ccohort%canopy_layer_yesterday rio_canopy_trim_co(io_idx_co) = ccohort%canopy_trim rio_l2fr_co(io_idx_co) = ccohort%l2fr + rio_nc_store_co(io_idx_co) = ccohort%nc_store + rio_pc_store_co(io_idx_co) = ccohort%pc_store rio_seed_prod_co(io_idx_co) = ccohort%seed_prod rio_size_class_lasttimestep(io_idx_co) = ccohort%size_class_lasttimestep rio_dbh_co(io_idx_co) = ccohort%dbh @@ -2164,7 +2186,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) io_idx_si_scpf = io_idx_si_scpf + 1 end do - rio_demorate_sisc(io_idx_si_sc) = sites(s)%demotion_rate(i_scls) + rio_demorate_sisc(io_idx_si_sc) = sites(s)%demotion_rate(i_scls) rio_promrate_sisc(io_idx_si_sc) = sites(s)%promotion_rate(i_scls) io_idx_si_sc = io_idx_si_sc + 1 @@ -2197,6 +2219,13 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_npatch_si(io_idx_si) = patchespersite + do i = 1,nclmax + do i_pft = 1, numpft + rio_recl2fr_sipfcl(io_idx_si_pfcl ) = sites(s)%rec_l2fr(i_pft,i) + io_idx_si_pfcl = io_idx_si_pfcl + 1 + end do + end do + do i = 1,numWaterMem ! numWaterMem currently 10 rio_watermem_siwm( io_idx_si_wmem ) = sites(s)%water_memory(i) io_idx_si_wmem = io_idx_si_wmem + 1 @@ -2385,7 +2414,7 @@ subroutine create_patchcohort_structure(this, nc, nsites, sites, bc_in, bc_out) ! correct boundary condition fields new_cohort%prt => null() call InitPRTObject(new_cohort%prt) - call InitPRTBoundaryConditions(new_cohort) + ! Allocate hydraulics arrays @@ -2498,6 +2527,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) integer :: io_idx_pa_dc ! each decomposability index integer :: io_idx_pa_ib ! each SW radiation band per patch (pa_ib) integer :: io_idx_si_wmem ! each water memory class within each site + integer :: io_idx_si_pfcl ! each pft x canopy layer class within each site integer :: io_idx_si_vtmem ! counter for vegetation temp memory integer :: io_idx_si_lyr_shell ! site - layer x shell index integer :: io_idx_si_scpf ! each size-class x pft index within site @@ -2545,6 +2575,8 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_canopy_layer_yesterday_co => this%rvars(ir_canopy_layer_yesterday_co)%r81d, & rio_canopy_trim_co => this%rvars(ir_canopy_trim_co)%r81d, & rio_l2fr_co => this%rvars(ir_l2fr_co)%r81d, & + rio_nc_store_co => this%rvars(ir_nc_store_co)%r81d, & + rio_pc_store_co => this%rvars(ir_pc_store_co)%r81d, & rio_seed_prod_co => this%rvars(ir_seed_prod_co)%r81d, & rio_size_class_lasttimestep => this%rvars(ir_size_class_lasttimestep_co)%int1d, & rio_dbh_co => this%rvars(ir_dbh_co)%r81d, & @@ -2591,6 +2623,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_agesinceanthrodist_pa => this%rvars(ir_agesinceanthrodist_pa)%r81d, & rio_nocomp_pft_label_pa => this%rvars(ir_nocomp_pft_label_pa)%int1d, & rio_area_pa => this%rvars(ir_area_pa)%r81d, & + rio_recl2fr_sipfcl => this%rvars(ir_recl2fr_sipfcl)%r81d, & rio_watermem_siwm => this%rvars(ir_watermem_siwm)%r81d, & rio_vegtempmem_sitm => this%rvars(ir_vegtempmem_sitm)%r81d, & rio_recrate_sift => this%rvars(ir_recrate_sift)%r81d, & @@ -2625,6 +2658,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) io_idx_co = io_idx_co_1st io_idx_pa_ib = io_idx_co_1st io_idx_si_wmem = io_idx_co_1st + io_idx_si_pfcl = io_idx_co_1st io_idx_si_vtmem = io_idx_co_1st io_idx_pa_ncl = io_idx_co_1st @@ -2732,7 +2766,9 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ccohort%canopy_layer = rio_canopy_layer_co(io_idx_co) ccohort%canopy_layer_yesterday = rio_canopy_layer_yesterday_co(io_idx_co) ccohort%canopy_trim = rio_canopy_trim_co(io_idx_co) - ccohort%l2fr = rio_l2fr_co(io_idx_co) + ccohort%l2fr = rio_l2fr_co(io_idx_co) + ccohort%nc_store = rio_nc_store_co(io_idx_co) + ccohort%pc_store = rio_pc_store_co(io_idx_co) ccohort%seed_prod = rio_seed_prod_co(io_idx_co) ccohort%size_class_lasttimestep = rio_size_class_lasttimestep(io_idx_co) ccohort%dbh = rio_dbh_co(io_idx_co) @@ -2778,6 +2814,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ccohort%status_coh = rio_status_co(io_idx_co) ccohort%isnew = ( rio_isnew_co(io_idx_co) .eq. new_cohort ) + call InitPRTBoundaryConditions(ccohort,ccohort%pft,4) call UpdateCohortBioPhysRates(ccohort) @@ -2949,6 +2986,13 @@ subroutine get_restart_vectors(this, nc, nsites, sites) call endrun(msg=errMsg(sourcefile, __LINE__)) end if + do i = 1,nclmax + do i_pft = 1, numpft + sites(s)%rec_l2fr(i_pft,i) = rio_recl2fr_sipfcl(io_idx_si_pfcl) + io_idx_si_pfcl = io_idx_si_pfcl + 1 + end do + end do + do i = 1,numWaterMem sites(s)%water_memory(i) = rio_watermem_siwm( io_idx_si_wmem ) io_idx_si_wmem = io_idx_si_wmem + 1 diff --git a/main/FatesRunningMeanMod.F90 b/main/FatesRunningMeanMod.F90 index f7887f3fb4..a1c51f6abf 100644 --- a/main/FatesRunningMeanMod.F90 +++ b/main/FatesRunningMeanMod.F90 @@ -93,7 +93,7 @@ module FatesRunningMeanMod class(rmean_def_type), public, pointer :: ema_lpa ! Exponential moving average - leaf photo acclimation class(rmean_def_type), public, pointer :: ema_60day ! Exponential moving average, 60 day ! Updated daily - + class(rmean_def_type), public, pointer :: ema_storemem ! EMA used for smoothing N/C and P/C storage ! If we want to have different running mean specs based on ! pft or other types of constants @@ -309,12 +309,13 @@ subroutine FuseRMean(this,donor,recip_wgt) class(rmean_type) :: this class(rmean_type), pointer :: donor real(r8),intent(in) :: recip_wgt ! Weighting factor for recipient (0-1) - - if(this%def_type%n_mem .ne. donor%def_type%n_mem) then - write(fates_log(), *) 'memory size is somehow different during fusion' - write(fates_log(), *) 'of two running mean variables: '!,this%name,donor%name - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + + ! Unecessary + !if(this%def_type%n_mem .ne. donor%def_type%n_mem) then + ! write(fates_log(), *) 'memory size is somehow different during fusion' + ! write(fates_log(), *) 'of two running mean variables: '!,this%name,donor%name + ! call endrun(msg=errMsg(sourcefile, __LINE__)) + !end if if(this%def_type%method .eq. fixed_window ) then if (this%c_index .ne. donor%c_index) then diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 5115a602b5..6a6b71bda2 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -18,7 +18,7 @@ module PRTAllometricCNPMod use PRTGenericMod , only : nitrogen_element use PRTGenericMod , only : phosphorus_element use PRTGenericMod , only : max_nleafage - + use PRTGenericMod , only : l2fr_min use PRTGenericMod , only : leaf_organ use PRTGenericMod , only : fnrt_organ use PRTGenericMod , only : sapw_organ @@ -147,8 +147,10 @@ module PRTAllometricCNPMod ! is dynamic with CNP integer, public, parameter :: acnp_bc_inout_id_netdn = 4 ! Index for the net daily NH4 input BC integer, public, parameter :: acnp_bc_inout_id_netdp = 5 ! Index for the net daily P input BC - - integer, public, parameter :: num_bc_inout = 5 + integer, public, parameter :: acnp_bc_inout_id_nc_store = 6 ! Index for the EMA log storage ratio N/C + integer, public, parameter :: acnp_bc_inout_id_pc_store = 7 ! Index for the EMA log storage ratio P/C + + integer, public, parameter :: num_bc_inout = 7 ! ------------------------------------------------------------------------------------- ! Input only Boundary Indices (These are public) @@ -158,10 +160,11 @@ module PRTAllometricCNPMod integer, public, parameter :: acnp_bc_in_id_ctrim = 2 ! Index for the canopy trim function integer, public, parameter :: acnp_bc_in_id_lstat = 3 ! phenology status logical integer, public, parameter :: acnp_bc_in_id_netdc = 4 ! Index for the net daily C input BC - + integer, public, parameter :: acnp_bc_in_id_nc_repro = 5 + integer, public, parameter :: acnp_bc_in_id_pc_repro = 6 ! 0=leaf off, 1=leaf on - integer, parameter :: num_bc_in = 4 + integer, parameter :: num_bc_in = 6 ! ------------------------------------------------------------------------------------- ! Output Boundary Indices (These are public) @@ -413,8 +416,7 @@ subroutine DailyPRTAllometricCNP(this) ! Also, we save the initial values of many of these BC's ! for checking and resetting if needed ! ----------------------------------------------------------------------------------- - c_gain = this%bc_in(acnp_bc_in_id_netdc)%rval; c_gain0 = c_gain - + c_gain = this%bc_in(acnp_bc_in_id_netdc)%rval canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival @@ -430,7 +432,7 @@ subroutine DailyPRTAllometricCNP(this) n_gain0 = n_gain p_gain0 = p_gain - + c_gain0 = c_gain ! Calculate Carbon allocation targets ! ----------------------------------------------------------------------------------- @@ -457,13 +459,9 @@ subroutine DailyPRTAllometricCNP(this) ! =================================================================================== ! This routine updates the l2fr (leaf 2 fine-root multiplier) variable - ! It will also update target_c(fnrt_organ) - call this%CNPAdjustFRootTargets(target_c) + ! It will also update the target + call this%CNPAdjustFRootTargets(target_c,target_dcdd) - c_gain0 = c_gain - n_gain0 = n_gain - p_gain0 = p_gain - ! Remember the original C,N,P states to help with final ! evaluation of how much was allocated ! ----------------------------------------------------------------------------------- @@ -627,7 +625,7 @@ subroutine DailyPRTAllometricCNP(this) abs(allocated_n - (n_gain0-n_gain)) > calloc_abs_error .or. & abs(allocated_p - (p_gain0-p_gain)) > calloc_abs_error ) then write(fates_log(),*) 'CNP allocation scheme did not balance mass.' - write(fates_log(),*) 'c_gain0: ',c_gain0,' allocated_c: ',allocated_c + write(fates_log(),*) 'c_gain0: ',c_gain0,' allocated_c: ',allocated_c,resp_excess,resp_excess0,c_efflux write(fates_log(),*) 'n_gain0: ',n_gain0,' allocated_n: ',allocated_n write(fates_log(),*) 'p_gain0: ',p_gain0,' allocated_p: ',allocated_p @@ -669,10 +667,11 @@ subroutine DailyPRTAllometricCNP(this) end subroutine DailyPRTAllometricCNP ! ===================================================================================== - subroutine CNPAdjustFRootTargets(this, target_c) + subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd) class(cnp_allom_prt_vartypes) :: this real(r8) :: target_c(:) + real(r8) :: target_dcdd(:) real(r8), pointer :: l2fr ! leaf to fineroot target biomass scaler integer :: ipft ! PFT index @@ -688,14 +687,19 @@ subroutine CNPAdjustFRootTargets(this, target_c) real(r8) :: l2fr_delta_scale real(r8) :: logi_k real(r8) :: l2fr_mult + real(r8), pointer :: nc_store + real(r8), pointer :: pc_store real(r8), parameter :: max_l2fr_cgain_frac = 0.99_r8 + real(r8), parameter :: wgt = 1._r8/10._r8 ! 10-day smoothing + ipft = this%bc_in(acnp_bc_in_id_pft)%ival l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval - + nc_store => this%bc_inout(acnp_bc_inout_id_nc_store)%rval + pc_store => this%bc_inout(acnp_bc_inout_id_pc_store)%rval ! Step 1: Determine the nutrient to carbon ratio (aka relative health factor) ! ----------------------------------------------------------------------------------- @@ -717,6 +721,8 @@ subroutine CNPAdjustFRootTargets(this, target_c) n_ratio = min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max)/(store_c_act/store_c_max))) + nc_store = wgt*log(n_ratio) + (1._r8-wgt)*nc_store + end if if(p_uptake_mode.ne.prescribed_p_uptake)then @@ -726,10 +732,11 @@ subroutine CNPAdjustFRootTargets(this, target_c) store_nut_max = this%GetNutrientTarget(phosphorus_element,store_organ,stoich_growth_min) - store_nut_act = this%GetState(store_organ, phosphorus_element) + this%bc_inout(acnp_bc_inout_id_netdp)%rval - + store_nut_act = this%GetState(store_organ, phosphorus_element) + this%bc_inout(acnp_bc_inout_id_netdp)%rval p_ratio = min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max)/(store_c_act/store_c_max))) + pc_store = wgt*log(p_ratio) + (1._r8-wgt)*pc_store + end if ! Use the limiting nutrient species @@ -739,13 +746,13 @@ subroutine CNPAdjustFRootTargets(this, target_c) cnp_store_ratio = 1._r8 return else - cnp_store_ratio = p_ratio + cnp_store_ratio = exp(pc_store) end if else if(p_uptake_mode.eq.prescribed_p_uptake)then - cnp_store_ratio = n_ratio + cnp_store_ratio = exp(nc_store) else - cnp_store_ratio = min(n_ratio, p_ratio) + cnp_store_ratio = min(exp(nc_store),exp(pc_store)) end if end if @@ -805,31 +812,17 @@ subroutine CNPAdjustFRootTargets(this, target_c) l2fr_mult = min(l2fr_mult,l2fr_delta_max) end if - ! Use the derivative approach - ! ----------------------------------------------------------------------------------- - - ! gamma = log(np_ratio) - - ! Calculate how close the change in gamma was to what was predicted - - !gamma_del = gamma - dlambda_dgamma*gamma_prev - - - !l2fr_deriv = gamma * dlambda_dgamma - - - ! Only update L2FR if some leaves are out if(this%GetState(leaf_organ, carbon12_element)/target_c(leaf_organ) > 0.5_r8) then !l2fr = (1._r8-err_beta)*(l2fr * l2fr_mult) + err_beta*l2fr_deriv - l2fr = l2fr * l2fr_mult + l2fr = max(l2fr_min,l2fr * l2fr_mult) end if ! Find the updated target fineroot biomass - call bfineroot(dbh,ipft,canopy_trim, l2fr, target_c(fnrt_organ)) + call bfineroot(dbh,ipft,canopy_trim, l2fr, target_c(fnrt_organ),target_dcdd(fnrt_organ)) return end subroutine CNPAdjustFRootTargets @@ -857,11 +850,11 @@ subroutine TrimFineRoot(this) real(r8) :: pc_fnrt real(r8) :: target_fnrt_c real(r8),parameter :: nday_buffer = 0._r8 - real(r8),parameter :: fnrt_opt_eff = 0._r8 ! If we want to transfer resources to storage + real(r8),parameter :: fnrt_opt_eff = 1._r8 ! If we want to transfer resources to storage if(.not.use_unrestricted_contraction)return - associate( ipft => this%bc_in(acnp_bc_in_id_pft)%ival, & + associate( ipft => this%bc_in(acnp_bc_in_id_pft)%ival, & l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval, & dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval, & canopy_trim => this%bc_in(acnp_bc_in_id_ctrim)%rval) @@ -1658,8 +1651,10 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & write(fates_log(),*) 'Aborting' write(fates_log(),*) 'mask: ',state_mask write(fates_log(),*) 'smallest deltaC',this%ode_opt_step - write(fates_log(),*) 'totalC',totalC + write(fates_log(),*) 'totalC',totalC,c_gain,neq_cgain,peq_cgain write(fates_log(),*) 'pft: ',ipft + write(fates_log(),*) 'trim: ',canopy_trim + write(fates_log(),*) 'l2fr: ',l2fr write(fates_log(),*) 'dbh: ',dbh write(fates_log(),*) 'dCleaf_dd: ',target_dcdd(leaf_organ) write(fates_log(),*) 'dCfnrt_dd: ',target_dcdd(fnrt_organ) @@ -1839,7 +1834,6 @@ subroutine CNPAllocateRemainder(this, c_gain, n_gain, p_gain, & ! Update carbon based allometric targets call bstore_allom(dbh,ipft,canopy_trim, store_c_target) - ! Allow some overflow store_c_target = store_c_target * (1._r8 + prt_params%store_ovrflw_frac(ipft)) @@ -1962,12 +1956,15 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe real(r8) :: leaf_c_target,fnrt_c_target real(r8) :: sapw_c_target,agw_c_target real(r8) :: bgw_c_target,struct_c_target + real(r8) :: nc_repro,pc_repro dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival i_cvar = prt_global%sp_organ_map(organ_id,carbon12_element) l2fr = this%bc_inout(acnp_bc_inout_id_l2fr)%rval + nc_repro = this%bc_in(acnp_bc_in_id_nc_repro)%rval + pc_repro = this%bc_in(acnp_bc_in_id_pc_repro)%rval ! Storage of nutrients are assumed to have different compartments than ! for carbon, and thus their targets are not associated with a tissue @@ -2013,9 +2010,9 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe target_c = this%variables(i_cvar)%val(1) if( element_id == nitrogen_element) then - target_m = target_c * prt_params%nitr_recr_stoich(ipft) + target_m = target_c * nc_repro else - target_m = target_c * prt_params%phos_recr_stoich(ipft) + target_m = target_c * pc_repro end if else @@ -2387,8 +2384,10 @@ subroutine EstimateGrowthNC(this,target_c,target_dcdd,state_mask,avg_nc,avg_pc) real(r8) :: store_pc real(r8) :: repro_w,leaf_w,fnrt_w,sapw_w,struct_w,store_w - associate(dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval, & - ipft => this%bc_in(acnp_bc_in_id_pft)%ival ) + associate(dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval, & + ipft => this%bc_in(acnp_bc_in_id_pft)%ival, & + nc_repro => this%bc_in(acnp_bc_in_id_nc_repro)%rval, & + pc_repro => this%bc_in(acnp_bc_in_id_pc_repro)%rval) if(state_mask(repro_id)) then if (dbh <= prt_params%dbh_repro_threshold(ipft)) then @@ -2448,11 +2447,10 @@ subroutine EstimateGrowthNC(this,target_c,target_dcdd,state_mask,avg_nc,avg_pc) repro_w = total_w * repro_c_frac/(1._r8 - repro_c_frac) total_w = total_w + repro_w - avg_nc = avg_nc + repro_w * prt_params%nitr_recr_stoich(ipft) - avg_pc = avg_pc + repro_w * prt_params%phos_recr_stoich(ipft) + avg_nc = avg_nc + repro_w * nc_repro + avg_pc = avg_pc + repro_w * pc_repro end if - avg_nc = avg_nc / total_w avg_pc = avg_pc / total_w diff --git a/parteh/PRTGenericMod.F90 b/parteh/PRTGenericMod.F90 index d3538b528d..f3e995f18a 100644 --- a/parteh/PRTGenericMod.F90 +++ b/parteh/PRTGenericMod.F90 @@ -146,6 +146,11 @@ module PRTGenericMod ! (used for allocating scratch space) integer, parameter, public :: max_nleafage = 4 + + ! This is the minimum allowable L2FR, this is needed so that plants + ! in the understory don't shrink their roots down so far that + ! they dissappear and cause numerical issues + real(r8), parameter, public :: l2fr_min = 0.01_r8 ! ------------------------------------------------------------------------------------- ! diff --git a/parteh/PRTParametersMod.F90 b/parteh/PRTParametersMod.F90 index e1f418f09e..b83727570a 100644 --- a/parteh/PRTParametersMod.F90 +++ b/parteh/PRTParametersMod.F90 @@ -8,7 +8,7 @@ module PRTParametersMod ! that data, for that is model dependent (ie FATES may have a different ! way than another TBM) ! This code does perform checks on parameters. - + type,public :: prt_param_type ! The following three PFT classes @@ -61,10 +61,6 @@ module PRTParametersMod integer, allocatable :: organ_id(:) ! Mapping of the organ index in the parameter file, to the ! global list of organs found in PRTGenericMod.F90 - - - - real(r8), allocatable :: alloc_priority(:,:) ! Allocation priority for each organ (pft x organ) [integer 0-6] real(r8), allocatable :: cushion(:) ! labile carbon storage target as multiple of leaf pool. real(r8), allocatable :: leaf_stor_priority(:) ! leaf turnover vs labile carbon use prioritisation @@ -81,13 +77,6 @@ module PRTParametersMod ! by all the possible organs in parteh, and each index ! may point to the index in the parameter file, or will be -1 - real(r8), allocatable :: nitr_recr_stoich(:) ! This is the N:C ratio of newly recruited plants that are - ! on allometry at their recruitment diameter - - real(r8), allocatable :: phos_recr_stoich(:) ! This is the P:C ratio of newly recruited plants that are - ! on allometry at their recruitment diameter - - ! Allometry Parameters ! -------------------------------------------------------------------------------------------- diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index fb1338c5cd..9eec0ccaa3 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -50,6 +50,7 @@ module PRTInitParamsFatesMod public :: PRTReceiveParams public :: PRTCheckParams public :: PRTDerivedParams + public :: NewRecruitTotalStoichiometry !----------------------------------------------------------------------- contains @@ -967,8 +968,6 @@ subroutine PRTDerivedParams() ! Set the reverse lookup map for organs to the parameter file index allocate(prt_params%organ_param_id(num_organ_types)) - allocate(prt_params%nitr_recr_stoich(npft)) - allocate(prt_params%phos_recr_stoich(npft)) ! Initialize them as invalid prt_params%organ_param_id(:) = -1 @@ -977,18 +976,6 @@ subroutine PRTDerivedParams() prt_params%organ_param_id(prt_params%organ_id(i)) = i end do - - ! Calculate the stoichiometry of a new recruit, and use this for defining - ! seed stoichiometry and - - do ft = 1,npft - - prt_params%nitr_recr_stoich(ft) = NewRecruitTotalStoichiometry(ft,nitrogen_element) - prt_params%phos_recr_stoich(ft) = NewRecruitTotalStoichiometry(ft,phosphorus_element) - - end do - - return end subroutine PRTDerivedParams @@ -1466,7 +1453,7 @@ end subroutine PRTCheckParams ! ==================================================================================== - function NewRecruitTotalStoichiometry(ft,element_id) result(recruit_stoich) + function NewRecruitTotalStoichiometry(ft,l2fr,element_id) result(recruit_stoich) ! ---------------------------------------------------------------------------------- ! This function calculates the total N:C or P:C ratio for a newly recruited plant @@ -1480,10 +1467,10 @@ function NewRecruitTotalStoichiometry(ft,element_id) result(recruit_stoich) ! into new recruits. ! ---------------------------------------------------------------------------------- - - integer,intent(in) :: ft - integer,intent(in) :: element_id - real(r8) :: recruit_stoich ! nutrient to carbon ratio of recruit + integer,intent(in) :: ft + integer,intent(in) :: element_id + real(r8),intent(in) :: l2fr + real(r8) :: recruit_stoich ! nutrient to carbon ratio of recruit real(r8) :: dbh ! dbh of the new recruit [cm] real(r8) :: c_leaf ! target leaf biomass [kgC] @@ -1499,7 +1486,7 @@ function NewRecruitTotalStoichiometry(ft,element_id) result(recruit_stoich) call h2d_allom(EDPftvarcon_inst%hgt_min(ft),ft,dbh) call bleaf(dbh,ft,init_recruit_trim,c_leaf) - call bfineroot(dbh,ft,init_recruit_trim,prt_params%allom_l2fr(ft),c_fnrt) + call bfineroot(dbh,ft,init_recruit_trim,l2fr,c_fnrt) call bsap_allom(dbh,ft,init_recruit_trim,a_sapw, c_sapw) call bagw_allom(dbh,ft,c_agw) call bbgw_allom(dbh,ft,c_bgw) From d4b7913e9eb7a5b571bd5a54fa9afa0a63cd6fa9 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Sun, 31 Jul 2022 10:08:46 -0600 Subject: [PATCH 303/852] Removed extra end-if closures I added while updating phenology logic --- biogeochem/EDPhysiologyMod.F90 | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index a47d1fe433..4ecd61c340 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1066,7 +1066,7 @@ subroutine phenology_leafonoff(currentSite) real(r8) :: deficit_c ! Amount of C needed to get flushing pools "on-allometry" real(r8) :: target_leaf_c real(r8) :: target_sapw_c - real(r8) :: target_agw_c, target_bgw_c, target_agw_c, target_struct_c + real(r8) :: target_agw_c, target_bgw_c, target_struct_c real(r8) :: sapw_area integer :: ipft real(r8), parameter :: leaf_drop_fraction = 1.0_r8 @@ -1097,9 +1097,9 @@ subroutine phenology_leafonoff(currentSite) ! The site level flags signify that it is no-longer too cold ! for leaves. Time to signal flushing - if (prt_params%season_decid(ipft) == itrue)then - if ( currentSite%cstatus == phen_cstat_notcold )then ! we have just moved to leaves being on . - if (currentCohort%status_coh == leaves_off)then ! Are the leaves currently off? + if_colddec: if (prt_params%season_decid(ipft) == itrue)then + if_notcold: if ( currentSite%cstatus == phen_cstat_notcold )then ! we have just moved to leaves being on . + if_leaves_off: if (currentCohort%status_coh == leaves_off)then ! Are the leaves currently off? currentCohort%status_coh = leaves_on ! Leaves are on, so change status to ! stop flow of carbon out of bstore. @@ -1153,16 +1153,15 @@ subroutine phenology_leafonoff(currentSite) end if - endif - endif !pft phenology - endif ! growing season + endif if_leaves_off + endif if_notcold !COLD LEAF OFF - if (currentSite%cstatus == phen_cstat_nevercold .or. & + if_cold: if (currentSite%cstatus == phen_cstat_nevercold .or. & currentSite%cstatus == phen_cstat_iscold) then ! past leaf drop day? Leaves still on tree? - - if (currentCohort%status_coh == leaves_on) then ! leaves have not dropped - + + if_leaves_on: if (currentCohort%status_coh == leaves_on) then ! leaves have not dropped + ! leaf off occur on individuals bigger than specific size for grass if (currentCohort%dbh > EDPftvarcon_inst%phen_cold_size_threshold(ipft) & .or. prt_params%woody(ipft)==itrue) then @@ -1187,9 +1186,9 @@ subroutine phenology_leafonoff(currentSite) endif ! woody plant check endif ! individual dbh size check - endif !leaf status - endif !currentSite status - endif !season_decid + endif if_leaves_on !leaf status + endif if_cold !currentSite status + endif if_colddec !season_decid ! DROUGHT LEAF ON ! Site level flag indicates it is no longer in drought condition @@ -1255,7 +1254,6 @@ subroutine phenology_leafonoff(currentSite) end if - endif ! woody plant check endif !currentCohort status again? endif !currentSite status From 67b9211e36b3a47fe027ed24826326f4681b5078 Mon Sep 17 00:00:00 2001 From: Shijie Shu Date: Tue, 2 Aug 2022 14:37:21 -0700 Subject: [PATCH 304/852] Pass NPP and AR to ELM for calculating NBP. --- main/EDMainMod.F90 | 9 +++++++++ main/FatesInterfaceMod.F90 | 3 +++ main/FatesInterfaceTypesMod.F90 | 2 ++ parteh/PRTGenericMod.F90 | 18 ++++++++++-------- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index b1c9ebb511..d0e5af8d96 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -342,6 +342,10 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) call get_frac_site_primary(currentSite, frac_site_primary) + ! Clear site GPP and AR passing to HLM + bc_out%gpp_site = 0._r8 + bc_out%ar_site = 0._r8 + ! Patch level biomass are required for C-based harvest call get_harvestable_carbon(currentSite, bc_in%site_area, bc_in%hlm_harvest_catnames, harvestable_forest_c, available_forest_c) @@ -422,6 +426,11 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentCohort%gpp_acc_hold = currentCohort%gpp_acc * real(hlm_days_per_year,r8) currentCohort%resp_acc_hold = currentCohort%resp_acc * real(hlm_days_per_year,r8) + ! Passing gpp_acc_hold to HLM + bc_out%gpp_site = bc_out%gpp_site + currentCohort%gpp_acc_hold * & + AREA_INV * currentCohort%n / hlm_days_per_year / sec_per_day + bc_out%ar_site = bc_out%ar_site + currentCohort%resp_acc_hold * & + AREA_INV * currentCohort%n / hlm_days_per_year / sec_per_day ! Conduct Maintenance Turnover (parteh) if(debug) call currentCohort%prt%CheckMassConservation(ft,3) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index d9ea82efcf..14ac272ae6 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -365,6 +365,9 @@ subroutine zero_bcs(fates,s) end if fates%bc_out(s)%plant_stored_h2o_si = 0.0_r8 + ! Land Use realated + fates%bc_out(s)%gpp_site = 0.0_r8 + fates%bc_out(s)%ar_site = 0.0_r8 fates%bc_out(s)%hrv_deadstemc_to_prod10c = 0.0_r8 fates%bc_out(s)%hrv_deadstemc_to_prod100c = 0.0_r8 diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index d1b0dddd12..e29aca8e39 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -710,6 +710,8 @@ module FatesInterfaceTypesMod ! FATES LULCC real(r8) :: hrv_deadstemc_to_prod10c ! Harvested C flux to 10-yr wood product pool [Site-Level, gC m-2 s-1] real(r8) :: hrv_deadstemc_to_prod100c ! Harvested C flux to 100-yr wood product pool [Site-Level, gC m-2 s-1] + real(r8) :: gpp_site ! Site level GPP, for NBP diagnosis in HLM [Site-Level, gC m-2 s-1] + real(r8) :: ar_site ! Site level Autotrophic Resp, for NBP diagnosis in HLM [Site-Level, gC m-2 s-1] end type bc_out_type diff --git a/parteh/PRTGenericMod.F90 b/parteh/PRTGenericMod.F90 index 3dab9563a3..00c0ac677b 100644 --- a/parteh/PRTGenericMod.F90 +++ b/parteh/PRTGenericMod.F90 @@ -866,15 +866,17 @@ subroutine DeallocatePRTVartypes(this) ! Check to see if there is any value in these pools? ! SHould not deallocate if there is any carbon left - do i_var = 1, prt_global%num_vars - deallocate(this%variables(i_var)%val) - deallocate(this%variables(i_var)%val0) - deallocate(this%variables(i_var)%net_alloc) - deallocate(this%variables(i_var)%turnover) - deallocate(this%variables(i_var)%burned) - end do + if(allocated(this%variables)) then + do i_var = 1, prt_global%num_vars + deallocate(this%variables(i_var)%val) + deallocate(this%variables(i_var)%val0) + deallocate(this%variables(i_var)%net_alloc) + deallocate(this%variables(i_var)%turnover) + deallocate(this%variables(i_var)%burned) + end do - deallocate(this%variables) + deallocate(this%variables) + end if if(allocated(this%bc_in))then deallocate(this%bc_in) From a75b6d6ceb0efad715aa095f78a42dfd983dcc7c Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 3 Aug 2022 12:35:29 -0400 Subject: [PATCH 305/852] Adding canopy layer x size x pft history diagnostics --- biogeochem/EDCohortDynamicsMod.F90 | 4 +- biogeochem/EDPhysiologyMod.F90 | 11 + main/EDMainMod.F90 | 16 +- main/EDTypesMod.F90 | 2 + main/FatesHistoryInterfaceMod.F90 | 793 +++++++++++++++------------- main/FatesHistoryVariableType.F90 | 8 +- main/FatesIODimensionsMod.F90 | 6 +- main/FatesIOVariableKindMod.F90 | 3 +- main/FatesSizeAgeTypeIndicesMod.F90 | 30 +- parteh/PRTAllometricCNPMod.F90 | 5 +- parteh/PRTGenericMod.F90 | 3 +- 11 files changed, 496 insertions(+), 385 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 234dc1bc9d..e671d8982e 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -431,8 +431,8 @@ subroutine InitPRTBoundaryConditions(new_cohort,ft,call_id) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_lstat,bc_ival = new_cohort%status_coh) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdc, bc_rval = new_cohort%npp_acc) - call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_nc_repro,bc_rval = new_cohort%patchptr%nitr_repro_stoich(ft)) - call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_pc_repro,bc_rval = new_cohort%patchptr%phos_repro_stoich(ft)) + call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_nc_repro,bc_rval = new_cohort%nc_repro) !patchptr%nitr_repro_stoich(ft)) + call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_pc_repro,bc_rval = new_cohort%pc_repro) !patchptr%phos_repro_stoich(ft)) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_dbh,bc_rval = new_cohort%dbh) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_resp_excess,bc_rval = new_cohort%resp_excess) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index f381c53347..a260285c42 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2662,6 +2662,7 @@ subroutine UpdateRecruitStoich(csite) type(ed_site_type) :: csite type(ed_patch_type), pointer :: cpatch + type(ed_cohort_type), pointer :: ccohort integer :: ft ! functional type index integer :: cl ! canopy layer index real(r8) :: rec_l2fr_pft ! Actual l2fr of a pft in it's patch @@ -2671,6 +2672,7 @@ subroutine UpdateRecruitStoich(csite) cpatch => csite%youngest_patch do while(associated(cpatch)) cl = cpatch%ncl_p + do ft = 1,numpft rec_l2fr_pft = csite%rec_l2fr(ft,cl) cpatch%nitr_repro_stoich(ft) = & @@ -2678,6 +2680,15 @@ subroutine UpdateRecruitStoich(csite) cpatch%phos_repro_stoich(ft) = & NewRecruitTotalStoichiometry(ft,rec_l2fr_pft,phosphorus_element) end do + + ccohort => cpatch%shortest + cloop: do while(associated(ccohort)) + rec_l2fr_pft = csite%rec_l2fr(ccohort%pft,cl) + ccohort%nc_repro = NewRecruitTotalStoichiometry(ccohort%pft,rec_l2fr_pft,nitrogen_element) + ccohort%pc_repro = NewRecruitTotalStoichiometry(ccohort%pft,rec_l2fr_pft,phosphorus_element) + ccohort => ccohort%taller + end do cloop + cpatch => cpatch%older end do diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 5aaa4f25f2..305fbcafb1 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -469,13 +469,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) call EffluxIntoLitterPools(currentSite, currentPatch, currentCohort, bc_in ) - ! Update history diagnostics related to Nutrient fluxes and C efflux (if any) - ! ----------------------------------------------------------------------------- - call fates_hist%update_history_nutrflux(currentSite,currentPatch,currentCohort) - - - currentCohort%daily_n_fixation = 0._r8 ! Mass balance for N uptake currentSite%mass_balance(element_pos(nitrogen_element))%net_root_uptake = & @@ -550,13 +544,18 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentPatch => currentPatch%older end do - - + ! We keep a record of the L2FRs of plants ! that are near the recruit size, for different ! pfts and canopy layer. We use this mean to ! set the L2FRs of newly recruited plants + call UpdateRecruitL2FR(currentSite) + + ! Update history diagnostics related to Nutrients (if any) + ! ----------------------------------------------------------------------------- + + call fates_hist%update_history_nutrflux(currentSite) ! When plants die, the water goes with them. This effects ! the water balance. @@ -612,6 +611,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentCohort => currentPatch%shortest do while(associated(currentCohort)) currentCohort%n = max(0._r8,currentCohort%n + currentCohort%dndt * hlm_freq_day ) + currentCohort%daily_n_fixation = 0._r8 currentCohort => currentCohort%taller enddo currentPatch => currentPatch%older diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 7adba898a1..4a1b434676 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -226,6 +226,8 @@ module EDTypesMod integer :: cnp_limiter ! Which species is limiting growth? ! 0=none,1=C,2=N,3=P real(r8) :: nc_store ! Exponential moving average of the log of the N/C storage ratio real(r8) :: pc_store ! Exponential moving average of the log of the P/C storage ratio + real(r8) :: nc_repro ! The NC ratio of a new recruit in this patch + real(r8) :: pc_repro ! The PC ratio of a new recruit in this patch ! VEGETATION STRUCTURE diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index c5223c18f5..9e71cb5a29 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -16,6 +16,7 @@ module FatesHistoryInterfaceMod use EDTypesMod , only : ican_upper use PRTGenericMod , only : element_pos use PRTGenericMod , only : num_elements + use PRTGenericMod , only : prt_cnp_flex_allom_hyp use EDTypesMod , only : site_fluxdiags_type use EDtypesMod , only : ed_site_type use EDtypesMod , only : ed_cohort_type @@ -82,6 +83,7 @@ module FatesHistoryInterfaceMod use PRTGenericMod , only : nitrogen_element, phosphorus_element use PRTGenericMod , only : prt_carbon_allom_hyp use PRTAllometricCNPMod , only : stoich_max,stoich_growth_min + use FatesSizeAgeTypeIndicesMod, only : get_layersizetype_class_index implicit none private ! By default everything is private @@ -171,32 +173,59 @@ module FatesHistoryInterfaceMod integer :: ih_reproc_si integer :: ih_totvegc_si + ! Nutrient relevant diagnostics (CNP) + ! --------------------------------------------------------------- + ! These are active if if(any(element_list(:)==nitrogen_element)) integer :: ih_storen_si integer :: ih_leafn_si integer :: ih_sapwn_si integer :: ih_fnrtn_si integer :: ih_repron_si integer :: ih_totvegn_si - - integer :: ih_storep_si + integer :: ih_storentfrac_si + integer :: ih_totvegn_scpf + integer :: ih_leafn_scpf + integer :: ih_fnrtn_scpf + integer :: ih_storen_scpf + integer :: ih_sapwn_scpf + integer :: ih_repron_scpf + integer :: ih_storentfrac_canopy_scpf + integer :: ih_storentfrac_understory_scpf + ! These are active if if(any(element_list(:)==phosphorus_element)) + integer :: ih_storep_si integer :: ih_leafp_si integer :: ih_sapwp_si integer :: ih_fnrtp_si integer :: ih_reprop_si integer :: ih_totvegp_si + integer :: ih_storeptfrac_si + integer :: ih_totvegp_scpf + integer :: ih_leafp_scpf + integer :: ih_fnrtp_scpf + integer :: ih_reprop_scpf + integer :: ih_storep_scpf + integer :: ih_sapwp_scpf + integer :: ih_storeptfrac_canopy_scpf + integer :: ih_storeptfrac_understory_scpf + ! These are active if hlm_parteh_mode = prt_cnp_flex_allom_hyp integer :: ih_l2fr_si - integer :: ih_l2fr_canopy_scpf - integer :: ih_l2fr_understory_scpf + integer :: ih_l2fr_clscpf integer :: ih_recl2fr_canopy_pf integer :: ih_recl2fr_ustory_pf + integer :: ih_ngrowlim_clscpf + integer :: ih_pgrowlim_clscpf + integer :: ih_nh4uptake_scpf + integer :: ih_no3uptake_scpf + integer :: ih_puptake_scpf integer :: ih_nh4uptake_si integer :: ih_no3uptake_si integer :: ih_puptake_si - integer :: ih_cefflux_si integer :: ih_nefflux_si integer :: ih_pefflux_si + integer :: ih_nefflux_scpf + integer :: ih_pefflux_scpf integer :: ih_ndemand_si integer :: ih_ndemand_scpf integer :: ih_pdemand_si @@ -204,20 +233,25 @@ module FatesHistoryInterfaceMod integer :: ih_nfix_si integer :: ih_nfix_scpf + ! These dimensions are useful for upscaling (weighting clscpf) + integer :: ih_fnrtc_clscpf + integer :: ih_gpp_clscpf + integer :: ih_totvegc_clscpf + + integer :: ih_trimming_si integer :: ih_area_plant_si integer :: ih_area_trees_si - integer :: ih_cwd_elcwd - + + integer :: ih_litter_in_elem + integer :: ih_litter_out_elem + integer :: ih_seed_bank_elem integer :: ih_litter_in_si ! carbon only integer :: ih_litter_out_si ! carbon only integer :: ih_seed_bank_si ! carbon only integer :: ih_seeds_in_si ! carbon only - - integer :: ih_litter_in_elem - integer :: ih_litter_out_elem - integer :: ih_seed_bank_elem + integer :: ih_seeds_in_local_elem integer :: ih_seeds_in_extern_elem integer :: ih_seed_decay_elem @@ -227,6 +261,7 @@ module FatesHistoryInterfaceMod integer :: ih_fines_bg_elem integer :: ih_cwd_ag_elem integer :: ih_cwd_bg_elem + integer :: ih_cwd_elcwd integer :: ih_burn_flux_elem ! Size-class x PFT mass states @@ -236,43 +271,12 @@ module FatesHistoryInterfaceMod integer :: ih_bleaf_canopy_si_scpf integer :: ih_bleaf_understory_si_scpf - - - integer :: ih_totvegn_scpf - integer :: ih_leafn_scpf - integer :: ih_fnrtn_scpf - integer :: ih_storen_scpf - integer :: ih_storentfrac_si - integer :: ih_storentfrac_canopy_scpf - integer :: ih_storentfrac_understory_scpf - integer :: ih_sapwn_scpf - integer :: ih_repron_scpf - integer,public :: ih_nh4uptake_scpf - integer,public :: ih_no3uptake_scpf - integer :: ih_nefflux_scpf - - integer :: ih_totvegc_scpf integer :: ih_leafc_scpf integer :: ih_fnrtc_scpf integer :: ih_storec_scpf integer :: ih_sapwc_scpf integer :: ih_reproc_scpf - integer :: ih_cefflux_scpf - - integer :: ih_totvegp_scpf - integer :: ih_leafp_scpf - integer :: ih_fnrtp_scpf - integer :: ih_reprop_scpf - integer :: ih_storep_scpf - integer :: ih_storeptfrac_si - integer :: ih_storeptfrac_canopy_scpf - integer :: ih_storeptfrac_understory_scpf - integer :: ih_sapwp_scpf - integer,public :: ih_puptake_scpf - integer :: ih_pefflux_scpf - - integer :: ih_bdead_si integer :: ih_balive_si integer :: ih_agb_si @@ -397,7 +401,6 @@ module FatesHistoryInterfaceMod integer :: ih_npp_agdw_si_scpf integer :: ih_npp_stor_si_scpf - integer :: ih_mortality_canopy_si_scpf integer :: ih_mortality_understory_si_scpf integer :: ih_nplant_canopy_si_scpf @@ -684,7 +687,7 @@ module FatesHistoryInterfaceMod integer, private :: levelem_index_, levelpft_index_ integer, private :: levelcwd_index_, levelage_index_ integer, private :: levcacls_index_, levcapf_index_ - + integer, private :: levclscpf_index_ contains @@ -724,7 +727,8 @@ module FatesHistoryInterfaceMod procedure :: levelcwd_index procedure :: levelage_index procedure :: levagefuel_index - + procedure :: levclscpf_index + ! private work functions procedure, private :: define_history_vars procedure, private :: set_history_var @@ -749,7 +753,8 @@ module FatesHistoryInterfaceMod procedure, private :: set_levagepft_index procedure, private :: set_levheight_index procedure, private :: set_levagefuel_index - + procedure, private :: set_levclscpf_index + procedure, private :: set_levelem_index procedure, private :: set_levelpft_index procedure, private :: set_levelcwd_index @@ -785,7 +790,7 @@ subroutine Init(this, num_threads, fates_bounds) use FatesIODimensionsMod, only : fates_bounds_type use FatesIODimensionsMod, only : levheight, levagefuel use FatesIODimensionsMod, only : levelem, levelpft - use FatesIODimensionsMod, only : levelcwd, levelage + use FatesIODimensionsMod, only : levelcwd, levelage, levclscpf implicit none @@ -910,6 +915,11 @@ subroutine Init(this, num_threads, fates_bounds) call this%dim_bounds(dim_count)%Init(levagefuel, num_threads, & fates_bounds%agefuel_begin, fates_bounds%agefuel_end) + dim_count = dim_count + 1 + call this%set_levclscpf_index(dim_count) + call this%dim_bounds(dim_count)%Init(levclscpf, num_threads, & + fates_bounds%clscpf_begin, fates_bounds%clscpf_end) + end subroutine Init ! ====================================================================== @@ -1018,9 +1028,9 @@ subroutine SetThreadBoundsEach(this, thread_index, thread_bounds) call this%dim_bounds(index)%SetThreadBounds(thread_index, & thread_bounds%agefuel_begin, thread_bounds%agefuel_end) - - - + index = this%levclscpf_index() + call this%dim_bounds(index)%SetThreadBounds(thread_index, & + thread_bounds%clscpf_begin, thread_bounds%clscpf_end) end subroutine SetThreadBoundsEach @@ -1036,7 +1046,7 @@ subroutine assemble_history_output_types(this) use FatesIOVariableKindMod, only : site_can_r8, site_cnlf_r8, site_cnlfpft_r8 use FatesIOVariableKindMod, only : site_height_r8, site_agefuel_r8 use FatesIOVariableKindMod, only : site_elem_r8, site_elpft_r8 - use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8 + use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8, site_clscpf_r8 implicit none @@ -1117,7 +1127,9 @@ subroutine assemble_history_output_types(this) call this%set_dim_indices(site_agefuel_r8, 1, this%column_index()) call this%set_dim_indices(site_agefuel_r8, 2, this%levagefuel_index()) - + call this%set_dim_indices(site_clscpf_r8, 1, this%column_index()) + call this%set_dim_indices(site_clscpf_r8, 2, this%levclscpf_index()) + end subroutine assemble_history_output_types ! =================================================================================== @@ -1487,6 +1499,20 @@ integer function levagefuel_index(this) class(fates_history_interface_type), intent(in) :: this levagefuel_index = this%levagefuel_index_ end function levagefuel_index + ! ====================================================================================== + + subroutine set_levclscpf_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levclscpf_index_ = index + end subroutine set_levclscpf_index + + integer function levclscpf_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levclscpf_index = this%levclscpf_index_ + end function levclscpf_index ! ====================================================================================== @@ -1628,7 +1654,7 @@ subroutine init_dim_kinds_maps(this) use FatesIOVariableKindMod, only : site_can_r8, site_cnlf_r8, site_cnlfpft_r8 use FatesIOVariableKindMod, only : site_height_r8, site_agefuel_r8 use FatesIOVariableKindMod, only : site_elem_r8, site_elpft_r8 - use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8 + use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8, site_clscpf_r8 implicit none @@ -1738,140 +1764,226 @@ subroutine init_dim_kinds_maps(this) index = index + 1 call this%dim_kinds(index)%Init(site_agefuel_r8, 2) + ! site x age x fuel size class + index = index + 1 + call this%dim_kinds(index)%Init(site_clscpf_r8, 2) ! FIXME(bja, 2016-10) assert(index == fates_history_num_dim_kinds) end subroutine init_dim_kinds_maps - ! ======================================================================= - - subroutine update_history_nutrflux(this,csite,cpatch,ccohort) + ! ======================================================================= + + subroutine update_history_nutrflux(this,csite) - ! Update history diagnostics for nutrient fluxes. + ! Update history diagnostics for nutrient dynamics variables. ! This is a separate routine because we like to handle these ! things before patches are reshuffled during disturbance, and ! thus this is called immediately after PARTEH allocation ! These diagnostics must be zero'd at the beginning ! of the dynamics call (not here, because this is a ! being called at the cohort level) - + ! Arguments class(fates_history_interface_type) :: this type(ed_site_type), intent(in) :: csite - type(ed_patch_type), intent(in) :: cpatch - type(ed_cohort_type), intent(in) :: ccohort - ! locals + type(ed_patch_type), pointer :: cpatch + type(ed_cohort_type), pointer :: ccohort + integer :: iclscpf ! layer x size x pft class index integer :: iscpf ! Size x pft class index integer :: io_si ! site's global index in the history vector integer :: el ! element loop index + integer :: ft real(r8):: uconv ! combined unit conversion factor + + ! We use gpp and fineroot C for weighted averages + real(r8) :: gpp_clscpf(nclmax*numpft*nlevsclass) + real(r8) :: gpp_si + real(r8) :: fnrtc_clscpf(nclmax*numpft*nlevsclass) + real(r8) :: fnrtc_si + real(r8) :: fnrt_c - ! size class index - iscpf = ccohort%size_by_pft_class + associate( & + hio_ngrowlim_clscpf => this%hvars(ih_ngrowlim_clscpf)%r82d, & + hio_pgrowlim_clscpf => this%hvars(ih_pgrowlim_clscpf)%r82d, & + hio_l2fr_clscpf => this%hvars(ih_l2fr_clscpf)%r82d, & + hio_l2fr_si => this%hvars(ih_l2fr_si)%r81d, & + hio_recl2fr_canopy_pf => this%hvars(ih_recl2fr_canopy_pf)%r82d, & + hio_recl2fr_ustory_pf => this%hvars(ih_recl2fr_ustory_pf)%r82d ) + + gpp_clscpf(:) = 0._r8 + gpp_si = 0._r8 + fnrtc_clscpf(:) = 0._r8 + fnrtc_si = 0._r8 + + cpatch => csite%youngest_patch + do while(associated(cpatch)) - ! history site index - io_si = csite%h_gid + ccohort => cpatch%shortest + do while(associated(ccohort)) - ! unit conversion factor to get x/plant/day -> x/m2/sec - uconv = ccohort%n * ha_per_m2 * days_per_sec - - ! Loop over the different elements. - do el = 1, num_elements - - select case (element_list(el)) - case (carbon12_element) + ! If this is a new cohort, do not make diagnostics + if(ccohort%isnew) cycle + + ! size class index + iscpf = ccohort%size_by_pft_class - ! Excess carbon respired - this%hvars(ih_excess_resp_si)%r81d(io_si) = & - this%hvars(ih_excess_resp_si)%r81d(io_si) + & - ccohort%resp_excess*uconv - - ! Efflux/exudation - this%hvars(ih_cefflux_scpf)%r82d(io_si,iscpf) = & - this%hvars(ih_cefflux_scpf)%r82d(io_si,iscpf) + & - ccohort%daily_c_efflux*uconv - - this%hvars(ih_cefflux_si)%r81d(io_si) = & - this%hvars(ih_cefflux_si)%r81d(io_si)+ & - ccohort%daily_c_efflux*uconv + ! layer by size by pft index + iclscpf = get_layersizetype_class_index(ccohort%canopy_layer,ccohort%dbh,ccohort%pft) + + ! history site index + io_si = csite%h_gid + + ! unit conversion factor to get x/plant/day -> x/m2/sec + uconv = ccohort%n * ha_per_m2 * days_per_sec + + ! Growth Limitations + select case(ccohort%cnp_limiter) + case(2) ! Nitrogen + hio_ngrowlim_clscpf(io_si,iclscpf) = hio_ngrowlim_clscpf(io_si,iclscpf) + & + ccohort%n*ccohort%gpp_acc_hold + case(3) + hio_ngrowlim_clscpf(io_si,iclscpf) = hio_ngrowlim_clscpf(io_si,iclscpf) + & + ccohort%n*ccohort%gpp_acc_hold + end select + - case (nitrogen_element) - - ! Mineralized uptake of NH4, NO3 - fates_hist%hvars(ih_nh4uptake_scpf)%r82d(io_si,iscpf) = & - fates_hist%hvars(ih_nh4uptake_scpf)%r82d(io_si,iscpf) + & - ccohort%daily_nh4_uptake*uconv - - fates_hist%hvars(ih_no3uptake_scpf)%r82d(io_si,iscpf) = & - fates_hist%hvars(ih_no3uptake_scpf)%r82d(io_si,iscpf) + & - ccohort%daily_no3_uptake*uconv - - fates_hist%hvars(ih_nh4uptake_si)%r81d(io_si) = & - fates_hist%hvars(ih_nh4uptake_si)%r81d(io_si) + & - ccohort%daily_nh4_uptake*uconv - - fates_hist%hvars(ih_no3uptake_si)%r81d(io_si) = & - fates_hist%hvars(ih_no3uptake_si)%r81d(io_si) + & - ccohort%daily_no3_uptake*uconv - - ! Symbiotic Fixation - fates_hist%hvars(ih_nfix_si)%r81d(io_si) = & - fates_hist%hvars(ih_nfix_si)%r81d(io_si) + & - ccohort%daily_n_fixation*uconv - - fates_hist%hvars(ih_nfix_scpf)%r82d(io_si,iscpf) = & - fates_hist%hvars(ih_nfix_scpf)%r82d(io_si,iscpf) + & - ccohort%daily_n_fixation*uconv - - ! Efflux/exudation - this%hvars(ih_nefflux_scpf)%r82d(io_si,iscpf) = & - this%hvars(ih_nefflux_scpf)%r82d(io_si,iscpf) + & - ccohort%daily_n_efflux*uconv - - this%hvars(ih_nefflux_si)%r81d(io_si) = & - this%hvars(ih_nefflux_si)%r81d(io_si) + & - ccohort%daily_n_efflux*uconv - - ! Demand - this%hvars(ih_ndemand_scpf)%r82d(io_si,iscpf) = & - this%hvars(ih_ndemand_scpf)%r82d(io_si,iscpf) + & - ccohort%daily_n_demand*uconv - - this%hvars(ih_ndemand_si)%r81d(io_si) = & - this%hvars(ih_ndemand_si)%r81d(io_si) + & - ccohort%daily_n_demand*uconv - - case (phosphorus_element) - - fates_hist%hvars(ih_puptake_scpf)%r82d(io_si,iscpf) = & - fates_hist%hvars(ih_puptake_scpf)%r82d(io_si,iscpf) + & - ccohort%daily_p_uptake*uconv + fnrt_c = ccohort%prt%GetState(fnrt_organ, carbon12_element) + hio_l2fr_clscpf(io_si,iclscpf) = & + hio_l2fr_clscpf(io_si,iclscpf) + ccohort%n*fnrt_c*ccohort%l2fr - fates_hist%hvars(ih_puptake_si)%r81d(io_si) = & - fates_hist%hvars(ih_puptake_si)%r81d(io_si) + & - ccohort%daily_p_uptake*uconv + hio_l2fr_si(io_si) = hio_l2fr_si(io_si) + ccohort%n*fnrt_c*ccohort%l2fr + + ! These are used for normalizing weighted averages + gpp_si = gpp_si + ccohort%n*ccohort%gpp_acc_hold + gpp_clscpf(iclscpf) = gpp_clscpf(iclscpf) + ccohort%n*ccohort%gpp_acc_hold + fnrtc_clscpf(iclscpf) = fnrtc_clscpf(iclscpf) + ccohort%n*fnrt_c + fnrtc_si = fnrtc_si + ccohort%n*fnrt_c + + ! Loop over the different elements. + do el = 1, num_elements - this%hvars(ih_pefflux_scpf)%r82d(io_si,iscpf) = & - this%hvars(ih_pefflux_scpf)%r82d(io_si,iscpf) + & - ccohort%daily_p_efflux*uconv - - this%hvars(ih_pefflux_si)%r81d(io_si) = & - this%hvars(ih_pefflux_si)%r81d(io_si) + & - ccohort%daily_p_efflux*uconv + select case (element_list(el)) + case (carbon12_element) + + ! Excess carbon respired + this%hvars(ih_excess_resp_si)%r81d(io_si) = & + this%hvars(ih_excess_resp_si)%r81d(io_si) + & + ccohort%resp_excess*uconv + + case (nitrogen_element) + + ! Mineralized uptake of NH4, NO3 + fates_hist%hvars(ih_nh4uptake_scpf)%r82d(io_si,iscpf) = & + fates_hist%hvars(ih_nh4uptake_scpf)%r82d(io_si,iscpf) + & + ccohort%daily_nh4_uptake*uconv + + fates_hist%hvars(ih_no3uptake_scpf)%r82d(io_si,iscpf) = & + fates_hist%hvars(ih_no3uptake_scpf)%r82d(io_si,iscpf) + & + ccohort%daily_no3_uptake*uconv + + fates_hist%hvars(ih_nh4uptake_si)%r81d(io_si) = & + fates_hist%hvars(ih_nh4uptake_si)%r81d(io_si) + & + ccohort%daily_nh4_uptake*uconv + + fates_hist%hvars(ih_no3uptake_si)%r81d(io_si) = & + fates_hist%hvars(ih_no3uptake_si)%r81d(io_si) + & + ccohort%daily_no3_uptake*uconv + + ! Symbiotic Fixation + fates_hist%hvars(ih_nfix_si)%r81d(io_si) = & + fates_hist%hvars(ih_nfix_si)%r81d(io_si) + & + ccohort%daily_n_fixation*uconv + + fates_hist%hvars(ih_nfix_scpf)%r82d(io_si,iscpf) = & + fates_hist%hvars(ih_nfix_scpf)%r82d(io_si,iscpf) + & + ccohort%daily_n_fixation*uconv + + ! Efflux/exudation + this%hvars(ih_nefflux_scpf)%r82d(io_si,iscpf) = & + this%hvars(ih_nefflux_scpf)%r82d(io_si,iscpf) + & + ccohort%daily_n_efflux*uconv + + this%hvars(ih_nefflux_si)%r81d(io_si) = & + this%hvars(ih_nefflux_si)%r81d(io_si) + & + ccohort%daily_n_efflux*uconv + + ! Demand + this%hvars(ih_ndemand_scpf)%r82d(io_si,iscpf) = & + this%hvars(ih_ndemand_scpf)%r82d(io_si,iscpf) + & + ccohort%daily_n_demand*uconv + + this%hvars(ih_ndemand_si)%r81d(io_si) = & + this%hvars(ih_ndemand_si)%r81d(io_si) + & + ccohort%daily_n_demand*uconv + + case (phosphorus_element) + + fates_hist%hvars(ih_puptake_scpf)%r82d(io_si,iscpf) = & + fates_hist%hvars(ih_puptake_scpf)%r82d(io_si,iscpf) + & + ccohort%daily_p_uptake*uconv + + fates_hist%hvars(ih_puptake_si)%r81d(io_si) = & + fates_hist%hvars(ih_puptake_si)%r81d(io_si) + & + ccohort%daily_p_uptake*uconv + + this%hvars(ih_pefflux_scpf)%r82d(io_si,iscpf) = & + this%hvars(ih_pefflux_scpf)%r82d(io_si,iscpf) + & + ccohort%daily_p_efflux*uconv + + this%hvars(ih_pefflux_si)%r81d(io_si) = & + this%hvars(ih_pefflux_si)%r81d(io_si) + & + ccohort%daily_p_efflux*uconv + + this%hvars(ih_pdemand_scpf)%r82d(io_si,iscpf) = & + this%hvars(ih_pdemand_scpf)%r82d(io_si,iscpf) + & + ccohort%daily_p_demand*uconv + + this%hvars(ih_pdemand_si)%r81d(io_si) = & + ccohort%daily_p_demand*uconv + end select + end do + + ccohort => ccohort%taller + end do + + cpatch => cpatch%older + end do + + ! Normalize the layer x size x pft arrays + do iclscpf = 1,nclmax*numpft*nlevsclass + if(gpp_clscpf(iclscpf)>nearzero) then + hio_ngrowlim_clscpf(io_si,iclscpf) = hio_ngrowlim_clscpf(io_si,iclscpf) / gpp_clscpf(iclscpf) + hio_pgrowlim_clscpf(io_si,iclscpf) = hio_pgrowlim_clscpf(io_si,iclscpf) / gpp_clscpf(iclscpf) + else + hio_ngrowlim_clscpf(io_si,iclscpf) = hlm_hio_ignore_val + hio_pgrowlim_clscpf(io_si,iclscpf) = hlm_hio_ignore_val + end if + if(fnrtc_clscpf(iclscpf)>nearzero) then + hio_l2fr_clscpf(io_si,iclscpf) = hio_l2fr_clscpf(io_si,iclscpf) / fnrtc_clscpf(iclscpf) + else + hio_l2fr_clscpf(io_si,iclscpf) = hlm_hio_ignore_val + end if + end do + + do ft = 1,numpft + hio_recl2fr_canopy_pf(io_si,ft) = csite%rec_l2fr(ft,1) + hio_recl2fr_ustory_pf(io_si,ft) = csite%rec_l2fr(ft,2) + end do + + if(fnrtc_si>nearzero)then + hio_l2fr_si(io_si) = hio_l2fr_si(io_si)/fnrtc_si + else + hio_l2fr_si(io_si) = hlm_hio_ignore_val + end if + + + + end associate - this%hvars(ih_pdemand_scpf)%r82d(io_si,iscpf) = & - this%hvars(ih_pdemand_scpf)%r82d(io_si,iscpf) + & - ccohort%daily_p_demand*uconv - - this%hvars(ih_pdemand_si)%r81d(io_si) = & - ccohort%daily_p_demand*uconv - end select - end do return end subroutine update_history_nutrflux - - ! ==================================================================================== subroutine update_history_dyn(this,nc,nsites,sites,bc_in) @@ -1894,6 +2006,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) use FatesSizeAgeTypeIndicesMod, only : get_height_index use FatesSizeAgeTypeIndicesMod, only : sizetype_class_index use FatesSizeAgeTypeIndicesMod, only : coagetype_class_index + use EDTypesMod , only : nlevleaf use EDParamsMod , only : ED_val_history_height_bin_edges @@ -1969,8 +2082,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) real(r8) :: area_frac real(r8) :: crown_depth - real(r8) :: fnrtc_canopy_scpf(numpft*nlevsclass) - real(r8) :: fnrtc_understory_scpf(numpft*nlevsclass) real(r8) :: storen_canopy_scpf(numpft*nlevsclass) real(r8) :: storen_understory_scpf(numpft*nlevsclass) real(r8) :: storep_canopy_scpf(numpft*nlevsclass) @@ -1986,24 +2097,11 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) real(r8), parameter :: tiny = 1.e-5_r8 ! some small number real(r8), parameter :: reallytalltrees = 1000. ! some large number (m) - - ! Set this to true if you want the size-pft l2fr variables to - ! take a mean over the site, otherwise it just tracks the oldest patch - - logical, parameter :: do_site_l2fr_scpf = .false. - - - integer :: tmp associate( hio_npatches_si => this%hvars(ih_npatches_si)%r81d, & hio_ncohorts_si => this%hvars(ih_ncohorts_si)%r81d, & hio_trimming_si => this%hvars(ih_trimming_si)%r81d, & - hio_l2fr_si => this%hvars(ih_l2fr_si)%r81d, & - hio_recl2fr_canopy_pf => this%hvars(ih_recl2fr_canopy_pf)%r82d, & - hio_recl2fr_ustory_pf => this%hvars(ih_recl2fr_ustory_pf)%r82d, & - hio_l2fr_canopy_scpf => this%hvars(ih_l2fr_canopy_scpf)%r82d, & - hio_l2fr_understory_scpf => this%hvars(ih_l2fr_understory_scpf)%r82d, & hio_area_plant_si => this%hvars(ih_area_plant_si)%r81d, & hio_area_trees_si => this%hvars(ih_area_trees_si)%r81d, & hio_canopy_spread_si => this%hvars(ih_canopy_spread_si)%r81d, & @@ -2246,8 +2344,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) model_day_int = nint(hlm_model_day) - - ! --------------------------------------------------------------------------------- @@ -2258,9 +2354,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) io_si = sites(s)%h_gid - ! These are weighting factors used for calculating l2fr_scpf - fnrtc_canopy_scpf(:) = 0._r8 - fnrtc_understory_scpf(:) = 0._r8 + ! These are weighting factors storen_canopy_scpf(:) = 0._r8 storen_understory_scpf(:) = 0._r8 storep_canopy_scpf(:) = 0._r8 @@ -2277,11 +2371,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) sites(s)%mass_balance(element_pos(carbon12_element))%burn_flux_to_atm * & ha_per_m2 * days_per_sec - do ft = 1,numpft - hio_recl2fr_canopy_pf(io_si,ft) = sites(s)%rec_l2fr(ft,1) - hio_recl2fr_ustory_pf(io_si,ft) = sites(s)%rec_l2fr(ft,2) - end do - do el = 1, num_elements ! Total model error [kg/day -> kg/s] (all elements) @@ -2553,23 +2642,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) this%hvars(ih_totvegc_si)%r81d(io_si)+ ccohort%n * & total_m / m2_per_ha - - ! These L2FR diagnostics are weighted by fineroot carbon biomass - hio_l2fr_si(io_si) = hio_l2fr_si(io_si) + ccohort%n*fnrt_m/m2_per_ha*ccohort%l2fr - - - ! Constrain L2FR to oldest patch? - if(do_site_l2fr_scpf .or. associated(cpatch,sites(s)%oldest_patch)) then - if (ccohort%canopy_layer .eq. 1) then - hio_l2fr_canopy_scpf(io_si,i_scpf) = & - hio_l2fr_canopy_scpf(io_si,i_scpf) + ccohort%n*fnrt_m *ccohort%l2fr - fnrtc_canopy_scpf(i_scpf) = fnrtc_canopy_scpf(i_scpf) + ccohort%n*fnrt_m - else - hio_l2fr_understory_scpf(io_si,i_scpf) = & - hio_l2fr_understory_scpf(io_si,i_scpf) + ccohort%n*fnrt_m*ccohort%l2fr - fnrtc_understory_scpf(i_scpf) = fnrtc_understory_scpf(i_scpf) + ccohort%n*fnrt_m - end if - end if call bstore_allom(ccohort%dbh,ccohort%pft,ccohort%canopy_trim, store_max) this%hvars(ih_storectfrac_si)%r81d(io_si) = & @@ -3215,12 +3287,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) cpatch => cpatch%younger end do patchloop !patch loop - ! Normalize the l2fr value by total biomass - if(this%hvars(ih_fnrtc_si)%r81d(io_si)>nearzero)then - hio_l2fr_si(io_si) = hio_l2fr_si(io_si)/this%hvars(ih_fnrtc_si)%r81d(io_si) - end if - !!hio_l2fr_ema_si(io_si) = hio_l2fr_ema_si(io_si)/this%hvars(ih_fnrtc_si)%r81d(io_si) - ! divide so-far-just-summed but to-be-averaged patch-age-class variables by patch-age-class area to get mean values do ipa2 = 1, nlevage @@ -3456,8 +3522,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) this%hvars(ih_storec_scpf)%r82d(io_si,:) = 0._r8 this%hvars(ih_reproc_scpf)%r82d(io_si,:) = 0._r8 - - elseif(element_list(el).eq.nitrogen_element)then this%hvars(ih_totvegn_scpf)%r82d(io_si,:) = 0._r8 @@ -3466,8 +3530,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) this%hvars(ih_sapwn_scpf)%r82d(io_si,:) = 0._r8 this%hvars(ih_storen_scpf)%r82d(io_si,:) = 0._r8 this%hvars(ih_repron_scpf)%r82d(io_si,:) = 0._r8 - - elseif(element_list(el).eq.phosphorus_element)then this%hvars(ih_totvegp_scpf)%r82d(io_si,:) = 0._r8 @@ -3635,14 +3697,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) do i_pft = 1, numpft do i_scls = 1,nlevsclass i_scpf = (i_pft-1)*nlevsclass + i_scls - if(fnrtc_canopy_scpf(i_scpf)>nearzero)then - hio_l2fr_canopy_scpf(io_si,i_scpf) = & - hio_l2fr_canopy_scpf(io_si,i_scpf)/fnrtc_canopy_scpf(i_scpf) - end if - if(fnrtc_understory_scpf(i_scpf)>nearzero)then - hio_l2fr_understory_scpf(io_si,i_scpf) = & - hio_l2fr_understory_scpf(io_si,i_scpf)/fnrtc_understory_scpf(i_scpf) - end if if( this%hvars(ih_storectfrac_canopy_scpf)%r82d(io_si,i_scpf)>nearzero ) then this%hvars(ih_storectfrac_canopy_scpf)%r82d(io_si,i_scpf) = & @@ -4591,7 +4645,7 @@ subroutine define_history_vars(this, initialize_variables) use FatesIOVariableKindMod, only : site_fuel_r8, site_cwdsc_r8, site_scag_r8 use FatesIOVariableKindMod, only : site_can_r8, site_cnlf_r8, site_cnlfpft_r8 use FatesIOVariableKindMod, only : site_scagpft_r8, site_agepft_r8 - use FatesIOVariableKindMod, only : site_elem_r8, site_elpft_r8 + use FatesIOVariableKindMod, only : site_elem_r8, site_elpft_r8, site_clscpf_r8 use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8 @@ -4626,15 +4680,11 @@ subroutine define_history_vars(this, initialize_variables) ! patch age x pft (site_agepft_r8) : APPF ! canopy layer x leaf layer (site_cnlf_r8) : CLLL ! canopy layer x leaf layer x pft (site_cnlfpft_r8) : CLLLPF - ! canopy layer x pft (site_clpf_r8) : CLPF ! element x cwd size (site_elcwd_r8) : ELDC ! cohort size x patch age (site_scag_r8) : SZAP ! cohort size x patch age x pft (site_scagpft_r8) : SZAPPF ! cohort size x pft (site_size_pft_r8) : SZPF - - - - + ! canopy layer x size x pft (site_clscpf_r8) : CLSZPF ! Site level counting variables @@ -4650,42 +4700,15 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_ncohorts_si) - ! Patch variables call this%set_history_var(vname='FATES_TRIMMING', units='1', & long='degree to which canopy expansion is limited by leaf economics (0-1)', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_trimming_si) - call this%set_history_var(vname='FATES_L2FR', units='kg kg-1', & - long='The leaf to fineroot biomass multiplier for target allometry', & - use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_l2fr_si) - - call this%set_history_var(vname='FATES_RECL2FR_CANOPY_PF', units='kg kg-1', & - long='The leaf to fineroot biomass multiplier for recruits (canopy)', & - use_default='active', & - avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_recl2fr_canopy_pf) - call this%set_history_var(vname='FATES_RECL2FR_USTORY_PF', units='kg kg-1', & - long='The leaf to fineroot biomass multiplier for recruits (understory)', & - use_default='active', & - avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_recl2fr_ustory_pf) - - call this%set_history_var(vname='FATES_L2FR_CANOPY_SZPF', units='kg kg-1', & - long='The leaf to fineroot biomass multiplier for target allometry in canopy plants', & - use_default='active', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_l2fr_canopy_scpf) + - call this%set_history_var(vname='FATES_L2FR_USTORY_SZPF', units='kg kg-1', & - long='The leaf to fineroot biomass multiplier for target allometry in understory plants', & - use_default='active', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_l2fr_understory_scpf) call this%set_history_var(vname='FATES_AREA_PLANTS', units='m2 m-2', & long='area occupied by all plants per m2 land area', use_default='active', & @@ -5188,13 +5211,111 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_reproc_si) - call this%set_history_var(vname='FATES_CEFFLUX', units='kg m-2 s-1', & - long='carbon efflux, root to soil, in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=5, ivar=ivar, initialize=initialize_variables, & - index = ih_cefflux_si) + ! Output specific to the chemical species dynamics used (parteh) + select case(hlm_parteh_mode) + case (prt_cnp_flex_allom_hyp) + + call this%set_history_var(vname='FATES_L2FR', units='kg kg-1', & + long='The leaf to fineroot biomass multiplier for target allometry', & + use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_l2fr_si) + + call this%set_history_var(vname='FATES_RECL2FR_CANOPY_PF', units='kg kg-1', & + long='The leaf to fineroot biomass multiplier for recruits (canopy)', & + use_default='active', & + avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_recl2fr_canopy_pf) + + call this%set_history_var(vname='FATES_RECL2FR_USTORY_PF', units='kg kg-1', & + long='The leaf to fineroot biomass multiplier for recruits (understory)', & + use_default='active', & + avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_recl2fr_ustory_pf) + + call this%set_history_var(vname='FATES_NGROWLIM_CLSZPF', units='', & + long='The fraction of gpp*days where stature growth is limited by N (vs C or P)', & + use_default='inactive', & + avgflag='A', vtype=site_clscpf_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_ngrowlim_clscpf) + + call this%set_history_var(vname='FATES_PGROWLIM_CLSZPF', units='', & + long='The fraction of gpp*days where stature growth is limited by P (vs N or C) (canopy)', & + use_default='inactive', & + avgflag='A', vtype=site_clscpf_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_pgrowlim_clscpf) + + call this%set_history_var(vname='FATES_L2FR_CLSZPF', units='kg kg-1', & + long='The leaf to fineroot biomass multiplier for target allometry', & + use_default='inactive', & + avgflag='A', vtype=site_clscpf_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_l2fr_clscpf) + call this%set_history_var(vname='FATES_NH4UPTAKE_SZPF', & + units='kg m-2 s-1', & + long='ammonium uptake rate by plants by size-class x pft in kg NH4 per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=5, ivar=ivar, & + initialize=initialize_variables, index = ih_nh4uptake_scpf) + + call this%set_history_var(vname='FATES_NO3UPTAKE_SZPF', & + units='kg m-2 s-1', & + long='nitrate uptake rate by plants by size-class x pft in kg NO3 per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=5, ivar=ivar, & + initialize=initialize_variables, index = ih_no3uptake_scpf) + + call this%set_history_var(vname='FATES_NEFFLUX_SZPF', units='kg m-2 s-1', & + long='nitrogen efflux, root to soil, by size-class x pft in kg N per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=5, ivar=ivar, & + initialize=initialize_variables, index = ih_nefflux_scpf) + call this%set_history_var(vname='FATES_NDEMAND_SZPF', units='kg m-2 s-1', & + long='plant N need (algorithm dependent), by size-class x pft in kg N per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=5, ivar=ivar, & + initialize=initialize_variables, index = ih_ndemand_scpf) + + call this%set_history_var(vname='FATES_SYMNFIX_SZPF', units='kg m-2 s-1', & + long='symbiotic dinitrogen fixation, by size-class x pft in kg N per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=5, ivar=ivar, & + initialize=initialize_variables, index = ih_nfix_scpf) + + + call this%set_history_var(vname='FATES_NH4UPTAKE', units='kg m-2 s-1', & + long='ammonium uptake rate by plants in kg NH4 per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=5, ivar=ivar, initialize=initialize_variables, & + index = ih_nh4uptake_si) + + call this%set_history_var(vname='FATES_NO3UPTAKE', units='kg m-2 s-1', & + long='nitrate uptake rate by plants in kg NO3 per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=5, ivar=ivar, initialize=initialize_variables, & + index = ih_no3uptake_si) + + call this%set_history_var(vname='FATES_NEFFLUX', units='kg m-2 s-1', & + long='nitrogen effluxed from plant in kg N per m2 per second (unused)', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=5, ivar=ivar, initialize=initialize_variables, & + index = ih_nefflux_si) + + call this%set_history_var(vname='FATES_NDEMAND', units='kg m-2 s-1', & + long='plant nitrogen need (algorithm dependent) in kg N per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=5, ivar=ivar, initialize=initialize_variables, & + index = ih_ndemand_si) + + call this%set_history_var(vname='FATES_SYMNFIX', units='kg m-2 s-1', & + long='symbiotic dinitrogen fixation in kg N per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=5, ivar=ivar, initialize=initialize_variables, & + index = ih_nfix_si) + + end select + nitrogen_active_if: if(any(element_list(:)==nitrogen_element)) then call this%set_history_var(vname='FATES_STOREN', units='kg m-2', & long='total nitrogen in live plant storage', use_default='active', & @@ -5233,35 +5354,58 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_repron_si) - call this%set_history_var(vname='FATES_NH4UPTAKE', units='kg m-2 s-1', & - long='ammonium uptake rate by plants in kg NH4 per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=5, ivar=ivar, initialize=initialize_variables, & - index = ih_nh4uptake_si) + call this%set_history_var(vname='FATES_VEGN_SZPF', units='kg m-2', & + long='total (live) vegetation nitrogen mass by size-class x pft in kg N per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_totvegn_scpf) - call this%set_history_var(vname='FATES_NO3UPTAKE', units='kg m-2 s-1', & - long='nitrate uptake rate by plants in kg NO3 per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=5, ivar=ivar, initialize=initialize_variables, & - index = ih_no3uptake_si) + call this%set_history_var(vname='FATES_LEAFN_SZPF', units='kg m-2', & + long='leaf nitrogen mass by size-class x pft in kg N per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_leafn_scpf) - call this%set_history_var(vname='FATES_NEFFLUX', units='kg m-2 s-1', & - long='nitrogen effluxed from plant in kg N per m2 per second (unused)', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=5, ivar=ivar, initialize=initialize_variables, & - index = ih_nefflux_si) + call this%set_history_var(vname='FATES_FROOTN_SZPF', units='kg m-2', & + long='fine-root nitrogen mass by size-class x pft in kg N per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_fnrtn_scpf) - call this%set_history_var(vname='FATES_NDEMAND', units='kg m-2 s-1', & - long='plant nitrogen need (algorithm dependent) in kg N per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=5, ivar=ivar, initialize=initialize_variables, & - index = ih_ndemand_si) + call this%set_history_var(vname='FATES_SAPWOODN_SZPF', units='kg m-2', & + long='sapwood nitrogen mass by size-class x pft in kg N per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_sapwn_scpf) - call this%set_history_var(vname='FATES_SYMNFIX', units='kg m-2 s-1', & - long='symbiotic dinitrogen fixation in kg N per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=5, ivar=ivar, initialize=initialize_variables, & - index = ih_nfix_si) + call this%set_history_var(vname='FATES_STOREN_SZPF', units='kg m-2', & + long='storage nitrogen mass by size-class x pft in kg N per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_storen_scpf) + + call this%set_history_var(vname='FATES_STOREN_TFRAC_CANOPY_SZPF', & + units='1', & + long='storage nitrogen fraction (0-1) of target, in canopy, by size-class x pft', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_storentfrac_canopy_scpf) + + call this%set_history_var(vname='FATES_STOREN_TFRAC_USTORY_SZPF', & + units='1', & + long='storage nitrogen fraction (0-1) of target, in understory, by size-class x pft', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, & + index = ih_storentfrac_understory_scpf) + + call this%set_history_var(vname='FATES_REPRON_SZPF', units='kg m-2', & + long='reproductive nitrogen mass (on plant) by size-class x pft in kg N per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_repron_scpf) + + end if nitrogen_active_if @@ -6885,98 +7029,13 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_reproc_scpf) - call this%set_history_var(vname='FATES_CEFFLUX_SZPF', units='kg m-2 s-1', & - long='carbon efflux, root to soil, by size-class x pft in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=5, ivar=ivar, initialize=initialize_variables, & - index = ih_cefflux_scpf) - ! NITROGEN nitrogen_active_if2: if(any(element_list(:)==nitrogen_element)) then - call this%set_history_var(vname='FATES_VEGN_SZPF', units='kg m-2', & - long='total (live) vegetation nitrogen mass by size-class x pft in kg N per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_totvegn_scpf) - - call this%set_history_var(vname='FATES_LEAFN_SZPF', units='kg m-2', & - long='leaf nitrogen mass by size-class x pft in kg N per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_leafn_scpf) - - call this%set_history_var(vname='FATES_FROOTN_SZPF', units='kg m-2', & - long='fine-root nitrogen mass by size-class x pft in kg N per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_fnrtn_scpf) - call this%set_history_var(vname='FATES_SAPWOODN_SZPF', units='kg m-2', & - long='sapwood nitrogen mass by size-class x pft in kg N per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_sapwn_scpf) - call this%set_history_var(vname='FATES_STOREN_SZPF', units='kg m-2', & - long='storage nitrogen mass by size-class x pft in kg N per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_storen_scpf) - - call this%set_history_var(vname='FATES_STOREN_TFRAC_CANOPY_SZPF', & - units='1', & - long='storage nitrogen fraction (0-1) of target, in canopy, by size-class x pft', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_storentfrac_canopy_scpf) - - call this%set_history_var(vname='FATES_STOREN_TFRAC_USTORY_SZPF', & - units='1', & - long='storage nitrogen fraction (0-1) of target, in understory, by size-class x pft', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_storentfrac_understory_scpf) - - call this%set_history_var(vname='FATES_REPRON_SZPF', units='kg m-2', & - long='reproductive nitrogen mass (on plant) by size-class x pft in kg N per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_repron_scpf) - - call this%set_history_var(vname='FATES_NH4UPTAKE_SZPF', & - units='kg m-2 s-1', & - long='ammonium uptake rate by plants by size-class x pft in kg NH4 per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=5, ivar=ivar, & - initialize=initialize_variables, index = ih_nh4uptake_scpf) - - call this%set_history_var(vname='FATES_NO3UPTAKE_SZPF', & - units='kg m-2 s-1', & - long='nitrate uptake rate by plants by size-class x pft in kg NO3 per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=5, ivar=ivar, & - initialize=initialize_variables, index = ih_no3uptake_scpf) - - call this%set_history_var(vname='FATES_NEFFLUX_SZPF', units='kg m-2 s-1', & - long='nitrogen efflux, root to soil, by size-class x pft in kg N per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=5, ivar=ivar, & - initialize=initialize_variables, index = ih_nefflux_scpf) - - call this%set_history_var(vname='FATES_NDEMAND_SZPF', units='kg m-2 s-1', & - long='plant N need (algorithm dependent), by size-class x pft in kg N per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=5, ivar=ivar, & - initialize=initialize_variables, index = ih_ndemand_scpf) - - call this%set_history_var(vname='FATES_SYMNFIX_SZPF', units='kg m-2 s-1', & - long='symbiotic dinitrogen fixation, by size-class x pft in kg N per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=5, ivar=ivar, & - initialize=initialize_variables, index = ih_nfix_scpf) + end if nitrogen_active_if2 diff --git a/main/FatesHistoryVariableType.F90 b/main/FatesHistoryVariableType.F90 index 6457e644f1..e5331dcbcf 100644 --- a/main/FatesHistoryVariableType.F90 +++ b/main/FatesHistoryVariableType.F90 @@ -14,7 +14,7 @@ module FatesHistoryVariableType use FatesIOVariableKindMod, only : site_can_r8, site_cnlf_r8, site_cnlfpft_r8 use FatesIOVariableKindMod, only : site_elem_r8, site_elpft_r8 use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8 - use FatesIOVariableKindMod, only : iotype_index, site_agefuel_r8 + use FatesIOVariableKindMod, only : iotype_index, site_agefuel_r8, site_clscpf_r8 implicit none private ! By default everything is private @@ -205,6 +205,10 @@ subroutine Init(this, vname, units, long, use_default, & allocate(this%r82d(lb1:ub1, lb2:ub2)) this%r82d(:,:) = flushval + case(site_clscpf_r8) + allocate(this%r82d(lb1:ub1, lb2:ub2)) + this%r82d(:,:) = flushval + case default write(fates_log(),*) 'Incompatible vtype passed to set_history_var' write(fates_log(),*) 'vtype = ',trim(vtype),' ?' @@ -334,6 +338,8 @@ subroutine Flush(this, thread, dim_bounds, dim_kinds) this%r82d(lb1:ub1, lb2:ub2) = this%flushval case(site_agefuel_r8) this%r82d(lb1:ub1, lb2:ub2) = this%flushval + case(site_clscpf_r8) + this%r82d(lb1:ub1, lb2:ub2) = this%flushval case default write(fates_log(),*) 'fates history variable type undefined while flushing history variables' stop diff --git a/main/FatesIODimensionsMod.F90 b/main/FatesIODimensionsMod.F90 index 522da97653..8707313dbc 100644 --- a/main/FatesIODimensionsMod.F90 +++ b/main/FatesIODimensionsMod.F90 @@ -28,7 +28,7 @@ module FatesIODimensionsMod character(*), parameter, public :: levcnlf = 'fates_levcnlf' ! matches histFileMod character(*), parameter, public :: levcnlfpft = 'fates_levcnlfpf' ! matches histFileMod character(*), parameter, public :: levagefuel = 'fates_levagefuel' ! matches histFileMod - + character(*), parameter, public :: levclscpf = 'fates_levclscpf' character(*), parameter, public :: levelem = 'fates_levelem' character(*), parameter, public :: levelpft = 'fates_levelpft' character(*), parameter, public :: levelcwd = 'fates_levelcwd' @@ -93,6 +93,8 @@ module FatesIODimensionsMod ! levagefuel = This is a strcture that records the boundaries for the ! number of patch age x fuel size class + ! levclscpf = '' number of canopy layers x pft x size class + ! levelem = This records the boundaries for the number of elements ! levelpft = This records the boundaries for elements x pft ! levelcwd = This records the boundaries for element x cwd @@ -148,6 +150,8 @@ module FatesIODimensionsMod integer :: elage_end integer :: agefuel_begin integer :: agefuel_end + integer :: clscpf_begin + integer :: clscpf_end end type fates_bounds_type diff --git a/main/FatesIOVariableKindMod.F90 b/main/FatesIOVariableKindMod.F90 index 93b34ebab3..9981ae0285 100644 --- a/main/FatesIOVariableKindMod.F90 +++ b/main/FatesIOVariableKindMod.F90 @@ -35,7 +35,8 @@ module FatesIOVariableKindMod character(*), parameter, public :: site_scagpft_r8 = 'SI_SCAGPFT_R8' character(*), parameter, public :: site_agepft_r8 = 'SI_AGEPFT_R8' character(*), parameter, public :: site_agefuel_r8 = 'SI_AGEFUEL_R8' - + character(*), parameter, public :: site_clscpf_r8 = 'SI_CLSCPF_R8' + ! Element, and multiplexed element dimensions character(*), parameter, public :: site_elem_r8 = 'SI_ELEM_R8' character(*), parameter, public :: site_elpft_r8 = 'SI_ELEMPFT_R8' diff --git a/main/FatesSizeAgeTypeIndicesMod.F90 b/main/FatesSizeAgeTypeIndicesMod.F90 index d624db1e24..307bc31c94 100644 --- a/main/FatesSizeAgeTypeIndicesMod.F90 +++ b/main/FatesSizeAgeTypeIndicesMod.F90 @@ -5,6 +5,7 @@ module FatesSizeAgeTypeIndicesMod use FatesInterfaceTypesMod, only : nlevage use FatesInterfaceTypesMod, only : nlevheight use FatesInterfaceTypesMod, only : nlevcoage + use EDTypesMod, only : nclmax use EDParamsMod, only : ED_val_history_sizeclass_bin_edges use EDParamsMod, only : ED_val_history_ageclass_bin_edges use EDParamsMod, only : ED_val_history_height_bin_edges @@ -24,7 +25,8 @@ module FatesSizeAgeTypeIndicesMod public :: coagetype_class_index public :: get_coage_class_index public :: get_agefuel_class_index - + public :: get_layersizetype_class_index + contains ! ===================================================================================== @@ -41,6 +43,32 @@ end function get_age_class_index ! ===================================================================================== + function get_layersizetype_class_index(layer,dbh,pft) result(iclscpf) + + ! Get the 1D index for a canopy layer x size x pft triplet + + ! Arguments + integer,intent(in) :: layer + real(r8),intent(in) :: dbh + integer,intent(in) :: pft + + integer :: size_class + integer :: iclscpf + + size_class = get_size_class_index(dbh) + + iclscpf = (pft-1)*nlevsclass*nclmax + (size_class-1)*nclmax + layer + + ! FOR ANALYSIS CODE, REVERSE: (assuming indices starting at 1): + + ! pft = ceiling(real(index,r8)/real(nlevsclass*nclmax,r8)) + ! size_class = ceiling(real(index-(pft-1)*nlevsclass*nclmax,r8)/real(nclmax,r8)) + ! layer = index - ((pft-1)*nlevsclass*nclmax + (size_class-1)*nclmax) + + end function get_layersizetype_class_index + + ! ===================================================================================== + function get_sizeage_class_index(dbh,age) result(size_by_age_class) ! Arguments diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 6a6b71bda2..7b8a687985 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -691,6 +691,7 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd) real(r8), pointer :: pc_store real(r8), parameter :: max_l2fr_cgain_frac = 0.99_r8 + real(r8), parameter :: xc_ratio_correction = 1.2_r8 real(r8), parameter :: wgt = 1._r8/10._r8 ! 10-day smoothing @@ -719,7 +720,7 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd) store_nut_act = this%GetState(store_organ, nitrogen_element) + & this%bc_inout(acnp_bc_inout_id_netdn)%rval - n_ratio = min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max)/(store_c_act/store_c_max))) + n_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max)/(store_c_act/store_c_max))) nc_store = wgt*log(n_ratio) + (1._r8-wgt)*nc_store @@ -733,7 +734,7 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd) store_nut_max = this%GetNutrientTarget(phosphorus_element,store_organ,stoich_growth_min) store_nut_act = this%GetState(store_organ, phosphorus_element) + this%bc_inout(acnp_bc_inout_id_netdp)%rval - p_ratio = min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max)/(store_c_act/store_c_max))) + p_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max)/(store_c_act/store_c_max))) pc_store = wgt*log(p_ratio) + (1._r8-wgt)*pc_store diff --git a/parteh/PRTGenericMod.F90 b/parteh/PRTGenericMod.F90 index f3e995f18a..40cc75898e 100644 --- a/parteh/PRTGenericMod.F90 +++ b/parteh/PRTGenericMod.F90 @@ -67,8 +67,7 @@ module PRTGenericMod ! ------------------------------------------------------------------------------------- integer, parameter, public :: prt_carbon_allom_hyp = 1 - integer, parameter, public :: prt_cnp_flex_allom_hyp = 2 ! Still under development - + integer, parameter, public :: prt_cnp_flex_allom_hyp = 2 ! ------------------------------------------------------------------------------------- ! Organ types From 8186d50c402df8737a891b5fdcd1d27bff434c05 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 3 Aug 2022 15:19:15 -0700 Subject: [PATCH 306/852] correct conversion to radians --- main/FatesConstantsMod.F90 | 1 + main/FatesUtilsMod.F90 | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index 11d209865a..dfade42b5b 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -233,5 +233,6 @@ module FatesConstantsMod ! PI real(fates_r8), parameter, public :: pi_const = 3.14159265359_fates_r8 + real(fates_r8), parameter, public :: rad_per_deg = pi_const/180.0_fates_r8 end module FatesConstantsMod diff --git a/main/FatesUtilsMod.F90 b/main/FatesUtilsMod.F90 index 6dfd2dbcc0..27eef57247 100644 --- a/main/FatesUtilsMod.F90 +++ b/main/FatesUtilsMod.F90 @@ -86,7 +86,7 @@ end subroutine check_var_real real(r8) function GreatCircleDist(slons,slonf,slats,slatf) use FatesConstantsMod, only : earth_radius_eq & - , pi_const + , rad_per_deg implicit none !----- Local variables. ----------------------------------------------------------------! @@ -107,10 +107,10 @@ real(r8) function GreatCircleDist(slons,slonf,slats,slatf) !---------------------------------------------------------------------------------------! !----- Convert the co-ordinates to double precision and to radians. --------------------! - lons = slons * pi_const - lonf = slonf * pi_const - lats = slats * pi_const - latf = slatf * pi_const + lons = slons * rad_per_deg + lonf = slonf * rad_per_deg + lats = slats * rad_per_deg + latf = slatf * rad_per_deg dlon = lonf - lons dlat = latf - lats From 73596b7a35ea65d6595fcc46bd14eab085d0b8a8 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 4 Aug 2022 12:36:02 -0400 Subject: [PATCH 307/852] Added nearzero to if logic --- biogeochem/EDCanopyStructureMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 6fb7529bf1..4066aec6b6 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1555,7 +1555,7 @@ subroutine leaf_area_profile( currentSite ) ! This may indeed be zero if there is a sensecent grass ! ---------------------------------------------------------------- - if( (currentCohort%treelai+currentCohort%treesai) > 0._r8)then + if( (currentCohort%treelai+currentCohort%treesai) > nearzero)then fleaf = currentCohort%treelai / (currentCohort%treelai + currentCohort%treesai) else fleaf = 0._r8 From 658c14b43d21f660192b41e22e391c78439658d2 Mon Sep 17 00:00:00 2001 From: ckoven Date: Thu, 4 Aug 2022 12:23:19 -0600 Subject: [PATCH 308/852] updated EDPatchDynamics to also send grass stem biomass to leaf litter rather than CWD pools --- biogeochem/EDPatchDynamicsMod.F90 | 35 +++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index d1c9a79b3d..d81aa10634 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1637,12 +1637,24 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & ! across ground surface. ! ----------------------------------------------------------------------- - sapw_m = currentCohort%prt%GetState(sapw_organ, element_id) - struct_m = currentCohort%prt%GetState(struct_organ, element_id) - leaf_m = currentCohort%prt%GetState(leaf_organ, element_id) fnrt_m = currentCohort%prt%GetState(fnrt_organ, element_id) store_m = currentCohort%prt%GetState(store_organ, element_id) repro_m = currentCohort%prt%GetState(repro_organ, element_id) + + if (prt_params%woody(currentCohort%pft) == itrue) then + ! Assumption: for woody plants, we lump fluxes from deadwood and sapwood together in CWD pool. + ! for non-woody plants, we put all stem fluxes into the same leaf litter pool. + leaf_m = currentCohort%prt%GetState(leaf_organ,element_id) + sapw_m = currentCohort%prt%GetState(sapw_organ,element_id) + struct_m = currentCohort%prt%GetState(struct_organ,element_id) + else + leaf_m = currentCohort%prt%GetState(leaf_organ,element_id) + & + currentCohort%prt%GetState(sapw_organ,element_id) + & + currentCohort%prt%GetState(struct_organ,element_id) + sapw_m = 0._r8 + struct_m = 0._r8 + end if + ! Absolute number of dead trees being transfered in with the donated area num_dead_trees = (currentCohort%fire_mort*currentCohort%n * & @@ -1823,13 +1835,24 @@ subroutine mortality_litter_fluxes(currentSite, currentPatch, & pft = currentCohort%pft - sapw_m = currentCohort%prt%GetState(sapw_organ, element_id) - struct_m = currentCohort%prt%GetState(struct_organ, element_id) - leaf_m = currentCohort%prt%GetState(leaf_organ, element_id) fnrt_m = currentCohort%prt%GetState(fnrt_organ, element_id) store_m = currentCohort%prt%GetState(store_organ, element_id) repro_m = currentCohort%prt%GetState(repro_organ, element_id) + if (prt_params%woody(currentCohort%pft) == itrue) then + ! Assumption: for woody plants, we lump fluxes from deadwood and sapwood together in CWD pool. + ! for non-woody plants, we put all stem fluxes into the same leaf litter pool. + leaf_m = currentCohort%prt%GetState(leaf_organ,element_id) + sapw_m = currentCohort%prt%GetState(sapw_organ,element_id) + struct_m = currentCohort%prt%GetState(struct_organ,element_id) + else + leaf_m = currentCohort%prt%GetState(leaf_organ,element_id) + & + currentCohort%prt%GetState(sapw_organ,element_id) + & + currentCohort%prt%GetState(struct_organ,element_id) + sapw_m = 0._r8 + struct_m = 0._r8 + end if + if(currentCohort%canopy_layer == 1)then ! Upper canopy trees. The total dead is based on their disturbance From 84e4e5dd90f94ebeca915958e6dc7558f7147a38 Mon Sep 17 00:00:00 2001 From: ckoven Date: Mon, 25 Jul 2022 15:37:18 -0600 Subject: [PATCH 309/852] updated litterfall logic so that grass stem litterfall goes into leaf litter rather than CWD pools --- biogeochem/EDPhysiologyMod.F90 | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 9a43af3226..7ccea5079c 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2197,20 +2197,38 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) call set_root_fraction(currentSite%rootfrac_scr, pft, currentSite%zi_soil, & bc_in%max_rooting_depth_index_col) - leaf_m_turnover = currentCohort%prt%GetTurnover(leaf_organ,element_id) store_m_turnover = currentCohort%prt%GetTurnover(store_organ,element_id) fnrt_m_turnover = currentCohort%prt%GetTurnover(fnrt_organ,element_id) - sapw_m_turnover = currentCohort%prt%GetTurnover(sapw_organ,element_id) - struct_m_turnover = currentCohort%prt%GetTurnover(struct_organ,element_id) repro_m_turnover = currentCohort%prt%GetTurnover(repro_organ,element_id) - leaf_m = currentCohort%prt%GetState(leaf_organ,element_id) store_m = currentCohort%prt%GetState(store_organ,element_id) fnrt_m = currentCohort%prt%GetState(fnrt_organ,element_id) - sapw_m = currentCohort%prt%GetState(sapw_organ,element_id) - struct_m = currentCohort%prt%GetState(struct_organ,element_id) repro_m = currentCohort%prt%GetState(repro_organ,element_id) + if (prt_params%woody(currentCohort%pft) == itrue) then + ! Assumption: for woody plants, we lump fluxes from deadwood and sapwood together in CWD pool. + ! for non-woody plants, we put all stem fluxes into the same leaf litter pool. + leaf_m_turnover = currentCohort%prt%GetTurnover(leaf_organ,element_id) + sapw_m_turnover = currentCohort%prt%GetTurnover(sapw_organ,element_id) + struct_m_turnover = currentCohort%prt%GetTurnover(struct_organ,element_id) + + leaf_m = currentCohort%prt%GetState(leaf_organ,element_id) + sapw_m = currentCohort%prt%GetState(sapw_organ,element_id) + struct_m = currentCohort%prt%GetState(struct_organ,element_id) + else + leaf_m_turnover = currentCohort%prt%GetTurnover(leaf_organ,element_id) + & + currentCohort%prt%GetTurnover(sapw_organ,element_id) + & + currentCohort%prt%GetTurnover(struct_organ,element_id) + sapw_m_turnover = 0._r8 + struct_m_turnover = 0._r8 + + leaf_m = currentCohort%prt%GetState(leaf_organ,element_id) + & + currentCohort%prt%GetState(sapw_organ,element_id) + & + currentCohort%prt%GetState(struct_organ,element_id) + sapw_m = 0._r8 + struct_m = 0._r8 + end if + plant_dens = currentCohort%n/currentPatch%area ! --------------------------------------------------------------------------------- From 434c0e0b0b5894923f59875c2c6860ff540c8b52 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 8 Aug 2022 13:05:40 -0400 Subject: [PATCH 310/852] Added in CNP limiter logic --- biogeochem/EDCohortDynamicsMod.F90 | 4 +- parteh/PRTAllometricCNPMod.F90 | 196 +++++++++++++++++++++++++---- 2 files changed, 174 insertions(+), 26 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index e671d8982e..67dde74f5c 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -252,8 +252,8 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & new_cohort%l2fr = prt_params%allom_l2fr(pft) - new_cohort%nc_store = 1._r8 ! Assume balanced N/C stores - new_cohort%pc_store = 1._r8 ! Assume balanced P/C stores + new_cohort%nc_store = 0._r8 ! Assume balanced N/C stores ie log(1) = 0 + new_cohort%pc_store = 0._r8 ! Assume balanced P/C stores ie log(1) = 0 ! This sets things like vcmax25top, that depend on the ! leaf age fractions (which are defined by PARTEH) diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 7b8a687985..6c1d966125 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -131,6 +131,10 @@ module PRTAllometricCNPMod integer, parameter :: num_intgr_vars = 7 + integer, parameter :: cnp_limited = 0 + integer, parameter :: c_limited = 1 + integer, parameter :: n_limited = 2 + integer, parameter :: p_limited = 3 ! ------------------------------------------------------------------------------------- ! Input/Output Boundary Indices (These are public, and therefore @@ -361,7 +365,7 @@ subroutine DailyPRTAllometricCNP(this) real(r8) :: agw_c_target,agw_dcdd_target real(r8) :: bgw_c_target,bgw_dcdd_target real(r8) :: sapw_area - real(r8) :: store_c_flux + real(r8) :: store_flux integer :: i ! generic organ loop index integer :: i_org ! organ index integer :: i_var ! variable index @@ -378,6 +382,10 @@ subroutine DailyPRTAllometricCNP(this) real(r8) :: p_gain0 real(r8) :: resp_excess0 + real(r8) :: c_alloc_nso ! Allocated C not including changes in storage overflow + real(r8) :: n_alloc_nso ! Allocated N not including changes in storage overflow + real(r8) :: p_alloc_nso ! Allocated P not including changes in storage overflow + ! Used for mass checking, total mass allocated based ! on change in the states, should match gain0's real(r8) :: allocated_c @@ -387,6 +395,8 @@ subroutine DailyPRTAllometricCNP(this) real(r8) :: sum_c ! error checking sum + print*,"ALLOC" + ! If more than 1 leaf age bin is present, this ! call advances leaves in their age, but does ! not actually remove any biomass from the plant @@ -482,23 +492,53 @@ subroutine DailyPRTAllometricCNP(this) c_efflux => this%bc_out(acnp_bc_out_id_cefflux)%rval; c_efflux = 0._r8 n_efflux => this%bc_out(acnp_bc_out_id_nefflux)%rval; n_efflux = 0._r8 p_efflux => this%bc_out(acnp_bc_out_id_pefflux)%rval; p_efflux = 0._r8 - + + ! Bring storage pools down to the first target put overflow into gain pools + store_flux = max(0._r8, this%variables(store_c_id)%val(1) - target_c(store_organ)) + c_gain = c_gain + store_flux + this%variables(store_c_id)%val(1) = this%variables(store_c_id)%val(1) - store_flux + target_n = this%GetNutrientTarget(nitrogen_element,store_organ,stoich_growth_min) + store_flux = max(0._r8, this%variables(store_n_id)%val(1) - target_n) + n_gain = n_gain + store_flux + print*,"n store flux: ",store_flux + this%variables(store_n_id)%val(1) = this%variables(store_n_id)%val(1) - store_flux + target_p = this%GetNutrientTarget(phosphorus_element,store_organ,stoich_growth_min) + store_flux = max(0._r8, this%variables(store_p_id)%val(1) - target_p) + p_gain = p_gain + store_flux + print*,"p store flux: ",store_flux + this%variables(store_p_id)%val(1) = this%variables(store_p_id)%val(1) - store_flux + + n_alloc_nso = 0._r8 + c_alloc_nso = 0._r8 + p_alloc_nso = 0._r8 + do i = 1,num_organs + i_org = l2g_organ_list(i) ! global index from PRTGeneric + i_var = prt_global%sp_organ_map(i_org,carbon12_element) + c_alloc_nso = c_alloc_nso - this%variables(i_var)%val(1) + i_var = prt_global%sp_organ_map(i_org,nitrogen_element) + n_alloc_nso = n_alloc_nso - this%variables(i_var)%val(1) + i_var = prt_global%sp_organ_map(i_org,phosphorus_element) + p_alloc_nso = p_alloc_nso - this%variables(i_var)%val(1) + end do + + ! =================================================================================== ! Step 0. Transfer all stored nutrient into the daily uptake pool. Also ! transfer C storage that is above the target (ie transfer overflow) ! =================================================================================== ! Put overflow storage into the net daily pool - store_c_flux = max(0._r8, this%variables(store_c_id)%val(1) - target_c(store_organ)) - - c_gain = c_gain + store_c_flux - this%variables(store_c_id)%val(1) = this%variables(store_c_id)%val(1) - store_c_flux - + !store_flux = max(0._r8, this%variables(store_c_id)%val(1) - target_c(store_organ)) + !c_gain = c_gain + store_flux + !this%variables(store_c_id)%val(1) = this%variables(store_c_id)%val(1) - store_flux + n_gain = n_gain + sum(this%variables(store_n_id)%val(:)) this%variables(store_n_id)%val(:) = 0._r8 p_gain = p_gain + sum(this%variables(store_p_id)%val(:)) this%variables(store_p_id)%val(:) = 0._r8 + + ! =================================================================================== ! Step 2. Prioritized allocation to replace tissues from turnover, and/or pay @@ -553,8 +593,20 @@ subroutine DailyPRTAllometricCNP(this) ! At this point, at least 1 of the 3 resources have been used up. ! Allocate the remaining resources, or as a last resort, efflux them. ! =================================================================================== + + do i = 1,num_organs + i_org = l2g_organ_list(i) ! global index from PRTGeneric + i_var = prt_global%sp_organ_map(i_org,carbon12_element) + c_alloc_nso = c_alloc_nso + this%variables(i_var)%val(1) + i_var = prt_global%sp_organ_map(i_org,nitrogen_element) + n_alloc_nso = n_alloc_nso + this%variables(i_var)%val(1) + i_var = prt_global%sp_organ_map(i_org,phosphorus_element) + p_alloc_nso = p_alloc_nso + this%variables(i_var)%val(1) + end do - call this%CNPAllocateRemainder(c_gain, n_gain, p_gain, & + call this%CNPAllocateRemainder(c_gain, n_gain, p_gain, & + c_gain0, n_gain0, p_gain0, & + c_alloc_nso, n_alloc_nso, p_alloc_nso, & c_efflux, n_efflux, p_efflux) @@ -689,10 +741,10 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd) real(r8) :: l2fr_mult real(r8), pointer :: nc_store real(r8), pointer :: pc_store - + !real(r8), parameter :: wgt = 1._r8/10._r8 ! 10-day smoothing real(r8), parameter :: max_l2fr_cgain_frac = 0.99_r8 - real(r8), parameter :: xc_ratio_correction = 1.2_r8 - real(r8), parameter :: wgt = 1._r8/10._r8 ! 10-day smoothing + real(r8), parameter :: xc_ratio_correction = 1.0_r8 + ipft = this%bc_in(acnp_bc_in_id_pft)%ival @@ -722,7 +774,7 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd) n_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max)/(store_c_act/store_c_max))) - nc_store = wgt*log(n_ratio) + (1._r8-wgt)*nc_store + !nc_store = wgt*log(n_ratio) + (1._r8-wgt)*nc_store end if @@ -736,7 +788,7 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd) store_nut_act = this%GetState(store_organ, phosphorus_element) + this%bc_inout(acnp_bc_inout_id_netdp)%rval p_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max)/(store_c_act/store_c_max))) - pc_store = wgt*log(p_ratio) + (1._r8-wgt)*pc_store + !pc_store = wgt*log(p_ratio) + (1._r8-wgt)*pc_store end if @@ -851,7 +903,7 @@ subroutine TrimFineRoot(this) real(r8) :: pc_fnrt real(r8) :: target_fnrt_c real(r8),parameter :: nday_buffer = 0._r8 - real(r8),parameter :: fnrt_opt_eff = 1._r8 ! If we want to transfer resources to storage + real(r8),parameter :: fnrt_opt_eff = 0._r8 ! If we want to transfer resources to storage if(.not.use_unrestricted_contraction)return @@ -1337,9 +1389,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & integer, parameter :: grow_lim_type = grow_lim_estNP real :: neq_cgain, peq_cgain ! N and P equivalent c_gain spent on growth real :: cnp_gain ! used as a check to see efficiency of limited growth - integer, parameter :: c_limited = 1 - integer, parameter :: n_limited = 2 - integer, parameter :: p_limited = 3 + leaf_status = this%bc_in(acnp_bc_in_id_lstat)%ival @@ -1350,7 +1400,15 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & l2fr = this%bc_inout(acnp_bc_inout_id_l2fr)%rval ! This variable is not updated in this ! routine, and is therefore not a pointer - + if( c_gain <= calloc_abs_error ) then + limiter = c_limited + if((n_gain <= 0.1_r8*calloc_abs_error) .or. & + (p_gain <= 0.02_r8*calloc_abs_error)) limiter = cnp_limited + else + if(n_gain <= 0.1_r8*calloc_abs_error) limiter = n_limited + if(p_gain <= 0.02_r8*calloc_abs_error) limiter = p_limited + end if + ! If any of these resources is essentially tapped out, ! then there is no point in performing growth ! It also seems impossible that we would be in a leaf-off status @@ -1364,7 +1422,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & leaf_status.eq.leaves_off .or. & n_gain <= 0.1_r8*calloc_abs_error .or. & p_gain <= 0.02_r8*calloc_abs_error ) then - limiter = 0 + print*,"lim: ",limiter return end if @@ -1750,19 +1808,27 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & p_gain, phosphorus_element,mask_gorgans(1:n_mask_organs)) end if if_stature_growth - + print*,"lim:",limiter return end subroutine CNPStatureGrowth ! ===================================================================================== - subroutine CNPAllocateRemainder(this, c_gain, n_gain, p_gain, & - c_efflux, n_efflux, p_efflux) + subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & + c_gain0, n_gain0, p_gain0, & + c_alloc_nso, n_alloc_nso, p_alloc_nso, & + c_efflux, n_efflux, p_efflux) class(cnp_allom_prt_vartypes) :: this real(r8), intent(inout) :: c_gain real(r8), intent(inout) :: n_gain - real(r8), intent(inout) :: p_gain + real(r8), intent(inout) :: p_gain + real(r8), intent(in) :: c_alloc_nso ! Allocated C + real(r8), intent(in) :: n_alloc_nso ! Allocated N + real(r8), intent(in) :: p_alloc_nso ! Allocated P + real(r8), intent(in) :: c_gain0 ! Total C gain for the day + real(r8), intent(in) :: n_gain0 ! Total N gain for the day + real(r8), intent(in) :: p_gain0 ! Total P gain for the day real(r8), intent(inout) :: c_efflux real(r8), intent(inout) :: n_efflux real(r8), intent(inout) :: p_efflux @@ -1777,15 +1843,93 @@ subroutine CNPAllocateRemainder(this, c_gain, n_gain, p_gain, & real(r8) :: store_m_flux ! Flux into storage [kg] real(r8), pointer :: dbh real(r8), pointer :: resp_excess + real(r8), pointer :: nc_store,pc_store integer :: ipft + integer, pointer :: limiter real(r8) :: canopy_trim - + real(r8) :: n_ratio,p_ratio,c_ratio + real(r8) :: nc_ratio,pc_ratio + real(r8), pointer :: l2fr + real(r8), parameter :: wgt = 1._r8/5._r8 ! 10-day smoothing dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival resp_excess => this%bc_inout(acnp_bc_inout_id_resp_excess)%rval + nc_store => this%bc_inout(acnp_bc_inout_id_nc_store)%rval + pc_store => this%bc_inout(acnp_bc_inout_id_pc_store)%rval + l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval + limiter => this%bc_out(acnp_bc_out_id_limiter)%ival + + ! Update the F_NPC + + ! n_ratio the ratio of n_gain/n_alloc / c_gain/c_alloc + ! If either n or p uptake is in prescribed mode + ! set the gains to something massive. 1 kilo of pure + ! nutrient should be wayyy more than enough + if(.false.)then + if(c_alloc_nso Date: Tue, 9 Aug 2022 12:56:30 -0400 Subject: [PATCH 311/852] Alternative PID error terms in CNP --- parteh/PRTAllometricCNPMod.F90 | 228 +++++++++++++++------------------ 1 file changed, 101 insertions(+), 127 deletions(-) diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 6c1d966125..95049cf95b 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -100,6 +100,15 @@ module PRTAllometricCNPMod integer, parameter :: num_vars = 18 + ! Setpoint Error controller method + integer, parameter, private :: storage_spe = 0 + integer, parameter, private :: binary_limiter_spe = 1 + integer, parameter, private :: daily_gain_ratio_spe = 2 + + integer, parameter, private :: pid_spe_controller = storage_spe + + real(r8), parameter, private :: pid_int_wgt = 1._r8/5._r8 ! n-day smoothing (K on the integral of PID) + ! Global identifiers for the two stoichiometry values integer,public, parameter :: stoich_growth_min = 1 ! Flag for stoichiometry associated with ! minimum needed for growth @@ -382,10 +391,6 @@ subroutine DailyPRTAllometricCNP(this) real(r8) :: p_gain0 real(r8) :: resp_excess0 - real(r8) :: c_alloc_nso ! Allocated C not including changes in storage overflow - real(r8) :: n_alloc_nso ! Allocated N not including changes in storage overflow - real(r8) :: p_alloc_nso ! Allocated P not including changes in storage overflow - ! Used for mass checking, total mass allocated based ! on change in the states, should match gain0's real(r8) :: allocated_c @@ -394,9 +399,6 @@ subroutine DailyPRTAllometricCNP(this) real(r8) :: target_n,target_p real(r8) :: sum_c ! error checking sum - - print*,"ALLOC" - ! If more than 1 leaf age bin is present, this ! call advances leaves in their age, but does ! not actually remove any biomass from the plant @@ -500,28 +502,12 @@ subroutine DailyPRTAllometricCNP(this) target_n = this%GetNutrientTarget(nitrogen_element,store_organ,stoich_growth_min) store_flux = max(0._r8, this%variables(store_n_id)%val(1) - target_n) n_gain = n_gain + store_flux - print*,"n store flux: ",store_flux this%variables(store_n_id)%val(1) = this%variables(store_n_id)%val(1) - store_flux target_p = this%GetNutrientTarget(phosphorus_element,store_organ,stoich_growth_min) store_flux = max(0._r8, this%variables(store_p_id)%val(1) - target_p) p_gain = p_gain + store_flux - print*,"p store flux: ",store_flux this%variables(store_p_id)%val(1) = this%variables(store_p_id)%val(1) - store_flux - n_alloc_nso = 0._r8 - c_alloc_nso = 0._r8 - p_alloc_nso = 0._r8 - do i = 1,num_organs - i_org = l2g_organ_list(i) ! global index from PRTGeneric - i_var = prt_global%sp_organ_map(i_org,carbon12_element) - c_alloc_nso = c_alloc_nso - this%variables(i_var)%val(1) - i_var = prt_global%sp_organ_map(i_org,nitrogen_element) - n_alloc_nso = n_alloc_nso - this%variables(i_var)%val(1) - i_var = prt_global%sp_organ_map(i_org,phosphorus_element) - p_alloc_nso = p_alloc_nso - this%variables(i_var)%val(1) - end do - - ! =================================================================================== ! Step 0. Transfer all stored nutrient into the daily uptake pool. Also ! transfer C storage that is above the target (ie transfer overflow) @@ -594,19 +580,8 @@ subroutine DailyPRTAllometricCNP(this) ! Allocate the remaining resources, or as a last resort, efflux them. ! =================================================================================== - do i = 1,num_organs - i_org = l2g_organ_list(i) ! global index from PRTGeneric - i_var = prt_global%sp_organ_map(i_org,carbon12_element) - c_alloc_nso = c_alloc_nso + this%variables(i_var)%val(1) - i_var = prt_global%sp_organ_map(i_org,nitrogen_element) - n_alloc_nso = n_alloc_nso + this%variables(i_var)%val(1) - i_var = prt_global%sp_organ_map(i_org,phosphorus_element) - p_alloc_nso = p_alloc_nso + this%variables(i_var)%val(1) - end do - call this%CNPAllocateRemainder(c_gain, n_gain, p_gain, & c_gain0, n_gain0, p_gain0, & - c_alloc_nso, n_alloc_nso, p_alloc_nso, & c_efflux, n_efflux, p_efflux) @@ -741,7 +716,7 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd) real(r8) :: l2fr_mult real(r8), pointer :: nc_store real(r8), pointer :: pc_store - !real(r8), parameter :: wgt = 1._r8/10._r8 ! 10-day smoothing + real(r8), parameter :: max_l2fr_cgain_frac = 0.99_r8 real(r8), parameter :: xc_ratio_correction = 1.0_r8 @@ -753,45 +728,48 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd) canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval nc_store => this%bc_inout(acnp_bc_inout_id_nc_store)%rval pc_store => this%bc_inout(acnp_bc_inout_id_pc_store)%rval - - ! Step 1: Determine the nutrient to carbon ratio (aka relative health factor) - ! ----------------------------------------------------------------------------------- - - store_c_max = target_c(store_organ) - - store_c_act = this%GetState(store_organ, carbon12_element) + & - this%bc_in(acnp_bc_in_id_netdc)%rval - - if(n_uptake_mode.ne.prescribed_n_uptake)then - - ! Calculate the relative nitrogen storage fraction, - ! over the relative carbon storage fraction. - - store_nut_max = this%GetNutrientTarget(nitrogen_element,store_organ,stoich_growth_min) - - store_nut_act = this%GetState(store_organ, nitrogen_element) + & - this%bc_inout(acnp_bc_inout_id_netdn)%rval - n_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max)/(store_c_act/store_c_max))) - !nc_store = wgt*log(n_ratio) + (1._r8-wgt)*nc_store + if(pid_spe_controller == storage_spe) then - end if - - if(p_uptake_mode.ne.prescribed_p_uptake)then - - ! Calculate the relative phosphorus storage fraction, - ! over the relative carbon storage fraction. - - store_nut_max = this%GetNutrientTarget(phosphorus_element,store_organ,stoich_growth_min) - - store_nut_act = this%GetState(store_organ, phosphorus_element) + this%bc_inout(acnp_bc_inout_id_netdp)%rval - p_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max)/(store_c_act/store_c_max))) + ! Step 1: Determine the nutrient to carbon ratio (aka relative health factor) + ! ----------------------------------------------------------------------------------- + + store_c_max = target_c(store_organ) + + store_c_act = this%GetState(store_organ, carbon12_element) + & + this%bc_in(acnp_bc_in_id_netdc)%rval + + if(n_uptake_mode.ne.prescribed_n_uptake)then + + ! Calculate the relative nitrogen storage fraction, + ! over the relative carbon storage fraction. + + store_nut_max = this%GetNutrientTarget(nitrogen_element,store_organ,stoich_growth_min) + + store_nut_act = this%GetState(store_organ, nitrogen_element) + & + this%bc_inout(acnp_bc_inout_id_netdn)%rval - !pc_store = wgt*log(p_ratio) + (1._r8-wgt)*pc_store + n_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max)/(store_c_act/store_c_max))) + + nc_store = pid_int_wgt*log(n_ratio) + (1._r8-pid_int_wgt)*nc_store + + end if + if(p_uptake_mode.ne.prescribed_p_uptake)then + + ! Calculate the relative phosphorus storage fraction, + ! over the relative carbon storage fraction. + + store_nut_max = this%GetNutrientTarget(phosphorus_element,store_organ,stoich_growth_min) + + store_nut_act = this%GetState(store_organ, phosphorus_element) + this%bc_inout(acnp_bc_inout_id_netdp)%rval + p_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max)/(store_c_act/store_c_max))) + + pc_store = pid_int_wgt*log(p_ratio) + (1._r8-pid_int_wgt)*pc_store + + end if end if - ! Use the limiting nutrient species if(n_uptake_mode.eq.prescribed_n_uptake)then @@ -1422,7 +1400,6 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & leaf_status.eq.leaves_off .or. & n_gain <= 0.1_r8*calloc_abs_error .or. & p_gain <= 0.02_r8*calloc_abs_error ) then - print*,"lim: ",limiter return end if @@ -1808,7 +1785,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & p_gain, phosphorus_element,mask_gorgans(1:n_mask_organs)) end if if_stature_growth - print*,"lim:",limiter + return end subroutine CNPStatureGrowth @@ -1816,16 +1793,12 @@ end subroutine CNPStatureGrowth subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & c_gain0, n_gain0, p_gain0, & - c_alloc_nso, n_alloc_nso, p_alloc_nso, & c_efflux, n_efflux, p_efflux) class(cnp_allom_prt_vartypes) :: this real(r8), intent(inout) :: c_gain real(r8), intent(inout) :: n_gain real(r8), intent(inout) :: p_gain - real(r8), intent(in) :: c_alloc_nso ! Allocated C - real(r8), intent(in) :: n_alloc_nso ! Allocated N - real(r8), intent(in) :: p_alloc_nso ! Allocated P real(r8), intent(in) :: c_gain0 ! Total C gain for the day real(r8), intent(in) :: n_gain0 ! Total N gain for the day real(r8), intent(in) :: p_gain0 ! Total P gain for the day @@ -1850,7 +1823,6 @@ subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & real(r8) :: n_ratio,p_ratio,c_ratio real(r8) :: nc_ratio,pc_ratio real(r8), pointer :: l2fr - real(r8), parameter :: wgt = 1._r8/5._r8 ! 10-day smoothing dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval @@ -1867,68 +1839,70 @@ subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & ! If either n or p uptake is in prescribed mode ! set the gains to something massive. 1 kilo of pure ! nutrient should be wayyy more than enough - if(.false.)then - if(c_alloc_nso Date: Thu, 11 Aug 2022 15:40:25 -0700 Subject: [PATCH 312/852] refactored neighborhood code into fates --- main/FatesInterfaceMod.F90 | 169 +++++++++++++++++++++++++++++++- main/FatesInterfaceTypesMod.F90 | 49 ++++++++- main/FatesUtilsMod.F90 | 19 +++- 3 files changed, 231 insertions(+), 6 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index f0c859ed44..4cef727a2b 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -134,8 +134,6 @@ module FatesInterfaceMod end type fates_interface_type - - character(len=*), parameter :: sourcefile = & __FILE__ @@ -153,6 +151,7 @@ module FatesInterfaceMod public :: set_bcs public :: UpdateFatesRMeansTStep public :: InitTimeAveragingGlobals + public :: DetermineGridCellNeighbors contains @@ -1884,5 +1883,171 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) return end subroutine UpdateFatesRMeansTStep + + ! ====================================================================================== + + subroutine DetermineGridCellNeighbors(neighbors) + + ! This subroutine utilizes information from the decomposition and domain types to determine + ! the set of grid cell neighbors within some maximum distance. It records the distance for each + ! neighbor for later use. This should be called after decompInit_lnd and surf_get_grid + ! as it relies on ldecomp and ldomain information. + + use decompMod , only : ldecomp, procinfo, get_proc_global + use domainMod , only : ldomain + use spmdMod , only : MPI_REAL8, MPI_INTEGER, mpicom, npes, masterproc, iam + use perf_mod , only : t_startf, t_stopf + use FatesInterfaceTypesMod, only : neighborhood_type, neighbor_type + use FatesUtilsMod , only : GetNeighborDistance + + ! Arguments + type(neighborhood_type), intent(inout), pointer :: neighbors(:) + + ! Local variables + type (neighbor_type), pointer :: current_neighbor + type (neighbor_type), pointer :: another_neighbor + + integer :: gi,gj ! indices + integer :: numg ! number of land gridcells + integer :: ngcheck ! number of land gridcells, globally + integer :: numproc ! number of processors, globally + integer :: ier,mpierr ! error code + integer :: i + + integer :: ldsize ! ldomain size + integer, allocatable :: ncells_array(:), begg_array(:) + real(r8), allocatable :: gclat(:), gclon(:) + + real(r8) :: g2g_dist ! grid cell distance + + ! Parameters and constants, to be moved to fates param file + ! Both of these should probably be per pft + real(r8) :: decay_rate = 1._r8 + real(r8) :: g2g_dist_max = 2500._r8 * 1000._r8 ! maximum search distance [m] + ! 5 deg = 785.8 km, 10 deg = 1569 km, 15deg = 2345 km assumes cartesian layout with diagonal distance + + ! Allocate array neighbor type + numg = size(ldecomp%gdc2glo) + ! call get_proc_global(ng=ngcheck,np=numproc) + + ! write(fates_log(),*)'DGCN: numg, ngcheck: ', numg, ngcheck + ! write(fates_log(),*)'DGCN: npes, numproc: ', npes, numproc + + allocate(neighbors(numg), stat=ier) + neighbors(:)%dist_weight_tot = nan + neighbors(:)%neighbor_count = 0 + + allocate(gclat(numg)) + allocate(gclon(numg)) + gclon = nan + gclat = nan + + allocate(ncells_array(0:npes-1)) + allocate(begg_array(0:npes-1)) + ncells_array = -999 + begg_array = -999 + + write(fates_log(),*)'DGCN: procinfo%ncells: ', procinfo%ncells + write(fates_log(),*)'DGCN: procinfo%begg: ', procinfo%begg + + call t_startf('fates-seed-init-allgather') + ! Gather the sizes of the ldomain that each mpi rank is passing + call MPI_Allgather(procinfo%ncells,1,MPI_INTEGER,ncells_array,1,MPI_INTEGER,mpicom,mpierr) + + ! Gather the starting index for each ldomain (reduce begging index by one for mpi rank conversion) + call MPI_Allgather(procinfo%begg-1,1,MPI_INTEGER,begg_array,1,MPI_INTEGER,mpicom,mpierr) + + ! Gather the domain information together into the neighbor type + call MPI_Allgatherv(ldomain%latc,procinfo%ncells,MPI_REAL8,gclat,ncells_array,begg_array,MPI_REAL8,mpicom,mpierr) + call MPI_Allgatherv(ldomain%lonc,procinfo%ncells,MPI_REAL8,gclon,ncells_array,begg_array,MPI_REAL8,mpicom,mpierr) + + if (iam==1) then + write(fates_log(),*)'DGCN: ncells_array: ', ncells_array + write(fates_log(),*)'DGCN: begg_array: ', begg_array + write(fates_log(),*)'DGCN: sum(gclat):, sum(gclon): ', sum(gclat), sum(gclon) + do i = 1,numg + write(fates_log(),*)'DGCN: i, gclat, gclon: ', i, gclat(i), gclon(i) + end do + end if + + call t_stopf('fates-seed-init-allgather') + + call t_startf('fates-seed-init-decomp') + + ! Iterate through the grid cell indices and determine if any neighboring cells are in range + gc_loop: do gi = 1,numg-1 + + ! Seach forward through all indices for neighbors to current grid cell index + neighbor_search: do gj = gi+1,numg + + ! Determine distance to old grid cells to the current one + g2g_dist = GetNeighborDistance(gi,gj,gclat,gclon) + + dist_check: if (g2g_dist .le. g2g_dist_max) then + + ! Add neighbor index to current grid cell index list + allocate(current_neighbor) + current_neighbor%next_neighbor => null() + + ! ldomain and ldecomp indices match per initGridCells + current_neighbor%gindex = ldecomp%gdc2glo(gj) + + current_neighbor%gc_dist = g2g_dist + current_neighbor%dist_weight = current_neighbor%DistWeightCalc(g2g_dist,decay_rate) + + if (associated(neighbors(gi)%first_neighbor)) then + neighbors(gi)%last_neighbor%next_neighbor => current_neighbor + neighbors(gi)%last_neighbor => current_neighbor + else + neighbors(gi)%first_neighbor => current_neighbor + neighbors(gi)%last_neighbor => current_neighbor + end if + + neighbors(gi)%neighbor_count = neighbors(gi)%neighbor_count + 1 + neighbors(gi)%dist_weight_tot = neighbors(gi)%dist_weight_tot + current_neighbor%dist_weight + + ! Add current grid cell index to the neighbor's list as well + allocate(another_neighbor) + another_neighbor%next_neighbor => null() + + ! ldomain and ldecomp indices match per initGridCells + another_neighbor%gindex = ldecomp%gdc2glo(gi) + + another_neighbor%gc_dist = current_neighbor%gc_dist + another_neighbor%dist_weight = current_neighbor%dist_weight + + if (associated(neighbors(gj)%first_neighbor)) then + neighbors(gj)%last_neighbor%next_neighbor => another_neighbor + neighbors(gj)%last_neighbor => another_neighbor + else + neighbors(gj)%first_neighbor => another_neighbor + neighbors(gj)%last_neighbor => another_neighbor + end if + + neighbors(gj)%neighbor_count = neighbors(gj)%neighbor_count + 1 + neighbors(gj)%dist_weight_tot = neighbors(gj)%dist_weight_tot + another_neighbor%dist_weight + + end if dist_check + end do neighbor_search + end do gc_loop + + call t_stopf('fates-seed-init-decomp') + + ! Diagnostic output + !YL-------- + ! if (masterproc) then + ! write(fates_log(),*)' Surface Grid Characteristics' + ! write(fates_log(),*)' longitude points = ',lni + ! write(fates_log(),*)' latitude points = ',lnj + ! write(fates_log(),*)' total number of land gridcells = ',numg + ! write(fates_log(),*)' Decomposition Characteristics' + ! write(fates_log(),*)' clumps per process = ',clump_pproc + ! write(fates_log(),*)' gsMap Characteristics' + ! write(fates_log(),*) ' lnd gsmap glo num of segs = ',mct_gsMap_ngseg(gsMap_lnd_gdc2glo) + ! write(fates_log(),*) + ! end if + !---------- + + end subroutine DetermineGridCellNeighbors end module FatesInterfaceMod diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 4ee3e42018..586bfd4a8d 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -753,12 +753,57 @@ module FatesInterfaceTypesMod end type bc_pconst_type + ! Neighbor node + type, public :: neighbor_type + + ! Grid cell neighbor + type(neighbor_type), pointer :: next_neighbor => null() + + integer :: gindex ! grid cell index + real(r8) :: gc_dist ! distance between source and neighbor + real(r8) :: dist_weight ! distance-based weight scalar + + contains + procedure :: DistWeightCalc + + end type neighbor_type + + ! Neighborhood linked list + type, public :: neighborhood_type + + ! Linked list of neighbors for a given source grid cell + type(neighbor_type), pointer :: first_neighbor => null() + type(neighbor_type), pointer :: last_neighbor => null() + + integer :: neighbor_count ! total neighbors near source + real(r8) :: dist_weight_tot ! sum of dist weight scalars + ! real(r8) :: gclat ! source gridcell latitude (deg) + ! real(r8) :: gclon ! source gridcell longitude (deg) + + end type neighborhood_type + type(neighborhood_type), public, pointer :: lneighbors(:) contains + + ! ====================================================================================== - ! ==================================================================================== + function DistWeightCalc(this, g2g_dist, decay_rate) result(dist_weight) + + ! Arguments + class(neighbor_type) :: this + real(r8), intent(in) :: g2g_dist + real(r8), intent(in) :: decay_rate + real(r8) :: dist_weight + + ! Assuming simple exponential decay. In the future perhaps this could be an interface + ! for different weight calculations (and could be held only in fates) + + dist_weight = exp(-decay_rate*g2g_dist) + + end function DistWeightCalc + ! ==================================================================================== - + end module FatesInterfaceTypesMod diff --git a/main/FatesUtilsMod.F90 b/main/FatesUtilsMod.F90 index 27eef57247..779ded76e9 100644 --- a/main/FatesUtilsMod.F90 +++ b/main/FatesUtilsMod.F90 @@ -12,7 +12,7 @@ module FatesUtilsMod ! Make public necessary subroutines and functions public :: check_hlm_list public :: check_var_real - public :: GreatCircleDist + public :: GetNeighborDistance contains @@ -126,8 +126,23 @@ real(r8) function GreatCircleDist(slons,slonf,slats,slatf) return end function GreatCircleDist + + + ! ====================================================================================== + + function GetNeighborDistance(gi,gj,latc,lonc) result(gcd) + integer, intent(in) :: gi,gj ! indices of gridcells + real(r8), intent(in) :: latc(:),lonc(:) ! lat/lon of gridcells + real(r8) :: gcd + + ! write(fates_log(),*)'neighborhood: size ldomain latc/lonc: ', size(ldomain%latc), size(ldomain%lonc) + + gcd = GreatCircleDist(lonc(gi),lonc(gj), & + latc(gi),latc(gj)) - + end function GetNeighborDistance + + ! ====================================================================================== end module FatesUtilsMod From b48bc3c0cc84d845a22465591198b1e6d852cc1b Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 11 Aug 2022 16:59:04 -0700 Subject: [PATCH 313/852] temporarily updating distance weighting to use a generic type-bound procedure --- main/FatesInterfaceTypesMod.F90 | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 586bfd4a8d..e187e86a07 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -764,7 +764,8 @@ module FatesInterfaceTypesMod real(r8) :: dist_weight ! distance-based weight scalar contains - procedure :: DistWeightCalc + generic, public :: DistWeightCalc => SWC + procedure, private :: SWC => SimpleWeightCalc end type neighbor_type @@ -783,12 +784,17 @@ module FatesInterfaceTypesMod end type neighborhood_type type(neighborhood_type), public, pointer :: lneighbors(:) + + ! + interface DistWeightCalc + module procedure SimpleWeightCalc + end interface DistWeightCalc contains ! ====================================================================================== - function DistWeightCalc(this, g2g_dist, decay_rate) result(dist_weight) + function SimpleWeightCalc(this, g2g_dist, decay_rate) result(dist_weight) ! Arguments class(neighbor_type) :: this @@ -801,7 +807,7 @@ function DistWeightCalc(this, g2g_dist, decay_rate) result(dist_weight) dist_weight = exp(-decay_rate*g2g_dist) - end function DistWeightCalc + end function SimpleWeightCalc ! ==================================================================================== From 681e4f5359bf1092cf6a68420ab74b354ad73368 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Sun, 14 Aug 2022 10:04:08 -0400 Subject: [PATCH 314/852] Testing different PID controller methods and data prep methods. --- biogeochem/EDCanopyStructureMod.F90 | 1 - biogeochem/EDCohortDynamicsMod.F90 | 30 +-- main/EDMainMod.F90 | 18 +- main/EDTypesMod.F90 | 15 +- main/FatesHistoryInterfaceMod.F90 | 12 +- main/FatesRestartInterfaceMod.F90 | 40 ++-- parteh/PRTAllometricCNPMod.F90 | 283 ++++++++++++++++++++-------- parteh/PRTAllometricCarbonMod.F90 | 5 +- parteh/PRTGenericMod.F90 | 5 +- 9 files changed, 279 insertions(+), 130 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index bbca1054e9..9bae9e6a35 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -720,7 +720,6 @@ subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr,bc_in) end if ! kill the ones which go into canopy layers that are not allowed - if(currentCohort%canopy_layer>nclmax )then ! put the litter from the terminated cohorts diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 67dde74f5c..e820f7f6fb 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -94,9 +94,10 @@ module EDCohortDynamicsMod use PRTAllometricCNPMod, only : cnp_allom_prt_vartypes use PRTAllometricCNPMod, only : acnp_bc_in_id_pft, acnp_bc_in_id_ctrim use PRTAllometricCNPMod, only : acnp_bc_in_id_lstat, acnp_bc_inout_id_dbh - use PRTAllometricCNPMod, only : acnp_bc_inout_id_nc_store - use PRTAllometricCNPMod, only : acnp_bc_inout_id_pc_store use PRTAllometricCNPMod, only : acnp_bc_inout_id_l2fr + use PRTAllometricCNPMod, only : acnp_bc_inout_id_emaxc + use PRTAllometricCNPMod, only : acnp_bc_inout_id_xc0 + use PRTAllometricCNPMod, only : acnp_bc_inout_id_emadxcdt use PRTAllometricCNPMod, only : acnp_bc_in_id_nc_repro use PRTAllometricCNPMod, only : acnp_bc_in_id_pc_repro use PRTAllometricCNPMod, only : acnp_bc_inout_id_resp_excess, acnp_bc_in_id_netdc @@ -252,8 +253,9 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & new_cohort%l2fr = prt_params%allom_l2fr(pft) - new_cohort%nc_store = 0._r8 ! Assume balanced N/C stores ie log(1) = 0 - new_cohort%pc_store = 0._r8 ! Assume balanced P/C stores ie log(1) = 0 + new_cohort%ema_xc = 0._r8 ! Assume balanced N,P/C stores ie log(1) = 0 + new_cohort%xc0 = 0._r8 ! Assume balanced N,P/C stores ie log(1) = 0 + new_cohort%ema_dxcdt = 0._r8 ! Assume unchanged dXC/dt ! This sets things like vcmax25top, that depend on the ! leaf age fractions (which are defined by PARTEH) @@ -437,8 +439,9 @@ subroutine InitPRTBoundaryConditions(new_cohort,ft,call_id) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_dbh,bc_rval = new_cohort%dbh) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_resp_excess,bc_rval = new_cohort%resp_excess) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_l2fr,bc_rval = new_cohort%l2fr) - call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_nc_store,bc_rval = new_cohort%nc_store) - call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_pc_store,bc_rval = new_cohort%pc_store) + call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_emaxc,bc_rval = new_cohort%ema_xc) + call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_emadxcdt,bc_rval = new_cohort%ema_dxcdt) + call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_xc0,bc_rval = new_cohort%xc0) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_netdn, bc_rval = new_cohort%daily_n_gain) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_netdp, bc_rval = new_cohort%daily_p_uptake) @@ -1190,10 +1193,12 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) end do end if - currentCohort%nc_store = (currentCohort%n*currentCohort%nc_store & - + nextc%n*nextc%nc_store)/newn - currentCohort%pc_store = (currentCohort%n*currentCohort%pc_store & - + nextc%n*nextc%pc_store)/newn + currentCohort%ema_xc = (currentCohort%n*currentCohort%ema_xc & + + nextc%n*nextc%ema_xc)/newn + currentCohort%ema_dxcdt = (currentCohort%n*currentCohort%ema_dxcdt & + + nextc%n*nextc%ema_dxcdt)/newn + currentCohort%xc0 = (currentCohort%n*currentCohort%xc0 & + + nextc%n*nextc%xc0)/newn ! new cohort age is weighted mean of two cohorts currentCohort%coage = & @@ -1840,8 +1845,9 @@ subroutine copy_cohort( currentCohort,copyc ) n%kp25top = o%kp25top ! Copy over running means - n%nc_store = o%nc_store - n%pc_store = o%pc_store + n%ema_xc = o%ema_xc + n%ema_dxcdt = o%ema_dxcdt + n%xc0 = o%xc0 ! CARBON FLUXES n%gpp_acc_hold = o%gpp_acc_hold diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 305fbcafb1..0e527e83e5 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -150,7 +150,7 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) type(ed_patch_type), pointer :: currentPatch integer :: el ! Loop counter for elements integer :: do_patch_dynamics ! for some modes, we turn off patch dynamics - + integer :: co_num !----------------------------------------------------------------------- if ( hlm_masterproc==itrue ) write(fates_log(),'(A,I4,A,I2.2,A,I2.2)') 'FATES Dynamics: ',& @@ -344,6 +344,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) real(r8) :: leaf_c_target ! target leaf crabon [kg] real(r8) :: current_npp ! place holder for calculating npp each year in prescribed physiology mode real(r8) :: target_storec + integer :: co_num ! simple cohort counter !----------------------------------------------------------------------- real(r8) :: frac_site_primary @@ -358,8 +359,9 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! prior to the growth sequence, where reproductive ! tissues are allocated call UpdateRecruitStoich(currentSite) - - currentPatch => currentSite%youngest_patch + + co_num = 1 + currentPatch => currentSite%oldest_patch do while(associated(currentPatch)) currentPatch%age = currentPatch%age + hlm_freq_day @@ -379,7 +381,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentPatch%age_class = get_age_class_index(currentPatch%age) ! Update Canopy Biomass Pools - currentCohort => currentPatch%shortest + currentCohort => currentPatch%tallest do while(associated(currentCohort)) ft = currentCohort%pft @@ -461,7 +463,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! ----------------------------------------------------------------------------- currentCohort%resp_excess = 0._r8 - call currentCohort%prt%DailyPRT() + call currentCohort%prt%DailyPRT(co_num,currentCohort%n) ! Send any efflux/exudates to the labile litter pools in the HLM ! ----------------------------------------------------------------------------- @@ -538,11 +540,11 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentCohort%coage_class,currentCohort%coage_by_pft_class) end if - - currentCohort => currentCohort%taller + co_num=co_num+1 + currentCohort => currentCohort%shorter end do - currentPatch => currentPatch%older + currentPatch => currentPatch%younger end do ! We keep a record of the L2FRs of plants diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 4a1b434676..7e1ef6fcc0 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -223,11 +223,16 @@ module EDTypesMod ! Used for CNP - integer :: cnp_limiter ! Which species is limiting growth? ! 0=none,1=C,2=N,3=P - real(r8) :: nc_store ! Exponential moving average of the log of the N/C storage ratio - real(r8) :: pc_store ! Exponential moving average of the log of the P/C storage ratio - real(r8) :: nc_repro ! The NC ratio of a new recruit in this patch - real(r8) :: pc_repro ! The PC ratio of a new recruit in this patch + integer :: cnp_limiter ! Which species is limiting growth? ! 0=none,1=C,2=N,3=P + real(r8) :: ema_xc ! Exponential moving average of the log of the error term + ! that controls the l2fr set-point in the PID controller + ! the term is probably a ratio of storage or a ratio of + ! gain efficiencies + real(r8) :: ema_dxcdt ! The derivative of ema_xc per day + real(r8) :: xc0 ! The value on the previous time-step of the log of + ! the PID error term (not smoothed) + real(r8) :: nc_repro ! The NC ratio of a new recruit in this patch + real(r8) :: pc_repro ! The PC ratio of a new recruit in this patch ! VEGETATION STRUCTURE diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 9e71cb5a29..b5f6c9a6dd 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -1815,6 +1815,9 @@ subroutine update_history_nutrflux(this,csite) gpp_si = 0._r8 fnrtc_clscpf(:) = 0._r8 fnrtc_si = 0._r8 + + ! history site index + io_si = csite%h_gid cpatch => csite%youngest_patch do while(associated(cpatch)) @@ -1823,16 +1826,16 @@ subroutine update_history_nutrflux(this,csite) do while(associated(ccohort)) ! If this is a new cohort, do not make diagnostics - if(ccohort%isnew) cycle + if(ccohort%isnew) then + ccohort => ccohort%taller + cycle + end if ! size class index iscpf = ccohort%size_by_pft_class ! layer by size by pft index iclscpf = get_layersizetype_class_index(ccohort%canopy_layer,ccohort%dbh,ccohort%pft) - - ! history site index - io_si = csite%h_gid ! unit conversion factor to get x/plant/day -> x/m2/sec uconv = ccohort%n * ha_per_m2 * days_per_sec @@ -1952,6 +1955,7 @@ subroutine update_history_nutrflux(this,csite) ! Normalize the layer x size x pft arrays do iclscpf = 1,nclmax*numpft*nlevsclass + if(gpp_clscpf(iclscpf)>nearzero) then hio_ngrowlim_clscpf(io_si,iclscpf) = hio_ngrowlim_clscpf(io_si,iclscpf) / gpp_clscpf(iclscpf) hio_pgrowlim_clscpf(io_si,iclscpf) = hio_pgrowlim_clscpf(io_si,iclscpf) / gpp_clscpf(iclscpf) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 15604aba25..94fd47b1de 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -96,7 +96,9 @@ module FatesRestartInterfaceMod integer :: ir_canopy_layer_yesterday_co integer :: ir_canopy_trim_co integer :: ir_l2fr_co - integer :: ir_nc_store_co + integer :: ir_emaxc_co + integer :: ir_emadxcdt_co + integer :: ir_xc0_co integer :: ir_pc_store_co integer :: ir_size_class_lasttimestep_co integer :: ir_dbh_co @@ -700,13 +702,17 @@ subroutine define_restart_vars(this, initialize_variables) long_name='ed cohort - l2fr', units='fraction', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_l2fr_co ) - call this%set_restart_var(vname='fates_nc_store', vtype=cohort_r8, & - long_name='ed cohort - nc_store', units='fraction', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_nc_store_co ) + call this%set_restart_var(vname='fates_emaxc', vtype=cohort_r8, & + long_name='ed cohort - emaxc', units='fraction', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_emaxc_co ) - call this%set_restart_var(vname='fates_pc_store', vtype=cohort_r8, & - long_name='ed cohort - pc_store', units='fraction', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_pc_store_co ) + call this%set_restart_var(vname='fates_emadxcdt', vtype=cohort_r8, & + long_name='ed cohort - emadxcdt', units='fraction', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_emadxcdt_co ) + + call this%set_restart_var(vname='fates_xc0', vtype=cohort_r8, & + long_name='ed cohort - xc0', units='fraction', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_xc0_co ) call this%set_restart_var(vname='fates_size_class_lasttimestep', vtype=cohort_int, & long_name='ed cohort - size-class last timestep', units='index', flushval = flushzero, & @@ -1748,8 +1754,9 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_canopy_layer_yesterday_co => this%rvars(ir_canopy_layer_yesterday_co)%r81d, & rio_canopy_trim_co => this%rvars(ir_canopy_trim_co)%r81d, & rio_l2fr_co => this%rvars(ir_l2fr_co)%r81d, & - rio_nc_store_co => this%rvars(ir_nc_store_co)%r81d, & - rio_pc_store_co => this%rvars(ir_pc_store_co)%r81d, & + rio_emaxc_co => this%rvars(ir_emaxc_co)%r81d, & + rio_emadxcdt_co => this%rvars(ir_emadxcdt_co)%r81d, & + rio_xc0_co => this%rvars(ir_xc0_co)%r81d, & rio_seed_prod_co => this%rvars(ir_seed_prod_co)%r81d, & rio_size_class_lasttimestep => this%rvars(ir_size_class_lasttimestep_co)%int1d, & rio_dbh_co => this%rvars(ir_dbh_co)%r81d, & @@ -1967,8 +1974,9 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_canopy_layer_yesterday_co(io_idx_co) = ccohort%canopy_layer_yesterday rio_canopy_trim_co(io_idx_co) = ccohort%canopy_trim rio_l2fr_co(io_idx_co) = ccohort%l2fr - rio_nc_store_co(io_idx_co) = ccohort%nc_store - rio_pc_store_co(io_idx_co) = ccohort%pc_store + rio_emaxc_co(io_idx_co) = ccohort%ema_xc + rio_emadxcdt_co(io_idx_co) = ccohort%ema_dxcdt + rio_xc0_co(io_idx_co) = ccohort%xc0 rio_seed_prod_co(io_idx_co) = ccohort%seed_prod rio_size_class_lasttimestep(io_idx_co) = ccohort%size_class_lasttimestep rio_dbh_co(io_idx_co) = ccohort%dbh @@ -2575,8 +2583,9 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_canopy_layer_yesterday_co => this%rvars(ir_canopy_layer_yesterday_co)%r81d, & rio_canopy_trim_co => this%rvars(ir_canopy_trim_co)%r81d, & rio_l2fr_co => this%rvars(ir_l2fr_co)%r81d, & - rio_nc_store_co => this%rvars(ir_nc_store_co)%r81d, & - rio_pc_store_co => this%rvars(ir_pc_store_co)%r81d, & + rio_emaxc_co => this%rvars(ir_emaxc_co)%r81d, & + rio_emadxcdt_co => this%rvars(ir_emadxcdt_co)%r81d, & + rio_xc0_co => this%rvars(ir_xc0_co)%r81d, & rio_seed_prod_co => this%rvars(ir_seed_prod_co)%r81d, & rio_size_class_lasttimestep => this%rvars(ir_size_class_lasttimestep_co)%int1d, & rio_dbh_co => this%rvars(ir_dbh_co)%r81d, & @@ -2767,8 +2776,9 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ccohort%canopy_layer_yesterday = rio_canopy_layer_yesterday_co(io_idx_co) ccohort%canopy_trim = rio_canopy_trim_co(io_idx_co) ccohort%l2fr = rio_l2fr_co(io_idx_co) - ccohort%nc_store = rio_nc_store_co(io_idx_co) - ccohort%pc_store = rio_pc_store_co(io_idx_co) + ccohort%ema_xc = rio_emaxc_co(io_idx_co) + ccohort%ema_dxcdt = rio_emadxcdt_co(io_idx_co) + ccohort%xc0 = rio_xc0_co(io_idx_co) ccohort%seed_prod = rio_seed_prod_co(io_idx_co) ccohort%size_class_lasttimestep = rio_size_class_lasttimestep(io_idx_co) ccohort%dbh = rio_dbh_co(io_idx_co) diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 95049cf95b..de34316837 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -107,7 +107,8 @@ module PRTAllometricCNPMod integer, parameter, private :: pid_spe_controller = storage_spe - real(r8), parameter, private :: pid_int_wgt = 1._r8/5._r8 ! n-day smoothing (K on the integral of PID) + real(r8), parameter, private :: pid_int_wgt = 1._r8/30._r8 ! n-day smoothing (K on the integral of PID) + real(r8), parameter, private :: pid_drv_wgt = 1._r8/30._r8 ! n-day smoothing (K on the derivative of PID) ! Global identifiers for the two stoichiometry values integer,public, parameter :: stoich_growth_min = 1 ! Flag for stoichiometry associated with @@ -160,10 +161,10 @@ module PRTAllometricCNPMod ! is dynamic with CNP integer, public, parameter :: acnp_bc_inout_id_netdn = 4 ! Index for the net daily NH4 input BC integer, public, parameter :: acnp_bc_inout_id_netdp = 5 ! Index for the net daily P input BC - integer, public, parameter :: acnp_bc_inout_id_nc_store = 6 ! Index for the EMA log storage ratio N/C - integer, public, parameter :: acnp_bc_inout_id_pc_store = 7 ! Index for the EMA log storage ratio P/C - - integer, public, parameter :: num_bc_inout = 7 + integer, public, parameter :: acnp_bc_inout_id_emaxc = 6 ! Index for the EMA log storage ratio max(N,P)/C + integer, public, parameter :: acnp_bc_inout_id_xc0 = 7 ! Index for the previous step's log storage ratio max(N,P)/C + integer, public, parameter :: acnp_bc_inout_id_emadxcdt = 8 ! Index for the EMA log storage ratio derivative d max(NP)/C dt + integer, public, parameter :: num_bc_inout = 8 ! ------------------------------------------------------------------------------------- ! Input only Boundary Indices (These are public) @@ -222,6 +223,12 @@ module PRTAllometricCNPMod logical, parameter :: use_gains_in_regulator = .true. logical, parameter :: use_unrestricted_contraction = .true. + + integer, parameter :: pid_ratio = 1 + integer, parameter :: pid_logratio = 2 + + integer, parameter :: pid_method = pid_logratio + ! ------------------------------------------------------------------------------------- ! This is the core type that holds this specific @@ -345,9 +352,11 @@ end subroutine InitPRTGlobalAllometricCNP ! ===================================================================================== - subroutine DailyPRTAllometricCNP(this) + subroutine DailyPRTAllometricCNP(this,co_num,nplant) class(cnp_allom_prt_vartypes) :: this + integer,intent(in) :: co_num ! Cohort index + real(r8),intent(in) :: nplant ! Pointers to in-out bcs real(r8),pointer :: dbh ! Diameter at breast height [cm] @@ -472,7 +481,7 @@ subroutine DailyPRTAllometricCNP(this) ! This routine updates the l2fr (leaf 2 fine-root multiplier) variable ! It will also update the target - call this%CNPAdjustFRootTargets(target_c,target_dcdd) + call this%CNPAdjustFRootTargets(target_c,target_dcdd,co_num,nplant) ! Remember the original C,N,P states to help with final ! evaluation of how much was allocated @@ -694,43 +703,64 @@ subroutine DailyPRTAllometricCNP(this) end subroutine DailyPRTAllometricCNP ! ===================================================================================== - subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd) + subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) + use FatesInterfaceTypesMod , only : hlm_day_of_year + use FatesInterfaceTypesMod , only : hlm_days_per_year + use FatesInterfaceTypesMod , only : hlm_current_year + class(cnp_allom_prt_vartypes) :: this real(r8) :: target_c(:) real(r8) :: target_dcdd(:) - + integer,intent(in) :: co_num + real(r8),intent(in) :: nplant + real(r8), pointer :: l2fr ! leaf to fineroot target biomass scaler integer :: ipft ! PFT index real(r8), pointer :: dbh real(r8) :: canopy_trim - real(r8) :: cnp_store_ratio real(r8) :: store_c_max, store_c_act real(r8) :: store_nut_max, store_nut_act real(r8) :: n_ratio, p_ratio, np_ratio real(r8) :: fnrt_c,leaf_c,store_c,struct_c,sapw_c,c_gain,c_fnrt_expand real(r8) :: l2fr_delta_max + real(r8) :: l2fr_delta_minmax ! Hard cap on maximum change scale*log(2) real(r8) :: l2fr_delta_scale real(r8) :: logi_k real(r8) :: l2fr_mult - real(r8), pointer :: nc_store - real(r8), pointer :: pc_store - + real(r8) :: l2fr_delta + real(r8) :: dxcdt_ratio ! log change (derivative) of the maximum of the N/C and P/C storage ratio + real(r8) :: xc_ratio ! log Maximum of the N/C and P/C storage ratio + real(r8), pointer :: ema_xc ! The exponential moving average of the N-or-P versus C PID error function + real(r8), pointer :: xc0 ! The log of the xc ratio from previous time-step + real(r8), pointer :: ema_dxcdt ! the EMA of the change in log storage ratio + integer :: sup_flag real(r8), parameter :: max_l2fr_cgain_frac = 0.99_r8 real(r8), parameter :: xc_ratio_correction = 1.0_r8 - - - - ipft = this%bc_in(acnp_bc_in_id_pft)%ival - l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval - dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval - canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval - nc_store => this%bc_inout(acnp_bc_inout_id_nc_store)%rval - pc_store => this%bc_inout(acnp_bc_inout_id_pc_store)%rval + ! This is the relative scaling strength of the derivative term (K_d), + ! compared to the combined proportion and integral term (K_p and K_i) + ! Note the strength of the derivative is should be about half of the period + ! for an oscillation when turned off, to balance the K_p and K_i terms. + ! This will have to be tuned in a sequence of 1, 10, 100, etc... + real(r8) :: l2fr_deriv_scale != 200._r8 + real(r8) :: l2fr_int_scale + + ! If we do not have leaves out, then the relative nutrient vs carbon + ! balancing is meaningless, just leave this routine + if(this%GetState(leaf_organ, carbon12_element)/target_c(leaf_organ) < 0.5_r8) return + - if(pid_spe_controller == storage_spe) then + ipft = this%bc_in(acnp_bc_in_id_pft)%ival + l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval + dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval + canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval + ema_xc => this%bc_inout(acnp_bc_inout_id_emaxc)%rval + xc0 => this%bc_inout(acnp_bc_inout_id_xc0)%rval + ema_dxcdt => this%bc_inout(acnp_bc_inout_id_emadxcdt)%rval + + if_storage_spe: if(pid_spe_controller == storage_spe) then ! Step 1: Determine the nutrient to carbon ratio (aka relative health factor) ! ----------------------------------------------------------------------------------- @@ -750,10 +780,18 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd) store_nut_act = this%GetState(store_organ, nitrogen_element) + & this%bc_inout(acnp_bc_inout_id_netdn)%rval - n_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max)/(store_c_act/store_c_max))) - - nc_store = pid_int_wgt*log(n_ratio) + (1._r8-pid_int_wgt)*nc_store + !n_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max)/(store_c_act/store_c_max))) + !n_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max))) + !n_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,1._r8/(store_c_act/store_c_max))) + + if((store_nut_act/store_nut_max) > (store_c_act/store_c_max))then + n_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_c_max/store_c_act))) + else + n_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max))) + end if + else + n_ratio = -1._r8 end if if(p_uptake_mode.ne.prescribed_p_uptake)then @@ -763,29 +801,44 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd) store_nut_max = this%GetNutrientTarget(phosphorus_element,store_organ,stoich_growth_min) - store_nut_act = this%GetState(store_organ, phosphorus_element) + this%bc_inout(acnp_bc_inout_id_netdp)%rval - p_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max)/(store_c_act/store_c_max))) + store_nut_act = this%GetState(store_organ, phosphorus_element) + & + this%bc_inout(acnp_bc_inout_id_netdp)%rval - pc_store = pid_int_wgt*log(p_ratio) + (1._r8-pid_int_wgt)*pc_store - - end if - end if - ! Use the limiting nutrient species + !p_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max)/(store_c_act/store_c_max))) + p_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max))) + !p_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,1._r8/(store_c_act/store_c_max))) - if(n_uptake_mode.eq.prescribed_n_uptake)then - if(p_uptake_mode.eq.prescribed_p_uptake)then - cnp_store_ratio = 1._r8 - return + if((store_nut_act/store_nut_max) > (store_c_act/store_c_max))then + p_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_c_max/store_c_act))) + else + p_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max))) + end if + + else - cnp_store_ratio = exp(pc_store) + p_ratio = -1._r8 end if - else - if(p_uptake_mode.eq.prescribed_p_uptake)then - cnp_store_ratio = exp(nc_store) + + ! Use the limiting nutrient species + if(n_uptake_mode.eq.prescribed_n_uptake .and. p_uptake_mode.eq.prescribed_p_uptake)then + ema_xc = 0._r8 + ema_dxcdt = 0._r8 + xc0 = 0.0_r8 + return else - cnp_store_ratio = min(exp(nc_store),exp(pc_store)) + + xc_ratio = log(min(n_ratio,p_ratio)) + + dxcdt_ratio = xc_ratio-xc0 + + ema_xc = pid_int_wgt*xc_ratio + (1._r8-pid_int_wgt)*ema_xc + ema_dxcdt = pid_drv_wgt*dxcdt_ratio + (1._r8-pid_drv_wgt)*ema_dxcdt + xc0 = xc_ratio + + end if - end if + + end if if_storage_spe ! ----------------------------------------------------------------------------- ! To decide the upper limit on expanding root growth, we perform a carbon @@ -822,35 +875,95 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd) max(0._r8,target_c(struct_organ)-struct_c) - & max(0._r8,target_c(store_organ)-store_c)) - l2fr_delta_max = (c_fnrt_expand + target_c(fnrt_organ))/target_c(fnrt_organ) + if(pid_method==pid_ratio) then + + l2fr_delta_max = (c_fnrt_expand + target_c(fnrt_organ))/target_c(fnrt_organ) + + ! This value could be negative if there is no gain, or less gain + ! than what can replace tissues, just ensure the multiplier is GT 1 + + l2fr_delta_max = max(1._r8,l2fr_delta_max) - ! This value could be negative if there is no gain, or less gain - ! than what can replace tissues, just ensure the multiplier is GT 1 + ! Determine the max change for the doubling timescale + ! 2.0 = l2fr_delta_max^frnt_adapt_tscl + + l2fr_delta_scale = 2._r8**(1._r8/prt_params%fnrt_adapt_tscale(ipft))-1.0_r8 - l2fr_delta_max = max(1._r8,l2fr_delta_max) + ! Calculate the un-regulated l2fr multiplier + + logi_k = EDPftvarcon_inst%dev_arbitrary_pft(ipft) + l2fr_mult = l2fr_delta_scale*(2.0_r8/(1.0_r8 + exp(ema_xc)**logi_k)-1.0_r8)+1.0_r8 + + + if(l2fr_mult>1.0_r8)then + l2fr_mult = min(l2fr_mult,l2fr_delta_max) + end if - ! Determine the max change for the doubling timescale - ! 2.0 = l2fr_delta_max^frnt_adapt_tscl - - l2fr_delta_scale = 2._r8**(1._r8/prt_params%fnrt_adapt_tscale(ipft))-1.0_r8 + l2fr = max(l2fr_min,l2fr * l2fr_mult) - ! Calculate the un-regulated l2fr multiplier - - logi_k = EDPftvarcon_inst%dev_arbitrary_pft(ipft) - l2fr_mult = l2fr_delta_scale*(2.0_r8/(1.0_r8 + cnp_store_ratio**logi_k)-1.0_r8)+1.0_r8 - if(l2fr_mult>1.0_r8)then - l2fr_mult = min(l2fr_mult,l2fr_delta_max) - end if + elseif(pid_method==pid_logratio) then - ! Only update L2FR if some leaves are out - if(this%GetState(leaf_organ, carbon12_element)/target_c(leaf_organ) > 0.5_r8) then + ! When using a log based (additive) PID search method + ! we define 1/fnrt_adapt_tscale as delta we want + ! when we have a 2:1 ratio. For instance if fnrt_adapt_tscale = 100, + ! then we want a scaling parameter that generates a change in l2fr of 1/100 + ! when there is 2:1 ratio of nutrient versus carbon storage. This + ! value is akin to the K_p and K_i terms in a PID controller (and + ! the ema timescale is the relative weight of K_p and K_i) + + l2fr_delta_scale = (1._r8/prt_params%fnrt_adapt_tscale(ipft))/log(2.0_r8) + + ! ema_xc is already in log form to allow for averaging + + ! Want the derivative to be strongest when storage is most disproportionate + l2fr_deriv_scale = 0.0_r8 !0.25*abs(ema_xc/ema_dxcdt) + l2fr_int_scale = 0.0_r8 + + + ! To limit overshoot, when either positive and decending or negative and ascending + ! we have already corrected enough to change the behavior, lets + ! decrease the scaling + + if( ((ema_xc > 0._r8) .and. (ema_dxcdt<0)) .or. ((ema_xc < 0._r8) .and. (ema_dxcdt>0))) then + l2fr_delta_scale = 0.05_r8 * l2fr_delta_scale + sup_flag = 1 + else + sup_flag = 0 + + end if - !l2fr = (1._r8-err_beta)*(l2fr * l2fr_mult) + err_beta*l2fr_deriv - l2fr = max(l2fr_min,l2fr * l2fr_mult) - end if + !l2fr_delta = -l2fr_delta_scale*(min(0.2,max(-0.2,xc_ratio)) + ema_xc*l2fr_int_scale + ema_dxcdt*l2fr_deriv_scale) + l2fr_delta = -l2fr_delta_scale*(xc_ratio + ema_xc*l2fr_int_scale + ema_dxcdt*l2fr_deriv_scale) + + ! Cap growth and shrinkage to avoid large changes + ! (currently capping at projected rate for a 2:1 ratio + l2fr_delta_minmax = l2fr_delta_scale*log(2.0) + ! Don't allow more growth than we have carbon to pay for + l2fr_delta_max = min(l2fr_delta_minmax,l2fr*(c_fnrt_expand + target_c(fnrt_organ))/target_c(fnrt_organ)) + + + l2fr_delta = max(-l2fr_delta_minmax,min(l2fr_delta,l2fr_delta_max)) + + ! Apply the delta, also, avoid generating incredibly small l2fr's, + ! super small l2frs will occur in plants that perpetually get almost + ! now carbon gain, such as newly recruited plants in a dark understory + + l2fr = max(l2fr_min, l2fr + l2fr_delta ) + + !if(co_num==1) + print*,'AAX1',co_num,hlm_current_year,hlm_day_of_year,dbh,nplant,sup_flag,xc_ratio,l2fr + + + else + + write(fates_log(),*) 'unknown PID controller method', pid_method + call endrun(msg=errMsg(sourcefile, __LINE__)) + + end if + ! Find the updated target fineroot biomass call bfineroot(dbh,ipft,canopy_trim, l2fr, target_c(fnrt_organ),target_dcdd(fnrt_organ)) @@ -1816,23 +1929,26 @@ subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & real(r8) :: store_m_flux ! Flux into storage [kg] real(r8), pointer :: dbh real(r8), pointer :: resp_excess - real(r8), pointer :: nc_store,pc_store + real(r8), pointer :: ema_xc + real(r8), pointer :: ema_dxcdt + real(r8), pointer :: xc0 + real(r8) :: dxcdt_ratio integer :: ipft integer, pointer :: limiter real(r8) :: canopy_trim real(r8) :: n_ratio,p_ratio,c_ratio - real(r8) :: nc_ratio,pc_ratio + real(r8) :: xc_ratio,nc_ratio,pc_ratio real(r8), pointer :: l2fr dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival resp_excess => this%bc_inout(acnp_bc_inout_id_resp_excess)%rval - nc_store => this%bc_inout(acnp_bc_inout_id_nc_store)%rval - pc_store => this%bc_inout(acnp_bc_inout_id_pc_store)%rval l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval limiter => this%bc_out(acnp_bc_out_id_limiter)%ival - + ema_xc => this%bc_inout(acnp_bc_inout_id_emaxc)%rval + ema_dxcdt => this%bc_inout(acnp_bc_inout_id_emadxcdt)%rval + xc0 => this%bc_inout(acnp_bc_inout_id_xc0)%rval ! Update the F_NPC ! n_ratio the ratio of n_gain/n_alloc / c_gain/c_alloc @@ -1880,29 +1996,34 @@ subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & end if end if + xc_ratio = log(min(nc_ratio,pc_ratio)) + + dxcdt_ratio = xc_ratio-xc0 + + ema_xc = pid_int_wgt*xc_ratio + (1._r8-pid_int_wgt)*ema_xc + ema_dxcdt = pid_drv_wgt*dxcdt_ratio + (1._r8-pid_drv_wgt)*ema_dxcdt + xc0 = xc_ratio + + elseif( pid_spe_controller==binary_limiter_spe) then select case(limiter) case(cnp_limited) - nc_ratio = exp(nc_store) - pc_ratio = exp(pc_store) + xc_ratio = exp(ema_xc) case(c_limited) - nc_ratio = 2.0_r8 - pc_ratio = 2.0_r8 + xc_ratio = 2.0_r8 case(n_limited,p_limited) - nc_ratio = 0.5_r8 - pc_ratio = 0.5_r8 + xc_ratio = 0.5_r8 end select - if(n_uptake_mode.eq.prescribed_n_uptake) then - nc_ratio = 1.0_r8 - end if - if(p_uptake_mode.eq.prescribed_p_uptake) then - pc_ratio = 1.0_r8 + if((n_uptake_mode.eq.prescribed_n_uptake) .and. (p_uptake_mode.eq.prescribed_p_uptake) ) then + xc_ratio = 1.0_r8 end if + + ema_xc = pid_int_wgt*log(xc_ratio) + (1._r8-pid_int_wgt)*ema_xc + end if - nc_store = pid_int_wgt*log(nc_ratio) + (1._r8-pid_int_wgt)*nc_store - pc_store = pid_int_wgt*log(pc_ratio) + (1._r8-pid_int_wgt)*pc_store + ! ----------------------------------------------------------------------------------- ! If nutrients are still available, then we can bump up the values in the pools diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 407d3e2c88..a291f835eb 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -238,7 +238,7 @@ end subroutine InitPRTGlobalAllometricCarbon ! ===================================================================================== - subroutine DailyPRTAllometricCarbon(this) + subroutine DailyPRTAllometricCarbon(this,co_num,nplant) ! ----------------------------------------------------------------------------------- ! @@ -283,7 +283,8 @@ subroutine DailyPRTAllometricCarbon(this) ! The class is the only argument class(callom_prt_vartypes) :: this ! this class - + integer,intent(in) :: co_num ! cohort index + real(r8),intent(in) :: nplant ! ----------------------------------------------------------------------------------- ! These are local copies of the in/out boundary condition structure ! ----------------------------------------------------------------------------------- diff --git a/parteh/PRTGenericMod.F90 b/parteh/PRTGenericMod.F90 index 40cc75898e..9dd01047a2 100644 --- a/parteh/PRTGenericMod.F90 +++ b/parteh/PRTGenericMod.F90 @@ -1159,10 +1159,11 @@ end function GetCoordVal ! ==================================================================================== - subroutine DailyPRTBase(this) + subroutine DailyPRTBase(this,co_num,nplant) class(prt_vartypes) :: this - + integer,intent(in) :: co_num ! cohort number + real(r8),intent(in) :: nplant write(fates_log(),*)'Daily PRT Allocation must be extended' call endrun(msg=errMsg(sourcefile, __LINE__)) From 0d6527dd24a68579dd3d6c0263bba7ec6dfad2d7 Mon Sep 17 00:00:00 2001 From: ZacharyRobbins Date: Tue, 16 Aug 2022 09:50:05 -0600 Subject: [PATCH 315/852] Grass PFT only creates leaves not cwd In response to issue #884 Modified EDCohortDynamicsMod.F90 (@ln970): if the pft is grass then all of its organs are treated as leaves for calculation of coarse woody debris(cwd). EDPatchDynamicsMod.F90 (@ln 1641): When patches spawn, only tree pft donate dead tress or cwd, and mass to the new patch, if pft is grass it assumed that grass was consumed in fire. This may not resolve fluxes to the atmosphere accurately. EDPhysiologyMod.F90 (@ln 2199): When other litter fluxes occur, if pft is grass, then it only turnsover or contributes leaves not coarse woody debris. --- biogeochem/EDCohortDynamicsMod.F90 | 26 ++++++++++---- biogeochem/EDPatchDynamicsMod.F90 | 33 +++++++++--------- biogeochem/EDPhysiologyMod.F90 | 54 +++++++++++++++++++++--------- 3 files changed, 76 insertions(+), 37 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 4948f68129..957c3847ae 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -967,12 +967,26 @@ subroutine SendCohortToLitter(csite,cpatch,ccohort,nplant,bc_in) do el=1,num_elements - leaf_m = ccohort%prt%GetState(leaf_organ, element_list(el)) - store_m = ccohort%prt%GetState(store_organ, element_list(el)) - sapw_m = ccohort%prt%GetState(sapw_organ, element_list(el)) - fnrt_m = ccohort%prt%GetState(fnrt_organ, element_list(el)) - struct_m = ccohort%prt%GetState(struct_organ, element_list(el)) - repro_m = ccohort%prt%GetState(repro_organ, element_list(el)) + if ( prt_params%woody(pft) == itrue) then !trees only + leaf_m = ccohort%prt%GetState(leaf_organ, element_list(el)) + store_m = ccohort%prt%GetState(store_organ, element_list(el)) + sapw_m = ccohort%prt%GetState(sapw_organ, element_list(el)) + fnrt_m = ccohort%prt%GetState(fnrt_organ, element_list(el)) + struct_m = ccohort%prt%GetState(struct_organ, element_list(el)) + repro_m = ccohort%prt%GetState(repro_organ, element_list(el)) + else + leaf_m = ccohort%prt%GetState(leaf_organ, element_list(el))+ & + ccohort%prt%GetState(store_organ, element_list(el))+ & + ccohort%prt%GetState(sapw_organ, element_list(el))+ & + ccohort%prt%GetState(fnrt_organ, element_list(el))+ & + ccohort%prt%GetState(struct_organ, element_list(el))+ & + ccohort%prt%GetState(repro_organ, element_list(el)) + store_m = 0_r8 + sapw_m = 0_r8 + fnrt_m = 0_r8 + struct_m = 0_r8 + repro_m = 0_r8 + end if litt => cpatch%litter(el) flux_diags => csite%flux_diags(el) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index d1c9a79b3d..dc4ef3d989 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1637,13 +1637,17 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & ! across ground surface. ! ----------------------------------------------------------------------- - sapw_m = currentCohort%prt%GetState(sapw_organ, element_id) - struct_m = currentCohort%prt%GetState(struct_organ, element_id) - leaf_m = currentCohort%prt%GetState(leaf_organ, element_id) - fnrt_m = currentCohort%prt%GetState(fnrt_organ, element_id) - store_m = currentCohort%prt%GetState(store_organ, element_id) - repro_m = currentCohort%prt%GetState(repro_organ, element_id) - + if ( prt_params%woody(pft) == itrue) then !trees only, May require additional accounting for the atm_fluxes when PFT is grass. + ! Goal was to not add to pools in the event of grass fire. Grass would typically not introduce a flux of dead leaves + ! or coarse woody debris. This may be too coarse a solution in the long term. + leaf_m = currentCohort%prt%GetState(leaf_organ, element_list(el)) + store_m = currentCohort%prt%GetState(store_organ, element_list(el)) + sapw_m = currentCohort%prt%GetState(sapw_organ, element_list(el)) + fnrt_m = currentCohort%prt%GetState(fnrt_organ, element_list(el)) + struct_m = currentCohort%prt%GetState(struct_organ, element_list(el)) + repro_m = currentCohort%prt%GetState(repro_organ, element_list(el)) + + ! Absolute number of dead trees being transfered in with the donated area num_dead_trees = (currentCohort%fire_mort*currentCohort%n * & patch_site_areadis/currentPatch%area) @@ -1654,7 +1658,7 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & ! Contribution of dead trees to leaf burn-flux burned_mass = num_dead_trees * (leaf_m+repro_m) * currentCohort%fraction_crown_burned - + do dcmpy=1,ndcmpy dcmpy_frac = GetDecompyFrac(pft,leaf_organ,dcmpy) new_litt%leaf_fines(dcmpy) = new_litt%leaf_fines(dcmpy) + & @@ -1667,9 +1671,7 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & call set_root_fraction(currentSite%rootfrac_scr, pft, currentSite%zi_soil, & bc_in%max_rooting_depth_index_col) - - ! Contribution of dead trees to root litter (no root burn flux to atm) - do dcmpy=1,ndcmpy + do dcmpy=1,ndcmpy dcmpy_frac = GetDecompyFrac(pft,fnrt_organ,dcmpy) do sl = 1,currentSite%nlevsoil donatable_mass = num_dead_trees * (fnrt_m+store_m) * currentSite%rootfrac_scr(sl) @@ -1688,10 +1690,10 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & flux_diags%root_litter_input(pft) = & flux_diags%root_litter_input(pft) + & (fnrt_m + store_m) * num_dead_trees - + ! coarse root biomass per tree bcroot = (sapw_m + struct_m) * (1.0_r8 - prt_params%allom_agb_frac(pft) ) - + ! below ground coarse woody debris from burned trees do c = 1,ncwd do sl = 1,currentSite%nlevsoil @@ -1719,14 +1721,15 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & donatable_mass = num_dead_trees * SF_val_CWD_frac(c) * bstem if (c == 1 .or. c == 2) then donatable_mass = donatable_mass * (1.0_r8-currentCohort%fraction_crown_burned) - burned_mass = num_dead_trees * SF_val_CWD_frac(c) * bstem * & + burned_mass = num_dead_trees * SF_val_CWD_frac(c) * bstem * & currentCohort%fraction_crown_burned site_mass%burn_flux_to_atm = site_mass%burn_flux_to_atm + burned_mass endif new_litt%ag_cwd(c) = new_litt%ag_cwd(c) + donatable_mass * donate_m2 curr_litt%ag_cwd(c) = curr_litt%ag_cwd(c) + donatable_mass * retain_m2 flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + donatable_mass - enddo + enddo + endif currentCohort => currentCohort%taller diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 9a43af3226..71c483b2df 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2193,24 +2193,46 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) currentCohort => currentPatch%shortest do while(associated(currentCohort)) pft = currentCohort%pft - - call set_root_fraction(currentSite%rootfrac_scr, pft, currentSite%zi_soil, & + call set_root_fraction(currentSite%rootfrac_scr, pft, currentSite%zi_soil, & bc_in%max_rooting_depth_index_col) - leaf_m_turnover = currentCohort%prt%GetTurnover(leaf_organ,element_id) - store_m_turnover = currentCohort%prt%GetTurnover(store_organ,element_id) - fnrt_m_turnover = currentCohort%prt%GetTurnover(fnrt_organ,element_id) - sapw_m_turnover = currentCohort%prt%GetTurnover(sapw_organ,element_id) - struct_m_turnover = currentCohort%prt%GetTurnover(struct_organ,element_id) - repro_m_turnover = currentCohort%prt%GetTurnover(repro_organ,element_id) - - leaf_m = currentCohort%prt%GetState(leaf_organ,element_id) - store_m = currentCohort%prt%GetState(store_organ,element_id) - fnrt_m = currentCohort%prt%GetState(fnrt_organ,element_id) - sapw_m = currentCohort%prt%GetState(sapw_organ,element_id) - struct_m = currentCohort%prt%GetState(struct_organ,element_id) - repro_m = currentCohort%prt%GetState(repro_organ,element_id) - + if ( prt_params%woody(pft) == itrue) then !trees only + leaf_m_turnover = currentCohort%prt%GetTurnover(leaf_organ, element_id) + store_m_turnover = currentCohort%prt%GetTurnover(store_organ,element_id) + sapw_m_turnover = currentCohort%prt%GetTurnover(sapw_organ, element_id) + fnrt_m_turnover = currentCohort%prt%GetTurnover(fnrt_organ, element_id) + struct_m_turnover = currentCohort%prt%GetTurnover(struct_organ, element_id) + repro_m_turnover = currentCohort%prt%GetTurnover(repro_organ, element_id) + leaf_m = currentCohort%prt%GetState(leaf_organ, element_id) + store_m = currentCohort%prt%GetState(store_organ, element_id) + sapw_m = currentCohort%prt%GetState(sapw_organ, element_id) + fnrt_m = currentCohort%prt%GetState(fnrt_organ, element_id) + struct_m = currentCohort%prt%GetState(struct_organ, element_id) + repro_m = currentCohort%prt%GetState(repro_organ, element_id) + else ! grass PFTs should not spawn anything other than leaves. + leaf_m_turnover = currentCohort%prt%GetTurnover(leaf_organ, element_id)+ & + currentCohort%prt%GetTurnover(store_organ, element_id)+ & + currentCohort%prt%GetTurnover(sapw_organ, element_id)+ & + currentCohort%prt%GetTurnover(fnrt_organ, element_id)+ & + currentCohort%prt%GetTurnover(struct_organ, element_id)+ & + currentCohort%prt%GetTurnover(repro_organ, element_id) + store_m_turnover = 0_r8 + sapw_m_turnover = 0_r8 + fnrt_m_turnover = 0_r8 + struct_m_turnover = 0_r8 + repro_m_turnover = 0_r8 + leaf_m = currentCohort%prt%GetState(leaf_organ, element_id)+ & + currentCohort%prt%GetState(store_organ, element_id)+ & + currentCohort%prt%GetState(sapw_organ, element_id)+ & + currentCohort%prt%GetState(fnrt_organ, element_id)+ & + currentCohort%prt%GetState(struct_organ, element_id)+ & + currentCohort%prt%GetState(repro_organ, element_id) + store_m = 0_r8 + sapw_m = 0_r8 + fnrt_m = 0_r8 + struct_m = 0_r8 + repro_m = 0_r8 + end if plant_dens = currentCohort%n/currentPatch%area ! --------------------------------------------------------------------------------- From 89536812f4d9c8c1b6510497dc3fb6d39a1f41c9 Mon Sep 17 00:00:00 2001 From: ZacharyRobbins Date: Tue, 16 Aug 2022 11:24:11 -0600 Subject: [PATCH 316/852] Updated to comments by JK Revised commit to issue on PR #891. Adjusted so fine roots are retained within that pool. Fixed the spacing on EDPatchDynamics.F90 --- biogeochem/EDCohortDynamicsMod.F90 | 3 +- biogeochem/EDPatchDynamicsMod.F90 | 89 ++++++++++++++---------------- biogeochem/EDPhysiologyMod.F90 | 7 +-- 3 files changed, 46 insertions(+), 53 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 957c3847ae..e283dfb006 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -978,12 +978,11 @@ subroutine SendCohortToLitter(csite,cpatch,ccohort,nplant,bc_in) leaf_m = ccohort%prt%GetState(leaf_organ, element_list(el))+ & ccohort%prt%GetState(store_organ, element_list(el))+ & ccohort%prt%GetState(sapw_organ, element_list(el))+ & - ccohort%prt%GetState(fnrt_organ, element_list(el))+ & ccohort%prt%GetState(struct_organ, element_list(el))+ & ccohort%prt%GetState(repro_organ, element_list(el)) store_m = 0_r8 sapw_m = 0_r8 - fnrt_m = 0_r8 + fnrt_m = ccohort%prt%GetState(fnrt_organ, element_list(el)) struct_m = 0_r8 repro_m = 0_r8 end if diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index dc4ef3d989..2ee60936e0 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1646,89 +1646,84 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & fnrt_m = currentCohort%prt%GetState(fnrt_organ, element_list(el)) struct_m = currentCohort%prt%GetState(struct_organ, element_list(el)) repro_m = currentCohort%prt%GetState(repro_organ, element_list(el)) - - - ! Absolute number of dead trees being transfered in with the donated area - num_dead_trees = (currentCohort%fire_mort*currentCohort%n * & + ! Absolute number of dead trees being transfered in with the donated area + num_dead_trees = (currentCohort%fire_mort*currentCohort%n * & patch_site_areadis/currentPatch%area) - - ! Contribution of dead trees to leaf litter - donatable_mass = num_dead_trees * (leaf_m+repro_m) * & + + ! Contribution of dead trees to leaf litter + donatable_mass = num_dead_trees * (leaf_m+repro_m) * & (1.0_r8-currentCohort%fraction_crown_burned) - ! Contribution of dead trees to leaf burn-flux - burned_mass = num_dead_trees * (leaf_m+repro_m) * currentCohort%fraction_crown_burned + ! Contribution of dead trees to leaf burn-flux + burned_mass = num_dead_trees * (leaf_m+repro_m) * currentCohort%fraction_crown_burned - do dcmpy=1,ndcmpy - dcmpy_frac = GetDecompyFrac(pft,leaf_organ,dcmpy) - new_litt%leaf_fines(dcmpy) = new_litt%leaf_fines(dcmpy) + & - donatable_mass*donate_m2*dcmpy_frac - curr_litt%leaf_fines(dcmpy) = curr_litt%leaf_fines(dcmpy) + & + do dcmpy=1,ndcmpy + dcmpy_frac = GetDecompyFrac(pft,leaf_organ,dcmpy) + new_litt%leaf_fines(dcmpy) = new_litt%leaf_fines(dcmpy) + & + donatable_mass*donate_m2*dcmpy_frac + curr_litt%leaf_fines(dcmpy) = curr_litt%leaf_fines(dcmpy) + & donatable_mass*retain_m2*dcmpy_frac - end do + end do - site_mass%burn_flux_to_atm = site_mass%burn_flux_to_atm + burned_mass + site_mass%burn_flux_to_atm = site_mass%burn_flux_to_atm + burned_mass - call set_root_fraction(currentSite%rootfrac_scr, pft, currentSite%zi_soil, & + call set_root_fraction(currentSite%rootfrac_scr, pft, currentSite%zi_soil, & bc_in%max_rooting_depth_index_col) - do dcmpy=1,ndcmpy - dcmpy_frac = GetDecompyFrac(pft,fnrt_organ,dcmpy) - do sl = 1,currentSite%nlevsoil + do dcmpy=1,ndcmpy + dcmpy_frac = GetDecompyFrac(pft,fnrt_organ,dcmpy) + do sl = 1,currentSite%nlevsoil donatable_mass = num_dead_trees * (fnrt_m+store_m) * currentSite%rootfrac_scr(sl) new_litt%root_fines(dcmpy,sl) = new_litt%root_fines(dcmpy,sl) + & donatable_mass*donate_m2*dcmpy_frac curr_litt%root_fines(dcmpy,sl) = curr_litt%root_fines(dcmpy,sl) + & donatable_mass*retain_m2*dcmpy_frac - end do - end do - - ! Track as diagnostic fluxes - flux_diags%leaf_litter_input(pft) = & + end do + end do + ! Track as diagnostic fluxes + flux_diags%leaf_litter_input(pft) = & flux_diags%leaf_litter_input(pft) + & num_dead_trees * (leaf_m+repro_m) * (1.0_r8-currentCohort%fraction_crown_burned) - flux_diags%root_litter_input(pft) = & - flux_diags%root_litter_input(pft) + & - (fnrt_m + store_m) * num_dead_trees + flux_diags%root_litter_input(pft) = & + flux_diags%root_litter_input(pft) + & + (fnrt_m + store_m) * num_dead_trees ! coarse root biomass per tree - bcroot = (sapw_m + struct_m) * (1.0_r8 - prt_params%allom_agb_frac(pft) ) + bcroot = (sapw_m + struct_m) * (1.0_r8 - prt_params%allom_agb_frac(pft) ) ! below ground coarse woody debris from burned trees - do c = 1,ncwd - do sl = 1,currentSite%nlevsoil - donatable_mass = num_dead_trees * SF_val_CWD_frac(c) * & + do c = 1,ncwd + do sl = 1,currentSite%nlevsoil + donatable_mass = num_dead_trees * SF_val_CWD_frac(c) * & bcroot * currentSite%rootfrac_scr(sl) - - new_litt%bg_cwd(c,sl) = new_litt%bg_cwd(c,sl) + & + new_litt%bg_cwd(c,sl) = new_litt%bg_cwd(c,sl) + & donatable_mass * donate_m2 - curr_litt%bg_cwd(c,sl) = curr_litt%bg_cwd(c,sl) + & + curr_litt%bg_cwd(c,sl) = curr_litt%bg_cwd(c,sl) + & donatable_mass * retain_m2 ! track diagnostics - flux_diags%cwd_bg_input(c) = & + flux_diags%cwd_bg_input(c) = & flux_diags%cwd_bg_input(c) + & donatable_mass - enddo - end do - + enddo + end do ! stem biomass per tree bstem = (sapw_m + struct_m) * prt_params%allom_agb_frac(pft) ! Above ground coarse woody debris from twigs and small branches ! a portion of this pool may burn - do c = 1,ncwd - donatable_mass = num_dead_trees * SF_val_CWD_frac(c) * bstem - if (c == 1 .or. c == 2) then + do c = 1,ncwd + donatable_mass = num_dead_trees * SF_val_CWD_frac(c) * bstem + if (c == 1 .or. c == 2) then donatable_mass = donatable_mass * (1.0_r8-currentCohort%fraction_crown_burned) burned_mass = num_dead_trees * SF_val_CWD_frac(c) * bstem * & currentCohort%fraction_crown_burned site_mass%burn_flux_to_atm = site_mass%burn_flux_to_atm + burned_mass - endif - new_litt%ag_cwd(c) = new_litt%ag_cwd(c) + donatable_mass * donate_m2 - curr_litt%ag_cwd(c) = curr_litt%ag_cwd(c) + donatable_mass * retain_m2 - flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + donatable_mass - enddo + endif + new_litt%ag_cwd(c) = new_litt%ag_cwd(c) + donatable_mass * donate_m2 + curr_litt%ag_cwd(c) = curr_litt%ag_cwd(c) + donatable_mass * retain_m2 + flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + donatable_mass + enddo endif diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 71c483b2df..884d8d8288 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2213,23 +2213,22 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) leaf_m_turnover = currentCohort%prt%GetTurnover(leaf_organ, element_id)+ & currentCohort%prt%GetTurnover(store_organ, element_id)+ & currentCohort%prt%GetTurnover(sapw_organ, element_id)+ & - currentCohort%prt%GetTurnover(fnrt_organ, element_id)+ & + currentCohort%prt%GetTurnover(struct_organ, element_id)+ & currentCohort%prt%GetTurnover(repro_organ, element_id) store_m_turnover = 0_r8 sapw_m_turnover = 0_r8 - fnrt_m_turnover = 0_r8 + fnrt_m_turnover = currentCohort%prt%GetTurnover(fnrt_organ, element_id) struct_m_turnover = 0_r8 repro_m_turnover = 0_r8 leaf_m = currentCohort%prt%GetState(leaf_organ, element_id)+ & currentCohort%prt%GetState(store_organ, element_id)+ & currentCohort%prt%GetState(sapw_organ, element_id)+ & - currentCohort%prt%GetState(fnrt_organ, element_id)+ & currentCohort%prt%GetState(struct_organ, element_id)+ & currentCohort%prt%GetState(repro_organ, element_id) store_m = 0_r8 sapw_m = 0_r8 - fnrt_m = 0_r8 + fnrt_m = currentCohort%prt%GetState(fnrt_organ, element_id) struct_m = 0_r8 repro_m = 0_r8 end if From 4fcb869bcca85df79868a493ed9b3da5f9d93028 Mon Sep 17 00:00:00 2001 From: ckoven Date: Thu, 18 Aug 2022 15:49:20 -0600 Subject: [PATCH 317/852] added basal-area and crown-area weghted mean heights --- main/FatesHistoryInterfaceMod.F90 | 35 +++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 7ab5c9c0ca..ff462a83f7 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -195,6 +195,9 @@ module FatesHistoryInterfaceMod integer :: ih_fates_fraction_si + integer :: ih_ba_weighted_height + integer :: ih_ca_weighted_height + integer :: ih_cwd_elcwd integer :: ih_litter_in_si ! carbon only @@ -1807,6 +1810,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_area_plant_si => this%hvars(ih_area_plant_si)%r81d, & hio_area_trees_si => this%hvars(ih_area_trees_si)%r81d, & hio_fates_fraction_si => this%hvars(ih_fates_fraction_si)%r81d, & + hio_ba_weighted_height => this%hvars(ih_ba_weighted_height)%r81d, & + hio_ca_weighted_height => this%hvars(ih_ca_weighted_height)%r81d, & hio_canopy_spread_si => this%hvars(ih_canopy_spread_si)%r81d, & hio_biomass_si_pft => this%hvars(ih_biomass_si_pft)%r82d, & hio_leafbiomass_si_pft => this%hvars(ih_leafbiomass_si_pft)%r82d, & @@ -2535,17 +2540,21 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! basal area [m2/m2] hio_ba_si_scpf(io_si,scpf) = hio_ba_si_scpf(io_si,scpf) + & - 0.25_r8*3.14159_r8*((dbh/100.0_r8)**2.0_r8)*ccohort%n / m2_per_ha + 0.25_r8*pi_const*((dbh/100.0_r8)**2.0_r8)*ccohort%n / m2_per_ha ! also by size class only hio_ba_si_scls(io_si,scls) = hio_ba_si_scls(io_si,scls) + & - 0.25_r8*3.14159_r8*((dbh/100.0_r8)**2.0_r8)* & + 0.25_r8*pi_const*((dbh/100.0_r8)**2.0_r8)* & ccohort%n / m2_per_ha ! growth increment hio_ddbh_si_scpf(io_si,scpf) = hio_ddbh_si_scpf(io_si,scpf) + & ccohort%ddbhdt*ccohort%n / m2_per_ha * m_per_cm + hio_ba_weighted_height(io_si) = hio_ba_weighted_height(io_si) + & + ccohort%hite * & + 0.25_r8*pi_const*((dbh/100.0_r8)**2.0_r8)*ccohort%n / m2_per_ha + end if ! mortality sums [#/m2] @@ -2753,6 +2762,9 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_yesterdaycanopylevel_canopy_si_scls(io_si,scls) = & hio_yesterdaycanopylevel_canopy_si_scls(io_si,scls) + & ccohort%canopy_layer_yesterday * ccohort%n / m2_per_ha + + hio_ca_weighted_height(io_si) = hio_ca_weighted_height(io_si) + & + ccohort%hite * ccohort%c_area / m2_per_ha else canlayer hio_nplant_understory_si_scag(io_si,iscag) = hio_nplant_understory_si_scag(io_si,iscag) + ccohort%n / m2_per_ha hio_mortality_understory_si_scag(io_si,iscag) = hio_mortality_understory_si_scag(io_si,iscag) + & @@ -2954,6 +2966,13 @@ subroutine update_history_dyn(this,nc,nsites,sites) cpatch => cpatch%younger end do patchloop !patch loop + ! divide basal-area-weighted height by basal area to get mean + if ( sum(hio_ba_si_scpf(io_si,:)) .gt. tiny ) then + hio_ba_weighted_height(io_si) = hio_ba_weighted_height(io_si) / sum(hio_ba_si_scpf(io_si,:)) + else + hio_ba_weighted_height(io_si) = 0._r8 + endif + ! divide so-far-just-summed but to-be-averaged patch-age-class variables by patch-age-class area to get mean values do ipa2 = 1, nlevage if (hio_area_si_age(io_si, ipa2) .gt. tiny) then @@ -4459,6 +4478,18 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_fates_fraction_si, flush_to_zero=.true.) + call this%set_history_var(vname='FATES_BA_WEIGHTED_HEIGHT', units='m', & + long='basal area-weighted mean height of woody plants', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_ba_weighted_heght_si) + + call this%set_history_var(vname='FATES_CA_WEIGHTED_HEIGHT', units='m', & + long='crown area-weighted mean height of canopy plants', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_ca_weighted_heght_si) + call this%set_history_var(vname='FATES_COLD_STATUS', units='', & long='site-level cold status, 0=not cold-dec, 1=too cold for leaves, 2=not too cold', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & From e9afae9ce7da26088f0bcf9f1ecdccc240d64c2d Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 18 Aug 2022 15:18:28 -0700 Subject: [PATCH 318/852] add dispersal module with multiple kernels --- main/FatesDispersalMod.F90 | 135 ++++++++++++++++++++++++++++++++ main/FatesInterfaceTypesMod.F90 | 63 +++------------ 2 files changed, 144 insertions(+), 54 deletions(-) create mode 100644 main/FatesDispersalMod.F90 diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 new file mode 100644 index 0000000000..1eb534a3b0 --- /dev/null +++ b/main/FatesDispersalMod.F90 @@ -0,0 +1,135 @@ +module FatesDispersalMod + + use shr_log_mod , only : errMsg => shr_log_errMsg + use FatesGlobals , only : endrun => fates_endrun + use FatesGlobals , only : fates_log + use FatesConstantsMod , only : r8 => fates_r8 + use FatesConstantsMod , only : pi_const + + implicit none + + ! Neighbor node + type, public :: neighbor_type + + ! Grid cell neighbor + type(neighbor_type), pointer :: next_neighbor => null() + + integer :: gindex ! grid cell index + real(r8) :: gc_dist ! distance between source and neighbor + real(r8) :: density_prob ! probability density from source + + contains + + procedure :: ProbabilityDensity + + end type neighbor_type + + ! Neighborhood linked list + type, public :: neighborhood_type + + ! Linked list of neighbors for a given source grid cell + type(neighbor_type), pointer :: first_neighbor => null() + type(neighbor_type), pointer :: last_neighbor => null() + + integer :: neighbor_count ! total neighbors near source + + end type neighborhood_type + + type(neighborhood_type), public, pointer :: lneighbors(:) + + +contains + + ! ==================================================================================== + + subroutine ProbabilityDensity(pd, ipft, dist) + + ! Main subroutine that calls difference routines based on case select mode + + ! Use + use FatesInterfaceTypesMod, only : hlm_dispersal_kernel_exponential, & + hlm_dispersal_kernel_exppower, & + hlm_dispersal_kernel_logsech, & + hlm_dispersal_kernel_mode + + ! Arguments + real(r8), intent(out) :: pd ! Probability density + integer, intent(in) :: ipft ! pft index + real(r8), intent(in) :: dist ! distance + + ! Local - temp + + hlm_dispersal_kernel_mode = 1 + hlm_dispersal_kernel_exponential = 1 + hlm_dispersal_kernel_exppower = 2 + hlm_dispersal_kernel_logsech = 3 + + select case(hlm_dispersal_kernel_mode) + + case (hlm_dispersal_kernel_exponential) + pd = PD_exponential(dist,param_a) + case (hlm_dispersal_kernel_exppower) + pd = PD_exppower(dist,param_a, param_b) + case (hlm_dispersal_kernel_logsech) + pd = PD_logsech(dist,param_a, param_b) + case default + write(fates_log(),*) 'ERROR: An undefined dispersal kernel was specified: ', hlm_dispersal_kernel_mode + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select + + end subroutine ProbabilityDensity + + ! ==================================================================================== + + real(r8) function PD_exponential(dist,param_a) + + ! Arguments + real(r8), intent(in) :: dist + real(r8), intent(in) :: param_a + + ! Assuming simple exponential decay. In the future perhaps this could be an interface + ! for different weight calculations (and could be held only in fates) + + PD_exponential = exp(-param_a*dist) + + end function PD_exponential + + ! ==================================================================================== + + real(r8) function PD_exppower(dist,param_a,param_b) + + ! Arguments + real(r8), intent(in) :: dist + real(r8), intent(in) :: param_a + real(r8), intent(in) :: param_b + + ! Assuming simple exponential decay. In the future perhaps this could be an interface + ! for different weight calculations (and could be held only in fates) + + PD_exppower = (param_b / (2*pi_const*gamma(2/param_b))) * & + exp(-(dist**param_b)/(param_a**param_b)) + + end function PD_exppower + + ! ==================================================================================== + + real(r8) function PD_logsech(dist,param_a,param_b) + + ! Arguments + real(r8), intent(in) :: dist + real(r8), intent(in) :: param_a + real(r8), intent(in) :: param_b + + ! Assuming simple exponential decay. In the future perhaps this could be an interface + ! for different weight calculations (and could be held only in fates) + + PD_logsech = (1/(pi_const**2 * param_b * dist**2)) / & + ((dist/param_a)**(1/param_b) + & + (dist/param_a)**(-1/param_b)) + + end function PD_logsech + + ! ==================================================================================== + + +end module FatesDispersalMod \ No newline at end of file diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index e187e86a07..98e69a2dba 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -195,6 +195,15 @@ module FatesInterfaceTypesMod integer, public :: hlm_use_sp ! Flag to use FATES satellite phenology (LAI) mode ! 1 = TRUE, 0 = FALSE + + integer, public :: hlm_dispersal_kernel_mode ! Flag to signal the use of grid cell seed dispersal + ! Setting this to greater than zero overrides seed rain + + integer, public :: hlm_dispersal_kernel_none ! no dispersal (use seed rain) + integer, public :: hlm_dispersal_kernel_exponential ! exponential dispersal kernel + integer, public :: hlm_dispersal_kernel_exppower ! exponential power (ExP) dispersal kernel + integer, public :: hlm_dispersal_kernel_logsech ! logistic-sech (LogS) dispersal kernel + ! ------------------------------------------------------------------------------------- ! Parameters that are dictated by FATES and known to be required knowledge ! needed by the HLMs @@ -753,63 +762,9 @@ module FatesInterfaceTypesMod end type bc_pconst_type - ! Neighbor node - type, public :: neighbor_type - - ! Grid cell neighbor - type(neighbor_type), pointer :: next_neighbor => null() - - integer :: gindex ! grid cell index - real(r8) :: gc_dist ! distance between source and neighbor - real(r8) :: dist_weight ! distance-based weight scalar - - contains - generic, public :: DistWeightCalc => SWC - procedure, private :: SWC => SimpleWeightCalc - - end type neighbor_type - - ! Neighborhood linked list - type, public :: neighborhood_type - - ! Linked list of neighbors for a given source grid cell - type(neighbor_type), pointer :: first_neighbor => null() - type(neighbor_type), pointer :: last_neighbor => null() - - integer :: neighbor_count ! total neighbors near source - real(r8) :: dist_weight_tot ! sum of dist weight scalars - ! real(r8) :: gclat ! source gridcell latitude (deg) - ! real(r8) :: gclon ! source gridcell longitude (deg) - - end type neighborhood_type - - type(neighborhood_type), public, pointer :: lneighbors(:) - - ! - interface DistWeightCalc - module procedure SimpleWeightCalc - end interface DistWeightCalc - contains ! ====================================================================================== - - function SimpleWeightCalc(this, g2g_dist, decay_rate) result(dist_weight) - ! Arguments - class(neighbor_type) :: this - real(r8), intent(in) :: g2g_dist - real(r8), intent(in) :: decay_rate - real(r8) :: dist_weight - - ! Assuming simple exponential decay. In the future perhaps this could be an interface - ! for different weight calculations (and could be held only in fates) - - dist_weight = exp(-decay_rate*g2g_dist) - - end function SimpleWeightCalc - - ! ==================================================================================== - end module FatesInterfaceTypesMod From f882f84f50ad46a9efd02023ec255443bb496684 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 18 Aug 2022 15:36:44 -0700 Subject: [PATCH 319/852] update calls for new dispersal location --- main/FatesDispersalMod.F90 | 7 ++++--- main/FatesInterfaceMod.F90 | 17 ++++++++++------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index 1eb534a3b0..e4307790ba 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -42,7 +42,7 @@ module FatesDispersalMod ! ==================================================================================== - subroutine ProbabilityDensity(pd, ipft, dist) + subroutine ProbabilityDensity(pd, dist) ! Main subroutine that calls difference routines based on case select mode @@ -54,11 +54,12 @@ subroutine ProbabilityDensity(pd, ipft, dist) ! Arguments real(r8), intent(out) :: pd ! Probability density - integer, intent(in) :: ipft ! pft index + ! integer, intent(in) :: ipft ! pft index - future arg real(r8), intent(in) :: dist ! distance ! Local - temp - + param_a = 1._r8 + param_b = 1._r8 hlm_dispersal_kernel_mode = 1 hlm_dispersal_kernel_exponential = 1 hlm_dispersal_kernel_exppower = 2 diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 4cef727a2b..2b1733b1ee 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1897,7 +1897,7 @@ subroutine DetermineGridCellNeighbors(neighbors) use domainMod , only : ldomain use spmdMod , only : MPI_REAL8, MPI_INTEGER, mpicom, npes, masterproc, iam use perf_mod , only : t_startf, t_stopf - use FatesInterfaceTypesMod, only : neighborhood_type, neighbor_type + use FatesDispersalMod , only : neighborhood_type, neighbor_type use FatesUtilsMod , only : GetNeighborDistance ! Arguments @@ -1919,10 +1919,11 @@ subroutine DetermineGridCellNeighbors(neighbors) real(r8), allocatable :: gclat(:), gclon(:) real(r8) :: g2g_dist ! grid cell distance + real(r8) :: pdf ! temp ! Parameters and constants, to be moved to fates param file ! Both of these should probably be per pft - real(r8) :: decay_rate = 1._r8 + ! real(r8) :: decay_rate = 1._r8 real(r8) :: g2g_dist_max = 2500._r8 * 1000._r8 ! maximum search distance [m] ! 5 deg = 785.8 km, 10 deg = 1569 km, 15deg = 2345 km assumes cartesian layout with diagonal distance @@ -1934,7 +1935,7 @@ subroutine DetermineGridCellNeighbors(neighbors) ! write(fates_log(),*)'DGCN: npes, numproc: ', npes, numproc allocate(neighbors(numg), stat=ier) - neighbors(:)%dist_weight_tot = nan + ! neighbors(:)%density_prob_tot = nan neighbors(:)%neighbor_count = 0 allocate(gclat(numg)) @@ -1993,7 +1994,9 @@ subroutine DetermineGridCellNeighbors(neighbors) current_neighbor%gindex = ldecomp%gdc2glo(gj) current_neighbor%gc_dist = g2g_dist - current_neighbor%dist_weight = current_neighbor%DistWeightCalc(g2g_dist,decay_rate) + call current_neighbor%DistWeightCalc(pdf, g2g_dist) + current_neighbor%density_prob = pdf + ! current_neighbor%density_prob = current_neighbor%DistWeightCalc(g2g_dist,decay_rate) if (associated(neighbors(gi)%first_neighbor)) then neighbors(gi)%last_neighbor%next_neighbor => current_neighbor @@ -2004,7 +2007,7 @@ subroutine DetermineGridCellNeighbors(neighbors) end if neighbors(gi)%neighbor_count = neighbors(gi)%neighbor_count + 1 - neighbors(gi)%dist_weight_tot = neighbors(gi)%dist_weight_tot + current_neighbor%dist_weight + ! neighbors(gi)%density_prob_tot = neighbors(gi)%density_prob_tot + current_neighbor%density_prob ! Add current grid cell index to the neighbor's list as well allocate(another_neighbor) @@ -2014,7 +2017,7 @@ subroutine DetermineGridCellNeighbors(neighbors) another_neighbor%gindex = ldecomp%gdc2glo(gi) another_neighbor%gc_dist = current_neighbor%gc_dist - another_neighbor%dist_weight = current_neighbor%dist_weight + another_neighbor%density_prob = current_neighbor%density_prob if (associated(neighbors(gj)%first_neighbor)) then neighbors(gj)%last_neighbor%next_neighbor => another_neighbor @@ -2025,7 +2028,7 @@ subroutine DetermineGridCellNeighbors(neighbors) end if neighbors(gj)%neighbor_count = neighbors(gj)%neighbor_count + 1 - neighbors(gj)%dist_weight_tot = neighbors(gj)%dist_weight_tot + another_neighbor%dist_weight + ! neighbors(gj)%density_prob_tot = neighbors(gj)%density_prob_tot + another_neighbor%density_prob end if dist_check end do neighbor_search From 2f481ff74fc2e5b5a8d51b5a5dc25b0b2c291bdb Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 18 Aug 2022 16:37:36 -0700 Subject: [PATCH 320/852] fix errors --- main/FatesDispersalMod.F90 | 17 +++++++---------- main/FatesInterfaceMod.F90 | 4 ++-- main/FatesInterfaceTypesMod.F90 | 8 ++++---- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index e4307790ba..2d94766883 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -18,10 +18,6 @@ module FatesDispersalMod real(r8) :: gc_dist ! distance between source and neighbor real(r8) :: density_prob ! probability density from source - contains - - procedure :: ProbabilityDensity - end type neighbor_type ! Neighborhood linked list @@ -37,6 +33,9 @@ module FatesDispersalMod type(neighborhood_type), public, pointer :: lneighbors(:) + public :: ProbabilityDensity + + character(len=*), parameter, private :: sourcefile = __FILE__ contains @@ -58,12 +57,10 @@ subroutine ProbabilityDensity(pd, dist) real(r8), intent(in) :: dist ! distance ! Local - temp - param_a = 1._r8 - param_b = 1._r8 + real(r8) :: param_a = 1._r8 + real(r8) :: param_b = 1._r8 + hlm_dispersal_kernel_mode = 1 - hlm_dispersal_kernel_exponential = 1 - hlm_dispersal_kernel_exppower = 2 - hlm_dispersal_kernel_logsech = 3 select case(hlm_dispersal_kernel_mode) @@ -133,4 +130,4 @@ end function PD_logsech ! ==================================================================================== -end module FatesDispersalMod \ No newline at end of file +end module FatesDispersalMod diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 2b1733b1ee..e55e531ea7 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1897,7 +1897,7 @@ subroutine DetermineGridCellNeighbors(neighbors) use domainMod , only : ldomain use spmdMod , only : MPI_REAL8, MPI_INTEGER, mpicom, npes, masterproc, iam use perf_mod , only : t_startf, t_stopf - use FatesDispersalMod , only : neighborhood_type, neighbor_type + use FatesDispersalMod , only : neighborhood_type, neighbor_type, ProbabilityDensity use FatesUtilsMod , only : GetNeighborDistance ! Arguments @@ -1994,7 +1994,7 @@ subroutine DetermineGridCellNeighbors(neighbors) current_neighbor%gindex = ldecomp%gdc2glo(gj) current_neighbor%gc_dist = g2g_dist - call current_neighbor%DistWeightCalc(pdf, g2g_dist) + call ProbabilityDensity(pdf, g2g_dist) current_neighbor%density_prob = pdf ! current_neighbor%density_prob = current_neighbor%DistWeightCalc(g2g_dist,decay_rate) diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 98e69a2dba..59aba2bc76 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -199,10 +199,10 @@ module FatesInterfaceTypesMod integer, public :: hlm_dispersal_kernel_mode ! Flag to signal the use of grid cell seed dispersal ! Setting this to greater than zero overrides seed rain - integer, public :: hlm_dispersal_kernel_none ! no dispersal (use seed rain) - integer, public :: hlm_dispersal_kernel_exponential ! exponential dispersal kernel - integer, public :: hlm_dispersal_kernel_exppower ! exponential power (ExP) dispersal kernel - integer, public :: hlm_dispersal_kernel_logsech ! logistic-sech (LogS) dispersal kernel + integer, parameter, public :: hlm_dispersal_kernel_none = 0 ! no dispersal (use seed rain) + integer, parameter, public :: hlm_dispersal_kernel_exponential = 1 ! exponential dispersal kernel + integer, parameter, public :: hlm_dispersal_kernel_exppower = 2 ! exponential power (ExP) dispersal kernel + integer, parameter, public :: hlm_dispersal_kernel_logsech = 3 ! logistic-sech (LogS) dispersal kernel ! ------------------------------------------------------------------------------------- ! Parameters that are dictated by FATES and known to be required knowledge From 4a004f9b307e9026ffd6c5800a4f569d15ba73f3 Mon Sep 17 00:00:00 2001 From: ckoven Date: Thu, 18 Aug 2022 22:08:54 -0600 Subject: [PATCH 321/852] fix typo --- main/FatesHistoryInterfaceMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index ff462a83f7..2941418635 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -4482,13 +4482,13 @@ subroutine define_history_vars(this, initialize_variables) long='basal area-weighted mean height of woody plants', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_ba_weighted_heght_si) + index=ih_ba_weighted_height_si) call this%set_history_var(vname='FATES_CA_WEIGHTED_HEIGHT', units='m', & long='crown area-weighted mean height of canopy plants', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_ca_weighted_heght_si) + index=ih_ca_weighted_height_si) call this%set_history_var(vname='FATES_COLD_STATUS', units='', & long='site-level cold status, 0=not cold-dec, 1=too cold for leaves, 2=not too cold', & From 2c2eb561584833c9e221eea13727c9ef4d11b809 Mon Sep 17 00:00:00 2001 From: ckoven Date: Thu, 18 Aug 2022 22:40:07 -0600 Subject: [PATCH 322/852] fixing more typos --- main/FatesHistoryInterfaceMod.F90 | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 2941418635..23190290c5 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -195,8 +195,8 @@ module FatesHistoryInterfaceMod integer :: ih_fates_fraction_si - integer :: ih_ba_weighted_height - integer :: ih_ca_weighted_height + integer :: ih_ba_weighted_height_si + integer :: ih_ca_weighted_height_si integer :: ih_cwd_elcwd @@ -1810,8 +1810,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_area_plant_si => this%hvars(ih_area_plant_si)%r81d, & hio_area_trees_si => this%hvars(ih_area_trees_si)%r81d, & hio_fates_fraction_si => this%hvars(ih_fates_fraction_si)%r81d, & - hio_ba_weighted_height => this%hvars(ih_ba_weighted_height)%r81d, & - hio_ca_weighted_height => this%hvars(ih_ca_weighted_height)%r81d, & + hio_ba_weighted_height_si => this%hvars(ih_ba_weighted_height_si)%r81d, & + hio_ca_weighted_height_si => this%hvars(ih_ca_weighted_height_si)%r81d, & hio_canopy_spread_si => this%hvars(ih_canopy_spread_si)%r81d, & hio_biomass_si_pft => this%hvars(ih_biomass_si_pft)%r82d, & hio_leafbiomass_si_pft => this%hvars(ih_leafbiomass_si_pft)%r82d, & @@ -2551,7 +2551,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_ddbh_si_scpf(io_si,scpf) = hio_ddbh_si_scpf(io_si,scpf) + & ccohort%ddbhdt*ccohort%n / m2_per_ha * m_per_cm - hio_ba_weighted_height(io_si) = hio_ba_weighted_height(io_si) + & + hio_ba_weighted_height_si(io_si) = hio_ba_weighted_height_si(io_si) + & ccohort%hite * & 0.25_r8*pi_const*((dbh/100.0_r8)**2.0_r8)*ccohort%n / m2_per_ha @@ -2763,7 +2763,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_yesterdaycanopylevel_canopy_si_scls(io_si,scls) + & ccohort%canopy_layer_yesterday * ccohort%n / m2_per_ha - hio_ca_weighted_height(io_si) = hio_ca_weighted_height(io_si) + & + hio_ca_weighted_height_si(io_si) = hio_ca_weighted_height_si(io_si) + & ccohort%hite * ccohort%c_area / m2_per_ha else canlayer hio_nplant_understory_si_scag(io_si,iscag) = hio_nplant_understory_si_scag(io_si,iscag) + ccohort%n / m2_per_ha @@ -2968,9 +2968,9 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! divide basal-area-weighted height by basal area to get mean if ( sum(hio_ba_si_scpf(io_si,:)) .gt. tiny ) then - hio_ba_weighted_height(io_si) = hio_ba_weighted_height(io_si) / sum(hio_ba_si_scpf(io_si,:)) + hio_ba_weighted_height_si(io_si) = hio_ba_weighted_height_si(io_si) / sum(hio_ba_si_scpf(io_si,:)) else - hio_ba_weighted_height(io_si) = 0._r8 + hio_ba_weighted_height_si(io_si) = 0._r8 endif ! divide so-far-just-summed but to-be-averaged patch-age-class variables by patch-age-class area to get mean values From 43ee9b93ead585992235d76531ec7434f87bab64 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 19 Aug 2022 13:58:12 -0400 Subject: [PATCH 323/852] yet more reorganization and PID algorithm testing --- biogeochem/EDPhysiologyMod.F90 | 2 - parteh/PRTAllometricCNPMod.F90 | 155 ++++++++++++++++++--------------- 2 files changed, 86 insertions(+), 71 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index a260285c42..2573dae56e 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2647,8 +2647,6 @@ subroutine UpdateRecruitL2FR(csite) rec_l2fr0(ft,cl) = rec_l2fr0(ft,cl) / rec_n(ft,cl) csite%rec_l2fr(ft,cl) = & (1._r8-smth_wgt)*csite%rec_l2fr(ft,cl) + smth_wgt*rec_l2fr0(ft,cl) - - !print*,"REC_L2FR:",cl,csite%rec_l2fr(ft,cl) end if end do end do diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index de34316837..e79c63ab6d 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -107,8 +107,8 @@ module PRTAllometricCNPMod integer, parameter, private :: pid_spe_controller = storage_spe - real(r8), parameter, private :: pid_int_wgt = 1._r8/30._r8 ! n-day smoothing (K on the integral of PID) - real(r8), parameter, private :: pid_drv_wgt = 1._r8/30._r8 ! n-day smoothing (K on the derivative of PID) + real(r8), parameter, private :: pid_int_wgt = 1._r8/10._r8 ! n-day smoothing (K on the integral of PID) + real(r8), parameter, private :: pid_drv_wgt = 1._r8/10._r8 ! n-day smoothing (K on the derivative of PID) ! Global identifiers for the two stoichiometry values integer,public, parameter :: stoich_growth_min = 1 ! Flag for stoichiometry associated with @@ -481,7 +481,7 @@ subroutine DailyPRTAllometricCNP(this,co_num,nplant) ! This routine updates the l2fr (leaf 2 fine-root multiplier) variable ! It will also update the target - call this%CNPAdjustFRootTargets(target_c,target_dcdd,co_num,nplant) + !call this%CNPAdjustFRootTargets(target_c,target_dcdd,co_num,nplant) ! Remember the original C,N,P states to help with final ! evaluation of how much was allocated @@ -582,6 +582,11 @@ subroutine DailyPRTAllometricCNP(this,co_num,nplant) end do call endrun(msg=errMsg(sourcefile, __LINE__)) end if + + + ! This routine updates the l2fr (leaf 2 fine-root multiplier) variable + ! It will also update the target + !call this%CNPAdjustFRootTargets(target_c,target_dcdd,co_num,nplant) ! =================================================================================== ! Step 3. @@ -591,7 +596,7 @@ subroutine DailyPRTAllometricCNP(this,co_num,nplant) call this%CNPAllocateRemainder(c_gain, n_gain, p_gain, & c_gain0, n_gain0, p_gain0, & - c_efflux, n_efflux, p_efflux) + c_efflux, n_efflux, p_efflux,co_num,nplant,target_c,target_dcdd) if(n_uptake_mode.ne.prescribed_n_uptake) then @@ -730,6 +735,7 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) real(r8) :: logi_k real(r8) :: l2fr_mult real(r8) :: l2fr_delta + real(r8) :: nc_ratio, pc_ratio real(r8) :: dxcdt_ratio ! log change (derivative) of the maximum of the N/C and P/C storage ratio real(r8) :: xc_ratio ! log Maximum of the N/C and P/C storage ratio real(r8), pointer :: ema_xc ! The exponential moving average of the N-or-P versus C PID error function @@ -739,6 +745,14 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) real(r8), parameter :: max_l2fr_cgain_frac = 0.99_r8 real(r8), parameter :: xc_ratio_correction = 1.0_r8 + integer, parameter :: pid_c_function = 0 + integer, parameter :: pid_n_function = 1 + integer, parameter :: pid_minnc_function = 2 + integer, parameter :: pid_alogmaxnc_function = 3 + integer, parameter :: pid_ncratio_function = 4 + + !integer, parameter :: pid_function = pid_c_function + ! This is the relative scaling strength of the derivative term (K_d), ! compared to the combined proportion and integral term (K_p and K_i) ! Note the strength of the derivative is should be about half of the period @@ -767,8 +781,8 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) store_c_max = target_c(store_organ) - store_c_act = this%GetState(store_organ, carbon12_element) + & - this%bc_in(acnp_bc_in_id_netdc)%rval + store_c_act = max(0.001_r8*store_c_max,this%GetState(store_organ, carbon12_element) + & + this%bc_in(acnp_bc_in_id_netdc)%rval) if(n_uptake_mode.ne.prescribed_n_uptake)then @@ -780,15 +794,28 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) store_nut_act = this%GetState(store_organ, nitrogen_element) + & this%bc_inout(acnp_bc_inout_id_netdn)%rval - !n_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max)/(store_c_act/store_c_max))) - !n_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max))) - !n_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,1._r8/(store_c_act/store_c_max))) - - if((store_nut_act/store_nut_max) > (store_c_act/store_c_max))then - n_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_c_max/store_c_act))) - else - n_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max))) - end if + select case(nint(EDPftvarcon_inst%dev_arbitrary_pft(ipft))) + case(pid_c_function) + n_ratio = store_c_max/store_c_act + case(pid_n_function) + n_ratio = store_nut_act/store_nut_max + case(pid_minnc_function) + if((store_nut_act/store_nut_max) > (store_c_act/store_c_max))then + n_ratio = (store_c_max/store_c_act) + else + n_ratio = (store_nut_act/store_nut_max) + end if + case(pid_alogmaxnc_function) + if( abs(log(store_nut_act/store_nut_max)) < abs(log(store_c_act/store_c_max))) then + n_ratio = (store_c_max/store_c_act) + else + n_ratio = (store_nut_act/store_nut_max) + end if + case(pid_ncratio_function) + n_ratio = (store_nut_act/store_nut_max)/(store_c_act/store_c_max) + end select + + nc_ratio = (store_nut_act/store_nut_max)/(store_c_act/store_c_max) else n_ratio = -1._r8 @@ -804,16 +831,28 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) store_nut_act = this%GetState(store_organ, phosphorus_element) + & this%bc_inout(acnp_bc_inout_id_netdp)%rval - !p_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max)/(store_c_act/store_c_max))) - p_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max))) - !p_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,1._r8/(store_c_act/store_c_max))) - - if((store_nut_act/store_nut_max) > (store_c_act/store_c_max))then - p_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_c_max/store_c_act))) - else - p_ratio = xc_ratio_correction*min(50.0_r8,max(0.02_r8,(store_nut_act/store_nut_max))) - end if - + select case(nint(EDPftvarcon_inst%dev_arbitrary_pft(ipft))) + case(pid_c_function) + p_ratio = store_c_max/store_c_act + case(pid_n_function) + p_ratio = store_nut_act/store_nut_max + case(pid_minnc_function) + if((store_nut_act/store_nut_max) > (store_c_act/store_c_max))then + p_ratio = (store_c_max/store_c_act) + else + p_ratio = (store_nut_act/store_nut_max) + end if + case(pid_alogmaxnc_function) + if( abs(log(store_nut_act/store_nut_max)) < abs(log(store_c_act/store_c_max))) then + p_ratio = (store_c_max/store_c_act) + else + p_ratio = (store_nut_act/store_nut_max) + end if + case(pid_ncratio_function) + p_ratio = (store_nut_act/store_nut_max)/(store_c_act/store_c_max) + end select + + pc_ratio = (store_nut_act/store_nut_max)/(store_c_act/store_c_max) else p_ratio = -1._r8 @@ -875,34 +914,7 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) max(0._r8,target_c(struct_organ)-struct_c) - & max(0._r8,target_c(store_organ)-store_c)) - if(pid_method==pid_ratio) then - - l2fr_delta_max = (c_fnrt_expand + target_c(fnrt_organ))/target_c(fnrt_organ) - - ! This value could be negative if there is no gain, or less gain - ! than what can replace tissues, just ensure the multiplier is GT 1 - - l2fr_delta_max = max(1._r8,l2fr_delta_max) - - ! Determine the max change for the doubling timescale - ! 2.0 = l2fr_delta_max^frnt_adapt_tscl - - l2fr_delta_scale = 2._r8**(1._r8/prt_params%fnrt_adapt_tscale(ipft))-1.0_r8 - - ! Calculate the un-regulated l2fr multiplier - - logi_k = EDPftvarcon_inst%dev_arbitrary_pft(ipft) - l2fr_mult = l2fr_delta_scale*(2.0_r8/(1.0_r8 + exp(ema_xc)**logi_k)-1.0_r8)+1.0_r8 - - - if(l2fr_mult>1.0_r8)then - l2fr_mult = min(l2fr_mult,l2fr_delta_max) - end if - - l2fr = max(l2fr_min,l2fr * l2fr_mult) - - - elseif(pid_method==pid_logratio) then + if(pid_method==pid_logratio) then ! When using a log based (additive) PID search method ! we define 1/fnrt_adapt_tscale as delta we want @@ -914,10 +926,12 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) l2fr_delta_scale = (1._r8/prt_params%fnrt_adapt_tscale(ipft))/log(2.0_r8) + ! log(2.0_r8)*l2fr_delta_scale = (1._r8/prt_params%fnrt_adapt_tscale(ipft)) + ! ema_xc is already in log form to allow for averaging ! Want the derivative to be strongest when storage is most disproportionate - l2fr_deriv_scale = 0.0_r8 !0.25*abs(ema_xc/ema_dxcdt) + l2fr_deriv_scale = 0.0_r8 !-20.0_r8 !0.25*abs(ema_xc/ema_dxcdt) l2fr_int_scale = 0.0_r8 @@ -925,27 +939,28 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) ! we have already corrected enough to change the behavior, lets ! decrease the scaling - if( ((ema_xc > 0._r8) .and. (ema_dxcdt<0)) .or. ((ema_xc < 0._r8) .and. (ema_dxcdt>0))) then - l2fr_delta_scale = 0.05_r8 * l2fr_delta_scale + if( ((ema_xc > 0._r8) .and. (ema_dxcdt<0._r8)) .or. ((ema_xc < 0._r8) .and. (ema_dxcdt>0._r8))) then + l2fr_delta_scale = 0.1_r8 * l2fr_delta_scale sup_flag = 1 else sup_flag = 0 - end if !l2fr_delta = -l2fr_delta_scale*(min(0.2,max(-0.2,xc_ratio)) + ema_xc*l2fr_int_scale + ema_dxcdt*l2fr_deriv_scale) l2fr_delta = -l2fr_delta_scale*(xc_ratio + ema_xc*l2fr_int_scale + ema_dxcdt*l2fr_deriv_scale) - + ! Cap growth and shrinkage to avoid large changes ! (currently capping at projected rate for a 2:1 ratio - l2fr_delta_minmax = l2fr_delta_scale*log(2.0) + l2fr_delta_minmax = l2fr_delta_scale*log(20.0) ! Don't allow more growth than we have carbon to pay for - l2fr_delta_max = min(l2fr_delta_minmax,l2fr*(c_fnrt_expand + target_c(fnrt_organ))/target_c(fnrt_organ)) + !! l2fr_delta_max = min(l2fr_delta_minmax,l2fr*(c_fnrt_expand + target_c(fnrt_organ))/target_c(fnrt_organ)) - l2fr_delta = max(-l2fr_delta_minmax,min(l2fr_delta,l2fr_delta_max)) + !! l2fr_delta = max(-l2fr_delta_minmax,min(l2fr_delta,l2fr_delta_max)) + !!l2fr_delta = max(-l2fr_delta_minmax,min(l2fr_delta,l2fr_delta_minmax)) + ! Apply the delta, also, avoid generating incredibly small l2fr's, ! super small l2frs will occur in plants that perpetually get almost @@ -953,9 +968,7 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) l2fr = max(l2fr_min, l2fr + l2fr_delta ) - !if(co_num==1) - print*,'AAX1',co_num,hlm_current_year,hlm_day_of_year,dbh,nplant,sup_flag,xc_ratio,l2fr - + if(co_num==1) print*,'AAX1',co_num,hlm_current_year,hlm_day_of_year,dbh,nplant,sup_flag,log(nc_ratio),l2fr else @@ -1906,7 +1919,7 @@ end subroutine CNPStatureGrowth subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & c_gain0, n_gain0, p_gain0, & - c_efflux, n_efflux, p_efflux) + c_efflux, n_efflux, p_efflux,co_num,nplant,target_c,target_dcdd) class(cnp_allom_prt_vartypes) :: this real(r8), intent(inout) :: c_gain @@ -1918,7 +1931,11 @@ subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & real(r8), intent(inout) :: c_efflux real(r8), intent(inout) :: n_efflux real(r8), intent(inout) :: p_efflux - + integer,intent(in) :: co_num + real(r8),intent(in) :: nplant + real(r8) :: target_c(:) + real(r8) :: target_dcdd(:) + integer :: i real(r8), dimension(num_organs) :: deficit_n real(r8), dimension(num_organs) :: deficit_p @@ -2040,7 +2057,7 @@ subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & deficit_p(i) = max(0._r8,this%GetDeficit(phosphorus_element,l2g_organ_list(i),target_p)) end do - + ! ----------------------------------------------------------------------------------- ! Nutrient Fluxes proportionally to each pool (these should be fully actualized) ! (this also removes from the gain pools) @@ -2054,8 +2071,8 @@ subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & call ProportionalNutrAllocation(this,deficit_p(1:num_organs), & p_gain, phosphorus_element, l2g_organ_list(1:num_organs)) - - + call this%CNPAdjustFRootTargets(target_c,target_dcdd,co_num,nplant) + ! ----------------------------------------------------------------------------------- From 82aa37007a9ceba5de3e7dab5be888a35fb2c6da Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 22 Aug 2022 14:06:14 -0400 Subject: [PATCH 324/852] Removed declaration of cohort structure lai and sai --- main/EDTypesMod.F90 | 3 --- 1 file changed, 3 deletions(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index dfdfcdf43b..16ceda6115 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -218,9 +218,6 @@ module EDTypesMod real(r8) :: canopy_layer_yesterday ! recent canopy status of cohort ! (1 = canopy, 2 = understorey, etc.) ! real to be conservative during fusion - - real(r8) :: lai ! leaf area index of cohort: m2 leaf area of entire cohort per m2 of canopy area of a patch - real(r8) :: sai ! stem area index of cohort: m2 leaf area of entire cohort per m2 of canopy area of a patch real(r8) :: g_sb_laweight ! Total conductance (stomata+boundary layer) of the cohort, weighted by its leaf area [m/s]*[m2] real(r8) :: canopy_trim ! What is the fraction of the maximum leaf biomass that we are targeting? :- real(r8) :: leaf_cost ! How much does it cost to maintain leaves: kgC/m2/year-1 From 8dbc9f6a16ea981287bcbab71ad59d10a4892e14 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 22 Aug 2022 14:14:40 -0400 Subject: [PATCH 325/852] Removed unused smooth_leaf switch --- biogeochem/EDCanopyStructureMod.F90 | 2 -- 1 file changed, 2 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 4066aec6b6..b3175202ba 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1493,7 +1493,6 @@ subroutine leaf_area_profile( currentSite ) real(r8) :: fraction_exposed ! how much of this layer is not covered by snow? real(r8) :: layer_top_hite ! notional top height of this canopy layer (m) real(r8) :: layer_bottom_hite ! notional bottom height of this canopy layer (m) - integer :: smooth_leaf_distribution ! is the leaf distribution this option (1) or not (0) real(r8) :: frac_canopy(N_HITE_BINS) ! amount of canopy in each height class real(r8) :: minh(N_HITE_BINS) ! minimum height in height class (m) real(r8) :: maxh(N_HITE_BINS) ! maximum height in height class (m) @@ -1504,7 +1503,6 @@ subroutine leaf_area_profile( currentSite ) !---------------------------------------------------------------------- - smooth_leaf_distribution = 0 ! Here we are trying to generate a profile of leaf area, indexed by 'z' and by pft ! We assume that each point in the canopy recieved the light attenuated by the average From 1f4693bb01f2d54ff320a8b7ffa9d0c3f0118dbd Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 25 Aug 2022 12:21:09 -0600 Subject: [PATCH 326/852] Added model_day_int def --- main/FatesHistoryInterfaceMod.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 417f38e2b9..b9d539be2c 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -1755,6 +1755,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) integer :: height_bin_max, height_bin_min ! which height bin a given cohort's canopy is in integer :: i_heightbin ! iterator for height bins integer :: el ! Loop index for elements + integer :: model_day_int ! Integer model day since simulation start integer :: ageclass_since_anthrodist ! what is the equivalent age class for ! time-since-anthropogenic-disturbance of secondary forest From 82bdb8327631a34ca015ae2c94c04b32403e2c9c Mon Sep 17 00:00:00 2001 From: ckoven Date: Tue, 30 Aug 2022 12:42:46 -0600 Subject: [PATCH 327/852] changed tiny to nearzero --- main/FatesHistoryInterfaceMod.F90 | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 23190290c5..3d55be3e49 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -1799,7 +1799,6 @@ subroutine update_history_dyn(this,nc,nsites,sites) type(ed_patch_type),pointer :: cpatch type(ed_cohort_type),pointer :: ccohort - real(r8), parameter :: tiny = 1.e-5_r8 ! some small number real(r8), parameter :: reallytalltrees = 1000. ! some large number (m) integer :: tmp @@ -2967,7 +2966,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) end do patchloop !patch loop ! divide basal-area-weighted height by basal area to get mean - if ( sum(hio_ba_si_scpf(io_si,:)) .gt. tiny ) then + if ( sum(hio_ba_si_scpf(io_si,:)) .gt. nearzero ) then hio_ba_weighted_height_si(io_si) = hio_ba_weighted_height_si(io_si) / sum(hio_ba_si_scpf(io_si,:)) else hio_ba_weighted_height_si(io_si) = 0._r8 @@ -2975,7 +2974,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! divide so-far-just-summed but to-be-averaged patch-age-class variables by patch-age-class area to get mean values do ipa2 = 1, nlevage - if (hio_area_si_age(io_si, ipa2) .gt. tiny) then + if (hio_area_si_age(io_si, ipa2) .gt. nearzero) then hio_lai_si_age(io_si, ipa2) = hio_lai_si_age(io_si, ipa2) / (hio_area_si_age(io_si, ipa2)*AREA) hio_ncl_si_age(io_si, ipa2) = hio_ncl_si_age(io_si, ipa2) / (hio_area_si_age(io_si, ipa2)*AREA) do i_pft = 1, numpft @@ -3562,7 +3561,6 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) real(r8) :: patch_area_by_age(nlevage) ! patch area in each bin for normalizing purposes real(r8) :: canopy_area_by_age(nlevage) ! canopy area in each bin for normalizing purposes real(r8) :: site_area_veg ! area of the site that is not bare-ground - real(r8), parameter :: tiny = 1.e-5_r8 ! some small number integer :: ipa2 ! patch incrementer integer :: cnlfpft_indx, cnlf_indx, ipft, ican, ileaf ! more iterators and indices type(ed_patch_type),pointer :: cpatch @@ -3938,7 +3936,7 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) end do !patch loop do ipa2 = 1, nlevage - if (patch_area_by_age(ipa2) .gt. tiny) then + if (patch_area_by_age(ipa2) .gt. nearzero) then hio_gpp_si_age(io_si, ipa2) = hio_gpp_si_age(io_si, ipa2) / (patch_area_by_age(ipa2)) hio_npp_si_age(io_si, ipa2) = hio_npp_si_age(io_si, ipa2) / (patch_area_by_age(ipa2)) else @@ -3947,7 +3945,7 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) endif ! Normalize resistance diagnostics - if (canopy_area_by_age(ipa2) .gt. tiny) then + if (canopy_area_by_age(ipa2) .gt. nearzero) then hio_c_stomata_si_age(io_si,ipa2) = & hio_c_stomata_si_age(io_si,ipa2) / canopy_area_by_age(ipa2) @@ -3961,7 +3959,7 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) end do ! Normalize resistance diagnostics - if ( sum(canopy_area_by_age(1:nlevage)) .gt. tiny) then + if ( sum(canopy_area_by_age(1:nlevage)) .gt. nearzero) then hio_c_stomata_si(io_si) = hio_c_stomata_si(io_si) / sum(canopy_area_by_age(1:nlevage)) hio_c_lblayer_si(io_si) = hio_c_lblayer_si(io_si) / sum(canopy_area_by_age(1:nlevage)) else @@ -4003,7 +4001,6 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) integer :: ipa ! The local "I"ndex of "PA"tches integer :: ft ! functional type index ! integer :: io_shsl ! The combined "SH"ell "S"oil "L"ayer index in the IO array - real(r8), parameter :: tiny = 1.e-5_r8 ! some small number real(r8) :: ncohort_scpf(nlevsclass*maxpft) ! Bins to count up cohorts counts used in weighting ! should be "hio_nplant_si_scpf" real(r8) :: nplant_scpf(nlevsclass*maxpft) ! Bins to count up cohorts counts used in weighting From 131a65682a68c72457432081f2822bda4b904b7b Mon Sep 17 00:00:00 2001 From: JunyanDing <43835195+JunyanDing@users.noreply.github.com> Date: Fri, 9 Sep 2022 12:55:52 -0700 Subject: [PATCH 328/852] Update fates_params_default.cdl --- 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 c33aa39485..244c3716f6 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1445,7 +1445,7 @@ data: fates_maintresp_model = 1 ; - fates_mort_disturb_frac = 1 ; + fates_mort_disturb_frac = 0 ; fates_mort_understorey_death = 0.55983 ; From bf99a0b6ba0901411875ce566c8a69d2b507c180 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 13 Sep 2022 10:07:37 -0600 Subject: [PATCH 329/852] use lai instead of treelai for b4b --- biogeochem/EDCanopyStructureMod.F90 | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index b3175202ba..3305d2d857 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1499,7 +1499,8 @@ subroutine leaf_area_profile( currentSite ) real(r8) :: dh ! vertical detph of height class (m) real(r8) :: min_chite ! bottom of cohort canopy (m) real(r8) :: max_chite ! top of cohort canopy (m) - real(r8) :: lai ! summed lai for checking m2 m-2 + real(r8) :: lai ! we use this to preserve b4b right now (m2/m2) + real(r8) :: sai ! "" !---------------------------------------------------------------------- @@ -1552,9 +1553,11 @@ subroutine leaf_area_profile( currentSite ) ! How much of each tree is stem area index? Assuming that there is ! This may indeed be zero if there is a sensecent grass ! ---------------------------------------------------------------- - + lai = currentCohort%treelai * currentCohort%c_area/currentPatch%total_canopy_area + sai = currentCohort%treesai * currentCohort%c_area/currentPatch%total_canopy_area if( (currentCohort%treelai+currentCohort%treesai) > nearzero)then - fleaf = currentCohort%treelai / (currentCohort%treelai + currentCohort%treesai) + !fleaf = currentCohort%treelai / (currentCohort%treelai + currentCohort%treesai) + fleaf = lai / (lai+sai) else fleaf = 0._r8 endif From cdb8fcae592db0ff6ccb557550cbe46ea5790714 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 13 Sep 2022 16:21:54 -0600 Subject: [PATCH 330/852] minor comment updates on lai usage during fleaf --- biogeochem/EDCanopyStructureMod.F90 | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 3305d2d857..0c508edce3 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1499,8 +1499,8 @@ subroutine leaf_area_profile( currentSite ) real(r8) :: dh ! vertical detph of height class (m) real(r8) :: min_chite ! bottom of cohort canopy (m) real(r8) :: max_chite ! top of cohort canopy (m) - real(r8) :: lai ! we use this to preserve b4b right now (m2/m2) - real(r8) :: sai ! "" + real(r8) :: lai ! leaf area per canopy area + real(r8) :: sai ! stem area per canopy area !---------------------------------------------------------------------- @@ -1556,7 +1556,9 @@ subroutine leaf_area_profile( currentSite ) lai = currentCohort%treelai * currentCohort%c_area/currentPatch%total_canopy_area sai = currentCohort%treesai * currentCohort%c_area/currentPatch%total_canopy_area if( (currentCohort%treelai+currentCohort%treesai) > nearzero)then - !fleaf = currentCohort%treelai / (currentCohort%treelai + currentCohort%treesai) + + ! See issue: https://github.com/NGEET/fates/issues/899 + ! fleaf = currentCohort%treelai / (currentCohort%treelai + currentCohort%treesai) fleaf = lai / (lai+sai) else fleaf = 0._r8 From 2ead8aa4a516f5a03e0de0c504682ce45d3dd776 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 15 Sep 2022 12:02:53 -0700 Subject: [PATCH 331/852] update README to correct out of date information --- README.md | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index a7688d60fa..05952078c8 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,9 @@ This repository holds the Functionally Assembled Terrestrial Ecosystem Simulator (FATES). FATES is a numerical terrestrial ecosystem model. Its development and support is primarily supported by the Department of Energy's Office of Science, through the Next Generation Ecosystem Experiment - Tropics ([NGEE-T](https://ngee-tropics.lbl.gov/)) project. -For more information on the FATES model, see our [User's Guide](https://fates-users-guide.readthedocs.io/en/latest/) and [technical documentation](https://fates-docs.readthedocs.io/en/latest/index.html). +For more information on the FATES model, see our [User's Guide](https://fates-users-guide.readthedocs.io/en/latest/) and [technical documentation](https://fates-docs.readthedocs.io/en/latest/index.html). +Please submit any questions you may have to the [FATES Github Discussions board](https://github.com/NGEET/fates/discussions). ## Important Guides: ------------------------------ @@ -21,7 +22,6 @@ For more information on the FATES model, see our [User's Guide](https://fates-us [Code of Conduct](https://github.com/NGEET/fates/blob/master/CODE_OF_CONDUCT.md) - ## Important Note: ------------------------------ @@ -33,13 +33,4 @@ https://github.com/E3SM-Project/E3SM https://github.com/ESCOMP/cesm -## Important Note About Host-Models and Compatible Branches: ------------------------------------------------------------- - -The FATES and E3SM teams maintain compatability of the NGEET/FATES master branch with the **E3SM master** branch. When changes to the FATES API force compatability updates with E3SM, there may be some modest lag time. - -The FATES team maintains compatability of the NGEET/FATES master branch with the **CTSM fates_next_api** branch. Since the FATES team uses this branch for its internal testing, this compatability is tightly (immediately) maintained and these two should always be in sync. However, CTSM master may become out of sync with FATES master for large periods (months) of time. - - - - +The FATES, E3SM and CTSM teams maintain compatability of the NGEET/FATES master branch with the E3SM master and CTSM master branches respectively. There may be some modest lag time in which the latest commit on the FATES master branch is available to these host land models (HLM) by default. This is typically correlated with FATES development updates forcing necessary changes to the FATES API. See the table of [FATES API/HLM compatibility](https://fates-users-guide.readthedocs.io/en/latest/user/Table-of-FATES-API-and-HLM-STATUS.html) for information on which fates tag corresponds to which HLM tag or commit. From eadc8955715f9af5bff9c8217c70945f96c140ea Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 15 Sep 2022 22:16:07 -0400 Subject: [PATCH 332/852] Syntax updates for tree damage mode --- biogeochem/EDCanopyStructureMod.F90 | 5 +- biogeochem/EDPatchDynamicsMod.F90 | 1 - fire/SFMainMod.F90 | 2 - main/EDTypesMod.F90 | 2 +- main/FatesInventoryInitMod.F90 | 8 +- parameter_files/patch_default_bciopt224.xml | 84 ++++++++++----------- 6 files changed, 49 insertions(+), 53 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 6efbbeee93..d3332432e8 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1546,7 +1546,7 @@ subroutine leaf_area_profile( currentSite ) if (currentPatch%total_canopy_area > nearzero ) then - call UpdatePatchLAI(currentPatch, patch_lai, CurrentSite) + call UpdatePatchLAI(currentPatch, patch_lai) if(smooth_leaf_distribution == 1)then @@ -2183,7 +2183,7 @@ end subroutine CanopyLayerArea ! =============================================================================================== - subroutine UpdatePatchLAI(currentPatch, patch_lai, currentSite) + subroutine UpdatePatchLAI(currentPatch, patch_lai) ! -------------------------------------------------------------------------------------------- ! This subroutine works through the current patch cohorts and updates the canopy_layer_tlai @@ -2195,7 +2195,6 @@ subroutine UpdatePatchLAI(currentPatch, patch_lai, currentSite) ! Arguments type(ed_patch_type),intent(inout), target :: currentPatch - type(ed_site_type),intent(inout), target :: currentSite real(r8), intent(inout) :: patch_lai ! Local Variables diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 8f652d541b..833ca3d07d 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -47,7 +47,6 @@ module EDPatchDynamicsMod use FatesInterfaceTypesMod , only : hlm_use_sp use FatesInterfaceTypesMod , only : hlm_use_nocomp use FatesInterfaceTypesMod , only : hlm_use_fixed_biogeog - use FatesInterfaceTypesMod , only : hlm_use_tree_damage use FatesGlobals , only : endrun => fates_endrun use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : itrue, ifalse diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index 7f2c037846..d5cf38d004 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -427,8 +427,6 @@ subroutine rate_of_spread ( currentSite ) SF_val_miner_damp, & SF_val_fuel_energy - use FatesInterfaceTypesMod, only : hlm_current_day, hlm_current_month - type(ed_site_type), intent(in), target :: currentSite type(ed_patch_type), pointer :: currentPatch diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index b7a14a6902..1d4cd39d9f 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -54,7 +54,7 @@ module EDTypesMod integer, parameter, public :: idiffuse = 2 ! This is the array index for diffuse radiation ! parameters that govern the VAI (LAI+SAI) bins used in radiative transfer code - integer, parameter, public :: nlevleaf = 30 ! number of leaf+stem layers in canopy layer + integer, parameter, public :: nlevleaf = 50 ! number of leaf+stem layers in canopy layer real(r8), public :: dinc_vai(nlevleaf) = fates_unset_r8 ! VAI bin widths array real(r8), public :: dlower_vai(nlevleaf) = fates_unset_r8 ! lower edges of VAI bins diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index 5b591716fd..31cc2b07ad 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -1031,17 +1031,19 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & ! Calculate the leaf biomass (calculates a maximum first, then applies canopy trim ! and sla scaling factors) - call bleaf(temp_cohort%dbh,temp_cohort%pft,1,& + call bleaf(temp_cohort%dbh,temp_cohort%pft,temp_cohort%crowndamage,& temp_cohort%canopy_trim,c_leaf) ! Calculate fine root biomass call bfineroot(temp_cohort%dbh,temp_cohort%pft,temp_cohort%canopy_trim,c_fnrt) ! Calculate sapwood biomass - call bsap_allom(temp_cohort%dbh,temp_cohort%pft,1, 1.0_r8,temp_cohort%canopy_trim, a_sapw, c_sapw) + call bsap_allom(temp_cohort%dbh,temp_cohort%pft,temp_cohort%crowndamage, & + temp_cohort%canopy_trim, a_sapw, c_sapw) call bdead_allom( c_agw, c_bgw, c_sapw, temp_cohort%pft, c_struct ) - call bstore_allom(temp_cohort%dbh, temp_cohort%pft, 1, temp_cohort%canopy_trim, c_store) + call bstore_allom(temp_cohort%dbh, temp_cohort%pft, temp_cohort%crowndamage, & + temp_cohort%canopy_trim, c_store) temp_cohort%leafmemory = 0._r8 temp_cohort%sapwmemory = 0._r8 temp_cohort%structmemory = 0._r8 diff --git a/parameter_files/patch_default_bciopt224.xml b/parameter_files/patch_default_bciopt224.xml index bfcc288efa..635f634d11 100644 --- a/parameter_files/patch_default_bciopt224.xml +++ b/parameter_files/patch_default_bciopt224.xml @@ -5,48 +5,46 @@ fates_params_opt224_vmn6phi_080621.cdl 1 - 0 - 0 - 1,1,3,4 - 0.03347526,0.024,1e-08,0.0047 - 0.03347526,0.024,1e-08,0.0047 - 0.025,0,0,0 - 0.45,0.25,0,0 - 0.8012471 - 30.94711 - 0.0673 - 0.976 - -9 - -9 - 3 - 0.1266844 - 1.281329 - -9 - 0.768654 - 0.768654 - 57.6 - 0.74 - 21.6 - 200 - 2 - 5 - 0.4863088 - 3 - 3e-06 - 3e-06 - 3e-07 - 3e-08 - 0.03991654 - 0.01995827 - 0.01303514 - 0.02955703 - 3 - 3 - 0.04680188 - 0.001 - 0.8374751 - -1 - 0.5 - 1 + 0 + 0 + 1,1,3,4 + 0.03347526,0.024,1e-08,0.0047 + 0.45,0.25,0,0 + 0.8012471 + 30.94711 + 0.0673 + 0.976 + -9 + -9 + 3 + 0.1266844 + 1.281329 + -9 + 0.768654 + 0.768654 + 57.6 + 0.74 + 21.6 + 200 + 2 + 5 + 0.4863088 + 3 + 3e-06 + 3e-06 + 3e-07 + 3e-08 + 0.03991654 + 0.01995827 + 0.01303514 + 0.02955703 + 3 + 3 + 0.04680188 + 0.001 + 0.8374751 + -1 + 0.5 + 1 From 32a5a4d7cbd895f76f60b603a2d2619327577bed Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 15 Sep 2022 22:16:33 -0400 Subject: [PATCH 333/852] slight correction to crown damage calc --- biogeochem/EDPhysiologyMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 04783e01c2..540a42e5f9 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -282,10 +282,10 @@ subroutine GenerateDamageAndLitterFluxes( csite, cpatch, bc_in ) ccohort%n = ccohort%n - num_trees_cd ! update crown area here - for cohort fusion and canopy organisation below - call carea_allom(ndcohort%dbh, ndcohort%n, csite%spread,& + call carea_allom(ndcohort%dbh, ndcohort%n, csite%spread, & ipft, ndcohort%crowndamage, ndcohort%c_area) - call GetCrownReduction(cd, crown_loss_frac) + call GetCrownReduction(cd-ccohort%crowndamage, crown_loss_frac) do_element: do el = 1, num_elements From cf912373776756eeab84a32fa66f601cfca86090 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 15 Sep 2022 22:17:08 -0400 Subject: [PATCH 334/852] Fixes to allocation phases vis-a-vis recovery --- main/EDMainMod.F90 | 16 +++++++++------- parteh/PRTAllometricCarbonMod.F90 | 14 ++++++++++---- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index b53efda20e..847962fdb5 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -514,18 +514,19 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! of mass from the oldest bin into the litter pool, that is something else. ! ----------------------------------------------------------------------------------- call currentCohort%prt%AgeLeaves(ft,sec_per_day) - + end if if_not_newlyrecovered - ! If the current diameter of a plant is somehow less than what is consistent ! with what is allometrically consistent with the stuctural biomass, then ! correct the dbh to match. call EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) + ! We want to save these values for the newly recovered cohort as well hite_old = currentCohort%hite dbh_old = currentCohort%dbh + ! ----------------------------------------------------------------------------- ! Growth and Allocation (PARTEH) ! ----------------------------------------------------------------------------- @@ -543,9 +544,8 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! to grow in stature (phase 2) call currentCohort%prt%DailyPRT(phase=1) - - if((newly_recovered .eq. .false.) .and. & - (hlm_use_tree_damage .eq. itrue) ) then + + if((.not.newly_recovered) .and. (hlm_use_tree_damage .eq. itrue) ) then ! The loop order is shortest to tallest ! The recovered cohort (ie one with larger targets) ! is newly created in DamageRecovery(), and @@ -560,14 +560,16 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! the cohort is NOT split, and the whole thing graduates to a lesser ! damage class if(.not.newly_recovered)then - call currentCohort%prt%DailyPRT(phase=1) + call currentCohort%prt%DailyPRT(phase=2) end if else newly_recovered = .false. end if + + !print*,"CD:",currentcohort%crowndamage - call currentCohort%prt%DailyPRT(phase=2) + call currentCohort%prt%DailyPRT(phase=3) ! Update the mass balance tracking for the daily nutrient uptake flux ! Then zero out the daily uptakes, they have been used diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 56f8c8e1f4..53f20a1538 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -474,7 +474,7 @@ subroutine DailyPRTAllometricCarbon(this,phase) ! Phase 1: Replace losses, push pools towards targets ! ----------------------------------------------------------------------------------- - if_phase: if(phase.eq.1) then + if_phase1: if(phase.eq.1) then ! III. Prioritize some amount of carbon to replace leaf/root turnover ! Make sure it isn't a negative payment, and either pay what is available @@ -544,6 +544,11 @@ subroutine DailyPRTAllometricCarbon(this,phase) end if + end if if_phase1 + + + if_phase12: if((phase==1) .or. (phase==2))then + ! ----------------------------------------------------------------------------------- ! V. If carbon is still available, prioritize some allocation to replace ! the rest of the leaf/fineroot deficit @@ -628,8 +633,9 @@ subroutine DailyPRTAllometricCarbon(this,phase) end if end if - - elseif( (phase.eq.2) .and. ( carbon_balance > calloc_abs_error )) then + end if if_phase12 + + if_phase3: if( (phase.eq.3) .and. ( carbon_balance > calloc_abs_error )) then ! ----------------------------------------------------------------------------------- ! VIII. If carbon is yet still available ... @@ -850,7 +856,7 @@ subroutine DailyPRTAllometricCarbon(this,phase) end do do_solve_check - end if if_phase + end if if_phase3 ! Track the net allocations and transport from this routine ! (the AgeLeaves() routine handled tracking allocation through aging) From dc3e5f433024c5a8e8f31352c834a2a3fb4f711f Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 16 Sep 2022 15:11:04 -0400 Subject: [PATCH 335/852] Subtle fixes to the allocation phasing and damage --- biogeochem/EDCohortDynamicsMod.F90 | 17 ++--------------- main/EDMainMod.F90 | 16 +++++----------- 2 files changed, 7 insertions(+), 26 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 2cf8b4a5f0..e43942b0b8 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -2341,24 +2341,11 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) max_recover_nplant = available_m * ccohort%n / recovery_demand ! 4. Use the scalar to decide how many to recover - nplant_recover = min(nplant_recover,max(0._r8,max_recover_nplant * & - EDPftvarcon_inst%damage_recovery_scalar(ipft) )) + nplant_recover = min(nplant_recover,min(ccohort%n,max(0._r8,max_recover_nplant * & + EDPftvarcon_inst%damage_recovery_scalar(ipft) ))) end do - ! there is a special case where damage_recovery_scalar = 1, but - ! max_recover_nplant > n (i.e. there is more carbon than needed for all - ! individuals to recover to the next damage class. - ! in this case we can cheat, by making n_recover 0 and simply - ! allowing the donor cohort to recover and then go through - ! prt - will this work though? if they are not anywhere near allometry? - - if( abs(EDPftvarcon_inst%damage_recovery_scalar(ipft)-1._r8) < nearzero .and. & - nplant_recover > ccohort%n) then - nplant_recover = 0.0_r8 - ccohort%crowndamage = ccohort%crowndamage - 1 - end if - if(nplant_recover < nearzero) then newly_recovered = .false. diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 847962fdb5..93970bc888 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -543,8 +543,12 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! The first phase of allocation. Both cohorts have the opportunity (if resources remain) ! to grow in stature (phase 2) - call currentCohort%prt%DailyPRT(phase=1) + if(.not.newly_recovered)then + call currentCohort%prt%DailyPRT(phase=1) + end if + call currentCohort%prt%DailyPRT(phase=2) + if((.not.newly_recovered) .and. (hlm_use_tree_damage .eq. itrue) ) then ! The loop order is shortest to tallest ! The recovered cohort (ie one with larger targets) @@ -555,20 +559,10 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! needed for diagnostics call DamageRecovery(currentSite,currentPatch,currentCohort,newly_recovered) - ! New targets may have been issued (based on damage status). If so, - ! we need to repeat phase 1 of allocation. This only happens if - ! the cohort is NOT split, and the whole thing graduates to a lesser - ! damage class - if(.not.newly_recovered)then - call currentCohort%prt%DailyPRT(phase=2) - end if - else newly_recovered = .false. end if - !print*,"CD:",currentcohort%crowndamage - call currentCohort%prt%DailyPRT(phase=3) ! Update the mass balance tracking for the daily nutrient uptake flux From d5e9ad456c475cb63313c673ee6af3721aad3e25 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 16 Sep 2022 15:17:21 -0400 Subject: [PATCH 336/852] Fixes, yet again, to allocation and phasing --- main/EDMainMod.F90 | 18 ++++++++---------- parteh/PRTAllometricCarbonMod.F90 | 4 ++-- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 93970bc888..681645a71b 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -532,16 +532,14 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! ----------------------------------------------------------------------------- ! We split the allocation into phases (currently for all hypotheses) - ! In phase 1, allocation gets the mass of organs to match targets - ! In phase 2, allocation increases the mass of organs along with stature growth (dbh) - ! The reason why we split is to accomodate the damage code. Following phase 1, - ! we will allow the damage status of the cohorts to potentially recover, if they - ! have any left-over C/N/P resources. In this process, the cohort will be split - ! into two, each having a number count summing to the original. Where one cohort - ! will remain in the original damage class proceed with allocation, and the other - ! will reduce its damage class with new mass tarets. The latter will have to re-play - ! The first phase of allocation. Both cohorts have the opportunity (if resources remain) - ! to grow in stature (phase 2) + ! In phase 1, allocation, we address prioritized allocation that should + ! only happen once per day, this is only allocation that does not grow stature. + ! In phase 2, allocation , we address allocation that can be performed + ! as many times as necessary. This is allocation that does not contain stature + ! growth. This is separate from phase 1, because some recovering plants + ! will have new allocation targets that need to be updated after they change status. + ! In Phase 3, we assume that the plant has reached its targets, and any + ! left-over resources are used to grow the stature of the plant if(.not.newly_recovered)then call currentCohort%prt%DailyPRT(phase=1) diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 53f20a1538..be4b2bbdff 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -547,7 +547,7 @@ subroutine DailyPRTAllometricCarbon(this,phase) end if if_phase1 - if_phase12: if((phase==1) .or. (phase==2))then + if_phase2: if(phase.eq.2)then ! ----------------------------------------------------------------------------------- ! V. If carbon is still available, prioritize some allocation to replace @@ -633,7 +633,7 @@ subroutine DailyPRTAllometricCarbon(this,phase) end if end if - end if if_phase12 + end if if_phase2 if_phase3: if( (phase.eq.3) .and. ( carbon_balance > calloc_abs_error )) then From 38d9f3292d8f097c0502e5745cbfa0dbb667f6aa Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Fri, 16 Sep 2022 13:30:21 -0700 Subject: [PATCH 337/852] Changes to sapwood respiration to account for aboveground damage. --- biogeochem/DamageMainMod.F90 | 3 +- biogeophys/FatesPlantRespPhotosynthMod.F90 | 45 ++++++++++++++++++---- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/biogeochem/DamageMainMod.F90 b/biogeochem/DamageMainMod.F90 index 41e32ef59d..227c97f795 100644 --- a/biogeochem/DamageMainMod.F90 +++ b/biogeochem/DamageMainMod.F90 @@ -156,8 +156,7 @@ subroutine GetDamageFrac(cc_cd, nc_cd, pft, dist_frac) integer, intent(in) :: pft real(r8), intent(out) :: dist_frac ! probability of current cohort moving to new damage level - dist_frac = param_derived%damage_transitions(cc_cd, nc_cd, pft) !* years_per_day - ! (if damage is occuring annually don't do this) + dist_frac = param_derived%damage_transitions(cc_cd, nc_cd, pft) end subroutine GetDamageFrac diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index e3286d7b00..7e9e29b5e5 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -248,10 +248,12 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) real(r8) :: agb_frac ! fraction of biomass aboveground real(r8) :: branch_frac ! fraction of aboveground woody biomass in branches real(r8) :: crown_reduction ! reduction in crown biomass from damage - real(r8) :: sapw_c_predamage ! pre damage sapwood - real(r8) :: sapw_n ! sapwood n - real(r8) :: sapw_n_predamage ! pre damage sapwood n - + real(r8) :: sapw_c_bgw ! belowground sapwood + real(r8) :: sapw_c_agw ! aboveground sapwood + real(r8) :: sapw_n ! sapwood nitrogen + real(r8) :: sapw_n_bgw ! nitrogen in belowground portion of sapwood + real(r8) :: sapw_n_agw ! nitrogen in aboveground portion of sapwood + ! ----------------------------------------------------------------------------------- ! Keeping these two definitions in case they need to be added later ! @@ -280,6 +282,8 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! Photosynthesis and stomatal conductance parameters, from: ! Bonan et al (2011) JGR, 116, doi:10.1029/2010JG001593 ! ----------------------------------------------------------------------------------- + + associate( & c3psn => EDPftvarcon_inst%c3psn , & @@ -653,15 +657,23 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) + if (hlm_use_tree_damage .eq. itrue) then + + ! Crown damage currenly only reduces the aboveground portion of + ! sapwood. Therefore we calculate the aboveground and the belowground portion + ! sapwood for use in stem respiration. agb_frac = prt_params%allom_agb_frac(currentCohort%pft) branch_frac = param_derived%branch_frac(currentCohort%pft) call GetCrownReduction(currentCohort%crowndamage, crown_reduction) - ! need the undamaged version if using ratios with roots - sapw_c = sapw_c / & + ! Undamaged below ground portion + sapw_c_bgw = sapw_c / & (1.0_r8 - (agb_frac * branch_frac * (1.0_r8-crown_reduction))) + ! Damaged aboveground portion + sapw_c_agw = sapw_c - sapw_c_bgw + end if @@ -669,10 +681,10 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) case (prt_carbon_allom_hyp) live_stem_n = prt_params%allom_agb_frac(currentCohort%pft) * & - sapw_c * prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) + sapw_c_agw * prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) live_croot_n = (1.0_r8-prt_params%allom_agb_frac(currentCohort%pft)) * & - sapw_c * prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) + sapw_c_bgw * prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) fnrt_n = fnrt_c * prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)) @@ -684,8 +696,25 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) live_croot_n = (1.0_r8-prt_params%allom_agb_frac(currentCohort%pft)) * & currentCohort%prt%GetState(sapw_organ, nitrogen_element) + fnrt_n = currentCohort%prt%GetState(fnrt_organ, nitrogen_element) + if (hlm_use_tree_damage .eq. itrue) then + + sapw_n = currentCohort%prt%GetState(sapw_organ, nitrogen_element) + + sapw_n_bgw = sapw_n / & + (1.0_r8 - (agb_frac * branch_frac * (1.0_r8 - crown_reduction))) + sapw_n_agw = sapw_n - sapw_n_bgw + + live_croot_n = (1.0_r8-prt_params%allom_agb_frac(currentCohort%pft)) * & + sapw_n_bgw + + live_stem_n = prt_params%allom_agb_frac(currentCohort%pft) * & + sapw_n_agw + + end if + ! If one wants to break coupling with dynamic N conentrations, ! use the stoichiometry parameter ! From 6fc3bef30fd454fa3859258069319ef475b6a058 Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Sat, 17 Sep 2022 08:23:55 -0700 Subject: [PATCH 338/852] Fix the sapwood respiration bug --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 7e9e29b5e5..b4b3dabaa0 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -250,9 +250,11 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) real(r8) :: crown_reduction ! reduction in crown biomass from damage real(r8) :: sapw_c_bgw ! belowground sapwood real(r8) :: sapw_c_agw ! aboveground sapwood + real(r8) :: sapw_c_undamaged ! the target sapwood of an undamaged tree real(r8) :: sapw_n ! sapwood nitrogen real(r8) :: sapw_n_bgw ! nitrogen in belowground portion of sapwood real(r8) :: sapw_n_agw ! nitrogen in aboveground portion of sapwood + real(r8) :: sapw_n_undamaged ! nitrogen in sapwood of undamaged tree ! ----------------------------------------------------------------------------------- ! Keeping these two definitions in case they need to be added later @@ -668,9 +670,11 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) branch_frac = param_derived%branch_frac(currentCohort%pft) call GetCrownReduction(currentCohort%crowndamage, crown_reduction) - ! Undamaged below ground portion - sapw_c_bgw = sapw_c / & + sapw_c_undamaged = sapw_c / & (1.0_r8 - (agb_frac * branch_frac * (1.0_r8-crown_reduction))) + ! Undamaged below ground portion + sapw_c_bgw = sapw_c_undamaged * (1.0_r8 - agb_frac) + ! Damaged aboveground portion sapw_c_agw = sapw_c - sapw_c_bgw @@ -703,8 +707,10 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) sapw_n = currentCohort%prt%GetState(sapw_organ, nitrogen_element) - sapw_n_bgw = sapw_n / & + sapw_n_undamaged = sapw_n / & (1.0_r8 - (agb_frac * branch_frac * (1.0_r8 - crown_reduction))) + + sapw_n_bgw = sapw_n_undamaged * (1.0_r8 - agb_frac) sapw_n_agw = sapw_n - sapw_n_bgw live_croot_n = (1.0_r8-prt_params%allom_agb_frac(currentCohort%pft)) * & From c955cf182eb111a0ab9c5c7dedacd27e4fce76e2 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 20 Sep 2022 14:35:56 -0400 Subject: [PATCH 339/852] Slight update to allow FATES CNP to work with new phased allocation, albeit not compatible with tree damage --- parteh/PRTAllometricCNPMod.F90 | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 6170a7ae2e..d640797e6f 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -389,11 +389,12 @@ subroutine DailyPRTAllometricCNP(this,phase) real(r8) :: sum_c ! error checking sum - ! We do not use damage with parteh_mode 2, so just - ! do everything in phase 1 and short-circuit the phase 2 call - ! ---------------------------------------------------------- - if(phase.eq.2) return - + ! Right now FATES CNP is not compatable with tree damage + ! only simulate calls for phase 1 (ie call this once) + ! Compatability will be enabled with PR #880 + + if(phase>1)return + ! integrator variables @@ -511,6 +512,7 @@ subroutine DailyPRTAllometricCNP(this,phase) call endrun(msg=errMsg(sourcefile, __LINE__)) end if + ! =================================================================================== ! Step 2. Grow out the stature of the plant by allocating to tissues beyond ! current targets. @@ -626,7 +628,7 @@ end subroutine DailyPRTAllometricCNP ! ===================================================================================== - subroutine CNPPrioritizedReplacement(this, & + subroutine CNPPrioritizedReplacement(this, & maint_r_deficit, c_gain, n_gain, p_gain, & state_c, state_n, state_p, target_c) @@ -698,8 +700,11 @@ subroutine CNPPrioritizedReplacement(this, & ! If it is, then we track the variable ids associated with that pool for each CNP ! species. It "should" work fine if there are NO priority=1 pools... ! ----------------------------------------------------------------------------------- + + curpri_org(:) = fates_unset_int ! reset "current-priority" organ ids + i = 0 do ii = 1, num_organs @@ -843,9 +848,8 @@ subroutine CNPPrioritizedReplacement(this, & state_c(store_id)%ptr = state_c(store_id)%ptr + store_c_flux - end if + end if - ! ----------------------------------------------------------------------------------- ! If carbon is still available, allocate to remaining high ! carbon balance is guaranteed to be >=0 beyond this point From ae40104e214c8d797b2dc146f89da585bcc2b2d6 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 20 Sep 2022 14:41:38 -0400 Subject: [PATCH 340/852] Added user name checks for damage mode and parteh 2 --- main/FatesInterfaceMod.F90 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index b73b378aa0..07b8375cdc 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1536,6 +1536,14 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) if(hlm_use_tree_damage .eq. unset_int) then write(fates_log(),*) 'FATES dimension/parameter unset: hlm_use_tree_damage, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) + else + if((hlm_use_tree_damage .eq. itrue) .and. & + (hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp))then + write(fates_log(),*) 'FATES tree damage is not (yet) compatible with CNP allocation (fates_parteh_mode = 2)' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + end if if(hlm_nitrogen_spec .eq. unset_int) then From 2b064f02309c839b214a37917ec35104a1c51dff Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 20 Sep 2022 14:50:35 -0400 Subject: [PATCH 341/852] Updated error statement for fates cnp and tree damage --- main/FatesInterfaceMod.F90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 07b8375cdc..ea18390877 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1539,7 +1539,8 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) else if((hlm_use_tree_damage .eq. itrue) .and. & (hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp))then - write(fates_log(),*) 'FATES tree damage is not (yet) compatible with CNP allocation (fates_parteh_mode = 2)' + write(fates_log(),*) 'FATES tree damage (use_fates_tree_damage = .true.) is not' + write(fates_log(),*) '(yet) compatible with CNP allocation (fates_parteh_mode = 2)' call endrun(msg=errMsg(sourcefile, __LINE__)) end if From f99840782a4b080ceba423cd5bfb1b2040a95624 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 20 Sep 2022 20:17:16 -0400 Subject: [PATCH 342/852] reverting nlevleaf --- main/EDTypesMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index e58fecdb25..071b54f424 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -54,7 +54,7 @@ module EDTypesMod integer, parameter, public :: idiffuse = 2 ! This is the array index for diffuse radiation ! parameters that govern the VAI (LAI+SAI) bins used in radiative transfer code - integer, parameter, public :: nlevleaf = 50 ! number of leaf+stem layers in canopy layer + integer, parameter, public :: nlevleaf = 30 ! number of leaf+stem layers in canopy layer real(r8), public :: dinc_vai(nlevleaf) = fates_unset_r8 ! VAI bin widths array real(r8), public :: dlower_vai(nlevleaf) = fates_unset_r8 ! lower edges of VAI bins From 8df96ae17d830cf3f7fe0b9c38dbb7eb8d30a020 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 20 Sep 2022 21:46:44 -0400 Subject: [PATCH 343/852] various code modifications while exploring PID functions --- biogeochem/EDCanopyStructureMod.F90 | 6 + biogeochem/EDPhysiologyMod.F90 | 1 - biogeophys/FatesPlantRespPhotosynthMod.F90 | 3 +- main/EDMainMod.F90 | 31 ++--- parteh/PRTAllometricCNPMod.F90 | 134 ++++++++++++--------- 5 files changed, 98 insertions(+), 77 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 9bae9e6a35..a683ef8a11 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -720,6 +720,12 @@ subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr,bc_in) end if ! kill the ones which go into canopy layers that are not allowed + + ! USE THIS OVERRIDE IF YOU ARE FORCING A ONE COHORT SIMULATION + ! (also make sure to turn off germination, external seed rain, + ! (use only one PFT, and make sure disturb_frac is 0) + ! (RGK-0822) + !if(currentCohort%canopy_layer>1) then if(currentCohort%canopy_layer>nclmax )then ! put the litter from the terminated cohorts diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 2573dae56e..6e3a1a8bd0 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -751,7 +751,6 @@ subroutine phenology( currentSite, bc_in ) ! continues monotonically, indefinitely model_day_int = nint(hlm_model_day) - ! Use the following layer index to calculate drought conditions ilayer_swater = minloc(abs(bc_in%z_sisl(:)-dphen_soil_depth),dim=1) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 80228bb582..32fa3c04ec 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -346,6 +346,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! CO2 compensation point (Pa) ! leaf boundary layer conductance of h20 ! constrained vapor pressure + call GetCanopyGasParameters(bc_in(s)%forc_pbot, & ! in bc_in(s)%oair_pa(ifp), & ! in bc_in(s)%t_veg_pa(ifp), & ! in @@ -2127,7 +2128,7 @@ subroutine lowstorage_maintresp_reduction(frac, pft, maintresp_reduction_factor) ! --------------------------------------------------------------------------------- if( frac .lt. 1._r8 )then - if ( EDPftvarcon_inst%maintresp_reduction_curvature(pft) .ne. 1._r8 ) then + if ( abs(EDPftvarcon_inst%maintresp_reduction_curvature(pft)-1._r8) > nearzero ) then maintresp_reduction_factor = (1._r8 - EDPftvarcon_inst%maintresp_reduction_intercept(pft)) + & EDPftvarcon_inst%maintresp_reduction_intercept(pft) * & (1._r8 - EDPftvarcon_inst%maintresp_reduction_curvature(pft)**frac) & diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 0e527e83e5..fd3fe332d6 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -431,7 +431,6 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentCohort%gpp_acc_hold = currentCohort%gpp_acc * real(hlm_days_per_year,r8) currentCohort%resp_acc_hold = currentCohort%resp_acc * real(hlm_days_per_year,r8) - ! Conduct Maintenance Turnover (parteh) if(debug) call currentCohort%prt%CheckMassConservation(ft,3) if(any(currentSite%dstatus == [phen_dstat_moiston,phen_dstat_timeon])) then @@ -470,18 +469,18 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) call EffluxIntoLitterPools(currentSite, currentPatch, currentCohort, bc_in ) - - - - ! Mass balance for N uptake - currentSite%mass_balance(element_pos(nitrogen_element))%net_root_uptake = & - currentSite%mass_balance(element_pos(nitrogen_element))%net_root_uptake + & - (currentCohort%daily_n_gain-currentCohort%daily_n_efflux)*currentCohort%n - - ! Mass balance for P uptake - currentSite%mass_balance(element_pos(phosphorus_element))%net_root_uptake = & - currentSite%mass_balance(element_pos(phosphorus_element))%net_root_uptake + & - (currentCohort%daily_p_uptake-currentCohort%daily_p_efflux)*currentCohort%n + if(element_pos(nitrogen_element)>0) then + ! Mass balance for N uptake + currentSite%mass_balance(element_pos(nitrogen_element))%net_root_uptake = & + currentSite%mass_balance(element_pos(nitrogen_element))%net_root_uptake + & + (currentCohort%daily_n_gain-currentCohort%daily_n_efflux)*currentCohort%n + end if + if(element_pos(phosphorus_element)>0) then + ! Mass balance for P uptake + currentSite%mass_balance(element_pos(phosphorus_element))%net_root_uptake = & + currentSite%mass_balance(element_pos(phosphorus_element))%net_root_uptake + & + (currentCohort%daily_p_uptake-currentCohort%daily_p_efflux)*currentCohort%n + end if ! mass balance for C efflux (if any) currentSite%mass_balance(element_pos(carbon12_element))%net_root_uptake = & @@ -556,8 +555,10 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! Update history diagnostics related to Nutrients (if any) ! ----------------------------------------------------------------------------- - - call fates_hist%update_history_nutrflux(currentSite) + select case(hlm_parteh_mode) + case (prt_cnp_flex_allom_hyp) + call fates_hist%update_history_nutrflux(currentSite) + end select ! When plants die, the water goes with them. This effects ! the water balance. diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index e79c63ab6d..21c4544a41 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -107,8 +107,8 @@ module PRTAllometricCNPMod integer, parameter, private :: pid_spe_controller = storage_spe - real(r8), parameter, private :: pid_int_wgt = 1._r8/10._r8 ! n-day smoothing (K on the integral of PID) - real(r8), parameter, private :: pid_drv_wgt = 1._r8/10._r8 ! n-day smoothing (K on the derivative of PID) + real(r8), parameter, private :: pid_int_wgt = 1._r8/1._r8 ! n-day smoothing (K on the integral of PID) + real(r8), parameter, private :: pid_drv_wgt = 1._r8/20._r8 ! n-day smoothing (K on the derivative of PID) ! Global identifiers for the two stoichiometry values integer,public, parameter :: stoich_growth_min = 1 ! Flag for stoichiometry associated with @@ -504,35 +504,21 @@ subroutine DailyPRTAllometricCNP(this,co_num,nplant) n_efflux => this%bc_out(acnp_bc_out_id_nefflux)%rval; n_efflux = 0._r8 p_efflux => this%bc_out(acnp_bc_out_id_pefflux)%rval; p_efflux = 0._r8 - ! Bring storage pools down to the first target put overflow into gain pools - store_flux = max(0._r8, this%variables(store_c_id)%val(1) - target_c(store_organ)) - c_gain = c_gain + store_flux - this%variables(store_c_id)%val(1) = this%variables(store_c_id)%val(1) - store_flux - target_n = this%GetNutrientTarget(nitrogen_element,store_organ,stoich_growth_min) - store_flux = max(0._r8, this%variables(store_n_id)%val(1) - target_n) - n_gain = n_gain + store_flux - this%variables(store_n_id)%val(1) = this%variables(store_n_id)%val(1) - store_flux - target_p = this%GetNutrientTarget(phosphorus_element,store_organ,stoich_growth_min) - store_flux = max(0._r8, this%variables(store_p_id)%val(1) - target_p) - p_gain = p_gain + store_flux - this%variables(store_p_id)%val(1) = this%variables(store_p_id)%val(1) - store_flux - ! =================================================================================== ! Step 0. Transfer all stored nutrient into the daily uptake pool. Also ! transfer C storage that is above the target (ie transfer overflow) ! =================================================================================== ! Put overflow storage into the net daily pool - !store_flux = max(0._r8, this%variables(store_c_id)%val(1) - target_c(store_organ)) - !c_gain = c_gain + store_flux - !this%variables(store_c_id)%val(1) = this%variables(store_c_id)%val(1) - store_flux + store_flux = max(0._r8, this%variables(store_c_id)%val(1) - target_c(store_organ)) + c_gain = c_gain + store_flux + this%variables(store_c_id)%val(1) = this%variables(store_c_id)%val(1) - store_flux n_gain = n_gain + sum(this%variables(store_n_id)%val(:)) this%variables(store_n_id)%val(:) = 0._r8 p_gain = p_gain + sum(this%variables(store_p_id)%val(:)) this%variables(store_p_id)%val(:) = 0._r8 - ! =================================================================================== @@ -707,6 +693,24 @@ subroutine DailyPRTAllometricCNP(this,co_num,nplant) return end subroutine DailyPRTAllometricCNP + + function SafeLog(val) result(logval) + + ! The log functions used to transform storage ratios + ! need not be large. Even a ratio of 10 is sending a strong signal to the + ! root adaptation algorithm to change course pretty strongly. We set + ! bounds of e3 here to prevent numerical overflows and underflows + + real(r8) :: val + real(r8) :: logval + real(r8), parameter :: safelog_min = 0.001_r8 !Don't pass anything smaller to a log + real(r8), parameter :: safelog_max = 1000._r8 + + logval = log(max(safelog_min,min(safelog_max,val))) + + end function SafeLog + + ! ===================================================================================== subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) @@ -735,7 +739,7 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) real(r8) :: logi_k real(r8) :: l2fr_mult real(r8) :: l2fr_delta - real(r8) :: nc_ratio, pc_ratio + real(r8) :: cn_ratio, cp_ratio real(r8) :: dxcdt_ratio ! log change (derivative) of the maximum of the N/C and P/C storage ratio real(r8) :: xc_ratio ! log Maximum of the N/C and P/C storage ratio real(r8), pointer :: ema_xc ! The exponential moving average of the N-or-P versus C PID error function @@ -745,6 +749,7 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) real(r8), parameter :: max_l2fr_cgain_frac = 0.99_r8 real(r8), parameter :: xc_ratio_correction = 1.0_r8 + integer, parameter :: pid_c_function = 0 integer, parameter :: pid_n_function = 1 integer, parameter :: pid_minnc_function = 2 @@ -758,8 +763,9 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) ! Note the strength of the derivative is should be about half of the period ! for an oscillation when turned off, to balance the K_p and K_i terms. ! This will have to be tuned in a sequence of 1, 10, 100, etc... - real(r8) :: l2fr_deriv_scale != 200._r8 - real(r8) :: l2fr_int_scale + real(r8) :: pid_k_i ! Integral scaling coefficient in PID + real(r8) :: pid_k_d ! Derivative scaling coefficient in PID + real(r8) :: pid_k_p ! Proportional scaling coefficient in PID ! If we do not have leaves out, then the relative nutrient vs carbon ! balancing is meaningless, just leave this routine @@ -791,10 +797,11 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) store_nut_max = this%GetNutrientTarget(nitrogen_element,store_organ,stoich_growth_min) - store_nut_act = this%GetState(store_organ, nitrogen_element) + & - this%bc_inout(acnp_bc_inout_id_netdn)%rval + store_nut_act = max(0.001_r8*store_nut_max, & + this%GetState(store_organ, nitrogen_element) + & + this%bc_inout(acnp_bc_inout_id_netdn)%rval) - select case(nint(EDPftvarcon_inst%dev_arbitrary_pft(ipft))) + select case(pid_ncratio_function) !nint(EDPftvarcon_inst%dev_arbitrary_pft(ipft)) ) case(pid_c_function) n_ratio = store_c_max/store_c_act case(pid_n_function) @@ -806,16 +813,16 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) n_ratio = (store_nut_act/store_nut_max) end if case(pid_alogmaxnc_function) - if( abs(log(store_nut_act/store_nut_max)) < abs(log(store_c_act/store_c_max))) then + if( abs(SafeLog(store_nut_act/store_nut_max)) < abs(SafeLog(store_c_act/store_c_max))) then n_ratio = (store_c_max/store_c_act) else n_ratio = (store_nut_act/store_nut_max) end if case(pid_ncratio_function) - n_ratio = (store_nut_act/store_nut_max)/(store_c_act/store_c_max) + n_ratio = (store_c_act/store_c_max)/(store_nut_act/store_nut_max) end select - nc_ratio = (store_nut_act/store_nut_max)/(store_c_act/store_c_max) + cn_ratio = (store_c_act/store_c_max)/(store_nut_act/store_nut_max) else n_ratio = -1._r8 @@ -828,10 +835,11 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) store_nut_max = this%GetNutrientTarget(phosphorus_element,store_organ,stoich_growth_min) - store_nut_act = this%GetState(store_organ, phosphorus_element) + & - this%bc_inout(acnp_bc_inout_id_netdp)%rval + store_nut_act = max(0.001_r8*store_nut_max, & + this%GetState(store_organ, phosphorus_element) + & + this%bc_inout(acnp_bc_inout_id_netdp)%rval) - select case(nint(EDPftvarcon_inst%dev_arbitrary_pft(ipft))) + select case(pid_ncratio_function) !nint(EDPftvarcon_inst%dev_arbitrary_pft(ipft))) case(pid_c_function) p_ratio = store_c_max/store_c_act case(pid_n_function) @@ -843,16 +851,16 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) p_ratio = (store_nut_act/store_nut_max) end if case(pid_alogmaxnc_function) - if( abs(log(store_nut_act/store_nut_max)) < abs(log(store_c_act/store_c_max))) then + if( abs(SafeLog(store_nut_act/store_nut_max)) < abs(SafeLog(store_c_act/store_c_max))) then p_ratio = (store_c_max/store_c_act) else p_ratio = (store_nut_act/store_nut_max) end if case(pid_ncratio_function) - p_ratio = (store_nut_act/store_nut_max)/(store_c_act/store_c_max) + p_ratio = (store_c_act/store_c_max)/(store_nut_act/store_nut_max) end select - pc_ratio = (store_nut_act/store_nut_max)/(store_c_act/store_c_max) + cp_ratio = (store_c_act/store_c_max)/(store_nut_act/store_nut_max) else p_ratio = -1._r8 @@ -866,12 +874,28 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) return else - xc_ratio = log(min(n_ratio,p_ratio)) + xc_ratio = SafeLog(max(n_ratio,p_ratio)) - dxcdt_ratio = xc_ratio-xc0 + ! If xc_ratio has just crossed zero, then + ! reset the integrator. This will be true if + ! the sign of the current ratio is different than + ! the sign of the previous - ema_xc = pid_int_wgt*xc_ratio + (1._r8-pid_int_wgt)*ema_xc + if( (xc_ratio/abs(xc_ratio) - xc0/abs(xc0)) > nearzero ) then + ema_xc = xc_ratio + else + ema_xc = ema_xc + xc_ratio + end if + + dxcdt_ratio = xc_ratio-xc0 + + !ema_xc = pid_int_wgt*xc_ratio + (1._r8-pid_int_wgt)*ema_xc ema_dxcdt = pid_drv_wgt*dxcdt_ratio + (1._r8-pid_drv_wgt)*ema_dxcdt + + + !ema_xc = (1._r8/EDPftvarcon_inst%dev_arbitrary_pft(ipft))*xc_ratio + & + ! (1._r8-(1._r8/EDPftvarcon_inst%dev_arbitrary_pft(ipft)))*ema_xc + xc0 = xc_ratio @@ -926,30 +950,15 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) l2fr_delta_scale = (1._r8/prt_params%fnrt_adapt_tscale(ipft))/log(2.0_r8) - ! log(2.0_r8)*l2fr_delta_scale = (1._r8/prt_params%fnrt_adapt_tscale(ipft)) - - ! ema_xc is already in log form to allow for averaging - ! Want the derivative to be strongest when storage is most disproportionate - l2fr_deriv_scale = 0.0_r8 !-20.0_r8 !0.25*abs(ema_xc/ema_dxcdt) - l2fr_int_scale = 0.0_r8 - - - ! To limit overshoot, when either positive and decending or negative and ascending - ! we have already corrected enough to change the behavior, lets - ! decrease the scaling - - if( ((ema_xc > 0._r8) .and. (ema_dxcdt<0._r8)) .or. ((ema_xc < 0._r8) .and. (ema_dxcdt>0._r8))) then - l2fr_delta_scale = 0.1_r8 * l2fr_delta_scale - sup_flag = 1 - else - sup_flag = 0 - end if - + pid_k_d = prt_params%fnrt_adapt_tscale(ipft) !-0.1_r8 + pid_k_i = 0.0_r8 !EDPftvarcon_inst%dev_arbitrary_pft(ipft) !-0.0001_r8 + pid_k_p = EDPftvarcon_inst%dev_arbitrary_pft(ipft) !0.0005_r8 - !l2fr_delta = -l2fr_delta_scale*(min(0.2,max(-0.2,xc_ratio)) + ema_xc*l2fr_int_scale + ema_dxcdt*l2fr_deriv_scale) - l2fr_delta = -l2fr_delta_scale*(xc_ratio + ema_xc*l2fr_int_scale + ema_dxcdt*l2fr_deriv_scale) + l2fr_delta = pid_k_p*xc_ratio + pid_k_i*ema_xc + pid_k_d*ema_dxcdt + !l2fr_delta = ema_xc/abs(ema_xc)*l2fr_int_scale + ema_dxcdt*l2fr_deriv_scale + ! Cap growth and shrinkage to avoid large changes ! (currently capping at projected rate for a 2:1 ratio l2fr_delta_minmax = l2fr_delta_scale*log(20.0) @@ -968,7 +977,8 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) l2fr = max(l2fr_min, l2fr + l2fr_delta ) - if(co_num==1) print*,'AAX1',co_num,hlm_current_year,hlm_day_of_year,dbh,nplant,sup_flag,log(nc_ratio),l2fr + !if((co_num==1) .or. (co_num==2)) print*,'AAX1',co_num,hlm_current_year,hlm_day_of_year, & + ! dbh,nplant,(store_c_act/store_c_max),cn_ratio,SafeLog(cn_ratio),l2fr else @@ -977,6 +987,7 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) end if + ! Find the updated target fineroot biomass call bfineroot(dbh,ipft,canopy_trim, l2fr, target_c(fnrt_organ),target_dcdd(fnrt_organ)) @@ -2036,8 +2047,11 @@ subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & xc_ratio = 1.0_r8 end if + dxcdt_ratio = log(xc_ratio)-xc0 ema_xc = pid_int_wgt*log(xc_ratio) + (1._r8-pid_int_wgt)*ema_xc - + ema_dxcdt = pid_drv_wgt*dxcdt_ratio + (1._r8-pid_drv_wgt)*ema_dxcdt + xc0 = log(xc_ratio) + end if From 75a771082759d2fdf9dcd125260c486c8be368c3 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 21 Sep 2022 22:24:07 -0400 Subject: [PATCH 344/852] Updating parameter names to include PID. Cleaning up parteh CNP code --- parameter_files/fates_params_default.cdl | 29 +- parameter_files/patch_default_bciopt224.xml | 5 +- parteh/PRTAllometricCNPMod.F90 | 335 ++++++-------------- parteh/PRTParametersMod.F90 | 9 +- parteh/PRTParamsFATESMod.F90 | 30 +- 5 files changed, 141 insertions(+), 267 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 3028fcb968..5cc5cbbbfa 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -44,9 +44,6 @@ variables: char fates_prt_organ_name(fates_prt_organs, fates_string_length) ; fates_prt_organ_name:units = "unitless - string" ; fates_prt_organ_name:long_name = "Name of plant organs (order must match PRTGenericMod.F90)" ; - double fates_fnrt_adapt_tscale(fates_pft) ; - fates_fnrt_adapt_tscale:units = "fraction" ; - fates_fnrt_adapt_tscale:long_name = "Number of days that is the shortest possible doubling period for CNP fine-root adaptation" ; double fates_alloc_storage_cushion(fates_pft) ; fates_alloc_storage_cushion:units = "fraction" ; fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; @@ -159,6 +156,15 @@ variables: double fates_c2b(fates_pft) ; fates_c2b:units = "ratio" ; fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; + double fates_cnp_pid_kd(fates_pft) ; + fates_cnp_pid_kd:units = "unknown" ; + fates_cnp_pid_kd:long_name = "derivative constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_pid_ki(fates_pft) ; + fates_cnp_pid_ki:units = "unknown" ; + fates_cnp_pid_ki:long_name = "integral constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_pid_kp(fates_pft) ; + fates_cnp_pid_kp:units = "unknown" ; + fates_cnp_pid_kp:long_name = "proportional constant of the PID controller on adaptive fine-root biomass" ; 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" ; @@ -505,9 +511,9 @@ variables: double fates_smpso(fates_pft) ; fates_smpso:units = "mm" ; fates_smpso:long_name = "Soil water potential at full stomatal opening" ; - double fates_store_ovrflw_frac(fates_pft) ; - fates_store_ovrflw_frac:units = "fraction" ; - fates_store_ovrflw_frac:long_name = "size of overflow storage (CNP only) as a fraction of storage target" ; + double fates_cnp_store_ovrflw_frac(fates_pft) ; + fates_cnp_store_ovrflw_frac:units = "fraction" ; + fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (CNP only) as a fraction of storage target" ; double fates_taulnir(fates_pft) ; fates_taulnir:units = "fraction" ; fates_taulnir:long_name = "Leaf transmittance: near-IR" ; @@ -813,9 +819,6 @@ data: "sapwood ", "structure " ; - - fates_fnrt_adapt_tscale = 30.0,30.0,30.0,30.0,30.0,30.0,30.0,30.0, 30.0,30.0,30.0,30.0; - fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 ; @@ -907,6 +910,12 @@ data: fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + fates_cnp_pid_kd = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; + + fates_cnp_pid_ki = 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ; + + fates_cnp_pid_kp = 5e-4, 5e-4, 5e-4, 5e-4, 5e-4, 5e-4, 5e-4, 5e-4, 5e-4, 5e-4, 5e-4, 5e-4 ; + fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; fates_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, @@ -1295,7 +1304,7 @@ data: fates_smpso = -66000, -66000, -66000, -66000, -66000, -66000, -66000, -66000, -66000, -66000, -66000, -66000 ; - fates_store_ovrflw_frac = 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 ; + fates_cnp_store_ovrflw_frac = 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 ; fates_taulnir = 0.25, 0.1, 0.1, 0.25, 0.25, 0.25, 0.1, 0.25, 0.25, 0.34, 0.34, 0.34 ; diff --git a/parameter_files/patch_default_bciopt224.xml b/parameter_files/patch_default_bciopt224.xml index 73f37057d6..9897db82d6 100644 --- a/parameter_files/patch_default_bciopt224.xml +++ b/parameter_files/patch_default_bciopt224.xml @@ -2,7 +2,7 @@ This parameter dataset was created by Ryan Knox rgknox@lbl.gov. Please contact if using in published work. The calibration uses the following datasets: [1] Ely et al. 2019. Leaf mass area, Panama. NGEE-Tropics data collection.http://dx.doi.org/10.15486/ngt/1411973 and [2] Condit et al. 2019. Complete data from the Barro Colorado 50-ha plot. https://doi.org/10.15146/5xcp-0d46. [3] Koven et al. 2019. Benchmarking and parameter sensitivity of physiological and vegetation dynamics using the functionally assembled terrestrial ecosystem simulator. Biogeosciences. The ECA nutrient aquisition parmeters are unconstrained, the file output naming convention vmn6phi is shorthand for vmax for nitrogen uptake is order e-6 and for phosphorus is excessively high. These parameters were calibrated with the special fates modification in main/EDTypesMod.F90: nclmax = 3 fates_params_default.cdl - fates_params_opt224_040822.cdl + fates_params_opt224_040822_v2.cdl 1 0 @@ -33,8 +33,7 @@ 5 0.4863088 0.0 - 10 - 1 + 1 3 5e-09 5e-09 diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 21c4544a41..84713c8b91 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -73,8 +73,6 @@ module PRTAllometricCNPMod ! ! ------------------------------------------------------------------------------------- - - integer, parameter :: leaf_c_id = 1 ! leaf carbon index integer, parameter :: fnrt_c_id = 2 ! fine-root carbon index integer, parameter :: sapw_c_id = 3 ! sapwood carbon index @@ -98,17 +96,7 @@ module PRTAllometricCNPMod ! Total number of state variables integer, parameter :: num_vars = 18 - - - ! Setpoint Error controller method - integer, parameter, private :: storage_spe = 0 - integer, parameter, private :: binary_limiter_spe = 1 - integer, parameter, private :: daily_gain_ratio_spe = 2 - - integer, parameter, private :: pid_spe_controller = storage_spe - - real(r8), parameter, private :: pid_int_wgt = 1._r8/1._r8 ! n-day smoothing (K on the integral of PID) - real(r8), parameter, private :: pid_drv_wgt = 1._r8/20._r8 ! n-day smoothing (K on the derivative of PID) + ! Global identifiers for the two stoichiometry values integer,public, parameter :: stoich_growth_min = 1 ! Flag for stoichiometry associated with @@ -141,10 +129,7 @@ module PRTAllometricCNPMod integer, parameter :: num_intgr_vars = 7 - integer, parameter :: cnp_limited = 0 - integer, parameter :: c_limited = 1 - integer, parameter :: n_limited = 2 - integer, parameter :: p_limited = 3 + ! ------------------------------------------------------------------------------------- ! Input/Output Boundary Indices (These are public, and therefore @@ -201,41 +186,42 @@ module PRTAllometricCNPMod ! ------------------------------------------------------------------------------------- ! Define the size of the coorindate vector. For this hypothesis, there is only ! one pool per each species x organ combination, except for leaves (WHICH HAVE AGE) + ! icd refers to the first index in the leaf array, which is the youngest. Growth + ! and allocation only happens in the youngest bin by definition ! ------------------------------------------------------------------------------------- integer, parameter :: icd = 1 + ! These constants define different methods of dealing with excess carbon at + ! the end of the allocation process, assuming that N or P is limiting growth. + ! You can either exude (send to soil), retain (grow storage without limit), + ! or burn (as respiration to the atm). integer, parameter :: exude_c_store_overflow = 1 integer, parameter :: retain_c_store_overflow = 2 integer, parameter :: burn_c_store_overflow = 3 - integer, parameter :: store_c_overflow = burn_c_store_overflow - ! Following growth, if desired, you can prioritize reproductive - logical, parameter :: prioritize_repro_nutr_growth = .true. + ! These constants define if/how growth is limited by + ! one of the 3 chemical species, 0 indicates there is some + ! degree of co limitation + integer, parameter :: cnp_limited = 0 + integer, parameter :: c_limited = 1 + integer, parameter :: n_limited = 2 + integer, parameter :: p_limited = 3 + - ! Definitions for the regulation functions. These typically translate - ! a storage fraction into a scalar used to regulate resources somehow + ! Following growth, if desired, you can prioritize that + ! reproductive tissues get balanced CNP + logical, parameter :: prioritize_repro_nutr_growth = .true. - integer, parameter :: regulate_linear = 1 ! DEPRECATED - integer, parameter :: regulate_logi = 2 ! DEPRECATED - integer, parameter :: regulate_CN_logi = 3 ! almost deprecated - integer, parameter :: regulate_CN_dfdd = 4 - - logical, parameter :: use_gains_in_regulator = .true. + ! If this parameter is true, then the fine-root l2fr optimization + ! scheme will remove biomass from roots without restriction if the + ! l2fr is getting smaller. logical, parameter :: use_unrestricted_contraction = .true. - integer, parameter :: pid_ratio = 1 - integer, parameter :: pid_logratio = 2 - - integer, parameter :: pid_method = pid_logratio - - ! ------------------------------------------------------------------------------------- ! This is the core type that holds this specific ! plant reactive transport (PRT) module ! ------------------------------------------------------------------------------------- - - type, public, extends(prt_vartypes) :: cnp_allom_prt_vartypes contains @@ -498,7 +484,6 @@ subroutine DailyPRTAllometricCNP(this,co_num,nplant) end do - ! Output only boundary conditions c_efflux => this%bc_out(acnp_bc_out_id_cefflux)%rval; c_efflux = 0._r8 n_efflux => this%bc_out(acnp_bc_out_id_nefflux)%rval; n_efflux = 0._r8 @@ -732,23 +717,21 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) real(r8) :: store_c_max, store_c_act real(r8) :: store_nut_max, store_nut_act real(r8) :: n_ratio, p_ratio, np_ratio - real(r8) :: fnrt_c,leaf_c,store_c,struct_c,sapw_c,c_gain,c_fnrt_expand + real(r8) :: fnrt_c,leaf_c,store_c,struct_c,sapw_c,c_gain + real(r8) :: c_fnrt_expand real(r8) :: l2fr_delta_max - real(r8) :: l2fr_delta_minmax ! Hard cap on maximum change scale*log(2) - real(r8) :: l2fr_delta_scale real(r8) :: logi_k real(r8) :: l2fr_mult real(r8) :: l2fr_delta real(r8) :: cn_ratio, cp_ratio real(r8) :: dxcdt_ratio ! log change (derivative) of the maximum of the N/C and P/C storage ratio - real(r8) :: xc_ratio ! log Maximum of the N/C and P/C storage ratio - real(r8), pointer :: ema_xc ! The exponential moving average of the N-or-P versus C PID error function - real(r8), pointer :: xc0 ! The log of the xc ratio from previous time-step - real(r8), pointer :: ema_dxcdt ! the EMA of the change in log storage ratio + real(r8) :: cx_logratio ! log Maximum of the C/N and C/P storage ratio + real(r8), pointer :: cx_int ! Integration of the cx_logratio + real(r8), pointer :: cx0 ! The log of the cx ratio from previous time-step + real(r8), pointer :: ema_dcxdt ! the EMA of the change in log storage ratio integer :: sup_flag real(r8), parameter :: max_l2fr_cgain_frac = 0.99_r8 - real(r8), parameter :: xc_ratio_correction = 1.0_r8 - + real(r8), parameter :: pid_drv_wgt = 1._r8/20._r8 ! n-day smoothing (K on the derivative of PID) integer, parameter :: pid_c_function = 0 integer, parameter :: pid_n_function = 1 @@ -756,17 +739,6 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) integer, parameter :: pid_alogmaxnc_function = 3 integer, parameter :: pid_ncratio_function = 4 - !integer, parameter :: pid_function = pid_c_function - - ! This is the relative scaling strength of the derivative term (K_d), - ! compared to the combined proportion and integral term (K_p and K_i) - ! Note the strength of the derivative is should be about half of the period - ! for an oscillation when turned off, to balance the K_p and K_i terms. - ! This will have to be tuned in a sequence of 1, 10, 100, etc... - real(r8) :: pid_k_i ! Integral scaling coefficient in PID - real(r8) :: pid_k_d ! Derivative scaling coefficient in PID - real(r8) :: pid_k_p ! Proportional scaling coefficient in PID - ! If we do not have leaves out, then the relative nutrient vs carbon ! balancing is meaningless, just leave this routine if(this%GetState(leaf_organ, carbon12_element)/target_c(leaf_organ) < 0.5_r8) return @@ -776,12 +748,10 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval - ema_xc => this%bc_inout(acnp_bc_inout_id_emaxc)%rval - xc0 => this%bc_inout(acnp_bc_inout_id_xc0)%rval - ema_dxcdt => this%bc_inout(acnp_bc_inout_id_emadxcdt)%rval + cx_int => this%bc_inout(acnp_bc_inout_id_emaxc)%rval + cx0 => this%bc_inout(acnp_bc_inout_id_xc0)%rval + ema_dcxdt => this%bc_inout(acnp_bc_inout_id_emadxcdt)%rval - if_storage_spe: if(pid_spe_controller == storage_spe) then - ! Step 1: Determine the nutrient to carbon ratio (aka relative health factor) ! ----------------------------------------------------------------------------------- @@ -801,27 +771,29 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) this%GetState(store_organ, nitrogen_element) + & this%bc_inout(acnp_bc_inout_id_netdn)%rval) - select case(pid_ncratio_function) !nint(EDPftvarcon_inst%dev_arbitrary_pft(ipft)) ) + select case(pid_ncratio_function) case(pid_c_function) - n_ratio = store_c_max/store_c_act + n_ratio = store_c_act/store_c_max case(pid_n_function) - n_ratio = store_nut_act/store_nut_max + n_ratio = store_nut_max/store_nut_act case(pid_minnc_function) if((store_nut_act/store_nut_max) > (store_c_act/store_c_max))then - n_ratio = (store_c_max/store_c_act) + n_ratio = (store_c_act/store_c_max) else - n_ratio = (store_nut_act/store_nut_max) + n_ratio = (store_nut_max/store_nut_act) end if case(pid_alogmaxnc_function) if( abs(SafeLog(store_nut_act/store_nut_max)) < abs(SafeLog(store_c_act/store_c_max))) then - n_ratio = (store_c_max/store_c_act) + n_ratio = (store_c_act/store_c_max) else - n_ratio = (store_nut_act/store_nut_max) + n_ratio = (store_nut_max/store_nut_act) end if case(pid_ncratio_function) n_ratio = (store_c_act/store_c_max)/(store_nut_act/store_nut_max) end select + ! This is more of a diagnostic, to see if the other process functions + ! are as good as the ratio of relative ratios cn_ratio = (store_c_act/store_c_max)/(store_nut_act/store_nut_max) else @@ -839,22 +811,22 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) this%GetState(store_organ, phosphorus_element) + & this%bc_inout(acnp_bc_inout_id_netdp)%rval) - select case(pid_ncratio_function) !nint(EDPftvarcon_inst%dev_arbitrary_pft(ipft))) + select case(pid_ncratio_function) case(pid_c_function) - p_ratio = store_c_max/store_c_act + p_ratio = store_c_act/store_c_max case(pid_n_function) - p_ratio = store_nut_act/store_nut_max + p_ratio = store_nut_max/store_nut_act case(pid_minnc_function) if((store_nut_act/store_nut_max) > (store_c_act/store_c_max))then - p_ratio = (store_c_max/store_c_act) + p_ratio = (store_c_act/store_c_max) else - p_ratio = (store_nut_act/store_nut_max) + p_ratio = (store_nut_max/store_nut_act) end if case(pid_alogmaxnc_function) if( abs(SafeLog(store_nut_act/store_nut_max)) < abs(SafeLog(store_c_act/store_c_max))) then - p_ratio = (store_c_max/store_c_act) + p_ratio = (store_c_act/store_c_max) else - p_ratio = (store_nut_act/store_nut_max) + p_ratio = (store_nut_max/store_nut_act) end if case(pid_ncratio_function) p_ratio = (store_c_act/store_c_max)/(store_nut_act/store_nut_max) @@ -867,42 +839,50 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) end if ! Use the limiting nutrient species - if(n_uptake_mode.eq.prescribed_n_uptake .and. p_uptake_mode.eq.prescribed_p_uptake)then - ema_xc = 0._r8 - ema_dxcdt = 0._r8 - xc0 = 0.0_r8 + if( (n_uptake_mode.eq.prescribed_n_uptake) .and. & + (p_uptake_mode.eq.prescribed_p_uptake) )then + cx_int = 0._r8 + ema_dcxdt = 0._r8 + cx0 = 0.0_r8 return else - xc_ratio = SafeLog(max(n_ratio,p_ratio)) + cx_logratio = SafeLog(max(n_ratio,p_ratio)) - ! If xc_ratio has just crossed zero, then + ! If cx_logratio has just crossed zero, then ! reset the integrator. This will be true if ! the sign of the current ratio is different than ! the sign of the previous - if( (xc_ratio/abs(xc_ratio) - xc0/abs(xc0)) > nearzero ) then - ema_xc = xc_ratio + if( (cx_logratio/abs(cx_logratio) - cx0/abs(cx0)) > nearzero ) then + cx_int = cx_logratio else - ema_xc = ema_xc + xc_ratio + cx_int = cx_int + cx_logratio end if - dxcdt_ratio = xc_ratio-xc0 + dxcdt_ratio = cx_logratio-cx0 - !ema_xc = pid_int_wgt*xc_ratio + (1._r8-pid_int_wgt)*ema_xc - ema_dxcdt = pid_drv_wgt*dxcdt_ratio + (1._r8-pid_drv_wgt)*ema_dxcdt - + ema_dcxdt = pid_drv_wgt*dxcdt_ratio + (1._r8-pid_drv_wgt)*ema_dcxdt - !ema_xc = (1._r8/EDPftvarcon_inst%dev_arbitrary_pft(ipft))*xc_ratio + & - ! (1._r8-(1._r8/EDPftvarcon_inst%dev_arbitrary_pft(ipft)))*ema_xc - - xc0 = xc_ratio + cx0 = cx_logratio end if - - end if if_storage_spe + + fnrt_c = this%GetState(fnrt_organ, carbon12_element) + leaf_c = this%GetState(leaf_organ, carbon12_element) + store_c = this%GetState(store_organ, carbon12_element) + struct_c = this%GetState(struct_organ, carbon12_element) + sapw_c = this%GetState(sapw_organ, carbon12_element) + + ! If there is overflow storage, add this to the gain + c_gain = this%bc_in(acnp_bc_in_id_netdc)%rval + max(0._r8,store_c-target_c(store_organ)) + + l2fr_delta = prt_params%pid_kp(ipft)*cx_logratio + & + prt_params%pid_ki(ipft)*cx_int + & + prt_params%pid_kd(ipft)*ema_dcxdt + ! ----------------------------------------------------------------------------- ! To decide the upper limit on expanding root growth, we perform a carbon ! balance. Note that if we are growing roots out more, than we have proportionaly @@ -919,74 +899,32 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) ! (target_sapw_c-actual_sapw_c) - ! (target_dead_c-actual_dead_c) - ! (target_stor_c-actual_stor_c) - ! ! ------------------------------------------------------------------------------ - - fnrt_c = this%GetState(fnrt_organ, carbon12_element) - leaf_c = this%GetState(leaf_organ, carbon12_element) - store_c = this%GetState(store_organ, carbon12_element) - struct_c = this%GetState(struct_organ, carbon12_element) - sapw_c = this%GetState(sapw_organ, carbon12_element) - - ! If there is overflow storage, add this to the gain - c_gain = this%bc_in(acnp_bc_in_id_netdc)%rval + max(0._r8,store_c-target_c(store_organ)) - + ! This is a rough estimate of the amount of carbon we will have to spend + ! on root expansion after we get back on allometry c_fnrt_expand = max_l2fr_cgain_frac* ( c_gain - & max(0._r8,target_c(fnrt_organ)-fnrt_c) - & max(0._r8,target_c(leaf_organ)-leaf_c) - & max(0._r8,target_c(sapw_organ)-sapw_c) - & max(0._r8,target_c(struct_organ)-struct_c) - & max(0._r8,target_c(store_organ)-store_c)) + + !c_fnrt_expand > (l2fr+l2fr_delta)*target_c(leaf_organ) - l2fr*target_c(leaf_organ) + !c_fnrt_expand = (l2fr+l2fr_delta_max)*target_c(leaf_organ) - l2fr*target_c(leaf_organ) + !c_fnrt_expand = l2fr_delta_max*target_c(leaf_organ) - if(pid_method==pid_logratio) then - - ! When using a log based (additive) PID search method - ! we define 1/fnrt_adapt_tscale as delta we want - ! when we have a 2:1 ratio. For instance if fnrt_adapt_tscale = 100, - ! then we want a scaling parameter that generates a change in l2fr of 1/100 - ! when there is 2:1 ratio of nutrient versus carbon storage. This - ! value is akin to the K_p and K_i terms in a PID controller (and - ! the ema timescale is the relative weight of K_p and K_i) - - l2fr_delta_scale = (1._r8/prt_params%fnrt_adapt_tscale(ipft))/log(2.0_r8) - - ! Want the derivative to be strongest when storage is most disproportionate - pid_k_d = prt_params%fnrt_adapt_tscale(ipft) !-0.1_r8 - pid_k_i = 0.0_r8 !EDPftvarcon_inst%dev_arbitrary_pft(ipft) !-0.0001_r8 - pid_k_p = EDPftvarcon_inst%dev_arbitrary_pft(ipft) !0.0005_r8 - - l2fr_delta = pid_k_p*xc_ratio + pid_k_i*ema_xc + pid_k_d*ema_dxcdt - - !l2fr_delta = ema_xc/abs(ema_xc)*l2fr_int_scale + ema_dxcdt*l2fr_deriv_scale - - ! Cap growth and shrinkage to avoid large changes - ! (currently capping at projected rate for a 2:1 ratio - l2fr_delta_minmax = l2fr_delta_scale*log(20.0) - - ! Don't allow more growth than we have carbon to pay for - !! l2fr_delta_max = min(l2fr_delta_minmax,l2fr*(c_fnrt_expand + target_c(fnrt_organ))/target_c(fnrt_organ)) - - - !! l2fr_delta = max(-l2fr_delta_minmax,min(l2fr_delta,l2fr_delta_max)) - !!l2fr_delta = max(-l2fr_delta_minmax,min(l2fr_delta,l2fr_delta_minmax)) - - - ! Apply the delta, also, avoid generating incredibly small l2fr's, - ! super small l2frs will occur in plants that perpetually get almost - ! now carbon gain, such as newly recruited plants in a dark understory - - l2fr = max(l2fr_min, l2fr + l2fr_delta ) + l2fr_delta_max = max(0._r8,c_fnrt_expand/target_c(leaf_organ)) + + ! Apply the delta, also, avoid generating incredibly small l2fr's, + ! super small l2frs will occur in plants that perpetually get almost + ! now carbon gain, such as newly recruited plants in a dark understory - !if((co_num==1) .or. (co_num==2)) print*,'AAX1',co_num,hlm_current_year,hlm_day_of_year, & - ! dbh,nplant,(store_c_act/store_c_max),cn_ratio,SafeLog(cn_ratio),l2fr - - else - - write(fates_log(),*) 'unknown PID controller method', pid_method - call endrun(msg=errMsg(sourcefile, __LINE__)) - - end if + !l2fr = max(l2fr_min, l2fr + l2fr_delta) + l2fr = max(l2fr_min, l2fr + min(l2fr_delta_max,l2fr_delta)) + + !if((co_num==1) .or. (co_num==2)) print*,'AAX1',co_num,hlm_current_year,hlm_day_of_year, & + ! dbh,nplant,(store_c_act/store_c_max),cn_ratio,SafeLog(cn_ratio),l2fr ! Find the updated target fineroot biomass @@ -1034,8 +972,6 @@ subroutine TrimFineRoot(this) if(fnrt_flux_c>nearzero) then - !EDPftvarcon_inst%dev_arbitrary_pft(ipft) - turn_flux_c = (1._r8 - fnrt_opt_eff)*fnrt_flux_c store_flux_c = fnrt_opt_eff*fnrt_flux_c @@ -1957,104 +1893,15 @@ subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & real(r8) :: store_m_flux ! Flux into storage [kg] real(r8), pointer :: dbh real(r8), pointer :: resp_excess - real(r8), pointer :: ema_xc - real(r8), pointer :: ema_dxcdt - real(r8), pointer :: xc0 - real(r8) :: dxcdt_ratio integer :: ipft integer, pointer :: limiter real(r8) :: canopy_trim - real(r8) :: n_ratio,p_ratio,c_ratio - real(r8) :: xc_ratio,nc_ratio,pc_ratio - real(r8), pointer :: l2fr dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival resp_excess => this%bc_inout(acnp_bc_inout_id_resp_excess)%rval - l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval limiter => this%bc_out(acnp_bc_out_id_limiter)%ival - ema_xc => this%bc_inout(acnp_bc_inout_id_emaxc)%rval - ema_dxcdt => this%bc_inout(acnp_bc_inout_id_emadxcdt)%rval - xc0 => this%bc_inout(acnp_bc_inout_id_xc0)%rval - ! Update the F_NPC - - ! n_ratio the ratio of n_gain/n_alloc / c_gain/c_alloc - ! If either n or p uptake is in prescribed mode - ! set the gains to something massive. 1 kilo of pure - ! nutrient should be wayyy more than enough - - if(pid_spe_controller == daily_gain_ratio_spe) then - - if(c_gain0 Date: Thu, 22 Sep 2022 17:21:35 -0400 Subject: [PATCH 346/852] Updated parameter format to add PID terms, remove adaptive timescale and update longname of nfix1 --- parameter_files/apichange_24to25.xml | 49 ++++++++++++++++++++++++ parameter_files/fates_params_default.cdl | 29 +++++++++----- tools/UpdateParamAPI.py | 31 ++++----------- 3 files changed, 75 insertions(+), 34 deletions(-) create mode 100644 parameter_files/apichange_24to25.xml diff --git a/parameter_files/apichange_24to25.xml b/parameter_files/apichange_24to25.xml new file mode 100644 index 0000000000..44f37eefa3 --- /dev/null +++ b/parameter_files/apichange_24to25.xml @@ -0,0 +1,49 @@ + + + + + + + + + + fates_params_default.cdl + fates_params_default_api25.cdl + 1,2,3,4,5,6,7,8,9,10,11,12 + + + fates_cnp_fnrt_adapt_tscale + + + fates_cnp_pid_kd + fates_pft + unknown + derivative constant of the PID controller on adaptive fine-root biomass + 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 + + + fates_cnp_pid_ki + fates_pft + unknown + integral constant of the PID controller on adaptive fine-root biomass + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + + + fates_cnp_pid_kp + fates_pft + unknown + proportional constant of the PID controller on adaptive fine-root biomass + 5e-4, 5e-4, 5e-4, 5e-4, 5e-4, 5e-4, 5e-4, 5e-4, 5e-4, 5e-4, 5e-4, 5e-4 + + + fractional surcharge added to maintenance respiration that drives symbiotic fixation + fraction + + + diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 569e6a1ab6..c1388cd90b 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1,4 +1,4 @@ -netcdf fates_params_default_api24 { +netcdf tmp { dimensions: fates_NCWD = 4 ; fates_history_age_bins = 7 ; @@ -197,18 +197,24 @@ variables: double fates_cnp_eca_vmax_ptase(fates_pft) ; fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; - double fates_cnp_fnrt_adapt_tscale(fates_pft) ; - fates_cnp_fnrt_adapt_tscale:units = "days" ; - fates_cnp_fnrt_adapt_tscale:long_name = "Number of days that is shortest possible doubling period for fine-root adaptation to C/N/P balance" ; double fates_cnp_nfix1(fates_pft) ; - fates_cnp_nfix1:units = "NA" ; - fates_cnp_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; + fates_cnp_nfix1:units = "fraction" ; + fates_cnp_nfix1:long_name = "fractional surcharge added to maintenance respiration that drives symbiotic fixation" ; double fates_cnp_nitr_store_ratio(fates_pft) ; fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; fates_cnp_nitr_store_ratio:long_name = "storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code)" ; double fates_cnp_phos_store_ratio(fates_pft) ; fates_cnp_phos_store_ratio:units = "(gP/gP)" ; fates_cnp_phos_store_ratio:long_name = "storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code)" ; + double fates_cnp_pid_kd(fates_pft) ; + fates_cnp_pid_kd:units = "unknown" ; + fates_cnp_pid_kd:long_name = "derivative constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_pid_ki(fates_pft) ; + fates_cnp_pid_ki:units = "unknown" ; + fates_cnp_pid_ki:long_name = "integral constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_pid_kp(fates_pft) ; + fates_cnp_pid_kp:units = "unknown" ; + fates_cnp_pid_kp:long_name = "proportional constant of the PID controller on adaptive fine-root biomass" ; double fates_cnp_prescribed_nuptake(fates_pft) ; fates_cnp_prescribed_nuptake:units = "fraction" ; fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; @@ -221,7 +227,6 @@ variables: double fates_cnp_store_ovrflw_frac(fates_pft) ; fates_cnp_store_ovrflw_frac:units = "fraction" ; fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; - fates_cnp_store_ovrflw_frac:use_case = "None" ; double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; fates_cnp_turnover_nitr_retrans:units = "fraction" ; fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; @@ -975,9 +980,6 @@ data: fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - fates_cnp_fnrt_adapt_tscale = 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100, 100 ; - fates_cnp_nfix1 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, @@ -986,6 +988,13 @@ data: fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5 ; + fates_cnp_pid_kd = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; + + fates_cnp_pid_ki = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_pid_kp = 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005 ; + fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; diff --git a/tools/UpdateParamAPI.py b/tools/UpdateParamAPI.py index fe35d6a0c9..df8ea6be31 100755 --- a/tools/UpdateParamAPI.py +++ b/tools/UpdateParamAPI.py @@ -54,14 +54,13 @@ def str2ivec(numstr): # ======================================================================================= -def createvar(ncfile,paramname,dimnames,units,longname,usecase,dcode,sel_values): +def createvar(ncfile,paramname,dimnames,units,longname,dcode,sel_values): # Create a new netcdf variable inside an existing netcdf dataset (append) ncvar = ncfile.createVariable(paramname,dcode,dimnames) ncvar.units = units ncvar.long_name = longname - ncvar.use_case = usecase if( not dimnames): ncvar.assignValue(sel_values) else: @@ -315,11 +314,6 @@ def main(): except: print("no long-name (ln), exiting");exit(2) - #try: - # usecase = mod.find('uc').text.strip() - #except: - # print("no use case (uc), exiting");exit(2) - try: values = str2fvec(mod.find('val').text.strip()) except: @@ -344,10 +338,10 @@ def main(): print("Unknown value type: {} {}".format(type(values[0]),paramname));exit(2) - sel_values = selectvalues(ncfile,list(dimnames),ipft_list,values,dcode) - ncfile = netcdf.netcdf_file(base_nc,"a",mmap=False) - [ncfile,ncvar] = createvar(ncfile,paramname,dimnames,units,longname,usecase,dcode,sel_values) + sel_values = selectvalues(ncfile,list(dimnames),ipft_list,values,dcode) + + [ncfile,ncvar] = createvar(ncfile,paramname,dimnames,units,longname,dcode,sel_values) ncfile.flush() ncfile.close() @@ -378,10 +372,6 @@ def main(): dtype_o = ncvar_o.typecode() units_o = ncvar_o.units.decode("utf-8") longname_o = ncvar_o.long_name.decode("utf-8") - try: - usecase_o = ncvar_o.use_case.decode("utf-8") - except: - usecase_o = 'undefined' try: paramname = mod.find('na').text.strip() @@ -391,9 +381,9 @@ def main(): # Change the parameter's name if(not isinstance(paramname,type(None))): if not dims_o: - [ncfile,ncvar] = createvar(ncfile,paramname,dims_o,units_o,longname_o,usecase_o,dtype_o,float(ncvar_o.data)) + [ncfile,ncvar] = createvar(ncfile,paramname,dims_o,units_o,longname_o,dtype_o,float(ncvar_o.data)) else: - [ncfile,ncvar] = createvar(ncfile,paramname,dims_o,units_o,longname_o,usecase_o,dtype_o,ncvar_o[:].copy()) + [ncfile,ncvar] = createvar(ncfile,paramname,dims_o,units_o,longname_o,dtype_o,ncvar_o[:].copy()) else: ncvar = ncvar_o @@ -412,13 +402,6 @@ def main(): if(not isinstance(longname,type(None))): ncvar.long_name = longname - #try: - # usecase = mod.find('uc').text.strip() - #except: - usecase = None - #if(not isinstance(usecase,type(None))): - # ncvar.use_case = use_case - try: values = str2fvec(mod.find('val').text.strip()) except: @@ -444,7 +427,7 @@ def main(): removevar(base_nc,paramname_o) paramname = paramname_o - print("parameter: {}, modified".format(paramname)) + print("parameter: {}, modified".format(paramname_o)) # Sort the new file From ce81248dc4ae8cc65b38a2e9a63d261a6352cd13 Mon Sep 17 00:00:00 2001 From: Shijie Shu Date: Thu, 22 Sep 2022 18:17:54 -0700 Subject: [PATCH 347/852] Removed hlm_harvest_bypass_criteria. Applied fix on global restart run. --- biogeochem/EDLoggingMortalityMod.F90 | 3 -- biogeochem/EDPatchDynamicsMod.F90 | 5 ++- biogeochem/EDPhysiologyMod.F90 | 12 +++++-- main/EDInitMod.F90 | 14 ++++++--- main/EDTypesMod.F90 | 4 +++ main/FatesHistoryInterfaceMod.F90 | 12 +++---- main/FatesInterfaceMod.F90 | 14 --------- main/FatesInterfaceTypesMod.F90 | 6 ---- main/FatesRestartInterfaceMod.F90 | 47 ++++++++++++++++------------ 9 files changed, 57 insertions(+), 60 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index d17010a33a..cb5dcc84dd 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -49,7 +49,6 @@ module EDLoggingMortalityMod use FatesInterfaceTypesMod , only : hlm_day_of_year use FatesInterfaceTypesMod , only : hlm_days_per_year use FatesInterfaceTypesMod , only : hlm_use_lu_harvest - use FatesInterfaceTypesMod , only : hlm_harvest_bypass_criteria use FatesInterfaceTypesMod , only : hlm_num_lu_harvest_cats use FatesInterfaceTypesMod , only : hlm_use_logging use FatesInterfaceTypesMod , only : hlm_use_planthydro @@ -307,8 +306,6 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & else lmort_direct = 0.0_r8 end if - else if (cur_harvest_tag == 1 .and. hlm_harvest_bypass_criteria == 1) then - lmort_direct = harvest_rate * logging_direct_frac else lmort_direct = 0.0_r8 end if diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index b1036035a0..b190d48168 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -50,7 +50,6 @@ module EDPatchDynamicsMod use FatesInterfaceTypesMod , only : hlm_use_nocomp use FatesInterfaceTypesMod , only : hlm_use_fixed_biogeog use FatesInterfaceTypesMod , only : hlm_num_lu_harvest_cats - use FatesInterfaceTypesMod , only : hlm_harvest_bypass_criteria use FatesGlobals , only : endrun => fates_endrun use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : itrue, ifalse @@ -281,7 +280,7 @@ subroutine disturbance_rates( site_in, bc_in) if (harvest_debt_primary == 0) then if ( currentPatch%anthro_disturbance_label .eq. primaryforest ) then if ( harvest_tag(h_index) == 2 .or. & - (harvest_tag(h_index) == 1 .and. .not. (hlm_harvest_bypass_criteria))) then + (harvest_tag(h_index) == 1 )) then ! h_index points to primary forest harvest if((bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1")) then harvest_debt_primary = 1 @@ -295,7 +294,7 @@ subroutine disturbance_rates( site_in, bc_in) if ( currentPatch%anthro_disturbance_label .eq. secondaryforest ) then patch_no_secondary = patch_no_secondary + 1 if ( harvest_tag(h_index) == 2 .or. & - (harvest_tag(h_index) == 1 .and. .not. (hlm_harvest_bypass_criteria))) then + (harvest_tag(h_index) == 1 )) then ! h_index points to secondary forest harvest if((bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH1") .or. & (bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2")) then diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 5d66f56d39..6577b47b35 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -746,7 +746,12 @@ subroutine phenology( currentSite, bc_in ) ! This is the integer model day. The first day of the simulation is 1, and it ! continues monotonically, indefinitely - model_day_int = nint(hlm_model_day) + ! Advance it. (this should be a global, no reason + ! for site level, but we don't have global scalars in the + ! restart file) + + currentSite%phen_model_date = currentSite%phen_model_date + 1 + model_day_int = currentSite%phen_model_date ! Use the following layer index to calculate drought conditions @@ -851,7 +856,7 @@ subroutine phenology( currentSite, bc_in ) end if if (model_day_int < currentSite%cleafondate) then - dayssincecleafon = model_day_int - (currentSite%cleafondate-365) + dayssincecleafon = model_day_int - (currentSite%cleafondate - 365) else dayssincecleafon = model_day_int - currentSite%cleafondate end if @@ -1063,6 +1068,8 @@ subroutine phenology( currentSite, bc_in ) call phenology_leafonoff(currentSite) + return + end subroutine phenology @@ -1591,7 +1598,6 @@ subroutine SeedIn( currentSite, bc_in ) ! !USES: use EDTypesMod, only : area use EDTypesMod, only : homogenize_seed_pfts - !use FatesInterfaceTypesMod, only : hlm_use_fixed_biogeog ! For future reduced complexity? ! ! !ARGUMENTS type(ed_site_type), intent(inout), target :: currentSite diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index ac0b80a182..917a718cf4 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -22,6 +22,7 @@ module EDInitMod use EDPatchDynamicsMod , only : set_patchno use EDPhysiologyMod , only : assign_cohort_sp_properties use ChecksBalancesMod , only : SiteMassStock + use FatesInterfaceTypesMod , only : hlm_day_of_year use EDTypesMod , only : ed_site_type, ed_patch_type, ed_cohort_type use EDTypesMod , only : numWaterMem use EDTypesMod , only : num_vegtemp_mem @@ -201,6 +202,8 @@ subroutine zero_site( site_in ) site_in%water_memory(:) = nan site_in%vegtemp_memory(:) = nan ! record of last 10 days temperature for senescence model. + site_in%phen_model_date = fates_unset_int + ! Disturbance rates tracking site_in%primary_land_patchfusion_error = 0.0_r8 site_in%harvest_carbon_flux = 0.0_r8 @@ -316,11 +319,12 @@ subroutine set_site_properties( nsites, sites,bc_in ) ! is memory-less, but needed ! for first value in history file - sites(s)%cleafondate = cleafon - sites(s)%cleafoffdate = cleafoff - sites(s)%dleafoffdate = dleafoff - sites(s)%dleafondate = dleafon - sites(s)%grow_deg_days = GDD + sites(s)%phen_model_date = 0 + sites(s)%cleafondate = cleafon - hlm_day_of_year + sites(s)%cleafoffdate = cleafoff - hlm_day_of_year + sites(s)%dleafoffdate = dleafoff - hlm_day_of_year + sites(s)%dleafondate = dleafon - hlm_day_of_year + sites(s)%grow_deg_days = GDD sites(s)%water_memory(1:numWaterMem) = watermem sites(s)%vegtemp_memory(1:num_vegtemp_mem) = 0._r8 diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index ba32b647b1..f5a2a12ceb 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -749,6 +749,10 @@ module EDTypesMod integer :: cleafoffdate ! model date (day integer) of leaf off (cold):- integer :: dleafondate ! model date (day integer) of leaf on drought:- integer :: dleafoffdate ! model date (day integer) of leaf off drought:- + integer :: phen_model_date ! current model date (day integer) + ! this date stays continuous when + ! in runs that are restarted, regardless of + ! the conditions of restart real(r8) :: water_memory(numWaterMem) ! last 10 days of soil moisture memory... diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index da508d8f2e..f9e3e1dc4f 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -1764,7 +1764,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) integer :: height_bin_max, height_bin_min ! which height bin a given cohort's canopy is in integer :: i_heightbin ! iterator for height bins integer :: el ! Loop index for elements - integer :: model_day_int ! integer model day from reference + integer :: model_day_int ! Integer model day since simulation start integer :: ageclass_since_anthrodist ! what is the equivalent age class for ! time-since-anthropogenic-disturbance of secondary forest @@ -2062,7 +2062,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_cleafoff_si => this%hvars(ih_cleafoff_si)%r81d, & hio_cleafon_si => this%hvars(ih_cleafon_si)%r81d, & hio_dleafoff_si => this%hvars(ih_dleafoff_si)%r81d, & - hio_dleafon_si => this%hvars(ih_dleafoff_si)%r81d, & + hio_dleafon_si => this%hvars(ih_dleafon_si)%r81d, & hio_tveg24 => this%hvars(ih_tveg24_si)%r81d, & hio_meanliqvol_si => this%hvars(ih_meanliqvol_si)%r81d, & hio_cbal_err_fates_si => this%hvars(ih_cbal_err_fates_si)%r81d, & @@ -2118,10 +2118,10 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_gdd_si(io_si) = sites(s)%grow_deg_days ! Model days elapsed since leaf on/off for cold- and drought-deciduous - hio_cleafoff_si(io_si) = real(model_day_int - sites(s)%cleafoffdate,r8) - hio_cleafon_si(io_si) = real(model_day_int - sites(s)%cleafondate,r8) - hio_dleafoff_si(io_si) = real(model_day_int - sites(s)%dleafoffdate,r8) - hio_dleafon_si(io_si) = real(model_day_int - sites(s)%dleafondate,r8) + hio_cleafoff_si(io_si) = real(sites(s)%phen_model_date - sites(s)%cleafoffdate,r8) + hio_cleafon_si(io_si) = real(sites(s)%phen_model_date - sites(s)%cleafondate,r8) + hio_dleafoff_si(io_si) = real(sites(s)%phen_model_date - sites(s)%dleafoffdate,r8) + hio_dleafon_si(io_si) = real(sites(s)%phen_model_date - sites(s)%dleafondate,r8) ! Mean liquid water content (m3/m3) used for drought phenology if(model_day_int>numWaterMem)then diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 14ac272ae6..cc3e305fac 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1294,7 +1294,6 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) hlm_sf_anthro_ignitions_def = unset_int hlm_use_planthydro = unset_int hlm_use_lu_harvest = unset_int - hlm_harvest_bypass_criteria = unset_int hlm_num_lu_harvest_cats = unset_int hlm_use_cohort_age_tracking = unset_int hlm_use_logging = unset_int @@ -1357,13 +1356,6 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if ( (hlm_harvest_bypass_criteria .lt. 0).or.(hlm_harvest_bypass_criteria .gt. 1) ) then - if (fates_global_verbose()) then - write(fates_log(), *) 'The FATES bypass harvest scenario flag must be 0 or 1, exiting' - end if - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - if ( (hlm_num_lu_harvest_cats .lt. 0) ) then if (fates_global_verbose()) then write(fates_log(), *) 'The FATES number of hlm harvest cats must be >= 0, exiting' @@ -1777,12 +1769,6 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) write(fates_log(),*) 'Transfering hlm_use_lu_harvest= ',ival,' to FATES' end if - case('use_harvest_bypass_criteria') - hlm_harvest_bypass_criteria = ival - if (fates_global_verbose()) then - write(fates_log(),*) 'Transfering hlm_harvest_bypass_criteria= ',ival,' to FATES' - end if - case('num_lu_harvest_cats') hlm_num_lu_harvest_cats = ival if (fates_global_verbose()) then diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index e29aca8e39..35bf37aa7e 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -120,12 +120,6 @@ module FatesInterfaceTypesMod ! If 1, it automatically sets ! hlm_use_logging to 1 - integer, public :: hlm_harvest_bypass_criteria ! This flag signals whether or not to bypass the logging criteria - ! when using carbon-based harvest and all available forest C under - ! criteria are not enough - ! 0 = do not bypass criteria - ! 1 = allow to bypass the criteria - integer, public :: hlm_num_lu_harvest_cats ! number of hlm harvest categories (e.g. primary forest harvest, secondary young forest harvest, etc.) ! this is the first dimension of: ! harvest_rates in dynHarvestMod diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 0605767cd6..a423282144 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -83,10 +83,11 @@ module FatesRestartInterfaceMod integer :: ir_dd_status_si integer :: ir_nchill_days_si integer :: ir_ncold_days_si - integer :: ir_leafondate_si - integer :: ir_leafoffdate_si + integer :: ir_cleafondate_si + integer :: ir_cleafoffdate_si integer :: ir_dleafondate_si integer :: ir_dleafoffdate_si + integer :: ir_phenmodeldate_si integer :: ir_acc_ni_si integer :: ir_gdd_si integer :: ir_snow_depth_si @@ -618,22 +619,26 @@ subroutine define_restart_vars(this, initialize_variables) long_name='cold day counter', units='unitless', flushval = flushinvalid, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_ncold_days_si ) - call this%set_restart_var(vname='fates_leafondate', vtype=site_int, & - long_name='the day of year for leaf on', units='day of year', flushval = flushinvalid, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_leafondate_si ) + call this%set_restart_var(vname='fates_cold_leafondate', vtype=site_int, & + long_name='the model day of last cold leaf on', units='absolute integer day', flushval = flushinvalid, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_cleafondate_si ) - call this%set_restart_var(vname='fates_leafoffdate', vtype=site_int, & - long_name='the day of year for leaf off', units='day of year', flushval = flushinvalid, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_leafoffdate_si ) + call this%set_restart_var(vname='fates_cold_leafoffdate', vtype=site_int, & + long_name='the model day last cold leaf off', units='absolute integer day', flushval = flushinvalid, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_cleafoffdate_si ) call this%set_restart_var(vname='fates_drought_leafondate', vtype=site_int, & - long_name='the day of year for drought based leaf-on', units='day of year', flushval = flushinvalid, & + long_name='the model day of last drought based leaf-on', units='absolute integer day', flushval = flushinvalid, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_dleafondate_si ) call this%set_restart_var(vname='fates_drought_leafoffdate', vtype=site_int, & - long_name='the day of year for drought based leaf-off', units='day of year', flushval = flushinvalid, & + long_name='the model day of last drought based leaf-off', units='absolute integer day', flushval = flushinvalid, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_dleafoffdate_si ) + call this%set_restart_var(vname='fates_phen_model_date', vtype=site_int, & + long_name='integer model day used for phen timing', units='absolute integer day', flushval = flushinvalid, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_phenmodeldate_si ) + call this%set_restart_var(vname='fates_acc_nesterov_id', vtype=site_r8, & long_name='a nesterov index accumulator', units='unitless', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_acc_ni_si ) @@ -1748,10 +1753,11 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_dd_status_si => this%rvars(ir_dd_status_si)%int1d, & rio_nchill_days_si => this%rvars(ir_nchill_days_si)%int1d, & rio_ncold_days_si => this%rvars(ir_ncold_days_si)%int1d, & - rio_leafondate_si => this%rvars(ir_leafondate_si)%int1d, & - rio_leafoffdate_si => this%rvars(ir_leafoffdate_si)%int1d, & + rio_cleafondate_si => this%rvars(ir_cleafondate_si)%int1d, & + rio_cleafoffdate_si => this%rvars(ir_cleafoffdate_si)%int1d, & rio_dleafondate_si => this%rvars(ir_dleafondate_si)%int1d, & rio_dleafoffdate_si => this%rvars(ir_dleafoffdate_si)%int1d, & + rio_phenmodeldate_si => this%rvars(ir_phenmodeldate_si)%int1d, & rio_acc_ni_si => this%rvars(ir_acc_ni_si)%r81d, & rio_gdd_si => this%rvars(ir_gdd_si)%r81d, & rio_snow_depth_si => this%rvars(ir_snow_depth_si)%r81d, & @@ -2232,9 +2238,9 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_dd_status_si(io_idx_si) = sites(s)%dstatus rio_nchill_days_si(io_idx_si) = sites(s)%nchilldays rio_ncold_days_si(io_idx_si) = sites(s)%ncolddays - rio_leafondate_si(io_idx_si) = sites(s)%cleafondate - rio_leafoffdate_si(io_idx_si) = sites(s)%cleafoffdate - + rio_cleafondate_si(io_idx_si) = sites(s)%cleafondate + rio_cleafoffdate_si(io_idx_si) = sites(s)%cleafoffdate + rio_phenmodeldate_si(io_idx_si)= sites(s)%phen_model_date rio_dleafondate_si(io_idx_si) = sites(s)%dleafondate rio_dleafoffdate_si(io_idx_si) = sites(s)%dleafoffdate rio_acc_ni_si(io_idx_si) = sites(s)%acc_NI @@ -2579,10 +2585,11 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_dd_status_si => this%rvars(ir_dd_status_si)%int1d, & rio_nchill_days_si => this%rvars(ir_nchill_days_si)%int1d, & rio_ncold_days_si => this%rvars(ir_ncold_days_si)%int1d, & - rio_leafondate_si => this%rvars(ir_leafondate_si)%int1d, & - rio_leafoffdate_si => this%rvars(ir_leafoffdate_si)%int1d, & + rio_cleafondate_si => this%rvars(ir_cleafondate_si)%int1d, & + rio_cleafoffdate_si => this%rvars(ir_cleafoffdate_si)%int1d, & rio_dleafondate_si => this%rvars(ir_dleafondate_si)%int1d, & rio_dleafoffdate_si => this%rvars(ir_dleafoffdate_si)%int1d, & + rio_phenmodeldate_si => this%rvars(ir_phenmodeldate_si)%int1d, & rio_acc_ni_si => this%rvars(ir_acc_ni_si)%r81d, & rio_gdd_si => this%rvars(ir_gdd_si)%r81d, & rio_snow_depth_si => this%rvars(ir_snow_depth_si)%r81d, & @@ -3093,14 +3100,14 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%dstatus = rio_dd_status_si(io_idx_si) sites(s)%nchilldays = rio_nchill_days_si(io_idx_si) sites(s)%ncolddays = rio_ncold_days_si(io_idx_si) - sites(s)%cleafondate = rio_leafondate_si(io_idx_si) - sites(s)%cleafoffdate = rio_leafoffdate_si(io_idx_si) + sites(s)%cleafondate = rio_cleafondate_si(io_idx_si) + sites(s)%cleafoffdate = rio_cleafoffdate_si(io_idx_si) sites(s)%dleafondate = rio_dleafondate_si(io_idx_si) sites(s)%dleafoffdate = rio_dleafoffdate_si(io_idx_si) sites(s)%acc_NI = rio_acc_ni_si(io_idx_si) sites(s)%grow_deg_days = rio_gdd_si(io_idx_si) + sites(s)%phen_model_date= rio_phenmodeldate_si(io_idx_si) sites(s)%snow_depth = rio_snow_depth_si(io_idx_si) - sites(s)%resources_management%trunk_product_site = rio_trunk_product_si(io_idx_si) end do From 2ae674cdbe0f81b884777d3353d6e8b7bfb83beb Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 23 Sep 2022 16:28:07 -0400 Subject: [PATCH 348/852] Updating parameters for CNP, and various code cleaning for CNP --- biogeochem/EDCanopyStructureMod.F90 | 4 +-- biogeochem/EDCohortDynamicsMod.F90 | 39 ++++++++++----------- biogeochem/EDPatchDynamicsMod.F90 | 1 - biogeochem/EDPhysiologyMod.F90 | 19 +++++++--- parameter_files/patch_default_bciopt224.xml | 17 +++++---- parteh/PRTAllometricCNPMod.F90 | 18 +++++----- 6 files changed, 50 insertions(+), 48 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index aed0c855de..e0b1460768 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -18,7 +18,7 @@ module EDCanopyStructureMod use EDCohortDynamicsMod , only : InitPRTObject use EDCohortDynamicsMod , only : InitPRTBoundaryConditions use FatesAllometryMod , only : tree_lai - use FatesAllometryMod , only : tree_sai,bstore_allom + use FatesAllometryMod , only : tree_sai use EDtypesMod , only : ed_site_type, ed_patch_type, ed_cohort_type use EDTypesMod , only : nclmax use EDTypesMod , only : nlevleaf @@ -41,7 +41,6 @@ module EDCanopyStructureMod use PRTGenericMod, only : struct_organ use PRTGenericMod, only : SetState use PRTGenericMod, only : carbon12_element - use FatesRunningMeanMod, only : ema_lpa, ema_60day ! CIME Globals use shr_log_mod , only : errMsg => shr_log_errMsg @@ -143,7 +142,6 @@ subroutine canopy_structure( currentSite , bc_in ) logical :: area_not_balanced ! logical controlling if the patch layer areas ! have successfully been redistributed integer :: return_code ! math checks on variables will return>0 if problems exist - real(r8) :: target_storec ! We only iterate because of possible imprecisions generated by the cohort ! termination process. These should be super small, so at the most ! try to re-balance 3 times. If that doesn't give layer areas diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 17be68ebc6..b59d81f3ea 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -18,8 +18,6 @@ module EDCohortDynamicsMod use FatesConstantsMod , only : fates_unset_r8 use FatesConstantsMod , only : nearzero use FatesConstantsMod , only : calloc_abs_error - use FatesConstantsMod , only : sec_per_day - use FatesRunningMeanMod , only : ema_lpa, ema_60day, ema_storemem use FatesInterfaceTypesMod , only : hlm_days_per_year use FatesInterfaceTypesMod , only : nleafage use SFParamsMod , only : SF_val_CWD_frac @@ -65,7 +63,6 @@ module EDCohortDynamicsMod use FatesAllometryMod , only : bagw_allom use FatesAllometryMod , only : bbgw_allom use FatesAllometryMod , only : bdead_allom - use FatesAllometryMod , only : bstore_allom use FatesAllometryMod , only : h_allom use FatesAllometryMod , only : carea_allom use FatesAllometryMod , only : ForceDBH @@ -95,9 +92,9 @@ module EDCohortDynamicsMod use PRTAllometricCNPMod, only : acnp_bc_in_id_pft, acnp_bc_in_id_ctrim use PRTAllometricCNPMod, only : acnp_bc_in_id_lstat, acnp_bc_inout_id_dbh use PRTAllometricCNPMod, only : acnp_bc_inout_id_l2fr - use PRTAllometricCNPMod, only : acnp_bc_inout_id_emaxc - use PRTAllometricCNPMod, only : acnp_bc_inout_id_xc0 - use PRTAllometricCNPMod, only : acnp_bc_inout_id_emadxcdt + use PRTAllometricCNPMod, only : acnp_bc_inout_id_cx_int + use PRTAllometricCNPMod, only : acnp_bc_inout_id_cx0 + use PRTAllometricCNPMod, only : acnp_bc_inout_id_emadcxdt use PRTAllometricCNPMod, only : acnp_bc_in_id_nc_repro use PRTAllometricCNPMod, only : acnp_bc_in_id_pc_repro use PRTAllometricCNPMod, only : acnp_bc_inout_id_resp_excess, acnp_bc_in_id_netdc @@ -244,9 +241,9 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & new_cohort%l2fr = prt_params%allom_l2fr(pft) - new_cohort%ema_xc = 0._r8 ! Assume balanced N,P/C stores ie log(1) = 0 - new_cohort%xc0 = 0._r8 ! Assume balanced N,P/C stores ie log(1) = 0 - new_cohort%ema_dxcdt = 0._r8 ! Assume unchanged dXC/dt + new_cohort%cx_int = 0._r8 ! Assume balanced N,P/C stores ie log(1) = 0 + new_cohort%cx0 = 0._r8 ! Assume balanced N,P/C stores ie log(1) = 0 + new_cohort%ema_dcxdt = 0._r8 ! Assume unchanged dCX/dt ! This sets things like vcmax25top, that depend on the ! leaf age fractions (which are defined by PARTEH) @@ -429,9 +426,9 @@ subroutine InitPRTBoundaryConditions(new_cohort) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_dbh,bc_rval = new_cohort%dbh) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_resp_excess,bc_rval = new_cohort%resp_excess) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_l2fr,bc_rval = new_cohort%l2fr) - call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_emaxc,bc_rval = new_cohort%ema_xc) - call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_emadxcdt,bc_rval = new_cohort%ema_dxcdt) - call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_xc0,bc_rval = new_cohort%xc0) + call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_cx_int,bc_rval = new_cohort%cx_int) + call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_emadcxdt,bc_rval = new_cohort%ema_dcxdt) + call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_cx0,bc_rval = new_cohort%cx0) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_netdn, bc_rval = new_cohort%daily_n_gain) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_netdp, bc_rval = new_cohort%daily_p_uptake) @@ -1211,12 +1208,12 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) end do end if - currentCohort%ema_xc = (currentCohort%n*currentCohort%ema_xc & - + nextc%n*nextc%ema_xc)/newn - currentCohort%ema_dxcdt = (currentCohort%n*currentCohort%ema_dxcdt & - + nextc%n*nextc%ema_dxcdt)/newn - currentCohort%xc0 = (currentCohort%n*currentCohort%xc0 & - + nextc%n*nextc%xc0)/newn + currentCohort%cx_int = (currentCohort%n*currentCohort%cx_int & + + nextc%n*nextc%cx_int)/newn + currentCohort%ema_dcxdt = (currentCohort%n*currentCohort%ema_dcxdt & + + nextc%n*nextc%ema_dcxdt)/newn + currentCohort%cx0 = (currentCohort%n*currentCohort%cx0 & + + nextc%n*nextc%cx0)/newn ! new cohort age is weighted mean of two cohorts currentCohort%coage = & @@ -1829,9 +1826,9 @@ subroutine copy_cohort( currentCohort,copyc ) n%kp25top = o%kp25top ! Copy over running means - n%ema_xc = o%ema_xc - n%ema_dxcdt = o%ema_dxcdt - n%xc0 = o%xc0 + n%cx_int = o%ema_cx + n%ema_dcxdt = o%ema_dcxdt + n%cx0 = o%cx0 ! CARBON FLUXES n%gpp_acc_hold = o%gpp_acc_hold diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 82ccc3d706..279618f789 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -639,7 +639,6 @@ subroutine spawn_patches( currentSite, bc_in) ! correct boundary condition fields nc%prt => null() call InitPRTObject(nc%prt) - nc%patchptr => new_patch call InitPRTBoundaryConditions(nc) ! (Keeping as an example) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 2d65b371d4..71a513b84e 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1434,7 +1434,6 @@ subroutine assign_cohort_SP_properties(currentCohort,htop,tlai,tsai,parea,init,l ! translates them into a FATES structure with one patch and one cohort per PFT ! The leaf area of the cohort is modified each day to match that asserted by the HLM ! -----------------------------------------------------------------------------------! - use EDTypesMod , only : nclmax type(ed_cohort_type), intent(inout), target :: currentCohort @@ -1829,7 +1828,6 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) allocate(temp_cohort) ! create temporary cohort call zero_cohort(temp_cohort) - do ft = 1,numpft ! The following if block is for the prescribed biogeography and/or nocomp modes. @@ -2555,6 +2553,13 @@ end subroutine CWDOut subroutine UpdateRecruitL2FR(csite) + + ! When CNP is active, the l2fr (target leaf to fine-root biomass multiplier) + ! is dynamic. We therefore update what the l2fr for recruits + ! are, taking an exponential moving average of all plants that + ! are within recruit size limitations (less than recruit size + delta) + ! and less than the max_count cohort. + type(ed_site_type) :: csite type(ed_patch_type), pointer :: cpatch type(ed_cohort_type), pointer :: ccohort @@ -2571,6 +2576,8 @@ subroutine UpdateRecruitL2FR(csite) ! Difference in dbh (cm) to consider a plant was recruited fairly recently + if(hlm_parteh_mode .ne. prt_cnp_flex_allom_hyp) return + rec_n(1:numpft,1:nclmax) = 0._r8 rec_l2fr0(1:numpft,1:nclmax) = 0._r8 @@ -2630,6 +2637,9 @@ subroutine UpdateRecruitStoich(csite) ! Update the total plant stoichiometry of a new recruit, based on the updated ! L2FR values + + if(hlm_parteh_mode .ne. prt_cnp_flex_allom_hyp) return + cpatch => csite%youngest_patch do while(associated(cpatch)) cl = cpatch%ncl_p @@ -2660,15 +2670,14 @@ end subroutine UpdateRecruitStoich subroutine SetRecruitL2FR(csite) - ! I DONT THINK THIS ROUTINE IS ACTUALLY NEEDED... - ! TURN THIS OFF IN A B4B TEST - type(ed_site_type) :: csite type(ed_patch_type), pointer :: cpatch type(ed_cohort_type), pointer :: ccohort integer :: ft,cl + if(hlm_parteh_mode .ne. prt_cnp_flex_allom_hyp) return + cpatch => csite%youngest_patch do while(associated(cpatch)) ccohort => cpatch%shortest diff --git a/parameter_files/patch_default_bciopt224.xml b/parameter_files/patch_default_bciopt224.xml index 9897db82d6..1b02e03e4e 100644 --- a/parameter_files/patch_default_bciopt224.xml +++ b/parameter_files/patch_default_bciopt224.xml @@ -2,17 +2,16 @@ This parameter dataset was created by Ryan Knox rgknox@lbl.gov. Please contact if using in published work. The calibration uses the following datasets: [1] Ely et al. 2019. Leaf mass area, Panama. NGEE-Tropics data collection.http://dx.doi.org/10.15486/ngt/1411973 and [2] Condit et al. 2019. Complete data from the Barro Colorado 50-ha plot. https://doi.org/10.15146/5xcp-0d46. [3] Koven et al. 2019. Benchmarking and parameter sensitivity of physiological and vegetation dynamics using the functionally assembled terrestrial ecosystem simulator. Biogeosciences. The ECA nutrient aquisition parmeters are unconstrained, the file output naming convention vmn6phi is shorthand for vmax for nitrogen uptake is order e-6 and for phosphorus is excessively high. These parameters were calibrated with the special fates modification in main/EDTypesMod.F90: nclmax = 3 fates_params_default.cdl - fates_params_opt224_040822_v2.cdl + fates_params_opt224_040822_api24.cdl 1 - 0 - 0 - 1,1,3,4 - 0.03347526,0.024,1e-08,0.0047 - 0.002675,0.0005,0.00015,0.00015 - 0.0,0,0,0 - 0.45,0.25,0,0 - 0.65,0.25,0,0 + 0 + 0 + 1,1,3,4 + 0.03347526,0.024,1e-08,0.0047 + 0.002675,0.0005,0.00015,0.00015 + 0.45,0.25,0,0 + 0.65,0.25,0,0 0.8012471 30.94711 0.0673 diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 0dc7c5a12d..38f17053b3 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -148,9 +148,9 @@ module PRTAllometricCNPMod ! is dynamic with CNP integer, public, parameter :: acnp_bc_inout_id_netdn = 4 ! Index for the net daily NH4 input BC integer, public, parameter :: acnp_bc_inout_id_netdp = 5 ! Index for the net daily P input BC - integer, public, parameter :: acnp_bc_inout_id_emaxc = 6 ! Index for the EMA log storage ratio max(N,P)/C - integer, public, parameter :: acnp_bc_inout_id_xc0 = 7 ! Index for the previous step's log storage ratio max(N,P)/C - integer, public, parameter :: acnp_bc_inout_id_emadxcdt = 8 ! Index for the EMA log storage ratio derivative d max(NP)/C dt + integer, public, parameter :: acnp_bc_inout_id_cx_int = 6 ! Index for the EMA log storage ratio max(N,P)/C + integer, public, parameter :: acnp_bc_inout_id_cx0 = 7 ! Index for the previous step's log storage ratio max(N,P)/C + integer, public, parameter :: acnp_bc_inout_id_emadcxdt = 8 ! Index for the EMA log storage ratio derivative d max(NP)/C dt integer, public, parameter :: num_bc_inout = 8 ! ------------------------------------------------------------------------------------- @@ -726,7 +726,7 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) real(r8) :: l2fr_mult real(r8) :: l2fr_delta real(r8) :: cn_ratio, cp_ratio - real(r8) :: dxcdt_ratio ! log change (derivative) of the maximum of the N/C and P/C storage ratio + real(r8) :: dcxdt_ratio ! log change (derivative) of the maximum of the N/C and P/C storage ratio real(r8) :: cx_logratio ! log Maximum of the C/N and C/P storage ratio real(r8), pointer :: cx_int ! Integration of the cx_logratio real(r8), pointer :: cx0 ! The log of the cx ratio from previous time-step @@ -750,9 +750,9 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval - cx_int => this%bc_inout(acnp_bc_inout_id_emaxc)%rval - cx0 => this%bc_inout(acnp_bc_inout_id_xc0)%rval - ema_dcxdt => this%bc_inout(acnp_bc_inout_id_emadxcdt)%rval + cx_int => this%bc_inout(acnp_bc_inout_id_cx_int)%rval + cx0 => this%bc_inout(acnp_bc_inout_id_cx0)%rval + ema_dcxdt => this%bc_inout(acnp_bc_inout_id_emadcxdt)%rval ! Step 1: Determine the nutrient to carbon ratio (aka relative health factor) ! ----------------------------------------------------------------------------------- @@ -862,9 +862,9 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) cx_int = cx_int + cx_logratio end if - dxcdt_ratio = cx_logratio-cx0 + dcxdt_ratio = cx_logratio-cx0 - ema_dcxdt = pid_drv_wgt*dxcdt_ratio + (1._r8-pid_drv_wgt)*ema_dcxdt + ema_dcxdt = pid_drv_wgt*dcxdt_ratio + (1._r8-pid_drv_wgt)*ema_dcxdt cx0 = cx_logratio From 5d17995cf86cdcdf003cb35826d5cc2b82e61505 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 23 Sep 2022 19:55:29 -0400 Subject: [PATCH 349/852] Merge resolution fixes between CNP v2 and api24 --- biogeochem/EDCanopyStructureMod.F90 | 6 ++-- biogeochem/EDCohortDynamicsMod.F90 | 2 +- biogeochem/FatesSoilBGCFluxMod.F90 | 2 +- main/EDTypesMod.F90 | 23 ++++++------- main/FatesHistoryInterfaceMod.F90 | 3 +- main/FatesRestartInterfaceMod.F90 | 51 ++++++++++++++--------------- parteh/PRTAllometricCNPMod.F90 | 20 ++++------- parteh/PRTParamsFATESMod.F90 | 10 +++--- 8 files changed, 53 insertions(+), 64 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index e0b1460768..29e4b6fab0 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -678,7 +678,7 @@ subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr,bc_in) endif call copy_cohort(currentCohort, copyc) - call InitPRTBoundaryConditions(copyc,currentCohort%pft,1) + call InitPRTBoundaryConditions(copyc) newarea = currentCohort%c_area - cc_loss copyc%n = currentCohort%n*newarea/currentCohort%c_area @@ -1147,7 +1147,7 @@ subroutine PromoteIntoLayer(currentSite,currentPatch,i_lyr) ! init_value=currentPatch%tveg_lpa%GetMean()) call copy_cohort(currentCohort, copyc) !makes an identical copy... - call InitPRTBoundaryConditions(copyc,currentCohort%pft,2) + call InitPRTBoundaryConditions(copyc) newarea = currentCohort%c_area - cc_gain !new area of existing cohort @@ -2172,7 +2172,7 @@ subroutine UpdateCohortLAI(currentCohort, canopy_layer_tlai, patcharea) real(r8) :: leaf_c ! leaf carbon [kg] ! Obtain the leaf carbon - leaf_c = currentCohort%prt%GetState(leaf_organ,all_carbon_elements) + leaf_c = currentCohort%prt%GetState(leaf_organ,carbon12_element) ! Note that tree_lai has an internal check on the canopy locatoin currentCohort%treelai = tree_lai(leaf_c, currentCohort%pft, currentCohort%c_area, & diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index b59d81f3ea..78ec2a4f8e 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -1826,7 +1826,7 @@ subroutine copy_cohort( currentCohort,copyc ) n%kp25top = o%kp25top ! Copy over running means - n%cx_int = o%ema_cx + n%cx_int = o%cx_int n%ema_dcxdt = o%ema_dcxdt n%cx0 = o%cx0 diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index b176f4c558..19b01b318a 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -946,7 +946,7 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) sum_N = sum_N + area_frac*sum(litt%root_fines_frag)*(tot_fnrt_n / tot_fnrt_c) end if do ipft = 1,numpft - sum_N = sum_N + area_frac * prt_params%nitr_recr_stoich(ipft) * & + sum_N = sum_N + area_frac * currentPatch%nitr_repro_stoich(ipft) * & (litt%seed_decay(ipft) + litt%seed_germ_decay(ipft)) end do diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 5f6ce15539..7d6ffd2b5e 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -219,13 +219,10 @@ module EDTypesMod ! Used for CNP integer :: cnp_limiter ! Which species is limiting growth? ! 0=none,1=C,2=N,3=P - real(r8) :: ema_xc ! Exponential moving average of the log of the error term - ! that controls the l2fr set-point in the PID controller - ! the term is probably a ratio of storage or a ratio of - ! gain efficiencies - real(r8) :: ema_dxcdt ! The derivative of ema_xc per day - real(r8) :: xc0 ! The value on the previous time-step of the log of - ! the PID error term (not smoothed) + real(r8) :: cx_int ! The time integration of the log of the relative carbon storage over relative nutrient + real(r8) :: ema_dcxdt ! The derivative of the log of the relative carbon storage over relative nutrient + real(r8) :: cx0 ! The value on the previous time-step of log of the relative carbon + ! storage over relative nutrient real(r8) :: nc_repro ! The NC ratio of a new recruit in this patch real(r8) :: pc_repro ! The PC ratio of a new recruit in this patch @@ -1081,12 +1078,12 @@ subroutine dump_cohort(ccohort) write(fates_log(),*) 'co%hite = ', ccohort%hite write(fates_log(),*) 'co%coage = ', ccohort%coage write(fates_log(),*) 'co%l2fr = ', ccohort%l2fr - write(fates_log(),*) 'leaf carbon = ', ccohort%prt%GetState(leaf_organ,all_carbon_elements) - write(fates_log(),*) 'fineroot carbon = ', ccohort%prt%GetState(fnrt_organ,all_carbon_elements) - write(fates_log(),*) 'sapwood carbon = ', ccohort%prt%GetState(sapw_organ,all_carbon_elements) - write(fates_log(),*) 'structural (dead) carbon = ', ccohort%prt%GetState(struct_organ,all_carbon_elements) - write(fates_log(),*) 'storage carbon = ', ccohort%prt%GetState(store_organ,all_carbon_elements) - write(fates_log(),*) 'reproductive carbon = ', ccohort%prt%GetState(repro_organ,all_carbon_elements) + write(fates_log(),*) 'leaf carbon = ', ccohort%prt%GetState(leaf_organ,carbon12_element) + write(fates_log(),*) 'fineroot carbon = ', ccohort%prt%GetState(fnrt_organ,carbon12_element) + write(fates_log(),*) 'sapwood carbon = ', ccohort%prt%GetState(sapw_organ,carbon12_element) + write(fates_log(),*) 'structural (dead) carbon = ', ccohort%prt%GetState(struct_organ,carbon12_element) + write(fates_log(),*) 'storage carbon = ', ccohort%prt%GetState(store_organ,carbon12_element) + write(fates_log(),*) 'reproductive carbon = ', ccohort%prt%GetState(repro_organ,carbon12_element) write(fates_log(),*) 'co%g_sb_laweight = ', ccohort%g_sb_laweight write(fates_log(),*) 'co%leaf_cost = ', ccohort%leaf_cost write(fates_log(),*) 'co%canopy_layer = ', ccohort%canopy_layer diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index c7efa7edb9..15b3d0485e 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -249,7 +249,6 @@ module FatesHistoryInterfaceMod integer :: ih_fates_fraction_si integer :: ih_ba_weighted_height_si integer :: ih_ca_weighted_height_si - integer :: ih_cwd_elcwd integer :: ih_litter_in_si ! carbon only integer :: ih_litter_out_si ! carbon only integer :: ih_seed_bank_si ! carbon only @@ -5304,7 +5303,7 @@ subroutine define_history_vars(this, initialize_variables) call this%set_history_var(vname='FATES_FROOTC_SL', units='kg m-3', & long='Total carbon in live plant fine-roots over depth', use_default='active', & - avgflag='A', vtype=site_ground_r8, hlms='CLM:ALM', upfreq=1, & + avgflag='A', vtype=site_soil_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_fnrtc_sl ) call this%set_history_var(vname='FATES_REPROC', units='kg m-2', & diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index e7a9a2db8e..c3e9566f2d 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -97,9 +97,9 @@ module FatesRestartInterfaceMod integer :: ir_canopy_layer_yesterday_co integer :: ir_canopy_trim_co integer :: ir_l2fr_co - integer :: ir_emaxc_co - integer :: ir_emadxcdt_co - integer :: ir_xc0_co + integer :: ir_cx_int_co + integer :: ir_emadcxdt_co + integer :: ir_cx0_co integer :: ir_pc_store_co integer :: ir_size_class_lasttimestep_co integer :: ir_dbh_co @@ -704,17 +704,17 @@ subroutine define_restart_vars(this, initialize_variables) long_name='ed cohort - l2fr', units='fraction', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_l2fr_co ) - call this%set_restart_var(vname='fates_emaxc', vtype=cohort_r8, & - long_name='ed cohort - emaxc', units='fraction', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_emaxc_co ) + call this%set_restart_var(vname='fates_cx_int', vtype=cohort_r8, & + long_name='ed cohort - emacx', units='fraction', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_cx_int_co ) - call this%set_restart_var(vname='fates_emadxcdt', vtype=cohort_r8, & - long_name='ed cohort - emadxcdt', units='fraction', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_emadxcdt_co ) + call this%set_restart_var(vname='fates_emadcxdt', vtype=cohort_r8, & + long_name='ed cohort - emadcxdt', units='fraction', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_emadcxdt_co ) - call this%set_restart_var(vname='fates_xc0', vtype=cohort_r8, & - long_name='ed cohort - xc0', units='fraction', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_xc0_co ) + call this%set_restart_var(vname='fates_cx0', vtype=cohort_r8, & + long_name='ed cohort - cx0', units='fraction', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_cx0_co ) call this%set_restart_var(vname='fates_size_class_lasttimestep', vtype=cohort_int, & long_name='ed cohort - size-class last timestep', units='index', flushval = flushzero, & @@ -1746,9 +1746,9 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_canopy_layer_yesterday_co => this%rvars(ir_canopy_layer_yesterday_co)%r81d, & rio_canopy_trim_co => this%rvars(ir_canopy_trim_co)%r81d, & rio_l2fr_co => this%rvars(ir_l2fr_co)%r81d, & - rio_emaxc_co => this%rvars(ir_emaxc_co)%r81d, & - rio_emadxcdt_co => this%rvars(ir_emadxcdt_co)%r81d, & - rio_xc0_co => this%rvars(ir_xc0_co)%r81d, & + rio_cx_int_co => this%rvars(ir_cx_int_co)%r81d, & + rio_emadcxdt_co => this%rvars(ir_emadcxdt_co)%r81d, & + rio_cx0_co => this%rvars(ir_cx0_co)%r81d, & rio_seed_prod_co => this%rvars(ir_seed_prod_co)%r81d, & rio_size_class_lasttimestep => this%rvars(ir_size_class_lasttimestep_co)%int1d, & rio_dbh_co => this%rvars(ir_dbh_co)%r81d, & @@ -1964,9 +1964,9 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_canopy_layer_yesterday_co(io_idx_co) = ccohort%canopy_layer_yesterday rio_canopy_trim_co(io_idx_co) = ccohort%canopy_trim rio_l2fr_co(io_idx_co) = ccohort%l2fr - rio_emaxc_co(io_idx_co) = ccohort%ema_xc - rio_emadxcdt_co(io_idx_co) = ccohort%ema_dxcdt - rio_xc0_co(io_idx_co) = ccohort%xc0 + rio_cx_int_co(io_idx_co) = ccohort%cx_int + rio_emadcxdt_co(io_idx_co) = ccohort%ema_dcxdt + rio_cx0_co(io_idx_co) = ccohort%cx0 rio_seed_prod_co(io_idx_co) = ccohort%seed_prod rio_size_class_lasttimestep(io_idx_co) = ccohort%size_class_lasttimestep rio_dbh_co(io_idx_co) = ccohort%dbh @@ -2577,9 +2577,9 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_canopy_layer_yesterday_co => this%rvars(ir_canopy_layer_yesterday_co)%r81d, & rio_canopy_trim_co => this%rvars(ir_canopy_trim_co)%r81d, & rio_l2fr_co => this%rvars(ir_l2fr_co)%r81d, & - rio_emaxc_co => this%rvars(ir_emaxc_co)%r81d, & - rio_emadxcdt_co => this%rvars(ir_emadxcdt_co)%r81d, & - rio_xc0_co => this%rvars(ir_xc0_co)%r81d, & + rio_cx_int_co => this%rvars(ir_cx_int_co)%r81d, & + rio_emadcxdt_co => this%rvars(ir_emadcxdt_co)%r81d, & + rio_cx0_co => this%rvars(ir_cx0_co)%r81d, & rio_seed_prod_co => this%rvars(ir_seed_prod_co)%r81d, & rio_size_class_lasttimestep => this%rvars(ir_size_class_lasttimestep_co)%int1d, & rio_dbh_co => this%rvars(ir_dbh_co)%r81d, & @@ -2767,9 +2767,9 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ccohort%canopy_layer_yesterday = rio_canopy_layer_yesterday_co(io_idx_co) ccohort%canopy_trim = rio_canopy_trim_co(io_idx_co) ccohort%l2fr = rio_l2fr_co(io_idx_co) - ccohort%ema_xc = rio_emaxc_co(io_idx_co) - ccohort%ema_dxcdt = rio_emadxcdt_co(io_idx_co) - ccohort%xc0 = rio_xc0_co(io_idx_co) + ccohort%cx_int = rio_cx_int_co(io_idx_co) + ccohort%ema_dcxdt = rio_emadcxdt_co(io_idx_co) + ccohort%cx0 = rio_cx0_co(io_idx_co) ccohort%seed_prod = rio_seed_prod_co(io_idx_co) ccohort%size_class_lasttimestep = rio_size_class_lasttimestep(io_idx_co) ccohort%dbh = rio_dbh_co(io_idx_co) @@ -2812,10 +2812,9 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ccohort%status_coh = rio_status_co(io_idx_co) ccohort%isnew = ( rio_isnew_co(io_idx_co) .eq. new_cohort ) - call InitPRTBoundaryConditions(ccohort,ccohort%pft,4) + call InitPRTBoundaryConditions(ccohort) call UpdateCohortBioPhysRates(ccohort) - ! Initialize Plant Hydraulics if(hlm_use_planthydro==itrue)then diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 38f17053b3..66b9a55cfa 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -568,7 +568,6 @@ subroutine DailyPRTAllometricCNP(this,co_num,nplant) ! =================================================================================== call this%CNPAllocateRemainder(c_gain, n_gain, p_gain, & - c_gain0, n_gain0, p_gain0, & c_efflux, n_efflux, p_efflux,co_num,nplant,target_c,target_dcdd) @@ -1867,16 +1866,13 @@ end subroutine CNPStatureGrowth ! ===================================================================================== subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & - c_gain0, n_gain0, p_gain0, & - c_efflux, n_efflux, p_efflux,co_num,nplant,target_c,target_dcdd) + c_efflux, n_efflux, p_efflux, & + co_num,nplant,target_c,target_dcdd) class(cnp_allom_prt_vartypes) :: this real(r8), intent(inout) :: c_gain real(r8), intent(inout) :: n_gain real(r8), intent(inout) :: p_gain - real(r8), intent(in) :: c_gain0 ! Total C gain for the day - real(r8), intent(in) :: n_gain0 ! Total N gain for the day - real(r8), intent(in) :: p_gain0 ! Total P gain for the day real(r8), intent(inout) :: c_efflux real(r8), intent(inout) :: n_efflux real(r8), intent(inout) :: p_efflux @@ -1913,11 +1909,11 @@ subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & do i = 1, num_organs ! Update the nitrogen and phosphorus deficits - target_n = this%GetNutrientTarget(nitrogen_element,organ_list(i),stoich_growth_min) - deficit_n(i) = max(0._r8,this%GetDeficit(nitrogen_element,organ_list(i),target_n)) + target_n = this%GetNutrientTarget(nitrogen_element,l2g_organ_list(i),stoich_growth_min) + deficit_n(i) = max(0._r8,this%GetDeficit(nitrogen_element,l2g_organ_list(i),target_n)) - target_p = this%GetNutrientTarget(phosphorus_element,organ_list(i),stoich_growth_min) - deficit_p(i) = max(0._r8,this%GetDeficit(phosphorus_element,organ_list(i),target_p)) + target_p = this%GetNutrientTarget(phosphorus_element,l2g_organ_list(i),stoich_growth_min) + deficit_p(i) = max(0._r8,this%GetDeficit(phosphorus_element,l2g_organ_list(i),target_p)) end do @@ -1935,9 +1931,7 @@ subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & p_gain, phosphorus_element, l2g_organ_list(1:num_organs)) call this%CNPAdjustFRootTargets(target_c,target_dcdd,co_num,nplant) - - - + ! ----------------------------------------------------------------------------------- ! If carbon is still available, lets cram some into storage overflow ! We will do this last, because we wanted the non-overflow storage diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index feee2db976..0776c0d412 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -548,23 +548,23 @@ subroutine PRTReceivePFT(fates_params) data=prt_params%allom_l2fr) name = 'fates_cnp_pid_kp' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%pid_kp) name = 'fates_cnp_pid_ki' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%pid_ki) name = 'fates_cnp_pid_kd' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%pid_kd) name = 'fates_cnp_store_ovrflw_frac' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%store_ovrflw_frac) name = 'fates_nfix1' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%nfix_mresp_scfrac) name = 'fates_allom_agb_frac' From bec8928c4ab01e634df7afdb242c992819c9ef4e Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Fri, 23 Sep 2022 17:19:35 -0700 Subject: [PATCH 350/852] Tidy up some debugging print statements --- biogeochem/DamageMainMod.F90 | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/biogeochem/DamageMainMod.F90 b/biogeochem/DamageMainMod.F90 index cc336ec390..b56fd0363e 100644 --- a/biogeochem/DamageMainMod.F90 +++ b/biogeochem/DamageMainMod.F90 @@ -177,9 +177,6 @@ subroutine GetCrownReduction(crowndamage, crown_reduction) crown_reduction = ED_val_history_damage_bin_edges(crowndamage)/100.0_r8 - write(fates_log(),*) 'JN crowndamage', crowndamage - write(fates_log(),*) 'JN crownreduction', crown_reduction - return end subroutine GetCrownReduction @@ -217,7 +214,7 @@ subroutine GetDamageMortality(crowndamage,pft, dgmort) ! make damage mortality a function of crownloss and not crowndamage ! class so that it doesn't need to be re-parameterised if the number ! of damage classes change. - crown_loss = ED_val_history_damage_bin_edges(crowndamage)/ 100.0_r8 + crown_loss = ED_val_history_damage_bin_edges(crowndamage)/100.0_r8 if (crowndamage .eq. 1 ) then dgmort = 0.0_r8 From 26ee58219548cda3137f51e872c72953261380b7 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 23 Sep 2022 21:20:28 -0400 Subject: [PATCH 351/852] merge resolutions and parameter stuff --- main/EDPftvarcon.F90 | 20 +++++++++++++------- main/FatesInterfaceMod.F90 | 7 ++++--- main/FatesInterfaceTypesMod.F90 | 4 +++- parameter_files/apichange_24to25.xml | 13 +++++++++++++ 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 51df007c78..aeac0a9f29 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -134,10 +134,16 @@ module EDPftvarcon ! Nutrient Aquisition (ECA & RD) - !real(r8), allocatable :: rd_vmax_n(:) ! maximum production rate for plant n uptake [gN/gC/s] real(r8), allocatable :: decompmicc(:) ! microbial decomposer biomass gC/m3 ! on root surface + real(r8), allocatable :: vmax_nh4(:) ! maximum production rate for plant N uptake + ! For ECA: this is just ammonium: nh4 uptake [gN/gC/s] + ! For RD: this is the uptake of both (we can't have + ! unique parameter for RD, because it want's one demand, + ! and uses this vmax to set the demand, first drawing from + ! NH4 and then NO3 + ! ECA Parameters: See Zhu et al. Multiple soil nutrient competition between plants, ! microbes, and mineral surfaces: model development, parameterization, ! and example applications in several tropical forests. Biogeosciences, @@ -145,9 +151,9 @@ module EDPftvarcon ! KM: Michaeles-Menten half-saturation constants for ECA (plant–enzyme affinity) ! VMAX: Product of the reaction-rate and enzyme abundance for each PFT in ECA ! Note*: units of [gC] is grams carbon of fine-root - + real(r8), allocatable :: eca_km_nh4(:) ! half-saturation constant for plant nh4 uptake [gN/m3] - real(r8), allocatable :: eca_vmax_nh4(:) ! maximum production rate for plant nh4 uptake [gN/gC/s] + real(r8), allocatable :: eca_km_no3(:) ! half-saturation constant for plant no3 uptake [gN/m3] real(r8), allocatable :: eca_vmax_no3(:) ! maximum production rate for plant no3 uptake [gN/gC/s] real(r8), allocatable :: eca_km_p(:) ! half-saturation constant for plant p uptake [gP/m3] @@ -577,7 +583,7 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_cnp_eca_vmax_nh4' + name = 'fates_cnp_vmax_nh4' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -928,10 +934,10 @@ subroutine Receive_PFT(this, fates_params) name = 'fates_cnp_eca_km_nh4' call fates_params%RetrieveParameterAllocate(name=name, & data=this%eca_km_nh4) - - name = 'fates_cnp_eca_vmax_nh4' + + name = 'fates_cnp_vmax_nh4' call fates_params%RetrieveParameterAllocate(name=name, & - data=this%eca_vmax_nh4) + data=this%vmax_nh4) name = 'fates_cnp_eca_km_no3' call fates_params%RetrieveParameterAllocate(name=name, & diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 97d772fbc7..98eeb6d0c0 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -202,9 +202,9 @@ subroutine allocate_bcpconst(bc_pconst,nlevdecomp) type(bc_pconst_type), intent(inout) :: bc_pconst integer , intent(in) :: nlevdecomp - + + allocate(bc_pconst%vmax_nh4(numpft)) allocate(bc_pconst%eca_km_nh4(numpft)) - allocate(bc_pconst%eca_vmax_nh4(numpft)) allocate(bc_pconst%eca_km_no3(numpft)) allocate(bc_pconst%eca_vmax_no3(numpft)) allocate(bc_pconst%eca_km_p(numpft)) @@ -226,8 +226,9 @@ subroutine set_bcpconst(bc_pconst,nlevdecomp) integer , intent(in) :: nlevdecomp integer :: j + bc_pconst%vmax_nh4(1:numpft) = EDPftvarcon_inst%vmax_nh4(1:numpft) + bc_pconst%eca_km_nh4(1:numpft) = EDPftvarcon_inst%eca_km_nh4(1:numpft) - bc_pconst%eca_vmax_nh4(1:numpft) = EDPftvarcon_inst%eca_vmax_nh4(1:numpft) bc_pconst%eca_km_no3(1:numpft) = EDPftvarcon_inst%eca_km_no3(1:numpft) bc_pconst%eca_vmax_no3(1:numpft) = EDPftvarcon_inst%eca_vmax_no3(1:numpft) bc_pconst%eca_km_p(1:numpft) = EDPftvarcon_inst%eca_km_p(1:numpft) diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 4083c41a9a..be482a96ad 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -741,8 +741,10 @@ module FatesInterfaceTypesMod ! each column is inefficient. Each of these are dimensioned by PFT. integer :: max_plant_comps + + real(r8), pointer :: vmax_nh4(:) + real(r8), pointer :: eca_km_nh4(:) - real(r8), pointer :: eca_vmax_nh4(:) real(r8), pointer :: eca_km_no3(:) real(r8), pointer :: eca_vmax_no3(:) real(r8), pointer :: eca_km_p(:) diff --git a/parameter_files/apichange_24to25.xml b/parameter_files/apichange_24to25.xml index 44f37eefa3..f30eaa4860 100644 --- a/parameter_files/apichange_24to25.xml +++ b/parameter_files/apichange_24to25.xml @@ -20,6 +20,19 @@ fates_cnp_fnrt_adapt_tscale + + fates_cnp_eca_vmax_nh4 + + + fates_cnp_rd_vmax_n + + + fates_cnp_vmax_nh4 + fates_pft + gN/gC/s + maximum (potential) uptake rate of N (for RD) or NH4 (for ECA) per gC of fineroot biomass + 5e-9, 5e-9, 5e-9, 5e-9, 5e-9, 5e-9, 5e-9, 5e-9, 5e-9, 5e-9, 5e-9, 5e-9 + fates_cnp_pid_kd fates_pft From 6e019d2a296cb5576f311c46c1ad372b2c96ca32 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 23 Sep 2022 21:22:38 -0400 Subject: [PATCH 352/852] Updates to parameter file --- parameter_files/fates_params_default.cdl | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index c1388cd90b..221a559e3f 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -188,9 +188,6 @@ variables: double fates_cnp_eca_lambda_ptase(fates_pft) ; fates_cnp_eca_lambda_ptase:units = "g/m3" ; fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; - double fates_cnp_eca_vmax_nh4(fates_pft) ; - fates_cnp_eca_vmax_nh4:units = "gN/gC/s" ; - fates_cnp_eca_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA)" ; double fates_cnp_eca_vmax_no3(fates_pft) ; fates_cnp_eca_vmax_no3:units = "gN/gC/s" ; fates_cnp_eca_vmax_no3:long_name = "maximum production rate for plant no3 uptake (ECA)" ; @@ -221,9 +218,6 @@ variables: double fates_cnp_prescribed_puptake(fates_pft) ; fates_cnp_prescribed_puptake:units = "fraction" ; fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; - double fates_cnp_rd_vmax_n(fates_pft) ; - fates_cnp_rd_vmax_n:units = "gN/gC/s" ; - fates_cnp_rd_vmax_n:long_name = "maximum production rate for compbined (NH4+NO3) uptake (RD)" ; double fates_cnp_store_ovrflw_frac(fates_pft) ; fates_cnp_store_ovrflw_frac:units = "fraction" ; fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; @@ -233,6 +227,9 @@ variables: double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; fates_cnp_turnover_phos_retrans:units = "fraction" ; fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; + double fates_cnp_vmax_nh4(fates_pft) ; + fates_cnp_vmax_nh4:units = "gN/gC/s" ; + fates_cnp_vmax_nh4:long_name = "maximum (potential) uptake rate of N (for RD) or NH4 (for ECA) per gC of fineroot biomass" ; double fates_cnp_vmax_p(fates_pft) ; fates_cnp_vmax_p:units = "gP/gC/s" ; fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; @@ -971,9 +968,6 @@ data: fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_cnp_eca_vmax_nh4 = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, - 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - fates_cnp_eca_vmax_no3 = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; @@ -999,9 +993,6 @@ data: fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_cnp_rd_vmax_n = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, - 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_cnp_turnover_nitr_retrans = @@ -1016,6 +1007,9 @@ data: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_cnp_vmax_nh4 = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09 ; + fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10 ; From 06757edb661ae1bda939836ef9dc2016f3eadaac Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 23 Sep 2022 21:31:14 -0400 Subject: [PATCH 353/852] updating patch files --- parameter_files/patch_default_bciopt224.xml | 22 ++++++++++----------- parameter_files/patch_default_e3smtest.xml | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/parameter_files/patch_default_bciopt224.xml b/parameter_files/patch_default_bciopt224.xml index 1b02e03e4e..ba44feab36 100644 --- a/parameter_files/patch_default_bciopt224.xml +++ b/parameter_files/patch_default_bciopt224.xml @@ -2,7 +2,7 @@ This parameter dataset was created by Ryan Knox rgknox@lbl.gov. Please contact if using in published work. The calibration uses the following datasets: [1] Ely et al. 2019. Leaf mass area, Panama. NGEE-Tropics data collection.http://dx.doi.org/10.15486/ngt/1411973 and [2] Condit et al. 2019. Complete data from the Barro Colorado 50-ha plot. https://doi.org/10.15146/5xcp-0d46. [3] Koven et al. 2019. Benchmarking and parameter sensitivity of physiological and vegetation dynamics using the functionally assembled terrestrial ecosystem simulator. Biogeosciences. The ECA nutrient aquisition parmeters are unconstrained, the file output naming convention vmn6phi is shorthand for vmax for nitrogen uptake is order e-6 and for phosphorus is excessively high. These parameters were calibrated with the special fates modification in main/EDTypesMod.F90: nclmax = 3 fates_params_default.cdl - fates_params_opt224_040822_api24.cdl + fates_params_opt224_040822_api25.cdl 1 0 @@ -12,7 +12,7 @@ 0.002675,0.0005,0.00015,0.00015 0.45,0.25,0,0 0.65,0.25,0,0 - 0.8012471 + 0.8012471 30.94711 0.0673 0.976 @@ -31,21 +31,21 @@ 2 5 0.4863088 - 0.0 + 0.0 1 3 - 5e-09 - 5e-09 - 5e-10 - 3e-08 + 5e-09 + 5e-09 + 5e-10 + 3e-08 0.03991654 0.01995827 0.01303514 0.02955703 - 3 - 3 - 0.04680188 - 0.001 + 3 + 3 + 0.04680188 + 0.001 0.8374751 -1 0.5 diff --git a/parameter_files/patch_default_e3smtest.xml b/parameter_files/patch_default_e3smtest.xml index 01111c2200..56dbb9b844 100644 --- a/parameter_files/patch_default_e3smtest.xml +++ b/parameter_files/patch_default_e3smtest.xml @@ -4,7 +4,7 @@ fates_params_e3smtest.cdl 1,2,3,4,5,6,7,8,9,10,11,12 - 0,0,0,0,0,0,0,0,0,0,0,0 - 0,0,0,0,0,0,0,0,0,0,0,0 + 0,0,0,0,0,0,0,0,0,0,0,0 + 0,0,0,0,0,0,0,0,0,0,0,0 From 4465d7cd00fe541950803039d6ab0d319f221366 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Sun, 25 Sep 2022 19:28:12 -0400 Subject: [PATCH 354/852] More merge resolutions between cnp v2 and api24 --- biogeochem/FatesSoilBGCFluxMod.F90 | 2 +- main/FatesHistoryInterfaceMod.F90 | 16 ++++++++-------- parteh/PRTAllometricCNPMod.F90 | 13 +++++++------ parteh/PRTParamsFATESMod.F90 | 4 ++-- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index 19b01b318a..ce51586123 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -153,7 +153,7 @@ function GetPlantDemand(ccohort,element_id) result(plant_demand) if(element_id.eq.nitrogen_element) then - plant_demand = fnrt_c * EDPftvarcon_inst%eca_vmax_nh4(ccohort%pft) * sec_per_day + plant_demand = fnrt_c * EDPftvarcon_inst%vmax_nh4(ccohort%pft) * sec_per_day elseif(element_id.eq.phosphorus_element) then diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 15b3d0485e..da59b0d803 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -5259,18 +5259,18 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_storec_si) - call this%set_history_var(vname='FATES_STOREC_TFRAC', units='kg kg-1', & + call this%set_history_var(vname='FATES_STOREC_TF', units='kg kg-1', & long='Storage C fraction of target', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_storectfrac_si ) - call this%set_history_var(vname='FATES_STOREC_TFRAC_USTORY_SZPF', units='kg kg-1', & + call this%set_history_var(vname='FATES_STOREC_TF_USTORY_SZPF', units='kg kg-1', & long='Storage C fraction of target by size x pft, in the understory', use_default='inactive', & avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_storectfrac_ustory_scpf ) - call this%set_history_var(vname='FATES_STOREC_TFRAC_CANOPY_SZPF', units='kg kg-1', & + call this%set_history_var(vname='FATES_STOREC_TF_CANOPY_SZPF', units='kg kg-1', & long='Storage C fraction of target by size x pft, in the canopy', use_default='inactive', & avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_storectfrac_canopy_scpf ) @@ -5423,7 +5423,7 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_storen_si) - call this%set_history_var(vname='FATES_STOREN_TFRAC', units='1', & + call this%set_history_var(vname='FATES_STOREN_TF', units='1', & long='storage N fraction of target', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index = ih_storentfrac_si) @@ -5485,14 +5485,14 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index = ih_storen_scpf) - call this%set_history_var(vname='FATES_STOREN_TFRAC_CANOPY_SZPF', & + call this%set_history_var(vname='FATES_STOREN_TF_CANOPY_SZPF', & units='1', & long='storage nitrogen fraction (0-1) of target, in canopy, by size-class x pft', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index = ih_storentfrac_canopy_scpf) - call this%set_history_var(vname='FATES_STOREN_TFRAC_USTORY_SZPF', & + call this%set_history_var(vname='FATES_STOREN_TF_USTORY_SZPF', & units='1', & long='storage nitrogen fraction (0-1) of target, in understory, by size-class x pft', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & @@ -5519,7 +5519,7 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_storep_si) - call this%set_history_var(vname='FATES_STOREP_TFRAC', units='1', & + call this%set_history_var(vname='FATES_STOREP_TF', units='1', & long='storage P fraction of target', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, & @@ -7213,7 +7213,7 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index = ih_storep_scpf) - call this%set_history_var(vname='FATES_STOREP_TFRAC_CANOPY_SZPF', & + call this%set_history_var(vname='FATES_STOREP_TF_CANOPY_SZPF', & units='1', & long='storage phosphorus fraction (0-1) of target, in canopy, by size-class x pft', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 66b9a55cfa..36a25d9712 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -739,7 +739,8 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) integer, parameter :: pid_minnc_function = 2 integer, parameter :: pid_alogmaxnc_function = 3 integer, parameter :: pid_ncratio_function = 4 - + integer, parameter :: pid_function = pid_ncratio_function + ! If we do not have leaves out, then the relative nutrient vs carbon ! balancing is meaningless, just leave this routine if(this%GetState(leaf_organ, carbon12_element)/target_c(leaf_organ) < 0.5_r8) return @@ -772,7 +773,7 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) this%GetState(store_organ, nitrogen_element) + & this%bc_inout(acnp_bc_inout_id_netdn)%rval) - select case(pid_ncratio_function) + select case(pid_function) case(pid_c_function) n_ratio = store_c_act/store_c_max case(pid_n_function) @@ -812,7 +813,7 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) this%GetState(store_organ, phosphorus_element) + & this%bc_inout(acnp_bc_inout_id_netdp)%rval) - select case(pid_ncratio_function) + select case(pid_function) case(pid_c_function) p_ratio = store_c_act/store_c_max case(pid_n_function) @@ -914,15 +915,15 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) !c_fnrt_expand = (l2fr+l2fr_delta_max)*target_c(leaf_organ) - l2fr*target_c(leaf_organ) !c_fnrt_expand = l2fr_delta_max*target_c(leaf_organ) - l2fr_delta_max = max(0._r8,c_fnrt_expand/target_c(leaf_organ)) + !l2fr_delta_max = max(0._r8,c_fnrt_expand/target_c(leaf_organ)) ! Apply the delta, also, avoid generating incredibly small l2fr's, ! super small l2frs will occur in plants that perpetually get almost ! now carbon gain, such as newly recruited plants in a dark understory - !l2fr = max(l2fr_min, l2fr + l2fr_delta) + l2fr = max(l2fr_min, l2fr + l2fr_delta) - l2fr = max(l2fr_min, l2fr + min(l2fr_delta_max,l2fr_delta)) + !l2fr = max(l2fr_min, l2fr + min(l2fr_delta_max,l2fr_delta)) !if((co_num==1) .or. (co_num==2)) print*,'AAX1',co_num,hlm_current_year,hlm_day_of_year, & ! dbh,nplant,(store_c_act/store_c_max),cn_ratio,SafeLog(cn_ratio),l2fr diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index 0776c0d412..06e6ae20e8 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -252,7 +252,7 @@ subroutine PRTRegisterPFT(fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_nfix1' + name = 'fates_cnp_nfix1' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -563,7 +563,7 @@ subroutine PRTReceivePFT(fates_params) call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%store_ovrflw_frac) - name = 'fates_nfix1' + name = 'fates_cnp_nfix1' call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%nfix_mresp_scfrac) From 3efa3d0e557e80a8520fe30bef550a3f84d5b2b2 Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Mon, 26 Sep 2022 16:32:34 -0700 Subject: [PATCH 355/852] Fix damage transition matrix to account for flexible damage bins --- main/FatesParameterDerivedMod.F90 | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/main/FatesParameterDerivedMod.F90 b/main/FatesParameterDerivedMod.F90 index 1a2ff4e856..0eacab293f 100644 --- a/main/FatesParameterDerivedMod.F90 +++ b/main/FatesParameterDerivedMod.F90 @@ -141,11 +141,27 @@ subroutine InitDamageTransitions(this, numpft) ! local variables integer :: ft ! pft index integer :: i ! crowndamage index + integer :: j ! damage bin index real(r8) :: damage_frac ! damage fraction - real(r8) :: class_widths ! widths of each damage class + real(r8), allocatable :: damage_bin_edges_ex(:) ! including the upper bound of 100 + real(r8), allocatable :: class_widths(:) ! widths of each damage class call this%InitAllocateDamageTransitions(numpft) + + allocate(class_widths(1:nlevdamage)) + allocate(damage_bin_edges_ex(1:(nlevdamage+1))) + ! class widths + ! append 100 to ED_val_history_damage_bin_edges + do j = 1,nlevdamage + damage_bin_edges_ex(j) = ED_val_history_damage_bin_edges(j) + end do + damage_bin_edges_ex(j) = 100.0_r8 + + ! gets class widths (something like below) + class_widths = damage_bin_edges_ex(2:(nlevdamage+1)) - & + damage_bin_edges_ex(1:nlevdamage) + do ft = 1, numpft damage_frac = EDPftvarcon_inst%damage_frac(ft) @@ -157,16 +173,11 @@ subroutine InitDamageTransitions(this, numpft) ! damage rate stays the same this%damage_transitions(i,i,ft) = 1.0_r8 - damage_frac - ! class widths - ! append 100 to ED_val_history_damage_bin_edges - ! gets class widths (something like below) - !class_widths = ED_val_history_damage_bin_edges(2:nlevdamage) - & - ! ED_val_history_damage_bin_edges(1:(nlevdamage-1)) if(i < nlevdamage) then ! fraction damaged get split according to class width -! this%damage_transitions(i,i+1:nlevdamage,ft) = damage_frac/ & - ! sum(class_widths(i+1:nlevdamage)) * class_widths(i+1:nlevdamage) + this%damage_transitions(i,i+1:nlevdamage,ft) = damage_frac * & + class_widths(i+1:nlevdamage)/ SUM(class_widths(i+1:nlevdamage)) end if ! Make sure it sums to one - they have to go somewhere this%damage_transitions(i, :, ft) = this%damage_transitions(i, :, ft)/SUM(this%damage_transitions(i, :, ft)) From 0251401c2926f6c4087673b2736913ff42ca9b0a Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Mon, 26 Sep 2022 16:33:09 -0700 Subject: [PATCH 356/852] add crowndamage to allometry calls in EDPhysiologyMod --- biogeochem/EDPhysiologyMod.F90 | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index e9a28b63fd..7cdbc28ba4 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1296,10 +1296,12 @@ subroutine phenology_leafonoff(currentSite) currentCohort%status_coh = leaves_on ! Leaves are on, so change status to ! stop flow of carbon out of bstore. - call bleaf(currentCohort%dbh,currentCohort%pft,currentCohort%canopy_trim,target_leaf_c) - call bsap_allom(currentCohort%dbh,currentCohort%pft, & + call bleaf(currentCohort%dbh,currentCohort%pft,currentCohort%crowndamage, & + currentCohort%canopy_trim,target_leaf_c) + call bsap_allom(currentCohort%dbh,currentCohort%pft,currentCohort%crowndamage, & currentCohort%canopy_trim,sapw_area,target_sapw_c) - call bagw_allom(currentCohort%dbh,currentCohort%pft,target_agw_c) + call bagw_allom(currentCohort%dbh,currentCohort%pft,currentCohort%crowndamage,& + target_agw_c) call bbgw_allom(currentCohort%dbh,currentCohort%pft,target_bgw_c) call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, & currentCohort%pft, target_struct_c) @@ -1400,11 +1402,12 @@ subroutine phenology_leafonoff(currentSite) currentCohort%status_coh = leaves_on ! Leaves are on, so change status to ! stop flow of carbon out of bstore. - call bleaf(currentCohort%dbh,currentCohort%pft,& + call bleaf(currentCohort%dbh,currentCohort%pft,currentCohort%crowndamage,& currentCohort%canopy_trim,target_leaf_c) - call bsap_allom(currentCohort%dbh,currentCohort%pft, & + call bsap_allom(currentCohort%dbh,currentCohort%pft,currentCohort%crowndamage,& currentCohort%canopy_trim,sapw_area,target_sapw_c) - call bagw_allom(currentCohort%dbh,currentCohort%pft,target_agw_c) + call bagw_allom(currentCohort%dbh,currentCohort%pft,currentCohort%crowndamage,& + target_agw_c) call bbgw_allom(currentCohort%dbh,currentCohort%pft,target_bgw_c) call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, & currentCohort%pft, target_struct_c) From de822e461e068e1f7f89285314123016fb29f450 Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Mon, 26 Sep 2022 21:11:12 -0700 Subject: [PATCH 357/852] Update sapwood respiration to fix damage related bug --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index b4b3dabaa0..83971ba9f8 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -671,24 +671,22 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) call GetCrownReduction(currentCohort%crowndamage, crown_reduction) sapw_c_undamaged = sapw_c / & - (1.0_r8 - (agb_frac * branch_frac * (1.0_r8-crown_reduction))) + (1.0_r8 - (agb_frac * branch_frac * crown_reduction)) ! Undamaged below ground portion sapw_c_bgw = sapw_c_undamaged * (1.0_r8 - agb_frac) ! Damaged aboveground portion sapw_c_agw = sapw_c - sapw_c_bgw - + end if select case(hlm_parteh_mode) case (prt_carbon_allom_hyp) - live_stem_n = prt_params%allom_agb_frac(currentCohort%pft) * & - sapw_c_agw * prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) + live_stem_n = sapw_c_agw * prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) - live_croot_n = (1.0_r8-prt_params%allom_agb_frac(currentCohort%pft)) * & - sapw_c_bgw * prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) + live_croot_n = sapw_c_bgw * prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) fnrt_n = fnrt_c * prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)) @@ -708,16 +706,14 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) sapw_n = currentCohort%prt%GetState(sapw_organ, nitrogen_element) sapw_n_undamaged = sapw_n / & - (1.0_r8 - (agb_frac * branch_frac * (1.0_r8 - crown_reduction))) + (1.0_r8 - (agb_frac * branch_frac * crown_reduction)) sapw_n_bgw = sapw_n_undamaged * (1.0_r8 - agb_frac) sapw_n_agw = sapw_n - sapw_n_bgw - live_croot_n = (1.0_r8-prt_params%allom_agb_frac(currentCohort%pft)) * & - sapw_n_bgw + live_croot_n = sapw_n_bgw - live_stem_n = prt_params%allom_agb_frac(currentCohort%pft) * & - sapw_n_agw + live_stem_n = sapw_n_agw end if From e5b012122c03ba71590ec100d47a5fb20fbaa1e0 Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Mon, 3 Oct 2022 17:04:45 -0700 Subject: [PATCH 358/852] Tidy comments on damage code --- biogeochem/DamageMainMod.F90 | 14 +++++--------- biogeochem/EDCohortDynamicsMod.F90 | 10 +++------- biogeochem/EDPhysiologyMod.F90 | 2 +- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/biogeochem/DamageMainMod.F90 b/biogeochem/DamageMainMod.F90 index b56fd0363e..f0a05f7ee6 100644 --- a/biogeochem/DamageMainMod.F90 +++ b/biogeochem/DamageMainMod.F90 @@ -76,7 +76,7 @@ subroutine IsItDamageTime(is_master, currentSite) damage_time = .false. icode = int(damage_event_code) - model_day_int = nint(hlm_model_day) + model_day_int = int(hlm_model_day) if(icode .eq. 1) then ! Damage is turned off @@ -90,7 +90,7 @@ subroutine IsItDamageTime(is_master, currentSite) else if(icode .eq. 3) then ! Damage event every day - this is not recommended as it will result in a very large - ! number of cohorts + ! number of cohorts which will likely be terminated damage_time = .true. else if(icode .eq. 4) then @@ -147,8 +147,6 @@ subroutine GetDamageFrac(cc_cd, nc_cd, pft, dist_frac) ! This subroutine consults a look up table of transitions from param derived. ! USES - use FatesInterfaceTypesMod, only : nlevdamage - use FatesConstantsMod, only : years_per_day use FatesParameterDerivedMod, only : param_derived @@ -156,7 +154,7 @@ subroutine GetDamageFrac(cc_cd, nc_cd, pft, dist_frac) integer, intent(in) :: cc_cd ! current cohort crown damage integer, intent(in) :: nc_cd ! new cohort crown damage integer, intent(in) :: pft ! plant functional type - real(r8), intent(out) :: dist_frac ! probability of current cohort moving to + real(r8), intent(out) :: dist_frac ! fraction of current cohort moving to ! new damage level dist_frac = param_derived%damage_transitions(cc_cd, nc_cd, pft) @@ -167,10 +165,10 @@ end subroutine GetDamageFrac subroutine GetCrownReduction(crowndamage, crown_reduction) - !------------------------------------------------------------------ + !------------------------------------------------------------------ ! This subroutine takes the crown damage class of a cohort (integer) ! and returns the fraction of the crown that is lost. - !------------------------------------------------------------------- + !------------------------------------------------------------------- integer(i4), intent(in) :: crowndamage ! crown damage class of the cohort real(r8), intent(out) :: crown_reduction ! fraction of crown lost from damage @@ -195,8 +193,6 @@ subroutine GetDamageMortality(crowndamage,pft, dgmort) ! those unrepresented mechanisms. !------------------------------------------------------------------ - - use FatesInterfaceTypesMod , only : nlevdamage use EDPftvarcon , only : EDPftvarcon_inst integer(i4), intent(in) :: crowndamage ! crown damage class of the cohort diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index e4777ee86d..5e77496713 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -103,7 +103,6 @@ Module EDCohortDynamicsMod use PRTAllometricCNPMod, only : acnp_bc_out_id_pefflux, acnp_bc_in_id_cdamage use PRTAllometricCNPMod, only : acnp_bc_out_id_nneed use PRTAllometricCNPMod, only : acnp_bc_out_id_pneed - use DamageMainMod, only : GetCrownReduction use DamageMainMod, only : undamaged_class use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) @@ -2055,7 +2054,6 @@ subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) ! consistent with stuctural biomass (or, in the case of grasses, leaf biomass) ! then correct (increase) the dbh to match that. ! ----------------------------------------------------------------------------------- - use DamageMainMod, only : GetCrownReduction ! argument type(ed_cohort_type),intent(inout) :: currentCohort @@ -2161,7 +2159,7 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) ! locals type(ed_cohort_type), pointer :: rcohort ! New cohort that recovers by - ! having an lower damage class + ! having a lower damage class real(r8) :: sapw_area ! sapwood area real(r8) :: target_sapw_c,target_sapw_m ! sapwood mass, C and N/P real(r8) :: target_agw_c ! target above ground wood @@ -2178,7 +2176,7 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) real(r8) :: available_m ! available mass that can be used to ! improve damage class real(r8) :: recovery_demand ! amount of mass needed to get to - ! get to the target of the next damage class + ! the target of the next damage class real(r8) :: max_recover_nplant ! max number of plants that could get to ! target of next class real(r8) :: nplant_recover ! number of plants in cohort that will @@ -2336,9 +2334,7 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) ! Need to adjust the crown area which is NOT on a per individual basis call carea_allom(dbh,rcohort%n,csite%spread,ipft,rcohort%crowndamage,rcohort%c_area) - !rcohort%n/n_old * ccohort%c_area - !ccohort%c_area = ccohort%c_area - rcohort%c_area - + ! Update properties of the un-recovered (donor) cohort ccohort%n = ccohort%n - rcohort%n ccohort%c_area = ccohort%c_area * ccohort%n / (ccohort%n+rcohort%n) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 7cdbc28ba4..d86a4fe2e6 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -211,7 +211,7 @@ subroutine GenerateDamageAndLitterFluxes( csite, cpatch, bc_in ) ! Locals type(ed_cohort_type), pointer :: ccohort ! Current cohort - type(ed_cohort_type), pointer :: ndcohort ! Newly damage-class cohort + type(ed_cohort_type), pointer :: ndcohort ! New damage-class cohort type(litter_type), pointer :: litt ! Points to the litter object type(site_fluxdiags_type), pointer :: flux_diags ! pointer to site level flux diagnostics object integer :: cd ! Damage class index From 7551d46fd1811c57c1fc3f2aae39c209f023ed56 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 23 Sep 2022 18:24:10 -0600 Subject: [PATCH 359/852] add bareground area_pft calculation to restart --- main/FatesRestartInterfaceMod.F90 | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index a720d629f3..bba0d5ca79 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -18,7 +18,7 @@ module FatesRestartInterfaceMod use FatesInterfaceTypesMod, only : bc_in_type use FatesInterfaceTypesMod, only : bc_out_type use FatesInterfaceTypesMod, only : hlm_use_planthydro - use FatesInterfaceTypesMod, only : hlm_use_sp + use FatesInterfaceTypesMod, only : hlm_use_sp, hlm_use_nocomp use FatesInterfaceTypesMod, only : fates_maxElementsPerSite use EDCohortDynamicsMod, only : UpdateCohortBioPhysRates use FatesHydraulicsMemMod, only : nshell @@ -36,7 +36,7 @@ module FatesRestartInterfaceMod use FatesLitterMod, only : litter_type use FatesLitterMod, only : ncwd use FatesLitterMod, only : ndcmpy - use EDTypesMod, only : nfsc + use EDTypesMod, only : nfsc, nlevleaf, area use PRTGenericMod, only : prt_global use PRTGenericMod, only : num_elements use FatesRunningMeanMod, only : rmean_type @@ -2685,12 +2685,20 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%recruitment_rate(i_pft) = rio_recrate_sift(io_idx_co_1st+i_pft-1) enddo - !variables for fixed biogeography mode. These are currently used in restart even when this is off. + ! variables for fixed biogeography mode. These are currently used in restart even when this is off. do i_pft = 1,numpft sites(s)%use_this_pft(i_pft) = rio_use_this_pft_sift(io_idx_co_1st+i_pft-1) sites(s)%area_pft(i_pft) = rio_area_pft_sift(io_idx_co_1st+i_pft-1) enddo + ! calculate the bareground area for the pft in no competition modes + if (hlm_use_nocomp .eq. itrue) then + if (sum(sites(s)%area_pft(1:numpft)) .lt. area) then + sites(s)%area_pft(0) = area - sum(sites(s)%area_pft(1:numpft)) + else + sites(s)%area_pft(0) = 0.0_r8 + endif + ! Mass balance and diagnostics across elements at the site level do el = 1, num_elements From 44d2f59df333bbee6ae281b0ce4acba68a928105 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 5 Oct 2022 10:22:16 -0600 Subject: [PATCH 360/852] add missing end if to nocomp check --- main/FatesRestartInterfaceMod.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index bba0d5ca79..9a68e96b7d 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -2697,6 +2697,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%area_pft(0) = area - sum(sites(s)%area_pft(1:numpft)) else sites(s)%area_pft(0) = 0.0_r8 + endif endif ! Mass balance and diagnostics across elements at the site level From c9739ba043fa1e427f6cb783936c6bb8d9decb83 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 5 Oct 2022 12:37:14 -0600 Subject: [PATCH 361/852] add check to avoid conducting tveg running means calculation on bareground patches --- main/FatesInterfaceMod.F90 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 0ca5aafb63..9308c18390 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1926,6 +1926,7 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) ifp=0 cpatch => sites(s)%oldest_patch do while(associated(cpatch)) + if (cpatch%patchno .ne. 0) then ifp=ifp+1 call cpatch%tveg24%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) call cpatch%tveg_lpa%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) @@ -1936,6 +1937,7 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) ! call ccohort%tveg_lpa%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) ! ccohort => ccohort%shorter !end do + end if cpatch => cpatch%younger enddo From c3690080b27f50fed6b9c421e386885fee6a269e Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 5 Oct 2022 17:43:45 -0400 Subject: [PATCH 362/852] Updates to parameter batch patching, the modify pft script, and the xml format of the batch patch. --- parameter_files/patch_default_bciopt224.xml | 101 ++++++++-------- tools/BatchPatchParams.py | 122 ++++++++++++++++---- tools/modify_fates_paramfile.py | 4 +- 3 files changed, 160 insertions(+), 67 deletions(-) diff --git a/parameter_files/patch_default_bciopt224.xml b/parameter_files/patch_default_bciopt224.xml index bfcc288efa..c1c7a30e3c 100644 --- a/parameter_files/patch_default_bciopt224.xml +++ b/parameter_files/patch_default_bciopt224.xml @@ -2,51 +2,62 @@ This parameter dataset was created by Ryan Knox rgknox@lbl.gov. Please contact if using in published work. The calibration uses the following datasets: [1] Ely et al. 2019. Leaf mass area, Panama. NGEE-Tropics data collection.http://dx.doi.org/10.15486/ngt/1411973 and [2] Condit et al. 2019. Complete data from the Barro Colorado 50-ha plot. https://doi.org/10.15146/5xcp-0d46. [3] Koven et al. 2019. Benchmarking and parameter sensitivity of physiological and vegetation dynamics using the functionally assembled terrestrial ecosystem simulator. Biogeosciences. The ECA nutrient aquisition parmeters are unconstrained, the file output naming convention vmn6phi is shorthand for vmax for nitrogen uptake is order e-6 and for phosphorus is excessively high. These parameters were calibrated with the special fates modification in main/EDTypesMod.F90: nclmax = 3 fates_params_default.cdl - fates_params_opt224_vmn6phi_080621.cdl - 1 + fates_params_bciopt224_v1_api24.cdl + 1 - 0 - 0 - 1,1,3,4 - 0.03347526,0.024,1e-08,0.0047 - 0.03347526,0.024,1e-08,0.0047 - 0.025,0,0,0 - 0.45,0.25,0,0 - 0.8012471 - 30.94711 - 0.0673 - 0.976 - -9 - -9 - 3 - 0.1266844 - 1.281329 - -9 - 0.768654 - 0.768654 - 57.6 - 0.74 - 21.6 - 200 - 2 - 5 - 0.4863088 - 3 - 3e-06 - 3e-06 - 3e-07 - 3e-08 - 0.03991654 - 0.01995827 - 0.01303514 - 0.02955703 - 3 - 3 - 0.04680188 - 0.001 - 0.8374751 - -1 - 0.5 - 1 + + + + + + 0 + 0 + 0.03347526,0.024,1e-08,0.0047 + 0.002675,0.0005,0.00015,0.00015 + 0.45,0.25,0,0 + 0.65,0.25,0,0 + 0.8012471 + 30.94711 + 0.0673 + 0.976 + -9 + -9 + 3 + 0.1266844 + 1.281329 + -9 + 0.768654 + 0.768654 + 57.6 + 0.74 + 21.6 + 200 + 2 + 5 + 0.4863088 + 0.0 + 1 + 3 + 5e-09 + 5e-09 + 5e-09 + 5e-10 + 3e-08 + 0.03991654 + 0.01995827 + 0.01303514 + 0.02955703 + 3 + 3 + 0.04680188 + 0.001 + 0.8374751 + + + 1,1,3,4 + -1 + 0.5 + 1 + diff --git a/tools/BatchPatchParams.py b/tools/BatchPatchParams.py index ee78ebcbd0..b3d59d940b 100755 --- a/tools/BatchPatchParams.py +++ b/tools/BatchPatchParams.py @@ -8,7 +8,9 @@ import argparse import code # For development: code.interact(local=dict(globals(), **locals())) from scipy.io import netcdf +import xml.etree.ElementTree as et +debug = True # --------------------------------------------------------------------------------------- @@ -22,7 +24,7 @@ def __init__(self,name,values_text): def load_xml(xmlfile): - import xml.etree.ElementTree as et + xmlroot = et.parse(xmlfile).getroot() print("\nOpenend: "+xmlfile) @@ -30,16 +32,31 @@ def load_xml(xmlfile): base_cdl = xmlroot.find('base_file').text new_cdl = xmlroot.find('new_file').text - pftparams = xmlroot.find('pft_list').text.replace(" ","") + pftparams = xmlroot.find('pft_trim_list').text.replace(" ","") paramroot = xmlroot.find('parameters') - paramlist = [] - for param in paramroot: - print("parsing "+param.tag) - paramlist.append(param_type(param.tag,param.text)) + + grouplist = [] + for group in paramroot: + + if(not('ids' in group.attrib.keys())): + print("pft_mod_group must have an ids attribute with comma delimited pft indices") + print("exiting") + exit(2) + + pft_str = group.attrib['ids'].strip() + pft_strvec = pft_str.split(',') + pft_ids = [int(s) for s in pft_strvec] + print("Processing PFT group: "+group.tag+" ids: "+pft_str) + + #paramlist = [] + #for param in paramroot: + # print("parsing "+param.tag) + # paramlist.append(param_type(param.tag,param.text)) - + + code.interact(local=dict(globals(), **locals())) return(base_cdl,new_cdl,pftparams,paramlist) @@ -47,14 +64,20 @@ def load_xml(xmlfile): # Little function for assembling the call to the system to make the modification # ---------------------------------------------------------------------------------------- -def parse_syscall_str(fnamein,fnameout,param_name,param_val): - - sys_call_str = "../tools/modify_fates_paramfile.py"+" --fin " + fnamein + \ - " --fout " + fnameout + " --var " + param_name + " --silent " +\ - " --val " + "\" "+param_val+"\"" + " --overwrite --all" +def parse_syscall_str(fnamein,fnameout,pft_index,param_name,param_val): + if(pft_index==0): + sys_call_str = "../tools/modify_fates_paramfile.py"+" --fin " + fnamein + \ + " --fout " + fnameout + " --var " + param_name + " --silent " +\ + " --val " + "\" "+param_val+"\"" + " --overwrite --all" + else: + pft_str_index="{}".format(pft_index) + sys_call_str = "../tools/modify_fates_paramfile.py"+" --fin " + fnamein + \ + " --fout " + fnameout + " --var " + param_name + " --silent " +\ + " --val " + "\" "+param_val+"\"" + " --overwrite --pft "+pft_str_index - print(sys_call_str) + if(debug): + print(sys_call_str) return(sys_call_str) @@ -70,8 +93,13 @@ def main(): # Load the xml file, which contains the base cdl, the output cdl, # and the parameters to be modified - [base_cdl,new_cdl,pftlist,paramlist] = load_xml(args.xmlfile) + #[base_cdl,new_cdl,pftlist,paramlist] = load_xml(args.xmlfile) + + xmlroot = et.parse(args.xmlfile).getroot() + print("\nOpenend: "+args.xmlfile) + base_cdl = xmlroot.find('base_file').text + new_cdl = xmlroot.find('new_file').text # Convert the base cdl file into a temp nc binary base_nc = os.popen('mktemp').read().rstrip('\n') @@ -81,9 +109,9 @@ def main(): # Generate a temp output file name new_nc = os.popen('mktemp').read().rstrip('\n') - # Use FatesPFTIndexSwapper.py to prune out unwanted PFTs - swapcmd="../tools/FatesPFTIndexSwapper.py --pft-indices="+pftlist+" --fin="+base_nc+" --fout="+new_nc #+" 1>/dev/null" + pft_trim_list = xmlroot.find('pft_trim_list').text.replace(" ","") + swapcmd="../tools/FatesPFTIndexSwapper.py --pft-indices="+pft_trim_list+" --fin="+base_nc+" --fout="+new_nc #+" 1>/dev/null" os.system(swapcmd) # We open the new parameter file. We only use this @@ -91,22 +119,74 @@ def main(): fp_nc = netcdf.netcdf_file(base_nc, 'r') # On subsequent parameters, overwrite the file - for param in paramlist: - change_str = parse_syscall_str(new_nc,new_nc,param.name,param.values) - os.system(change_str) + paramroot = xmlroot.find('parameters') + + grouplist = [] + for group in paramroot: + + if(group.tag.strip() == 'non_pft_group'): + + print("Processing non_pft_group") + + for param in group: + print("parsing "+param.tag) + + change_str = parse_syscall_str(new_nc,new_nc,0,param.tag,param.text.replace(" ","")) + os.system(change_str) + elif(group.tag.strip() == 'pft_group'): + + if(not('ids' in group.attrib.keys())): + print("pft_mod_group must have an ids attribute with comma delimited pft indices") + print("exiting") + exit(2) + + pft_str = group.attrib['ids'].strip() + pft_strvec = pft_str.split(',') + pft_ids = [int(s) for s in pft_strvec] + + print("Processing PFT group: "+group.tag+" ids: "+pft_str) + + for param in group: + print("parsing "+param.tag) + + param_vec = [str_val for str_val in param.text.replace(" ", "").split(',')] + + # The number of parameters does not need to equal to the number of PFTs + # but it does need to be equally divisible by it + v_per_p = float(len(param_vec))/float(len(pft_ids)) + + if( int(100.0*v_per_p) != 100*int(v_per_p) ): + print("inconsistent number of parameter values and number of pfts specified") + print("exiting") + exit(2) + + for j,pft_id in enumerate(pft_ids): + j0 = j*int(v_per_p) + j1 = (j+1)*int(v_per_p) + #code.interact(local=dict(globals(), **locals())) + param_str = ",".join(param_vec[j0:j1]) + change_str = parse_syscall_str(new_nc,new_nc,pft_id,param.tag,param_str) + os.system(change_str) + + else: + print("Unidentified group, should be: non_pft_group or pft_group") + print("exiting") + exit(2) + + # Sort the new file newer_nc = os.popen('mktemp').read().rstrip('\n') os.system("../tools/ncvarsort.py --fin "+new_nc+" --fout "+newer_nc+" --overwrite") # Dump the new file to the cdl os.system("ncdump "+newer_nc+" > "+new_cdl) - + fp_nc.close() print("\nBatch parameter transfer complete\n") - + print("\nGenerated: {}\n".format(new_cdl)) # This is the actual call to main diff --git a/tools/modify_fates_paramfile.py b/tools/modify_fates_paramfile.py index 5ab1116500..adacb2457b 100755 --- a/tools/modify_fates_paramfile.py +++ b/tools/modify_fates_paramfile.py @@ -138,8 +138,10 @@ def main(): otherdimpresent = False elif var.dimensions[i] in ['fates_history_age_bins','fates_history_size_bins', \ 'fates_history_coage_bins','fates_history_height_bins', \ + 'fates_history_damage_bins', 'fates_NCWD','fates_litterclass','fates_leafage_class', \ - 'fates_prt_organs','fates_hydr_organs','fates_hlm_pftno']: + 'fates_plant_organs','fates_hydr_organs','fates_hlm_pftno', \ + 'fates_leafage_class']: otherdimpresent = True otherdimname = var.dimensions[i] otherdimlength = var.shape[i] From a28ca74af9f3417ecd2127564a71304652b3ed55 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 6 Oct 2022 10:43:24 -0700 Subject: [PATCH 363/852] refactor area_pft checks and add check against notional area --- main/EDInitMod.F90 | 57 +++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index d3177ca72a..a050ec5635 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -292,9 +292,11 @@ subroutine set_site_properties( nsites, sites,bc_in ) integer :: dleafoff ! DOY for drought-decid leaf-off, initial guess integer :: dleafon ! DOY for drought-decid leaf-on, initial guess integer :: ft ! PFT loop - real(r8) :: sumarea ! area of PFTs in nocomp mode. + real(r8) :: sumarea ! area of PFTs in nocomp mode integer :: hlm_pft ! used in fixed biogeog mode integer :: fates_pft ! used in fixed biogeog mode + + real(r8) :: small_patch_tol = 0.01_r8 ! Do not allocate pft area below this threshhold !---------------------------------------------------------------------- @@ -346,25 +348,38 @@ subroutine set_site_properties( nsites, sites,bc_in ) sites(s)%area_pft(1:numpft) = 0._r8 do hlm_pft = 1,size( EDPftvarcon_inst%hlm_pft_map,2) - do fates_pft = 1,numpft ! loop round all fates pfts for all hlm pfts + + ! loop round all fates pfts for all hlm pfts + do fates_pft = 1,numpft + sites(s)%area_pft(fates_pft) = sites(s)%area_pft(fates_pft) + & EDPftvarcon_inst%hlm_pft_map(fates_pft,hlm_pft) * bc_in(s)%pft_areafrac(hlm_pft) - end do - end do !hlm_pft - - do ft = 1,numpft - if(sites(s)%area_pft(ft).lt.0.01_r8.and.sites(s)%area_pft(ft).gt.0.0_r8)then - if(debug) write(fates_log(),*) 'removing small pft patches',s,ft,sites(s)%area_pft(ft) - sites(s)%area_pft(ft)=0.0_r8 + + ! Check for negative pft area + if(sites(s)%area_pft(fates_pft) .lt. 0._r8)then + write(fates_log(),*) 'negative area',s,ft,sites(s)%area_pft(ft) + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + ! remove tiny patches to prevent numerical errors in terminate patches - endif - if(sites(s)%area_pft(ft).lt.0._r8)then - write(fates_log(),*) 'negative area',s,ft,sites(s)%area_pft(ft) - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - sites(s)%area_pft(ft)= sites(s)%area_pft(ft) * AREA ! rescale units to m2. - end do + if(sites(s)%area_pft(fates_pft) .lt. small_patch_tol)then + if(debug) write(fates_log(),*) 'removing small pft patches',s,fates_pft,sites(s)%area_pft(fates_pft) + sites(s)%area_pft(fates_pft) = 0.0_r8 + endif + + ! rescale units to m2 + sites(s)%area_pft(fates_pft)= sites(s)%area_pft(fates_pft) * AREA + + end do !fates_pft + end do !hlm_pft + ! Check that the sum of the areas is not greater than the notional area + sumarea = sum(sites(s)%area_pft(1:numpft)) + if(sumarea .gt. area)then + write(fates_log(),*) 'Total pft area for site is larger than notional area',s,sum(sites(s)%area_pft) + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + ! re-normalize PFT area to ensure it sums to one. ! note that in areas of 'bare ground' (PFT 0 in CLM/ELM) ! the bare ground will no longer be proscribed and should emerge from FATES @@ -372,10 +387,9 @@ subroutine set_site_properties( nsites, sites,bc_in ) if(hlm_use_nocomp.eq.ifalse)then ! when not in nocomp (i.e. or SP) mode, ! subsume bare ground evenly into the existing patches. - - sumarea = sum(sites(s)%area_pft(1:numpft)) + do ft = 1,numpft - if(sumarea.gt.0._r8)then + if(area-sumarea.gt.nearzero)then sites(s)%area_pft(ft) = area * sites(s)%area_pft(ft)/sumarea else sites(s)%area_pft(ft) = area/numpft @@ -383,8 +397,8 @@ subroutine set_site_properties( nsites, sites,bc_in ) ! all pfts and let the model figure out whether land should be bare or not. end if end do !ft + else ! for sp and nocomp mode, assert a bare ground patch if needed - sumarea = sum(sites(s)%area_pft(1:numpft)) ! In all the other FATES modes, bareground is the area in which plants ! do not grow of their own accord. In SP mode we assert that the canopy is full for @@ -396,11 +410,12 @@ subroutine set_site_properties( nsites, sites,bc_in ) ! on canopy are inside FATES, and so in SP mode, we define the bare groud ! patch as having a PFT identifier as zero. - if(sumarea.lt.area)then !make some bare ground + if(area-sumarea.gt.nearzero)then !make some bare ground sites(s)%area_pft(0) = area - sumarea else sites(s)%area_pft(0) = 0.0_r8 end if + end if !sp mode end if !fixed biogeog From 1ee7fe8d6e2ade72eaaddab8386967961c610326 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 6 Oct 2022 10:49:12 -0700 Subject: [PATCH 364/852] update restart area_pft check to use tolerance --- main/FatesRestartInterfaceMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 9a68e96b7d..ae2c9e8bc2 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -2693,7 +2693,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ! calculate the bareground area for the pft in no competition modes if (hlm_use_nocomp .eq. itrue) then - if (sum(sites(s)%area_pft(1:numpft)) .lt. area) then + if (area-sum(sites(s)%area_pft(1:numpft)) .gt. nearzero) then sites(s)%area_pft(0) = area - sum(sites(s)%area_pft(1:numpft)) else sites(s)%area_pft(0) = 0.0_r8 From 2eb6cdf452a2b2e6f624d3829ee1af57b66eb72f Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 6 Oct 2022 14:17:56 -0700 Subject: [PATCH 365/852] add missing nearzero use call --- main/FatesRestartInterfaceMod.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index ae2c9e8bc2..360011123d 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -9,6 +9,7 @@ module FatesRestartInterfaceMod use FatesConstantsMod, only : ifalse use FatesConstantsMod, only : fates_unset_r8, fates_unset_int use FatesConstantsMod, only : primaryforest + use FatesConstantsMod, only : nearzero use FatesGlobals, only : fates_log use FatesGlobals, only : endrun => fates_endrun use FatesIODimensionsMod, only : fates_io_dimension_type From 8392331680f2890263ddb127f59b029630869222 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 6 Oct 2022 14:18:30 -0700 Subject: [PATCH 366/852] Revert "refactor area_pft checks and add check against notional area" This reverts commit a28ca74af9f3417ecd2127564a71304652b3ed55. --- main/EDInitMod.F90 | 57 +++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 36 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index a050ec5635..d3177ca72a 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -292,11 +292,9 @@ subroutine set_site_properties( nsites, sites,bc_in ) integer :: dleafoff ! DOY for drought-decid leaf-off, initial guess integer :: dleafon ! DOY for drought-decid leaf-on, initial guess integer :: ft ! PFT loop - real(r8) :: sumarea ! area of PFTs in nocomp mode + real(r8) :: sumarea ! area of PFTs in nocomp mode. integer :: hlm_pft ! used in fixed biogeog mode integer :: fates_pft ! used in fixed biogeog mode - - real(r8) :: small_patch_tol = 0.01_r8 ! Do not allocate pft area below this threshhold !---------------------------------------------------------------------- @@ -348,38 +346,25 @@ subroutine set_site_properties( nsites, sites,bc_in ) sites(s)%area_pft(1:numpft) = 0._r8 do hlm_pft = 1,size( EDPftvarcon_inst%hlm_pft_map,2) - - ! loop round all fates pfts for all hlm pfts - do fates_pft = 1,numpft - + do fates_pft = 1,numpft ! loop round all fates pfts for all hlm pfts sites(s)%area_pft(fates_pft) = sites(s)%area_pft(fates_pft) + & EDPftvarcon_inst%hlm_pft_map(fates_pft,hlm_pft) * bc_in(s)%pft_areafrac(hlm_pft) - - ! Check for negative pft area - if(sites(s)%area_pft(fates_pft) .lt. 0._r8)then - write(fates_log(),*) 'negative area',s,ft,sites(s)%area_pft(ft) - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - ! remove tiny patches to prevent numerical errors in terminate patches - if(sites(s)%area_pft(fates_pft) .lt. small_patch_tol)then - if(debug) write(fates_log(),*) 'removing small pft patches',s,fates_pft,sites(s)%area_pft(fates_pft) - sites(s)%area_pft(fates_pft) = 0.0_r8 - endif - - ! rescale units to m2 - sites(s)%area_pft(fates_pft)= sites(s)%area_pft(fates_pft) * AREA - - end do !fates_pft + end do end do !hlm_pft - ! Check that the sum of the areas is not greater than the notional area - sumarea = sum(sites(s)%area_pft(1:numpft)) - if(sumarea .gt. area)then - write(fates_log(),*) 'Total pft area for site is larger than notional area',s,sum(sites(s)%area_pft) - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - + do ft = 1,numpft + if(sites(s)%area_pft(ft).lt.0.01_r8.and.sites(s)%area_pft(ft).gt.0.0_r8)then + if(debug) write(fates_log(),*) 'removing small pft patches',s,ft,sites(s)%area_pft(ft) + sites(s)%area_pft(ft)=0.0_r8 + ! remove tiny patches to prevent numerical errors in terminate patches + endif + if(sites(s)%area_pft(ft).lt.0._r8)then + write(fates_log(),*) 'negative area',s,ft,sites(s)%area_pft(ft) + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + sites(s)%area_pft(ft)= sites(s)%area_pft(ft) * AREA ! rescale units to m2. + end do + ! re-normalize PFT area to ensure it sums to one. ! note that in areas of 'bare ground' (PFT 0 in CLM/ELM) ! the bare ground will no longer be proscribed and should emerge from FATES @@ -387,9 +372,10 @@ subroutine set_site_properties( nsites, sites,bc_in ) if(hlm_use_nocomp.eq.ifalse)then ! when not in nocomp (i.e. or SP) mode, ! subsume bare ground evenly into the existing patches. - + + sumarea = sum(sites(s)%area_pft(1:numpft)) do ft = 1,numpft - if(area-sumarea.gt.nearzero)then + if(sumarea.gt.0._r8)then sites(s)%area_pft(ft) = area * sites(s)%area_pft(ft)/sumarea else sites(s)%area_pft(ft) = area/numpft @@ -397,8 +383,8 @@ subroutine set_site_properties( nsites, sites,bc_in ) ! all pfts and let the model figure out whether land should be bare or not. end if end do !ft - else ! for sp and nocomp mode, assert a bare ground patch if needed + sumarea = sum(sites(s)%area_pft(1:numpft)) ! In all the other FATES modes, bareground is the area in which plants ! do not grow of their own accord. In SP mode we assert that the canopy is full for @@ -410,12 +396,11 @@ subroutine set_site_properties( nsites, sites,bc_in ) ! on canopy are inside FATES, and so in SP mode, we define the bare groud ! patch as having a PFT identifier as zero. - if(area-sumarea.gt.nearzero)then !make some bare ground + if(sumarea.lt.area)then !make some bare ground sites(s)%area_pft(0) = area - sumarea else sites(s)%area_pft(0) = 0.0_r8 end if - end if !sp mode end if !fixed biogeog From 7ba71f519b2efc73b1cbf3d96e18b13918124d58 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 6 Oct 2022 15:51:14 -0700 Subject: [PATCH 367/852] add fixed biogeo check to restart calc --- main/FatesRestartInterfaceMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 360011123d..1c3df69871 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -2692,8 +2692,8 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%area_pft(i_pft) = rio_area_pft_sift(io_idx_co_1st+i_pft-1) enddo - ! calculate the bareground area for the pft in no competition modes - if (hlm_use_nocomp .eq. itrue) then + ! calculate the bareground area for the pft in no competition + fixed biogeo modes + if (hlm_use_nocomp .eq. itrue .and. hlm_use_fixed_biogeog .eq. itrue) then if (area-sum(sites(s)%area_pft(1:numpft)) .gt. nearzero) then sites(s)%area_pft(0) = area - sum(sites(s)%area_pft(1:numpft)) else From 5fa6ca31bc8d80f4ab94d4f2ba329b5d30de402a Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 7 Oct 2022 12:21:50 -0700 Subject: [PATCH 368/852] add fixed biogeo use statement --- main/FatesRestartInterfaceMod.F90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 1c3df69871..d17759220a 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -19,7 +19,8 @@ module FatesRestartInterfaceMod use FatesInterfaceTypesMod, only : bc_in_type use FatesInterfaceTypesMod, only : bc_out_type use FatesInterfaceTypesMod, only : hlm_use_planthydro - use FatesInterfaceTypesMod, only : hlm_use_sp, hlm_use_nocomp + use FatesInterfaceTypesMod, only : hlm_use_sp + use FatesInterfaceTypesMod, only : hlm_use_nocomp, hlm_use_fixed_biogeog use FatesInterfaceTypesMod, only : fates_maxElementsPerSite use EDCohortDynamicsMod, only : UpdateCohortBioPhysRates use FatesHydraulicsMemMod, only : nshell From b83403e2d1c4bb7b7a62fffe04d1bf0334f8ddd7 Mon Sep 17 00:00:00 2001 From: ckoven Date: Mon, 10 Oct 2022 17:34:52 -0600 Subject: [PATCH 369/852] added live grass stem mass to live fuel and to burn fluxes (reimplementation rather than cherrypick of 6b2da50) --- biogeochem/EDPatchDynamicsMod.F90 | 21 ++++++++++++++++++++- fire/SFMainMod.F90 | 4 +++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index d81aa10634..b42b639046 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -859,6 +859,18 @@ subroutine spawn_patches( currentSite, bc_in) do el = 1,num_elements leaf_m = nc%prt%GetState(leaf_organ, element_list(el)) + ! for grasses burn all aboveground tissues, for woody plants burn only leaves + if(int(prt_params%woody(currentCohort%pft)) == itrue)then + + leaf_m = nc%prt%GetState(leaf_organ, element_list(el)) + + else + + leaf_m = nc%prt%GetState(leaf_organ, element_list(el)) + & + nc%prt%GetState(sapw_organ, element_list(el)) + & + nc%prt%GetState(struct_organ, element_list(el)) + + endif currentSite%mass_balance(el)%burn_flux_to_atm = & currentSite%mass_balance(el)%burn_flux_to_atm + & @@ -867,7 +879,14 @@ subroutine spawn_patches( currentSite, bc_in) ! Here the mass is removed from the plant - call PRTBurnLosses(nc%prt, leaf_organ, leaf_burn_frac) + if(int(prt_params%woody(currentCohort%pft)) == itrue)then + call PRTBurnLosses(nc%prt, leaf_organ, leaf_burn_frac) + else + call PRTBurnLosses(nc%prt, leaf_organ, leaf_burn_frac) + call PRTBurnLosses(nc%prt, sapw_organ, leaf_burn_frac) + call PRTBurnLosses(nc%prt, struct_organ, leaf_burn_frac) + endif + currentCohort%fraction_crown_burned = 0.0_r8 nc%fraction_crown_burned = 0.0_r8 diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index 7f2c037846..720f024a88 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -195,7 +195,9 @@ subroutine charecteristics_of_fuel ( currentSite ) if( prt_params%woody(currentCohort%pft) == ifalse)then currentPatch%livegrass = currentPatch%livegrass + & - currentCohort%prt%GetState(leaf_organ, all_carbon_elements) * & + ( currentCohort%prt%GetState(leaf_organ, all_carbon_elements) + & + currentCohort%prt%GetState(sapw_organ, all_carbon_elements) + & + currentCohort%prt%GetState(struct_organ, all_carbon_elements) ) * & currentCohort%n/currentPatch%area endif From 9daabc7c0a91ff4657bf2eeb6e80a62720535276 Mon Sep 17 00:00:00 2001 From: ckoven Date: Mon, 10 Oct 2022 17:58:47 -0600 Subject: [PATCH 370/852] changed grass -> CWD logic in SendCohortToLitter --- biogeochem/EDCohortDynamicsMod.F90 | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 4948f68129..8d995fdf1f 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -967,12 +967,20 @@ subroutine SendCohortToLitter(csite,cpatch,ccohort,nplant,bc_in) do el=1,num_elements - leaf_m = ccohort%prt%GetState(leaf_organ, element_list(el)) store_m = ccohort%prt%GetState(store_organ, element_list(el)) - sapw_m = ccohort%prt%GetState(sapw_organ, element_list(el)) fnrt_m = ccohort%prt%GetState(fnrt_organ, element_list(el)) - struct_m = ccohort%prt%GetState(struct_organ, element_list(el)) repro_m = ccohort%prt%GetState(repro_organ, element_list(el)) + if (prt_params%woody(currentCohort%pft) == itrue) then + leaf_m = ccohort%prt%GetState(leaf_organ, element_list(el)) + sapw_m = ccohort%prt%GetState(sapw_organ, element_list(el)) + struct_m = ccohort%prt%GetState(struct_organ, element_list(el)) + else + leaf_m = ccohort%prt%GetState(leaf_organ, element_list(el)) + & + ccohort%prt%GetState(sapw_organ, element_list(el)) + & + ccohort%prt%GetState(struct_organ, element_list(el)) + sapw_m = 0._r8 + struct_m = 0._r8 + endif litt => cpatch%litter(el) flux_diags => csite%flux_diags(el) From d49058402133859f7748f1aa2c4d6c61862415c4 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 11 Oct 2022 12:25:06 -0400 Subject: [PATCH 371/852] Cleanup in PRTAllometricCNP --- parteh/PRTAllometricCNPMod.F90 | 327 +++++++++++++++------------------ 1 file changed, 148 insertions(+), 179 deletions(-) diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 36a25d9712..3df92cfd3c 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -442,7 +442,8 @@ subroutine DailyPRTAllometricCNP(this,co_num,nplant) n_gain0 = n_gain p_gain0 = p_gain c_gain0 = c_gain - + + ! Calculate Carbon allocation targets ! ----------------------------------------------------------------------------------- @@ -674,8 +675,6 @@ subroutine DailyPRTAllometricCNP(this,co_num,nplant) ! then call this%TrimFineRoot() - - return end subroutine DailyPRTAllometricCNP @@ -698,54 +697,50 @@ end function SafeLog ! ===================================================================================== + subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) use FatesInterfaceTypesMod , only : hlm_day_of_year use FatesInterfaceTypesMod , only : hlm_days_per_year use FatesInterfaceTypesMod , only : hlm_current_year - + class(cnp_allom_prt_vartypes) :: this real(r8) :: target_c(:) real(r8) :: target_dcdd(:) integer,intent(in) :: co_num real(r8),intent(in) :: nplant - + real(r8), pointer :: l2fr ! leaf to fineroot target biomass scaler integer :: ipft ! PFT index real(r8), pointer :: dbh real(r8) :: canopy_trim - + integer :: leaf_status real(r8) :: store_c_max, store_c_act real(r8) :: store_nut_max, store_nut_act real(r8) :: n_ratio, p_ratio, np_ratio real(r8) :: fnrt_c,leaf_c,store_c,struct_c,sapw_c,c_gain - real(r8) :: c_fnrt_expand - real(r8) :: l2fr_delta_max - real(r8) :: logi_k - real(r8) :: l2fr_mult real(r8) :: l2fr_delta - real(r8) :: cn_ratio, cp_ratio + real(r8) :: cn_ratio, cp_ratio ! ratio of relative C storage over relative N or P storage real(r8) :: dcxdt_ratio ! log change (derivative) of the maximum of the N/C and P/C storage ratio - real(r8) :: cx_logratio ! log Maximum of the C/N and C/P storage ratio - real(r8), pointer :: cx_int ! Integration of the cx_logratio - real(r8), pointer :: cx0 ! The log of the cx ratio from previous time-step - real(r8), pointer :: ema_dcxdt ! the EMA of the change in log storage ratio - integer :: sup_flag - real(r8), parameter :: max_l2fr_cgain_frac = 0.99_r8 + real(r8) :: cx_logratio ! log Maximum of the C/N and C/P storage ratio + real(r8), pointer :: cx_int ! Integration of the cx_logratio + real(r8), pointer :: cx0 ! The log of the cx ratio from previous time-step + real(r8), pointer :: ema_dcxdt ! the EMA of the change in log storage ratio + real(r8), parameter :: pid_drv_wgt = 1._r8/20._r8 ! n-day smoothing (K on the derivative of PID) - + + ! These are different ways of defining the process function in the PID controller. pid_ncratio_function + ! is perhaps the most complete, in that it gives the true balance of relative C stores to relative N + ! stores. In the future we may just remove the alternatives + integer, parameter :: pid_c_function = 0 integer, parameter :: pid_n_function = 1 integer, parameter :: pid_minnc_function = 2 integer, parameter :: pid_alogmaxnc_function = 3 integer, parameter :: pid_ncratio_function = 4 integer, parameter :: pid_function = pid_ncratio_function - - ! If we do not have leaves out, then the relative nutrient vs carbon - ! balancing is meaningless, just leave this routine - if(this%GetState(leaf_organ, carbon12_element)/target_c(leaf_organ) < 0.5_r8) return - + leaf_status = this%bc_in(acnp_bc_in_id_lstat)%ival ipft = this%bc_in(acnp_bc_in_id_pft)%ival l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval @@ -753,188 +748,162 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) cx_int => this%bc_inout(acnp_bc_inout_id_cx_int)%rval cx0 => this%bc_inout(acnp_bc_inout_id_cx0)%rval ema_dcxdt => this%bc_inout(acnp_bc_inout_id_emadcxdt)%rval - - ! Step 1: Determine the nutrient to carbon ratio (aka relative health factor) - ! ----------------------------------------------------------------------------------- - - store_c_max = target_c(store_organ) - - store_c_act = max(0.001_r8*store_c_max,this%GetState(store_organ, carbon12_element) + & - this%bc_in(acnp_bc_in_id_netdc)%rval) - - if(n_uptake_mode.ne.prescribed_n_uptake)then - - ! Calculate the relative nitrogen storage fraction, - ! over the relative carbon storage fraction. - - store_nut_max = this%GetNutrientTarget(nitrogen_element,store_organ,stoich_growth_min) - - store_nut_act = max(0.001_r8*store_nut_max, & - this%GetState(store_organ, nitrogen_element) + & - this%bc_inout(acnp_bc_inout_id_netdn)%rval) - - select case(pid_function) - case(pid_c_function) - n_ratio = store_c_act/store_c_max - case(pid_n_function) - n_ratio = store_nut_max/store_nut_act - case(pid_minnc_function) - if((store_nut_act/store_nut_max) > (store_c_act/store_c_max))then - n_ratio = (store_c_act/store_c_max) - else - n_ratio = (store_nut_max/store_nut_act) - end if - case(pid_alogmaxnc_function) - if( abs(SafeLog(store_nut_act/store_nut_max)) < abs(SafeLog(store_c_act/store_c_max))) then - n_ratio = (store_c_act/store_c_max) - else - n_ratio = (store_nut_max/store_nut_act) - end if - case(pid_ncratio_function) - n_ratio = (store_c_act/store_c_max)/(store_nut_act/store_nut_max) - end select - - ! This is more of a diagnostic, to see if the other process functions - ! are as good as the ratio of relative ratios - cn_ratio = (store_c_act/store_c_max)/(store_nut_act/store_nut_max) - - else - n_ratio = -1._r8 - end if - - if(p_uptake_mode.ne.prescribed_p_uptake)then - - ! Calculate the relative phosphorus storage fraction, - ! over the relative carbon storage fraction. - - store_nut_max = this%GetNutrientTarget(phosphorus_element,store_organ,stoich_growth_min) - - store_nut_act = max(0.001_r8*store_nut_max, & - this%GetState(store_organ, phosphorus_element) + & - this%bc_inout(acnp_bc_inout_id_netdp)%rval) - - select case(pid_function) - case(pid_c_function) - p_ratio = store_c_act/store_c_max - case(pid_n_function) - p_ratio = store_nut_max/store_nut_act - case(pid_minnc_function) - if((store_nut_act/store_nut_max) > (store_c_act/store_c_max))then - p_ratio = (store_c_act/store_c_max) - else - p_ratio = (store_nut_max/store_nut_act) - end if - case(pid_alogmaxnc_function) - if( abs(SafeLog(store_nut_act/store_nut_max)) < abs(SafeLog(store_c_act/store_c_max))) then - p_ratio = (store_c_act/store_c_max) - else - p_ratio = (store_nut_max/store_nut_act) - end if - case(pid_ncratio_function) - p_ratio = (store_c_act/store_c_max)/(store_nut_act/store_nut_max) - end select - - cp_ratio = (store_c_act/store_c_max)/(store_nut_act/store_nut_max) - + + ! Abort if leaves are off + if(leaf_status.eq.leaves_off) return + + + ! Step 1: Determine the process function for the controller. Generally, this is + ! some indicator about the relative health of the plant in terms of carbon versus + ! nutrient. There are a few ways to cast this function, but right now we are using + ! the relative amount of Carbon storage (actual/maximum) divided by the relative amount + ! of nutrient (actual/maximum). We take the natural log of this ratio. And then we take + ! maximum of the two quotients that use nitrogen and phosphorus. + ! ----------------------------------------------------------------------------------- + + store_c_max = target_c(store_organ) + + store_c_act = max(0.001_r8*store_c_max,this%GetState(store_organ, carbon12_element) + & + this%bc_in(acnp_bc_in_id_netdc)%rval) + + if(n_uptake_mode.eq.prescribed_n_uptake)then + n_ratio = -1._r8 + else + + ! Calculate the relative nitrogen storage fraction, + ! over the relative carbon storage fraction. + + store_nut_max = this%GetNutrientTarget(nitrogen_element,store_organ,stoich_growth_min) + + store_nut_act = max(0.001_r8*store_nut_max, & + this%GetState(store_organ, nitrogen_element) + & + this%bc_inout(acnp_bc_inout_id_netdn)%rval) + + select case(pid_function) + case(pid_c_function) + n_ratio = store_c_act/store_c_max + case(pid_n_function) + n_ratio = store_nut_max/store_nut_act + case(pid_minnc_function) + if((store_nut_act/store_nut_max) > (store_c_act/store_c_max))then + n_ratio = (store_c_act/store_c_max) + else + n_ratio = (store_nut_max/store_nut_act) + end if + case(pid_alogmaxnc_function) + if( abs(SafeLog(store_nut_act/store_nut_max)) < abs(SafeLog(store_c_act/store_c_max))) then + n_ratio = (store_c_act/store_c_max) + else + n_ratio = (store_nut_max/store_nut_act) + end if + case(pid_ncratio_function) + n_ratio = (store_c_act/store_c_max)/(store_nut_act/store_nut_max) + end select + + ! This is more of a diagnostic, to see if the other process functions + ! are as good as the ratio of relative ratios + cn_ratio = (store_c_act/store_c_max)/(store_nut_act/store_nut_max) + + end if + + if(p_uptake_mode.eq.prescribed_p_uptake)then + p_ratio = -1._r8 + else + + ! Calculate the relative phosphorus storage fraction, + ! over the relative carbon storage fraction. + + store_nut_max = this%GetNutrientTarget(phosphorus_element,store_organ,stoich_growth_min) + + store_nut_act = max(0.001_r8*store_nut_max, & + this%GetState(store_organ, phosphorus_element) + & + this%bc_inout(acnp_bc_inout_id_netdp)%rval) + + select case(pid_function) + case(pid_c_function) + p_ratio = store_c_act/store_c_max + case(pid_n_function) + p_ratio = store_nut_max/store_nut_act + case(pid_minnc_function) + if((store_nut_act/store_nut_max) > (store_c_act/store_c_max))then + p_ratio = (store_c_act/store_c_max) + else + p_ratio = (store_nut_max/store_nut_act) + end if + case(pid_alogmaxnc_function) + if( abs(SafeLog(store_nut_act/store_nut_max)) < abs(SafeLog(store_c_act/store_c_max))) then + p_ratio = (store_c_act/store_c_max) + else + p_ratio = (store_nut_max/store_nut_act) + end if + case(pid_ncratio_function) + p_ratio = (store_c_act/store_c_max)/(store_nut_act/store_nut_max) + end select + + cp_ratio = (store_c_act/store_c_max)/(store_nut_act/store_nut_max) + + + end if + + ! Use the limiting nutrient species + if( (n_uptake_mode.eq.prescribed_n_uptake) .and. & + (p_uptake_mode.eq.prescribed_p_uptake) )then + cx_int = 0._r8 + ema_dcxdt = 0._r8 + cx0 = 0.0_r8 + return + else + + if (n_uptake_mode.eq.prescribed_n_uptake) then + cx_logratio = SafeLog(p_ratio) + elseif (p_uptake_mode.eq.prescribed_p_uptake) then + cx_logratio = SafeLog(n_ratio) else - p_ratio = -1._r8 + cx_logratio = SafeLog(max(p_ratio,n_ratio)) end if - - ! Use the limiting nutrient species - if( (n_uptake_mode.eq.prescribed_n_uptake) .and. & - (p_uptake_mode.eq.prescribed_p_uptake) )then - cx_int = 0._r8 - ema_dcxdt = 0._r8 - cx0 = 0.0_r8 - return - else - cx_logratio = SafeLog(max(n_ratio,p_ratio)) + ! If cx_logratio has just crossed zero, then + ! reset the integrator. This will be true if + ! the sign of the current ratio is different than + ! the sign of the previous - ! If cx_logratio has just crossed zero, then - ! reset the integrator. This will be true if - ! the sign of the current ratio is different than - ! the sign of the previous + cx_int = cx_int + cx_logratio + ! Reset the integrator if its sign changes + if( abs(cx_logratio)>nearzero .and. abs(cx0)>nearzero) then if( (cx_logratio/abs(cx_logratio) - cx0/abs(cx0)) > nearzero ) then cx_int = cx_logratio - else - cx_int = cx_int + cx_logratio end if - - dcxdt_ratio = cx_logratio-cx0 - - ema_dcxdt = pid_drv_wgt*dcxdt_ratio + (1._r8-pid_drv_wgt)*ema_dcxdt + end if - cx0 = cx_logratio + dcxdt_ratio = cx_logratio-cx0 - - end if + ema_dcxdt = pid_drv_wgt*dcxdt_ratio + (1._r8-pid_drv_wgt)*ema_dcxdt - fnrt_c = this%GetState(fnrt_organ, carbon12_element) - leaf_c = this%GetState(leaf_organ, carbon12_element) - store_c = this%GetState(store_organ, carbon12_element) - struct_c = this%GetState(struct_organ, carbon12_element) - sapw_c = this%GetState(sapw_organ, carbon12_element) + cx0 = cx_logratio - ! If there is overflow storage, add this to the gain - c_gain = this%bc_in(acnp_bc_in_id_netdc)%rval + max(0._r8,store_c-target_c(store_organ)) - + end if + l2fr_delta = prt_params%pid_kp(ipft)*cx_logratio + & - prt_params%pid_ki(ipft)*cx_int + & - prt_params%pid_kd(ipft)*ema_dcxdt - - ! ----------------------------------------------------------------------------- - ! To decide the upper limit on expanding root growth, we perform a carbon - ! balance. Note that if we are growing roots out more, than we have proportionaly - ! more C compared to other resources. Specifically, we want to limit root growth - ! such that allocation to roots can't exceed a certain fraction of the daily - ! available carbon. This fraction is "max_l2fr_cgain_frac". - ! Additional notes. When calculating the "allocation to roots", we consider - ! both the carbon necessary to get the roots "on allometry" plux the carbon - ! necessary to expand them. - ! - ! l2fr_delta_max*target_fnrt_c - target_fnrt_c < - ! c_gain - (target_fnrt_c-actual_fnrt_c) - - ! (target_leaf_c-actual_leaf_c) - - ! (target_sapw_c-actual_sapw_c) - - ! (target_dead_c-actual_dead_c) - - ! (target_stor_c-actual_stor_c) - ! ------------------------------------------------------------------------------ - ! This is a rough estimate of the amount of carbon we will have to spend - ! on root expansion after we get back on allometry - c_fnrt_expand = max_l2fr_cgain_frac* ( c_gain - & - max(0._r8,target_c(fnrt_organ)-fnrt_c) - & - max(0._r8,target_c(leaf_organ)-leaf_c) - & - max(0._r8,target_c(sapw_organ)-sapw_c) - & - max(0._r8,target_c(struct_organ)-struct_c) - & - max(0._r8,target_c(store_organ)-store_c)) - - !c_fnrt_expand > (l2fr+l2fr_delta)*target_c(leaf_organ) - l2fr*target_c(leaf_organ) - !c_fnrt_expand = (l2fr+l2fr_delta_max)*target_c(leaf_organ) - l2fr*target_c(leaf_organ) - !c_fnrt_expand = l2fr_delta_max*target_c(leaf_organ) - - !l2fr_delta_max = max(0._r8,c_fnrt_expand/target_c(leaf_organ)) - + prt_params%pid_ki(ipft)*cx_int + & + prt_params%pid_kd(ipft)*ema_dcxdt + ! Apply the delta, also, avoid generating incredibly small l2fr's, ! super small l2frs will occur in plants that perpetually get almost ! now carbon gain, such as newly recruited plants in a dark understory l2fr = max(l2fr_min, l2fr + l2fr_delta) - - !l2fr = max(l2fr_min, l2fr + min(l2fr_delta_max,l2fr_delta)) - + !if((co_num==1) .or. (co_num==2)) print*,'AAX1',co_num,hlm_current_year,hlm_day_of_year, & - ! dbh,nplant,(store_c_act/store_c_max),cn_ratio,SafeLog(cn_ratio),l2fr - + ! dbh,nplant,(store_c_act/store_c_max),cx_logratio,cx_int,ema_dcxdt,l2fr ! Find the updated target fineroot biomass call bfineroot(dbh,ipft,canopy_trim, l2fr, target_c(fnrt_organ),target_dcdd(fnrt_organ)) return end subroutine CNPAdjustFRootTargets - + ! ===================================================================================== subroutine TrimFineRoot(this) From 68d71c2101a24c2bc64df5b05d453570cfa437bb Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 11 Oct 2022 17:17:22 -0400 Subject: [PATCH 372/852] More cleanup CNP growth code, removal of unused variables, labels, units and encapsulation of symbiotic fixation routine --- biogeochem/EDCohortDynamicsMod.F90 | 4 +- main/EDTypesMod.F90 | 2 +- parteh/PRTAllometricCNPMod.F90 | 177 +++++------------------------ 3 files changed, 32 insertions(+), 151 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 78ec2a4f8e..47ed64fcc6 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -594,7 +594,7 @@ subroutine nan_cohort(cc_p) !RESPIRATION currentCohort%rdark = nan currentCohort%resp_m = nan ! Maintenance respiration. kGC/cohort/year - currentCohort%resp_excess = nan ! Respiration of excess (unallocatable) carbon + currentCohort%resp_excess = nan ! Respiration of excess (unallocatable) carbon (kg/indiv/day) currentCohort%livestem_mr = nan ! Live stem maintenance respiration. kgC/indiv/s-1 currentCohort%livecroot_mr = nan ! Coarse root maintenance respiration. kgC/indiv/s-1 currentCohort%froot_mr = nan ! Fine root maintenance respiration. kgC/indiv/s-1 @@ -707,7 +707,7 @@ subroutine zero_cohort(cc_p) currentCohort%daily_n_demand = -9._r8 ! Fixation is also integrated over the course of the day - ! and must be zeroid upon creation and after plant + ! and must be zeroed upon creation and after plant ! resource allocation currentCohort%daily_n_fixation = 0._r8 diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 7d6ffd2b5e..413ef48c4f 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -214,7 +214,7 @@ module EDTypesMod ! enabled simulations, this is dynamic, will ! vary between allom_l2fr_min and allom_l2fr_max ! parameters, with a tendency driven by - ! nutrient storage) + ! nutrient storage) [g root / g leaf] ! Used for CNP diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 3df92cfd3c..6b7f4d252c 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -255,7 +255,7 @@ module PRTAllometricCNPMod class(prt_global_type), public, target, allocatable :: prt_global_acnp character(len=*), parameter, private :: sourcefile = __FILE__ - logical, parameter :: debug = .true. + logical, parameter :: debug = .false. public :: InitPRTGlobalAllometricCNP @@ -376,10 +376,6 @@ subroutine DailyPRTAllometricCNP(this,co_num,nplant) integer :: i_org ! organ index integer :: i_var ! variable index - ! Agruments for allometry functions, that are not in the target_c array - - real(r8) :: max_store_n - ! These are daily mass gains, frozen in time, not drawn from, and thus ! these are only used for evaluating mass balancing at the end real(r8) :: dbh0 @@ -393,7 +389,6 @@ subroutine DailyPRTAllometricCNP(this,co_num,nplant) real(r8) :: allocated_c real(r8) :: allocated_n real(r8) :: allocated_p - real(r8) :: target_n,target_p real(r8) :: sum_c ! error checking sum ! If more than 1 leaf age bin is present, this @@ -404,11 +399,12 @@ subroutine DailyPRTAllometricCNP(this,co_num,nplant) ! In/out boundary conditions - resp_excess => this%bc_inout(acnp_bc_inout_id_resp_excess)%rval; - dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval; dbh0 = dbh + resp_excess => this%bc_inout(acnp_bc_inout_id_resp_excess)%rval + dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval + dbh0 = dbh l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval - n_gain => this%bc_inout(acnp_bc_inout_id_netdn)%rval; - p_gain => this%bc_inout(acnp_bc_inout_id_netdp)%rval; + n_gain => this%bc_inout(acnp_bc_inout_id_netdn)%rval + p_gain => this%bc_inout(acnp_bc_inout_id_netdp)%rval ! Assume that there is no other source of excess respiration @@ -433,10 +429,10 @@ subroutine DailyPRTAllometricCNP(this,co_num,nplant) ! set the gains to something massive. 1 kilo of pure ! nutrient should be wayyy more than enough if(n_uptake_mode.eq.prescribed_n_uptake) then - n_gain = 1.e3 + n_gain = 1.e3_r8 end if if(p_uptake_mode.eq.prescribed_p_uptake) then - p_gain = 1.e3 + p_gain = 1.e3_r8 end if n_gain0 = n_gain @@ -701,14 +697,13 @@ end function SafeLog subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) use FatesInterfaceTypesMod , only : hlm_day_of_year - use FatesInterfaceTypesMod , only : hlm_days_per_year use FatesInterfaceTypesMod , only : hlm_current_year class(cnp_allom_prt_vartypes) :: this real(r8) :: target_c(:) real(r8) :: target_dcdd(:) - integer,intent(in) :: co_num - real(r8),intent(in) :: nplant + integer,intent(in) :: co_num ! Used for single plant diagnostics + real(r8),intent(in) :: nplant ! Used for single plant diagnostics real(r8), pointer :: l2fr ! leaf to fineroot target biomass scaler integer :: ipft ! PFT index @@ -717,8 +712,7 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) integer :: leaf_status real(r8) :: store_c_max, store_c_act real(r8) :: store_nut_max, store_nut_act - real(r8) :: n_ratio, p_ratio, np_ratio - real(r8) :: fnrt_c,leaf_c,store_c,struct_c,sapw_c,c_gain + real(r8) :: n_ratio, p_ratio real(r8) :: l2fr_delta real(r8) :: cn_ratio, cp_ratio ! ratio of relative C storage over relative N or P storage real(r8) :: dcxdt_ratio ! log change (derivative) of the maximum of the N/C and P/C storage ratio @@ -727,7 +721,8 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) real(r8), pointer :: cx0 ! The log of the cx ratio from previous time-step real(r8), pointer :: ema_dcxdt ! the EMA of the change in log storage ratio - real(r8), parameter :: pid_drv_wgt = 1._r8/20._r8 ! n-day smoothing (K on the derivative of PID) + real(r8), parameter :: pid_drv_wgt = 1._r8/10._r8 ! n-day smoothing of the derivative + ! of the process function in the PID controller ! These are different ways of defining the process function in the PID controller. pid_ncratio_function ! is perhaps the most complete, in that it gives the true balance of relative C stores to relative N @@ -996,32 +991,22 @@ subroutine CNPPrioritizedReplacement(this,c_gain, n_gain, p_gain, target_c) real(r8), dimension(num_organs) :: deficit_p ! Deficit to get to target from current [kg] integer :: i, ii, i_org ! Loop indices (mostly for organs) - integer :: i_var ! variable index + integer :: i_var ! variable index integer :: i_pri ! loop index for priority integer :: ipft ! Plant functional type index of this plant integer :: leaf_status ! Is this plant in a leaf on or off status? - real(r8) :: dbh ! DBH [cm] real(r8) :: canopy_trim ! trim factor for maximum leaf biomass real(r8) :: target_n ! Target mass of N for a given organ [kg] real(r8) :: target_p ! Target mass of P for a given organ [kg] integer :: priority_code ! Index for priority level of each organ real(r8) :: sum_c_demand ! Carbon demanded to bring tissues up to allometry (kg) - real(r8) :: sum_n_deficit ! The nitrogen deficit of all pools for given priority level (kg) - real(r8) :: sum_p_deficit ! The phosphorus deficit of all pools for given priority level (kg) - real(r8) :: store_below_target - real(r8) :: store_target_fraction - real(r8) :: store_demand - real(r8) :: store_c_flux + real(r8) :: store_below_target ! The amount of storage that is less than the target (kg) + real(r8) :: store_target_fraction ! The fraction of actual storage carbon over the target (kg) + real(r8) :: store_demand ! Based on the target fraction, an exponential function defining + ! how much carbon we should try to put back into storage + real(r8) :: store_c_flux ! The amount of C we draw from gains to give back to storage (kg) real(r8) :: sum_c_flux ! The flux to bring tissues up to allometry (kg) - real(r8) :: sum_n_flux ! The flux of nitrogen "" (kg) - real(r8) :: sum_p_flux ! The flux of phosphorus "" (Kg) real(r8) :: c_flux ! carbon flux into an arbitrary pool (kg) - real(r8) :: gr_flux ! carbon flux to fulfill growth respiration of an arbitrary pool (kg) - real(r8) :: n_flux ! nitrogen flux into an arbitrary pool (kg) - real(r8) :: p_flux ! phosphorus flux into an arbitrary pool (kg) - real(r8) :: c_gain_flux ! Flux used to pay back negative carbon gain (from storage) (kgC) - real(r8) :: sapw_area - integer :: n_max_priority ! Maximum possible number of priority levels is ! the total number organs plus 1, which allows ! each organ to have its own level, and ignore @@ -1183,7 +1168,6 @@ subroutine CNPPrioritizedReplacement(this,c_gain, n_gain, p_gain, target_c) ! This is the desired need for carbon store_target_fraction = max(this%variables(store_c_id)%val(1)/target_c(store_organ),0._r8) - store_demand = max(c_gain*(exp(-1.*store_target_fraction**4._r8) - exp( -1.0_r8 )),0._r8) ! The flux is the (positive) minimum of all three @@ -1325,22 +1309,18 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & ! (new uptake + storage) real(r8), intent(inout) :: p_gain ! Total P available for allocation ! (new uptake + storage) - real(r8), intent(in) :: target_c(:) - real(r8), intent(in) :: target_dcdd(:) - + real(r8), intent(in) :: target_c(:) ! target carbon mass for each organ (before growth) + real(r8), intent(in) :: target_dcdd(:) ! target carbon mass derivative (wrt dbh) before growth) + + real(r8), pointer :: dbh integer :: ipft - integer, pointer :: limiter - real(r8) :: canopy_trim - real(r8) :: leaf_status - real(r8) :: l2fr - + integer, pointer :: limiter ! Integer flagging which (C,N,P) is limiting + real(r8) :: canopy_trim ! fraction of crown trimmed + real(r8) :: leaf_status ! leaves on or off? + real(r8) :: l2fr ! leaf to fineroot allometry multiplier integer :: i, ii ! organ index loops (masked and unmasked) integer :: i_org ! global organ index - integer :: istep ! outer step iteration loop - real(r8) :: grow_c_from_c ! carbon transferred into tissues - real(r8) :: grow_c_from_n ! carbon needed to match N transfers to tissues - real(r8) :: grow_c_from_p ! carbon needed to match P transfers to tissues real(r8) :: total_dcostdd ! Total carbon transferred to all pools for unit growth logical :: step_pass ! flag stating if the integration sub-steps passed checks real(r8) :: totalC ! total carbon sent to integrator (kg) @@ -1354,14 +1334,10 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & ! at current stature (dbh) [/] real(r8) :: sum_c_flux ! Sum of the carbon allocated, as reported ! by the ODE solver. [kg] - real(r8) :: np_limit - real(r8) :: n_match - real(r8) :: p_match real(r8) :: c_flux_adj ! Adjustment to total carbon flux during stature growth ! intended to correct integration error (kg/kg) real(r8) :: c_flux ! Carbon flux from the gain pool to an organ (kgC) real(r8) :: n_flux,p_flux - real(r8) :: gr_flux ! Growth respiration flux for the current transaction (kgC) real(r8) :: c_gstature ! Carbon reserved for stature growth (kg) real(r8) :: target_n ! Target mass of N for a given organ [kg] real(r8) :: target_p ! Target mass of P for a given organ [kg] @@ -1409,8 +1385,8 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & integer, parameter :: grow_lim_estNP = 2 ! Estimate equivalent C from N and P integer, parameter :: grow_lim_type = grow_lim_estNP - real :: neq_cgain, peq_cgain ! N and P equivalent c_gain spent on growth - real :: cnp_gain ! used as a check to see efficiency of limited growth + real(r8) :: neq_cgain, peq_cgain ! N and P equivalent c_gain spent on growth + real(r8) :: cnp_gain ! used as a check to see efficiency of limited growth @@ -1858,7 +1834,6 @@ subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & real(r8) :: target_p real(r8) :: store_c_target ! Target amount of C in storage including "overflow" [kgC] real(r8) :: total_c_flux ! Total C flux from gains into storage and growth R [kgC] - real(r8) :: store_m_flux ! Flux into storage [kg] real(r8), pointer :: dbh real(r8), pointer :: resp_excess integer :: ipft @@ -2261,7 +2236,6 @@ function AllomCNPGrowthDeriv(l_state_array,l_state_mask,cbalance,intgr_params) r real(r8) :: bgw_dcdd_target ! target BG wood biomass derivative wrt d, (kgC/cm) real(r8) :: store_dcdd_target ! target storage biomass derivative wrt d, (kgC/cm) real(r8) :: struct_dcdd_target ! target structural biomass derivative wrt d, (kgC/cm) - real(r8) :: total_dcdd_target ! target total (not reproductive) biomass derivative wrt d, (kgC/cm) real(r8) :: repro_fraction ! fraction of carbon balance directed towards reproduction (kgC/kgC) real(r8) :: total_dcostdd ! carbon cost for non-reproductive pools per unit increment of dbh @@ -2382,99 +2356,6 @@ function AllomCNPGrowthDeriv(l_state_array,l_state_mask,cbalance,intgr_params) r return end function AllomCNPGrowthDeriv - ! ==================================================================================== - - subroutine TargetAllometryCheck(b0_leaf,b0_fnrt,b0_sapw,b0_store,b0_struct, & - bleaf,bfnrt,bsapw,bstore,bstruct, & - bt_leaf,bt_fnrt,bt_sapw,bt_store,bt_struct, & - carbon_balance,ipft,leaf_status, & - grow_leaf,grow_fnrt,grow_sapw,grow_store,grow_struct) - - ! Arguments - real(r8),intent(in) :: b0_leaf !initial - real(r8),intent(in) :: b0_fnrt - real(r8),intent(in) :: b0_sapw - real(r8),intent(in) :: b0_store - real(r8),intent(in) :: b0_struct - real(r8),intent(in) :: bleaf !actual - real(r8),intent(in) :: bfnrt - real(r8),intent(in) :: bsapw - real(r8),intent(in) :: bstore - real(r8),intent(in) :: bstruct - real(r8),intent(in) :: bt_leaf !target - real(r8),intent(in) :: bt_fnrt - real(r8),intent(in) :: bt_sapw - real(r8),intent(in) :: bt_store - real(r8),intent(in) :: bt_struct - real(r8),intent(in) :: carbon_balance !remaining carbon balance - integer,intent(in) :: ipft !Plant functional type - integer,intent(in) :: leaf_status !Phenology status - logical,intent(out) :: grow_leaf !growth flag - logical,intent(out) :: grow_fnrt - logical,intent(out) :: grow_sapw - logical,intent(out) :: grow_store - logical,intent(out) :: grow_struct - ! Local variables - logical :: fine_leaf - logical :: fine_fnrt - logical :: fine_sapw - logical :: fine_store - logical :: fine_struct - logical :: all_fine - ! Local constants - character(len= 3), parameter :: fmth = '(a)' - character(len=27), parameter :: fmtb = '(a,3(1x,es12.5,1x,a),1x,l1)' - character(len=13), parameter :: fmte = '(a,1x,es12.5)' - character(len=10), parameter :: fmti = '(a,1x,i12)' - - - ! First test whether or not each pool looks reasonable. - fine_leaf = (bt_leaf - bleaf ) <= calloc_abs_error - fine_fnrt = (bt_fnrt - bfnrt ) <= calloc_abs_error - fine_sapw = (bt_sapw - bsapw ) <= calloc_abs_error - fine_store = (bt_store - bstore ) <= calloc_abs_error - fine_struct = (bt_struct - bstruct) <= calloc_abs_error - all_fine = fine_leaf .and. fine_fnrt .and. fine_sapw .and. & - fine_store .and. fine_struct - - ! Decide whether or not to grow tissues (but only if all tissues look fine). - ! We grow only when biomass is less than target biomass (with tolerance). - if (all_fine) then - grow_leaf = ( bleaf - bt_leaf ) <= calloc_abs_error - grow_fnrt = ( bfnrt - bt_fnrt ) <= calloc_abs_error - grow_sapw = ( bsapw - bt_sapw ) <= calloc_abs_error - grow_store = ( bstore - bt_store ) <= calloc_abs_error - grow_struct = ( bstruct - bt_struct ) <= calloc_abs_error - else - ! If anything looks not fine, write a detailed report - write(fates_log(),fmt=fmth) '======' - write(fates_log(),fmt=fmth) ' At least one tissue is not on-allometry at the growth step' - write(fates_log(),fmt=fmth) '======' - write(fates_log(),fmt=fmth) '' - write(fates_log(),fmt=fmth) ' Biomass and on-allometry test (''F'' means problem)' - write(fates_log(),fmt=fmth) '------' - write(fates_log(),fmt=fmth) ' Tissue | Initial | Current | Target | On-allometry' - write(fates_log(),fmt=fmtb) ' Leaf |',b0_leaf ,'|',bleaf ,'|',bt_leaf ,'|',fine_leaf - write(fates_log(),fmt=fmtb) ' Fine root |',b0_fnrt ,'|',bfnrt ,'|',bt_fnrt ,'|',fine_fnrt - write(fates_log(),fmt=fmtb) ' Sap wood |',b0_sapw ,'|',bsapw ,'|',bt_sapw ,'|',fine_sapw - write(fates_log(),fmt=fmtb) ' Storage |',b0_store ,'|',bstore ,'|',bt_store ,'|',fine_store - write(fates_log(),fmt=fmtb) ' Structural |',b0_struct ,'|',bstruct ,'|',bt_struct ,'|',fine_struct - write(fates_log(),fmt=fmth) '' - write(fates_log(),fmt=fmth) ' Ancillary information' - write(fates_log(),fmt=fmth) '------' - write(fates_log(),fmt=fmti) ' PFT = ',ipft - write(fates_log(),fmt=fmti) ' leaf_status = ',leaf_status - write(fates_log(),fmt=fmte) ' carbon_balance = ',carbon_balance - write(fates_log(),fmt=fmte) ' calloc_abs_error = ',calloc_abs_error - write(fates_log(),fmt=fmth) '' - write(fates_log(),fmt=fmth) '======' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - return - end subroutine TargetAllometryCheck - - ! ===================================================================================== From 33cd3ed85e5f414c458b1f147fbf57557479ec40 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 11 Oct 2022 15:46:57 -0700 Subject: [PATCH 373/852] add github workflow to add new issues to triage board automatically --- .github/workflows/add-to-gh_projects.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/add-to-gh_projects.yml diff --git a/.github/workflows/add-to-gh_projects.yml b/.github/workflows/add-to-gh_projects.yml new file mode 100644 index 0000000000..8c34dd6922 --- /dev/null +++ b/.github/workflows/add-to-gh_projects.yml @@ -0,0 +1,23 @@ +# This is a basic workflow to help you get started with Actions + +name: Add issue to github project issue triage board + +# Controls when the workflow will run +on: + issues: + types: + - opened + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + add-to-project: + name: add issue to issue triage board project + runs-on: ubuntu-latest + steps: + - uses: actions/add-to-project@v0.3.0 + with: + # URL of the project to add issues to + project-url: https://github.com/orgs/NGEET/projects/1 + # A GitHub personal access token with write access to the project + github-token: ${{ secrets.ADD_TO_PROJECT_PAT }} + From cf8971710caadd8f6cf66881b547512a9f346fca Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 14 Oct 2022 09:50:23 -0400 Subject: [PATCH 374/852] cnp v2, syntax cleanup --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 77 +++++++++++++++------- main/EDTypesMod.F90 | 2 +- parteh/PRTAllometricCNPMod.F90 | 8 +-- 3 files changed, 58 insertions(+), 29 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index b56e8073b4..fff5d74ce5 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -30,6 +30,7 @@ module FATESPlantRespPhotosynthMod use FatesConstantsMod, only : molar_mass_water use FatesConstantsMod, only : rgas_J_K_mol use FatesConstantsMod, only : fates_unset_r8 + use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm use FatesInterfaceTypesMod, only : hlm_use_planthydro use FatesInterfaceTypesMod, only : hlm_parteh_mode use FatesInterfaceTypesMod, only : numpft @@ -128,7 +129,6 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) use FatesConstantsMod, only : g_per_kg use FatesConstantsMod, only : umol_per_mmol use FatesConstantsMod, only : rgas => rgas_J_K_kmol - use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm use FatesParameterDerivedMod, only : param_derived use FatesAllometryMod, only : bleaf, bstore_allom @@ -240,9 +240,9 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) real(r8) :: cumulative_lai ! the cumulative LAI, top down, to the leaf layer of interest real(r8) :: leaf_psi ! leaf xylem matric potential [MPa] (only meaningful/used w/ hydro) real(r8) :: fnrt_mr_layer ! fine root maintenance respiation per layer [kgC/plant/s] - real(r8) :: c_cost_nfix ! carbon cost of N fixation [kgC/kgN] - real(r8) :: c_spent_nfix ! carbon spent on N fixation, per layer [kgC/plant/timestep] - + + real(r8) :: fnrt_mr_nfix_layer ! fineroot maintenance respiration specifically for symbiotic fixation [kgC/plant/layer/s] + real(r8) :: nfix_layer ! Nitrogen fixed in each layer this timestep [kgN/plant/layer/timestep] real(r8), allocatable :: rootfr_ft(:,:) ! Root fractions per depth and PFT ! ----------------------------------------------------------------------------------- @@ -269,11 +269,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! (gC/gN/s) ! ------------------------------------------------------------------------ - ! N fixation parameters from Houlton et al (2008) and Fisher et al (2010) - real(r8), parameter :: s_fix = -6.25_r8 ! s parameter from FUN model (fisher et al 2010) - real(r8), parameter :: a_fix = -3.62_r8 ! a parameter from Houlton et al. 2010 (a = -3.62 +/- 0.52) - real(r8), parameter :: b_fix = 0.27_r8 ! b parameter from Houlton et al. 2010 (b = 0.27 +/-0.04) - real(r8), parameter :: c_fix = 25.15_r8 ! c parameter from Houlton et al. 2010 (c = 25.15 +/- 0.66) + ! ----------------------------------------------------------------------------------- ! Photosynthesis and stomatal conductance parameters, from: ! Bonan et al (2011) JGR, 116, doi:10.1029/2010JG001593 @@ -722,18 +718,15 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) fnrt_mr_layer = fnrt_n * ED_val_base_mr_20 * tcsoi * rootfr_ft(ft,j) * maintresp_reduction_factor - currentCohort%froot_mr = currentCohort%froot_mr + fnrt_mr_layer * (1._r8 + prt_params%nfix_mresp_scfrac(ft)) - ! calculate the cost of carbon for N fixation in each soil layer and calculate N fixation rate based on that [kgC / kgN] - c_cost_nfix = s_fix * (exp(a_fix + b_fix * (bc_in(s)%t_soisno_sl(j)-tfrz) & - * (1._r8 - 0.5_r8 * (bc_in(s)%t_soisno_sl(j)-tfrz) / c_fix)) - 2._r8) - - ! Time integrated amount of carbon spent on fixation (in this layer) [kgC/plant/layer/tstep] - c_spent_nfix = fnrt_mr_layer * dtime * prt_params%nfix_mresp_scfrac(ft) + call RootLayerNFixation(bc_in(s)%t_soisno_sl(j),ft,dtime,fnrt_mr_layer,fnrt_mr_nfix_layer,nfix_layer) - currentCohort%daily_n_fixation = currentCohort%daily_n_fixation + c_spent_nfix / c_cost_nfix + currentCohort%froot_mr = currentCohort%froot_mr + fnrt_mr_nfix_layer + fnrt_mr_layer + currentCohort%daily_n_fixation = currentCohort%daily_n_fixation + nfix_layer + + enddo ! Coarse Root MR (kgC/plant/s) (below ground sapwood) @@ -886,6 +879,48 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) end associate end subroutine FatesPlantRespPhotosynthDrive +! =========================================================================================== + + +subroutine RootLayerNFixation(t_soil,ft,dtime,fnrt_mr_layer,fnrt_mr_nfix_layer,nfix_layer) + + real(r8),intent(in) :: t_soil ! Temperature of the current soil layer [degC] + integer,intent(in) :: ft ! Functional type index + real(r8),intent(in) :: dtime ! Time step length [s] + real(r8),intent(in) :: fnrt_mr_layer ! Amount of maintenance respiration in the fine-roots + ! for all non-fixation related processes [kgC/s] + + real(r8),intent(out) :: fnrt_mr_nfix_layer ! The added maintenance respiration due to nfixation + ! to be added as a surcharge to non-fixation MR [kgC] + real(r8),intent(out) :: nfix_layer ! The amount of N fixed in this layer through + ! symbiotic activity [kgN] + + real(r8) :: c_cost_nfix ! carbon cost of N fixation [kgC/kgN] + real(r8) :: c_spent_nfix ! carbon spent on N fixation, per layer [kgC/plant/timestep] + + ! N fixation parameters from Houlton et al (2008) and Fisher et al (2010) + real(r8), parameter :: s_fix = -6.25_r8 ! s parameter from FUN model (fisher et al 2010) + real(r8), parameter :: a_fix = -3.62_r8 ! a parameter from Houlton et al. 2010 (a = -3.62 +/- 0.52) + real(r8), parameter :: b_fix = 0.27_r8 ! b parameter from Houlton et al. 2010 (b = 0.27 +/-0.04) + real(r8), parameter :: c_fix = 25.15_r8 ! c parameter from Houlton et al. 2010 (c = 25.15 +/- 0.66) + + ! Amount of C spent (as part of MR respiration) on symbiotic fixation [kgC/s] + fnrt_mr_nfix_layer = fnrt_mr_layer * prt_params%nfix_mresp_scfrac(ft) + + ! This is the unit carbon cost for nitrogen fixation. It is temperature dependant [kgC/kgN] + c_cost_nfix = s_fix * (exp(a_fix + b_fix * (t_soil-tfrz) & + * (1._r8 - 0.5_r8 * (t_soil-tfrz) / c_fix)) - 2._r8) + + ! Time integrated amount of carbon spent on fixation (in this layer) [kgC/plant/layer/tstep] + c_spent_nfix = fnrt_mr_nfix_layer * dtime + + ! Amount of nitrogen fixed in this layer [kgC/plant/layer/tstep]/[kgC/kgN] = [kgN/plant/layer/tstep] + nfix_layer = c_spent_nfix / c_cost_nfix + + +end subroutine RootLayerNFixation + + ! ======================================================================================= subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in @@ -1572,7 +1607,7 @@ function ft1_f(tl, ha) result(ans) ! !!USES use FatesConstantsMod, only : rgas => rgas_J_K_kmol - use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm + ! ! !ARGUMENTS: real(r8), intent(in) :: tl ! leaf temperature in photosynthesis temperature function (K) @@ -1599,7 +1634,6 @@ function fth_f(tl,hd,se,scaleFactor) result(ans) ! 7/23/16: Copied over from CLM by Ryan Knox ! use FatesConstantsMod, only : rgas => rgas_J_K_kmol - use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm ! ! !ARGUMENTS: @@ -1631,7 +1665,6 @@ function fth25_f(hd,se)result(ans) !!USES use FatesConstantsMod, only : rgas => rgas_J_K_kmol - use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm ! ! !ARGUMENTS: @@ -1945,9 +1978,6 @@ subroutine LeafLayerMaintenanceRespiration(lmr25top_ft, & veg_tempk, & lmr) - use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm - - ! Arguments real(r8), intent(in) :: lmr25top_ft ! canopy top leaf maint resp rate at 25C ! for this pft (umol CO2/m**2/s) @@ -2015,7 +2045,6 @@ subroutine LeafLayerBiophysicalRates( parsun_lsl, & ! --------------------------------------------------------------------------------- use EDPftvarcon , only : EDPftvarcon_inst - use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm ! Arguments ! ------------------------------------------------------------------------------ diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 413ef48c4f..3a8073d274 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -28,7 +28,7 @@ module EDTypesMod private ! By default everything is private save - integer, parameter, public :: nclmax = 2 ! Maximum number of canopy layers + integer, parameter, public :: nclmax = 3 ! Maximum number of canopy layers integer, parameter, public :: ican_upper = 1 ! Nominal index for the upper canopy integer, parameter, public :: ican_ustory = 2 ! Nominal index for diagnostics that refer ! to understory layers (all layers that diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 6b7f4d252c..6de86ea2da 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -797,7 +797,7 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) ! This is more of a diagnostic, to see if the other process functions ! are as good as the ratio of relative ratios - cn_ratio = (store_c_act/store_c_max)/(store_nut_act/store_nut_max) + cn_ratio = (store_nut_act/store_nut_max) end if @@ -866,7 +866,7 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) ! Reset the integrator if its sign changes if( abs(cx_logratio)>nearzero .and. abs(cx0)>nearzero) then - if( (cx_logratio/abs(cx_logratio) - cx0/abs(cx0)) > nearzero ) then + if( abs(cx_logratio/abs(cx_logratio) - cx0/abs(cx0)) > nearzero ) then cx_int = cx_logratio end if end if @@ -890,8 +890,8 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) l2fr = max(l2fr_min, l2fr + l2fr_delta) - !if((co_num==1) .or. (co_num==2)) print*,'AAX1',co_num,hlm_current_year,hlm_day_of_year, & - ! dbh,nplant,(store_c_act/store_c_max),cx_logratio,cx_int,ema_dcxdt,l2fr + if((co_num==1)) print*,'AAX1',co_num,hlm_current_year,hlm_day_of_year, & + dbh,nplant,(store_c_act/store_c_max),cn_ratio,cx_logratio,ema_dcxdt,l2fr ! Find the updated target fineroot biomass call bfineroot(dbh,ipft,canopy_trim, l2fr, target_c(fnrt_organ),target_dcdd(fnrt_organ)) From 0bef1673da218368750b1759100f160661d54f55 Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Fri, 14 Oct 2022 17:19:51 -0700 Subject: [PATCH 375/852] Add two new history variables - aboveground woody mortality and aboveground woody productivity for comparison of FATES with forest plot data. --- biogeochem/EDCohortDynamicsMod.F90 | 5 ++++ biogeochem/EDPatchDynamicsMod.F90 | 14 +++++++++ main/EDInitMod.F90 | 8 +++++ main/EDTypesMod.F90 | 5 ++++ main/FatesHistoryInterfaceMod.F90 | 47 ++++++++++++++++++++++++++++++ main/FatesRestartInterfaceMod.F90 | 41 +++++++++++++++++++++++--- 6 files changed, 116 insertions(+), 4 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 2d796a9048..b1f4b98b44 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -864,6 +864,11 @@ subroutine terminate_cohort(currentSite, currentPatch, currentCohort, bc_in) currentCohort%n * (struct_c+sapw_c+leaf_c+fnrt_c+store_c+repro_c) end if + currentSite%term_bagw_flux(currentCohort%size_class, currentCohort%pft) = & + currentSite%term_bagw_flux(currentCohort%size_class, currentCohort%pft) + & + currentCohort%n * (struct_c+sapw_c) + + ! put the litter from the terminated cohorts ! straight into the fragmenting pools diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 141aaad52e..c67a42b0ba 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -722,6 +722,13 @@ subroutine spawn_patches( currentSite, bc_in) (nc%n * ED_val_understorey_death / hlm_freq_day ) * & total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 + currentSite%imort_bagw_flux(currentCohort%size_class, currentCohort%pft) = & + currentSite%imort_bagw_flux(currentCohort%size_class, currentCohort%pft) + & + (nc%n * ED_val_understorey_death / hlm_freq_day ) * & + (sapw_c + struct_c) * prt_params%allom_agb_frac(currentCohort%pft) * & + g_per_kg * days_per_sec * years_per_day * ha_per_m2 + + ! Step 2: Apply survivor ship function based on the understory death fraction ! remaining of understory plants of those that are knocked over ! by the overstorey trees dying... @@ -810,6 +817,13 @@ subroutine spawn_patches( currentSite, bc_in) total_c * g_per_kg * days_per_sec * ha_per_m2 end if + currentSite%fmort_bagw_flux(currentCohort%size_class, currentCohort%pft) = & + currentSite%fmort_bagw_flux(currentCohort%size_class, currentCohort%pft) + & + (nc%n * currentCohort%fire_mort) * & + (sapw_c + struct_c) * prt_params%allom_agb_frac(currentCohort%pft) * & + g_per_kg * days_per_sec * ha_per_m2 + + currentSite%fmort_rate_cambial(currentCohort%size_class, currentCohort%pft) = & currentSite%fmort_rate_cambial(currentCohort%size_class, currentCohort%pft) + & nc%n * currentCohort%cambial_mort / hlm_freq_day diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index d3177ca72a..fb7bc67219 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -135,6 +135,10 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) allocate(site_in%fmort_carbonflux_canopy(1:numpft)) allocate(site_in%fmort_carbonflux_ustory(1:numpft)) + allocate(site_in%term_bagw_flux(1:nlevsclass,1:numpft)) + allocate(site_in%imort_bagw_flux(1:nlevsclass,1:numpft)) + allocate(site_in%fmort_bagw_flux(1:nlevsclass,1:numpft)) + site_in%nlevsoil = bc_in%nlevsoil allocate(site_in%rootfrac_scr(site_in%nlevsoil)) allocate(site_in%zi_soil(0:site_in%nlevsoil)) @@ -245,6 +249,10 @@ subroutine zero_site( site_in ) site_in%fmort_carbonflux_ustory(:) = 0._r8 site_in%fmort_rate_cambial(:,:) = 0._r8 site_in%fmort_rate_crown(:,:) = 0._r8 + site_in%term_bagw_flux(:,:) = 0._r8 + site_in%imort_bagw_flux(:,:) = 0._r8 + site_in%fmort_bagw_flux(:,:) = 0._r8 + ! fusoin-induced growth flux of individuals site_in%growthflux_fusion(:,:) = 0._r8 diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 86bb36e31e..de5d87051d 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -796,6 +796,11 @@ module EDTypesMod real(r8), allocatable :: fmort_carbonflux_canopy(:) ! biomass of canopy indivs killed due to fire per year. [gC/m2/sec] real(r8), allocatable :: fmort_carbonflux_ustory(:) ! biomass of understory indivs killed due to fire per year [gC/m2/sec] + real(r8), allocatable :: term_bagw_flux(:,:) ! aboveground woody biomass lost due to termination mortality x size x pft + real(r8), allocatable :: imort_bagw_flux(:,:) ! aboveground woody biomass lost due to impact mortality x size x pft + real(r8), allocatable :: fmort_bagw_flux(:,:) ! aboveground woody biomass lost due to fire mortality x size x pft + + real(r8) :: demotion_carbonflux ! biomass of demoted individuals from canopy to understory [kgC/ha/day] real(r8) :: promotion_carbonflux ! biomass of promoted individuals from understory to canopy [kgC/ha/day] real(r8) :: recruitment_rate(1:maxpft) ! number of individuals that were recruited into new cohorts diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 391d5f87d9..5af9512088 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -417,6 +417,9 @@ module FatesHistoryInterfaceMod integer :: ih_crownfiremort_si_scpf integer :: ih_cambialfiremort_si_scpf + integer :: ih_bagw_mortality_si_scpf + integer :: ih_bagw_productivity_si_scpf + integer :: ih_m10_si_capf integer :: ih_nplant_si_capf @@ -1923,6 +1926,9 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_crownfiremort_si_scpf => this%hvars(ih_crownfiremort_si_scpf)%r82d, & hio_cambialfiremort_si_scpf => this%hvars(ih_cambialfiremort_si_scpf)%r82d, & + hio_bagw_mortality_si_scpf => this%hvars(ih_bagw_mortality_si_scpf)%r82d, & + hio_bagw_productivity_si_scpf => this%hvars(ih_bagw_productivity_si_scpf)%r82d, & + hio_fire_c_to_atm_si => this%hvars(ih_fire_c_to_atm_si)%r81d, & hio_burn_flux_elem => this%hvars(ih_burn_flux_elem)%r82d, & @@ -2534,6 +2540,10 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_npp_stor_si_scpf(io_si,scpf) = hio_npp_stor_si_scpf(io_si,scpf) + & store_m_net_alloc*n_perm2 / days_per_year / sec_per_day + hio_bagw_productivity_si_scpf(io_si,scpf) = hio_bagw_productivity_si_scpf(io_si,scpf) + & + (sapw_m_net_alloc + struct_m_net_alloc) * n_perm2 * (prt_params%allom_agb_frac(ccohort%pft)) / & + days_per_year / sec_per_day + ! Woody State Variables (basal area growth increment) if ( prt_params%woody(ft) == itrue) then @@ -2584,6 +2594,17 @@ subroutine update_history_dyn(this,nc,nsites,sites) ccohort%asmort*ccohort%n / m2_per_ha end if + hio_bagw_mortality_si_scpf(io_si,scpf) = hio_bagw_mortality_si_scpf(io_si,scpf) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort) * & + (sapw_m + struct_m) * prt_params%allom_agb_frac(ccohort%pft) * & + ccohort%n * days_per_sec * years_per_day * ha_per_m2 + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & + (sapw_m + struct_m) * prt_params%allom_agb_frac(ccohort%pft) * & + ccohort%n * ha_per_m2 + + + hio_m1_si_scls(io_si,scls) = hio_m1_si_scls(io_si,scls) + ccohort%bmort*ccohort%n / m2_per_ha hio_m2_si_scls(io_si,scls) = hio_m2_si_scls(io_si,scls) + ccohort%hmort*ccohort%n / m2_per_ha hio_m3_si_scls(io_si,scls) = hio_m3_si_scls(io_si,scls) + ccohort%cmort*ccohort%n / m2_per_ha @@ -3094,6 +3115,17 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_firemortality_carbonflux_si_pft(io_si,i_pft) = sites(s)%fmort_carbonflux_canopy(i_pft) / g_per_kg end do + ! add imort and fmort to aboveground woody mortality + do i_pft = 1, numpft + do i_scls = 1,nlevsclass + i_scpf = (i_pft-1)*nlevsclass + i_scls + hio_bagw_mortality_si_scpf(io_si,i_scpf) = hio_bagw_mortality_si_scpf(io_si,i_scpf) + & + (sites(s)%fmort_bagw_flux(i_scls,i_pft) / g_per_kg ) + & + (sites(s)%imort_bagw_flux(i_scls,i_pft) / g_per_kg) + & + (sites(s)%term_bagw_flux(i_scls,i_pft) * days_per_sec * ha_per_m2 ) ! jfn + end do + end do + sites(s)%term_nindivs_canopy(:,:) = 0._r8 sites(s)%term_nindivs_ustory(:,:) = 0._r8 sites(s)%imort_carbonflux(:) = 0._r8 @@ -3105,6 +3137,9 @@ subroutine update_history_dyn(this,nc,nsites,sites) sites(s)%fmort_rate_cambial(:,:) = 0._r8 sites(s)%fmort_rate_crown(:,:) = 0._r8 sites(s)%growthflux_fusion(:,:) = 0._r8 + sites(s)%fmort_bagw_flux(:,:) = 0._r8 + sites(s)%imort_bagw_flux(:,:) = 0._r8 + sites(s)%term_bagw_flux(:,:) = 0._r8 ! pass the recruitment rate as a flux to the history, and then reset the recruitment buffer do i_pft = 1, numpft @@ -5563,6 +5598,18 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_cstarvmortality_carbonflux_si_pft) + call this%set_history_var(vname='FATES_ABOVEGROUND_MORTALITY_SZPF', units='kg m-2 s-1', & + long='Aboveground woody flux of carbon from AGB to necromass due to mortality', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_bagw_mortality_si_scpf) + + call this%set_history_var(vname='FATES_ABOVEGROUND_PRODUCTIVITY_SZPF', units='kg m-2 s-1', & + long='Aboveground woody carbon productivity', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_bagw_productivity_si_scpf) + ! size class by age dimensioned variables call this%set_history_var(vname='FATES_NPLANT_SZAP', units = 'm-2', & diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index d17759220a..e028b8ab23 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -211,6 +211,9 @@ module FatesRestartInterfaceMod integer :: ir_imortcflux_sipft integer :: ir_fmortcflux_cano_sipft integer :: ir_fmortcflux_usto_sipft + integer :: ir_bagw_term_flux_siscpf + integer :: ir_bagw_imort_flux_siscpf + integer :: ir_bagw_fmort_flux_siscpf integer :: ir_cwdagin_flxdg integer :: ir_cwdbgin_flxdg integer :: ir_leaflittin_flxdg @@ -1246,7 +1249,22 @@ subroutine define_restart_vars(this, initialize_variables) call this%set_restart_var(vname='fates_termcflux_ustory', vtype=cohort_r8, & long_name='fates diagnostic term carbon flux understory', & units='', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_termcflux_usto_sipft ) + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_termcflux_usto_sipft ) + + call this%set_restart_var(vname='fates_bagw_term_flux', vtype=cohort_r8, & + long_name='fates aboveground biomass loss from termination mortality', & + units='', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_bagw_term_flux_siscpf ) + + call this%set_restart_var(vname='fates_bagw_imort_flux', vtype=cohort_r8, & + long_name='fates aboveground biomass loss from impact mortality', & + units='', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_bagw_imort_flux_siscpf ) + + call this%set_restart_var(vname='fates_bagw_fmort_flux', vtype=cohort_r8, & + long_name='fates aboveground biomass loss from fire mortality', & + units='', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_bagw_fmort_flux_siscpf ) call this%set_restart_var(vname='fates_democflux', vtype=site_r8, & long_name='fates diagnostic demotion carbon flux', & @@ -1825,8 +1843,11 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_promcflux_si => this%rvars(ir_promcflux_si)%r81d, & rio_imortcflux_sipft => this%rvars(ir_imortcflux_sipft)%r81d, & rio_fmortcflux_cano_sipft => this%rvars(ir_fmortcflux_cano_sipft)%r81d, & - rio_fmortcflux_usto_sipft => this%rvars(ir_fmortcflux_usto_sipft)%r81d) - + rio_fmortcflux_usto_sipft => this%rvars(ir_fmortcflux_usto_sipft)%r81d, & + rio_bagw_imort_flux_siscpf => this%rvars(ir_bagw_imort_flux_siscpf)%r81d, & + rio_bagw_fmort_flux_siscpf => this%rvars(ir_bagw_fmort_flux_siscpf)%r81d, & + rio_bagw_term_flux_siscpf => this%rvars(ir_bagw_term_flux_siscpf)%r81d ) + totalCohorts = 0 @@ -2199,6 +2220,10 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_termnindiv_usto_siscpf(io_idx_si_scpf) = sites(s)%term_nindivs_ustory(i_scls,i_pft) rio_growflx_fusion_siscpf(io_idx_si_scpf) = sites(s)%growthflux_fusion(i_scls, i_pft) + rio_bagw_term_flux_siscpf(io_idx_si_scpf) = sites(s)%term_bagw_flux(i_scls, i_pft) + rio_bagw_imort_flux_siscpf(io_idx_si_scpf) = sites(s)%imort_bagw_flux(i_scls, i_pft) + rio_bagw_fmort_flux_siscpf(io_idx_si_scpf) = sites(s)%fmort_bagw_flux(i_scls, i_pft) + io_idx_si_scpf = io_idx_si_scpf + 1 end do @@ -2658,7 +2683,10 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_promcflux_si => this%rvars(ir_promcflux_si)%r81d, & rio_imortcflux_sipft => this%rvars(ir_imortcflux_sipft)%r81d, & rio_fmortcflux_cano_sipft => this%rvars(ir_fmortcflux_cano_sipft)%r81d, & - rio_fmortcflux_usto_sipft => this%rvars(ir_fmortcflux_usto_sipft)%r81d) + rio_fmortcflux_usto_sipft => this%rvars(ir_fmortcflux_usto_sipft)%r81d, & + rio_bagw_term_flux_siscpf => this%rvars(ir_bagw_term_flux_siscpf)%r81d, & + rio_bagw_imort_flux_siscpf => this%rvars(ir_bagw_imort_flux_siscpf)%r81d, & + rio_bagw_fmort_flux_siscpf => this%rvars(ir_bagw_fmort_flux_siscpf)%r81d ) totalcohorts = 0 @@ -3068,6 +3096,11 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%term_nindivs_canopy(i_scls,i_pft) = rio_termnindiv_cano_siscpf(io_idx_si_scpf) sites(s)%term_nindivs_ustory(i_scls,i_pft) = rio_termnindiv_usto_siscpf(io_idx_si_scpf) sites(s)%growthflux_fusion(i_scls, i_pft) = rio_growflx_fusion_siscpf(io_idx_si_scpf) + + sites(s)%term_bagw_flux(i_scls,i_pft) = rio_bagw_term_flux_siscpf(io_idx_si_scpf) + sites(s)%imort_bagw_flux(i_scls,i_pft) = rio_bagw_imort_flux_siscpf(io_idx_si_scpf) + sites(s)%fmort_bagw_flux(i_scls,i_pft) = rio_bagw_fmort_flux_siscpf(io_idx_si_scpf) + io_idx_si_scpf = io_idx_si_scpf + 1 end do From 91bd8659d377fde6ea8b3bb728b44a8cf7d66caa Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 17 Oct 2022 11:29:10 -0400 Subject: [PATCH 376/852] cnp cleanup: change p uptake to p gain for consistency, remove temporary argument to the PRTDaily call, remove usage of all_carbon_types from PRTTurnover and various cleaning in PRTAllometricCNP --- biogeochem/EDCohortDynamicsMod.F90 | 16 ++-- biogeochem/FatesSoilBGCFluxMod.F90 | 4 +- main/EDMainMod.F90 | 6 +- main/EDTypesMod.F90 | 2 +- main/FatesHistoryInterfaceMod.F90 | 4 +- main/FatesRestartInterfaceMod.F90 | 4 +- parteh/PRTAllometricCNPMod.F90 | 132 +++++++++-------------------- parteh/PRTAllometricCarbonMod.F90 | 4 +- parteh/PRTGenericMod.F90 | 4 +- parteh/PRTLossFluxesMod.F90 | 21 +---- 10 files changed, 62 insertions(+), 135 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 47ed64fcc6..b6b83c1b2f 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -420,8 +420,8 @@ subroutine InitPRTBoundaryConditions(new_cohort) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_lstat,bc_ival = new_cohort%status_coh) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdc, bc_rval = new_cohort%npp_acc) - call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_nc_repro,bc_rval = new_cohort%nc_repro) !patchptr%nitr_repro_stoich(ft)) - call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_pc_repro,bc_rval = new_cohort%pc_repro) !patchptr%phos_repro_stoich(ft)) + call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_nc_repro,bc_rval = new_cohort%nc_repro) + call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_pc_repro,bc_rval = new_cohort%pc_repro) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_dbh,bc_rval = new_cohort%dbh) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_resp_excess,bc_rval = new_cohort%resp_excess) @@ -431,7 +431,7 @@ subroutine InitPRTBoundaryConditions(new_cohort) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_cx0,bc_rval = new_cohort%cx0) call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_netdn, bc_rval = new_cohort%daily_n_gain) - call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_netdp, bc_rval = new_cohort%daily_p_uptake) + call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_netdp, bc_rval = new_cohort%daily_p_gain) call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_cefflux, bc_rval = new_cohort%daily_c_efflux) call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_nefflux, bc_rval = new_cohort%daily_n_efflux) @@ -581,7 +581,7 @@ subroutine nan_cohort(cc_p) currentCohort%daily_no3_uptake = nan currentCohort%daily_n_gain = nan currentCohort%daily_n_fixation = nan - currentCohort%daily_p_uptake = nan + currentCohort%daily_p_gain = nan currentCohort%daily_c_efflux = nan currentCohort%daily_n_efflux = nan currentCohort%daily_p_efflux = nan @@ -696,7 +696,7 @@ subroutine zero_cohort(cc_p) currentCohort%daily_nh4_uptake = 0._r8 currentCohort%daily_no3_uptake = 0._r8 - currentCohort%daily_p_uptake = 0._r8 + currentCohort%daily_p_gain = 0._r8 currentCohort%daily_c_efflux = 0._r8 currentCohort%daily_n_efflux = 0._r8 @@ -1445,8 +1445,8 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) currentCohort%daily_n_gain = (currentCohort%n*currentCohort%daily_n_gain + & nextc%n*nextc%daily_n_gain)/newn - currentCohort%daily_p_uptake = (currentCohort%n*currentCohort%daily_p_uptake + & - nextc%n*nextc%daily_p_uptake)/newn + currentCohort%daily_p_gain = (currentCohort%n*currentCohort%daily_p_gain + & + nextc%n*nextc%daily_p_gain)/newn @@ -1852,7 +1852,7 @@ subroutine copy_cohort( currentCohort,copyc ) n%daily_no3_uptake = o%daily_no3_uptake n%daily_n_fixation = o%daily_n_fixation n%daily_n_gain = o%daily_n_gain - n%daily_p_uptake = o%daily_p_uptake + n%daily_p_gain = o%daily_p_gain n%daily_c_efflux = o%daily_c_efflux n%daily_n_efflux = o%daily_n_efflux n%daily_p_efflux = o%daily_p_efflux diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index ce51586123..defc0bf2eb 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -261,7 +261,7 @@ subroutine UnPackNutrientAquisitionBCs(sites, bc_in) do while (associated(ccohort)) pft = ccohort%pft !ccohort%daily_p_demand = GetPlantDemand(ccohort,phosphorus_element) - ccohort%daily_p_uptake = -9._r8 !EDPftvarcon_inst%prescribed_puptake(pft) * ccohort%daily_p_demand + ccohort%daily_p_gain = -9._r8 !EDPftvarcon_inst%prescribed_puptake(pft) * ccohort%daily_p_demand ccohort => ccohort%shorter end do cpatch => cpatch%younger @@ -277,7 +277,7 @@ subroutine UnPackNutrientAquisitionBCs(sites, bc_in) icomp = icomp+1 ccohort%daily_p_demand = GetPlantDemand(ccohort,phosphorus_element) ! P Uptake: Convert g/m2/day -> kg/plant/day - ccohort%daily_p_uptake = bc_in(s)%plant_p_uptake_flux(icomp,1)*kg_per_g*AREA/ccohort%n + ccohort%daily_p_gain = bc_in(s)%plant_p_uptake_flux(icomp,1)*kg_per_g*AREA/ccohort%n ccohort => ccohort%shorter end do cpatch => cpatch%younger diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index fd4b1fd2b1..b50370b96e 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -456,7 +456,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! ----------------------------------------------------------------------------- currentCohort%resp_excess = 0._r8 - call currentCohort%prt%DailyPRT(co_num,currentCohort%n) + call currentCohort%prt%DailyPRT() ! Send any efflux/exudates to the labile litter pools in the HLM ! ----------------------------------------------------------------------------- @@ -473,7 +473,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! Mass balance for P uptake currentSite%mass_balance(element_pos(phosphorus_element))%net_root_uptake = & currentSite%mass_balance(element_pos(phosphorus_element))%net_root_uptake + & - (currentCohort%daily_p_uptake-currentCohort%daily_p_efflux)*currentCohort%n + (currentCohort%daily_p_gain-currentCohort%daily_p_efflux)*currentCohort%n end if ! mass balance for C efflux (if any) @@ -848,7 +848,7 @@ subroutine TotalBalanceCheck (currentSite, call_index ) write(fates_log(),*) 'N efflux: ',currentCohort%daily_n_efflux*currentCohort%n write(fates_log(),*) 'N fixation: ',currentCohort%daily_n_fixation*currentCohort%n elseif(element_list(el).eq.phosphorus_element) then - write(fates_log(),*) 'P uptake: ',currentCohort%daily_p_uptake*currentCohort%n + write(fates_log(),*) 'P uptake: ',currentCohort%daily_p_gain*currentCohort%n write(fates_log(),*) 'P efflux: ',currentCohort%daily_p_efflux*currentCohort%n elseif(element_list(el).eq.carbon12_element) then write(fates_log(),*) 'C efflux: ',currentCohort%daily_c_efflux*currentCohort%n diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 3a8073d274..c2f4f3cb60 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -301,7 +301,7 @@ module EDTypesMod real(r8) :: daily_no3_uptake ! integrated daily uptake of mineralized nitrate through competitive acquisition in soil [kg N / plant/ day] real(r8) :: daily_n_fixation ! Rate of N fixation from the roots [kgN/indiv/day] real(r8) :: daily_n_gain ! sum of fixation and uptake of mineralized nh4/no3 in solution - real(r8) :: daily_p_uptake ! integrated daily uptake of mineralized P through competitive acquisition in soil [kg P / plant/ day] + real(r8) :: daily_p_gain ! integrated daily uptake of mineralized P through competitive acquisition in soil [kg P / plant/ day] real(r8) :: daily_c_efflux ! daily mean efflux of excess carbon from roots into labile pool [kg C/plant/day] real(r8) :: daily_n_efflux ! daily mean efflux of excess nitrogen from roots into labile pool [kg N/plant/day] diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index da59b0d803..0f4fb141c8 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -1895,11 +1895,11 @@ subroutine update_history_nutrflux(this,csite) fates_hist%hvars(ih_puptake_scpf)%r82d(io_si,iscpf) = & fates_hist%hvars(ih_puptake_scpf)%r82d(io_si,iscpf) + & - ccohort%daily_p_uptake*uconv + ccohort%daily_p_gain*uconv fates_hist%hvars(ih_puptake_si)%r81d(io_si) = & fates_hist%hvars(ih_puptake_si)%r81d(io_si) + & - ccohort%daily_p_uptake*uconv + ccohort%daily_p_gain*uconv this%hvars(ih_pefflux_scpf)%r82d(io_si,iscpf) = & this%hvars(ih_pefflux_scpf)%r82d(io_si,iscpf) + & diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index c3e9566f2d..6f7dde794e 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -1993,7 +1993,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) ! Nutrient uptake/efflux rio_daily_no3_uptake_co(io_idx_co) = ccohort%daily_no3_uptake rio_daily_nh4_uptake_co(io_idx_co) = ccohort%daily_nh4_uptake - rio_daily_p_uptake_co(io_idx_co) = ccohort%daily_p_uptake + rio_daily_p_uptake_co(io_idx_co) = ccohort%daily_p_gain rio_daily_n_fixation_co(io_idx_co) = ccohort%daily_n_fixation rio_daily_n_demand_co(io_idx_co) = ccohort%daily_n_demand @@ -2796,7 +2796,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ccohort%daily_nh4_uptake = rio_daily_nh4_uptake_co(io_idx_co) ccohort%daily_no3_uptake = rio_daily_no3_uptake_co(io_idx_co) ccohort%daily_n_fixation = rio_daily_n_fixation_co(io_idx_co) - ccohort%daily_p_uptake = rio_daily_p_uptake_co(io_idx_co) + ccohort%daily_p_gain = rio_daily_p_uptake_co(io_idx_co) ccohort%daily_n_demand = rio_daily_n_demand_co(io_idx_co) ccohort%daily_p_demand = rio_daily_p_demand_co(io_idx_co) diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 6de86ea2da..ad943702ba 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -210,7 +210,14 @@ module PRTAllometricCNPMod integer, parameter :: n_limited = 2 integer, parameter :: p_limited = 3 + ! Flags to select using the equivalent carbon method of co-limitation, + ! or to just grow with available carbon and let it fix itself on the + ! next step + integer, parameter :: grow_lim_conly = 1 ! Just use C to decide stature on this step + integer, parameter :: grow_lim_estNP = 2 ! Estimate equivalent C from N and P + integer, parameter :: grow_lim_type = grow_lim_estNP + ! Following growth, if desired, you can prioritize that ! reproductive tissues get balanced CNP logical, parameter :: prioritize_repro_nutr_growth = .true. @@ -340,11 +347,9 @@ end subroutine InitPRTGlobalAllometricCNP ! ===================================================================================== - subroutine DailyPRTAllometricCNP(this,co_num,nplant) + subroutine DailyPRTAllometricCNP(this) class(cnp_allom_prt_vartypes) :: this - integer,intent(in) :: co_num ! Cohort index - real(r8),intent(in) :: nplant ! Pointers to in-out bcs real(r8),pointer :: dbh ! Diameter at breast height [cm] @@ -464,9 +469,7 @@ subroutine DailyPRTAllometricCNP(this,co_num,nplant) ! and then attempt to get them up to stoichiometry targets. ! =================================================================================== - ! This routine updates the l2fr (leaf 2 fine-root multiplier) variable - ! It will also update the target - !call this%CNPAdjustFRootTargets(target_c,target_dcdd,co_num,nplant) + ! Remember the original C,N,P states to help with final ! evaluation of how much was allocated @@ -553,11 +556,6 @@ subroutine DailyPRTAllometricCNP(this,co_num,nplant) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - - ! This routine updates the l2fr (leaf 2 fine-root multiplier) variable - ! It will also update the target - !call this%CNPAdjustFRootTargets(target_c,target_dcdd,co_num,nplant) - ! =================================================================================== ! Step 3. ! At this point, at least 1 of the 3 resources have been used up. @@ -565,7 +563,7 @@ subroutine DailyPRTAllometricCNP(this,co_num,nplant) ! =================================================================================== call this%CNPAllocateRemainder(c_gain, n_gain, p_gain, & - c_efflux, n_efflux, p_efflux,co_num,nplant,target_c,target_dcdd) + c_efflux, n_efflux, p_efflux,target_c,target_dcdd) if(n_uptake_mode.ne.prescribed_n_uptake) then @@ -694,7 +692,7 @@ end function SafeLog ! ===================================================================================== - subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) + subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd) use FatesInterfaceTypesMod , only : hlm_day_of_year use FatesInterfaceTypesMod , only : hlm_current_year @@ -702,17 +700,15 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) class(cnp_allom_prt_vartypes) :: this real(r8) :: target_c(:) real(r8) :: target_dcdd(:) - integer,intent(in) :: co_num ! Used for single plant diagnostics - real(r8),intent(in) :: nplant ! Used for single plant diagnostics real(r8), pointer :: l2fr ! leaf to fineroot target biomass scaler integer :: ipft ! PFT index real(r8), pointer :: dbh real(r8) :: canopy_trim integer :: leaf_status + integer, pointer :: limiter real(r8) :: store_c_max, store_c_act real(r8) :: store_nut_max, store_nut_act - real(r8) :: n_ratio, p_ratio real(r8) :: l2fr_delta real(r8) :: cn_ratio, cp_ratio ! ratio of relative C storage over relative N or P storage real(r8) :: dcxdt_ratio ! log change (derivative) of the maximum of the N/C and P/C storage ratio @@ -721,20 +717,9 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) real(r8), pointer :: cx0 ! The log of the cx ratio from previous time-step real(r8), pointer :: ema_dcxdt ! the EMA of the change in log storage ratio - real(r8), parameter :: pid_drv_wgt = 1._r8/10._r8 ! n-day smoothing of the derivative + real(r8), parameter :: pid_drv_wgt = 1._r8/20._r8 ! n-day smoothing of the derivative ! of the process function in the PID controller - ! These are different ways of defining the process function in the PID controller. pid_ncratio_function - ! is perhaps the most complete, in that it gives the true balance of relative C stores to relative N - ! stores. In the future we may just remove the alternatives - - integer, parameter :: pid_c_function = 0 - integer, parameter :: pid_n_function = 1 - integer, parameter :: pid_minnc_function = 2 - integer, parameter :: pid_alogmaxnc_function = 3 - integer, parameter :: pid_ncratio_function = 4 - integer, parameter :: pid_function = pid_ncratio_function - leaf_status = this%bc_in(acnp_bc_in_id_lstat)%ival ipft = this%bc_in(acnp_bc_in_id_pft)%ival l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval @@ -743,7 +728,8 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) cx_int => this%bc_inout(acnp_bc_inout_id_cx_int)%rval cx0 => this%bc_inout(acnp_bc_inout_id_cx0)%rval ema_dcxdt => this%bc_inout(acnp_bc_inout_id_emadcxdt)%rval - + limiter => this%bc_out(acnp_bc_out_id_limiter)%ival + ! Abort if leaves are off if(leaf_status.eq.leaves_off) return @@ -762,7 +748,7 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) this%bc_in(acnp_bc_in_id_netdc)%rval) if(n_uptake_mode.eq.prescribed_n_uptake)then - n_ratio = -1._r8 + cn_ratio = -1._r8 else ! Calculate the relative nitrogen storage fraction, @@ -774,35 +760,12 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) this%GetState(store_organ, nitrogen_element) + & this%bc_inout(acnp_bc_inout_id_netdn)%rval) - select case(pid_function) - case(pid_c_function) - n_ratio = store_c_act/store_c_max - case(pid_n_function) - n_ratio = store_nut_max/store_nut_act - case(pid_minnc_function) - if((store_nut_act/store_nut_max) > (store_c_act/store_c_max))then - n_ratio = (store_c_act/store_c_max) - else - n_ratio = (store_nut_max/store_nut_act) - end if - case(pid_alogmaxnc_function) - if( abs(SafeLog(store_nut_act/store_nut_max)) < abs(SafeLog(store_c_act/store_c_max))) then - n_ratio = (store_c_act/store_c_max) - else - n_ratio = (store_nut_max/store_nut_act) - end if - case(pid_ncratio_function) - n_ratio = (store_c_act/store_c_max)/(store_nut_act/store_nut_max) - end select - - ! This is more of a diagnostic, to see if the other process functions - ! are as good as the ratio of relative ratios - cn_ratio = (store_nut_act/store_nut_max) + cn_ratio = (store_c_act/store_c_max)/(store_nut_act/store_nut_max) end if if(p_uptake_mode.eq.prescribed_p_uptake)then - p_ratio = -1._r8 + cp_ratio = -1._r8 else ! Calculate the relative phosphorus storage fraction, @@ -814,30 +777,8 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) this%GetState(store_organ, phosphorus_element) + & this%bc_inout(acnp_bc_inout_id_netdp)%rval) - select case(pid_function) - case(pid_c_function) - p_ratio = store_c_act/store_c_max - case(pid_n_function) - p_ratio = store_nut_max/store_nut_act - case(pid_minnc_function) - if((store_nut_act/store_nut_max) > (store_c_act/store_c_max))then - p_ratio = (store_c_act/store_c_max) - else - p_ratio = (store_nut_max/store_nut_act) - end if - case(pid_alogmaxnc_function) - if( abs(SafeLog(store_nut_act/store_nut_max)) < abs(SafeLog(store_c_act/store_c_max))) then - p_ratio = (store_c_act/store_c_max) - else - p_ratio = (store_nut_max/store_nut_act) - end if - case(pid_ncratio_function) - p_ratio = (store_c_act/store_c_max)/(store_nut_act/store_nut_max) - end select - cp_ratio = (store_c_act/store_c_max)/(store_nut_act/store_nut_max) - end if ! Use the limiting nutrient species @@ -850,11 +791,11 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) else if (n_uptake_mode.eq.prescribed_n_uptake) then - cx_logratio = SafeLog(p_ratio) + cx_logratio = SafeLog(cp_ratio) elseif (p_uptake_mode.eq.prescribed_p_uptake) then - cx_logratio = SafeLog(n_ratio) + cx_logratio = SafeLog(cn_ratio) else - cx_logratio = SafeLog(max(p_ratio,n_ratio)) + cx_logratio = SafeLog(max(cp_ratio,cn_ratio)) end if ! If cx_logratio has just crossed zero, then @@ -890,9 +831,6 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd,co_num,nplant) l2fr = max(l2fr_min, l2fr + l2fr_delta) - if((co_num==1)) print*,'AAX1',co_num,hlm_current_year,hlm_day_of_year, & - dbh,nplant,(store_c_act/store_c_max),cn_ratio,cx_logratio,ema_dcxdt,l2fr - ! Find the updated target fineroot biomass call bfineroot(dbh,ipft,canopy_trim, l2fr, target_c(fnrt_organ),target_dcdd(fnrt_organ)) @@ -1381,10 +1319,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & real(r8) :: intgr_params(num_intgr_parm) - integer, parameter :: grow_lim_conly = 1 ! Just use C to decide stature on this step - integer, parameter :: grow_lim_estNP = 2 ! Estimate equivalent C from N and P - integer, parameter :: grow_lim_type = grow_lim_estNP real(r8) :: neq_cgain, peq_cgain ! N and P equivalent c_gain spent on growth real(r8) :: cnp_gain ! used as a check to see efficiency of limited growth @@ -1406,7 +1341,9 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & if(n_gain <= 0.1_r8*calloc_abs_error) limiter = n_limited if(p_gain <= 0.02_r8*calloc_abs_error) limiter = p_limited end if - + + limiter = 0 + ! If any of these resources is essentially tapped out, ! then there is no point in performing growth ! It also seems impossible that we would be in a leaf-off status @@ -1545,6 +1482,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & if(grow_lim_type == grow_lim_conly) then c_gstature = c_gain + limiter = 0 elseif (grow_lim_type == grow_lim_estNP) then call EstimateGrowthNC(this,target_c,target_dcdd,state_mask,avg_nc,avg_pc) @@ -1813,7 +1751,7 @@ end subroutine CNPStatureGrowth subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & c_efflux, n_efflux, p_efflux, & - co_num,nplant,target_c,target_dcdd) + target_c,target_dcdd) class(cnp_allom_prt_vartypes) :: this real(r8), intent(inout) :: c_gain @@ -1822,8 +1760,6 @@ subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & real(r8), intent(inout) :: c_efflux real(r8), intent(inout) :: n_efflux real(r8), intent(inout) :: p_efflux - integer,intent(in) :: co_num - real(r8),intent(in) :: nplant real(r8) :: target_c(:) real(r8) :: target_dcdd(:) @@ -1855,9 +1791,14 @@ subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & ! Update the nitrogen and phosphorus deficits target_n = this%GetNutrientTarget(nitrogen_element,l2g_organ_list(i),stoich_growth_min) - deficit_n(i) = max(0._r8,this%GetDeficit(nitrogen_element,l2g_organ_list(i),target_n)) - target_p = this%GetNutrientTarget(phosphorus_element,l2g_organ_list(i),stoich_growth_min) + + if(l2g_organ_list(i)==store_organ)then + target_n = target_n * (1._r8 + prt_params%store_ovrflw_frac(ipft)) + target_p = target_p * (1._r8 + prt_params%store_ovrflw_frac(ipft)) + end if + + deficit_n(i) = max(0._r8,this%GetDeficit(nitrogen_element,l2g_organ_list(i),target_n)) deficit_p(i) = max(0._r8,this%GetDeficit(phosphorus_element,l2g_organ_list(i),target_p)) end do @@ -1875,7 +1816,10 @@ subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & call ProportionalNutrAllocation(this,deficit_p(1:num_organs), & p_gain, phosphorus_element, l2g_organ_list(1:num_organs)) - call this%CNPAdjustFRootTargets(target_c,target_dcdd,co_num,nplant) + + ! This routine updates the l2fr (leaf 2 fine-root multiplier) variable + ! It will also update the target + call this%CNPAdjustFRootTargets(target_c,target_dcdd) ! ----------------------------------------------------------------------------------- ! If carbon is still available, lets cram some into storage overflow @@ -1925,7 +1869,7 @@ subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & end if end if - + ! Figure out what to do with excess carbon and nutrients ! 1) excude through roots cap at 0 to flush out imprecisions diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index a4ad1607c1..b42fbfa01e 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -241,7 +241,7 @@ end subroutine InitPRTGlobalAllometricCarbon ! ===================================================================================== - subroutine DailyPRTAllometricCarbon(this,co_num,nplant) + subroutine DailyPRTAllometricCarbon(this) ! ----------------------------------------------------------------------------------- ! @@ -286,8 +286,6 @@ subroutine DailyPRTAllometricCarbon(this,co_num,nplant) ! The class is the only argument class(callom_prt_vartypes) :: this ! this class - integer,intent(in) :: co_num ! cohort index - real(r8),intent(in) :: nplant ! ----------------------------------------------------------------------------------- ! These are local copies of the in/out boundary condition structure ! ----------------------------------------------------------------------------------- diff --git a/parteh/PRTGenericMod.F90 b/parteh/PRTGenericMod.F90 index 9e1aaf8ef8..a8f5b3c183 100644 --- a/parteh/PRTGenericMod.F90 +++ b/parteh/PRTGenericMod.F90 @@ -1159,11 +1159,9 @@ end function GetCoordVal ! ==================================================================================== - subroutine DailyPRTBase(this,co_num,nplant) + subroutine DailyPRTBase(this) class(prt_vartypes) :: this - integer,intent(in) :: co_num ! cohort number - real(r8),intent(in) :: nplant write(fates_log(),*)'Daily PRT Allocation must be extended' call endrun(msg=errMsg(sourcefile, __LINE__)) diff --git a/parteh/PRTLossFluxesMod.F90 b/parteh/PRTLossFluxesMod.F90 index 33eb34b1ea..dcbf73ab10 100644 --- a/parteh/PRTLossFluxesMod.F90 +++ b/parteh/PRTLossFluxesMod.F90 @@ -8,7 +8,6 @@ module PRTLossFluxesMod use PRTGenericMod, only : store_organ use PRTGenericMod, only : repro_organ use PRTGenericMod, only : struct_organ - use PRTGenericMod, only : carbon_elements_list use PRTGenericMod, only : carbon12_element use PRTGenericMod, only : carbon13_element use PRTGenericMod, only : carbon14_element @@ -158,23 +157,11 @@ subroutine PRTPhenologyFlush(prt, ipft, organ_id, c_store_transfer_frac) element_id = prt_global%state_descriptor(i_var)%element_id ! This will filter IN all carbon related variables - if( any(element_id == carbon_elements_list) ) then + if( element_id == carbon12_element ) then - ! No hypotheses exist for how to flush carbon isotopes - ! yet. Please fill this in. - if( (element_id == carbon13_element) .or. & - (element_id == carbon14_element) )then - write(fates_log(),*) ' Phenology flushing routine does not know' - write(fates_log(),*) ' how to handle carbon isotopes. Please' - write(fates_log(),*) ' evaluate the code referenced in this message' - write(fates_log(),*) ' and provide a hypothesis.' - call endrun(msg=errMsg(__FILE__, __LINE__)) - end if - ! Get the variable id of the storage pool for this element (carbon12) i_store = prt_global%sp_organ_map(store_organ,element_id) - do i_pos = 1,i_leaf_pos ! Calculate the mass transferred out of storage into the pool of interest @@ -222,7 +209,7 @@ subroutine PRTPhenologyFlush(prt, ipft, organ_id, c_store_transfer_frac) element_id = prt_global%state_descriptor(i_var)%element_id ! This will filter OUT all carbon related elements - if ( .not. any(element_id == carbon_elements_list) ) then + if ( .not. (element_id == carbon12_element) ) then ! Get the variable id of the storage pool for this element i_store = prt_global%sp_organ_map(store_organ,element_id) @@ -509,7 +496,7 @@ subroutine DeciduousTurnoverSimpleRetranslocation(prt,ipft,organ_id,mass_fractio if( prt_params%organ_param_id(organ_id) < 1 ) then retrans = 0._r8 else - if ( any(element_id == carbon_elements_list) ) then + if ( element_id == carbon12_element ) then retrans = 0._r8 else if( element_id == nitrogen_element ) then retrans = prt_params%turnover_nitr_retrans(ipft,prt_params%organ_param_id(organ_id)) @@ -713,7 +700,7 @@ subroutine MaintTurnoverSimpleRetranslocation(prt,ipft,is_drought) if( prt_params%organ_param_id(organ_id) < 1 ) then retrans_frac = 0._r8 else - if ( any(element_id == carbon_elements_list) ) then + if ( element_id == carbon12_element ) then retrans_frac = 0._r8 else if( element_id == nitrogen_element ) then retrans_frac = prt_params%turnover_nitr_retrans(ipft,prt_params%organ_param_id(organ_id)) From 4ee19d22b6eceac600e760dbc25218a54ad527cc Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 17 Oct 2022 12:12:36 -0400 Subject: [PATCH 377/852] Reverting nclmax --- main/EDTypesMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index c2f4f3cb60..1f05882433 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -28,7 +28,7 @@ module EDTypesMod private ! By default everything is private save - integer, parameter, public :: nclmax = 3 ! Maximum number of canopy layers + integer, parameter, public :: nclmax = 2 ! Maximum number of canopy layers integer, parameter, public :: ican_upper = 1 ! Nominal index for the upper canopy integer, parameter, public :: ican_ustory = 2 ! Nominal index for diagnostics that refer ! to understory layers (all layers that From deb557ccb2e27a1d3e463ef1ab8c6b10d17859a1 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 17 Oct 2022 16:28:33 -0400 Subject: [PATCH 378/852] Modification to parameter defaults --- .../api24.1.0_101722_fates_params_default.cdl | 1538 +++++++++++++++++ .../archive/api24.1.0_101722_patch_params.xml | 50 + parameter_files/fates_params_default.cdl | 19 +- tools/BatchPatchParams.py | 4 +- tools/FatesPFTIndexSwapper.py | 4 +- 5 files changed, 1601 insertions(+), 14 deletions(-) create mode 100644 parameter_files/archive/api24.1.0_101722_fates_params_default.cdl create mode 100644 parameter_files/archive/api24.1.0_101722_patch_params.xml diff --git a/parameter_files/archive/api24.1.0_101722_fates_params_default.cdl b/parameter_files/archive/api24.1.0_101722_fates_params_default.cdl new file mode 100644 index 0000000000..569e6a1ab6 --- /dev/null +++ b/parameter_files/archive/api24.1.0_101722_fates_params_default.cdl @@ -0,0 +1,1538 @@ +netcdf fates_params_default_api24 { +dimensions: + fates_NCWD = 4 ; + fates_history_age_bins = 7 ; + fates_history_coage_bins = 2 ; + fates_history_damage_bins = 2 ; + fates_history_height_bins = 6 ; + fates_history_size_bins = 13 ; + fates_hlm_pftno = 14 ; + fates_hydr_organs = 4 ; + fates_leafage_class = 1 ; + fates_litterclass = 6 ; + fates_pft = 12 ; + fates_plant_organs = 4 ; + fates_string_length = 60 ; +variables: + double fates_history_ageclass_bin_edges(fates_history_age_bins) ; + fates_history_ageclass_bin_edges:units = "yr" ; + fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; + double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; + fates_history_coageclass_bin_edges:units = "years" ; + fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; + double fates_history_height_bin_edges(fates_history_height_bins) ; + fates_history_height_bin_edges:units = "m" ; + fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; + double fates_history_damage_bin_edges(fates_history_damage_bins) ; + fates_history_damage_bin_edges:units = "% crown loss" ; + fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; + double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; + fates_history_sizeclass_bin_edges:units = "cm" ; + fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; + double fates_alloc_organ_id(fates_plant_organs) ; + fates_alloc_organ_id:units = "unitless" ; + fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; + double fates_hydro_htftype_node(fates_hydr_organs) ; + fates_hydro_htftype_node:units = "unitless" ; + fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; + char fates_pftname(fates_pft, fates_string_length) ; + fates_pftname:units = "unitless - string" ; + fates_pftname:long_name = "Description of plant type" ; + char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; + fates_hydro_organ_name:units = "unitless - string" ; + fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; + char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; + fates_alloc_organ_name:units = "unitless - string" ; + fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; + 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" ; + 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" ; + double fates_alloc_storage_cushion(fates_pft) ; + fates_alloc_storage_cushion:units = "fraction" ; + fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; + double fates_alloc_store_priority_frac(fates_pft) ; + fates_alloc_store_priority_frac:units = "unitless" ; + fates_alloc_store_priority_frac:long_name = "for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage" ; + double fates_allom_agb1(fates_pft) ; + fates_allom_agb1:units = "variable" ; + fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; + double fates_allom_agb2(fates_pft) ; + fates_allom_agb2:units = "variable" ; + fates_allom_agb2:long_name = "Parameter 2 for agb allometry" ; + double fates_allom_agb3(fates_pft) ; + fates_allom_agb3:units = "variable" ; + fates_allom_agb3:long_name = "Parameter 3 for agb allometry" ; + double fates_allom_agb4(fates_pft) ; + fates_allom_agb4:units = "variable" ; + fates_allom_agb4:long_name = "Parameter 4 for agb allometry" ; + double fates_allom_agb_frac(fates_pft) ; + fates_allom_agb_frac:units = "fraction" ; + fates_allom_agb_frac:long_name = "Fraction of woody biomass that is above ground" ; + double fates_allom_amode(fates_pft) ; + fates_allom_amode:units = "index" ; + fates_allom_amode:long_name = "AGB allometry function index." ; + double fates_allom_blca_expnt_diff(fates_pft) ; + fates_allom_blca_expnt_diff:units = "unitless" ; + fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; + double fates_allom_cmode(fates_pft) ; + fates_allom_cmode:units = "index" ; + fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; + double fates_allom_crown_depth_frac(fates_pft) ; + fates_allom_crown_depth_frac:units = "fraction" ; + fates_allom_crown_depth_frac:long_name = "the depth of a cohort crown as a fraction of its height" ; + double fates_allom_d2bl1(fates_pft) ; + fates_allom_d2bl1:units = "variable" ; + fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; + double fates_allom_d2bl2(fates_pft) ; + fates_allom_d2bl2:units = "variable" ; + fates_allom_d2bl2:long_name = "Parameter 2 for d2bl allometry" ; + double fates_allom_d2bl3(fates_pft) ; + fates_allom_d2bl3:units = "unitless" ; + fates_allom_d2bl3:long_name = "Parameter 3 for d2bl allometry" ; + double fates_allom_d2ca_coefficient_max(fates_pft) ; + fates_allom_d2ca_coefficient_max:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_max:long_name = "max (savanna) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2ca_coefficient_min(fates_pft) ; + fates_allom_d2ca_coefficient_min:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_min:long_name = "min (forest) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2h1(fates_pft) ; + fates_allom_d2h1:units = "variable" ; + fates_allom_d2h1:long_name = "Parameter 1 for d2h allometry (intercept, or c)" ; + double fates_allom_d2h2(fates_pft) ; + fates_allom_d2h2:units = "variable" ; + fates_allom_d2h2:long_name = "Parameter 2 for d2h allometry (slope, or m)" ; + double fates_allom_d2h3(fates_pft) ; + fates_allom_d2h3:units = "variable" ; + fates_allom_d2h3:long_name = "Parameter 3 for d2h allometry (optional)" ; + double fates_allom_dbh_maxheight(fates_pft) ; + fates_allom_dbh_maxheight:units = "cm" ; + fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; + double fates_allom_fmode(fates_pft) ; + fates_allom_fmode:units = "index" ; + fates_allom_fmode:long_name = "fine root biomass allometry function index." ; + double fates_allom_fnrt_prof_a(fates_pft) ; + fates_allom_fnrt_prof_a:units = "unitless" ; + fates_allom_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; + double fates_allom_fnrt_prof_b(fates_pft) ; + fates_allom_fnrt_prof_b:units = "unitless" ; + fates_allom_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; + double fates_allom_fnrt_prof_mode(fates_pft) ; + fates_allom_fnrt_prof_mode:units = "index" ; + fates_allom_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; + double fates_allom_frbstor_repro(fates_pft) ; + fates_allom_frbstor_repro:units = "fraction" ; + fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; + double fates_allom_hmode(fates_pft) ; + fates_allom_hmode:units = "index" ; + fates_allom_hmode:long_name = "height allometry function index." ; + double fates_allom_l2fr(fates_pft) ; + fates_allom_l2fr:units = "gC/gC" ; + fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; + double fates_allom_la_per_sa_int(fates_pft) ; + fates_allom_la_per_sa_int:units = "m2/cm2" ; + fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; + double fates_allom_la_per_sa_slp(fates_pft) ; + fates_allom_la_per_sa_slp:units = "m2/cm2/m" ; + fates_allom_la_per_sa_slp:long_name = "Leaf area per sapwood area rate of change with height, slope (optional)" ; + double fates_allom_lmode(fates_pft) ; + fates_allom_lmode:units = "index" ; + fates_allom_lmode:long_name = "leaf biomass allometry function index." ; + double fates_allom_sai_scaler(fates_pft) ; + fates_allom_sai_scaler:units = "m2/m2" ; + fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; + double fates_allom_smode(fates_pft) ; + fates_allom_smode:units = "index" ; + fates_allom_smode:long_name = "sapwood allometry function index." ; + double fates_allom_stmode(fates_pft) ; + fates_allom_stmode:units = "index" ; + fates_allom_stmode:long_name = "storage allometry function index." ; + double fates_allom_zroot_k(fates_pft) ; + fates_allom_zroot_k:units = "unitless" ; + fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; + double fates_allom_zroot_max_dbh(fates_pft) ; + fates_allom_zroot_max_dbh:units = "cm" ; + fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; + double fates_allom_zroot_max_z(fates_pft) ; + fates_allom_zroot_max_z:units = "m" ; + fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_allom_zroot_min_dbh(fates_pft) ; + fates_allom_zroot_min_dbh:units = "cm" ; + fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; + double fates_allom_zroot_min_z(fates_pft) ; + fates_allom_zroot_min_z:units = "m" ; + fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_c2b(fates_pft) ; + fates_c2b:units = "ratio" ; + fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; + double fates_cnp_eca_alpha_ptase(fates_pft) ; + fates_cnp_eca_alpha_ptase:units = "g/m3" ; + fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; + double fates_cnp_eca_decompmicc(fates_pft) ; + fates_cnp_eca_decompmicc:units = "gC/m3" ; + fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; + double fates_cnp_eca_km_nh4(fates_pft) ; + fates_cnp_eca_km_nh4:units = "gN/m3" ; + fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; + double fates_cnp_eca_km_no3(fates_pft) ; + fates_cnp_eca_km_no3:units = "gN/m3" ; + fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; + double fates_cnp_eca_km_p(fates_pft) ; + fates_cnp_eca_km_p:units = "gP/m3" ; + fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; + double fates_cnp_eca_km_ptase(fates_pft) ; + fates_cnp_eca_km_ptase:units = "gP/m3" ; + fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; + double fates_cnp_eca_lambda_ptase(fates_pft) ; + fates_cnp_eca_lambda_ptase:units = "g/m3" ; + fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; + double fates_cnp_eca_vmax_nh4(fates_pft) ; + fates_cnp_eca_vmax_nh4:units = "gN/gC/s" ; + fates_cnp_eca_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA)" ; + double fates_cnp_eca_vmax_no3(fates_pft) ; + fates_cnp_eca_vmax_no3:units = "gN/gC/s" ; + fates_cnp_eca_vmax_no3:long_name = "maximum production rate for plant no3 uptake (ECA)" ; + double fates_cnp_eca_vmax_ptase(fates_pft) ; + fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; + fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; + double fates_cnp_fnrt_adapt_tscale(fates_pft) ; + fates_cnp_fnrt_adapt_tscale:units = "days" ; + fates_cnp_fnrt_adapt_tscale:long_name = "Number of days that is shortest possible doubling period for fine-root adaptation to C/N/P balance" ; + double fates_cnp_nfix1(fates_pft) ; + fates_cnp_nfix1:units = "NA" ; + fates_cnp_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; + double fates_cnp_nitr_store_ratio(fates_pft) ; + fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; + fates_cnp_nitr_store_ratio:long_name = "storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code)" ; + double fates_cnp_phos_store_ratio(fates_pft) ; + fates_cnp_phos_store_ratio:units = "(gP/gP)" ; + fates_cnp_phos_store_ratio:long_name = "storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code)" ; + double fates_cnp_prescribed_nuptake(fates_pft) ; + fates_cnp_prescribed_nuptake:units = "fraction" ; + fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; + double fates_cnp_prescribed_puptake(fates_pft) ; + fates_cnp_prescribed_puptake:units = "fraction" ; + fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; + double fates_cnp_rd_vmax_n(fates_pft) ; + fates_cnp_rd_vmax_n:units = "gN/gC/s" ; + fates_cnp_rd_vmax_n:long_name = "maximum production rate for compbined (NH4+NO3) uptake (RD)" ; + double fates_cnp_store_ovrflw_frac(fates_pft) ; + fates_cnp_store_ovrflw_frac:units = "fraction" ; + fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; + fates_cnp_store_ovrflw_frac:use_case = "None" ; + double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_nitr_retrans:units = "fraction" ; + fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; + double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_phos_retrans:units = "fraction" ; + fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; + double fates_cnp_vmax_p(fates_pft) ; + fates_cnp_vmax_p:units = "gP/gC/s" ; + fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; + double fates_damage_frac(fates_pft) ; + fates_damage_frac:units = "fraction" ; + fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; + double fates_damage_mort_p1(fates_pft) ; + fates_damage_mort_p1:units = "fraction" ; + fates_damage_mort_p1:long_name = "inflection point of damage mortality function, a value of 0.8 means 50% mortality with 80% loss of crown, turn off with a large number" ; + double fates_damage_mort_p2(fates_pft) ; + fates_damage_mort_p2:units = "unitless" ; + fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; + 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_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" ; + double fates_fire_alpha_SH(fates_pft) ; + fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; + fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; + double fates_fire_bark_scaler(fates_pft) ; + fates_fire_bark_scaler:units = "fraction" ; + fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; + double fates_fire_crown_kill(fates_pft) ; + fates_fire_crown_kill:units = "NA" ; + fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; + double fates_frag_fnrt_fcel(fates_pft) ; + fates_frag_fnrt_fcel:units = "fraction" ; + fates_frag_fnrt_fcel:long_name = "Fine root litter cellulose fraction" ; + double fates_frag_fnrt_flab(fates_pft) ; + fates_frag_fnrt_flab:units = "fraction" ; + fates_frag_fnrt_flab:long_name = "Fine root litter labile fraction" ; + double fates_frag_fnrt_flig(fates_pft) ; + fates_frag_fnrt_flig:units = "fraction" ; + fates_frag_fnrt_flig:long_name = "Fine root litter lignin fraction" ; + double fates_frag_leaf_fcel(fates_pft) ; + fates_frag_leaf_fcel:units = "fraction" ; + fates_frag_leaf_fcel:long_name = "Leaf litter cellulose fraction" ; + double fates_frag_leaf_flab(fates_pft) ; + fates_frag_leaf_flab:units = "fraction" ; + fates_frag_leaf_flab:long_name = "Leaf litter labile fraction" ; + double fates_frag_leaf_flig(fates_pft) ; + fates_frag_leaf_flig:units = "fraction" ; + fates_frag_leaf_flig:long_name = "Leaf litter lignin fraction" ; + double fates_frag_seed_decay_rate(fates_pft) ; + fates_frag_seed_decay_rate:units = "yr-1" ; + fates_frag_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; + double fates_grperc(fates_pft) ; + fates_grperc:units = "unitless" ; + fates_grperc:long_name = "Growth respiration factor" ; + double fates_hydro_avuln_gs(fates_pft) ; + fates_hydro_avuln_gs:units = "unitless" ; + fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; + double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; + fates_hydro_avuln_node:units = "unitless" ; + fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; + double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; + fates_hydro_epsil_node:units = "MPa" ; + fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; + double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; + fates_hydro_fcap_node:units = "unitless" ; + fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; + double fates_hydro_k_lwp(fates_pft) ; + fates_hydro_k_lwp:units = "unitless" ; + fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; + double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; + fates_hydro_kmax_node:units = "kg/MPa/m/s" ; + fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; + double fates_hydro_p50_gs(fates_pft) ; + fates_hydro_p50_gs:units = "MPa" ; + fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; + double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; + fates_hydro_p50_node:units = "MPa" ; + fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; + double fates_hydro_p_taper(fates_pft) ; + fates_hydro_p_taper:units = "unitless" ; + fates_hydro_p_taper:long_name = "xylem taper exponent" ; + double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pinot_node:units = "MPa" ; + fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; + double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pitlp_node:units = "MPa" ; + fates_hydro_pitlp_node:long_name = "turgor loss point" ; + double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; + fates_hydro_resid_node:units = "cm3/cm3" ; + fates_hydro_resid_node:long_name = "residual water conent" ; + double fates_hydro_rfrac_stem(fates_pft) ; + fates_hydro_rfrac_stem:units = "fraction" ; + fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; + double fates_hydro_rs2(fates_pft) ; + fates_hydro_rs2:units = "m" ; + fates_hydro_rs2:long_name = "absorbing root radius" ; + double fates_hydro_srl(fates_pft) ; + fates_hydro_srl:units = "m g-1" ; + fates_hydro_srl:long_name = "specific root length" ; + double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; + fates_hydro_thetas_node:units = "cm3/cm3" ; + fates_hydro_thetas_node:long_name = "saturated water content" ; + double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_alpha_node:units = "MPa-1" ; + fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; + double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_m_node:units = "unitless" ; + fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; + 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_leaf_c3psn(fates_pft) ; + fates_leaf_c3psn:units = "flag" ; + fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; + double fates_leaf_jmaxha(fates_pft) ; + fates_leaf_jmaxha:units = "J/mol" ; + fates_leaf_jmaxha:long_name = "activation energy for jmax" ; + double fates_leaf_jmaxhd(fates_pft) ; + fates_leaf_jmaxhd:units = "J/mol" ; + fates_leaf_jmaxhd:long_name = "deactivation energy for jmax" ; + double fates_leaf_jmaxse(fates_pft) ; + fates_leaf_jmaxse:units = "J/mol/K" ; + fates_leaf_jmaxse:long_name = "entropy term for jmax" ; + double fates_leaf_slamax(fates_pft) ; + fates_leaf_slamax:units = "m^2/gC" ; + fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; + double fates_leaf_slatop(fates_pft) ; + fates_leaf_slatop:units = "m^2/gC" ; + fates_leaf_slatop:long_name = "Specific Leaf Area (SLA) at top of canopy, projected area basis" ; + double fates_leaf_stomatal_intercept(fates_pft) ; + fates_leaf_stomatal_intercept:units = "umol H2O/m**2/s" ; + fates_leaf_stomatal_intercept:long_name = "Minimum unstressed stomatal conductance for Ball-Berry model and Medlyn model" ; + double fates_leaf_stomatal_slope_ballberry(fates_pft) ; + fates_leaf_stomatal_slope_ballberry:units = "unitless" ; + fates_leaf_stomatal_slope_ballberry:long_name = "stomatal slope parameter, as per Ball-Berry" ; + double fates_leaf_stomatal_slope_medlyn(fates_pft) ; + fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; + fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; + double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; + fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; + fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; + double fates_leaf_vcmaxha(fates_pft) ; + fates_leaf_vcmaxha:units = "J/mol" ; + fates_leaf_vcmaxha:long_name = "activation energy for vcmax" ; + double fates_leaf_vcmaxhd(fates_pft) ; + fates_leaf_vcmaxhd:units = "J/mol" ; + fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax" ; + double fates_leaf_vcmaxse(fates_pft) ; + fates_leaf_vcmaxse:units = "J/mol/K" ; + fates_leaf_vcmaxse:long_name = "entropy term for vcmax" ; + double fates_maintresp_reduction_curvature(fates_pft) ; + fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; + fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; + double fates_maintresp_reduction_intercept(fates_pft) ; + fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; + fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; + double fates_mort_bmort(fates_pft) ; + fates_mort_bmort:units = "1/yr" ; + fates_mort_bmort:long_name = "background mortality rate" ; + double fates_mort_freezetol(fates_pft) ; + fates_mort_freezetol:units = "degrees C" ; + fates_mort_freezetol:long_name = "minimum temperature tolerance" ; + double fates_mort_hf_flc_threshold(fates_pft) ; + fates_mort_hf_flc_threshold:units = "fraction" ; + fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; + double fates_mort_hf_sm_threshold(fates_pft) ; + fates_mort_hf_sm_threshold:units = "unitless" ; + fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; + double fates_mort_ip_age_senescence(fates_pft) ; + fates_mort_ip_age_senescence:units = "years" ; + fates_mort_ip_age_senescence:long_name = "Mortality cohort age senescence inflection point. If _ this mortality term is off. Setting this value turns on age dependent mortality. " ; + double fates_mort_ip_size_senescence(fates_pft) ; + fates_mort_ip_size_senescence:units = "dbh cm" ; + fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; + double fates_mort_prescribed_canopy(fates_pft) ; + fates_mort_prescribed_canopy:units = "1/yr" ; + fates_mort_prescribed_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; + double fates_mort_prescribed_understory(fates_pft) ; + fates_mort_prescribed_understory:units = "1/yr" ; + fates_mort_prescribed_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; + double fates_mort_r_age_senescence(fates_pft) ; + fates_mort_r_age_senescence:units = "mortality rate year^-1" ; + fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; + double fates_mort_r_size_senescence(fates_pft) ; + fates_mort_r_size_senescence:units = "mortality rate dbh^-1" ; + fates_mort_r_size_senescence:long_name = "Mortality dbh senescence rate of change. Sensible range is around 0.03-0.06. Larger values give steeper mortality curves." ; + double fates_mort_scalar_coldstress(fates_pft) ; + fates_mort_scalar_coldstress:units = "1/yr" ; + fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; + double fates_mort_scalar_cstarvation(fates_pft) ; + fates_mort_scalar_cstarvation:units = "1/yr" ; + fates_mort_scalar_cstarvation:long_name = "maximum mortality rate from carbon starvation" ; + double fates_mort_scalar_hydrfailure(fates_pft) ; + fates_mort_scalar_hydrfailure:units = "1/yr" ; + fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; + double fates_nonhydro_smpsc(fates_pft) ; + fates_nonhydro_smpsc:units = "mm" ; + fates_nonhydro_smpsc:long_name = "Soil water potential at full stomatal closure" ; + double fates_nonhydro_smpso(fates_pft) ; + fates_nonhydro_smpso:units = "mm" ; + fates_nonhydro_smpso:long_name = "Soil water potential at full stomatal opening" ; + double fates_phen_cold_size_threshold(fates_pft) ; + fates_phen_cold_size_threshold:units = "cm" ; + fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; + double fates_phen_evergreen(fates_pft) ; + fates_phen_evergreen:units = "logical flag" ; + fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; + double fates_phen_flush_fraction(fates_pft) ; + fates_phen_flush_fraction:units = "fraction" ; + fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; + double fates_phen_fnrt_drop_frac(fates_pft) ; + fates_phen_fnrt_drop_frac:units = "fraction" ; + fates_phen_fnrt_drop_frac:long_name = "fraction of fine roots to drop during drought or cold" ; + double fates_phen_season_decid(fates_pft) ; + fates_phen_season_decid:units = "logical flag" ; + fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; + double fates_phen_stem_drop_fraction(fates_pft) ; + fates_phen_stem_drop_fraction:units = "fraction" ; + fates_phen_stem_drop_fraction:long_name = "fraction of stems to drop for non-woody species during drought/cold" ; + double fates_phen_stress_decid(fates_pft) ; + fates_phen_stress_decid:units = "logical flag" ; + fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; + double fates_prescribed_npp_canopy(fates_pft) ; + fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; + double fates_prescribed_npp_understory(fates_pft) ; + fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; + double fates_rad_leaf_clumping_index(fates_pft) ; + fates_rad_leaf_clumping_index:units = "fraction (0-1)" ; + fates_rad_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; + double fates_rad_leaf_rhonir(fates_pft) ; + fates_rad_leaf_rhonir:units = "fraction" ; + fates_rad_leaf_rhonir:long_name = "Leaf reflectance: near-IR" ; + double fates_rad_leaf_rhovis(fates_pft) ; + fates_rad_leaf_rhovis:units = "fraction" ; + fates_rad_leaf_rhovis:long_name = "Leaf reflectance: visible" ; + double fates_rad_leaf_taunir(fates_pft) ; + fates_rad_leaf_taunir:units = "fraction" ; + fates_rad_leaf_taunir:long_name = "Leaf transmittance: near-IR" ; + double fates_rad_leaf_tauvis(fates_pft) ; + fates_rad_leaf_tauvis:units = "fraction" ; + fates_rad_leaf_tauvis:long_name = "Leaf transmittance: visible" ; + double fates_rad_leaf_xl(fates_pft) ; + fates_rad_leaf_xl:units = "unitless" ; + fates_rad_leaf_xl:long_name = "Leaf/stem orientation index" ; + double fates_rad_stem_rhonir(fates_pft) ; + fates_rad_stem_rhonir:units = "fraction" ; + fates_rad_stem_rhonir:long_name = "Stem reflectance: near-IR" ; + double fates_rad_stem_rhovis(fates_pft) ; + fates_rad_stem_rhovis:units = "fraction" ; + fates_rad_stem_rhovis:long_name = "Stem reflectance: visible" ; + double fates_rad_stem_taunir(fates_pft) ; + fates_rad_stem_taunir:units = "fraction" ; + fates_rad_stem_taunir:long_name = "Stem transmittance: near-IR" ; + double fates_rad_stem_tauvis(fates_pft) ; + fates_rad_stem_tauvis:units = "fraction" ; + fates_rad_stem_tauvis:long_name = "Stem transmittance: visible" ; + double fates_recruit_height_min(fates_pft) ; + fates_recruit_height_min:units = "m" ; + fates_recruit_height_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; + double fates_recruit_init_density(fates_pft) ; + fates_recruit_init_density:units = "stems/m2" ; + fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation" ; + double fates_recruit_prescribed_rate(fates_pft) ; + fates_recruit_prescribed_rate:units = "n/yr" ; + fates_recruit_prescribed_rate:long_name = "recruitment rate for prescribed physiology mode" ; + double fates_recruit_seed_alloc(fates_pft) ; + fates_recruit_seed_alloc:units = "fraction" ; + fates_recruit_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; + double fates_recruit_seed_alloc_mature(fates_pft) ; + fates_recruit_seed_alloc_mature:units = "fraction" ; + fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; + double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; + fates_recruit_seed_dbh_repro_threshold:units = "cm" ; + fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter (if any) where the plant will start extra clonal allocation to the seed pool" ; + double fates_recruit_seed_germination_rate(fates_pft) ; + fates_recruit_seed_germination_rate:units = "yr-1" ; + fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; + double fates_recruit_seed_supplement(fates_pft) ; + fates_recruit_seed_supplement:units = "KgC/m2/yr" ; + fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; + double fates_stoich_nitr(fates_plant_organs, fates_pft) ; + fates_stoich_nitr:units = "gN/gC" ; + fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; + double fates_stoich_phos(fates_plant_organs, fates_pft) ; + fates_stoich_phos:units = "gP/gC" ; + fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; + double fates_trim_inc(fates_pft) ; + fates_trim_inc:units = "m2/m2" ; + fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; + double fates_trim_limit(fates_pft) ; + fates_trim_limit:units = "m2/m2" ; + fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; + double fates_turb_displar(fates_pft) ; + fates_turb_displar:units = "unitless" ; + fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; + double fates_turb_leaf_diameter(fates_pft) ; + fates_turb_leaf_diameter:units = "m" ; + fates_turb_leaf_diameter:long_name = "Characteristic leaf dimension" ; + double fates_turb_z0mr(fates_pft) ; + fates_turb_z0mr:units = "unitless" ; + fates_turb_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; + double fates_turnover_branch(fates_pft) ; + fates_turnover_branch:units = "yr" ; + fates_turnover_branch:long_name = "turnover time of branches" ; + double fates_turnover_fnrt(fates_pft) ; + fates_turnover_fnrt:units = "yr" ; + fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; + double fates_turnover_leaf(fates_leafage_class, fates_pft) ; + fates_turnover_leaf:units = "yr" ; + fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; + double fates_turnover_senleaf_fdrought(fates_pft) ; + fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; + fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; + double fates_wood_density(fates_pft) ; + fates_wood_density:units = "g/cm3" ; + fates_wood_density:long_name = "mean density of woody tissue in plant" ; + double fates_woody(fates_pft) ; + fates_woody:units = "logical flag" ; + fates_woody:long_name = "Binary woody lifeform flag" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_fire_FBD(fates_litterclass) ; + fates_fire_FBD:units = "kg Biomass/m3" ; + fates_fire_FBD:long_name = "fuel bulk density" ; + double fates_fire_low_moisture_Coeff(fates_litterclass) ; + fates_fire_low_moisture_Coeff:units = "NA" ; + fates_fire_low_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_low_moisture_Slope(fates_litterclass) ; + fates_fire_low_moisture_Slope:units = "NA" ; + fates_fire_low_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture(fates_litterclass) ; + fates_fire_mid_moisture:units = "NA" ; + fates_fire_mid_moisture:long_name = "spitfire litter moisture threshold to be considered medium dry" ; + double fates_fire_mid_moisture_Coeff(fates_litterclass) ; + fates_fire_mid_moisture_Coeff:units = "NA" ; + fates_fire_mid_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture_Slope(fates_litterclass) ; + fates_fire_mid_moisture_Slope:units = "NA" ; + fates_fire_mid_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_min_moisture(fates_litterclass) ; + fates_fire_min_moisture:units = "NA" ; + fates_fire_min_moisture:long_name = "spitfire litter moisture threshold to be considered very dry" ; + double fates_fire_SAV(fates_litterclass) ; + fates_fire_SAV:units = "cm-1" ; + fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; + double fates_frag_maxdecomp(fates_litterclass) ; + fates_frag_maxdecomp:units = "yr-1" ; + fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; + 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_base_mr_20 ; + fates_base_mr_20:units = "gC/gN/s" ; + fates_base_mr_20:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; + 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" ; + double fates_cnp_eca_plant_escalar ; + fates_cnp_eca_plant_escalar:units = "" ; + fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; + double fates_cohort_age_fusion_tol ; + fates_cohort_age_fusion_tol:units = "unitless" ; + fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; + double fates_cohort_size_fusion_tol ; + fates_cohort_size_fusion_tol:units = "unitless" ; + fates_cohort_size_fusion_tol:long_name = "minimum fraction in difference in dbh between cohorts" ; + double fates_comp_excln ; + fates_comp_excln:units = "none" ; + fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; + double fates_damage_canopy_layer_code ; + fates_damage_canopy_layer_code:units = "unitless" ; + fates_damage_canopy_layer_code:long_name = "Integer code that decides whether damage affects canopy trees (1), understory trees (2)" ; + double fates_damage_event_code ; + fates_damage_event_code:units = "unitless" ; + fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; + double fates_dev_arbitrary ; + fates_dev_arbitrary:units = "unknown" ; + fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; + double fates_fire_active_crown_fire ; + fates_fire_active_crown_fire:units = "0 or 1" ; + fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; + double fates_fire_cg_strikes ; + fates_fire_cg_strikes:units = "fraction (0-1)" ; + fates_fire_cg_strikes:long_name = "fraction of cloud to ground lightning strikes" ; + double fates_fire_drying_ratio ; + fates_fire_drying_ratio:units = "NA" ; + fates_fire_drying_ratio:long_name = "spitfire parameter, fire drying ratio for fuel moisture, alpha_FMC EQ 6 Thonicke et al 2010" ; + double fates_fire_durat_slope ; + fates_fire_durat_slope:units = "NA" ; + fates_fire_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; + double fates_fire_fdi_a ; + fates_fire_fdi_a:units = "NA" ; + fates_fire_fdi_a:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010" ; + double fates_fire_fdi_alpha ; + fates_fire_fdi_alpha:units = "NA" ; + fates_fire_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; + double fates_fire_fdi_b ; + fates_fire_fdi_b:units = "NA" ; + fates_fire_fdi_b:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010 " ; + double fates_fire_fuel_energy ; + fates_fire_fuel_energy:units = "kJ/kg" ; + fates_fire_fuel_energy:long_name = "spitfire parameter, heat content of fuel" ; + double fates_fire_max_durat ; + fates_fire_max_durat:units = "minutes" ; + fates_fire_max_durat:long_name = "spitfire parameter, fire maximum duration, Equation 14 Thonicke et al 2010" ; + double fates_fire_miner_damp ; + fates_fire_miner_damp:units = "NA" ; + fates_fire_miner_damp:long_name = "spitfire parameter, mineral-dampening coefficient EQ A1 Thonicke et al 2010 " ; + double fates_fire_miner_total ; + fates_fire_miner_total:units = "fraction" ; + fates_fire_miner_total:long_name = "spitfire parameter, total mineral content, Table A1 Thonicke et al 2010" ; + double fates_fire_nignitions ; + fates_fire_nignitions:units = "ignitions per year per km2" ; + fates_fire_nignitions:long_name = "number of annual ignitions per square km" ; + double fates_fire_part_dens ; + fates_fire_part_dens:units = "kg/m2" ; + fates_fire_part_dens:long_name = "spitfire parameter, oven dry particle density, Table A1 Thonicke et al 2010" ; + double fates_fire_threshold ; + fates_fire_threshold:units = "kW/m" ; + fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; + double fates_frag_cwd_fcel ; + fates_frag_cwd_fcel:units = "unitless" ; + fates_frag_cwd_fcel:long_name = "Cellulose fraction for CWD" ; + double fates_frag_cwd_flig ; + fates_frag_cwd_flig:units = "unitless" ; + fates_frag_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; + double fates_hydro_kmax_rsurf1 ; + fates_hydro_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; + double fates_hydro_kmax_rsurf2 ; + fates_hydro_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; + double fates_hydro_psi0 ; + fates_hydro_psi0:units = "MPa" ; + fates_hydro_psi0:long_name = "sapwood water potential at saturation" ; + double fates_hydro_psicap ; + fates_hydro_psicap:units = "MPa" ; + fates_hydro_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; + 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_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" ; + double fates_landuse_logging_collateral_frac ; + fates_landuse_logging_collateral_frac:units = "fraction" ; + fates_landuse_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; + double fates_landuse_logging_dbhmax ; + fates_landuse_logging_dbhmax:units = "cm" ; + fates_landuse_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; + double fates_landuse_logging_dbhmax_infra ; + fates_landuse_logging_dbhmax_infra:units = "cm" ; + fates_landuse_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; + double fates_landuse_logging_dbhmin ; + fates_landuse_logging_dbhmin:units = "cm" ; + fates_landuse_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; + double fates_landuse_logging_direct_frac ; + fates_landuse_logging_direct_frac:units = "fraction" ; + fates_landuse_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; + double fates_landuse_logging_event_code ; + fates_landuse_logging_event_code:units = "unitless" ; + fates_landuse_logging_event_code:long_name = "Integer code that options how logging events are structured" ; + double fates_landuse_logging_export_frac ; + fates_landuse_logging_export_frac:units = "fraction" ; + fates_landuse_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; + double fates_landuse_logging_mechanical_frac ; + fates_landuse_logging_mechanical_frac:units = "fraction" ; + fates_landuse_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; + double fates_landuse_pprodharv10_forest_mean ; + fates_landuse_pprodharv10_forest_mean:units = "fraction" ; + fates_landuse_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; + double fates_leaf_photo_temp_acclim_timescale ; + fates_leaf_photo_temp_acclim_timescale:units = "days" ; + fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; + double fates_leaf_photo_tempsens_model ; + fates_leaf_photo_tempsens_model:units = "unitless" ; + fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; + double fates_leaf_stomatal_assim_model ; + fates_leaf_stomatal_assim_model:units = "unitless" ; + fates_leaf_stomatal_assim_model:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; + double fates_leaf_stomatal_model ; + fates_leaf_stomatal_model:units = "unitless" ; + fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; + double fates_leaf_theta_cj_c3 ; + fates_leaf_theta_cj_c3:units = "unitless" ; + fates_leaf_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; + double fates_leaf_theta_cj_c4 ; + fates_leaf_theta_cj_c4:units = "unitless" ; + fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; + double fates_maintresp_model ; + fates_maintresp_model:units = "unitless" ; + fates_maintresp_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991) (NOT USED)" ; + double fates_maxcohort ; + fates_maxcohort:units = "count" ; + fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; + double fates_maxpatch_primary ; + fates_maxpatch_primary:units = "count" ; + fates_maxpatch_primary:long_name = "maximum number of primary vegetation patches per site" ; + double fates_maxpatch_secondary ; + fates_maxpatch_secondary:units = "count" ; + fates_maxpatch_secondary:long_name = "maximum number of secondary vegetation patches per site" ; + double fates_mort_disturb_frac ; + fates_mort_disturb_frac:units = "fraction" ; + fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; + double fates_mort_understorey_death ; + fates_mort_understorey_death:units = "fraction" ; + fates_mort_understorey_death:long_name = "fraction of plants in understorey cohort impacted by overstorey tree-fall" ; + double fates_patch_fusion_tol ; + fates_patch_fusion_tol:units = "unitless" ; + fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; + double fates_phen_chilltemp ; + fates_phen_chilltemp:units = "degrees C" ; + fates_phen_chilltemp:long_name = "chilling day counting threshold for vegetation" ; + double fates_phen_coldtemp ; + fates_phen_coldtemp:units = "degrees C" ; + fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; + double fates_phen_drought_model ; + fates_phen_drought_model:units = "unitless" ; + fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; + double fates_phen_drought_threshold ; + fates_phen_drought_threshold:units = "m3/m3 or mm" ; + fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_gddthresh_a ; + fates_phen_gddthresh_a:units = "none" ; + fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_b ; + fates_phen_gddthresh_b:units = "none" ; + fates_phen_gddthresh_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_c ; + fates_phen_gddthresh_c:units = "none" ; + fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_mindaysoff ; + fates_phen_mindaysoff:units = "days" ; + fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves became off-allometry" ; + double fates_phen_mindayson ; + fates_phen_mindayson:units = "days" ; + fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; + double fates_phen_moist_threshold ; + fates_phen_moist_threshold:units = "m3/m3 or mm" ; + fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_ncolddayslim ; + fates_phen_ncolddayslim:units = "days" ; + fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; + double fates_q10_froz ; + fates_q10_froz:units = "unitless" ; + fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; + double fates_q10_mr ; + fates_q10_mr:units = "unitless" ; + fates_q10_mr:long_name = "Q10 for maintenance respiration" ; + double fates_soil_salinity ; + fates_soil_salinity:units = "ppt" ; + fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; + double fates_vai_top_bin_width ; + fates_vai_top_bin_width:units = "m2/m2" ; + fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; + double fates_vai_width_increase_factor ; + fates_vai_width_increase_factor:units = "unitless" ; + fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; + +// global attributes: + :history = "This parameter file is maintained in version control\nSee https://github.com/NGEET/fates/blob/master/parameter_files/fates_params_default.cdl \nFor changes, use git blame \n" ; +data: + + fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; + + fates_history_coageclass_bin_edges = 0, 5 ; + + fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; + + fates_history_damage_bin_edges = 0, 80 ; + + fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, + 80, 90, 100 ; + + fates_alloc_organ_id = 1, 2, 3, 6 ; + + fates_hydro_htftype_node = 1, 1, 1, 1 ; + + fates_pftname = + "broadleaf_evergreen_tropical_tree ", + "needleleaf_evergreen_extratrop_tree ", + "needleleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_tree ", + "broadleaf_hydrodecid_tropical_tree ", + "broadleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_shrub ", + "broadleaf_hydrodecid_extratrop_shrub ", + "broadleaf_colddecid_extratrop_shrub ", + "arctic_c3_grass ", + "cool_c3_grass ", + "c4_grass " ; + + fates_hydro_organ_name = + "leaf ", + "stem ", + "transporting root ", + "absorbing root " ; + + fates_alloc_organ_name = + "leaf", + "fine root", + "sapwood", + "structure" ; + + fates_litterclass_name = + "twig ", + "small branch ", + "large branch ", + "trunk ", + "dead leaves ", + "live grass " ; + + 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, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; + + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + 1.2, 1.2, 1.2 ; + + fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8, 0.8 ; + + fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, + 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; + + fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, + 0.572, 0.572, 0.572, 0.572 ; + + fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, + 1.94, 1.94, 1.94 ; + + fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, + 0.931, 0.931, 0.931, 0.931 ; + + fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6 ; + + fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, + 0.95, 1, 1, 1 ; + + fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07 ; + + fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, + 1.3 ; + + fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, + 0.55, 0.55, 0.55 ; + + fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464 ; + + fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119 ; + + fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, + 0.64, 0.64, 0.64 ; + + fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, + 0.37, 0.37, 0.37 ; + + fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, + -999.9, -999.9, -999.9, -999.9, -999.9 ; + + fates_allom_dbh_maxheight = 90, 90, 90, 90, 90, 90, 3, 3, 2, 0.35, 0.35, 0.35 ; + + fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; + + fates_allom_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; + + fates_allom_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8 ; + + fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_zroot_k = 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 ; + + fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; + + fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + + fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 280, 280 ; + + fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, + 0.14, 0.14, 0.14 ; + + fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, + 0.27, 0.27, 0.27 ; + + fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_vmax_nh4 = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_eca_vmax_no3 = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_fnrt_adapt_tscale = 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100 ; + + fates_cnp_nfix1 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_rd_vmax_n = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_turnover_nitr_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_turnover_phos_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, + 5e-10, 5e-10, 5e-10, 5e-10 ; + + fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01 ; + + fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; + + fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, + 5.5, 5.5 ; + + fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2 ; + + fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07, 0.07 ; + + fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, + 0.775, 0.775, 0.775, 0.775, 0.775 ; + + fates_frag_fnrt_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_fnrt_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_fnrt_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_leaf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, + 0.51, 0.51, 0.51, 0.51 ; + + fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, + 0.11, 0.11 ; + + fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + 2.5, 2.5 ; + + fates_hydro_avuln_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_hydro_epsil_node = + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_hydro_fcap_node = + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_kmax_node = + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; + + fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + -1.5, -1.5, -1.5 ; + + fates_hydro_p50_node = + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25 ; + + fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, + 0.333, 0.333, 0.333, 0.333, 0.333 ; + + fates_hydro_pinot_node = + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; + + fates_hydro_pitlp_node = + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + -1.67, -1.67, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; + + fates_hydro_resid_node = + 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; + + fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + 0.625, 0.625, 0.625, 0.625, 0.625 ; + + fates_hydro_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, + 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; + + fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; + + fates_hydro_thetas_node = + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; + + fates_hydro_vg_alpha_node = + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005 ; + + fates_hydro_vg_m_node = + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_hydro_vg_n_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_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, + 43540, 43540, 43540, 43540 ; + + fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, + 152040, 152040, 152040, 152040, 152040 ; + + fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, + 495 ; + + fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, + 0.03, 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, + 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, + 10000, 10000, 10000, 10000, 10000, 40000 ; + + fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, + 4.7, 2.2, 5.3, 1.6 ; + + fates_leaf_vcmax25top = + 50, 65, 39, 62, 41, 58, 62, 54, 54, 78, 78, 78 ; + + fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, + 65330, 65330, 65330, 65330 ; + + fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, + 149250, 149250, 149250, 149250, 149250 ; + + fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, + 485 ; + + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; + + fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, + 0.014, 0.014, 0.014, 0.014 ; + + fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -60, -10, -80, -80, + -20, 2.5 ; + + fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, + 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; + + fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_prescribed_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, + 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; + + fates_mort_prescribed_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, + 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; + + fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_nonhydro_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, + -255000, -255000, -255000, -255000, -255000, -255000 ; + + fates_nonhydro_smpso = -66000, -66000, -66000, -66000, -66000, -66000, + -66000, -66000, -66000, -66000, -66000, -66000 ; + + fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; + + fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, + 0.5 ; + + fates_phen_fnrt_drop_frac = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; + + fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; + + fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, + 0.4, 0.4, 0.4 ; + + fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, + 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; + + fates_rad_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, + 0.9, 0.75, 0.75, 0.75 ; + + fates_rad_leaf_rhonir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, + 0.41, 0.28, 0.28, 0.28 ; + + fates_rad_leaf_rhovis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, + 0.08, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_taunir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, + 0.43, 0.4, 0.4, 0.4 ; + + fates_rad_leaf_tauvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, + 0.06, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, + -0.23, -0.23, -0.23 ; + + fates_rad_stem_rhonir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, + 0.49, 0.53, 0.53, 0.53 ; + + fates_rad_stem_rhovis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.31, 0.31, 0.31 ; + + fates_rad_stem_taunir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.25, 0.25, 0.25 ; + + fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.12, 0.12, 0.12 ; + + fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, + 0.125, 0.125, 0.125 ; + + fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2, 0.2, 0.2 ; + + fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, + 0.02, 0.02, 0.02, 0.02, 0.02 ; + + fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, + 0.9 ; + + fates_recruit_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, + 1.47, 1.47, 1.47 ; + + fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_stoich_nitr = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; + + fates_stoich_phos = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; + + fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, + 0.03, 0.03 ; + + fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; + + fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, + 0.67, 0.67, 0.67 ; + + fates_turb_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.04, 0.04, 0.04, 0.04 ; + + fates_turb_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, + 0.055, 0.055, 0.055, 0.055 ; + + fates_turnover_branch = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; + + fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_leaf = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, + 0.7 ; + + fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; + + fates_hlm_pft_map = + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + + fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; + + fates_fire_low_moisture_Coeff = 1.12, 1.09, 0.98, 0.8, 1.15, 1.15 ; + + fates_fire_low_moisture_Slope = 0.62, 0.72, 0.85, 0.8, 0.62, 0.62 ; + + fates_fire_mid_moisture = 0.72, 0.51, 0.38, 1, 0.8, 0.8 ; + + fates_fire_mid_moisture_Coeff = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_mid_moisture_Slope = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_min_moisture = 0.18, 0.12, 0, 0, 0.24, 0.24 ; + + fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; + + fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; + + fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; + + fates_base_mr_20 = 2.52e-06 ; + + fates_canopy_closure_thresh = 0.8 ; + + fates_cnp_eca_plant_escalar = 1.25e-05 ; + + fates_cohort_age_fusion_tol = 0.08 ; + + fates_cohort_size_fusion_tol = 0.08 ; + + fates_comp_excln = 3 ; + + fates_damage_canopy_layer_code = 1 ; + + fates_damage_event_code = 1 ; + + fates_dev_arbitrary = _ ; + + fates_fire_active_crown_fire = 0 ; + + fates_fire_cg_strikes = 0.2 ; + + fates_fire_drying_ratio = 66000 ; + + fates_fire_durat_slope = -11.06 ; + + fates_fire_fdi_a = 17.62 ; + + fates_fire_fdi_alpha = 0.00037 ; + + fates_fire_fdi_b = 243.12 ; + + fates_fire_fuel_energy = 18000 ; + + fates_fire_max_durat = 240 ; + + fates_fire_miner_damp = 0.41739 ; + + fates_fire_miner_total = 0.055 ; + + fates_fire_nignitions = 15 ; + + fates_fire_part_dens = 513 ; + + fates_fire_threshold = 50 ; + + fates_frag_cwd_fcel = 0.76 ; + + fates_frag_cwd_flig = 0.24 ; + + fates_hydro_kmax_rsurf1 = 20 ; + + fates_hydro_kmax_rsurf2 = 0.0001 ; + + fates_hydro_psi0 = 0 ; + + fates_hydro_psicap = -0.6 ; + + fates_hydro_solver = 1 ; + + fates_landuse_logging_coll_under_frac = 0.55983 ; + + fates_landuse_logging_collateral_frac = 0.05 ; + + fates_landuse_logging_dbhmax = _ ; + + fates_landuse_logging_dbhmax_infra = 35 ; + + fates_landuse_logging_dbhmin = 50 ; + + fates_landuse_logging_direct_frac = 0.15 ; + + fates_landuse_logging_event_code = -30 ; + + fates_landuse_logging_export_frac = 0.8 ; + + fates_landuse_logging_mechanical_frac = 0.05 ; + + fates_landuse_pprodharv10_forest_mean = 0.8125 ; + + fates_leaf_photo_temp_acclim_timescale = 30 ; + + fates_leaf_photo_tempsens_model = 1 ; + + fates_leaf_stomatal_assim_model = 1 ; + + fates_leaf_stomatal_model = 1 ; + + fates_leaf_theta_cj_c3 = 0.999 ; + + fates_leaf_theta_cj_c4 = 0.999 ; + + fates_maintresp_model = 1 ; + + fates_maxcohort = 100 ; + + fates_maxpatch_primary = 10 ; + + fates_maxpatch_secondary = 4 ; + + fates_mort_disturb_frac = 1 ; + + fates_mort_understorey_death = 0.55983 ; + + fates_patch_fusion_tol = 0.05 ; + + fates_phen_chilltemp = 5 ; + + fates_phen_coldtemp = 7.5 ; + + fates_phen_drought_model = 0 ; + + fates_phen_drought_threshold = 0.15 ; + + fates_phen_gddthresh_a = -68 ; + + fates_phen_gddthresh_b = 638 ; + + fates_phen_gddthresh_c = -0.01 ; + + fates_phen_mindaysoff = 100 ; + + fates_phen_mindayson = 90 ; + + fates_phen_moist_threshold = 0.18 ; + + fates_phen_ncolddayslim = 5 ; + + fates_q10_froz = 1.5 ; + + fates_q10_mr = 1.5 ; + + fates_soil_salinity = 0.4 ; + + fates_vai_top_bin_width = 1 ; + + fates_vai_width_increase_factor = 1 ; +} diff --git a/parameter_files/archive/api24.1.0_101722_patch_params.xml b/parameter_files/archive/api24.1.0_101722_patch_params.xml new file mode 100644 index 0000000000..888f82beac --- /dev/null +++ b/parameter_files/archive/api24.1.0_101722_patch_params.xml @@ -0,0 +1,50 @@ + + + These parameter modifications are only applicable to the fates parameter file fates/parameter_files/fates_params_default.cdl, and only for the following API's: 24.0, 24.1. These calibrations were assembled by Jennifer Holm (jaholm@lbl.gov). These are available for public use, however please coordinate with Jennifer if these parameters are used in publication. Provenance: leaf parameters were derived from TRY (Kattge et al. 2020), wood density derived from the global wood density database (Chave et al.2009, Zanne et al. 2009) height parameters are manual calibrations and personal observation. The cold mortality threshold change is simply a correction to a previous omission. The reduction in the dbh threshold for extra seed allocation is based on a logical argument, that plants will start directing resources towards reproductive allocation at or before they hit their maximum height. Plants that were set higher than dbh at maximum height were reduced to max dbh at maximum height. + archive/api24.1.0_101722_fates_params_default.cdl + fates_params_default.cdl + 1,2,3,4,5,6,7,8,9,10,11,12 + + + + + + + + + + + + + + + + + + + + + + + + 0.005, 0.009 + 62, 61 + 0.4, 0.53 + + + 80, 80, 80, 80 + + + + 0.2, 0.2, 0.2 + + + -80 + + + 90, 0.35, 0.35, 0.35 + + + + + diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 569e6a1ab6..c420b334e6 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1,4 +1,4 @@ -netcdf fates_params_default_api24 { +netcdf tmp { dimensions: fates_NCWD = 4 ; fates_history_age_bins = 7 ; @@ -221,7 +221,6 @@ variables: double fates_cnp_store_ovrflw_frac(fates_pft) ; fates_cnp_store_ovrflw_frac:units = "fraction" ; fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; - fates_cnp_store_ovrflw_frac:use_case = "None" ; double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; fates_cnp_turnover_nitr_retrans:units = "fraction" ; fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; @@ -902,7 +901,7 @@ data: fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 ; - fates_allom_dbh_maxheight = 90, 90, 90, 90, 90, 90, 3, 3, 2, 0.35, 0.35, 0.35 ; + fates_allom_dbh_maxheight = 90, 80, 80, 80, 90, 80, 3, 3, 2, 0.35, 0.35, 0.35 ; fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -1173,7 +1172,7 @@ data: fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, 0.03, 0.03, 0.03, 0.03, 0.03 ; - fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, + fates_leaf_slatop = 0.012, 0.005, 0.024, 0.009, 0.03, 0.03, 0.012, 0.03, 0.03, 0.03, 0.03, 0.03 ; fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, @@ -1185,7 +1184,7 @@ data: 4.7, 2.2, 5.3, 1.6 ; fates_leaf_vcmax25top = - 50, 65, 39, 62, 41, 58, 62, 54, 54, 78, 78, 78 ; + 50, 62, 39, 61, 41, 58, 62, 54, 54, 78, 78, 78 ; fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330 ; @@ -1204,7 +1203,7 @@ data: fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014 ; - fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -60, -10, -80, -80, + fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -80, -60, -10, -80, -80, -20, 2.5 ; fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, @@ -1292,7 +1291,7 @@ data: fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.12, 0.12, 0.12 ; - fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, + fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.2, 0.2, 0.2, 0.125, 0.125, 0.125 ; fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, @@ -1307,8 +1306,8 @@ data: fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9 ; - fates_recruit_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, - 1.47, 1.47, 1.47 ; + fates_recruit_seed_dbh_repro_threshold = 90, 90, 90, 90, 90, 90, 3, 3, 2, + 0.35, 0.35, 0.35 ; fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; @@ -1357,7 +1356,7 @@ data: fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, + fates_wood_density = 0.7, 0.4, 0.7, 0.53, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7 ; fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; diff --git a/tools/BatchPatchParams.py b/tools/BatchPatchParams.py index b3d59d940b..5e558789fe 100755 --- a/tools/BatchPatchParams.py +++ b/tools/BatchPatchParams.py @@ -69,12 +69,12 @@ def parse_syscall_str(fnamein,fnameout,pft_index,param_name,param_val): if(pft_index==0): sys_call_str = "../tools/modify_fates_paramfile.py"+" --fin " + fnamein + \ " --fout " + fnameout + " --var " + param_name + " --silent " +\ - " --val " + "\" "+param_val+"\"" + " --overwrite --all" + " --val " + "\" "+param_val+"\"" + " --overwrite --all --nohist" else: pft_str_index="{}".format(pft_index) sys_call_str = "../tools/modify_fates_paramfile.py"+" --fin " + fnamein + \ " --fout " + fnameout + " --var " + param_name + " --silent " +\ - " --val " + "\" "+param_val+"\"" + " --overwrite --pft "+pft_str_index + " --val " + "\" "+param_val+"\"" + " --overwrite --pft "+pft_str_index+" --nohist" if(debug): print(sys_call_str) diff --git a/tools/FatesPFTIndexSwapper.py b/tools/FatesPFTIndexSwapper.py index e1a71d4334..6e9052b8e5 100755 --- a/tools/FatesPFTIndexSwapper.py +++ b/tools/FatesPFTIndexSwapper.py @@ -252,8 +252,8 @@ def main(argv): out_var.units = in_var.units out_var.long_name = in_var.long_name - fp_out.history = "This file was made from FatesPFTIndexSwapper.py \n Input File = {} \n Indices = {}"\ - .format(input_fname,donor_pft_indices) + fp_out.history = fp_in.history + #var_out.mode = var.mode #fp.flush() From 0fae9e419ff32c73a835d5e20551954a338ac43b Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 17 Oct 2022 16:41:39 -0400 Subject: [PATCH 379/852] Minor fix to file attribute --- 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 c420b334e6..50e7a73f3e 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1,4 +1,4 @@ -netcdf tmp { +netcdf fates_params_default { dimensions: fates_NCWD = 4 ; fates_history_age_bins = 7 ; From fa653001629e882d57dea6f014b6bdc15c4ccf2a Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 18 Oct 2022 11:52:21 -0400 Subject: [PATCH 380/852] Updated long text of fates_recruit_seed_dbh_repro_threshold --- 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 50e7a73f3e..14c23e78a6 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -499,7 +499,7 @@ variables: fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; fates_recruit_seed_dbh_repro_threshold:units = "cm" ; - fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter (if any) where the plant will start extra clonal allocation to the seed pool" ; + fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter where the plant will start extra allocation (via fates_recruit_seed_alloc_mature) to the seed pool" ; double fates_recruit_seed_germination_rate(fates_pft) ; fates_recruit_seed_germination_rate:units = "yr-1" ; fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; From 88af6748eddeb911c4b896398c00c251aeb7eb03 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 18 Oct 2022 15:51:47 -0700 Subject: [PATCH 381/852] add dispersal type --- main/FatesDispersalMod.F90 | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index 2d94766883..39a48ee55d 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -30,6 +30,19 @@ module FatesDispersalMod integer :: neighbor_count ! total neighbors near source end type neighborhood_type + + ! Dispersal type + type, public :: dispersal_type + + real(r8), allocatable :: outgoing_local(:) ! local gridcell array of outgoing seeds, gridcell x pft + real(r8), allocatable :: outgoing_global(:) ! global accumulation array of outgoing seeds, gridcell x pft + real(r8), allocatable :: incoming_global(:) ! + + contains + + procedure :: init + + end type dispersal_type type(neighborhood_type), public, pointer :: lneighbors(:) @@ -41,6 +54,23 @@ module FatesDispersalMod ! ==================================================================================== + subroutine init(this, numprocs) + + class(dispersal_type), intent(inout) :: this + integer, intent(in) :: numprocs + + allocate(this%outgoing_local(numprocs)) + allocate(this%outgoing_global(numprocs)) + allocate(this%incoming_global(numprocs)) + + this%outgoing_local(:) = 0._r8 + this%outgoing_global(:) = 0._r8 + this%incoming_global(:) = 0._r8 + + end subroutine init + + ! ==================================================================================== + subroutine ProbabilityDensity(pd, dist) ! Main subroutine that calls difference routines based on case select mode From f8910dc39279a685c9e1c4e42c704cd05dc69d7c Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Tue, 18 Oct 2022 16:42:44 -0700 Subject: [PATCH 382/852] [ Shorten history names - too many characters was causing an error ] [ Change aboveground to agw (aboveground woody) in history variable names ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary:no testing --- main/FatesHistoryInterfaceMod.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 5af9512088..6457c2ac5d 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -5598,18 +5598,18 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_cstarvmortality_carbonflux_si_pft) - call this%set_history_var(vname='FATES_ABOVEGROUND_MORTALITY_SZPF', units='kg m-2 s-1', & + call this%set_history_var(vname='FATES_AGW_MORTALITY_SZPF', units='kg m-2 s-1', & long='Aboveground woody flux of carbon from AGB to necromass due to mortality', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_bagw_mortality_si_scpf) - call this%set_history_var(vname='FATES_ABOVEGROUND_PRODUCTIVITY_SZPF', units='kg m-2 s-1', & + call this%set_history_var(vname='FATES_AGW_PRODUCTIVITY_SZPF', units='kg m-2 s-1', & long='Aboveground woody carbon productivity', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_bagw_productivity_si_scpf) - + ! size class by age dimensioned variables call this%set_history_var(vname='FATES_NPLANT_SZAP', units = 'm-2', & From b194c1fc9a2561799225568f10f0fd0bbc589ad3 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 19 Oct 2022 11:38:20 -0400 Subject: [PATCH 383/852] Clean up of fates cnp restart code and testing --- biogeochem/EDCohortDynamicsMod.F90 | 104 ++++++++-------- main/EDMainMod.F90 | 2 +- main/EDTypesMod.F90 | 27 +++-- main/FatesRestartInterfaceMod.F90 | 184 ++++++++++++++--------------- 4 files changed, 165 insertions(+), 152 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index b6b83c1b2f..e5eaeac366 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -241,10 +241,13 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & new_cohort%l2fr = prt_params%allom_l2fr(pft) - new_cohort%cx_int = 0._r8 ! Assume balanced N,P/C stores ie log(1) = 0 - new_cohort%cx0 = 0._r8 ! Assume balanced N,P/C stores ie log(1) = 0 - new_cohort%ema_dcxdt = 0._r8 ! Assume unchanged dCX/dt - + if(hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) then + new_cohort%cx_int = 0._r8 ! Assume balanced N,P/C stores ie log(1) = 0 + new_cohort%cx0 = 0._r8 ! Assume balanced N,P/C stores ie log(1) = 0 + new_cohort%ema_dcxdt = 0._r8 ! Assume unchanged dCX/dt + new_cohort%cnp_limiter = 0 ! Assume limitations are unknown + end if + ! This sets things like vcmax25top, that depend on the ! leaf age fractions (which are defined by PARTEH) call UpdateCohortBioPhysRates(new_cohort) @@ -581,12 +584,16 @@ subroutine nan_cohort(cc_p) currentCohort%daily_no3_uptake = nan currentCohort%daily_n_gain = nan currentCohort%daily_n_fixation = nan - currentCohort%daily_p_gain = nan - currentCohort%daily_c_efflux = nan - currentCohort%daily_n_efflux = nan - currentCohort%daily_p_efflux = nan - currentCohort%daily_n_demand = nan - currentCohort%daily_p_demand = nan + currentCohort%daily_p_gain = nan + currentCohort%daily_c_efflux = nan + currentCohort%daily_n_efflux = nan + currentCohort%daily_p_efflux = nan + currentCohort%daily_n_demand = nan + currentCohort%daily_p_demand = nan + currentCohort%cx_int = nan + currentCohort%cx0 = nan + currentCohort%ema_dcxdt = nan + currentCohort%cnp_limiter = fates_unset_int currentCohort%c13disc_clm = nan ! C13 discrimination, per mil at indiv/timestep currentCohort%c13disc_acc = nan ! C13 discrimination, per mil at indiv/timestep at indiv/daily at the end of a day @@ -1208,13 +1215,9 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) end do end if - currentCohort%cx_int = (currentCohort%n*currentCohort%cx_int & - + nextc%n*nextc%cx_int)/newn - currentCohort%ema_dcxdt = (currentCohort%n*currentCohort%ema_dcxdt & - + nextc%n*nextc%ema_dcxdt)/newn - currentCohort%cx0 = (currentCohort%n*currentCohort%cx0 & - + nextc%n*nextc%cx0)/newn + + ! new cohort age is weighted mean of two cohorts currentCohort%coage = & (currentCohort%coage * (currentCohort%n/(currentCohort%n + nextc%n))) + & @@ -1435,32 +1438,39 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) currentCohort%asmort = (currentCohort%n*currentCohort%asmort + nextc%n*nextc%asmort)/newn currentCohort%frmort = (currentCohort%n*currentCohort%frmort + nextc%n*nextc%frmort)/newn - ! Nutrient fluxes - currentCohort%daily_nh4_uptake = (currentCohort%n*currentCohort%daily_nh4_uptake + & - nextc%n*nextc%daily_nh4_uptake)/newn - currentCohort%daily_no3_uptake = (currentCohort%n*currentCohort%daily_no3_uptake + & - nextc%n*nextc%daily_no3_uptake)/newn - currentCohort%daily_n_fixation = (currentCohort%n*currentCohort%daily_n_fixation + & - nextc%n*nextc%daily_n_fixation)/newn - currentCohort%daily_n_gain = (currentCohort%n*currentCohort%daily_n_gain + & - nextc%n*nextc%daily_n_gain)/newn - - currentCohort%daily_p_gain = (currentCohort%n*currentCohort%daily_p_gain + & - nextc%n*nextc%daily_p_gain)/newn - - - - currentCohort%daily_p_demand = (currentCohort%n*currentCohort%daily_p_demand + & - nextc%n*nextc%daily_p_demand)/newn - currentCohort%daily_n_demand = (currentCohort%n*currentCohort%daily_n_demand + & - nextc%n*nextc%daily_n_demand)/newn - - currentCohort%daily_c_efflux = (currentCohort%n*currentCohort%daily_c_efflux + & - nextc%n*nextc%daily_c_efflux)/newn - currentCohort%daily_n_efflux = (currentCohort%n*currentCohort%daily_n_efflux + & - nextc%n*nextc%daily_n_efflux)/newn - currentCohort%daily_p_efflux = (currentCohort%n*currentCohort%daily_p_efflux + & - nextc%n*nextc%daily_p_efflux)/newn + ! Nutrients + if(hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) then + + if(nextc%n > currentCohort%n) currentCohort%cnp_limiter = nextc%cnp_limiter + + currentCohort%cx_int = (currentCohort%n*currentCohort%cx_int + & + nextc%n*nextc%cx_int)/newn + currentCohort%ema_dcxdt = (currentCohort%n*currentCohort%ema_dcxdt + & + nextc%n*nextc%ema_dcxdt)/newn + currentCohort%cx0 = (currentCohort%n*currentCohort%cx0 + & + nextc%n*nextc%cx0)/newn + currentCohort%daily_nh4_uptake = (currentCohort%n*currentCohort%daily_nh4_uptake + & + nextc%n*nextc%daily_nh4_uptake)/newn + currentCohort%daily_no3_uptake = (currentCohort%n*currentCohort%daily_no3_uptake + & + nextc%n*nextc%daily_no3_uptake)/newn + currentCohort%daily_n_fixation = (currentCohort%n*currentCohort%daily_n_fixation + & + nextc%n*nextc%daily_n_fixation)/newn + currentCohort%daily_n_gain = (currentCohort%n*currentCohort%daily_n_gain + & + nextc%n*nextc%daily_n_gain)/newn + currentCohort%daily_p_gain = (currentCohort%n*currentCohort%daily_p_gain + & + nextc%n*nextc%daily_p_gain)/newn + currentCohort%daily_p_demand = (currentCohort%n*currentCohort%daily_p_demand + & + nextc%n*nextc%daily_p_demand)/newn + currentCohort%daily_n_demand = (currentCohort%n*currentCohort%daily_n_demand + & + nextc%n*nextc%daily_n_demand)/newn + currentCohort%daily_c_efflux = (currentCohort%n*currentCohort%daily_c_efflux + & + nextc%n*nextc%daily_c_efflux)/newn + currentCohort%daily_n_efflux = (currentCohort%n*currentCohort%daily_n_efflux + & + nextc%n*nextc%daily_n_efflux)/newn + currentCohort%daily_p_efflux = (currentCohort%n*currentCohort%daily_p_efflux + & + nextc%n*nextc%daily_p_efflux)/newn + end if + ! logging mortality, Yi Xu currentCohort%lmort_direct = (currentCohort%n*currentCohort%lmort_direct + & @@ -1826,10 +1836,12 @@ subroutine copy_cohort( currentCohort,copyc ) n%kp25top = o%kp25top ! Copy over running means - n%cx_int = o%cx_int - n%ema_dcxdt = o%ema_dcxdt - n%cx0 = o%cx0 - + if(hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) then + n%cx_int = o%cx_int + n%ema_dcxdt = o%ema_dcxdt + n%cx0 = o%cx0 + end if + ! CARBON FLUXES n%gpp_acc_hold = o%gpp_acc_hold n%gpp_acc = o%gpp_acc diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index b50370b96e..3d52612fd7 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -455,7 +455,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! Growth and Allocation (PARTEH) ! ----------------------------------------------------------------------------- currentCohort%resp_excess = 0._r8 - + call currentCohort%prt%DailyPRT() ! Send any efflux/exudates to the labile litter pools in the HLM diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 1f05882433..28df1cc372 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -28,7 +28,7 @@ module EDTypesMod private ! By default everything is private save - integer, parameter, public :: nclmax = 2 ! Maximum number of canopy layers + integer, parameter, public :: nclmax = 3 ! Maximum number of canopy layers integer, parameter, public :: ican_upper = 1 ! Nominal index for the upper canopy integer, parameter, public :: ican_ustory = 2 ! Nominal index for diagnostics that refer ! to understory layers (all layers that @@ -214,17 +214,10 @@ module EDTypesMod ! enabled simulations, this is dynamic, will ! vary between allom_l2fr_min and allom_l2fr_max ! parameters, with a tendency driven by - ! nutrient storage) [g root / g leaf] + ! nutrient storage) [kg root / kg leaf] - ! Used for CNP - integer :: cnp_limiter ! Which species is limiting growth? ! 0=none,1=C,2=N,3=P - real(r8) :: cx_int ! The time integration of the log of the relative carbon storage over relative nutrient - real(r8) :: ema_dcxdt ! The derivative of the log of the relative carbon storage over relative nutrient - real(r8) :: cx0 ! The value on the previous time-step of log of the relative carbon - ! storage over relative nutrient - real(r8) :: nc_repro ! The NC ratio of a new recruit in this patch - real(r8) :: pc_repro ! The PC ratio of a new recruit in this patch + ! VEGETATION STRUCTURE @@ -295,6 +288,16 @@ module EDTypesMod real(r8) :: c13disc_clm ! carbon 13 discrimination in new synthesized carbon: part-per-mil, at each indiv/timestep real(r8) :: c13disc_acc ! carbon 13 discrimination in new synthesized carbon: part-per-mil, at each indiv/day, at the end of a day + + ! Used for CNP + integer :: cnp_limiter ! Which species is limiting growth? ! 0=none,1=C,2=N,3=P + real(r8) :: cx_int ! The time integration of the log of the relative carbon storage over relative nutrient + real(r8) :: ema_dcxdt ! The derivative of the log of the relative carbon storage over relative nutrient + real(r8) :: cx0 ! The value on the previous time-step of log of the relative carbon + ! storage over relative nutrient + real(r8) :: nc_repro ! The NC ratio of a new recruit, used also for defining reproductive stoich + real(r8) :: pc_repro ! The PC ratio of a new recruit + ! Nutrient Fluxes (if N, P, etc. are turned on) real(r8) :: daily_nh4_uptake ! integrated daily uptake of mineralized ammonium through competitive acquisition in soil [kg N / plant/ day] @@ -310,8 +313,6 @@ module EDTypesMod real(r8) :: daily_n_demand ! The daily amount of N demanded by the plant [kgN/plant/day] real(r8) :: daily_p_demand ! The daily amount of P demanded by the plant [kgN/plant/day] - ! N fixation rate - ! The following four biophysical rates are assumed to be ! at the canopy top, at reference temp 25C, and based on the @@ -538,6 +539,8 @@ module EDTypesMod real(r8) :: btran_ft(maxpft) ! btran calculated seperately for each PFT:- real(r8) :: bstress_sal_ft(maxpft) ! bstress from salinity calculated seperately for each PFT:- + + ! These two variables are only used for external seed rain currently. real(r8) :: nitr_repro_stoich(maxpft) ! The NC ratio of a new recruit in this patch real(r8) :: phos_repro_stoich(maxpft) ! The PC ratio of a new recruit in this patch diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 6f7dde794e..ef5e8a918d 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -18,6 +18,7 @@ module FatesRestartInterfaceMod use FatesInterfaceTypesMod, only : bc_in_type use FatesInterfaceTypesMod, only : bc_out_type use FatesInterfaceTypesMod, only : hlm_use_planthydro + use FatesInterfaceTypesMod, only : hlm_parteh_mode use FatesInterfaceTypesMod, only : hlm_use_sp use FatesInterfaceTypesMod, only : fates_maxElementsPerSite use EDCohortDynamicsMod, only : UpdateCohortBioPhysRates @@ -27,6 +28,7 @@ module FatesRestartInterfaceMod use FatesHydraulicsMemMod, only : nlevsoi_hyd_max use FatesPlantHydraulicsMod, only : UpdatePlantPsiFTCFromTheta use PRTGenericMod, only : prt_global + use PRTGenericMod, only : prt_cnp_flex_allom_hyp use EDCohortDynamicsMod, only : nan_cohort use EDCohortDynamicsMod, only : zero_cohort use EDCohortDynamicsMod, only : InitPRTObject @@ -97,10 +99,18 @@ module FatesRestartInterfaceMod integer :: ir_canopy_layer_yesterday_co integer :: ir_canopy_trim_co integer :: ir_l2fr_co + integer :: ir_cx_int_co integer :: ir_emadcxdt_co integer :: ir_cx0_co - integer :: ir_pc_store_co + integer :: ir_cnplimiter_co + integer :: ir_daily_nh4_uptake_co + integer :: ir_daily_no3_uptake_co + integer :: ir_daily_n_fixation_co + integer :: ir_daily_p_uptake_co + integer :: ir_daily_n_demand_co + integer :: ir_daily_p_demand_co + integer :: ir_size_class_lasttimestep_co integer :: ir_dbh_co integer :: ir_coage_co @@ -125,12 +135,7 @@ module FatesRestartInterfaceMod integer :: ir_treesai_co integer :: ir_canopy_layer_tlai_pa - integer :: ir_daily_nh4_uptake_co - integer :: ir_daily_no3_uptake_co - integer :: ir_daily_n_fixation_co - integer :: ir_daily_p_uptake_co - integer :: ir_daily_n_demand_co - integer :: ir_daily_p_demand_co + !Logging integer :: ir_lmort_direct_co @@ -704,18 +709,56 @@ subroutine define_restart_vars(this, initialize_variables) long_name='ed cohort - l2fr', units='fraction', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_l2fr_co ) - call this%set_restart_var(vname='fates_cx_int', vtype=cohort_r8, & - long_name='ed cohort - emacx', units='fraction', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_cx_int_co ) - - call this%set_restart_var(vname='fates_emadcxdt', vtype=cohort_r8, & - long_name='ed cohort - emadcxdt', units='fraction', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_emadcxdt_co ) - - call this%set_restart_var(vname='fates_cx0', vtype=cohort_r8, & - long_name='ed cohort - cx0', units='fraction', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_cx0_co ) + if(hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) then + call this%set_restart_var(vname='fates_cx_int', vtype=cohort_r8, & + long_name='ed cohort - emacx', units='fraction', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_cx_int_co ) + + call this%set_restart_var(vname='fates_emadcxdt', vtype=cohort_r8, & + long_name='ed cohort - emadcxdt', units='fraction', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_emadcxdt_co ) + + call this%set_restart_var(vname='fates_cx0', vtype=cohort_r8, & + long_name='ed cohort - cx0', units='fraction', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_cx0_co ) + + call this%set_restart_var(vname='fates_cnplimiter', vtype=cohort_r8, & + long_name='ed cohort - cnp limiter index', units='index', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_cnplimiter_co ) + + call this%set_restart_var(vname='fates_daily_nh4_uptake', vtype=cohort_r8, & + long_name='fates cohort- daily ammonium [NH4] uptake', & + units='kg/plant/day', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_daily_nh4_uptake_co ) + + call this%set_restart_var(vname='fates_daily_no3_uptake', vtype=cohort_r8, & + long_name='fates cohort- daily ammonium [NO3] uptake', & + units='kg/plant/day', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_daily_no3_uptake_co ) + + call this%set_restart_var(vname='fates_daily_n_fixation', vtype=cohort_r8, & + long_name='fates cohort- daily N symbiotic fixation', & + units='kg/plant/day', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_daily_n_fixation_co ) + + call this%set_restart_var(vname='fates_daily_p_uptake', vtype=cohort_r8, & + long_name='fates cohort- daily phosphorus uptake', & + units='kg/plant/day', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_daily_p_uptake_co ) + + call this%set_restart_var(vname='fates_daily_p_demand', vtype=cohort_r8, & + long_name='fates cohort- daily phosphorus demand', & + units='kgP/plant/day', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_daily_p_demand_co ) + + call this%set_restart_var(vname='fates_daily_n_demand', vtype=cohort_r8, & + long_name='fates cohort- daily nitrogen demand', & + units='kgN/plant/day', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_daily_n_demand_co ) + + end if + call this%set_restart_var(vname='fates_size_class_lasttimestep', vtype=cohort_int, & long_name='ed cohort - size-class last timestep', units='index', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_size_class_lasttimestep_co ) @@ -787,35 +830,7 @@ subroutine define_restart_vars(this, initialize_variables) units='/year', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_cmort_co ) - call this%set_restart_var(vname='fates_daily_nh4_uptake', vtype=cohort_r8, & - long_name='fates cohort- daily ammonium [NH4] uptake', & - units='kg/plant/day', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_daily_nh4_uptake_co ) - call this%set_restart_var(vname='fates_daily_no3_uptake', vtype=cohort_r8, & - long_name='fates cohort- daily ammonium [NO3] uptake', & - units='kg/plant/day', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_daily_no3_uptake_co ) - - call this%set_restart_var(vname='fates_daily_n_fixation', vtype=cohort_r8, & - long_name='fates cohort- daily N symbiotic fixation', & - units='kg/plant/day', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_daily_n_fixation_co ) - - call this%set_restart_var(vname='fates_daily_p_uptake', vtype=cohort_r8, & - long_name='fates cohort- daily phosphorus uptake', & - units='kg/plant/day', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_daily_p_uptake_co ) - - call this%set_restart_var(vname='fates_daily_p_demand', vtype=cohort_r8, & - long_name='fates cohort- daily phosphorus demand', & - units='kgP/plant/day', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_daily_p_demand_co ) - - call this%set_restart_var(vname='fates_daily_n_demand', vtype=cohort_r8, & - long_name='fates cohort- daily nitrogen demand', & - units='kgN/plant/day', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_daily_n_demand_co ) call this%set_restart_var(vname='fates_frmort', vtype=cohort_r8, & long_name='ed cohort - freezing mortality rate', & @@ -1746,9 +1761,6 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_canopy_layer_yesterday_co => this%rvars(ir_canopy_layer_yesterday_co)%r81d, & rio_canopy_trim_co => this%rvars(ir_canopy_trim_co)%r81d, & rio_l2fr_co => this%rvars(ir_l2fr_co)%r81d, & - rio_cx_int_co => this%rvars(ir_cx_int_co)%r81d, & - rio_emadcxdt_co => this%rvars(ir_emadcxdt_co)%r81d, & - rio_cx0_co => this%rvars(ir_cx0_co)%r81d, & rio_seed_prod_co => this%rvars(ir_seed_prod_co)%r81d, & rio_size_class_lasttimestep => this%rvars(ir_size_class_lasttimestep_co)%int1d, & rio_dbh_co => this%rvars(ir_dbh_co)%r81d, & @@ -1766,12 +1778,6 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_bmort_co => this%rvars(ir_bmort_co)%r81d, & rio_hmort_co => this%rvars(ir_hmort_co)%r81d, & rio_cmort_co => this%rvars(ir_cmort_co)%r81d, & - rio_daily_nh4_uptake_co => this%rvars(ir_daily_nh4_uptake_co)%r81d, & - rio_daily_no3_uptake_co => this%rvars(ir_daily_no3_uptake_co)%r81d, & - rio_daily_n_fixation_co => this%rvars(ir_daily_n_fixation_co)%r81d, & - rio_daily_p_uptake_co => this%rvars(ir_daily_p_uptake_co)%r81d, & - rio_daily_n_demand_co => this%rvars(ir_daily_n_demand_co)%r81d, & - rio_daily_p_demand_co => this%rvars(ir_daily_p_demand_co)%r81d, & rio_smort_co => this%rvars(ir_smort_co)%r81d, & rio_asmort_co => this%rvars(ir_asmort_co)%r81d, & rio_frmort_co => this%rvars(ir_frmort_co)%r81d, & @@ -1945,6 +1951,20 @@ subroutine set_restart_vectors(this,nc,nsites,sites) end do end do + rio_l2fr_co(io_idx_co) = ccohort%l2fr + + if(hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) then + this%rvars(ir_cx_int_co)%r81d(io_idx_co) = ccohort%cx_int + this%rvars(ir_emadcxdt_co)%r81d(io_idx_co) = ccohort%ema_dcxdt + this%rvars(ir_cx0_co)%r81d(io_idx_co) = ccohort%cx0 + this%rvars(ir_cnplimiter_co)%r81d(io_idx_co) = real(ccohort%cnp_limiter,r8) + this%rvars(ir_daily_no3_uptake_co)%r81d(io_idx_co) = ccohort%daily_no3_uptake + this%rvars(ir_daily_nh4_uptake_co)%r81d(io_idx_co) = ccohort%daily_nh4_uptake + this%rvars(ir_daily_p_uptake_co)%r81d(io_idx_co) = ccohort%daily_p_gain + this%rvars(ir_daily_n_fixation_co)%r81d(io_idx_co) = ccohort%daily_n_fixation + this%rvars(ir_daily_n_demand_co)%r81d(io_idx_co) = ccohort%daily_n_demand + this%rvars(ir_daily_p_demand_co)%r81d(io_idx_co) = ccohort%daily_p_demand + end if if(hlm_use_planthydro==itrue)then @@ -1963,10 +1983,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_canopy_layer_co(io_idx_co) = ccohort%canopy_layer rio_canopy_layer_yesterday_co(io_idx_co) = ccohort%canopy_layer_yesterday rio_canopy_trim_co(io_idx_co) = ccohort%canopy_trim - rio_l2fr_co(io_idx_co) = ccohort%l2fr - rio_cx_int_co(io_idx_co) = ccohort%cx_int - rio_emadcxdt_co(io_idx_co) = ccohort%ema_dcxdt - rio_cx0_co(io_idx_co) = ccohort%cx0 + rio_seed_prod_co(io_idx_co) = ccohort%seed_prod rio_size_class_lasttimestep(io_idx_co) = ccohort%size_class_lasttimestep rio_dbh_co(io_idx_co) = ccohort%dbh @@ -1990,14 +2007,6 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_asmort_co(io_idx_co) = ccohort%asmort rio_frmort_co(io_idx_co) = ccohort%frmort - ! Nutrient uptake/efflux - rio_daily_no3_uptake_co(io_idx_co) = ccohort%daily_no3_uptake - rio_daily_nh4_uptake_co(io_idx_co) = ccohort%daily_nh4_uptake - rio_daily_p_uptake_co(io_idx_co) = ccohort%daily_p_gain - rio_daily_n_fixation_co(io_idx_co) = ccohort%daily_n_fixation - - rio_daily_n_demand_co(io_idx_co) = ccohort%daily_n_demand - rio_daily_p_demand_co(io_idx_co) = ccohort%daily_p_demand !Logging rio_lmort_direct_co(io_idx_co) = ccohort%lmort_direct @@ -2577,9 +2586,6 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_canopy_layer_yesterday_co => this%rvars(ir_canopy_layer_yesterday_co)%r81d, & rio_canopy_trim_co => this%rvars(ir_canopy_trim_co)%r81d, & rio_l2fr_co => this%rvars(ir_l2fr_co)%r81d, & - rio_cx_int_co => this%rvars(ir_cx_int_co)%r81d, & - rio_emadcxdt_co => this%rvars(ir_emadcxdt_co)%r81d, & - rio_cx0_co => this%rvars(ir_cx0_co)%r81d, & rio_seed_prod_co => this%rvars(ir_seed_prod_co)%r81d, & rio_size_class_lasttimestep => this%rvars(ir_size_class_lasttimestep_co)%int1d, & rio_dbh_co => this%rvars(ir_dbh_co)%r81d, & @@ -2597,12 +2603,6 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_bmort_co => this%rvars(ir_bmort_co)%r81d, & rio_hmort_co => this%rvars(ir_hmort_co)%r81d, & rio_cmort_co => this%rvars(ir_cmort_co)%r81d, & - rio_daily_nh4_uptake_co => this%rvars(ir_daily_nh4_uptake_co)%r81d, & - rio_daily_no3_uptake_co => this%rvars(ir_daily_no3_uptake_co)%r81d, & - rio_daily_n_fixation_co => this%rvars(ir_daily_n_fixation_co)%r81d, & - rio_daily_p_uptake_co => this%rvars(ir_daily_p_uptake_co)%r81d, & - rio_daily_n_demand_co => this%rvars(ir_daily_n_demand_co)%r81d, & - rio_daily_p_demand_co => this%rvars(ir_daily_p_demand_co)%r81d, & rio_smort_co => this%rvars(ir_smort_co)%r81d, & rio_asmort_co => this%rvars(ir_asmort_co)%r81d, & rio_frmort_co => this%rvars(ir_frmort_co)%r81d, & @@ -2757,19 +2757,24 @@ subroutine get_restart_vectors(this, nc, nsites, sites) end do end do - !ccohort%vcmax25top - !ccohort%jmax25top - !ccohort%tpu25top - !ccohort%kp25top - - ccohort%canopy_layer = rio_canopy_layer_co(io_idx_co) ccohort%canopy_layer_yesterday = rio_canopy_layer_yesterday_co(io_idx_co) ccohort%canopy_trim = rio_canopy_trim_co(io_idx_co) ccohort%l2fr = rio_l2fr_co(io_idx_co) - ccohort%cx_int = rio_cx_int_co(io_idx_co) - ccohort%ema_dcxdt = rio_emadcxdt_co(io_idx_co) - ccohort%cx0 = rio_cx0_co(io_idx_co) + + if(hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) then + ccohort%cx_int = this%rvars(ir_cx_int_co)%r81d(io_idx_co) + ccohort%ema_dcxdt = this%rvars(ir_emadcxdt_co)%r81d(io_idx_co) + ccohort%cx0 = this%rvars(ir_cx0_co)%r81d(io_idx_co) + ccohort%cnp_limiter = int(this%rvars(ir_cnplimiter_co)%r81d(io_idx_co)) + ccohort%daily_nh4_uptake = this%rvars(ir_daily_nh4_uptake_co)%r81d(io_idx_co) + ccohort%daily_no3_uptake = this%rvars(ir_daily_no3_uptake_co)%r81d(io_idx_co) + ccohort%daily_n_fixation = this%rvars(ir_daily_n_fixation_co)%r81d(io_idx_co) + ccohort%daily_p_gain = this%rvars(ir_daily_p_uptake_co)%r81d(io_idx_co) + ccohort%daily_n_demand = this%rvars(ir_daily_n_demand_co)%r81d(io_idx_co) + ccohort%daily_p_demand = this%rvars(ir_daily_p_demand_co)%r81d(io_idx_co) + end if + ccohort%seed_prod = rio_seed_prod_co(io_idx_co) ccohort%size_class_lasttimestep = rio_size_class_lasttimestep(io_idx_co) ccohort%dbh = rio_dbh_co(io_idx_co) @@ -2792,14 +2797,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ccohort%asmort = rio_asmort_co(io_idx_co) ccohort%frmort = rio_frmort_co(io_idx_co) - ! Nutrient uptake / efflux - ccohort%daily_nh4_uptake = rio_daily_nh4_uptake_co(io_idx_co) - ccohort%daily_no3_uptake = rio_daily_no3_uptake_co(io_idx_co) - ccohort%daily_n_fixation = rio_daily_n_fixation_co(io_idx_co) - ccohort%daily_p_gain = rio_daily_p_uptake_co(io_idx_co) - - ccohort%daily_n_demand = rio_daily_n_demand_co(io_idx_co) - ccohort%daily_p_demand = rio_daily_p_demand_co(io_idx_co) + !Logging ccohort%lmort_direct = rio_lmort_direct_co(io_idx_co) From f972400a4a1313e18132780e3196e18ad263c576 Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Fri, 21 Oct 2022 10:38:21 -0700 Subject: [PATCH 384/852] [ Tidy up names, add leaves ] [ Since AWM and AWP are fluxes of AGB, and AGB includes leaves, add leaves to AWP and AWM calculations. Tidy up names as a result of this change. ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary: no testing --- biogeochem/EDCohortDynamicsMod.F90 | 7 +-- biogeochem/EDPatchDynamicsMod.F90 | 16 ++++--- main/EDInitMod.F90 | 12 +++--- main/EDTypesMod.F90 | 6 +-- main/FatesHistoryInterfaceMod.F90 | 68 +++++++++++++++++------------- main/FatesRestartInterfaceMod.F90 | 42 +++++++++--------- 6 files changed, 82 insertions(+), 69 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index b1f4b98b44..121c902616 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -864,9 +864,10 @@ subroutine terminate_cohort(currentSite, currentPatch, currentCohort, bc_in) currentCohort%n * (struct_c+sapw_c+leaf_c+fnrt_c+store_c+repro_c) end if - currentSite%term_bagw_flux(currentCohort%size_class, currentCohort%pft) = & - currentSite%term_bagw_flux(currentCohort%size_class, currentCohort%pft) + & - currentCohort%n * (struct_c+sapw_c) + currentSite%term_abg_flux(currentCohort%size_class, currentCohort%pft) = & + currentSite%term_abg_flux(currentCohort%size_class, currentCohort%pft) + & + currentCohort%n * ( (struct_c+sapw_c+store_c) * prt_params%allom_agb_frac(currentCohort%pft) + & + leaf_c ) ! put the litter from the terminated cohorts diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index c67a42b0ba..0e2d618ceb 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -399,6 +399,7 @@ subroutine spawn_patches( currentSite, bc_in) real(r8) :: sapw_c ! sapwood carbon [kg] real(r8) :: store_c ! storage carbon [kg] real(r8) :: struct_c ! structure carbon [kg] + real(r8) :: repro_c ! reproductive carbon [kg] real(r8) :: total_c ! total carbon of plant [kg] real(r8) :: leaf_burn_frac ! fraction of leaves burned in fire ! for both woody and grass species @@ -662,6 +663,7 @@ subroutine spawn_patches( currentSite, bc_in) leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) + repro_c = currentCohort%prt%GetState(repro_organ, all_carbon_elements) total_c = sapw_c + struct_c + leaf_c + fnrt_c + store_c ! treefall mortality is the current disturbance @@ -722,10 +724,11 @@ subroutine spawn_patches( currentSite, bc_in) (nc%n * ED_val_understorey_death / hlm_freq_day ) * & total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 - currentSite%imort_bagw_flux(currentCohort%size_class, currentCohort%pft) = & - currentSite%imort_bagw_flux(currentCohort%size_class, currentCohort%pft) + & + currentSite%imort_abg_flux(currentCohort%size_class, currentCohort%pft) = & + currentSite%imort_abg_flux(currentCohort%size_class, currentCohort%pft) + & (nc%n * ED_val_understorey_death / hlm_freq_day ) * & - (sapw_c + struct_c) * prt_params%allom_agb_frac(currentCohort%pft) * & + ( (sapw_c + struct_c + store_c) * prt_params%allom_agb_frac(currentCohort%pft) + & + leaf_c ) * & g_per_kg * days_per_sec * years_per_day * ha_per_m2 @@ -817,10 +820,11 @@ subroutine spawn_patches( currentSite, bc_in) total_c * g_per_kg * days_per_sec * ha_per_m2 end if - currentSite%fmort_bagw_flux(currentCohort%size_class, currentCohort%pft) = & - currentSite%fmort_bagw_flux(currentCohort%size_class, currentCohort%pft) + & + currentSite%fmort_abg_flux(currentCohort%size_class, currentCohort%pft) = & + currentSite%fmort_abg_flux(currentCohort%size_class, currentCohort%pft) + & (nc%n * currentCohort%fire_mort) * & - (sapw_c + struct_c) * prt_params%allom_agb_frac(currentCohort%pft) * & + ( (sapw_c + struct_c + store_c) * prt_params%allom_agb_frac(currentCohort%pft) + & + leaf_c ) * & g_per_kg * days_per_sec * ha_per_m2 diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index fb7bc67219..5a72c854e1 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -135,9 +135,9 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) allocate(site_in%fmort_carbonflux_canopy(1:numpft)) allocate(site_in%fmort_carbonflux_ustory(1:numpft)) - allocate(site_in%term_bagw_flux(1:nlevsclass,1:numpft)) - allocate(site_in%imort_bagw_flux(1:nlevsclass,1:numpft)) - allocate(site_in%fmort_bagw_flux(1:nlevsclass,1:numpft)) + allocate(site_in%term_abg_flux(1:nlevsclass,1:numpft)) + allocate(site_in%imort_abg_flux(1:nlevsclass,1:numpft)) + allocate(site_in%fmort_abg_flux(1:nlevsclass,1:numpft)) site_in%nlevsoil = bc_in%nlevsoil allocate(site_in%rootfrac_scr(site_in%nlevsoil)) @@ -249,9 +249,9 @@ subroutine zero_site( site_in ) site_in%fmort_carbonflux_ustory(:) = 0._r8 site_in%fmort_rate_cambial(:,:) = 0._r8 site_in%fmort_rate_crown(:,:) = 0._r8 - site_in%term_bagw_flux(:,:) = 0._r8 - site_in%imort_bagw_flux(:,:) = 0._r8 - site_in%fmort_bagw_flux(:,:) = 0._r8 + site_in%term_abg_flux(:,:) = 0._r8 + site_in%imort_abg_flux(:,:) = 0._r8 + site_in%fmort_abg_flux(:,:) = 0._r8 ! fusoin-induced growth flux of individuals diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index de5d87051d..4f15098155 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -796,9 +796,9 @@ module EDTypesMod real(r8), allocatable :: fmort_carbonflux_canopy(:) ! biomass of canopy indivs killed due to fire per year. [gC/m2/sec] real(r8), allocatable :: fmort_carbonflux_ustory(:) ! biomass of understory indivs killed due to fire per year [gC/m2/sec] - real(r8), allocatable :: term_bagw_flux(:,:) ! aboveground woody biomass lost due to termination mortality x size x pft - real(r8), allocatable :: imort_bagw_flux(:,:) ! aboveground woody biomass lost due to impact mortality x size x pft - real(r8), allocatable :: fmort_bagw_flux(:,:) ! aboveground woody biomass lost due to fire mortality x size x pft + real(r8), allocatable :: term_abg_flux(:,:) ! aboveground biomass lost due to termination mortality x size x pft + real(r8), allocatable :: imort_abg_flux(:,:) ! aboveground biomass lost due to impact mortality x size x pft + real(r8), allocatable :: fmort_abg_flux(:,:) ! aboveground biomass lost due to fire mortality x size x pft real(r8) :: demotion_carbonflux ! biomass of demoted individuals from canopy to understory [kgC/ha/day] diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 6457c2ac5d..4620555de2 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -417,8 +417,8 @@ module FatesHistoryInterfaceMod integer :: ih_crownfiremort_si_scpf integer :: ih_cambialfiremort_si_scpf - integer :: ih_bagw_mortality_si_scpf - integer :: ih_bagw_productivity_si_scpf + integer :: ih_abg_mortality_cflux_si_scpf + integer :: ih_abg_productivity_cflux_si_scpf integer :: ih_m10_si_capf integer :: ih_nplant_si_capf @@ -1926,8 +1926,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_crownfiremort_si_scpf => this%hvars(ih_crownfiremort_si_scpf)%r82d, & hio_cambialfiremort_si_scpf => this%hvars(ih_cambialfiremort_si_scpf)%r82d, & - hio_bagw_mortality_si_scpf => this%hvars(ih_bagw_mortality_si_scpf)%r82d, & - hio_bagw_productivity_si_scpf => this%hvars(ih_bagw_productivity_si_scpf)%r82d, & + hio_abg_mortality_cflux_si_scpf => this%hvars(ih_abg_mortality_cflux_si_scpf)%r82d, & + hio_abg_productivity_cflux_si_scpf => this%hvars(ih_abg_productivity_cflux_si_scpf)%r82d, & hio_fire_c_to_atm_si => this%hvars(ih_fire_c_to_atm_si)%r81d, & hio_burn_flux_elem => this%hvars(ih_burn_flux_elem)%r82d, & @@ -2540,10 +2540,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_npp_stor_si_scpf(io_si,scpf) = hio_npp_stor_si_scpf(io_si,scpf) + & store_m_net_alloc*n_perm2 / days_per_year / sec_per_day - hio_bagw_productivity_si_scpf(io_si,scpf) = hio_bagw_productivity_si_scpf(io_si,scpf) + & - (sapw_m_net_alloc + struct_m_net_alloc) * n_perm2 * (prt_params%allom_agb_frac(ccohort%pft)) / & - days_per_year / sec_per_day - + ! Woody State Variables (basal area growth increment) if ( prt_params%woody(ft) == itrue) then @@ -2594,15 +2591,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) ccohort%asmort*ccohort%n / m2_per_ha end if - hio_bagw_mortality_si_scpf(io_si,scpf) = hio_bagw_mortality_si_scpf(io_si,scpf) + & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort) * & - (sapw_m + struct_m) * prt_params%allom_agb_frac(ccohort%pft) * & - ccohort%n * days_per_sec * years_per_day * ha_per_m2 + & - (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & - (sapw_m + struct_m) * prt_params%allom_agb_frac(ccohort%pft) * & - ccohort%n * ha_per_m2 - + hio_m1_si_scls(io_si,scls) = hio_m1_si_scls(io_si,scls) + ccohort%bmort*ccohort%n / m2_per_ha @@ -2655,6 +2644,25 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_cstarvmortality_carbonflux_si_pft(io_si,ccohort%pft) = hio_cstarvmortality_carbonflux_si_pft(io_si,ccohort%pft) + & ccohort%cmort * total_m * ccohort%n * days_per_sec * years_per_day * ha_per_m2 + ! Aboveground woody mortality + hio_abg_mortality_cflux_si_scpf(io_si,scpf) = hio_abg_mortality_cflux_si_scpf(io_si,scpf) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort) * & + ( (sapw_m + struct_m + store_m ) * prt_params%allom_agb_frac(ccohort%pft) + & + leaf_m ) * & + ccohort%n * days_per_sec * years_per_day * ha_per_m2 + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & + ( (sapw_m + struct_m + store_m ) * prt_params%allom_agb_frac(ccohort%pft) + & + leaf_m ) * & + ccohort%n * ha_per_m2 + + ! Aboveground woody productivity + hio_abg_productivity_cflux_si_scpf(io_si,scpf) = hio_abg_productivity_cflux_si_scpf(io_si,scpf) + & + ( (sapw_m_net_alloc + struct_m_net_alloc + store_m_net_alloc) * prt_params%allom_agb_frac(ccohort%pft) + & + leaf_m_net_alloc ) * n_perm2 / & + days_per_year / sec_per_day + + ! number density by size and biomass hio_agb_si_scls(io_si,scls) = hio_agb_si_scls(io_si,scls) + & total_m * ccohort%n * prt_params%allom_agb_frac(ccohort%pft) * AREA_INV @@ -3119,10 +3127,10 @@ subroutine update_history_dyn(this,nc,nsites,sites) do i_pft = 1, numpft do i_scls = 1,nlevsclass i_scpf = (i_pft-1)*nlevsclass + i_scls - hio_bagw_mortality_si_scpf(io_si,i_scpf) = hio_bagw_mortality_si_scpf(io_si,i_scpf) + & - (sites(s)%fmort_bagw_flux(i_scls,i_pft) / g_per_kg ) + & - (sites(s)%imort_bagw_flux(i_scls,i_pft) / g_per_kg) + & - (sites(s)%term_bagw_flux(i_scls,i_pft) * days_per_sec * ha_per_m2 ) ! jfn + hio_abg_mortality_cflux_si_scpf(io_si,i_scpf) = hio_abg_mortality_cflux_si_scpf(io_si,i_scpf) + & + (sites(s)%fmort_abg_flux(i_scls,i_pft) / g_per_kg ) + & + (sites(s)%imort_abg_flux(i_scls,i_pft) / g_per_kg) + & + (sites(s)%term_abg_flux(i_scls,i_pft) * days_per_sec * ha_per_m2 ) ! jfn end do end do @@ -3137,9 +3145,9 @@ subroutine update_history_dyn(this,nc,nsites,sites) sites(s)%fmort_rate_cambial(:,:) = 0._r8 sites(s)%fmort_rate_crown(:,:) = 0._r8 sites(s)%growthflux_fusion(:,:) = 0._r8 - sites(s)%fmort_bagw_flux(:,:) = 0._r8 - sites(s)%imort_bagw_flux(:,:) = 0._r8 - sites(s)%term_bagw_flux(:,:) = 0._r8 + sites(s)%fmort_abg_flux(:,:) = 0._r8 + sites(s)%imort_abg_flux(:,:) = 0._r8 + sites(s)%term_abg_flux(:,:) = 0._r8 ! pass the recruitment rate as a flux to the history, and then reset the recruitment buffer do i_pft = 1, numpft @@ -5598,17 +5606,17 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_cstarvmortality_carbonflux_si_pft) - call this%set_history_var(vname='FATES_AGW_MORTALITY_SZPF', units='kg m-2 s-1', & - long='Aboveground woody flux of carbon from AGB to necromass due to mortality', & + call this%set_history_var(vname='FATES_ABOVEGROUND_MORT_SZPF', units='kg m-2 s-1', & + long='Aboveground flux of carbon from AGB to necromass due to mortality', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_bagw_mortality_si_scpf) + index=ih_abg_mortality_cflux_si_scpf) - call this%set_history_var(vname='FATES_AGW_PRODUCTIVITY_SZPF', units='kg m-2 s-1', & - long='Aboveground woody carbon productivity', & + call this%set_history_var(vname='FATES_ABOVEGROUND_PROD_SZPF', units='kg m-2 s-1', & + long='Aboveground carbon productivity', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_bagw_productivity_si_scpf) + index=ih_abg_productivity_cflux_si_scpf) ! size class by age dimensioned variables diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index e028b8ab23..6cb63489be 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -211,9 +211,9 @@ module FatesRestartInterfaceMod integer :: ir_imortcflux_sipft integer :: ir_fmortcflux_cano_sipft integer :: ir_fmortcflux_usto_sipft - integer :: ir_bagw_term_flux_siscpf - integer :: ir_bagw_imort_flux_siscpf - integer :: ir_bagw_fmort_flux_siscpf + integer :: ir_abg_term_flux_siscpf + integer :: ir_abg_imort_flux_siscpf + integer :: ir_abg_fmort_flux_siscpf integer :: ir_cwdagin_flxdg integer :: ir_cwdbgin_flxdg integer :: ir_leaflittin_flxdg @@ -1251,20 +1251,20 @@ subroutine define_restart_vars(this, initialize_variables) units='', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_termcflux_usto_sipft ) - call this%set_restart_var(vname='fates_bagw_term_flux', vtype=cohort_r8, & + call this%set_restart_var(vname='fates_abg_term_flux', vtype=cohort_r8, & long_name='fates aboveground biomass loss from termination mortality', & units='', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_bagw_term_flux_siscpf ) + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_abg_term_flux_siscpf ) - call this%set_restart_var(vname='fates_bagw_imort_flux', vtype=cohort_r8, & + call this%set_restart_var(vname='fates_abg_imort_flux', vtype=cohort_r8, & long_name='fates aboveground biomass loss from impact mortality', & units='', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_bagw_imort_flux_siscpf ) + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_abg_imort_flux_siscpf ) - call this%set_restart_var(vname='fates_bagw_fmort_flux', vtype=cohort_r8, & + call this%set_restart_var(vname='fates_abg_fmort_flux', vtype=cohort_r8, & long_name='fates aboveground biomass loss from fire mortality', & units='', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_bagw_fmort_flux_siscpf ) + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_abg_fmort_flux_siscpf ) call this%set_restart_var(vname='fates_democflux', vtype=site_r8, & long_name='fates diagnostic demotion carbon flux', & @@ -1844,9 +1844,9 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_imortcflux_sipft => this%rvars(ir_imortcflux_sipft)%r81d, & rio_fmortcflux_cano_sipft => this%rvars(ir_fmortcflux_cano_sipft)%r81d, & rio_fmortcflux_usto_sipft => this%rvars(ir_fmortcflux_usto_sipft)%r81d, & - rio_bagw_imort_flux_siscpf => this%rvars(ir_bagw_imort_flux_siscpf)%r81d, & - rio_bagw_fmort_flux_siscpf => this%rvars(ir_bagw_fmort_flux_siscpf)%r81d, & - rio_bagw_term_flux_siscpf => this%rvars(ir_bagw_term_flux_siscpf)%r81d ) + rio_abg_imort_flux_siscpf => this%rvars(ir_abg_imort_flux_siscpf)%r81d, & + rio_abg_fmort_flux_siscpf => this%rvars(ir_abg_fmort_flux_siscpf)%r81d, & + rio_abg_term_flux_siscpf => this%rvars(ir_abg_term_flux_siscpf)%r81d ) totalCohorts = 0 @@ -2220,9 +2220,9 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_termnindiv_usto_siscpf(io_idx_si_scpf) = sites(s)%term_nindivs_ustory(i_scls,i_pft) rio_growflx_fusion_siscpf(io_idx_si_scpf) = sites(s)%growthflux_fusion(i_scls, i_pft) - rio_bagw_term_flux_siscpf(io_idx_si_scpf) = sites(s)%term_bagw_flux(i_scls, i_pft) - rio_bagw_imort_flux_siscpf(io_idx_si_scpf) = sites(s)%imort_bagw_flux(i_scls, i_pft) - rio_bagw_fmort_flux_siscpf(io_idx_si_scpf) = sites(s)%fmort_bagw_flux(i_scls, i_pft) + rio_abg_term_flux_siscpf(io_idx_si_scpf) = sites(s)%term_abg_flux(i_scls, i_pft) + rio_abg_imort_flux_siscpf(io_idx_si_scpf) = sites(s)%imort_abg_flux(i_scls, i_pft) + rio_abg_fmort_flux_siscpf(io_idx_si_scpf) = sites(s)%fmort_abg_flux(i_scls, i_pft) io_idx_si_scpf = io_idx_si_scpf + 1 end do @@ -2684,9 +2684,9 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_imortcflux_sipft => this%rvars(ir_imortcflux_sipft)%r81d, & rio_fmortcflux_cano_sipft => this%rvars(ir_fmortcflux_cano_sipft)%r81d, & rio_fmortcflux_usto_sipft => this%rvars(ir_fmortcflux_usto_sipft)%r81d, & - rio_bagw_term_flux_siscpf => this%rvars(ir_bagw_term_flux_siscpf)%r81d, & - rio_bagw_imort_flux_siscpf => this%rvars(ir_bagw_imort_flux_siscpf)%r81d, & - rio_bagw_fmort_flux_siscpf => this%rvars(ir_bagw_fmort_flux_siscpf)%r81d ) + rio_abg_term_flux_siscpf => this%rvars(ir_abg_term_flux_siscpf)%r81d, & + rio_abg_imort_flux_siscpf => this%rvars(ir_abg_imort_flux_siscpf)%r81d, & + rio_abg_fmort_flux_siscpf => this%rvars(ir_abg_fmort_flux_siscpf)%r81d ) totalcohorts = 0 @@ -3097,9 +3097,9 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%term_nindivs_ustory(i_scls,i_pft) = rio_termnindiv_usto_siscpf(io_idx_si_scpf) sites(s)%growthflux_fusion(i_scls, i_pft) = rio_growflx_fusion_siscpf(io_idx_si_scpf) - sites(s)%term_bagw_flux(i_scls,i_pft) = rio_bagw_term_flux_siscpf(io_idx_si_scpf) - sites(s)%imort_bagw_flux(i_scls,i_pft) = rio_bagw_imort_flux_siscpf(io_idx_si_scpf) - sites(s)%fmort_bagw_flux(i_scls,i_pft) = rio_bagw_fmort_flux_siscpf(io_idx_si_scpf) + sites(s)%term_abg_flux(i_scls,i_pft) = rio_abg_term_flux_siscpf(io_idx_si_scpf) + sites(s)%imort_abg_flux(i_scls,i_pft) = rio_abg_imort_flux_siscpf(io_idx_si_scpf) + sites(s)%fmort_abg_flux(i_scls,i_pft) = rio_abg_fmort_flux_siscpf(io_idx_si_scpf) io_idx_si_scpf = io_idx_si_scpf + 1 end do From 8a07cbd2de7a96856cd8114861d14fa0df26336e Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Fri, 21 Oct 2022 11:39:46 -0700 Subject: [PATCH 385/852] [ Add termination mortality to total carbon flux mortality ] [ ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary:no testing --- main/FatesHistoryInterfaceMod.F90 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 4620555de2..f46490a8b9 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2644,7 +2644,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_cstarvmortality_carbonflux_si_pft(io_si,ccohort%pft) = hio_cstarvmortality_carbonflux_si_pft(io_si,ccohort%pft) + & ccohort%cmort * total_m * ccohort%n * days_per_sec * years_per_day * ha_per_m2 - ! Aboveground woody mortality + ! Aboveground mortality hio_abg_mortality_cflux_si_scpf(io_si,scpf) = hio_abg_mortality_cflux_si_scpf(io_si,scpf) + & (ccohort%bmort + ccohort%hmort + ccohort%cmort + & ccohort%frmort + ccohort%smort + ccohort%asmort) * & @@ -3118,7 +3118,9 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_mortality_carbonflux_si_pft(io_si,i_pft) = hio_mortality_carbonflux_si_pft(io_si,i_pft) + & (sites(s)%fmort_carbonflux_canopy(i_pft) + & sites(s)%fmort_carbonflux_ustory(i_pft) + & - sites(s)%imort_carbonflux(i_pft) ) / g_per_kg !cdk + sites(s)%imort_carbonflux(i_pft) ) / g_per_kg + & ! cdk + (sites(s)%term_carbonflux_canopy(i_pft) + & + sites(s)%term_carbonflux_ustory(i_pft) ) * days_per_sec * ha_per_m2 hio_firemortality_carbonflux_si_pft(io_si,i_pft) = sites(s)%fmort_carbonflux_canopy(i_pft) / g_per_kg end do From 4010842cd4602b9672c0c6378488d93b4699f2e8 Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Fri, 21 Oct 2022 14:41:51 -0700 Subject: [PATCH 386/852] [ Tidy up spacing ] [ ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary: no testing --- main/FatesHistoryInterfaceMod.F90 | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index f46490a8b9..9c11ef5b02 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2638,6 +2638,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * total_m * & ccohort%n * ha_per_m2 + hio_hydraulicmortality_carbonflux_si_pft(io_si,ccohort%pft) = hio_hydraulicmortality_carbonflux_si_pft(io_si,ccohort%pft) + & ccohort%hmort * total_m * ccohort%n * days_per_sec * years_per_day * ha_per_m2 @@ -2649,13 +2650,11 @@ subroutine update_history_dyn(this,nc,nsites,sites) (ccohort%bmort + ccohort%hmort + ccohort%cmort + & ccohort%frmort + ccohort%smort + ccohort%asmort) * & ( (sapw_m + struct_m + store_m ) * prt_params%allom_agb_frac(ccohort%pft) + & - leaf_m ) * & - ccohort%n * days_per_sec * years_per_day * ha_per_m2 + & + leaf_m ) * ccohort%n * days_per_sec * years_per_day * ha_per_m2 + & (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & ( (sapw_m + struct_m + store_m ) * prt_params%allom_agb_frac(ccohort%pft) + & - leaf_m ) * & - ccohort%n * ha_per_m2 - + leaf_m ) * ccohort%n * ha_per_m2 + ! Aboveground woody productivity hio_abg_productivity_cflux_si_scpf(io_si,scpf) = hio_abg_productivity_cflux_si_scpf(io_si,scpf) + & ( (sapw_m_net_alloc + struct_m_net_alloc + store_m_net_alloc) * prt_params%allom_agb_frac(ccohort%pft) + & @@ -2994,6 +2993,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) cpatch => cpatch%younger end do patchloop !patch loop + ! divide basal-area-weighted height by basal area to get mean if ( sum(hio_ba_si_scpf(io_si,:)) .gt. nearzero ) then hio_ba_weighted_height_si(io_si) = hio_ba_weighted_height_si(io_si) / sum(hio_ba_si_scpf(io_si,:)) @@ -3118,10 +3118,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_mortality_carbonflux_si_pft(io_si,i_pft) = hio_mortality_carbonflux_si_pft(io_si,i_pft) + & (sites(s)%fmort_carbonflux_canopy(i_pft) + & sites(s)%fmort_carbonflux_ustory(i_pft) + & - sites(s)%imort_carbonflux(i_pft) ) / g_per_kg + & ! cdk - (sites(s)%term_carbonflux_canopy(i_pft) + & - sites(s)%term_carbonflux_ustory(i_pft) ) * days_per_sec * ha_per_m2 - + sites(s)%imort_carbonflux(i_pft) ) / g_per_kg ! cdk + hio_firemortality_carbonflux_si_pft(io_si,i_pft) = sites(s)%fmort_carbonflux_canopy(i_pft) / g_per_kg end do @@ -3131,11 +3129,12 @@ subroutine update_history_dyn(this,nc,nsites,sites) i_scpf = (i_pft-1)*nlevsclass + i_scls hio_abg_mortality_cflux_si_scpf(io_si,i_scpf) = hio_abg_mortality_cflux_si_scpf(io_si,i_scpf) + & (sites(s)%fmort_abg_flux(i_scls,i_pft) / g_per_kg ) + & - (sites(s)%imort_abg_flux(i_scls,i_pft) / g_per_kg) + & + (sites(s)%imort_abg_flux(i_scls,i_pft) / g_per_kg) + & (sites(s)%term_abg_flux(i_scls,i_pft) * days_per_sec * ha_per_m2 ) ! jfn end do end do + sites(s)%term_nindivs_canopy(:,:) = 0._r8 sites(s)%term_nindivs_ustory(:,:) = 0._r8 sites(s)%imort_carbonflux(:) = 0._r8 From 9f228fd2ce0f48011213b6fe24096f83edee72bd Mon Sep 17 00:00:00 2001 From: Jessica Needham Date: Fri, 21 Oct 2022 15:08:45 -0700 Subject: [PATCH 387/852] [ Remove repro_m that wasn't needed ] [ To be consistent with AGB reproductive carbon isn't included so no need to add it here. ] Fixes: [NGT-ED Github issue #] User interface changes?: [Yes (describe what changes), No] Code review: [Names] Test suite: [suite name, machine, compilers] Test baseline: Test namelist changes: Test answer changes: [bit for bit, roundoff, climate changing] Test summary: no testing --- biogeochem/EDPatchDynamicsMod.F90 | 2 -- 1 file changed, 2 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 0e2d618ceb..099c658a06 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -399,7 +399,6 @@ subroutine spawn_patches( currentSite, bc_in) real(r8) :: sapw_c ! sapwood carbon [kg] real(r8) :: store_c ! storage carbon [kg] real(r8) :: struct_c ! structure carbon [kg] - real(r8) :: repro_c ! reproductive carbon [kg] real(r8) :: total_c ! total carbon of plant [kg] real(r8) :: leaf_burn_frac ! fraction of leaves burned in fire ! for both woody and grass species @@ -663,7 +662,6 @@ subroutine spawn_patches( currentSite, bc_in) leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) - repro_c = currentCohort%prt%GetState(repro_organ, all_carbon_elements) total_c = sapw_c + struct_c + leaf_c + fnrt_c + store_c ! treefall mortality is the current disturbance From 4a62529a5ae3d888edbe300c870b0c3070e1ccbf Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 21 Oct 2022 17:26:29 -0700 Subject: [PATCH 388/852] add pft dimension to outgoing and incoming seed arrays --- main/FatesDispersalMod.F90 | 28 +++++++++++++++------------- main/FatesInterfaceMod.F90 | 4 ++++ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index 39a48ee55d..ff30af3364 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -5,6 +5,7 @@ module FatesDispersalMod use FatesGlobals , only : fates_log use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : pi_const + use FatesInterfaceTypesMod, only : numpft implicit none @@ -14,9 +15,9 @@ module FatesDispersalMod ! Grid cell neighbor type(neighbor_type), pointer :: next_neighbor => null() - integer :: gindex ! grid cell index - real(r8) :: gc_dist ! distance between source and neighbor - real(r8) :: density_prob ! probability density from source + integer :: gindex ! grid cell index + real(r8) :: gc_dist ! distance between source and neighbor + real(r8), allocatable :: density_prob(:) ! probability density from source per pft end type neighbor_type @@ -34,9 +35,9 @@ module FatesDispersalMod ! Dispersal type type, public :: dispersal_type - real(r8), allocatable :: outgoing_local(:) ! local gridcell array of outgoing seeds, gridcell x pft - real(r8), allocatable :: outgoing_global(:) ! global accumulation array of outgoing seeds, gridcell x pft - real(r8), allocatable :: incoming_global(:) ! + real(r8), allocatable :: outgoing_local(:,:) ! local gridcell array of outgoing seeds, gridcell x pft + real(r8), allocatable :: outgoing_global(:,:) ! global accumulation array of outgoing seeds, gridcell x pft + real(r8), allocatable :: incoming_global(:,:) ! contains @@ -54,18 +55,19 @@ module FatesDispersalMod ! ==================================================================================== - subroutine init(this, numprocs) + subroutine init(this, numprocs, numpft) class(dispersal_type), intent(inout) :: this integer, intent(in) :: numprocs + integer, intent(in) :: numpft - allocate(this%outgoing_local(numprocs)) - allocate(this%outgoing_global(numprocs)) - allocate(this%incoming_global(numprocs)) + allocate(this%outgoing_local(numprocs,numpft)) + allocate(this%outgoing_global(numprocs,numpft)) + allocate(this%incoming_global(numprocs,numpft)) - this%outgoing_local(:) = 0._r8 - this%outgoing_global(:) = 0._r8 - this%incoming_global(:) = 0._r8 + this%outgoing_local(:,:) = 0._r8 + this%outgoing_global(:,:) = 0._r8 + this%incoming_global(:,:) = 0._r8 end subroutine init diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index e55e531ea7..cdd1e46857 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1899,6 +1899,7 @@ subroutine DetermineGridCellNeighbors(neighbors) use perf_mod , only : t_startf, t_stopf use FatesDispersalMod , only : neighborhood_type, neighbor_type, ProbabilityDensity use FatesUtilsMod , only : GetNeighborDistance + use FatesInterfaceTypesMod, only : numpft ! Arguments type(neighborhood_type), intent(inout), pointer :: neighbors(:) @@ -1994,6 +1995,8 @@ subroutine DetermineGridCellNeighbors(neighbors) current_neighbor%gindex = ldecomp%gdc2glo(gj) current_neighbor%gc_dist = g2g_dist + + allocate(current_neighbor%density_prob(numpft)) call ProbabilityDensity(pdf, g2g_dist) current_neighbor%density_prob = pdf ! current_neighbor%density_prob = current_neighbor%DistWeightCalc(g2g_dist,decay_rate) @@ -2016,6 +2019,7 @@ subroutine DetermineGridCellNeighbors(neighbors) ! ldomain and ldecomp indices match per initGridCells another_neighbor%gindex = ldecomp%gdc2glo(gi) + allocate(another_neighbor%density_prob(numpft)) another_neighbor%gc_dist = current_neighbor%gc_dist another_neighbor%density_prob = current_neighbor%density_prob From 9dddd746ec3983a495088f8c394ffef9eb2dc16c Mon Sep 17 00:00:00 2001 From: Gregory Lemieux <7565064+glemieux@users.noreply.github.com> Date: Mon, 24 Oct 2022 14:53:48 -0700 Subject: [PATCH 389/852] Update biogeophys/FatesPlantRespPhotosynthMod.F90 Refactor damage check to enable the use of `sap_c_` variables regardless of run mode --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 23 +++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 83971ba9f8..5dd700e77f 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -665,20 +665,21 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! Crown damage currenly only reduces the aboveground portion of ! sapwood. Therefore we calculate the aboveground and the belowground portion ! sapwood for use in stem respiration. - - agb_frac = prt_params%allom_agb_frac(currentCohort%pft) - branch_frac = param_derived%branch_frac(currentCohort%pft) call GetCrownReduction(currentCohort%crowndamage, crown_reduction) - - sapw_c_undamaged = sapw_c / & + + else + crown_reduction = 0.0_r8 + end if + + agb_frac = prt_params%allom_agb_frac(currentCohort%pft) + branch_frac = param_derived%branch_frac(currentCohort%pft) + sapw_c_undamaged = sapw_c / & (1.0_r8 - (agb_frac * branch_frac * crown_reduction)) - ! Undamaged below ground portion - sapw_c_bgw = sapw_c_undamaged * (1.0_r8 - agb_frac) + ! Undamaged below ground portion + sapw_c_bgw = sapw_c_undamaged * (1.0_r8 - agb_frac) - ! Damaged aboveground portion - sapw_c_agw = sapw_c - sapw_c_bgw - - end if + ! Damaged aboveground portion + sapw_c_agw = sapw_c - sapw_c_bgw select case(hlm_parteh_mode) From ab4e75b5b06a49a46d43c8e73998a30461a64f9d Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 24 Oct 2022 15:06:49 -0700 Subject: [PATCH 390/852] fix whitespace and add comment --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 25 +++++++++++----------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 5dd700e77f..4b8d34f664 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -667,19 +667,20 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! sapwood for use in stem respiration. call GetCrownReduction(currentCohort%crowndamage, crown_reduction) - else - crown_reduction = 0.0_r8 - end if + else + crown_reduction = 0.0_r8 + end if - agb_frac = prt_params%allom_agb_frac(currentCohort%pft) - branch_frac = param_derived%branch_frac(currentCohort%pft) - sapw_c_undamaged = sapw_c / & - (1.0_r8 - (agb_frac * branch_frac * crown_reduction)) - ! Undamaged below ground portion - sapw_c_bgw = sapw_c_undamaged * (1.0_r8 - agb_frac) - - ! Damaged aboveground portion - sapw_c_agw = sapw_c - sapw_c_bgw + ! If crown reduction is zero, undamaged sapwood target will equal sapwood carbon + agb_frac = prt_params%allom_agb_frac(currentCohort%pft) + branch_frac = param_derived%branch_frac(currentCohort%pft) + sapw_c_undamaged = sapw_c / (1.0_r8 - (agb_frac * branch_frac * crown_reduction)) + + ! Undamaged below ground portion + sapw_c_bgw = sapw_c_undamaged * (1.0_r8 - agb_frac) + + ! Damaged aboveground portion + sapw_c_agw = sapw_c - sapw_c_bgw select case(hlm_parteh_mode) From b1e4a1a0e047ec298216460b91b940994402df3f Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 24 Oct 2022 15:38:10 -0700 Subject: [PATCH 391/852] add debug check --- main/FatesParameterDerivedMod.F90 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/main/FatesParameterDerivedMod.F90 b/main/FatesParameterDerivedMod.F90 index 0eacab293f..aa1584feb0 100644 --- a/main/FatesParameterDerivedMod.F90 +++ b/main/FatesParameterDerivedMod.F90 @@ -46,6 +46,8 @@ module FatesParameterDerivedMod type(param_derived_type), public :: param_derived + logical :: debug = .false. ! for module level debugging + contains ! =================================================================================== @@ -183,7 +185,7 @@ subroutine InitDamageTransitions(this, numpft) this%damage_transitions(i, :, ft) = this%damage_transitions(i, :, ft)/SUM(this%damage_transitions(i, :, ft)) end do - write(fates_log(),'(a/,5(F12.6,1x))') 'annual transition matrix : ', this%damage_transitions(:,:,ft) + if (debug) write(fates_log(),'(a/,5(F12.6,1x))') 'annual transition matrix : ', this%damage_transitions(:,:,ft) end do From 0777a86996adac187c89f858baef3230ac38eb32 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 25 Oct 2022 10:27:56 -0700 Subject: [PATCH 392/852] update probability density call to accept pft index and neighbor type to use indexable density_prob variable --- main/FatesDispersalMod.F90 | 4 ++-- main/FatesInterfaceMod.F90 | 18 +++++++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index ff30af3364..c22a88b199 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -73,7 +73,7 @@ end subroutine init ! ==================================================================================== - subroutine ProbabilityDensity(pd, dist) + subroutine ProbabilityDensity(pd, ipft, dist) ! Main subroutine that calls difference routines based on case select mode @@ -85,7 +85,7 @@ subroutine ProbabilityDensity(pd, dist) ! Arguments real(r8), intent(out) :: pd ! Probability density - ! integer, intent(in) :: ipft ! pft index - future arg + integer, intent(in) :: ipft ! pft index real(r8), intent(in) :: dist ! distance ! Local - temp diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index cdd1e46857..da859bd8a7 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1912,8 +1912,8 @@ subroutine DetermineGridCellNeighbors(neighbors) integer :: numg ! number of land gridcells integer :: ngcheck ! number of land gridcells, globally integer :: numproc ! number of processors, globally - integer :: ier,mpierr ! error code - integer :: i + integer :: ier,mpierr ! error code + integer :: ipft ! pft index integer :: ldsize ! ldomain size integer, allocatable :: ncells_array(:), begg_array(:) @@ -1997,9 +1997,11 @@ subroutine DetermineGridCellNeighbors(neighbors) current_neighbor%gc_dist = g2g_dist allocate(current_neighbor%density_prob(numpft)) - call ProbabilityDensity(pdf, g2g_dist) - current_neighbor%density_prob = pdf - ! current_neighbor%density_prob = current_neighbor%DistWeightCalc(g2g_dist,decay_rate) + + do ipft = 1, numpft + call ProbabilityDensity(pdf, ifpt, g2g_dist) + current_neighbor%density_prob(ipft) = pdf + end do if (associated(neighbors(gi)%first_neighbor)) then neighbors(gi)%last_neighbor%next_neighbor => current_neighbor @@ -2019,9 +2021,11 @@ subroutine DetermineGridCellNeighbors(neighbors) ! ldomain and ldecomp indices match per initGridCells another_neighbor%gindex = ldecomp%gdc2glo(gi) - allocate(another_neighbor%density_prob(numpft)) another_neighbor%gc_dist = current_neighbor%gc_dist - another_neighbor%density_prob = current_neighbor%density_prob + allocate(another_neighbor%density_prob(numpft)) + do ipft = 1, numpft + another_neighbor%density_prob(ipft) = current_neighbor%density_prob(ipft) + end do if (associated(neighbors(gj)%first_neighbor)) then neighbors(gj)%last_neighbor%next_neighbor => another_neighbor From de4054765da6416f5d4e9508e5a598e946023bbe Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 25 Oct 2022 10:53:44 -0700 Subject: [PATCH 393/852] update dispersal kernel to use parameter file --- main/EDPftvarcon.F90 | 21 ++++++++++++++++- main/FatesDispersalMod.F90 | 48 ++++++++++++++++++++++++-------------- 2 files changed, 50 insertions(+), 19 deletions(-) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 3d695e4748..8e698ab130 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -99,7 +99,8 @@ module EDPftvarcon real(r8), allocatable :: germination_rate(:) ! Fraction of seed mass germinating per year (yr-1) real(r8), allocatable :: seed_decay_rate(:) ! Fraction of seed mass (both germinated and ! ungerminated), decaying per year (yr-1) - + real(r8), allocatable :: seed_dispersal_param_A(:) ! Seed dispersal scale parameter, Bullock et al. (2017) + real(r8), allocatable :: seed_dispersal_param_B(:) ! Seed dispersal shape parameter, Bullock et al. (2017) real(r8), allocatable :: trim_limit(:) ! Limit to reductions in leaf area w stress (m2/m2) real(r8), allocatable :: trim_inc(:) ! Incremental change in trimming function (m2/m2) real(r8), allocatable :: rhol(:, :) @@ -537,6 +538,14 @@ subroutine Register_PFT(this, fates_params) name = 'fates_seed_decay_rate' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_seed_dispersal_param_A' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_seed_dispersal_param_B' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) name = 'fates_trim_limit' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & @@ -885,6 +894,14 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetrieveParameterAllocate(name=name, & data=this%seed_decay_rate) + name = 'fates_seed_dispersal_param_A' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%seed_dispersal_param_A) + + name = 'fates_seed_dispersal_param_B' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%seed_dispersal_param_B) + name = 'fates_trim_limit' call fates_params%RetrieveParameterAllocate(name=name, & data=this%trim_limit) @@ -1425,6 +1442,8 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'jmaxse = ',EDPftvarcon_inst%jmaxse write(fates_log(),fmt0) 'germination_timescale = ',EDPftvarcon_inst%germination_rate write(fates_log(),fmt0) 'seed_decay_turnover = ',EDPftvarcon_inst%seed_decay_rate + write(fates_log(),fmt0) 'seed_decay_turnover = ',EDPftvarcon_inst%seed_dispersal_param_B + write(fates_log(),fmt0) 'seed_decay_turnover = ',EDPftvarcon_inst%seed_dispersal_param_B write(fates_log(),fmt0) 'trim_limit = ',EDPftvarcon_inst%trim_limit write(fates_log(),fmt0) 'trim_inc = ',EDPftvarcon_inst%trim_inc write(fates_log(),fmt0) 'rhol = ',EDPftvarcon_inst%rhol diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index c22a88b199..edf51f5ef3 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -89,19 +89,19 @@ subroutine ProbabilityDensity(pd, ipft, dist) real(r8), intent(in) :: dist ! distance ! Local - temp - real(r8) :: param_a = 1._r8 - real(r8) :: param_b = 1._r8 + ! real(r8) :: param_a = 1._r8 + ! real(r8) :: param_b = 1._r8 hlm_dispersal_kernel_mode = 1 select case(hlm_dispersal_kernel_mode) case (hlm_dispersal_kernel_exponential) - pd = PD_exponential(dist,param_a) + pd = PD_exponential(dist) case (hlm_dispersal_kernel_exppower) - pd = PD_exppower(dist,param_a, param_b) + pd = PD_exppower(dist) case (hlm_dispersal_kernel_logsech) - pd = PD_logsech(dist,param_a, param_b) + pd = PD_logsech(dist) case default write(fates_log(),*) 'ERROR: An undefined dispersal kernel was specified: ', hlm_dispersal_kernel_mode call endrun(msg=errMsg(sourcefile, __LINE__)) @@ -111,16 +111,18 @@ end subroutine ProbabilityDensity ! ==================================================================================== - real(r8) function PD_exponential(dist,param_a) + real(r8) function PD_exponential(dist) + use EDPftvarcon , only : EDPftvarcon_inst + ! Arguments real(r8), intent(in) :: dist - real(r8), intent(in) :: param_a + ! real(r8), intent(in) :: param_a ! Assuming simple exponential decay. In the future perhaps this could be an interface ! for different weight calculations (and could be held only in fates) - PD_exponential = exp(-param_a*dist) + PD_exponential = exp(-EDPftvarcon_inst%seed_dispersal_param_A(ipft)*dist) end function PD_exponential @@ -128,34 +130,44 @@ end function PD_exponential real(r8) function PD_exppower(dist,param_a,param_b) + use EDPftvarcon , only : EDPftvarcon_inst + ! Arguments real(r8), intent(in) :: dist - real(r8), intent(in) :: param_a - real(r8), intent(in) :: param_b + ! real(r8), intent(in) :: param_a + ! real(r8), intent(in) :: param_b - ! Assuming simple exponential decay. In the future perhaps this could be an interface - ! for different weight calculations (and could be held only in fates) + associate(& + param_a => EDPftvarcon_inst%seed_dispersal_param_A, & + param_b => EDPftvarcon_inst%seed_dispersal_param_B) PD_exppower = (param_b / (2*pi_const*gamma(2/param_b))) * & exp(-(dist**param_b)/(param_a**param_b)) + + end associate end function PD_exppower ! ==================================================================================== - real(r8) function PD_logsech(dist,param_a,param_b) + real(r8) function PD_logsech(dist) + use EDPftvarcon , only : EDPftvarcon_inst + ! Arguments real(r8), intent(in) :: dist - real(r8), intent(in) :: param_a - real(r8), intent(in) :: param_b - - ! Assuming simple exponential decay. In the future perhaps this could be an interface - ! for different weight calculations (and could be held only in fates) + ! real(r8), intent(in) :: param_a + ! real(r8), intent(in) :: param_b + + associate(& + param_a => EDPftvarcon_inst%seed_dispersal_param_A, & + param_b => EDPftvarcon_inst%seed_dispersal_param_B) PD_logsech = (1/(pi_const**2 * param_b * dist**2)) / & ((dist/param_a)**(1/param_b) + & (dist/param_a)**(-1/param_b)) + + end associate end function PD_logsech From 0ec9b53541143f33be50ae21a9167ff378bdd02b Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 25 Oct 2022 17:19:27 -0700 Subject: [PATCH 394/852] add param file with seed dispersal params and update relevant param file code --- main/EDPftvarcon.F90 | 25 + main/FatesDispersalMod.F90 | 8 + main/FatesInterfaceMod.F90 | 5 + .../fates_params_seed-dispersal.cdl | 1550 +++++++++++++++++ 4 files changed, 1588 insertions(+) create mode 100644 parameter_files/fates_params_seed-dispersal.cdl diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 8e698ab130..a911d4a97d 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1629,6 +1629,31 @@ subroutine FatesCheckParams(is_master) do ipft = 1,npft + ! Check that parameter ranges for the seed dispersal scale parameter make sense + !----------------------------------------------------------------------------------- + if ( ( EDPftvarcon_inst%fates_seed_dispersal_param_A(ipft) < fates_check_param_set ) .and. & + ( EDPftvarcon_inst%fates_seed_dispersal_param_B(ipft) > fates_check_param_set ) ) then + + write(fates_log(),*) 'Seed dispersal is on' + write(fates_log(),*) 'Please also set fates_seed_dispersal_param_B' + write(fates_log(),*) 'See Bullock et al. (2017) for reasonable values' + write(fates_log(),*) 'Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + ! Check that parameter ranges for the seed dispersal shape parameter make sense + !----------------------------------------------------------------------------------- + if ( ( EDPftvarcon_inst%fates_seed_dispersal_param_B(ipft) < fates_check_param_set ) .and. & + ( EDPftvarcon_inst%fates_seed_dispersal_param_A(ipft) > fates_check_param_set ) ) then + + write(fates_log(),*) 'Seed dispersal is on' + write(fates_log(),*) 'Please also set fates_seed_dispersal_param_A' + write(fates_log(),*) 'See Bullock et al. (2017) for reasonable values' + write(fates_log(),*) 'Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + ! Check that parameter ranges for age-dependent mortality make sense !----------------------------------------------------------------------------------- if ( ( EDPftvarcon_inst%mort_ip_age_senescence(ipft) < fates_check_param_set ) .and. & diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index edf51f5ef3..7628ef5541 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -57,10 +57,18 @@ module FatesDispersalMod subroutine init(this, numprocs, numpft) + ! Use + use EDPftvarcon , only : EDPftvarcon_inst + use FatesConstantsMod , only : fates_check_param_set + + ! Arguments class(dispersal_type), intent(inout) :: this integer, intent(in) :: numprocs integer, intent(in) :: numpft + ! Check if seed dispersal mode is 'turned on' by checking the parameter values + if (EDPftvarcon_inst%fates_seed_dispersal_param_A(ipft) > fates_check_param_set) return + allocate(this%outgoing_local(numprocs,numpft)) allocate(this%outgoing_global(numprocs,numpft)) allocate(this%incoming_global(numprocs,numpft)) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index da859bd8a7..67df6b721b 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1900,6 +1900,8 @@ subroutine DetermineGridCellNeighbors(neighbors) use FatesDispersalMod , only : neighborhood_type, neighbor_type, ProbabilityDensity use FatesUtilsMod , only : GetNeighborDistance use FatesInterfaceTypesMod, only : numpft + use EDPftvarcon , only : EDPftvarcon_inst + use FatesConstantsMod , only : fates_check_param_set ! Arguments type(neighborhood_type), intent(inout), pointer :: neighbors(:) @@ -1922,6 +1924,9 @@ subroutine DetermineGridCellNeighbors(neighbors) real(r8) :: g2g_dist ! grid cell distance real(r8) :: pdf ! temp + ! Check if seed dispersal mode is 'turned on' by checking the parameter values + if (EDPftvarcon_inst%fates_seed_dispersal_param_A(ipft) > fates_check_param_set) return + ! Parameters and constants, to be moved to fates param file ! Both of these should probably be per pft ! real(r8) :: decay_rate = 1._r8 diff --git a/parameter_files/fates_params_seed-dispersal.cdl b/parameter_files/fates_params_seed-dispersal.cdl new file mode 100644 index 0000000000..6335326e89 --- /dev/null +++ b/parameter_files/fates_params_seed-dispersal.cdl @@ -0,0 +1,1550 @@ +netcdf tmp { +dimensions: + fates_NCWD = 4 ; + fates_history_age_bins = 7 ; + fates_history_coage_bins = 2 ; + fates_history_damage_bins = 2 ; + fates_history_height_bins = 6 ; + fates_history_size_bins = 13 ; + fates_hlm_pftno = 14 ; + fates_hydr_organs = 4 ; + fates_leafage_class = 1 ; + fates_litterclass = 6 ; + fates_pft = 12 ; + fates_plant_organs = 4 ; + fates_string_length = 60 ; +variables: + double fates_history_ageclass_bin_edges(fates_history_age_bins) ; + fates_history_ageclass_bin_edges:units = "yr" ; + fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; + double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; + fates_history_coageclass_bin_edges:units = "years" ; + fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; + double fates_history_height_bin_edges(fates_history_height_bins) ; + fates_history_height_bin_edges:units = "m" ; + fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; + double fates_history_damage_bin_edges(fates_history_damage_bins) ; + fates_history_damage_bin_edges:units = "% crown loss" ; + fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; + double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; + fates_history_sizeclass_bin_edges:units = "cm" ; + fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; + double fates_alloc_organ_id(fates_plant_organs) ; + fates_alloc_organ_id:units = "unitless" ; + fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; + double fates_hydro_htftype_node(fates_hydr_organs) ; + fates_hydro_htftype_node:units = "unitless" ; + fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; + char fates_pftname(fates_pft, fates_string_length) ; + fates_pftname:units = "unitless - string" ; + fates_pftname:long_name = "Description of plant type" ; + char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; + fates_hydro_organ_name:units = "unitless - string" ; + fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; + char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; + fates_alloc_organ_name:units = "unitless - string" ; + fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; + 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" ; + 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" ; + double fates_alloc_storage_cushion(fates_pft) ; + fates_alloc_storage_cushion:units = "fraction" ; + fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; + double fates_alloc_store_priority_frac(fates_pft) ; + fates_alloc_store_priority_frac:units = "unitless" ; + fates_alloc_store_priority_frac:long_name = "for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage" ; + double fates_allom_agb1(fates_pft) ; + fates_allom_agb1:units = "variable" ; + fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; + double fates_allom_agb2(fates_pft) ; + fates_allom_agb2:units = "variable" ; + fates_allom_agb2:long_name = "Parameter 2 for agb allometry" ; + double fates_allom_agb3(fates_pft) ; + fates_allom_agb3:units = "variable" ; + fates_allom_agb3:long_name = "Parameter 3 for agb allometry" ; + double fates_allom_agb4(fates_pft) ; + fates_allom_agb4:units = "variable" ; + fates_allom_agb4:long_name = "Parameter 4 for agb allometry" ; + double fates_allom_agb_frac(fates_pft) ; + fates_allom_agb_frac:units = "fraction" ; + fates_allom_agb_frac:long_name = "Fraction of woody biomass that is above ground" ; + double fates_allom_amode(fates_pft) ; + fates_allom_amode:units = "index" ; + fates_allom_amode:long_name = "AGB allometry function index." ; + double fates_allom_blca_expnt_diff(fates_pft) ; + fates_allom_blca_expnt_diff:units = "unitless" ; + fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; + double fates_allom_cmode(fates_pft) ; + fates_allom_cmode:units = "index" ; + fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; + double fates_allom_crown_depth_frac(fates_pft) ; + fates_allom_crown_depth_frac:units = "fraction" ; + fates_allom_crown_depth_frac:long_name = "the depth of a cohort crown as a fraction of its height" ; + double fates_allom_d2bl1(fates_pft) ; + fates_allom_d2bl1:units = "variable" ; + fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; + double fates_allom_d2bl2(fates_pft) ; + fates_allom_d2bl2:units = "variable" ; + fates_allom_d2bl2:long_name = "Parameter 2 for d2bl allometry" ; + double fates_allom_d2bl3(fates_pft) ; + fates_allom_d2bl3:units = "unitless" ; + fates_allom_d2bl3:long_name = "Parameter 3 for d2bl allometry" ; + double fates_allom_d2ca_coefficient_max(fates_pft) ; + fates_allom_d2ca_coefficient_max:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_max:long_name = "max (savanna) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2ca_coefficient_min(fates_pft) ; + fates_allom_d2ca_coefficient_min:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_min:long_name = "min (forest) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2h1(fates_pft) ; + fates_allom_d2h1:units = "variable" ; + fates_allom_d2h1:long_name = "Parameter 1 for d2h allometry (intercept, or c)" ; + double fates_allom_d2h2(fates_pft) ; + fates_allom_d2h2:units = "variable" ; + fates_allom_d2h2:long_name = "Parameter 2 for d2h allometry (slope, or m)" ; + double fates_allom_d2h3(fates_pft) ; + fates_allom_d2h3:units = "variable" ; + fates_allom_d2h3:long_name = "Parameter 3 for d2h allometry (optional)" ; + double fates_allom_dbh_maxheight(fates_pft) ; + fates_allom_dbh_maxheight:units = "cm" ; + fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; + double fates_allom_fmode(fates_pft) ; + fates_allom_fmode:units = "index" ; + fates_allom_fmode:long_name = "fine root biomass allometry function index." ; + double fates_allom_fnrt_prof_a(fates_pft) ; + fates_allom_fnrt_prof_a:units = "unitless" ; + fates_allom_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; + double fates_allom_fnrt_prof_b(fates_pft) ; + fates_allom_fnrt_prof_b:units = "unitless" ; + fates_allom_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; + double fates_allom_fnrt_prof_mode(fates_pft) ; + fates_allom_fnrt_prof_mode:units = "index" ; + fates_allom_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; + double fates_allom_frbstor_repro(fates_pft) ; + fates_allom_frbstor_repro:units = "fraction" ; + fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; + double fates_allom_hmode(fates_pft) ; + fates_allom_hmode:units = "index" ; + fates_allom_hmode:long_name = "height allometry function index." ; + double fates_allom_l2fr(fates_pft) ; + fates_allom_l2fr:units = "gC/gC" ; + fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; + double fates_allom_la_per_sa_int(fates_pft) ; + fates_allom_la_per_sa_int:units = "m2/cm2" ; + fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; + double fates_allom_la_per_sa_slp(fates_pft) ; + fates_allom_la_per_sa_slp:units = "m2/cm2/m" ; + fates_allom_la_per_sa_slp:long_name = "Leaf area per sapwood area rate of change with height, slope (optional)" ; + double fates_allom_lmode(fates_pft) ; + fates_allom_lmode:units = "index" ; + fates_allom_lmode:long_name = "leaf biomass allometry function index." ; + double fates_allom_sai_scaler(fates_pft) ; + fates_allom_sai_scaler:units = "m2/m2" ; + fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; + double fates_allom_smode(fates_pft) ; + fates_allom_smode:units = "index" ; + fates_allom_smode:long_name = "sapwood allometry function index." ; + double fates_allom_stmode(fates_pft) ; + fates_allom_stmode:units = "index" ; + fates_allom_stmode:long_name = "storage allometry function index." ; + double fates_allom_zroot_k(fates_pft) ; + fates_allom_zroot_k:units = "unitless" ; + fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; + double fates_allom_zroot_max_dbh(fates_pft) ; + fates_allom_zroot_max_dbh:units = "cm" ; + fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; + double fates_allom_zroot_max_z(fates_pft) ; + fates_allom_zroot_max_z:units = "m" ; + fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_allom_zroot_min_dbh(fates_pft) ; + fates_allom_zroot_min_dbh:units = "cm" ; + fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; + double fates_allom_zroot_min_z(fates_pft) ; + fates_allom_zroot_min_z:units = "m" ; + fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_c2b(fates_pft) ; + fates_c2b:units = "ratio" ; + fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; + double fates_cnp_eca_alpha_ptase(fates_pft) ; + fates_cnp_eca_alpha_ptase:units = "g/m3" ; + fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; + double fates_cnp_eca_decompmicc(fates_pft) ; + fates_cnp_eca_decompmicc:units = "gC/m3" ; + fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; + double fates_cnp_eca_km_nh4(fates_pft) ; + fates_cnp_eca_km_nh4:units = "gN/m3" ; + fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; + double fates_cnp_eca_km_no3(fates_pft) ; + fates_cnp_eca_km_no3:units = "gN/m3" ; + fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; + double fates_cnp_eca_km_p(fates_pft) ; + fates_cnp_eca_km_p:units = "gP/m3" ; + fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; + double fates_cnp_eca_km_ptase(fates_pft) ; + fates_cnp_eca_km_ptase:units = "gP/m3" ; + fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; + double fates_cnp_eca_lambda_ptase(fates_pft) ; + fates_cnp_eca_lambda_ptase:units = "g/m3" ; + fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; + double fates_cnp_eca_vmax_nh4(fates_pft) ; + fates_cnp_eca_vmax_nh4:units = "gN/gC/s" ; + fates_cnp_eca_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA)" ; + double fates_cnp_eca_vmax_no3(fates_pft) ; + fates_cnp_eca_vmax_no3:units = "gN/gC/s" ; + fates_cnp_eca_vmax_no3:long_name = "maximum production rate for plant no3 uptake (ECA)" ; + double fates_cnp_eca_vmax_ptase(fates_pft) ; + fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; + fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; + double fates_cnp_fnrt_adapt_tscale(fates_pft) ; + fates_cnp_fnrt_adapt_tscale:units = "days" ; + fates_cnp_fnrt_adapt_tscale:long_name = "Number of days that is shortest possible doubling period for fine-root adaptation to C/N/P balance" ; + double fates_cnp_nfix1(fates_pft) ; + fates_cnp_nfix1:units = "NA" ; + fates_cnp_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; + double fates_cnp_nitr_store_ratio(fates_pft) ; + fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; + fates_cnp_nitr_store_ratio:long_name = "storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code)" ; + double fates_cnp_phos_store_ratio(fates_pft) ; + fates_cnp_phos_store_ratio:units = "(gP/gP)" ; + fates_cnp_phos_store_ratio:long_name = "storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code)" ; + double fates_cnp_prescribed_nuptake(fates_pft) ; + fates_cnp_prescribed_nuptake:units = "fraction" ; + fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; + double fates_cnp_prescribed_puptake(fates_pft) ; + fates_cnp_prescribed_puptake:units = "fraction" ; + fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; + double fates_cnp_rd_vmax_n(fates_pft) ; + fates_cnp_rd_vmax_n:units = "gN/gC/s" ; + fates_cnp_rd_vmax_n:long_name = "maximum production rate for compbined (NH4+NO3) uptake (RD)" ; + double fates_cnp_store_ovrflw_frac(fates_pft) ; + fates_cnp_store_ovrflw_frac:units = "fraction" ; + fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; + fates_cnp_store_ovrflw_frac:use_case = "None" ; + double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_nitr_retrans:units = "fraction" ; + fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; + double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_phos_retrans:units = "fraction" ; + fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; + double fates_cnp_vmax_p(fates_pft) ; + fates_cnp_vmax_p:units = "gP/gC/s" ; + fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; + double fates_damage_frac(fates_pft) ; + fates_damage_frac:units = "fraction" ; + fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; + double fates_damage_mort_p1(fates_pft) ; + fates_damage_mort_p1:units = "fraction" ; + fates_damage_mort_p1:long_name = "inflection point of damage mortality function, a value of 0.8 means 50% mortality with 80% loss of crown, turn off with a large number" ; + double fates_damage_mort_p2(fates_pft) ; + fates_damage_mort_p2:units = "unitless" ; + fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; + 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_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" ; + double fates_fire_alpha_SH(fates_pft) ; + fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; + fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; + double fates_fire_bark_scaler(fates_pft) ; + fates_fire_bark_scaler:units = "fraction" ; + fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; + double fates_fire_crown_kill(fates_pft) ; + fates_fire_crown_kill:units = "NA" ; + fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; + double fates_frag_fnrt_fcel(fates_pft) ; + fates_frag_fnrt_fcel:units = "fraction" ; + fates_frag_fnrt_fcel:long_name = "Fine root litter cellulose fraction" ; + double fates_frag_fnrt_flab(fates_pft) ; + fates_frag_fnrt_flab:units = "fraction" ; + fates_frag_fnrt_flab:long_name = "Fine root litter labile fraction" ; + double fates_frag_fnrt_flig(fates_pft) ; + fates_frag_fnrt_flig:units = "fraction" ; + fates_frag_fnrt_flig:long_name = "Fine root litter lignin fraction" ; + double fates_frag_leaf_fcel(fates_pft) ; + fates_frag_leaf_fcel:units = "fraction" ; + fates_frag_leaf_fcel:long_name = "Leaf litter cellulose fraction" ; + double fates_frag_leaf_flab(fates_pft) ; + fates_frag_leaf_flab:units = "fraction" ; + fates_frag_leaf_flab:long_name = "Leaf litter labile fraction" ; + double fates_frag_leaf_flig(fates_pft) ; + fates_frag_leaf_flig:units = "fraction" ; + fates_frag_leaf_flig:long_name = "Leaf litter lignin fraction" ; + double fates_frag_seed_decay_rate(fates_pft) ; + fates_frag_seed_decay_rate:units = "yr-1" ; + fates_frag_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; + double fates_grperc(fates_pft) ; + fates_grperc:units = "unitless" ; + fates_grperc:long_name = "Growth respiration factor" ; + double fates_hydro_avuln_gs(fates_pft) ; + fates_hydro_avuln_gs:units = "unitless" ; + fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; + double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; + fates_hydro_avuln_node:units = "unitless" ; + fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; + double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; + fates_hydro_epsil_node:units = "MPa" ; + fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; + double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; + fates_hydro_fcap_node:units = "unitless" ; + fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; + double fates_hydro_k_lwp(fates_pft) ; + fates_hydro_k_lwp:units = "unitless" ; + fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; + double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; + fates_hydro_kmax_node:units = "kg/MPa/m/s" ; + fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; + double fates_hydro_p50_gs(fates_pft) ; + fates_hydro_p50_gs:units = "MPa" ; + fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; + double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; + fates_hydro_p50_node:units = "MPa" ; + fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; + double fates_hydro_p_taper(fates_pft) ; + fates_hydro_p_taper:units = "unitless" ; + fates_hydro_p_taper:long_name = "xylem taper exponent" ; + double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pinot_node:units = "MPa" ; + fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; + double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pitlp_node:units = "MPa" ; + fates_hydro_pitlp_node:long_name = "turgor loss point" ; + double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; + fates_hydro_resid_node:units = "cm3/cm3" ; + fates_hydro_resid_node:long_name = "residual water conent" ; + double fates_hydro_rfrac_stem(fates_pft) ; + fates_hydro_rfrac_stem:units = "fraction" ; + fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; + double fates_hydro_rs2(fates_pft) ; + fates_hydro_rs2:units = "m" ; + fates_hydro_rs2:long_name = "absorbing root radius" ; + double fates_hydro_srl(fates_pft) ; + fates_hydro_srl:units = "m g-1" ; + fates_hydro_srl:long_name = "specific root length" ; + double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; + fates_hydro_thetas_node:units = "cm3/cm3" ; + fates_hydro_thetas_node:long_name = "saturated water content" ; + double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_alpha_node:units = "MPa-1" ; + fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; + double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_m_node:units = "unitless" ; + fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; + 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_leaf_c3psn(fates_pft) ; + fates_leaf_c3psn:units = "flag" ; + fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; + double fates_leaf_jmaxha(fates_pft) ; + fates_leaf_jmaxha:units = "J/mol" ; + fates_leaf_jmaxha:long_name = "activation energy for jmax" ; + double fates_leaf_jmaxhd(fates_pft) ; + fates_leaf_jmaxhd:units = "J/mol" ; + fates_leaf_jmaxhd:long_name = "deactivation energy for jmax" ; + double fates_leaf_jmaxse(fates_pft) ; + fates_leaf_jmaxse:units = "J/mol/K" ; + fates_leaf_jmaxse:long_name = "entropy term for jmax" ; + double fates_leaf_slamax(fates_pft) ; + fates_leaf_slamax:units = "m^2/gC" ; + fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; + double fates_leaf_slatop(fates_pft) ; + fates_leaf_slatop:units = "m^2/gC" ; + fates_leaf_slatop:long_name = "Specific Leaf Area (SLA) at top of canopy, projected area basis" ; + double fates_leaf_stomatal_intercept(fates_pft) ; + fates_leaf_stomatal_intercept:units = "umol H2O/m**2/s" ; + fates_leaf_stomatal_intercept:long_name = "Minimum unstressed stomatal conductance for Ball-Berry model and Medlyn model" ; + double fates_leaf_stomatal_slope_ballberry(fates_pft) ; + fates_leaf_stomatal_slope_ballberry:units = "unitless" ; + fates_leaf_stomatal_slope_ballberry:long_name = "stomatal slope parameter, as per Ball-Berry" ; + double fates_leaf_stomatal_slope_medlyn(fates_pft) ; + fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; + fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; + double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; + fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; + fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; + double fates_leaf_vcmaxha(fates_pft) ; + fates_leaf_vcmaxha:units = "J/mol" ; + fates_leaf_vcmaxha:long_name = "activation energy for vcmax" ; + double fates_leaf_vcmaxhd(fates_pft) ; + fates_leaf_vcmaxhd:units = "J/mol" ; + fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax" ; + double fates_leaf_vcmaxse(fates_pft) ; + fates_leaf_vcmaxse:units = "J/mol/K" ; + fates_leaf_vcmaxse:long_name = "entropy term for vcmax" ; + double fates_maintresp_reduction_curvature(fates_pft) ; + fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; + fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; + double fates_maintresp_reduction_intercept(fates_pft) ; + fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; + fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; + double fates_mort_bmort(fates_pft) ; + fates_mort_bmort:units = "1/yr" ; + fates_mort_bmort:long_name = "background mortality rate" ; + double fates_mort_freezetol(fates_pft) ; + fates_mort_freezetol:units = "degrees C" ; + fates_mort_freezetol:long_name = "minimum temperature tolerance" ; + double fates_mort_hf_flc_threshold(fates_pft) ; + fates_mort_hf_flc_threshold:units = "fraction" ; + fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; + double fates_mort_hf_sm_threshold(fates_pft) ; + fates_mort_hf_sm_threshold:units = "unitless" ; + fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; + double fates_mort_ip_age_senescence(fates_pft) ; + fates_mort_ip_age_senescence:units = "years" ; + fates_mort_ip_age_senescence:long_name = "Mortality cohort age senescence inflection point. If _ this mortality term is off. Setting this value turns on age dependent mortality. " ; + double fates_mort_ip_size_senescence(fates_pft) ; + fates_mort_ip_size_senescence:units = "dbh cm" ; + fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; + double fates_mort_prescribed_canopy(fates_pft) ; + fates_mort_prescribed_canopy:units = "1/yr" ; + fates_mort_prescribed_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; + double fates_mort_prescribed_understory(fates_pft) ; + fates_mort_prescribed_understory:units = "1/yr" ; + fates_mort_prescribed_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; + double fates_mort_r_age_senescence(fates_pft) ; + fates_mort_r_age_senescence:units = "mortality rate year^-1" ; + fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; + double fates_mort_r_size_senescence(fates_pft) ; + fates_mort_r_size_senescence:units = "mortality rate dbh^-1" ; + fates_mort_r_size_senescence:long_name = "Mortality dbh senescence rate of change. Sensible range is around 0.03-0.06. Larger values give steeper mortality curves." ; + double fates_mort_scalar_coldstress(fates_pft) ; + fates_mort_scalar_coldstress:units = "1/yr" ; + fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; + double fates_mort_scalar_cstarvation(fates_pft) ; + fates_mort_scalar_cstarvation:units = "1/yr" ; + fates_mort_scalar_cstarvation:long_name = "maximum mortality rate from carbon starvation" ; + double fates_mort_scalar_hydrfailure(fates_pft) ; + fates_mort_scalar_hydrfailure:units = "1/yr" ; + fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; + double fates_nonhydro_smpsc(fates_pft) ; + fates_nonhydro_smpsc:units = "mm" ; + fates_nonhydro_smpsc:long_name = "Soil water potential at full stomatal closure" ; + double fates_nonhydro_smpso(fates_pft) ; + fates_nonhydro_smpso:units = "mm" ; + fates_nonhydro_smpso:long_name = "Soil water potential at full stomatal opening" ; + double fates_phen_cold_size_threshold(fates_pft) ; + fates_phen_cold_size_threshold:units = "cm" ; + fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; + double fates_phen_evergreen(fates_pft) ; + fates_phen_evergreen:units = "logical flag" ; + fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; + double fates_phen_flush_fraction(fates_pft) ; + fates_phen_flush_fraction:units = "fraction" ; + fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; + double fates_phen_fnrt_drop_frac(fates_pft) ; + fates_phen_fnrt_drop_frac:units = "fraction" ; + fates_phen_fnrt_drop_frac:long_name = "fraction of fine roots to drop during drought or cold" ; + double fates_phen_season_decid(fates_pft) ; + fates_phen_season_decid:units = "logical flag" ; + fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; + double fates_phen_stem_drop_fraction(fates_pft) ; + fates_phen_stem_drop_fraction:units = "fraction" ; + fates_phen_stem_drop_fraction:long_name = "fraction of stems to drop for non-woody species during drought/cold" ; + double fates_phen_stress_decid(fates_pft) ; + fates_phen_stress_decid:units = "logical flag" ; + fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; + double fates_prescribed_npp_canopy(fates_pft) ; + fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; + double fates_prescribed_npp_understory(fates_pft) ; + fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; + double fates_rad_leaf_clumping_index(fates_pft) ; + fates_rad_leaf_clumping_index:units = "fraction (0-1)" ; + fates_rad_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; + double fates_rad_leaf_rhonir(fates_pft) ; + fates_rad_leaf_rhonir:units = "fraction" ; + fates_rad_leaf_rhonir:long_name = "Leaf reflectance: near-IR" ; + double fates_rad_leaf_rhovis(fates_pft) ; + fates_rad_leaf_rhovis:units = "fraction" ; + fates_rad_leaf_rhovis:long_name = "Leaf reflectance: visible" ; + double fates_rad_leaf_taunir(fates_pft) ; + fates_rad_leaf_taunir:units = "fraction" ; + fates_rad_leaf_taunir:long_name = "Leaf transmittance: near-IR" ; + double fates_rad_leaf_tauvis(fates_pft) ; + fates_rad_leaf_tauvis:units = "fraction" ; + fates_rad_leaf_tauvis:long_name = "Leaf transmittance: visible" ; + double fates_rad_leaf_xl(fates_pft) ; + fates_rad_leaf_xl:units = "unitless" ; + fates_rad_leaf_xl:long_name = "Leaf/stem orientation index" ; + double fates_rad_stem_rhonir(fates_pft) ; + fates_rad_stem_rhonir:units = "fraction" ; + fates_rad_stem_rhonir:long_name = "Stem reflectance: near-IR" ; + double fates_rad_stem_rhovis(fates_pft) ; + fates_rad_stem_rhovis:units = "fraction" ; + fates_rad_stem_rhovis:long_name = "Stem reflectance: visible" ; + double fates_rad_stem_taunir(fates_pft) ; + fates_rad_stem_taunir:units = "fraction" ; + fates_rad_stem_taunir:long_name = "Stem transmittance: near-IR" ; + double fates_rad_stem_tauvis(fates_pft) ; + fates_rad_stem_tauvis:units = "fraction" ; + fates_rad_stem_tauvis:long_name = "Stem transmittance: visible" ; + double fates_recruit_height_min(fates_pft) ; + fates_recruit_height_min:units = "m" ; + fates_recruit_height_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; + double fates_recruit_init_density(fates_pft) ; + fates_recruit_init_density:units = "stems/m2" ; + fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation" ; + double fates_recruit_prescribed_rate(fates_pft) ; + fates_recruit_prescribed_rate:units = "n/yr" ; + fates_recruit_prescribed_rate:long_name = "recruitment rate for prescribed physiology mode" ; + double fates_recruit_seed_alloc(fates_pft) ; + fates_recruit_seed_alloc:units = "fraction" ; + fates_recruit_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; + double fates_recruit_seed_alloc_mature(fates_pft) ; + fates_recruit_seed_alloc_mature:units = "fraction" ; + fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; + double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; + fates_recruit_seed_dbh_repro_threshold:units = "cm" ; + fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter (if any) where the plant will start extra clonal allocation to the seed pool" ; + double fates_recruit_seed_germination_rate(fates_pft) ; + fates_recruit_seed_germination_rate:units = "yr-1" ; + fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; + double fates_recruit_seed_supplement(fates_pft) ; + fates_recruit_seed_supplement:units = "KgC/m2/yr" ; + fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; + double fates_seed_dispersal_param_A(fates_pft) ; + fates_seed_dispersal_param_A:units = "unitless" ; + fates_seed_dispersal_param_A:long_name = "seed dispersal scale parameter" ; + fates_seed_dispersal_param_A:use_case = "None" ; + double fates_seed_dispersal_param_B(fates_pft) ; + fates_seed_dispersal_param_B:units = "unitless" ; + fates_seed_dispersal_param_B:long_name = "seed dispersal shape parameter" ; + fates_seed_dispersal_param_B:use_case = "None" ; + double fates_stoich_nitr(fates_plant_organs, fates_pft) ; + fates_stoich_nitr:units = "gN/gC" ; + fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; + double fates_stoich_phos(fates_plant_organs, fates_pft) ; + fates_stoich_phos:units = "gP/gC" ; + fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; + double fates_trim_inc(fates_pft) ; + fates_trim_inc:units = "m2/m2" ; + fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; + double fates_trim_limit(fates_pft) ; + fates_trim_limit:units = "m2/m2" ; + fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; + double fates_turb_displar(fates_pft) ; + fates_turb_displar:units = "unitless" ; + fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; + double fates_turb_leaf_diameter(fates_pft) ; + fates_turb_leaf_diameter:units = "m" ; + fates_turb_leaf_diameter:long_name = "Characteristic leaf dimension" ; + double fates_turb_z0mr(fates_pft) ; + fates_turb_z0mr:units = "unitless" ; + fates_turb_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; + double fates_turnover_branch(fates_pft) ; + fates_turnover_branch:units = "yr" ; + fates_turnover_branch:long_name = "turnover time of branches" ; + double fates_turnover_fnrt(fates_pft) ; + fates_turnover_fnrt:units = "yr" ; + fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; + double fates_turnover_leaf(fates_leafage_class, fates_pft) ; + fates_turnover_leaf:units = "yr" ; + fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; + double fates_turnover_senleaf_fdrought(fates_pft) ; + fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; + fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; + double fates_wood_density(fates_pft) ; + fates_wood_density:units = "g/cm3" ; + fates_wood_density:long_name = "mean density of woody tissue in plant" ; + double fates_woody(fates_pft) ; + fates_woody:units = "logical flag" ; + fates_woody:long_name = "Binary woody lifeform flag" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_fire_FBD(fates_litterclass) ; + fates_fire_FBD:units = "kg Biomass/m3" ; + fates_fire_FBD:long_name = "fuel bulk density" ; + double fates_fire_low_moisture_Coeff(fates_litterclass) ; + fates_fire_low_moisture_Coeff:units = "NA" ; + fates_fire_low_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_low_moisture_Slope(fates_litterclass) ; + fates_fire_low_moisture_Slope:units = "NA" ; + fates_fire_low_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture(fates_litterclass) ; + fates_fire_mid_moisture:units = "NA" ; + fates_fire_mid_moisture:long_name = "spitfire litter moisture threshold to be considered medium dry" ; + double fates_fire_mid_moisture_Coeff(fates_litterclass) ; + fates_fire_mid_moisture_Coeff:units = "NA" ; + fates_fire_mid_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture_Slope(fates_litterclass) ; + fates_fire_mid_moisture_Slope:units = "NA" ; + fates_fire_mid_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_min_moisture(fates_litterclass) ; + fates_fire_min_moisture:units = "NA" ; + fates_fire_min_moisture:long_name = "spitfire litter moisture threshold to be considered very dry" ; + double fates_fire_SAV(fates_litterclass) ; + fates_fire_SAV:units = "cm-1" ; + fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; + double fates_frag_maxdecomp(fates_litterclass) ; + fates_frag_maxdecomp:units = "yr-1" ; + fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; + 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_base_mr_20 ; + fates_base_mr_20:units = "gC/gN/s" ; + fates_base_mr_20:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; + 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" ; + double fates_cnp_eca_plant_escalar ; + fates_cnp_eca_plant_escalar:units = "" ; + fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; + double fates_cohort_age_fusion_tol ; + fates_cohort_age_fusion_tol:units = "unitless" ; + fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; + double fates_cohort_size_fusion_tol ; + fates_cohort_size_fusion_tol:units = "unitless" ; + fates_cohort_size_fusion_tol:long_name = "minimum fraction in difference in dbh between cohorts" ; + double fates_comp_excln ; + fates_comp_excln:units = "none" ; + fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; + double fates_damage_canopy_layer_code ; + fates_damage_canopy_layer_code:units = "unitless" ; + fates_damage_canopy_layer_code:long_name = "Integer code that decides whether damage affects canopy trees (1), understory trees (2)" ; + double fates_damage_event_code ; + fates_damage_event_code:units = "unitless" ; + fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; + double fates_dev_arbitrary ; + fates_dev_arbitrary:units = "unknown" ; + fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; + double fates_fire_active_crown_fire ; + fates_fire_active_crown_fire:units = "0 or 1" ; + fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; + double fates_fire_cg_strikes ; + fates_fire_cg_strikes:units = "fraction (0-1)" ; + fates_fire_cg_strikes:long_name = "fraction of cloud to ground lightning strikes" ; + double fates_fire_drying_ratio ; + fates_fire_drying_ratio:units = "NA" ; + fates_fire_drying_ratio:long_name = "spitfire parameter, fire drying ratio for fuel moisture, alpha_FMC EQ 6 Thonicke et al 2010" ; + double fates_fire_durat_slope ; + fates_fire_durat_slope:units = "NA" ; + fates_fire_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; + double fates_fire_fdi_a ; + fates_fire_fdi_a:units = "NA" ; + fates_fire_fdi_a:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010" ; + double fates_fire_fdi_alpha ; + fates_fire_fdi_alpha:units = "NA" ; + fates_fire_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; + double fates_fire_fdi_b ; + fates_fire_fdi_b:units = "NA" ; + fates_fire_fdi_b:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010 " ; + double fates_fire_fuel_energy ; + fates_fire_fuel_energy:units = "kJ/kg" ; + fates_fire_fuel_energy:long_name = "spitfire parameter, heat content of fuel" ; + double fates_fire_max_durat ; + fates_fire_max_durat:units = "minutes" ; + fates_fire_max_durat:long_name = "spitfire parameter, fire maximum duration, Equation 14 Thonicke et al 2010" ; + double fates_fire_miner_damp ; + fates_fire_miner_damp:units = "NA" ; + fates_fire_miner_damp:long_name = "spitfire parameter, mineral-dampening coefficient EQ A1 Thonicke et al 2010 " ; + double fates_fire_miner_total ; + fates_fire_miner_total:units = "fraction" ; + fates_fire_miner_total:long_name = "spitfire parameter, total mineral content, Table A1 Thonicke et al 2010" ; + double fates_fire_nignitions ; + fates_fire_nignitions:units = "ignitions per year per km2" ; + fates_fire_nignitions:long_name = "number of annual ignitions per square km" ; + double fates_fire_part_dens ; + fates_fire_part_dens:units = "kg/m2" ; + fates_fire_part_dens:long_name = "spitfire parameter, oven dry particle density, Table A1 Thonicke et al 2010" ; + double fates_fire_threshold ; + fates_fire_threshold:units = "kW/m" ; + fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; + double fates_frag_cwd_fcel ; + fates_frag_cwd_fcel:units = "unitless" ; + fates_frag_cwd_fcel:long_name = "Cellulose fraction for CWD" ; + double fates_frag_cwd_flig ; + fates_frag_cwd_flig:units = "unitless" ; + fates_frag_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; + double fates_hydro_kmax_rsurf1 ; + fates_hydro_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; + double fates_hydro_kmax_rsurf2 ; + fates_hydro_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; + double fates_hydro_psi0 ; + fates_hydro_psi0:units = "MPa" ; + fates_hydro_psi0:long_name = "sapwood water potential at saturation" ; + double fates_hydro_psicap ; + fates_hydro_psicap:units = "MPa" ; + fates_hydro_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; + 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_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" ; + double fates_landuse_logging_collateral_frac ; + fates_landuse_logging_collateral_frac:units = "fraction" ; + fates_landuse_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; + double fates_landuse_logging_dbhmax ; + fates_landuse_logging_dbhmax:units = "cm" ; + fates_landuse_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; + double fates_landuse_logging_dbhmax_infra ; + fates_landuse_logging_dbhmax_infra:units = "cm" ; + fates_landuse_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; + double fates_landuse_logging_dbhmin ; + fates_landuse_logging_dbhmin:units = "cm" ; + fates_landuse_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; + double fates_landuse_logging_direct_frac ; + fates_landuse_logging_direct_frac:units = "fraction" ; + fates_landuse_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; + double fates_landuse_logging_event_code ; + fates_landuse_logging_event_code:units = "unitless" ; + fates_landuse_logging_event_code:long_name = "Integer code that options how logging events are structured" ; + double fates_landuse_logging_export_frac ; + fates_landuse_logging_export_frac:units = "fraction" ; + fates_landuse_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; + double fates_landuse_logging_mechanical_frac ; + fates_landuse_logging_mechanical_frac:units = "fraction" ; + fates_landuse_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; + double fates_landuse_pprodharv10_forest_mean ; + fates_landuse_pprodharv10_forest_mean:units = "fraction" ; + fates_landuse_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; + double fates_leaf_photo_temp_acclim_timescale ; + fates_leaf_photo_temp_acclim_timescale:units = "days" ; + fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; + double fates_leaf_photo_tempsens_model ; + fates_leaf_photo_tempsens_model:units = "unitless" ; + fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; + double fates_leaf_stomatal_assim_model ; + fates_leaf_stomatal_assim_model:units = "unitless" ; + fates_leaf_stomatal_assim_model:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; + double fates_leaf_stomatal_model ; + fates_leaf_stomatal_model:units = "unitless" ; + fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; + double fates_leaf_theta_cj_c3 ; + fates_leaf_theta_cj_c3:units = "unitless" ; + fates_leaf_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; + double fates_leaf_theta_cj_c4 ; + fates_leaf_theta_cj_c4:units = "unitless" ; + fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; + double fates_maintresp_model ; + fates_maintresp_model:units = "unitless" ; + fates_maintresp_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991) (NOT USED)" ; + double fates_maxcohort ; + fates_maxcohort:units = "count" ; + fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; + double fates_maxpatch_primary ; + fates_maxpatch_primary:units = "count" ; + fates_maxpatch_primary:long_name = "maximum number of primary vegetation patches per site" ; + double fates_maxpatch_secondary ; + fates_maxpatch_secondary:units = "count" ; + fates_maxpatch_secondary:long_name = "maximum number of secondary vegetation patches per site" ; + double fates_mort_disturb_frac ; + fates_mort_disturb_frac:units = "fraction" ; + fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; + double fates_mort_understorey_death ; + fates_mort_understorey_death:units = "fraction" ; + fates_mort_understorey_death:long_name = "fraction of plants in understorey cohort impacted by overstorey tree-fall" ; + double fates_patch_fusion_tol ; + fates_patch_fusion_tol:units = "unitless" ; + fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; + double fates_phen_chilltemp ; + fates_phen_chilltemp:units = "degrees C" ; + fates_phen_chilltemp:long_name = "chilling day counting threshold for vegetation" ; + double fates_phen_coldtemp ; + fates_phen_coldtemp:units = "degrees C" ; + fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; + double fates_phen_drought_model ; + fates_phen_drought_model:units = "unitless" ; + fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; + double fates_phen_drought_threshold ; + fates_phen_drought_threshold:units = "m3/m3 or mm" ; + fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_gddthresh_a ; + fates_phen_gddthresh_a:units = "none" ; + fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_b ; + fates_phen_gddthresh_b:units = "none" ; + fates_phen_gddthresh_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_c ; + fates_phen_gddthresh_c:units = "none" ; + fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_mindaysoff ; + fates_phen_mindaysoff:units = "days" ; + fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves became off-allometry" ; + double fates_phen_mindayson ; + fates_phen_mindayson:units = "days" ; + fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; + double fates_phen_moist_threshold ; + fates_phen_moist_threshold:units = "m3/m3 or mm" ; + fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_ncolddayslim ; + fates_phen_ncolddayslim:units = "days" ; + fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; + double fates_q10_froz ; + fates_q10_froz:units = "unitless" ; + fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; + double fates_q10_mr ; + fates_q10_mr:units = "unitless" ; + fates_q10_mr:long_name = "Q10 for maintenance respiration" ; + double fates_soil_salinity ; + fates_soil_salinity:units = "ppt" ; + fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; + double fates_vai_top_bin_width ; + fates_vai_top_bin_width:units = "m2/m2" ; + fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; + double fates_vai_width_increase_factor ; + fates_vai_width_increase_factor:units = "unitless" ; + fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; + +// global attributes: + :history = "This parameter file is maintained in version control\nSee https://github.com/NGEET/fates/blob/master/parameter_files/fates_params_default.cdl \nFor changes, use git blame \n" ; +data: + + fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; + + fates_history_coageclass_bin_edges = 0, 5 ; + + fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; + + fates_history_damage_bin_edges = 0, 80 ; + + fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, + 80, 90, 100 ; + + fates_alloc_organ_id = 1, 2, 3, 6 ; + + fates_hydro_htftype_node = 1, 1, 1, 1 ; + + fates_pftname = + "broadleaf_evergreen_tropical_tree ", + "needleleaf_evergreen_extratrop_tree ", + "needleleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_tree ", + "broadleaf_hydrodecid_tropical_tree ", + "broadleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_shrub ", + "broadleaf_hydrodecid_extratrop_shrub ", + "broadleaf_colddecid_extratrop_shrub ", + "arctic_c3_grass ", + "cool_c3_grass ", + "c4_grass " ; + + fates_hydro_organ_name = + "leaf ", + "stem ", + "transporting root ", + "absorbing root " ; + + fates_alloc_organ_name = + "leaf", + "fine root", + "sapwood", + "structure" ; + + fates_litterclass_name = + "twig ", + "small branch ", + "large branch ", + "trunk ", + "dead leaves ", + "live grass " ; + + 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, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; + + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + 1.2, 1.2, 1.2 ; + + fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8, 0.8 ; + + fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, + 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; + + fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, + 0.572, 0.572, 0.572, 0.572 ; + + fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, + 1.94, 1.94, 1.94 ; + + fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, + 0.931, 0.931, 0.931, 0.931 ; + + fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6 ; + + fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, + 0.95, 1, 1, 1 ; + + fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07 ; + + fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, + 1.3 ; + + fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, + 0.55, 0.55, 0.55 ; + + fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464 ; + + fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119 ; + + fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, + 0.64, 0.64, 0.64 ; + + fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, + 0.37, 0.37, 0.37 ; + + fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, + -999.9, -999.9, -999.9, -999.9, -999.9 ; + + fates_allom_dbh_maxheight = 90, 90, 90, 90, 90, 90, 3, 3, 2, 0.35, 0.35, 0.35 ; + + fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; + + fates_allom_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; + + fates_allom_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8 ; + + fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_zroot_k = 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 ; + + fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; + + fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + + fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 280, 280 ; + + fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, + 0.14, 0.14, 0.14 ; + + fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, + 0.27, 0.27, 0.27 ; + + fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_vmax_nh4 = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_eca_vmax_no3 = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_fnrt_adapt_tscale = 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100 ; + + fates_cnp_nfix1 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_rd_vmax_n = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_turnover_nitr_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_turnover_phos_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, + 5e-10, 5e-10, 5e-10, 5e-10 ; + + fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01 ; + + fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; + + fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, + 5.5, 5.5 ; + + fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2 ; + + fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07, 0.07 ; + + fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, + 0.775, 0.775, 0.775, 0.775, 0.775 ; + + fates_frag_fnrt_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_fnrt_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_fnrt_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_leaf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, + 0.51, 0.51, 0.51, 0.51 ; + + fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, + 0.11, 0.11 ; + + fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + 2.5, 2.5 ; + + fates_hydro_avuln_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_hydro_epsil_node = + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_hydro_fcap_node = + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_kmax_node = + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; + + fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + -1.5, -1.5, -1.5 ; + + fates_hydro_p50_node = + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25 ; + + fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, + 0.333, 0.333, 0.333, 0.333, 0.333 ; + + fates_hydro_pinot_node = + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; + + fates_hydro_pitlp_node = + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + -1.67, -1.67, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; + + fates_hydro_resid_node = + 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; + + fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + 0.625, 0.625, 0.625, 0.625, 0.625 ; + + fates_hydro_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, + 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; + + fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; + + fates_hydro_thetas_node = + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; + + fates_hydro_vg_alpha_node = + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005 ; + + fates_hydro_vg_m_node = + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_hydro_vg_n_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_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, + 43540, 43540, 43540, 43540 ; + + fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, + 152040, 152040, 152040, 152040, 152040 ; + + fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, + 495 ; + + fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, + 0.03, 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, + 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, + 10000, 10000, 10000, 10000, 10000, 40000 ; + + fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, + 4.7, 2.2, 5.3, 1.6 ; + + fates_leaf_vcmax25top = + 50, 65, 39, 62, 41, 58, 62, 54, 54, 78, 78, 78 ; + + fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, + 65330, 65330, 65330, 65330 ; + + fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, + 149250, 149250, 149250, 149250, 149250 ; + + fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, + 485 ; + + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; + + fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, + 0.014, 0.014, 0.014, 0.014 ; + + fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -60, -10, -80, -80, + -20, 2.5 ; + + fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, + 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; + + fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_prescribed_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, + 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; + + fates_mort_prescribed_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, + 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; + + fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_nonhydro_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, + -255000, -255000, -255000, -255000, -255000, -255000 ; + + fates_nonhydro_smpso = -66000, -66000, -66000, -66000, -66000, -66000, + -66000, -66000, -66000, -66000, -66000, -66000 ; + + fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; + + fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, + 0.5 ; + + fates_phen_fnrt_drop_frac = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; + + fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; + + fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, + 0.4, 0.4, 0.4 ; + + fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, + 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; + + fates_rad_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, + 0.9, 0.75, 0.75, 0.75 ; + + fates_rad_leaf_rhonir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, + 0.41, 0.28, 0.28, 0.28 ; + + fates_rad_leaf_rhovis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, + 0.08, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_taunir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, + 0.43, 0.4, 0.4, 0.4 ; + + fates_rad_leaf_tauvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, + 0.06, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, + -0.23, -0.23, -0.23 ; + + fates_rad_stem_rhonir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, + 0.49, 0.53, 0.53, 0.53 ; + + fates_rad_stem_rhovis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.31, 0.31, 0.31 ; + + fates_rad_stem_taunir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.25, 0.25, 0.25 ; + + fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.12, 0.12, 0.12 ; + + fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, + 0.125, 0.125, 0.125 ; + + fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2, 0.2, 0.2 ; + + fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, + 0.02, 0.02, 0.02, 0.02, 0.02 ; + + fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, + 0.9 ; + + fates_recruit_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, + 1.47, 1.47, 1.47 ; + + fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_seed_dispersal_param_A = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_seed_dispersal_param_B = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_stoich_nitr = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; + + fates_stoich_phos = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; + + fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, + 0.03, 0.03 ; + + fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; + + fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, + 0.67, 0.67, 0.67 ; + + fates_turb_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.04, 0.04, 0.04, 0.04 ; + + fates_turb_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, + 0.055, 0.055, 0.055, 0.055 ; + + fates_turnover_branch = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; + + fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_leaf = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, + 0.7 ; + + fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; + + fates_hlm_pft_map = + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + + fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; + + fates_fire_low_moisture_Coeff = 1.12, 1.09, 0.98, 0.8, 1.15, 1.15 ; + + fates_fire_low_moisture_Slope = 0.62, 0.72, 0.85, 0.8, 0.62, 0.62 ; + + fates_fire_mid_moisture = 0.72, 0.51, 0.38, 1, 0.8, 0.8 ; + + fates_fire_mid_moisture_Coeff = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_mid_moisture_Slope = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_min_moisture = 0.18, 0.12, 0, 0, 0.24, 0.24 ; + + fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; + + fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; + + fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; + + fates_base_mr_20 = 2.52e-06 ; + + fates_canopy_closure_thresh = 0.8 ; + + fates_cnp_eca_plant_escalar = 1.25e-05 ; + + fates_cohort_age_fusion_tol = 0.08 ; + + fates_cohort_size_fusion_tol = 0.08 ; + + fates_comp_excln = 3 ; + + fates_damage_canopy_layer_code = 1 ; + + fates_damage_event_code = 1 ; + + fates_dev_arbitrary = _ ; + + fates_fire_active_crown_fire = 0 ; + + fates_fire_cg_strikes = 0.2 ; + + fates_fire_drying_ratio = 66000 ; + + fates_fire_durat_slope = -11.06 ; + + fates_fire_fdi_a = 17.62 ; + + fates_fire_fdi_alpha = 0.00037 ; + + fates_fire_fdi_b = 243.12 ; + + fates_fire_fuel_energy = 18000 ; + + fates_fire_max_durat = 240 ; + + fates_fire_miner_damp = 0.41739 ; + + fates_fire_miner_total = 0.055 ; + + fates_fire_nignitions = 15 ; + + fates_fire_part_dens = 513 ; + + fates_fire_threshold = 50 ; + + fates_frag_cwd_fcel = 0.76 ; + + fates_frag_cwd_flig = 0.24 ; + + fates_hydro_kmax_rsurf1 = 20 ; + + fates_hydro_kmax_rsurf2 = 0.0001 ; + + fates_hydro_psi0 = 0 ; + + fates_hydro_psicap = -0.6 ; + + fates_hydro_solver = 1 ; + + fates_landuse_logging_coll_under_frac = 0.55983 ; + + fates_landuse_logging_collateral_frac = 0.05 ; + + fates_landuse_logging_dbhmax = _ ; + + fates_landuse_logging_dbhmax_infra = 35 ; + + fates_landuse_logging_dbhmin = 50 ; + + fates_landuse_logging_direct_frac = 0.15 ; + + fates_landuse_logging_event_code = -30 ; + + fates_landuse_logging_export_frac = 0.8 ; + + fates_landuse_logging_mechanical_frac = 0.05 ; + + fates_landuse_pprodharv10_forest_mean = 0.8125 ; + + fates_leaf_photo_temp_acclim_timescale = 30 ; + + fates_leaf_photo_tempsens_model = 1 ; + + fates_leaf_stomatal_assim_model = 1 ; + + fates_leaf_stomatal_model = 1 ; + + fates_leaf_theta_cj_c3 = 0.999 ; + + fates_leaf_theta_cj_c4 = 0.999 ; + + fates_maintresp_model = 1 ; + + fates_maxcohort = 100 ; + + fates_maxpatch_primary = 10 ; + + fates_maxpatch_secondary = 4 ; + + fates_mort_disturb_frac = 1 ; + + fates_mort_understorey_death = 0.55983 ; + + fates_patch_fusion_tol = 0.05 ; + + fates_phen_chilltemp = 5 ; + + fates_phen_coldtemp = 7.5 ; + + fates_phen_drought_model = 0 ; + + fates_phen_drought_threshold = 0.15 ; + + fates_phen_gddthresh_a = -68 ; + + fates_phen_gddthresh_b = 638 ; + + fates_phen_gddthresh_c = -0.01 ; + + fates_phen_mindaysoff = 100 ; + + fates_phen_mindayson = 90 ; + + fates_phen_moist_threshold = 0.18 ; + + fates_phen_ncolddayslim = 5 ; + + fates_q10_froz = 1.5 ; + + fates_q10_mr = 1.5 ; + + fates_soil_salinity = 0.4 ; + + fates_vai_top_bin_width = 1 ; + + fates_vai_width_increase_factor = 1 ; +} From e85f4f21e4affe33331e048339a1c56756ce3ac8 Mon Sep 17 00:00:00 2001 From: ckoven Date: Wed, 26 Oct 2022 12:44:45 -0600 Subject: [PATCH 395/852] fixed typo on woody logic --- biogeochem/EDCohortDynamicsMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 8d995fdf1f..d2c153f575 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -970,7 +970,7 @@ subroutine SendCohortToLitter(csite,cpatch,ccohort,nplant,bc_in) store_m = ccohort%prt%GetState(store_organ, element_list(el)) fnrt_m = ccohort%prt%GetState(fnrt_organ, element_list(el)) repro_m = ccohort%prt%GetState(repro_organ, element_list(el)) - if (prt_params%woody(currentCohort%pft) == itrue) then + if (prt_params%woody(ccohort%pft) == itrue) then leaf_m = ccohort%prt%GetState(leaf_organ, element_list(el)) sapw_m = ccohort%prt%GetState(sapw_organ, element_list(el)) struct_m = ccohort%prt%GetState(struct_organ, element_list(el)) From 1fb522068614c2840e2f5c2178328e29ac8f70ab Mon Sep 17 00:00:00 2001 From: Shijie Shu Date: Wed, 26 Oct 2022 15:06:19 -0700 Subject: [PATCH 396/852] Remove "available_forest_c" and simplify the logic. --- biogeochem/EDLoggingMortalityMod.F90 | 33 +++++++------------------- biogeochem/EDMortalityFunctionsMod.F90 | 4 +--- biogeochem/EDPatchDynamicsMod.F90 | 12 ++++------ main/EDMainMod.F90 | 5 ++-- 4 files changed, 15 insertions(+), 39 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 2f02a7d3bf..79adc81838 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -203,7 +203,7 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & hlm_harvest_units, & patch_anthro_disturbance_label, secondary_age, & frac_site_primary, harvestable_forest_c, & - available_forest_c, harvest_tag) + harvest_tag) ! Arguments integer, intent(in) :: pft_i ! pft index @@ -216,8 +216,6 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & real(r8), intent(in) :: secondary_age ! patch level age_since_anthro_disturbance real(r8), intent(in) :: harvestable_forest_c(:) ! total harvestable forest carbon ! of all hlm harvest categories - real(r8), intent(in) :: available_forest_c(:) ! total forest carbon available for - ! harvest of all hlm harvest categories real(r8), intent(in) :: frac_site_primary real(r8), intent(out) :: lmort_direct ! direct (harvestable) mortality fraction real(r8), intent(out) :: lmort_collateral ! collateral damage mortality fraction @@ -282,12 +280,12 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & ! shall call another subroutine, which transfers biomass/carbon into fraction call get_harvest_rate_carbon (patch_anthro_disturbance_label, hlm_harvest_catnames, & - hlm_harvest_rates, secondary_age, harvestable_forest_c, available_forest_c, & + hlm_harvest_rates, secondary_age, harvestable_forest_c, & harvest_rate, harvest_tag, cur_harvest_tag) if (fates_global_verbose()) then write(fates_log(), *) 'Successfully Read Harvest Rate from HLM.', hlm_harvest_rates(:), harvest_rate & - harvestable_forest_c, available_forest_c + harvestable_forest_c end if write(fates_log(),*) 'HLM harvest carbon data not implemented yet. Exiting.' @@ -435,7 +433,7 @@ end subroutine get_harvest_rate_area ! ============================================================================ - subroutine get_harvestable_carbon (csite, site_area, hlm_harvest_catnames, harvestable_forest_c, available_forest_c) + subroutine get_harvestable_carbon (csite, site_area, hlm_harvest_catnames, harvestable_forest_c ) !USES: use SFParamsMod, only : SF_val_cwd_frac @@ -461,7 +459,6 @@ subroutine get_harvestable_carbon (csite, site_area, hlm_harvest_catnames, harve character(len=64), intent(in) :: hlm_harvest_catnames(:) ! names of hlm harvest categories real(r8), intent(out) :: harvestable_forest_c(hlm_num_lu_harvest_cats) - real(r8), intent(out) :: available_forest_c(hlm_num_lu_harvest_cats) ! Local Variables type(ed_patch_type), pointer :: currentPatch @@ -477,7 +474,6 @@ subroutine get_harvestable_carbon (csite, site_area, hlm_harvest_catnames, harve ! Initialization harvestable_forest_c = 0._r8 - available_forest_c = 0._r8 ! loop over patches currentPatch => csite%oldest_patch @@ -526,21 +522,18 @@ subroutine get_harvestable_carbon (csite, site_area, hlm_harvest_catnames, harve ! Primary if(hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1") then harvestable_forest_c(h_index) = harvestable_forest_c(h_index) + harvestable_patch_c - available_forest_c(h_index) = available_forest_c(h_index) + available_patch_c end if else if (currentPatch%anthro_disturbance_label .eq. secondaryforest .and. & currentPatch%age_since_anthro_disturbance >= secondary_age_threshold) then ! Secondary mature if(hlm_harvest_catnames(h_index) .eq. "HARVEST_SH1") then harvestable_forest_c(h_index) = harvestable_forest_c(h_index) + harvestable_patch_c - available_forest_c(h_index) = available_forest_c(h_index) + available_patch_c end if else if (currentPatch%anthro_disturbance_label .eq. secondaryforest .and. & currentPatch%age_since_anthro_disturbance < secondary_age_threshold) then ! Secondary young if(hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2") then harvestable_forest_c(h_index) = harvestable_forest_c(h_index) + harvestable_patch_c - available_forest_c(h_index) = available_forest_c(h_index) + available_patch_c end if end if end do @@ -552,7 +545,7 @@ end subroutine get_harvestable_carbon ! ============================================================================ subroutine get_harvest_rate_carbon (patch_anthro_disturbance_label, hlm_harvest_catnames, & - hlm_harvest_rates, secondary_age, harvestable_forest_c, available_forest_c, & + hlm_harvest_rates, secondary_age, harvestable_forest_c, & harvest_rate, harvest_tag, cur_harvest_tag) ! ------------------------------------------------------------------------------------------- @@ -567,7 +560,6 @@ subroutine get_harvest_rate_carbon (patch_anthro_disturbance_label, hlm_harvest_ integer, intent(in) :: patch_anthro_disturbance_label ! patch level anthro_disturbance_label real(r8), intent(in) :: secondary_age ! patch level age_since_anthro_disturbance real(r8), intent(in) :: harvestable_forest_c(:) ! site level forest c matching criteria available for harvest - real(r8), intent(in) :: available_forest_c(:) ! site level total forest c available for harvest real(r8), intent(out) :: harvest_rate integer, intent(inout) :: harvest_tag(:) ! 0. normal harvest; 1. current site does not have enough C but ! can perform harvest by ignoring criteria; 2. current site does @@ -600,11 +592,8 @@ subroutine get_harvest_rate_carbon (patch_anthro_disturbance_label, hlm_harvest_ if(harvestable_forest_c(h_index) >= harvest_rate_c) then harvest_rate_supply = harvest_rate_supply + harvestable_forest_c(h_index) harvest_tag(h_index) = 0 - else if (available_forest_c(h_index) >= harvest_rate_c) then - harvest_rate_supply = harvest_rate_supply + available_forest_c(h_index) - harvest_tag(h_index) = 1 else - harvest_tag(h_index) = 2 + harvest_tag(h_index) = 1 end if endif else if (patch_anthro_disturbance_label .eq. secondaryforest .and. & @@ -614,11 +603,8 @@ subroutine get_harvest_rate_carbon (patch_anthro_disturbance_label, hlm_harvest_ if(harvestable_forest_c(h_index) >= harvest_rate_c) then harvest_rate_supply = harvest_rate_supply + harvestable_forest_c(h_index) harvest_tag(h_index) = 0 - else if (available_forest_c(h_index) >= harvest_rate_c) then - harvest_rate_supply = harvest_rate_supply + available_forest_c(h_index) - harvest_tag(h_index) = 1 else - harvest_tag(h_index) = 2 + harvest_tag(h_index) = 1 end if endif else if (patch_anthro_disturbance_label .eq. secondaryforest .and. & @@ -629,11 +615,8 @@ subroutine get_harvest_rate_carbon (patch_anthro_disturbance_label, hlm_harvest_ if(harvestable_forest_c(h_index) >= harvest_rate_c) then harvest_rate_supply = harvest_rate_supply + harvestable_forest_c(h_index) harvest_tag(h_index) = 0 - else if (available_forest_c(h_index) >= harvest_rate_c) then - harvest_rate_supply = harvest_rate_supply + available_forest_c(h_index) - harvest_tag(h_index) = 1 else - harvest_tag(h_index) = 2 + harvest_tag(h_index) = 1 end if endif endif diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index 45b86adb68..5ab67a04bf 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -216,7 +216,7 @@ end subroutine mortality_rates ! ============================================================================ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_primary, & - harvestable_forest_c, available_forest_c, harvest_tag) + harvestable_forest_c, harvest_tag) ! ! !DESCRIPTION: @@ -233,7 +233,6 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_pr type(bc_in_type), intent(in) :: bc_in real(r8), intent(in) :: frac_site_primary real(r8), intent(in) :: harvestable_forest_c(:) - real(r8), intent(in) :: available_forest_c(:) integer, intent(inout) :: harvest_tag(:) ! @@ -266,7 +265,6 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_pr currentCohort%patchptr%age_since_anthro_disturbance, & frac_site_primary, & harvestable_forest_c, & - available_forest_c, & harvest_tag) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 6fd42101af..6e88e6cf08 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -196,7 +196,6 @@ subroutine disturbance_rates( site_in, bc_in) real(r8) :: harvest_rate real(r8) :: tempsum real(r8) :: harvestable_forest_c(hlm_num_lu_harvest_cats) - real(r8) :: available_forest_c(hlm_num_lu_harvest_cats) integer :: harvest_tag(hlm_num_lu_harvest_cats) integer :: harvest_debt_primary integer :: harvest_debt_secondary @@ -211,7 +210,7 @@ subroutine disturbance_rates( site_in, bc_in) call get_frac_site_primary(site_in, frac_site_primary) ! get available biomass for harvest for all patches - call get_harvestable_carbon(site_in, bc_in%site_area, bc_in%hlm_harvest_catnames, harvestable_forest_c, available_forest_c) + call get_harvestable_carbon(site_in, bc_in%site_area, bc_in%hlm_harvest_catnames, harvestable_forest_c) site_in%harvest_carbon_flux = 0._r8 harvest_debt_primary = 0 @@ -248,7 +247,6 @@ subroutine disturbance_rates( site_in, bc_in) currentPatch%age_since_anthro_disturbance, & frac_site_primary, & harvestable_forest_c, & - available_forest_c, & harvest_tag) currentCohort%lmort_direct = lmort_direct @@ -282,8 +280,7 @@ subroutine disturbance_rates( site_in, bc_in) ! Primary patch: Once a patch has debt, skip the calculation if (harvest_debt_primary == 0) then if ( currentPatch%anthro_disturbance_label .eq. primaryforest ) then - if ( harvest_tag(h_index) == 2 .or. & - (harvest_tag(h_index) == 1 )) then + if ( harvest_tag(h_index) == 1 ) then ! h_index points to primary forest harvest if((bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1")) then harvest_debt_primary = 1 @@ -296,8 +293,7 @@ subroutine disturbance_rates( site_in, bc_in) if (harvest_debt_secondary == 0) then if ( currentPatch%anthro_disturbance_label .eq. secondaryforest ) then patch_no_secondary = patch_no_secondary + 1 - if ( harvest_tag(h_index) == 2 .or. & - (harvest_tag(h_index) == 1 )) then + if ( harvest_tag(h_index) == 1 ) then ! h_index points to secondary forest harvest if((bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH1") .or. & (bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2")) then @@ -410,7 +406,7 @@ subroutine disturbance_rates( site_in, bc_in) if(bc_in%hlm_harvest_units == hlm_harvest_carbon) then call get_harvest_rate_carbon (currentPatch%anthro_disturbance_label, bc_in%hlm_harvest_catnames, & bc_in%hlm_harvest_rates, currentPatch%age_since_anthro_disturbance, harvestable_forest_c, & - available_forest_c, harvest_rate, harvest_tag) + harvest_rate, harvest_tag) else call get_harvest_rate_area (currentPatch%anthro_disturbance_label, bc_in%hlm_harvest_catnames, & bc_in%hlm_harvest_rates, frac_site_primary, currentPatch%age_since_anthro_disturbance, harvest_rate) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 790e5dc12e..fa62058bcf 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -336,7 +336,6 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) real(r8) :: frac_site_primary real(r8) :: harvestable_forest_c(hlm_num_lu_harvest_cats) - real(r8) :: available_forest_c(hlm_num_lu_harvest_cats) integer :: harvest_tag(hlm_num_lu_harvest_cats) @@ -347,7 +346,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) bc_out%ar_site = 0._r8 ! Patch level biomass are required for C-based harvest - call get_harvestable_carbon(currentSite, bc_in%site_area, bc_in%hlm_harvest_catnames, harvestable_forest_c, available_forest_c) + call get_harvestable_carbon(currentSite, bc_in%site_area, bc_in%hlm_harvest_catnames, harvestable_forest_c) ! Set a pointer to this sites carbon12 mass balance site_cmass => currentSite%mass_balance(element_pos(carbon12_element)) @@ -383,7 +382,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! Calculate the mortality derivatives call Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_primary, & - harvestable_forest_c, available_forest_c, harvest_tag) + harvestable_forest_c, harvest_tag ) ! ----------------------------------------------------------------------------- ! Apply Plant Allocation and Reactive Transport From cfe1d96c4890b0f27d46bc15282da88763c76694 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 27 Oct 2022 14:02:39 -0700 Subject: [PATCH 397/852] add google group outreach message to README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 05952078c8..3129042304 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ For more information on the FATES model, see our [User's Guide](https://fates-us Please submit any questions you may have to the [FATES Github Discussions board](https://github.com/NGEET/fates/discussions). +To receive email updates about forthcoming release tags, regular meeting notifications, and other important announcements, please join the [FATES Google group](https://groups.google.com/g/fates_model). + ## Important Guides: ------------------------------ From 616da60859e8f04d2d30565eed065ee0ab764b6e Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 27 Oct 2022 15:01:26 -0700 Subject: [PATCH 398/852] add no history output option to FatesPFTIndexSwapper and modify_fates_paramfile call --- tools/BatchPatchParams.py | 6 +++--- tools/FatesPFTIndexSwapper.py | 14 +++++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/tools/BatchPatchParams.py b/tools/BatchPatchParams.py index b3d59d940b..3eedc6224d 100755 --- a/tools/BatchPatchParams.py +++ b/tools/BatchPatchParams.py @@ -69,12 +69,12 @@ def parse_syscall_str(fnamein,fnameout,pft_index,param_name,param_val): if(pft_index==0): sys_call_str = "../tools/modify_fates_paramfile.py"+" --fin " + fnamein + \ " --fout " + fnameout + " --var " + param_name + " --silent " +\ - " --val " + "\" "+param_val+"\"" + " --overwrite --all" + " --val " + "\" "+param_val+"\"" + " --nohist --overwrite --all" else: pft_str_index="{}".format(pft_index) sys_call_str = "../tools/modify_fates_paramfile.py"+" --fin " + fnamein + \ " --fout " + fnameout + " --var " + param_name + " --silent " +\ - " --val " + "\" "+param_val+"\"" + " --overwrite --pft "+pft_str_index + " --val " + "\" "+param_val+"\"" + " --nohist --overwrite --pft "+pft_str_index if(debug): print(sys_call_str) @@ -111,7 +111,7 @@ def main(): # Use FatesPFTIndexSwapper.py to prune out unwanted PFTs pft_trim_list = xmlroot.find('pft_trim_list').text.replace(" ","") - swapcmd="../tools/FatesPFTIndexSwapper.py --pft-indices="+pft_trim_list+" --fin="+base_nc+" --fout="+new_nc #+" 1>/dev/null" + swapcmd="../tools/FatesPFTIndexSwapper.py --pft-indices="+pft_trim_list+" --fin="+base_nc+" --fout="+new_nc+" --nohist" #+" 1>/dev/null" os.system(swapcmd) # We open the new parameter file. We only use this diff --git a/tools/FatesPFTIndexSwapper.py b/tools/FatesPFTIndexSwapper.py index e1a71d4334..5e8772b5a9 100755 --- a/tools/FatesPFTIndexSwapper.py +++ b/tools/FatesPFTIndexSwapper.py @@ -86,8 +86,9 @@ def interp_args(argv): output_fname = "none" donor_pft_indices = -9 donot_pft_indices_str = '' + histflag = True try: - opts, args = getopt.getopt(argv, 'h',["fin=","fout=","pft-indices="]) + opts, args = getopt.getopt(argv, 'h',["fin=","fout=","pft-indices=","nohist"]) except getopt.GetoptError as err: print('Argument error, see usage') usage() @@ -103,6 +104,8 @@ def interp_args(argv): output_fname = a elif o in ("--pft-indices"): donor_pft_indices_str = a.strip() + elif o in ("--nohist"): + histflag = False else: assert False, "unhandled option" @@ -127,7 +130,7 @@ def interp_args(argv): donor_pft_indices.append(int(strpft)) - return (input_fname,output_fname,donor_pft_indices) + return (input_fname,output_fname,donor_pft_indices,histflag) # ======================================================================================== @@ -139,7 +142,7 @@ def interp_args(argv): def main(argv): # Interpret the arguments to the script - [input_fname,output_fname,donor_pft_indices] = interp_args(argv) + [input_fname,output_fname,donor_pft_indices,histflag] = interp_args(argv) num_pft_out = len(donor_pft_indices) @@ -252,8 +255,9 @@ def main(argv): out_var.units = in_var.units out_var.long_name = in_var.long_name - fp_out.history = "This file was made from FatesPFTIndexSwapper.py \n Input File = {} \n Indices = {}"\ - .format(input_fname,donor_pft_indices) + if(histflag): + fp_out.history = "This file was made from FatesPFTIndexSwapper.py \n Input File = {} \n Indices = {}"\ + .format(input_fname,donor_pft_indices) #var_out.mode = var.mode #fp.flush() From e0c8ab932d78f4db87b1682225ad7571dcd54e16 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 27 Oct 2022 17:12:19 -0700 Subject: [PATCH 399/852] remove dead code and add custom history output --- tools/BatchPatchParams.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/tools/BatchPatchParams.py b/tools/BatchPatchParams.py index 3eedc6224d..fbe322d8fe 100755 --- a/tools/BatchPatchParams.py +++ b/tools/BatchPatchParams.py @@ -96,7 +96,7 @@ def main(): #[base_cdl,new_cdl,pftlist,paramlist] = load_xml(args.xmlfile) xmlroot = et.parse(args.xmlfile).getroot() - print("\nOpenend: "+args.xmlfile) + print("\nOpened: "+args.xmlfile) base_cdl = xmlroot.find('base_file').text new_cdl = xmlroot.find('new_file').text @@ -114,10 +114,6 @@ def main(): swapcmd="../tools/FatesPFTIndexSwapper.py --pft-indices="+pft_trim_list+" --fin="+base_nc+" --fout="+new_nc+" --nohist" #+" 1>/dev/null" os.system(swapcmd) - # We open the new parameter file. We only use this - # to do some dimension checking. - fp_nc = netcdf.netcdf_file(base_nc, 'r') - # On subsequent parameters, overwrite the file paramroot = xmlroot.find('parameters') @@ -182,9 +178,22 @@ def main(): # Dump the new file to the cdl os.system("ncdump "+newer_nc+" > "+new_cdl) - + + # Generate ncfile and append history + final_nc = new_cdl.replace('.cdl','.nc') + gencmd = "ncgen -o "+final_nc+" "+new_cdl + os.system(gencmd) + fp_nc = netcdf.netcdf_file(final_nc, 'a') + fp_nc.history = "This file was generated by BatchPatchParams.py:\n"\ + "CDL Base File = {}\n"\ + "XML patch file = {}"\ + .format(base_cdl,args.xmlfile) fp_nc.close() + # Re-generate the cdl file + os.system("ncdump "+final_nc+" > "+new_cdl) + + print("\nBatch parameter transfer complete\n") print("\nGenerated: {}\n".format(new_cdl)) From d491d8f04cf444ad7f07eb8b24a922e508110afe Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 28 Oct 2022 13:57:21 -0700 Subject: [PATCH 400/852] add pft dependent dispersal calls and correct error in parameter calls --- main/EDPftvarcon.F90 | 12 ++++++------ main/FatesDispersalMod.F90 | 32 ++++++++++++++++---------------- main/FatesInterfaceMod.F90 | 9 +++++---- tools/ModifyParams.sh | 35 ----------------------------------- 4 files changed, 27 insertions(+), 61 deletions(-) delete mode 100644 tools/ModifyParams.sh diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index a911d4a97d..213d9f7993 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1442,8 +1442,8 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'jmaxse = ',EDPftvarcon_inst%jmaxse write(fates_log(),fmt0) 'germination_timescale = ',EDPftvarcon_inst%germination_rate write(fates_log(),fmt0) 'seed_decay_turnover = ',EDPftvarcon_inst%seed_decay_rate - write(fates_log(),fmt0) 'seed_decay_turnover = ',EDPftvarcon_inst%seed_dispersal_param_B - write(fates_log(),fmt0) 'seed_decay_turnover = ',EDPftvarcon_inst%seed_dispersal_param_B + write(fates_log(),fmt0) 'seed_dispersal_param_A = ',EDPftvarcon_inst%seed_dispersal_param_A + write(fates_log(),fmt0) 'seed_dispersal_param_B = ',EDPftvarcon_inst%seed_dispersal_param_B write(fates_log(),fmt0) 'trim_limit = ',EDPftvarcon_inst%trim_limit write(fates_log(),fmt0) 'trim_inc = ',EDPftvarcon_inst%trim_inc write(fates_log(),fmt0) 'rhol = ',EDPftvarcon_inst%rhol @@ -1631,8 +1631,8 @@ subroutine FatesCheckParams(is_master) ! Check that parameter ranges for the seed dispersal scale parameter make sense !----------------------------------------------------------------------------------- - if ( ( EDPftvarcon_inst%fates_seed_dispersal_param_A(ipft) < fates_check_param_set ) .and. & - ( EDPftvarcon_inst%fates_seed_dispersal_param_B(ipft) > fates_check_param_set ) ) then + if ( ( EDPftvarcon_inst%seed_dispersal_param_A(ipft) < fates_check_param_set ) .and. & + ( EDPftvarcon_inst%seed_dispersal_param_B(ipft) > fates_check_param_set ) ) then write(fates_log(),*) 'Seed dispersal is on' write(fates_log(),*) 'Please also set fates_seed_dispersal_param_B' @@ -1643,8 +1643,8 @@ subroutine FatesCheckParams(is_master) ! Check that parameter ranges for the seed dispersal shape parameter make sense !----------------------------------------------------------------------------------- - if ( ( EDPftvarcon_inst%fates_seed_dispersal_param_B(ipft) < fates_check_param_set ) .and. & - ( EDPftvarcon_inst%fates_seed_dispersal_param_A(ipft) > fates_check_param_set ) ) then + if ( ( EDPftvarcon_inst%seed_dispersal_param_B(ipft) < fates_check_param_set ) .and. & + ( EDPftvarcon_inst%seed_dispersal_param_A(ipft) > fates_check_param_set ) ) then write(fates_log(),*) 'Seed dispersal is on' write(fates_log(),*) 'Please also set fates_seed_dispersal_param_A' diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index 7628ef5541..75bb55f539 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -67,7 +67,9 @@ subroutine init(this, numprocs, numpft) integer, intent(in) :: numpft ! Check if seed dispersal mode is 'turned on' by checking the parameter values - if (EDPftvarcon_inst%fates_seed_dispersal_param_A(ipft) > fates_check_param_set) return + ! This assumes we consistency in the parameter file across all pfts, i.e. either + ! all 'on' or all 'off' + if (EDPftvarcon_inst%seed_dispersal_param_A(1) > fates_check_param_set) return allocate(this%outgoing_local(numprocs,numpft)) allocate(this%outgoing_global(numprocs,numpft)) @@ -105,11 +107,11 @@ subroutine ProbabilityDensity(pd, ipft, dist) select case(hlm_dispersal_kernel_mode) case (hlm_dispersal_kernel_exponential) - pd = PD_exponential(dist) + pd = PD_exponential(dist,ipft) case (hlm_dispersal_kernel_exppower) - pd = PD_exppower(dist) + pd = PD_exppower(dist,ipft) case (hlm_dispersal_kernel_logsech) - pd = PD_logsech(dist) + pd = PD_logsech(dist,ipft) case default write(fates_log(),*) 'ERROR: An undefined dispersal kernel was specified: ', hlm_dispersal_kernel_mode call endrun(msg=errMsg(sourcefile, __LINE__)) @@ -119,13 +121,13 @@ end subroutine ProbabilityDensity ! ==================================================================================== - real(r8) function PD_exponential(dist) + real(r8) function PD_exponential(dist, ipft) use EDPftvarcon , only : EDPftvarcon_inst ! Arguments real(r8), intent(in) :: dist - ! real(r8), intent(in) :: param_a + integer, intent(in) :: ipft ! Assuming simple exponential decay. In the future perhaps this could be an interface ! for different weight calculations (and could be held only in fates) @@ -136,18 +138,17 @@ end function PD_exponential ! ==================================================================================== - real(r8) function PD_exppower(dist,param_a,param_b) + real(r8) function PD_exppower(dist, ipft) use EDPftvarcon , only : EDPftvarcon_inst ! Arguments real(r8), intent(in) :: dist - ! real(r8), intent(in) :: param_a - ! real(r8), intent(in) :: param_b + integer, intent(in) :: ipft associate(& - param_a => EDPftvarcon_inst%seed_dispersal_param_A, & - param_b => EDPftvarcon_inst%seed_dispersal_param_B) + param_a => EDPftvarcon_inst%seed_dispersal_param_A(ipft), & + param_b => EDPftvarcon_inst%seed_dispersal_param_B(ipft)) PD_exppower = (param_b / (2*pi_const*gamma(2/param_b))) * & exp(-(dist**param_b)/(param_a**param_b)) @@ -158,18 +159,17 @@ end function PD_exppower ! ==================================================================================== - real(r8) function PD_logsech(dist) + real(r8) function PD_logsech(dist, ipft) use EDPftvarcon , only : EDPftvarcon_inst ! Arguments real(r8), intent(in) :: dist - ! real(r8), intent(in) :: param_a - ! real(r8), intent(in) :: param_b + integer, intent(in) :: ipft associate(& - param_a => EDPftvarcon_inst%seed_dispersal_param_A, & - param_b => EDPftvarcon_inst%seed_dispersal_param_B) + param_a => EDPftvarcon_inst%seed_dispersal_param_A(ipft), & + param_b => EDPftvarcon_inst%seed_dispersal_param_B(ipft)) PD_logsech = (1/(pi_const**2 * param_b * dist**2)) / & ((dist/param_a)**(1/param_b) + & diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 67df6b721b..79ec8a5666 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1910,7 +1910,7 @@ subroutine DetermineGridCellNeighbors(neighbors) type (neighbor_type), pointer :: current_neighbor type (neighbor_type), pointer :: another_neighbor - integer :: gi,gj ! indices + integer :: i, gi,gj ! indices integer :: numg ! number of land gridcells integer :: ngcheck ! number of land gridcells, globally integer :: numproc ! number of processors, globally @@ -1922,15 +1922,16 @@ subroutine DetermineGridCellNeighbors(neighbors) real(r8), allocatable :: gclat(:), gclon(:) real(r8) :: g2g_dist ! grid cell distance + real(r8) :: g2g_dist_max ! grid cell distance real(r8) :: pdf ! temp ! Check if seed dispersal mode is 'turned on' by checking the parameter values - if (EDPftvarcon_inst%fates_seed_dispersal_param_A(ipft) > fates_check_param_set) return + if (EDPftvarcon_inst%seed_dispersal_param_A(1) > fates_check_param_set) return ! Parameters and constants, to be moved to fates param file ! Both of these should probably be per pft ! real(r8) :: decay_rate = 1._r8 - real(r8) :: g2g_dist_max = 2500._r8 * 1000._r8 ! maximum search distance [m] + g2g_dist_max = 2500._r8 * 1000._r8 ! maximum search distance [m] ! 5 deg = 785.8 km, 10 deg = 1569 km, 15deg = 2345 km assumes cartesian layout with diagonal distance ! Allocate array neighbor type @@ -2004,7 +2005,7 @@ subroutine DetermineGridCellNeighbors(neighbors) allocate(current_neighbor%density_prob(numpft)) do ipft = 1, numpft - call ProbabilityDensity(pdf, ifpt, g2g_dist) + call ProbabilityDensity(pdf, ipft, g2g_dist) current_neighbor%density_prob(ipft) = pdf end do diff --git a/tools/ModifyParams.sh b/tools/ModifyParams.sh deleted file mode 100644 index bf52a181d2..0000000000 --- a/tools/ModifyParams.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/sh -# Put in ~/global/scratch/users/yanlanliu/E3SM/components/elm/src/external_models/fates/tools -cp fates_parameter_default.nc fates_params_seednew_bkp.nc - -./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_recruit_initd --value 0.0 --allPFTs - -./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_recruit_initd --value 0.4 --pft 7 - -./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_recruit_initd --value 0.4 --pft 9 - -./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_recruit_initd --value 0.4 --pft 10 - - -./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_seed_alloc --value 0.3 --pft 7 - -./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_seed_alloc --value 0.3 --pft 9 - -./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_seed_alloc --value 0.3 --pft 10 - -./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_seed_alloc_mature --value 0.7 --pft 7 - -./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_seed_alloc_mature --value 0.7 --pft 9 - -./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_seed_alloc_mature --value 0.7 --pft 10 - -./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_seed_dbh_repro_threshold --value 0.5 --pft 7 - -./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_seed_dbh_repro_threshold --value 0.5 --pft 9 - -./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_seed_dbh_repro_threshold --value 0.5 --pft 10 - -./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_phen_chiltemp --value -2.0 - -./modify_fates_paramfile.py --input fates_params_seednew_bkp.nc --output fates_params_seednew_bkp.nc --O --var fates_phen_coldtemp --value -0.0 - From ad337ea66b92e7420d7d05e83d1c8298f2f04eb7 Mon Sep 17 00:00:00 2001 From: Shijie Shu Date: Fri, 28 Oct 2022 14:28:02 -0700 Subject: [PATCH 401/852] Minor revisions on comments, temporary commit --- biogeochem/EDCanopyStructureMod.F90 | 3 +- biogeochem/EDLoggingMortalityMod.F90 | 58 ++++++----------- biogeochem/EDMortalityFunctionsMod.F90 | 2 +- biogeochem/EDPatchDynamicsMod.F90 | 25 +++----- main/FatesHistoryInterfaceMod.F90 | 86 +++----------------------- 5 files changed, 37 insertions(+), 137 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 8d12f0827d..65af6fa31f 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1785,7 +1785,6 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) integer, intent(in) :: nsites type(ed_site_type), intent(inout), target :: sites(nsites) integer, intent(in) :: fcolumn(nsites) - type(bc_in_type), intent(inout) :: bc_in(nsites) type(bc_out_type), intent(inout) :: bc_out(nsites) ! Locals @@ -1978,7 +1977,7 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) end if ! Pass FATES Harvested C to bc_out. - call UpdateHarvestC(sites(s),bc_in(s),bc_out(s)) + call UpdateHarvestC(sites(s),bc_out(s)) end do diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 79adc81838..4b3383b333 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -87,11 +87,6 @@ module EDLoggingMortalityMod real(r8), parameter :: harvest_litter_localization = 0.0_r8 - ! ! transfer factor from kg biomass (dry matter) to kg carbon - ! ! now we applied a simple fraction of 50% based on the IPCC - ! ! guideline - ! real(r8), parameter :: carbon_per_kg_biomass = 0.5_r8 - character(len=*), parameter, private :: sourcefile = & __FILE__ @@ -284,13 +279,9 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & harvest_rate, harvest_tag, cur_harvest_tag) if (fates_global_verbose()) then - write(fates_log(), *) 'Successfully Read Harvest Rate from HLM.', hlm_harvest_rates(:), harvest_rate & - harvestable_forest_c + write(fates_log(), *) 'Successfully Read Harvest Rate from HLM.', hlm_harvest_rates(:), harvest_rate, harvestable_forest_c end if - write(fates_log(),*) 'HLM harvest carbon data not implemented yet. Exiting.' - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif ! transfer of area to secondary land is based on overall area affected, not just logged crown area @@ -304,7 +295,9 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & ! since there is an .and. .not. after the first conditional, the dbh:dbhmax comparison needs to be ! the opposite of what would otherwise be expected... lmort_direct = harvest_rate * logging_direct_frac - + else + lmort_direct = 0.0_r8 + end if else lmort_direct = 0.0_r8 end if @@ -375,8 +368,8 @@ subroutine get_harvest_rate_area (patch_anthro_disturbance_label, hlm_harvest_ca harvest_rate = 0._r8 do h_index = 1,hlm_num_lu_harvest_cats if (patch_anthro_disturbance_label .eq. primaryforest) then - if(hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1") then! .or. & - ! hlm_harvest_catnames(h_index) .eq. "HARVEST_VH2") then + if(hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1" .or. & + hlm_harvest_catnames(h_index) .eq. "HARVEST_VH2") then harvest_rate = harvest_rate + hlm_harvest_rates(h_index) endif else if (patch_anthro_disturbance_label .eq. secondaryforest .and. & @@ -386,8 +379,8 @@ subroutine get_harvest_rate_area (patch_anthro_disturbance_label, hlm_harvest_ca endif else if (patch_anthro_disturbance_label .eq. secondaryforest .and. & secondary_age < secondary_age_threshold) then - if(hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2") then! .or. & - ! hlm_harvest_catnames(h_index) .eq. "HARVEST_SH3") then + if(hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2" .or. & + hlm_harvest_catnames(h_index) .eq. "HARVEST_SH3") then harvest_rate = harvest_rate + hlm_harvest_rates(h_index) endif endif @@ -447,7 +440,6 @@ subroutine get_harvestable_carbon (csite, site_area, hlm_harvest_catnames, harve ! primary forest, secondary mature forest and secondary young forest ! under two different scenarios: ! harvestable carbon: aggregate all cohorts matching the dbhmin harvest criteria - ! available carbon: aggregate all cohorts ! ! this subroutine shall be called outside the patch loop ! output will be used to estimate the area-based harvest rate (get_harvest_rate_carbon) @@ -463,10 +455,8 @@ subroutine get_harvestable_carbon (csite, site_area, hlm_harvest_catnames, harve ! Local Variables type(ed_patch_type), pointer :: currentPatch type(ed_cohort_type), pointer :: currentCohort - real(r8) :: harvestable_patch_c ! temporary variable - real(r8) :: harvestable_cohort_c ! temporary variable - real(r8) :: available_patch_c ! temporary variable - real(r8) :: available_cohort_c ! temporary variable + real(r8) :: harvestable_patch_c ! temporary variable, kgC site-1 + real(r8) :: harvestable_cohort_c ! temporary variable, kgC site-1 real(r8) :: sapw_m ! Biomass of sap wood real(r8) :: struct_m ! Biomass of structural organs integer :: pft ! Index of plant functional type @@ -479,7 +469,6 @@ subroutine get_harvestable_carbon (csite, site_area, hlm_harvest_catnames, harve currentPatch => csite%oldest_patch do while (associated(currentPatch)) harvestable_patch_c = 0._r8 - available_patch_c = 0._r8 currentCohort => currentPatch%tallest do while (associated(currentCohort)) @@ -504,10 +493,6 @@ subroutine get_harvestable_carbon (csite, site_area, hlm_harvest_catnames, harve ((logging_dbhmax < fates_check_param_set) .and. (currentCohort%dbh >= logging_dbhmax )) ) then ! Harvestable C: aggregate cohorts fit the criteria harvestable_patch_c = harvestable_patch_c + harvestable_cohort_c - ! Available C: aggregate all cohorts - available_patch_c = available_patch_c + harvestable_cohort_c - else - available_patch_c = available_patch_c + harvestable_cohort_c end if end if end if @@ -559,8 +544,8 @@ subroutine get_harvest_rate_carbon (patch_anthro_disturbance_label, hlm_harvest_ character(len=64), intent(in) :: hlm_harvest_catnames(:) ! names of hlm harvest categories integer, intent(in) :: patch_anthro_disturbance_label ! patch level anthro_disturbance_label real(r8), intent(in) :: secondary_age ! patch level age_since_anthro_disturbance - real(r8), intent(in) :: harvestable_forest_c(:) ! site level forest c matching criteria available for harvest - real(r8), intent(out) :: harvest_rate + real(r8), intent(in) :: harvestable_forest_c(:) ! site level forest c matching criteria available for harvest, kgC site-1 + real(r8), intent(out) :: harvest_rate ! area fraction integer, intent(inout) :: harvest_tag(:) ! 0. normal harvest; 1. current site does not have enough C but ! can perform harvest by ignoring criteria; 2. current site does ! not have enough carbon @@ -573,20 +558,20 @@ subroutine get_harvest_rate_carbon (patch_anthro_disturbance_label, hlm_harvest_ ! Local Variables integer :: h_index ! for looping over harvest categories integer :: icode ! Integer equivalent of the event code (parameter file only allows reals) - real(r8) :: harvest_rate_c ! Temporary variable - real(r8) :: harvest_rate_supply ! Temporary variable + real(r8) :: harvest_rate_c ! Temporary variable, kgC site-1 + real(r8) :: harvest_rate_supply ! Temporary variable, kgC site-1 ! Loop around harvest categories to determine the hlm harvest rate demand and actual harvest rate for the ! current cohort based on patch history info harvest_rate = 0._r8 harvest_rate_c = 0._r8 harvest_rate_supply = 0._r8 - harvest_tag = 2 + harvest_tag(:) = 1 do h_index = 1,hlm_num_lu_harvest_cats if (patch_anthro_disturbance_label .eq. primaryforest) then - if(hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1") then! .or. & - ! hlm_harvest_catnames(h_index) .eq. "HARVEST_VH2") then + if(hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1" .or. & + hlm_harvest_catnames(h_index) .eq. "HARVEST_VH2") then harvest_rate_c = harvest_rate_c + hlm_harvest_rates(h_index) ! Determine the total supply of available C for harvest if(harvestable_forest_c(h_index) >= harvest_rate_c) then @@ -609,8 +594,8 @@ subroutine get_harvest_rate_carbon (patch_anthro_disturbance_label, hlm_harvest_ endif else if (patch_anthro_disturbance_label .eq. secondaryforest .and. & secondary_age < secondary_age_threshold) then - if(hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2") then! .or. & - ! hlm_harvest_catnames(h_index) .eq. "HARVEST_SH3") then + if(hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2" .or. & + hlm_harvest_catnames(h_index) .eq. "HARVEST_SH3") then harvest_rate_c = harvest_rate_c + hlm_harvest_rates(h_index) if(harvestable_forest_c(h_index) >= harvest_rate_c) then harvest_rate_supply = harvest_rate_supply + harvestable_forest_c(h_index) @@ -625,11 +610,6 @@ subroutine get_harvest_rate_carbon (patch_anthro_disturbance_label, hlm_harvest_ ! If any harvest category available, assign to cur_harvest_tag and trigger logging event if(present(cur_harvest_tag))then cur_harvest_tag = minval(harvest_tag) - !write(fates_log(), *) 'cur_harvest_tag:', cur_harvest_tag - !write(fates_log(), *) 'harvest tags:', harvest_tag - !write(fates_log(), *) 'harvest rate c:', harvest_rate_c - !write(fates_log(), *) 'harvest rate supply:', harvest_rate_supply - !write(fates_log(), *) 'hlm harvest rates:', hlm_harvest_rates end if ! Transfer carbon-based harvest rate to area-based harvest rate diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index 5ab67a04bf..0259772e20 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -232,7 +232,7 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_pr type(ed_cohort_type),intent(inout), target :: currentCohort type(bc_in_type), intent(in) :: bc_in real(r8), intent(in) :: frac_site_primary - real(r8), intent(in) :: harvestable_forest_c(:) + real(r8), intent(in) :: harvestable_forest_c(:) ! total carbon available for logging, kgC site-1 integer, intent(inout) :: harvest_tag(:) ! diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 6e88e6cf08..ed11a4d6be 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -212,7 +212,6 @@ subroutine disturbance_rates( site_in, bc_in) ! get available biomass for harvest for all patches call get_harvestable_carbon(site_in, bc_in%site_area, bc_in%hlm_harvest_catnames, harvestable_forest_c) - site_in%harvest_carbon_flux = 0._r8 harvest_debt_primary = 0 harvest_debt_secondary = 0 patch_no_secondary = 0 @@ -254,21 +253,13 @@ subroutine disturbance_rates( site_in, bc_in) currentCohort%lmort_infra = lmort_infra currentCohort%l_degrad = l_degrad - ! estimate the wood product (trunk_product_site) - if (currentCohort%canopy_layer>=1) then - ! kgC m-2 day-1 - site_in%harvest_carbon_flux = site_in%harvest_carbon_flux + & - currentCohort%lmort_direct * currentCohort%n * & - ( currentCohort%prt%GetState(sapw_organ, all_carbon_elements) + & - currentCohort%prt%GetState(struct_organ, all_carbon_elements)) * & - prt_params%allom_agb_frac(currentCohort%pft) * & - SF_val_CWD_frac(ncwd) * logging_export_frac * AREA_INV - endif - currentCohort => currentCohort%taller end do - ! Determine harvest debt status from all three categories + ! Determine harvest debt for primary land and secondary land + ! Harvest debt is the accumulated total carbon amount once + ! available carbon for harvest is smaller than the harvest + ! rate of forcing data for each site. ! Each cohort has the same harvest tag but not each patch ! Hence this part shall be within the patch loop ! TODO: we can define harvest debt as a fraction of the @@ -314,8 +305,8 @@ subroutine disturbance_rates( site_in, bc_in) do h_index = 1, hlm_num_lu_harvest_cats if ( harvest_debt_primary == 1 ) then ! Only account for primary forest harvest rate - if((bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1")) then !.or. & - ! (bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_VH2")) then + if((bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1") .or. & + (bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_VH2")) then site_in%resources_management%harvest_debt = site_in%resources_management%harvest_debt + & bc_in%hlm_harvest_rates(h_index) end if @@ -323,8 +314,8 @@ subroutine disturbance_rates( site_in, bc_in) if (harvest_debt_secondary == 1 .or. patch_no_secondary == 0) then ! Only account for secondary forest harvest rate if((bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH1") .or. & - (bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2")) then !.or. & - ! (bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH3")) then + (bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2") .or. & + (bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH3")) then site_in%resources_management%harvest_debt = site_in%resources_management%harvest_debt + & bc_in%hlm_harvest_rates(h_index) site_in%resources_management%harvest_debt_sec = site_in%resources_management%harvest_debt_sec + & diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index cbc13104f0..f634a02c15 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -1796,7 +1796,6 @@ subroutine update_history_dyn(this,nc,nsites,sites) real(r8) :: binbottom,bintop ! edges of height bins real(r8) :: gpp_cached ! variable used to cache gpp value in previous time step; for C13 discrimination - real(r8) :: lai_patch_cached ! temporary variable to cache mean lai of current patch ! The following are all carbon states, turnover and net allocation flux variables ! the organs of relevance should be self explanatory @@ -2183,7 +2182,6 @@ subroutine update_history_dyn(this,nc,nsites,sites) this%hvars(ih_h2oveg_recruit_si)%r81d(io_si) = sites(s)%si_hydr%h2oveg_recruit this%hvars(ih_h2oveg_growturn_err_si)%r81d(io_si) = sites(s)%si_hydr%h2oveg_growturn_err end if - hio_harvest_carbonflux_si(io_si) = sites(s)%harvest_carbon_flux hio_harvest_debt_si(io_si) = sites(s)%resources_management%harvest_debt hio_harvest_debt_sec_si(io_si) = sites(s)%resources_management%harvest_debt_sec @@ -2266,15 +2264,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! Secondary forest mean LAI if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then - lai_patch_cached = 0._r8 - do ican = 1, cpatch%NCL_p - do i_pft = 1, numpft - lai_patch_cached = lai_patch_cached + sum(cpatch%canopy_area_profile(ican,i_pft,1:cpatch%nrad(ican,i_pft)) * & - cpatch%tlai_profile(ican,i_pft,1:cpatch%nrad(ican,i_pft))) - end do - end do hio_lai_secondary_si(io_si) = hio_lai_secondary_si(io_si) & - + lai_patch_cached * min(1.0_r8, (cpatch%total_canopy_area/cpatch%area)) * cpatch%area * AREA_INV + + sum(cpatch%tlai_profile(:,:,:)) * cpatch%total_canopy_area end if ! patch-age-resolved fire variables @@ -3100,6 +3091,13 @@ subroutine update_history_dyn(this,nc,nsites,sites) endif end do + ! divide secondary plant leaf area by secondary forest area to get the secondary forest LAI + if (hio_fraction_secondary_forest_si(io_si) .gt. nearzero) then + hio_lai_secondary_si(io_si) = hio_lai_secondary_si(io_si) / (hio_fraction_secondary_forest_si(io_si)*AREA) + else + hio_lai_secondary_si(io_si) = 0._r8 + end if + ! pass the cohort termination mortality as a flux to the history, and then reset the termination mortality buffer ! note there are various ways of reporting the total mortality, so pass to these as well do i_pft = 1, numpft @@ -5412,74 +5410,6 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & ivar=ivar, initialize=initialize_variables, index = ih_rad_error_si) - ! disturbance rates - call this%set_history_var(vname='PRIMARYLAND_PATCHFUSION_ERROR', units='m2 m-2 d-1', & - long='Error in total primary lands associated with patch fusion', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_primaryland_fusion_error_si ) - - call this%set_history_var(vname='DISTURBANCE_RATE_P2P', units='m2 m-2 d-1', & - long='Disturbance rate from primary to primary lands', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_disturbance_rate_p2p_si ) - - call this%set_history_var(vname='DISTURBANCE_RATE_P2S', units='m2 m-2 d-1', & - long='Disturbance rate from primary to secondary lands', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_disturbance_rate_p2s_si ) - - call this%set_history_var(vname='DISTURBANCE_RATE_S2S', units='m2 m-2 d-1', & - long='Disturbance rate from secondary to secondary lands', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_disturbance_rate_s2s_si ) - -! call this%set_history_var(vname='DISTURBANCE_RATE_FIRE', units='m2 m-2 d-1', & -! long='Disturbance rate from fire', use_default='active', & -! avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & -! ivar=ivar, initialize=initialize_variables, index = ih_fire_disturbance_rate_si ) -! -! call this%set_history_var(vname='DISTURBANCE_RATE_LOGGING', units='m2 m-2 d-1', & -! long='Disturbance rate from logging', use_default='active', & -! avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & -! ivar=ivar, initialize=initialize_variables, index = ih_logging_disturbance_rate_si ) -! -! call this%set_history_var(vname='DISTURBANCE_RATE_TREEFALL', units='m2 m-2 d-1', & -! long='Disturbance rate from treefall', use_default='active', & -! avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & -! ivar=ivar, initialize=initialize_variables, index = ih_fall_disturbance_rate_si ) -! -! call this%set_history_var(vname='DISTURBANCE_RATE_POTENTIAL', units='m2 m-2 d-1', & -! long='Potential (i.e., including unresolved) disturbance rate', use_default='active', & -! avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & -! ivar=ivar, initialize=initialize_variables, index = ih_potential_disturbance_rate_si ) - - call this%set_history_var(vname='HARVEST_CARBON_FLUX', units='kg C m-2 d-1', & - long='Harvest carbon flux', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_harvest_carbonflux_si ) - - call this%set_history_var(vname='HARVEST_DEBT', units='kg C', & - long='Accumulated carbon failed to be harvested', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_harvest_debt_si ) - - call this%set_history_var(vname='HARVEST_DEBT_SEC', units='kg C', & - long='Accumulated carbon failed to be harvested from secondary patches', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_harvest_debt_sec_si ) - - ! Canopy Resistance - - call this%set_history_var(vname='C_STOMATA', units='umol m-2 s-1', & - long='mean stomatal conductance', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_c_stomata_si ) - - call this%set_history_var(vname='C_LBLAYER', units='umol m-2 s-1', & - long='mean leaf boundary layer conductance', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_c_lblayer_si ) - ! Ecosystem Carbon Fluxes (updated rapidly, upfreq=2) From 4e4054b77d37a4948e9e084729d9e36ac2106fd2 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 28 Oct 2022 16:57:23 -0700 Subject: [PATCH 402/852] adding new seed dispersal parameter file --- parameter_files/fates_params_default.cdl | 1489 ---------------- .../fates_params_seed-dispersal.cdl | 1550 ----------------- 2 files changed, 3039 deletions(-) delete mode 100644 parameter_files/fates_params_default.cdl delete mode 100644 parameter_files/fates_params_seed-dispersal.cdl diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl deleted file mode 100644 index 45e4a3509c..0000000000 --- a/parameter_files/fates_params_default.cdl +++ /dev/null @@ -1,1489 +0,0 @@ -netcdf fates_params_default.c210629_sorted { -dimensions: - fates_NCWD = 4 ; - fates_history_age_bins = 7 ; - fates_history_height_bins = 6 ; - fates_history_size_bins = 13 ; - fates_history_coage_bins = 2 ; - fates_hydr_organs = 4 ; - fates_leafage_class = 1 ; - fates_litterclass = 6 ; - fates_pft = 12 ; - fates_prt_organs = 4 ; - fates_string_length = 60 ; - fates_hlm_pftno = 14 ; -variables: - double fates_history_ageclass_bin_edges(fates_history_age_bins) ; - fates_history_ageclass_bin_edges:units = "yr" ; - fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; - double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; - fates_history_coageclass_bin_edges:units = "years" ; - fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; - double fates_history_height_bin_edges(fates_history_height_bins) ; - fates_history_height_bin_edges:units = "m" ; - fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; - double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; - fates_history_sizeclass_bin_edges:units = "cm" ; - fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; - double fates_hydr_htftype_node(fates_hydr_organs) ; - fates_hydr_htftype_node:units = "unitless" ; - fates_hydr_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; - fates_hydr_htftype_node:possible_values = "1: Christofferson et al. 2016 (TFS); 2: Van Genuchten 1980" ; - double fates_prt_organ_id(fates_prt_organs) ; - fates_prt_organ_id:units = "index, unitless" ; - fates_prt_organ_id:long_name = "This is the global index the organ in this file is associated with in PRTGenericMod.F90" ; - char fates_pftname(fates_pft, fates_string_length) ; - fates_pftname:units = "unitless - string" ; - fates_pftname:long_name = "Description of plant type" ; - char fates_hydr_organname_node(fates_hydr_organs, fates_string_length) ; - fates_hydr_organname_node:units = "unitless - string" ; - fates_hydr_organname_node:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; - 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_prt_organ_name(fates_prt_organs, fates_string_length) ; - fates_prt_organ_name:units = "unitless - string" ; - fates_prt_organ_name:long_name = "Name of plant organs (order must match PRTGenericMod.F90)" ; - double fates_alloc_storage_cushion(fates_pft) ; - fates_alloc_storage_cushion:units = "fraction" ; - fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; - double fates_allom_agb1(fates_pft) ; - fates_allom_agb1:units = "variable" ; - fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; - double fates_allom_agb2(fates_pft) ; - fates_allom_agb2:units = "variable" ; - fates_allom_agb2:long_name = "Parameter 2 for agb allometry" ; - double fates_allom_agb3(fates_pft) ; - fates_allom_agb3:units = "variable" ; - fates_allom_agb3:long_name = "Parameter 3 for agb allometry" ; - double fates_allom_agb4(fates_pft) ; - fates_allom_agb4:units = "variable" ; - fates_allom_agb4:long_name = "Parameter 4 for agb allometry" ; - double fates_allom_agb_frac(fates_pft) ; - fates_allom_agb_frac:units = "fraction" ; - fates_allom_agb_frac:long_name = "Fraction of woody biomass that is above ground" ; - double fates_allom_amode(fates_pft) ; - fates_allom_amode:units = "index" ; - fates_allom_amode:long_name = "AGB allometry function index." ; - fates_allom_amode:possible_values = "1: Saldarriaga 1998; 2: 2 parameter power law; 3: Chave 2014" ; - double fates_allom_blca_expnt_diff(fates_pft) ; - fates_allom_blca_expnt_diff:units = "unitless" ; - fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; - double fates_allom_cmode(fates_pft) ; - fates_allom_cmode:units = "index" ; - fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; - fates_allom_cmode:possible_values = "1: Constant fraction on AGB" ; - double fates_allom_d2bl1(fates_pft) ; - fates_allom_d2bl1:units = "variable" ; - fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; - double fates_allom_d2bl2(fates_pft) ; - fates_allom_d2bl2:units = "variable" ; - fates_allom_d2bl2:long_name = "Parameter 2 for d2bl allometry" ; - double fates_allom_d2bl3(fates_pft) ; - fates_allom_d2bl3:units = "unitless" ; - fates_allom_d2bl3:long_name = "Parameter 3 for d2bl allometry" ; - double fates_allom_d2ca_coefficient_max(fates_pft) ; - fates_allom_d2ca_coefficient_max:units = "m2 cm^(-1/beta)" ; - fates_allom_d2ca_coefficient_max:long_name = "max (savanna) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; - double fates_allom_d2ca_coefficient_min(fates_pft) ; - fates_allom_d2ca_coefficient_min:units = "m2 cm^(-1/beta)" ; - fates_allom_d2ca_coefficient_min:long_name = "min (forest) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; - double fates_allom_d2h1(fates_pft) ; - fates_allom_d2h1:units = "variable" ; - fates_allom_d2h1:long_name = "Parameter 1 for d2h allometry (intercept, or c)" ; - double fates_allom_d2h2(fates_pft) ; - fates_allom_d2h2:units = "variable" ; - fates_allom_d2h2:long_name = "Parameter 2 for d2h allometry (slope, or m)" ; - double fates_allom_d2h3(fates_pft) ; - fates_allom_d2h3:units = "variable" ; - fates_allom_d2h3:long_name = "Parameter 3 for d2h allometry (optional)" ; - double fates_allom_dbh_maxheight(fates_pft) ; - fates_allom_dbh_maxheight:units = "cm" ; - fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; - double fates_allom_fmode(fates_pft) ; - fates_allom_fmode:units = "index" ; - fates_allom_fmode:long_name = "fine root biomass allometry function index." ; - fates_allom_fmode:possible_values = "1: constant fraction of trimmed bleaf; 2: constant fraction of untrimmed bleaf." ; - double fates_allom_frbstor_repro(fates_pft) ; - fates_allom_frbstor_repro:units = "fraction" ; - fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; - double fates_allom_hmode(fates_pft) ; - fates_allom_hmode:units = "index" ; - fates_allom_hmode:long_name = "height allometry function index." ; - fates_allom_hmode:possible_values = "1: OBrien 1995; 2: Poorter 2006; 3: 2 parameter power law; 4: Chave 2014; 5: Martinez-Cano 2019." ; - double fates_allom_l2fr(fates_pft) ; - fates_allom_l2fr:units = "gC/gC" ; - fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; - double fates_allom_la_per_sa_int(fates_pft) ; - fates_allom_la_per_sa_int:units = "m2/cm2" ; - fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; - double fates_allom_la_per_sa_slp(fates_pft) ; - fates_allom_la_per_sa_slp:units = "m2/cm2/m" ; - fates_allom_la_per_sa_slp:long_name = "Leaf area per sapwood area rate of change with height, slope (optional)" ; - double fates_allom_lmode(fates_pft) ; - fates_allom_lmode:units = "index" ; - fates_allom_lmode:long_name = "leaf biomass allometry function index." ; - fates_allom_lmode:possible_values = "1: Saldarriaga 1998 (capped-dbh power law); 2: generic power law; 3: generic capped-dbh power law." ; - double fates_allom_sai_scaler(fates_pft) ; - fates_allom_sai_scaler:units = "m2/m2" ; - fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; - double fates_allom_smode(fates_pft) ; - fates_allom_smode:units = "index" ; - fates_allom_smode:long_name = "sapwood allometry function index." ; - fates_allom_smode:possible_values = "1: sapwood area proportional to leaf area based on target leaf biomass" ; - double fates_allom_stmode(fates_pft) ; - fates_allom_stmode:units = "index" ; - fates_allom_stmode:long_name = "storage allometry function index." ; - fates_allom_stmode:possible_values = "1: target storage proportional to trimmed maximum leaf biomass." ; - double fates_allom_zroot_k(fates_pft) ; - fates_allom_zroot_k:units = "unitless" ; - fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; - double fates_allom_zroot_max_dbh(fates_pft) ; - fates_allom_zroot_max_dbh:units = "cm" ; - fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; - double fates_allom_zroot_max_z(fates_pft) ; - fates_allom_zroot_max_z:units = "m" ; - fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; - double fates_allom_zroot_min_dbh(fates_pft) ; - fates_allom_zroot_min_dbh:units = "cm" ; - fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; - double fates_allom_zroot_min_z(fates_pft) ; - fates_allom_zroot_min_z:units = "m" ; - fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; - double fates_branch_turnover(fates_pft) ; - fates_branch_turnover:units = "yr" ; - fates_branch_turnover:long_name = "turnover time of branches" ; - double fates_c2b(fates_pft) ; - fates_c2b:units = "ratio" ; - fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; - 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" ; - double fates_displar(fates_pft) ; - fates_displar:units = "unitless" ; - fates_displar:long_name = "Ratio of displacement height to canopy top height" ; - double fates_eca_alpha_ptase(fates_pft) ; - fates_eca_alpha_ptase:units = "g/m3" ; - fates_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; - double fates_eca_decompmicc(fates_pft) ; - fates_eca_decompmicc:units = "gC/m3" ; - fates_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; - double fates_eca_km_nh4(fates_pft) ; - fates_eca_km_nh4:units = "gN/m3" ; - fates_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; - double fates_eca_km_no3(fates_pft) ; - fates_eca_km_no3:units = "gN/m3" ; - fates_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; - double fates_eca_km_p(fates_pft) ; - fates_eca_km_p:units = "gP/m3" ; - fates_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; - double fates_eca_km_ptase(fates_pft) ; - fates_eca_km_ptase:units = "gP/m3" ; - fates_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; - double fates_eca_lambda_ptase(fates_pft) ; - fates_eca_lambda_ptase:units = "g/m3" ; - fates_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; - double fates_eca_vmax_nh4(fates_pft) ; - fates_eca_vmax_nh4:units = "gN/gC/s" ; - fates_eca_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA)" ; - double fates_eca_vmax_no3(fates_pft) ; - fates_eca_vmax_no3:units = "gN/gC/s" ; - fates_eca_vmax_no3:long_name = "maximum production rate for plant no3 uptake (ECA)" ; - double fates_eca_vmax_p(fates_pft) ; - fates_eca_vmax_p:units = "gP/gC/s" ; - fates_eca_vmax_p:long_name = "maximum production rate for plant p uptake (ECA)" ; - double fates_eca_vmax_ptase(fates_pft) ; - fates_eca_vmax_ptase:units = "gP/m2/s" ; - fates_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; - double fates_fire_alpha_SH(fates_pft) ; - fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; - fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; - double fates_fire_bark_scaler(fates_pft) ; - fates_fire_bark_scaler:units = "fraction" ; - fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; - double fates_fire_crown_depth_frac(fates_pft) ; - fates_fire_crown_depth_frac:units = "fraction" ; - fates_fire_crown_depth_frac:long_name = "the depth of a cohorts crown as a fraction of its height" ; - double fates_fire_crown_kill(fates_pft) ; - fates_fire_crown_kill:units = "NA" ; - fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; - double fates_fnrt_prof_a(fates_pft) ; - fates_fnrt_prof_a:units = "unitless" ; - fates_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; - double fates_fnrt_prof_b(fates_pft) ; - fates_fnrt_prof_b:units = "unitless" ; - fates_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; - double fates_fnrt_prof_mode(fates_pft) ; - fates_fnrt_prof_mode:units = "index" ; - fates_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; - double fates_fr_fcel(fates_pft) ; - fates_fr_fcel:units = "fraction" ; - fates_fr_fcel:long_name = "Fine root litter cellulose fraction" ; - double fates_fr_flab(fates_pft) ; - fates_fr_flab:units = "fraction" ; - fates_fr_flab:long_name = "Fine root litter labile fraction" ; - double fates_fr_flig(fates_pft) ; - fates_fr_flig:units = "fraction" ; - fates_fr_flig:long_name = "Fine root litter lignin fraction" ; - double fates_grperc(fates_pft) ; - fates_grperc:units = "unitless" ; - fates_grperc:long_name = "Growth respiration factor" ; - double fates_hydr_avuln_gs(fates_pft) ; - fates_hydr_avuln_gs:units = "unitless" ; - fates_hydr_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; - double fates_hydr_avuln_node(fates_hydr_organs, fates_pft) ; - fates_hydr_avuln_node:units = "unitless" ; - fates_hydr_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; - double fates_hydr_epsil_node(fates_hydr_organs, fates_pft) ; - fates_hydr_epsil_node:units = "MPa" ; - fates_hydr_epsil_node:long_name = "bulk elastic modulus" ; - double fates_hydr_fcap_node(fates_hydr_organs, fates_pft) ; - fates_hydr_fcap_node:units = "unitless" ; - fates_hydr_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; - double fates_hydr_k_lwp(fates_pft) ; - fates_hydr_k_lwp:units = "unitless" ; - fates_hydr_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; - fates_hydr_k_lwp:possible_values = "0: turns off leaf humidity effects on conductance. 1-10 activates humidity effects" ; - double fates_hydr_kmax_node(fates_hydr_organs, fates_pft) ; - fates_hydr_kmax_node:units = "kg/MPa/m/s" ; - fates_hydr_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; - double fates_hydr_p50_gs(fates_pft) ; - fates_hydr_p50_gs:units = "MPa" ; - fates_hydr_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; - double fates_hydr_p50_node(fates_hydr_organs, fates_pft) ; - fates_hydr_p50_node:units = "MPa" ; - fates_hydr_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; - double fates_hydr_p_taper(fates_pft) ; - fates_hydr_p_taper:units = "unitless" ; - fates_hydr_p_taper:long_name = "xylem taper exponent" ; - double fates_hydr_pinot_node(fates_hydr_organs, fates_pft) ; - fates_hydr_pinot_node:units = "MPa" ; - fates_hydr_pinot_node:long_name = "osmotic potential at full turgor" ; - double fates_hydr_pitlp_node(fates_hydr_organs, fates_pft) ; - fates_hydr_pitlp_node:units = "MPa" ; - fates_hydr_pitlp_node:long_name = "turgor loss point" ; - double fates_hydr_resid_node(fates_hydr_organs, fates_pft) ; - fates_hydr_resid_node:units = "cm3/cm3" ; - fates_hydr_resid_node:long_name = "residual water conent" ; - double fates_hydr_rfrac_stem(fates_pft) ; - fates_hydr_rfrac_stem:units = "fraction" ; - fates_hydr_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; - double fates_hydr_rs2(fates_pft) ; - fates_hydr_rs2:units = "m" ; - fates_hydr_rs2:long_name = "absorbing root radius" ; - double fates_hydr_srl(fates_pft) ; - fates_hydr_srl:units = "m g-1" ; - fates_hydr_srl:long_name = "specific root length" ; - double fates_hydr_thetas_node(fates_hydr_organs, fates_pft) ; - fates_hydr_thetas_node:units = "cm3/cm3" ; - fates_hydr_thetas_node:long_name = "saturated water content" ; - double fates_hydr_vg_alpha_node(fates_hydr_organs, fates_pft) ; - fates_hydr_vg_alpha_node:units = "MPa-1" ; - fates_hydr_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; - double fates_hydr_vg_m_node(fates_hydr_organs, fates_pft) ; - fates_hydr_vg_m_node:units = "unitless" ; - fates_hydr_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; - double fates_hydr_vg_n_node(fates_hydr_organs, fates_pft) ; - fates_hydr_vg_n_node:units = "unitless" ; - fates_hydr_vg_n_node:long_name = "(used if hydr_htftype_node = 2),n in van Genuchten 1980 model, pore size distribution parameter" ; - double fates_leaf_c3psn(fates_pft) ; - fates_leaf_c3psn:units = "flag" ; - fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; - double fates_leaf_clumping_index(fates_pft) ; - fates_leaf_clumping_index:units = "fraction (0-1)" ; - fates_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; - double fates_leaf_diameter(fates_pft) ; - fates_leaf_diameter:units = "m" ; - fates_leaf_diameter:long_name = "Characteristic leaf dimension" ; - double fates_leaf_jmaxha(fates_pft) ; - fates_leaf_jmaxha:units = "J/mol" ; - fates_leaf_jmaxha:long_name = "activation energy for jmax" ; - double fates_leaf_jmaxhd(fates_pft) ; - fates_leaf_jmaxhd:units = "J/mol" ; - fates_leaf_jmaxhd:long_name = "deactivation energy for jmax" ; - double fates_leaf_jmaxse(fates_pft) ; - fates_leaf_jmaxse:units = "J/mol/K" ; - fates_leaf_jmaxse:long_name = "entropy term for jmax" ; - double fates_leaf_long(fates_leafage_class, fates_pft) ; - fates_leaf_long:units = "yr" ; - fates_leaf_long:long_name = "Leaf longevity (ie turnover timescale)" ; - double fates_leaf_slamax(fates_pft) ; - fates_leaf_slamax:units = "m^2/gC" ; - fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; - double fates_leaf_slatop(fates_pft) ; - fates_leaf_slatop:units = "m^2/gC" ; - fates_leaf_slatop:long_name = "Specific Leaf Area (SLA) at top of canopy, projected area basis" ; - double fates_leaf_stomatal_intercept(fates_pft) ; - fates_leaf_stomatal_intercept:units = "umol H2O/m**2/s" ; - fates_leaf_stomatal_intercept:long_name = "Minimum unstressed stomatal conductance for Ball-Berry model and Medlyn model" ; - double fates_leaf_stomatal_slope_ballberry(fates_pft) ; - fates_leaf_stomatal_slope_ballberry:units = "unitless" ; - fates_leaf_stomatal_slope_ballberry:long_name = "stomatal slope parameter, as per Ball-Berry" ; - double fates_leaf_stomatal_slope_medlyn(fates_pft) ; - fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; - fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; - double fates_leaf_stor_priority(fates_pft) ; - fates_leaf_stor_priority:units = "unitless" ; - fates_leaf_stor_priority:long_name = "factor governing priority of replacing storage with NPP" ; - double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; - fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; - fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; - double fates_leaf_vcmaxha(fates_pft) ; - fates_leaf_vcmaxha:units = "J/mol" ; - fates_leaf_vcmaxha:long_name = "activation energy for vcmax" ; - double fates_leaf_vcmaxhd(fates_pft) ; - fates_leaf_vcmaxhd:units = "J/mol" ; - fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax" ; - double fates_leaf_vcmaxse(fates_pft) ; - fates_leaf_vcmaxse:units = "J/mol/K" ; - fates_leaf_vcmaxse:long_name = "entropy term for vcmax" ; - double fates_leaf_xl(fates_pft) ; - fates_leaf_xl:units = "unitless" ; - fates_leaf_xl:long_name = "Leaf/stem orientation index" ; - double fates_lf_fcel(fates_pft) ; - fates_lf_fcel:units = "fraction" ; - fates_lf_fcel:long_name = "Leaf litter cellulose fraction" ; - double fates_lf_flab(fates_pft) ; - fates_lf_flab:units = "fraction" ; - fates_lf_flab:long_name = "Leaf litter labile fraction" ; - double fates_lf_flig(fates_pft) ; - fates_lf_flig:units = "fraction" ; - fates_lf_flig:long_name = "Leaf litter lignin fraction" ; - double fates_maintresp_reduction_curvature(fates_pft) ; - fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; - fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; - double fates_maintresp_reduction_intercept(fates_pft) ; - fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; - fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; - double fates_mort_bmort(fates_pft) ; - fates_mort_bmort:units = "1/yr" ; - fates_mort_bmort:long_name = "background mortality rate" ; - double fates_mort_freezetol(fates_pft) ; - fates_mort_freezetol:units = "degrees C" ; - fates_mort_freezetol:long_name = "minimum temperature tolerance" ; - double fates_mort_hf_flc_threshold(fates_pft) ; - fates_mort_hf_flc_threshold:units = "fraction" ; - fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; - double fates_mort_hf_sm_threshold(fates_pft) ; - fates_mort_hf_sm_threshold:units = "unitless" ; - fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; - double fates_mort_ip_age_senescence(fates_pft) ; - fates_mort_ip_age_senescence:units = "years" ; - fates_mort_ip_age_senescence:long_name = "Mortality cohort age senescence inflection point. If _ this mortality term is off. Setting this value turns on age dependent mortality. " ; - double fates_mort_ip_size_senescence(fates_pft) ; - fates_mort_ip_size_senescence:units = "dbh cm" ; - fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; - double fates_mort_r_age_senescence(fates_pft) ; - fates_mort_r_age_senescence:units = "mortality rate year^-1" ; - fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; - double fates_mort_r_size_senescence(fates_pft) ; - fates_mort_r_size_senescence:units = "mortality rate dbh^-1" ; - fates_mort_r_size_senescence:long_name = "Mortality dbh senescence rate of change. Sensible range is around 0.03-0.06. Larger values give steeper mortality curves." ; - double fates_mort_scalar_coldstress(fates_pft) ; - fates_mort_scalar_coldstress:units = "1/yr" ; - fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; - double fates_mort_scalar_cstarvation(fates_pft) ; - fates_mort_scalar_cstarvation:units = "1/yr" ; - fates_mort_scalar_cstarvation:long_name = "maximum mortality rate from carbon starvation" ; - double fates_mort_scalar_hydrfailure(fates_pft) ; - fates_mort_scalar_hydrfailure:units = "1/yr" ; - fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; - double fates_nfix1(fates_pft) ; - fates_nfix1:units = "NA" ; - fates_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; - double fates_nfix2(fates_pft) ; - fates_nfix2:units = "NA" ; - fates_nfix2:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; - double fates_nitr_store_ratio(fates_pft) ; - fates_nitr_store_ratio:units = "(gN/gN)" ; - fates_nitr_store_ratio:long_name = "ratio of storeable N, to functional N bound in cell structures of leaf,root,sap" ; - double fates_phen_cold_size_threshold(fates_pft) ; - fates_phen_cold_size_threshold:units = "cm" ; - fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; - double fates_phen_evergreen(fates_pft) ; - fates_phen_evergreen:units = "logical flag" ; - fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; - double fates_phen_season_decid(fates_pft) ; - fates_phen_season_decid:units = "logical flag" ; - fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; - double fates_phen_stem_drop_fraction(fates_pft) ; - fates_phen_stem_drop_fraction:units = "fraction" ; - fates_phen_stem_drop_fraction:long_name = "fraction of stems to drop for non-woody species during drought/cold" ; - double fates_phen_stress_decid(fates_pft) ; - fates_phen_stress_decid:units = "logical flag" ; - fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; - double fates_phenflush_fraction(fates_pft) ; - fates_phenflush_fraction:units = "fraction" ; - fates_phenflush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; - double fates_phos_store_ratio(fates_pft) ; - fates_phos_store_ratio:units = "(gP/gP)" ; - fates_phos_store_ratio:long_name = "ratio of storeable P, to functional P bound in cell structures of leaf,root,sap" ; - double fates_prescribed_mortality_canopy(fates_pft) ; - fates_prescribed_mortality_canopy:units = "1/yr" ; - fates_prescribed_mortality_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; - double fates_prescribed_mortality_understory(fates_pft) ; - fates_prescribed_mortality_understory:units = "1/yr" ; - fates_prescribed_mortality_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; - double fates_prescribed_npp_canopy(fates_pft) ; - fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; - fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; - double fates_prescribed_npp_understory(fates_pft) ; - fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; - fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; - double fates_prescribed_nuptake(fates_pft) ; - fates_prescribed_nuptake:units = "fraction" ; - fates_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; - double fates_prescribed_puptake(fates_pft) ; - fates_prescribed_puptake:units = "fraction" ; - fates_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; - double fates_prescribed_recruitment(fates_pft) ; - fates_prescribed_recruitment:units = "n/yr" ; - fates_prescribed_recruitment:long_name = "recruitment rate for prescribed physiology mode" ; - double fates_prt_alloc_priority(fates_prt_organs, fates_pft) ; - fates_prt_alloc_priority:units = "index (0-fates_prt_organs)" ; - fates_prt_alloc_priority:long_name = "Priority order for allocation (C storage=2)" ; - double fates_prt_nitr_stoich_p1(fates_prt_organs, fates_pft) ; - fates_prt_nitr_stoich_p1:units = "(gN/gC)" ; - fates_prt_nitr_stoich_p1:long_name = "nitrogen stoichiometry, parameter 1" ; - double fates_prt_nitr_stoich_p2(fates_prt_organs, fates_pft) ; - fates_prt_nitr_stoich_p2:units = "(gN/gC)" ; - fates_prt_nitr_stoich_p2:long_name = "nitrogen stoichiometry, parameter 2" ; - double fates_prt_phos_stoich_p1(fates_prt_organs, fates_pft) ; - fates_prt_phos_stoich_p1:units = "(gP/gC)" ; - fates_prt_phos_stoich_p1:long_name = "phosphorous stoichiometry, parameter 1" ; - double fates_prt_phos_stoich_p2(fates_prt_organs, fates_pft) ; - fates_prt_phos_stoich_p2:units = "(gP/gC)" ; - fates_prt_phos_stoich_p2:long_name = "phosphorous stoichiometry, parameter 2" ; - double fates_recruit_hgt_min(fates_pft) ; - fates_recruit_hgt_min:units = "m" ; - fates_recruit_hgt_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; - double fates_recruit_initd(fates_pft) ; - fates_recruit_initd:units = "stems/m2" ; - fates_recruit_initd:long_name = "initial seedling density for a cold-start near-bare-ground simulation" ; - double fates_rholnir(fates_pft) ; - fates_rholnir:units = "fraction" ; - fates_rholnir:long_name = "Leaf reflectance: near-IR" ; - double fates_rholvis(fates_pft) ; - fates_rholvis:units = "fraction" ; - fates_rholvis:long_name = "Leaf reflectance: visible" ; - double fates_rhosnir(fates_pft) ; - fates_rhosnir:units = "fraction" ; - fates_rhosnir:long_name = "Stem reflectance: near-IR" ; - double fates_rhosvis(fates_pft) ; - fates_rhosvis:units = "fraction" ; - fates_rhosvis:long_name = "Stem reflectance: visible" ; - double fates_root_long(fates_pft) ; - fates_root_long:units = "yr" ; - fates_root_long:long_name = "root longevity (alternatively, turnover time)" ; - double fates_seed_alloc(fates_pft) ; - fates_seed_alloc:units = "fraction" ; - fates_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; - double fates_seed_alloc_mature(fates_pft) ; - fates_seed_alloc_mature:units = "fraction" ; - fates_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; - double fates_seed_dbh_repro_threshold(fates_pft) ; - fates_seed_dbh_repro_threshold:units = "cm" ; - fates_seed_dbh_repro_threshold:long_name = "the diameter (if any) where the plant will start extra clonal allocation to the seed pool" ; - double fates_seed_decay_rate(fates_pft) ; - fates_seed_decay_rate:units = "yr-1" ; - fates_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; - double fates_seed_germination_rate(fates_pft) ; - fates_seed_germination_rate:units = "yr-1" ; - fates_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; - double fates_seed_suppl(fates_pft) ; - fates_seed_suppl:units = "KgC/m2/yr" ; - fates_seed_suppl:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; - double fates_senleaf_long_fdrought(fates_pft) ; - fates_senleaf_long_fdrought:units = "unitless[0-1]" ; - fates_senleaf_long_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; - double fates_smpsc(fates_pft) ; - fates_smpsc:units = "mm" ; - fates_smpsc:long_name = "Soil water potential at full stomatal closure" ; - double fates_smpso(fates_pft) ; - fates_smpso:units = "mm" ; - fates_smpso:long_name = "Soil water potential at full stomatal opening" ; - double fates_taulnir(fates_pft) ; - fates_taulnir:units = "fraction" ; - fates_taulnir:long_name = "Leaf transmittance: near-IR" ; - double fates_taulvis(fates_pft) ; - fates_taulvis:units = "fraction" ; - fates_taulvis:long_name = "Leaf transmittance: visible" ; - double fates_tausnir(fates_pft) ; - fates_tausnir:units = "fraction" ; - fates_tausnir:long_name = "Stem transmittance: near-IR" ; - double fates_tausvis(fates_pft) ; - fates_tausvis:units = "fraction" ; - fates_tausvis:long_name = "Stem transmittance: visible" ; - double fates_trim_inc(fates_pft) ; - fates_trim_inc:units = "m2/m2" ; - fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; - double fates_trim_limit(fates_pft) ; - fates_trim_limit:units = "m2/m2" ; - fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; - double fates_turnover_carb_retrans(fates_prt_organs, fates_pft) ; - fates_turnover_carb_retrans:units = "-" ; - fates_turnover_carb_retrans:long_name = "retranslocation fraction of carbon in turnover" ; - double fates_turnover_nitr_retrans(fates_prt_organs, fates_pft) ; - fates_turnover_nitr_retrans:units = "-" ; - fates_turnover_nitr_retrans:long_name = "retranslocation fraction of nitrogen in turnover" ; - double fates_turnover_phos_retrans(fates_prt_organs, fates_pft) ; - fates_turnover_phos_retrans:units = "-" ; - fates_turnover_phos_retrans:long_name = "retranslocation fraction of phosphorous in turnover, parameter 1" ; - double fates_turnover_retrans_mode(fates_pft) ; - fates_turnover_retrans_mode:units = "index" ; - fates_turnover_retrans_mode:long_name = "retranslocation method for leaf/fineroot turnover." ; - fates_turnover_retrans_mode:possible_values = "1: constant fraction." ; - double fates_wood_density(fates_pft) ; - fates_wood_density:units = "g/cm3" ; - fates_wood_density:long_name = "mean density of woody tissue in plant" ; - double fates_woody(fates_pft) ; - fates_woody:units = "logical flag" ; - fates_woody:long_name = "Binary woody lifeform flag" ; - double fates_z0mr(fates_pft) ; - fates_z0mr:units = "unitless" ; - fates_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; - double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; - fates_hlm_pft_map:units = "area fraction" ; - fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; - double fates_fire_FBD(fates_litterclass) ; - fates_fire_FBD:units = "kg Biomass/m3" ; - fates_fire_FBD:long_name = "fuel bulk density" ; - double fates_fire_low_moisture_Coeff(fates_litterclass) ; - fates_fire_low_moisture_Coeff:units = "NA" ; - fates_fire_low_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_low_moisture_Slope(fates_litterclass) ; - fates_fire_low_moisture_Slope:units = "NA" ; - fates_fire_low_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_mid_moisture(fates_litterclass) ; - fates_fire_mid_moisture:units = "NA" ; - fates_fire_mid_moisture:long_name = "spitfire litter moisture threshold to be considered medium dry" ; - double fates_fire_mid_moisture_Coeff(fates_litterclass) ; - fates_fire_mid_moisture_Coeff:units = "NA" ; - fates_fire_mid_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_mid_moisture_Slope(fates_litterclass) ; - fates_fire_mid_moisture_Slope:units = "NA" ; - fates_fire_mid_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_min_moisture(fates_litterclass) ; - fates_fire_min_moisture:units = "NA" ; - fates_fire_min_moisture:long_name = "spitfire litter moisture threshold to be considered very dry" ; - double fates_fire_SAV(fates_litterclass) ; - fates_fire_SAV:units = "cm-1" ; - fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; - double fates_max_decomp(fates_litterclass) ; - fates_max_decomp:units = "yr-1" ; - fates_max_decomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; - double fates_CWD_frac(fates_NCWD) ; - fates_CWD_frac:units = "fraction" ; - fates_CWD_frac:long_name = "fraction of woody (bdead+bsw) biomass destined for CWD pool" ; - double fates_base_mr_20 ; - fates_base_mr_20:units = "gC/gN/s" ; - fates_base_mr_20:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; - 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" ; - double fates_cohort_age_fusion_tol ; - fates_cohort_age_fusion_tol:units = "unitless" ; - fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; - double fates_cohort_size_fusion_tol ; - fates_cohort_size_fusion_tol:units = "unitless" ; - fates_cohort_size_fusion_tol:long_name = "minimum fraction in difference in dbh between cohorts" ; - double fates_comp_excln ; - fates_comp_excln:units = "none" ; - fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; - double fates_cwd_fcel ; - fates_cwd_fcel:units = "unitless" ; - fates_cwd_fcel:long_name = "Cellulose fraction for CWD" ; - double fates_cwd_flig ; - fates_cwd_flig:units = "unitless" ; - fates_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; - double fates_dev_arbitrary ; - fates_dev_arbitrary:units = "unknown" ; - fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; - double fates_eca_plant_escalar ; - fates_eca_plant_escalar:units = "" ; - fates_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; - double fates_fire_active_crown_fire ; - fates_fire_active_crown_fire:units = "0 or 1" ; - fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; - double fates_fire_cg_strikes ; - fates_fire_cg_strikes:units = "fraction (0-1)" ; - fates_fire_cg_strikes:long_name = "fraction of cloud to ground lightning strikes" ; - double fates_fire_drying_ratio ; - fates_fire_drying_ratio:units = "NA" ; - fates_fire_drying_ratio:long_name = "spitfire parameter, fire drying ratio for fuel moisture, alpha_FMC EQ 6 Thonicke et al 2010" ; - double fates_fire_durat_slope ; - fates_fire_durat_slope:units = "NA" ; - fates_fire_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; - double fates_fire_fdi_a ; - fates_fire_fdi_a:units = "NA" ; - fates_fire_fdi_a:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010" ; - double fates_fire_fdi_alpha ; - fates_fire_fdi_alpha:units = "NA" ; - fates_fire_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; - double fates_fire_fdi_b ; - fates_fire_fdi_b:units = "NA" ; - fates_fire_fdi_b:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010 " ; - double fates_fire_fuel_energy ; - fates_fire_fuel_energy:units = "kJ/kg" ; - fates_fire_fuel_energy:long_name = "spitfire parameter, heat content of fuel" ; - double fates_fire_max_durat ; - fates_fire_max_durat:units = "minutes" ; - fates_fire_max_durat:long_name = "spitfire parameter, fire maximum duration, Equation 14 Thonicke et al 2010" ; - double fates_fire_miner_damp ; - fates_fire_miner_damp:units = "NA" ; - fates_fire_miner_damp:long_name = "spitfire parameter, mineral-dampening coefficient EQ A1 Thonicke et al 2010 " ; - double fates_fire_miner_total ; - fates_fire_miner_total:units = "fraction" ; - fates_fire_miner_total:long_name = "spitfire parameter, total mineral content, Table A1 Thonicke et al 2010" ; - double fates_fire_nignitions ; - fates_fire_nignitions:units = "ignitions per year per km2" ; - fates_fire_nignitions:long_name = "number of annual ignitions per square km" ; - double fates_fire_part_dens ; - fates_fire_part_dens:units = "kg/m2" ; - fates_fire_part_dens:long_name = "spitfire parameter, oven dry particle density, Table A1 Thonicke et al 2010" ; - double fates_fire_threshold ; - fates_fire_threshold:units = "kW/m" ; - fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; - double fates_hydr_kmax_rsurf1 ; - fates_hydr_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; - fates_hydr_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; - double fates_hydr_kmax_rsurf2 ; - fates_hydr_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; - fates_hydr_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; - double fates_hydr_psi0 ; - fates_hydr_psi0:units = "MPa" ; - fates_hydr_psi0:long_name = "sapwood water potential at saturation" ; - double fates_hydr_psicap ; - fates_hydr_psicap:units = "MPa" ; - fates_hydr_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; - double fates_init_litter ; - fates_init_litter:units = "NA" ; - fates_init_litter:long_name = "Initialization value for litter pool in cold-start (NOT USED)" ; - double fates_leaf_stomatal_model ; - fates_leaf_stomatal_model:units = "unitless" ; - fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; - double fates_logging_coll_under_frac ; - fates_logging_coll_under_frac:units = "fraction" ; - fates_logging_coll_under_frac:long_name = "Fraction of stems killed in the understory when logging generates disturbance" ; - double fates_logging_collateral_frac ; - fates_logging_collateral_frac:units = "fraction" ; - fates_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; - double fates_logging_dbhmax ; - fates_logging_dbhmax:units = "cm" ; - fates_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; - double fates_logging_dbhmax_infra ; - fates_logging_dbhmax_infra:units = "cm" ; - fates_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; - double fates_logging_dbhmin ; - fates_logging_dbhmin:units = "cm" ; - fates_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; - double fates_logging_direct_frac ; - fates_logging_direct_frac:units = "fraction" ; - fates_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; - double fates_logging_event_code ; - fates_logging_event_code:units = "unitless" ; - fates_logging_event_code:long_name = "Integer code that options how logging events are structured" ; - double fates_logging_export_frac ; - fates_logging_export_frac:units = "fraction" ; - fates_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; - double fates_logging_mechanical_frac ; - fates_logging_mechanical_frac:units = "fraction" ; - fates_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; - double fates_maintresp_model ; - fates_maintresp_model:units = "unitless" ; - fates_maintresp_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991) (NOT USED)" ; - double fates_mort_disturb_frac ; - fates_mort_disturb_frac:units = "fraction" ; - fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; - double fates_mort_understorey_death ; - fates_mort_understorey_death:units = "fraction" ; - fates_mort_understorey_death:long_name = "fraction of plants in understorey cohort impacted by overstorey tree-fall" ; - double fates_patch_fusion_tol ; - fates_patch_fusion_tol:units = "unitless" ; - fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; - double fates_phen_a ; - fates_phen_a:units = "none" ; - fates_phen_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_b ; - fates_phen_b:units = "none" ; - fates_phen_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_c ; - fates_phen_c:units = "none" ; - fates_phen_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_chiltemp ; - fates_phen_chiltemp:units = "degrees C" ; - fates_phen_chiltemp:long_name = "chilling day counting threshold for vegetation" ; - double fates_phen_coldtemp ; - fates_phen_coldtemp:units = "degrees C" ; - fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; - double fates_phen_doff_time ; - fates_phen_doff_time:units = "days" ; - fates_phen_doff_time:long_name = "day threshold compared against days since leaves became off-allometry" ; - double fates_phen_drought_threshold ; - fates_phen_drought_threshold:units = "m3/m3" ; - fates_phen_drought_threshold:long_name = "liquid volume in soil layer, threashold for drought phenology" ; - double fates_phen_mindayson ; - fates_phen_mindayson:units = "days" ; - fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; - double fates_phen_ncolddayslim ; - fates_phen_ncolddayslim:units = "days" ; - fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; - double fates_photo_temp_acclim_timescale ; - fates_photo_temp_acclim_timescale:units = "days" ; - fates_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; - double fates_photo_tempsens_model ; - fates_photo_tempsens_model:units = "unitless" ; - fates_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; - double fates_q10_froz ; - fates_q10_froz:units = "unitless" ; - fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; - double fates_q10_mr ; - fates_q10_mr:units = "unitless" ; - fates_q10_mr:long_name = "Q10 for maintenance respiration" ; - double fates_soil_salinity ; - fates_soil_salinity:units = "ppt" ; - fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; - double fates_theta_cj_c3 ; - fates_theta_cj_c3:units = "unitless" ; - fates_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; - double fates_theta_cj_c4 ; - fates_theta_cj_c4:units = "unitless" ; - fates_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; - double fates_vai_top_bin_width ; - fates_vai_top_bin_width:units = "m2/m2" ; - fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer (NOT USED)" ; - double fates_vai_width_increase_factor ; - fates_vai_width_increase_factor:units = "unitless" ; - fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing) (NOT USED)" ; - -// global attributes: - :history = "This parameter file is maintained in version control\nSee https://github.com/NGEET/fates/blob/master/parameter_files/fates_params_default.cdl \nFor changes, use git blame \n" ; -data: - - fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; - - fates_history_coageclass_bin_edges = 0, 5 ; - - fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; - - fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, - 80, 90, 100 ; - - fates_hydr_htftype_node = 1, 1, 1, 1 ; - - fates_prt_organ_id = 1, 2, 3, 6 ; - - fates_pftname = - "broadleaf_evergreen_tropical_tree ", - "needleleaf_evergreen_extratrop_tree ", - "needleleaf_colddecid_extratrop_tree ", - "broadleaf_evergreen_extratrop_tree ", - "broadleaf_hydrodecid_tropical_tree ", - "broadleaf_colddecid_extratrop_tree ", - "broadleaf_evergreen_extratrop_shrub ", - "broadleaf_hydrodecid_extratrop_shrub ", - "broadleaf_colddecid_extratrop_shrub ", - "arctic_c3_grass ", - "cool_c3_grass ", - "c4_grass " ; - - fates_hydr_organname_node = - "leaf ", - "stem ", - "transporting root ", - "absorbing root " ; - - fates_litterclass_name = - "twig ", - "small branch ", - "large branch ", - "trunk ", - "dead leaves ", - "live grass " ; - - fates_prt_organ_name = - "leaf ", - "fine root ", - "sapwood ", - "structure " ; - - fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, - 1.2, 1.2, 1.2 ; - - fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, - 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; - - fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, - 0.572, 0.572, 0.572, 0.572 ; - - fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, - 1.94, 1.94, 1.94 ; - - fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, - 0.931, 0.931, 0.931, 0.931 ; - - fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6 ; - - fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, - 0.07, 0.07, 0.07 ; - - fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, - 1.3 ; - - fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, - 0.55, 0.55, 0.55 ; - - fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464 ; - - fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119 ; - - fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, - 0.64, 0.64, 0.64 ; - - fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, - 0.37, 0.37, 0.37 ; - - fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, - -999.9, -999.9, -999.9, -999.9, -999.9 ; - - fates_allom_dbh_maxheight = 90, 90, 90, 90, 90, 90, 3, 3, 2, 0.35, 0.35, 0.35 ; - - fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, - 0.8, 0.8, 0.8 ; - - fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1, 0.1 ; - - fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_zroot_k = 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 ; - - fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; - - fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100 ; - - fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1 ; - - fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100 ; - - fates_branch_turnover = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; - - fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; - - fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, - 0.67, 0.67 ; - - fates_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5 ; - - fates_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, - 280, 280 ; - - fates_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, - 0.14, 0.14, 0.14 ; - - fates_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, - 0.27, 0.27, 0.27 ; - - fates_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; - - fates_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_eca_vmax_nh4 = 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, - 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07 ; - - fates_eca_vmax_no3 = 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, - 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08 ; - - fates_eca_vmax_p = 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, - 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09 ; - - fates_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, - 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - - fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, - 0.2 ; - - fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, - 0.07, 0.07, 0.07, 0.07 ; - - fates_fire_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, - 0.95, 1, 1, 1 ; - - fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, - 0.775, 0.775, 0.775, 0.775, 0.775 ; - - fates_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; - - fates_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; - - fates_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - - fates_fr_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_fr_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25 ; - - fates_fr_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25 ; - - fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, - 0.11, 0.11 ; - - fates_hydr_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, - 2.5 ; - - fates_hydr_avuln_node = - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 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_hydr_epsil_node = - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - - fates_hydr_fcap_node = - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, - 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_hydr_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_hydr_kmax_node = - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; - - fates_hydr_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, - -1.5, -1.5, -1.5 ; - - fates_hydr_p50_node = - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25 ; - - fates_hydr_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, - 0.333, 0.333, 0.333, 0.333 ; - - fates_hydr_pinot_node = - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; - - fates_hydr_pitlp_node = - -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, - -1.67, -1.67, - -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, - -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, - -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; - - fates_hydr_resid_node = - 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, - 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - - fates_hydr_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, - 0.625, 0.625, 0.625, 0.625, 0.625 ; - - fates_hydr_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, - 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; - - fates_hydr_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; - - fates_hydr_thetas_node = - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; - - fates_hydr_vg_alpha_node = - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005 ; - - fates_hydr_vg_m_node = - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_hydr_vg_n_node = - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 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_leaf_c3psn = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ; - - fates_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, - 0.9, 0.75, 0.75, 0.75 ; - - fates_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.04, 0.04, 0.04 ; - - fates_leaf_jmaxha = 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, - 43540, 43540, 43540, 43540 ; - - fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, - 152040, 152040, 152040, 152040, 152040 ; - - fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, - 495 ; - - fates_leaf_long = - 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - - fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, - 0.03, 0.03, 0.03, 0.03, 0.03 ; - - fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, - 0.03, 0.03, 0.03, 0.03 ; - - fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, - 10000, 10000, 10000, 10000, 10000, 40000 ; - - fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - - fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, - 4.7, 2.2, 5.3, 1.6 ; - - fates_leaf_stor_priority = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, - 0.8, 0.8 ; - - fates_leaf_vcmax25top = - 50, 65, 39, 62, 41, 58, 62, 54, 54, 78, 78, 78 ; - - fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, - 65330, 65330, 65330, 65330 ; - - fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, - 149250, 149250, 149250, 149250, 149250 ; - - fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, - 485 ; - - fates_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, -0.23, - -0.23, -0.23 ; - - fates_lf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_lf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25 ; - - fates_lf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25 ; - - fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, - 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; - - fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, - 0.014, 0.014, 0.014, 0.014 ; - - fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -60, -10, -80, -80, - -20, 2.5 ; - - fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5 ; - - fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, - 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; - - fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - - fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6, 0.6 ; - - fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6, 0.6 ; - - fates_nfix1 = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_nfix2 = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5 ; - - fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; - - fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; - - fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; - - fates_phenflush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5 ; - - fates_prescribed_mortality_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, - 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; - - fates_prescribed_mortality_understory = 0.025, 0.025, 0.025, 0.025, 0.025, - 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; - - fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, - 0.4, 0.4, 0.4 ; - - fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, - 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; - - fates_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_prescribed_recruitment = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, - 0.02, 0.02, 0.02, 0.02, 0.02 ; - - fates_prt_alloc_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, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; - - fates_prt_nitr_stoich_p1 = - 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, - 0.0047, 0.0047, 0.0047 ; - - fates_prt_nitr_stoich_p2 = - 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, - 0.0047, 0.0047, 0.0047 ; - - fates_prt_phos_stoich_p1 = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, - 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, - 0.00047, 0.00047, 0.00047, 0.00047 ; - - fates_prt_phos_stoich_p2 = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, - 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, - 0.00047, 0.00047, 0.00047, 0.00047 ; - - fates_recruit_hgt_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, - 0.125, 0.125, 0.125 ; - - fates_recruit_initd = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, - 0.2 ; - - fates_rholnir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, 0.41, 0.28, - 0.28, 0.28 ; - - fates_rholvis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, 0.08, 0.05, 0.05, 0.05 ; - - fates_rhosnir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, 0.49, 0.53, - 0.53, 0.53 ; - - fates_rhosvis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.31, - 0.31, 0.31 ; - - fates_root_long = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - - fates_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; - - fates_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9 ; - - fates_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, 1.47, - 1.47, 1.47 ; - - fates_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, - 0.51, 0.51, 0.51, 0.51 ; - - fates_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5 ; - - fates_seed_suppl = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_senleaf_long_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, -255000, - -255000, -255000, -255000, -255000, -255000 ; - - fates_smpso = -66000, -66000, -66000, -66000, -66000, -66000, -66000, - -66000, -66000, -66000, -66000, -66000 ; - - fates_taulnir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, 0.43, 0.4, - 0.4, 0.4 ; - - fates_taulvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.05, - 0.05, 0.05 ; - - fates_tausnir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, - 0.001, 0.25, 0.25, 0.25 ; - - fates_tausvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, - 0.001, 0.12, 0.12, 0.12 ; - - fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, - 0.03, 0.03 ; - - fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; - - fates_turnover_carb_retrans = - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_turnover_nitr_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_turnover_phos_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_turnover_retrans_mode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, - 0.7 ; - - fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; - - fates_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, - 0.055, 0.055, 0.055 ; - - fates_hlm_pft_map = - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; - - fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; - - fates_fire_low_moisture_Coeff = 1.12, 1.09, 0.98, 0.8, 1.15, 1.15 ; - - fates_fire_low_moisture_Slope = 0.62, 0.72, 0.85, 0.8, 0.62, 0.62 ; - - fates_fire_mid_moisture = 0.72, 0.51, 0.38, 1, 0.8, 0.8 ; - - fates_fire_mid_moisture_Coeff = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; - - fates_fire_mid_moisture_Slope = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; - - fates_fire_min_moisture = 0.18, 0.12, 0, 0, 0.24, 0.24 ; - - fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; - - fates_max_decomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; - - fates_CWD_frac = 0.045, 0.075, 0.21, 0.67 ; - - fates_base_mr_20 = 2.52e-06 ; - - fates_canopy_closure_thresh = 0.8 ; - - fates_cohort_age_fusion_tol = 0.08 ; - - fates_cohort_size_fusion_tol = 0.08 ; - - fates_comp_excln = 3 ; - - fates_cwd_fcel = 0.76 ; - - fates_cwd_flig = 0.24 ; - - fates_dev_arbitrary = _ ; - - fates_eca_plant_escalar = 1.25e-05 ; - - fates_fire_active_crown_fire = 0 ; - - fates_fire_cg_strikes = 0.2 ; - - fates_fire_drying_ratio = 66000 ; - - fates_fire_durat_slope = -11.06 ; - - fates_fire_fdi_a = 17.62 ; - - fates_fire_fdi_alpha = 0.00037 ; - - fates_fire_fdi_b = 243.12 ; - - fates_fire_fuel_energy = 18000 ; - - fates_fire_max_durat = 240 ; - - fates_fire_miner_damp = 0.41739 ; - - fates_fire_miner_total = 0.055 ; - - fates_fire_nignitions = 15 ; - - fates_fire_part_dens = 513 ; - - fates_fire_threshold = 50 ; - - fates_hydr_kmax_rsurf1 = 20 ; - - fates_hydr_kmax_rsurf2 = 0.0001 ; - - fates_hydr_psi0 = 0 ; - - fates_hydr_psicap = -0.6 ; - - fates_init_litter = 0.05 ; - - fates_leaf_stomatal_model = 1 ; - - fates_logging_coll_under_frac = 0.55983 ; - - fates_logging_collateral_frac = 0.05 ; - - fates_logging_dbhmax = _ ; - - fates_logging_dbhmax_infra = 35 ; - - fates_logging_dbhmin = 50 ; - - fates_logging_direct_frac = 0.15 ; - - fates_logging_event_code = -30 ; - - fates_logging_export_frac = 0.8 ; - - fates_logging_mechanical_frac = 0.05 ; - - fates_maintresp_model = 1 ; - - fates_mort_disturb_frac = 1 ; - - fates_mort_understorey_death = 0.55983 ; - - fates_patch_fusion_tol = 0.05 ; - - fates_phen_a = -68 ; - - fates_phen_b = 638 ; - - fates_phen_c = -0.01 ; - - fates_phen_chiltemp = 5 ; - - fates_phen_coldtemp = 7.5 ; - - fates_phen_doff_time = 100 ; - - fates_phen_drought_threshold = 0.15 ; - - fates_phen_mindayson = 90 ; - - fates_phen_ncolddayslim = 5 ; - - fates_photo_temp_acclim_timescale = 30 ; - - fates_photo_tempsens_model = 1 ; - - fates_q10_froz = 1.5 ; - - fates_q10_mr = 1.5 ; - - fates_soil_salinity = 0.4 ; - - fates_theta_cj_c3 = 0.999 ; - - fates_theta_cj_c4 = 0.999 ; - - fates_vai_top_bin_width = 1 ; - - fates_vai_width_increase_factor = 1 ; -} diff --git a/parameter_files/fates_params_seed-dispersal.cdl b/parameter_files/fates_params_seed-dispersal.cdl deleted file mode 100644 index 6335326e89..0000000000 --- a/parameter_files/fates_params_seed-dispersal.cdl +++ /dev/null @@ -1,1550 +0,0 @@ -netcdf tmp { -dimensions: - fates_NCWD = 4 ; - fates_history_age_bins = 7 ; - fates_history_coage_bins = 2 ; - fates_history_damage_bins = 2 ; - fates_history_height_bins = 6 ; - fates_history_size_bins = 13 ; - fates_hlm_pftno = 14 ; - fates_hydr_organs = 4 ; - fates_leafage_class = 1 ; - fates_litterclass = 6 ; - fates_pft = 12 ; - fates_plant_organs = 4 ; - fates_string_length = 60 ; -variables: - double fates_history_ageclass_bin_edges(fates_history_age_bins) ; - fates_history_ageclass_bin_edges:units = "yr" ; - fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; - double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; - fates_history_coageclass_bin_edges:units = "years" ; - fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; - double fates_history_height_bin_edges(fates_history_height_bins) ; - fates_history_height_bin_edges:units = "m" ; - fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; - double fates_history_damage_bin_edges(fates_history_damage_bins) ; - fates_history_damage_bin_edges:units = "% crown loss" ; - fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; - double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; - fates_history_sizeclass_bin_edges:units = "cm" ; - fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; - double fates_alloc_organ_id(fates_plant_organs) ; - fates_alloc_organ_id:units = "unitless" ; - fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; - double fates_hydro_htftype_node(fates_hydr_organs) ; - fates_hydro_htftype_node:units = "unitless" ; - fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; - char fates_pftname(fates_pft, fates_string_length) ; - fates_pftname:units = "unitless - string" ; - fates_pftname:long_name = "Description of plant type" ; - char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; - fates_hydro_organ_name:units = "unitless - string" ; - fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; - char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; - fates_alloc_organ_name:units = "unitless - string" ; - fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; - 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" ; - 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" ; - double fates_alloc_storage_cushion(fates_pft) ; - fates_alloc_storage_cushion:units = "fraction" ; - fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; - double fates_alloc_store_priority_frac(fates_pft) ; - fates_alloc_store_priority_frac:units = "unitless" ; - fates_alloc_store_priority_frac:long_name = "for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage" ; - double fates_allom_agb1(fates_pft) ; - fates_allom_agb1:units = "variable" ; - fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; - double fates_allom_agb2(fates_pft) ; - fates_allom_agb2:units = "variable" ; - fates_allom_agb2:long_name = "Parameter 2 for agb allometry" ; - double fates_allom_agb3(fates_pft) ; - fates_allom_agb3:units = "variable" ; - fates_allom_agb3:long_name = "Parameter 3 for agb allometry" ; - double fates_allom_agb4(fates_pft) ; - fates_allom_agb4:units = "variable" ; - fates_allom_agb4:long_name = "Parameter 4 for agb allometry" ; - double fates_allom_agb_frac(fates_pft) ; - fates_allom_agb_frac:units = "fraction" ; - fates_allom_agb_frac:long_name = "Fraction of woody biomass that is above ground" ; - double fates_allom_amode(fates_pft) ; - fates_allom_amode:units = "index" ; - fates_allom_amode:long_name = "AGB allometry function index." ; - double fates_allom_blca_expnt_diff(fates_pft) ; - fates_allom_blca_expnt_diff:units = "unitless" ; - fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; - double fates_allom_cmode(fates_pft) ; - fates_allom_cmode:units = "index" ; - fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; - double fates_allom_crown_depth_frac(fates_pft) ; - fates_allom_crown_depth_frac:units = "fraction" ; - fates_allom_crown_depth_frac:long_name = "the depth of a cohort crown as a fraction of its height" ; - double fates_allom_d2bl1(fates_pft) ; - fates_allom_d2bl1:units = "variable" ; - fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; - double fates_allom_d2bl2(fates_pft) ; - fates_allom_d2bl2:units = "variable" ; - fates_allom_d2bl2:long_name = "Parameter 2 for d2bl allometry" ; - double fates_allom_d2bl3(fates_pft) ; - fates_allom_d2bl3:units = "unitless" ; - fates_allom_d2bl3:long_name = "Parameter 3 for d2bl allometry" ; - double fates_allom_d2ca_coefficient_max(fates_pft) ; - fates_allom_d2ca_coefficient_max:units = "m2 cm^(-1/beta)" ; - fates_allom_d2ca_coefficient_max:long_name = "max (savanna) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; - double fates_allom_d2ca_coefficient_min(fates_pft) ; - fates_allom_d2ca_coefficient_min:units = "m2 cm^(-1/beta)" ; - fates_allom_d2ca_coefficient_min:long_name = "min (forest) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; - double fates_allom_d2h1(fates_pft) ; - fates_allom_d2h1:units = "variable" ; - fates_allom_d2h1:long_name = "Parameter 1 for d2h allometry (intercept, or c)" ; - double fates_allom_d2h2(fates_pft) ; - fates_allom_d2h2:units = "variable" ; - fates_allom_d2h2:long_name = "Parameter 2 for d2h allometry (slope, or m)" ; - double fates_allom_d2h3(fates_pft) ; - fates_allom_d2h3:units = "variable" ; - fates_allom_d2h3:long_name = "Parameter 3 for d2h allometry (optional)" ; - double fates_allom_dbh_maxheight(fates_pft) ; - fates_allom_dbh_maxheight:units = "cm" ; - fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; - double fates_allom_fmode(fates_pft) ; - fates_allom_fmode:units = "index" ; - fates_allom_fmode:long_name = "fine root biomass allometry function index." ; - double fates_allom_fnrt_prof_a(fates_pft) ; - fates_allom_fnrt_prof_a:units = "unitless" ; - fates_allom_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; - double fates_allom_fnrt_prof_b(fates_pft) ; - fates_allom_fnrt_prof_b:units = "unitless" ; - fates_allom_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; - double fates_allom_fnrt_prof_mode(fates_pft) ; - fates_allom_fnrt_prof_mode:units = "index" ; - fates_allom_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; - double fates_allom_frbstor_repro(fates_pft) ; - fates_allom_frbstor_repro:units = "fraction" ; - fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; - double fates_allom_hmode(fates_pft) ; - fates_allom_hmode:units = "index" ; - fates_allom_hmode:long_name = "height allometry function index." ; - double fates_allom_l2fr(fates_pft) ; - fates_allom_l2fr:units = "gC/gC" ; - fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; - double fates_allom_la_per_sa_int(fates_pft) ; - fates_allom_la_per_sa_int:units = "m2/cm2" ; - fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; - double fates_allom_la_per_sa_slp(fates_pft) ; - fates_allom_la_per_sa_slp:units = "m2/cm2/m" ; - fates_allom_la_per_sa_slp:long_name = "Leaf area per sapwood area rate of change with height, slope (optional)" ; - double fates_allom_lmode(fates_pft) ; - fates_allom_lmode:units = "index" ; - fates_allom_lmode:long_name = "leaf biomass allometry function index." ; - double fates_allom_sai_scaler(fates_pft) ; - fates_allom_sai_scaler:units = "m2/m2" ; - fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; - double fates_allom_smode(fates_pft) ; - fates_allom_smode:units = "index" ; - fates_allom_smode:long_name = "sapwood allometry function index." ; - double fates_allom_stmode(fates_pft) ; - fates_allom_stmode:units = "index" ; - fates_allom_stmode:long_name = "storage allometry function index." ; - double fates_allom_zroot_k(fates_pft) ; - fates_allom_zroot_k:units = "unitless" ; - fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; - double fates_allom_zroot_max_dbh(fates_pft) ; - fates_allom_zroot_max_dbh:units = "cm" ; - fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; - double fates_allom_zroot_max_z(fates_pft) ; - fates_allom_zroot_max_z:units = "m" ; - fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; - double fates_allom_zroot_min_dbh(fates_pft) ; - fates_allom_zroot_min_dbh:units = "cm" ; - fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; - double fates_allom_zroot_min_z(fates_pft) ; - fates_allom_zroot_min_z:units = "m" ; - fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; - double fates_c2b(fates_pft) ; - fates_c2b:units = "ratio" ; - fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; - double fates_cnp_eca_alpha_ptase(fates_pft) ; - fates_cnp_eca_alpha_ptase:units = "g/m3" ; - fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; - double fates_cnp_eca_decompmicc(fates_pft) ; - fates_cnp_eca_decompmicc:units = "gC/m3" ; - fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; - double fates_cnp_eca_km_nh4(fates_pft) ; - fates_cnp_eca_km_nh4:units = "gN/m3" ; - fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; - double fates_cnp_eca_km_no3(fates_pft) ; - fates_cnp_eca_km_no3:units = "gN/m3" ; - fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; - double fates_cnp_eca_km_p(fates_pft) ; - fates_cnp_eca_km_p:units = "gP/m3" ; - fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; - double fates_cnp_eca_km_ptase(fates_pft) ; - fates_cnp_eca_km_ptase:units = "gP/m3" ; - fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; - double fates_cnp_eca_lambda_ptase(fates_pft) ; - fates_cnp_eca_lambda_ptase:units = "g/m3" ; - fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; - double fates_cnp_eca_vmax_nh4(fates_pft) ; - fates_cnp_eca_vmax_nh4:units = "gN/gC/s" ; - fates_cnp_eca_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA)" ; - double fates_cnp_eca_vmax_no3(fates_pft) ; - fates_cnp_eca_vmax_no3:units = "gN/gC/s" ; - fates_cnp_eca_vmax_no3:long_name = "maximum production rate for plant no3 uptake (ECA)" ; - double fates_cnp_eca_vmax_ptase(fates_pft) ; - fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; - fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; - double fates_cnp_fnrt_adapt_tscale(fates_pft) ; - fates_cnp_fnrt_adapt_tscale:units = "days" ; - fates_cnp_fnrt_adapt_tscale:long_name = "Number of days that is shortest possible doubling period for fine-root adaptation to C/N/P balance" ; - double fates_cnp_nfix1(fates_pft) ; - fates_cnp_nfix1:units = "NA" ; - fates_cnp_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; - double fates_cnp_nitr_store_ratio(fates_pft) ; - fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; - fates_cnp_nitr_store_ratio:long_name = "storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code)" ; - double fates_cnp_phos_store_ratio(fates_pft) ; - fates_cnp_phos_store_ratio:units = "(gP/gP)" ; - fates_cnp_phos_store_ratio:long_name = "storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code)" ; - double fates_cnp_prescribed_nuptake(fates_pft) ; - fates_cnp_prescribed_nuptake:units = "fraction" ; - fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; - double fates_cnp_prescribed_puptake(fates_pft) ; - fates_cnp_prescribed_puptake:units = "fraction" ; - fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; - double fates_cnp_rd_vmax_n(fates_pft) ; - fates_cnp_rd_vmax_n:units = "gN/gC/s" ; - fates_cnp_rd_vmax_n:long_name = "maximum production rate for compbined (NH4+NO3) uptake (RD)" ; - double fates_cnp_store_ovrflw_frac(fates_pft) ; - fates_cnp_store_ovrflw_frac:units = "fraction" ; - fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; - fates_cnp_store_ovrflw_frac:use_case = "None" ; - double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; - fates_cnp_turnover_nitr_retrans:units = "fraction" ; - fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; - double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; - fates_cnp_turnover_phos_retrans:units = "fraction" ; - fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; - double fates_cnp_vmax_p(fates_pft) ; - fates_cnp_vmax_p:units = "gP/gC/s" ; - fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; - double fates_damage_frac(fates_pft) ; - fates_damage_frac:units = "fraction" ; - fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; - double fates_damage_mort_p1(fates_pft) ; - fates_damage_mort_p1:units = "fraction" ; - fates_damage_mort_p1:long_name = "inflection point of damage mortality function, a value of 0.8 means 50% mortality with 80% loss of crown, turn off with a large number" ; - double fates_damage_mort_p2(fates_pft) ; - fates_damage_mort_p2:units = "unitless" ; - fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; - 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_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" ; - double fates_fire_alpha_SH(fates_pft) ; - fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; - fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; - double fates_fire_bark_scaler(fates_pft) ; - fates_fire_bark_scaler:units = "fraction" ; - fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; - double fates_fire_crown_kill(fates_pft) ; - fates_fire_crown_kill:units = "NA" ; - fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; - double fates_frag_fnrt_fcel(fates_pft) ; - fates_frag_fnrt_fcel:units = "fraction" ; - fates_frag_fnrt_fcel:long_name = "Fine root litter cellulose fraction" ; - double fates_frag_fnrt_flab(fates_pft) ; - fates_frag_fnrt_flab:units = "fraction" ; - fates_frag_fnrt_flab:long_name = "Fine root litter labile fraction" ; - double fates_frag_fnrt_flig(fates_pft) ; - fates_frag_fnrt_flig:units = "fraction" ; - fates_frag_fnrt_flig:long_name = "Fine root litter lignin fraction" ; - double fates_frag_leaf_fcel(fates_pft) ; - fates_frag_leaf_fcel:units = "fraction" ; - fates_frag_leaf_fcel:long_name = "Leaf litter cellulose fraction" ; - double fates_frag_leaf_flab(fates_pft) ; - fates_frag_leaf_flab:units = "fraction" ; - fates_frag_leaf_flab:long_name = "Leaf litter labile fraction" ; - double fates_frag_leaf_flig(fates_pft) ; - fates_frag_leaf_flig:units = "fraction" ; - fates_frag_leaf_flig:long_name = "Leaf litter lignin fraction" ; - double fates_frag_seed_decay_rate(fates_pft) ; - fates_frag_seed_decay_rate:units = "yr-1" ; - fates_frag_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; - double fates_grperc(fates_pft) ; - fates_grperc:units = "unitless" ; - fates_grperc:long_name = "Growth respiration factor" ; - double fates_hydro_avuln_gs(fates_pft) ; - fates_hydro_avuln_gs:units = "unitless" ; - fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; - double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; - fates_hydro_avuln_node:units = "unitless" ; - fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; - double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; - fates_hydro_epsil_node:units = "MPa" ; - fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; - double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; - fates_hydro_fcap_node:units = "unitless" ; - fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; - double fates_hydro_k_lwp(fates_pft) ; - fates_hydro_k_lwp:units = "unitless" ; - fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; - double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; - fates_hydro_kmax_node:units = "kg/MPa/m/s" ; - fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; - double fates_hydro_p50_gs(fates_pft) ; - fates_hydro_p50_gs:units = "MPa" ; - fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; - double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; - fates_hydro_p50_node:units = "MPa" ; - fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; - double fates_hydro_p_taper(fates_pft) ; - fates_hydro_p_taper:units = "unitless" ; - fates_hydro_p_taper:long_name = "xylem taper exponent" ; - double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; - fates_hydro_pinot_node:units = "MPa" ; - fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; - double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; - fates_hydro_pitlp_node:units = "MPa" ; - fates_hydro_pitlp_node:long_name = "turgor loss point" ; - double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; - fates_hydro_resid_node:units = "cm3/cm3" ; - fates_hydro_resid_node:long_name = "residual water conent" ; - double fates_hydro_rfrac_stem(fates_pft) ; - fates_hydro_rfrac_stem:units = "fraction" ; - fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; - double fates_hydro_rs2(fates_pft) ; - fates_hydro_rs2:units = "m" ; - fates_hydro_rs2:long_name = "absorbing root radius" ; - double fates_hydro_srl(fates_pft) ; - fates_hydro_srl:units = "m g-1" ; - fates_hydro_srl:long_name = "specific root length" ; - double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; - fates_hydro_thetas_node:units = "cm3/cm3" ; - fates_hydro_thetas_node:long_name = "saturated water content" ; - double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; - fates_hydro_vg_alpha_node:units = "MPa-1" ; - fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; - double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; - fates_hydro_vg_m_node:units = "unitless" ; - fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; - 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_leaf_c3psn(fates_pft) ; - fates_leaf_c3psn:units = "flag" ; - fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; - double fates_leaf_jmaxha(fates_pft) ; - fates_leaf_jmaxha:units = "J/mol" ; - fates_leaf_jmaxha:long_name = "activation energy for jmax" ; - double fates_leaf_jmaxhd(fates_pft) ; - fates_leaf_jmaxhd:units = "J/mol" ; - fates_leaf_jmaxhd:long_name = "deactivation energy for jmax" ; - double fates_leaf_jmaxse(fates_pft) ; - fates_leaf_jmaxse:units = "J/mol/K" ; - fates_leaf_jmaxse:long_name = "entropy term for jmax" ; - double fates_leaf_slamax(fates_pft) ; - fates_leaf_slamax:units = "m^2/gC" ; - fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; - double fates_leaf_slatop(fates_pft) ; - fates_leaf_slatop:units = "m^2/gC" ; - fates_leaf_slatop:long_name = "Specific Leaf Area (SLA) at top of canopy, projected area basis" ; - double fates_leaf_stomatal_intercept(fates_pft) ; - fates_leaf_stomatal_intercept:units = "umol H2O/m**2/s" ; - fates_leaf_stomatal_intercept:long_name = "Minimum unstressed stomatal conductance for Ball-Berry model and Medlyn model" ; - double fates_leaf_stomatal_slope_ballberry(fates_pft) ; - fates_leaf_stomatal_slope_ballberry:units = "unitless" ; - fates_leaf_stomatal_slope_ballberry:long_name = "stomatal slope parameter, as per Ball-Berry" ; - double fates_leaf_stomatal_slope_medlyn(fates_pft) ; - fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; - fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; - double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; - fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; - fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; - double fates_leaf_vcmaxha(fates_pft) ; - fates_leaf_vcmaxha:units = "J/mol" ; - fates_leaf_vcmaxha:long_name = "activation energy for vcmax" ; - double fates_leaf_vcmaxhd(fates_pft) ; - fates_leaf_vcmaxhd:units = "J/mol" ; - fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax" ; - double fates_leaf_vcmaxse(fates_pft) ; - fates_leaf_vcmaxse:units = "J/mol/K" ; - fates_leaf_vcmaxse:long_name = "entropy term for vcmax" ; - double fates_maintresp_reduction_curvature(fates_pft) ; - fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; - fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; - double fates_maintresp_reduction_intercept(fates_pft) ; - fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; - fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; - double fates_mort_bmort(fates_pft) ; - fates_mort_bmort:units = "1/yr" ; - fates_mort_bmort:long_name = "background mortality rate" ; - double fates_mort_freezetol(fates_pft) ; - fates_mort_freezetol:units = "degrees C" ; - fates_mort_freezetol:long_name = "minimum temperature tolerance" ; - double fates_mort_hf_flc_threshold(fates_pft) ; - fates_mort_hf_flc_threshold:units = "fraction" ; - fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; - double fates_mort_hf_sm_threshold(fates_pft) ; - fates_mort_hf_sm_threshold:units = "unitless" ; - fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; - double fates_mort_ip_age_senescence(fates_pft) ; - fates_mort_ip_age_senescence:units = "years" ; - fates_mort_ip_age_senescence:long_name = "Mortality cohort age senescence inflection point. If _ this mortality term is off. Setting this value turns on age dependent mortality. " ; - double fates_mort_ip_size_senescence(fates_pft) ; - fates_mort_ip_size_senescence:units = "dbh cm" ; - fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; - double fates_mort_prescribed_canopy(fates_pft) ; - fates_mort_prescribed_canopy:units = "1/yr" ; - fates_mort_prescribed_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; - double fates_mort_prescribed_understory(fates_pft) ; - fates_mort_prescribed_understory:units = "1/yr" ; - fates_mort_prescribed_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; - double fates_mort_r_age_senescence(fates_pft) ; - fates_mort_r_age_senescence:units = "mortality rate year^-1" ; - fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; - double fates_mort_r_size_senescence(fates_pft) ; - fates_mort_r_size_senescence:units = "mortality rate dbh^-1" ; - fates_mort_r_size_senescence:long_name = "Mortality dbh senescence rate of change. Sensible range is around 0.03-0.06. Larger values give steeper mortality curves." ; - double fates_mort_scalar_coldstress(fates_pft) ; - fates_mort_scalar_coldstress:units = "1/yr" ; - fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; - double fates_mort_scalar_cstarvation(fates_pft) ; - fates_mort_scalar_cstarvation:units = "1/yr" ; - fates_mort_scalar_cstarvation:long_name = "maximum mortality rate from carbon starvation" ; - double fates_mort_scalar_hydrfailure(fates_pft) ; - fates_mort_scalar_hydrfailure:units = "1/yr" ; - fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; - double fates_nonhydro_smpsc(fates_pft) ; - fates_nonhydro_smpsc:units = "mm" ; - fates_nonhydro_smpsc:long_name = "Soil water potential at full stomatal closure" ; - double fates_nonhydro_smpso(fates_pft) ; - fates_nonhydro_smpso:units = "mm" ; - fates_nonhydro_smpso:long_name = "Soil water potential at full stomatal opening" ; - double fates_phen_cold_size_threshold(fates_pft) ; - fates_phen_cold_size_threshold:units = "cm" ; - fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; - double fates_phen_evergreen(fates_pft) ; - fates_phen_evergreen:units = "logical flag" ; - fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; - double fates_phen_flush_fraction(fates_pft) ; - fates_phen_flush_fraction:units = "fraction" ; - fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; - double fates_phen_fnrt_drop_frac(fates_pft) ; - fates_phen_fnrt_drop_frac:units = "fraction" ; - fates_phen_fnrt_drop_frac:long_name = "fraction of fine roots to drop during drought or cold" ; - double fates_phen_season_decid(fates_pft) ; - fates_phen_season_decid:units = "logical flag" ; - fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; - double fates_phen_stem_drop_fraction(fates_pft) ; - fates_phen_stem_drop_fraction:units = "fraction" ; - fates_phen_stem_drop_fraction:long_name = "fraction of stems to drop for non-woody species during drought/cold" ; - double fates_phen_stress_decid(fates_pft) ; - fates_phen_stress_decid:units = "logical flag" ; - fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; - double fates_prescribed_npp_canopy(fates_pft) ; - fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; - fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; - double fates_prescribed_npp_understory(fates_pft) ; - fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; - fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; - double fates_rad_leaf_clumping_index(fates_pft) ; - fates_rad_leaf_clumping_index:units = "fraction (0-1)" ; - fates_rad_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; - double fates_rad_leaf_rhonir(fates_pft) ; - fates_rad_leaf_rhonir:units = "fraction" ; - fates_rad_leaf_rhonir:long_name = "Leaf reflectance: near-IR" ; - double fates_rad_leaf_rhovis(fates_pft) ; - fates_rad_leaf_rhovis:units = "fraction" ; - fates_rad_leaf_rhovis:long_name = "Leaf reflectance: visible" ; - double fates_rad_leaf_taunir(fates_pft) ; - fates_rad_leaf_taunir:units = "fraction" ; - fates_rad_leaf_taunir:long_name = "Leaf transmittance: near-IR" ; - double fates_rad_leaf_tauvis(fates_pft) ; - fates_rad_leaf_tauvis:units = "fraction" ; - fates_rad_leaf_tauvis:long_name = "Leaf transmittance: visible" ; - double fates_rad_leaf_xl(fates_pft) ; - fates_rad_leaf_xl:units = "unitless" ; - fates_rad_leaf_xl:long_name = "Leaf/stem orientation index" ; - double fates_rad_stem_rhonir(fates_pft) ; - fates_rad_stem_rhonir:units = "fraction" ; - fates_rad_stem_rhonir:long_name = "Stem reflectance: near-IR" ; - double fates_rad_stem_rhovis(fates_pft) ; - fates_rad_stem_rhovis:units = "fraction" ; - fates_rad_stem_rhovis:long_name = "Stem reflectance: visible" ; - double fates_rad_stem_taunir(fates_pft) ; - fates_rad_stem_taunir:units = "fraction" ; - fates_rad_stem_taunir:long_name = "Stem transmittance: near-IR" ; - double fates_rad_stem_tauvis(fates_pft) ; - fates_rad_stem_tauvis:units = "fraction" ; - fates_rad_stem_tauvis:long_name = "Stem transmittance: visible" ; - double fates_recruit_height_min(fates_pft) ; - fates_recruit_height_min:units = "m" ; - fates_recruit_height_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; - double fates_recruit_init_density(fates_pft) ; - fates_recruit_init_density:units = "stems/m2" ; - fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation" ; - double fates_recruit_prescribed_rate(fates_pft) ; - fates_recruit_prescribed_rate:units = "n/yr" ; - fates_recruit_prescribed_rate:long_name = "recruitment rate for prescribed physiology mode" ; - double fates_recruit_seed_alloc(fates_pft) ; - fates_recruit_seed_alloc:units = "fraction" ; - fates_recruit_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; - double fates_recruit_seed_alloc_mature(fates_pft) ; - fates_recruit_seed_alloc_mature:units = "fraction" ; - fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; - double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; - fates_recruit_seed_dbh_repro_threshold:units = "cm" ; - fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter (if any) where the plant will start extra clonal allocation to the seed pool" ; - double fates_recruit_seed_germination_rate(fates_pft) ; - fates_recruit_seed_germination_rate:units = "yr-1" ; - fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; - double fates_recruit_seed_supplement(fates_pft) ; - fates_recruit_seed_supplement:units = "KgC/m2/yr" ; - fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; - double fates_seed_dispersal_param_A(fates_pft) ; - fates_seed_dispersal_param_A:units = "unitless" ; - fates_seed_dispersal_param_A:long_name = "seed dispersal scale parameter" ; - fates_seed_dispersal_param_A:use_case = "None" ; - double fates_seed_dispersal_param_B(fates_pft) ; - fates_seed_dispersal_param_B:units = "unitless" ; - fates_seed_dispersal_param_B:long_name = "seed dispersal shape parameter" ; - fates_seed_dispersal_param_B:use_case = "None" ; - double fates_stoich_nitr(fates_plant_organs, fates_pft) ; - fates_stoich_nitr:units = "gN/gC" ; - fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; - double fates_stoich_phos(fates_plant_organs, fates_pft) ; - fates_stoich_phos:units = "gP/gC" ; - fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; - double fates_trim_inc(fates_pft) ; - fates_trim_inc:units = "m2/m2" ; - fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; - double fates_trim_limit(fates_pft) ; - fates_trim_limit:units = "m2/m2" ; - fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; - double fates_turb_displar(fates_pft) ; - fates_turb_displar:units = "unitless" ; - fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; - double fates_turb_leaf_diameter(fates_pft) ; - fates_turb_leaf_diameter:units = "m" ; - fates_turb_leaf_diameter:long_name = "Characteristic leaf dimension" ; - double fates_turb_z0mr(fates_pft) ; - fates_turb_z0mr:units = "unitless" ; - fates_turb_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; - double fates_turnover_branch(fates_pft) ; - fates_turnover_branch:units = "yr" ; - fates_turnover_branch:long_name = "turnover time of branches" ; - double fates_turnover_fnrt(fates_pft) ; - fates_turnover_fnrt:units = "yr" ; - fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; - double fates_turnover_leaf(fates_leafage_class, fates_pft) ; - fates_turnover_leaf:units = "yr" ; - fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; - double fates_turnover_senleaf_fdrought(fates_pft) ; - fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; - fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; - double fates_wood_density(fates_pft) ; - fates_wood_density:units = "g/cm3" ; - fates_wood_density:long_name = "mean density of woody tissue in plant" ; - double fates_woody(fates_pft) ; - fates_woody:units = "logical flag" ; - fates_woody:long_name = "Binary woody lifeform flag" ; - double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; - fates_hlm_pft_map:units = "area fraction" ; - fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; - double fates_fire_FBD(fates_litterclass) ; - fates_fire_FBD:units = "kg Biomass/m3" ; - fates_fire_FBD:long_name = "fuel bulk density" ; - double fates_fire_low_moisture_Coeff(fates_litterclass) ; - fates_fire_low_moisture_Coeff:units = "NA" ; - fates_fire_low_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_low_moisture_Slope(fates_litterclass) ; - fates_fire_low_moisture_Slope:units = "NA" ; - fates_fire_low_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_mid_moisture(fates_litterclass) ; - fates_fire_mid_moisture:units = "NA" ; - fates_fire_mid_moisture:long_name = "spitfire litter moisture threshold to be considered medium dry" ; - double fates_fire_mid_moisture_Coeff(fates_litterclass) ; - fates_fire_mid_moisture_Coeff:units = "NA" ; - fates_fire_mid_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_mid_moisture_Slope(fates_litterclass) ; - fates_fire_mid_moisture_Slope:units = "NA" ; - fates_fire_mid_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_min_moisture(fates_litterclass) ; - fates_fire_min_moisture:units = "NA" ; - fates_fire_min_moisture:long_name = "spitfire litter moisture threshold to be considered very dry" ; - double fates_fire_SAV(fates_litterclass) ; - fates_fire_SAV:units = "cm-1" ; - fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; - double fates_frag_maxdecomp(fates_litterclass) ; - fates_frag_maxdecomp:units = "yr-1" ; - fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; - 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_base_mr_20 ; - fates_base_mr_20:units = "gC/gN/s" ; - fates_base_mr_20:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; - 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" ; - double fates_cnp_eca_plant_escalar ; - fates_cnp_eca_plant_escalar:units = "" ; - fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; - double fates_cohort_age_fusion_tol ; - fates_cohort_age_fusion_tol:units = "unitless" ; - fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; - double fates_cohort_size_fusion_tol ; - fates_cohort_size_fusion_tol:units = "unitless" ; - fates_cohort_size_fusion_tol:long_name = "minimum fraction in difference in dbh between cohorts" ; - double fates_comp_excln ; - fates_comp_excln:units = "none" ; - fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; - double fates_damage_canopy_layer_code ; - fates_damage_canopy_layer_code:units = "unitless" ; - fates_damage_canopy_layer_code:long_name = "Integer code that decides whether damage affects canopy trees (1), understory trees (2)" ; - double fates_damage_event_code ; - fates_damage_event_code:units = "unitless" ; - fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; - double fates_dev_arbitrary ; - fates_dev_arbitrary:units = "unknown" ; - fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; - double fates_fire_active_crown_fire ; - fates_fire_active_crown_fire:units = "0 or 1" ; - fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; - double fates_fire_cg_strikes ; - fates_fire_cg_strikes:units = "fraction (0-1)" ; - fates_fire_cg_strikes:long_name = "fraction of cloud to ground lightning strikes" ; - double fates_fire_drying_ratio ; - fates_fire_drying_ratio:units = "NA" ; - fates_fire_drying_ratio:long_name = "spitfire parameter, fire drying ratio for fuel moisture, alpha_FMC EQ 6 Thonicke et al 2010" ; - double fates_fire_durat_slope ; - fates_fire_durat_slope:units = "NA" ; - fates_fire_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; - double fates_fire_fdi_a ; - fates_fire_fdi_a:units = "NA" ; - fates_fire_fdi_a:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010" ; - double fates_fire_fdi_alpha ; - fates_fire_fdi_alpha:units = "NA" ; - fates_fire_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; - double fates_fire_fdi_b ; - fates_fire_fdi_b:units = "NA" ; - fates_fire_fdi_b:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010 " ; - double fates_fire_fuel_energy ; - fates_fire_fuel_energy:units = "kJ/kg" ; - fates_fire_fuel_energy:long_name = "spitfire parameter, heat content of fuel" ; - double fates_fire_max_durat ; - fates_fire_max_durat:units = "minutes" ; - fates_fire_max_durat:long_name = "spitfire parameter, fire maximum duration, Equation 14 Thonicke et al 2010" ; - double fates_fire_miner_damp ; - fates_fire_miner_damp:units = "NA" ; - fates_fire_miner_damp:long_name = "spitfire parameter, mineral-dampening coefficient EQ A1 Thonicke et al 2010 " ; - double fates_fire_miner_total ; - fates_fire_miner_total:units = "fraction" ; - fates_fire_miner_total:long_name = "spitfire parameter, total mineral content, Table A1 Thonicke et al 2010" ; - double fates_fire_nignitions ; - fates_fire_nignitions:units = "ignitions per year per km2" ; - fates_fire_nignitions:long_name = "number of annual ignitions per square km" ; - double fates_fire_part_dens ; - fates_fire_part_dens:units = "kg/m2" ; - fates_fire_part_dens:long_name = "spitfire parameter, oven dry particle density, Table A1 Thonicke et al 2010" ; - double fates_fire_threshold ; - fates_fire_threshold:units = "kW/m" ; - fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; - double fates_frag_cwd_fcel ; - fates_frag_cwd_fcel:units = "unitless" ; - fates_frag_cwd_fcel:long_name = "Cellulose fraction for CWD" ; - double fates_frag_cwd_flig ; - fates_frag_cwd_flig:units = "unitless" ; - fates_frag_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; - double fates_hydro_kmax_rsurf1 ; - fates_hydro_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; - fates_hydro_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; - double fates_hydro_kmax_rsurf2 ; - fates_hydro_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; - fates_hydro_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; - double fates_hydro_psi0 ; - fates_hydro_psi0:units = "MPa" ; - fates_hydro_psi0:long_name = "sapwood water potential at saturation" ; - double fates_hydro_psicap ; - fates_hydro_psicap:units = "MPa" ; - fates_hydro_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; - 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_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" ; - double fates_landuse_logging_collateral_frac ; - fates_landuse_logging_collateral_frac:units = "fraction" ; - fates_landuse_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; - double fates_landuse_logging_dbhmax ; - fates_landuse_logging_dbhmax:units = "cm" ; - fates_landuse_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; - double fates_landuse_logging_dbhmax_infra ; - fates_landuse_logging_dbhmax_infra:units = "cm" ; - fates_landuse_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; - double fates_landuse_logging_dbhmin ; - fates_landuse_logging_dbhmin:units = "cm" ; - fates_landuse_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; - double fates_landuse_logging_direct_frac ; - fates_landuse_logging_direct_frac:units = "fraction" ; - fates_landuse_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; - double fates_landuse_logging_event_code ; - fates_landuse_logging_event_code:units = "unitless" ; - fates_landuse_logging_event_code:long_name = "Integer code that options how logging events are structured" ; - double fates_landuse_logging_export_frac ; - fates_landuse_logging_export_frac:units = "fraction" ; - fates_landuse_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; - double fates_landuse_logging_mechanical_frac ; - fates_landuse_logging_mechanical_frac:units = "fraction" ; - fates_landuse_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; - double fates_landuse_pprodharv10_forest_mean ; - fates_landuse_pprodharv10_forest_mean:units = "fraction" ; - fates_landuse_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; - double fates_leaf_photo_temp_acclim_timescale ; - fates_leaf_photo_temp_acclim_timescale:units = "days" ; - fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; - double fates_leaf_photo_tempsens_model ; - fates_leaf_photo_tempsens_model:units = "unitless" ; - fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; - double fates_leaf_stomatal_assim_model ; - fates_leaf_stomatal_assim_model:units = "unitless" ; - fates_leaf_stomatal_assim_model:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; - double fates_leaf_stomatal_model ; - fates_leaf_stomatal_model:units = "unitless" ; - fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; - double fates_leaf_theta_cj_c3 ; - fates_leaf_theta_cj_c3:units = "unitless" ; - fates_leaf_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; - double fates_leaf_theta_cj_c4 ; - fates_leaf_theta_cj_c4:units = "unitless" ; - fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; - double fates_maintresp_model ; - fates_maintresp_model:units = "unitless" ; - fates_maintresp_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991) (NOT USED)" ; - double fates_maxcohort ; - fates_maxcohort:units = "count" ; - fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; - double fates_maxpatch_primary ; - fates_maxpatch_primary:units = "count" ; - fates_maxpatch_primary:long_name = "maximum number of primary vegetation patches per site" ; - double fates_maxpatch_secondary ; - fates_maxpatch_secondary:units = "count" ; - fates_maxpatch_secondary:long_name = "maximum number of secondary vegetation patches per site" ; - double fates_mort_disturb_frac ; - fates_mort_disturb_frac:units = "fraction" ; - fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; - double fates_mort_understorey_death ; - fates_mort_understorey_death:units = "fraction" ; - fates_mort_understorey_death:long_name = "fraction of plants in understorey cohort impacted by overstorey tree-fall" ; - double fates_patch_fusion_tol ; - fates_patch_fusion_tol:units = "unitless" ; - fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; - double fates_phen_chilltemp ; - fates_phen_chilltemp:units = "degrees C" ; - fates_phen_chilltemp:long_name = "chilling day counting threshold for vegetation" ; - double fates_phen_coldtemp ; - fates_phen_coldtemp:units = "degrees C" ; - fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; - double fates_phen_drought_model ; - fates_phen_drought_model:units = "unitless" ; - fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; - double fates_phen_drought_threshold ; - fates_phen_drought_threshold:units = "m3/m3 or mm" ; - fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; - double fates_phen_gddthresh_a ; - fates_phen_gddthresh_a:units = "none" ; - fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_gddthresh_b ; - fates_phen_gddthresh_b:units = "none" ; - fates_phen_gddthresh_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_gddthresh_c ; - fates_phen_gddthresh_c:units = "none" ; - fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_mindaysoff ; - fates_phen_mindaysoff:units = "days" ; - fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves became off-allometry" ; - double fates_phen_mindayson ; - fates_phen_mindayson:units = "days" ; - fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; - double fates_phen_moist_threshold ; - fates_phen_moist_threshold:units = "m3/m3 or mm" ; - fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; - double fates_phen_ncolddayslim ; - fates_phen_ncolddayslim:units = "days" ; - fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; - double fates_q10_froz ; - fates_q10_froz:units = "unitless" ; - fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; - double fates_q10_mr ; - fates_q10_mr:units = "unitless" ; - fates_q10_mr:long_name = "Q10 for maintenance respiration" ; - double fates_soil_salinity ; - fates_soil_salinity:units = "ppt" ; - fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; - double fates_vai_top_bin_width ; - fates_vai_top_bin_width:units = "m2/m2" ; - fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; - double fates_vai_width_increase_factor ; - fates_vai_width_increase_factor:units = "unitless" ; - fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; - -// global attributes: - :history = "This parameter file is maintained in version control\nSee https://github.com/NGEET/fates/blob/master/parameter_files/fates_params_default.cdl \nFor changes, use git blame \n" ; -data: - - fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; - - fates_history_coageclass_bin_edges = 0, 5 ; - - fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; - - fates_history_damage_bin_edges = 0, 80 ; - - fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, - 80, 90, 100 ; - - fates_alloc_organ_id = 1, 2, 3, 6 ; - - fates_hydro_htftype_node = 1, 1, 1, 1 ; - - fates_pftname = - "broadleaf_evergreen_tropical_tree ", - "needleleaf_evergreen_extratrop_tree ", - "needleleaf_colddecid_extratrop_tree ", - "broadleaf_evergreen_extratrop_tree ", - "broadleaf_hydrodecid_tropical_tree ", - "broadleaf_colddecid_extratrop_tree ", - "broadleaf_evergreen_extratrop_shrub ", - "broadleaf_hydrodecid_extratrop_shrub ", - "broadleaf_colddecid_extratrop_shrub ", - "arctic_c3_grass ", - "cool_c3_grass ", - "c4_grass " ; - - fates_hydro_organ_name = - "leaf ", - "stem ", - "transporting root ", - "absorbing root " ; - - fates_alloc_organ_name = - "leaf", - "fine root", - "sapwood", - "structure" ; - - fates_litterclass_name = - "twig ", - "small branch ", - "large branch ", - "trunk ", - "dead leaves ", - "live grass " ; - - 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, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; - - fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, - 1.2, 1.2, 1.2 ; - - fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, - 0.8, 0.8, 0.8, 0.8 ; - - fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, - 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; - - fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, - 0.572, 0.572, 0.572, 0.572 ; - - fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, - 1.94, 1.94, 1.94 ; - - fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, - 0.931, 0.931, 0.931, 0.931 ; - - fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6 ; - - fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, - 0.95, 1, 1, 1 ; - - fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, - 0.07, 0.07, 0.07 ; - - fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, - 1.3 ; - - fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, - 0.55, 0.55, 0.55 ; - - fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464 ; - - fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119 ; - - fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, - 0.64, 0.64, 0.64 ; - - fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, - 0.37, 0.37, 0.37 ; - - fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, - -999.9, -999.9, -999.9, -999.9, -999.9 ; - - fates_allom_dbh_maxheight = 90, 90, 90, 90, 90, 90, 3, 3, 2, 0.35, 0.35, 0.35 ; - - fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; - - fates_allom_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; - - fates_allom_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - - fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, - 0.8, 0.8, 0.8 ; - - fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1, 0.1 ; - - fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_zroot_k = 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 ; - - fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; - - fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100 ; - - fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1 ; - - fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100 ; - - fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; - - fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5 ; - - fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, - 280, 280 ; - - fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, - 0.14, 0.14, 0.14 ; - - fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, - 0.27, 0.27, 0.27 ; - - fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1 ; - - fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_eca_vmax_nh4 = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, - 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - - fates_cnp_eca_vmax_no3 = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, - 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - - fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, - 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - - fates_cnp_fnrt_adapt_tscale = 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100, 100 ; - - fates_cnp_nfix1 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5, 1.5 ; - - fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5, 1.5 ; - - fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_rd_vmax_n = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, - 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - - fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_turnover_nitr_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_turnover_phos_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, - 5e-10, 5e-10, 5e-10, 5e-10 ; - - fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, - 0.01, 0.01, 0.01 ; - - fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; - - fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, - 5.5, 5.5 ; - - fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, - 0.2 ; - - fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, - 0.07, 0.07, 0.07, 0.07 ; - - fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, - 0.775, 0.775, 0.775, 0.775, 0.775 ; - - fates_frag_fnrt_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5 ; - - fates_frag_fnrt_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; - - fates_frag_fnrt_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; - - fates_frag_leaf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5 ; - - fates_frag_leaf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; - - fates_frag_leaf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; - - fates_frag_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, - 0.51, 0.51, 0.51, 0.51 ; - - fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, - 0.11, 0.11 ; - - fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, - 2.5, 2.5 ; - - fates_hydro_avuln_node = - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 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_hydro_epsil_node = - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - - fates_hydro_fcap_node = - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, - 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_hydro_kmax_node = - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; - - fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, - -1.5, -1.5, -1.5 ; - - fates_hydro_p50_node = - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25 ; - - fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, - 0.333, 0.333, 0.333, 0.333, 0.333 ; - - fates_hydro_pinot_node = - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; - - fates_hydro_pitlp_node = - -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, - -1.67, -1.67, - -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, - -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, - -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; - - fates_hydro_resid_node = - 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, - 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - - fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, - 0.625, 0.625, 0.625, 0.625, 0.625 ; - - fates_hydro_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, - 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; - - fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; - - fates_hydro_thetas_node = - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; - - fates_hydro_vg_alpha_node = - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005 ; - - fates_hydro_vg_m_node = - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_hydro_vg_n_node = - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 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_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, - 43540, 43540, 43540, 43540 ; - - fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, - 152040, 152040, 152040, 152040, 152040 ; - - fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, - 495 ; - - fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, - 0.03, 0.03, 0.03, 0.03, 0.03 ; - - fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, - 0.03, 0.03, 0.03, 0.03 ; - - fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, - 10000, 10000, 10000, 10000, 10000, 40000 ; - - fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - - fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, - 4.7, 2.2, 5.3, 1.6 ; - - fates_leaf_vcmax25top = - 50, 65, 39, 62, 41, 58, 62, 54, 54, 78, 78, 78 ; - - fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, - 65330, 65330, 65330, 65330 ; - - fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, - 149250, 149250, 149250, 149250, 149250 ; - - fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, - 485 ; - - fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, - 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; - - fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, - 0.014, 0.014, 0.014, 0.014 ; - - fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -60, -10, -80, -80, - -20, 2.5 ; - - fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5 ; - - fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, - 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; - - fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_prescribed_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, - 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; - - fates_mort_prescribed_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, - 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; - - fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - - fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6, 0.6 ; - - fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6, 0.6 ; - - fates_nonhydro_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, - -255000, -255000, -255000, -255000, -255000, -255000 ; - - fates_nonhydro_smpso = -66000, -66000, -66000, -66000, -66000, -66000, - -66000, -66000, -66000, -66000, -66000, -66000 ; - - fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; - - fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, - 0.5 ; - - fates_phen_fnrt_drop_frac = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; - - fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; - - fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, - 0.4, 0.4, 0.4 ; - - fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, - 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; - - fates_rad_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, - 0.9, 0.75, 0.75, 0.75 ; - - fates_rad_leaf_rhonir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, - 0.41, 0.28, 0.28, 0.28 ; - - fates_rad_leaf_rhovis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, - 0.08, 0.05, 0.05, 0.05 ; - - fates_rad_leaf_taunir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, - 0.43, 0.4, 0.4, 0.4 ; - - fates_rad_leaf_tauvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, - 0.06, 0.05, 0.05, 0.05 ; - - fates_rad_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, - -0.23, -0.23, -0.23 ; - - fates_rad_stem_rhonir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, - 0.49, 0.53, 0.53, 0.53 ; - - fates_rad_stem_rhovis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.21, 0.31, 0.31, 0.31 ; - - fates_rad_stem_taunir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, - 0.001, 0.001, 0.25, 0.25, 0.25 ; - - fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, - 0.001, 0.001, 0.12, 0.12, 0.12 ; - - fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, - 0.125, 0.125, 0.125 ; - - fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, - 0.2, 0.2, 0.2 ; - - fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, - 0.02, 0.02, 0.02, 0.02, 0.02 ; - - fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1, 0.1 ; - - fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, - 0.9 ; - - fates_recruit_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, - 1.47, 1.47, 1.47 ; - - fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_seed_dispersal_param_A = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_seed_dispersal_param_B = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_stoich_nitr = - 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, - 0.0047, 0.0047, 0.0047 ; - - fates_stoich_phos = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, - 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, - 0.00047, 0.00047, 0.00047, 0.00047 ; - - fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, - 0.03, 0.03 ; - - fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; - - fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, - 0.67, 0.67, 0.67 ; - - fates_turb_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.04, 0.04, 0.04, 0.04 ; - - fates_turb_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, - 0.055, 0.055, 0.055, 0.055 ; - - fates_turnover_branch = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; - - fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - - fates_turnover_leaf = - 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - - fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, - 0.7 ; - - fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; - - fates_hlm_pft_map = - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; - - fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; - - fates_fire_low_moisture_Coeff = 1.12, 1.09, 0.98, 0.8, 1.15, 1.15 ; - - fates_fire_low_moisture_Slope = 0.62, 0.72, 0.85, 0.8, 0.62, 0.62 ; - - fates_fire_mid_moisture = 0.72, 0.51, 0.38, 1, 0.8, 0.8 ; - - fates_fire_mid_moisture_Coeff = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; - - fates_fire_mid_moisture_Slope = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; - - fates_fire_min_moisture = 0.18, 0.12, 0, 0, 0.24, 0.24 ; - - fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; - - fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; - - fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; - - fates_base_mr_20 = 2.52e-06 ; - - fates_canopy_closure_thresh = 0.8 ; - - fates_cnp_eca_plant_escalar = 1.25e-05 ; - - fates_cohort_age_fusion_tol = 0.08 ; - - fates_cohort_size_fusion_tol = 0.08 ; - - fates_comp_excln = 3 ; - - fates_damage_canopy_layer_code = 1 ; - - fates_damage_event_code = 1 ; - - fates_dev_arbitrary = _ ; - - fates_fire_active_crown_fire = 0 ; - - fates_fire_cg_strikes = 0.2 ; - - fates_fire_drying_ratio = 66000 ; - - fates_fire_durat_slope = -11.06 ; - - fates_fire_fdi_a = 17.62 ; - - fates_fire_fdi_alpha = 0.00037 ; - - fates_fire_fdi_b = 243.12 ; - - fates_fire_fuel_energy = 18000 ; - - fates_fire_max_durat = 240 ; - - fates_fire_miner_damp = 0.41739 ; - - fates_fire_miner_total = 0.055 ; - - fates_fire_nignitions = 15 ; - - fates_fire_part_dens = 513 ; - - fates_fire_threshold = 50 ; - - fates_frag_cwd_fcel = 0.76 ; - - fates_frag_cwd_flig = 0.24 ; - - fates_hydro_kmax_rsurf1 = 20 ; - - fates_hydro_kmax_rsurf2 = 0.0001 ; - - fates_hydro_psi0 = 0 ; - - fates_hydro_psicap = -0.6 ; - - fates_hydro_solver = 1 ; - - fates_landuse_logging_coll_under_frac = 0.55983 ; - - fates_landuse_logging_collateral_frac = 0.05 ; - - fates_landuse_logging_dbhmax = _ ; - - fates_landuse_logging_dbhmax_infra = 35 ; - - fates_landuse_logging_dbhmin = 50 ; - - fates_landuse_logging_direct_frac = 0.15 ; - - fates_landuse_logging_event_code = -30 ; - - fates_landuse_logging_export_frac = 0.8 ; - - fates_landuse_logging_mechanical_frac = 0.05 ; - - fates_landuse_pprodharv10_forest_mean = 0.8125 ; - - fates_leaf_photo_temp_acclim_timescale = 30 ; - - fates_leaf_photo_tempsens_model = 1 ; - - fates_leaf_stomatal_assim_model = 1 ; - - fates_leaf_stomatal_model = 1 ; - - fates_leaf_theta_cj_c3 = 0.999 ; - - fates_leaf_theta_cj_c4 = 0.999 ; - - fates_maintresp_model = 1 ; - - fates_maxcohort = 100 ; - - fates_maxpatch_primary = 10 ; - - fates_maxpatch_secondary = 4 ; - - fates_mort_disturb_frac = 1 ; - - fates_mort_understorey_death = 0.55983 ; - - fates_patch_fusion_tol = 0.05 ; - - fates_phen_chilltemp = 5 ; - - fates_phen_coldtemp = 7.5 ; - - fates_phen_drought_model = 0 ; - - fates_phen_drought_threshold = 0.15 ; - - fates_phen_gddthresh_a = -68 ; - - fates_phen_gddthresh_b = 638 ; - - fates_phen_gddthresh_c = -0.01 ; - - fates_phen_mindaysoff = 100 ; - - fates_phen_mindayson = 90 ; - - fates_phen_moist_threshold = 0.18 ; - - fates_phen_ncolddayslim = 5 ; - - fates_q10_froz = 1.5 ; - - fates_q10_mr = 1.5 ; - - fates_soil_salinity = 0.4 ; - - fates_vai_top_bin_width = 1 ; - - fates_vai_width_increase_factor = 1 ; -} From f05214c3d4e2f20b16ec1198d379ea6a67116bd0 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 28 Oct 2022 17:00:26 -0700 Subject: [PATCH 403/852] Revert "adding new seed dispersal parameter file" This reverts commit 4e4054b77d37a4948e9e084729d9e36ac2106fd2. --- parameter_files/fates_params_default.cdl | 1489 ++++++++++++++++ .../fates_params_seed-dispersal.cdl | 1550 +++++++++++++++++ 2 files changed, 3039 insertions(+) create mode 100644 parameter_files/fates_params_default.cdl create mode 100644 parameter_files/fates_params_seed-dispersal.cdl diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl new file mode 100644 index 0000000000..45e4a3509c --- /dev/null +++ b/parameter_files/fates_params_default.cdl @@ -0,0 +1,1489 @@ +netcdf fates_params_default.c210629_sorted { +dimensions: + fates_NCWD = 4 ; + fates_history_age_bins = 7 ; + fates_history_height_bins = 6 ; + fates_history_size_bins = 13 ; + fates_history_coage_bins = 2 ; + fates_hydr_organs = 4 ; + fates_leafage_class = 1 ; + fates_litterclass = 6 ; + fates_pft = 12 ; + fates_prt_organs = 4 ; + fates_string_length = 60 ; + fates_hlm_pftno = 14 ; +variables: + double fates_history_ageclass_bin_edges(fates_history_age_bins) ; + fates_history_ageclass_bin_edges:units = "yr" ; + fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; + double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; + fates_history_coageclass_bin_edges:units = "years" ; + fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; + double fates_history_height_bin_edges(fates_history_height_bins) ; + fates_history_height_bin_edges:units = "m" ; + fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; + double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; + fates_history_sizeclass_bin_edges:units = "cm" ; + fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; + double fates_hydr_htftype_node(fates_hydr_organs) ; + fates_hydr_htftype_node:units = "unitless" ; + fates_hydr_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; + fates_hydr_htftype_node:possible_values = "1: Christofferson et al. 2016 (TFS); 2: Van Genuchten 1980" ; + double fates_prt_organ_id(fates_prt_organs) ; + fates_prt_organ_id:units = "index, unitless" ; + fates_prt_organ_id:long_name = "This is the global index the organ in this file is associated with in PRTGenericMod.F90" ; + char fates_pftname(fates_pft, fates_string_length) ; + fates_pftname:units = "unitless - string" ; + fates_pftname:long_name = "Description of plant type" ; + char fates_hydr_organname_node(fates_hydr_organs, fates_string_length) ; + fates_hydr_organname_node:units = "unitless - string" ; + fates_hydr_organname_node:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; + 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_prt_organ_name(fates_prt_organs, fates_string_length) ; + fates_prt_organ_name:units = "unitless - string" ; + fates_prt_organ_name:long_name = "Name of plant organs (order must match PRTGenericMod.F90)" ; + double fates_alloc_storage_cushion(fates_pft) ; + fates_alloc_storage_cushion:units = "fraction" ; + fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; + double fates_allom_agb1(fates_pft) ; + fates_allom_agb1:units = "variable" ; + fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; + double fates_allom_agb2(fates_pft) ; + fates_allom_agb2:units = "variable" ; + fates_allom_agb2:long_name = "Parameter 2 for agb allometry" ; + double fates_allom_agb3(fates_pft) ; + fates_allom_agb3:units = "variable" ; + fates_allom_agb3:long_name = "Parameter 3 for agb allometry" ; + double fates_allom_agb4(fates_pft) ; + fates_allom_agb4:units = "variable" ; + fates_allom_agb4:long_name = "Parameter 4 for agb allometry" ; + double fates_allom_agb_frac(fates_pft) ; + fates_allom_agb_frac:units = "fraction" ; + fates_allom_agb_frac:long_name = "Fraction of woody biomass that is above ground" ; + double fates_allom_amode(fates_pft) ; + fates_allom_amode:units = "index" ; + fates_allom_amode:long_name = "AGB allometry function index." ; + fates_allom_amode:possible_values = "1: Saldarriaga 1998; 2: 2 parameter power law; 3: Chave 2014" ; + double fates_allom_blca_expnt_diff(fates_pft) ; + fates_allom_blca_expnt_diff:units = "unitless" ; + fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; + double fates_allom_cmode(fates_pft) ; + fates_allom_cmode:units = "index" ; + fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; + fates_allom_cmode:possible_values = "1: Constant fraction on AGB" ; + double fates_allom_d2bl1(fates_pft) ; + fates_allom_d2bl1:units = "variable" ; + fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; + double fates_allom_d2bl2(fates_pft) ; + fates_allom_d2bl2:units = "variable" ; + fates_allom_d2bl2:long_name = "Parameter 2 for d2bl allometry" ; + double fates_allom_d2bl3(fates_pft) ; + fates_allom_d2bl3:units = "unitless" ; + fates_allom_d2bl3:long_name = "Parameter 3 for d2bl allometry" ; + double fates_allom_d2ca_coefficient_max(fates_pft) ; + fates_allom_d2ca_coefficient_max:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_max:long_name = "max (savanna) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2ca_coefficient_min(fates_pft) ; + fates_allom_d2ca_coefficient_min:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_min:long_name = "min (forest) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2h1(fates_pft) ; + fates_allom_d2h1:units = "variable" ; + fates_allom_d2h1:long_name = "Parameter 1 for d2h allometry (intercept, or c)" ; + double fates_allom_d2h2(fates_pft) ; + fates_allom_d2h2:units = "variable" ; + fates_allom_d2h2:long_name = "Parameter 2 for d2h allometry (slope, or m)" ; + double fates_allom_d2h3(fates_pft) ; + fates_allom_d2h3:units = "variable" ; + fates_allom_d2h3:long_name = "Parameter 3 for d2h allometry (optional)" ; + double fates_allom_dbh_maxheight(fates_pft) ; + fates_allom_dbh_maxheight:units = "cm" ; + fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; + double fates_allom_fmode(fates_pft) ; + fates_allom_fmode:units = "index" ; + fates_allom_fmode:long_name = "fine root biomass allometry function index." ; + fates_allom_fmode:possible_values = "1: constant fraction of trimmed bleaf; 2: constant fraction of untrimmed bleaf." ; + double fates_allom_frbstor_repro(fates_pft) ; + fates_allom_frbstor_repro:units = "fraction" ; + fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; + double fates_allom_hmode(fates_pft) ; + fates_allom_hmode:units = "index" ; + fates_allom_hmode:long_name = "height allometry function index." ; + fates_allom_hmode:possible_values = "1: OBrien 1995; 2: Poorter 2006; 3: 2 parameter power law; 4: Chave 2014; 5: Martinez-Cano 2019." ; + double fates_allom_l2fr(fates_pft) ; + fates_allom_l2fr:units = "gC/gC" ; + fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; + double fates_allom_la_per_sa_int(fates_pft) ; + fates_allom_la_per_sa_int:units = "m2/cm2" ; + fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; + double fates_allom_la_per_sa_slp(fates_pft) ; + fates_allom_la_per_sa_slp:units = "m2/cm2/m" ; + fates_allom_la_per_sa_slp:long_name = "Leaf area per sapwood area rate of change with height, slope (optional)" ; + double fates_allom_lmode(fates_pft) ; + fates_allom_lmode:units = "index" ; + fates_allom_lmode:long_name = "leaf biomass allometry function index." ; + fates_allom_lmode:possible_values = "1: Saldarriaga 1998 (capped-dbh power law); 2: generic power law; 3: generic capped-dbh power law." ; + double fates_allom_sai_scaler(fates_pft) ; + fates_allom_sai_scaler:units = "m2/m2" ; + fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; + double fates_allom_smode(fates_pft) ; + fates_allom_smode:units = "index" ; + fates_allom_smode:long_name = "sapwood allometry function index." ; + fates_allom_smode:possible_values = "1: sapwood area proportional to leaf area based on target leaf biomass" ; + double fates_allom_stmode(fates_pft) ; + fates_allom_stmode:units = "index" ; + fates_allom_stmode:long_name = "storage allometry function index." ; + fates_allom_stmode:possible_values = "1: target storage proportional to trimmed maximum leaf biomass." ; + double fates_allom_zroot_k(fates_pft) ; + fates_allom_zroot_k:units = "unitless" ; + fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; + double fates_allom_zroot_max_dbh(fates_pft) ; + fates_allom_zroot_max_dbh:units = "cm" ; + fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; + double fates_allom_zroot_max_z(fates_pft) ; + fates_allom_zroot_max_z:units = "m" ; + fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_allom_zroot_min_dbh(fates_pft) ; + fates_allom_zroot_min_dbh:units = "cm" ; + fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; + double fates_allom_zroot_min_z(fates_pft) ; + fates_allom_zroot_min_z:units = "m" ; + fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_branch_turnover(fates_pft) ; + fates_branch_turnover:units = "yr" ; + fates_branch_turnover:long_name = "turnover time of branches" ; + double fates_c2b(fates_pft) ; + fates_c2b:units = "ratio" ; + fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; + 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" ; + double fates_displar(fates_pft) ; + fates_displar:units = "unitless" ; + fates_displar:long_name = "Ratio of displacement height to canopy top height" ; + double fates_eca_alpha_ptase(fates_pft) ; + fates_eca_alpha_ptase:units = "g/m3" ; + fates_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; + double fates_eca_decompmicc(fates_pft) ; + fates_eca_decompmicc:units = "gC/m3" ; + fates_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; + double fates_eca_km_nh4(fates_pft) ; + fates_eca_km_nh4:units = "gN/m3" ; + fates_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; + double fates_eca_km_no3(fates_pft) ; + fates_eca_km_no3:units = "gN/m3" ; + fates_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; + double fates_eca_km_p(fates_pft) ; + fates_eca_km_p:units = "gP/m3" ; + fates_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; + double fates_eca_km_ptase(fates_pft) ; + fates_eca_km_ptase:units = "gP/m3" ; + fates_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; + double fates_eca_lambda_ptase(fates_pft) ; + fates_eca_lambda_ptase:units = "g/m3" ; + fates_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; + double fates_eca_vmax_nh4(fates_pft) ; + fates_eca_vmax_nh4:units = "gN/gC/s" ; + fates_eca_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA)" ; + double fates_eca_vmax_no3(fates_pft) ; + fates_eca_vmax_no3:units = "gN/gC/s" ; + fates_eca_vmax_no3:long_name = "maximum production rate for plant no3 uptake (ECA)" ; + double fates_eca_vmax_p(fates_pft) ; + fates_eca_vmax_p:units = "gP/gC/s" ; + fates_eca_vmax_p:long_name = "maximum production rate for plant p uptake (ECA)" ; + double fates_eca_vmax_ptase(fates_pft) ; + fates_eca_vmax_ptase:units = "gP/m2/s" ; + fates_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; + double fates_fire_alpha_SH(fates_pft) ; + fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; + fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; + double fates_fire_bark_scaler(fates_pft) ; + fates_fire_bark_scaler:units = "fraction" ; + fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; + double fates_fire_crown_depth_frac(fates_pft) ; + fates_fire_crown_depth_frac:units = "fraction" ; + fates_fire_crown_depth_frac:long_name = "the depth of a cohorts crown as a fraction of its height" ; + double fates_fire_crown_kill(fates_pft) ; + fates_fire_crown_kill:units = "NA" ; + fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; + double fates_fnrt_prof_a(fates_pft) ; + fates_fnrt_prof_a:units = "unitless" ; + fates_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; + double fates_fnrt_prof_b(fates_pft) ; + fates_fnrt_prof_b:units = "unitless" ; + fates_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; + double fates_fnrt_prof_mode(fates_pft) ; + fates_fnrt_prof_mode:units = "index" ; + fates_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; + double fates_fr_fcel(fates_pft) ; + fates_fr_fcel:units = "fraction" ; + fates_fr_fcel:long_name = "Fine root litter cellulose fraction" ; + double fates_fr_flab(fates_pft) ; + fates_fr_flab:units = "fraction" ; + fates_fr_flab:long_name = "Fine root litter labile fraction" ; + double fates_fr_flig(fates_pft) ; + fates_fr_flig:units = "fraction" ; + fates_fr_flig:long_name = "Fine root litter lignin fraction" ; + double fates_grperc(fates_pft) ; + fates_grperc:units = "unitless" ; + fates_grperc:long_name = "Growth respiration factor" ; + double fates_hydr_avuln_gs(fates_pft) ; + fates_hydr_avuln_gs:units = "unitless" ; + fates_hydr_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; + double fates_hydr_avuln_node(fates_hydr_organs, fates_pft) ; + fates_hydr_avuln_node:units = "unitless" ; + fates_hydr_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; + double fates_hydr_epsil_node(fates_hydr_organs, fates_pft) ; + fates_hydr_epsil_node:units = "MPa" ; + fates_hydr_epsil_node:long_name = "bulk elastic modulus" ; + double fates_hydr_fcap_node(fates_hydr_organs, fates_pft) ; + fates_hydr_fcap_node:units = "unitless" ; + fates_hydr_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; + double fates_hydr_k_lwp(fates_pft) ; + fates_hydr_k_lwp:units = "unitless" ; + fates_hydr_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; + fates_hydr_k_lwp:possible_values = "0: turns off leaf humidity effects on conductance. 1-10 activates humidity effects" ; + double fates_hydr_kmax_node(fates_hydr_organs, fates_pft) ; + fates_hydr_kmax_node:units = "kg/MPa/m/s" ; + fates_hydr_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; + double fates_hydr_p50_gs(fates_pft) ; + fates_hydr_p50_gs:units = "MPa" ; + fates_hydr_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; + double fates_hydr_p50_node(fates_hydr_organs, fates_pft) ; + fates_hydr_p50_node:units = "MPa" ; + fates_hydr_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; + double fates_hydr_p_taper(fates_pft) ; + fates_hydr_p_taper:units = "unitless" ; + fates_hydr_p_taper:long_name = "xylem taper exponent" ; + double fates_hydr_pinot_node(fates_hydr_organs, fates_pft) ; + fates_hydr_pinot_node:units = "MPa" ; + fates_hydr_pinot_node:long_name = "osmotic potential at full turgor" ; + double fates_hydr_pitlp_node(fates_hydr_organs, fates_pft) ; + fates_hydr_pitlp_node:units = "MPa" ; + fates_hydr_pitlp_node:long_name = "turgor loss point" ; + double fates_hydr_resid_node(fates_hydr_organs, fates_pft) ; + fates_hydr_resid_node:units = "cm3/cm3" ; + fates_hydr_resid_node:long_name = "residual water conent" ; + double fates_hydr_rfrac_stem(fates_pft) ; + fates_hydr_rfrac_stem:units = "fraction" ; + fates_hydr_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; + double fates_hydr_rs2(fates_pft) ; + fates_hydr_rs2:units = "m" ; + fates_hydr_rs2:long_name = "absorbing root radius" ; + double fates_hydr_srl(fates_pft) ; + fates_hydr_srl:units = "m g-1" ; + fates_hydr_srl:long_name = "specific root length" ; + double fates_hydr_thetas_node(fates_hydr_organs, fates_pft) ; + fates_hydr_thetas_node:units = "cm3/cm3" ; + fates_hydr_thetas_node:long_name = "saturated water content" ; + double fates_hydr_vg_alpha_node(fates_hydr_organs, fates_pft) ; + fates_hydr_vg_alpha_node:units = "MPa-1" ; + fates_hydr_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; + double fates_hydr_vg_m_node(fates_hydr_organs, fates_pft) ; + fates_hydr_vg_m_node:units = "unitless" ; + fates_hydr_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; + double fates_hydr_vg_n_node(fates_hydr_organs, fates_pft) ; + fates_hydr_vg_n_node:units = "unitless" ; + fates_hydr_vg_n_node:long_name = "(used if hydr_htftype_node = 2),n in van Genuchten 1980 model, pore size distribution parameter" ; + double fates_leaf_c3psn(fates_pft) ; + fates_leaf_c3psn:units = "flag" ; + fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; + double fates_leaf_clumping_index(fates_pft) ; + fates_leaf_clumping_index:units = "fraction (0-1)" ; + fates_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; + double fates_leaf_diameter(fates_pft) ; + fates_leaf_diameter:units = "m" ; + fates_leaf_diameter:long_name = "Characteristic leaf dimension" ; + double fates_leaf_jmaxha(fates_pft) ; + fates_leaf_jmaxha:units = "J/mol" ; + fates_leaf_jmaxha:long_name = "activation energy for jmax" ; + double fates_leaf_jmaxhd(fates_pft) ; + fates_leaf_jmaxhd:units = "J/mol" ; + fates_leaf_jmaxhd:long_name = "deactivation energy for jmax" ; + double fates_leaf_jmaxse(fates_pft) ; + fates_leaf_jmaxse:units = "J/mol/K" ; + fates_leaf_jmaxse:long_name = "entropy term for jmax" ; + double fates_leaf_long(fates_leafage_class, fates_pft) ; + fates_leaf_long:units = "yr" ; + fates_leaf_long:long_name = "Leaf longevity (ie turnover timescale)" ; + double fates_leaf_slamax(fates_pft) ; + fates_leaf_slamax:units = "m^2/gC" ; + fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; + double fates_leaf_slatop(fates_pft) ; + fates_leaf_slatop:units = "m^2/gC" ; + fates_leaf_slatop:long_name = "Specific Leaf Area (SLA) at top of canopy, projected area basis" ; + double fates_leaf_stomatal_intercept(fates_pft) ; + fates_leaf_stomatal_intercept:units = "umol H2O/m**2/s" ; + fates_leaf_stomatal_intercept:long_name = "Minimum unstressed stomatal conductance for Ball-Berry model and Medlyn model" ; + double fates_leaf_stomatal_slope_ballberry(fates_pft) ; + fates_leaf_stomatal_slope_ballberry:units = "unitless" ; + fates_leaf_stomatal_slope_ballberry:long_name = "stomatal slope parameter, as per Ball-Berry" ; + double fates_leaf_stomatal_slope_medlyn(fates_pft) ; + fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; + fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; + double fates_leaf_stor_priority(fates_pft) ; + fates_leaf_stor_priority:units = "unitless" ; + fates_leaf_stor_priority:long_name = "factor governing priority of replacing storage with NPP" ; + double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; + fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; + fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; + double fates_leaf_vcmaxha(fates_pft) ; + fates_leaf_vcmaxha:units = "J/mol" ; + fates_leaf_vcmaxha:long_name = "activation energy for vcmax" ; + double fates_leaf_vcmaxhd(fates_pft) ; + fates_leaf_vcmaxhd:units = "J/mol" ; + fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax" ; + double fates_leaf_vcmaxse(fates_pft) ; + fates_leaf_vcmaxse:units = "J/mol/K" ; + fates_leaf_vcmaxse:long_name = "entropy term for vcmax" ; + double fates_leaf_xl(fates_pft) ; + fates_leaf_xl:units = "unitless" ; + fates_leaf_xl:long_name = "Leaf/stem orientation index" ; + double fates_lf_fcel(fates_pft) ; + fates_lf_fcel:units = "fraction" ; + fates_lf_fcel:long_name = "Leaf litter cellulose fraction" ; + double fates_lf_flab(fates_pft) ; + fates_lf_flab:units = "fraction" ; + fates_lf_flab:long_name = "Leaf litter labile fraction" ; + double fates_lf_flig(fates_pft) ; + fates_lf_flig:units = "fraction" ; + fates_lf_flig:long_name = "Leaf litter lignin fraction" ; + double fates_maintresp_reduction_curvature(fates_pft) ; + fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; + fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; + double fates_maintresp_reduction_intercept(fates_pft) ; + fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; + fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; + double fates_mort_bmort(fates_pft) ; + fates_mort_bmort:units = "1/yr" ; + fates_mort_bmort:long_name = "background mortality rate" ; + double fates_mort_freezetol(fates_pft) ; + fates_mort_freezetol:units = "degrees C" ; + fates_mort_freezetol:long_name = "minimum temperature tolerance" ; + double fates_mort_hf_flc_threshold(fates_pft) ; + fates_mort_hf_flc_threshold:units = "fraction" ; + fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; + double fates_mort_hf_sm_threshold(fates_pft) ; + fates_mort_hf_sm_threshold:units = "unitless" ; + fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; + double fates_mort_ip_age_senescence(fates_pft) ; + fates_mort_ip_age_senescence:units = "years" ; + fates_mort_ip_age_senescence:long_name = "Mortality cohort age senescence inflection point. If _ this mortality term is off. Setting this value turns on age dependent mortality. " ; + double fates_mort_ip_size_senescence(fates_pft) ; + fates_mort_ip_size_senescence:units = "dbh cm" ; + fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; + double fates_mort_r_age_senescence(fates_pft) ; + fates_mort_r_age_senescence:units = "mortality rate year^-1" ; + fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; + double fates_mort_r_size_senescence(fates_pft) ; + fates_mort_r_size_senescence:units = "mortality rate dbh^-1" ; + fates_mort_r_size_senescence:long_name = "Mortality dbh senescence rate of change. Sensible range is around 0.03-0.06. Larger values give steeper mortality curves." ; + double fates_mort_scalar_coldstress(fates_pft) ; + fates_mort_scalar_coldstress:units = "1/yr" ; + fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; + double fates_mort_scalar_cstarvation(fates_pft) ; + fates_mort_scalar_cstarvation:units = "1/yr" ; + fates_mort_scalar_cstarvation:long_name = "maximum mortality rate from carbon starvation" ; + double fates_mort_scalar_hydrfailure(fates_pft) ; + fates_mort_scalar_hydrfailure:units = "1/yr" ; + fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; + double fates_nfix1(fates_pft) ; + fates_nfix1:units = "NA" ; + fates_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; + double fates_nfix2(fates_pft) ; + fates_nfix2:units = "NA" ; + fates_nfix2:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; + double fates_nitr_store_ratio(fates_pft) ; + fates_nitr_store_ratio:units = "(gN/gN)" ; + fates_nitr_store_ratio:long_name = "ratio of storeable N, to functional N bound in cell structures of leaf,root,sap" ; + double fates_phen_cold_size_threshold(fates_pft) ; + fates_phen_cold_size_threshold:units = "cm" ; + fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; + double fates_phen_evergreen(fates_pft) ; + fates_phen_evergreen:units = "logical flag" ; + fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; + double fates_phen_season_decid(fates_pft) ; + fates_phen_season_decid:units = "logical flag" ; + fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; + double fates_phen_stem_drop_fraction(fates_pft) ; + fates_phen_stem_drop_fraction:units = "fraction" ; + fates_phen_stem_drop_fraction:long_name = "fraction of stems to drop for non-woody species during drought/cold" ; + double fates_phen_stress_decid(fates_pft) ; + fates_phen_stress_decid:units = "logical flag" ; + fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; + double fates_phenflush_fraction(fates_pft) ; + fates_phenflush_fraction:units = "fraction" ; + fates_phenflush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; + double fates_phos_store_ratio(fates_pft) ; + fates_phos_store_ratio:units = "(gP/gP)" ; + fates_phos_store_ratio:long_name = "ratio of storeable P, to functional P bound in cell structures of leaf,root,sap" ; + double fates_prescribed_mortality_canopy(fates_pft) ; + fates_prescribed_mortality_canopy:units = "1/yr" ; + fates_prescribed_mortality_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; + double fates_prescribed_mortality_understory(fates_pft) ; + fates_prescribed_mortality_understory:units = "1/yr" ; + fates_prescribed_mortality_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; + double fates_prescribed_npp_canopy(fates_pft) ; + fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; + double fates_prescribed_npp_understory(fates_pft) ; + fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; + double fates_prescribed_nuptake(fates_pft) ; + fates_prescribed_nuptake:units = "fraction" ; + fates_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; + double fates_prescribed_puptake(fates_pft) ; + fates_prescribed_puptake:units = "fraction" ; + fates_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; + double fates_prescribed_recruitment(fates_pft) ; + fates_prescribed_recruitment:units = "n/yr" ; + fates_prescribed_recruitment:long_name = "recruitment rate for prescribed physiology mode" ; + double fates_prt_alloc_priority(fates_prt_organs, fates_pft) ; + fates_prt_alloc_priority:units = "index (0-fates_prt_organs)" ; + fates_prt_alloc_priority:long_name = "Priority order for allocation (C storage=2)" ; + double fates_prt_nitr_stoich_p1(fates_prt_organs, fates_pft) ; + fates_prt_nitr_stoich_p1:units = "(gN/gC)" ; + fates_prt_nitr_stoich_p1:long_name = "nitrogen stoichiometry, parameter 1" ; + double fates_prt_nitr_stoich_p2(fates_prt_organs, fates_pft) ; + fates_prt_nitr_stoich_p2:units = "(gN/gC)" ; + fates_prt_nitr_stoich_p2:long_name = "nitrogen stoichiometry, parameter 2" ; + double fates_prt_phos_stoich_p1(fates_prt_organs, fates_pft) ; + fates_prt_phos_stoich_p1:units = "(gP/gC)" ; + fates_prt_phos_stoich_p1:long_name = "phosphorous stoichiometry, parameter 1" ; + double fates_prt_phos_stoich_p2(fates_prt_organs, fates_pft) ; + fates_prt_phos_stoich_p2:units = "(gP/gC)" ; + fates_prt_phos_stoich_p2:long_name = "phosphorous stoichiometry, parameter 2" ; + double fates_recruit_hgt_min(fates_pft) ; + fates_recruit_hgt_min:units = "m" ; + fates_recruit_hgt_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; + double fates_recruit_initd(fates_pft) ; + fates_recruit_initd:units = "stems/m2" ; + fates_recruit_initd:long_name = "initial seedling density for a cold-start near-bare-ground simulation" ; + double fates_rholnir(fates_pft) ; + fates_rholnir:units = "fraction" ; + fates_rholnir:long_name = "Leaf reflectance: near-IR" ; + double fates_rholvis(fates_pft) ; + fates_rholvis:units = "fraction" ; + fates_rholvis:long_name = "Leaf reflectance: visible" ; + double fates_rhosnir(fates_pft) ; + fates_rhosnir:units = "fraction" ; + fates_rhosnir:long_name = "Stem reflectance: near-IR" ; + double fates_rhosvis(fates_pft) ; + fates_rhosvis:units = "fraction" ; + fates_rhosvis:long_name = "Stem reflectance: visible" ; + double fates_root_long(fates_pft) ; + fates_root_long:units = "yr" ; + fates_root_long:long_name = "root longevity (alternatively, turnover time)" ; + double fates_seed_alloc(fates_pft) ; + fates_seed_alloc:units = "fraction" ; + fates_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; + double fates_seed_alloc_mature(fates_pft) ; + fates_seed_alloc_mature:units = "fraction" ; + fates_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; + double fates_seed_dbh_repro_threshold(fates_pft) ; + fates_seed_dbh_repro_threshold:units = "cm" ; + fates_seed_dbh_repro_threshold:long_name = "the diameter (if any) where the plant will start extra clonal allocation to the seed pool" ; + double fates_seed_decay_rate(fates_pft) ; + fates_seed_decay_rate:units = "yr-1" ; + fates_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; + double fates_seed_germination_rate(fates_pft) ; + fates_seed_germination_rate:units = "yr-1" ; + fates_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; + double fates_seed_suppl(fates_pft) ; + fates_seed_suppl:units = "KgC/m2/yr" ; + fates_seed_suppl:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; + double fates_senleaf_long_fdrought(fates_pft) ; + fates_senleaf_long_fdrought:units = "unitless[0-1]" ; + fates_senleaf_long_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; + double fates_smpsc(fates_pft) ; + fates_smpsc:units = "mm" ; + fates_smpsc:long_name = "Soil water potential at full stomatal closure" ; + double fates_smpso(fates_pft) ; + fates_smpso:units = "mm" ; + fates_smpso:long_name = "Soil water potential at full stomatal opening" ; + double fates_taulnir(fates_pft) ; + fates_taulnir:units = "fraction" ; + fates_taulnir:long_name = "Leaf transmittance: near-IR" ; + double fates_taulvis(fates_pft) ; + fates_taulvis:units = "fraction" ; + fates_taulvis:long_name = "Leaf transmittance: visible" ; + double fates_tausnir(fates_pft) ; + fates_tausnir:units = "fraction" ; + fates_tausnir:long_name = "Stem transmittance: near-IR" ; + double fates_tausvis(fates_pft) ; + fates_tausvis:units = "fraction" ; + fates_tausvis:long_name = "Stem transmittance: visible" ; + double fates_trim_inc(fates_pft) ; + fates_trim_inc:units = "m2/m2" ; + fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; + double fates_trim_limit(fates_pft) ; + fates_trim_limit:units = "m2/m2" ; + fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; + double fates_turnover_carb_retrans(fates_prt_organs, fates_pft) ; + fates_turnover_carb_retrans:units = "-" ; + fates_turnover_carb_retrans:long_name = "retranslocation fraction of carbon in turnover" ; + double fates_turnover_nitr_retrans(fates_prt_organs, fates_pft) ; + fates_turnover_nitr_retrans:units = "-" ; + fates_turnover_nitr_retrans:long_name = "retranslocation fraction of nitrogen in turnover" ; + double fates_turnover_phos_retrans(fates_prt_organs, fates_pft) ; + fates_turnover_phos_retrans:units = "-" ; + fates_turnover_phos_retrans:long_name = "retranslocation fraction of phosphorous in turnover, parameter 1" ; + double fates_turnover_retrans_mode(fates_pft) ; + fates_turnover_retrans_mode:units = "index" ; + fates_turnover_retrans_mode:long_name = "retranslocation method for leaf/fineroot turnover." ; + fates_turnover_retrans_mode:possible_values = "1: constant fraction." ; + double fates_wood_density(fates_pft) ; + fates_wood_density:units = "g/cm3" ; + fates_wood_density:long_name = "mean density of woody tissue in plant" ; + double fates_woody(fates_pft) ; + fates_woody:units = "logical flag" ; + fates_woody:long_name = "Binary woody lifeform flag" ; + double fates_z0mr(fates_pft) ; + fates_z0mr:units = "unitless" ; + fates_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_fire_FBD(fates_litterclass) ; + fates_fire_FBD:units = "kg Biomass/m3" ; + fates_fire_FBD:long_name = "fuel bulk density" ; + double fates_fire_low_moisture_Coeff(fates_litterclass) ; + fates_fire_low_moisture_Coeff:units = "NA" ; + fates_fire_low_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_low_moisture_Slope(fates_litterclass) ; + fates_fire_low_moisture_Slope:units = "NA" ; + fates_fire_low_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture(fates_litterclass) ; + fates_fire_mid_moisture:units = "NA" ; + fates_fire_mid_moisture:long_name = "spitfire litter moisture threshold to be considered medium dry" ; + double fates_fire_mid_moisture_Coeff(fates_litterclass) ; + fates_fire_mid_moisture_Coeff:units = "NA" ; + fates_fire_mid_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture_Slope(fates_litterclass) ; + fates_fire_mid_moisture_Slope:units = "NA" ; + fates_fire_mid_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_min_moisture(fates_litterclass) ; + fates_fire_min_moisture:units = "NA" ; + fates_fire_min_moisture:long_name = "spitfire litter moisture threshold to be considered very dry" ; + double fates_fire_SAV(fates_litterclass) ; + fates_fire_SAV:units = "cm-1" ; + fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; + double fates_max_decomp(fates_litterclass) ; + fates_max_decomp:units = "yr-1" ; + fates_max_decomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; + double fates_CWD_frac(fates_NCWD) ; + fates_CWD_frac:units = "fraction" ; + fates_CWD_frac:long_name = "fraction of woody (bdead+bsw) biomass destined for CWD pool" ; + double fates_base_mr_20 ; + fates_base_mr_20:units = "gC/gN/s" ; + fates_base_mr_20:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; + 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" ; + double fates_cohort_age_fusion_tol ; + fates_cohort_age_fusion_tol:units = "unitless" ; + fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; + double fates_cohort_size_fusion_tol ; + fates_cohort_size_fusion_tol:units = "unitless" ; + fates_cohort_size_fusion_tol:long_name = "minimum fraction in difference in dbh between cohorts" ; + double fates_comp_excln ; + fates_comp_excln:units = "none" ; + fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; + double fates_cwd_fcel ; + fates_cwd_fcel:units = "unitless" ; + fates_cwd_fcel:long_name = "Cellulose fraction for CWD" ; + double fates_cwd_flig ; + fates_cwd_flig:units = "unitless" ; + fates_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; + double fates_dev_arbitrary ; + fates_dev_arbitrary:units = "unknown" ; + fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; + double fates_eca_plant_escalar ; + fates_eca_plant_escalar:units = "" ; + fates_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; + double fates_fire_active_crown_fire ; + fates_fire_active_crown_fire:units = "0 or 1" ; + fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; + double fates_fire_cg_strikes ; + fates_fire_cg_strikes:units = "fraction (0-1)" ; + fates_fire_cg_strikes:long_name = "fraction of cloud to ground lightning strikes" ; + double fates_fire_drying_ratio ; + fates_fire_drying_ratio:units = "NA" ; + fates_fire_drying_ratio:long_name = "spitfire parameter, fire drying ratio for fuel moisture, alpha_FMC EQ 6 Thonicke et al 2010" ; + double fates_fire_durat_slope ; + fates_fire_durat_slope:units = "NA" ; + fates_fire_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; + double fates_fire_fdi_a ; + fates_fire_fdi_a:units = "NA" ; + fates_fire_fdi_a:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010" ; + double fates_fire_fdi_alpha ; + fates_fire_fdi_alpha:units = "NA" ; + fates_fire_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; + double fates_fire_fdi_b ; + fates_fire_fdi_b:units = "NA" ; + fates_fire_fdi_b:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010 " ; + double fates_fire_fuel_energy ; + fates_fire_fuel_energy:units = "kJ/kg" ; + fates_fire_fuel_energy:long_name = "spitfire parameter, heat content of fuel" ; + double fates_fire_max_durat ; + fates_fire_max_durat:units = "minutes" ; + fates_fire_max_durat:long_name = "spitfire parameter, fire maximum duration, Equation 14 Thonicke et al 2010" ; + double fates_fire_miner_damp ; + fates_fire_miner_damp:units = "NA" ; + fates_fire_miner_damp:long_name = "spitfire parameter, mineral-dampening coefficient EQ A1 Thonicke et al 2010 " ; + double fates_fire_miner_total ; + fates_fire_miner_total:units = "fraction" ; + fates_fire_miner_total:long_name = "spitfire parameter, total mineral content, Table A1 Thonicke et al 2010" ; + double fates_fire_nignitions ; + fates_fire_nignitions:units = "ignitions per year per km2" ; + fates_fire_nignitions:long_name = "number of annual ignitions per square km" ; + double fates_fire_part_dens ; + fates_fire_part_dens:units = "kg/m2" ; + fates_fire_part_dens:long_name = "spitfire parameter, oven dry particle density, Table A1 Thonicke et al 2010" ; + double fates_fire_threshold ; + fates_fire_threshold:units = "kW/m" ; + fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; + double fates_hydr_kmax_rsurf1 ; + fates_hydr_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; + fates_hydr_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; + double fates_hydr_kmax_rsurf2 ; + fates_hydr_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; + fates_hydr_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; + double fates_hydr_psi0 ; + fates_hydr_psi0:units = "MPa" ; + fates_hydr_psi0:long_name = "sapwood water potential at saturation" ; + double fates_hydr_psicap ; + fates_hydr_psicap:units = "MPa" ; + fates_hydr_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; + double fates_init_litter ; + fates_init_litter:units = "NA" ; + fates_init_litter:long_name = "Initialization value for litter pool in cold-start (NOT USED)" ; + double fates_leaf_stomatal_model ; + fates_leaf_stomatal_model:units = "unitless" ; + fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; + double fates_logging_coll_under_frac ; + fates_logging_coll_under_frac:units = "fraction" ; + fates_logging_coll_under_frac:long_name = "Fraction of stems killed in the understory when logging generates disturbance" ; + double fates_logging_collateral_frac ; + fates_logging_collateral_frac:units = "fraction" ; + fates_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; + double fates_logging_dbhmax ; + fates_logging_dbhmax:units = "cm" ; + fates_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; + double fates_logging_dbhmax_infra ; + fates_logging_dbhmax_infra:units = "cm" ; + fates_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; + double fates_logging_dbhmin ; + fates_logging_dbhmin:units = "cm" ; + fates_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; + double fates_logging_direct_frac ; + fates_logging_direct_frac:units = "fraction" ; + fates_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; + double fates_logging_event_code ; + fates_logging_event_code:units = "unitless" ; + fates_logging_event_code:long_name = "Integer code that options how logging events are structured" ; + double fates_logging_export_frac ; + fates_logging_export_frac:units = "fraction" ; + fates_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; + double fates_logging_mechanical_frac ; + fates_logging_mechanical_frac:units = "fraction" ; + fates_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; + double fates_maintresp_model ; + fates_maintresp_model:units = "unitless" ; + fates_maintresp_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991) (NOT USED)" ; + double fates_mort_disturb_frac ; + fates_mort_disturb_frac:units = "fraction" ; + fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; + double fates_mort_understorey_death ; + fates_mort_understorey_death:units = "fraction" ; + fates_mort_understorey_death:long_name = "fraction of plants in understorey cohort impacted by overstorey tree-fall" ; + double fates_patch_fusion_tol ; + fates_patch_fusion_tol:units = "unitless" ; + fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; + double fates_phen_a ; + fates_phen_a:units = "none" ; + fates_phen_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_b ; + fates_phen_b:units = "none" ; + fates_phen_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_c ; + fates_phen_c:units = "none" ; + fates_phen_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_chiltemp ; + fates_phen_chiltemp:units = "degrees C" ; + fates_phen_chiltemp:long_name = "chilling day counting threshold for vegetation" ; + double fates_phen_coldtemp ; + fates_phen_coldtemp:units = "degrees C" ; + fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; + double fates_phen_doff_time ; + fates_phen_doff_time:units = "days" ; + fates_phen_doff_time:long_name = "day threshold compared against days since leaves became off-allometry" ; + double fates_phen_drought_threshold ; + fates_phen_drought_threshold:units = "m3/m3" ; + fates_phen_drought_threshold:long_name = "liquid volume in soil layer, threashold for drought phenology" ; + double fates_phen_mindayson ; + fates_phen_mindayson:units = "days" ; + fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; + double fates_phen_ncolddayslim ; + fates_phen_ncolddayslim:units = "days" ; + fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; + double fates_photo_temp_acclim_timescale ; + fates_photo_temp_acclim_timescale:units = "days" ; + fates_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; + double fates_photo_tempsens_model ; + fates_photo_tempsens_model:units = "unitless" ; + fates_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; + double fates_q10_froz ; + fates_q10_froz:units = "unitless" ; + fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; + double fates_q10_mr ; + fates_q10_mr:units = "unitless" ; + fates_q10_mr:long_name = "Q10 for maintenance respiration" ; + double fates_soil_salinity ; + fates_soil_salinity:units = "ppt" ; + fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; + double fates_theta_cj_c3 ; + fates_theta_cj_c3:units = "unitless" ; + fates_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; + double fates_theta_cj_c4 ; + fates_theta_cj_c4:units = "unitless" ; + fates_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; + double fates_vai_top_bin_width ; + fates_vai_top_bin_width:units = "m2/m2" ; + fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer (NOT USED)" ; + double fates_vai_width_increase_factor ; + fates_vai_width_increase_factor:units = "unitless" ; + fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing) (NOT USED)" ; + +// global attributes: + :history = "This parameter file is maintained in version control\nSee https://github.com/NGEET/fates/blob/master/parameter_files/fates_params_default.cdl \nFor changes, use git blame \n" ; +data: + + fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; + + fates_history_coageclass_bin_edges = 0, 5 ; + + fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; + + fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, + 80, 90, 100 ; + + fates_hydr_htftype_node = 1, 1, 1, 1 ; + + fates_prt_organ_id = 1, 2, 3, 6 ; + + fates_pftname = + "broadleaf_evergreen_tropical_tree ", + "needleleaf_evergreen_extratrop_tree ", + "needleleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_tree ", + "broadleaf_hydrodecid_tropical_tree ", + "broadleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_shrub ", + "broadleaf_hydrodecid_extratrop_shrub ", + "broadleaf_colddecid_extratrop_shrub ", + "arctic_c3_grass ", + "cool_c3_grass ", + "c4_grass " ; + + fates_hydr_organname_node = + "leaf ", + "stem ", + "transporting root ", + "absorbing root " ; + + fates_litterclass_name = + "twig ", + "small branch ", + "large branch ", + "trunk ", + "dead leaves ", + "live grass " ; + + fates_prt_organ_name = + "leaf ", + "fine root ", + "sapwood ", + "structure " ; + + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + 1.2, 1.2, 1.2 ; + + fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, + 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; + + fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, + 0.572, 0.572, 0.572, 0.572 ; + + fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, + 1.94, 1.94, 1.94 ; + + fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, + 0.931, 0.931, 0.931, 0.931 ; + + fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6 ; + + fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07 ; + + fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, + 1.3 ; + + fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, + 0.55, 0.55, 0.55 ; + + fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464 ; + + fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119 ; + + fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, + 0.64, 0.64, 0.64 ; + + fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, + 0.37, 0.37, 0.37 ; + + fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, + -999.9, -999.9, -999.9, -999.9, -999.9 ; + + fates_allom_dbh_maxheight = 90, 90, 90, 90, 90, 90, 3, 3, 2, 0.35, 0.35, 0.35 ; + + fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8 ; + + fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_zroot_k = 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 ; + + fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; + + fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_branch_turnover = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; + + fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + + fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, + 0.67, 0.67 ; + + fates_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 280, 280 ; + + fates_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, + 0.14, 0.14, 0.14 ; + + fates_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, + 0.27, 0.27, 0.27 ; + + fates_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; + + fates_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_eca_vmax_nh4 = 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, + 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07 ; + + fates_eca_vmax_no3 = 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, + 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08 ; + + fates_eca_vmax_p = 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, + 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09 ; + + fates_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2 ; + + fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07, 0.07 ; + + fates_fire_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, + 0.95, 1, 1, 1 ; + + fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, + 0.775, 0.775, 0.775, 0.775, 0.775 ; + + fates_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; + + fates_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; + + fates_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_fr_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_fr_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25 ; + + fates_fr_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25 ; + + fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, + 0.11, 0.11 ; + + fates_hydr_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + 2.5 ; + + fates_hydr_avuln_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_hydr_epsil_node = + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_hydr_fcap_node = + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydr_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydr_kmax_node = + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; + + fates_hydr_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + -1.5, -1.5, -1.5 ; + + fates_hydr_p50_node = + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25 ; + + fates_hydr_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, + 0.333, 0.333, 0.333, 0.333 ; + + fates_hydr_pinot_node = + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; + + fates_hydr_pitlp_node = + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + -1.67, -1.67, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; + + fates_hydr_resid_node = + 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; + + fates_hydr_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + 0.625, 0.625, 0.625, 0.625, 0.625 ; + + fates_hydr_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, + 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; + + fates_hydr_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; + + fates_hydr_thetas_node = + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; + + fates_hydr_vg_alpha_node = + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005 ; + + fates_hydr_vg_m_node = + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_hydr_vg_n_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_leaf_c3psn = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ; + + fates_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, + 0.9, 0.75, 0.75, 0.75 ; + + fates_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.04, 0.04, 0.04 ; + + fates_leaf_jmaxha = 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, + 43540, 43540, 43540, 43540 ; + + fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, + 152040, 152040, 152040, 152040, 152040 ; + + fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, + 495 ; + + fates_leaf_long = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, + 0.03, 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, + 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, + 10000, 10000, 10000, 10000, 10000, 40000 ; + + fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, + 4.7, 2.2, 5.3, 1.6 ; + + fates_leaf_stor_priority = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8 ; + + fates_leaf_vcmax25top = + 50, 65, 39, 62, 41, 58, 62, 54, 54, 78, 78, 78 ; + + fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, + 65330, 65330, 65330, 65330 ; + + fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, + 149250, 149250, 149250, 149250, 149250 ; + + fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, + 485 ; + + fates_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, -0.23, + -0.23, -0.23 ; + + fates_lf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_lf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25 ; + + fates_lf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25 ; + + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; + + fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, + 0.014, 0.014, 0.014, 0.014 ; + + fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -60, -10, -80, -80, + -20, 2.5 ; + + fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, + 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; + + fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_nfix1 = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_nfix2 = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5 ; + + fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; + + fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; + + fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; + + fates_phenflush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5 ; + + fates_prescribed_mortality_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, + 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; + + fates_prescribed_mortality_understory = 0.025, 0.025, 0.025, 0.025, 0.025, + 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; + + fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, + 0.4, 0.4, 0.4 ; + + fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, + 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; + + fates_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_prescribed_recruitment = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, + 0.02, 0.02, 0.02, 0.02, 0.02 ; + + fates_prt_alloc_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, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; + + fates_prt_nitr_stoich_p1 = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; + + fates_prt_nitr_stoich_p2 = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; + + fates_prt_phos_stoich_p1 = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; + + fates_prt_phos_stoich_p2 = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; + + fates_recruit_hgt_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, + 0.125, 0.125, 0.125 ; + + fates_recruit_initd = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2 ; + + fates_rholnir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, 0.41, 0.28, + 0.28, 0.28 ; + + fates_rholvis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, 0.08, 0.05, 0.05, 0.05 ; + + fates_rhosnir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, 0.49, 0.53, + 0.53, 0.53 ; + + fates_rhosvis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.31, + 0.31, 0.31 ; + + fates_root_long = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; + + fates_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9 ; + + fates_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, 1.47, + 1.47, 1.47 ; + + fates_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, + 0.51, 0.51, 0.51, 0.51 ; + + fates_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_seed_suppl = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_senleaf_long_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, -255000, + -255000, -255000, -255000, -255000, -255000 ; + + fates_smpso = -66000, -66000, -66000, -66000, -66000, -66000, -66000, + -66000, -66000, -66000, -66000, -66000 ; + + fates_taulnir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, 0.43, 0.4, + 0.4, 0.4 ; + + fates_taulvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.05, + 0.05, 0.05 ; + + fates_tausnir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.25, 0.25, 0.25 ; + + fates_tausvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.12, 0.12, 0.12 ; + + fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, + 0.03, 0.03 ; + + fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; + + fates_turnover_carb_retrans = + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_turnover_nitr_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_turnover_phos_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_turnover_retrans_mode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, + 0.7 ; + + fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; + + fates_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, + 0.055, 0.055, 0.055 ; + + fates_hlm_pft_map = + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + + fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; + + fates_fire_low_moisture_Coeff = 1.12, 1.09, 0.98, 0.8, 1.15, 1.15 ; + + fates_fire_low_moisture_Slope = 0.62, 0.72, 0.85, 0.8, 0.62, 0.62 ; + + fates_fire_mid_moisture = 0.72, 0.51, 0.38, 1, 0.8, 0.8 ; + + fates_fire_mid_moisture_Coeff = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_mid_moisture_Slope = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_min_moisture = 0.18, 0.12, 0, 0, 0.24, 0.24 ; + + fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; + + fates_max_decomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; + + fates_CWD_frac = 0.045, 0.075, 0.21, 0.67 ; + + fates_base_mr_20 = 2.52e-06 ; + + fates_canopy_closure_thresh = 0.8 ; + + fates_cohort_age_fusion_tol = 0.08 ; + + fates_cohort_size_fusion_tol = 0.08 ; + + fates_comp_excln = 3 ; + + fates_cwd_fcel = 0.76 ; + + fates_cwd_flig = 0.24 ; + + fates_dev_arbitrary = _ ; + + fates_eca_plant_escalar = 1.25e-05 ; + + fates_fire_active_crown_fire = 0 ; + + fates_fire_cg_strikes = 0.2 ; + + fates_fire_drying_ratio = 66000 ; + + fates_fire_durat_slope = -11.06 ; + + fates_fire_fdi_a = 17.62 ; + + fates_fire_fdi_alpha = 0.00037 ; + + fates_fire_fdi_b = 243.12 ; + + fates_fire_fuel_energy = 18000 ; + + fates_fire_max_durat = 240 ; + + fates_fire_miner_damp = 0.41739 ; + + fates_fire_miner_total = 0.055 ; + + fates_fire_nignitions = 15 ; + + fates_fire_part_dens = 513 ; + + fates_fire_threshold = 50 ; + + fates_hydr_kmax_rsurf1 = 20 ; + + fates_hydr_kmax_rsurf2 = 0.0001 ; + + fates_hydr_psi0 = 0 ; + + fates_hydr_psicap = -0.6 ; + + fates_init_litter = 0.05 ; + + fates_leaf_stomatal_model = 1 ; + + fates_logging_coll_under_frac = 0.55983 ; + + fates_logging_collateral_frac = 0.05 ; + + fates_logging_dbhmax = _ ; + + fates_logging_dbhmax_infra = 35 ; + + fates_logging_dbhmin = 50 ; + + fates_logging_direct_frac = 0.15 ; + + fates_logging_event_code = -30 ; + + fates_logging_export_frac = 0.8 ; + + fates_logging_mechanical_frac = 0.05 ; + + fates_maintresp_model = 1 ; + + fates_mort_disturb_frac = 1 ; + + fates_mort_understorey_death = 0.55983 ; + + fates_patch_fusion_tol = 0.05 ; + + fates_phen_a = -68 ; + + fates_phen_b = 638 ; + + fates_phen_c = -0.01 ; + + fates_phen_chiltemp = 5 ; + + fates_phen_coldtemp = 7.5 ; + + fates_phen_doff_time = 100 ; + + fates_phen_drought_threshold = 0.15 ; + + fates_phen_mindayson = 90 ; + + fates_phen_ncolddayslim = 5 ; + + fates_photo_temp_acclim_timescale = 30 ; + + fates_photo_tempsens_model = 1 ; + + fates_q10_froz = 1.5 ; + + fates_q10_mr = 1.5 ; + + fates_soil_salinity = 0.4 ; + + fates_theta_cj_c3 = 0.999 ; + + fates_theta_cj_c4 = 0.999 ; + + fates_vai_top_bin_width = 1 ; + + fates_vai_width_increase_factor = 1 ; +} diff --git a/parameter_files/fates_params_seed-dispersal.cdl b/parameter_files/fates_params_seed-dispersal.cdl new file mode 100644 index 0000000000..6335326e89 --- /dev/null +++ b/parameter_files/fates_params_seed-dispersal.cdl @@ -0,0 +1,1550 @@ +netcdf tmp { +dimensions: + fates_NCWD = 4 ; + fates_history_age_bins = 7 ; + fates_history_coage_bins = 2 ; + fates_history_damage_bins = 2 ; + fates_history_height_bins = 6 ; + fates_history_size_bins = 13 ; + fates_hlm_pftno = 14 ; + fates_hydr_organs = 4 ; + fates_leafage_class = 1 ; + fates_litterclass = 6 ; + fates_pft = 12 ; + fates_plant_organs = 4 ; + fates_string_length = 60 ; +variables: + double fates_history_ageclass_bin_edges(fates_history_age_bins) ; + fates_history_ageclass_bin_edges:units = "yr" ; + fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; + double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; + fates_history_coageclass_bin_edges:units = "years" ; + fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; + double fates_history_height_bin_edges(fates_history_height_bins) ; + fates_history_height_bin_edges:units = "m" ; + fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; + double fates_history_damage_bin_edges(fates_history_damage_bins) ; + fates_history_damage_bin_edges:units = "% crown loss" ; + fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; + double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; + fates_history_sizeclass_bin_edges:units = "cm" ; + fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; + double fates_alloc_organ_id(fates_plant_organs) ; + fates_alloc_organ_id:units = "unitless" ; + fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; + double fates_hydro_htftype_node(fates_hydr_organs) ; + fates_hydro_htftype_node:units = "unitless" ; + fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; + char fates_pftname(fates_pft, fates_string_length) ; + fates_pftname:units = "unitless - string" ; + fates_pftname:long_name = "Description of plant type" ; + char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; + fates_hydro_organ_name:units = "unitless - string" ; + fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; + char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; + fates_alloc_organ_name:units = "unitless - string" ; + fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; + 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" ; + 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" ; + double fates_alloc_storage_cushion(fates_pft) ; + fates_alloc_storage_cushion:units = "fraction" ; + fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; + double fates_alloc_store_priority_frac(fates_pft) ; + fates_alloc_store_priority_frac:units = "unitless" ; + fates_alloc_store_priority_frac:long_name = "for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage" ; + double fates_allom_agb1(fates_pft) ; + fates_allom_agb1:units = "variable" ; + fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; + double fates_allom_agb2(fates_pft) ; + fates_allom_agb2:units = "variable" ; + fates_allom_agb2:long_name = "Parameter 2 for agb allometry" ; + double fates_allom_agb3(fates_pft) ; + fates_allom_agb3:units = "variable" ; + fates_allom_agb3:long_name = "Parameter 3 for agb allometry" ; + double fates_allom_agb4(fates_pft) ; + fates_allom_agb4:units = "variable" ; + fates_allom_agb4:long_name = "Parameter 4 for agb allometry" ; + double fates_allom_agb_frac(fates_pft) ; + fates_allom_agb_frac:units = "fraction" ; + fates_allom_agb_frac:long_name = "Fraction of woody biomass that is above ground" ; + double fates_allom_amode(fates_pft) ; + fates_allom_amode:units = "index" ; + fates_allom_amode:long_name = "AGB allometry function index." ; + double fates_allom_blca_expnt_diff(fates_pft) ; + fates_allom_blca_expnt_diff:units = "unitless" ; + fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; + double fates_allom_cmode(fates_pft) ; + fates_allom_cmode:units = "index" ; + fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; + double fates_allom_crown_depth_frac(fates_pft) ; + fates_allom_crown_depth_frac:units = "fraction" ; + fates_allom_crown_depth_frac:long_name = "the depth of a cohort crown as a fraction of its height" ; + double fates_allom_d2bl1(fates_pft) ; + fates_allom_d2bl1:units = "variable" ; + fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; + double fates_allom_d2bl2(fates_pft) ; + fates_allom_d2bl2:units = "variable" ; + fates_allom_d2bl2:long_name = "Parameter 2 for d2bl allometry" ; + double fates_allom_d2bl3(fates_pft) ; + fates_allom_d2bl3:units = "unitless" ; + fates_allom_d2bl3:long_name = "Parameter 3 for d2bl allometry" ; + double fates_allom_d2ca_coefficient_max(fates_pft) ; + fates_allom_d2ca_coefficient_max:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_max:long_name = "max (savanna) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2ca_coefficient_min(fates_pft) ; + fates_allom_d2ca_coefficient_min:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_min:long_name = "min (forest) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2h1(fates_pft) ; + fates_allom_d2h1:units = "variable" ; + fates_allom_d2h1:long_name = "Parameter 1 for d2h allometry (intercept, or c)" ; + double fates_allom_d2h2(fates_pft) ; + fates_allom_d2h2:units = "variable" ; + fates_allom_d2h2:long_name = "Parameter 2 for d2h allometry (slope, or m)" ; + double fates_allom_d2h3(fates_pft) ; + fates_allom_d2h3:units = "variable" ; + fates_allom_d2h3:long_name = "Parameter 3 for d2h allometry (optional)" ; + double fates_allom_dbh_maxheight(fates_pft) ; + fates_allom_dbh_maxheight:units = "cm" ; + fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; + double fates_allom_fmode(fates_pft) ; + fates_allom_fmode:units = "index" ; + fates_allom_fmode:long_name = "fine root biomass allometry function index." ; + double fates_allom_fnrt_prof_a(fates_pft) ; + fates_allom_fnrt_prof_a:units = "unitless" ; + fates_allom_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; + double fates_allom_fnrt_prof_b(fates_pft) ; + fates_allom_fnrt_prof_b:units = "unitless" ; + fates_allom_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; + double fates_allom_fnrt_prof_mode(fates_pft) ; + fates_allom_fnrt_prof_mode:units = "index" ; + fates_allom_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; + double fates_allom_frbstor_repro(fates_pft) ; + fates_allom_frbstor_repro:units = "fraction" ; + fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; + double fates_allom_hmode(fates_pft) ; + fates_allom_hmode:units = "index" ; + fates_allom_hmode:long_name = "height allometry function index." ; + double fates_allom_l2fr(fates_pft) ; + fates_allom_l2fr:units = "gC/gC" ; + fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; + double fates_allom_la_per_sa_int(fates_pft) ; + fates_allom_la_per_sa_int:units = "m2/cm2" ; + fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; + double fates_allom_la_per_sa_slp(fates_pft) ; + fates_allom_la_per_sa_slp:units = "m2/cm2/m" ; + fates_allom_la_per_sa_slp:long_name = "Leaf area per sapwood area rate of change with height, slope (optional)" ; + double fates_allom_lmode(fates_pft) ; + fates_allom_lmode:units = "index" ; + fates_allom_lmode:long_name = "leaf biomass allometry function index." ; + double fates_allom_sai_scaler(fates_pft) ; + fates_allom_sai_scaler:units = "m2/m2" ; + fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; + double fates_allom_smode(fates_pft) ; + fates_allom_smode:units = "index" ; + fates_allom_smode:long_name = "sapwood allometry function index." ; + double fates_allom_stmode(fates_pft) ; + fates_allom_stmode:units = "index" ; + fates_allom_stmode:long_name = "storage allometry function index." ; + double fates_allom_zroot_k(fates_pft) ; + fates_allom_zroot_k:units = "unitless" ; + fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; + double fates_allom_zroot_max_dbh(fates_pft) ; + fates_allom_zroot_max_dbh:units = "cm" ; + fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; + double fates_allom_zroot_max_z(fates_pft) ; + fates_allom_zroot_max_z:units = "m" ; + fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_allom_zroot_min_dbh(fates_pft) ; + fates_allom_zroot_min_dbh:units = "cm" ; + fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; + double fates_allom_zroot_min_z(fates_pft) ; + fates_allom_zroot_min_z:units = "m" ; + fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_c2b(fates_pft) ; + fates_c2b:units = "ratio" ; + fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; + double fates_cnp_eca_alpha_ptase(fates_pft) ; + fates_cnp_eca_alpha_ptase:units = "g/m3" ; + fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; + double fates_cnp_eca_decompmicc(fates_pft) ; + fates_cnp_eca_decompmicc:units = "gC/m3" ; + fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; + double fates_cnp_eca_km_nh4(fates_pft) ; + fates_cnp_eca_km_nh4:units = "gN/m3" ; + fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; + double fates_cnp_eca_km_no3(fates_pft) ; + fates_cnp_eca_km_no3:units = "gN/m3" ; + fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; + double fates_cnp_eca_km_p(fates_pft) ; + fates_cnp_eca_km_p:units = "gP/m3" ; + fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; + double fates_cnp_eca_km_ptase(fates_pft) ; + fates_cnp_eca_km_ptase:units = "gP/m3" ; + fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; + double fates_cnp_eca_lambda_ptase(fates_pft) ; + fates_cnp_eca_lambda_ptase:units = "g/m3" ; + fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; + double fates_cnp_eca_vmax_nh4(fates_pft) ; + fates_cnp_eca_vmax_nh4:units = "gN/gC/s" ; + fates_cnp_eca_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA)" ; + double fates_cnp_eca_vmax_no3(fates_pft) ; + fates_cnp_eca_vmax_no3:units = "gN/gC/s" ; + fates_cnp_eca_vmax_no3:long_name = "maximum production rate for plant no3 uptake (ECA)" ; + double fates_cnp_eca_vmax_ptase(fates_pft) ; + fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; + fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; + double fates_cnp_fnrt_adapt_tscale(fates_pft) ; + fates_cnp_fnrt_adapt_tscale:units = "days" ; + fates_cnp_fnrt_adapt_tscale:long_name = "Number of days that is shortest possible doubling period for fine-root adaptation to C/N/P balance" ; + double fates_cnp_nfix1(fates_pft) ; + fates_cnp_nfix1:units = "NA" ; + fates_cnp_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; + double fates_cnp_nitr_store_ratio(fates_pft) ; + fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; + fates_cnp_nitr_store_ratio:long_name = "storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code)" ; + double fates_cnp_phos_store_ratio(fates_pft) ; + fates_cnp_phos_store_ratio:units = "(gP/gP)" ; + fates_cnp_phos_store_ratio:long_name = "storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code)" ; + double fates_cnp_prescribed_nuptake(fates_pft) ; + fates_cnp_prescribed_nuptake:units = "fraction" ; + fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; + double fates_cnp_prescribed_puptake(fates_pft) ; + fates_cnp_prescribed_puptake:units = "fraction" ; + fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; + double fates_cnp_rd_vmax_n(fates_pft) ; + fates_cnp_rd_vmax_n:units = "gN/gC/s" ; + fates_cnp_rd_vmax_n:long_name = "maximum production rate for compbined (NH4+NO3) uptake (RD)" ; + double fates_cnp_store_ovrflw_frac(fates_pft) ; + fates_cnp_store_ovrflw_frac:units = "fraction" ; + fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; + fates_cnp_store_ovrflw_frac:use_case = "None" ; + double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_nitr_retrans:units = "fraction" ; + fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; + double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_phos_retrans:units = "fraction" ; + fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; + double fates_cnp_vmax_p(fates_pft) ; + fates_cnp_vmax_p:units = "gP/gC/s" ; + fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; + double fates_damage_frac(fates_pft) ; + fates_damage_frac:units = "fraction" ; + fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; + double fates_damage_mort_p1(fates_pft) ; + fates_damage_mort_p1:units = "fraction" ; + fates_damage_mort_p1:long_name = "inflection point of damage mortality function, a value of 0.8 means 50% mortality with 80% loss of crown, turn off with a large number" ; + double fates_damage_mort_p2(fates_pft) ; + fates_damage_mort_p2:units = "unitless" ; + fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; + 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_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" ; + double fates_fire_alpha_SH(fates_pft) ; + fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; + fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; + double fates_fire_bark_scaler(fates_pft) ; + fates_fire_bark_scaler:units = "fraction" ; + fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; + double fates_fire_crown_kill(fates_pft) ; + fates_fire_crown_kill:units = "NA" ; + fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; + double fates_frag_fnrt_fcel(fates_pft) ; + fates_frag_fnrt_fcel:units = "fraction" ; + fates_frag_fnrt_fcel:long_name = "Fine root litter cellulose fraction" ; + double fates_frag_fnrt_flab(fates_pft) ; + fates_frag_fnrt_flab:units = "fraction" ; + fates_frag_fnrt_flab:long_name = "Fine root litter labile fraction" ; + double fates_frag_fnrt_flig(fates_pft) ; + fates_frag_fnrt_flig:units = "fraction" ; + fates_frag_fnrt_flig:long_name = "Fine root litter lignin fraction" ; + double fates_frag_leaf_fcel(fates_pft) ; + fates_frag_leaf_fcel:units = "fraction" ; + fates_frag_leaf_fcel:long_name = "Leaf litter cellulose fraction" ; + double fates_frag_leaf_flab(fates_pft) ; + fates_frag_leaf_flab:units = "fraction" ; + fates_frag_leaf_flab:long_name = "Leaf litter labile fraction" ; + double fates_frag_leaf_flig(fates_pft) ; + fates_frag_leaf_flig:units = "fraction" ; + fates_frag_leaf_flig:long_name = "Leaf litter lignin fraction" ; + double fates_frag_seed_decay_rate(fates_pft) ; + fates_frag_seed_decay_rate:units = "yr-1" ; + fates_frag_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; + double fates_grperc(fates_pft) ; + fates_grperc:units = "unitless" ; + fates_grperc:long_name = "Growth respiration factor" ; + double fates_hydro_avuln_gs(fates_pft) ; + fates_hydro_avuln_gs:units = "unitless" ; + fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; + double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; + fates_hydro_avuln_node:units = "unitless" ; + fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; + double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; + fates_hydro_epsil_node:units = "MPa" ; + fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; + double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; + fates_hydro_fcap_node:units = "unitless" ; + fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; + double fates_hydro_k_lwp(fates_pft) ; + fates_hydro_k_lwp:units = "unitless" ; + fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; + double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; + fates_hydro_kmax_node:units = "kg/MPa/m/s" ; + fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; + double fates_hydro_p50_gs(fates_pft) ; + fates_hydro_p50_gs:units = "MPa" ; + fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; + double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; + fates_hydro_p50_node:units = "MPa" ; + fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; + double fates_hydro_p_taper(fates_pft) ; + fates_hydro_p_taper:units = "unitless" ; + fates_hydro_p_taper:long_name = "xylem taper exponent" ; + double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pinot_node:units = "MPa" ; + fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; + double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pitlp_node:units = "MPa" ; + fates_hydro_pitlp_node:long_name = "turgor loss point" ; + double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; + fates_hydro_resid_node:units = "cm3/cm3" ; + fates_hydro_resid_node:long_name = "residual water conent" ; + double fates_hydro_rfrac_stem(fates_pft) ; + fates_hydro_rfrac_stem:units = "fraction" ; + fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; + double fates_hydro_rs2(fates_pft) ; + fates_hydro_rs2:units = "m" ; + fates_hydro_rs2:long_name = "absorbing root radius" ; + double fates_hydro_srl(fates_pft) ; + fates_hydro_srl:units = "m g-1" ; + fates_hydro_srl:long_name = "specific root length" ; + double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; + fates_hydro_thetas_node:units = "cm3/cm3" ; + fates_hydro_thetas_node:long_name = "saturated water content" ; + double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_alpha_node:units = "MPa-1" ; + fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; + double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_m_node:units = "unitless" ; + fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; + 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_leaf_c3psn(fates_pft) ; + fates_leaf_c3psn:units = "flag" ; + fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; + double fates_leaf_jmaxha(fates_pft) ; + fates_leaf_jmaxha:units = "J/mol" ; + fates_leaf_jmaxha:long_name = "activation energy for jmax" ; + double fates_leaf_jmaxhd(fates_pft) ; + fates_leaf_jmaxhd:units = "J/mol" ; + fates_leaf_jmaxhd:long_name = "deactivation energy for jmax" ; + double fates_leaf_jmaxse(fates_pft) ; + fates_leaf_jmaxse:units = "J/mol/K" ; + fates_leaf_jmaxse:long_name = "entropy term for jmax" ; + double fates_leaf_slamax(fates_pft) ; + fates_leaf_slamax:units = "m^2/gC" ; + fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; + double fates_leaf_slatop(fates_pft) ; + fates_leaf_slatop:units = "m^2/gC" ; + fates_leaf_slatop:long_name = "Specific Leaf Area (SLA) at top of canopy, projected area basis" ; + double fates_leaf_stomatal_intercept(fates_pft) ; + fates_leaf_stomatal_intercept:units = "umol H2O/m**2/s" ; + fates_leaf_stomatal_intercept:long_name = "Minimum unstressed stomatal conductance for Ball-Berry model and Medlyn model" ; + double fates_leaf_stomatal_slope_ballberry(fates_pft) ; + fates_leaf_stomatal_slope_ballberry:units = "unitless" ; + fates_leaf_stomatal_slope_ballberry:long_name = "stomatal slope parameter, as per Ball-Berry" ; + double fates_leaf_stomatal_slope_medlyn(fates_pft) ; + fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; + fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; + double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; + fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; + fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; + double fates_leaf_vcmaxha(fates_pft) ; + fates_leaf_vcmaxha:units = "J/mol" ; + fates_leaf_vcmaxha:long_name = "activation energy for vcmax" ; + double fates_leaf_vcmaxhd(fates_pft) ; + fates_leaf_vcmaxhd:units = "J/mol" ; + fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax" ; + double fates_leaf_vcmaxse(fates_pft) ; + fates_leaf_vcmaxse:units = "J/mol/K" ; + fates_leaf_vcmaxse:long_name = "entropy term for vcmax" ; + double fates_maintresp_reduction_curvature(fates_pft) ; + fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; + fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; + double fates_maintresp_reduction_intercept(fates_pft) ; + fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; + fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; + double fates_mort_bmort(fates_pft) ; + fates_mort_bmort:units = "1/yr" ; + fates_mort_bmort:long_name = "background mortality rate" ; + double fates_mort_freezetol(fates_pft) ; + fates_mort_freezetol:units = "degrees C" ; + fates_mort_freezetol:long_name = "minimum temperature tolerance" ; + double fates_mort_hf_flc_threshold(fates_pft) ; + fates_mort_hf_flc_threshold:units = "fraction" ; + fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; + double fates_mort_hf_sm_threshold(fates_pft) ; + fates_mort_hf_sm_threshold:units = "unitless" ; + fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; + double fates_mort_ip_age_senescence(fates_pft) ; + fates_mort_ip_age_senescence:units = "years" ; + fates_mort_ip_age_senescence:long_name = "Mortality cohort age senescence inflection point. If _ this mortality term is off. Setting this value turns on age dependent mortality. " ; + double fates_mort_ip_size_senescence(fates_pft) ; + fates_mort_ip_size_senescence:units = "dbh cm" ; + fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; + double fates_mort_prescribed_canopy(fates_pft) ; + fates_mort_prescribed_canopy:units = "1/yr" ; + fates_mort_prescribed_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; + double fates_mort_prescribed_understory(fates_pft) ; + fates_mort_prescribed_understory:units = "1/yr" ; + fates_mort_prescribed_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; + double fates_mort_r_age_senescence(fates_pft) ; + fates_mort_r_age_senescence:units = "mortality rate year^-1" ; + fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; + double fates_mort_r_size_senescence(fates_pft) ; + fates_mort_r_size_senescence:units = "mortality rate dbh^-1" ; + fates_mort_r_size_senescence:long_name = "Mortality dbh senescence rate of change. Sensible range is around 0.03-0.06. Larger values give steeper mortality curves." ; + double fates_mort_scalar_coldstress(fates_pft) ; + fates_mort_scalar_coldstress:units = "1/yr" ; + fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; + double fates_mort_scalar_cstarvation(fates_pft) ; + fates_mort_scalar_cstarvation:units = "1/yr" ; + fates_mort_scalar_cstarvation:long_name = "maximum mortality rate from carbon starvation" ; + double fates_mort_scalar_hydrfailure(fates_pft) ; + fates_mort_scalar_hydrfailure:units = "1/yr" ; + fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; + double fates_nonhydro_smpsc(fates_pft) ; + fates_nonhydro_smpsc:units = "mm" ; + fates_nonhydro_smpsc:long_name = "Soil water potential at full stomatal closure" ; + double fates_nonhydro_smpso(fates_pft) ; + fates_nonhydro_smpso:units = "mm" ; + fates_nonhydro_smpso:long_name = "Soil water potential at full stomatal opening" ; + double fates_phen_cold_size_threshold(fates_pft) ; + fates_phen_cold_size_threshold:units = "cm" ; + fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; + double fates_phen_evergreen(fates_pft) ; + fates_phen_evergreen:units = "logical flag" ; + fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; + double fates_phen_flush_fraction(fates_pft) ; + fates_phen_flush_fraction:units = "fraction" ; + fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; + double fates_phen_fnrt_drop_frac(fates_pft) ; + fates_phen_fnrt_drop_frac:units = "fraction" ; + fates_phen_fnrt_drop_frac:long_name = "fraction of fine roots to drop during drought or cold" ; + double fates_phen_season_decid(fates_pft) ; + fates_phen_season_decid:units = "logical flag" ; + fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; + double fates_phen_stem_drop_fraction(fates_pft) ; + fates_phen_stem_drop_fraction:units = "fraction" ; + fates_phen_stem_drop_fraction:long_name = "fraction of stems to drop for non-woody species during drought/cold" ; + double fates_phen_stress_decid(fates_pft) ; + fates_phen_stress_decid:units = "logical flag" ; + fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; + double fates_prescribed_npp_canopy(fates_pft) ; + fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; + double fates_prescribed_npp_understory(fates_pft) ; + fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; + double fates_rad_leaf_clumping_index(fates_pft) ; + fates_rad_leaf_clumping_index:units = "fraction (0-1)" ; + fates_rad_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; + double fates_rad_leaf_rhonir(fates_pft) ; + fates_rad_leaf_rhonir:units = "fraction" ; + fates_rad_leaf_rhonir:long_name = "Leaf reflectance: near-IR" ; + double fates_rad_leaf_rhovis(fates_pft) ; + fates_rad_leaf_rhovis:units = "fraction" ; + fates_rad_leaf_rhovis:long_name = "Leaf reflectance: visible" ; + double fates_rad_leaf_taunir(fates_pft) ; + fates_rad_leaf_taunir:units = "fraction" ; + fates_rad_leaf_taunir:long_name = "Leaf transmittance: near-IR" ; + double fates_rad_leaf_tauvis(fates_pft) ; + fates_rad_leaf_tauvis:units = "fraction" ; + fates_rad_leaf_tauvis:long_name = "Leaf transmittance: visible" ; + double fates_rad_leaf_xl(fates_pft) ; + fates_rad_leaf_xl:units = "unitless" ; + fates_rad_leaf_xl:long_name = "Leaf/stem orientation index" ; + double fates_rad_stem_rhonir(fates_pft) ; + fates_rad_stem_rhonir:units = "fraction" ; + fates_rad_stem_rhonir:long_name = "Stem reflectance: near-IR" ; + double fates_rad_stem_rhovis(fates_pft) ; + fates_rad_stem_rhovis:units = "fraction" ; + fates_rad_stem_rhovis:long_name = "Stem reflectance: visible" ; + double fates_rad_stem_taunir(fates_pft) ; + fates_rad_stem_taunir:units = "fraction" ; + fates_rad_stem_taunir:long_name = "Stem transmittance: near-IR" ; + double fates_rad_stem_tauvis(fates_pft) ; + fates_rad_stem_tauvis:units = "fraction" ; + fates_rad_stem_tauvis:long_name = "Stem transmittance: visible" ; + double fates_recruit_height_min(fates_pft) ; + fates_recruit_height_min:units = "m" ; + fates_recruit_height_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; + double fates_recruit_init_density(fates_pft) ; + fates_recruit_init_density:units = "stems/m2" ; + fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation" ; + double fates_recruit_prescribed_rate(fates_pft) ; + fates_recruit_prescribed_rate:units = "n/yr" ; + fates_recruit_prescribed_rate:long_name = "recruitment rate for prescribed physiology mode" ; + double fates_recruit_seed_alloc(fates_pft) ; + fates_recruit_seed_alloc:units = "fraction" ; + fates_recruit_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; + double fates_recruit_seed_alloc_mature(fates_pft) ; + fates_recruit_seed_alloc_mature:units = "fraction" ; + fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; + double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; + fates_recruit_seed_dbh_repro_threshold:units = "cm" ; + fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter (if any) where the plant will start extra clonal allocation to the seed pool" ; + double fates_recruit_seed_germination_rate(fates_pft) ; + fates_recruit_seed_germination_rate:units = "yr-1" ; + fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; + double fates_recruit_seed_supplement(fates_pft) ; + fates_recruit_seed_supplement:units = "KgC/m2/yr" ; + fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; + double fates_seed_dispersal_param_A(fates_pft) ; + fates_seed_dispersal_param_A:units = "unitless" ; + fates_seed_dispersal_param_A:long_name = "seed dispersal scale parameter" ; + fates_seed_dispersal_param_A:use_case = "None" ; + double fates_seed_dispersal_param_B(fates_pft) ; + fates_seed_dispersal_param_B:units = "unitless" ; + fates_seed_dispersal_param_B:long_name = "seed dispersal shape parameter" ; + fates_seed_dispersal_param_B:use_case = "None" ; + double fates_stoich_nitr(fates_plant_organs, fates_pft) ; + fates_stoich_nitr:units = "gN/gC" ; + fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; + double fates_stoich_phos(fates_plant_organs, fates_pft) ; + fates_stoich_phos:units = "gP/gC" ; + fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; + double fates_trim_inc(fates_pft) ; + fates_trim_inc:units = "m2/m2" ; + fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; + double fates_trim_limit(fates_pft) ; + fates_trim_limit:units = "m2/m2" ; + fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; + double fates_turb_displar(fates_pft) ; + fates_turb_displar:units = "unitless" ; + fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; + double fates_turb_leaf_diameter(fates_pft) ; + fates_turb_leaf_diameter:units = "m" ; + fates_turb_leaf_diameter:long_name = "Characteristic leaf dimension" ; + double fates_turb_z0mr(fates_pft) ; + fates_turb_z0mr:units = "unitless" ; + fates_turb_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; + double fates_turnover_branch(fates_pft) ; + fates_turnover_branch:units = "yr" ; + fates_turnover_branch:long_name = "turnover time of branches" ; + double fates_turnover_fnrt(fates_pft) ; + fates_turnover_fnrt:units = "yr" ; + fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; + double fates_turnover_leaf(fates_leafage_class, fates_pft) ; + fates_turnover_leaf:units = "yr" ; + fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; + double fates_turnover_senleaf_fdrought(fates_pft) ; + fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; + fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; + double fates_wood_density(fates_pft) ; + fates_wood_density:units = "g/cm3" ; + fates_wood_density:long_name = "mean density of woody tissue in plant" ; + double fates_woody(fates_pft) ; + fates_woody:units = "logical flag" ; + fates_woody:long_name = "Binary woody lifeform flag" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_fire_FBD(fates_litterclass) ; + fates_fire_FBD:units = "kg Biomass/m3" ; + fates_fire_FBD:long_name = "fuel bulk density" ; + double fates_fire_low_moisture_Coeff(fates_litterclass) ; + fates_fire_low_moisture_Coeff:units = "NA" ; + fates_fire_low_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_low_moisture_Slope(fates_litterclass) ; + fates_fire_low_moisture_Slope:units = "NA" ; + fates_fire_low_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture(fates_litterclass) ; + fates_fire_mid_moisture:units = "NA" ; + fates_fire_mid_moisture:long_name = "spitfire litter moisture threshold to be considered medium dry" ; + double fates_fire_mid_moisture_Coeff(fates_litterclass) ; + fates_fire_mid_moisture_Coeff:units = "NA" ; + fates_fire_mid_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture_Slope(fates_litterclass) ; + fates_fire_mid_moisture_Slope:units = "NA" ; + fates_fire_mid_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_min_moisture(fates_litterclass) ; + fates_fire_min_moisture:units = "NA" ; + fates_fire_min_moisture:long_name = "spitfire litter moisture threshold to be considered very dry" ; + double fates_fire_SAV(fates_litterclass) ; + fates_fire_SAV:units = "cm-1" ; + fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; + double fates_frag_maxdecomp(fates_litterclass) ; + fates_frag_maxdecomp:units = "yr-1" ; + fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; + 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_base_mr_20 ; + fates_base_mr_20:units = "gC/gN/s" ; + fates_base_mr_20:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; + 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" ; + double fates_cnp_eca_plant_escalar ; + fates_cnp_eca_plant_escalar:units = "" ; + fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; + double fates_cohort_age_fusion_tol ; + fates_cohort_age_fusion_tol:units = "unitless" ; + fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; + double fates_cohort_size_fusion_tol ; + fates_cohort_size_fusion_tol:units = "unitless" ; + fates_cohort_size_fusion_tol:long_name = "minimum fraction in difference in dbh between cohorts" ; + double fates_comp_excln ; + fates_comp_excln:units = "none" ; + fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; + double fates_damage_canopy_layer_code ; + fates_damage_canopy_layer_code:units = "unitless" ; + fates_damage_canopy_layer_code:long_name = "Integer code that decides whether damage affects canopy trees (1), understory trees (2)" ; + double fates_damage_event_code ; + fates_damage_event_code:units = "unitless" ; + fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; + double fates_dev_arbitrary ; + fates_dev_arbitrary:units = "unknown" ; + fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; + double fates_fire_active_crown_fire ; + fates_fire_active_crown_fire:units = "0 or 1" ; + fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; + double fates_fire_cg_strikes ; + fates_fire_cg_strikes:units = "fraction (0-1)" ; + fates_fire_cg_strikes:long_name = "fraction of cloud to ground lightning strikes" ; + double fates_fire_drying_ratio ; + fates_fire_drying_ratio:units = "NA" ; + fates_fire_drying_ratio:long_name = "spitfire parameter, fire drying ratio for fuel moisture, alpha_FMC EQ 6 Thonicke et al 2010" ; + double fates_fire_durat_slope ; + fates_fire_durat_slope:units = "NA" ; + fates_fire_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; + double fates_fire_fdi_a ; + fates_fire_fdi_a:units = "NA" ; + fates_fire_fdi_a:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010" ; + double fates_fire_fdi_alpha ; + fates_fire_fdi_alpha:units = "NA" ; + fates_fire_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; + double fates_fire_fdi_b ; + fates_fire_fdi_b:units = "NA" ; + fates_fire_fdi_b:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010 " ; + double fates_fire_fuel_energy ; + fates_fire_fuel_energy:units = "kJ/kg" ; + fates_fire_fuel_energy:long_name = "spitfire parameter, heat content of fuel" ; + double fates_fire_max_durat ; + fates_fire_max_durat:units = "minutes" ; + fates_fire_max_durat:long_name = "spitfire parameter, fire maximum duration, Equation 14 Thonicke et al 2010" ; + double fates_fire_miner_damp ; + fates_fire_miner_damp:units = "NA" ; + fates_fire_miner_damp:long_name = "spitfire parameter, mineral-dampening coefficient EQ A1 Thonicke et al 2010 " ; + double fates_fire_miner_total ; + fates_fire_miner_total:units = "fraction" ; + fates_fire_miner_total:long_name = "spitfire parameter, total mineral content, Table A1 Thonicke et al 2010" ; + double fates_fire_nignitions ; + fates_fire_nignitions:units = "ignitions per year per km2" ; + fates_fire_nignitions:long_name = "number of annual ignitions per square km" ; + double fates_fire_part_dens ; + fates_fire_part_dens:units = "kg/m2" ; + fates_fire_part_dens:long_name = "spitfire parameter, oven dry particle density, Table A1 Thonicke et al 2010" ; + double fates_fire_threshold ; + fates_fire_threshold:units = "kW/m" ; + fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; + double fates_frag_cwd_fcel ; + fates_frag_cwd_fcel:units = "unitless" ; + fates_frag_cwd_fcel:long_name = "Cellulose fraction for CWD" ; + double fates_frag_cwd_flig ; + fates_frag_cwd_flig:units = "unitless" ; + fates_frag_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; + double fates_hydro_kmax_rsurf1 ; + fates_hydro_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; + double fates_hydro_kmax_rsurf2 ; + fates_hydro_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; + double fates_hydro_psi0 ; + fates_hydro_psi0:units = "MPa" ; + fates_hydro_psi0:long_name = "sapwood water potential at saturation" ; + double fates_hydro_psicap ; + fates_hydro_psicap:units = "MPa" ; + fates_hydro_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; + 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_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" ; + double fates_landuse_logging_collateral_frac ; + fates_landuse_logging_collateral_frac:units = "fraction" ; + fates_landuse_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; + double fates_landuse_logging_dbhmax ; + fates_landuse_logging_dbhmax:units = "cm" ; + fates_landuse_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; + double fates_landuse_logging_dbhmax_infra ; + fates_landuse_logging_dbhmax_infra:units = "cm" ; + fates_landuse_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; + double fates_landuse_logging_dbhmin ; + fates_landuse_logging_dbhmin:units = "cm" ; + fates_landuse_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; + double fates_landuse_logging_direct_frac ; + fates_landuse_logging_direct_frac:units = "fraction" ; + fates_landuse_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; + double fates_landuse_logging_event_code ; + fates_landuse_logging_event_code:units = "unitless" ; + fates_landuse_logging_event_code:long_name = "Integer code that options how logging events are structured" ; + double fates_landuse_logging_export_frac ; + fates_landuse_logging_export_frac:units = "fraction" ; + fates_landuse_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; + double fates_landuse_logging_mechanical_frac ; + fates_landuse_logging_mechanical_frac:units = "fraction" ; + fates_landuse_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; + double fates_landuse_pprodharv10_forest_mean ; + fates_landuse_pprodharv10_forest_mean:units = "fraction" ; + fates_landuse_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; + double fates_leaf_photo_temp_acclim_timescale ; + fates_leaf_photo_temp_acclim_timescale:units = "days" ; + fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; + double fates_leaf_photo_tempsens_model ; + fates_leaf_photo_tempsens_model:units = "unitless" ; + fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; + double fates_leaf_stomatal_assim_model ; + fates_leaf_stomatal_assim_model:units = "unitless" ; + fates_leaf_stomatal_assim_model:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; + double fates_leaf_stomatal_model ; + fates_leaf_stomatal_model:units = "unitless" ; + fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; + double fates_leaf_theta_cj_c3 ; + fates_leaf_theta_cj_c3:units = "unitless" ; + fates_leaf_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; + double fates_leaf_theta_cj_c4 ; + fates_leaf_theta_cj_c4:units = "unitless" ; + fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; + double fates_maintresp_model ; + fates_maintresp_model:units = "unitless" ; + fates_maintresp_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991) (NOT USED)" ; + double fates_maxcohort ; + fates_maxcohort:units = "count" ; + fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; + double fates_maxpatch_primary ; + fates_maxpatch_primary:units = "count" ; + fates_maxpatch_primary:long_name = "maximum number of primary vegetation patches per site" ; + double fates_maxpatch_secondary ; + fates_maxpatch_secondary:units = "count" ; + fates_maxpatch_secondary:long_name = "maximum number of secondary vegetation patches per site" ; + double fates_mort_disturb_frac ; + fates_mort_disturb_frac:units = "fraction" ; + fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; + double fates_mort_understorey_death ; + fates_mort_understorey_death:units = "fraction" ; + fates_mort_understorey_death:long_name = "fraction of plants in understorey cohort impacted by overstorey tree-fall" ; + double fates_patch_fusion_tol ; + fates_patch_fusion_tol:units = "unitless" ; + fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; + double fates_phen_chilltemp ; + fates_phen_chilltemp:units = "degrees C" ; + fates_phen_chilltemp:long_name = "chilling day counting threshold for vegetation" ; + double fates_phen_coldtemp ; + fates_phen_coldtemp:units = "degrees C" ; + fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; + double fates_phen_drought_model ; + fates_phen_drought_model:units = "unitless" ; + fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; + double fates_phen_drought_threshold ; + fates_phen_drought_threshold:units = "m3/m3 or mm" ; + fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_gddthresh_a ; + fates_phen_gddthresh_a:units = "none" ; + fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_b ; + fates_phen_gddthresh_b:units = "none" ; + fates_phen_gddthresh_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_c ; + fates_phen_gddthresh_c:units = "none" ; + fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_mindaysoff ; + fates_phen_mindaysoff:units = "days" ; + fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves became off-allometry" ; + double fates_phen_mindayson ; + fates_phen_mindayson:units = "days" ; + fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; + double fates_phen_moist_threshold ; + fates_phen_moist_threshold:units = "m3/m3 or mm" ; + fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_ncolddayslim ; + fates_phen_ncolddayslim:units = "days" ; + fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; + double fates_q10_froz ; + fates_q10_froz:units = "unitless" ; + fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; + double fates_q10_mr ; + fates_q10_mr:units = "unitless" ; + fates_q10_mr:long_name = "Q10 for maintenance respiration" ; + double fates_soil_salinity ; + fates_soil_salinity:units = "ppt" ; + fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; + double fates_vai_top_bin_width ; + fates_vai_top_bin_width:units = "m2/m2" ; + fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; + double fates_vai_width_increase_factor ; + fates_vai_width_increase_factor:units = "unitless" ; + fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; + +// global attributes: + :history = "This parameter file is maintained in version control\nSee https://github.com/NGEET/fates/blob/master/parameter_files/fates_params_default.cdl \nFor changes, use git blame \n" ; +data: + + fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; + + fates_history_coageclass_bin_edges = 0, 5 ; + + fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; + + fates_history_damage_bin_edges = 0, 80 ; + + fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, + 80, 90, 100 ; + + fates_alloc_organ_id = 1, 2, 3, 6 ; + + fates_hydro_htftype_node = 1, 1, 1, 1 ; + + fates_pftname = + "broadleaf_evergreen_tropical_tree ", + "needleleaf_evergreen_extratrop_tree ", + "needleleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_tree ", + "broadleaf_hydrodecid_tropical_tree ", + "broadleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_shrub ", + "broadleaf_hydrodecid_extratrop_shrub ", + "broadleaf_colddecid_extratrop_shrub ", + "arctic_c3_grass ", + "cool_c3_grass ", + "c4_grass " ; + + fates_hydro_organ_name = + "leaf ", + "stem ", + "transporting root ", + "absorbing root " ; + + fates_alloc_organ_name = + "leaf", + "fine root", + "sapwood", + "structure" ; + + fates_litterclass_name = + "twig ", + "small branch ", + "large branch ", + "trunk ", + "dead leaves ", + "live grass " ; + + 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, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; + + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + 1.2, 1.2, 1.2 ; + + fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8, 0.8 ; + + fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, + 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; + + fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, + 0.572, 0.572, 0.572, 0.572 ; + + fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, + 1.94, 1.94, 1.94 ; + + fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, + 0.931, 0.931, 0.931, 0.931 ; + + fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6 ; + + fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, + 0.95, 1, 1, 1 ; + + fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07 ; + + fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, + 1.3 ; + + fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, + 0.55, 0.55, 0.55 ; + + fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464 ; + + fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119 ; + + fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, + 0.64, 0.64, 0.64 ; + + fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, + 0.37, 0.37, 0.37 ; + + fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, + -999.9, -999.9, -999.9, -999.9, -999.9 ; + + fates_allom_dbh_maxheight = 90, 90, 90, 90, 90, 90, 3, 3, 2, 0.35, 0.35, 0.35 ; + + fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; + + fates_allom_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; + + fates_allom_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8 ; + + fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_zroot_k = 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 ; + + fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; + + fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + + fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 280, 280 ; + + fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, + 0.14, 0.14, 0.14 ; + + fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, + 0.27, 0.27, 0.27 ; + + fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_vmax_nh4 = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_eca_vmax_no3 = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_fnrt_adapt_tscale = 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100 ; + + fates_cnp_nfix1 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_rd_vmax_n = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_turnover_nitr_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_turnover_phos_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, + 5e-10, 5e-10, 5e-10, 5e-10 ; + + fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01 ; + + fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; + + fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, + 5.5, 5.5 ; + + fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2 ; + + fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07, 0.07 ; + + fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, + 0.775, 0.775, 0.775, 0.775, 0.775 ; + + fates_frag_fnrt_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_fnrt_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_fnrt_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_leaf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, + 0.51, 0.51, 0.51, 0.51 ; + + fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, + 0.11, 0.11 ; + + fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + 2.5, 2.5 ; + + fates_hydro_avuln_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_hydro_epsil_node = + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_hydro_fcap_node = + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_kmax_node = + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; + + fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + -1.5, -1.5, -1.5 ; + + fates_hydro_p50_node = + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25 ; + + fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, + 0.333, 0.333, 0.333, 0.333, 0.333 ; + + fates_hydro_pinot_node = + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; + + fates_hydro_pitlp_node = + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + -1.67, -1.67, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; + + fates_hydro_resid_node = + 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; + + fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + 0.625, 0.625, 0.625, 0.625, 0.625 ; + + fates_hydro_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, + 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; + + fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; + + fates_hydro_thetas_node = + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; + + fates_hydro_vg_alpha_node = + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005 ; + + fates_hydro_vg_m_node = + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_hydro_vg_n_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_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, + 43540, 43540, 43540, 43540 ; + + fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, + 152040, 152040, 152040, 152040, 152040 ; + + fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, + 495 ; + + fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, + 0.03, 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, + 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, + 10000, 10000, 10000, 10000, 10000, 40000 ; + + fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, + 4.7, 2.2, 5.3, 1.6 ; + + fates_leaf_vcmax25top = + 50, 65, 39, 62, 41, 58, 62, 54, 54, 78, 78, 78 ; + + fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, + 65330, 65330, 65330, 65330 ; + + fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, + 149250, 149250, 149250, 149250, 149250 ; + + fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, + 485 ; + + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; + + fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, + 0.014, 0.014, 0.014, 0.014 ; + + fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -60, -10, -80, -80, + -20, 2.5 ; + + fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, + 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; + + fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_prescribed_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, + 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; + + fates_mort_prescribed_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, + 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; + + fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_nonhydro_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, + -255000, -255000, -255000, -255000, -255000, -255000 ; + + fates_nonhydro_smpso = -66000, -66000, -66000, -66000, -66000, -66000, + -66000, -66000, -66000, -66000, -66000, -66000 ; + + fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; + + fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, + 0.5 ; + + fates_phen_fnrt_drop_frac = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; + + fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; + + fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, + 0.4, 0.4, 0.4 ; + + fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, + 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; + + fates_rad_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, + 0.9, 0.75, 0.75, 0.75 ; + + fates_rad_leaf_rhonir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, + 0.41, 0.28, 0.28, 0.28 ; + + fates_rad_leaf_rhovis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, + 0.08, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_taunir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, + 0.43, 0.4, 0.4, 0.4 ; + + fates_rad_leaf_tauvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, + 0.06, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, + -0.23, -0.23, -0.23 ; + + fates_rad_stem_rhonir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, + 0.49, 0.53, 0.53, 0.53 ; + + fates_rad_stem_rhovis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.31, 0.31, 0.31 ; + + fates_rad_stem_taunir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.25, 0.25, 0.25 ; + + fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.12, 0.12, 0.12 ; + + fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, + 0.125, 0.125, 0.125 ; + + fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2, 0.2, 0.2 ; + + fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, + 0.02, 0.02, 0.02, 0.02, 0.02 ; + + fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, + 0.9 ; + + fates_recruit_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, + 1.47, 1.47, 1.47 ; + + fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_seed_dispersal_param_A = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_seed_dispersal_param_B = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_stoich_nitr = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; + + fates_stoich_phos = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; + + fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, + 0.03, 0.03 ; + + fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; + + fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, + 0.67, 0.67, 0.67 ; + + fates_turb_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.04, 0.04, 0.04, 0.04 ; + + fates_turb_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, + 0.055, 0.055, 0.055, 0.055 ; + + fates_turnover_branch = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; + + fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_leaf = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, + 0.7 ; + + fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; + + fates_hlm_pft_map = + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + + fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; + + fates_fire_low_moisture_Coeff = 1.12, 1.09, 0.98, 0.8, 1.15, 1.15 ; + + fates_fire_low_moisture_Slope = 0.62, 0.72, 0.85, 0.8, 0.62, 0.62 ; + + fates_fire_mid_moisture = 0.72, 0.51, 0.38, 1, 0.8, 0.8 ; + + fates_fire_mid_moisture_Coeff = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_mid_moisture_Slope = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_min_moisture = 0.18, 0.12, 0, 0, 0.24, 0.24 ; + + fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; + + fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; + + fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; + + fates_base_mr_20 = 2.52e-06 ; + + fates_canopy_closure_thresh = 0.8 ; + + fates_cnp_eca_plant_escalar = 1.25e-05 ; + + fates_cohort_age_fusion_tol = 0.08 ; + + fates_cohort_size_fusion_tol = 0.08 ; + + fates_comp_excln = 3 ; + + fates_damage_canopy_layer_code = 1 ; + + fates_damage_event_code = 1 ; + + fates_dev_arbitrary = _ ; + + fates_fire_active_crown_fire = 0 ; + + fates_fire_cg_strikes = 0.2 ; + + fates_fire_drying_ratio = 66000 ; + + fates_fire_durat_slope = -11.06 ; + + fates_fire_fdi_a = 17.62 ; + + fates_fire_fdi_alpha = 0.00037 ; + + fates_fire_fdi_b = 243.12 ; + + fates_fire_fuel_energy = 18000 ; + + fates_fire_max_durat = 240 ; + + fates_fire_miner_damp = 0.41739 ; + + fates_fire_miner_total = 0.055 ; + + fates_fire_nignitions = 15 ; + + fates_fire_part_dens = 513 ; + + fates_fire_threshold = 50 ; + + fates_frag_cwd_fcel = 0.76 ; + + fates_frag_cwd_flig = 0.24 ; + + fates_hydro_kmax_rsurf1 = 20 ; + + fates_hydro_kmax_rsurf2 = 0.0001 ; + + fates_hydro_psi0 = 0 ; + + fates_hydro_psicap = -0.6 ; + + fates_hydro_solver = 1 ; + + fates_landuse_logging_coll_under_frac = 0.55983 ; + + fates_landuse_logging_collateral_frac = 0.05 ; + + fates_landuse_logging_dbhmax = _ ; + + fates_landuse_logging_dbhmax_infra = 35 ; + + fates_landuse_logging_dbhmin = 50 ; + + fates_landuse_logging_direct_frac = 0.15 ; + + fates_landuse_logging_event_code = -30 ; + + fates_landuse_logging_export_frac = 0.8 ; + + fates_landuse_logging_mechanical_frac = 0.05 ; + + fates_landuse_pprodharv10_forest_mean = 0.8125 ; + + fates_leaf_photo_temp_acclim_timescale = 30 ; + + fates_leaf_photo_tempsens_model = 1 ; + + fates_leaf_stomatal_assim_model = 1 ; + + fates_leaf_stomatal_model = 1 ; + + fates_leaf_theta_cj_c3 = 0.999 ; + + fates_leaf_theta_cj_c4 = 0.999 ; + + fates_maintresp_model = 1 ; + + fates_maxcohort = 100 ; + + fates_maxpatch_primary = 10 ; + + fates_maxpatch_secondary = 4 ; + + fates_mort_disturb_frac = 1 ; + + fates_mort_understorey_death = 0.55983 ; + + fates_patch_fusion_tol = 0.05 ; + + fates_phen_chilltemp = 5 ; + + fates_phen_coldtemp = 7.5 ; + + fates_phen_drought_model = 0 ; + + fates_phen_drought_threshold = 0.15 ; + + fates_phen_gddthresh_a = -68 ; + + fates_phen_gddthresh_b = 638 ; + + fates_phen_gddthresh_c = -0.01 ; + + fates_phen_mindaysoff = 100 ; + + fates_phen_mindayson = 90 ; + + fates_phen_moist_threshold = 0.18 ; + + fates_phen_ncolddayslim = 5 ; + + fates_q10_froz = 1.5 ; + + fates_q10_mr = 1.5 ; + + fates_soil_salinity = 0.4 ; + + fates_vai_top_bin_width = 1 ; + + fates_vai_width_increase_factor = 1 ; +} From c4ac1801e1c0bc08a76d970eccf502f2dce7db9d Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 28 Oct 2022 17:01:41 -0700 Subject: [PATCH 404/852] add new seed dispersal param file --- ... => fates_params_seed-dispersal_api23.cdl} | 1284 ++++++++--------- 1 file changed, 617 insertions(+), 667 deletions(-) rename parameter_files/{fates_params_seed-dispersal.cdl => fates_params_seed-dispersal_api23.cdl} (53%) diff --git a/parameter_files/fates_params_seed-dispersal.cdl b/parameter_files/fates_params_seed-dispersal_api23.cdl similarity index 53% rename from parameter_files/fates_params_seed-dispersal.cdl rename to parameter_files/fates_params_seed-dispersal_api23.cdl index 6335326e89..5bc0892433 100644 --- a/parameter_files/fates_params_seed-dispersal.cdl +++ b/parameter_files/fates_params_seed-dispersal_api23.cdl @@ -2,17 +2,16 @@ netcdf tmp { dimensions: fates_NCWD = 4 ; fates_history_age_bins = 7 ; - fates_history_coage_bins = 2 ; - fates_history_damage_bins = 2 ; fates_history_height_bins = 6 ; fates_history_size_bins = 13 ; - fates_hlm_pftno = 14 ; + fates_history_coage_bins = 2 ; fates_hydr_organs = 4 ; fates_leafage_class = 1 ; fates_litterclass = 6 ; fates_pft = 12 ; - fates_plant_organs = 4 ; + fates_prt_organs = 4 ; fates_string_length = 60 ; + fates_hlm_pftno = 14 ; variables: double fates_history_ageclass_bin_edges(fates_history_age_bins) ; fates_history_ageclass_bin_edges:units = "yr" ; @@ -23,39 +22,31 @@ variables: double fates_history_height_bin_edges(fates_history_height_bins) ; fates_history_height_bin_edges:units = "m" ; fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; - double fates_history_damage_bin_edges(fates_history_damage_bins) ; - fates_history_damage_bin_edges:units = "% crown loss" ; - fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; fates_history_sizeclass_bin_edges:units = "cm" ; fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; - double fates_alloc_organ_id(fates_plant_organs) ; - fates_alloc_organ_id:units = "unitless" ; - fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; - double fates_hydro_htftype_node(fates_hydr_organs) ; - fates_hydro_htftype_node:units = "unitless" ; - fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; + double fates_hydr_htftype_node(fates_hydr_organs) ; + fates_hydr_htftype_node:units = "unitless" ; + fates_hydr_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; + fates_hydr_htftype_node:possible_values = "1: Christofferson et al. 2016 (TFS); 2: Van Genuchten 1980" ; + double fates_prt_organ_id(fates_prt_organs) ; + fates_prt_organ_id:units = "index, unitless" ; + fates_prt_organ_id:long_name = "This is the global index the organ in this file is associated with in PRTGenericMod.F90" ; char fates_pftname(fates_pft, fates_string_length) ; fates_pftname:units = "unitless - string" ; fates_pftname:long_name = "Description of plant type" ; - char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; - fates_hydro_organ_name:units = "unitless - string" ; - fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; - char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; - fates_alloc_organ_name:units = "unitless - string" ; - fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; + char fates_hydr_organname_node(fates_hydr_organs, fates_string_length) ; + fates_hydr_organname_node:units = "unitless - string" ; + fates_hydr_organname_node:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; 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" ; - 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" ; + char fates_prt_organ_name(fates_prt_organs, fates_string_length) ; + fates_prt_organ_name:units = "unitless - string" ; + fates_prt_organ_name:long_name = "Name of plant organs (order must match PRTGenericMod.F90)" ; double fates_alloc_storage_cushion(fates_pft) ; fates_alloc_storage_cushion:units = "fraction" ; fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; - double fates_alloc_store_priority_frac(fates_pft) ; - fates_alloc_store_priority_frac:units = "unitless" ; - fates_alloc_store_priority_frac:long_name = "for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage" ; double fates_allom_agb1(fates_pft) ; fates_allom_agb1:units = "variable" ; fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; @@ -74,15 +65,14 @@ variables: double fates_allom_amode(fates_pft) ; fates_allom_amode:units = "index" ; fates_allom_amode:long_name = "AGB allometry function index." ; + fates_allom_amode:possible_values = "1: Saldarriaga 1998; 2: 2 parameter power law; 3: Chave 2014" ; double fates_allom_blca_expnt_diff(fates_pft) ; fates_allom_blca_expnt_diff:units = "unitless" ; fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; double fates_allom_cmode(fates_pft) ; fates_allom_cmode:units = "index" ; fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; - double fates_allom_crown_depth_frac(fates_pft) ; - fates_allom_crown_depth_frac:units = "fraction" ; - fates_allom_crown_depth_frac:long_name = "the depth of a cohort crown as a fraction of its height" ; + fates_allom_cmode:possible_values = "1: Constant fraction on AGB" ; double fates_allom_d2bl1(fates_pft) ; fates_allom_d2bl1:units = "variable" ; fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; @@ -113,21 +103,14 @@ variables: double fates_allom_fmode(fates_pft) ; fates_allom_fmode:units = "index" ; fates_allom_fmode:long_name = "fine root biomass allometry function index." ; - double fates_allom_fnrt_prof_a(fates_pft) ; - fates_allom_fnrt_prof_a:units = "unitless" ; - fates_allom_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; - double fates_allom_fnrt_prof_b(fates_pft) ; - fates_allom_fnrt_prof_b:units = "unitless" ; - fates_allom_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; - double fates_allom_fnrt_prof_mode(fates_pft) ; - fates_allom_fnrt_prof_mode:units = "index" ; - fates_allom_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; + fates_allom_fmode:possible_values = "1: constant fraction of trimmed bleaf; 2: constant fraction of untrimmed bleaf." ; double fates_allom_frbstor_repro(fates_pft) ; fates_allom_frbstor_repro:units = "fraction" ; fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; double fates_allom_hmode(fates_pft) ; fates_allom_hmode:units = "index" ; fates_allom_hmode:long_name = "height allometry function index." ; + fates_allom_hmode:possible_values = "1: OBrien 1995; 2: Poorter 2006; 3: 2 parameter power law; 4: Chave 2014; 5: Martinez-Cano 2019." ; double fates_allom_l2fr(fates_pft) ; fates_allom_l2fr:units = "gC/gC" ; fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; @@ -140,15 +123,18 @@ variables: double fates_allom_lmode(fates_pft) ; fates_allom_lmode:units = "index" ; fates_allom_lmode:long_name = "leaf biomass allometry function index." ; + fates_allom_lmode:possible_values = "1: Saldarriaga 1998 (capped-dbh power law); 2: generic power law; 3: generic capped-dbh power law." ; double fates_allom_sai_scaler(fates_pft) ; fates_allom_sai_scaler:units = "m2/m2" ; fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; double fates_allom_smode(fates_pft) ; fates_allom_smode:units = "index" ; fates_allom_smode:long_name = "sapwood allometry function index." ; + fates_allom_smode:possible_values = "1: sapwood area proportional to leaf area based on target leaf biomass" ; double fates_allom_stmode(fates_pft) ; fates_allom_stmode:units = "index" ; fates_allom_stmode:long_name = "storage allometry function index." ; + fates_allom_stmode:possible_values = "1: target storage proportional to trimmed maximum leaf biomass." ; double fates_allom_zroot_k(fates_pft) ; fates_allom_zroot_k:units = "unitless" ; fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; @@ -164,181 +150,151 @@ variables: double fates_allom_zroot_min_z(fates_pft) ; fates_allom_zroot_min_z:units = "m" ; fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_branch_turnover(fates_pft) ; + fates_branch_turnover:units = "yr" ; + fates_branch_turnover:long_name = "turnover time of branches" ; double fates_c2b(fates_pft) ; fates_c2b:units = "ratio" ; fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; - double fates_cnp_eca_alpha_ptase(fates_pft) ; - fates_cnp_eca_alpha_ptase:units = "g/m3" ; - fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; - double fates_cnp_eca_decompmicc(fates_pft) ; - fates_cnp_eca_decompmicc:units = "gC/m3" ; - fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; - double fates_cnp_eca_km_nh4(fates_pft) ; - fates_cnp_eca_km_nh4:units = "gN/m3" ; - fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; - double fates_cnp_eca_km_no3(fates_pft) ; - fates_cnp_eca_km_no3:units = "gN/m3" ; - fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; - double fates_cnp_eca_km_p(fates_pft) ; - fates_cnp_eca_km_p:units = "gP/m3" ; - fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; - double fates_cnp_eca_km_ptase(fates_pft) ; - fates_cnp_eca_km_ptase:units = "gP/m3" ; - fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; - double fates_cnp_eca_lambda_ptase(fates_pft) ; - fates_cnp_eca_lambda_ptase:units = "g/m3" ; - fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; - double fates_cnp_eca_vmax_nh4(fates_pft) ; - fates_cnp_eca_vmax_nh4:units = "gN/gC/s" ; - fates_cnp_eca_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA)" ; - double fates_cnp_eca_vmax_no3(fates_pft) ; - fates_cnp_eca_vmax_no3:units = "gN/gC/s" ; - fates_cnp_eca_vmax_no3:long_name = "maximum production rate for plant no3 uptake (ECA)" ; - double fates_cnp_eca_vmax_ptase(fates_pft) ; - fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; - fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; - double fates_cnp_fnrt_adapt_tscale(fates_pft) ; - fates_cnp_fnrt_adapt_tscale:units = "days" ; - fates_cnp_fnrt_adapt_tscale:long_name = "Number of days that is shortest possible doubling period for fine-root adaptation to C/N/P balance" ; - double fates_cnp_nfix1(fates_pft) ; - fates_cnp_nfix1:units = "NA" ; - fates_cnp_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; - double fates_cnp_nitr_store_ratio(fates_pft) ; - fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; - fates_cnp_nitr_store_ratio:long_name = "storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code)" ; - double fates_cnp_phos_store_ratio(fates_pft) ; - fates_cnp_phos_store_ratio:units = "(gP/gP)" ; - fates_cnp_phos_store_ratio:long_name = "storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code)" ; - double fates_cnp_prescribed_nuptake(fates_pft) ; - fates_cnp_prescribed_nuptake:units = "fraction" ; - fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; - double fates_cnp_prescribed_puptake(fates_pft) ; - fates_cnp_prescribed_puptake:units = "fraction" ; - fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; - double fates_cnp_rd_vmax_n(fates_pft) ; - fates_cnp_rd_vmax_n:units = "gN/gC/s" ; - fates_cnp_rd_vmax_n:long_name = "maximum production rate for compbined (NH4+NO3) uptake (RD)" ; - double fates_cnp_store_ovrflw_frac(fates_pft) ; - fates_cnp_store_ovrflw_frac:units = "fraction" ; - fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; - fates_cnp_store_ovrflw_frac:use_case = "None" ; - double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; - fates_cnp_turnover_nitr_retrans:units = "fraction" ; - fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; - double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; - fates_cnp_turnover_phos_retrans:units = "fraction" ; - fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; - double fates_cnp_vmax_p(fates_pft) ; - fates_cnp_vmax_p:units = "gP/gC/s" ; - fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; - double fates_damage_frac(fates_pft) ; - fates_damage_frac:units = "fraction" ; - fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; - double fates_damage_mort_p1(fates_pft) ; - fates_damage_mort_p1:units = "fraction" ; - fates_damage_mort_p1:long_name = "inflection point of damage mortality function, a value of 0.8 means 50% mortality with 80% loss of crown, turn off with a large number" ; - double fates_damage_mort_p2(fates_pft) ; - fates_damage_mort_p2:units = "unitless" ; - fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; - 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_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" ; + double fates_displar(fates_pft) ; + fates_displar:units = "unitless" ; + fates_displar:long_name = "Ratio of displacement height to canopy top height" ; + double fates_eca_alpha_ptase(fates_pft) ; + fates_eca_alpha_ptase:units = "g/m3" ; + fates_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; + double fates_eca_decompmicc(fates_pft) ; + fates_eca_decompmicc:units = "gC/m3" ; + fates_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; + double fates_eca_km_nh4(fates_pft) ; + fates_eca_km_nh4:units = "gN/m3" ; + fates_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; + double fates_eca_km_no3(fates_pft) ; + fates_eca_km_no3:units = "gN/m3" ; + fates_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; + double fates_eca_km_p(fates_pft) ; + fates_eca_km_p:units = "gP/m3" ; + fates_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; + double fates_eca_km_ptase(fates_pft) ; + fates_eca_km_ptase:units = "gP/m3" ; + fates_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; + double fates_eca_lambda_ptase(fates_pft) ; + fates_eca_lambda_ptase:units = "g/m3" ; + fates_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; + double fates_eca_vmax_nh4(fates_pft) ; + fates_eca_vmax_nh4:units = "gN/gC/s" ; + fates_eca_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA)" ; + double fates_eca_vmax_no3(fates_pft) ; + fates_eca_vmax_no3:units = "gN/gC/s" ; + fates_eca_vmax_no3:long_name = "maximum production rate for plant no3 uptake (ECA)" ; + double fates_eca_vmax_p(fates_pft) ; + fates_eca_vmax_p:units = "gP/gC/s" ; + fates_eca_vmax_p:long_name = "maximum production rate for plant p uptake (ECA)" ; + double fates_eca_vmax_ptase(fates_pft) ; + fates_eca_vmax_ptase:units = "gP/m2/s" ; + fates_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; double fates_fire_alpha_SH(fates_pft) ; fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; double fates_fire_bark_scaler(fates_pft) ; fates_fire_bark_scaler:units = "fraction" ; fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; + double fates_fire_crown_depth_frac(fates_pft) ; + fates_fire_crown_depth_frac:units = "fraction" ; + fates_fire_crown_depth_frac:long_name = "the depth of a cohorts crown as a fraction of its height" ; double fates_fire_crown_kill(fates_pft) ; fates_fire_crown_kill:units = "NA" ; fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; - double fates_frag_fnrt_fcel(fates_pft) ; - fates_frag_fnrt_fcel:units = "fraction" ; - fates_frag_fnrt_fcel:long_name = "Fine root litter cellulose fraction" ; - double fates_frag_fnrt_flab(fates_pft) ; - fates_frag_fnrt_flab:units = "fraction" ; - fates_frag_fnrt_flab:long_name = "Fine root litter labile fraction" ; - double fates_frag_fnrt_flig(fates_pft) ; - fates_frag_fnrt_flig:units = "fraction" ; - fates_frag_fnrt_flig:long_name = "Fine root litter lignin fraction" ; - double fates_frag_leaf_fcel(fates_pft) ; - fates_frag_leaf_fcel:units = "fraction" ; - fates_frag_leaf_fcel:long_name = "Leaf litter cellulose fraction" ; - double fates_frag_leaf_flab(fates_pft) ; - fates_frag_leaf_flab:units = "fraction" ; - fates_frag_leaf_flab:long_name = "Leaf litter labile fraction" ; - double fates_frag_leaf_flig(fates_pft) ; - fates_frag_leaf_flig:units = "fraction" ; - fates_frag_leaf_flig:long_name = "Leaf litter lignin fraction" ; - double fates_frag_seed_decay_rate(fates_pft) ; - fates_frag_seed_decay_rate:units = "yr-1" ; - fates_frag_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; + double fates_fnrt_prof_a(fates_pft) ; + fates_fnrt_prof_a:units = "unitless" ; + fates_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; + double fates_fnrt_prof_b(fates_pft) ; + fates_fnrt_prof_b:units = "unitless" ; + fates_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; + double fates_fnrt_prof_mode(fates_pft) ; + fates_fnrt_prof_mode:units = "index" ; + fates_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; + double fates_fr_fcel(fates_pft) ; + fates_fr_fcel:units = "fraction" ; + fates_fr_fcel:long_name = "Fine root litter cellulose fraction" ; + double fates_fr_flab(fates_pft) ; + fates_fr_flab:units = "fraction" ; + fates_fr_flab:long_name = "Fine root litter labile fraction" ; + double fates_fr_flig(fates_pft) ; + fates_fr_flig:units = "fraction" ; + fates_fr_flig:long_name = "Fine root litter lignin fraction" ; double fates_grperc(fates_pft) ; fates_grperc:units = "unitless" ; fates_grperc:long_name = "Growth respiration factor" ; - double fates_hydro_avuln_gs(fates_pft) ; - fates_hydro_avuln_gs:units = "unitless" ; - fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; - double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; - fates_hydro_avuln_node:units = "unitless" ; - fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; - double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; - fates_hydro_epsil_node:units = "MPa" ; - fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; - double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; - fates_hydro_fcap_node:units = "unitless" ; - fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; - double fates_hydro_k_lwp(fates_pft) ; - fates_hydro_k_lwp:units = "unitless" ; - fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; - double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; - fates_hydro_kmax_node:units = "kg/MPa/m/s" ; - fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; - double fates_hydro_p50_gs(fates_pft) ; - fates_hydro_p50_gs:units = "MPa" ; - fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; - double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; - fates_hydro_p50_node:units = "MPa" ; - fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; - double fates_hydro_p_taper(fates_pft) ; - fates_hydro_p_taper:units = "unitless" ; - fates_hydro_p_taper:long_name = "xylem taper exponent" ; - double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; - fates_hydro_pinot_node:units = "MPa" ; - fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; - double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; - fates_hydro_pitlp_node:units = "MPa" ; - fates_hydro_pitlp_node:long_name = "turgor loss point" ; - double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; - fates_hydro_resid_node:units = "cm3/cm3" ; - fates_hydro_resid_node:long_name = "residual water conent" ; - double fates_hydro_rfrac_stem(fates_pft) ; - fates_hydro_rfrac_stem:units = "fraction" ; - fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; - double fates_hydro_rs2(fates_pft) ; - fates_hydro_rs2:units = "m" ; - fates_hydro_rs2:long_name = "absorbing root radius" ; - double fates_hydro_srl(fates_pft) ; - fates_hydro_srl:units = "m g-1" ; - fates_hydro_srl:long_name = "specific root length" ; - double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; - fates_hydro_thetas_node:units = "cm3/cm3" ; - fates_hydro_thetas_node:long_name = "saturated water content" ; - double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; - fates_hydro_vg_alpha_node:units = "MPa-1" ; - fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; - double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; - fates_hydro_vg_m_node:units = "unitless" ; - fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; - 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_hydr_avuln_gs(fates_pft) ; + fates_hydr_avuln_gs:units = "unitless" ; + fates_hydr_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; + double fates_hydr_avuln_node(fates_hydr_organs, fates_pft) ; + fates_hydr_avuln_node:units = "unitless" ; + fates_hydr_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; + double fates_hydr_epsil_node(fates_hydr_organs, fates_pft) ; + fates_hydr_epsil_node:units = "MPa" ; + fates_hydr_epsil_node:long_name = "bulk elastic modulus" ; + double fates_hydr_fcap_node(fates_hydr_organs, fates_pft) ; + fates_hydr_fcap_node:units = "unitless" ; + fates_hydr_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; + double fates_hydr_k_lwp(fates_pft) ; + fates_hydr_k_lwp:units = "unitless" ; + fates_hydr_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; + fates_hydr_k_lwp:possible_values = "0: turns off leaf humidity effects on conductance. 1-10 activates humidity effects" ; + double fates_hydr_kmax_node(fates_hydr_organs, fates_pft) ; + fates_hydr_kmax_node:units = "kg/MPa/m/s" ; + fates_hydr_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; + double fates_hydr_p50_gs(fates_pft) ; + fates_hydr_p50_gs:units = "MPa" ; + fates_hydr_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; + double fates_hydr_p50_node(fates_hydr_organs, fates_pft) ; + fates_hydr_p50_node:units = "MPa" ; + fates_hydr_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; + double fates_hydr_p_taper(fates_pft) ; + fates_hydr_p_taper:units = "unitless" ; + fates_hydr_p_taper:long_name = "xylem taper exponent" ; + double fates_hydr_pinot_node(fates_hydr_organs, fates_pft) ; + fates_hydr_pinot_node:units = "MPa" ; + fates_hydr_pinot_node:long_name = "osmotic potential at full turgor" ; + double fates_hydr_pitlp_node(fates_hydr_organs, fates_pft) ; + fates_hydr_pitlp_node:units = "MPa" ; + fates_hydr_pitlp_node:long_name = "turgor loss point" ; + double fates_hydr_resid_node(fates_hydr_organs, fates_pft) ; + fates_hydr_resid_node:units = "cm3/cm3" ; + fates_hydr_resid_node:long_name = "residual water conent" ; + double fates_hydr_rfrac_stem(fates_pft) ; + fates_hydr_rfrac_stem:units = "fraction" ; + fates_hydr_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; + double fates_hydr_rs2(fates_pft) ; + fates_hydr_rs2:units = "m" ; + fates_hydr_rs2:long_name = "absorbing root radius" ; + double fates_hydr_srl(fates_pft) ; + fates_hydr_srl:units = "m g-1" ; + fates_hydr_srl:long_name = "specific root length" ; + double fates_hydr_thetas_node(fates_hydr_organs, fates_pft) ; + fates_hydr_thetas_node:units = "cm3/cm3" ; + fates_hydr_thetas_node:long_name = "saturated water content" ; + double fates_hydr_vg_alpha_node(fates_hydr_organs, fates_pft) ; + fates_hydr_vg_alpha_node:units = "MPa-1" ; + fates_hydr_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; + double fates_hydr_vg_m_node(fates_hydr_organs, fates_pft) ; + fates_hydr_vg_m_node:units = "unitless" ; + fates_hydr_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; + double fates_hydr_vg_n_node(fates_hydr_organs, fates_pft) ; + fates_hydr_vg_n_node:units = "unitless" ; + fates_hydr_vg_n_node:long_name = "(used if hydr_htftype_node = 2),n in van Genuchten 1980 model, pore size distribution parameter" ; double fates_leaf_c3psn(fates_pft) ; fates_leaf_c3psn:units = "flag" ; fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; + double fates_leaf_clumping_index(fates_pft) ; + fates_leaf_clumping_index:units = "fraction (0-1)" ; + fates_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; + double fates_leaf_diameter(fates_pft) ; + fates_leaf_diameter:units = "m" ; + fates_leaf_diameter:long_name = "Characteristic leaf dimension" ; double fates_leaf_jmaxha(fates_pft) ; fates_leaf_jmaxha:units = "J/mol" ; fates_leaf_jmaxha:long_name = "activation energy for jmax" ; @@ -348,6 +304,9 @@ variables: double fates_leaf_jmaxse(fates_pft) ; fates_leaf_jmaxse:units = "J/mol/K" ; fates_leaf_jmaxse:long_name = "entropy term for jmax" ; + double fates_leaf_long(fates_leafage_class, fates_pft) ; + fates_leaf_long:units = "yr" ; + fates_leaf_long:long_name = "Leaf longevity (ie turnover timescale)" ; double fates_leaf_slamax(fates_pft) ; fates_leaf_slamax:units = "m^2/gC" ; fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; @@ -363,6 +322,9 @@ variables: double fates_leaf_stomatal_slope_medlyn(fates_pft) ; fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; + double fates_leaf_stor_priority(fates_pft) ; + fates_leaf_stor_priority:units = "unitless" ; + fates_leaf_stor_priority:long_name = "factor governing priority of replacing storage with NPP" ; double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; @@ -375,6 +337,18 @@ variables: double fates_leaf_vcmaxse(fates_pft) ; fates_leaf_vcmaxse:units = "J/mol/K" ; fates_leaf_vcmaxse:long_name = "entropy term for vcmax" ; + double fates_leaf_xl(fates_pft) ; + fates_leaf_xl:units = "unitless" ; + fates_leaf_xl:long_name = "Leaf/stem orientation index" ; + double fates_lf_fcel(fates_pft) ; + fates_lf_fcel:units = "fraction" ; + fates_lf_fcel:long_name = "Leaf litter cellulose fraction" ; + double fates_lf_flab(fates_pft) ; + fates_lf_flab:units = "fraction" ; + fates_lf_flab:long_name = "Leaf litter labile fraction" ; + double fates_lf_flig(fates_pft) ; + fates_lf_flig:units = "fraction" ; + fates_lf_flig:long_name = "Leaf litter lignin fraction" ; double fates_maintresp_reduction_curvature(fates_pft) ; fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; @@ -399,12 +373,6 @@ variables: double fates_mort_ip_size_senescence(fates_pft) ; fates_mort_ip_size_senescence:units = "dbh cm" ; fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; - double fates_mort_prescribed_canopy(fates_pft) ; - fates_mort_prescribed_canopy:units = "1/yr" ; - fates_mort_prescribed_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; - double fates_mort_prescribed_understory(fates_pft) ; - fates_mort_prescribed_understory:units = "1/yr" ; - fates_mort_prescribed_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; double fates_mort_r_age_senescence(fates_pft) ; fates_mort_r_age_senescence:units = "mortality rate year^-1" ; fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; @@ -420,24 +388,21 @@ variables: double fates_mort_scalar_hydrfailure(fates_pft) ; fates_mort_scalar_hydrfailure:units = "1/yr" ; fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; - double fates_nonhydro_smpsc(fates_pft) ; - fates_nonhydro_smpsc:units = "mm" ; - fates_nonhydro_smpsc:long_name = "Soil water potential at full stomatal closure" ; - double fates_nonhydro_smpso(fates_pft) ; - fates_nonhydro_smpso:units = "mm" ; - fates_nonhydro_smpso:long_name = "Soil water potential at full stomatal opening" ; + double fates_nfix1(fates_pft) ; + fates_nfix1:units = "NA" ; + fates_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; + double fates_nfix2(fates_pft) ; + fates_nfix2:units = "NA" ; + fates_nfix2:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; + double fates_nitr_store_ratio(fates_pft) ; + fates_nitr_store_ratio:units = "(gN/gN)" ; + fates_nitr_store_ratio:long_name = "ratio of storeable N, to functional N bound in cell structures of leaf,root,sap" ; double fates_phen_cold_size_threshold(fates_pft) ; fates_phen_cold_size_threshold:units = "cm" ; fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; double fates_phen_evergreen(fates_pft) ; fates_phen_evergreen:units = "logical flag" ; fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; - double fates_phen_flush_fraction(fates_pft) ; - fates_phen_flush_fraction:units = "fraction" ; - fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; - double fates_phen_fnrt_drop_frac(fates_pft) ; - fates_phen_fnrt_drop_frac:units = "fraction" ; - fates_phen_fnrt_drop_frac:long_name = "fraction of fine roots to drop during drought or cold" ; double fates_phen_season_decid(fates_pft) ; fates_phen_season_decid:units = "logical flag" ; fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; @@ -447,113 +412,142 @@ variables: double fates_phen_stress_decid(fates_pft) ; fates_phen_stress_decid:units = "logical flag" ; fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; + double fates_phenflush_fraction(fates_pft) ; + fates_phenflush_fraction:units = "fraction" ; + fates_phenflush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; + double fates_phos_store_ratio(fates_pft) ; + fates_phos_store_ratio:units = "(gP/gP)" ; + fates_phos_store_ratio:long_name = "ratio of storeable P, to functional P bound in cell structures of leaf,root,sap" ; + double fates_prescribed_mortality_canopy(fates_pft) ; + fates_prescribed_mortality_canopy:units = "1/yr" ; + fates_prescribed_mortality_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; + double fates_prescribed_mortality_understory(fates_pft) ; + fates_prescribed_mortality_understory:units = "1/yr" ; + fates_prescribed_mortality_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; double fates_prescribed_npp_canopy(fates_pft) ; fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; double fates_prescribed_npp_understory(fates_pft) ; fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; - double fates_rad_leaf_clumping_index(fates_pft) ; - fates_rad_leaf_clumping_index:units = "fraction (0-1)" ; - fates_rad_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; - double fates_rad_leaf_rhonir(fates_pft) ; - fates_rad_leaf_rhonir:units = "fraction" ; - fates_rad_leaf_rhonir:long_name = "Leaf reflectance: near-IR" ; - double fates_rad_leaf_rhovis(fates_pft) ; - fates_rad_leaf_rhovis:units = "fraction" ; - fates_rad_leaf_rhovis:long_name = "Leaf reflectance: visible" ; - double fates_rad_leaf_taunir(fates_pft) ; - fates_rad_leaf_taunir:units = "fraction" ; - fates_rad_leaf_taunir:long_name = "Leaf transmittance: near-IR" ; - double fates_rad_leaf_tauvis(fates_pft) ; - fates_rad_leaf_tauvis:units = "fraction" ; - fates_rad_leaf_tauvis:long_name = "Leaf transmittance: visible" ; - double fates_rad_leaf_xl(fates_pft) ; - fates_rad_leaf_xl:units = "unitless" ; - fates_rad_leaf_xl:long_name = "Leaf/stem orientation index" ; - double fates_rad_stem_rhonir(fates_pft) ; - fates_rad_stem_rhonir:units = "fraction" ; - fates_rad_stem_rhonir:long_name = "Stem reflectance: near-IR" ; - double fates_rad_stem_rhovis(fates_pft) ; - fates_rad_stem_rhovis:units = "fraction" ; - fates_rad_stem_rhovis:long_name = "Stem reflectance: visible" ; - double fates_rad_stem_taunir(fates_pft) ; - fates_rad_stem_taunir:units = "fraction" ; - fates_rad_stem_taunir:long_name = "Stem transmittance: near-IR" ; - double fates_rad_stem_tauvis(fates_pft) ; - fates_rad_stem_tauvis:units = "fraction" ; - fates_rad_stem_tauvis:long_name = "Stem transmittance: visible" ; - double fates_recruit_height_min(fates_pft) ; - fates_recruit_height_min:units = "m" ; - fates_recruit_height_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; - double fates_recruit_init_density(fates_pft) ; - fates_recruit_init_density:units = "stems/m2" ; - fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation" ; - double fates_recruit_prescribed_rate(fates_pft) ; - fates_recruit_prescribed_rate:units = "n/yr" ; - fates_recruit_prescribed_rate:long_name = "recruitment rate for prescribed physiology mode" ; - double fates_recruit_seed_alloc(fates_pft) ; - fates_recruit_seed_alloc:units = "fraction" ; - fates_recruit_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; - double fates_recruit_seed_alloc_mature(fates_pft) ; - fates_recruit_seed_alloc_mature:units = "fraction" ; - fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; - double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; - fates_recruit_seed_dbh_repro_threshold:units = "cm" ; - fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter (if any) where the plant will start extra clonal allocation to the seed pool" ; - double fates_recruit_seed_germination_rate(fates_pft) ; - fates_recruit_seed_germination_rate:units = "yr-1" ; - fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; - double fates_recruit_seed_supplement(fates_pft) ; - fates_recruit_seed_supplement:units = "KgC/m2/yr" ; - fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; + double fates_prescribed_nuptake(fates_pft) ; + fates_prescribed_nuptake:units = "fraction" ; + fates_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; + double fates_prescribed_puptake(fates_pft) ; + fates_prescribed_puptake:units = "fraction" ; + fates_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; + double fates_prescribed_recruitment(fates_pft) ; + fates_prescribed_recruitment:units = "n/yr" ; + fates_prescribed_recruitment:long_name = "recruitment rate for prescribed physiology mode" ; + double fates_prt_alloc_priority(fates_prt_organs, fates_pft) ; + fates_prt_alloc_priority:units = "index (0-fates_prt_organs)" ; + fates_prt_alloc_priority:long_name = "Priority order for allocation (C storage=2)" ; + double fates_prt_nitr_stoich_p1(fates_prt_organs, fates_pft) ; + fates_prt_nitr_stoich_p1:units = "(gN/gC)" ; + fates_prt_nitr_stoich_p1:long_name = "nitrogen stoichiometry, parameter 1" ; + double fates_prt_nitr_stoich_p2(fates_prt_organs, fates_pft) ; + fates_prt_nitr_stoich_p2:units = "(gN/gC)" ; + fates_prt_nitr_stoich_p2:long_name = "nitrogen stoichiometry, parameter 2" ; + double fates_prt_phos_stoich_p1(fates_prt_organs, fates_pft) ; + fates_prt_phos_stoich_p1:units = "(gP/gC)" ; + fates_prt_phos_stoich_p1:long_name = "phosphorous stoichiometry, parameter 1" ; + double fates_prt_phos_stoich_p2(fates_prt_organs, fates_pft) ; + fates_prt_phos_stoich_p2:units = "(gP/gC)" ; + fates_prt_phos_stoich_p2:long_name = "phosphorous stoichiometry, parameter 2" ; + double fates_recruit_hgt_min(fates_pft) ; + fates_recruit_hgt_min:units = "m" ; + fates_recruit_hgt_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; + double fates_recruit_initd(fates_pft) ; + fates_recruit_initd:units = "stems/m2" ; + fates_recruit_initd:long_name = "initial seedling density for a cold-start near-bare-ground simulation" ; + double fates_rholnir(fates_pft) ; + fates_rholnir:units = "fraction" ; + fates_rholnir:long_name = "Leaf reflectance: near-IR" ; + double fates_rholvis(fates_pft) ; + fates_rholvis:units = "fraction" ; + fates_rholvis:long_name = "Leaf reflectance: visible" ; + double fates_rhosnir(fates_pft) ; + fates_rhosnir:units = "fraction" ; + fates_rhosnir:long_name = "Stem reflectance: near-IR" ; + double fates_rhosvis(fates_pft) ; + fates_rhosvis:units = "fraction" ; + fates_rhosvis:long_name = "Stem reflectance: visible" ; + double fates_root_long(fates_pft) ; + fates_root_long:units = "yr" ; + fates_root_long:long_name = "root longevity (alternatively, turnover time)" ; + double fates_seed_alloc(fates_pft) ; + fates_seed_alloc:units = "fraction" ; + fates_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; + double fates_seed_alloc_mature(fates_pft) ; + fates_seed_alloc_mature:units = "fraction" ; + fates_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; + double fates_seed_dbh_repro_threshold(fates_pft) ; + fates_seed_dbh_repro_threshold:units = "cm" ; + fates_seed_dbh_repro_threshold:long_name = "the diameter (if any) where the plant will start extra clonal allocation to the seed pool" ; + double fates_seed_decay_rate(fates_pft) ; + fates_seed_decay_rate:units = "yr-1" ; + fates_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; double fates_seed_dispersal_param_A(fates_pft) ; fates_seed_dispersal_param_A:units = "unitless" ; fates_seed_dispersal_param_A:long_name = "seed dispersal scale parameter" ; - fates_seed_dispersal_param_A:use_case = "None" ; double fates_seed_dispersal_param_B(fates_pft) ; fates_seed_dispersal_param_B:units = "unitless" ; - fates_seed_dispersal_param_B:long_name = "seed dispersal shape parameter" ; - fates_seed_dispersal_param_B:use_case = "None" ; - double fates_stoich_nitr(fates_plant_organs, fates_pft) ; - fates_stoich_nitr:units = "gN/gC" ; - fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; - double fates_stoich_phos(fates_plant_organs, fates_pft) ; - fates_stoich_phos:units = "gP/gC" ; - fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; + fates_seed_dispersal_param_B:long_name = "seed dispersal scale parameter" ; + double fates_seed_germination_rate(fates_pft) ; + fates_seed_germination_rate:units = "yr-1" ; + fates_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; + double fates_seed_suppl(fates_pft) ; + fates_seed_suppl:units = "KgC/m2/yr" ; + fates_seed_suppl:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; + double fates_senleaf_long_fdrought(fates_pft) ; + fates_senleaf_long_fdrought:units = "unitless[0-1]" ; + fates_senleaf_long_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; + double fates_smpsc(fates_pft) ; + fates_smpsc:units = "mm" ; + fates_smpsc:long_name = "Soil water potential at full stomatal closure" ; + double fates_smpso(fates_pft) ; + fates_smpso:units = "mm" ; + fates_smpso:long_name = "Soil water potential at full stomatal opening" ; + double fates_taulnir(fates_pft) ; + fates_taulnir:units = "fraction" ; + fates_taulnir:long_name = "Leaf transmittance: near-IR" ; + double fates_taulvis(fates_pft) ; + fates_taulvis:units = "fraction" ; + fates_taulvis:long_name = "Leaf transmittance: visible" ; + double fates_tausnir(fates_pft) ; + fates_tausnir:units = "fraction" ; + fates_tausnir:long_name = "Stem transmittance: near-IR" ; + double fates_tausvis(fates_pft) ; + fates_tausvis:units = "fraction" ; + fates_tausvis:long_name = "Stem transmittance: visible" ; double fates_trim_inc(fates_pft) ; fates_trim_inc:units = "m2/m2" ; fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; double fates_trim_limit(fates_pft) ; fates_trim_limit:units = "m2/m2" ; fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; - double fates_turb_displar(fates_pft) ; - fates_turb_displar:units = "unitless" ; - fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; - double fates_turb_leaf_diameter(fates_pft) ; - fates_turb_leaf_diameter:units = "m" ; - fates_turb_leaf_diameter:long_name = "Characteristic leaf dimension" ; - double fates_turb_z0mr(fates_pft) ; - fates_turb_z0mr:units = "unitless" ; - fates_turb_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; - double fates_turnover_branch(fates_pft) ; - fates_turnover_branch:units = "yr" ; - fates_turnover_branch:long_name = "turnover time of branches" ; - double fates_turnover_fnrt(fates_pft) ; - fates_turnover_fnrt:units = "yr" ; - fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; - double fates_turnover_leaf(fates_leafage_class, fates_pft) ; - fates_turnover_leaf:units = "yr" ; - fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; - double fates_turnover_senleaf_fdrought(fates_pft) ; - fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; - fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; + double fates_turnover_carb_retrans(fates_prt_organs, fates_pft) ; + fates_turnover_carb_retrans:units = "-" ; + fates_turnover_carb_retrans:long_name = "retranslocation fraction of carbon in turnover" ; + double fates_turnover_nitr_retrans(fates_prt_organs, fates_pft) ; + fates_turnover_nitr_retrans:units = "-" ; + fates_turnover_nitr_retrans:long_name = "retranslocation fraction of nitrogen in turnover" ; + double fates_turnover_phos_retrans(fates_prt_organs, fates_pft) ; + fates_turnover_phos_retrans:units = "-" ; + fates_turnover_phos_retrans:long_name = "retranslocation fraction of phosphorous in turnover, parameter 1" ; + double fates_turnover_retrans_mode(fates_pft) ; + fates_turnover_retrans_mode:units = "index" ; + fates_turnover_retrans_mode:long_name = "retranslocation method for leaf/fineroot turnover." ; + fates_turnover_retrans_mode:possible_values = "1: constant fraction." ; double fates_wood_density(fates_pft) ; fates_wood_density:units = "g/cm3" ; fates_wood_density:long_name = "mean density of woody tissue in plant" ; double fates_woody(fates_pft) ; fates_woody:units = "logical flag" ; fates_woody:long_name = "Binary woody lifeform flag" ; + double fates_z0mr(fates_pft) ; + fates_z0mr:units = "unitless" ; + fates_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; fates_hlm_pft_map:units = "area fraction" ; fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; @@ -581,21 +575,18 @@ variables: double fates_fire_SAV(fates_litterclass) ; fates_fire_SAV:units = "cm-1" ; fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; - double fates_frag_maxdecomp(fates_litterclass) ; - fates_frag_maxdecomp:units = "yr-1" ; - fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; - 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_max_decomp(fates_litterclass) ; + fates_max_decomp:units = "yr-1" ; + fates_max_decomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; + double fates_CWD_frac(fates_NCWD) ; + fates_CWD_frac:units = "fraction" ; + fates_CWD_frac:long_name = "fraction of woody (bdead+bsw) biomass destined for CWD pool" ; double fates_base_mr_20 ; fates_base_mr_20:units = "gC/gN/s" ; fates_base_mr_20:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; 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" ; - double fates_cnp_eca_plant_escalar ; - fates_cnp_eca_plant_escalar:units = "" ; - fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; double fates_cohort_age_fusion_tol ; fates_cohort_age_fusion_tol:units = "unitless" ; fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; @@ -605,15 +596,18 @@ variables: double fates_comp_excln ; fates_comp_excln:units = "none" ; fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; - double fates_damage_canopy_layer_code ; - fates_damage_canopy_layer_code:units = "unitless" ; - fates_damage_canopy_layer_code:long_name = "Integer code that decides whether damage affects canopy trees (1), understory trees (2)" ; - double fates_damage_event_code ; - fates_damage_event_code:units = "unitless" ; - fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; + double fates_cwd_fcel ; + fates_cwd_fcel:units = "unitless" ; + fates_cwd_fcel:long_name = "Cellulose fraction for CWD" ; + double fates_cwd_flig ; + fates_cwd_flig:units = "unitless" ; + fates_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; double fates_dev_arbitrary ; fates_dev_arbitrary:units = "unknown" ; fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; + double fates_eca_plant_escalar ; + fates_eca_plant_escalar:units = "" ; + fates_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; double fates_fire_active_crown_fire ; fates_fire_active_crown_fire:units = "0 or 1" ; fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; @@ -656,87 +650,54 @@ variables: double fates_fire_threshold ; fates_fire_threshold:units = "kW/m" ; fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; - double fates_frag_cwd_fcel ; - fates_frag_cwd_fcel:units = "unitless" ; - fates_frag_cwd_fcel:long_name = "Cellulose fraction for CWD" ; - double fates_frag_cwd_flig ; - fates_frag_cwd_flig:units = "unitless" ; - fates_frag_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; - double fates_hydro_kmax_rsurf1 ; - fates_hydro_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; - fates_hydro_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; - double fates_hydro_kmax_rsurf2 ; - fates_hydro_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; - fates_hydro_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; - double fates_hydro_psi0 ; - fates_hydro_psi0:units = "MPa" ; - fates_hydro_psi0:long_name = "sapwood water potential at saturation" ; - double fates_hydro_psicap ; - fates_hydro_psicap:units = "MPa" ; - fates_hydro_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; - 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_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" ; - double fates_landuse_logging_collateral_frac ; - fates_landuse_logging_collateral_frac:units = "fraction" ; - fates_landuse_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; - double fates_landuse_logging_dbhmax ; - fates_landuse_logging_dbhmax:units = "cm" ; - fates_landuse_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; - double fates_landuse_logging_dbhmax_infra ; - fates_landuse_logging_dbhmax_infra:units = "cm" ; - fates_landuse_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; - double fates_landuse_logging_dbhmin ; - fates_landuse_logging_dbhmin:units = "cm" ; - fates_landuse_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; - double fates_landuse_logging_direct_frac ; - fates_landuse_logging_direct_frac:units = "fraction" ; - fates_landuse_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; - double fates_landuse_logging_event_code ; - fates_landuse_logging_event_code:units = "unitless" ; - fates_landuse_logging_event_code:long_name = "Integer code that options how logging events are structured" ; - double fates_landuse_logging_export_frac ; - fates_landuse_logging_export_frac:units = "fraction" ; - fates_landuse_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; - double fates_landuse_logging_mechanical_frac ; - fates_landuse_logging_mechanical_frac:units = "fraction" ; - fates_landuse_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; - double fates_landuse_pprodharv10_forest_mean ; - fates_landuse_pprodharv10_forest_mean:units = "fraction" ; - fates_landuse_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; - double fates_leaf_photo_temp_acclim_timescale ; - fates_leaf_photo_temp_acclim_timescale:units = "days" ; - fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; - double fates_leaf_photo_tempsens_model ; - fates_leaf_photo_tempsens_model:units = "unitless" ; - fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; - double fates_leaf_stomatal_assim_model ; - fates_leaf_stomatal_assim_model:units = "unitless" ; - fates_leaf_stomatal_assim_model:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; + double fates_hydr_kmax_rsurf1 ; + fates_hydr_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; + fates_hydr_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; + double fates_hydr_kmax_rsurf2 ; + fates_hydr_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; + fates_hydr_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; + double fates_hydr_psi0 ; + fates_hydr_psi0:units = "MPa" ; + fates_hydr_psi0:long_name = "sapwood water potential at saturation" ; + double fates_hydr_psicap ; + fates_hydr_psicap:units = "MPa" ; + fates_hydr_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; + double fates_init_litter ; + fates_init_litter:units = "NA" ; + fates_init_litter:long_name = "Initialization value for litter pool in cold-start (NOT USED)" ; double fates_leaf_stomatal_model ; fates_leaf_stomatal_model:units = "unitless" ; fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; - double fates_leaf_theta_cj_c3 ; - fates_leaf_theta_cj_c3:units = "unitless" ; - fates_leaf_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; - double fates_leaf_theta_cj_c4 ; - fates_leaf_theta_cj_c4:units = "unitless" ; - fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; + double fates_logging_coll_under_frac ; + fates_logging_coll_under_frac:units = "fraction" ; + fates_logging_coll_under_frac:long_name = "Fraction of stems killed in the understory when logging generates disturbance" ; + double fates_logging_collateral_frac ; + fates_logging_collateral_frac:units = "fraction" ; + fates_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; + double fates_logging_dbhmax ; + fates_logging_dbhmax:units = "cm" ; + fates_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; + double fates_logging_dbhmax_infra ; + fates_logging_dbhmax_infra:units = "cm" ; + fates_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; + double fates_logging_dbhmin ; + fates_logging_dbhmin:units = "cm" ; + fates_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; + double fates_logging_direct_frac ; + fates_logging_direct_frac:units = "fraction" ; + fates_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; + double fates_logging_event_code ; + fates_logging_event_code:units = "unitless" ; + fates_logging_event_code:long_name = "Integer code that options how logging events are structured" ; + double fates_logging_export_frac ; + fates_logging_export_frac:units = "fraction" ; + fates_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; + double fates_logging_mechanical_frac ; + fates_logging_mechanical_frac:units = "fraction" ; + fates_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; double fates_maintresp_model ; fates_maintresp_model:units = "unitless" ; fates_maintresp_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991) (NOT USED)" ; - double fates_maxcohort ; - fates_maxcohort:units = "count" ; - fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; - double fates_maxpatch_primary ; - fates_maxpatch_primary:units = "count" ; - fates_maxpatch_primary:long_name = "maximum number of primary vegetation patches per site" ; - double fates_maxpatch_secondary ; - fates_maxpatch_secondary:units = "count" ; - fates_maxpatch_secondary:long_name = "maximum number of secondary vegetation patches per site" ; double fates_mort_disturb_frac ; fates_mort_disturb_frac:units = "fraction" ; fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; @@ -746,39 +707,39 @@ variables: double fates_patch_fusion_tol ; fates_patch_fusion_tol:units = "unitless" ; fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; - double fates_phen_chilltemp ; - fates_phen_chilltemp:units = "degrees C" ; - fates_phen_chilltemp:long_name = "chilling day counting threshold for vegetation" ; + double fates_phen_a ; + fates_phen_a:units = "none" ; + fates_phen_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_b ; + fates_phen_b:units = "none" ; + fates_phen_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_c ; + fates_phen_c:units = "none" ; + fates_phen_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_chiltemp ; + fates_phen_chiltemp:units = "degrees C" ; + fates_phen_chiltemp:long_name = "chilling day counting threshold for vegetation" ; double fates_phen_coldtemp ; fates_phen_coldtemp:units = "degrees C" ; fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; - double fates_phen_drought_model ; - fates_phen_drought_model:units = "unitless" ; - fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; + double fates_phen_doff_time ; + fates_phen_doff_time:units = "days" ; + fates_phen_doff_time:long_name = "day threshold compared against days since leaves became off-allometry" ; double fates_phen_drought_threshold ; - fates_phen_drought_threshold:units = "m3/m3 or mm" ; - fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; - double fates_phen_gddthresh_a ; - fates_phen_gddthresh_a:units = "none" ; - fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_gddthresh_b ; - fates_phen_gddthresh_b:units = "none" ; - fates_phen_gddthresh_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_gddthresh_c ; - fates_phen_gddthresh_c:units = "none" ; - fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_mindaysoff ; - fates_phen_mindaysoff:units = "days" ; - fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves became off-allometry" ; + fates_phen_drought_threshold:units = "m3/m3" ; + fates_phen_drought_threshold:long_name = "liquid volume in soil layer, threashold for drought phenology" ; double fates_phen_mindayson ; fates_phen_mindayson:units = "days" ; fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; - double fates_phen_moist_threshold ; - fates_phen_moist_threshold:units = "m3/m3 or mm" ; - fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; double fates_phen_ncolddayslim ; fates_phen_ncolddayslim:units = "days" ; fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; + double fates_photo_temp_acclim_timescale ; + fates_photo_temp_acclim_timescale:units = "days" ; + fates_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; + double fates_photo_tempsens_model ; + fates_photo_tempsens_model:units = "unitless" ; + fates_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; double fates_q10_froz ; fates_q10_froz:units = "unitless" ; fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; @@ -788,12 +749,18 @@ variables: double fates_soil_salinity ; fates_soil_salinity:units = "ppt" ; fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; + double fates_theta_cj_c3 ; + fates_theta_cj_c3:units = "unitless" ; + fates_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; + double fates_theta_cj_c4 ; + fates_theta_cj_c4:units = "unitless" ; + fates_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; double fates_vai_top_bin_width ; fates_vai_top_bin_width:units = "m2/m2" ; - fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; + fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer (NOT USED)" ; double fates_vai_width_increase_factor ; fates_vai_width_increase_factor:units = "unitless" ; - fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; + fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing) (NOT USED)" ; // global attributes: :history = "This parameter file is maintained in version control\nSee https://github.com/NGEET/fates/blob/master/parameter_files/fates_params_default.cdl \nFor changes, use git blame \n" ; @@ -805,14 +772,12 @@ data: fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; - fates_history_damage_bin_edges = 0, 80 ; - fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100 ; - fates_alloc_organ_id = 1, 2, 3, 6 ; + fates_hydr_htftype_node = 1, 1, 1, 1 ; - fates_hydro_htftype_node = 1, 1, 1, 1 ; + fates_prt_organ_id = 1, 2, 3, 6 ; fates_pftname = "broadleaf_evergreen_tropical_tree ", @@ -828,18 +793,12 @@ data: "cool_c3_grass ", "c4_grass " ; - fates_hydro_organ_name = + fates_hydr_organname_node = "leaf ", "stem ", "transporting root ", "absorbing root " ; - fates_alloc_organ_name = - "leaf", - "fine root", - "sapwood", - "structure" ; - fates_litterclass_name = "twig ", "small branch ", @@ -848,18 +807,15 @@ data: "dead leaves ", "live grass " ; - 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, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; + fates_prt_organ_name = + "leaf ", + "fine root ", + "sapwood ", + "structure " ; fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 ; - fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, - 0.8, 0.8, 0.8, 0.8 ; - fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; @@ -881,9 +837,6 @@ data: fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, - 0.95, 1, 1, 1 ; - fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07 ; @@ -914,12 +867,6 @@ data: fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; - - fates_allom_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; - - fates_allom_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -953,149 +900,107 @@ data: fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 ; + fates_branch_turnover = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; + fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; - fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5 ; + fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, + 0.67, 0.67 ; - fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + fates_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280 ; - fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, + fates_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14 ; - fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, + fates_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27 ; - fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1 ; + fates_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; - fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_cnp_eca_vmax_nh4 = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, - 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - - fates_cnp_eca_vmax_no3 = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, - 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - - fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, - 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - - fates_cnp_fnrt_adapt_tscale = 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100, 100 ; + fates_eca_vmax_nh4 = 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, + 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07 ; - fates_cnp_nfix1 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_eca_vmax_no3 = 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, + 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08 ; - fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5, 1.5 ; + fates_eca_vmax_p = 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, + 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09 ; - fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5, 1.5 ; - - fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_rd_vmax_n = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + fates_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_turnover_nitr_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_turnover_phos_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, - 5e-10, 5e-10, 5e-10, 5e-10 ; - - fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, - 0.01, 0.01, 0.01 ; - - fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; - - fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, - 5.5, 5.5 ; - - fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; - fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 ; fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07 ; + fates_fire_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, + 0.95, 1, 1, 1 ; + fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775 ; - fates_frag_fnrt_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5 ; - - fates_frag_fnrt_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; + fates_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; - fates_frag_fnrt_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; + fates_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; - fates_frag_leaf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5 ; + fates_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - fates_frag_leaf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; + fates_fr_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_frag_leaf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; + fates_fr_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25 ; - fates_frag_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, - 0.51, 0.51, 0.51, 0.51 ; + fates_fr_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25 ; fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, - 2.5, 2.5 ; + fates_hydr_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + 2.5 ; - fates_hydro_avuln_node = + fates_hydr_avuln_node = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 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_hydro_epsil_node = + fates_hydr_epsil_node = 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - fates_hydro_fcap_node = + fates_hydr_fcap_node = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_hydr_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_hydro_kmax_node = + fates_hydr_kmax_node = -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; - fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + fates_hydr_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5 ; - fates_hydro_p50_node = + fates_hydr_p50_node = -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, @@ -1105,10 +1010,10 @@ data: -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25 ; - fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, - 0.333, 0.333, 0.333, 0.333, 0.333 ; + fates_hydr_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, + 0.333, 0.333, 0.333, 0.333 ; - fates_hydro_pinot_node = + fates_hydr_pinot_node = -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, @@ -1118,34 +1023,34 @@ data: -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; - fates_hydro_pitlp_node = + fates_hydr_pitlp_node = -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; - fates_hydro_resid_node = + fates_hydr_resid_node = 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + fates_hydr_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625 ; - fates_hydro_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, + fates_hydr_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; - fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; + fates_hydr_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; - fates_hydro_thetas_node = + fates_hydr_thetas_node = 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; - fates_hydro_vg_alpha_node = + fates_hydr_vg_alpha_node = 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, @@ -1155,13 +1060,13 @@ data: 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005 ; - fates_hydro_vg_m_node = + fates_hydr_vg_m_node = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_hydro_vg_n_node = + fates_hydr_vg_n_node = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -1169,6 +1074,12 @@ data: fates_leaf_c3psn = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ; + fates_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, + 0.9, 0.75, 0.75, 0.75 ; + + fates_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.04, 0.04, 0.04 ; + fates_leaf_jmaxha = 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540 ; @@ -1178,6 +1089,9 @@ data: fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495 ; + fates_leaf_long = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, 0.03, 0.03, 0.03, 0.03, 0.03 ; @@ -1192,6 +1106,9 @@ data: fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, 4.7, 2.2, 5.3, 1.6 ; + fates_leaf_stor_priority = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8 ; + fates_leaf_vcmax25top = 50, 65, 39, 62, 41, 58, 62, 54, 54, 78, 78, 78 ; @@ -1204,6 +1121,17 @@ data: fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485 ; + fates_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, -0.23, + -0.23, -0.23 ; + + fates_lf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_lf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25 ; + + fates_lf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25 ; + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; @@ -1225,12 +1153,6 @@ data: fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - fates_mort_prescribed_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, - 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; - - fates_mort_prescribed_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, - 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; - fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; @@ -1243,137 +1165,183 @@ data: fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6 ; - fates_nonhydro_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, - -255000, -255000, -255000, -255000, -255000, -255000 ; + fates_nfix1 = _, _, _, _, _, _, _, _, _, _, _, _ ; - fates_nonhydro_smpso = -66000, -66000, -66000, -66000, -66000, -66000, - -66000, -66000, -66000, -66000, -66000, -66000 ; + fates_nfix2 = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5 ; fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; - fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, - 0.5 ; - - fates_phen_fnrt_drop_frac = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; + fates_phenflush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5 ; + + fates_prescribed_mortality_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, + 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; + + fates_prescribed_mortality_understory = 0.025, 0.025, 0.025, 0.025, 0.025, + 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; + fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4 ; fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; - fates_rad_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, - 0.9, 0.75, 0.75, 0.75 ; + fates_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_rad_leaf_rhonir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, - 0.41, 0.28, 0.28, 0.28 ; + fates_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_rad_leaf_rhovis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, - 0.08, 0.05, 0.05, 0.05 ; + fates_prescribed_recruitment = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, + 0.02, 0.02, 0.02, 0.02, 0.02 ; - fates_rad_leaf_taunir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, - 0.43, 0.4, 0.4, 0.4 ; + fates_prt_alloc_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, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; - fates_rad_leaf_tauvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, - 0.06, 0.05, 0.05, 0.05 ; + fates_prt_nitr_stoich_p1 = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; + + fates_prt_nitr_stoich_p2 = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; - fates_rad_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, - -0.23, -0.23, -0.23 ; + fates_prt_phos_stoich_p1 = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; - fates_rad_stem_rhonir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, - 0.49, 0.53, 0.53, 0.53 ; + fates_prt_phos_stoich_p2 = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; - fates_rad_stem_rhovis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.21, 0.31, 0.31, 0.31 ; + fates_recruit_hgt_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, + 0.125, 0.125, 0.125 ; - fates_rad_stem_taunir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, - 0.001, 0.001, 0.25, 0.25, 0.25 ; + fates_recruit_initd = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2 ; - fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, - 0.001, 0.001, 0.12, 0.12, 0.12 ; + fates_rholnir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, 0.41, 0.28, + 0.28, 0.28 ; - fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, - 0.125, 0.125, 0.125 ; + fates_rholvis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, 0.08, 0.05, + 0.05, 0.05 ; - fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, - 0.2, 0.2, 0.2 ; + fates_rhosnir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, 0.49, 0.53, + 0.53, 0.53 ; - fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, - 0.02, 0.02, 0.02, 0.02, 0.02 ; + fates_rhosvis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.31, + 0.31, 0.31 ; - fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1, 0.1 ; + fates_root_long = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, - 0.9 ; + fates_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; - fates_recruit_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, - 1.47, 1.47, 1.47 ; + fates_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9 ; - fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5 ; + fates_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, 1.47, + 1.47, 1.47 ; - fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, + 0.51, 0.51, 0.51, 0.51 ; fates_seed_dispersal_param_A = _, _, _, _, _, _, _, _, _, _, _, _ ; fates_seed_dispersal_param_B = _, _, _, _, _, _, _, _, _, _, _, _ ; - fates_stoich_nitr = - 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, - 0.0047, 0.0047, 0.0047 ; + fates_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; - fates_stoich_phos = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, - 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, - 0.00047, 0.00047, 0.00047, 0.00047 ; + fates_seed_suppl = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, - 0.03, 0.03 ; + fates_senleaf_long_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; + fates_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, -255000, + -255000, -255000, -255000, -255000, -255000 ; - fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, - 0.67, 0.67, 0.67 ; + fates_smpso = -66000, -66000, -66000, -66000, -66000, -66000, -66000, + -66000, -66000, -66000, -66000, -66000 ; - fates_turb_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.04, 0.04, 0.04, 0.04 ; + fates_taulnir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, 0.43, 0.4, + 0.4, 0.4 ; - fates_turb_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, - 0.055, 0.055, 0.055, 0.055 ; + fates_taulvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.05, + 0.05, 0.05 ; - fates_turnover_branch = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; + fates_tausnir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.25, 0.25, 0.25 ; - fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + fates_tausvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.12, 0.12, 0.12 ; - fates_turnover_leaf = - 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, + 0.03, 0.03 ; - fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; + + fates_turnover_carb_retrans = + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_turnover_nitr_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_turnover_phos_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_turnover_retrans_mode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7 ; fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; + fates_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, + 0.055, 0.055, 0.055 ; + fates_hlm_pft_map = 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1406,28 +1374,28 @@ data: fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; - fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; + fates_max_decomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; - fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; + fates_CWD_frac = 0.045, 0.075, 0.21, 0.67 ; fates_base_mr_20 = 2.52e-06 ; fates_canopy_closure_thresh = 0.8 ; - fates_cnp_eca_plant_escalar = 1.25e-05 ; - fates_cohort_age_fusion_tol = 0.08 ; fates_cohort_size_fusion_tol = 0.08 ; fates_comp_excln = 3 ; - fates_damage_canopy_layer_code = 1 ; + fates_cwd_fcel = 0.76 ; - fates_damage_event_code = 1 ; + fates_cwd_flig = 0.24 ; fates_dev_arbitrary = _ ; + fates_eca_plant_escalar = 1.25e-05 ; + fates_fire_active_crown_fire = 0 ; fates_fire_cg_strikes = 0.2 ; @@ -1456,94 +1424,76 @@ data: fates_fire_threshold = 50 ; - fates_frag_cwd_fcel = 0.76 ; + fates_hydr_kmax_rsurf1 = 20 ; - fates_frag_cwd_flig = 0.24 ; + fates_hydr_kmax_rsurf2 = 0.0001 ; - fates_hydro_kmax_rsurf1 = 20 ; + fates_hydr_psi0 = 0 ; - fates_hydro_kmax_rsurf2 = 0.0001 ; + fates_hydr_psicap = -0.6 ; - fates_hydro_psi0 = 0 ; + fates_init_litter = 0.05 ; - fates_hydro_psicap = -0.6 ; - - fates_hydro_solver = 1 ; - - fates_landuse_logging_coll_under_frac = 0.55983 ; - - fates_landuse_logging_collateral_frac = 0.05 ; - - fates_landuse_logging_dbhmax = _ ; - - fates_landuse_logging_dbhmax_infra = 35 ; - - fates_landuse_logging_dbhmin = 50 ; - - fates_landuse_logging_direct_frac = 0.15 ; - - fates_landuse_logging_event_code = -30 ; + fates_leaf_stomatal_model = 1 ; - fates_landuse_logging_export_frac = 0.8 ; + fates_logging_coll_under_frac = 0.55983 ; - fates_landuse_logging_mechanical_frac = 0.05 ; + fates_logging_collateral_frac = 0.05 ; - fates_landuse_pprodharv10_forest_mean = 0.8125 ; + fates_logging_dbhmax = _ ; - fates_leaf_photo_temp_acclim_timescale = 30 ; + fates_logging_dbhmax_infra = 35 ; - fates_leaf_photo_tempsens_model = 1 ; + fates_logging_dbhmin = 50 ; - fates_leaf_stomatal_assim_model = 1 ; + fates_logging_direct_frac = 0.15 ; - fates_leaf_stomatal_model = 1 ; + fates_logging_event_code = -30 ; - fates_leaf_theta_cj_c3 = 0.999 ; + fates_logging_export_frac = 0.8 ; - fates_leaf_theta_cj_c4 = 0.999 ; + fates_logging_mechanical_frac = 0.05 ; fates_maintresp_model = 1 ; - fates_maxcohort = 100 ; - - fates_maxpatch_primary = 10 ; - - fates_maxpatch_secondary = 4 ; - fates_mort_disturb_frac = 1 ; fates_mort_understorey_death = 0.55983 ; fates_patch_fusion_tol = 0.05 ; - fates_phen_chilltemp = 5 ; - - fates_phen_coldtemp = 7.5 ; + fates_phen_a = -68 ; - fates_phen_drought_model = 0 ; + fates_phen_b = 638 ; - fates_phen_drought_threshold = 0.15 ; + fates_phen_c = -0.01 ; - fates_phen_gddthresh_a = -68 ; + fates_phen_chiltemp = 5 ; - fates_phen_gddthresh_b = 638 ; + fates_phen_coldtemp = 7.5 ; - fates_phen_gddthresh_c = -0.01 ; + fates_phen_doff_time = 100 ; - fates_phen_mindaysoff = 100 ; + fates_phen_drought_threshold = 0.15 ; fates_phen_mindayson = 90 ; - fates_phen_moist_threshold = 0.18 ; - fates_phen_ncolddayslim = 5 ; + fates_photo_temp_acclim_timescale = 30 ; + + fates_photo_tempsens_model = 1 ; + fates_q10_froz = 1.5 ; fates_q10_mr = 1.5 ; fates_soil_salinity = 0.4 ; + fates_theta_cj_c3 = 0.999 ; + + fates_theta_cj_c4 = 0.999 ; + fates_vai_top_bin_width = 1 ; fates_vai_width_increase_factor = 1 ; From 81ebf3264eb862652dc45859511a231200de56b2 Mon Sep 17 00:00:00 2001 From: Shijie Shu Date: Fri, 28 Oct 2022 14:28:02 -0700 Subject: [PATCH 405/852] Minor revisions on comments and merged with master branch, temporary commit --- biogeochem/EDCanopyStructureMod.F90 | 2 +- biogeochem/EDLoggingMortalityMod.F90 | 257 ++++++++++++++++++++++--- biogeochem/EDMortalityFunctionsMod.F90 | 4 + biogeochem/EDPatchDynamicsMod.F90 | 72 ++++++- main/FatesHistoryInterfaceMod.F90 | 15 ++ 5 files changed, 326 insertions(+), 24 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index f195f59f0a..5ac8343a2e 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -2063,7 +2063,7 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) ! Pass FATES Harvested C to bc_out. call UpdateHarvestC(sites(s),bc_out(s)) - + end do ! This call to RecruitWaterStorage() makes an accounting of diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index b03e9485f5..cf920cd429 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -86,11 +86,6 @@ module EDLoggingMortalityMod real(r8), parameter :: harvest_litter_localization = 0.0_r8 - ! ! transfer factor from kg biomass (dry matter) to kg carbon - ! ! now we applied a simple fraction of 50% based on the IPCC - ! ! guideline - ! real(r8), parameter :: carbon_per_kg_biomass = 0.5_r8 - character(len=*), parameter, private :: sourcefile = & __FILE__ @@ -267,30 +262,30 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & ! Is it the correct place to call the function? ! Inputs: patch_area, patch_biomass, what else? - ! call get_harvest_rate_carbon (patch_anthro_disturbance_label, hlm_harvest_catnames, & - ! hlm_harvest_rates, frac_site_primary, secondary_age, harvest_rate) + call get_harvest_rate_carbon (patch_anthro_disturbance_label, hlm_harvest_catnames, & + hlm_harvest_rates, secondary_age, harvestable_forest_c, & + harvest_rate, harvest_tag, cur_harvest_tag) - ! if (fates_global_verbose()) then - ! write(fates_log(), *) 'Successfully Read Harvest Rate from HLM.', hlm_harvest_rates(:), harvest_rate - ! end if - - write(fates_log(),*) 'HLM harvest carbon data not implemented yet. Exiting.' - call endrun(msg=errMsg(sourcefile, __LINE__)) + if (fates_global_verbose()) then + write(fates_log(), *) 'Successfully Read Harvest Rate from HLM.', hlm_harvest_rates(:), harvest_rate, harvestable_forest_c + end if endif ! transfer of area to secondary land is based on overall area affected, not just logged crown area ! l_degrad accounts for the affected area between logged crowns if(prt_params%woody(pft_i) == itrue)then ! only set logging rates for trees - - ! direct logging rates, based on dbh min and max criteria - if (dbh >= logging_dbhmin .and. .not. & - ((logging_dbhmax < fates_check_param_set) .and. (dbh >= logging_dbhmax )) ) then - ! the logic of the above line is a bit unintuitive but allows turning off the dbhmax comparison entirely. - ! since there is an .and. .not. after the first conditional, the dbh:dbhmax comparison needs to be - ! the opposite of what would otherwise be expected... - lmort_direct = harvest_rate * logging_direct_frac - + if (cur_harvest_tag == 0) then + ! direct logging rates, based on dbh min and max criteria + if (dbh >= logging_dbhmin .and. .not. & + ((logging_dbhmax < fates_check_param_set) .and. (dbh >= logging_dbhmax )) ) then + ! the logic of the above line is a bit unintuitive but allows turning off the dbhmax comparison entirely. + ! since there is an .and. .not. after the first conditional, the dbh:dbhmax comparison needs to be + ! the opposite of what would otherwise be expected... + lmort_direct = harvest_rate * logging_direct_frac + else + lmort_direct = 0.0_r8 + end if else lmort_direct = 0.0_r8 end if @@ -418,6 +413,224 @@ end subroutine get_harvest_rate_area ! ============================================================================ + subroutine get_harvestable_carbon (csite, site_area, hlm_harvest_catnames, harvestable_forest_c ) + + !USES: + use SFParamsMod, only : SF_val_cwd_frac + use EDTypesMod, only : AREA_INV + + + ! ------------------------------------------------------------------------------------------- + ! + ! DESCRIPTION: + ! get the total carbon availale for harvest for three different harvest categories: + ! primary forest, secondary mature forest and secondary young forest + ! under two different scenarios: + ! harvestable carbon: aggregate all cohorts matching the dbhmin harvest criteria + ! + ! this subroutine shall be called outside the patch loop + ! output will be used to estimate the area-based harvest rate (get_harvest_rate_carbon) + ! for each cohort. + + ! Arguments + type(ed_site_type), intent(in), target :: csite + real(r8), intent(in) :: site_area ! temporary variable + character(len=64), intent(in) :: hlm_harvest_catnames(:) ! names of hlm harvest categories + + real(r8), intent(out) :: harvestable_forest_c(hlm_num_lu_harvest_cats) + + ! Local Variables + type(ed_patch_type), pointer :: currentPatch + type(ed_cohort_type), pointer :: currentCohort + real(r8) :: harvestable_patch_c ! temporary variable, kgC site-1 + real(r8) :: harvestable_cohort_c ! temporary variable, kgC site-1 + real(r8) :: sapw_m ! Biomass of sap wood + real(r8) :: struct_m ! Biomass of structural organs + integer :: pft ! Index of plant functional type + integer :: h_index ! for looping over harvest categories + + ! Initialization + harvestable_forest_c = 0._r8 + + ! loop over patches + currentPatch => csite%oldest_patch + do while (associated(currentPatch)) + harvestable_patch_c = 0._r8 + currentCohort => currentPatch%tallest + + do while (associated(currentCohort)) + pft = currentCohort%pft + + ! only account for cohorts matching the following conditions + if(int(prt_params%woody(pft)) == 1)then ! only set logging rates for trees + sapw_m = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) + struct_m = currentCohort%prt%GetState(struct_organ, all_carbon_elements) + ! logging_direct_frac shall be 1 for LUH2 driven simulation and global simulation + ! in site level study logging_direct_frac shall be surveyed + ! unit: [kgC ] = [kgC/plant] * [plant/ha] * [ha/ 10k m2] * [ m2 area ] + harvestable_cohort_c = logging_direct_frac * ( sapw_m + struct_m ) * & + prt_params%allom_agb_frac(currentCohort%pft) * & + SF_val_CWD_frac(ncwd) * logging_export_frac * & + currentCohort%n * AREA_INV * site_area + + ! No harvest for trees without canopy + if (currentCohort%canopy_layer>=1) then + ! logging amount are based on dbh min and max criteria + if (currentCohort%dbh >= logging_dbhmin .and. .not. & + ((logging_dbhmax < fates_check_param_set) .and. (currentCohort%dbh >= logging_dbhmax )) ) then + ! Harvestable C: aggregate cohorts fit the criteria + harvestable_patch_c = harvestable_patch_c + harvestable_cohort_c + end if + end if + end if + currentCohort => currentCohort%shorter + end do + + ! judge which category the current patch belong to + ! since we have not separated forest vs. non-forest + ! all carbon belongs to the forest categories + do h_index = 1,hlm_num_lu_harvest_cats + if (currentPatch%anthro_disturbance_label .eq. primaryforest) then + ! Primary + if(hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1") then + harvestable_forest_c(h_index) = harvestable_forest_c(h_index) + harvestable_patch_c + end if + else if (currentPatch%anthro_disturbance_label .eq. secondaryforest .and. & + currentPatch%age_since_anthro_disturbance >= secondary_age_threshold) then + ! Secondary mature + if(hlm_harvest_catnames(h_index) .eq. "HARVEST_SH1") then + harvestable_forest_c(h_index) = harvestable_forest_c(h_index) + harvestable_patch_c + end if + else if (currentPatch%anthro_disturbance_label .eq. secondaryforest .and. & + currentPatch%age_since_anthro_disturbance < secondary_age_threshold) then + ! Secondary young + if(hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2") then + harvestable_forest_c(h_index) = harvestable_forest_c(h_index) + harvestable_patch_c + end if + end if + end do + currentPatch => currentPatch%younger + end do + + end subroutine get_harvestable_carbon + + ! ============================================================================ + + subroutine get_harvest_rate_carbon (patch_anthro_disturbance_label, hlm_harvest_catnames, & + hlm_harvest_rates, secondary_age, harvestable_forest_c, & + harvest_rate, harvest_tag, cur_harvest_tag) + + ! ------------------------------------------------------------------------------------------- + ! + ! DESCRIPTION: + ! get the carbon-based harvest rates based on info passed to FATES from the boundary conditions in. + ! assumes logging_time == true + + ! Arguments + real(r8), intent(in) :: hlm_harvest_rates(:) ! annual harvest rate per hlm category + character(len=64), intent(in) :: hlm_harvest_catnames(:) ! names of hlm harvest categories + integer, intent(in) :: patch_anthro_disturbance_label ! patch level anthro_disturbance_label + real(r8), intent(in) :: secondary_age ! patch level age_since_anthro_disturbance + real(r8), intent(in) :: harvestable_forest_c(:) ! site level forest c matching criteria available for harvest, kgC site-1 + real(r8), intent(out) :: harvest_rate ! area fraction + integer, intent(inout) :: harvest_tag(:) ! 0. normal harvest; 1. current site does not have enough C but + ! can perform harvest by ignoring criteria; 2. current site does + ! not have enough carbon + ! This harvest tag shall be a patch level variable but since all + ! logging functions happen within cohort loop we can only put the + ! calculation here. Can think about optimizing the logging calculation + ! in the future. + integer, intent(out), optional :: cur_harvest_tag ! harvest tag of the current cohort + + ! Local Variables + integer :: h_index ! for looping over harvest categories + integer :: icode ! Integer equivalent of the event code (parameter file only allows reals) + real(r8) :: harvest_rate_c ! Temporary variable, kgC site-1 + real(r8) :: harvest_rate_supply ! Temporary variable, kgC site-1 + + ! Loop around harvest categories to determine the hlm harvest rate demand and actual harvest rate for the + ! current cohort based on patch history info + harvest_rate = 0._r8 + harvest_rate_c = 0._r8 + harvest_rate_supply = 0._r8 + harvest_tag(:) = 1 + + do h_index = 1,hlm_num_lu_harvest_cats + if (patch_anthro_disturbance_label .eq. primaryforest) then + if(hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1" .or. & + hlm_harvest_catnames(h_index) .eq. "HARVEST_VH2") then + harvest_rate_c = harvest_rate_c + hlm_harvest_rates(h_index) + ! Determine the total supply of available C for harvest + if(harvestable_forest_c(h_index) >= harvest_rate_c) then + harvest_rate_supply = harvest_rate_supply + harvestable_forest_c(h_index) + harvest_tag(h_index) = 0 + else + harvest_tag(h_index) = 1 + end if + endif + else if (patch_anthro_disturbance_label .eq. secondaryforest .and. & + secondary_age >= secondary_age_threshold) then + if(hlm_harvest_catnames(h_index) .eq. "HARVEST_SH1") then + harvest_rate_c = harvest_rate_c + hlm_harvest_rates(h_index) + if(harvestable_forest_c(h_index) >= harvest_rate_c) then + harvest_rate_supply = harvest_rate_supply + harvestable_forest_c(h_index) + harvest_tag(h_index) = 0 + else + harvest_tag(h_index) = 1 + end if + endif + else if (patch_anthro_disturbance_label .eq. secondaryforest .and. & + secondary_age < secondary_age_threshold) then + if(hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2" .or. & + hlm_harvest_catnames(h_index) .eq. "HARVEST_SH3") then + harvest_rate_c = harvest_rate_c + hlm_harvest_rates(h_index) + if(harvestable_forest_c(h_index) >= harvest_rate_c) then + harvest_rate_supply = harvest_rate_supply + harvestable_forest_c(h_index) + harvest_tag(h_index) = 0 + else + harvest_tag(h_index) = 1 + end if + endif + endif + end do + + ! If any harvest category available, assign to cur_harvest_tag and trigger logging event + if(present(cur_harvest_tag))then + cur_harvest_tag = minval(harvest_tag) + end if + + ! Transfer carbon-based harvest rate to area-based harvest rate + if (harvest_rate_supply > rsnbl_math_prec .and. harvest_rate_supply > harvest_rate_c) then + harvest_rate = harvest_rate_c / harvest_rate_supply + else + harvest_rate = 0._r8 + end if + + ! For carbon-based harvest rate, normalizing by site-level primary or secondary forest fraction + ! is not needed + + ! calculate today's harvest rate + ! whether to harvest today has already been determined by IsItLoggingTime + ! for icode == 2, icode < 0, and icode > 10000 apply the annual rate one time (no calc) + ! Bad logging event flag is caught in IsItLoggingTime, so don't check it here + icode = int(logging_event_code) + if(icode .eq. 1) then + ! Logging is turned off - not sure why we need another switch + harvest_rate = 0._r8 + else if(icode .eq. 3) then + ! Logging event every day - this may not work due to the mortality exclusivity + harvest_rate = harvest_rate / hlm_days_per_year + else if(icode .eq. 4) then + ! logging event once a month + if(hlm_current_day.eq.1 ) then + harvest_rate = harvest_rate / months_per_year + end if + end if + + end subroutine get_harvest_rate_carbon + + ! ============================================================================ + subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site_areadis, bc_in) ! ------------------------------------------------------------------------------------------- diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index 605c377508..40dc0fb067 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -231,6 +231,10 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_pr type(ed_cohort_type),intent(inout), target :: currentCohort type(bc_in_type), intent(in) :: bc_in real(r8), intent(in) :: frac_site_primary + + real(r8), intent(in) :: harvestable_forest_c(:) ! total carbon available for logging, kgC site-1 + integer, intent(inout) :: harvest_tag(:) + ! ! !LOCAL VARIABLES: real(r8) :: cmort ! starvation mortality rate (fraction per year) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 56d9cc3b5a..e42c21478c 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -197,6 +197,10 @@ subroutine disturbance_rates( site_in, bc_in) ! first calculate the fractino of the site that is primary land call get_frac_site_primary(site_in, frac_site_primary) + harvest_debt_primary = 0 + harvest_debt_secondary = 0 + patch_no_secondary = 0 + currentPatch => site_in%oldest_patch do while (associated(currentPatch)) @@ -234,10 +238,76 @@ subroutine disturbance_rates( site_in, bc_in) currentCohort => currentCohort%taller end do - currentPatch%disturbance_mode = fates_unset_int + + ! Determine harvest debt for primary land and secondary land + ! Harvest debt is the accumulated total carbon amount once + ! available carbon for harvest is smaller than the harvest + ! rate of forcing data for each site. + ! Each cohort has the same harvest tag but not each patch + ! Hence this part shall be within the patch loop + ! TODO: we can define harvest debt as a fraction of the + ! harvest rate in the future + ! Warning: Non-forest harvest is not accounted for yet + ! Thus the harvest tag for non-forest are not effective + if(logging_time) then + harvest_debt_loop: do h_index = 1, hlm_num_lu_harvest_cats + ! Primary patch: Once a patch has debt, skip the calculation + if (harvest_debt_primary == 0) then + if ( currentPatch%anthro_disturbance_label .eq. primaryforest ) then + if ( harvest_tag(h_index) == 1 ) then + ! h_index points to primary forest harvest + if((bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1")) then + harvest_debt_primary = 1 + exit harvest_debt_loop + end if + end if + end if + end if + ! Secondary patch + if (harvest_debt_secondary == 0) then + if ( currentPatch%anthro_disturbance_label .eq. secondaryforest ) then + patch_no_secondary = patch_no_secondary + 1 + if ( harvest_tag(h_index) == 1 ) then + ! h_index points to secondary forest harvest + if((bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH1") .or. & + (bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2")) then + harvest_debt_secondary = 1 + exit harvest_debt_loop + end if + end if + end if + end if + end do harvest_debt_loop + end if + currentPatch => currentPatch%younger end do + ! Obatin actual harvest debt. This shall be outside the patch loop + if(logging_time) then + do h_index = 1, hlm_num_lu_harvest_cats + if ( harvest_debt_primary == 1 ) then + ! Only account for primary forest harvest rate + if((bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1") .or. & + (bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_VH2")) then + site_in%resources_management%harvest_debt = site_in%resources_management%harvest_debt + & + bc_in%hlm_harvest_rates(h_index) + end if + end if + if (harvest_debt_secondary == 1 .or. patch_no_secondary == 0) then + ! Only account for secondary forest harvest rate + if((bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH1") .or. & + (bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2") .or. & + (bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH3")) then + site_in%resources_management%harvest_debt = site_in%resources_management%harvest_debt + & + bc_in%hlm_harvest_rates(h_index) + site_in%resources_management%harvest_debt_sec = site_in%resources_management%harvest_debt_sec + & + bc_in%hlm_harvest_rates(h_index) + end if + end if + end do + end if + ! --------------------------------------------------------------------------------------------- ! Calculate Disturbance Rates based on the mortality rates just calculated ! --------------------------------------------------------------------------------------------- diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 3ef7fd14df..ada2330a58 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2135,6 +2135,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) this%hvars(ih_h2oveg_recruit_si)%r81d(io_si) = sites(s)%si_hydr%h2oveg_recruit this%hvars(ih_h2oveg_growturn_err_si)%r81d(io_si) = sites(s)%si_hydr%h2oveg_growturn_err end if + hio_harvest_debt_si(io_si) = sites(s)%resources_management%harvest_debt + hio_harvest_debt_sec_si(io_si) = sites(s)%resources_management%harvest_debt_sec ! error in primary lands from patch fusion [m2 m-2 day-1] -> [m2 m-2 yr-1] hio_primaryland_fusion_error_si(io_si) = sites(s)%primary_land_patchfusion_error * days_per_year @@ -2210,6 +2212,12 @@ subroutine update_history_dyn(this,nc,nsites,sites) + cpatch%area * AREA_INV endif + ! Secondary forest mean LAI + if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + hio_lai_secondary_si(io_si) = hio_lai_secondary_si(io_si) & + + sum(cpatch%tlai_profile(:,:,:)) * cpatch%total_canopy_area + end if + ! patch-age-resolved fire variables do i_pft = 1,numpft ! for scorch height, weight the value by patch area within any @@ -2970,6 +2978,13 @@ subroutine update_history_dyn(this,nc,nsites,sites) endif end do + ! divide secondary plant leaf area by secondary forest area to get the secondary forest LAI + if (hio_fraction_secondary_forest_si(io_si) .gt. nearzero) then + hio_lai_secondary_si(io_si) = hio_lai_secondary_si(io_si) / (hio_fraction_secondary_forest_si(io_si)*AREA) + else + hio_lai_secondary_si(io_si) = 0._r8 + end if + ! pass the cohort termination mortality as a flux to the history, and then reset the termination mortality buffer ! note there are various ways of reporting the total mortality, so pass to these as well do i_pft = 1, numpft From 91d4576c997361dd815c0c68bbf96c2834d67abe Mon Sep 17 00:00:00 2001 From: Shijie Shu Date: Mon, 31 Oct 2022 12:22:36 -0700 Subject: [PATCH 406/852] Patch up paralell disturbance and model phenology issue. --- biogeochem/EDPatchDynamicsMod.F90 | 207 ++++++++++-------------------- biogeochem/EDPhysiologyMod.F90 | 10 +- main/EDInitMod.F90 | 29 +++-- main/EDMainMod.F90 | 1 - main/EDTypesMod.F90 | 9 +- main/FatesHistoryInterfaceMod.F90 | 12 +- main/FatesRestartInterfaceMod.F90 | 47 ++++--- 7 files changed, 132 insertions(+), 183 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index e42c21478c..022bed4ac6 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -188,6 +188,7 @@ subroutine disturbance_rates( site_in, bc_in) integer :: i_dist real(r8) :: frac_site_primary real(r8) :: harvest_rate + real(r8) :: tempsum !---------------------------------------------------------------------------------------------- ! Calculate Mortality Rates (these were previously calculated during growth derivatives) @@ -402,90 +403,11 @@ subroutine disturbance_rates( site_in, bc_in) call FatesWarn(msg,index=2) endif - - - - ! ------------------------------------------------------------------------------------------ - ! Determine which disturbance is dominant, and force mortality diagnostics in the upper - ! canopy to be zero for the non-dominant mode. Note: upper-canopy tree-fall mortality is - ! not always disturbance generating, so when tree-fall mort is non-dominant, make sure - ! to still diagnose and track the non-disturbance rate - ! ------------------------------------------------------------------------------------------ - - ! DISTURBANCE IS LOGGING - if (currentPatch%disturbance_rates(dtype_ilog) > currentPatch%disturbance_rates(dtype_ifall) .and. & - currentPatch%disturbance_rates(dtype_ilog) > currentPatch%disturbance_rates(dtype_ifire) ) then - - currentPatch%disturbance_rate = currentPatch%disturbance_rates(dtype_ilog) - currentPatch%disturbance_mode = dtype_ilog - - ! Update diagnostics - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - if(currentCohort%canopy_layer == 1)then - currentCohort%cmort = currentCohort%cmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%hmort = currentCohort%hmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%bmort = currentCohort%bmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%dmort = currentCohort%dmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%frmort = currentCohort%frmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%smort = currentCohort%smort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%asmort = currentCohort%asmort*(1.0_r8 - fates_mortality_disturbance_fraction) - end if - currentCohort => currentCohort%taller - enddo !currentCohort - - ! DISTURBANCE IS FIRE - elseif (currentPatch%disturbance_rates(dtype_ifire) > currentPatch%disturbance_rates(dtype_ifall) .and. & - currentPatch%disturbance_rates(dtype_ifire) > currentPatch%disturbance_rates(dtype_ilog) ) then - - currentPatch%disturbance_rate = currentPatch%disturbance_rates(dtype_ifire) - currentPatch%disturbance_mode = dtype_ifire - - ! Update diagnostics, zero non-fire mortality rates - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - if(currentCohort%canopy_layer == 1)then - currentCohort%cmort = currentCohort%cmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%hmort = currentCohort%hmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%bmort = currentCohort%bmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%dmort = currentCohort%dmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%frmort = currentCohort%frmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%smort = currentCohort%smort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%asmort = currentCohort%asmort*(1.0_r8 - fates_mortality_disturbance_fraction) - currentCohort%lmort_direct = 0.0_r8 - currentCohort%lmort_collateral = 0.0_r8 - currentCohort%lmort_infra = 0.0_r8 - currentCohort%l_degrad = 0.0_r8 - end if - - ! This may be counter-intuitive, but the diagnostic fire-mortality rate - ! will stay zero in the patch that undergoes fire, this is because - ! the actual cohorts who experience the fire are only those in the - ! newly created patch so currentCohort%fmort = 0.0_r8 - ! Don't worry, the cohorts in the newly created patch will reflect burn - - currentCohort => currentCohort%taller - enddo !currentCohort - - else ! If fire and logging are not greater than treefall, just set disturbance rate to tree-fall - ! which is most likely a 0.0 - - currentPatch%disturbance_rate = currentPatch%disturbance_rates(dtype_ifall) - currentPatch%disturbance_mode = dtype_ifall - - ! Update diagnostics, zero non-treefall mortality rates - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - if(currentCohort%canopy_layer == 1)then - currentCohort%lmort_direct = 0.0_r8 - currentCohort%lmort_collateral = 0.0_r8 - currentCohort%lmort_infra = 0.0_r8 - currentCohort%l_degrad = 0.0_r8 - end if - currentCohort => currentCohort%taller - enddo !currentCohort - - + if ( sum(currentPatch%disturbance_rates(:)) .gt. 1.0_r8 ) then + tempsum = sum(currentPatch%disturbance_rates(:)) + do i_dist = 1,N_DIST_TYPES + currentPatch%disturbance_rates(i_dist) = currentPatch%disturbance_rates(i_dist) / tempsum + end do endif currentPatch => currentPatch%younger @@ -550,6 +472,9 @@ subroutine spawn_patches( currentSite, bc_in) real(r8) :: leaf_m ! leaf mass during partial burn calculations logical :: found_youngest_primary ! logical for finding the first primary forest patch integer :: min_nocomp_pft, max_nocomp_pft, i_nocomp_pft + integer :: i_disturbance_type, i_dist2 ! iterators for looping over disturbance types + real(r8) :: disturbance_rate ! rate of disturbance being resolved [fraction of patch area / day] + real(r8) :: oldarea ! old patch area prior to disturbance !--------------------------------------------------------------------- storesmallcohort => null() ! storage of the smallest cohort for insertion routine @@ -574,6 +499,8 @@ subroutine spawn_patches( currentSite, bc_in) ! If nocomp is not enabled, then this is not much of a loop, it only passes through once. nocomp_pft_loop: do i_nocomp_pft = min_nocomp_pft,max_nocomp_pft + disturbance_type_loop: do i_disturbance_type = 1,N_DIST_TYPES + ! calculate area of disturbed land, in this timestep, by summing contributions from each existing patch. currentPatch => currentSite%youngest_patch @@ -584,47 +511,42 @@ subroutine spawn_patches( currentSite, bc_in) cp_nocomp_matches_1_if: if ( hlm_use_nocomp .eq. ifalse .or. & currentPatch%nocomp_pft_label .eq. i_nocomp_pft ) then - - if(currentPatch%disturbance_rate > (1.0_r8 + rsnbl_math_prec)) then - write(fates_log(),*) 'patch disturbance rate > 1 ?',currentPatch%disturbance_rate + + disturbance_rate = currentPatch%disturbance_rates(i_disturbance_type) + + if(disturbance_rate > (1.0_r8 + rsnbl_math_prec)) then + write(fates_log(),*) 'patch disturbance rate > 1 ?',disturbance_rate call dump_patch(currentPatch) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - ! Check to make sure that the disturbance mode of the patch is set - if( .not.any(currentPatch%disturbance_mode == [dtype_ilog,dtype_ifall,dtype_ifire])) then - write(fates_log(),*) 'undefined disturbance mode? : ',currentPatch%disturbance_mode - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - ! Only create new patches that have non-negligible amount of land - if((currentPatch%area*currentPatch%disturbance_rate) > nearzero ) then + if((currentPatch%area*disturbance_rate) > nearzero ) then ! figure out whether the receiver patch for disturbance from this patch will be ! primary or secondary land receiver patch is primary forest only if both the - ! donor patch is primary forest and the dominant disturbance type is not logging + ! donor patch is primary forest and the current disturbance type is not logging if ( currentPatch%anthro_disturbance_label .eq. primaryforest .and. & - (currentPatch%disturbance_mode .ne. dtype_ilog) ) then + (i_disturbance_type .ne. dtype_ilog) ) then - site_areadis_primary = site_areadis_primary + currentPatch%area * currentPatch%disturbance_rate + site_areadis_primary = site_areadis_primary + currentPatch%area * disturbance_rate ! track disturbance rates to output to history - currentSite%disturbance_rates_primary_to_primary(currentPatch%disturbance_mode) = & - currentSite%disturbance_rates_primary_to_primary(currentPatch%disturbance_mode) + & - currentPatch%area * currentPatch%disturbance_rate * AREA_INV + currentSite%disturbance_rates_primary_to_primary(i_disturbance_type) = & + currentSite%disturbance_rates_primary_to_primary(i_disturbance_type) + & + currentPatch%area * disturbance_rate * AREA_INV else - site_areadis_secondary = site_areadis_secondary + currentPatch%area * currentPatch%disturbance_rate + site_areadis_secondary = site_areadis_secondary + currentPatch%area * disturbance_rate ! track disturbance rates to output to history if (currentPatch%anthro_disturbance_label .eq. secondaryforest) then - currentSite%disturbance_rates_secondary_to_secondary(currentPatch%disturbance_mode) = & - currentSite%disturbance_rates_secondary_to_secondary(currentPatch%disturbance_mode) + & - currentPatch%area * currentPatch%disturbance_rate * AREA_INV + currentSite%disturbance_rates_secondary_to_secondary(i_disturbance_type) = & + currentSite%disturbance_rates_secondary_to_secondary(i_disturbance_type) + & + currentPatch%area * disturbance_rate * AREA_INV else - currentSite%disturbance_rates_primary_to_secondary(currentPatch%disturbance_mode) = & - currentSite%disturbance_rates_primary_to_secondary(currentPatch%disturbance_mode) + & - currentPatch%area * currentPatch%disturbance_rate * AREA_INV + currentSite%disturbance_rates_primary_to_secondary(i_disturbance_type) = & + currentSite%disturbance_rates_primary_to_secondary(i_disturbance_type) + & + currentPatch%area * disturbance_rate * AREA_INV endif endif @@ -698,17 +620,17 @@ subroutine spawn_patches( currentSite, bc_in) currentPatch%nocomp_pft_label .eq. i_nocomp_pft ) then ! This is the amount of patch area that is disturbed, and donated by the donor - patch_site_areadis = currentPatch%area * currentPatch%disturbance_rate - + disturbance_rate = currentPatch%disturbance_rates(i_disturbance_type) + patch_site_areadis = currentPatch%area * disturbance_rate if ( patch_site_areadis > nearzero ) then ! figure out whether the receiver patch for disturbance from this patch ! will be primary or secondary land receiver patch is primary forest - ! only if both the donor patch is primary forest and the dominant + ! only if both the donor patch is primary forest and the current ! disturbance type is not logging if (currentPatch%anthro_disturbance_label .eq. primaryforest .and. & - (currentPatch%disturbance_mode .ne. dtype_ilog)) then + (i_disturbance_type .ne. dtype_ilog)) then new_patch => new_patch_primary else new_patch => new_patch_secondary @@ -721,24 +643,23 @@ subroutine spawn_patches( currentSite, bc_in) end if ! for the case where the donating patch is secondary forest, if - ! the dominant disturbance from this patch is non-anthropogenic, + ! the current disturbance from this patch is non-anthropogenic, ! we need to average in the time-since-anthropogenic-disturbance ! from the donor patch into that of the receiver patch if ( currentPatch%anthro_disturbance_label .eq. secondaryforest .and. & - (currentPatch%disturbance_mode .ne. dtype_ilog) ) then + (i_disturbance_type .ne. dtype_ilog) ) then new_patch%age_since_anthro_disturbance = new_patch%age_since_anthro_disturbance + & currentPatch%age_since_anthro_disturbance * (patch_site_areadis / site_areadis_secondary) endif - ! Transfer the litter existing already in the donor patch to the new patch ! This call will only transfer non-burned litter to new patch ! and burned litter to atmosphere. Thus it is important to zero burnt_frac_litter when - ! fire is not the dominant disturbance regime. + ! fire is not the current disturbance regime. - if(currentPatch%disturbance_mode .ne. dtype_ifire) then + if(i_disturbance_type .ne. dtype_ifire) then currentPatch%burnt_frac_litter(:) = 0._r8 end if @@ -746,10 +667,10 @@ subroutine spawn_patches( currentSite, bc_in) ! Transfer in litter fluxes from plants in various contexts of death and destruction - if(currentPatch%disturbance_mode .eq. dtype_ilog) then + if(i_disturbance_type .eq. dtype_ilog) then call logging_litter_fluxes(currentSite, currentPatch, & new_patch, patch_site_areadis,bc_in) - elseif(currentPatch%disturbance_mode .eq. dtype_ifire) then + elseif(i_disturbance_type .eq. dtype_ifire) then call fire_litter_fluxes(currentSite, currentPatch, & new_patch, patch_site_areadis,bc_in) else @@ -808,8 +729,8 @@ subroutine spawn_patches( currentSite, bc_in) store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) total_c = sapw_c + struct_c + leaf_c + fnrt_c + store_c - ! treefall mortality is the dominant disturbance - if(currentPatch%disturbance_mode .eq. dtype_ifall) then + ! treefall mortality is the current disturbance + if(i_disturbance_type .eq. dtype_ifall) then if(currentCohort%canopy_layer == 1)then @@ -919,8 +840,8 @@ subroutine spawn_patches( currentSite, bc_in) endif endif - ! Fire is the dominant disturbance - elseif (currentPatch%disturbance_mode .eq. dtype_ifire ) then + ! Fire is the current disturbance + elseif (i_disturbance_type .eq. dtype_ifire ) then ! Number of members in the new patch, before we impose fire survivorship nc%n = currentCohort%n * patch_site_areadis/currentPatch%area @@ -1020,8 +941,8 @@ subroutine spawn_patches( currentSite, bc_in) - ! Logging is the dominant disturbance - elseif (currentPatch%disturbance_mode .eq. dtype_ilog ) then + ! Logging is the current disturbance + elseif (i_disturbance_type .eq. dtype_ilog ) then ! If this cohort is in the upper canopy. It generated if(currentCohort%canopy_layer == 1)then @@ -1055,7 +976,7 @@ subroutine spawn_patches( currentSite, bc_in) else - ! WHat to do with cohorts in the understory of a logging generated + ! What to do with cohorts in the understory of a logging generated ! disturbance patch? if(prt_params%woody(currentCohort%pft) == itrue)then @@ -1140,7 +1061,7 @@ subroutine spawn_patches( currentSite, bc_in) else write(fates_log(),*) 'unknown disturbance mode?' - write(fates_log(),*) 'disturbance_mode: ',currentPatch%disturbance_mode + write(fates_log(),*) 'i_disturbance_type: ', i_disturbance_type call endrun(msg=errMsg(sourcefile, __LINE__)) end if ! Select disturbance mode @@ -1181,8 +1102,18 @@ subroutine spawn_patches( currentSite, bc_in) call sort_cohorts(currentPatch) !update area of donor patch + oldarea = currentPatch%area currentPatch%area = currentPatch%area - patch_site_areadis + ! for all disturbance rates that haven't been resolved yet, increase their amount so that + ! they are the same amount of gridcell-scale disturbance relative to the original patch size + if (i_disturbance_type .ne. N_DIST_TYPES) then + do i_dist2 = i_disturbance_type+1,N_DIST_TYPES + currentPatch%disturbance_rates(i_dist2) = currentPatch%disturbance_rates(i_dist2) & + * oldarea / currentPatch%area + end do + end if + ! sort out the cohorts, since some of them may be so small as to need removing. ! the first call to terminate cohorts removes sparse number densities, ! the second call removes for all other reasons (sparse culling must happen @@ -1194,11 +1125,6 @@ subroutine spawn_patches( currentSite, bc_in) end if ! if ( new_patch%area > nearzero ) then - !zero disturbance rate trackers - currentPatch%disturbance_rate = 0._r8 - currentPatch%disturbance_rates = 0._r8 - currentPatch%fract_ldist_not_harvested = 0._r8 - end if cp_nocomp_matches_2_if currentPatch => currentPatch%younger @@ -1280,8 +1206,19 @@ subroutine spawn_patches( currentSite, bc_in) call check_patch_area(currentSite) call set_patchno(currentSite) - + + end do disturbance_type_loop + end do nocomp_pft_loop + + !zero disturbance rate trackers on all patches + currentPatch => currentSite%oldest_patch + do while(associated(currentPatch)) + currentPatch%disturbance_rates(:) = 0._r8 + currentPatch%fract_ldist_not_harvested = 0._r8 + currentPatch => currentPatch%younger + end do + return end subroutine spawn_patches @@ -2170,7 +2107,6 @@ subroutine create_patch(currentSite, new_patch, age, areap, label,nocomp_pft) ! This new value will be generated when the calculate disturbance ! rates routine is called. This does not need to be remembered or in the restart file. - new_patch%disturbance_mode = fates_unset_int new_patch%f_sun = 0._r8 new_patch%ed_laisun_z(:,:,:) = 0._r8 @@ -2273,8 +2209,7 @@ subroutine zero_patch(cp_p) currentPatch%pft_agb_profile(:,:) = nan ! DISTURBANCE - currentPatch%disturbance_rates = 0._r8 - currentPatch%disturbance_rate = 0._r8 + currentPatch%disturbance_rates(:) = 0._r8 currentPatch%fract_ldist_not_harvested = 0._r8 diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 9a43af3226..6721f0dfa8 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -737,8 +737,12 @@ subroutine phenology( currentSite, bc_in ) ! This is the integer model day. The first day of the simulation is 1, and it ! continues monotonically, indefinitely - model_day_int = nint(hlm_model_day) + ! Advance it. (this should be a global, no reason + ! for site level, but we don't have global scalars in the + ! restart file) + currentSite%phen_model_date = currentSite%phen_model_date + 1 + model_day_int = currentSite%phen_model_date ! Use the following layer index to calculate drought conditions ilayer_swater = minloc(abs(bc_in%z_sisl(:)-dphen_soil_depth),dim=1) @@ -842,7 +846,7 @@ subroutine phenology( currentSite, bc_in ) end if if (model_day_int < currentSite%cleafondate) then - dayssincecleafon = model_day_int - (currentSite%cleafondate-365) + dayssincecleafon = model_day_int - (currentSite%cleafondate - 365) else dayssincecleafon = model_day_int - currentSite%cleafondate end if @@ -1054,6 +1058,7 @@ subroutine phenology( currentSite, bc_in ) call phenology_leafonoff(currentSite) + return end subroutine phenology @@ -1582,7 +1587,6 @@ subroutine SeedIn( currentSite, bc_in ) ! !USES: use EDTypesMod, only : area use EDTypesMod, only : homogenize_seed_pfts - !use FatesInterfaceTypesMod, only : hlm_use_fixed_biogeog ! For future reduced complexity? ! ! !ARGUMENTS type(ed_site_type), intent(inout), target :: currentSite diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 451834a9ec..d0e38d9df9 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -22,6 +22,7 @@ module EDInitMod use EDPatchDynamicsMod , only : set_patchno use EDPhysiologyMod , only : assign_cohort_sp_properties use ChecksBalancesMod , only : SiteMassStock + use FatesInterfaceTypesMod , only : hlm_day_of_year use EDTypesMod , only : ed_site_type, ed_patch_type, ed_cohort_type use EDTypesMod , only : numWaterMem use EDTypesMod , only : num_vegtemp_mem @@ -200,13 +201,15 @@ subroutine zero_site( site_in ) site_in%snow_depth = nan site_in%nchilldays = fates_unset_int site_in%ncolddays = fates_unset_int - site_in%cleafondate = fates_unset_int ! doy of leaf on - site_in%cleafoffdate = fates_unset_int ! doy of leaf off - site_in%dleafondate = fates_unset_int ! doy of leaf on drought - site_in%dleafoffdate = fates_unset_int ! doy of leaf on drought + site_in%cleafondate = fates_unset_int + site_in%cleafoffdate = fates_unset_int + site_in%dleafondate = fates_unset_int + site_in%dleafoffdate = fates_unset_int site_in%water_memory(:) = nan site_in%vegtemp_memory(:) = nan ! record of last 10 days temperature for senescence model. + site_in%phen_model_date = fates_unset_int + ! Disturbance rates tracking site_in%primary_land_patchfusion_error = 0.0_r8 site_in%potential_disturbance_rates(:) = 0.0_r8 @@ -315,15 +318,15 @@ subroutine set_site_properties( nsites, sites,bc_in ) do s = 1,nsites sites(s)%nchilldays = 0 sites(s)%ncolddays = 0 ! recalculated in phenology - ! immediately, so yes this - ! is memory-less, but needed - ! for first value in history file - - sites(s)%cleafondate = cleafon - sites(s)%cleafoffdate = cleafoff - sites(s)%dleafoffdate = dleafoff - sites(s)%dleafondate = dleafon - sites(s)%grow_deg_days = GDD + ! immediately, so yes this + ! is memory-less, but needed + ! for first value in history file + sites(s)%phen_model_date = 0 + sites(s)%cleafondate = cleafon - hlm_day_of_year + sites(s)%cleafoffdate = cleafoff - hlm_day_of_year + sites(s)%dleafoffdate = dleafoff - hlm_day_of_year + sites(s)%dleafondate = dleafon - hlm_day_of_year + sites(s)%grow_deg_days = GDD sites(s)%water_memory(1:numWaterMem) = watermem sites(s)%vegtemp_memory(1:num_vegtemp_mem) = 0._r8 diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index d05966ef14..7b9d623413 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -847,7 +847,6 @@ subroutine TotalBalanceCheck (currentSite, call_index ) write(fates_log(),*) 'BG CWD (by layer): ', sum(litt%bg_cwd,dim=1) write(fates_log(),*) 'leaf litter:',sum(litt%leaf_fines) write(fates_log(),*) 'root litter (by layer): ',sum(litt%root_fines,dim=1) - write(fates_log(),*) 'dist mode: ',currentPatch%disturbance_mode write(fates_log(),*) 'anthro_disturbance_label: ',currentPatch%anthro_disturbance_label write(fates_log(),*) 'use_this_pft: ', currentSite%use_this_pft(:) if(print_cohorts)then diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 1c76f44a54..6f3bf6ee52 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -532,9 +532,6 @@ module EDTypesMod real(r8) :: disturbance_rates(n_dist_types) ! disturbance rate from 1) mortality ! 2) fire: fraction/day ! 3) logging mortatliy - real(r8) :: disturbance_rate ! larger effective disturbance rate: fraction/day - integer :: disturbance_mode ! index identifying which disturbance was applied - ! can be one of: dtype_ifall, dtype_ilog or dtype_ifire real(r8) :: fract_ldist_not_harvested ! fraction of logged area that is canopy trees that weren't harvested @@ -745,6 +742,11 @@ module EDTypesMod integer :: dleafondate ! model date (day integer) of leaf on drought:- integer :: dleafoffdate ! model date (day integer) of leaf off drought:- + integer :: phen_model_date ! current model date (day integer) + ! this date stays continuous when + ! in runs that are restarted, regardless of + ! the conditions of restart + real(r8) :: water_memory(numWaterMem) ! last 10 days of soil moisture memory... @@ -1008,7 +1010,6 @@ subroutine dump_patch(cpatch) write(fates_log(),*) 'pa%gnd_alb_dir = ',cpatch%gnd_alb_dir(:) write(fates_log(),*) 'pa%c_stomata = ',cpatch%c_stomata write(fates_log(),*) 'pa%c_lblayer = ',cpatch%c_lblayer - write(fates_log(),*) 'pa%disturbance_rate = ',cpatch%disturbance_rate write(fates_log(),*) 'pa%disturbance_rates = ',cpatch%disturbance_rates(:) write(fates_log(),*) 'pa%anthro_disturbance_label = ',cpatch%anthro_disturbance_label write(fates_log(),*) '----------------------------------------' diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index ada2330a58..829a683ecd 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -1755,7 +1755,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) integer :: height_bin_max, height_bin_min ! which height bin a given cohort's canopy is in integer :: i_heightbin ! iterator for height bins integer :: el ! Loop index for elements - integer :: model_day_int ! integer model day from reference + integer :: model_day_int ! Integer model day since simulation start integer :: ageclass_since_anthrodist ! what is the equivalent age class for ! time-since-anthropogenic-disturbance of secondary forest @@ -2041,7 +2041,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_cleafoff_si => this%hvars(ih_cleafoff_si)%r81d, & hio_cleafon_si => this%hvars(ih_cleafon_si)%r81d, & hio_dleafoff_si => this%hvars(ih_dleafoff_si)%r81d, & - hio_dleafon_si => this%hvars(ih_dleafoff_si)%r81d, & + hio_dleafon_si => this%hvars(ih_dleafon_si)%r81d, & hio_tveg24 => this%hvars(ih_tveg24_si)%r81d, & hio_meanliqvol_si => this%hvars(ih_meanliqvol_si)%r81d, & hio_cbal_err_fates_si => this%hvars(ih_cbal_err_fates_si)%r81d, & @@ -2101,10 +2101,10 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_gdd_si(io_si) = sites(s)%grow_deg_days ! Model days elapsed since leaf on/off for cold- and drought-deciduous - hio_cleafoff_si(io_si) = real(model_day_int - sites(s)%cleafoffdate,r8) - hio_cleafon_si(io_si) = real(model_day_int - sites(s)%cleafondate,r8) - hio_dleafoff_si(io_si) = real(model_day_int - sites(s)%dleafoffdate,r8) - hio_dleafon_si(io_si) = real(model_day_int - sites(s)%dleafondate,r8) + hio_cleafoff_si(io_si) = real(sites(s)%phen_model_date - sites(s)%cleafoffdate,r8) + hio_cleafon_si(io_si) = real(sites(s)%phen_model_date - sites(s)%cleafondate,r8) + hio_dleafoff_si(io_si) = real(sites(s)%phen_model_date - sites(s)%dleafoffdate,r8) + hio_dleafon_si(io_si) = real(sites(s)%phen_model_date - sites(s)%dleafondate,r8) ! Mean liquid water content (m3/m3) used for drought phenology if(model_day_int>numWaterMem)then diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index c61c87fd4b..7de6fcb5aa 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -83,10 +83,11 @@ module FatesRestartInterfaceMod integer :: ir_dd_status_si integer :: ir_nchill_days_si integer :: ir_ncold_days_si - integer :: ir_leafondate_si - integer :: ir_leafoffdate_si + integer :: ir_cleafondate_si + integer :: ir_cleafoffdate_si integer :: ir_dleafondate_si integer :: ir_dleafoffdate_si + integer :: ir_phenmodeldate_si integer :: ir_acc_ni_si integer :: ir_gdd_si integer :: ir_snow_depth_si @@ -618,22 +619,26 @@ subroutine define_restart_vars(this, initialize_variables) long_name='cold day counter', units='unitless', flushval = flushinvalid, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_ncold_days_si ) - call this%set_restart_var(vname='fates_leafondate', vtype=site_int, & - long_name='the day of year for leaf on', units='day of year', flushval = flushinvalid, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_leafondate_si ) + call this%set_restart_var(vname='fates_cold_leafondate', vtype=site_int, & + long_name='the model day of last cold leaf on', units='absolute integer day', flushval = flushinvalid, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_cleafondate_si ) - call this%set_restart_var(vname='fates_leafoffdate', vtype=site_int, & - long_name='the day of year for leaf off', units='day of year', flushval = flushinvalid, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_leafoffdate_si ) + call this%set_restart_var(vname='fates_cold_leafoffdate', vtype=site_int, & + long_name='the model day last cold leaf off', units='absolute integer day', flushval = flushinvalid, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_cleafoffdate_si ) call this%set_restart_var(vname='fates_drought_leafondate', vtype=site_int, & - long_name='the day of year for drought based leaf-on', units='day of year', flushval = flushinvalid, & + long_name='the model day of last drought based leaf-on', units='absolute integer day', flushval = flushinvalid, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_dleafondate_si ) call this%set_restart_var(vname='fates_drought_leafoffdate', vtype=site_int, & - long_name='the day of year for drought based leaf-off', units='day of year', flushval = flushinvalid, & + long_name='the model day of last drought based leaf-off', units='absolute integer day', flushval = flushinvalid, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_dleafoffdate_si ) + call this%set_restart_var(vname='fates_phen_model_date', vtype=site_int, & + long_name='integer model day used for phen timing', units='absolute integer day', flushval = flushinvalid, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_phenmodeldate_si ) + call this%set_restart_var(vname='fates_acc_nesterov_id', vtype=site_r8, & long_name='a nesterov index accumulator', units='unitless', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_acc_ni_si ) @@ -1752,10 +1757,11 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_dd_status_si => this%rvars(ir_dd_status_si)%int1d, & rio_nchill_days_si => this%rvars(ir_nchill_days_si)%int1d, & rio_ncold_days_si => this%rvars(ir_ncold_days_si)%int1d, & - rio_leafondate_si => this%rvars(ir_leafondate_si)%int1d, & - rio_leafoffdate_si => this%rvars(ir_leafoffdate_si)%int1d, & + rio_cleafondate_si => this%rvars(ir_cleafondate_si)%int1d, & + rio_cleafoffdate_si => this%rvars(ir_cleafoffdate_si)%int1d, & rio_dleafondate_si => this%rvars(ir_dleafondate_si)%int1d, & rio_dleafoffdate_si => this%rvars(ir_dleafoffdate_si)%int1d, & + rio_phenmodeldate_si => this%rvars(ir_phenmodeldate_si)%int1d, & rio_acc_ni_si => this%rvars(ir_acc_ni_si)%r81d, & rio_gdd_si => this%rvars(ir_gdd_si)%r81d, & rio_snow_depth_si => this%rvars(ir_snow_depth_si)%r81d, & @@ -2244,9 +2250,9 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_dd_status_si(io_idx_si) = sites(s)%dstatus rio_nchill_days_si(io_idx_si) = sites(s)%nchilldays rio_ncold_days_si(io_idx_si) = sites(s)%ncolddays - rio_leafondate_si(io_idx_si) = sites(s)%cleafondate - rio_leafoffdate_si(io_idx_si) = sites(s)%cleafoffdate - + rio_cleafondate_si(io_idx_si) = sites(s)%cleafondate + rio_cleafoffdate_si(io_idx_si) = sites(s)%cleafoffdate + rio_phenmodeldate_si(io_idx_si)= sites(s)%phen_model_date rio_dleafondate_si(io_idx_si) = sites(s)%dleafondate rio_dleafoffdate_si(io_idx_si) = sites(s)%dleafoffdate rio_acc_ni_si(io_idx_si) = sites(s)%acc_NI @@ -2591,10 +2597,11 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_dd_status_si => this%rvars(ir_dd_status_si)%int1d, & rio_nchill_days_si => this%rvars(ir_nchill_days_si)%int1d, & rio_ncold_days_si => this%rvars(ir_ncold_days_si)%int1d, & - rio_leafondate_si => this%rvars(ir_leafondate_si)%int1d, & - rio_leafoffdate_si => this%rvars(ir_leafoffdate_si)%int1d, & + rio_cleafondate_si => this%rvars(ir_cleafondate_si)%int1d, & + rio_cleafoffdate_si => this%rvars(ir_cleafoffdate_si)%int1d, & rio_dleafondate_si => this%rvars(ir_dleafondate_si)%int1d, & rio_dleafoffdate_si => this%rvars(ir_dleafoffdate_si)%int1d, & + rio_phenmodeldate_si => this%rvars(ir_phenmodeldate_si)%int1d, & rio_acc_ni_si => this%rvars(ir_acc_ni_si)%r81d, & rio_gdd_si => this%rvars(ir_gdd_si)%r81d, & rio_snow_depth_si => this%rvars(ir_snow_depth_si)%r81d, & @@ -3109,14 +3116,14 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%dstatus = rio_dd_status_si(io_idx_si) sites(s)%nchilldays = rio_nchill_days_si(io_idx_si) sites(s)%ncolddays = rio_ncold_days_si(io_idx_si) - sites(s)%cleafondate = rio_leafondate_si(io_idx_si) - sites(s)%cleafoffdate = rio_leafoffdate_si(io_idx_si) + sites(s)%cleafondate = rio_cleafondate_si(io_idx_si) + sites(s)%cleafoffdate = rio_cleafoffdate_si(io_idx_si) sites(s)%dleafondate = rio_dleafondate_si(io_idx_si) sites(s)%dleafoffdate = rio_dleafoffdate_si(io_idx_si) sites(s)%acc_NI = rio_acc_ni_si(io_idx_si) sites(s)%grow_deg_days = rio_gdd_si(io_idx_si) + sites(s)%phen_model_date= rio_phenmodeldate_si(io_idx_si) sites(s)%snow_depth = rio_snow_depth_si(io_idx_si) - sites(s)%resources_management%trunk_product_site = rio_trunk_product_si(io_idx_si) end do From bed5e4052c61e4e35045dd3e9cffc628f1154843 Mon Sep 17 00:00:00 2001 From: Shijie Shu Date: Tue, 1 Nov 2022 11:30:49 -0700 Subject: [PATCH 407/852] Patch up some errors when merging with FATES API 24. --- biogeochem/EDLoggingMortalityMod.F90 | 18 +- biogeochem/EDMortalityFunctionsMod.F90 | 5 +- biogeochem/EDPatchDynamicsMod.F90 | 28 ++- main/EDMainMod.F90 | 20 +- main/EDTypesMod.F90 | 3 + main/FatesHistoryInterfaceMod.F90 | 277 +++++++++++++++++++++++-- main/FatesInterfaceTypesMod.F90 | 6 +- 7 files changed, 334 insertions(+), 23 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index cf920cd429..8145191bcc 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -14,6 +14,7 @@ module EDLoggingMortalityMod ! ==================================================================================== use FatesConstantsMod , only : r8 => fates_r8 + use FatesConstantsMod , only : rsnbl_math_prec use EDTypesMod , only : ed_cohort_type use EDTypesMod , only : ed_patch_type use EDTypesMod , only : site_massbal_type @@ -94,6 +95,8 @@ module EDLoggingMortalityMod public :: logging_time public :: IsItLoggingTime public :: get_harvest_rate_area + public :: get_harvestable_carbon + public :: get_harvest_rate_carbon public :: UpdateHarvestC contains @@ -194,7 +197,9 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & hlm_harvest_rates, hlm_harvest_catnames, & hlm_harvest_units, & patch_anthro_disturbance_label, secondary_age, & - frac_site_primary) + frac_site_primary, harvestable_forest_c, & + harvest_tag) + ! Arguments integer, intent(in) :: pft_i ! pft index @@ -205,6 +210,9 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & integer, intent(in) :: hlm_harvest_units ! unit type of hlm harvest rates: [area vs. mass] integer, intent(in) :: patch_anthro_disturbance_label ! patch level anthro_disturbance_label real(r8), intent(in) :: secondary_age ! patch level age_since_anthro_disturbance + real(r8), intent(in) :: harvestable_forest_c(:) ! total harvestable forest carbon + ! of all hlm harvest categories + real(r8), intent(in) :: frac_site_primary real(r8), intent(out) :: lmort_direct ! direct (harvestable) mortality fraction real(r8), intent(out) :: lmort_collateral ! collateral damage mortality fraction real(r8), intent(out) :: lmort_infra ! infrastructure mortality fraction @@ -212,9 +220,11 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & ! but suffer from forest degradation (i.e. they ! are moved to newly-anthro-disturbed secondary ! forest patch) - real(r8), intent(in) :: frac_site_primary + integer, intent(out) :: harvest_tag(:) ! tag to record the harvest status, 0 - successful; + ! 1 - unsuccessful since not enough carbon ! Local variables + integer :: cur_harvest_tag ! the harvest tag of the cohort today real(r8) :: harvest_rate ! the final harvest rate to apply to this cohort today ! todo: probably lower the dbhmin default value to 30 cm @@ -252,6 +262,10 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & call get_harvest_rate_area (patch_anthro_disturbance_label, hlm_harvest_catnames, & hlm_harvest_rates, frac_site_primary, secondary_age, harvest_rate) + ! For area-based harvest, harvest_tag shall always be 0. + harvest_tag = 0 + cur_harvest_tag = 0 + if (fates_global_verbose()) then write(fates_log(), *) 'Successfully Read Harvest Rate from HLM.' end if diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index 40dc0fb067..8f4009512b 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -214,7 +214,8 @@ end subroutine mortality_rates ! ============================================================================ - subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_primary) + subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_primary, & + harvestable_forest_c, harvest_tag) ! ! !DESCRIPTION: @@ -262,7 +263,7 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_pr bc_in%hlm_harvest_units, & currentCohort%patchptr%anthro_disturbance_label, & currentCohort%patchptr%age_since_anthro_disturbance, & - frac_site_primary) + frac_site_primary, harvestable_forest_c, harvest_tag) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 022bed4ac6..95aaefa763 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -48,6 +48,7 @@ module EDPatchDynamicsMod use FatesInterfaceTypesMod , only : hlm_use_sp use FatesInterfaceTypesMod , only : hlm_use_nocomp use FatesInterfaceTypesMod , only : hlm_use_fixed_biogeog + use FatesInterfaceTypesMod , only : hlm_num_lu_harvest_cats use FatesGlobals , only : endrun => fates_endrun use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : itrue, ifalse @@ -58,6 +59,8 @@ module EDPatchDynamicsMod use EDLoggingMortalityMod, only : logging_litter_fluxes use EDLoggingMortalityMod, only : logging_time use EDLoggingMortalityMod, only : get_harvest_rate_area + use EDLoggingMortalityMod, only : get_harvest_rate_carbon + use EDLoggingMortalityMod, only : get_harvestable_carbon use EDParamsMod , only : fates_mortality_disturbance_fraction use FatesAllometryMod , only : carea_allom use FatesAllometryMod , only : set_root_fraction @@ -70,6 +73,7 @@ module EDPatchDynamicsMod use FatesConstantsMod , only : n_anthro_disturbance_categories use FatesConstantsMod , only : fates_unset_r8 use FatesConstantsMod , only : fates_unset_int + use FatesConstantsMod , only : hlm_harvest_carbon use EDCohortDynamicsMod , only : InitPRTObject use EDCohortDynamicsMod , only : InitPRTBoundaryConditions use ChecksBalancesMod, only : SiteMassStock @@ -186,9 +190,15 @@ subroutine disturbance_rates( site_in, bc_in) real(r8) :: dist_rate_ldist_notharvested integer :: threshold_sizeclass integer :: i_dist + integer :: h_index real(r8) :: frac_site_primary real(r8) :: harvest_rate real(r8) :: tempsum + real(r8) :: harvestable_forest_c(hlm_num_lu_harvest_cats) + integer :: harvest_tag(hlm_num_lu_harvest_cats) + integer :: harvest_debt_primary + integer :: harvest_debt_secondary + integer :: patch_no_secondary !---------------------------------------------------------------------------------------------- ! Calculate Mortality Rates (these were previously calculated during growth derivatives) @@ -197,6 +207,10 @@ subroutine disturbance_rates( site_in, bc_in) ! first calculate the fractino of the site that is primary land call get_frac_site_primary(site_in, frac_site_primary) + + ! get available biomass for harvest for all patches + call get_harvestable_carbon(site_in, bc_in%site_area, bc_in%hlm_harvest_catnames, harvestable_forest_c) + harvest_debt_primary = 0 harvest_debt_secondary = 0 @@ -230,7 +244,9 @@ subroutine disturbance_rates( site_in, bc_in) bc_in%hlm_harvest_units, & currentPatch%anthro_disturbance_label, & currentPatch%age_since_anthro_disturbance, & - frac_site_primary) + frac_site_primary, & + harvestable_forest_c, & + harvest_tag) currentCohort%lmort_direct = lmort_direct currentCohort%lmort_collateral = lmort_collateral @@ -371,8 +387,14 @@ subroutine disturbance_rates( site_in, bc_in) (currentPatch%area - currentPatch%total_canopy_area) .gt. fates_tiny ) then ! The canopy is NOT closed. - call get_harvest_rate_area (currentPatch%anthro_disturbance_label, bc_in%hlm_harvest_catnames, & - bc_in%hlm_harvest_rates, frac_site_primary, currentPatch%age_since_anthro_disturbance, harvest_rate) + if(bc_in%hlm_harvest_units == hlm_harvest_carbon) then + call get_harvest_rate_carbon (currentPatch%anthro_disturbance_label, bc_in%hlm_harvest_catnames, & + bc_in%hlm_harvest_rates, currentPatch%age_since_anthro_disturbance, harvestable_forest_c, & + harvest_rate, harvest_tag) + else + call get_harvest_rate_area (currentPatch%anthro_disturbance_label, bc_in%hlm_harvest_catnames, & + bc_in%hlm_harvest_rates, frac_site_primary, currentPatch%age_since_anthro_disturbance, harvest_rate) + end if currentPatch%disturbance_rates(dtype_ilog) = currentPatch%disturbance_rates(dtype_ilog) + & (currentPatch%area - currentPatch%total_canopy_area) * harvest_rate / currentPatch%area diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 7b9d623413..aa2670f534 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -80,6 +80,7 @@ module EDMainMod use FatesPlantHydraulicsMod , only : AccumulateMortalityWaterStorage use FatesAllometryMod , only : h_allom,tree_sai,tree_lai use EDLoggingMortalityMod , only : IsItLoggingTime + use EDLoggingMortalityMod , only : get_harvestable_carbon use EDPatchDynamicsMod , only : get_frac_site_primary use FatesGlobals , only : endrun => fates_endrun use ChecksBalancesMod , only : SiteMassStock @@ -303,6 +304,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! FIX(SPM,032414) refactor so everything goes through interface ! ! !USES: + use FatesInterfaceTypesMod, only : hlm_num_lu_harvest_cats use FatesInterfaceTypesMod, only : hlm_use_cohort_age_tracking use FatesConstantsMod, only : itrue ! !ARGUMENTS: @@ -333,9 +335,19 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) !----------------------------------------------------------------------- real(r8) :: frac_site_primary + real(r8) :: harvestable_forest_c(hlm_num_lu_harvest_cats) + integer :: harvest_tag(hlm_num_lu_harvest_cats) + call get_frac_site_primary(currentSite, frac_site_primary) + ! Clear site GPP and AR passing to HLM + bc_out%gpp_site = 0._r8 + bc_out%ar_site = 0._r8 + + ! Patch level biomass are required for C-based harvest + call get_harvestable_carbon(currentSite, bc_in%site_area, bc_in%hlm_harvest_catnames, harvestable_forest_c) + ! Set a pointer to this sites carbon12 mass balance site_cmass => currentSite%mass_balance(element_pos(carbon12_element)) @@ -369,7 +381,8 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ft = currentCohort%pft ! Calculate the mortality derivatives - call Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_primary ) + call Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_primary, & + harvestable_forest_c, harvest_tag) ! ----------------------------------------------------------------------------- ! Apply Plant Allocation and Reactive Transport @@ -413,6 +426,11 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentCohort%gpp_acc_hold = currentCohort%gpp_acc * real(hlm_days_per_year,r8) currentCohort%resp_acc_hold = currentCohort%resp_acc * real(hlm_days_per_year,r8) + ! Passing gpp_acc_hold to HLM + bc_out%gpp_site = bc_out%gpp_site + currentCohort%gpp_acc_hold * & + AREA_INV * currentCohort%n / hlm_days_per_year / sec_per_day + bc_out%ar_site = bc_out%ar_site + currentCohort%resp_acc_hold * & + AREA_INV * currentCohort%n / hlm_days_per_year / sec_per_day ! Conduct Maintenance Turnover (parteh) if(debug) call currentCohort%prt%CheckMassConservation(ft,3) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 6f3bf6ee52..df2a75b44b 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -585,6 +585,9 @@ module EDTypesMod type, public :: ed_resources_management_type real(r8) :: trunk_product_site ! Actual trunk product at site level KgC/site + real(r8) :: harvest_debt ! the amount of kgC per site that did not successfully harvested + real(r8) :: harvest_debt_sec ! the amount of kgC per site from secondary patches that did + ! not successfully harvested !debug variables real(r8) :: delta_litter_stock ! kgC/site = kgC/ha diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 829a683ecd..8b8fb053e1 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -276,6 +276,12 @@ module FatesHistoryInterfaceMod integer :: ih_canopy_biomass_si integer :: ih_understory_biomass_si + integer :: ih_npp_secondary_si + integer :: ih_gpp_secondary_si + integer :: ih_aresp_secondary_si + integer :: ih_maint_resp_secondary_si + integer :: ih_growth_resp_secondary_si + integer :: ih_primaryland_fusion_error_si integer :: ih_disturbance_rate_p2p_si integer :: ih_disturbance_rate_p2s_si @@ -285,6 +291,8 @@ module FatesHistoryInterfaceMod integer :: ih_fall_disturbance_rate_si integer :: ih_potential_disturbance_rate_si integer :: ih_harvest_carbonflux_si + integer :: ih_harvest_debt_si + integer :: ih_harvest_debt_sec_si ! Indices to site by size-class by age variables integer :: ih_nplant_si_scag @@ -305,7 +313,7 @@ module FatesHistoryInterfaceMod ! Indices to (site) variables integer :: ih_tveg24_si - integer :: ih_tveg_si + !integer :: ih_tveg_si integer :: ih_nep_si integer :: ih_hr_si @@ -320,7 +328,9 @@ module FatesHistoryInterfaceMod integer :: ih_err_fates_si integer :: ih_npatches_si + integer :: ih_npatches_sec_si integer :: ih_ncohorts_si + integer :: ih_ncohorts_sec_si integer :: ih_demotion_carbonflux_si integer :: ih_promotion_carbonflux_si integer :: ih_canopy_mortality_carbonflux_si @@ -448,6 +458,7 @@ module FatesHistoryInterfaceMod integer :: ih_ddbh_understory_si_scls integer :: ih_agb_si_scls integer :: ih_biomass_si_scls + integer :: ih_mortality_canopy_secondary_si_scls ! mortality vars integer :: ih_m1_si_scls @@ -461,6 +472,14 @@ module FatesHistoryInterfaceMod integer :: ih_m9_si_scls integer :: ih_m10_si_scls + integer :: ih_m1_sec_si_scls + integer :: ih_m2_sec_si_scls + integer :: ih_m3_sec_si_scls + integer :: ih_m7_sec_si_scls + integer :: ih_m8_sec_si_scls + integer :: ih_m9_sec_si_scls + integer :: ih_m10_sec_si_scls + integer :: ih_m10_si_cacls integer :: ih_nplant_si_cacls @@ -510,9 +529,11 @@ module FatesHistoryInterfaceMod ! indices to (site x pft) variables integer :: ih_biomass_si_pft + integer :: ih_biomass_sec_si_pft integer :: ih_leafbiomass_si_pft integer :: ih_storebiomass_si_pft integer :: ih_nindivs_si_pft + integer :: ih_nindivs_sec_si_pft integer :: ih_recruitment_si_pft integer :: ih_mortality_si_pft integer :: ih_mortality_carbonflux_si_pft @@ -522,7 +543,9 @@ module FatesHistoryInterfaceMod integer :: ih_crownarea_si_pft integer :: ih_canopycrownarea_si_pft integer :: ih_gpp_si_pft + integer :: ih_gpp_sec_si_pft integer :: ih_npp_si_pft + integer :: ih_npp_sec_si_pft integer :: ih_nocomp_pftpatchfraction_si_pft integer :: ih_nocomp_pftnpatches_si_pft integer :: ih_nocomp_pftburnedarea_si_pft @@ -546,6 +569,8 @@ module FatesHistoryInterfaceMod integer :: ih_fire_intensity_si_age integer :: ih_fire_sum_fuel_si_age + integer :: ih_lai_secondary_si + ! indices to (site x height) variables integer :: ih_canopy_height_dist_si_height integer :: ih_leaf_height_dist_si_height @@ -1802,16 +1827,20 @@ subroutine update_history_dyn(this,nc,nsites,sites) integer :: tmp associate( hio_npatches_si => this%hvars(ih_npatches_si)%r81d, & + hio_npatches_sec_si => this%hvars(ih_npatches_sec_si)%r81d, & hio_ncohorts_si => this%hvars(ih_ncohorts_si)%r81d, & + hio_ncohorts_sec_si => this%hvars(ih_ncohorts_sec_si)%r81d, & hio_trimming_si => this%hvars(ih_trimming_si)%r81d, & hio_area_plant_si => this%hvars(ih_area_plant_si)%r81d, & hio_area_trees_si => this%hvars(ih_area_trees_si)%r81d, & hio_fates_fraction_si => this%hvars(ih_fates_fraction_si)%r81d, & hio_canopy_spread_si => this%hvars(ih_canopy_spread_si)%r81d, & hio_biomass_si_pft => this%hvars(ih_biomass_si_pft)%r82d, & + hio_biomass_sec_si_pft => this%hvars(ih_biomass_sec_si_pft)%r82d, & hio_leafbiomass_si_pft => this%hvars(ih_leafbiomass_si_pft)%r82d, & hio_storebiomass_si_pft => this%hvars(ih_storebiomass_si_pft)%r82d, & hio_nindivs_si_pft => this%hvars(ih_nindivs_si_pft)%r82d, & + hio_nindivs_sec_si_pft => this%hvars(ih_nindivs_sec_si_pft)%r82d, & hio_recruitment_si_pft => this%hvars(ih_recruitment_si_pft)%r82d, & hio_mortality_si_pft => this%hvars(ih_mortality_si_pft)%r82d, & hio_mortality_carbonflux_si_pft => this%hvars(ih_mortality_carbonflux_si_pft)%r82d, & @@ -1821,7 +1850,9 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_crownarea_si_pft => this%hvars(ih_crownarea_si_pft)%r82d, & hio_canopycrownarea_si_pft => this%hvars(ih_canopycrownarea_si_pft)%r82d, & hio_gpp_si_pft => this%hvars(ih_gpp_si_pft)%r82d, & + hio_gpp_sec_si_pft => this%hvars(ih_gpp_sec_si_pft)%r82d, & hio_npp_si_pft => this%hvars(ih_npp_si_pft)%r82d, & + hio_npp_sec_si_pft => this%hvars(ih_npp_sec_si_pft)%r82d, & hio_nesterov_fire_danger_si => this%hvars(ih_nesterov_fire_danger_si)%r81d, & hio_fire_nignitions_si => this%hvars(ih_fire_nignitions_si)%r81d, & hio_fire_fdi_si => this%hvars(ih_fire_fdi_si)%r81d, & @@ -1862,6 +1893,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_fall_disturbance_rate_si => this%hvars(ih_fall_disturbance_rate_si)%r81d, & hio_potential_disturbance_rate_si => this%hvars(ih_potential_disturbance_rate_si)%r81d, & hio_harvest_carbonflux_si => this%hvars(ih_harvest_carbonflux_si)%r81d, & + hio_harvest_debt_si => this%hvars(ih_harvest_debt_si)%r81d, & + hio_harvest_debt_sec_si => this%hvars(ih_harvest_debt_sec_si)%r81d, & hio_gpp_si_scpf => this%hvars(ih_gpp_si_scpf)%r82d, & hio_npp_totl_si_scpf => this%hvars(ih_npp_totl_si_scpf)%r82d, & hio_npp_leaf_si_scpf => this%hvars(ih_npp_leaf_si_scpf)%r82d, & @@ -1885,6 +1918,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_lai_canopy_si_scpf => this%hvars(ih_lai_canopy_si_scpf)%r82d, & hio_lai_understory_si_scpf => this%hvars(ih_lai_understory_si_scpf)%r82d, & hio_mortality_canopy_si_scpf => this%hvars(ih_mortality_canopy_si_scpf)%r82d, & + hio_mortality_canopy_secondary_si_scls => this%hvars(ih_mortality_canopy_secondary_si_scls)%r82d, & hio_mortality_understory_si_scpf => this%hvars(ih_mortality_understory_si_scpf)%r82d, & hio_nplant_canopy_si_scpf => this%hvars(ih_nplant_canopy_si_scpf)%r82d, & hio_nplant_understory_si_scpf => this%hvars(ih_nplant_understory_si_scpf)%r82d, & @@ -1934,6 +1968,14 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_m10_si_scls => this%hvars(ih_m10_si_scls)%r82d, & hio_m10_si_cacls => this%hvars(ih_m10_si_cacls)%r82d, & + hio_m1_sec_si_scls => this%hvars(ih_m1_sec_si_scls)%r82d, & + hio_m2_sec_si_scls => this%hvars(ih_m2_sec_si_scls)%r82d, & + hio_m3_sec_si_scls => this%hvars(ih_m3_sec_si_scls)%r82d, & + hio_m7_sec_si_scls => this%hvars(ih_m7_sec_si_scls)%r82d, & + hio_m8_sec_si_scls => this%hvars(ih_m8_sec_si_scls)%r82d, & + hio_m9_sec_si_scls => this%hvars(ih_m9_sec_si_scls)%r82d, & + hio_m10_sec_si_scls => this%hvars(ih_m10_sec_si_scls)%r82d, & + hio_c13disc_si_scpf => this%hvars(ih_c13disc_si_scpf)%r82d, & hio_cwd_elcwd => this%hvars(ih_cwd_elcwd)%r82d, & @@ -1998,6 +2040,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_yesterdaycanopylevel_understory_si_scls => this%hvars(ih_yesterdaycanopylevel_understory_si_scls)%r82d, & hio_area_si_age => this%hvars(ih_area_si_age)%r82d, & hio_lai_si_age => this%hvars(ih_lai_si_age)%r82d, & + hio_lai_secondary_si => this%hvars(ih_lai_secondary_si)%r81d, & hio_canopy_area_si_age => this%hvars(ih_canopy_area_si_age)%r82d, & hio_ncl_si_age => this%hvars(ih_ncl_si_age)%r82d, & hio_npatches_si_age => this%hvars(ih_npatches_si_age)%r82d, & @@ -2172,6 +2215,9 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! Increment the number of patches per site hio_npatches_si(io_si) = hio_npatches_si(io_si) + 1._r8 + if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + hio_npatches_sec_si(io_si) = hio_npatches_sec_si(io_si) + 1._r8 + end if cpatch%age_class = get_age_class_index(cpatch%age) @@ -2283,6 +2329,10 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! Increment the number of cohorts per site hio_ncohorts_si(io_si) = hio_ncohorts_si(io_si) + 1._r8 + if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + hio_ncohorts_sec_si(io_si) = hio_ncohorts_sec_si(io_si) + 1._r8 + end if + n_perm2 = ccohort%n * AREA_INV hio_canopy_area_si_age(io_si,cpatch%age_class) = hio_canopy_area_si_age(io_si,cpatch%age_class) & @@ -2375,9 +2425,19 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_nindivs_si_pft(io_si,ft) = hio_nindivs_si_pft(io_si,ft) + & ccohort%n * AREA_INV + if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + hio_nindivs_sec_si_pft(io_si,ft) = hio_nindivs_sec_si_pft(io_si,ft) + & + ccohort%n * AREA_INV + end if + hio_biomass_si_pft(io_si, ft) = hio_biomass_si_pft(io_si, ft) + & (ccohort%n * AREA_INV) * total_m + if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + hio_biomass_sec_si_pft(io_si, ft) = hio_biomass_sec_si_pft(io_si, ft) + & + (ccohort%n * AREA_INV) * total_m + end if + ! update total biomass per age bin hio_biomass_si_age(io_si,cpatch%age_class) = hio_biomass_si_age(io_si,cpatch%age_class) & + total_m * ccohort%n * AREA_INV @@ -2460,6 +2520,13 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_npp_si_pft(io_si, ft) = hio_npp_si_pft(io_si, ft) + & ccohort%npp_acc_hold * n_perm2 / days_per_year / sec_per_day + if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + hio_gpp_sec_si_pft(io_si, ft) = hio_gpp_sec_si_pft(io_si, ft) + & + ccohort%gpp_acc_hold * n_perm2 / days_per_year / sec_per_day + hio_npp_sec_si_pft(io_si, ft) = hio_npp_sec_si_pft(io_si, ft) + & + ccohort%npp_acc_hold * n_perm2 / days_per_year / sec_per_day + end if + ! Site by Size-Class x PFT (SCPF) ! ------------------------------------------------------------------------ @@ -2592,7 +2659,24 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_m8_si_scls(io_si,scls) = hio_m8_si_scls(io_si,scls) + & ccohort%frmort*ccohort%n / m2_per_ha hio_m9_si_scls(io_si,scls) = hio_m9_si_scls(io_si,scls) + ccohort%smort*ccohort%n / m2_per_ha + ! Examine secondary forest mortality and mortality rates + if(cpatch%anthro_disturbance_label .eq. secondaryforest) then + + if (hlm_use_cohort_age_tracking .eq.itrue) then + hio_m10_sec_si_scls(io_si,scls) = hio_m10_sec_si_scls(io_si,scls) + & + ccohort%asmort*ccohort%n / m2_per_ha + end if + + hio_m1_sec_si_scls(io_si,scls) = hio_m1_sec_si_scls(io_si,scls) + ccohort%bmort*ccohort%n / m2_per_ha + hio_m2_sec_si_scls(io_si,scls) = hio_m2_sec_si_scls(io_si,scls) + ccohort%hmort*ccohort%n / m2_per_ha + hio_m3_sec_si_scls(io_si,scls) = hio_m3_sec_si_scls(io_si,scls) + ccohort%cmort*ccohort%n / m2_per_ha + hio_m7_sec_si_scls(io_si,scls) = hio_m7_sec_si_scls(io_si,scls) + & + (ccohort%lmort_direct+ccohort%lmort_collateral+ccohort%lmort_infra) * ccohort%n / m2_per_ha + hio_m8_sec_si_scls(io_si,scls) = hio_m8_sec_si_scls(io_si,scls) + & + ccohort%frmort*ccohort%n / m2_per_ha + hio_m9_sec_si_scls(io_si,scls) = hio_m9_sec_si_scls(io_si,scls) + ccohort%smort*ccohort%n / m2_per_ha + end if !C13 discrimination if(gpp_cached + ccohort%gpp_acc_hold > 0.0_r8)then @@ -2787,6 +2871,15 @@ subroutine update_history_dyn(this,nc,nsites,sites) (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & ccohort%n * sec_per_day * days_per_year / m2_per_ha + if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + hio_mortality_canopy_secondary_si_scls(io_si,scls) = hio_mortality_canopy_secondary_si_scls(io_si,scls) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort) * ccohort%n / m2_per_ha + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & + ccohort%n * sec_per_day * days_per_year / m2_per_ha + end if + + hio_nplant_understory_si_scpf(io_si,scpf) = hio_nplant_understory_si_scpf(io_si,scpf) + ccohort%n / m2_per_ha hio_nplant_understory_si_scls(io_si,scls) = hio_nplant_understory_si_scls(io_si,scls) + ccohort%n / m2_per_ha hio_lai_understory_si_scls(io_si,scls) = hio_lai_understory_si_scls(io_si,scls) + & @@ -3566,10 +3659,15 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) real(r8) :: per_dt_tstep ! Time step in frequency units (/s) associate( hio_gpp_si => this%hvars(ih_gpp_si)%r81d, & + hio_gpp_secondary_si => this%hvars(ih_gpp_secondary_si)%r81d, & hio_npp_si => this%hvars(ih_npp_si)%r81d, & + hio_npp_secondary_si => this%hvars(ih_npp_secondary_si)%r81d, & hio_aresp_si => this%hvars(ih_aresp_si)%r81d, & + hio_aresp_secondary_si => this%hvars(ih_aresp_secondary_si)%r81d, & hio_maint_resp_si => this%hvars(ih_maint_resp_si)%r81d, & + hio_maint_resp_secondary_si => this%hvars(ih_maint_resp_secondary_si)%r81d, & hio_growth_resp_si => this%hvars(ih_growth_resp_si)%r81d, & + hio_growth_resp_secondary_si => this%hvars(ih_growth_resp_secondary_si)%r81d, & hio_c_stomata_si => this%hvars(ih_c_stomata_si)%r81d, & hio_c_lblayer_si => this%hvars(ih_c_lblayer_si)%r81d, & hio_rad_error_si => this%hvars(ih_rad_error_si)%r81d, & @@ -3634,8 +3732,8 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) hio_fabi_sun_top_si_can => this%hvars(ih_fabi_sun_top_si_can)%r82d, & hio_fabi_sha_top_si_can => this%hvars(ih_fabi_sha_top_si_can)%r82d, & hio_parsun_top_si_can => this%hvars(ih_parsun_top_si_can)%r82d, & - hio_parsha_top_si_can => this%hvars(ih_parsha_top_si_can)%r82d, & - hio_tveg => this%hvars(ih_tveg_si)%r81d) + hio_parsha_top_si_can => this%hvars(ih_parsha_top_si_can)%r82d)!, & + !hio_tveg => this%hvars(ih_tveg_si)%r81d) ! Flush the relevant history variables call this%flush_hvars(nc,upfreq_in=2) @@ -3690,12 +3788,12 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) hio_rad_error_si(io_si) = hio_rad_error_si(io_si) + & cpatch%radiation_error * cpatch%area * AREA_INV - ! Only accumulate the instantaneous vegetation temperature for vegetated patches - if (cpatch%patchno .ne. 0) then - hio_tveg(io_si) = hio_tveg(io_si) + & - (bc_in(s)%t_veg_pa(cpatch%patchno) - t_water_freeze_k_1atm) * & - cpatch%area / site_area_veg - end if + ! ! Only accumulate the instantaneous vegetation temperature for vegetated patches + ! if (cpatch%patchno .ne. 0) then + ! hio_tveg(io_si) = hio_tveg(io_si) + & + ! (bc_in(s)%t_veg_pa(cpatch%patchno) - t_water_freeze_k_1atm) * & + ! cpatch%area / site_area_veg + ! end if ccohort => cpatch%shortest do while(associated(ccohort)) @@ -3725,6 +3823,21 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) hio_maint_resp_si(io_si) = hio_maint_resp_si(io_si) + & ccohort%resp_m * n_perm2 * per_dt_tstep + ! Secondary forest only + if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + hio_npp_secondary_si(io_si) = hio_npp_secondary_si(io_si) + & + npp * n_perm2 * per_dt_tstep + hio_gpp_secondary_si(io_si) = hio_gpp_secondary_si(io_si) + & + ccohort%gpp_tstep * n_perm2 * per_dt_tstep + hio_aresp_secondary_si(io_si) = hio_aresp_secondary_si(io_si) + & + aresp * n_perm2 * per_dt_tstep + hio_growth_resp_secondary_si(io_si) = hio_growth_resp_secondary_si(io_si) + & + resp_g * n_perm2 * per_dt_tstep + hio_maint_resp_secondary_si(io_si) = hio_maint_resp_secondary_si(io_si) + & + ccohort%resp_m * n_perm2 * per_dt_tstep + end if + + ! Add up the total Net Ecosystem Production ! for this timestep. [kgC/m2/s] hio_nep_si(io_si) = hio_nep_si(io_si) + & @@ -4448,6 +4561,18 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_ncohorts_si) + call this%set_history_var(vname='FATES_NPATCHES_SECONDARY', units='', & + long='total number of patches per site', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_npatches_sec_si) + + call this%set_history_var(vname='FATES_NCOHORTS_SECONDARY', units='', & + long='total number of cohorts per site', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_ncohorts_sec_si) + ! Patch variables call this%set_history_var(vname='FATES_TRIMMING', units='1', & long='degree to which canopy expansion is limited by leaf economics (0-1)', & @@ -4546,6 +4671,12 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_biomass_si_pft) + call this%set_history_var(vname='FATES_VEGC_SE_PF', units='kg m-2', & + long='total PFT-level biomass in kg of carbon per land area, secondary patches', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_biomass_sec_si_pft) + call this%set_history_var(vname='FATES_LEAFC_PF', units='kg m-2', & long='total PFT-level leaf biomass in kg carbon per m2 land area', & use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & @@ -4582,12 +4713,30 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_npp_si_pft) + call this%set_history_var(vname='FATES_GPP_SE_PF', units='kg m-2 s-1', & + long='total PFT-level GPP in kg carbon per m2 land area per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_gpp_sec_si_pft) + + call this%set_history_var(vname='FATES_NPP_SE_PF', units='kg m-2 yr-1', & + long='total PFT-level NPP in kg carbon per m2 land area per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_npp_sec_si_pft) + call this%set_history_var(vname='FATES_NPLANT_PF', units='m-2', & long='total PFT-level number of individuals per m2 land area', & use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_nindivs_si_pft) + call this%set_history_var(vname='FATES_NPLANT_SEC_PF', units='m-2', & + long='total PFT-level number of individuals per m2 land area, secondary patches', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_nindivs_sec_si_pft) + call this%set_history_var(vname='FATES_RECRUITMENT_PF', & units='m-2 yr-1', & long='PFT-level recruitment rate in number of individuals per m2 land area per year', & @@ -4633,6 +4782,12 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_lai_si_age) + call this%set_history_var(vname='FATES_LAI_SECONDARY', units='m2 m-2', & + long='leaf area index per m2 land area, secondary patches', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_lai_secondary_si) + call this%set_history_var(vname='FATES_CANOPYAREA_AP', units='m2 m-2', & long='canopy area by age bin per m2 land area', use_default='active', & avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & @@ -5205,11 +5360,11 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_tveg24_si ) - call this%set_history_var(vname='FATES_TVEG', units='degree_Celsius', & - long='fates instantaneous mean vegetation temperature by site', & - use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_tveg_si ) + ! call this%set_history_var(vname='FATES_TVEG', units='degree_Celsius', & + ! long='fates instantaneous mean vegetation temperature by site', & + ! use_default='active', & + ! avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & + ! ivar=ivar, initialize=initialize_variables, index = ih_tveg_si ) ! radiation error @@ -5218,6 +5373,17 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & ivar=ivar, initialize=initialize_variables, index = ih_rad_error_si) + call this%set_history_var(vname='FATES_HARVEST_DEBT', units='kg C', & + long='Accumulated carbon failed to be harvested', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_harvest_debt_si ) + + call this%set_history_var(vname='FATES_HARVEST_DEBT_SEC', units='kg C', & + long='Accumulated carbon failed to be harvested from secondary patches', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_harvest_debt_sec_si ) + + ! Ecosystem Carbon Fluxes (updated rapidly, upfreq=2) @@ -5226,28 +5392,55 @@ subroutine define_history_vars(this, initialize_variables) use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_npp_si) + call this%set_history_var(vname='FATES_NPP_SECONDARY', units='kg m-2 s-1', & + long='net primary production in kg carbon per m2 per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_npp_secondary_si) + call this%set_history_var(vname='FATES_GPP', units='kg m-2 s-1', & long='gross primary production in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_gpp_si) + call this%set_history_var(vname='FATES_GPP_SECONDARY', units='kg m-2 s-1', & + long='gross primary production in kg carbon per m2 per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_gpp_secondary_si) + call this%set_history_var(vname='FATES_AUTORESP', units='kg m-2 s-1', & long='autotrophic respiration in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_aresp_si) + call this%set_history_var(vname='FATES_AUTORESP_SECONDARY', units='kg m-2 s-1', & + long='autotrophic respiration in kg carbon per m2 per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_aresp_secondary_si) + call this%set_history_var(vname='FATES_GROWTH_RESP', units='kg m-2 s-1', & long='growth respiration in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=2, ivar=ivar, initialize=initialize_variables, & index = ih_growth_resp_si) + call this%set_history_var(vname='FATES_GROWTH_RESP_SECONDARY', units='kg m-2 s-1', & + long='growth respiration in kg carbon per m2 per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, & + index = ih_growth_resp_secondary_si) + call this%set_history_var(vname='FATES_MAINT_RESP', units='kg m-2 s-1', & long='maintenance respiration in kg carbon per m2 land area per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=2, ivar=ivar, initialize=initialize_variables, & index = ih_maint_resp_si) + call this%set_history_var(vname='FATES_MAINT_RESP_SECONDARY', units='kg m-2 s-1', & + long='maintenance respiration in kg carbon per m2 land area per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, & + index = ih_maint_resp_secondary_si) + ! Canopy resistance call this%set_history_var(vname='FATES_STOMATAL_COND_AP', & @@ -6127,6 +6320,13 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index = ih_mortality_canopy_si_scls) + call this%set_history_var(vname='FATES_MORTALITY_CANOPY_SE_SZ', & + units = 'm-2 yr-1', & + long='total mortality of canopy trees by size class in number of plants per m2, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_mortality_canopy_secondary_si_scls) + call this%set_history_var(vname='FATES_NPLANT_USTORY_SZ', & units = 'm-2', & long='number of understory plants per m2 by size class', & @@ -6180,6 +6380,27 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index = ih_m3_si_scls) + call this%set_history_var(vname='FATES_MORTALITY_BACKGROUND_SE_SZ', & + units = 'm-2 yr-1', & + long='background mortality by size in number of plants per m2 per year, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m1_sec_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_HYDRAULIC_SE_SZ', & + units = 'm-2 yr-1', & + long='hydraulic mortality by size in number of plants per m2 per year, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m2_sec_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_CSTARV_SE_SZ', & + units = 'm-2 yr-1', & + long='carbon starvation mortality by size in number of plants per m2 per year, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m3_sec_si_scls) + call this%set_history_var(vname='FATES_MORTALITY_IMPACT_SZ', & units = 'm-2 yr-1', & long='impact mortality by size in number of plants per m2 per year', & @@ -6236,6 +6457,34 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index = ih_m10_si_cacls) + call this%set_history_var(vname='FATES_MORTALITY_LOGGING_SE_SZ', & + units = 'm-2 yr-1', & + long='logging mortality by size in number of plants per m2 per event, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m7_sec_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_FREEZING_SE_SZ', & + units = 'm-2 event-1', & + long='freezing mortality by size in number of plants per m2 per event, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m8_sec_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_SENESCENCE_SE_SZ', & + units = 'm-2 yr-1', & + long='senescence mortality by size in number of plants per m2 per event, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m9_sec_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_AGESCEN_SE_SZ', & + units = 'm-2 yr-1', & + long='age senescence mortality by size in number of plants per m2 per year, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m10_sec_si_scls) + call this%set_history_var(vname='FATES_NPP_CANOPY_SZ', units = 'kg m-2 s-1', & long='NPP of canopy plants by size class in kg carbon per m2 per second', & use_default='inactive', avgflag='A', vtype=site_size_r8, & diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index f08fba4ce8..0b6eda45c8 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -532,6 +532,8 @@ module FatesInterfaceTypesMod integer :: hlm_harvest_units ! what units are the harvest rates specified in? [area vs carbon] + real(r8) :: site_area ! Actual area of current site [m2], only used in carbon-based harvest + ! Fixed biogeography mode real(r8), allocatable :: pft_areafrac(:) ! Fractional area of the FATES column occupied by each PFT @@ -725,7 +727,9 @@ module FatesInterfaceTypesMod ! FATES LULCC real(r8) :: hrv_deadstemc_to_prod10c ! Harvested C flux to 10-yr wood product pool [Site-Level, gC m-2 s-1] real(r8) :: hrv_deadstemc_to_prod100c ! Harvested C flux to 100-yr wood product pool [Site-Level, gC m-2 s-1] - + real(r8) :: gpp_site ! Site level GPP, for NBP diagnosis in HLM [Site-Level, gC m-2 s-1] + real(r8) :: ar_site ! Site level Autotrophic Resp, for NBP diagnosis in HLM [Site-Level, gC m-2 s-1] + end type bc_out_type From b907af73f1987d7ce551d765de51ca6bd14ccaf1 Mon Sep 17 00:00:00 2001 From: ckoven Date: Tue, 1 Nov 2022 16:28:04 -0600 Subject: [PATCH 408/852] starting to add hooks for multiple leaf maintenance respiration models --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 100 ++++++++++++++++++--- main/EDParamsMod.F90 | 2 +- main/FatesConstantsMod.F90 | 4 + 3 files changed, 94 insertions(+), 12 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 4b8d34f664..c43ed0cbcb 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -40,6 +40,10 @@ module FATESPlantRespPhotosynthMod use PRTGenericMod, only : max_nleafage use EDTypesMod, only : do_fates_salinity use EDParamsMod, only : q10_mr + use EDParamsMod, only : maintresp_model + use FatesConstantsMod, only : lmrmodel_ryan_1991 + use FatesConstantsMod, only : lmrmodel_atkin_etal_2015 + use FatesConstantsMod, only : lmrmodel_heskel_etal_2018 use PRTGenericMod, only : prt_carbon_allom_hyp use PRTGenericMod, only : prt_cnp_flex_allom_hyp use PRTGenericMod, only : all_carbon_elements @@ -520,17 +524,40 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) end select - ! MLO - Shouldn't these numbers be parameters too? - lmr25top = 2.525e-6_r8 * (1.5_r8 ** ((25._r8 - 20._r8)/10._r8)) - lmr25top = lmr25top * lnc_top / (umolC_to_kgC * g_per_kg) + ! Part VII: Calculate dark respiration (leaf maintenance) for this layer + select case (maintresp_model) + case (lmrmodel_ryan_1991) - ! Part VII: Calculate dark respiration (leaf maintenance) for this layer - call LeafLayerMaintenanceRespiration( lmr25top, & ! in - nscaler, & ! in - ft, & ! in - bc_in(s)%t_veg_pa(ifp), & ! in - lmr_z(iv,ft,cl)) ! out + ! MLO - Shouldn't these numbers be parameters too? + lmr25top = 2.525e-6_r8 * (1.5_r8 ** ((25._r8 - 20._r8)/10._r8)) + lmr25top = lmr25top * lnc_top / (umolC_to_kgC * g_per_kg) + + call LeafLayerMaintenanceRespiration_Ryan_1991( lmr25top, & ! in + nscaler, & ! in + ft, & ! in + bc_in(s)%t_veg_pa(ifp), & ! in + lmr_z(iv,ft,cl)) ! out + + case (lmrmodel_atkin_etal_2015) + + call LeafLayerMaintenanceRespiration_Atkin_etal_2015(lnc_top, & ! in + nscaler, & ! in + ft, & ! in + bc_in(s)%t_veg_pa(ifp), & ! in + currentPatch%tveg_lpa, & ! in + lmr_z(iv,ft,cl)) ! out + + case (lmrmodel_heskel_etal_2016) + + call LeafLayerMaintenanceRespiration_Heskel_etal_2016(lnc_top, & ! in + nscaler, & ! in + ft, & ! in + bc_in(s)%t_veg_pa(ifp), & ! in + currentPatch%tveg_lpa, & ! in + lmr_z(iv,ft,cl)) ! out + + end select ! Part VII: Calculate (1) maximum rate of carboxylation (vcmax), ! (2) maximum electron transport rate, (3) triose phosphate @@ -1966,7 +1993,7 @@ end subroutine GetCanopyGasParameters ! ==================================================================================== -subroutine LeafLayerMaintenanceRespiration(lmr25top_ft, & +subroutine LeafLayerMaintenanceRespiration_Ryan_1991(lmr25top_ft, & nscaler, & ft, & veg_tempk, & @@ -2012,7 +2039,58 @@ subroutine LeafLayerMaintenanceRespiration(lmr25top_ft, & ! Any hydrodynamic limitations could go here, currently none ! lmr = lmr * (nothing) -end subroutine LeafLayerMaintenanceRespiration +end subroutine LeafLayerMaintenanceRespiration_Ryan_1991 + +! ==================================================================================== + +subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2015(lnc, & + nscaler, & + ft, & + veg_tempk, & + tgrowth, & + lmr) + + use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm + + ! Arguments + real(r8), intent(in) :: lnc + 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 + real(r8), intent(in) :: tgrowth ! lagged vegetation temperature averaged over acclimation timescale + real(r8), intent(out) :: lmr ! Leaf Maintenance Respiration (umol CO2/m**2/s) + + ! Locals + real(r8) :: lmr25 ! leaf layer: leaf maintenance respiration rate at 25C (umol CO2/m**2/s) + + ! Parameter + + +end subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2015 + +! ==================================================================================== + +subroutine LeafLayerMaintenanceRespiration_Heskel_etal_2016(lnc, & + nscaler, & + ft, & + veg_tempk, & + tgrowth, & + lmr) + + use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm + + ! Arguments + real(r8), intent(in) :: lnc + 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 + real(r8), intent(in) :: tgrowth ! lagged vegetation temperature averaged over acclimation timescale + real(r8), intent(out) :: lmr ! Leaf Maintenance Respiration (umol CO2/m**2/s) + + ! Locals + real(r8) :: lmr25 ! leaf layer: leaf maintenance respiration rate at 25C (umol CO2/m**2/s) + +end subroutine LeafLayerMaintenanceRespiration_Heskel_etal_2016 ! ==================================================================================== diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 2923f59d06..8b16890738 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -32,7 +32,7 @@ module EDParamsMod ! temperature acclimation (NOT YET IMPLEMENTED) integer,protected, public :: maintresp_model ! switch for choosing between leaf maintenance - ! respiration model. 1=Ryan (1991) (NOT YET IMPLEMENTED) + ! respiration model. 1=Ryan (1991), 2=Atkin et al (2015), 3=Heskel et al (2016) integer,protected, public :: photo_tempsens_model ! switch for choosing the model that defines the temperature ! sensitivity of photosynthetic parameters (vcmax, jmax). ! 1=non-acclimating (NOT YET IMPLEMENTED) diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index 0ec836fe0f..e9a5971dfb 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -74,6 +74,10 @@ module FatesConstantsMod integer, parameter, public :: hlm_harvest_area_fraction = 1 ! Code for harvesting by area integer, parameter, public :: hlm_harvest_carbon = 2 ! Code for harvesting based on carbon extracted. + ! integer labels for specifying leaf maintenance respiration models + integer, parameter, public :: lmrmodel_ryan_1991 = 1 + integer, parameter, public :: lmrmodel_atkin_etal_2015 = 2 + integer, parameter, public :: lmrmodel_heskel_etal_2016 = 3 ! Error Tolerances From f1efd31a4ecbf7bc42b15dec34c04c396f4f4828 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 2 Nov 2022 14:39:31 -0700 Subject: [PATCH 409/852] Add seed dispersal max distance to parameter file This moves the hardcoded max dist value to the parameter file. This also moves the location of the dispersal mode initialization and setting to be more in line with the fates derived parameters that get sent to the hlm. All checks for the dispersal mode are updated as well. --- main/EDPftvarcon.F90 | 40 +++++++++++++++---- main/FatesDispersalMod.F90 | 24 ++++++----- main/FatesInterfaceMod.F90 | 30 +++++++++----- main/FatesInterfaceTypesMod.F90 | 17 ++++---- .../fates_params_seed-dispersal_api23.cdl | 6 +++ 5 files changed, 79 insertions(+), 38 deletions(-) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 213d9f7993..191248abcf 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -101,6 +101,7 @@ module EDPftvarcon ! ungerminated), decaying per year (yr-1) real(r8), allocatable :: seed_dispersal_param_A(:) ! Seed dispersal scale parameter, Bullock et al. (2017) real(r8), allocatable :: seed_dispersal_param_B(:) ! Seed dispersal shape parameter, Bullock et al. (2017) + real(r8), allocatable :: seed_dispersal_max_dist(:) ! Maximum seed dispersal distance parameter (m) real(r8), allocatable :: trim_limit(:) ! Limit to reductions in leaf area w stress (m2/m2) real(r8), allocatable :: trim_inc(:) ! Incremental change in trimming function (m2/m2) real(r8), allocatable :: rhol(:, :) @@ -547,6 +548,10 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_seed_dispersal_max_dist' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_trim_limit' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -901,6 +906,10 @@ subroutine Receive_PFT(this, fates_params) name = 'fates_seed_dispersal_param_B' call fates_params%RetrieveParameterAllocate(name=name, & data=this%seed_dispersal_param_B) + + name = 'fates_seed_dispersal_max_dist' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%seed_dispersal_max_dist) name = 'fates_trim_limit' call fates_params%RetrieveParameterAllocate(name=name, & @@ -1444,6 +1453,7 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'seed_decay_turnover = ',EDPftvarcon_inst%seed_decay_rate write(fates_log(),fmt0) 'seed_dispersal_param_A = ',EDPftvarcon_inst%seed_dispersal_param_A write(fates_log(),fmt0) 'seed_dispersal_param_B = ',EDPftvarcon_inst%seed_dispersal_param_B + write(fates_log(),fmt0) 'seed_dispersal_max_dist = ',EDPftvarcon_inst%seed_dispersal_max_dist write(fates_log(),fmt0) 'trim_limit = ',EDPftvarcon_inst%trim_limit write(fates_log(),fmt0) 'trim_inc = ',EDPftvarcon_inst%trim_inc write(fates_log(),fmt0) 'rhol = ',EDPftvarcon_inst%rhol @@ -1631,11 +1641,12 @@ subroutine FatesCheckParams(is_master) ! Check that parameter ranges for the seed dispersal scale parameter make sense !----------------------------------------------------------------------------------- - if ( ( EDPftvarcon_inst%seed_dispersal_param_A(ipft) < fates_check_param_set ) .and. & - ( EDPftvarcon_inst%seed_dispersal_param_B(ipft) > fates_check_param_set ) ) then + if (( EDPftvarcon_inst%seed_dispersal_param_A(ipft) < fates_check_param_set ) .and. & + (( EDPftvarcon_inst%seed_dispersal_max_dist(ipft) > fates_check_param_set ) .or. & + ( EDPftvarcon_inst%seed_dispersal_param_B(ipft) > fates_check_param_set )) ) then - write(fates_log(),*) 'Seed dispersal is on' - write(fates_log(),*) 'Please also set fates_seed_dispersal_param_B' + write(fates_log(),*) 'Seed dispersal is on per fates_seed_dispersal_param_A being set' + write(fates_log(),*) 'Please also set fates_seed_dispersal_param_B and fates_seed_dispersal_max_dist' write(fates_log(),*) 'See Bullock et al. (2017) for reasonable values' write(fates_log(),*) 'Aborting' call endrun(msg=errMsg(sourcefile, __LINE__)) @@ -1643,16 +1654,29 @@ subroutine FatesCheckParams(is_master) ! Check that parameter ranges for the seed dispersal shape parameter make sense !----------------------------------------------------------------------------------- - if ( ( EDPftvarcon_inst%seed_dispersal_param_B(ipft) < fates_check_param_set ) .and. & - ( EDPftvarcon_inst%seed_dispersal_param_A(ipft) > fates_check_param_set ) ) then + if (( EDPftvarcon_inst%seed_dispersal_param_B(ipft) < fates_check_param_set ) .and. & + (( EDPftvarcon_inst%seed_dispersal_max_dist(ipft) > fates_check_param_set ) .or. & + ( EDPftvarcon_inst%seed_dispersal_param_A(ipft) > fates_check_param_set ))) then - write(fates_log(),*) 'Seed dispersal is on' - write(fates_log(),*) 'Please also set fates_seed_dispersal_param_A' + write(fates_log(),*) 'Seed dispersal is on per fates_seed_dispersal_param_B being set' + write(fates_log(),*) 'Please also set fates_seed_dispersal_param_A and fates_seed_dispersal_max_dist' write(fates_log(),*) 'See Bullock et al. (2017) for reasonable values' write(fates_log(),*) 'Aborting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if + + ! Check that parameter ranges for the seed dispersal shape parameter make sense + !----------------------------------------------------------------------------------- + if (( EDPftvarcon_inst%seed_dispersal_max_dist(ipft) < fates_check_param_set ) .and. & + (( EDPftvarcon_inst%seed_dispersal_param_B(ipft) > fates_check_param_set ) .or. & + ( EDPftvarcon_inst%seed_dispersal_param_A(ipft) > fates_check_param_set ))) then + write(fates_log(),*) 'Seed dispersal is on per seed_dispersal_max_dist being set' + write(fates_log(),*) 'Please also set fates_seed_dispersal_param_A and fates_seed_dispersal_param_B' + write(fates_log(),*) 'See Bullock et al. (2017) for reasonable values' + write(fates_log(),*) 'Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if ! Check that parameter ranges for age-dependent mortality make sense !----------------------------------------------------------------------------------- diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index 75bb55f539..11cb0c8190 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -60,6 +60,8 @@ subroutine init(this, numprocs, numpft) ! Use use EDPftvarcon , only : EDPftvarcon_inst use FatesConstantsMod , only : fates_check_param_set + use FatesInterfaceTypesMod, only : fates_dispersal_kernel_mode + use FatesInterfaceTypesMod, only : fates_dispersal_kernel_none ! Arguments class(dispersal_type), intent(inout) :: this @@ -69,7 +71,7 @@ subroutine init(this, numprocs, numpft) ! Check if seed dispersal mode is 'turned on' by checking the parameter values ! This assumes we consistency in the parameter file across all pfts, i.e. either ! all 'on' or all 'off' - if (EDPftvarcon_inst%seed_dispersal_param_A(1) > fates_check_param_set) return + if (fates_dispersal_kernel_mode .eq. fates_dispersal_kernel_none) return allocate(this%outgoing_local(numprocs,numpft)) allocate(this%outgoing_global(numprocs,numpft)) @@ -88,10 +90,10 @@ subroutine ProbabilityDensity(pd, ipft, dist) ! Main subroutine that calls difference routines based on case select mode ! Use - use FatesInterfaceTypesMod, only : hlm_dispersal_kernel_exponential, & - hlm_dispersal_kernel_exppower, & - hlm_dispersal_kernel_logsech, & - hlm_dispersal_kernel_mode + use FatesInterfaceTypesMod, only : fates_dispersal_kernel_exponential, & + fates_dispersal_kernel_exppower, & + fates_dispersal_kernel_logsech, & + fates_dispersal_kernel_mode ! Arguments real(r8), intent(out) :: pd ! Probability density @@ -102,18 +104,18 @@ subroutine ProbabilityDensity(pd, ipft, dist) ! real(r8) :: param_a = 1._r8 ! real(r8) :: param_b = 1._r8 - hlm_dispersal_kernel_mode = 1 + fates_dispersal_kernel_mode = 1 - select case(hlm_dispersal_kernel_mode) + select case(fates_dispersal_kernel_mode) - case (hlm_dispersal_kernel_exponential) + case (fates_dispersal_kernel_exponential) pd = PD_exponential(dist,ipft) - case (hlm_dispersal_kernel_exppower) + case (fates_dispersal_kernel_exppower) pd = PD_exppower(dist,ipft) - case (hlm_dispersal_kernel_logsech) + case (fates_dispersal_kernel_logsech) pd = PD_logsech(dist,ipft) case default - write(fates_log(),*) 'ERROR: An undefined dispersal kernel was specified: ', hlm_dispersal_kernel_mode + write(fates_log(),*) 'ERROR: An undefined dispersal kernel was specified: ', fates_dispersal_kernel_mode call endrun(msg=errMsg(sourcefile, __LINE__)) end select diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 79ec8a5666..3ee71c6280 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -748,7 +748,8 @@ subroutine SetFatesGlobalElements(use_fates) ! FATES derived. ! ! -------------------------------------------------------------------------------- - + + use FatesConstantsMod, only : fates_check_param_set implicit none @@ -889,6 +890,17 @@ subroutine SetFatesGlobalElements(use_fates) call endrun(msg=errMsg(sourcefile, __LINE__)) end if end do + + ! Set the fates dispersal kernel mode if there are any seed dispersal parameters set. + ! The validation of the parameter values is check in FatesCheckParams prior to this check. + ! This is currently hard coded. + if(any(EDPftvarcon_inst%seed_dispersal_param_A .lt. fates_check_param_set)) then + fates_dispersal_kernel_mode = fates_dispersal_kernel_exponential + ! fates_dispersal_kernel_mode = fates_dispersal_kernel_exppower + ! fates_dispersal_kernel_mode = fates_dispersal_kernel_logsech + else + fates_dispersal_kernel_mode = fates_dispersal_kernel_none + end if ! Initialize Hydro globals ! (like water retention functions) @@ -1899,7 +1911,6 @@ subroutine DetermineGridCellNeighbors(neighbors) use perf_mod , only : t_startf, t_stopf use FatesDispersalMod , only : neighborhood_type, neighbor_type, ProbabilityDensity use FatesUtilsMod , only : GetNeighborDistance - use FatesInterfaceTypesMod, only : numpft use EDPftvarcon , only : EDPftvarcon_inst use FatesConstantsMod , only : fates_check_param_set @@ -1921,18 +1932,15 @@ subroutine DetermineGridCellNeighbors(neighbors) integer, allocatable :: ncells_array(:), begg_array(:) real(r8), allocatable :: gclat(:), gclon(:) - real(r8) :: g2g_dist ! grid cell distance - real(r8) :: g2g_dist_max ! grid cell distance - real(r8) :: pdf ! temp + ! 5 deg = 785.8 km, 10 deg = 1569 km, 15deg = 2345 km assumes cartesian layout with diagonal distance + real(r8) :: g2g_dist ! grid cell distance (m) + real(r8) :: pdf ! Check if seed dispersal mode is 'turned on' by checking the parameter values if (EDPftvarcon_inst%seed_dispersal_param_A(1) > fates_check_param_set) return - ! Parameters and constants, to be moved to fates param file - ! Both of these should probably be per pft - ! real(r8) :: decay_rate = 1._r8 - g2g_dist_max = 2500._r8 * 1000._r8 ! maximum search distance [m] - ! 5 deg = 785.8 km, 10 deg = 1569 km, 15deg = 2345 km assumes cartesian layout with diagonal distance + if(hlm_is_restart .eq. itrue) write(fates_log(),*) 'gridcell initialization during restart' + ! Allocate array neighbor type numg = size(ldecomp%gdc2glo) @@ -1991,7 +1999,7 @@ subroutine DetermineGridCellNeighbors(neighbors) ! Determine distance to old grid cells to the current one g2g_dist = GetNeighborDistance(gi,gj,gclat,gclon) - dist_check: if (g2g_dist .le. g2g_dist_max) then + dist_check: if (any(EDPftvarcon_inst%seed_dispersal_max_dist .gt. g2g_dist)) then ! Add neighbor index to current grid cell index list allocate(current_neighbor) diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 59aba2bc76..9b67c14c78 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -196,14 +196,6 @@ module FatesInterfaceTypesMod integer, public :: hlm_use_sp ! Flag to use FATES satellite phenology (LAI) mode ! 1 = TRUE, 0 = FALSE - integer, public :: hlm_dispersal_kernel_mode ! Flag to signal the use of grid cell seed dispersal - ! Setting this to greater than zero overrides seed rain - - integer, parameter, public :: hlm_dispersal_kernel_none = 0 ! no dispersal (use seed rain) - integer, parameter, public :: hlm_dispersal_kernel_exponential = 1 ! exponential dispersal kernel - integer, parameter, public :: hlm_dispersal_kernel_exppower = 2 ! exponential power (ExP) dispersal kernel - integer, parameter, public :: hlm_dispersal_kernel_logsech = 3 ! logistic-sech (LogS) dispersal kernel - ! ------------------------------------------------------------------------------------- ! Parameters that are dictated by FATES and known to be required knowledge ! needed by the HLMs @@ -229,6 +221,15 @@ module FatesInterfaceTypesMod integer, public :: max_comp_per_site ! This is the maximum number of nutrient aquisition ! competitors that will be generated on each site + + integer, public :: fates_dispersal_kernel_mode !Flag to signal the use of grid cell seed dispersal + ! Setting this to greater than zero overrides seed rain + + integer, parameter, public :: fates_dispersal_kernel_none = 0 ! no dispersal (use seed rain) + integer, parameter, public :: fates_dispersal_kernel_exponential = 1 ! exponential dispersal kernel + integer, parameter, public :: fates_dispersal_kernel_exppower = 2 ! exponential power (ExP) dispersal kernel + integer, parameter, public :: fates_dispersal_kernel_logsech = 3 ! logistic-sech (LogS) dispersal kernel + ! ------------------------------------------------------------------------------------- ! These vectors are used for history output mapping ! CLM/ALM have limited support for multi-dimensional history output arrays. diff --git a/parameter_files/fates_params_seed-dispersal_api23.cdl b/parameter_files/fates_params_seed-dispersal_api23.cdl index 5bc0892433..0dd4df8b7e 100644 --- a/parameter_files/fates_params_seed-dispersal_api23.cdl +++ b/parameter_files/fates_params_seed-dispersal_api23.cdl @@ -487,6 +487,10 @@ variables: double fates_seed_decay_rate(fates_pft) ; fates_seed_decay_rate:units = "yr-1" ; fates_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; + double fates_seed_dispersal_max_dist(fates_pft) ; + fates_seed_dispersal_max_dist:units = "m" ; + fates_seed_dispersal_max_dist:long_name = "maximum seed dispersal distance for a given pft" ; + fates_seed_dispersal_max_dist:use_case = "undefined" ; double fates_seed_dispersal_param_A(fates_pft) ; fates_seed_dispersal_param_A:units = "unitless" ; fates_seed_dispersal_param_A:long_name = "seed dispersal scale parameter" ; @@ -1280,6 +1284,8 @@ data: fates_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51 ; + fates_seed_dispersal_max_dist = _, _, _, _, _, _, _, _, _, _, _, _ ; + fates_seed_dispersal_param_A = _, _, _, _, _, _, _, _, _, _, _, _ ; fates_seed_dispersal_param_B = _, _, _, _, _, _, _, _, _, _, _, _ ; From 33bb12c1279156e4066c3a8d4e032bafcbbd266b Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 2 Nov 2022 14:48:11 -0700 Subject: [PATCH 410/852] remove duplicated hard coded dispersal mode --- main/FatesDispersalMod.F90 | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index 11cb0c8190..3706df5b9a 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -100,12 +100,8 @@ subroutine ProbabilityDensity(pd, ipft, dist) integer, intent(in) :: ipft ! pft index real(r8), intent(in) :: dist ! distance - ! Local - temp - ! real(r8) :: param_a = 1._r8 - ! real(r8) :: param_b = 1._r8 - - fates_dispersal_kernel_mode = 1 - + ! Select the function to use based on the kernel mode + ! Note that fates_dispersal_kernel_none mode is checked prior to this call being made select case(fates_dispersal_kernel_mode) case (fates_dispersal_kernel_exponential) From c5b3b20d1b78ccbd2ac9c3e4f05c2516e424e6c3 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 2 Nov 2022 14:57:39 -0700 Subject: [PATCH 411/852] clean up comments --- biogeochem/EDPhysiologyMod.F90 | 34 ++------------------------------- main/ChecksBalancesMod.F90 | 3 --- main/EDMainMod.F90 | 3 --- main/FatesInterfaceMod.F90 | 23 ---------------------- main/FatesInterfaceTypesMod.F90 | 6 ------ 5 files changed, 2 insertions(+), 67 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 02f6d798ec..b5d741c9f7 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -319,10 +319,6 @@ subroutine PreDisturbanceIntegrateLitter(currentPatch) litt%seed_germ_in(pft) - & litt%seed_germ_decay(pft) - !YL------ - !write(fates_log(),*) 'el, pft, litt%seed_germ(pft), litt%seed(pft), litt%seed_in_local(pft): ', el, pft, litt%seed_germ(pft), litt%seed(pft), litt%seed_in_local(pft) - !------- - enddo ! Update the Coarse Woody Debris pools (above and below) @@ -1569,10 +1565,7 @@ end subroutine assign_cohort_SP_properties ! ===================================================================================== - !YL-------------- - !subroutine SeedIn( currentSite, bc_in) subroutine SeedIn( currentSite, bc_in, bc_out) - !---------------- ! ----------------------------------------------------------------------------------- ! Flux from plants into the seed pool. @@ -1594,10 +1587,7 @@ subroutine SeedIn( currentSite, bc_in, bc_out) ! !ARGUMENTS type(ed_site_type), intent(inout), target :: currentSite type(bc_in_type), intent(in) :: bc_in - - !YL--------- type(bc_out_type), intent(inout) :: bc_out - !----------- type(ed_patch_type), pointer :: currentPatch type(litter_type), pointer :: litt @@ -1613,19 +1603,13 @@ subroutine SeedIn( currentSite, bc_in, bc_out) integer :: n_litt_types ! number of litter element types (c,n,p, etc) integer :: el ! loop counter for litter element types integer :: element_id ! element id consistent with parteh/PRTGenericMod.F90 - - - !YL--------- real(r8) :: disp_frac(maxpft) ! fraction of seed-rain among the site_seed_rain that's leaving the site [unitless] - !----------- do el = 1, num_elements site_seed_rain(:) = 0._r8 - !YL------- disp_frac(:) = 0.2 ! to be specified in the parameter file or calculated using dispersal kernel - !--------- element_id = element_list(el) @@ -1695,11 +1679,8 @@ subroutine SeedIn( currentSite, bc_in, bc_out) if(currentSite%use_this_pft(pft).eq.itrue)then ! Seed input from local sources (within site) - !YL----- - !litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)/area litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)*(1-disp_frac(pft))/area ![kg/m2/day] !write(fates_log(),*) 'pft, litt%seed_in_local(pft), site_seed_rain(pft): ', pft, litt%seed_in_local(pft), site_seed_rain(pft) - !------- ! If there is forced external seed rain, we calculate the input mass flux ! from the different elements, usung the seed optimal stoichiometry @@ -1718,17 +1699,10 @@ subroutine SeedIn( currentSite, bc_in, bc_out) end select ! Seed input from external sources (user param seed rain, or dispersal model) - - !YL, include both prescribed seed_suppl and seed_in dispersed from neighbouring gridcells --------- - - !seed_in_external = seed_stoich*EDPftvarcon_inst%seed_suppl(pft)*years_per_day ![kg/m2/day] - - ! bc%seed_in(pft) in [kg/site/day] + ! Include both prescribed seed_suppl and seed_in dispersed from neighbouring gridcells seed_in_external = bc_in%seed_in(pft)/area + seed_stoich*EDPftvarcon_inst%seed_suppl(pft)*years_per_day ![kg/m2/day] + ! write(fates_log(),*) 'pft, bc_in%seed_in(pft),bc_in%seed_in(pft)/currentPatch%area, seed_in_external: ', pft, bc_in%seed_in(pft), bc_in%seed_in(pft)/currentPatch%area, seed_in_external - write(fates_log(),*) 'pft, bc_in%seed_in(pft),bc_in%seed_in(pft)/currentPatch%area, seed_in_external: ', pft, bc_in%seed_in(pft), bc_in%seed_in(pft)/currentPatch%area, seed_in_external - - !-------------------------------------------------------------------------------------------------- litt%seed_in_extern(pft) = litt%seed_in_extern(pft) + seed_in_external ! Seeds entering externally [kg/site/day] @@ -1741,21 +1715,17 @@ subroutine SeedIn( currentSite, bc_in, bc_out) currentPatch => currentPatch%younger enddo - !YL, 06/23/2021, track seed mass (of each element) leaving the site ----------- do pft = 1,numpft site_mass%seed_out = site_mass%seed_out + site_seed_rain(pft)*disp_frac(pft) ![kg/site/day] !write(fates_log(),*) 'pft, site_seed_rain(pft), site_mass%seed_out: ', pft, site_mass%seed_out end do - !----------------------------------------------------------------------------- end do - !YL--------- do pft = 1,numpft bc_out%seed_out(pft) = bc_out%seed_out(pft) + site_seed_rain(pft)*disp_frac(pft) ![kg/site/day] write(fates_log(),*) 'pft, bc_in%seed_in(pft), bc_out%seed_out(pft): ', pft, bc_in%seed_in(pft), bc_out%seed_out(pft) end do - !----------- return end subroutine SeedIn diff --git a/main/ChecksBalancesMod.F90 b/main/ChecksBalancesMod.F90 index d2aead36d0..d7739e689e 100644 --- a/main/ChecksBalancesMod.F90 +++ b/main/ChecksBalancesMod.F90 @@ -72,9 +72,6 @@ subroutine SiteMassStock(currentSite,el,total_stock,biomass_stock,litter_stock,s total_stock = biomass_stock + seed_stock + litter_stock - !YL----- - !write(fates_log(),*) 'seed_stock, litter_stock: ', seed_stock, litter_stock - !------- return end subroutine SiteMassStock diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index d6621674ae..f46f4fb910 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -606,10 +606,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! fluxes. However, because this is potentially a cross-patch mixing model ! we will calculate this as a group - !YL------- - !call SeedIn(currentSite,bc_in) call SeedIn(currentSite,bc_in,bc_out) - !--------- ! Calculate all other litter fluxes ! ----------------------------------------------------------------------------------- diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 3ee71c6280..b9f1b0c2f9 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -369,10 +369,8 @@ subroutine zero_bcs(fates,s) end if fates%bc_out(s)%plant_stored_h2o_si = 0.0_r8 - !YL------- fates%bc_in(s)%seed_in(:) = 0.0_r8 fates%bc_out(s)%seed_out(:) = 0.0_r8 - !--------- return end subroutine zero_bcs @@ -533,12 +531,8 @@ subroutine allocate_bcin(bc_in, nlevsoil_in, nlevdecomp_in, num_lu_harvest_cats) allocate(bc_in%h2o_liq_sisl(nlevsoil_in)); bc_in%h2o_liq_sisl = nan end if - - !YL--------- ! Seed dispersal allocate(bc_in%seed_in(1:numpft)) - !----------- - ! Land use @@ -692,10 +686,8 @@ subroutine allocate_bcout(bc_out, nlevsoil_in, nlevdecomp_in) allocate(bc_out%qflx_ro_sisl(nlevsoil_in)) end if - !YL--------- ! Seed dispersal allocate(bc_out%seed_out(1:numpft)) - !----------- return end subroutine allocate_bcout @@ -2058,21 +2050,6 @@ subroutine DetermineGridCellNeighbors(neighbors) call t_stopf('fates-seed-init-decomp') - ! Diagnostic output - !YL-------- - ! if (masterproc) then - ! write(fates_log(),*)' Surface Grid Characteristics' - ! write(fates_log(),*)' longitude points = ',lni - ! write(fates_log(),*)' latitude points = ',lnj - ! write(fates_log(),*)' total number of land gridcells = ',numg - ! write(fates_log(),*)' Decomposition Characteristics' - ! write(fates_log(),*)' clumps per process = ',clump_pproc - ! write(fates_log(),*)' gsMap Characteristics' - ! write(fates_log(),*) ' lnd gsmap glo num of segs = ',mct_gsMap_ngseg(gsMap_lnd_gdc2glo) - ! write(fates_log(),*) - ! end if - !---------- - end subroutine DetermineGridCellNeighbors end module FatesInterfaceMod diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 9b67c14c78..2d1e568bf9 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -521,10 +521,7 @@ module FatesInterfaceTypesMod real(r8),allocatable :: hksat_sisl(:) ! hydraulic conductivity at saturation (mm H2O /s) real(r8),allocatable :: h2o_liq_sisl(:) ! Liquid water mass in each layer (kg/m2) real(r8) :: smpmin_si ! restriction for min of soil potential (mm) - - !YL------------ real(r8), allocatable :: seed_in(:) ! amount of seed dispersed into the site from neighbouring cells [kg/site/day] - !-------------- ! Land use ! --------------------------------------------------------------------------------- @@ -724,10 +721,7 @@ module FatesInterfaceTypesMod ! small fluxes for various reasons ! [mm H2O/s] - !YL------------- - ! Seed dispersal real(r8),allocatable :: seed_out(:) ! amount of seed leaving the site [kg/site/day] - !--------------- end type bc_out_type From 2baaaff9630519feb9a1dc3fdf09777b004785f3 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 2 Nov 2022 15:03:07 -0700 Subject: [PATCH 412/852] minor cleanup --- main/FatesInterfaceMod.F90 | 2 -- 1 file changed, 2 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index b9f1b0c2f9..8ca29313af 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -2018,7 +2018,6 @@ subroutine DetermineGridCellNeighbors(neighbors) end if neighbors(gi)%neighbor_count = neighbors(gi)%neighbor_count + 1 - ! neighbors(gi)%density_prob_tot = neighbors(gi)%density_prob_tot + current_neighbor%density_prob ! Add current grid cell index to the neighbor's list as well allocate(another_neighbor) @@ -2042,7 +2041,6 @@ subroutine DetermineGridCellNeighbors(neighbors) end if neighbors(gj)%neighbor_count = neighbors(gj)%neighbor_count + 1 - ! neighbors(gj)%density_prob_tot = neighbors(gj)%density_prob_tot + another_neighbor%density_prob end if dist_check end do neighbor_search From 4e0d95853e0df8679916393ca7d62286ce0e0d33 Mon Sep 17 00:00:00 2001 From: ckoven Date: Wed, 2 Nov 2022 17:29:02 -0600 Subject: [PATCH 413/852] added Atkin et al 2017 respiration model --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 106 +++++++++++---------- main/EDParamsMod.F90 | 2 +- main/FatesConstantsMod.F90 | 3 +- parameter_files/fates_params_default.cdl | 5 +- 4 files changed, 60 insertions(+), 56 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index c43ed0cbcb..22271ad435 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -42,8 +42,7 @@ module FATESPlantRespPhotosynthMod use EDParamsMod, only : q10_mr use EDParamsMod, only : maintresp_model use FatesConstantsMod, only : lmrmodel_ryan_1991 - use FatesConstantsMod, only : lmrmodel_atkin_etal_2015 - use FatesConstantsMod, only : lmrmodel_heskel_etal_2018 + use FatesConstantsMod, only : lmrmodel_atkin_etal_2017 use PRTGenericMod, only : prt_carbon_allom_hyp use PRTGenericMod, only : prt_cnp_flex_allom_hyp use PRTGenericMod, only : all_carbon_elements @@ -273,12 +272,6 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) integer :: iage ! loop counter for leaf age classes ! Parameters - ! ----------------------------------------------------------------------- - ! Base maintenance respiration rate for plant tissues base_mr_20 - ! M. Ryan, 1991. Effects of climate change on plant respiration. - ! Ecological Applications, 1(2), 157-167. - ! Original expression is br = 0.0106 molC/(molN h) - ! Conversion by molecular weights of C and N gives 2.525e-6 gC/(gN s) ! ! Base rate is at 20C. Adjust to 25C using the CN Q10 = 1.5 ! (gC/gN/s) @@ -529,33 +522,25 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) case (lmrmodel_ryan_1991) - ! MLO - Shouldn't these numbers be parameters too? - lmr25top = 2.525e-6_r8 * (1.5_r8 ** ((25._r8 - 20._r8)/10._r8)) - lmr25top = lmr25top * lnc_top / (umolC_to_kgC * g_per_kg) - - call LeafLayerMaintenanceRespiration_Ryan_1991( lmr25top, & ! in + call LeafLayerMaintenanceRespiration_Ryan_1991( lnc_top, & ! in nscaler, & ! in ft, & ! in bc_in(s)%t_veg_pa(ifp), & ! in lmr_z(iv,ft,cl)) ! out - case (lmrmodel_atkin_etal_2015) + case (lmrmodel_atkin_etal_2017) - call LeafLayerMaintenanceRespiration_Atkin_etal_2015(lnc_top, & ! in + call LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & ! in nscaler, & ! in ft, & ! in bc_in(s)%t_veg_pa(ifp), & ! in currentPatch%tveg_lpa, & ! in lmr_z(iv,ft,cl)) ! out - case (lmrmodel_heskel_etal_2016) + case default - call LeafLayerMaintenanceRespiration_Heskel_etal_2016(lnc_top, & ! in - nscaler, & ! in - ft, & ! in - bc_in(s)%t_veg_pa(ifp), & ! in - currentPatch%tveg_lpa, & ! in - lmr_z(iv,ft,cl)) ! out + write (fates_log(),*)'error, incorrect leaf respiration model specified') + call endrun(msg=errMsg(sourcefile, __LINE__)) end select @@ -1993,7 +1978,7 @@ end subroutine GetCanopyGasParameters ! ==================================================================================== -subroutine LeafLayerMaintenanceRespiration_Ryan_1991(lmr25top_ft, & +subroutine LeafLayerMaintenanceRespiration_Ryan_1991(lnc_top, & nscaler, & ft, & veg_tempk, & @@ -2001,10 +1986,16 @@ subroutine LeafLayerMaintenanceRespiration_Ryan_1991(lmr25top_ft, & use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm + ! ----------------------------------------------------------------------- + ! Base maintenance respiration rate for plant tissues base_mr_20 + ! M. Ryan, 1991. Effects of climate change on plant respiration. + ! Ecological Applications, 1(2), 157-167. + ! Original expression is br = 0.0106 molC/(molN h) + ! Conversion by molecular weights of C and N gives 2.525e-6 gC/(gN s) ! Arguments - real(r8), intent(in) :: lmr25top_ft ! canopy top leaf maint resp rate at 25C - ! for this pft (umol CO2/m**2/s) + real(r8), intent(in) :: lnc_top ! Leaf nitrogen content per unit area at canopy top [gN/m2] + 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 @@ -2012,6 +2003,7 @@ subroutine LeafLayerMaintenanceRespiration_Ryan_1991(lmr25top_ft, & ! Locals real(r8) :: lmr25 ! leaf layer: leaf maintenance respiration rate at 25C (umol CO2/m**2/s) + real(r8) :: lmr25top ! canopy top leaf maint resp rate at 25C for this pft (umol CO2/m**2/s) ! Parameter real(r8), parameter :: lmrha = 46390._r8 ! activation energy for lmr (J/mol) @@ -2021,7 +2013,9 @@ subroutine LeafLayerMaintenanceRespiration_Ryan_1991(lmr25top_ft, & ! temperature inhibition (25 C = 1.0) - + ! MLO - Shouldn't these numbers be parameters too? + lmr25top = 2.525e-6_r8 * (1.5_r8 ** ((25._r8 - 20._r8)/10._r8)) + lmr25top = lmr25top * lnc_top / (umolC_to_kgC * g_per_kg) ! Part I: Leaf Maintenance respiration: umol CO2 / m**2 [leaf] / s @@ -2043,7 +2037,7 @@ end subroutine LeafLayerMaintenanceRespiration_Ryan_1991 ! ==================================================================================== -subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2015(lnc, & +subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & nscaler, & ft, & veg_tempk, & @@ -2053,44 +2047,54 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2015(lnc, & use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm ! Arguments - real(r8), intent(in) :: lnc + real(r8), intent(in) :: lnc_top ! Leaf nitrogen content per unit area at canopy top [gN/m2] 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 - real(r8), intent(in) :: tgrowth ! lagged vegetation temperature averaged over acclimation timescale + real(r8), intent(in) :: veg_tempk ! vegetation temperature (degrees K) + 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) ! Locals real(r8) :: lmr25 ! leaf layer: leaf maintenance respiration rate at 25C (umol CO2/m**2/s) + real(r8) :: r_0 ! base respiration rate, PFT-dependent (umol CO2/m**2/s) + real(r8) :: r_t_ref ! acclimated ref respiration rate (umol CO2/m**2/s) - ! Parameter + ! Parameters + ! values from Atkin et al., 2017 https://doi.org/10.1007/978-3-319-68703-2_6 + ! and Heskel et al., 2016 https://doi.org/10.1073/pnas.1520282113 + real(r8), parameter :: b = 0.1012_r8 (degrees C**-1) + real(r8), parameter :: c = -0.0005_r8 (degrees C**-2) + real(r8), parameter :: Tref = tfrz+25._r8 (degrees K) + real(r8), parameter :: r_1 = 0.2061_r8 (umol CO2/m**2/s / (gN/(m2 leaf))) + real(r8), parameter :: r_2 = -0.0402_r8 (umol CO2/m**2/s/degree C) + + ! parameter values of r_0 as listed in Atkin et al 2017: (umol CO2/m**2/s) + ! Broad-leaved trees 1.7560 + ! Needle-leaf trees 1.4995 + ! Shrubs 2.0749 + ! C3 herbs/grasses 2.1956 + + lnc = lnc_top * nscaler + if ( nint(EDpftvarcon_inst%c3psn(ft)) == 1)then -end subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2015 + ! r_0 currently put into the EDpftvarcon_inst%fates_dev_arbitrary_pft + r_0 = EDpftvarcon_inst%fates_dev_arbitrary_pft(ft) + r_t_ref = r_0 + r_1 * lnc + r_2 * tgrowth -! ==================================================================================== + lmr = r_t_ref * exp(b * (veg_tempk - Tref) + c * (veg_tempk**2 - Tref**2)) -subroutine LeafLayerMaintenanceRespiration_Heskel_etal_2016(lnc, & - nscaler, & - ft, & - veg_tempk, & - tgrowth, & - lmr) + else + ! revert to Q10 model for C4 plants, parameter values as described above - use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm + lmr25top = 2.525e-6_r8 * (1.5_r8 ** ((25._r8 - 20._r8)/10._r8)) + lmr25top = lmr25top * lnc / (umolC_to_kgC * g_per_kg) - ! Arguments - real(r8), intent(in) :: lnc - 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 - real(r8), intent(in) :: tgrowth ! lagged vegetation temperature averaged over acclimation timescale - real(r8), intent(out) :: lmr ! Leaf Maintenance Respiration (umol CO2/m**2/s) - - ! Locals - real(r8) :: lmr25 ! leaf layer: leaf maintenance respiration rate at 25C (umol CO2/m**2/s) + lmr = lmr25 * 2._r8**((veg_tempk-(tfrz+25._r8))/10._r8) + lmr = lmr / (1._r8 + exp( 1.3_r8*(veg_tempk-(tfrz+55._r8)) )) + end if -end subroutine LeafLayerMaintenanceRespiration_Heskel_etal_2016 +end subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017 ! ==================================================================================== diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 8b16890738..705490d8ca 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -32,7 +32,7 @@ module EDParamsMod ! temperature acclimation (NOT YET IMPLEMENTED) integer,protected, public :: maintresp_model ! switch for choosing between leaf maintenance - ! respiration model. 1=Ryan (1991), 2=Atkin et al (2015), 3=Heskel et al (2016) + ! respiration model. 1=Ryan (1991), 2=Atkin et al (2017) integer,protected, public :: photo_tempsens_model ! switch for choosing the model that defines the temperature ! sensitivity of photosynthetic parameters (vcmax, jmax). ! 1=non-acclimating (NOT YET IMPLEMENTED) diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index e9a5971dfb..579de3ba0d 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -76,8 +76,7 @@ module FatesConstantsMod ! integer labels for specifying leaf maintenance respiration models integer, parameter, public :: lmrmodel_ryan_1991 = 1 - integer, parameter, public :: lmrmodel_atkin_etal_2015 = 2 - integer, parameter, public :: lmrmodel_heskel_etal_2016 = 3 + integer, parameter, public :: lmrmodel_atkin_etal_2017 = 2 ! Error Tolerances diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 569e6a1ab6..0fb9311fdf 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1020,7 +1020,8 @@ data: fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; + fates_dev_arbitrary_pft = 1.7560, 1.4995, 1.4995, 1.7560, 1.7560, 1.7560, + 2.0749, 2.0749, 2.0749, 2.1956, 2.1956, _ ; fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 ; @@ -1490,7 +1491,7 @@ data: fates_leaf_theta_cj_c4 = 0.999 ; - fates_maintresp_model = 1 ; + fates_maintresp_model = 2 ; fates_maxcohort = 100 ; From e4d03305a335c56cc189ee2b42743bb624a6cfd6 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 2 Nov 2022 16:48:42 -0700 Subject: [PATCH 414/852] change name of SeedIn routine to SeedUpdate now that it also updates the output --- biogeochem/EDPhysiologyMod.F90 | 4 ++-- main/EDMainMod.F90 | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index b5d741c9f7..d46245983f 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1565,7 +1565,7 @@ end subroutine assign_cohort_SP_properties ! ===================================================================================== - subroutine SeedIn( currentSite, bc_in, bc_out) + subroutine SeedUpdate( currentSite, bc_in, bc_out) ! ----------------------------------------------------------------------------------- ! Flux from plants into the seed pool. @@ -1728,7 +1728,7 @@ subroutine SeedIn( currentSite, bc_in, bc_out) end do return - end subroutine SeedIn + end subroutine SeedUpdate ! ============================================================================ diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index f46f4fb910..c00049ecf5 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -606,7 +606,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! fluxes. However, because this is potentially a cross-patch mixing model ! we will calculate this as a group - call SeedIn(currentSite,bc_in,bc_out) + call SeedUpdate(currentSite,bc_in,bc_out) ! Calculate all other litter fluxes ! ----------------------------------------------------------------------------------- From 08d755ccb74ddd9fbae8665c8a0870c24bd55a70 Mon Sep 17 00:00:00 2001 From: ckoven Date: Wed, 2 Nov 2022 18:26:59 -0600 Subject: [PATCH 415/852] bugfixes --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 41 +++++++++++++--------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 22271ad435..5f5cc8df16 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -128,7 +128,6 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) use FatesInterfaceTypesMod , only : bc_out_type use EDCanopyStructureMod, only : calc_areaindex use FatesConstantsMod, only : umolC_to_kgC - use FatesConstantsMod, only : g_per_kg use FatesConstantsMod, only : umol_per_mmol use FatesConstantsMod, only : rgas => rgas_J_K_kmol use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm @@ -531,15 +530,15 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) case (lmrmodel_atkin_etal_2017) call LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & ! in - nscaler, & ! in - ft, & ! in - bc_in(s)%t_veg_pa(ifp), & ! in - currentPatch%tveg_lpa, & ! in - lmr_z(iv,ft,cl)) ! out + nscaler, & ! in + ft, & ! in + bc_in(s)%t_veg_pa(ifp), & ! in + currentPatch%tveg_lpa%GetMean(), & ! in + lmr_z(iv,ft,cl)) ! out case default - write (fates_log(),*)'error, incorrect leaf respiration model specified') + write (fates_log(),*)'error, incorrect leaf respiration model specified' call endrun(msg=errMsg(sourcefile, __LINE__)) end select @@ -1985,6 +1984,9 @@ subroutine LeafLayerMaintenanceRespiration_Ryan_1991(lnc_top, & lmr) use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm + use FatesConstantsMod, only : umolC_to_kgC + use FatesConstantsMod, only : g_per_kg + use EDPftvarcon , only : EDPftvarcon_inst ! ----------------------------------------------------------------------- ! Base maintenance respiration rate for plant tissues base_mr_20 @@ -2020,9 +2022,9 @@ subroutine LeafLayerMaintenanceRespiration_Ryan_1991(lnc_top, & ! Part I: Leaf Maintenance respiration: umol CO2 / m**2 [leaf] / s ! ---------------------------------------------------------------------------------- - lmr25 = lmr25top_ft * nscaler + lmr25 = lmr25top * nscaler - if ( nint(EDpftvarcon_inst%c3psn(ft)) == 1)then + if ( nint(EDPftvarcon_inst%c3psn(ft)) == 1)then lmr = lmr25 * ft1_f(veg_tempk, lmrha) * & fth_f(veg_tempk, lmrhd, lmrse, lmrc) else @@ -2045,6 +2047,9 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & lmr) use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm + use FatesConstantsMod, only : umolC_to_kgC + use FatesConstantsMod, only : g_per_kg + use EDPftvarcon , only : EDPftvarcon_inst ! Arguments real(r8), intent(in) :: lnc_top ! Leaf nitrogen content per unit area at canopy top [gN/m2] @@ -2058,15 +2063,17 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & real(r8) :: lmr25 ! leaf layer: leaf maintenance respiration rate at 25C (umol CO2/m**2/s) real(r8) :: r_0 ! base respiration rate, PFT-dependent (umol CO2/m**2/s) real(r8) :: r_t_ref ! acclimated ref respiration rate (umol CO2/m**2/s) + real(r8) :: lnc ! Leaf nitrogen content per unit area at this level [gN/m2] + real(r8) :: lmr25top ! canopy top leaf maint resp rate at 25C for this pft (umol CO2/m**2/s) ! Parameters ! values from Atkin et al., 2017 https://doi.org/10.1007/978-3-319-68703-2_6 ! and Heskel et al., 2016 https://doi.org/10.1073/pnas.1520282113 - real(r8), parameter :: b = 0.1012_r8 (degrees C**-1) - real(r8), parameter :: c = -0.0005_r8 (degrees C**-2) - real(r8), parameter :: Tref = tfrz+25._r8 (degrees K) - real(r8), parameter :: r_1 = 0.2061_r8 (umol CO2/m**2/s / (gN/(m2 leaf))) - real(r8), parameter :: r_2 = -0.0402_r8 (umol CO2/m**2/s/degree C) + real(r8), parameter :: b = 0.1012_r8 ! (degrees C**-1) + real(r8), parameter :: c = -0.0005_r8 ! (degrees C**-2) + real(r8), parameter :: Tref = tfrz+25._r8 ! (degrees K) + real(r8), parameter :: r_1 = 0.2061_r8 ! (umol CO2/m**2/s / (gN/(m2 leaf))) + real(r8), parameter :: r_2 = -0.0402_r8 ! (umol CO2/m**2/s/degree C) ! parameter values of r_0 as listed in Atkin et al 2017: (umol CO2/m**2/s) ! Broad-leaved trees 1.7560 @@ -2076,10 +2083,10 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & lnc = lnc_top * nscaler - if ( nint(EDpftvarcon_inst%c3psn(ft)) == 1)then + if ( nint(EDPftvarcon_inst%c3psn(ft)) == 1)then - ! r_0 currently put into the EDpftvarcon_inst%fates_dev_arbitrary_pft - r_0 = EDpftvarcon_inst%fates_dev_arbitrary_pft(ft) + ! r_0 currently put into the EDPftvarcon_inst%dev_arbitrary_pft + r_0 = EDPftvarcon_inst%dev_arbitrary_pft(ft) r_t_ref = r_0 + r_1 * lnc + r_2 * tgrowth lmr = r_t_ref * exp(b * (veg_tempk - Tref) + c * (veg_tempk**2 - Tref**2)) From bd091b08b175f07208026c41cc61d3885919ab09 Mon Sep 17 00:00:00 2001 From: ckoven Date: Wed, 2 Nov 2022 21:21:03 -0600 Subject: [PATCH 416/852] fixed some Celsius vs Kelvin unit errors --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 5f5cc8df16..d3710567d0 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -2071,7 +2071,7 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & ! and Heskel et al., 2016 https://doi.org/10.1073/pnas.1520282113 real(r8), parameter :: b = 0.1012_r8 ! (degrees C**-1) real(r8), parameter :: c = -0.0005_r8 ! (degrees C**-2) - real(r8), parameter :: Tref = tfrz+25._r8 ! (degrees K) + real(r8), parameter :: TrefC = 25._r8 ! (degrees C) real(r8), parameter :: r_1 = 0.2061_r8 ! (umol CO2/m**2/s / (gN/(m2 leaf))) real(r8), parameter :: r_2 = -0.0402_r8 ! (umol CO2/m**2/s/degree C) @@ -2086,13 +2086,14 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & if ( nint(EDPftvarcon_inst%c3psn(ft)) == 1)then ! r_0 currently put into the EDPftvarcon_inst%dev_arbitrary_pft + ! all figs in Atkin et al 2017 stop at zero Celsius so we will assume acclimation is fixed below that r_0 = EDPftvarcon_inst%dev_arbitrary_pft(ft) - r_t_ref = r_0 + r_1 * lnc + r_2 * tgrowth + r_t_ref = r_0 + r_1 * lnc + r_2 * max(0._r8, (tgrowth - tfrz) ) - lmr = r_t_ref * exp(b * (veg_tempk - Tref) + c * (veg_tempk**2 - Tref**2)) + lmr = r_t_ref * exp(b * (veg_tempk - tfrz - TrefC) + c * ((veg_tempk-tfrz)**2 - TrefC**2)) else - ! revert to Q10 model for C4 plants, parameter values as described above + ! revert to Q10 model for C4 plants, parameter values as described above in Ryan 1991 method lmr25top = 2.525e-6_r8 * (1.5_r8 ** ((25._r8 - 20._r8)/10._r8)) lmr25top = lmr25top * lnc / (umolC_to_kgC * g_per_kg) From 422723e2653d18ef02cb8cb040518ae170bdce41 Mon Sep 17 00:00:00 2001 From: Shijie Shu Date: Thu, 3 Nov 2022 17:21:54 -0700 Subject: [PATCH 417/852] Ignore small logging rate which would produce tiny secondary patch. --- biogeochem/EDLoggingMortalityMod.F90 | 3 +++ biogeochem/EDPatchDynamicsMod.F90 | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 8145191bcc..93af25cb01 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -620,6 +620,9 @@ subroutine get_harvest_rate_carbon (patch_anthro_disturbance_label, hlm_harvest_ harvest_rate = 0._r8 end if + ! Prevent the generation of tiny secondary patches + if(harvest_rate < 1e-8) harvest_rate = 0._r8 + ! For carbon-based harvest rate, normalizing by site-level primary or secondary forest fraction ! is not needed diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 95aaefa763..374b5a92ad 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -372,7 +372,7 @@ subroutine disturbance_rates( site_in, bc_in) currentCohort%lmort_infra + & currentCohort%l_degrad ) * & currentCohort%c_area/currentPatch%area - + ! Non-harvested part of the logging disturbance rate dist_rate_ldist_notharvested = dist_rate_ldist_notharvested + currentCohort%l_degrad * & currentCohort%c_area/currentPatch%area @@ -404,6 +404,11 @@ subroutine disturbance_rates( site_in, bc_in) (currentPatch%area - currentPatch%total_canopy_area) * harvest_rate / currentPatch%area endif + ! For nocomp mode, we need to prevent producing too small patches, which may produce small patches + if(hlm_use_nocomp .and. currentPatch%disturbance_rates(dtype_ilog)*currentPatch%area < min_patch_area_forced ) then + currentPatch%disturbance_rates(dtype_ilog) = 0._r8 + end if + ! fraction of the logging disturbance rate that is non-harvested if (currentPatch%disturbance_rates(dtype_ilog) .gt. nearzero) then currentPatch%fract_ldist_not_harvested = dist_rate_ldist_notharvested / & From a0fefc2c533e131e76c00107f9a05233cb0ba911 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 4 Nov 2022 14:57:39 -0700 Subject: [PATCH 418/852] update SeedUpdate use and public calls --- biogeochem/EDPhysiologyMod.F90 | 2 +- main/EDMainMod.F90 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index d46245983f..fb56464fc1 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -121,7 +121,7 @@ module EDPhysiologyMod public :: ZeroAllocationRates public :: PreDisturbanceLitterFluxes public :: PreDisturbanceIntegrateLitter - public :: SeedIn + public :: SeedUpdate logical, parameter :: debug = .false. ! local debug flag character(len=*), parameter, private :: sourcefile = & diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index c00049ecf5..40f9602d55 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -43,7 +43,7 @@ module EDMainMod use EDPhysiologyMod , only : satellite_phenology use EDPhysiologyMod , only : recruitment use EDPhysiologyMod , only : trim_canopy - use EDPhysiologyMod , only : SeedIn + use EDPhysiologyMod , only : SeedUpdate use EDPhysiologyMod , only : ZeroAllocationRates use EDPhysiologyMod , only : ZeroLitterFluxes use EDPhysiologyMod , only : PreDisturbanceLitterFluxes From 9e69a0f4ed91c867bb26df6532e7344b738379b4 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 8 Nov 2022 09:52:40 -0500 Subject: [PATCH 419/852] Added NPP boundary condition with ELM/CLM to enable npp hypothesis on free-living fixers --- biogeochem/FatesSoilBGCFluxMod.F90 | 19 ++++++++++++++++++- main/EDInitMod.F90 | 6 +++++- main/EDTypesMod.F90 | 11 +++++++++-- main/FatesConstantsMod.F90 | 2 +- main/FatesInterfaceMod.F90 | 4 ++++ main/FatesInterfaceTypesMod.F90 | 2 ++ parteh/PRTAllometricCNPMod.F90 | 29 +++++++++++++++++++++++------ 7 files changed, 62 insertions(+), 11 deletions(-) diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index defc0bf2eb..f07d51a46a 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -315,6 +315,7 @@ subroutine PrepCH4BCs(csite,bc_in,bc_out) integer :: fp ! patch index of the site real(r8) :: agnpp ! Above ground daily npp real(r8) :: bgnpp ! Below ground daily npp + real(r8) :: site_npp ! Site level NPP gC/m2/year real(r8) :: plant_area ! crown area (m2) of all plants in patch real(r8) :: woody_area ! corwn area (m2) of woody plants in patch real(r8) :: fnrt_c ! Fine root carbon [kg/plant] @@ -325,8 +326,10 @@ subroutine PrepCH4BCs(csite,bc_in,bc_out) real(r8) :: struct_net_alloc real(r8) :: repro_net_alloc + real(r8), parameter :: ema_npp_tscale = 10._r8 ! 10 day + ! Exit if we need not communicate with the hlm's ch4 module - if(.not.(hlm_use_ch4==itrue)) return + if(.not.(hlm_use_ch4==itrue) .and. .not.(hlm_parteh_mode==prt_cnp_flex_allom_hyp) ) return ! Initialize to zero bc_out%annavg_agnpp_pa(:) = 0._r8 @@ -336,6 +339,7 @@ subroutine PrepCH4BCs(csite,bc_in,bc_out) bc_out%frootc_pa(:) = 0._r8 bc_out%root_resp(:) = 0._r8 bc_out%woody_frac_aere_pa(:) = 0._r8 + site_npp = 0._r8 fp = 0 cpatch => csite%oldest_patch @@ -431,6 +435,8 @@ subroutine PrepCH4BCs(csite,bc_in,bc_out) ! gc/m2/yr bc_out%annsum_npp_pa(fp) = (bgnpp+agnpp)*days_per_year*sec_per_day + site_npp = site_npp + bc_out%annsum_npp_pa(fp)*cpatch%area*area_inv + if(plant_area>nearzero) then bc_out%woody_frac_aere_pa(fp) = woody_area/plant_area end if @@ -438,6 +444,17 @@ subroutine PrepCH4BCs(csite,bc_in,bc_out) cpatch => cpatch%younger end do + ! Smoothed [gc/m2/yr] + if(csite%ema_npp<-10000._r8)then + ! Its difficult to come up with a resonable starting smoothing value, so + ! we initialize on a cold-start to -1 + csite%ema_npp = site_npp + else + csite%ema_npp = (1._r8-1._r8/ema_npp_tscale)*csite%ema_npp + (1._r8/ema_npp_tscale)*site_npp + end if + + bc_out%ema_npp = csite%ema_npp + return end subroutine PrepCH4BCs diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 162195ea5e..9bd9b4b01f 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -342,7 +342,11 @@ subroutine set_site_properties( nsites, sites,bc_in ) do ft = 1,numpft sites(s)%rec_l2fr(ft,:) = prt_params%allom_l2fr(ft) end do - + + ! Its difficult to come up with a resonable starting smoothing value, so + ! we initialize on a cold-start to -1 + sites(s)%ema_npp = -9999._r8 + if(hlm_use_fixed_biogeog.eq.itrue)then ! MAPPING OF FATES PFTs on to HLM_PFTs ! add up the area associated with each FATES PFT diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 28df1cc372..41889ad3b7 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -721,8 +721,15 @@ module EDTypesMod ! Total area of patches in each age bin [m2] real(r8), allocatable :: area_by_age(:) - real(r8), allocatable :: rec_l2fr(:,:) ! A running mean of the l2fr's for the newly - ! recruited, pft x canopy_layer + ! Nutrient relevant + real(r8), allocatable :: rec_l2fr(:,:) ! A running mean of the l2fr's for the newly + ! recruited, pft x canopy_layer + real(r8) :: ema_npp ! An exponential moving average of NPP [gC/m2/year] + ! The lengthscale is hard-coded "ema_npp_tcale" + ! in FatesSoilBGCFluxMod. Used solely to inform bc_out%ema_npp + ! which is used for fixation + + ! SP mode target PFT level variables real(r8), allocatable :: sp_tlai(:) ! target TLAI per FATES pft diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index c60558526d..ee3bd6cfb3 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -57,7 +57,7 @@ module FatesConstantsMod ! This flag specifies the scaling of how we present ! nutrient competitors to the HLM's soil BGC model - integer, public :: fates_np_comp_scaling = -1 + integer, public :: fates_np_comp_scaling = fates_unset_int real(fates_r8), parameter, public :: secondary_age_threshold = 94._fates_r8 ! less than this value is young secondary land ! based on average age of global diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 98eeb6d0c0..813178e25b 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -627,6 +627,9 @@ subroutine allocate_bcout(bc_out, nlevsoil_in, nlevdecomp_in) bc_out%rootfr_pa(0,1:nlevsoil_in)=1._r8/real(nlevsoil_in,r8) end if + bc_out%ema_npp = nan + + ! Fates -> BGC fragmentation mass fluxes select case(hlm_parteh_mode) case(prt_carbon_allom_hyp) @@ -635,6 +638,7 @@ subroutine allocate_bcout(bc_out, nlevsoil_in, nlevdecomp_in) allocate(bc_out%litt_flux_lab_c_si(nlevdecomp_in)) case(prt_cnp_flex_allom_hyp) + allocate(bc_out%litt_flux_cel_c_si(nlevdecomp_in)) allocate(bc_out%litt_flux_lig_c_si(nlevdecomp_in)) allocate(bc_out%litt_flux_lab_c_si(nlevdecomp_in)) diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index be482a96ad..2e3ce781ed 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -677,6 +677,8 @@ module FatesInterfaceTypesMod real(r8), pointer :: woody_frac_aere_pa(:) ! Woody plant fraction (by crown area) of all plants ! used for calculating patch-level aerenchyma porosity + real(r8) :: ema_npp ! site-level NPP smoothed over time, see PrepCH4BCs() + ! used for N fixation in ELM/CLM right now ! Canopy Structure real(r8), allocatable :: elai_pa(:) ! exposed leaf area index diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index ad943702ba..01a45e3900 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -1861,15 +1861,32 @@ subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & ! Estimate the overflow store_c_target = store_c_target * (1._r8 + prt_params%store_ovrflw_frac(ipft)) - total_c_flux = min(c_gain,max(0.0, (store_c_target - this%variables(store_c_id)%val(1)))) + total_c_flux = max(0.0, min(c_gain, store_c_target - this%variables(store_c_id)%val(1))) ! Transfer excess carbon into storage overflow this%variables(store_c_id)%val(1) = this%variables(store_c_id)%val(1) + total_c_flux - c_gain = c_gain - total_c_flux + c_gain = c_gain - total_c_flux end if end if + ! If we had some poor numerical precision resulting + ! in negative gains, use storage to get them back to zero + ! they should be very very small + if(c_gain<-nearzero) then + this%variables(store_c_id)%val(1) = this%variables(store_c_id)%val(1) + c_gain + c_gain = 0 + end if + if(n_gain<-nearzero) then + this%variables(store_n_id)%val(1) = this%variables(store_n_id)%val(1) + n_gain + n_gain = 0 + end if + if(p_gain<-nearzero) then + this%variables(store_p_id)%val(1) = this%variables(store_p_id)%val(1) + p_gain + p_gain = 0 + end if + + ! Figure out what to do with excess carbon and nutrients ! 1) excude through roots cap at 0 to flush out imprecisions @@ -1883,19 +1900,19 @@ subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & if(n_uptake_mode.eq.prescribed_n_uptake) then n_efflux = 0._r8 else - n_efflux = max(0.0_r8,n_gain) + n_efflux = n_gain n_gain = 0._r8 end if if(p_uptake_mode.eq.prescribed_p_uptake) then p_efflux = 0._r8 else - p_efflux = max(0.0_r8,p_gain) + p_efflux = p_gain p_gain = 0._r8 end if - c_efflux = max(0.0_r8,c_gain) - c_gain = 0.0_r8 + c_efflux = c_gain + c_gain = 0.0_r8 From bd9d357a5a16f338c7bef8574b9d19a967773b88 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 8 Nov 2022 13:36:04 -0800 Subject: [PATCH 420/852] update seed dispersal run mode check for DetermineGridCellNeighbors --- main/FatesInterfaceMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 8ca29313af..983dff00bf 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1929,7 +1929,7 @@ subroutine DetermineGridCellNeighbors(neighbors) real(r8) :: pdf ! Check if seed dispersal mode is 'turned on' by checking the parameter values - if (EDPftvarcon_inst%seed_dispersal_param_A(1) > fates_check_param_set) return + if (fates_dispersal_kernel_mode .eq. fates_dispersal_kernel_none) return if(hlm_is_restart .eq. itrue) write(fates_log(),*) 'gridcell initialization during restart' From a7fa496db16d8408a9897f55b7546553806cf591 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 8 Nov 2022 13:36:58 -0800 Subject: [PATCH 421/852] add clarifying comment --- main/FatesInterfaceTypesMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 2d1e568bf9..9bc5efecbd 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -225,7 +225,7 @@ module FatesInterfaceTypesMod integer, public :: fates_dispersal_kernel_mode !Flag to signal the use of grid cell seed dispersal ! Setting this to greater than zero overrides seed rain - integer, parameter, public :: fates_dispersal_kernel_none = 0 ! no dispersal (use seed rain) + integer, parameter, public :: fates_dispersal_kernel_none = 0 ! no dispersal (use seed rain only) integer, parameter, public :: fates_dispersal_kernel_exponential = 1 ! exponential dispersal kernel integer, parameter, public :: fates_dispersal_kernel_exppower = 2 ! exponential power (ExP) dispersal kernel integer, parameter, public :: fates_dispersal_kernel_logsech = 3 ! logistic-sech (LogS) dispersal kernel From 33468d2aa226fcf082006a364b3bbc36a4f60485 Mon Sep 17 00:00:00 2001 From: ZacharyRobbins Date: Wed, 9 Nov 2022 08:41:00 -0700 Subject: [PATCH 422/852] Fixing attribution (JS) --- biogeochem/CMIP data.txt | 24 ++++++++++++++++++++++++ fire/SFMainMod.F90 | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 biogeochem/CMIP data.txt diff --git a/biogeochem/CMIP data.txt b/biogeochem/CMIP data.txt new file mode 100644 index 0000000000..e80436482b --- /dev/null +++ b/biogeochem/CMIP data.txt @@ -0,0 +1,24 @@ +. +CMIP6.CMIP.NCAR.CESM2.historical.r11i1p1f1.day.rlds.gn' + + + +CF Standard Name | Unit | AMIP + +---------------- | ---- | ---- + +specific_humidity | 1 | hus + +precipitation_flux | kg m-2 s-1 | pr + +surface_air_pressure | Pa | ps + +surface_downwelling_longwave_flux_in_air | W/m2 | rlds + +surface_downwelling_shortwave_flux_in_air | W/m2 | rsds + +air_temperature | K | ta + +eastward_wind | ms-1 | ua + +northward_wind | ms-1 | va \ No newline at end of file diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index 720f024a88..f8e07d4c73 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -764,7 +764,7 @@ subroutine area_burnt_intensity ( currentSite, bc_in ) lb = (1.0_r8 + (8.729_r8 * & ((1.0_r8 -(exp(-0.03_r8 * m_per_min__to__km_per_hour * currentPatch%effect_wspeed)))**2.155_r8))) else ! EQ 80 grass fuels (CFFBPS Ont.Inf.Rep. ST-X-3, 1992, but with a correction from an errata published within - ! Information Report GLC-X-10 by Bottom et al., 2009 because there is a typo in CFFBPS Ont.Inf.Rep. ST-X-3, 1992) + ! Information Report GLC-X-10 by Wotten et al., 2009 because there is a typo in CFFBPS Ont.Inf.Rep. ST-X-3, 1992) lb = (1.1_r8*((m_per_min__to__km_per_hour * currentPatch%effect_wspeed)**0.464_r8)) endif endif From 20e1c769bbe94462d9fbe1e5f913c2dfc6fe7588 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 9 Nov 2022 16:42:03 -0500 Subject: [PATCH 423/852] fixes to symbiotic fixation --- biogeochem/EDCohortDynamicsMod.F90 | 20 ++++-- biogeophys/EDAccumulateFluxesMod.F90 | 2 + biogeophys/FatesPlantRespPhotosynthMod.F90 | 5 +- main/EDMainMod.F90 | 6 +- main/EDTypesMod.F90 | 5 +- main/FatesHistoryInterfaceMod.F90 | 6 +- main/FatesRestartInterfaceMod.F90 | 4 +- parteh/PRTAllometricCNPMod.F90 | 79 ++++++++++++---------- 8 files changed, 75 insertions(+), 52 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index b54c0eea3e..0bc96346af 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -592,7 +592,8 @@ subroutine nan_cohort(cc_p) currentCohort%daily_nh4_uptake = nan currentCohort%daily_no3_uptake = nan currentCohort%daily_n_gain = nan - currentCohort%daily_n_fixation = nan + currentCohort%sym_nfix_daily = nan + currentCohort%sym_nfix_tstep = nan currentCohort%daily_p_gain = nan currentCohort%daily_c_efflux = nan currentCohort%daily_n_efflux = nan @@ -725,7 +726,7 @@ subroutine zero_cohort(cc_p) ! Fixation is also integrated over the course of the day ! and must be zeroed upon creation and after plant ! resource allocation - currentCohort%daily_n_fixation = 0._r8 + currentCohort%sym_nfix_daily = 0._r8 end subroutine zero_cohort @@ -1469,12 +1470,16 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) nextc%n*nextc%ema_dcxdt)/newn currentCohort%cx0 = (currentCohort%n*currentCohort%cx0 + & nextc%n*nextc%cx0)/newn + + ! These variables do not need to be rescaled because they + ! are written to history immediately after calculation + currentCohort%daily_nh4_uptake = (currentCohort%n*currentCohort%daily_nh4_uptake + & nextc%n*nextc%daily_nh4_uptake)/newn currentCohort%daily_no3_uptake = (currentCohort%n*currentCohort%daily_no3_uptake + & nextc%n*nextc%daily_no3_uptake)/newn - currentCohort%daily_n_fixation = (currentCohort%n*currentCohort%daily_n_fixation + & - nextc%n*nextc%daily_n_fixation)/newn + currentCohort%sym_nfix_daily = (currentCohort%n*currentCohort%sym_nfix_daily + & + nextc%n*nextc%sym_nfix_daily)/newn currentCohort%daily_n_gain = (currentCohort%n*currentCohort%daily_n_gain + & nextc%n*nextc%daily_n_gain)/newn currentCohort%daily_p_gain = (currentCohort%n*currentCohort%daily_p_gain + & @@ -1882,9 +1887,12 @@ subroutine copy_cohort( currentCohort,copyc ) n%year_net_uptake = o%year_net_uptake n%ts_net_uptake = o%ts_net_uptake + ! These do not need to be copied because they + ! are written to history before dynamics occurs + ! and cohorts are reformed n%daily_nh4_uptake = o%daily_nh4_uptake n%daily_no3_uptake = o%daily_no3_uptake - n%daily_n_fixation = o%daily_n_fixation + n%sym_nfix_daily = o%sym_nfix_daily n%daily_n_gain = o%daily_n_gain n%daily_p_gain = o%daily_p_gain n%daily_c_efflux = o%daily_c_efflux @@ -2253,7 +2261,7 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) ! Target total dead (structrual) biomass [kgC] call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, ipft, target_struct_c) ! Target fine-root biomass and deriv. according to allometry and trimming [kgC, kgC/cm] - call bfineroot(dbh,ipft,canopy_trim,target_fnrt_c) + call bfineroot(dbh,ipft,canopy_trim,ccohort%l2fr,target_fnrt_c) ! Target storage carbon [kgC,kgC/cm] call bstore_allom(dbh,ipft,ccohort%crowndamage-1, canopy_trim,target_store_c) ! Target leaf biomass according to allometry and trimming diff --git a/biogeophys/EDAccumulateFluxesMod.F90 b/biogeophys/EDAccumulateFluxesMod.F90 index 8eae0f4a50..559fa5b0af 100644 --- a/biogeophys/EDAccumulateFluxesMod.F90 +++ b/biogeophys/EDAccumulateFluxesMod.F90 @@ -86,6 +86,8 @@ subroutine AccumulateFluxes_ED(nsites, sites, bc_in, bc_out, dt_time) ccohort%gpp_acc = ccohort%gpp_acc + ccohort%gpp_tstep ccohort%resp_acc = ccohort%resp_acc + ccohort%resp_tstep + ccohort%sym_nfix_daily = ccohort%sym_nfix_daily + ccohort%sym_nfix_tstep + ! weighted mean of D13C by gpp if((ccohort%gpp_acc + ccohort%gpp_tstep) .eq. 0.0_r8) then ccohort%c13disc_acc = 0.0_r8 diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index a404ece479..d313ac9ce2 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -765,7 +765,8 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! for now use dev_arbitrary_pft as scaling term between 0 and 1 as additional increment of root respiration used for N fixation ! ------------------------------------------------------------------ currentCohort%froot_mr = 0._r8 - + currentCohort%sym_nfix_tstep = 0._r8 + ! n_fixation is integrated over the course of the day ! this variable is zeroed at the end of the FATES dynamics sequence @@ -780,7 +781,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) currentCohort%froot_mr = currentCohort%froot_mr + fnrt_mr_nfix_layer + fnrt_mr_layer - currentCohort%daily_n_fixation = currentCohort%daily_n_fixation + nfix_layer + currentCohort%sym_nfix_tstep = currentCohort%sym_nfix_tstep + nfix_layer enddo diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 63b27c0dd0..025969b07a 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -525,7 +525,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! allocation scheme currentCohort%daily_n_gain = currentCohort%daily_nh4_uptake + & - currentCohort%daily_no3_uptake + currentCohort%daily_n_fixation + currentCohort%daily_no3_uptake + currentCohort%sym_nfix_daily currentCohort%resp_excess = 0._r8 @@ -731,7 +731,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentCohort => currentPatch%shortest do while(associated(currentCohort)) currentCohort%n = max(0._r8,currentCohort%n + currentCohort%dndt * hlm_freq_day ) - currentCohort%daily_n_fixation = 0._r8 + currentCohort%sym_nfix_daily = 0._r8 currentCohort => currentCohort%taller enddo currentPatch => currentPatch%older @@ -968,7 +968,7 @@ subroutine TotalBalanceCheck (currentSite, call_index ) write(fates_log(),*) 'NH4 uptake: ',currentCohort%daily_nh4_uptake*currentCohort%n write(fates_log(),*) 'NO3 uptake: ',currentCohort%daily_no3_uptake*currentCohort%n write(fates_log(),*) 'N efflux: ',currentCohort%daily_n_efflux*currentCohort%n - write(fates_log(),*) 'N fixation: ',currentCohort%daily_n_fixation*currentCohort%n + write(fates_log(),*) 'N fixation: ',currentCohort%sym_nfix_daily*currentCohort%n elseif(element_list(el).eq.phosphorus_element) then write(fates_log(),*) 'P uptake: ',currentCohort%daily_p_gain*currentCohort%n write(fates_log(),*) 'P efflux: ',currentCohort%daily_p_efflux*currentCohort%n diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index ff5404b9b2..5f9ead2229 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -301,7 +301,10 @@ module EDTypesMod real(r8) :: daily_nh4_uptake ! integrated daily uptake of mineralized ammonium through competitive acquisition in soil [kg N / plant/ day] real(r8) :: daily_no3_uptake ! integrated daily uptake of mineralized nitrate through competitive acquisition in soil [kg N / plant/ day] - real(r8) :: daily_n_fixation ! Rate of N fixation from the roots [kgN/indiv/day] + + real(r8) :: sym_nfix_daily ! Accumulated symbiotic N fixation from the roots [kgN/indiv/day] + real(r8) :: sym_nfix_tstep ! Symbiotic N fixation from the roots for the time-step[kgN/indiv/tstep] + real(r8) :: daily_n_gain ! sum of fixation and uptake of mineralized nh4/no3 in solution as well as symbiotic fixation real(r8) :: daily_p_gain ! integrated daily uptake of mineralized P through competitive acquisition in soil [kg P / plant/ day] diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index d8203319cf..1f8c2708b3 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2002,11 +2002,11 @@ subroutine update_history_nutrflux(this,csite) ! Symbiotic Fixation fates_hist%hvars(ih_nfix_si)%r81d(io_si) = & fates_hist%hvars(ih_nfix_si)%r81d(io_si) + & - ccohort%daily_n_fixation*uconv + ccohort%sym_nfix_daily*uconv fates_hist%hvars(ih_nfix_scpf)%r82d(io_si,iscpf) = & fates_hist%hvars(ih_nfix_scpf)%r82d(io_si,iscpf) + & - ccohort%daily_n_fixation*uconv + ccohort%sym_nfix_daily*uconv ! Efflux/exudation this%hvars(ih_nefflux_scpf)%r82d(io_si,iscpf) = & @@ -2801,7 +2801,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) total_m / m2_per_ha - call bstore_allom(ccohort%dbh,ccohort%pft,ccohort%canopy_trim, store_max) + call bstore_allom(ccohort%dbh,ccohort%pft,ccohort%crowndamage,ccohort%canopy_trim, store_max) this%hvars(ih_storectfrac_si)%r81d(io_si) = & this%hvars(ih_storectfrac_si)%r81d(io_si) + ccohort%n * store_max/m2_per_ha diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index b23328c59d..040af0400b 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -2108,7 +2108,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) this%rvars(ir_daily_no3_uptake_co)%r81d(io_idx_co) = ccohort%daily_no3_uptake this%rvars(ir_daily_nh4_uptake_co)%r81d(io_idx_co) = ccohort%daily_nh4_uptake this%rvars(ir_daily_p_uptake_co)%r81d(io_idx_co) = ccohort%daily_p_gain - this%rvars(ir_daily_n_fixation_co)%r81d(io_idx_co) = ccohort%daily_n_fixation + this%rvars(ir_daily_n_fixation_co)%r81d(io_idx_co) = ccohort%sym_nfix_daily this%rvars(ir_daily_n_demand_co)%r81d(io_idx_co) = ccohort%daily_n_demand this%rvars(ir_daily_p_demand_co)%r81d(io_idx_co) = ccohort%daily_p_demand end if @@ -2989,7 +2989,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ccohort%cnp_limiter = int(this%rvars(ir_cnplimiter_co)%r81d(io_idx_co)) ccohort%daily_nh4_uptake = this%rvars(ir_daily_nh4_uptake_co)%r81d(io_idx_co) ccohort%daily_no3_uptake = this%rvars(ir_daily_no3_uptake_co)%r81d(io_idx_co) - ccohort%daily_n_fixation = this%rvars(ir_daily_n_fixation_co)%r81d(io_idx_co) + ccohort%sym_nfix_daily = this%rvars(ir_daily_n_fixation_co)%r81d(io_idx_co) ccohort%daily_p_gain = this%rvars(ir_daily_p_uptake_co)%r81d(io_idx_co) ccohort%daily_n_demand = this%rvars(ir_daily_n_demand_co)%r81d(io_idx_co) ccohort%daily_p_demand = this%rvars(ir_daily_p_demand_co)%r81d(io_idx_co) diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 999c8d77ad..ab8e1abb2d 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -163,9 +163,10 @@ module PRTAllometricCNPMod integer, public, parameter :: acnp_bc_in_id_netdc = 4 ! Index for the net daily C input BC integer, public, parameter :: acnp_bc_in_id_nc_repro = 5 integer, public, parameter :: acnp_bc_in_id_pc_repro = 6 + integer, public, parameter :: acnp_bc_in_id_cdamage = 7 ! 0=leaf off, 1=leaf on - integer, parameter :: num_bc_in = 6 + integer, parameter :: num_bc_in = 7 ! ------------------------------------------------------------------------------------- ! Output Boundary Indices (These are public) @@ -180,10 +181,11 @@ module PRTAllometricCNPMod ! Indices for parameters passed to the integrator - integer,private, parameter :: intgr_parm_ctrim = 1 - integer,private, parameter :: intgr_parm_pft = 2 - integer,private, parameter :: intgr_parm_l2fr = 3 - integer,private, parameter :: num_intgr_parm = 3 + integer,private, parameter :: intgr_parm_ctrim = 1 + integer,private, parameter :: intgr_parm_pft = 2 + integer,private, parameter :: intgr_parm_l2fr = 3 + integer,private, parameter :: intgr_parm_cdamage = 4 + integer,private, parameter :: num_intgr_parm = 4 ! ------------------------------------------------------------------------------------- ! Define the size of the coorindate vector. For this hypothesis, there is only @@ -363,11 +365,12 @@ subroutine DailyPRTAllometricCNP(this,phase) real(r8),pointer :: l2fr ! Leaf to fineroot ratio of target biomass ! Input only bcs - integer :: ipft ! Plant Functional Type index - real(r8) :: c_gain ! Daily carbon balance for this cohort [kgC] - real(r8),pointer :: n_gain ! Daily nitrogen uptake through fine-roots [kgN] - real(r8),pointer :: p_gain ! Daily phosphorus uptake through fine-roots [kgN] - real(r8) :: canopy_trim ! The canopy trimming function [0-1] + integer :: ipft ! Plant Functional Type index + real(r8) :: c_gain ! Daily carbon balance for this cohort [kgC] + real(r8),pointer :: n_gain ! Daily nitrogen uptake through fine-roots [kgN] + real(r8),pointer :: p_gain ! Daily phosphorus uptake through fine-roots [kgN] + real(r8) :: canopy_trim ! The canopy trimming function [0-1] + integer :: crown_damage ! Damage status of the crown (for allometry) ! Pointers to output bcs real(r8),pointer :: c_efflux ! Total plant efflux of carbon (kgC) @@ -435,7 +438,8 @@ subroutine DailyPRTAllometricCNP(this,phase) c_gain = this%bc_in(acnp_bc_in_id_netdc)%rval canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival - + crown_damage = this%bc_in(acnp_bc_in_id_cdamage)%ival + ! If either n or p uptake is in prescribed mode ! set the gains to something massive. 1 kilo of pure ! nutrient should be wayyy more than enough @@ -457,14 +461,14 @@ subroutine DailyPRTAllometricCNP(this,phase) ! Set carbon targets based on the plant's current stature target_c(:) = fates_unset_r8 target_dcdd(:) = fates_unset_r8 - call bsap_allom(dbh,ipft,canopy_trim,sapw_area,target_c(sapw_organ),target_dcdd(sapw_organ)) - call bagw_allom(dbh,ipft,agw_c_target,agw_dcdd_target) + call bsap_allom(dbh,ipft,crown_damage,canopy_trim,sapw_area,target_c(sapw_organ),target_dcdd(sapw_organ)) + call bagw_allom(dbh,ipft,crown_damage,agw_c_target,agw_dcdd_target) call bbgw_allom(dbh,ipft,bgw_c_target,bgw_dcdd_target) call bdead_allom(agw_c_target,bgw_c_target,target_c(sapw_organ),ipft,target_c(struct_organ), & agw_dcdd_target,bgw_dcdd_target,target_dcdd(sapw_organ),target_dcdd(struct_organ)) - call bleaf(dbh,ipft,canopy_trim, target_c(leaf_organ), target_dcdd(leaf_organ)) + call bleaf(dbh,ipft,crown_damage,canopy_trim, target_c(leaf_organ), target_dcdd(leaf_organ)) call bfineroot(dbh,ipft,canopy_trim, l2fr, target_c(fnrt_organ), target_dcdd(fnrt_organ)) - call bstore_allom(dbh,ipft,canopy_trim, target_c(store_organ), target_dcdd(store_organ)) + call bstore_allom(dbh,ipft,crown_damage, canopy_trim, target_c(store_organ), target_dcdd(store_organ)) target_c(repro_organ) = 0._r8 target_dcdd(repro_organ) = 0._r8 @@ -1261,6 +1265,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & integer :: ipft integer, pointer :: limiter ! Integer flagging which (C,N,P) is limiting real(r8) :: canopy_trim ! fraction of crown trimmed + integer :: crown_damage ! Damage status level real(r8) :: leaf_status ! leaves on or off? real(r8) :: l2fr ! leaf to fineroot allometry multiplier integer :: i, ii ! organ index loops (masked and unmasked) @@ -1334,6 +1339,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & leaf_status = this%bc_in(acnp_bc_in_id_lstat)%ival dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival + crown_damage = this%bc_in(acnp_bc_in_id_cdamage)%ival limiter => this%bc_out(acnp_bc_out_id_limiter)%ival canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval l2fr = this%bc_inout(acnp_bc_inout_id_l2fr)%rval ! This variable is not updated in this @@ -1365,15 +1371,12 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & p_gain <= 0.02_r8*calloc_abs_error ) then return end if - - - - intgr_params(:) = fates_unset_r8 intgr_params(intgr_parm_ctrim) = this%bc_in(acnp_bc_in_id_ctrim)%rval intgr_params(intgr_parm_pft) = real(this%bc_in(acnp_bc_in_id_pft)%ival) intgr_params(intgr_parm_l2fr) = this%bc_inout(acnp_bc_inout_id_l2fr)%rval + intgr_params(intgr_parm_cdamage) = real(this%bc_in(acnp_bc_in_id_cdamage)%ival) state_mask(:) = .false. mask_organs(:) = fates_unset_int @@ -1573,7 +1576,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & leafc_tp1 = leafc_tp1 + this%variables(i_var)%val(i) end do - call CheckIntegratedAllometries(state_array_out(dbh_id),ipft,canopy_trim, l2fr, & + call CheckIntegratedAllometries(state_array_out(dbh_id),ipft,crown_damage,canopy_trim, l2fr, & leafc_tp1, state_array_out(fnrt_id), state_array_out(sapw_id), & state_array_out(store_id), state_array_out(struct_id), & state_mask(leaf_id), state_mask(fnrt_id), state_mask(sapw_id), & @@ -1669,13 +1672,13 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & storec_tp1 = state_array_out(store_id) structc_tp1 = state_array_out(struct_id) - call bleaf(dbh_tp1,ipft,canopy_trim,leaf_c_target_tp1) + call bleaf(dbh_tp1,ipft,crown_damage,canopy_trim,leaf_c_target_tp1) call bfineroot(dbh_tp1,ipft,canopy_trim,l2fr,fnrt_c_target_tp1) - call bsap_allom(dbh_tp1,ipft,canopy_trim,sapw_area,sapw_c_target_tp1) - call bagw_allom(dbh_tp1,ipft,agw_c_target_tp1) + call bsap_allom(dbh_tp1,ipft,crown_damage,canopy_trim,sapw_area,sapw_c_target_tp1) + call bagw_allom(dbh_tp1,ipft,crown_damage,agw_c_target_tp1) call bbgw_allom(dbh_tp1,ipft,bgw_c_target_tp1) call bdead_allom(agw_c_target_tp1,bgw_c_target_tp1, sapw_c_target_tp1, ipft, struct_c_target_tp1) - call bstore_allom(dbh_tp1,ipft,canopy_trim,store_c_target_tp1) + call bstore_allom(dbh_tp1,ipft,crown_damage,canopy_trim,store_c_target_tp1) write(fates_log(),*) 'leaf_c: ',leafc_tp1, leaf_c_target_tp1,leafc_tp1-leaf_c_target_tp1 write(fates_log(),*) 'fnrt_c: ',fnrtc_tp1, fnrt_c_target_tp1,fnrtc_tp1- fnrt_c_target_tp1 @@ -1781,12 +1784,14 @@ subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & integer :: ipft integer, pointer :: limiter real(r8) :: canopy_trim - + integer :: crown_damage + dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival resp_excess => this%bc_inout(acnp_bc_inout_id_resp_excess)%rval limiter => this%bc_out(acnp_bc_out_id_limiter)%ival + crown_damage = this%bc_in(acnp_bc_in_id_cdamage)%ival ! ----------------------------------------------------------------------------------- ! If nutrients are still available, then we can bump up the values in the pools @@ -1845,7 +1850,7 @@ subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & elseif(store_c_overflow == burn_c_store_overflow) then ! Update carbon based allometric targets - call bstore_allom(dbh,ipft,canopy_trim, store_c_target) + call bstore_allom(dbh,ipft,crown_damage,canopy_trim, store_c_target) ! Allow some overflow store_c_target = store_c_target * (1._r8 + prt_params%store_ovrflw_frac(ipft)) @@ -1862,7 +1867,7 @@ subroutine CNPAllocateRemainder(this, c_gain,n_gain,p_gain, & elseif(store_c_overflow == exude_c_store_overflow)then ! Update carbon based allometric targets - call bstore_allom(dbh,ipft,canopy_trim, store_c_target) + call bstore_allom(dbh,ipft,crown_damage,canopy_trim, store_c_target) ! Estimate the overflow store_c_target = store_c_target * (1._r8 + prt_params%store_ovrflw_frac(ipft)) @@ -1982,6 +1987,7 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe real(r8) :: l2fr integer :: ipft integer :: i_cvar + integer :: crown_damage real(r8) :: sapw_area real(r8) :: leaf_c_target,fnrt_c_target real(r8) :: sapw_c_target,agw_c_target @@ -1995,6 +2001,7 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe l2fr = this%bc_inout(acnp_bc_inout_id_l2fr)%rval nc_repro = this%bc_in(acnp_bc_in_id_nc_repro)%rval pc_repro = this%bc_in(acnp_bc_in_id_pc_repro)%rval + crown_damage = this%bc_in(acnp_bc_in_id_cdamage)%ival ! Storage of nutrients are assumed to have different compartments than ! for carbon, and thus their targets are not associated with a tissue @@ -2003,10 +2010,10 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe if(organ_id == store_organ) then - call bleaf(dbh,ipft,canopy_trim,leaf_c_target) + call bleaf(dbh,ipft,crown_damage,canopy_trim,leaf_c_target) call bfineroot(dbh,ipft,canopy_trim,l2fr,fnrt_c_target) - call bsap_allom(dbh,ipft,canopy_trim,sapw_area,sapw_c_target) - call bagw_allom(dbh,ipft,agw_c_target) + call bsap_allom(dbh,ipft,crown_damage,canopy_trim,sapw_area,sapw_c_target) + call bagw_allom(dbh,ipft,crown_damage,agw_c_target) call bbgw_allom(dbh,ipft,bgw_c_target) call bdead_allom(agw_c_target,bgw_c_target, sapw_c_target, ipft, struct_c_target) @@ -2187,6 +2194,7 @@ function AllomCNPGrowthDeriv(l_state_array,l_state_mask,cbalance,intgr_params) r ! locals integer :: ipft ! PFT index real(r8) :: canopy_trim ! Canopy trimming function (boundary condition [0-1] + integer :: crown_damage ! Damage class real(r8) :: l2fr ! leaf to fineroot biomass multiplier real(r8) :: leaf_c_target ! target leaf biomass, dummy var (kgC) real(r8) :: fnrt_c_target ! target fine-root biomass, dummy var (kgC) @@ -2225,15 +2233,16 @@ function AllomCNPGrowthDeriv(l_state_array,l_state_mask,cbalance,intgr_params) r canopy_trim = intgr_params(intgr_parm_ctrim) ipft = int(intgr_params(intgr_parm_pft)) l2fr = intgr_params(intgr_parm_l2fr) - - call bleaf(dbh,ipft,canopy_trim,leaf_c_target,leaf_dcdd_target) + crown_damage = int(intgr_params(acnp_bc_in_id_cdamage)) + + call bleaf(dbh,ipft,crown_damage,canopy_trim,leaf_c_target,leaf_dcdd_target) call bfineroot(dbh,ipft,canopy_trim,l2fr,fnrt_c_target,fnrt_dcdd_target) - call bsap_allom(dbh,ipft,canopy_trim,sapw_area,sapw_c_target,sapw_dcdd_target) - call bagw_allom(dbh,ipft,agw_c_target,agw_dcdd_target) + call bsap_allom(dbh,ipft,crown_damage,canopy_trim,sapw_area,sapw_c_target,sapw_dcdd_target) + call bagw_allom(dbh,ipft,crown_damage,agw_c_target,agw_dcdd_target) call bbgw_allom(dbh,ipft,bgw_c_target,bgw_dcdd_target) call bdead_allom(agw_c_target,bgw_c_target, sapw_c_target, ipft, struct_c_target, & agw_dcdd_target, bgw_dcdd_target, sapw_dcdd_target, struct_dcdd_target) - call bstore_allom(dbh,ipft,canopy_trim,store_c_target,store_dcdd_target) + call bstore_allom(dbh,ipft,crown_damage,canopy_trim,store_c_target,store_dcdd_target) if (mask_repro) then ! fraction of carbon going towards reproduction From fec6597f21b3f70abd87d50bfe82622ab297d7f8 Mon Sep 17 00:00:00 2001 From: Shijie Shu Date: Wed, 9 Nov 2022 14:35:11 -0800 Subject: [PATCH 424/852] Clarify calculations and comments on the harvest debt. --- biogeochem/EDLoggingMortalityMod.F90 | 74 +++++++++++------ biogeochem/EDMortalityFunctionsMod.F90 | 8 +- biogeochem/EDPatchDynamicsMod.F90 | 108 +++++++++++-------------- main/FatesHistoryInterfaceMod.F90 | 6 +- 4 files changed, 108 insertions(+), 88 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 93af25cb01..b7c4209faf 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -220,8 +220,12 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & ! but suffer from forest degradation (i.e. they ! are moved to newly-anthro-disturbed secondary ! forest patch) - integer, intent(out) :: harvest_tag(:) ! tag to record the harvest status, 0 - successful; + integer, intent(out) :: harvest_tag(:) ! tag to record the harvest status + ! for the calculation of harvest debt in C-based + ! harvest mode + ! 0 - successful; ! 1 - unsuccessful since not enough carbon + ! 2 - not applicable ! Local variables integer :: cur_harvest_tag ! the harvest tag of the cohort today @@ -262,9 +266,9 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & call get_harvest_rate_area (patch_anthro_disturbance_label, hlm_harvest_catnames, & hlm_harvest_rates, frac_site_primary, secondary_age, harvest_rate) - ! For area-based harvest, harvest_tag shall always be 0. - harvest_tag = 0 - cur_harvest_tag = 0 + ! For area-based harvest, harvest_tag shall always be 2 (not applicable). + harvest_tag = 2 + cur_harvest_tag = 2 if (fates_global_verbose()) then write(fates_log(), *) 'Successfully Read Harvest Rate from HLM.' @@ -456,8 +460,8 @@ subroutine get_harvestable_carbon (csite, site_area, hlm_harvest_catnames, harve ! Local Variables type(ed_patch_type), pointer :: currentPatch type(ed_cohort_type), pointer :: currentCohort - real(r8) :: harvestable_patch_c ! temporary variable, kgC site-1 - real(r8) :: harvestable_cohort_c ! temporary variable, kgC site-1 + real(r8) :: harvestable_patch_c ! patch level total carbon available for harvest, kgC site-1 + real(r8) :: harvestable_cohort_c ! cohort level total carbon available for harvest, kgC site-1 real(r8) :: sapw_m ! Biomass of sap wood real(r8) :: struct_m ! Biomass of structural organs integer :: pft ! Index of plant functional type @@ -562,50 +566,73 @@ subroutine get_harvest_rate_carbon (patch_anthro_disturbance_label, hlm_harvest_ real(r8) :: harvest_rate_c ! Temporary variable, kgC site-1 real(r8) :: harvest_rate_supply ! Temporary variable, kgC site-1 - ! Loop around harvest categories to determine the hlm harvest rate demand and actual harvest rate for the + ! This subroutine follows the same logic of get_harvest_rate_area + ! Loop over harvest categories to determine the hlm harvest rate demand and actual harvest rate for the ! current cohort based on patch history info + + ! Initialize local variables harvest_rate = 0._r8 harvest_rate_c = 0._r8 harvest_rate_supply = 0._r8 - harvest_tag(:) = 1 + harvest_tag(:) = 2 + ! Since we have five harvest categories from forcing data but in FATES non-forest harvest + ! is merged with forest harvest, we only have three logging type in FATES (primary, secondary + ! mature and secondary young). + ! Get the harvest rate from HLM do h_index = 1,hlm_num_lu_harvest_cats if (patch_anthro_disturbance_label .eq. primaryforest) then if(hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1" .or. & hlm_harvest_catnames(h_index) .eq. "HARVEST_VH2") then harvest_rate_c = harvest_rate_c + hlm_harvest_rates(h_index) - ! Determine the total supply of available C for harvest - if(harvestable_forest_c(h_index) >= harvest_rate_c) then - harvest_rate_supply = harvest_rate_supply + harvestable_forest_c(h_index) - harvest_tag(h_index) = 0 - else - harvest_tag(h_index) = 1 - end if endif else if (patch_anthro_disturbance_label .eq. secondaryforest .and. & secondary_age >= secondary_age_threshold) then if(hlm_harvest_catnames(h_index) .eq. "HARVEST_SH1") then harvest_rate_c = harvest_rate_c + hlm_harvest_rates(h_index) + endif + else if (patch_anthro_disturbance_label .eq. secondaryforest .and. & + secondary_age < secondary_age_threshold) then + if(hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2" .or. & + hlm_harvest_catnames(h_index) .eq. "HARVEST_SH3") then + harvest_rate_c = harvest_rate_c + hlm_harvest_rates(h_index) + endif + endif + end do + + ! Determine harvest status (succesful or not) + ! Here only three categories are used + do h_index = 1,hlm_num_lu_harvest_cats + if (patch_anthro_disturbance_label .eq. primaryforest) then + if(hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1" ) then if(harvestable_forest_c(h_index) >= harvest_rate_c) then harvest_rate_supply = harvest_rate_supply + harvestable_forest_c(h_index) harvest_tag(h_index) = 0 else harvest_tag(h_index) = 1 end if - endif + end if else if (patch_anthro_disturbance_label .eq. secondaryforest .and. & - secondary_age < secondary_age_threshold) then - if(hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2" .or. & - hlm_harvest_catnames(h_index) .eq. "HARVEST_SH3") then - harvest_rate_c = harvest_rate_c + hlm_harvest_rates(h_index) + secondary_age >= secondary_age_threshold) then + if(hlm_harvest_catnames(h_index) .eq. "HARVEST_SH1" ) then if(harvestable_forest_c(h_index) >= harvest_rate_c) then harvest_rate_supply = harvest_rate_supply + harvestable_forest_c(h_index) harvest_tag(h_index) = 0 else harvest_tag(h_index) = 1 end if - endif - endif + end if + else if (patch_anthro_disturbance_label .eq. secondaryforest .and. & + secondary_age < secondary_age_threshold) then + if(hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2" ) then + if(harvestable_forest_c(h_index) >= harvest_rate_c) then + harvest_rate_supply = harvest_rate_supply + harvestable_forest_c(h_index) + harvest_tag(h_index) = 0 + else + harvest_tag(h_index) = 1 + end if + end if + end if end do ! If any harvest category available, assign to cur_harvest_tag and trigger logging event @@ -617,7 +644,8 @@ subroutine get_harvest_rate_carbon (patch_anthro_disturbance_label, hlm_harvest_ if (harvest_rate_supply > rsnbl_math_prec .and. harvest_rate_supply > harvest_rate_c) then harvest_rate = harvest_rate_c / harvest_rate_supply else - harvest_rate = 0._r8 + ! Force to harvest the whole cohort + harvest_rate = 1._r8 end if ! Prevent the generation of tiny secondary patches diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index 8f4009512b..65a26c8ced 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -234,8 +234,12 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_pr real(r8), intent(in) :: frac_site_primary real(r8), intent(in) :: harvestable_forest_c(:) ! total carbon available for logging, kgC site-1 - integer, intent(inout) :: harvest_tag(:) - + integer, intent(out) :: harvest_tag(:) ! tag to record the harvest status + ! for the calculation of harvest debt in C-based + ! harvest mode + ! 0 - successful; + ! 1 - unsuccessful since not enough carbon + ! 2 - not applicable ! ! !LOCAL VARIABLES: real(r8) :: cmort ! starvation mortality rate (fraction per year) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 374b5a92ad..b2ad741b7d 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -194,10 +194,11 @@ subroutine disturbance_rates( site_in, bc_in) real(r8) :: frac_site_primary real(r8) :: harvest_rate real(r8) :: tempsum + real(r8) :: harvest_debt_pri + real(r8) :: harvest_debt_sec_mature + real(r8) :: harvest_debt_sec_young real(r8) :: harvestable_forest_c(hlm_num_lu_harvest_cats) integer :: harvest_tag(hlm_num_lu_harvest_cats) - integer :: harvest_debt_primary - integer :: harvest_debt_secondary integer :: patch_no_secondary !---------------------------------------------------------------------------------------------- @@ -211,10 +212,11 @@ subroutine disturbance_rates( site_in, bc_in) ! get available biomass for harvest for all patches call get_harvestable_carbon(site_in, bc_in%site_area, bc_in%hlm_harvest_catnames, harvestable_forest_c) - - harvest_debt_primary = 0 - harvest_debt_secondary = 0 + ! Initialize local variables patch_no_secondary = 0 + harvest_debt_pri = 0._r8 + harvest_debt_sec_mature = 0._r8 + harvest_debt_sec_young = 0._r8 currentPatch => site_in%oldest_patch do while (associated(currentPatch)) @@ -256,70 +258,56 @@ subroutine disturbance_rates( site_in, bc_in) currentCohort => currentCohort%taller end do - ! Determine harvest debt for primary land and secondary land - ! Harvest debt is the accumulated total carbon amount once - ! available carbon for harvest is smaller than the harvest - ! rate of forcing data for each site. - ! Each cohort has the same harvest tag but not each patch - ! Hence this part shall be within the patch loop - ! TODO: we can define harvest debt as a fraction of the - ! harvest rate in the future - ! Warning: Non-forest harvest is not accounted for yet - ! Thus the harvest tag for non-forest are not effective - if(logging_time) then - harvest_debt_loop: do h_index = 1, hlm_num_lu_harvest_cats - ! Primary patch: Once a patch has debt, skip the calculation - if (harvest_debt_primary == 0) then - if ( currentPatch%anthro_disturbance_label .eq. primaryforest ) then - if ( harvest_tag(h_index) == 1 ) then - ! h_index points to primary forest harvest - if((bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1")) then - harvest_debt_primary = 1 - exit harvest_debt_loop - end if - end if - end if - end if - ! Secondary patch - if (harvest_debt_secondary == 0) then - if ( currentPatch%anthro_disturbance_label .eq. secondaryforest ) then - patch_no_secondary = patch_no_secondary + 1 - if ( harvest_tag(h_index) == 1 ) then - ! h_index points to secondary forest harvest - if((bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH1") .or. & - (bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2")) then - harvest_debt_secondary = 1 - exit harvest_debt_loop - end if - end if - end if - end if - end do harvest_debt_loop - end if + ! ! Counter of secondary patch used in logging debt calculation + ! if ( currentPatch%anthro_disturbance_label .eq. secondaryforest ) then + ! patch_no_secondary = patch_no_secondary + 1 + ! end if currentPatch => currentPatch%younger end do - ! Obatin actual harvest debt. This shall be outside the patch loop + ! Calculate if we have harvest debt for primary and secondary land + ! Harvest debt is the accumulated total carbon + ! deficiency once the carbon amount available for harvest + ! is smaller than the harvest rate of forcing data. + ! Harvest debt is calculated on site level + ! TODO: we can define harvest debt as a fraction of the + ! harvest rate in the future + ! Note 1: Non-forest harvest is accounted for under forest + ! harvest, thus the harvest tag for non-forest is not applicable (= 2) + ! Note 2: Since we will completely harvest all forest C from patches + ! with debt, the harvest debt shall subtract the harvestable forest C + if(logging_time) then + ! First we need to get harvest rate for all three categories do h_index = 1, hlm_num_lu_harvest_cats - if ( harvest_debt_primary == 1 ) then - ! Only account for primary forest harvest rate - if((bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1") .or. & - (bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_VH2")) then - site_in%resources_management%harvest_debt = site_in%resources_management%harvest_debt + & - bc_in%hlm_harvest_rates(h_index) - end if + ! Primary forest harvest rate + if(bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1" .or. & + bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_VH2" ) then + harvest_debt_pri = harvest_debt_pri + bc_in%hlm_harvest_rates(h_index) + else if(bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH1") then + harvest_debt_sec_mature = harvest_debt_sec_mature + bc_in%hlm_harvest_rates(h_index) + else if(bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2" .or. & + bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH3") then + harvest_debt_sec_mature = harvest_debt_sec_mature + bc_in%hlm_harvest_rates(h_index) end if - if (harvest_debt_secondary == 1 .or. patch_no_secondary == 0) then - ! Only account for secondary forest harvest rate - if((bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH1") .or. & - (bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2") .or. & - (bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH3")) then + end do + ! Next we get the harvest debt through the harvest tag + do h_index = 1, hlm_num_lu_harvest_cats + if (harvest_tag(h_index) .eq. 1) then + if(bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1") then + site_in%resources_management%harvest_debt = site_in%resources_management%harvest_debt + & + harvest_debt_pri - harvestable_forest_c(h_index) + else if(bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH1") then + site_in%resources_management%harvest_debt = site_in%resources_management%harvest_debt + & + harvest_debt_sec_mature - harvestable_forest_c(h_index) + site_in%resources_management%harvest_debt_sec = site_in%resources_management%harvest_debt_sec + & + harvest_debt_sec_mature - harvestable_forest_c(h_index) + else if(bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2") then site_in%resources_management%harvest_debt = site_in%resources_management%harvest_debt + & - bc_in%hlm_harvest_rates(h_index) + harvest_debt_sec_young - harvestable_forest_c(h_index) site_in%resources_management%harvest_debt_sec = site_in%resources_management%harvest_debt_sec + & - bc_in%hlm_harvest_rates(h_index) + harvest_debt_sec_young - harvestable_forest_c(h_index) end if end if end do diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 8b8fb053e1..acc32afba4 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -4839,20 +4839,20 @@ subroutine define_history_vars(this, initialize_variables) call this%set_history_var(vname='FATES_SECONDARY_FOREST_FRACTION', & units='m2 m-2', long='secondary forest fraction', & - use_default='inactive', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_fraction_secondary_forest_si) call this%set_history_var(vname='FATES_WOOD_PRODUCT', units='kg m-2', & long='total wood product from logging in kg carbon per m2 land area', & - use_default='inactive', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_woodproduct_si) call this%set_history_var(vname='FATES_SECONDARY_FOREST_VEGC', & units='kg m-2', & long='biomass on secondary lands in kg carbon per m2 land area (mult by FATES_SECONDARY_FOREST_FRACTION to get per secondary forest area)', & - use_default='inactive', avgflag='A', vtype=site_r8, & + use_default='active', avgflag='A', vtype=site_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_biomass_secondary_forest_si) From 0445ecce824ba939082b4a3f2b171b494e16494d Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 10 Nov 2022 16:46:09 -0800 Subject: [PATCH 425/852] initialize crowndamage for the temp cohort for sp mode as well --- main/EDInitMod.F90 | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 77d75f86b3..b8697ed6c7 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -808,8 +808,11 @@ subroutine init_cohorts( site_in, patch_in, bc_in) temp_cohort%canopy_trim = 1.0_r8 - ! h,dbh,leafc,n from SP values or from small initial size. + ! Assume no damage to begin with - since we assume no damage + ! we do not need to initialise branch frac just yet. + temp_cohort%crowndamage = 1 + ! h,dbh,leafc,n from SP values or from small initial size. if(hlm_use_sp.eq.itrue)then init = itrue ! At this point, we do not know the bc_in values of tlai tsai and htop, @@ -820,10 +823,6 @@ subroutine init_cohorts( site_in, patch_in, bc_in) else temp_cohort%hite = EDPftvarcon_inst%hgt_min(pft) - ! Assume no damage to begin with - since we assume no damage - ! we do not need to initialise branch frac just yet. - temp_cohort%crowndamage = 1 - ! Calculate the plant diameter from height call h2d_allom(temp_cohort%hite,pft,temp_cohort%dbh) From ba57f9ed3a82991761c0d03bc6bf9b1e5e1510ba Mon Sep 17 00:00:00 2001 From: jkshuman Date: Fri, 11 Nov 2022 13:51:23 -0700 Subject: [PATCH 426/852] Update biogeochem/EDPatchDynamicsMod.F90 --- biogeochem/EDPatchDynamicsMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 156cf443e1..6b245ba011 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -859,7 +859,7 @@ subroutine spawn_patches( currentSite, bc_in) do el = 1,num_elements leaf_m = nc%prt%GetState(leaf_organ, element_list(el)) - ! for grasses burn all aboveground tissues, for woody plants burn only leaves + ! for woody plants burn only leaves if(int(prt_params%woody(currentCohort%pft)) == itrue)then leaf_m = nc%prt%GetState(leaf_organ, element_list(el)) From 7ed8792976df40fe4bce1e57886a1df050d4e75d Mon Sep 17 00:00:00 2001 From: jkshuman Date: Fri, 11 Nov 2022 13:51:32 -0700 Subject: [PATCH 427/852] Update biogeochem/EDPatchDynamicsMod.F90 --- biogeochem/EDPatchDynamicsMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 6b245ba011..19ab67c748 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -865,7 +865,7 @@ subroutine spawn_patches( currentSite, bc_in) leaf_m = nc%prt%GetState(leaf_organ, element_list(el)) else - + ! for grasses burn all aboveground tissues leaf_m = nc%prt%GetState(leaf_organ, element_list(el)) + & nc%prt%GetState(sapw_organ, element_list(el)) + & nc%prt%GetState(struct_organ, element_list(el)) From 81732ffc9550adad74a9bb0dfc7552c14eea2336 Mon Sep 17 00:00:00 2001 From: jkshuman Date: Fri, 11 Nov 2022 13:51:46 -0700 Subject: [PATCH 428/852] Update biogeochem/EDPatchDynamicsMod.F90 --- biogeochem/EDPatchDynamicsMod.F90 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 19ab67c748..fb6efea769 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1661,8 +1661,7 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & repro_m = currentCohort%prt%GetState(repro_organ, element_id) if (prt_params%woody(currentCohort%pft) == itrue) then - ! Assumption: for woody plants, we lump fluxes from deadwood and sapwood together in CWD pool. - ! for non-woody plants, we put all stem fluxes into the same leaf litter pool. + ! Assumption: for woody plants fluxes from deadwood and sapwood go together in CWD pool leaf_m = currentCohort%prt%GetState(leaf_organ,element_id) sapw_m = currentCohort%prt%GetState(sapw_organ,element_id) struct_m = currentCohort%prt%GetState(struct_organ,element_id) From ef47c5cf5e3a786379027ad256469b85bfe93e36 Mon Sep 17 00:00:00 2001 From: jkshuman Date: Fri, 11 Nov 2022 13:51:55 -0700 Subject: [PATCH 429/852] Update biogeochem/EDPatchDynamicsMod.F90 --- biogeochem/EDPatchDynamicsMod.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index fb6efea769..a5b49a64ae 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1666,6 +1666,7 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & sapw_m = currentCohort%prt%GetState(sapw_organ,element_id) struct_m = currentCohort%prt%GetState(struct_organ,element_id) else + ! for non-woody plants all stem fluxes go into the same leaf litter pool leaf_m = currentCohort%prt%GetState(leaf_organ,element_id) + & currentCohort%prt%GetState(sapw_organ,element_id) + & currentCohort%prt%GetState(struct_organ,element_id) From 64dc01a4425905848d934645ba11b891a60e3bfd Mon Sep 17 00:00:00 2001 From: jkshuman Date: Fri, 11 Nov 2022 13:52:04 -0700 Subject: [PATCH 430/852] Update biogeochem/EDPatchDynamicsMod.F90 --- biogeochem/EDPatchDynamicsMod.F90 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index a5b49a64ae..d9bbfdc834 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1859,8 +1859,7 @@ subroutine mortality_litter_fluxes(currentSite, currentPatch, & repro_m = currentCohort%prt%GetState(repro_organ, element_id) if (prt_params%woody(currentCohort%pft) == itrue) then - ! Assumption: for woody plants, we lump fluxes from deadwood and sapwood together in CWD pool. - ! for non-woody plants, we put all stem fluxes into the same leaf litter pool. + ! Assumption: for woody plants fluxes from deadwood and sapwood go together in CWD pool leaf_m = currentCohort%prt%GetState(leaf_organ,element_id) sapw_m = currentCohort%prt%GetState(sapw_organ,element_id) struct_m = currentCohort%prt%GetState(struct_organ,element_id) From 1e90789fa26a510bf0b12111f0b34f9b173eba51 Mon Sep 17 00:00:00 2001 From: jkshuman Date: Fri, 11 Nov 2022 13:52:41 -0700 Subject: [PATCH 431/852] Update biogeochem/EDPatchDynamicsMod.F90 --- biogeochem/EDPatchDynamicsMod.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index d9bbfdc834..f95a09d442 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1864,6 +1864,7 @@ subroutine mortality_litter_fluxes(currentSite, currentPatch, & sapw_m = currentCohort%prt%GetState(sapw_organ,element_id) struct_m = currentCohort%prt%GetState(struct_organ,element_id) else + ! for non-woody plants all stem fluxes go into the same leaf litter pool leaf_m = currentCohort%prt%GetState(leaf_organ,element_id) + & currentCohort%prt%GetState(sapw_organ,element_id) + & currentCohort%prt%GetState(struct_organ,element_id) From 7f0231088715458d9cf2ab46c3d6bbd7ba528c97 Mon Sep 17 00:00:00 2001 From: jkshuman Date: Fri, 11 Nov 2022 13:52:50 -0700 Subject: [PATCH 432/852] Update biogeochem/EDPhysiologyMod.F90 --- biogeochem/EDPhysiologyMod.F90 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index cfa5c83f6c..4cb66045ae 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2205,8 +2205,7 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) repro_m = currentCohort%prt%GetState(repro_organ,element_id) if (prt_params%woody(currentCohort%pft) == itrue) then - ! Assumption: for woody plants, we lump fluxes from deadwood and sapwood together in CWD pool. - ! for non-woody plants, we put all stem fluxes into the same leaf litter pool. + ! Assumption: for woody plants fluxes from deadwood and sapwood go together in CWD pool leaf_m_turnover = currentCohort%prt%GetTurnover(leaf_organ,element_id) sapw_m_turnover = currentCohort%prt%GetTurnover(sapw_organ,element_id) struct_m_turnover = currentCohort%prt%GetTurnover(struct_organ,element_id) From bf7dea44f77199afd7832e141a4b092dac44d272 Mon Sep 17 00:00:00 2001 From: jkshuman Date: Fri, 11 Nov 2022 13:52:57 -0700 Subject: [PATCH 433/852] Update biogeochem/EDPhysiologyMod.F90 --- biogeochem/EDPhysiologyMod.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 4cb66045ae..5ed53dfec9 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2214,6 +2214,7 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) sapw_m = currentCohort%prt%GetState(sapw_organ,element_id) struct_m = currentCohort%prt%GetState(struct_organ,element_id) else + ! for non-woody plants all stem fluxes go into the same leaf litter pool leaf_m_turnover = currentCohort%prt%GetTurnover(leaf_organ,element_id) + & currentCohort%prt%GetTurnover(sapw_organ,element_id) + & currentCohort%prt%GetTurnover(struct_organ,element_id) From 935f601c4a47aa46bebeacd3ec145e15133c40d2 Mon Sep 17 00:00:00 2001 From: jkshuman Date: Fri, 11 Nov 2022 13:53:09 -0700 Subject: [PATCH 434/852] Update fire/SFMainMod.F90 --- fire/SFMainMod.F90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index f8e07d4c73..d5bdfdf2d7 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -192,7 +192,8 @@ subroutine charecteristics_of_fuel ( currentSite ) currentPatch%livegrass = 0.0_r8 currentCohort => currentPatch%tallest do while(associated(currentCohort)) - if( prt_params%woody(currentCohort%pft) == ifalse)then + ! for grasses sum all aboveground tissues + if( prt_params%woody(currentCohort%pft) == ifalse)then currentPatch%livegrass = currentPatch%livegrass + & ( currentCohort%prt%GetState(leaf_organ, all_carbon_elements) + & From 1a8a24b0a80fcc3bca6e1536edbfea36c5ce656d Mon Sep 17 00:00:00 2001 From: jkshuman Date: Fri, 11 Nov 2022 13:53:16 -0700 Subject: [PATCH 435/852] Update fire/SFMainMod.F90 --- fire/SFMainMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index d5bdfdf2d7..9f4188f3dd 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -765,7 +765,7 @@ subroutine area_burnt_intensity ( currentSite, bc_in ) lb = (1.0_r8 + (8.729_r8 * & ((1.0_r8 -(exp(-0.03_r8 * m_per_min__to__km_per_hour * currentPatch%effect_wspeed)))**2.155_r8))) else ! EQ 80 grass fuels (CFFBPS Ont.Inf.Rep. ST-X-3, 1992, but with a correction from an errata published within - ! Information Report GLC-X-10 by Wotten et al., 2009 because there is a typo in CFFBPS Ont.Inf.Rep. ST-X-3, 1992) + ! Information Report GLC-X-10 by Wotton et al., 2009 for a typo in CFFBPS Ont.Inf.Rep. ST-X-3, 1992) lb = (1.1_r8*((m_per_min__to__km_per_hour * currentPatch%effect_wspeed)**0.464_r8)) endif endif From b62fe84cbfd29ddafc116d07b380ce98490e8026 Mon Sep 17 00:00:00 2001 From: Shijie Shu Date: Fri, 11 Nov 2022 15:01:46 -0800 Subject: [PATCH 436/852] Change back EDPatchDynamicsMod.F90 for sanity purpose. --- biogeochem/EDLoggingMortalityMod.F90 | 6 +- biogeochem/EDPatchDynamicsMod.F90 | 1375 +++++++++++++------------- 2 files changed, 691 insertions(+), 690 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index e1736b9495..4e2da8d83c 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -642,8 +642,10 @@ subroutine get_harvest_rate_carbon (patch_anthro_disturbance_label, hlm_harvest_ if (harvest_rate_supply > rsnbl_math_prec .and. harvest_rate_supply > harvest_rate_c) then harvest_rate = harvest_rate_c / harvest_rate_supply else - ! Force to harvest the whole cohort - harvest_rate = 1._r8 + ! If we force harvest rate to 1 when we don't have enough C, we will produce + ! primary patch with no area, which cannot be terminated under nocomp mode. + ! So we still keep the harvest rate to 0 for now. + harvest_rate = 0._r8 end if ! Prevent the generation of tiny secondary patches diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index b2ad741b7d..c0f6ade5e3 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -162,6 +162,7 @@ subroutine disturbance_rates( site_in, bc_in) ! !USES: use EDMortalityFunctionsMod , only : mortality_rates + use EDMortalityFunctionsMod , only : ExemptTreefallDist ! loging flux use EDLoggingMortalityMod , only : LoggingMortality_frac @@ -273,10 +274,8 @@ subroutine disturbance_rates( site_in, bc_in) ! Harvest debt is calculated on site level ! TODO: we can define harvest debt as a fraction of the ! harvest rate in the future - ! Note 1: Non-forest harvest is accounted for under forest + ! Note: Non-forest harvest is accounted for under forest ! harvest, thus the harvest tag for non-forest is not applicable (= 2) - ! Note 2: Since we will completely harvest all forest C from patches - ! with debt, the harvest debt shall subtract the harvestable forest C if(logging_time) then ! First we need to get harvest rate for all three categories @@ -297,17 +296,17 @@ subroutine disturbance_rates( site_in, bc_in) if (harvest_tag(h_index) .eq. 1) then if(bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1") then site_in%resources_management%harvest_debt = site_in%resources_management%harvest_debt + & - harvest_debt_pri - harvestable_forest_c(h_index) + harvest_debt_pri else if(bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH1") then site_in%resources_management%harvest_debt = site_in%resources_management%harvest_debt + & - harvest_debt_sec_mature - harvestable_forest_c(h_index) + harvest_debt_sec_mature site_in%resources_management%harvest_debt_sec = site_in%resources_management%harvest_debt_sec + & - harvest_debt_sec_mature - harvestable_forest_c(h_index) + harvest_debt_sec_mature else if(bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2") then site_in%resources_management%harvest_debt = site_in%resources_management%harvest_debt + & - harvest_debt_sec_young - harvestable_forest_c(h_index) + harvest_debt_sec_young site_in%resources_management%harvest_debt_sec = site_in%resources_management%harvest_debt_sec + & - harvest_debt_sec_young - harvestable_forest_c(h_index) + harvest_debt_sec_young end if end if end do @@ -348,10 +347,12 @@ subroutine disturbance_rates( site_in, bc_in) if(currentCohort%canopy_layer == 1)then - ! Treefall Disturbance Rate - currentPatch%disturbance_rates(dtype_ifall) = currentPatch%disturbance_rates(dtype_ifall) + & - fates_mortality_disturbance_fraction * & - min(1.0_r8,currentCohort%dmort)*hlm_freq_day*currentCohort%c_area/currentPatch%area + ! Treefall Disturbance Rate. Only count this for trees, not grasses + if ( .not. ExemptTreefallDist(currentCohort) ) then + currentPatch%disturbance_rates(dtype_ifall) = currentPatch%disturbance_rates(dtype_ifall) + & + fates_mortality_disturbance_fraction * & + min(1.0_r8,currentCohort%dmort)*hlm_freq_day*currentCohort%c_area/currentPatch%area + end if ! Logging Disturbance Rate currentPatch%disturbance_rates(dtype_ilog) = currentPatch%disturbance_rates(dtype_ilog) + & @@ -361,6 +362,11 @@ subroutine disturbance_rates( site_in, bc_in) currentCohort%l_degrad ) * & currentCohort%c_area/currentPatch%area + if(currentPatch%disturbance_rates(dtype_ilog)>1.0) then + write(fates_log(),*) 'See luc mortalities:', currentCohort%lmort_direct, & + currentCohort%lmort_collateral, currentCohort%lmort_infra, currentCohort%l_degrad + end if + ! Non-harvested part of the logging disturbance rate dist_rate_ldist_notharvested = dist_rate_ldist_notharvested + currentCohort%l_degrad * & currentCohort%c_area/currentPatch%area @@ -370,7 +376,7 @@ subroutine disturbance_rates( site_in, bc_in) enddo !currentCohort ! for non-closed-canopy areas subject to logging, add an additional increment of area disturbed - ! equivalent to the fradction logged to account for transfer of interstitial ground area to new secondary lands + ! equivalent to the fraction logged to account for transfer of interstitial ground area to new secondary lands if ( logging_time .and. & (currentPatch%area - currentPatch%total_canopy_area) .gt. fates_tiny ) then ! The canopy is NOT closed. @@ -392,11 +398,6 @@ subroutine disturbance_rates( site_in, bc_in) (currentPatch%area - currentPatch%total_canopy_area) * harvest_rate / currentPatch%area endif - ! For nocomp mode, we need to prevent producing too small patches, which may produce small patches - if(hlm_use_nocomp .and. currentPatch%disturbance_rates(dtype_ilog)*currentPatch%area < min_patch_area_forced ) then - currentPatch%disturbance_rates(dtype_ilog) = 0._r8 - end if - ! fraction of the logging disturbance rate that is non-harvested if (currentPatch%disturbance_rates(dtype_ilog) .gt. nearzero) then currentPatch%fract_ldist_not_harvested = dist_rate_ldist_notharvested / & @@ -418,6 +419,7 @@ subroutine disturbance_rates( site_in, bc_in) call FatesWarn(msg,index=2) endif + ! if the sum of all disturbance rates is such that they will exceed total patch area on this day, then reduce them all proportionally. if ( sum(currentPatch%disturbance_rates(:)) .gt. 1.0_r8 ) then tempsum = sum(currentPatch%disturbance_rates(:)) do i_dist = 1,N_DIST_TYPES @@ -510,719 +512,721 @@ subroutine spawn_patches( currentSite, bc_in) ! in the nocomp cases, since every patch has a PFT identity, it can only receive patch area from patches ! that have the same identity. In order to allow this, we have this very high level loop over nocomp PFTs - ! and only do the disturbance for any patches that have that nocomp PFT identity. + ! and only do the disturbance for any patches that have that nocomp PFT identity. ! If nocomp is not enabled, then this is not much of a loop, it only passes through once. nocomp_pft_loop: do i_nocomp_pft = min_nocomp_pft,max_nocomp_pft - disturbance_type_loop: do i_disturbance_type = 1,N_DIST_TYPES + disturbance_type_loop: do i_disturbance_type = 1,N_DIST_TYPES - ! calculate area of disturbed land, in this timestep, by summing contributions from each existing patch. - currentPatch => currentSite%youngest_patch + ! calculate area of disturbed land, in this timestep, by summing contributions from each existing patch. + currentPatch => currentSite%youngest_patch - site_areadis_primary = 0.0_r8 - site_areadis_secondary = 0.0_r8 + site_areadis_primary = 0.0_r8 + site_areadis_secondary = 0.0_r8 - do while(associated(currentPatch)) + do while(associated(currentPatch)) - cp_nocomp_matches_1_if: if ( hlm_use_nocomp .eq. ifalse .or. & - currentPatch%nocomp_pft_label .eq. i_nocomp_pft ) then + cp_nocomp_matches_1_if: if ( hlm_use_nocomp .eq. ifalse .or. & + currentPatch%nocomp_pft_label .eq. i_nocomp_pft ) then - disturbance_rate = currentPatch%disturbance_rates(i_disturbance_type) + disturbance_rate = currentPatch%disturbance_rates(i_disturbance_type) - if(disturbance_rate > (1.0_r8 + rsnbl_math_prec)) then - write(fates_log(),*) 'patch disturbance rate > 1 ?',disturbance_rate - call dump_patch(currentPatch) - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + if(disturbance_rate > (1.0_r8 + rsnbl_math_prec)) then + write(fates_log(),*) 'patch disturbance rate > 1 ?',disturbance_rate + call dump_patch(currentPatch) + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if - ! Only create new patches that have non-negligible amount of land - if((currentPatch%area*disturbance_rate) > nearzero ) then - - ! figure out whether the receiver patch for disturbance from this patch will be - ! primary or secondary land receiver patch is primary forest only if both the - ! donor patch is primary forest and the current disturbance type is not logging - if ( currentPatch%anthro_disturbance_label .eq. primaryforest .and. & - (i_disturbance_type .ne. dtype_ilog) ) then - - site_areadis_primary = site_areadis_primary + currentPatch%area * disturbance_rate + ! Only create new patches that have non-negligible amount of land + if((currentPatch%area*disturbance_rate) > nearzero ) then - ! track disturbance rates to output to history - currentSite%disturbance_rates_primary_to_primary(i_disturbance_type) = & - currentSite%disturbance_rates_primary_to_primary(i_disturbance_type) + & - currentPatch%area * disturbance_rate * AREA_INV - else - site_areadis_secondary = site_areadis_secondary + currentPatch%area * disturbance_rate + ! figure out whether the receiver patch for disturbance from this patch will be + ! primary or secondary land receiver patch is primary forest only if both the + ! donor patch is primary forest and the current disturbance type is not logging + if ( currentPatch%anthro_disturbance_label .eq. primaryforest .and. & + (i_disturbance_type .ne. dtype_ilog) ) then - ! track disturbance rates to output to history - if (currentPatch%anthro_disturbance_label .eq. secondaryforest) then - currentSite%disturbance_rates_secondary_to_secondary(i_disturbance_type) = & - currentSite%disturbance_rates_secondary_to_secondary(i_disturbance_type) + & - currentPatch%area * disturbance_rate * AREA_INV - else - currentSite%disturbance_rates_primary_to_secondary(i_disturbance_type) = & - currentSite%disturbance_rates_primary_to_secondary(i_disturbance_type) + & - currentPatch%area * disturbance_rate * AREA_INV - endif + site_areadis_primary = site_areadis_primary + currentPatch%area * disturbance_rate - endif - - end if - - end if cp_nocomp_matches_1_if - currentPatch => currentPatch%older - enddo ! end loop over patches. sum area disturbed for all patches. + ! track disturbance rates to output to history + currentSite%disturbance_rates_primary_to_primary(i_disturbance_type) = & + currentSite%disturbance_rates_primary_to_primary(i_disturbance_type) + & + currentPatch%area * disturbance_rate * AREA_INV + else + site_areadis_secondary = site_areadis_secondary + currentPatch%area * disturbance_rate - ! It is possible that no disturbance area was generated - if ( (site_areadis_primary + site_areadis_secondary) > nearzero) then - - age = 0.0_r8 + ! track disturbance rates to output to history + if (currentPatch%anthro_disturbance_label .eq. secondaryforest) then + currentSite%disturbance_rates_secondary_to_secondary(i_disturbance_type) = & + currentSite%disturbance_rates_secondary_to_secondary(i_disturbance_type) + & + currentPatch%area * disturbance_rate * AREA_INV + else + currentSite%disturbance_rates_primary_to_secondary(i_disturbance_type) = & + currentSite%disturbance_rates_primary_to_secondary(i_disturbance_type) + & + currentPatch%area * disturbance_rate * AREA_INV + endif - ! create two empty patches, to absorb newly disturbed primary and secondary forest area - ! first create patch to receive primary forest area - if ( site_areadis_primary .gt. nearzero ) then - allocate(new_patch_primary) + endif - call create_patch(currentSite, new_patch_primary, age, & - site_areadis_primary, primaryforest, i_nocomp_pft) - - ! Initialize the litter pools to zero, these - ! pools will be populated by looping over the existing patches - ! and transfering in mass - do el=1,num_elements - call new_patch_primary%litter(el)%InitConditions(init_leaf_fines=0._r8, & - init_root_fines=0._r8, & - init_ag_cwd=0._r8, & - init_bg_cwd=0._r8, & - init_seed=0._r8, & - init_seed_germ=0._r8) - end do - new_patch_primary%tallest => null() - new_patch_primary%shortest => null() + end if - endif + end if cp_nocomp_matches_1_if + currentPatch => currentPatch%older + enddo ! end loop over patches. sum area disturbed for all patches. + + ! It is possible that no disturbance area was generated + if ( (site_areadis_primary + site_areadis_secondary) > nearzero) then + + age = 0.0_r8 + + ! create two empty patches, to absorb newly disturbed primary and secondary forest area + ! first create patch to receive primary forest area + if ( site_areadis_primary .gt. nearzero ) then + allocate(new_patch_primary) + + call create_patch(currentSite, new_patch_primary, age, & + site_areadis_primary, primaryforest, i_nocomp_pft) + + ! Initialize the litter pools to zero, these + ! pools will be populated by looping over the existing patches + ! and transfering in mass + do el=1,num_elements + call new_patch_primary%litter(el)%InitConditions(init_leaf_fines=0._r8, & + init_root_fines=0._r8, & + init_ag_cwd=0._r8, & + init_bg_cwd=0._r8, & + init_seed=0._r8, & + init_seed_germ=0._r8) + end do + new_patch_primary%tallest => null() + new_patch_primary%shortest => null() - ! next create patch to receive secondary forest area - if ( site_areadis_secondary .gt. nearzero) then - allocate(new_patch_secondary) - call create_patch(currentSite, new_patch_secondary, age, & - site_areadis_secondary, secondaryforest,i_nocomp_pft) - - ! Initialize the litter pools to zero, these - ! pools will be populated by looping over the existing patches - ! and transfering in mass - do el=1,num_elements - call new_patch_secondary%litter(el)%InitConditions(init_leaf_fines=0._r8, & - init_root_fines=0._r8, & - init_ag_cwd=0._r8, & - init_bg_cwd=0._r8, & - init_seed=0._r8, & - init_seed_germ=0._r8) - end do - new_patch_secondary%tallest => null() - new_patch_secondary%shortest => null() + endif - endif - - ! loop round all the patches that contribute surviving indivduals and litter - ! pools to the new patch. We only loop the pre-existing patches, so - ! quit the loop if the current patch is either null, or matches the - ! two new pointers. + ! next create patch to receive secondary forest area + if ( site_areadis_secondary .gt. nearzero) then + allocate(new_patch_secondary) + call create_patch(currentSite, new_patch_secondary, age, & + site_areadis_secondary, secondaryforest,i_nocomp_pft) + + ! Initialize the litter pools to zero, these + ! pools will be populated by looping over the existing patches + ! and transfering in mass + do el=1,num_elements + call new_patch_secondary%litter(el)%InitConditions(init_leaf_fines=0._r8, & + init_root_fines=0._r8, & + init_ag_cwd=0._r8, & + init_bg_cwd=0._r8, & + init_seed=0._r8, & + init_seed_germ=0._r8) + end do + new_patch_secondary%tallest => null() + new_patch_secondary%shortest => null() - currentPatch => currentSite%oldest_patch - do while(associated(currentPatch)) + endif - cp_nocomp_matches_2_if: if ( hlm_use_nocomp .eq. ifalse .or. & - currentPatch%nocomp_pft_label .eq. i_nocomp_pft ) then + ! loop round all the patches that contribute surviving indivduals and litter + ! pools to the new patch. We only loop the pre-existing patches, so + ! quit the loop if the current patch is either null, or matches the + ! two new pointers. - ! This is the amount of patch area that is disturbed, and donated by the donor - disturbance_rate = currentPatch%disturbance_rates(i_disturbance_type) - patch_site_areadis = currentPatch%area * disturbance_rate - - if ( patch_site_areadis > nearzero ) then - - ! figure out whether the receiver patch for disturbance from this patch - ! will be primary or secondary land receiver patch is primary forest - ! only if both the donor patch is primary forest and the current - ! disturbance type is not logging - if (currentPatch%anthro_disturbance_label .eq. primaryforest .and. & - (i_disturbance_type .ne. dtype_ilog)) then - new_patch => new_patch_primary - else - new_patch => new_patch_secondary - endif - - if(.not.associated(new_patch))then - write(fates_log(),*) 'Patch spawning has attempted to point to' - write(fates_log(),*) 'an un-allocated patch' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - ! for the case where the donating patch is secondary forest, if - ! the current disturbance from this patch is non-anthropogenic, - ! we need to average in the time-since-anthropogenic-disturbance - ! from the donor patch into that of the receiver patch - if ( currentPatch%anthro_disturbance_label .eq. secondaryforest .and. & - (i_disturbance_type .ne. dtype_ilog) ) then - - new_patch%age_since_anthro_disturbance = new_patch%age_since_anthro_disturbance + & - currentPatch%age_since_anthro_disturbance * (patch_site_areadis / site_areadis_secondary) + currentPatch => currentSite%oldest_patch + do while(associated(currentPatch)) - endif - - ! Transfer the litter existing already in the donor patch to the new patch - ! This call will only transfer non-burned litter to new patch - ! and burned litter to atmosphere. Thus it is important to zero burnt_frac_litter when - ! fire is not the current disturbance regime. + cp_nocomp_matches_2_if: if ( hlm_use_nocomp .eq. ifalse .or. & + currentPatch%nocomp_pft_label .eq. i_nocomp_pft ) then - if(i_disturbance_type .ne. dtype_ifire) then - currentPatch%burnt_frac_litter(:) = 0._r8 - end if + ! This is the amount of patch area that is disturbed, and donated by the donor + disturbance_rate = currentPatch%disturbance_rates(i_disturbance_type) + patch_site_areadis = currentPatch%area * disturbance_rate - call TransLitterNewPatch( currentSite, currentPatch, new_patch, patch_site_areadis) - ! Transfer in litter fluxes from plants in various contexts of death and destruction + if ( patch_site_areadis > nearzero ) then - if(i_disturbance_type .eq. dtype_ilog) then - call logging_litter_fluxes(currentSite, currentPatch, & - new_patch, patch_site_areadis,bc_in) - elseif(i_disturbance_type .eq. dtype_ifire) then - call fire_litter_fluxes(currentSite, currentPatch, & - new_patch, patch_site_areadis,bc_in) - else - call mortality_litter_fluxes(currentSite, currentPatch, & - new_patch, patch_site_areadis,bc_in) - endif + ! figure out whether the receiver patch for disturbance from this patch + ! will be primary or secondary land receiver patch is primary forest + ! only if both the donor patch is primary forest and the current + ! disturbance type is not logging + if (currentPatch%anthro_disturbance_label .eq. primaryforest .and. & + (i_disturbance_type .ne. dtype_ilog)) then + new_patch => new_patch_primary + else + new_patch => new_patch_secondary + endif + if(.not.associated(new_patch))then + write(fates_log(),*) 'Patch spawning has attempted to point to' + write(fates_log(),*) 'an un-allocated patch' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if - ! Copy any means or timers from the original patch to the new patch - ! These values will inherit all info from the original patch - ! -------------------------------------------------------------------------- - call new_patch%tveg24%CopyFromDonor(currentPatch%tveg24) - call new_patch%tveg_lpa%CopyFromDonor(currentPatch%tveg_lpa) - - - ! -------------------------------------------------------------------------- - ! The newly formed patch from disturbance (new_patch), has now been given - ! some litter from dead plants and pre-existing litter from the donor patches. - ! - ! Next, we loop through the cohorts in the donor patch, copy them with - ! area modified number density into the new-patch, and apply survivorship. - ! ------------------------------------------------------------------------- - - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - - allocate(nc) - if(hlm_use_planthydro.eq.itrue) call InitHydrCohort(CurrentSite,nc) - - ! Initialize the PARTEH object and point to the - ! correct boundary condition fields - nc%prt => null() - call InitPRTObject(nc%prt) - call InitPRTBoundaryConditions(nc) - - ! (Keeping as an example) - ! Allocate running mean functions - !allocate(nc%tveg_lpa) - !call nc%tveg_lpa%InitRMean(ema_lpa,init_value=new_patch%tveg_lpa%GetMean()) - - call zero_cohort(nc) - - ! nc is the new cohort that goes in the disturbed patch (new_patch)... currentCohort - ! is the curent cohort that stays in the donor patch (currentPatch) - call copy_cohort(currentCohort, nc) - - !this is the case as the new patch probably doesn't have a closed canopy, and - ! even if it does, that will be sorted out in canopy_structure. - nc%canopy_layer = 1 - nc%canopy_layer_yesterday = 1._r8 - - sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) - struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) - leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) - fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) - store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) - total_c = sapw_c + struct_c + leaf_c + fnrt_c + store_c - - ! treefall mortality is the current disturbance - if(i_disturbance_type .eq. dtype_ifall) then - - if(currentCohort%canopy_layer == 1)then - - ! In the donor patch we are left with fewer trees because the area has decreased - ! the plant density for large trees does not actually decrease in the donor patch - ! because this is the part of the original patch where no trees have actually fallen - ! The diagnostic cmort,bmort,hmort, and frmort rates have already been saved - - currentCohort%n = currentCohort%n * (1.0_r8 - fates_mortality_disturbance_fraction * & - min(1.0_r8,currentCohort%dmort * hlm_freq_day)) - - nc%n = 0.0_r8 ! kill all of the trees who caused the disturbance. - - nc%cmort = nan ! The mortality diagnostics are set to nan - ! because the cohort should dissappear - nc%hmort = nan - nc%bmort = nan - nc%frmort = nan - nc%smort = nan - nc%asmort = nan - nc%lmort_direct = nan - nc%lmort_collateral = nan - nc%lmort_infra = nan - nc%l_degrad = nan - - else - ! small trees - if( prt_params%woody(currentCohort%pft) == itrue)then - - - ! Survivorship of undestory woody plants. Two step process. - ! Step 1: Reduce current number of plants to reflect the - ! change in area. - ! The number density per square are doesn't change, - ! but since the patch is smaller and cohort counts - ! are absolute, reduce this number. - - nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - - ! because the mortality rate due to impact for the cohorts which - ! had been in the understory and are now in the newly- - ! disturbed patch is very high, passing the imort directly to history - ! results in large numerical errors, on account of the sharply - ! reduced number densities. so instead pass this info via a - ! site-level diagnostic variable before reducing the number density. - - currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) = & - currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) + & - nc%n * ED_val_understorey_death / hlm_freq_day - - - currentSite%imort_carbonflux(currentCohort%pft) = & - currentSite%imort_carbonflux(currentCohort%pft) + & - (nc%n * ED_val_understorey_death / hlm_freq_day ) * & - total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 - - ! Step 2: Apply survivor ship function based on the understory death fraction - ! remaining of understory plants of those that are knocked over - ! by the overstorey trees dying... - nc%n = nc%n * (1.0_r8 - ED_val_understorey_death) - - ! since the donor patch split and sent a fraction of its members - ! to the new patch and a fraction to be preserved in itself, - ! when reporting diagnostic rates, we must carry over the mortality rates from - ! the donor that were applied before the patch split. Remember this is only - ! for diagnostics. But think of it this way, the rates are weighted by - ! number density in EDCLMLink, and the number density of this new patch is donated - ! so with the number density must come the effective mortality rates. - - nc%cmort = currentCohort%cmort - nc%hmort = currentCohort%hmort - nc%bmort = currentCohort%bmort - nc%frmort = currentCohort%frmort - nc%smort = currentCohort%smort - nc%asmort = currentCohort%asmort - nc%dmort = currentCohort%dmort - nc%lmort_direct = currentCohort%lmort_direct - nc%lmort_collateral = currentCohort%lmort_collateral - nc%lmort_infra = currentCohort%lmort_infra - - ! understory trees that might potentially be knocked over in the disturbance. - ! The existing (donor) patch should not have any impact mortality, it should - ! only lose cohorts due to the decrease in area. This is not mortality. - ! Besides, the current and newly created patch sum to unity - - currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - - else - ! grass is not killed by mortality disturbance events. Just move it into the new patch area. - ! Just split the grass into the existing and new patch structures - nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - - ! Those remaining in the existing - currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - - nc%cmort = currentCohort%cmort - nc%hmort = currentCohort%hmort - nc%bmort = currentCohort%bmort - nc%frmort = currentCohort%frmort - nc%smort = currentCohort%smort - nc%asmort = currentCohort%asmort - nc%dmort = currentCohort%dmort - nc%lmort_direct = currentCohort%lmort_direct - nc%lmort_collateral = currentCohort%lmort_collateral - nc%lmort_infra = currentCohort%lmort_infra - - endif - endif - - ! Fire is the current disturbance - elseif (i_disturbance_type .eq. dtype_ifire ) then - - ! Number of members in the new patch, before we impose fire survivorship - nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - - ! loss of individuals from source patch due to area shrinking - currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - - levcan = currentCohort%canopy_layer - - if(levcan==ican_upper) then - - ! before changing number densities, track total rate of trees that died - ! due to fire, as well as from each fire mortality term - currentSite%fmort_rate_canopy(currentCohort%size_class, currentCohort%pft) = & - currentSite%fmort_rate_canopy(currentCohort%size_class, currentCohort%pft) + & - nc%n * currentCohort%fire_mort / hlm_freq_day - - currentSite%fmort_carbonflux_canopy(currentCohort%pft) = & - currentSite%fmort_carbonflux_canopy(currentCohort%pft) + & - (nc%n * currentCohort%fire_mort) * & - total_c * g_per_kg * days_per_sec * ha_per_m2 - - else - currentSite%fmort_rate_ustory(currentCohort%size_class, currentCohort%pft) = & - currentSite%fmort_rate_ustory(currentCohort%size_class, currentCohort%pft) + & - nc%n * currentCohort%fire_mort / hlm_freq_day - - currentSite%fmort_carbonflux_ustory(currentCohort%pft) = & - currentSite%fmort_carbonflux_ustory(currentCohort%pft) + & - (nc%n * currentCohort%fire_mort) * & - total_c * g_per_kg * days_per_sec * ha_per_m2 - end if - - currentSite%fmort_rate_cambial(currentCohort%size_class, currentCohort%pft) = & - currentSite%fmort_rate_cambial(currentCohort%size_class, currentCohort%pft) + & - nc%n * currentCohort%cambial_mort / hlm_freq_day - currentSite%fmort_rate_crown(currentCohort%size_class, currentCohort%pft) = & - currentSite%fmort_rate_crown(currentCohort%size_class, currentCohort%pft) + & - nc%n * currentCohort%crownfire_mort / hlm_freq_day - - ! loss of individual from fire in new patch. - nc%n = nc%n * (1.0_r8 - currentCohort%fire_mort) - - nc%cmort = currentCohort%cmort - nc%hmort = currentCohort%hmort - nc%bmort = currentCohort%bmort - nc%frmort = currentCohort%frmort - nc%smort = currentCohort%smort - nc%asmort = currentCohort%asmort - nc%dmort = currentCohort%dmort - nc%lmort_direct = currentCohort%lmort_direct - nc%lmort_collateral = currentCohort%lmort_collateral - nc%lmort_infra = currentCohort%lmort_infra - - - ! Some of of the leaf mass from living plants has been - ! burned off. Here, we remove that mass, and - ! tally it in the flux we sent to the atmosphere - - if(prt_params%woody(currentCohort%pft) == itrue)then - leaf_burn_frac = currentCohort%fraction_crown_burned - else + ! for the case where the donating patch is secondary forest, if + ! the current disturbance from this patch is non-anthropogenic, + ! we need to average in the time-since-anthropogenic-disturbance + ! from the donor patch into that of the receiver patch + if ( currentPatch%anthro_disturbance_label .eq. secondaryforest .and. & + (i_disturbance_type .ne. dtype_ilog) ) then - ! Grasses determine their fraction of leaves burned here + new_patch%age_since_anthro_disturbance = new_patch%age_since_anthro_disturbance + & + currentPatch%age_since_anthro_disturbance * (patch_site_areadis / site_areadis_secondary) - leaf_burn_frac = currentPatch%burnt_frac_litter(lg_sf) - endif - - ! Perform a check to make sure that spitfire gave - ! us reasonable mortality and burn fraction rates - - if( (leaf_burn_frac < 0._r8) .or. & - (leaf_burn_frac > 1._r8) .or. & - (currentCohort%fire_mort < 0._r8) .or. & - (currentCohort%fire_mort > 1._r8)) then - write(fates_log(),*) 'unexpected fire fractions' - write(fates_log(),*) prt_params%woody(currentCohort%pft) - write(fates_log(),*) leaf_burn_frac - write(fates_log(),*) currentCohort%fire_mort - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - do el = 1,num_elements - - leaf_m = nc%prt%GetState(leaf_organ, element_list(el)) - - currentSite%mass_balance(el)%burn_flux_to_atm = & - currentSite%mass_balance(el)%burn_flux_to_atm + & - leaf_burn_frac * leaf_m * nc%n - end do + endif - ! Here the mass is removed from the plant - call PRTBurnLosses(nc%prt, leaf_organ, leaf_burn_frac) - currentCohort%fraction_crown_burned = 0.0_r8 - nc%fraction_crown_burned = 0.0_r8 + ! Transfer the litter existing already in the donor patch to the new patch + ! This call will only transfer non-burned litter to new patch + ! and burned litter to atmosphere. Thus it is important to zero burnt_frac_litter when + ! fire is not the current disturbance regime. + if(i_disturbance_type .ne. dtype_ifire) then + currentPatch%burnt_frac_litter(:) = 0._r8 + end if + call TransLitterNewPatch( currentSite, currentPatch, new_patch, patch_site_areadis) - ! Logging is the current disturbance - elseif (i_disturbance_type .eq. dtype_ilog ) then - - ! If this cohort is in the upper canopy. It generated - if(currentCohort%canopy_layer == 1)then - - ! calculate the survivorship of disturbed trees because non-harvested - nc%n = currentCohort%n * currentCohort%l_degrad - ! nc%n = (currentCohort%l_degrad / (currentCohort%l_degrad + & - ! currentCohort%lmort_direct + currentCohort%lmort_collateral + - ! currentCohort%lmort_infra) ) * & - ! currentCohort%n * patch_site_areadis/currentPatch%area - - ! Reduce counts in the existing/donor patch according to the logging rate - currentCohort%n = currentCohort%n * & - (1.0_r8 - min(1.0_r8,(currentCohort%lmort_direct + & - currentCohort%lmort_collateral + & - currentCohort%lmort_infra + currentCohort%l_degrad))) - - nc%cmort = currentCohort%cmort - nc%hmort = currentCohort%hmort - nc%bmort = currentCohort%bmort - nc%frmort = currentCohort%frmort - nc%smort = currentCohort%smort - nc%asmort = currentCohort%asmort - nc%dmort = currentCohort%dmort - - ! since these are the ones that weren't logged, - ! set the logging mortality rates as zero - nc%lmort_direct = 0._r8 - nc%lmort_collateral = 0._r8 - nc%lmort_infra = 0._r8 - - else - - ! What to do with cohorts in the understory of a logging generated - ! disturbance patch? - - if(prt_params%woody(currentCohort%pft) == itrue)then - - - ! Survivorship of undestory woody plants. Two step process. - ! Step 1: Reduce current number of plants to reflect the - ! change in area. - ! The number density per square are doesn't change, - ! but since the patch is smaller - ! and cohort counts are absolute, reduce this number. - nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - - ! because the mortality rate due to impact for the cohorts which had - ! been in the understory and are now in the newly- - ! disturbed patch is very high, passing the imort directly to - ! history results in large numerical errors, on account - ! of the sharply reduced number densities. so instead pass this info - ! via a site-level diagnostic variable before reducing - ! the number density. - currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) = & - currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) + & - nc%n * currentPatch%fract_ldist_not_harvested * & - logging_coll_under_frac / hlm_freq_day - - currentSite%imort_carbonflux(currentCohort%pft) = & - currentSite%imort_carbonflux(currentCohort%pft) + & - (nc%n * currentPatch%fract_ldist_not_harvested * & - logging_coll_under_frac/ hlm_freq_day ) * & - total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 - - - ! Step 2: Apply survivor ship function based on the understory death fraction - - ! remaining of understory plants of those that are knocked - ! over by the overstorey trees dying... - ! LOGGING SURVIVORSHIP OF UNDERSTORY PLANTS IS SET AS A NEW PARAMETER - ! in the fatesparameter files - nc%n = nc%n * (1.0_r8 - & - (1.0_r8-currentPatch%fract_ldist_not_harvested) * logging_coll_under_frac) - - ! Step 3: Reduce the number count of cohorts in the - ! original/donor/non-disturbed patch to reflect the area change - currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - - nc%cmort = currentCohort%cmort - nc%hmort = currentCohort%hmort - nc%bmort = currentCohort%bmort - nc%frmort = currentCohort%frmort - nc%smort = currentCohort%smort - nc%asmort = currentCohort%asmort - nc%dmort = currentCohort%dmort - nc%lmort_direct = currentCohort%lmort_direct - nc%lmort_collateral = currentCohort%lmort_collateral - nc%lmort_infra = currentCohort%lmort_infra - + ! Transfer in litter fluxes from plants in various contexts of death and destruction + + if(i_disturbance_type .eq. dtype_ilog) then + call logging_litter_fluxes(currentSite, currentPatch, & + new_patch, patch_site_areadis,bc_in) + elseif(i_disturbance_type .eq. dtype_ifire) then + call fire_litter_fluxes(currentSite, currentPatch, & + new_patch, patch_site_areadis,bc_in) else - - ! grass is not killed by mortality disturbance events. - ! Just move it into the new patch area. - ! Just split the grass into the existing and new patch structures - nc%n = currentCohort%n * patch_site_areadis/currentPatch%area - - ! Those remaining in the existing - currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) - - ! No grass impact mortality imposed on the newly created patch - nc%cmort = currentCohort%cmort - nc%hmort = currentCohort%hmort - nc%bmort = currentCohort%bmort - nc%frmort = currentCohort%frmort - nc%smort = currentCohort%smort - nc%asmort = currentCohort%asmort - nc%dmort = currentCohort%dmort - nc%lmort_direct = currentCohort%lmort_direct - nc%lmort_collateral = currentCohort%lmort_collateral - nc%lmort_infra = currentCohort%lmort_infra - - endif ! is/is-not woody - - endif ! Select canopy layer - - else - write(fates_log(),*) 'unknown disturbance mode?' - write(fates_log(),*) 'i_disturbance_type: ', i_disturbance_type - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if ! Select disturbance mode - - if (nc%n > 0.0_r8) then - storebigcohort => new_patch%tallest - storesmallcohort => new_patch%shortest - if(associated(new_patch%tallest))then - tnull = 0 - else - tnull = 1 - new_patch%tallest => nc - nc%taller => null() - endif - - if(associated(new_patch%shortest))then - snull = 0 + call mortality_litter_fluxes(currentSite, currentPatch, & + new_patch, patch_site_areadis,bc_in) + endif + + + ! Copy any means or timers from the original patch to the new patch + ! These values will inherit all info from the original patch + ! -------------------------------------------------------------------------- + call new_patch%tveg24%CopyFromDonor(currentPatch%tveg24) + call new_patch%tveg_lpa%CopyFromDonor(currentPatch%tveg_lpa) + + + ! -------------------------------------------------------------------------- + ! The newly formed patch from disturbance (new_patch), has now been given + ! some litter from dead plants and pre-existing litter from the donor patches. + ! + ! Next, we loop through the cohorts in the donor patch, copy them with + ! area modified number density into the new-patch, and apply survivorship. + ! ------------------------------------------------------------------------- + + currentCohort => currentPatch%shortest + do while(associated(currentCohort)) + + allocate(nc) + if(hlm_use_planthydro.eq.itrue) call InitHydrCohort(CurrentSite,nc) + + ! Initialize the PARTEH object and point to the + ! correct boundary condition fields + nc%prt => null() + call InitPRTObject(nc%prt) + call InitPRTBoundaryConditions(nc) + + ! (Keeping as an example) + ! Allocate running mean functions + !allocate(nc%tveg_lpa) + !call nc%tveg_lpa%InitRMean(ema_lpa,init_value=new_patch%tveg_lpa%GetMean()) + + call zero_cohort(nc) + + ! nc is the new cohort that goes in the disturbed patch (new_patch)... currentCohort + ! is the curent cohort that stays in the donor patch (currentPatch) + call copy_cohort(currentCohort, nc) + + !this is the case as the new patch probably doesn't have a closed canopy, and + ! even if it does, that will be sorted out in canopy_structure. + nc%canopy_layer = 1 + nc%canopy_layer_yesterday = 1._r8 + + sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) + struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) + leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) + fnrt_c = currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) + store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) + total_c = sapw_c + struct_c + leaf_c + fnrt_c + store_c + + ! treefall mortality is the current disturbance + if(i_disturbance_type .eq. dtype_ifall) then + + if(currentCohort%canopy_layer == 1)then + + ! In the donor patch we are left with fewer trees because the area has decreased + ! the plant density for large trees does not actually decrease in the donor patch + ! because this is the part of the original patch where no trees have actually fallen + ! The diagnostic cmort,bmort,hmort, and frmort rates have already been saved + + currentCohort%n = currentCohort%n * (1.0_r8 - fates_mortality_disturbance_fraction * & + min(1.0_r8,currentCohort%dmort * hlm_freq_day)) + + nc%n = 0.0_r8 ! kill all of the trees who caused the disturbance. + + nc%cmort = nan ! The mortality diagnostics are set to nan + ! because the cohort should dissappear + nc%hmort = nan + nc%bmort = nan + nc%frmort = nan + nc%smort = nan + nc%asmort = nan + nc%lmort_direct = nan + nc%lmort_collateral = nan + nc%lmort_infra = nan + nc%l_degrad = nan + + else + ! small trees + if( prt_params%woody(currentCohort%pft) == itrue)then + + + ! Survivorship of undestory woody plants. Two step process. + ! Step 1: Reduce current number of plants to reflect the + ! change in area. + ! The number density per square are doesn't change, + ! but since the patch is smaller and cohort counts + ! are absolute, reduce this number. + + nc%n = currentCohort%n * patch_site_areadis/currentPatch%area + + ! because the mortality rate due to impact for the cohorts which + ! had been in the understory and are now in the newly- + ! disturbed patch is very high, passing the imort directly to history + ! results in large numerical errors, on account of the sharply + ! reduced number densities. so instead pass this info via a + ! site-level diagnostic variable before reducing the number density. + + currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) = & + currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) + & + nc%n * ED_val_understorey_death / hlm_freq_day + + + currentSite%imort_carbonflux(currentCohort%pft) = & + currentSite%imort_carbonflux(currentCohort%pft) + & + (nc%n * ED_val_understorey_death / hlm_freq_day ) * & + total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 + + ! Step 2: Apply survivor ship function based on the understory death fraction + ! remaining of understory plants of those that are knocked over + ! by the overstorey trees dying... + nc%n = nc%n * (1.0_r8 - ED_val_understorey_death) + + ! since the donor patch split and sent a fraction of its members + ! to the new patch and a fraction to be preserved in itself, + ! when reporting diagnostic rates, we must carry over the mortality rates from + ! the donor that were applied before the patch split. Remember this is only + ! for diagnostics. But think of it this way, the rates are weighted by + ! number density in EDCLMLink, and the number density of this new patch is donated + ! so with the number density must come the effective mortality rates. + + nc%cmort = currentCohort%cmort + nc%hmort = currentCohort%hmort + nc%bmort = currentCohort%bmort + nc%frmort = currentCohort%frmort + nc%smort = currentCohort%smort + nc%asmort = currentCohort%asmort + nc%dmort = currentCohort%dmort + nc%lmort_direct = currentCohort%lmort_direct + nc%lmort_collateral = currentCohort%lmort_collateral + nc%lmort_infra = currentCohort%lmort_infra + + ! understory trees that might potentially be knocked over in the disturbance. + ! The existing (donor) patch should not have any impact mortality, it should + ! only lose cohorts due to the decrease in area. This is not mortality. + ! Besides, the current and newly created patch sum to unity + + currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) + + else + ! grass is not killed by mortality disturbance events. Just move it into the new patch area. + ! Just split the grass into the existing and new patch structures + nc%n = currentCohort%n * patch_site_areadis/currentPatch%area + + ! Those remaining in the existing + currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) + + nc%cmort = currentCohort%cmort + nc%hmort = currentCohort%hmort + nc%bmort = currentCohort%bmort + nc%frmort = currentCohort%frmort + nc%smort = currentCohort%smort + nc%asmort = currentCohort%asmort + nc%dmort = currentCohort%dmort + nc%lmort_direct = currentCohort%lmort_direct + nc%lmort_collateral = currentCohort%lmort_collateral + nc%lmort_infra = currentCohort%lmort_infra + + endif + endif + + ! Fire is the current disturbance + elseif (i_disturbance_type .eq. dtype_ifire ) then + + ! Number of members in the new patch, before we impose fire survivorship + nc%n = currentCohort%n * patch_site_areadis/currentPatch%area + + ! loss of individuals from source patch due to area shrinking + currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) + + levcan = currentCohort%canopy_layer + + if(levcan==ican_upper) then + + ! before changing number densities, track total rate of trees that died + ! due to fire, as well as from each fire mortality term + currentSite%fmort_rate_canopy(currentCohort%size_class, currentCohort%pft) = & + currentSite%fmort_rate_canopy(currentCohort%size_class, currentCohort%pft) + & + nc%n * currentCohort%fire_mort / hlm_freq_day + + currentSite%fmort_carbonflux_canopy(currentCohort%pft) = & + currentSite%fmort_carbonflux_canopy(currentCohort%pft) + & + (nc%n * currentCohort%fire_mort) * & + total_c * g_per_kg * days_per_sec * ha_per_m2 + + else + currentSite%fmort_rate_ustory(currentCohort%size_class, currentCohort%pft) = & + currentSite%fmort_rate_ustory(currentCohort%size_class, currentCohort%pft) + & + nc%n * currentCohort%fire_mort / hlm_freq_day + + currentSite%fmort_carbonflux_ustory(currentCohort%pft) = & + currentSite%fmort_carbonflux_ustory(currentCohort%pft) + & + (nc%n * currentCohort%fire_mort) * & + total_c * g_per_kg * days_per_sec * ha_per_m2 + end if + + currentSite%fmort_rate_cambial(currentCohort%size_class, currentCohort%pft) = & + currentSite%fmort_rate_cambial(currentCohort%size_class, currentCohort%pft) + & + nc%n * currentCohort%cambial_mort / hlm_freq_day + currentSite%fmort_rate_crown(currentCohort%size_class, currentCohort%pft) = & + currentSite%fmort_rate_crown(currentCohort%size_class, currentCohort%pft) + & + nc%n * currentCohort%crownfire_mort / hlm_freq_day + + ! loss of individual from fire in new patch. + nc%n = nc%n * (1.0_r8 - currentCohort%fire_mort) + + nc%cmort = currentCohort%cmort + nc%hmort = currentCohort%hmort + nc%bmort = currentCohort%bmort + nc%frmort = currentCohort%frmort + nc%smort = currentCohort%smort + nc%asmort = currentCohort%asmort + nc%dmort = currentCohort%dmort + nc%lmort_direct = currentCohort%lmort_direct + nc%lmort_collateral = currentCohort%lmort_collateral + nc%lmort_infra = currentCohort%lmort_infra + + + ! Some of of the leaf mass from living plants has been + ! burned off. Here, we remove that mass, and + ! tally it in the flux we sent to the atmosphere + + if(prt_params%woody(currentCohort%pft) == itrue)then + leaf_burn_frac = currentCohort%fraction_crown_burned + else + + ! Grasses determine their fraction of leaves burned here + + leaf_burn_frac = currentPatch%burnt_frac_litter(lg_sf) + endif + + ! Perform a check to make sure that spitfire gave + ! us reasonable mortality and burn fraction rates + + if( (leaf_burn_frac < 0._r8) .or. & + (leaf_burn_frac > 1._r8) .or. & + (currentCohort%fire_mort < 0._r8) .or. & + (currentCohort%fire_mort > 1._r8)) then + write(fates_log(),*) 'unexpected fire fractions' + write(fates_log(),*) prt_params%woody(currentCohort%pft) + write(fates_log(),*) leaf_burn_frac + write(fates_log(),*) currentCohort%fire_mort + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + do el = 1,num_elements + + leaf_m = nc%prt%GetState(leaf_organ, element_list(el)) + + currentSite%mass_balance(el)%burn_flux_to_atm = & + currentSite%mass_balance(el)%burn_flux_to_atm + & + leaf_burn_frac * leaf_m * nc%n + end do + + ! Here the mass is removed from the plant + + call PRTBurnLosses(nc%prt, leaf_organ, leaf_burn_frac) + currentCohort%fraction_crown_burned = 0.0_r8 + nc%fraction_crown_burned = 0.0_r8 + + + + ! Logging is the current disturbance + elseif (i_disturbance_type .eq. dtype_ilog ) then + + ! If this cohort is in the upper canopy. It generated + if(currentCohort%canopy_layer == 1)then + + ! calculate the survivorship of disturbed trees because non-harvested + nc%n = currentCohort%n * currentCohort%l_degrad + ! nc%n = (currentCohort%l_degrad / (currentCohort%l_degrad + & + ! currentCohort%lmort_direct + currentCohort%lmort_collateral + + ! currentCohort%lmort_infra) ) * & + ! currentCohort%n * patch_site_areadis/currentPatch%area + + ! Reduce counts in the existing/donor patch according to the logging rate + currentCohort%n = currentCohort%n * & + (1.0_r8 - min(1.0_r8,(currentCohort%lmort_direct + & + currentCohort%lmort_collateral + & + currentCohort%lmort_infra + currentCohort%l_degrad))) + + nc%cmort = currentCohort%cmort + nc%hmort = currentCohort%hmort + nc%bmort = currentCohort%bmort + nc%frmort = currentCohort%frmort + nc%smort = currentCohort%smort + nc%asmort = currentCohort%asmort + nc%dmort = currentCohort%dmort + + ! since these are the ones that weren't logged, + ! set the logging mortality rates as zero + nc%lmort_direct = 0._r8 + nc%lmort_collateral = 0._r8 + nc%lmort_infra = 0._r8 + + else + + ! What to do with cohorts in the understory of a logging generated + ! disturbance patch? + + if(prt_params%woody(currentCohort%pft) == itrue)then + + + ! Survivorship of undestory woody plants. Two step process. + ! Step 1: Reduce current number of plants to reflect the + ! change in area. + ! The number density per square are doesn't change, + ! but since the patch is smaller + ! and cohort counts are absolute, reduce this number. + nc%n = currentCohort%n * patch_site_areadis/currentPatch%area + + ! because the mortality rate due to impact for the cohorts which had + ! been in the understory and are now in the newly- + ! disturbed patch is very high, passing the imort directly to + ! history results in large numerical errors, on account + ! of the sharply reduced number densities. so instead pass this info + ! via a site-level diagnostic variable before reducing + ! the number density. + currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) = & + currentSite%imort_rate(currentCohort%size_class, currentCohort%pft) + & + nc%n * currentPatch%fract_ldist_not_harvested * & + logging_coll_under_frac / hlm_freq_day + + currentSite%imort_carbonflux(currentCohort%pft) = & + currentSite%imort_carbonflux(currentCohort%pft) + & + (nc%n * currentPatch%fract_ldist_not_harvested * & + logging_coll_under_frac/ hlm_freq_day ) * & + total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 + + + ! Step 2: Apply survivor ship function based on the understory death fraction + + ! remaining of understory plants of those that are knocked + ! over by the overstorey trees dying... + ! LOGGING SURVIVORSHIP OF UNDERSTORY PLANTS IS SET AS A NEW PARAMETER + ! in the fatesparameter files + nc%n = nc%n * (1.0_r8 - & + (1.0_r8-currentPatch%fract_ldist_not_harvested) * logging_coll_under_frac) + + ! Step 3: Reduce the number count of cohorts in the + ! original/donor/non-disturbed patch to reflect the area change + currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) + + nc%cmort = currentCohort%cmort + nc%hmort = currentCohort%hmort + nc%bmort = currentCohort%bmort + nc%frmort = currentCohort%frmort + nc%smort = currentCohort%smort + nc%asmort = currentCohort%asmort + nc%dmort = currentCohort%dmort + nc%lmort_direct = currentCohort%lmort_direct + nc%lmort_collateral = currentCohort%lmort_collateral + nc%lmort_infra = currentCohort%lmort_infra + + else + + ! grass is not killed by mortality disturbance events. + ! Just move it into the new patch area. + ! Just split the grass into the existing and new patch structures + nc%n = currentCohort%n * patch_site_areadis/currentPatch%area + + ! Those remaining in the existing + currentCohort%n = currentCohort%n * (1._r8 - patch_site_areadis/currentPatch%area) + + ! No grass impact mortality imposed on the newly created patch + nc%cmort = currentCohort%cmort + nc%hmort = currentCohort%hmort + nc%bmort = currentCohort%bmort + nc%frmort = currentCohort%frmort + nc%smort = currentCohort%smort + nc%asmort = currentCohort%asmort + nc%dmort = currentCohort%dmort + nc%lmort_direct = currentCohort%lmort_direct + nc%lmort_collateral = currentCohort%lmort_collateral + nc%lmort_infra = currentCohort%lmort_infra + + endif ! is/is-not woody + + endif ! Select canopy layer + + else + write(fates_log(),*) 'unknown disturbance mode?' + write(fates_log(),*) 'i_disturbance_type: ',i_disturbance_type + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if ! Select disturbance mode + + if (nc%n > 0.0_r8) then + storebigcohort => new_patch%tallest + storesmallcohort => new_patch%shortest + if(associated(new_patch%tallest))then + tnull = 0 + else + tnull = 1 + new_patch%tallest => nc + nc%taller => null() + endif + + if(associated(new_patch%shortest))then + snull = 0 + else + snull = 1 + new_patch%shortest => nc + nc%shorter => null() + endif + nc%patchptr => new_patch + call insert_cohort(nc, new_patch%tallest, new_patch%shortest, & + tnull, snull, storebigcohort, storesmallcohort) + + new_patch%tallest => storebigcohort + new_patch%shortest => storesmallcohort + else + + ! Get rid of the new temporary cohort + call DeallocateCohort(nc) + deallocate(nc) + + endif + + currentCohort => currentCohort%taller + enddo ! currentCohort + call sort_cohorts(currentPatch) + + !update area of donor patch + oldarea = currentPatch%area + currentPatch%area = currentPatch%area - patch_site_areadis + + ! for all disturbance rates that haven't been resolved yet, increase their amount so that + ! they are the same amount of gridcell-scale disturbance relative to the original patch size + if (i_disturbance_type .ne. N_DIST_TYPES) then + do i_dist2 = i_disturbance_type+1,N_DIST_TYPES + currentPatch%disturbance_rates(i_dist2) = currentPatch%disturbance_rates(i_dist2) & + * oldarea / currentPatch%area + end do + end if + + ! sort out the cohorts, since some of them may be so small as to need removing. + ! the first call to terminate cohorts removes sparse number densities, + ! the second call removes for all other reasons (sparse culling must happen + ! before fusion) + call terminate_cohorts(currentSite, currentPatch, 1,16,bc_in) + call fuse_cohorts(currentSite,currentPatch, bc_in) + call terminate_cohorts(currentSite, currentPatch, 2,16,bc_in) + call sort_cohorts(currentPatch) + + end if ! if ( new_patch%area > nearzero ) then + + end if cp_nocomp_matches_2_if + currentPatch => currentPatch%younger + + enddo ! currentPatch patch loop. + + !*************************/ + !** INSERT NEW PATCH(ES) INTO LINKED LIST + !*************************/ + + if ( site_areadis_primary .gt. nearzero) then + currentPatch => currentSite%youngest_patch + ! insert new youngest primary patch after all the secondary patches, if there are any. + ! this requires first finding the current youngest primary to insert the new one ahead of + if (currentPatch%anthro_disturbance_label .eq. secondaryforest ) then + found_youngest_primary = .false. + do while(associated(currentPatch) .and. .not. found_youngest_primary) + currentPatch => currentPatch%older + if (associated(currentPatch)) then + if (currentPatch%anthro_disturbance_label .eq. primaryforest) then + found_youngest_primary = .true. + endif + endif + end do + if (associated(currentPatch)) then + ! the case where we've found a youngest primary patch + new_patch_primary%older => currentPatch + new_patch_primary%younger => currentPatch%younger + currentPatch%younger%older => new_patch_primary + currentPatch%younger => new_patch_primary else - snull = 1 - new_patch%shortest => nc - nc%shorter => null() + ! the case where we haven't, because the patches are all secondaary, + ! and are putting a primary patch at the oldest end of the + ! linked list (not sure how this could happen, but who knows...) + new_patch_primary%older => null() + new_patch_primary%younger => currentSite%oldest_patch + currentSite%oldest_patch%older => new_patch_primary + currentSite%oldest_patch => new_patch_primary endif - nc%patchptr => new_patch - call insert_cohort(nc, new_patch%tallest, new_patch%shortest, & - tnull, snull, storebigcohort, storesmallcohort) - - new_patch%tallest => storebigcohort - new_patch%shortest => storesmallcohort else - - ! Get rid of the new temporary cohort - call DeallocateCohort(nc) - deallocate(nc) - + ! the case where there are no secondary patches at the start of the linked list (prior logic) + new_patch_primary%older => currentPatch + new_patch_primary%younger => null() + currentPatch%younger => new_patch_primary + currentSite%youngest_patch => new_patch_primary endif - - currentCohort => currentCohort%taller - enddo ! currentCohort - call sort_cohorts(currentPatch) - - !update area of donor patch - oldarea = currentPatch%area - currentPatch%area = currentPatch%area - patch_site_areadis - - ! for all disturbance rates that haven't been resolved yet, increase their amount so that - ! they are the same amount of gridcell-scale disturbance relative to the original patch size - if (i_disturbance_type .ne. N_DIST_TYPES) then - do i_dist2 = i_disturbance_type+1,N_DIST_TYPES - currentPatch%disturbance_rates(i_dist2) = currentPatch%disturbance_rates(i_dist2) & - * oldarea / currentPatch%area - end do - end if + endif + + ! insert first secondary at the start of the list + if ( site_areadis_secondary .gt. nearzero) then + currentPatch => currentSite%youngest_patch + new_patch_secondary%older => currentPatch + new_patch_secondary%younger=> null() + currentPatch%younger => new_patch_secondary + currentSite%youngest_patch => new_patch_secondary + endif - ! sort out the cohorts, since some of them may be so small as to need removing. + + ! sort out the cohorts, since some of them may be so small as to need removing. ! the first call to terminate cohorts removes sparse number densities, ! the second call removes for all other reasons (sparse culling must happen ! before fusion) - call terminate_cohorts(currentSite, currentPatch, 1,16,bc_in) - call fuse_cohorts(currentSite,currentPatch, bc_in) - call terminate_cohorts(currentSite, currentPatch, 2,16,bc_in) - call sort_cohorts(currentPatch) - end if ! if ( new_patch%area > nearzero ) then - - end if cp_nocomp_matches_2_if - currentPatch => currentPatch%younger - - enddo ! currentPatch patch loop. + if ( site_areadis_primary .gt. nearzero) then + call terminate_cohorts(currentSite, new_patch_primary, 1,17, bc_in) + call fuse_cohorts(currentSite,new_patch_primary, bc_in) + call terminate_cohorts(currentSite, new_patch_primary, 2,17, bc_in) + call sort_cohorts(new_patch_primary) + endif - !*************************/ - !** INSERT NEW PATCH(ES) INTO LINKED LIST - !*************************/ - - if ( site_areadis_primary .gt. nearzero) then - currentPatch => currentSite%youngest_patch - ! insert new youngest primary patch after all the secondary patches, if there are any. - ! this requires first finding the current youngest primary to insert the new one ahead of - if (currentPatch%anthro_disturbance_label .eq. secondaryforest ) then - found_youngest_primary = .false. - do while(associated(currentPatch) .and. .not. found_youngest_primary) - currentPatch => currentPatch%older - if (associated(currentPatch)) then - if (currentPatch%anthro_disturbance_label .eq. primaryforest) then - found_youngest_primary = .true. - endif - endif - end do - if (associated(currentPatch)) then - ! the case where we've found a youngest primary patch - new_patch_primary%older => currentPatch - new_patch_primary%younger => currentPatch%younger - currentPatch%younger%older => new_patch_primary - currentPatch%younger => new_patch_primary - else - ! the case where we haven't, because the patches are all secondaary, - ! and are putting a primary patch at the oldest end of the - ! linked list (not sure how this could happen, but who knows...) - new_patch_primary%older => null() - new_patch_primary%younger => currentSite%oldest_patch - currentSite%oldest_patch%older => new_patch_primary - currentSite%oldest_patch => new_patch_primary + if ( site_areadis_secondary .gt. nearzero) then + call terminate_cohorts(currentSite, new_patch_secondary, 1,18,bc_in) + call fuse_cohorts(currentSite,new_patch_secondary, bc_in) + call terminate_cohorts(currentSite, new_patch_secondary, 2,18,bc_in) + call sort_cohorts(new_patch_secondary) endif - else - ! the case where there are no secondary patches at the start of the linked list (prior logic) - new_patch_primary%older => currentPatch - new_patch_primary%younger => null() - currentPatch%younger => new_patch_primary - currentSite%youngest_patch => new_patch_primary - endif - endif - - ! insert first secondary at the start of the list - if ( site_areadis_secondary .gt. nearzero) then - currentPatch => currentSite%youngest_patch - new_patch_secondary%older => currentPatch - new_patch_secondary%younger=> null() - currentPatch%younger => new_patch_secondary - currentSite%youngest_patch => new_patch_secondary - endif - - - ! sort out the cohorts, since some of them may be so small as to need removing. - ! the first call to terminate cohorts removes sparse number densities, - ! the second call removes for all other reasons (sparse culling must happen - ! before fusion) - - if ( site_areadis_primary .gt. nearzero) then - call terminate_cohorts(currentSite, new_patch_primary, 1,17, bc_in) - call fuse_cohorts(currentSite,new_patch_primary, bc_in) - call terminate_cohorts(currentSite, new_patch_primary, 2,17, bc_in) - call sort_cohorts(new_patch_primary) - endif - - if ( site_areadis_secondary .gt. nearzero) then - call terminate_cohorts(currentSite, new_patch_secondary, 1,18,bc_in) - call fuse_cohorts(currentSite,new_patch_secondary, bc_in) - call terminate_cohorts(currentSite, new_patch_secondary, 2,18,bc_in) - call sort_cohorts(new_patch_secondary) - endif - - endif !end new_patch area - - - call check_patch_area(currentSite) - call set_patchno(currentSite) - - end do disturbance_type_loop + + endif !end new_patch area + + + call check_patch_area(currentSite) + call set_patchno(currentSite) + + end do disturbance_type_loop end do nocomp_pft_loop @@ -2401,11 +2405,6 @@ subroutine fuse_patches( csite, bc_in ) tpp => currentSite%youngest_patch tpp_loop: do while(associated(tpp)) - if(.not.associated(currentPatch))then - write(fates_log(),*) 'FATES fuse_patches(): currentPatch is not associated?' - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - both_associated_if: if(associated(tpp).and.associated(currentPatch))then !--------------------------------------------------------------------! ! only fuse patches whose anthropogenic disturbance category matches ! From 5ddd19e86ff4d42637a39c87454292a5dbd7d339 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 14 Nov 2022 13:36:56 -0500 Subject: [PATCH 437/852] Updated default seed repro threshold for mature plants, to 80cm for pfts 2,3,4,6 --- .../archive/api24.1.0_101722_patch_params.xml | 1 + parameter_files/fates_params_default.cdl | 530 +++++++++--------- 2 files changed, 267 insertions(+), 264 deletions(-) diff --git a/parameter_files/archive/api24.1.0_101722_patch_params.xml b/parameter_files/archive/api24.1.0_101722_patch_params.xml index 888f82beac..c985072be0 100644 --- a/parameter_files/archive/api24.1.0_101722_patch_params.xml +++ b/parameter_files/archive/api24.1.0_101722_patch_params.xml @@ -33,6 +33,7 @@ 80, 80, 80, 80 + 80, 80, 80, 80 diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 14c23e78a6..92f04f973b 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -14,42 +14,15 @@ dimensions: fates_plant_organs = 4 ; fates_string_length = 60 ; variables: - double fates_history_ageclass_bin_edges(fates_history_age_bins) ; - fates_history_ageclass_bin_edges:units = "yr" ; - fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; - double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; - fates_history_coageclass_bin_edges:units = "years" ; - fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; - double fates_history_height_bin_edges(fates_history_height_bins) ; - fates_history_height_bin_edges:units = "m" ; - fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; - double fates_history_damage_bin_edges(fates_history_damage_bins) ; - fates_history_damage_bin_edges:units = "% crown loss" ; - fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; fates_history_sizeclass_bin_edges:units = "cm" ; fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; - double fates_alloc_organ_id(fates_plant_organs) ; - fates_alloc_organ_id:units = "unitless" ; - fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; - double fates_hydro_htftype_node(fates_hydr_organs) ; - fates_hydro_htftype_node:units = "unitless" ; - fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; char fates_pftname(fates_pft, fates_string_length) ; fates_pftname:units = "unitless - string" ; fates_pftname:long_name = "Description of plant type" ; - char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; - fates_hydro_organ_name:units = "unitless - string" ; - fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; - char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; - fates_alloc_organ_name:units = "unitless - string" ; - fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; - 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" ; - 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" ; double fates_alloc_storage_cushion(fates_pft) ; fates_alloc_storage_cushion:units = "fraction" ; fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; @@ -221,12 +194,6 @@ variables: double fates_cnp_store_ovrflw_frac(fates_pft) ; fates_cnp_store_ovrflw_frac:units = "fraction" ; fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; - double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; - fates_cnp_turnover_nitr_retrans:units = "fraction" ; - fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; - double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; - fates_cnp_turnover_phos_retrans:units = "fraction" ; - fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; double fates_cnp_vmax_p(fates_pft) ; fates_cnp_vmax_p:units = "gP/gC/s" ; fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; @@ -281,39 +248,15 @@ variables: double fates_hydro_avuln_gs(fates_pft) ; fates_hydro_avuln_gs:units = "unitless" ; fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; - double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; - fates_hydro_avuln_node:units = "unitless" ; - fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; - double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; - fates_hydro_epsil_node:units = "MPa" ; - fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; - double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; - fates_hydro_fcap_node:units = "unitless" ; - fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; double fates_hydro_k_lwp(fates_pft) ; fates_hydro_k_lwp:units = "unitless" ; fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; - double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; - fates_hydro_kmax_node:units = "kg/MPa/m/s" ; - fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; double fates_hydro_p50_gs(fates_pft) ; fates_hydro_p50_gs:units = "MPa" ; fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; - double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; - fates_hydro_p50_node:units = "MPa" ; - fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; double fates_hydro_p_taper(fates_pft) ; fates_hydro_p_taper:units = "unitless" ; fates_hydro_p_taper:long_name = "xylem taper exponent" ; - double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; - fates_hydro_pinot_node:units = "MPa" ; - fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; - double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; - fates_hydro_pitlp_node:units = "MPa" ; - fates_hydro_pitlp_node:long_name = "turgor loss point" ; - double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; - fates_hydro_resid_node:units = "cm3/cm3" ; - fates_hydro_resid_node:long_name = "residual water conent" ; double fates_hydro_rfrac_stem(fates_pft) ; fates_hydro_rfrac_stem:units = "fraction" ; fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; @@ -323,18 +266,6 @@ variables: double fates_hydro_srl(fates_pft) ; fates_hydro_srl:units = "m g-1" ; fates_hydro_srl:long_name = "specific root length" ; - double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; - fates_hydro_thetas_node:units = "cm3/cm3" ; - fates_hydro_thetas_node:long_name = "saturated water content" ; - double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; - fates_hydro_vg_alpha_node:units = "MPa-1" ; - fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; - double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; - fates_hydro_vg_m_node:units = "unitless" ; - fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; - 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_leaf_c3psn(fates_pft) ; fates_leaf_c3psn:units = "flag" ; fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; @@ -362,9 +293,6 @@ variables: double fates_leaf_stomatal_slope_medlyn(fates_pft) ; fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; - double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; - fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; - fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; double fates_leaf_vcmaxha(fates_pft) ; fates_leaf_vcmaxha:units = "J/mol" ; fates_leaf_vcmaxha:long_name = "activation energy for vcmax" ; @@ -499,19 +427,13 @@ variables: fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; fates_recruit_seed_dbh_repro_threshold:units = "cm" ; - fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter where the plant will start extra allocation (via fates_recruit_seed_alloc_mature) to the seed pool" ; + fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter (if any) where the plant will start extra clonal allocation to the seed pool" ; double fates_recruit_seed_germination_rate(fates_pft) ; fates_recruit_seed_germination_rate:units = "yr-1" ; fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; double fates_recruit_seed_supplement(fates_pft) ; fates_recruit_seed_supplement:units = "KgC/m2/yr" ; fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; - double fates_stoich_nitr(fates_plant_organs, fates_pft) ; - fates_stoich_nitr:units = "gN/gC" ; - fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; - double fates_stoich_phos(fates_plant_organs, fates_pft) ; - fates_stoich_phos:units = "gP/gC" ; - fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; double fates_trim_inc(fates_pft) ; fates_trim_inc:units = "m2/m2" ; fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; @@ -533,9 +455,6 @@ variables: double fates_turnover_fnrt(fates_pft) ; fates_turnover_fnrt:units = "yr" ; fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; - double fates_turnover_leaf(fates_leafage_class, fates_pft) ; - fates_turnover_leaf:units = "yr" ; - fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; double fates_turnover_senleaf_fdrought(fates_pft) ; fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; @@ -545,9 +464,15 @@ variables: double fates_woody(fates_pft) ; fates_woody:units = "logical flag" ; fates_woody:long_name = "Binary woody lifeform flag" ; - double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; - fates_hlm_pft_map:units = "area fraction" ; - fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_history_ageclass_bin_edges(fates_history_age_bins) ; + fates_history_ageclass_bin_edges:units = "yr" ; + fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; + 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" ; + double fates_history_height_bin_edges(fates_history_height_bins) ; + fates_history_height_bin_edges:units = "m" ; + fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; double fates_fire_FBD(fates_litterclass) ; fates_fire_FBD:units = "kg Biomass/m3" ; fates_fire_FBD:long_name = "fuel bulk density" ; @@ -575,9 +500,84 @@ variables: double fates_frag_maxdecomp(fates_litterclass) ; fates_frag_maxdecomp:units = "yr-1" ; fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; + char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; + fates_hydro_organ_name:units = "unitless - string" ; + fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; + char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; + fates_alloc_organ_name:units = "unitless - string" ; + fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; + 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" ; + double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_nitr_retrans:units = "fraction" ; + fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; + double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_phos_retrans:units = "fraction" ; + fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; + double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; + fates_hydro_avuln_node:units = "unitless" ; + fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; + double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; + fates_hydro_epsil_node:units = "MPa" ; + fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; + double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; + fates_hydro_fcap_node:units = "unitless" ; + fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; + double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; + fates_hydro_kmax_node:units = "kg/MPa/m/s" ; + fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; + double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; + fates_hydro_p50_node:units = "MPa" ; + fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; + double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pinot_node:units = "MPa" ; + fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; + double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pitlp_node:units = "MPa" ; + fates_hydro_pitlp_node:long_name = "turgor loss point" ; + double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; + fates_hydro_resid_node:units = "cm3/cm3" ; + fates_hydro_resid_node:long_name = "residual water conent" ; + double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; + fates_hydro_thetas_node:units = "cm3/cm3" ; + fates_hydro_thetas_node:long_name = "saturated water content" ; + double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_alpha_node:units = "MPa-1" ; + fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; + double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_m_node:units = "unitless" ; + fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; + 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_stoich_nitr(fates_plant_organs, fates_pft) ; + fates_stoich_nitr:units = "gN/gC" ; + fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; + double fates_stoich_phos(fates_plant_organs, fates_pft) ; + fates_stoich_phos:units = "gP/gC" ; + fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; + double fates_alloc_organ_id(fates_plant_organs) ; + fates_alloc_organ_id:units = "unitless" ; + fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; + double fates_hydro_htftype_node(fates_hydr_organs) ; + fates_hydro_htftype_node:units = "unitless" ; + fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; 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_history_coageclass_bin_edges(fates_history_coage_bins) ; + fates_history_coageclass_bin_edges:units = "years" ; + fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; + double fates_history_damage_bin_edges(fates_history_damage_bins) ; + fates_history_damage_bin_edges:units = "% crown loss" ; + fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; + double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; + fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; + fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; + double fates_turnover_leaf(fates_leafage_class, fates_pft) ; + fates_turnover_leaf:units = "yr" ; + fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; double fates_base_mr_20 ; fates_base_mr_20:units = "gC/gN/s" ; fates_base_mr_20:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; @@ -787,24 +787,30 @@ variables: fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; // global attributes: - :history = "This parameter file is maintained in version control\nSee https://github.com/NGEET/fates/blob/master/parameter_files/fates_params_default.cdl \nFor changes, use git blame \n" ; + :history = "This file was generated by BatchPatchParams.py:\n", + "CDL Base File = archive/api24.1.0_101722_fates_params_default.cdl\n", + "XML patch file = archive/api24.1.0_101722_patch_params.xml" ; data: - fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; - - fates_history_coageclass_bin_edges = 0, 5 ; - - fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; - - fates_history_damage_bin_edges = 0, 80 ; + fates_hlm_pft_map = + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100 ; - fates_alloc_organ_id = 1, 2, 3, 6 ; - - fates_hydro_htftype_node = 1, 1, 1, 1 ; - fates_pftname = "broadleaf_evergreen_tropical_tree ", "needleleaf_evergreen_extratrop_tree ", @@ -819,32 +825,6 @@ data: "cool_c3_grass ", "c4_grass " ; - fates_hydro_organ_name = - "leaf ", - "stem ", - "transporting root ", - "absorbing root " ; - - fates_alloc_organ_name = - "leaf", - "fine root", - "sapwood", - "structure" ; - - fates_litterclass_name = - "twig ", - "small branch ", - "large branch ", - "trunk ", - "dead leaves ", - "live grass " ; - - 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, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; - fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 ; @@ -994,18 +974,6 @@ data: fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_cnp_turnover_nitr_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_turnover_phos_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10 ; @@ -1057,71 +1025,14 @@ data: fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5 ; - fates_hydro_avuln_node = - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 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_hydro_epsil_node = - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - - fates_hydro_fcap_node = - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, - 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_hydro_kmax_node = - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; - fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5 ; - fates_hydro_p50_node = - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25 ; - fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333 ; - fates_hydro_pinot_node = - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; - - fates_hydro_pitlp_node = - -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, - -1.67, -1.67, - -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, - -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, - -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; - - fates_hydro_resid_node = - 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, - 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625 ; @@ -1130,34 +1041,6 @@ data: fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; - fates_hydro_thetas_node = - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; - - fates_hydro_vg_alpha_node = - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005 ; - - fates_hydro_vg_m_node = - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_hydro_vg_n_node = - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 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_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, @@ -1183,9 +1066,6 @@ data: fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, 4.7, 2.2, 5.3, 1.6 ; - fates_leaf_vcmax25top = - 50, 62, 39, 61, 41, 58, 62, 54, 54, 78, 78, 78 ; - fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330 ; @@ -1306,7 +1186,7 @@ data: fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9 ; - fates_recruit_seed_dbh_repro_threshold = 90, 90, 90, 90, 90, 90, 3, 3, 2, + fates_recruit_seed_dbh_repro_threshold = 90, 80, 80, 80, 90, 80, 3, 3, 2, 0.35, 0.35, 0.35 ; fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, @@ -1314,25 +1194,6 @@ data: fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_stoich_nitr = - 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, - 0.0047, 0.0047, 0.0047 ; - - fates_stoich_phos = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, - 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, - 0.00047, 0.00047, 0.00047, 0.00047 ; - fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03 ; @@ -1351,9 +1212,6 @@ data: fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - fates_turnover_leaf = - 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_wood_density = 0.7, 0.4, 0.7, 0.53, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, @@ -1361,21 +1219,17 @@ data: fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; - fates_hlm_pft_map = - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; + + fates_litterclass_name = + "twig ", + "small branch ", + "large branch ", + "trunk ", + "dead leaves ", + "live grass " ; + + fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; @@ -1395,8 +1249,156 @@ data: fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; + fates_hydro_organ_name = + "leaf ", + "stem ", + "transporting root ", + "absorbing root " ; + + fates_alloc_organ_name = + "leaf", + "fine root", + "sapwood", + "structure" ; + + 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, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; + + fates_cnp_turnover_nitr_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_turnover_phos_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_avuln_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_hydro_epsil_node = + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_hydro_fcap_node = + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_kmax_node = + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; + + fates_hydro_p50_node = + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25 ; + + fates_hydro_pinot_node = + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; + + fates_hydro_pitlp_node = + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + -1.67, -1.67, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; + + fates_hydro_resid_node = + 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; + + fates_hydro_thetas_node = + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; + + fates_hydro_vg_alpha_node = + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005 ; + + fates_hydro_vg_m_node = + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_hydro_vg_n_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_stoich_nitr = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; + + fates_stoich_phos = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; + + fates_alloc_organ_id = 1, 2, 3, 6 ; + + fates_hydro_htftype_node = 1, 1, 1, 1 ; + fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; + fates_history_coageclass_bin_edges = 0, 5 ; + + fates_history_damage_bin_edges = 0, 80 ; + + fates_leaf_vcmax25top = + 50, 62, 39, 61, 41, 58, 62, 54, 54, 78, 78, 78 ; + + fates_turnover_leaf = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + fates_base_mr_20 = 2.52e-06 ; fates_canopy_closure_thresh = 0.8 ; From f0b9902314d9cf880e7697b8ebc78bd3ed98baf0 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 14 Nov 2022 13:40:31 -0500 Subject: [PATCH 438/852] Updated metadata on mature seed allocatino parameter --- 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 92f04f973b..4d5fdc8ec6 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -427,7 +427,7 @@ variables: fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; fates_recruit_seed_dbh_repro_threshold:units = "cm" ; - fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter (if any) where the plant will start extra clonal allocation to the seed pool" ; + fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter where the plant will increase allocation to the seed pool by fraction: fates_recruit_seed_alloc_mature" ; double fates_recruit_seed_germination_rate(fates_pft) ; fates_recruit_seed_germination_rate:units = "yr-1" ; fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; From 8cd2c19fb7d5fa489a5a57c268aa5755a75c8133 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 15 Nov 2022 12:32:20 -0500 Subject: [PATCH 439/852] Sorted fates_params_default.cdl --- parameter_files/fates_params_default.cdl | 542 +++++++++++------------ 1 file changed, 270 insertions(+), 272 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 4d5fdc8ec6..0c89520e40 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -14,15 +14,42 @@ dimensions: fates_plant_organs = 4 ; fates_string_length = 60 ; variables: - double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; - fates_hlm_pft_map:units = "area fraction" ; - fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_history_ageclass_bin_edges(fates_history_age_bins) ; + fates_history_ageclass_bin_edges:units = "yr" ; + fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; + double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; + fates_history_coageclass_bin_edges:units = "years" ; + fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; + double fates_history_height_bin_edges(fates_history_height_bins) ; + fates_history_height_bin_edges:units = "m" ; + fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; + double fates_history_damage_bin_edges(fates_history_damage_bins) ; + fates_history_damage_bin_edges:units = "% crown loss" ; + fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; fates_history_sizeclass_bin_edges:units = "cm" ; fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; + double fates_alloc_organ_id(fates_plant_organs) ; + fates_alloc_organ_id:units = "unitless" ; + fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; + double fates_hydro_htftype_node(fates_hydr_organs) ; + fates_hydro_htftype_node:units = "unitless" ; + fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; char fates_pftname(fates_pft, fates_string_length) ; fates_pftname:units = "unitless - string" ; fates_pftname:long_name = "Description of plant type" ; + char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; + fates_hydro_organ_name:units = "unitless - string" ; + fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; + char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; + fates_alloc_organ_name:units = "unitless - string" ; + fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; + 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" ; + 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" ; double fates_alloc_storage_cushion(fates_pft) ; fates_alloc_storage_cushion:units = "fraction" ; fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; @@ -194,6 +221,12 @@ variables: double fates_cnp_store_ovrflw_frac(fates_pft) ; fates_cnp_store_ovrflw_frac:units = "fraction" ; fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; + double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_nitr_retrans:units = "fraction" ; + fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; + double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_phos_retrans:units = "fraction" ; + fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; double fates_cnp_vmax_p(fates_pft) ; fates_cnp_vmax_p:units = "gP/gC/s" ; fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; @@ -248,15 +281,39 @@ variables: double fates_hydro_avuln_gs(fates_pft) ; fates_hydro_avuln_gs:units = "unitless" ; fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; + double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; + fates_hydro_avuln_node:units = "unitless" ; + fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; + double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; + fates_hydro_epsil_node:units = "MPa" ; + fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; + double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; + fates_hydro_fcap_node:units = "unitless" ; + fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; double fates_hydro_k_lwp(fates_pft) ; fates_hydro_k_lwp:units = "unitless" ; fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; + double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; + fates_hydro_kmax_node:units = "kg/MPa/m/s" ; + fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; double fates_hydro_p50_gs(fates_pft) ; fates_hydro_p50_gs:units = "MPa" ; fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; + double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; + fates_hydro_p50_node:units = "MPa" ; + fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; double fates_hydro_p_taper(fates_pft) ; fates_hydro_p_taper:units = "unitless" ; fates_hydro_p_taper:long_name = "xylem taper exponent" ; + double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pinot_node:units = "MPa" ; + fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; + double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pitlp_node:units = "MPa" ; + fates_hydro_pitlp_node:long_name = "turgor loss point" ; + double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; + fates_hydro_resid_node:units = "cm3/cm3" ; + fates_hydro_resid_node:long_name = "residual water conent" ; double fates_hydro_rfrac_stem(fates_pft) ; fates_hydro_rfrac_stem:units = "fraction" ; fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; @@ -266,6 +323,18 @@ variables: double fates_hydro_srl(fates_pft) ; fates_hydro_srl:units = "m g-1" ; fates_hydro_srl:long_name = "specific root length" ; + double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; + fates_hydro_thetas_node:units = "cm3/cm3" ; + fates_hydro_thetas_node:long_name = "saturated water content" ; + double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_alpha_node:units = "MPa-1" ; + fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; + double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_m_node:units = "unitless" ; + fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; + 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_leaf_c3psn(fates_pft) ; fates_leaf_c3psn:units = "flag" ; fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; @@ -293,6 +362,9 @@ variables: double fates_leaf_stomatal_slope_medlyn(fates_pft) ; fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; + double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; + fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; + fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; double fates_leaf_vcmaxha(fates_pft) ; fates_leaf_vcmaxha:units = "J/mol" ; fates_leaf_vcmaxha:long_name = "activation energy for vcmax" ; @@ -434,6 +506,12 @@ variables: double fates_recruit_seed_supplement(fates_pft) ; fates_recruit_seed_supplement:units = "KgC/m2/yr" ; fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; + double fates_stoich_nitr(fates_plant_organs, fates_pft) ; + fates_stoich_nitr:units = "gN/gC" ; + fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; + double fates_stoich_phos(fates_plant_organs, fates_pft) ; + fates_stoich_phos:units = "gP/gC" ; + fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; double fates_trim_inc(fates_pft) ; fates_trim_inc:units = "m2/m2" ; fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; @@ -455,6 +533,9 @@ variables: double fates_turnover_fnrt(fates_pft) ; fates_turnover_fnrt:units = "yr" ; fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; + double fates_turnover_leaf(fates_leafage_class, fates_pft) ; + fates_turnover_leaf:units = "yr" ; + fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; double fates_turnover_senleaf_fdrought(fates_pft) ; fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; @@ -464,15 +545,9 @@ variables: double fates_woody(fates_pft) ; fates_woody:units = "logical flag" ; fates_woody:long_name = "Binary woody lifeform flag" ; - double fates_history_ageclass_bin_edges(fates_history_age_bins) ; - fates_history_ageclass_bin_edges:units = "yr" ; - fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; - 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" ; - double fates_history_height_bin_edges(fates_history_height_bins) ; - fates_history_height_bin_edges:units = "m" ; - fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; double fates_fire_FBD(fates_litterclass) ; fates_fire_FBD:units = "kg Biomass/m3" ; fates_fire_FBD:long_name = "fuel bulk density" ; @@ -500,84 +575,9 @@ variables: double fates_frag_maxdecomp(fates_litterclass) ; fates_frag_maxdecomp:units = "yr-1" ; fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; - char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; - fates_hydro_organ_name:units = "unitless - string" ; - fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; - char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; - fates_alloc_organ_name:units = "unitless - string" ; - fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; - 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" ; - double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; - fates_cnp_turnover_nitr_retrans:units = "fraction" ; - fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; - double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; - fates_cnp_turnover_phos_retrans:units = "fraction" ; - fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; - double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; - fates_hydro_avuln_node:units = "unitless" ; - fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; - double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; - fates_hydro_epsil_node:units = "MPa" ; - fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; - double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; - fates_hydro_fcap_node:units = "unitless" ; - fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; - double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; - fates_hydro_kmax_node:units = "kg/MPa/m/s" ; - fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; - double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; - fates_hydro_p50_node:units = "MPa" ; - fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; - double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; - fates_hydro_pinot_node:units = "MPa" ; - fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; - double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; - fates_hydro_pitlp_node:units = "MPa" ; - fates_hydro_pitlp_node:long_name = "turgor loss point" ; - double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; - fates_hydro_resid_node:units = "cm3/cm3" ; - fates_hydro_resid_node:long_name = "residual water conent" ; - double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; - fates_hydro_thetas_node:units = "cm3/cm3" ; - fates_hydro_thetas_node:long_name = "saturated water content" ; - double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; - fates_hydro_vg_alpha_node:units = "MPa-1" ; - fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; - double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; - fates_hydro_vg_m_node:units = "unitless" ; - fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; - 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_stoich_nitr(fates_plant_organs, fates_pft) ; - fates_stoich_nitr:units = "gN/gC" ; - fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; - double fates_stoich_phos(fates_plant_organs, fates_pft) ; - fates_stoich_phos:units = "gP/gC" ; - fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; - double fates_alloc_organ_id(fates_plant_organs) ; - fates_alloc_organ_id:units = "unitless" ; - fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; - double fates_hydro_htftype_node(fates_hydr_organs) ; - fates_hydro_htftype_node:units = "unitless" ; - fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; 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_history_coageclass_bin_edges(fates_history_coage_bins) ; - fates_history_coageclass_bin_edges:units = "years" ; - fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; - double fates_history_damage_bin_edges(fates_history_damage_bins) ; - fates_history_damage_bin_edges:units = "% crown loss" ; - fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; - double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; - fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; - fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; - double fates_turnover_leaf(fates_leafage_class, fates_pft) ; - fates_turnover_leaf:units = "yr" ; - fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; double fates_base_mr_20 ; fates_base_mr_20:units = "gC/gN/s" ; fates_base_mr_20:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; @@ -787,30 +787,24 @@ variables: fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; // global attributes: - :history = "This file was generated by BatchPatchParams.py:\n", - "CDL Base File = archive/api24.1.0_101722_fates_params_default.cdl\n", - "XML patch file = archive/api24.1.0_101722_patch_params.xml" ; + :history = "This file was generated by BatchPatchParams.py:\nCDL Base File = archive/api24.1.0_101722_fates_params_default.cdl\nXML patch file = archive/api24.1.0_101722_patch_params.xml" ; data: - fates_hlm_pft_map = - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; + + fates_history_coageclass_bin_edges = 0, 5 ; + + fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; + + fates_history_damage_bin_edges = 0, 80 ; fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100 ; + fates_alloc_organ_id = 1, 2, 3, 6 ; + + fates_hydro_htftype_node = 1, 1, 1, 1 ; + fates_pftname = "broadleaf_evergreen_tropical_tree ", "needleleaf_evergreen_extratrop_tree ", @@ -825,6 +819,32 @@ data: "cool_c3_grass ", "c4_grass " ; + fates_hydro_organ_name = + "leaf ", + "stem ", + "transporting root ", + "absorbing root " ; + + fates_alloc_organ_name = + "leaf", + "fine root", + "sapwood", + "structure" ; + + fates_litterclass_name = + "twig ", + "small branch ", + "large branch ", + "trunk ", + "dead leaves ", + "live grass " ; + + 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, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 ; @@ -974,6 +994,18 @@ data: fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_cnp_turnover_nitr_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_turnover_phos_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10 ; @@ -1025,22 +1057,107 @@ data: fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5 ; - fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, - -1.5, -1.5, -1.5 ; + fates_hydro_avuln_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, - 0.333, 0.333, 0.333, 0.333, 0.333 ; + fates_hydro_epsil_node = + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, - 0.625, 0.625, 0.625, 0.625, 0.625 ; + fates_hydro_fcap_node = + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_kmax_node = + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; + + fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + -1.5, -1.5, -1.5 ; + + fates_hydro_p50_node = + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25 ; + + fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, + 0.333, 0.333, 0.333, 0.333, 0.333 ; + + fates_hydro_pinot_node = + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; + + fates_hydro_pitlp_node = + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + -1.67, -1.67, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; + + fates_hydro_resid_node = + 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; + + fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + 0.625, 0.625, 0.625, 0.625, 0.625 ; fates_hydro_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; + fates_hydro_thetas_node = + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; + + fates_hydro_vg_alpha_node = + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005 ; + + fates_hydro_vg_m_node = + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_hydro_vg_n_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_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, @@ -1066,6 +1183,9 @@ data: fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, 4.7, 2.2, 5.3, 1.6 ; + fates_leaf_vcmax25top = + 50, 62, 39, 61, 41, 58, 62, 54, 54, 78, 78, 78 ; + fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330 ; @@ -1194,6 +1314,25 @@ data: fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_stoich_nitr = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; + + fates_stoich_phos = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; + fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03 ; @@ -1212,6 +1351,9 @@ data: fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + fates_turnover_leaf = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_wood_density = 0.7, 0.4, 0.7, 0.53, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, @@ -1219,17 +1361,21 @@ data: fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; - fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; - - fates_litterclass_name = - "twig ", - "small branch ", - "large branch ", - "trunk ", - "dead leaves ", - "live grass " ; - - fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; + fates_hlm_pft_map = + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; @@ -1249,156 +1395,8 @@ data: fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; - fates_hydro_organ_name = - "leaf ", - "stem ", - "transporting root ", - "absorbing root " ; - - fates_alloc_organ_name = - "leaf", - "fine root", - "sapwood", - "structure" ; - - 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, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; - - fates_cnp_turnover_nitr_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_turnover_phos_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_hydro_avuln_node = - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 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_hydro_epsil_node = - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - - fates_hydro_fcap_node = - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, - 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_hydro_kmax_node = - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; - - fates_hydro_p50_node = - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25 ; - - fates_hydro_pinot_node = - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; - - fates_hydro_pitlp_node = - -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, - -1.67, -1.67, - -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, - -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, - -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; - - fates_hydro_resid_node = - 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, - 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - - fates_hydro_thetas_node = - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; - - fates_hydro_vg_alpha_node = - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005 ; - - fates_hydro_vg_m_node = - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_hydro_vg_n_node = - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 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_stoich_nitr = - 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, - 0.0047, 0.0047, 0.0047 ; - - fates_stoich_phos = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, - 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, - 0.00047, 0.00047, 0.00047, 0.00047 ; - - fates_alloc_organ_id = 1, 2, 3, 6 ; - - fates_hydro_htftype_node = 1, 1, 1, 1 ; - fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; - fates_history_coageclass_bin_edges = 0, 5 ; - - fates_history_damage_bin_edges = 0, 80 ; - - fates_leaf_vcmax25top = - 50, 62, 39, 61, 41, 58, 62, 54, 54, 78, 78, 78 ; - - fates_turnover_leaf = - 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - fates_base_mr_20 = 2.52e-06 ; fates_canopy_closure_thresh = 0.8 ; From fa8841e24a761f5fef6a769e7fe3c63312d7417e Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 15 Nov 2022 12:54:54 -0500 Subject: [PATCH 440/852] update to bci xml parameter patch --- parameter_files/patch_default_bciopt224.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parameter_files/patch_default_bciopt224.xml b/parameter_files/patch_default_bciopt224.xml index ae10a43d8e..8ab504ed31 100644 --- a/parameter_files/patch_default_bciopt224.xml +++ b/parameter_files/patch_default_bciopt224.xml @@ -38,8 +38,8 @@ 0.0 1 3 - 5e-09 - 5e-09 + 5e-09 + 0 5e-10 3e-08 0.03991654 From 5b372c9c8ab4343bdb8d838b534537746f19a9b6 Mon Sep 17 00:00:00 2001 From: ckoven Date: Tue, 15 Nov 2022 15:26:19 -0700 Subject: [PATCH 441/852] changed vertical profile of leaf MR to be propotional to SLA and leaf N/area --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index d3710567d0..0110a95118 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -2081,14 +2081,15 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & ! Shrubs 2.0749 ! C3 herbs/grasses 2.1956 - lnc = lnc_top * nscaler + ! note that this code uses the relationship between leaf N and respiration from Atkin et al + ! for the top of the canopy, but then assumes proportionality with N through the canopy. if ( nint(EDPftvarcon_inst%c3psn(ft)) == 1)then ! r_0 currently put into the EDPftvarcon_inst%dev_arbitrary_pft ! all figs in Atkin et al 2017 stop at zero Celsius so we will assume acclimation is fixed below that r_0 = EDPftvarcon_inst%dev_arbitrary_pft(ft) - r_t_ref = r_0 + r_1 * lnc + r_2 * max(0._r8, (tgrowth - tfrz) ) + r_t_ref = nscaler * (r_0 + r_1 * lnc_top + r_2 * max(0._r8, (tgrowth - tfrz) )) lmr = r_t_ref * exp(b * (veg_tempk - tfrz - TrefC) + c * ((veg_tempk-tfrz)**2 - TrefC**2)) @@ -2096,7 +2097,7 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & ! revert to Q10 model for C4 plants, parameter values as described above in Ryan 1991 method lmr25top = 2.525e-6_r8 * (1.5_r8 ** ((25._r8 - 20._r8)/10._r8)) - lmr25top = lmr25top * lnc / (umolC_to_kgC * g_per_kg) + lmr25 = lmr25top * lnc_top * nscaler / (umolC_to_kgC * g_per_kg) lmr = lmr25 * 2._r8**((veg_tempk-(tfrz+25._r8))/10._r8) lmr = lmr / (1._r8 + exp( 1.3_r8*(veg_tempk-(tfrz+55._r8)) )) From a16e1b5eb99692515bdfdf86b85164ab8d061595 Mon Sep 17 00:00:00 2001 From: ckoven Date: Tue, 15 Nov 2022 15:29:45 -0700 Subject: [PATCH 442/852] fixed bug in C4 respiration in prior version --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index d3710567d0..962b434929 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -2096,7 +2096,7 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & ! revert to Q10 model for C4 plants, parameter values as described above in Ryan 1991 method lmr25top = 2.525e-6_r8 * (1.5_r8 ** ((25._r8 - 20._r8)/10._r8)) - lmr25top = lmr25top * lnc / (umolC_to_kgC * g_per_kg) + lmr25 = lmr25top * lnc / (umolC_to_kgC * g_per_kg) lmr = lmr25 * 2._r8**((veg_tempk-(tfrz+25._r8))/10._r8) lmr = lmr / (1._r8 + exp( 1.3_r8*(veg_tempk-(tfrz+55._r8)) )) From a4d107b26443de2a410b87ab11a46793e8ccf93c Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 15 Nov 2022 17:53:49 -0700 Subject: [PATCH 443/852] remove text file that accidentally came in with sci.1.60.2_api.24.1.0 --- biogeochem/CMIP data.txt | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 biogeochem/CMIP data.txt diff --git a/biogeochem/CMIP data.txt b/biogeochem/CMIP data.txt deleted file mode 100644 index e80436482b..0000000000 --- a/biogeochem/CMIP data.txt +++ /dev/null @@ -1,24 +0,0 @@ -. -CMIP6.CMIP.NCAR.CESM2.historical.r11i1p1f1.day.rlds.gn' - - - -CF Standard Name | Unit | AMIP - ----------------- | ---- | ---- - -specific_humidity | 1 | hus - -precipitation_flux | kg m-2 s-1 | pr - -surface_air_pressure | Pa | ps - -surface_downwelling_longwave_flux_in_air | W/m2 | rlds - -surface_downwelling_shortwave_flux_in_air | W/m2 | rsds - -air_temperature | K | ta - -eastward_wind | ms-1 | ua - -northward_wind | ms-1 | va \ No newline at end of file From 6f2daa99d1b74e7d39d3410d9a73177f9bcc6c95 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 16 Nov 2022 16:40:35 -0800 Subject: [PATCH 444/852] add gridcell seed out and in diagnostic history outputs --- main/FatesHistoryInterfaceMod.F90 | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 1d8e31328c..c50c564b6a 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -1685,7 +1685,7 @@ end subroutine init_dim_kinds_maps ! ==================================================================================== - subroutine update_history_dyn(this,nc,nsites,sites) + subroutine update_history_dyn(this,nc,nsites,sites,bc_in,bc_out) ! --------------------------------------------------------------------------------- ! This is the call to update the history IO arrays that are expected to only change @@ -1713,6 +1713,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) integer , intent(in) :: nc ! clump index integer , intent(in) :: nsites type(ed_site_type) , intent(inout), target :: sites(nsites) + type(bc_out_type) , intent(in) :: bc_out(nsites) + type(bc_in_type) , intent(in) :: bc_in(nsites) ! Locals type(litter_type), pointer :: litt_c ! Pointer to the carbon12 litter pool @@ -1798,6 +1800,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_storebiomass_si_pft => this%hvars(ih_storebiomass_si_pft)%r82d, & hio_nindivs_si_pft => this%hvars(ih_nindivs_si_pft)%r82d, & hio_recruitment_si_pft => this%hvars(ih_recruitment_si_pft)%r82d, & + hio_seeds_out_gc_si_pft => this%hvars(ih_seeds_out_gc_si_pft)%r82d, & + hio_seeds_in_gc_si_pft => this%hvars(ih_seeds_in_gc_si_pft)%r82d, & hio_mortality_si_pft => this%hvars(ih_mortality_si_pft)%r82d, & hio_crownarea_si_pft => this%hvars(ih_crownarea_si_pft)%r82d, & hio_canopycrownarea_si_pft => this%hvars(ih_canopycrownarea_si_pft)%r82d, & @@ -3045,9 +3049,14 @@ subroutine update_history_dyn(this,nc,nsites,sites) sites(s)%fmort_rate_crown(:,:) = 0._r8 sites(s)%growthflux_fusion(:,:) = 0._r8 - ! pass the recruitment rate as a flux to the history, and then reset the recruitment buffer + ! site-level pft diagnostics do i_pft = 1, numpft + ! pass the recruitment rate as a flux to the history, and then reset the recruitment buffer hio_recruitment_si_pft(io_si,i_pft) = sites(s)%recruitment_rate(i_pft) * days_per_year / m2_per_ha + + ! Gridcell output and inputs + hio_seeds_out_gc_si_pft(io_si,i_pft) = bc_out(s)%seed_out(i_pft) + hio_seeds_in_gc_si_pft(io_si,i_pft) = bc_in(s)%seed_in(i_pft) end do sites(s)%recruitment_rate(:) = 0._r8 @@ -4530,7 +4539,21 @@ subroutine define_history_vars(this, initialize_variables) use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_recruitment_si_pft) + + call this%set_history_var(vname='FATES_SEEDS_IN_GRIDCELL_PF', & + units='kg', & + long='Site-level seed mass input from neighboring gridcells per pft', & + use_default='inactive', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_seeds_in_gc_si_pft) + call this%set_history_var(vname='FATES_SEEDS_OUT_GRIDCELL_PF', & + units='kg', & + long='Site-level seed mass output from neighboring gridcells per pft', & + use_default='inactive', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_seeds_out_gc_si_pft) + call this%set_history_var(vname='FATES_MORTALITY_PF', units='m-2 yr-1', & long='PFT-level mortality rate in number of individuals per m2 land area per year', & use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & From 18cad9edb1070b386fcf14309ad4642995349d46 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 16 Nov 2022 19:46:09 -0800 Subject: [PATCH 445/852] add type for index --- main/FatesHistoryInterfaceMod.F90 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index c50c564b6a..e8407474ed 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -520,6 +520,8 @@ module FatesHistoryInterfaceMod integer :: ih_nocomp_pftpatchfraction_si_pft integer :: ih_nocomp_pftnpatches_si_pft integer :: ih_nocomp_pftburnedarea_si_pft + integer :: ih_seeds_out_gc_si_pft + integer :: ih_seeds_in_gc_si_pft ! indices to (site x patch-age) variables integer :: ih_area_si_age From 4793deef5537fb5ac704f10621a2676eeb2b8367 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 16 Nov 2022 19:52:44 -0800 Subject: [PATCH 446/852] add missing use of bc_out type --- main/FatesHistoryInterfaceMod.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index e8407474ed..91550a754b 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -46,6 +46,7 @@ module FatesHistoryInterfaceMod use FatesInterfaceTypesMod , only : nlevsclass, nlevage use FatesInterfaceTypesMod , only : nlevheight use FatesInterfaceTypesMod , only : bc_in_type + use FatesInterfaceTypesMod , only : bc_out_type use FatesInterfaceTypesMod , only : hlm_model_day use FatesInterfaceTypesMod , only : nlevcoage use FatesInterfaceTypesMod , only : hlm_use_nocomp From d582af769a484bde4b20eac87048580c54270368 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 22 Nov 2022 16:55:25 -0800 Subject: [PATCH 447/852] add logical function to check if it is dispersal time --- main/FatesDispersalMod.F90 | 44 +++++++++++++++++++++++++++++++++ main/FatesInterfaceMod.F90 | 10 ++++++++ main/FatesInterfaceTypesMod.F90 | 10 ++++++-- 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index 3706df5b9a..b0d0fe4742 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -48,7 +48,10 @@ module FatesDispersalMod type(neighborhood_type), public, pointer :: lneighbors(:) public :: ProbabilityDensity + public :: IsItDispersalTime + integer :: prev_dispersal_date = 0 + character(len=*), parameter, private :: sourcefile = __FILE__ contains @@ -178,6 +181,47 @@ real(r8) function PD_logsech(dist, ipft) end function PD_logsech ! ==================================================================================== + + logical function IsItDispersalTime() + + ! Determine if seeds should be dispersed across gridcells. This eventually could be + ! driven by plant reproduction dynamics. For now this is based strictly on a calendar + + use FatesInterfaceMod, only : hlm_current_day, & + hlm_current_month, & + hlm_current_year, & + hlm_current_date + use FatesInterfaceTypesMod, only : fates_dispersal_cadence, & + fates_dispersal_cadence_daily, & + fates_dispersal_cadence_monthly, & + fates_dispersal_cadence_yearly + + ! LOCAL + integer :: check_date = 0 + + ! initialize the return value as false + IsItDispersalTime = .false. + + ! Select the date type to check against based on the dispersal candence + select case(fates_dispersal_cadence) + case (fates_dispersal_cadence_daily) + check_date = hlm_current_day + case (fates_dispersal_cadence_monthly) + check_date = hlm_current_month + case (fates_dispersal_cadence_yearly) + check_date = hlm_current_year + case default + write(fates_log(),*) 'ERROR: An undefined dispersal cadence was specified: ', fates_dispersal_cadence + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select + + ! Determine if it is a new day, month, or year. If true update the previous date to the current value + if (check_date .ne. prev_dispersal_date) then + IsItDispersalTime = .true. + prev_dispersal_date = check_date + end if + + end function IsItDispersalTime end module FatesDispersalMod diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 983dff00bf..952b87228b 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -893,6 +893,16 @@ subroutine SetFatesGlobalElements(use_fates) else fates_dispersal_kernel_mode = fates_dispersal_kernel_none end if + + ! Set the fates dispersal cadence if seed dispersal parameters are set. + ! This could be a parameter value setting as well. Currently hardcoded + if(any(EDPftvarcon_inst%seed_dispersal_param_A .lt. fates_check_param_set)) then + ! fates_dispersal_cadence = fates_dispersal_cadence_daily + fates_dispersal_cadence = fates_dispersal_cadence_monthly + ! fates_dispersal_cadence = fates_dispersal_cadence_yearly + else + fates_dispersal_cadence = 0 + end if ! Initialize Hydro globals ! (like water retention functions) diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 9bc5efecbd..33c1416501 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -222,13 +222,19 @@ module FatesInterfaceTypesMod ! competitors that will be generated on each site - integer, public :: fates_dispersal_kernel_mode !Flag to signal the use of grid cell seed dispersal + integer, public :: fates_dispersal_kernel_mode ! Flag to signal the use of grid cell seed dispersal ! Setting this to greater than zero overrides seed rain - + integer, parameter, public :: fates_dispersal_kernel_none = 0 ! no dispersal (use seed rain only) integer, parameter, public :: fates_dispersal_kernel_exponential = 1 ! exponential dispersal kernel integer, parameter, public :: fates_dispersal_kernel_exppower = 2 ! exponential power (ExP) dispersal kernel integer, parameter, public :: fates_dispersal_kernel_logsech = 3 ! logistic-sech (LogS) dispersal kernel + + integer, public :: fates_dispersal_cadence ! Setting to denote how often seed dispersal should occur + + integer, parameter, public :: fates_dispersal_cadence_daily = 1 ! Disperse seeds daily + integer, parameter, public :: fates_dispersal_cadence_monthly = 2 ! Disperse seeds monthly + integer, parameter, public :: fates_dispersal_cadence_yearly = 3 ! Disperse seeds yearly ! ------------------------------------------------------------------------------------- ! These vectors are used for history output mapping From 86ae4be3940ad71346775089c0abb3f7da855f53 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 22 Nov 2022 17:23:16 -0800 Subject: [PATCH 448/852] correct use call for dispersal timing function --- main/FatesDispersalMod.F90 | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index b0d0fe4742..080abb70e6 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -118,6 +118,8 @@ subroutine ProbabilityDensity(pd, ipft, dist) call endrun(msg=errMsg(sourcefile, __LINE__)) end select + write(fates_log(),*) 'ipft,dist,pd: ', ipft, dist, pd + end subroutine ProbabilityDensity ! ==================================================================================== @@ -134,6 +136,7 @@ real(r8) function PD_exponential(dist, ipft) ! for different weight calculations (and could be held only in fates) PD_exponential = exp(-EDPftvarcon_inst%seed_dispersal_param_A(ipft)*dist) + write(fates_log(),*) 'ipft,dist,PD_exp: ', ipft, dist, PD_exponential end function PD_exponential @@ -187,11 +190,11 @@ logical function IsItDispersalTime() ! Determine if seeds should be dispersed across gridcells. This eventually could be ! driven by plant reproduction dynamics. For now this is based strictly on a calendar - use FatesInterfaceMod, only : hlm_current_day, & + use FatesInterfaceTypesMod, only : hlm_current_day, & hlm_current_month, & hlm_current_year, & - hlm_current_date - use FatesInterfaceTypesMod, only : fates_dispersal_cadence, & + hlm_current_date, & + fates_dispersal_cadence, & fates_dispersal_cadence_daily, & fates_dispersal_cadence_monthly, & fates_dispersal_cadence_yearly From b35025e727028454ae7c1c8f9949526f8fb5a062 Mon Sep 17 00:00:00 2001 From: Shijie Shu Date: Wed, 23 Nov 2022 16:42:50 -0800 Subject: [PATCH 449/852] Ignore small logging disturbance. --- biogeochem/EDPatchDynamicsMod.F90 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index c0f6ade5e3..9c5034c647 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -398,6 +398,12 @@ subroutine disturbance_rates( site_in, bc_in) (currentPatch%area - currentPatch%total_canopy_area) * harvest_rate / currentPatch%area endif + ! For nocomp mode, we need to prevent producing too small patches, which may produce small patches + if ((hlm_use_nocomp .eq. itrue) .and. & + (currentPatch%disturbance_rates(dtype_ilog)*currentPatch%area .lt. min_patch_area_forced)) then + currentPatch%disturbance_rates(dtype_ilog) = 0._r8 + end if + ! fraction of the logging disturbance rate that is non-harvested if (currentPatch%disturbance_rates(dtype_ilog) .gt. nearzero) then currentPatch%fract_ldist_not_harvested = dist_rate_ldist_notharvested / & From fb5a9de0af8d9d2cc5d6df0157763b3b4b228751 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 28 Nov 2022 13:51:59 -0500 Subject: [PATCH 450/852] Updated the fates default parameter file API update xmls --- ...api24.2.0_112822_fates_params_default.cdl} | 23 +++++++++---------- .../{ => archive}/apichange_23to24.xml | 0 .../apichange_24.2to25.xml} | 4 ++-- 3 files changed, 13 insertions(+), 14 deletions(-) rename parameter_files/archive/{fates_params_default_api24.1.0_c221109.cdl => api24.2.0_112822_fates_params_default.cdl} (98%) rename parameter_files/{ => archive}/apichange_23to24.xml (100%) rename parameter_files/{apichange_24to25.xml => archive/apichange_24.2to25.xml} (95%) diff --git a/parameter_files/archive/fates_params_default_api24.1.0_c221109.cdl b/parameter_files/archive/api24.2.0_112822_fates_params_default.cdl similarity index 98% rename from parameter_files/archive/fates_params_default_api24.1.0_c221109.cdl rename to parameter_files/archive/api24.2.0_112822_fates_params_default.cdl index 569e6a1ab6..0c89520e40 100644 --- a/parameter_files/archive/fates_params_default_api24.1.0_c221109.cdl +++ b/parameter_files/archive/api24.2.0_112822_fates_params_default.cdl @@ -1,4 +1,4 @@ -netcdf fates_params_default_api24 { +netcdf fates_params_default { dimensions: fates_NCWD = 4 ; fates_history_age_bins = 7 ; @@ -221,7 +221,6 @@ variables: double fates_cnp_store_ovrflw_frac(fates_pft) ; fates_cnp_store_ovrflw_frac:units = "fraction" ; fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; - fates_cnp_store_ovrflw_frac:use_case = "None" ; double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; fates_cnp_turnover_nitr_retrans:units = "fraction" ; fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; @@ -500,7 +499,7 @@ variables: fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; fates_recruit_seed_dbh_repro_threshold:units = "cm" ; - fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter (if any) where the plant will start extra clonal allocation to the seed pool" ; + fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter where the plant will increase allocation to the seed pool by fraction: fates_recruit_seed_alloc_mature" ; double fates_recruit_seed_germination_rate(fates_pft) ; fates_recruit_seed_germination_rate:units = "yr-1" ; fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; @@ -788,7 +787,7 @@ variables: fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; // global attributes: - :history = "This parameter file is maintained in version control\nSee https://github.com/NGEET/fates/blob/master/parameter_files/fates_params_default.cdl \nFor changes, use git blame \n" ; + :history = "This file was generated by BatchPatchParams.py:\nCDL Base File = archive/api24.1.0_101722_fates_params_default.cdl\nXML patch file = archive/api24.1.0_101722_patch_params.xml" ; data: fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; @@ -902,7 +901,7 @@ data: fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 ; - fates_allom_dbh_maxheight = 90, 90, 90, 90, 90, 90, 3, 3, 2, 0.35, 0.35, 0.35 ; + fates_allom_dbh_maxheight = 90, 80, 80, 80, 90, 80, 3, 3, 2, 0.35, 0.35, 0.35 ; fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -1173,7 +1172,7 @@ data: fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, 0.03, 0.03, 0.03, 0.03, 0.03 ; - fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, + fates_leaf_slatop = 0.012, 0.005, 0.024, 0.009, 0.03, 0.03, 0.012, 0.03, 0.03, 0.03, 0.03, 0.03 ; fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, @@ -1185,7 +1184,7 @@ data: 4.7, 2.2, 5.3, 1.6 ; fates_leaf_vcmax25top = - 50, 65, 39, 62, 41, 58, 62, 54, 54, 78, 78, 78 ; + 50, 62, 39, 61, 41, 58, 62, 54, 54, 78, 78, 78 ; fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330 ; @@ -1204,7 +1203,7 @@ data: fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014 ; - fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -60, -10, -80, -80, + fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -80, -60, -10, -80, -80, -20, 2.5 ; fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, @@ -1292,7 +1291,7 @@ data: fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.12, 0.12, 0.12 ; - fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, + fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.2, 0.2, 0.2, 0.125, 0.125, 0.125 ; fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, @@ -1307,8 +1306,8 @@ data: fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9 ; - fates_recruit_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, - 1.47, 1.47, 1.47 ; + fates_recruit_seed_dbh_repro_threshold = 90, 80, 80, 80, 90, 80, 3, 3, 2, + 0.35, 0.35, 0.35 ; fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; @@ -1357,7 +1356,7 @@ data: fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, + fates_wood_density = 0.7, 0.4, 0.7, 0.53, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7 ; fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; diff --git a/parameter_files/apichange_23to24.xml b/parameter_files/archive/apichange_23to24.xml similarity index 100% rename from parameter_files/apichange_23to24.xml rename to parameter_files/archive/apichange_23to24.xml diff --git a/parameter_files/apichange_24to25.xml b/parameter_files/archive/apichange_24.2to25.xml similarity index 95% rename from parameter_files/apichange_24to25.xml rename to parameter_files/archive/apichange_24.2to25.xml index a1725eba0f..41d3ea711b 100644 --- a/parameter_files/apichange_24to25.xml +++ b/parameter_files/archive/apichange_24.2to25.xml @@ -13,8 +13,8 @@ the variables --> - fates_params_default.cdl - fates_params_default_api25.cdl + archive/api24.2.0_112822_fates_params_default.cdl + fates_params_default_api25_v2.cdl 1,2,3,4,5,6,7,8,9,10,11,12 From dd6f0670c4c5fd95d5794a0588873fdecdf42d90 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 28 Nov 2022 20:51:20 -0700 Subject: [PATCH 451/852] fix typo on carbon12_element --- fire/SFMainMod.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index efdd51c691..fdb3501bd2 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -195,9 +195,9 @@ subroutine charecteristics_of_fuel ( currentSite ) if( prt_params%woody(currentCohort%pft) == ifalse)then currentPatch%livegrass = currentPatch%livegrass + & - ( currentCohort%prt%GetState(leaf_organ, carbon12_elements) + & - currentCohort%prt%GetState(sapw_organ, carbon12_elements) + & - currentCohort%prt%GetState(struct_organ, carbon12_elements) ) * & + ( currentCohort%prt%GetState(leaf_organ, carbon12_element) + & + currentCohort%prt%GetState(sapw_organ, carbon12_element) + & + currentCohort%prt%GetState(struct_organ, carbon12_element) ) * & currentCohort%n/currentPatch%area endif From ab7af564b9e6e5da660159f936d09c1a29d24d37 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 29 Nov 2022 15:24:44 -0700 Subject: [PATCH 452/852] bug fix in fineroot allometry --- biogeochem/FatesAllometryMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index 1f4fbaa30d..1a2b16283e 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -1056,7 +1056,7 @@ subroutine bfineroot(d,ipft,canopy_trim,l2fr,bfr,dbfrdd) bfr = blmax*l2fr if(present(dbfrdd))then - dbfrdd = dbfrmaxdd*l2fr + dbfrdd = dblmaxdd*l2fr end if case DEFAULT From 9f6b8e9ccf96dbcf41bb858bfad71df520abefda Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 29 Nov 2022 15:25:02 -0700 Subject: [PATCH 453/852] Removed unused variable --- biogeochem/FatesSoilBGCFluxMod.F90 | 2 -- 1 file changed, 2 deletions(-) diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index ff5b2c7653..ae01df7c93 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -636,8 +636,6 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) real(r8), pointer :: flux_cel_si(:) real(r8), pointer :: flux_lab_si(:) real(r8), pointer :: flux_lig_si(:) - real(r8), pointer :: efflux_ptr ! Points to the current - ! element's root efflux type(litter_type), pointer :: litt real(r8) :: surface_prof(bc_in%nlevsoil) ! this array is used to distribute From b746edd6ab07c75ec6d2e0af7ef6c68f1ba4944d Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 29 Nov 2022 18:46:44 -0700 Subject: [PATCH 454/852] Reverting nclmax to 2 --- main/EDTypesMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 5f9ead2229..252709009a 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -27,7 +27,7 @@ module EDTypesMod private ! By default everything is private save - integer, parameter, public :: nclmax = 3 ! Maximum number of canopy layers + integer, parameter, public :: nclmax = 2 ! Maximum number of canopy layers integer, parameter, public :: ican_upper = 1 ! Nominal index for the upper canopy integer, parameter, public :: ican_ustory = 2 ! Nominal index for diagnostics that refer ! to understory layers (all layers that From d7e1ebef9433e828a90da71f1af93dad9a528448 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 29 Nov 2022 20:52:49 -0500 Subject: [PATCH 455/852] Added cohort_hydr pointer --- biogeophys/FatesPlantHydraulicsMod.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 23f488aa6c..752c903b03 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -2750,6 +2750,7 @@ subroutine hydraulics_bc ( nsites, sites, bc_in, bc_out, dtime) ccohort=>cpatch%tallest do while(associated(ccohort)) + ccohort_hydr => ccohort%co_hydr sum_l_aroot = sum(ccohort_hydr%l_aroot_layer(:)) ft = ccohort%pft From db6cebe79dafe50c41c13f53fcd2efd39c5bc2b6 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 29 Nov 2022 20:57:06 -0500 Subject: [PATCH 456/852] Syntactical fixes --- main/FatesHistoryInterfaceMod.F90 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 836c532a02..7c7be86182 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2209,6 +2209,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) io_si = sites(s)%h_gid + flux_diags_c => sites(s)%flux_diags(element_pos(carbon12_element)) + ! set the fates fraction to one, since it is zero on non-fates columns, & ! the average is the total gridcell fates fraction hio_fates_fraction_si(io_si) = 1._r8 @@ -3216,7 +3218,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! Update Litter Flux Variables litt_c => cpatch%litter(element_pos(carbon12_element)) - flux_diags_c => sites(s)%flux_diags(element_pos(carbon12_element)) + do i_cwd = 1, ncwd @@ -3462,12 +3464,10 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! Some carbon only litter diagnostics (legacy) ! ------------------------------------------------------------------------------ - flux_diags => sites(s)%flux_diags(element_pos(carbon12_element)) - - hio_litter_in_si(io_si) = (sum(flux_diags%cwd_ag_input(:)) + & - sum(flux_diags%cwd_bg_input(:)) + & - sum(flux_diags%leaf_litter_input(:)) + & - sum(flux_diags%root_litter_input(:))) * & + hio_litter_in_si(io_si) = (sum(flux_diags_c%cwd_ag_input(:)) + & + sum(flux_diags_c%cwd_bg_input(:)) + & + sum(flux_diags_c%leaf_litter_input(:)) + & + sum(flux_diags_c%root_litter_input(:))) * & AREA_INV * days_per_sec hio_litter_out_si(io_si) = 0._r8 From 89cf208716e988dd2026383007e2c1c8a50e7def Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 30 Nov 2022 08:09:52 -0700 Subject: [PATCH 457/852] fixed integration array indices for CNP --- parteh/PRTAllometricCNPMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index ab8e1abb2d..9e53e422a6 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -2233,7 +2233,7 @@ function AllomCNPGrowthDeriv(l_state_array,l_state_mask,cbalance,intgr_params) r canopy_trim = intgr_params(intgr_parm_ctrim) ipft = int(intgr_params(intgr_parm_pft)) l2fr = intgr_params(intgr_parm_l2fr) - crown_damage = int(intgr_params(acnp_bc_in_id_cdamage)) + crown_damage = int(intgr_params(intgr_parm_cdamage)) call bleaf(dbh,ipft,crown_damage,canopy_trim,leaf_c_target,leaf_dcdd_target) call bfineroot(dbh,ipft,canopy_trim,l2fr,fnrt_c_target,fnrt_dcdd_target) From 257e26cc8367124d61c17b3b2acc293b1180c784 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 30 Nov 2022 13:06:25 -0500 Subject: [PATCH 458/852] Removed unused string --- main/EDTypesMod.F90 | 2 -- 1 file changed, 2 deletions(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 071b54f424..b68e6ce5e6 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -174,8 +174,6 @@ module EDTypesMod real(r8), parameter, public :: min_n_safemath = 1.0E-12_r8 ! in some cases, we want to immediately remove super small ! number densities of cohorts to prevent FPEs - character*4 yearchar - ! special mode to cause PFTs to create seed mass of all currently-existing PFTs logical, parameter, public :: homogenize_seed_pfts = .false. From d3279d39ffa10346bc4833f431b380c3156660bd Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 1 Dec 2022 08:06:48 -0700 Subject: [PATCH 459/852] Removed the CLSZPF dimension temporarily to pass clm tests --- main/FatesHistoryInterfaceMod.F90 | 247 +++++++++++------------------- 1 file changed, 91 insertions(+), 156 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 1f8c2708b3..0b8ac5ecdc 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -218,8 +218,6 @@ module FatesHistoryInterfaceMod integer :: ih_l2fr_clscpf integer :: ih_recl2fr_canopy_pf integer :: ih_recl2fr_ustory_pf - integer :: ih_ngrowlim_clscpf - integer :: ih_pgrowlim_clscpf integer :: ih_nh4uptake_scpf integer :: ih_no3uptake_scpf integer :: ih_puptake_scpf @@ -237,12 +235,6 @@ module FatesHistoryInterfaceMod integer :: ih_nfix_si integer :: ih_nfix_scpf - ! These dimensions are useful for upscaling (weighting clscpf) - integer :: ih_fnrtc_clscpf - integer :: ih_gpp_clscpf - integer :: ih_totvegc_clscpf - - integer :: ih_trimming_si integer :: ih_area_plant_si integer :: ih_area_trees_si @@ -1903,23 +1895,17 @@ subroutine update_history_nutrflux(this,csite) real(r8):: uconv ! combined unit conversion factor ! We use gpp and fineroot C for weighted averages - real(r8) :: gpp_clscpf(nclmax*numpft*nlevsclass) real(r8) :: gpp_si - real(r8) :: fnrtc_clscpf(nclmax*numpft*nlevsclass) real(r8) :: fnrtc_si real(r8) :: fnrt_c associate( & - hio_ngrowlim_clscpf => this%hvars(ih_ngrowlim_clscpf)%r82d, & - hio_pgrowlim_clscpf => this%hvars(ih_pgrowlim_clscpf)%r82d, & - hio_l2fr_clscpf => this%hvars(ih_l2fr_clscpf)%r82d, & + !hio_l2fr_clscpf => this%hvars(ih_l2fr_clscpf)%r82d, & hio_l2fr_si => this%hvars(ih_l2fr_si)%r81d, & hio_recl2fr_canopy_pf => this%hvars(ih_recl2fr_canopy_pf)%r82d, & hio_recl2fr_ustory_pf => this%hvars(ih_recl2fr_ustory_pf)%r82d ) - gpp_clscpf(:) = 0._r8 gpp_si = 0._r8 - fnrtc_clscpf(:) = 0._r8 fnrtc_si = 0._r8 ! history site index @@ -1946,27 +1932,15 @@ subroutine update_history_nutrflux(this,csite) ! unit conversion factor to get x/plant/day -> x/m2/sec uconv = ccohort%n * ha_per_m2 * days_per_sec - ! Growth Limitations - select case(ccohort%cnp_limiter) - case(2) ! Nitrogen - hio_ngrowlim_clscpf(io_si,iclscpf) = hio_ngrowlim_clscpf(io_si,iclscpf) + & - ccohort%n*ccohort%gpp_acc_hold - case(3) - hio_ngrowlim_clscpf(io_si,iclscpf) = hio_ngrowlim_clscpf(io_si,iclscpf) + & - ccohort%n*ccohort%gpp_acc_hold - end select - fnrt_c = ccohort%prt%GetState(fnrt_organ, carbon12_element) - hio_l2fr_clscpf(io_si,iclscpf) = & - hio_l2fr_clscpf(io_si,iclscpf) + ccohort%n*fnrt_c*ccohort%l2fr + !hio_l2fr_clscpf(io_si,iclscpf) = & + ! hio_l2fr_clscpf(io_si,iclscpf) + ccohort%n*fnrt_c*ccohort%l2fr hio_l2fr_si(io_si) = hio_l2fr_si(io_si) + ccohort%n*fnrt_c*ccohort%l2fr ! These are used for normalizing weighted averages gpp_si = gpp_si + ccohort%n*ccohort%gpp_acc_hold - gpp_clscpf(iclscpf) = gpp_clscpf(iclscpf) + ccohort%n*ccohort%gpp_acc_hold - fnrtc_clscpf(iclscpf) = fnrtc_clscpf(iclscpf) + ccohort%n*fnrt_c fnrtc_si = fnrtc_si + ccohort%n*fnrt_c ! Loop over the different elements. @@ -2060,21 +2034,13 @@ subroutine update_history_nutrflux(this,csite) end do ! Normalize the layer x size x pft arrays - do iclscpf = 1,nclmax*numpft*nlevsclass - - if(gpp_clscpf(iclscpf)>nearzero) then - hio_ngrowlim_clscpf(io_si,iclscpf) = hio_ngrowlim_clscpf(io_si,iclscpf) / gpp_clscpf(iclscpf) - hio_pgrowlim_clscpf(io_si,iclscpf) = hio_pgrowlim_clscpf(io_si,iclscpf) / gpp_clscpf(iclscpf) - else - hio_ngrowlim_clscpf(io_si,iclscpf) = hlm_hio_ignore_val - hio_pgrowlim_clscpf(io_si,iclscpf) = hlm_hio_ignore_val - end if - if(fnrtc_clscpf(iclscpf)>nearzero) then - hio_l2fr_clscpf(io_si,iclscpf) = hio_l2fr_clscpf(io_si,iclscpf) / fnrtc_clscpf(iclscpf) - else - hio_l2fr_clscpf(io_si,iclscpf) = hlm_hio_ignore_val - end if - end do + !do iclscpf = 1,nclmax*numpft*nlevsclass + !if(fnrtc_clscpf(iclscpf)>nearzero) then + ! hio_l2fr_clscpf(io_si,iclscpf) = hio_l2fr_clscpf(io_si,iclscpf) / fnrtc_clscpf(iclscpf) + !else + ! hio_l2fr_clscpf(io_si,iclscpf) = hlm_hio_ignore_val + !end if + !end do do ft = 1,numpft hio_recl2fr_canopy_pf(io_si,ft) = csite%rec_l2fr(ft,1) @@ -5085,7 +5051,7 @@ subroutine define_history_vars(this, initialize_variables) ! cohort size x patch age (site_scag_r8) : SZAP ! cohort size x patch age x pft (site_scagpft_r8) : SZAPPF ! cohort size x pft (site_size_pft_r8) : SZPF - ! canopy layer x size x pft (site_clscpf_r8) : CLSZPF + ! canopy layer x size x pft (site_clscpf_r8) : CLSZPF (NOT ACTIVE) ! cohort size x crown damage (site_cdsc_r8) : SZCD ! cohort size x crown damage x pft (site_cdpf_r8) : CDPF @@ -5662,35 +5628,24 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_l2fr_si) - call this%set_history_var(vname='FATES_RECL2FR_CANOPY_PF', units='kg kg-1', & + call this%set_history_var(vname='FATES_L2FR_CANOPY_REC_PF', units='kg kg-1', & long='The leaf to fineroot biomass multiplier for recruits (canopy)', & use_default='active', & avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_recl2fr_canopy_pf) - call this%set_history_var(vname='FATES_RECL2FR_USTORY_PF', units='kg kg-1', & + call this%set_history_var(vname='FATES_L2FR_USTORY_REC_PF', units='kg kg-1', & long='The leaf to fineroot biomass multiplier for recruits (understory)', & use_default='active', & avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_recl2fr_ustory_pf) - call this%set_history_var(vname='FATES_NGROWLIM_CLSZPF', units='', & - long='The fraction of gpp*days where stature growth is limited by N (vs C or P)', & - use_default='inactive', & - avgflag='A', vtype=site_clscpf_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_ngrowlim_clscpf) - - call this%set_history_var(vname='FATES_PGROWLIM_CLSZPF', units='', & - long='The fraction of gpp*days where stature growth is limited by P (vs N or C) (canopy)', & - use_default='inactive', & - avgflag='A', vtype=site_clscpf_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_pgrowlim_clscpf) - - call this%set_history_var(vname='FATES_L2FR_CLSZPF', units='kg kg-1', & - long='The leaf to fineroot biomass multiplier for target allometry', & - use_default='inactive', & - avgflag='A', vtype=site_clscpf_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_l2fr_clscpf) + !call this%set_history_var(vname='FATES_L2FR_CLSZPF', units='kg kg-1', & + ! long='The leaf to fineroot biomass multiplier for target allometry', & + ! use_default='inactive', & + ! avgflag='A', vtype=site_clscpf_r8, hlms='CLM:ALM', upfreq=1, & + ! ivar=ivar, initialize=initialize_variables, index = ih_l2fr_clscpf) + call this%set_history_var(vname='FATES_NH4UPTAKE_SZPF', & units='kg m-2 s-1', & long='ammonium uptake rate by plants by size-class x pft in kg NH4 per m2 per second', & @@ -5717,7 +5672,7 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=5, ivar=ivar, & initialize=initialize_variables, index = ih_ndemand_scpf) - call this%set_history_var(vname='FATES_SYMNFIX_SZPF', units='kg m-2 s-1', & + call this%set_history_var(vname='FATES_NFIX_SYM_SZPF', units='kg m-2 s-1', & long='symbiotic dinitrogen fixation, by size-class x pft in kg N per m2 per second', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & hlms='CLM:ALM', upfreq=5, ivar=ivar, & @@ -5748,7 +5703,7 @@ subroutine define_history_vars(this, initialize_variables) upfreq=5, ivar=ivar, initialize=initialize_variables, & index = ih_ndemand_si) - call this%set_history_var(vname='FATES_SYMNFIX', units='kg m-2 s-1', & + call this%set_history_var(vname='FATES_NFIX_SYM', units='kg m-2 s-1', & long='symbiotic dinitrogen fixation in kg N per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=5, ivar=ivar, initialize=initialize_variables, & @@ -5844,9 +5799,6 @@ subroutine define_history_vars(this, initialize_variables) use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index = ih_repron_scpf) - - - end if nitrogen_active_if @@ -5910,6 +5862,76 @@ subroutine define_history_vars(this, initialize_variables) upfreq=5, ivar=ivar, initialize=initialize_variables, & index = ih_pdemand_si) + call this%set_history_var(vname='FATES_VEGP_SZPF', units='kg m-2', & + long='total (live) vegetation phosphorus mass by size-class x pft in kg P per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_totvegp_scpf) + + call this%set_history_var(vname='FATES_LEAFP_SZPF', units='kg m-2', & + long='leaf phosphorus mass by size-class x pft', use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_leafp_scpf ) + + call this%set_history_var(vname='FATES_FROOTP_SZPF', units='kg m-2', & + long='fine-root phosphorus mass by size-class x pft in kg P per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_fnrtp_scpf) + + call this%set_history_var(vname='FATES_SAPWOODP_SZPF', units='kg m-2', & + long='sapwood phosphorus mass by size-class x pft in kg P per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_sapwp_scpf) + + call this%set_history_var(vname='FATES_STOREP_SZPF', units='kg m-2', & + long='storage phosphorus mass by size-class x pft in kg P per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_storep_scpf) + + call this%set_history_var(vname='FATES_STOREP_TF_CANOPY_SZPF', & + units='1', & + long='storage phosphorus fraction (0-1) of target, in canopy, by size-class x pft', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_storeptfrac_canopy_scpf) + + call this%set_history_var(vname='FATES_STOREP_TF_USTORY_SZPF', & + units='1', & + long='storage phosphorus fraction (0-1) of target, in understory, by size-class x pft', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, & + index = ih_storeptfrac_understory_scpf) + + call this%set_history_var(vname='FATES_REPROP_SZPF', units='kg m-2', & + long='reproductive phosphorus mass (on plant) by size-class x pft in kg P per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_reprop_scpf) + + call this%set_history_var(vname='FATES_PUPTAKE_SZPF', & + units='kg m-2 s-1', & + long='phosphorus uptake rate by plants, by size-class x pft in kg P per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=5, ivar=ivar, & + initialize=initialize_variables, index = ih_puptake_scpf) + + call this%set_history_var(vname='FATES_PEFFLUX_SZPF', & + units='kg m-2 s-1', & + long='phosphorus efflux, root to soil, by size-class x pft in kg P per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=5, ivar=ivar, & + initialize=initialize_variables, index = ih_pefflux_scpf) + + call this%set_history_var(vname='FATES_PDEMAND_SZPF', units='kg m-2 s-1', & + long='plant P need (algorithm dependent), by size-class x pft in kg P per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=5, ivar=ivar, & + initialize=initialize_variables, index = ih_pdemand_scpf) + end if phosphorus_active_if call this%set_history_var(vname='FATES_STRUCTC', units='kg m-2', & @@ -7646,93 +7668,6 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_reproc_scpf) - ! NITROGEN - - nitrogen_active_if2: if(any(element_list(:)==nitrogen_element)) then - - - - - - - end if nitrogen_active_if2 - - ! PHOSPHORUS - - phosphorus_active_if2: if(any(element_list(:)==phosphorus_element))then - - call this%set_history_var(vname='FATES_VEGP_SZPF', units='kg m-2', & - long='total (live) vegetation phosphorus mass by size-class x pft in kg P per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_totvegp_scpf) - - call this%set_history_var(vname='FATES_LEAFP_SZPF', units='kg m-2', & - long='leaf phosphorus mass by size-class x pft', use_default='inactive', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_leafp_scpf ) - - call this%set_history_var(vname='FATES_FROOTP_SZPF', units='kg m-2', & - long='fine-root phosphorus mass by size-class x pft in kg P per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_fnrtp_scpf) - - call this%set_history_var(vname='FATES_SAPWOODP_SZPF', units='kg m-2', & - long='sapwood phosphorus mass by size-class x pft in kg P per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_sapwp_scpf) - - call this%set_history_var(vname='FATES_STOREP_SZPF', units='kg m-2', & - long='storage phosphorus mass by size-class x pft in kg P per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_storep_scpf) - - call this%set_history_var(vname='FATES_STOREP_TF_CANOPY_SZPF', & - units='1', & - long='storage phosphorus fraction (0-1) of target, in canopy, by size-class x pft', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_storeptfrac_canopy_scpf) - - call this%set_history_var(vname='FATES_STOREP_TF_USTORY_SZPF', & - units='1', & - long='storage phosphorus fraction (0-1) of target, in understory, by size-class x pft', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_storeptfrac_understory_scpf) - - call this%set_history_var(vname='FATES_REPROP_SZPF', units='kg m-2', & - long='reproductive phosphorus mass (on plant) by size-class x pft in kg P per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_reprop_scpf) - - call this%set_history_var(vname='FATES_PUPTAKE_SZPF', & - units='kg m-2 s-1', & - long='phosphorus uptake rate by plants, by size-class x pft in kg P per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=5, ivar=ivar, & - initialize=initialize_variables, index = ih_puptake_scpf) - - call this%set_history_var(vname='FATES_PEFFLUX_SZPF', & - units='kg m-2 s-1', & - long='phosphorus efflux, root to soil, by size-class x pft in kg P per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=5, ivar=ivar, & - initialize=initialize_variables, index = ih_pefflux_scpf) - - call this%set_history_var(vname='FATES_PDEMAND_SZPF', units='kg m-2 s-1', & - long='plant P need (algorithm dependent), by size-class x pft in kg P per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=5, ivar=ivar, & - initialize=initialize_variables, index = ih_pdemand_scpf) - - end if phosphorus_active_if2 - ! organ-partitioned NPP / allocation fluxes call this%set_history_var(vname='FATES_LEAF_ALLOC', units='kg m-2 s-1', & From f9d92208c72014a4337d6aaded68371dcdb78c85 Mon Sep 17 00:00:00 2001 From: Marcos Longo Date: Thu, 1 Dec 2022 13:30:29 -0800 Subject: [PATCH 460/852] Changes and updates to drought deciduous phenology to improve process representation. A summary of the changes: 1. The soil moisture threshold is now defined for the rooting layer instead of at an arbitrary soil depth. 2. Because the rooting depth is PFT-dependent, most variables driving phenology became PFT variables too. 3. The code now accepts thresholds both in terms of liquid volume (m3/m3) or matric potential (mm) 4. Drought phenology can now be defined either as a "hard" deciduous or semi-deciduous. The difference is that in semi-deciduous, plants may reduce foliage when soil is moderately dry, and only shed all leaves under very dry conditions. 5. The code now allows PFTs to actively abscise fine roots as a strategy to reduce carbon costs. There will be additional implementations in upcoming commits. --- biogeochem/EDCohortDynamicsMod.F90 | 33 +- biogeochem/EDPhysiologyMod.F90 | 1007 +++++++++++++--------- biogeochem/FatesAllometryMod.F90 | 11 +- main/EDInitMod.F90 | 120 ++- main/EDMainMod.F90 | 2 +- main/EDParamsMod.F90 | 10 + main/EDPftvarcon.F90 | 65 +- main/EDTypesMod.F90 | 46 +- main/FatesHistoryInterfaceMod.F90 | 131 ++- main/FatesInventoryInitMod.F90 | 67 +- main/FatesRestartInterfaceMod.F90 | 186 +++- parameter_files/fates_params_default.cdl | 17 +- parteh/PRTAllometricCNPMod.F90 | 136 ++- parteh/PRTAllometricCarbonMod.F90 | 187 +++- parteh/PRTLossFluxesMod.F90 | 46 +- parteh/PRTParametersMod.F90 | 14 +- parteh/PRTParamsFATESMod.F90 | 43 +- 17 files changed, 1471 insertions(+), 650 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 2d796a9048..14522c575f 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -90,9 +90,15 @@ module EDCohortDynamicsMod use PRTAllometricCarbonMod, only : ac_bc_in_id_ctrim use PRTAllometricCarbonMod, only : ac_bc_inout_id_dbh use PRTAllometricCarbonMod, only : ac_bc_in_id_lstat + use PRTAllometricCarbonMod, only : ac_bc_in_id_efleaf + use PRTAllometricCarbonMod, only : ac_bc_in_id_effnrt + use PRTAllometricCarbonMod, only : ac_bc_in_id_efstem use PRTAllometricCNPMod, only : cnp_allom_prt_vartypes use PRTAllometricCNPMod, only : acnp_bc_in_id_pft, acnp_bc_in_id_ctrim use PRTAllometricCNPMod, only : acnp_bc_in_id_lstat, acnp_bc_inout_id_dbh + use PRTAllometricCNPMod, only : acnp_bc_in_id_efleaf + use PRTAllometricCNPMod, only : acnp_bc_in_id_effnrt + use PRTAllometricCNPMod, only : acnp_bc_in_id_efstem use PRTAllometricCNPMod, only : acnp_bc_inout_id_rmaint_def, acnp_bc_in_id_netdc use PRTAllometricCNPMod, only : acnp_bc_in_id_netdnh4, acnp_bc_in_id_netdno3, acnp_bc_in_id_netdp use PRTAllometricCNPMod, only : acnp_bc_out_id_cefflux, acnp_bc_out_id_nefflux @@ -147,7 +153,8 @@ module EDCohortDynamicsMod subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & - prt, status, recruitstatus,ctrim, carea, clayer, spread, bc_in) + prt, elongf_leaf, elongf_fnrt, elongf_stem, status, & + recruitstatus,ctrim, carea, clayer, spread, bc_in) ! ! !DESCRIPTION: ! create new cohort @@ -178,6 +185,12 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & real(r8), intent(in) :: hite ! height: meters real(r8), intent(in) :: coage ! cohort age in years real(r8), intent(in) :: dbh ! dbh: cm + real(r8), intent(in) :: elongf_leaf ! leaf elongation factor (fraction) + real(r8), intent(in) :: elongf_fnrt ! fine-root "elongation factor" (fraction) + real(r8), intent(in) :: elongf_stem ! stem "elongation factor" (fraction) + ! For all elongation factors: + ! 0 means fully abscissed + ! 1 means fully flushed class(prt_vartypes),target :: prt ! The allocated PARTEH ! object real(r8), intent(in) :: ctrim ! What is the fraction of the maximum @@ -223,6 +236,9 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & new_cohort%pft = pft new_cohort%status_coh = status + new_cohort%efleaf_coh = elongf_leaf + new_cohort%effnrt_coh = elongf_fnrt + new_cohort%efstem_coh = elongf_stem new_cohort%n = nn new_cohort%hite = hite new_cohort%dbh = dbh @@ -400,12 +416,18 @@ subroutine InitPRTBoundaryConditions(new_cohort) call new_cohort%prt%RegisterBCIn(ac_bc_in_id_pft,bc_ival = new_cohort%pft) call new_cohort%prt%RegisterBCIn(ac_bc_in_id_ctrim,bc_rval = new_cohort%canopy_trim) call new_cohort%prt%RegisterBCIn(ac_bc_in_id_lstat,bc_ival = new_cohort%status_coh) + call new_cohort%prt%RegisterBCIn(ac_bc_in_id_efleaf,bc_rval = new_cohort%efleaf_coh) + call new_cohort%prt%RegisterBCIn(ac_bc_in_id_effnrt,bc_rval = new_cohort%effnrt_coh) + call new_cohort%prt%RegisterBCIn(ac_bc_in_id_efstem,bc_rval = new_cohort%efstem_coh) case (prt_cnp_flex_allom_hyp) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_pft,bc_ival = new_cohort%pft) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_ctrim,bc_rval = new_cohort%canopy_trim) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_lstat,bc_ival = new_cohort%status_coh) + call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_efleaf,bc_rval = new_cohort%efleaf_coh) + call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_effnrt,bc_rval = new_cohort%effnrt_coh) + call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_efstem,bc_rval = new_cohort%efstem_coh) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdc, bc_rval = new_cohort%npp_acc) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdnh4, bc_rval = new_cohort%daily_nh4_uptake) call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdno3, bc_rval = new_cohort%daily_no3_uptake) @@ -522,6 +544,9 @@ subroutine nan_cohort(cc_p) currentCohort%canopy_layer_yesterday = nan ! recent canopy status of cohort (1 = canopy, 2 = understorey, etc.) currentCohort%NV = fates_unset_int ! Number of leaf layers: - currentCohort%status_coh = fates_unset_int ! growth status of plant (2 = leaves on , 1 = leaves off) + currentCohort%efleaf_coh = nan ! leaf elongation factor (fraction from 0 (fully abscissed) to 1 (fully flushed) + currentCohort%effnrt_coh = nan ! fine-root "elongation factor" (fraction from 0 (fully abscissed) to 1 (fully flushed) + currentCohort%efstem_coh = nan ! stem "elongation factor" (fraction from 0 (fully abscissed) to 1 (fully flushed) currentCohort%size_class = fates_unset_int ! size class index currentCohort%size_class_lasttimestep = fates_unset_int ! size class index currentCohort%size_by_pft_class = fates_unset_int ! size by pft classification index @@ -633,6 +658,9 @@ subroutine zero_cohort(cc_p) currentCohort%NV = 0 currentCohort%status_coh = 0 + currentCohort%efleaf_coh = 0._r8 + currentCohort%effnrt_coh = 0._r8 + currentCohort%efstem_coh = 0._r8 currentCohort%rdark = 0._r8 currentCohort%resp_m = 0._r8 currentCohort%resp_m_def = 0._r8 @@ -1789,6 +1817,9 @@ subroutine copy_cohort( currentCohort,copyc ) n%canopy_layer_yesterday = o%canopy_layer_yesterday n%nv = o%nv n%status_coh = o%status_coh + n%efleaf_coh = o%efleaf_coh + n%effnrt_coh = o%effnrt_coh + n%efstem_coh = o%efstem_coh n%canopy_trim = o%canopy_trim n%excl_weight = o%excl_weight n%prom_weight = o%prom_weight diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 95ea3f8cfb..456469ed28 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -51,6 +51,9 @@ module EDPhysiologyMod use EDTypesMod , only : ed_site_type, ed_patch_type, ed_cohort_type use EDTypesMod , only : leaves_on use EDTypesMod , only : leaves_off + use EDTypesMod , only : leaves_pshed + use EDTypesMod , only : ihard_stress_decid + use EDTypesMod , only : isemi_stress_decid use EDTypesMod , only : min_n_safemath use PRTGenericMod , only : num_elements use PRTGenericMod , only : element_list @@ -63,6 +66,7 @@ module EDPhysiologyMod use EDTypesMod , only : phen_dstat_moistoff use EDTypesMod , only : phen_dstat_moiston use EDTypesMod , only : phen_dstat_timeon + use EDTypesMod , only : phen_dstat_pshed use EDTypesMod , only : init_recruit_trim use shr_log_mod , only : errMsg => shr_log_errMsg use FatesGlobals , only : fates_log @@ -236,7 +240,7 @@ subroutine PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in ) ! Calculate seed germination rate, the status flags prevent ! germination from occuring when the site is in a drought ! (for drought deciduous) or too cold (for cold deciduous) - call SeedGermination(litt, currentSite%cstatus, currentSite%dstatus) + call SeedGermination(litt, currentSite%cstatus, currentSite%dstatus(1:numpft)) ! Send fluxes from newly created litter into the litter pools ! This litter flux is from non-disturbance inducing mortality, as well @@ -674,9 +678,14 @@ subroutine phenology( currentSite, bc_in ) ! ! !USES: use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm - use EDParamsMod, only : ED_val_phen_drought_threshold, ED_val_phen_doff_time - use EDParamsMod, only : ED_val_phen_a, ED_val_phen_b, ED_val_phen_c, ED_val_phen_chiltemp - use EDParamsMod, only : ED_val_phen_mindayson, ED_val_phen_ncolddayslim, ED_val_phen_coldtemp + use EDParamsMod, only : ED_val_phen_drought_threshold + use EDParamsMod, only : ED_val_phen_moist_threshold + use EDParamsMod, only : ED_val_phen_doff_time + use EDParamsMod, only : ED_val_phen_a, ED_val_phen_b, ED_val_phen_c + use EDParamsMod, only : ED_val_phen_chiltemp + use EDParamsMod, only : ED_val_phen_mindayson + use EDParamsMod, only : ED_val_phen_ncolddayslim + use EDParamsMod, only : ED_val_phen_coldtemp ! ! !ARGUMENTS: @@ -691,48 +700,66 @@ subroutine phenology( currentSite, bc_in ) integer :: ncolddays ! no days underneath the threshold for leaf drop integer :: i_wmem ! Loop counter for water mem days integer :: i_tmem ! Loop counter for veg temp mem days - integer :: dayssincedleafon ! Days since drought-decid leaf-on started - integer :: dayssincedleafoff ! Days since drought-decid leaf-off started - integer :: dayssincecleafon ! Days since cold-decid leaf-on started - integer :: dayssincecleafoff ! Days since cold-decid leaf-off started - real(r8) :: mean_10day_liqvol ! mean liquid volume (m3/m3) over last 10 days + integer :: ipft ! plant functional type index + real(r8) :: mean_10day_liqvol ! mean soil liquid volume over last 10 days [m3/m3] + real(r8) :: mean_10day_smp ! mean soil matric potential over last 10 days [mm] real(r8) :: leaf_c ! leaf carbon [kg] real(r8) :: fnrt_c ! fineroot carbon [kg] real(r8) :: sapw_c ! sapwood carbon [kg] real(r8) :: store_c ! storage carbon [kg] real(r8) :: struct_c ! structure carbon [kg] real(r8) :: gdd_threshold ! GDD accumulation function, - integer :: ilayer_swater ! Layer index for soil water - ! which also depends on chilling days. + real(r8) :: rootfrac_notop ! Total rooting fraction excluding the top soil layer integer :: ncdstart ! beginning of counting period for chilling degree days. integer :: gddstart ! beginning of counting period for growing degree days. - real(r8) :: temp_in_C ! daily averaged temperature in celcius + integer :: nlevroot ! Number of rooting levels to consider + real(r8) :: temp_in_C ! daily averaged temperature in celsius + real(r8) :: elongf_prev ! Elongation factor from previous time + real(r8) :: elongf_1st ! First guess for elongation factor + integer :: pft_leaf_lifespan ! PFT life span of drought deciduous. + ! This is the shortest between the PFT leaf lifespan + ! and the maximum lifespan of drought deciduous + ! (see canopy_leaf_lifespan below) + + ! Logical tests to make code more readable + logical :: smoist_below_threshold ! Is soil moisture below threshold? + logical :: recent_flush ! Last full flushing event is still very recent. + logical :: recent_abscission ! Last abscission event is still very recent. + logical :: exceed_min_on_period ! Have leaves been flushed for a minimum period of time? + logical :: exceed_min_off_period ! Have leaves been off for a minimum period of time? + logical :: prolonged_on_period ! Has leaves been flushed for too long? + logical :: prolonged_off_period ! Have leaves been abscissed for too long? + logical :: last_flush_long_ago ! Has it been a very long time since last flushing? integer, parameter :: canopy_leaf_lifespan = 365 ! Maximum lifespan of drought decid leaves - integer, parameter :: min_daysoff_dforcedflush = 30 ! THis is the number of days that must had elapsed - ! since leaves had dropped, in order to forcably - ! flush leaves again. This does not impact flushing - ! due to real moisture constraints, and will prevent - ! drought deciduous in perennially wet environments - ! that have been forced to drop their leaves, from - ! flushing them back immediately. - - real(r8),parameter :: dphen_soil_depth = 0.1 ! Use liquid soil water that is - ! closest to this depth [m] + integer, parameter :: min_daysoff_dforcedflush = 30 ! This is the number of days that must had elapsed + ! since leaves had dropped, in order to forcably + ! flush leaves again. This does not impact flushing + ! due to real moisture constraints, and will prevent + ! drought deciduous in perennially wet environments + ! that have been forced to drop their leaves, from + ! flushing them back immediately. + + integer, parameter :: dd_offon_toler = 30 ! When flushing or shedding leaves, we check that + ! the dates are near last year's dates. This controls + ! the tolerance for deviating from last year. + + real(r8), parameter :: elongf_min = 0.05_r8 ! Minimum elongation factor. If elongation factor + ! reaches or falls below elongf_min, we assume + ! complete abscission. This avoids carrying out + ! a residual amount of leaves, which may create + ! computational problems. The current threshold + ! is the same used in ED-2.2. ! This is the integer model day. The first day of the simulation is 1, and it ! continues monotonically, indefinitely ! Advance it. (this should be a global, no reason ! for site level, but we don't have global scalars in the ! restart file) - currentSite%phen_model_date = currentSite%phen_model_date + 1 model_day_int = currentSite%phen_model_date - ! Use the following layer index to calculate drought conditions - ilayer_swater = minloc(abs(bc_in%z_sisl(:)-dphen_soil_depth),dim=1) - ! Parameter of drought decid leaf loss in mm in top layer...FIX(RF,032414) ! - this is arbitrary and poorly understood. Needs work. ED_ @@ -826,15 +853,15 @@ subroutine phenology( currentSite, bc_in ) ! not had occured yet, so set it to last year to get things rolling if (model_day_int < currentSite%cleafoffdate) then - dayssincecleafoff = model_day_int - (currentSite%cleafoffdate - 365) + currentSite%cndaysleafoff = model_day_int - (currentSite%cleafoffdate - 365) else - dayssincecleafoff = model_day_int - currentSite%cleafoffdate + currentSite%cndaysleafoff = model_day_int - currentSite%cleafoffdate end if if (model_day_int < currentSite%cleafondate) then - dayssincecleafon = model_day_int - (currentSite%cleafondate - 365) + currentSite%cndaysleafon = model_day_int - (currentSite%cleafondate-365) else - dayssincecleafon = model_day_int - currentSite%cleafondate + currentSite%cndaysleafon = model_day_int - currentSite%cleafondate end if @@ -847,14 +874,13 @@ subroutine phenology( currentSite, bc_in ) ! from ever re-flushing after they have reached their maximum age (thus ! preventing them from competing - if ( (currentSite%cstatus == phen_cstat_iscold .or. & - currentSite%cstatus == phen_cstat_nevercold) .and. & + if ( any(currentSite%cstatus == [phen_cstat_iscold,phen_cstat_nevercold]) .and. & (currentSite%grow_deg_days > gdd_threshold) .and. & - (dayssincecleafoff > ED_val_phen_mindayson) .and. & + (currentSite%cndaysleafoff > ED_val_phen_mindayson) .and. & (currentSite%nchilldays >= 1)) then currentSite%cstatus = phen_cstat_notcold ! Set to not-cold status (leaves can come on) currentSite%cleafondate = model_day_int - dayssincecleafon = 0 + currentSite%cndaysleafon = 0 currentSite%grow_deg_days = 0._r8 ! zero GDD for the rest of the year until counting season begins. if ( debug ) write(fates_log(),*) 'leaves on' endif !GDD @@ -873,7 +899,7 @@ subroutine phenology( currentSite, bc_in ) if ( (currentSite%cstatus == phen_cstat_notcold) .and. & (model_day_int > num_vegtemp_mem) .and. & (ncolddays > ED_val_phen_ncolddayslim) .and. & - (dayssincecleafon > ED_val_phen_mindayson) )then + (currentSite%cndaysleafon > ED_val_phen_mindayson) )then currentSite%grow_deg_days = 0._r8 ! The equations for Botta et al ! are for calculations of @@ -882,6 +908,7 @@ subroutine phenology( currentSite, bc_in ) ! leaves to flush later in the year currentSite%cstatus = phen_cstat_iscold ! alter status of site to 'leaves off' currentSite%cleafoffdate = model_day_int ! record leaf off date + currentSite%cndaysleafoff = 0 if ( debug ) write(fates_log(),*) 'leaves off' endif @@ -893,7 +920,7 @@ subroutine phenology( currentSite, bc_in ) ! plants from re-emerging in areas without at least some cold days if( (currentSite%cstatus == phen_cstat_notcold) .and. & - (dayssincecleafoff > 400)) then ! remove leaves after a whole year + (currentSite%cndaysleafoff > 400)) then ! remove leaves after a whole year ! when there is no 'off' period. currentSite%grow_deg_days = 0._r8 @@ -901,146 +928,325 @@ subroutine phenology( currentSite, bc_in ) ! site is never really cold enough ! for cold deciduous currentSite%cleafoffdate = model_day_int ! record leaf off date + currentSite%cndaysleafoff = 0 if ( debug ) write(fates_log(),*) 'leaves off' endif - !-----------------Drought Phenology--------------------! - ! Principles of drought-deciduos phenology model... - ! The 'is_drought' flag is false when leaves are on, and true when leaves area off. - ! The following sets those site-level flags, which are acted on in phenology_deciduos. - ! A* The leaves live for either the length of time the soil moisture is over the threshold - ! or the lifetime of the leaves, whichever is shorter. - ! B*: If the soil is only wet for a very short time, then the leaves stay on for 100 days - ! C*: The leaves are only permitted to come ON for a 60 day window around when they last came on, - ! to prevent 'flickering' on in response to wet season storms - ! D*: We don't allow anything to happen in the first ten days to allow the water memory window - ! to come into equlibirium. - ! E*: If the soil is always wet, the leaves come on at the beginning of the window, and then - ! last for their lifespan. - ! ISSUES - ! 1. It's not clear what water content we should track. Here we are tracking the top layer, - ! but we probably should track something like BTRAN, but BTRAN is defined for each PFT, - ! and there could potentially be more than one stress-dec PFT.... ? - ! 2. In the beginning, the window is set at an arbitrary time of the year, so the leaves - ! might come on in the dry season, using up stored reserves - ! for the stress-dec plants, and potentially killing them. To get around this, - ! we need to read in the 'leaf on' date from some kind of start-up file - ! but we would need that to happen for every resolution, etc. - ! 3. Will this methodology properly kill off the stress-dec trees where there is no - ! water stress? What about where the wet period coincides with the warm period? - ! We would just get them overlapping with the cold-dec trees, even though that isn't appropriate - ! Why don't the drought deciduous trees grow in the North? - ! Is cold decidousness maybe even the same as drought deciduosness there (and so does this - ! distinction actually matter??).... - - ! Accumulate surface water memory of last 10 days. - ! Liquid volume in ground layer (m3/m3) - do i_wmem = 1,numWaterMem-1 !shift memory along one - currentSite%water_memory(numWaterMem+1-i_wmem) = currentSite%water_memory(numWaterMem-i_wmem) - enddo - currentSite%water_memory(1) = bc_in%h2o_liqvol_sl(ilayer_swater) - - ! Calculate the mean water content over the last 10 days (m3/m3) - mean_10day_liqvol = sum(currentSite%water_memory(1:numWaterMem))/real(numWaterMem,r8) - - ! In drought phenology, we often need to force the leaves to stay - ! on or off as moisture fluctuates... - - ! Calculate days since leaves have come off, but make a provision - ! for the first year of simulation, we have to assume a leaf drop - ! date to start, so if that is in the future, set it to last year - - if (model_day_int < currentSite%dleafoffdate) then - dayssincedleafoff = model_day_int - (currentSite%dleafoffdate-365) - else - dayssincedleafoff = model_day_int - currentSite%dleafoffdate - endif - - ! the leaves are on. How long have they been on? - if (model_day_int < currentSite%dleafondate) then - dayssincedleafon = model_day_int - (currentSite%dleafondate-365) - else - dayssincedleafon = model_day_int - currentSite%dleafondate - endif - ! LEAF ON: DROUGHT DECIDUOUS WETNESS - ! Here, we used a window of oppurtunity to determine if we are - ! close to the time when then leaves came on last year - - ! Has it been ... - ! a) a year, plus or minus 1 month since we last had leaf-on? - ! b) Has there also been at least a nominaly short amount of "leaf-off" - ! c) is the model day at least > 10 (let soil water spin-up) - ! Note that cold-starts begin in the "leaf-on" - ! status - if ( (currentSite%dstatus == phen_dstat_timeoff .or. & - currentSite%dstatus == phen_dstat_moistoff) .and. & - (model_day_int > numWaterMem) .and. & - (dayssincedleafon >= 365-30 .and. dayssincedleafon <= 365+30 ) .and. & - (dayssincedleafoff > ED_val_phen_doff_time) ) then - - ! If leaves are off, and have been off for at least a few days - ! and the time is consistent with the correct - ! time window... test if the moisture conditions allow for leaf-on - - if ( mean_10day_liqvol >= ED_val_phen_drought_threshold ) then - currentSite%dstatus = phen_dstat_moiston ! set status to leaf-on - currentSite%dleafondate = model_day_int ! save the model day we start flushing - dayssincedleafon = 0 - endif - endif - ! LEAF ON: DROUGHT DECIDUOUS TIME EXCEEDANCE - ! If we still haven't done budburst by end of window, then force it + ! Loop through every PFT to assign the elongation factor. + ! Add PFT look to account for different PFT rooting depth profiles. + pft_elong_loop: do ipft=1,numpft - ! If the status is "phen_dstat_moistoff", it means this site currently has - ! leaves off due to actual moisture limitations. - ! So we trigger bud-burst at the end of the month since - ! last year's bud-burst. If this is imposed, then we set the new - ! status to indicate bud-burst was forced by timing + ! Update soil moisture information memory (we always track the last 10 days) + do i_wmem = numWaterMem,2,-1 !shift memory to previous day, to make room for current day + currentSite%liqvol_memory(i_wmem,ipft) = currentSite%liqvol_memory(i_wmem-1,ipft) + currentSite%smp_memory (i_wmem,ipft) = currentSite%smp_memory (i_wmem-1,ipft) + end do - if( currentSite%dstatus == phen_dstat_moistoff ) then - if ( dayssincedleafon > 365+30 ) then - currentSite%dstatus = phen_dstat_timeon ! force budburst! - currentSite%dleafondate = model_day_int ! record leaf on date - dayssincedleafon = 0 + ! Find the rooting depth distribution for PFT + call set_root_fraction( currentSite%rootfrac_scr, ipft, currentSite%zi_soil, & + bc_in%max_rooting_depth_index_col ) + nlevroot = max(2,min(ubound(currentSite%zi_soil,1),bc_in%max_rooting_depth_index_col)) + + ! The top most layer is typically very thin (~ 2cm) and dries rather quickly. Despite + ! being thin, it can have a non-negligible rooting fraction (e.g., using + ! exponential_2p_root_profile with default parameters make the top layer to contain + ! about 7% of the total fine root density). To avoid overestimating dryness, we + ! ignore the top layer when calculating the memory. + rootfrac_notop = sum(currentSite%rootfrac_scr(2:nlevroot)) + if ( rootfrac_notop <= nearzero ) then + ! Unlikely, but just in case all roots are in the first layer, we use the second + ! layer the second layer (to avoid FPE issues). + currentSite%rootfrac_scr(2) = 1.0_r8 + rootfrac_notop = 1.0_r8 end if - end if - ! But if leaves are off due to time, then we enforce - ! a longer cool-down (because this is a perrenially wet system) - - if(currentSite%dstatus == phen_dstat_timeoff ) then - if (dayssincedleafoff > min_daysoff_dforcedflush) then - currentSite%dstatus = phen_dstat_timeon ! force budburst! - currentSite%dleafondate = model_day_int ! record leaf on date - dayssincedleafon = 0 + ! Set the memory to be the weighted average of the soil properties, using the + ! root fraction of each layer (except the topmost one) as the weighting factor. + currentSite%liqvol_memory(1,ipft) = sum( bc_in%h2o_liqvol_sl (2:nlevroot) * & + currentSite%rootfrac_scr(2:nlevroot) ) / & + rootfrac_notop + currentSite%smp_memory (1,ipft) = sum( bc_in%smp_sl (2:nlevroot) * & + currentSite%rootfrac_scr(2:nlevroot) ) / & + rootfrac_notop + + ! Calculate the mean soil moisture ( liquid volume (m3/m3) and matric potential (mm)) + ! over the last 10 days + mean_10day_liqvol = sum(currentSite%liqvol_memory(1:numWaterMem,ipft)) / & + real(numWaterMem,r8) + mean_10day_smp = sum(currentSite%smp_memory (1:numWaterMem,ipft)) / & + real(numWaterMem,r8) + + ! Compare the moisture with the threshold. + if ( ED_val_phen_drought_threshold >= 0. ) then + ! Liquid volume in reference layer (m3/m3) + smoist_below_threshold = mean_10day_liqvol < ED_val_phen_drought_threshold + else + ! Soil matric potential in reference layer (mm) + smoist_below_threshold = mean_10day_smp < ED_val_phen_drought_threshold end if - end if - ! LEAF OFF: DROUGHT DECIDUOUS LIFESPAN - if the leaf gets to - ! the end of its useful life. A*, E* - ! i.e. Are the leaves rouhgly at the end of their lives? + ! Calculate days since last flushing and shedding event, but make a provision + ! for the first year of simulation, we have to assume leaf drop / leaf flush + ! dates to start, so if that is in the future, set it to last year + if (model_day_int < currentSite%dleafoffdate(ipft)) then + currentSite%dndaysleafoff(ipft) = model_day_int - (currentSite%dleafoffdate(ipft)-365) + else + currentSite%dndaysleafoff(ipft) = model_day_int - currentSite%dleafoffdate(ipft) + end if + if (model_day_int < currentSite%dleafondate(ipft)) then + currentSite%dndaysleafon(ipft) = model_day_int - (currentSite%dleafondate(ipft)-365) + else + currentSite%dndaysleafon(ipft) = model_day_int - currentSite%dleafondate(ipft) + end if - if ( (currentSite%dstatus == phen_dstat_moiston .or. & - currentSite%dstatus == phen_dstat_timeon ) .and. & - (dayssincedleafon > canopy_leaf_lifespan) )then - currentSite%dstatus = phen_dstat_timeoff !alter status of site to 'leaves off' - currentSite%dleafoffdate = model_day_int !record leaf on date - endif - ! LEAF OFF: DROUGHT DECIDUOUS DRYNESS - if the soil gets too dry, - ! and the leaves have already been on a while... + ! Elongation factor from the previous step. + elongf_prev = currentSite%elong_factor(ipft) + + + ! PFT leaf lifespan in days. This is the shortest between the leaf longevity + ! (defined as a PFT parameter) and the maximum canopy leaf life span allowed + ! for drought deciduous (local parameter). + ! MLO: Need to double check that this will not cause unintended problems + pft_leaf_lifespan = min( canopy_leaf_lifespan, & + nint(365*maxval(prt_params%leaf_long(ipft,:))) ) + + + + ! Find elongation factor by comparing the moisture with the thresholds. + case_drought_phen: select case (prt_params%stress_decid(ipft)) + case (ihard_stress_decid) + !---~--- + ! Default ("hard") drought deciduous phenology. The decision on whether to + ! abscise (shed) or flush leaves is in principle defined by the soil moisture + ! in the rooting zone. However, we must also account the time since last + ! abscission or flushing event, to avoid excessive "flickering" of the leaf + ! elongation factor if soil moisture is right at the threshold. + ! + ! (MLO thought: maybe we should define moisture equivalents of GDD and chilling + ! days to simplify the cases a bit...) + !---~--- + + + !---~--- + ! Save some conditions in logical variables to simplify code below + !---~--- + ! Leaves have been "on" for longer than the minimum number of days. + exceed_min_on_period = & + any( currentSite%dstatus(ipft) == [phen_dstat_timeon,phen_dstat_moiston] ) .and. & + (currentSite%dndaysleafon(ipft) > dleafon_drycheck) + ! Leaves have been "off" for longer than the minimum number of days. + exceed_min_off_period = & + ( currentSite%dstatus(ipft) == phen_dstat_timeoff ) .and. & + ( currentSite%dndaysleafoff(ipft) > min_daysoff_dforcedflush ) + ! Leaves have been "on" for longer than the leaf lifetime. + prolonged_on_period = & + any( currentSite%dstatus(ipft) == [phen_dstat_timeon,phen_dstat_moiston] ) .and. & + ( currentSite%dndaysleafon(ipft) > pft_leaf_lifespan ) + ! Leaves have been "off" for a sufficiently long time and the last flushing + ! was about one year ago (+/- tolerance). + prolonged_off_period = & + any( currentSite%dstatus(ipft) == [phen_dstat_timeoff,phen_dstat_moistoff] ) .and. & + ( currentSite%dndaysleafoff(ipft) > ED_val_phen_doff_time ) .and. & + ( currentSite%dndaysleafon(ipft) >= 365-dd_offon_toler ) .and. & + ( currentSite%dndaysleafon(ipft) <= 365+dd_offon_toler ) + ! Last flushing was a very long time ago. + last_flush_long_ago = & + ( currentSite%dstatus(ipft) == phen_dstat_moistoff ) .and. & + ( currentSite%dndaysleafon(ipft) > 365+dd_offon_toler ) + !---~--- + + + !---~--- + ! Revision of the conditions to simplify nested if and added an if/elseif/else + ! structure to ensure only up to one change occurs at any given time (ML 20211120). + drought_smoist_ifelse: if (model_day_int <= numWaterMem) then + ! Too early in the simulation. Do not change phenology status as we need to + ! populate the soil moisture memory. + continue + + elseif ( prolonged_off_period .and. ( .not. smoist_below_threshold ) ) then + ! LEAF ON: DROUGHT DECIDUOUS WETNESS + ! Here, we used a window of oppurtunity to determine if we are + ! close to the time when then leaves came on last year + ! The following conditions must be met + ! a) a year, plus or minus 1 month since we last had leaf-on? + ! b) Has there also been at least a nominaly short amount of "leaf-off"? + ! c) Is the soil moisture sufficiently high? + currentSite%dstatus(ipft) = phen_dstat_moiston ! set status to leaf-on + currentSite%dleafondate(ipft) = model_day_int ! save the model day we start flushing + currentSite%dndaysleafon(ipft) = 0 + currentSite%elong_factor(ipft) = 1. + + elseif ( last_flush_long_ago ) then + ! LEAF ON: DROUGHT DECIDUOUS TIME EXCEEDANCE + ! If we still haven't done budburst by end of window, then force it + + ! If the status is "phen_dstat_moistoff", it means this site currently has + ! leaves off due to actual moisture limitations. + ! So we trigger bud-burst at the end of the month since + ! last year's bud-burst. If this is imposed, then we set the new + ! status to indicate bud-burst was forced by timing + currentSite%dstatus(ipft) = phen_dstat_timeon ! force budburst! + currentSite%dleafondate(ipft) = model_day_int ! record leaf on date + currentSite%dndaysleafon(ipft) = 0 + currentSite%elong_factor(ipft) = 1. + + elseif ( exceed_min_off_period ) then + ! LEAF ON: DROUGHT DECIDUOUS EXCEEDED MINIMUM OFF PERIOD + ! Leaves were off due to time, not really moisture, so we allow them to + ! flush again as soon as they exceed a minimum off time + ! This typically occurs in a perennially wet system. + currentSite%dstatus(ipft) = phen_dstat_timeon ! force budburst! + currentSite%dleafondate(ipft) = model_day_int ! record leaf on date + currentSite%dndaysleafon(ipft) = 0 + currentSite%elong_factor(ipft) = 1. + + elseif ( prolonged_on_period ) then + ! LEAF OFF: DROUGHT DECIDUOUS LIFESPAN + ! Are the leaves rouhgly at the end of their lives? If so, shed leaves + ! even if it is not dry. + currentSite%dstatus(ipft) = phen_dstat_timeoff !alter status of site to 'leaves off' + currentSite%dleafoffdate(ipft) = model_day_int !record leaf on date + currentSite%dndaysleafoff(ipft) = 0 + currentSite%elong_factor(ipft) = 0. + + elseif ( exceed_min_on_period .and. smoist_below_threshold ) then + ! LEAF OFF: DROUGHT DECIDUOUS DRYNESS - if the soil gets too dry, + ! and the leaves have already been on a while... + currentSite%dstatus(ipft) = phen_dstat_moistoff ! alter status of site to 'leaves off' + currentSite%dleafoffdate(ipft) = model_day_int ! record leaf on date + currentSite%dndaysleafoff(ipft) = 0 + currentSite%elong_factor(ipft) = 0. + end if drought_smoist_ifelse + + + case (isemi_stress_decid) + !------ + ! Semi-deciduous PFT, based on ED2. We compare the moisture with the lower + ! and upper thresholds. If the moisture is in between the thresholds, we must + ! also check whether or not the drought is developing or regressing. + !------ + + + ! First guess elongation factor + if (ED_val_phen_drought_threshold >= 0.) then + elongf_1st = elongf_min + (1.0_r8 - elongf_min ) * & + ( mean_10day_liqvol - ED_val_phen_drought_threshold ) / & + ( ED_val_phen_moist_threshold - ED_val_phen_drought_threshold ) + else + elongf_1st = elongf_min + (1.0_r8 - elongf_min ) * & + ( mean_10day_smp - ED_val_phen_drought_threshold ) / & + ( ED_val_phen_moist_threshold - ED_val_phen_drought_threshold ) + end if + elongf_1st = max(0.0_r8,min(1.0_r8,elongf_1st)) + + + + !---~--- + ! Save some conditions in logical variables to simplify code below + !---~--- + ! Leaves have been flushing for a short period of time. + recent_flush = elongf_prev >= elongf_min .and. & + ( currentSite%dndaysleafon(ipft) <= dleafon_drycheck ) + ! Leaves have been abscissing for a short period of time. + recent_abscission = elongf_prev < elongf_min .and. & + ( currentSite%dndaysleafoff(ipft) <= min_daysoff_dforcedflush ) + ! Leaves have been flushing for longer than their time span. + prolonged_on_period = all( [elongf_prev,elongf_1st] >= elongf_min ) .and. & + ( currentSite%dndaysleafon(ipft) > pft_leaf_lifespan ) + ! It's been a long time since the + last_flush_long_ago = all( [elongf_prev,elongf_1st] < elongf_min ) .and. & + ( currentSite%dndaysleafon(ipft) > 365+dd_offon_toler ) + !---~--- + + + ! Make sure elongation factor is bounded and check for special cases. + drought_gradual_ifelse: if ( model_day_int <= numWaterMem ) then + ! Too early in the simulation, keep the same elongation factor as the day before. + currentSite%elong_factor(ipft) = elongf_prev + + elseif ( prolonged_on_period ) then + ! Leaves have been on for too long and exceeded leaf lifespan. Force abscission + currentSite%elong_factor(ipft) = 0.0_r8 ! Force full budburst + currentSite%dstatus(ipft) = phen_dstat_timeoff ! Flag that this has been forced + currentSite%dleafoffdate(ipft) = model_day_int ! Record leaf off date + currentSite%dndaysleafoff(ipft) = 0 ! Reset clock + + elseif ( last_flush_long_ago ) then + ! Plant has not flushed at all for a very long time. Force flushing + currentSite%elong_factor(ipft) = elongf_min ! Force minimum budburst + currentSite%dstatus(ipft) = phen_dstat_timeon ! Flag that this has been forced + currentSite%dleafondate(ipft) = model_day_int ! Record leaf on date + currentSite%dndaysleafon(ipft) = 0 ! Reset clock + + elseif ( recent_flush .and. elongf_1st < elongf_prev ) then + ! Leaves have only recently reached flushed status. Elongation factor cannot decrease + currentSite%elong_factor(ipft) = elongf_prev ! Elongation factor cannot decrease + currentSite%dstatus(ipft) = phen_dstat_timeon ! Flag that this has been forced + + elseif ( recent_abscission .and. elongf_1st > elongf_min ) then + ! Leaves have only recently abscissed. Prevent plant to flush leaves. + currentSite%elong_factor(ipft) = 0.0_r8 ! Elongation factor must remain 0. + currentSite%dstatus(ipft) = phen_dstat_timeoff ! Flag that this has been forced + + elseif ( elongf_1st < elongf_min ) then + ! First guess of elongation factor below minimum. Impose full abscission. + currentSite%elong_factor(ipft) = 0.0_r8 + + if (elongf_prev >= elongf_min ) then + ! This is the first day moisture fell below minimum. Flag change of status. + currentSite%dstatus(ipft) = phen_dstat_moistoff ! Flag that this has not been forced + currentSite%dleafoffdate(ipft) = model_day_int ! Record leaf off date + currentSite%dndaysleafoff(ipft) = 0 ! Reset clock + end if - if ( (currentSite%dstatus == phen_dstat_moiston .or. & - currentSite%dstatus == phen_dstat_timeon ) .and. & - (model_day_int > numWaterMem) .and. & - (mean_10day_liqvol <= ED_val_phen_drought_threshold) .and. & - (dayssincedleafon > dleafon_drycheck ) ) then - currentSite%dstatus = phen_dstat_moistoff ! alter status of site to 'leaves off' - currentSite%dleafoffdate = model_day_int ! record leaf on date - endif + else + ! First guess of elongation factor is valid, use it. + currentSite%elong_factor(ipft) = elongf_1st + + + if (elongf_prev < elongf_min ) then + ! This is the first day moisture allows leaves to exist. Flag change of status. + currentSite%dstatus(ipft) = phen_dstat_moiston ! Flag that this has not been forced + currentSite%dleafondate(ipft) = model_day_int ! Record leaf on date + currentSite%dndaysleafon(ipft) = 0 ! Reset clock + elseif (elongf_1st < elongf_prev) then + currentSite%dstatus(ipft) = phen_dstat_pshed ! Flag partial shedding, + ! but do not reset the clock + end if + end if drought_gradual_ifelse + + + case default + ! Neither hard deciduous or semi-deciduous. For now we treat this as synonym + ! of non-drought deciduous. In the future we may consider other drought deciduous + ! strategies (e.g., abscission driven by moisture, flushing driven by photo- + ! period). + currentSite%dstatus(ipft) = phen_dstat_moiston + + ! Assign elongation factors for non-drought deciduous PFTs, which will be used + ! to define the cohort status. + case_cold_phen: select case(prt_params%season_decid(ipft)) + case (ifalse) + ! Evergreen, ensure that elongation factor is always one. + currentSite%elong_factor(ipft) = 1.0_r8 + case (itrue) + ! Cold-deciduous. Define elongation factor based on cold status + select case (currentSite%cstatus) + case (phen_cstat_nevercold,phen_cstat_iscold) + currentSite%elong_factor(ipft) = 0.0_r8 + case (phen_cstat_notcold) + currentSite%elong_factor(ipft) = 1.0_r8 + end select + end select case_cold_phen + + end select case_drought_phen + + end do pft_elong_loop call phenology_leafonoff(currentSite) @@ -1063,27 +1269,49 @@ subroutine phenology_leafonoff(currentSite) type(ed_patch_type) , pointer :: currentPatch type(ed_cohort_type), pointer :: currentCohort - real(r8) :: leaf_c ! leaf carbon [kg] - real(r8) :: sapw_c ! sapwood carbon [kg] - real(r8) :: struct_c ! structural wood carbon [kg] - real(r8) :: store_c ! storage carbon [kg] - real(r8) :: store_c_transfer_frac ! Fraction of storage carbon used to flush leaves - real(r8) :: deficit_c ! Amount of C needed to get flushing pools "on-allometry" - real(r8) :: target_leaf_c - real(r8) :: target_sapw_c - real(r8) :: target_agw_c, target_bgw_c, target_struct_c - real(r8) :: sapw_area - integer :: ipft - real(r8), parameter :: leaf_drop_fraction = 1.0_r8 + real(r8) :: leaf_c ! leaf carbon [kg] + real(r8) :: fnrt_c ! fine root carbon [kg] + real(r8) :: sapw_c ! sapwood carbon [kg] + real(r8) :: struct_c ! structural wood carbon [kg] + real(r8) :: store_c ! storage carbon [kg] + real(r8) :: store_c_transfer_frac ! Fraction of storage carbon used to flush leaves + + real(r8) :: leaf_deficit_c ! leaf carbon deficit (relative to target) [kg] + real(r8) :: fnrt_deficit_c ! fine root carbon deficit (relative to target) [kg] + real(r8) :: sapw_deficit_c ! sapwood carbon deficit (relative to target) [kg] + real(r8) :: struct_deficit_c ! structural wood carbon deficit (relative to target) [kg] + real(r8) :: total_deficit_c ! total carbon deficit (relative to target) [kg] + + real(r8) :: target_leaf_c ! target leaf carbon (allometry scaled by elongation factor) [kg] + real(r8) :: target_fnrt_c ! target fine root carbon (allometry scaled by elongation factor) [kg] + real(r8) :: target_sapw_c ! target sapwood carbon (allometry scaled by elongation factor) [kg] + real(r8) :: target_agw_c ! target Above ground biomass [kgC] + real(r8) :: target_bgw_c ! target Below ground biomass [kgC] + real(r8) :: target_struct_c ! target structural wood carbon (allometry scaled by elongation factor) [kg] + + real(r8) :: sapw_area ! Sapwood area + + real(r8) :: eff_leaf_drop_fraction ! Effective leaf drop fraction + real(r8) :: eff_fnrt_drop_fraction ! Effective fine-root drop fraction + real(r8) :: eff_sapw_drop_fraction ! Effective sapwood drop fraction + real(r8) :: eff_struct_drop_fraction ! Effective structural wood drop fraction + + logical :: is_flushing_time ! Time to flush leaves + logical :: is_shedding_time ! Time to shed leaves + + real(r8) :: fnrt_drop_fraction ! Fine root relative drop fraction (0 = no drop, 1 = as much as leaves) + real(r8) :: stem_drop_fraction ! Stem drop relative fraction (0 = no drop, 1 = as much as leaves) + + integer :: ipft ! Plant functional type index + real(r8), parameter :: leaf_drop_fraction = 1.0_r8 real(r8), parameter :: carbon_store_buffer = 0.10_r8 - real(r8) :: stem_drop_fraction !------------------------------------------------------------------------ currentPatch => CurrentSite%oldest_patch - do while(associated(currentPatch)) + patch_loop: do while(associated(currentPatch)) currentCohort => currentPatch%tallest - do while(associated(currentCohort)) + cohort_loop: do while(associated(currentCohort)) ipft = currentCohort%pft @@ -1091,210 +1319,172 @@ subroutine phenology_leafonoff(currentSite) if(debug) call currentCohort%prt%CheckMassConservation(ipft,0) - store_c = currentCohort%prt%GetState(store_organ, carbon12_element) - leaf_c = currentCohort%prt%GetState(leaf_organ, carbon12_element) - sapw_c = currentCohort%prt%GetState(sapw_organ, carbon12_element) - struct_c = currentCohort%prt%GetState(struct_organ, carbon12_element) + store_c = currentCohort%prt%GetState(store_organ , carbon12_element) + leaf_c = currentCohort%prt%GetState(leaf_organ , carbon12_element) + fnrt_c = currentCohort%prt%GetState(fnrt_organ , carbon12_element) + sapw_c = currentCohort%prt%GetState(sapw_organ , carbon12_element) + struct_c = currentCohort%prt%GetState(struct_organ, carbon12_element) + fnrt_drop_fraction = EDPftvarcon_inst%phen_fnrt_drop_fraction(ipft) stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(ipft) - ! COLD LEAF ON - ! The site level flags signify that it is no-longer too cold - ! for leaves. Time to signal flushing - - if_colddec: if (prt_params%season_decid(ipft) == itrue)then - if_notcold: if ( currentSite%cstatus == phen_cstat_notcold )then ! we have just moved to leaves being on . - if_leaves_off: if (currentCohort%status_coh == leaves_off)then ! Are the leaves currently off? - currentCohort%status_coh = leaves_on ! Leaves are on, so change status to - ! stop flow of carbon out of bstore. - - call bleaf(currentCohort%dbh,currentCohort%pft,currentCohort%canopy_trim,target_leaf_c) - call bsap_allom(currentCohort%dbh,currentCohort%pft, & - currentCohort%canopy_trim,sapw_area,target_sapw_c) - call bagw_allom(currentCohort%dbh,currentCohort%pft,target_agw_c) - call bbgw_allom(currentCohort%dbh,currentCohort%pft,target_bgw_c) - call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, & - currentCohort%pft, target_struct_c) - - if (stem_drop_fraction .gt. 0.0_r8) then - ! Note, this is only true for some grasses, woody plants don't - ! have a stem drop fraction - deficit_c = target_leaf_c + (target_sapw_c-sapw_c) + (target_struct_c-struct_c) - else - deficit_c = target_leaf_c - end if - - if(store_c>nearzero) then - - ! flush either the amount to get to the target, or -most- of the storage pool - ! RF: added a criterion to stop the entire store pool emptying and triggering termination mortality - ! n.b. this might not be necessary if we adopted a more gradual approach to leaf flushing... - store_c_transfer_frac = min((EDPftvarcon_inst%phenflush_fraction(ipft)*deficit_c)/store_c, & - (1.0_r8-carbon_store_buffer)) - - else - store_c_transfer_frac = 0.0_r8 - end if - - ! This call will request that storage carbon will be transferred to - ! leaf tissues. It is specified as a fraction of the available storage - ! Check that the stem drop fraction is set to non-zero amount - ! otherwise flush all carbon store to leaves - if (stem_drop_fraction .gt. 0.0_r8) then - - call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & - store_c_transfer_frac*target_leaf_c/deficit_c) - - call PRTPhenologyFlush(currentCohort%prt, ipft, sapw_organ, & - store_c_transfer_frac*(target_sapw_c-sapw_c)/deficit_c) - - call PRTPhenologyFlush(currentCohort%prt, ipft, struct_organ, & - store_c_transfer_frac*(target_struct_c-struct_c)/deficit_c) - - else - - call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & - store_c_transfer_frac) - - end if - - endif if_leaves_off - endif if_notcold - - !COLD LEAF OFF - if_cold: if (currentSite%cstatus == phen_cstat_nevercold .or. & - currentSite%cstatus == phen_cstat_iscold) then ! past leaf drop day? Leaves still on tree? - - if_leaves_on: if (currentCohort%status_coh == leaves_on) then ! leaves have not dropped - - ! leaf off occur on individuals bigger than specific size for grass - if (currentCohort%dbh > EDPftvarcon_inst%phen_cold_size_threshold(ipft) & - .or. prt_params%woody(ipft)==itrue) then - - ! This sets the cohort to the "leaves off" flag - currentCohort%status_coh = leaves_off - - ! Drop Leaves (this routine will update the leaf state variables, - ! for carbon and any other element that are prognostic. It will - ! also track the turnover masses that will be sent to litter later on) - - call PRTDeciduousTurnover(currentCohort%prt,ipft, & - leaf_organ, leaf_drop_fraction) - - if(prt_params%woody(ipft).ne.itrue)then - - call PRTDeciduousTurnover(currentCohort%prt,ipft, & - sapw_organ, stem_drop_fraction) - - call PRTDeciduousTurnover(currentCohort%prt,ipft, & - struct_organ, stem_drop_fraction) - - endif ! woody plant check - endif ! individual dbh size check - endif if_leaves_on !leaf status - endif if_cold !currentSite status - endif if_colddec !season_decid - - ! DROUGHT LEAF ON - ! Site level flag indicates it is no longer in drought condition - ! deciduous plants can flush - - if (prt_params%stress_decid(ipft) == itrue )then - - if (currentSite%dstatus == phen_dstat_moiston .or. & - currentSite%dstatus == phen_dstat_timeon )then - - ! we have just moved to leaves being on . - if (currentCohort%status_coh == leaves_off)then - - !is it the leaf-on day? Are the leaves currently off? - - currentCohort%status_coh = leaves_on ! Leaves are on, so change status to - ! stop flow of carbon out of bstore. - - call bleaf(currentCohort%dbh,currentCohort%pft,& - currentCohort%canopy_trim,target_leaf_c) - call bsap_allom(currentCohort%dbh,currentCohort%pft, & - currentCohort%canopy_trim,sapw_area,target_sapw_c) - call bagw_allom(currentCohort%dbh,currentCohort%pft,target_agw_c) - call bbgw_allom(currentCohort%dbh,currentCohort%pft,target_bgw_c) - call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, & - currentCohort%pft, target_struct_c) - - if (stem_drop_fraction .gt. 0.0_r8) then - ! Note, this is only true for some grasses, woody plants don't - ! have a stem drop fraction - deficit_c = target_leaf_c + (target_sapw_c-sapw_c) + (target_struct_c-struct_c) - else - deficit_c = target_leaf_c - end if - - if(store_c>nearzero) then - - store_c_transfer_frac = & - min((EDPftvarcon_inst%phenflush_fraction(ipft)*deficit_c)/store_c, & - (1.0_r8-carbon_store_buffer)) - - else - store_c_transfer_frac = 0.0_r8 - endif - - ! This call will request that storage carbon will be transferred to - ! leaf tissues. It is specified as a fraction of the available storage - if (stem_drop_fraction .gt. 0.0_r8) then - - call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & - store_c_transfer_frac*target_leaf_c/deficit_c) - + ! MLO. To avoid duplicating code for drought and cold deciduous PFTs, we first + ! check whether or not it's time to flush or time to shed leaves, then + ! use a common code for flushing or shedding leaves. + is_time_block: if (prt_params%season_decid(ipft) == itrue) then ! Cold deciduous + + ! A. Is this the time for COLD LEAVES to switch to ON? + is_flushing_time = ( currentSite%cstatus == phen_cstat_notcold .and. & ! We just moved to leaves being on + currentCohort%status_coh == leaves_off ) ! Leaves are currently off + ! B. Is this the time for COLD LEAVES to switch to OFF? + is_shedding_time = any(currentSite%cstatus == [phen_cstat_nevercold,phen_cstat_iscold]) .and. & ! Past leaf drop day or too cold + currentCohort%status_coh == leaves_on .and. & ! Leaves have not dropped yet + ( currentCohort%dbh > EDPftvarcon_inst%phen_cold_size_threshold(ipft) .or. & ! Grasses are big enough or... + prt_params%woody(ipft) == itrue ) ! this is a woody PFT. + + elseif (any(prt_params%stress_decid(ipft) == [ihard_stress_decid,isemi_stress_decid]) ) then ! Drought deciduous + + ! A. Is this the time for DROUGHT LEAVES to switch to ON? + is_flushing_time = any( currentSite%dstatus(ipft) == [phen_dstat_moiston,phen_dstat_timeon] ) .and. & ! Leaf flushing time (moisture or time) + any( currentCohort%status_coh == [leaves_off,leaves_pshed] ) + ! B. Is this the time for DROUGHT LEAVES to switch to OFF? + ! This will be true when leaves are abscissing (partially or fully) due to moisture or time + is_shedding_time = any( currentSite%dstatus(ipft) == [phen_dstat_moistoff,phen_dstat_timeoff,phen_dstat_pshed] ) .and. & + any( currentCohort%status_coh == [leaves_on,leaves_pshed] ) + else + ! This PFT is not deciduous. + is_flushing_time = .false. + is_shedding_time = .false. + end if is_time_block + + + + ! Elongation factor for leaves is always the same as the site- and + ! PFT-dependent factor computed in subroutine phenology. For evergreen + ! PFTs, this value should be always 1.0. + currentCohort%efleaf_coh = currentSite%elong_factor(ipft) + + ! Find the effective "elongation factor" for fine roots and stems. The effective drop fraction is + ! a combination of the elongation factor (e) and the drop fraction (x), which will ensure + ! that the remaining tissue biomass will be exactly e when x=1, and exactly the original + ! biomass when x = 0. For leaves it is always assumed that the drop fraction is one. + currentCohort%effnrt_coh = 1.0_r8 - (1.0_r8 - currentCohort%efleaf_coh ) * fnrt_drop_fraction + currentCohort%efstem_coh = 1.0_r8 - (1.0_r8 - currentCohort%efleaf_coh ) * stem_drop_fraction + + ! Find the target biomass for each tissue when tissues are fully flushed. + call bleaf(currentCohort%dbh,currentCohort%pft,currentCohort%canopy_trim, & + target_leaf_c) + call bfineroot(currentCohort%dbh,currentCohort%pft,currentCohort%canopy_trim, & + target_fnrt_c) + call bsap_allom(currentCohort%dbh,currentCohort%pft, & + currentCohort%canopy_trim,sapw_area,target_sapw_c) + call bagw_allom(currentCohort%dbh,currentCohort%pft,target_agw_c) + call bbgw_allom(currentCohort%dbh,currentCohort%pft,target_bgw_c) + call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, & + currentCohort%pft, target_struct_c) + + ! Correct the target biomass for each tissue when accounting for elongation + ! factors. Note that the target works for both flushing and shedding leaves. + target_leaf_c = currentCohort%efleaf_coh * target_leaf_c + target_fnrt_c = currentCohort%effnrt_coh * target_fnrt_c + target_sapw_c = currentCohort%efstem_coh * target_sapw_c + target_struct_c = currentCohort%efstem_coh * target_struct_c + + + ! A. This is time to switch to (COLD or DROUGHT) LEAF ON + flush_block: if (is_flushing_time) then + currentCohort%status_coh = leaves_on ! Leaves are on, so change status to + ! stop flow of carbon out of bstore. + + ! Transfer carbon from storage to living tissues (only if there is any carbon in storage) + transf_block: if ( store_c > nearzero ) then + ! Find the total deficit. We no longer distinguish between woody and non-woody + ! PFTs here (as sapwmemory is the same as sapw_c if this is a woody tissue). + leaf_deficit_c = max(0.0_r8, target_leaf_c - leaf_c ) + fnrt_deficit_c = max(0.0_r8, target_fnrt_c - fnrt_c ) + sapw_deficit_c = max(0.0_r8, target_sapw_c - sapw_c ) + struct_deficit_c = max(0.0_r8, target_struct_c - struct_c) + total_deficit_c = leaf_deficit_c + fnrt_deficit_c + sapw_deficit_c + & + struct_deficit_c + + ! Flush either the amount required from the memory, or -most- of the storage pool + ! RF: added a criterion to stop the entire store pool emptying and triggering termination mortality + ! n.b. this might not be necessary if we adopted a more gradual approach to leaf flushing... + store_c_transfer_frac = min( EDPftvarcon_inst%phenflush_fraction(ipft) * & + total_deficit_c / store_c, & + 1.0_r8 - carbon_store_buffer ) + + ! This call will request that storage carbon will be transferred to + ! each tissue. It is specified as a fraction of the available storage + ! MLO - Just to be safe, skip steps in the unlikely case total_deficit is zero, to avoid FPE errors. + if (total_deficit_c > nearzero) then + call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & + store_c_transfer_frac*leaf_deficit_c/total_deficit_c) + call PRTPhenologyFlush(currentCohort%prt, ipft, fnrt_organ, & + store_c_transfer_frac*fnrt_deficit_c/total_deficit_c) + + ! MLO - stem_drop_fraction is a PFT parameter, do we really need this + ! check for woody/non-woody PFT? + if ( prt_params%woody(ipft) == ifalse ) then call PRTPhenologyFlush(currentCohort%prt, ipft, sapw_organ, & - store_c_transfer_frac*(target_sapw_c-sapw_c)/deficit_c) - + store_c_transfer_frac*sapw_deficit_c/total_deficit_c) call PRTPhenologyFlush(currentCohort%prt, ipft, struct_organ, & - store_c_transfer_frac*(target_struct_c-struct_c)/deficit_c) - - else - - call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & - store_c_transfer_frac) - + store_c_transfer_frac*struct_deficit_c/total_deficit_c) end if + end if + else + ! Not enough carbon to flush any living tissue. + store_c_transfer_frac = 0.0_r8 + end if transf_block + end if flush_block + + + + ! B. This is time to switch to (COLD or DROUGHT) LEAF OFF + shed_block: if (is_shedding_time) then + if ( currentCohort%efleaf_coh > 0.0_r8 ) then + ! Partial shedding + currentCohort%status_coh = leaves_pshed + else + ! Complete abscission + currentCohort%status_coh = leaves_off + end if - endif !currentCohort status again? - endif !currentSite status - - !DROUGHT LEAF OFF - if (currentSite%dstatus == phen_dstat_moistoff .or. & - currentSite%dstatus == phen_dstat_timeoff) then - - if (currentCohort%status_coh == leaves_on) then ! leaves have not dropped - - ! This sets the cohort to the "leaves off" flag - currentCohort%status_coh = leaves_off - - call PRTDeciduousTurnover(currentCohort%prt,ipft, & - leaf_organ, leaf_drop_fraction) - - if(prt_params%woody(ipft).ne.itrue)then - - call PRTDeciduousTurnover(currentCohort%prt,ipft, & - sapw_organ, stem_drop_fraction) - - call PRTDeciduousTurnover(currentCohort%prt,ipft, & - struct_organ, stem_drop_fraction) - endif - endif - endif !status - endif !drought dec. + ! Find the effective fraction to drop. This fraction must be calculated every time + ! because we must account for partial abscission. The simplest approach is to simply + ! use the ratio between the target and the original biomass of each pool. The + ! max(tissue_c,nearzero) is overly cautious, because leaf_c = 0 would imply that + ! leaves are already off, and this wouldn't be considered shedding time. + eff_leaf_drop_fraction = max( 0.0_r8, min( 1.0_r8,1.0_r8 - target_leaf_c / max( leaf_c , nearzero ) ) ) + eff_fnrt_drop_fraction = max( 0.0_r8, min( 1.0_r8,1.0_r8 - target_fnrt_c / max( fnrt_c , nearzero ) ) ) + eff_sapw_drop_fraction = max( 0.0_r8, min( 1.0_r8,1.0_r8 - target_sapw_c / max( sapw_c , nearzero ) ) ) + eff_struct_drop_fraction = max( 0.0_r8, min( 1.0_r8,1.0_r8 - target_struct_c / max( struct_c, nearzero ) ) ) + + ! Drop leaves + call PRTDeciduousTurnover(currentCohort%prt,ipft, leaf_organ, eff_leaf_drop_fraction) + + ! Drop fine roots + call PRTDeciduousTurnover(currentCohort%prt,ipft, fnrt_organ, eff_fnrt_drop_fraction) + + ! If plant is not woody, shed sapwood and heartwood (they may have a minimum amount of woody tissues for + ! running plant hydraulics, and it makes sense to shed them along with leaves when they should be off). + ! MLO - stem_drop_fraction is a PFT parameter, do we really need this check for woody/non-woody PFT? + if ( prt_params%woody(ipft) == ifalse ) then + ! Shed sapwood and heartwood. + call PRTDeciduousTurnover(currentCohort%prt,ipft,sapw_organ , eff_sapw_drop_fraction ) + call PRTDeciduousTurnover(currentCohort%prt,ipft,struct_organ, eff_struct_drop_fraction) + end if + end if shed_block if(debug) call currentCohort%prt%CheckMassConservation(ipft,1) currentCohort => currentCohort%shorter - enddo !currentCohort + end do cohort_loop currentPatch => currentPatch%younger - enddo !currentPatch + end do patch_loop end subroutine phenology_leafonoff @@ -1725,8 +1915,8 @@ subroutine SeedGermination( litt, cold_stat, drought_stat ) ! ! !ARGUMENTS type(litter_type) :: litt - integer, intent(in) :: cold_stat ! Is the site in cold leaf-off status? - integer, intent(in) :: drought_stat ! Is the site in drought leaf-off status? + integer , intent(in) :: cold_stat ! Is the site in cold leaf-off status? + integer, dimension(numpft), intent(in) :: drought_stat ! Is the site in drought leaf-off status? ! ! !LOCAL VARIABLES: integer :: pft @@ -1757,13 +1947,18 @@ subroutine SeedGermination( litt, cold_stat, drought_stat ) (any(cold_stat == [phen_cstat_nevercold,phen_cstat_iscold]))) then litt%seed_germ_in(pft) = 0.0_r8 endif - if ((prt_params%stress_decid(pft) == itrue ) .and. & - (any(drought_stat == [phen_dstat_timeoff,phen_dstat_moistoff]))) then - litt%seed_germ_in(pft) = 0.0_r8 - end if + ! Drought deciduous, halt germination when status is shedding, even leaves are not + ! completely abscissed. MLO + select case (prt_params%stress_decid(pft)) + case (ihard_stress_decid,isemi_stress_decid) + if (any(drought_stat(pft) == [phen_dstat_timeoff,phen_dstat_moistoff,phen_dstat_pshed])) then + litt%seed_germ_in(pft) = 0.0_r8 + end if + end select - enddo + + end do end subroutine SeedGermination @@ -1807,6 +2002,9 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) real(r8) :: c_bgw ! target Below ground biomass [kgC] real(r8) :: c_struct ! target Structural biomass [kgc] real(r8) :: c_store ! target Storage biomass [kgC] + real(r8) :: elongf_leaf ! leaf elongation factor [fraction] + real(r8) :: elongf_fnrt ! fine-root "elongation factor" [fraction] + real(r8) :: elongf_stem ! stem "elongation factor" [fraction] real(r8) :: m_leaf ! leaf mass (element agnostic) [kg] real(r8) :: m_fnrt ! fine-root mass (element agnostic) [kg] real(r8) :: m_sapw ! sapwood mass (element agnostic) [kg] @@ -1818,6 +2016,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) real(r8) :: mass_avail ! The mass of each nutrient/carbon available in the seed_germination pool [kg] real(r8) :: mass_demand ! Total mass demanded by the plant to achieve the stoichiometric targets ! of all the organs in the recruits. Used for both [kg per plant] and [kg per cohort] + real(r8) :: fnrt_drop_fraction real(r8) :: stem_drop_fraction !---------------------------------------------------------------------- @@ -1840,7 +2039,8 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) temp_cohort%pft = ft temp_cohort%hite = EDPftvarcon_inst%hgt_min(ft) temp_cohort%coage = 0.0_r8 - stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(ft) + fnrt_drop_fraction = EDPftvarcon_inst%phen_fnrt_drop_fraction(ft) + stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(ft) call h2d_allom(temp_cohort%hite,ft,temp_cohort%dbh) @@ -1853,38 +2053,55 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) call bdead_allom(c_agw,c_bgw,c_sapw,ft,c_struct) call bstore_allom(temp_cohort%dbh,ft,temp_cohort%canopy_trim,c_store) - ! Default assumption is that leaves are on + ! Default assumption is that leaves are on and fully flushed cohortstatus = leaves_on + elongf_leaf = 1.0_r8 + elongf_fnrt = 1.0_r8 + elongf_stem = 1.0_r8 ! But if the plant is seasonally (cold) deciduous, and the site status is flagged ! as "cold", then set the cohort's status to leaves_off, and remember the leaf biomass if ((prt_params%season_decid(ft) == itrue) .and. & (any(currentSite%cstatus == [phen_cstat_nevercold,phen_cstat_iscold]))) then - c_leaf = 0.0_r8 + elongf_leaf = 0.0_r8 + elongf_fnrt = 1.0_r8 - fnrt_drop_fraction + elongf_stem = 1.0_r8 - stem_drop_fraction - ! If plant is not woody then set sapwood and structural biomass as well - if (prt_params%woody(ft).ne.itrue) then - c_sapw = (1.0_r8 - stem_drop_fraction) * c_sapw - c_struct = (1.0_r8 - stem_drop_fraction) * c_struct - endif - cohortstatus = leaves_off - endif + c_leaf = elongf_leaf * c_leaf + c_fnrt = elongf_fnrt * c_fnrt + c_sapw = elongf_stem * c_sapw + c_struct = elongf_stem * c_struct - ! Or.. if the plant is drought deciduous, and the site status is flagged as - ! "in a drought", then likewise, set the cohort's status to leaves_off, and remember leaf - ! biomass - if ((prt_params%stress_decid(ft) == itrue) .and. & - (any(currentSite%dstatus == [phen_dstat_timeoff,phen_dstat_moistoff]))) then - c_leaf = 0.0_r8 - - ! If plant is not woody then set sapwood and structural biomass as well - if(prt_params%woody(ft).ne.itrue)then - c_sapw = (1.0_r8 - stem_drop_fraction) * c_sapw - c_struct = (1.0_r8 - stem_drop_fraction) * c_struct - endif cohortstatus = leaves_off + endif + ! Or.. if the plant is drought deciduous, make sure leaf status is consistent with the + ! leaf elongation factor. + ! For tissues other than leaves, the actual drop fraction is a combination of the + ! elongation factor (e) and the drop fraction (x), which will ensure that the remaining + ! tissue biomass will be exactly e when x=1, and exactly the original biomass when x = 0. + select case (prt_params%stress_decid(ft)) + case (ihard_stress_decid,isemi_stress_decid) + elongf_leaf = currentSite%elong_factor(ft) + elongf_fnrt = 1.0_r8 - (1.0_r8 - elongf_leaf ) * fnrt_drop_fraction + elongf_stem = 1.0_r8 - (1.0_r8 - elongf_leaf ) * stem_drop_fraction + + c_leaf = elongf_leaf * c_leaf + c_fnrt = elongf_fnrt * c_fnrt + c_sapw = elongf_stem * c_sapw + c_struct = elongf_stem * c_struct + + ! For the initial state, we always assume that leaves are flushing (instead of partially abscissing) + ! whenever the elongation factor is non-zero. If the elongation factor is zero, then leaves are in + ! the "off" state. + if ( elongf_leaf > 0.0_r8 ) then + cohortstatus = leaves_on + else + cohortstatus = leaves_off + end if + end select + ! Cycle through available carbon and nutrients, find the limiting element ! to dictate the total number of plants that can be generated @@ -2059,7 +2276,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) ! This initializes the cohort call create_cohort(currentSite,currentPatch, temp_cohort%pft, temp_cohort%n, & temp_cohort%hite, temp_cohort%coage, temp_cohort%dbh, prt, & - cohortstatus, recruitstatus, & + elongf_leaf, elongf_fnrt, elongf_stem, cohortstatus, recruitstatus, & temp_cohort%canopy_trim,temp_cohort%c_area, & currentPatch%NCL_p, currentSite%spread, bc_in) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index c678fb0dab..9dc1d96292 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -161,6 +161,7 @@ module FatesAllometryMod ! ============================================================================ subroutine CheckIntegratedAllometries(dbh,ipft,canopy_trim, & + elongf_leaf, elongf_fnrt, elongf_stem, & bl,bfr,bsap,bstore,bdead, & grow_leaf, grow_fr, grow_sap, grow_store, grow_dead, & max_err, l_pass) @@ -176,6 +177,9 @@ subroutine CheckIntegratedAllometries(dbh,ipft,canopy_trim, & real(r8),intent(in) :: dbh ! diameter of plant [cm] integer,intent(in) :: ipft ! plant functional type index real(r8),intent(in) :: canopy_trim ! trimming function + real(r8),intent(in) :: elongf_leaf ! Leaf elongation factor + real(r8),intent(in) :: elongf_fnrt ! Fine-root elongation factor + real(r8),intent(in) :: elongf_stem ! Stem elongation factor real(r8),intent(in) :: bl ! integrated leaf biomass [kgC] real(r8),intent(in) :: bfr ! integrated fine root biomass [kgC] real(r8),intent(in) :: bsap ! integrated sapwood biomass [kgC] @@ -206,6 +210,7 @@ subroutine CheckIntegratedAllometries(dbh,ipft,canopy_trim, & if (grow_leaf) then call bleaf(dbh,ipft,canopy_trim,bl_diag) + bl_diag = bl_diag * elongf_leaf if( abs(bl_diag-bl) > max_err ) then if(verbose_logging) then write(fates_log(),*) 'disparity in integrated/diagnosed leaf carbon' @@ -220,6 +225,7 @@ subroutine CheckIntegratedAllometries(dbh,ipft,canopy_trim, & if (grow_fr) then call bfineroot(dbh,ipft,canopy_trim,bfr_diag) + bfr_diag = bfr_diag * elongf_fnrt if( abs(bfr_diag-bfr) > max_err ) then if(verbose_logging) then write(fates_log(),*) 'disparity in integrated/diagnosed fineroot carbon' @@ -234,6 +240,7 @@ subroutine CheckIntegratedAllometries(dbh,ipft,canopy_trim, & if (grow_sap) then call bsap_allom(dbh,ipft,canopy_trim,asap_diag,bsap_diag) + bsap_diag = bsap_diag * elongf_stem if( abs(bsap_diag-bsap) > max_err ) then if(verbose_logging) then write(fates_log(),*) 'disparity in integrated/diagnosed sapwood carbon' @@ -265,6 +272,8 @@ subroutine CheckIntegratedAllometries(dbh,ipft,canopy_trim, & call bagw_allom(dbh,ipft,bagw_diag) call bbgw_allom(dbh,ipft,bbgw_diag) call bdead_allom( bagw_diag, bbgw_diag, bsap_diag, ipft, bdead_diag ) + bdead_diag = bdead_diag * elongf_stem + if( abs(bdead_diag-bdead) > max_err ) then if(verbose_logging) then write(fates_log(),*) 'disparity in integrated/diagnosed structural carbon' @@ -2462,7 +2471,7 @@ subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl ) write(fates_log(),*) 'dbh counter: ',counter,' is woody: ',& (prt_params%woody(ipft) == itrue) - if(int(prt_params%woody(ipft))==itrue)then + if(prt_params%woody(ipft)==itrue)then warn_msg = 'dbh counter: '//trim(I2S(counter))//' is woody' else warn_msg = 'dbh counter: '//trim(I2S(counter))//' is not woody' diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index d3177ca72a..249cc9e3b3 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -32,6 +32,8 @@ module EDInitMod use EDTypesMod , only : init_spread_inventory use EDTypesMod , only : leaves_on use EDTypesMod , only : leaves_off + use EDTypesMod , only : ihard_stress_decid + use EDTypesMod , only : isemi_stress_decid use PRTGenericMod , only : num_elements use PRTGenericMod , only : element_list use EDTypesMod , only : phen_cstat_nevercold @@ -196,16 +198,23 @@ subroutine zero_site( site_in ) ! PHENOLOGY site_in%cstatus = fates_unset_int ! are leaves in this pixel on or off? - site_in%dstatus = fates_unset_int + site_in%dstatus(:) = fates_unset_int site_in%grow_deg_days = nan ! growing degree days site_in%snow_depth = nan site_in%nchilldays = fates_unset_int site_in%ncolddays = fates_unset_int - site_in%cleafondate = fates_unset_int - site_in%cleafoffdate = fates_unset_int - site_in%dleafondate = fates_unset_int - site_in%dleafoffdate = fates_unset_int - site_in%water_memory(:) = nan + site_in%cleafondate = fates_unset_int ! doy of leaf on (cold) + site_in%cleafoffdate = fates_unset_int ! doy of leaf off (cold) + site_in%dleafondate(:) = fates_unset_int ! doy of leaf on (drought) + site_in%dleafoffdate(:) = fates_unset_int ! doy of leaf off (drought) + site_in%cndaysleafon = fates_unset_int ! days since leaf on (cold) + site_in%cndaysleafoff = fates_unset_int ! days since leaf off (cold) + site_in%dndaysleafon(:) = fates_unset_int ! days since leaf on (drought) + site_in%dndaysleafoff(:) = fates_unset_int ! days since leaf off (drought) + site_in%elong_factor(:) = nan ! Elongation factor (0 - full abscission; 1 - fully flushed) + + site_in%liqvol_memory(:,:) = nan + site_in%smp_memory(:,:) = nan site_in%vegtemp_memory(:) = nan ! record of last 10 days temperature for senescence model. site_in%phen_model_date = fates_unset_int @@ -286,11 +295,17 @@ subroutine set_site_properties( nsites, sites,bc_in ) real(r8) :: GDD integer :: dstat ! drought status phenology flag real(r8) :: acc_NI - real(r8) :: watermem + real(r8) :: liqvolmem + real(r8) :: smpmem + real(r8) :: elong_factor ! Elongation factor (0 - fully off; 1 - fully on) integer :: cleafon ! DOY for cold-decid leaf-on, initial guess integer :: cleafoff ! DOY for cold-decid leaf-off, initial guess integer :: dleafoff ! DOY for drought-decid leaf-off, initial guess integer :: dleafon ! DOY for drought-decid leaf-on, initial guess + integer :: cndleafon ! days since leaf on (cold), initial guess + integer :: cndleafoff ! days since leaf off (cold), initial guess + integer :: dndleafon ! days since leaf on (drought), initial guess + integer :: dndleafoff ! days since leaf off (drought), initial guess integer :: ft ! PFT loop real(r8) :: sumarea ! area of PFTs in nocomp mode. integer :: hlm_pft ! used in fixed biogeog mode @@ -308,12 +323,18 @@ subroutine set_site_properties( nsites, sites,bc_in ) GDD = 30.0_r8 cleafon = 100 cleafoff = 300 + cndleafon = 0 + cndleafoff = 0 cstat = phen_cstat_notcold ! Leaves are on acc_NI = 0.0_r8 dstat = phen_dstat_moiston ! Leaves are on dleafoff = 300 dleafon = 100 - watermem = 0.5_r8 + dndleafon = 0 + dndleafoff = 0 + liqvolmem = 0.5_r8 + smpmem = 0._r8 + elong_factor = 1._r8 do s = 1,nsites sites(s)%nchilldays = 0 @@ -321,18 +342,27 @@ subroutine set_site_properties( nsites, sites,bc_in ) ! immediately, so yes this ! is memory-less, but needed ! for first value in history file - sites(s)%phen_model_date = 0 - sites(s)%cleafondate = cleafon - hlm_day_of_year - sites(s)%cleafoffdate = cleafoff - hlm_day_of_year - sites(s)%dleafoffdate = dleafoff - hlm_day_of_year - sites(s)%dleafondate = dleafon - hlm_day_of_year + sites(s)%phen_model_date = 0 + sites(s)%cleafondate = cleafon - hlm_day_of_year + sites(s)%cleafoffdate = cleafoff - hlm_day_of_year + sites(s)%cndaysleafon = cndleafon + sites(s)%cndaysleafoff = cndleafoff + sites(s)%dleafoffdate (1:numpft) = dleafoff - hlm_day_of_year + sites(s)%dleafondate (1:numpft) = dleafon - hlm_day_of_year + sites(s)%dndaysleafon (1:numpft) = dndleafon + sites(s)%dndaysleafoff(1:numpft) = dndleafoff + + + sites(s)%grow_deg_days = GDD - sites(s)%water_memory(1:numWaterMem) = watermem + sites(s)%liqvol_memory(1:numWaterMem,1:numpft) = liqvolmem + sites(s)%smp_memory(1:numWaterMem,1:numpft) = smpmem sites(s)%vegtemp_memory(1:num_vegtemp_mem) = 0._r8 sites(s)%cstatus = cstat - sites(s)%dstatus = dstat + sites(s)%dstatus(1:numpft) = dstat + sites(s)%elong_factor(1:numpft) = elong_factor sites(s)%acc_NI = acc_NI sites(s)%NF = 0.0_r8 @@ -706,7 +736,11 @@ subroutine init_cohorts( site_in, patch_in, bc_in) real(r8) :: m_sapw ! Generic mass for sapwood [kg] real(r8) :: m_store ! Generic mass for storage [kg] real(r8) :: m_repro ! Generic mass for reproductive tissues [kg] - real(r8) :: stem_drop_fraction + real(r8) :: elongf_leaf ! Leaf elongation factor + real(r8) :: elongf_fnrt ! Fine-root "elongation factor" + real(r8) :: elongf_stem ! Stem "elongation factor" + real(r8) :: fnrt_drop_fraction ! Fraction of fine roots to absciss when leaves absciss + real(r8) :: stem_drop_fraction ! Fraction of stems to absciss when leaves absciss integer, parameter :: rstatus = 0 integer init @@ -797,27 +831,52 @@ subroutine init_cohorts( site_in, patch_in, bc_in) call bstore_allom(temp_cohort%dbh, pft, temp_cohort%canopy_trim, c_store) - cstatus = leaves_on + ! Assume leaves are fully flushed, and update if needed. + cstatus = leaves_on + elongf_leaf = 1.0_r8 + elongf_fnrt = 1.0_r8 + elongf_stem = 1.0_r8 + fnrt_drop_fraction = EDPftvarcon_inst%phen_fnrt_drop_fraction(temp_cohort%pft) stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(temp_cohort%pft) if(hlm_use_sp.eq.ifalse)then ! do not override SP vales with phenology if( prt_params%season_decid(pft) == itrue .and. & any(site_in%cstatus == [phen_cstat_nevercold,phen_cstat_iscold])) then - c_leaf = 0._r8 - c_sapw = (1.0_r8-stem_drop_fraction) * c_sapw - c_struct = (1.0_r8-stem_drop_fraction) * c_struct - cstatus = leaves_off - endif + elongf_leaf = 0._r8 + elongf_fnrt = 1.0_r8 - fnrt_drop_fraction + elongf_stem = 1.0_r8 - stem_drop_fraction + + c_leaf = elongf_leaf * c_leaf + c_fnrt = elongf_fnrt * c_fnrt + c_sapw = elongf_stem * c_sapw + c_struct = elongf_stem * c_struct - if ( prt_params%stress_decid(pft) == itrue .and. & - any(site_in%dstatus == [phen_dstat_timeoff,phen_dstat_moistoff])) then - c_leaf = 0._r8 - c_sapw = (1.0_r8-stem_drop_fraction) * c_sapw - c_struct = (1.0_r8-stem_drop_fraction) * c_struct cstatus = leaves_off - endif + elseif ( any(prt_params%stress_decid(pft) == [ihard_stress_decid,isemi_stress_decid])) then + ! If the plant is drought deciduous, make sure leaf status is + ! always consistent with the leaf elongation factor. For tissues + ! other than leaves, the actual drop fraction is a combination of the + ! elongation factor (e) and the drop fraction (x), which will ensure + ! that the remaining tissue biomass will be exactly e when x=1, and + ! exactly the original biomass when x = 0. + elongf_leaf = site_in%elong_factor(pft) + elongf_fnrt = 1.0_r8 - (1.0_r8 - elongf_leaf ) * fnrt_drop_fraction + elongf_stem = 1.0_r8 - (1.0_r8 - elongf_leaf ) * stem_drop_fraction + + + c_leaf = elongf_leaf * c_leaf + c_fnrt = elongf_fnrt * c_fnrt + c_sapw = elongf_stem * c_sapw + c_struct = elongf_stem * c_struct + + if (elongf_leaf > 0.0_r8) then + cstatus = leaves_on + else + cstatus = leaves_off + end if + end if end if ! SP mode @@ -894,8 +953,9 @@ subroutine init_cohorts( site_in, patch_in, bc_in) call prt_obj%CheckInitialConditions() call create_cohort(site_in, patch_in, pft, temp_cohort%n, temp_cohort%hite, & - temp_cohort%coage, temp_cohort%dbh, prt_obj, cstatus, rstatus, & - temp_cohort%canopy_trim, temp_cohort%c_area,1, site_in%spread, bc_in) + temp_cohort%coage, temp_cohort%dbh, prt_obj, elongf_leaf, elongf_fnrt, & + elongf_stem, cstatus, rstatus, temp_cohort%canopy_trim, & + temp_cohort%c_area,1, site_in%spread, bc_in) deallocate(temp_cohort) ! get rid of temporary cohort diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 7b9d623413..b7e83b598c 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -416,7 +416,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! Conduct Maintenance Turnover (parteh) if(debug) call currentCohort%prt%CheckMassConservation(ft,3) - if(any(currentSite%dstatus == [phen_dstat_moiston,phen_dstat_timeon])) then + if(any(currentSite%dstatus(ft) == [phen_dstat_moiston,phen_dstat_timeon])) then is_drought = .false. else is_drought = .true. diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 2923f59d06..4dacaecf5b 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -47,6 +47,7 @@ module EDParamsMod real(r8),protected, public :: ED_val_cwd_flig real(r8),protected, public :: ED_val_base_mr_20 real(r8),protected, public :: ED_val_phen_drought_threshold + real(r8),protected, public :: ED_val_phen_moist_threshold real(r8),protected, public :: ED_val_phen_doff_time real(r8),protected, public :: ED_val_phen_a real(r8),protected, public :: ED_val_phen_b @@ -107,6 +108,7 @@ module EDParamsMod character(len=param_string_length),parameter,public :: ED_name_cwd_flig= "fates_frag_cwd_flig" character(len=param_string_length),parameter,public :: ED_name_base_mr_20= "fates_base_mr_20" character(len=param_string_length),parameter,public :: ED_name_phen_drought_threshold= "fates_phen_drought_threshold" + character(len=param_string_length),parameter,public :: ED_name_phen_moist_threshold= "fates_phen_moist_threshold" character(len=param_string_length),parameter,public :: ED_name_phen_doff_time= "fates_phen_mindaysoff" character(len=param_string_length),parameter,public :: ED_name_phen_a= "fates_phen_gddthresh_a" character(len=param_string_length),parameter,public :: ED_name_phen_b= "fates_phen_gddthresh_b" @@ -276,6 +278,7 @@ subroutine FatesParamsInit() ED_val_cwd_flig = nan ED_val_base_mr_20 = nan ED_val_phen_drought_threshold = nan + ED_val_phen_moist_threshold = nan ED_val_phen_doff_time = nan ED_val_phen_a = nan ED_val_phen_b = nan @@ -390,6 +393,9 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=ED_name_phen_drought_threshold, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=ED_name_phen_moist_threshold, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=ED_name_phen_doff_time, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -589,6 +595,9 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetrieveParameter(name=ED_name_phen_drought_threshold, & data=ED_val_phen_drought_threshold) + call fates_params%RetrieveParameter(name=ED_name_phen_moist_threshold, & + data=ED_val_phen_moist_threshold) + call fates_params%RetrieveParameter(name=ED_name_phen_doff_time, & data=ED_val_phen_doff_time) @@ -780,6 +789,7 @@ subroutine FatesReportParams(is_master) write(fates_log(),fmt0) 'ED_val_cwd_flig = ',ED_val_cwd_flig write(fates_log(),fmt0) 'ED_val_base_mr_20 = ', ED_val_base_mr_20 write(fates_log(),fmt0) 'ED_val_phen_drought_threshold = ',ED_val_phen_drought_threshold + write(fates_log(),fmt0) 'ED_val_phen_moist_threshold = ',ED_val_phen_moist_threshold write(fates_log(),fmt0) 'ED_val_phen_doff_time = ',ED_val_phen_doff_time write(fates_log(),fmt0) 'ED_val_phen_a = ',ED_val_phen_a write(fates_log(),fmt0) 'ED_val_phen_b = ',ED_val_phen_b diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index e381ab8bc7..d7d40b8222 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -169,7 +169,8 @@ module EDPftvarcon ! on bud-burst [kgC/kgC] real(r8), allocatable :: phen_cold_size_threshold(:) ! stem/leaf drop occurs on DBH size of decidious non-woody ! (coastal grass) plants larger than the threshold value - real(r8), allocatable :: phen_stem_drop_fraction(:) ! Fraction of stem dropped/senescened for decidious + real(r8), allocatable :: phen_fnrt_drop_fraction(:) ! Fraction of fine roots abscissed when leaves absciss + real(r8), allocatable :: phen_stem_drop_fraction(:) ! Fraction of stem abscissed when leaves absciss, for deciduous ! non-woody (grass) plants ! Nutrient Aquisition parameters @@ -570,6 +571,10 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_phen_fnrt_drop_fraction' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + ! Nutrient competition parameters @@ -913,6 +918,10 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetrieveParameterAllocate(name=name, & data=this%phen_stem_drop_fraction) + name = 'fates_phen_fnrt_drop_fraction' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%phen_fnrt_drop_fraction) + name = 'fates_cnp_prescribed_nuptake' call fates_params%RetrieveParameterAllocate(name=name, & data=this%prescribed_nuptake) @@ -1429,6 +1438,7 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'taus = ',EDPftvarcon_inst%taus write(fates_log(),fmt0) 'phen_flush_fraction',EDpftvarcon_inst%phenflush_fraction write(fates_log(),fmt0) 'phen_cold_size_threshold = ',EDPftvarcon_inst%phen_cold_size_threshold + write(fates_log(),fmt0) 'phen_fnrt_drop_fraction',EDpftvarcon_inst%phen_fnrt_drop_fraction write(fates_log(),fmt0) 'phen_stem_drop_fraction',EDpftvarcon_inst%phen_stem_drop_fraction write(fates_log(),fmt0) 'fire_alpha_SH = ',EDPftvarcon_inst%fire_alpha_SH write(fates_log(),fmt0) 'allom_frbstor_repro = ',EDPftvarcon_inst%allom_frbstor_repro @@ -1476,6 +1486,9 @@ subroutine FatesCheckParams(is_master) use FatesConstantsMod , only : itrue, ifalse use EDParamsMod , only : logging_mechanical_frac, logging_collateral_frac use EDParamsMod , only : logging_direct_frac,logging_export_frac + use EDParamsMod , only : ED_val_phen_drought_threshold + use EDParamsMod , only : ED_val_phen_moist_threshold + use EDTypesMod , only : isemi_stress_decid use FatesInterfaceTypesMod, only : hlm_use_fixed_biogeog,hlm_use_sp, hlm_name ! Argument @@ -1665,7 +1678,7 @@ subroutine FatesCheckParams(is_master) ! Check if the fraction of storage used for flushing deciduous trees ! is greater than zero, and less than or equal to 1. - if ( int(prt_params%evergreen(ipft)) .ne. 1 ) then + if (prt_params%evergreen(ipft) == ifalse) then if ( ( EDPftvarcon_inst%phenflush_fraction(ipft) < nearzero ) .or. & ( EDPFtvarcon_inst%phenflush_fraction(ipft) > 1 ) ) then @@ -1673,17 +1686,27 @@ subroutine FatesCheckParams(is_master) write(fates_log(),*) ' on bud-burst. If phenflush_fraction is not greater than 0' write(fates_log(),*) ' it will not be able to put out any leaves. Plants need leaves.' write(fates_log(),*) ' PFT#: ',ipft - write(fates_log(),*) ' evergreen flag: (shold be 0):',int(prt_params%evergreen(ipft)) + write(fates_log(),*) ' evergreen flag: (should be 0):',int(prt_params%evergreen(ipft)) write(fates_log(),*) ' phenflush_fraction: ', EDPFtvarcon_inst%phenflush_fraction(ipft) write(fates_log(),*) ' Aborting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if + if ( ( EDPftvarcon_inst%phen_fnrt_drop_fraction(ipft) < 0.0_r8 ) .or. & + ( EDPFtvarcon_inst%phen_fnrt_drop_fraction(ipft) > 1.0_r8 ) ) then + write(fates_log(),*) ' Abscission rate for fine roots must be between 0 and 1 for ' + write(fates_log(),*) ' deciduous PFTs.' + write(fates_log(),*) ' PFT#: ',ipft + write(fates_log(),*) ' evergreen flag: (should be 0):',int(prt_params%evergreen(ipft)) + write(fates_log(),*) ' phen_fnrt_drop_fraction: ', EDPFtvarcon_inst%phen_fnrt_drop_fraction(ipft) + write(fates_log(),*) ' Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if if ( ( EDPftvarcon_inst%phen_stem_drop_fraction(ipft) < 0.0_r8 ) .or. & - ( EDPFtvarcon_inst%phen_stem_drop_fraction(ipft) > 1 ) ) then + ( EDPFtvarcon_inst%phen_stem_drop_fraction(ipft) > 1.0_r8 ) ) then write(fates_log(),*) ' Deciduous non-wood plants must keep 0-100% of their stems' write(fates_log(),*) ' during the deciduous period.' write(fates_log(),*) ' PFT#: ',ipft - write(fates_log(),*) ' evergreen flag: (shold be 0):',int(prt_params%evergreen(ipft)) + write(fates_log(),*) ' evergreen flag: (should be 0):',int(prt_params%evergreen(ipft)) write(fates_log(),*) ' phen_stem_drop_fraction: ', EDPFtvarcon_inst%phen_stem_drop_fraction(ipft) write(fates_log(),*) ' Aborting' call endrun(msg=errMsg(sourcefile, __LINE__)) @@ -1794,6 +1817,38 @@ subroutine FatesCheckParams(is_master) !! end do + ! When using the the gradual (ED2-like) phenology, we must ensure that the lower + ! and upper thresholds are consistent (i.e., that both are based on either soil + ! water content or soil matric potential). + is_semi_decid: if (any(prt_params%stress_decid(:) == isemi_stress_decid)) then + + if (ED_val_phen_drought_threshold*ED_val_phen_moist_threshold < 0._r8) then + ! In case the product of the lower and upper thresholds is negative, the + ! thresholds are inconsistent as both should be defined using the same + ! quantity. + write(fates_log(),*) ' When using gradual (ED2-like) drought deciduous phenology,' + write(fates_log(),*) ' the moist threshold should be have the same sign as' + write(fates_log(),*) ' the dry threshold. Positive = soil water content [m3/m3],' + write(fates_log(),*) ' Negative = soil matric potential [mm].' + write(fates_log(),*) ' fates_phen_drought_threshold (dry threshold) = ',ED_val_phen_drought_threshold + write(fates_log(),*) ' fates_phen_moist_threshold (moist threshold) = ',ED_val_phen_moist_threshold + write(fates_log(),*) ' Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + + elseif ( ED_val_phen_drought_threshold >= ED_val_phen_moist_threshold) then + write(fates_log(),*) ' When using gradual (ED2-like) drought deciduous phenology,' + write(fates_log(),*) ' the moist threshold should be greater than the dry threshold.' + write(fates_log(),*) ' By greater we mean more positive or less negative, and' + write(fates_log(),*) ' they cannot be the identical.' + write(fates_log(),*) ' fates_phen_drought_threshold (dry threshold) = ',ED_val_phen_drought_threshold + write(fates_log(),*) ' fates_phen_moist_threshold (moist threshold) = ',ED_val_phen_moist_threshold + write(fates_log(),*) ' Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + end if is_semi_decid + + return end subroutine FatesCheckParams diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 86bb36e31e..ef96506eb5 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -85,12 +85,32 @@ module EDTypesMod ! can be approximated to be equal to the visible band + integer, parameter, public :: leaves_pshed = 3 ! Flag specifying that a deciduous plant has leaves + ! but is shedding them (partial shedding). This plant + ! should not allocate carbon towards growth or + ! reproduction. integer, parameter, public :: leaves_on = 2 ! Flag specifying that a deciduous plant has leaves ! and should be allocating to them as well integer, parameter, public :: leaves_off = 1 ! Flag specifying that a deciduous plant has dropped ! its leaves and should not be trying to allocate ! towards any growth. + integer, parameter, public :: ihard_stress_decid = 1 ! If the PFT is stress (drought) deciduous, + ! this flag is used to tell that the PFT + ! is a "hard" deciduous (i.e., the plant + ! has only two statuses, the plant either + ! sheds all leaves when it's time, or seeks + ! to flush the leaves back to allometry + ! when conditions improve. + integer, parameter, public :: isemi_stress_decid = 2 ! If the PFT is stress (drought) deciduous, + ! this flag is used to tell that the PFT + ! is a semi-deciduous (i.e., the plant + ! can downregulate the amount of leaves + ! relative to the allometry based on + ! soil moisture conditions. It can still + ! shed all leaves if conditions are very + ! dry. + ! Flag to turn on/off salinity effects on the effective "btran" ! btran stress function. @@ -140,6 +160,7 @@ module EDTypesMod integer, parameter, public :: phen_dstat_moistoff = 1 ! Leaves off due to moisture avail (drought phenology) integer, parameter, public :: phen_dstat_moiston = 2 ! Leaves on due to moisture avail (drought phenology) integer, parameter, public :: phen_dstat_timeon = 3 ! Leaves on due to time exceedance (drought phenology) + integer, parameter, public :: phen_dstat_pshed = 4 ! Leaves partially abscissing (drought phenology) ! SPITFIRE @@ -225,6 +246,11 @@ module EDTypesMod real(r8) :: prom_weight ! How much of this cohort is promoted each year, as a proportion of all cohorts:- integer :: nv ! Number of leaf layers: - integer :: status_coh ! growth status of plant (2 = leaves on , 1 = leaves off) + real(r8) :: efleaf_coh ! Elongation factor for leaves (fraction) + real(r8) :: effnrt_coh ! Elongation factor for fine roots (fraction) + real(r8) :: efstem_coh ! Elongation factor for stem (fraction) + ! For all the elongation factors, zero means fully abscissed, and + ! one means fully flushed. real(r8) :: c_area ! areal extent of canopy (m2) real(r8) :: treelai ! lai of an individual within cohort leaf area (m2) / crown area (m2) real(r8) :: treesai ! stem area index of an indiv. within cohort: stem area (m2) / crown area (m2) @@ -723,25 +749,32 @@ module EDTypesMod ! 400 days, leaves are dropped and flagged as non-cold region ! 1 = this site is in a cold-state where leaves should have fallen ! 2 = this site is in a warm-state where leaves are allowed to flush - integer :: dstatus ! are leaves in this pixel on or off for drought decid + integer :: dstatus(maxpft) ! are leaves in this pixel on or off for drought decid ! 0 = leaves off due to time exceedance ! 1 = leaves off due to moisture avail ! 2 = leaves on due to moisture avail ! 3 = leaves on due to time exceedance + ! 4 = leaves partially on (ED2-like phenology) integer :: nchilldays ! num chilling days: (for botta gdd trheshold calculation) integer :: ncolddays ! num cold days: (must exceed threshold to drop leaves) real(r8) :: vegtemp_memory(num_vegtemp_mem) ! record of last 10 days temperature for senescence model. deg C integer :: cleafondate ! model date (day integer) of leaf on (cold):- integer :: cleafoffdate ! model date (day integer) of leaf off (cold):- - integer :: dleafondate ! model date (day integer) of leaf on drought:- - integer :: dleafoffdate ! model date (day integer) of leaf off drought:- + integer :: cndaysleafon ! number of days since leaf on period started (cold) + integer :: cndaysleafoff ! number of days since leaf off period started (cold) + integer :: dleafondate(maxpft) ! model date (day integer) of leaf on drought:- + integer :: dleafoffdate(maxpft) ! model date (day integer) of leaf off drought:- + integer :: dndaysleafon(maxpft) ! number of days since leaf on period started (drought) + integer :: dndaysleafoff(maxpft) ! number of days since leaf off period started (drought) + real(r8) :: elong_factor(maxpft) ! Elongation factor (ED2-like phenology). This is zero when leaves are + ! completely off, and one when they are completely flushed. integer :: phen_model_date ! current model date (day integer) ! this date stays continuous when ! in runs that are restarted, regardless of ! the conditions of restart - - real(r8) :: water_memory(numWaterMem) ! last 10 days of soil moisture memory... + real(r8) :: liqvol_memory(numWaterMem,maxpft) ! last 10 days of soil liquid water volume (drought phenology) + real(r8) :: smp_memory(numWaterMem,maxpft) ! last 10 days of soil matric potential (drought phenology) ! FIRE @@ -1049,6 +1082,9 @@ subroutine dump_cohort(ccohort) write(fates_log(),*) 'co%canopy_layer_yesterday = ', ccohort%canopy_layer_yesterday write(fates_log(),*) 'co%nv = ', ccohort%nv write(fates_log(),*) 'co%status_coh = ', ccohort%status_coh + write(fates_log(),*) 'co%efleaf_coh = ', ccohort%efleaf_coh + write(fates_log(),*) 'co%effnrt_coh = ', ccohort%effnrt_coh + write(fates_log(),*) 'co%efstem_coh = ', ccohort%efstem_coh write(fates_log(),*) 'co%canopy_trim = ', ccohort%canopy_trim write(fates_log(),*) 'co%excl_weight = ', ccohort%excl_weight write(fates_log(),*) 'co%prom_weight = ', ccohort%prom_weight diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 391d5f87d9..5f6965bbbf 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -67,9 +67,12 @@ module FatesHistoryInterfaceMod use FatesConstantsMod , only : J_per_kJ use FatesConstantsMod , only : m2_per_ha use FatesConstantsMod , only : m_per_cm + use FatesConstantsMod , only : mm_per_m use FatesConstantsMod , only : sec_per_min use FatesConstantsMod , only : umol_per_mol,mol_per_umol use FatesConstantsMod , only : pa_per_mpa + use FatesConstantsMod , only : dens_fresh_liquid_water + use FatesConstantsMod , only : grav_earth use FatesLitterMod , only : litter_type use FatesConstantsMod , only : secondaryforest @@ -349,15 +352,11 @@ module FatesHistoryInterfaceMod integer :: ih_h2oveg_hydro_err_si integer :: ih_site_cstatus_si - integer :: ih_site_dstatus_si integer :: ih_gdd_si integer :: ih_site_nchilldays_si integer :: ih_site_ncolddays_si integer :: ih_cleafoff_si integer :: ih_cleafon_si - integer :: ih_dleafoff_si - integer :: ih_dleafon_si - integer :: ih_meanliqvol_si integer :: ih_nesterov_fire_danger_si integer :: ih_fire_nignitions_si @@ -526,6 +525,12 @@ module FatesHistoryInterfaceMod integer :: ih_canopycrownarea_si_pft integer :: ih_gpp_si_pft integer :: ih_npp_si_pft + integer :: ih_site_dstatus_si_pft + integer :: ih_dleafoff_si_pft + integer :: ih_dleafon_si_pft + integer :: ih_meanliqvol_si_pft + integer :: ih_meansmp_si_pft + integer :: ih_elong_factor_si_pft integer :: ih_nocomp_pftpatchfraction_si_pft integer :: ih_nocomp_pftnpatches_si_pft integer :: ih_nocomp_pftburnedarea_si_pft @@ -2038,16 +2043,18 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_mortality_canopy_si_scag => this%hvars(ih_mortality_canopy_si_scag)%r82d, & hio_mortality_understory_si_scag => this%hvars(ih_mortality_understory_si_scag)%r82d, & hio_site_cstatus_si => this%hvars(ih_site_cstatus_si)%r81d, & - hio_site_dstatus_si => this%hvars(ih_site_dstatus_si)%r81d, & hio_gdd_si => this%hvars(ih_gdd_si)%r81d, & hio_site_ncolddays_si => this%hvars(ih_site_ncolddays_si)%r81d, & hio_site_nchilldays_si => this%hvars(ih_site_nchilldays_si)%r81d, & hio_cleafoff_si => this%hvars(ih_cleafoff_si)%r81d, & hio_cleafon_si => this%hvars(ih_cleafon_si)%r81d, & - hio_dleafoff_si => this%hvars(ih_dleafoff_si)%r81d, & - hio_dleafon_si => this%hvars(ih_dleafon_si)%r81d, & + hio_site_dstatus_si_pft => this%hvars(ih_site_dstatus_si_pft)%r82d, & + hio_dleafoff_si_pft => this%hvars(ih_dleafoff_si_pft)%r82d, & + hio_dleafon_si_pft => this%hvars(ih_dleafon_si_pft)%r82d, & + hio_meanliqvol_si_pft => this%hvars(ih_meanliqvol_si_pft)%r82d, & + hio_meansmp_si_pft => this%hvars(ih_meansmp_si_pft)%r82d, & + hio_elong_factor_si_pft => this%hvars(ih_elong_factor_si_pft)%r82d, & hio_tveg24 => this%hvars(ih_tveg24_si)%r81d, & - hio_meanliqvol_si => this%hvars(ih_meanliqvol_si)%r81d, & hio_cbal_err_fates_si => this%hvars(ih_cbal_err_fates_si)%r81d, & hio_err_fates_si => this%hvars(ih_err_fates_si)%r82d ) @@ -2092,10 +2099,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! Canopy spread index (0-1) hio_canopy_spread_si(io_si) = sites(s)%spread - ! Site statuses (stati?) for cold deciduous and drought - ! deciduous - hio_site_cstatus_si(io_si) = real(sites(s)%cstatus,r8) - hio_site_dstatus_si(io_si) = real(sites(s)%dstatus,r8) + ! Update the site status for cold deciduous (drought deciduous is now PFT dependent) + hio_site_cstatus_si(io_si) = real(sites(s)%cstatus,r8) ! Number of chill days and cold days hio_site_nchilldays_si(io_si) = real(sites(s)%nchilldays,r8) @@ -2104,17 +2109,34 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! Growing degree-days hio_gdd_si(io_si) = sites(s)%grow_deg_days - ! Model days elapsed since leaf on/off for cold- and drought-deciduous + ! Model days elapsed since leaf on/off for cold-deciduous hio_cleafoff_si(io_si) = real(sites(s)%phen_model_date - sites(s)%cleafoffdate,r8) hio_cleafon_si(io_si) = real(sites(s)%phen_model_date - sites(s)%cleafondate,r8) - hio_dleafoff_si(io_si) = real(sites(s)%phen_model_date - sites(s)%dleafoffdate,r8) - hio_dleafon_si(io_si) = real(sites(s)%phen_model_date - sites(s)%dleafondate,r8) - ! Mean liquid water content (m3/m3) used for drought phenology - if(model_day_int>numWaterMem)then - hio_meanliqvol_si(io_si) = & - sum(sites(s)%water_memory(1:numWaterMem))/real(numWaterMem,r8) - end if + + ! Update drought deciduous information (now separated by PFT). + do i_pft = 1,numpft + ! Update the site-PFT status for drought deciduous + hio_site_dstatus_si_pft(io_si,i_pft) = real(sites(s)%dstatus(i_pft),r8) + + ! Model days elapsed since leaf off/on for drought deciduous + hio_dleafoff_si_pft(io_si,i_pft) = real(sites(s)%dndaysleafon (i_pft),r8) + hio_dleafon_si_pft(io_si,i_pft) = real(sites(s)%dndaysleafoff(i_pft),r8) + + ! Leaf elongation factor (0 means fully abscissed, 1 means fully flushed). + hio_elong_factor_si_pft(io_si,i_pft) = sites(s)%elong_factor(i_pft) + + if(model_day_int>numWaterMem)then + ! Mean liquid water content (m3/m3) used for drought phenology + hio_meanliqvol_si_pft(io_si,i_pft) = & + sum(sites(s)%liqvol_memory(1:numWaterMem,i_pft))/real(numWaterMem,r8) + + ! Mean soil matric potential (Pa) used for drought phenology + hio_meansmp_si_pft(io_si,i_pft) = & + sum(sites(s)%smp_memory(1:numWaterMem,i_pft))/real(numWaterMem,r8) & + * dens_fresh_liquid_water * grav_earth * mm_per_m + end if + end do ! track total wood product accumulation at the site level hio_woodproduct_si(io_si) = sites(s)%resources_management%trunk_product_site & @@ -4493,13 +4515,6 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_site_cstatus_si) - call this%set_history_var(vname='FATES_DROUGHT_STATUS', & - units='', & - long='site-level drought status, <2 too dry for leaves, >=2 not too dry', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_site_dstatus_si) - call this%set_history_var(vname='FATES_GDD', units='degree_Celsius', & long='site-level growing degree days', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', & @@ -4529,26 +4544,6 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_cleafon_si) - call this%set_history_var(vname='FATES_DAYSINCE_DROUGHTLEAFOFF', & - units='days', long='site level days elapsed since drought leaf drop', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_dleafoff_si) - - call this%set_history_var(vname='FATES_DAYSINCE_DROUGHTLEAFON', & - units='days', & - long='site-level days elapsed since drought leaf flush', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_dleafon_si) - - call this%set_history_var(vname='FATES_MEANLIQVOL_DROUGHTPHEN', & - units='m3 m-3', & - long='site-level mean liquid water volume for drought phenolgy', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_meanliqvol_si) - call this%set_history_var(vname='FATES_CANOPY_SPREAD', units='', & long='scaling factor (0-1) between tree basal area and canopy area', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & @@ -4616,6 +4611,48 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_mortality_si_pft) + !MLO - Drought-deciduous phenology variables are now defined for each PFT. + call this%set_history_var(vname='FATES_DROUGHT_STATUS_PF', & + units='', & + long='PFT-level drought status, <2 too dry for leaves, >=2 not too dry', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_site_dstatus_si_pft) + + call this%set_history_var(vname='FATES_DAYSINCE_DROUGHTLEAFOFF_PF', & + units='days', long='PFT-level days elapsed since drought leaf drop', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_dleafoff_si_pft) + + call this%set_history_var(vname='FATES_DAYSINCE_DROUGHTLEAFON_PF', & + units='days', & + long='PFT-level days elapsed since drought leaf flush', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_dleafon_si_pft) + + call this%set_history_var(vname='FATES_MEANLIQVOL_DROUGHTPHEN_PF', & + units='m3 m-3', & + long='PFT-level mean liquid water volume for drought phenolgy', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_meanliqvol_si_pft) + + call this%set_history_var(vname='FATES_MEANSMP_DROUGHTPHEN_PF', & + units='Pa', & + long='PFT-level mean soil matric potential for drought phenology', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_meansmp_si_pft) + + call this%set_history_var(vname='FATES_ELONG_FACTOR_PF', & + units='1', & + long='PFT-level mean elongation factor (partial flushing/abscission)', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_elong_factor_si_pft) + nocomp_if: if (hlm_use_nocomp .eq. itrue) then call this%set_history_var(vname='FATES_NOCOMP_NPATCHES_PF', units='', & long='number of patches per PFT (nocomp-mode-only)', & diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index a76ae9df4f..e1ad4e63cb 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -38,6 +38,8 @@ module FatesInventoryInitMod use EDTypesMod , only : area use EDTypesMod , only : leaves_on use EDTypesMod , only : leaves_off + use EDTypesMod , only : ihard_stress_decid + use EDTypesMod , only : isemi_stress_decid use PRTGenericMod , only : num_elements use PRTGenericMod , only : element_list use EDTypesMod , only : phen_cstat_nevercold @@ -915,7 +917,11 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & real(r8) :: m_sapw ! Generic mass for sapwood [kg] real(r8) :: m_store ! Generic mass for storage [kg] real(r8) :: m_repro ! Generic mass for reproductive tissues [kg] - real(r8) :: stem_drop_fraction + real(r8) :: elongf_leaf ! Leaf elongation factor + real(r8) :: elongf_fnrt ! Fine-root "elongation factor" + real(r8) :: elongf_stem ! Stem "elongation factor" + real(r8) :: fnrt_drop_fraction ! Fine-root abscission fraction + real(r8) :: stem_drop_fraction ! Stem abscission fraction integer :: i_pft, ncohorts_to_create character(len=128),parameter :: wr_fmt = & @@ -1042,23 +1048,53 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & call bstore_allom(temp_cohort%dbh, temp_cohort%pft, temp_cohort%canopy_trim, c_store) cstatus = leaves_on + elongf_leaf = 1.0_r8 + elongf_fnrt = 1.0_r8 + elongf_stem = 1.0_r8 + + fnrt_drop_fraction = EDPftvarcon_inst%phen_fnrt_drop_fraction(temp_cohort%pft) stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(temp_cohort%pft) if( prt_params%season_decid(temp_cohort%pft) == itrue .and. & any(csite%cstatus == [phen_cstat_nevercold,phen_cstat_iscold])) then - c_leaf = 0._r8 - c_sapw = (1._r8 - stem_drop_fraction) * c_sapw - c_struct = (1._r8 - stem_drop_fraction) * c_struct - cstatus = leaves_off - endif - - if ( prt_params%stress_decid(temp_cohort%pft) == itrue .and. & - any(csite%dstatus == [phen_dstat_timeoff,phen_dstat_moistoff])) then - c_leaf = 0._r8 - c_sapw = (1._r8 - stem_drop_fraction) * c_sapw - c_struct = (1._r8 - stem_drop_fraction) * c_struct - cstatus = leaves_off - endif + elongf_leaf = 0.0_r8 + elongf_fnrt = 1._r8 - fnrt_drop_fraction + elongf_stem = 1._r8 - stem_drop_fraction + + c_leaf = elongf_leaf * c_leaf + c_fnrt = elongf_fnrt * c_fnrt + c_sapw = elongf_stem * c_sapw + c_struct = elongf_stem * c_struct + + cstatus = leaves_off + elseif ( any(prt_params%stress_decid(temp_cohort%pft) == [ihard_stress_decid,isemi_stress_decid])) then + ! Drought deciduous. For the default approach, elongation factor is either + ! zero (full abscission) or one (fully flushed), but this can also be a + ! fraction in other approaches. Here we assume that leaves are "on" (i.e. + ! either fully flushed or growing) if elongation factor is not 0 for the + ! initial conditions. + ! + ! For tissues other than leaves, the actual drop fraction is a combination + ! of the elongation factor (e) and the drop fraction (x), which will ensure + ! that the remaining tissue biomass will be exactly e when x=1, and exactly + ! the original biomass when x = 0. + elongf_leaf = csite%elong_factor(temp_cohort%pft) + elongf_fnrt = 1.0_r8 - (1.0_r8 - elongf_leaf ) * fnrt_drop_fraction + elongf_stem = 1.0_r8 - (1.0_r8 - elongf_leaf ) * stem_drop_fraction + + + c_leaf = elongf_leaf * c_leaf + c_fnrt = elongf_fnrt * c_fnrt + c_sapw = elongf_stem * c_sapw + c_struct = elongf_stem * c_struct + if (elongf_leaf > 0.0_r8) then + ! Assume leaves are growing even if they are not fully flushed. + cstatus = leaves_on + else + ! Leaves are off (abscissing). + cstatus = leaves_off + end if + end if prt_obj => null() call InitPRTObject(prt_obj) @@ -1151,7 +1187,8 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & call create_cohort(csite, cpatch, temp_cohort%pft, temp_cohort%n, temp_cohort%hite, & temp_cohort%coage, temp_cohort%dbh, & - prt_obj, cstatus, rstatus, temp_cohort%canopy_trim,temp_cohort%c_area, & + prt_obj, elongf_leaf, elongf_fnrt, elongf_stem, cstatus, rstatus, & + temp_cohort%canopy_trim,temp_cohort%c_area, & 1, csite%spread, bc_in) deallocate(temp_cohort) ! get rid of temporary cohort diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index d17759220a..231fa16494 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -82,13 +82,12 @@ module FatesRestartInterfaceMod integer :: ir_npatch_si integer :: ir_cd_status_si - integer :: ir_dd_status_si integer :: ir_nchill_days_si integer :: ir_ncold_days_si integer :: ir_cleafondate_si integer :: ir_cleafoffdate_si - integer :: ir_dleafondate_si - integer :: ir_dleafoffdate_si + integer :: ir_cndaysleafon_si + integer :: ir_cndaysleafoff_si integer :: ir_phenmodeldate_si integer :: ir_acc_ni_si integer :: ir_gdd_si @@ -156,6 +155,9 @@ module FatesRestartInterfaceMod integer :: ir_resp_tstep_co integer :: ir_pft_co integer :: ir_status_co + integer :: ir_efleaf_co + integer :: ir_effnrt_co + integer :: ir_efstem_co integer :: ir_isnew_co ! Litter @@ -187,7 +189,14 @@ module FatesRestartInterfaceMod integer :: ir_litter_moisture_pa_nfsc ! Site level - integer :: ir_watermem_siwm + integer :: ir_dd_status_sift + integer :: ir_dleafondate_sift + integer :: ir_dleafoffdate_sift + integer :: ir_dndaysleafon_sift + integer :: ir_dndaysleafoff_sift + integer :: ir_elong_factor_sift + integer :: ir_liqvolmem_siwmft + integer :: ir_smpmem_siwmft integer :: ir_vegtempmem_sitm integer :: ir_seed_bank_sift integer :: ir_spread_si @@ -606,10 +615,6 @@ subroutine define_restart_vars(this, initialize_variables) long_name='status flag for cold deciduous plants', units='unitless', flushval = flushinvalid, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_cd_status_si ) - call this%set_restart_var(vname='fates_drought_dec_status', vtype=site_int, & - long_name='status flag for drought deciduous plants', units='unitless', flushval = flushinvalid, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_dd_status_si ) - call this%set_restart_var(vname='fates_chilling_days', vtype=site_int, & long_name='chilling day counter', units='unitless', flushval = flushinvalid, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_nchill_days_si ) @@ -626,13 +631,13 @@ subroutine define_restart_vars(this, initialize_variables) long_name='the model day last cold leaf off', units='absolute integer day', flushval = flushinvalid, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_cleafoffdate_si ) - call this%set_restart_var(vname='fates_drought_leafondate', vtype=site_int, & - long_name='the model day of last drought based leaf-on', units='absolute integer day', flushval = flushinvalid, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_dleafondate_si ) + call this%set_restart_var(vname='fates_cold_ndaysleafon', vtype=site_int, & + long_name='number of days since leaf on (cold deciduous)', units='days', flushval = flushinvalid, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_cndaysleafon_si ) - call this%set_restart_var(vname='fates_drought_leafoffdate', vtype=site_int, & - long_name='the model day of last drought based leaf-off', units='absolute integer day', flushval = flushinvalid, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_dleafoffdate_si ) + call this%set_restart_var(vname='fates_cold_ndaysleafoff', vtype=site_int, & + long_name='number of days since leaf off (cold deciduous)', units='days', flushval = flushinvalid, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_cndaysleafoff_si ) call this%set_restart_var(vname='fates_phen_model_date', vtype=site_int, & long_name='integer model day used for phen timing', units='absolute integer day', flushval = flushinvalid, & @@ -871,6 +876,18 @@ subroutine define_restart_vars(this, initialize_variables) long_name='ed cohort - plant phenology status', units='unitless', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_status_co ) + call this%set_restart_var(vname='fates_efleaf_coh', vtype=cohort_r8, & + long_name='ed cohort - leaf elongation factor', units='unitless', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_efleaf_co ) + + call this%set_restart_var(vname='fates_effnrt_coh', vtype=cohort_r8, & + long_name='ed cohort - fine-root elongation factor', units='unitless', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_effnrt_co ) + + call this%set_restart_var(vname='fates_efstem_coh', vtype=cohort_r8, & + long_name='ed cohort - stem elongation factor', units='unitless', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_efstem_co ) + call this%set_restart_var(vname='fates_isnew', vtype=cohort_int, & long_name='ed cohort - binary flag specifying if a plant has experienced a full day cycle', & units='0/1', flushval = flushone, & @@ -1147,10 +1164,39 @@ subroutine define_restart_vars(this, initialize_variables) ! site x time level vars ! - call this%set_restart_var(vname='fates_water_memory', vtype=cohort_r8, & + call this%set_restart_var(vname='fates_drought_dec_status', vtype=cohort_int, & + long_name='status flag for drought deciduous plants', units='unitless', flushval = flushinvalid, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_dd_status_sift ) + + call this%set_restart_var(vname='fates_drought_leafondate', vtype=cohort_int, & + long_name='the day of year for drought based leaf-on', units='day of year', flushval = flushinvalid, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_dleafondate_sift ) + + call this%set_restart_var(vname='fates_drought_leafoffdate', vtype=cohort_int, & + long_name='the day of year for drought based leaf-off', units='day of year', flushval = flushinvalid, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_dleafoffdate_sift ) + + call this%set_restart_var(vname='fates_drought_ndaysleafon', vtype=cohort_int, & + long_name='number of days since leaf on (drought deciduous)', units='days', flushval = flushinvalid, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_dndaysleafon_sift ) + + call this%set_restart_var(vname='fates_drought_ndaysleafoff', vtype=cohort_int, & + long_name='number of days since leaf off (drought deciduous)', units='days', flushval = flushinvalid, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_dndaysleafoff_sift ) + + call this%set_restart_var(vname='fates_elong_factor', vtype=cohort_r8, & + long_name='leaf elongation factor (0 - completely abscissed; 1 - completely flushed)', units='unitless', flushval = flushinvalid, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_elong_factor_sift ) + + call this%set_restart_var(vname='fates_liqvol_memory', vtype=cohort_r8, & long_name='last 10 days of volumetric soil water, by site x day-index', & units='m3/m3', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_watermem_siwm ) + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_liqvolmem_siwmft ) + + call this%set_restart_var(vname='fates_smp_memory', vtype=cohort_r8, & + long_name='last 10 days of soil matric potential, by site x day-index', & + units='mm', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_smpmem_siwmft ) call this%set_restart_var(vname='fates_vegtemp_memory', vtype=cohort_r8, & long_name='last 10 days of 24-hour vegetation temperature, by site x day-index', & @@ -1738,13 +1784,12 @@ subroutine set_restart_vectors(this,nc,nsites,sites) associate( rio_npatch_si => this%rvars(ir_npatch_si)%int1d, & rio_cd_status_si => this%rvars(ir_cd_status_si)%int1d, & - rio_dd_status_si => this%rvars(ir_dd_status_si)%int1d, & rio_nchill_days_si => this%rvars(ir_nchill_days_si)%int1d, & rio_ncold_days_si => this%rvars(ir_ncold_days_si)%int1d, & rio_cleafondate_si => this%rvars(ir_cleafondate_si)%int1d, & rio_cleafoffdate_si => this%rvars(ir_cleafoffdate_si)%int1d, & - rio_dleafondate_si => this%rvars(ir_dleafondate_si)%int1d, & - rio_dleafoffdate_si => this%rvars(ir_dleafoffdate_si)%int1d, & + rio_cndaysleafon_si => this%rvars(ir_cndaysleafon_si)%int1d, & + rio_cndaysleafoff_si => this%rvars(ir_cndaysleafoff_si)%int1d, & rio_phenmodeldate_si => this%rvars(ir_phenmodeldate_si)%int1d, & rio_acc_ni_si => this%rvars(ir_acc_ni_si)%r81d, & rio_gdd_si => this%rvars(ir_gdd_si)%r81d, & @@ -1794,6 +1839,9 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_resp_tstep_co => this%rvars(ir_resp_tstep_co)%r81d, & rio_pft_co => this%rvars(ir_pft_co)%int1d, & rio_status_co => this%rvars(ir_status_co)%int1d, & + rio_efleaf_co => this%rvars(ir_efleaf_co)%r81d, & + rio_effnrt_co => this%rvars(ir_effnrt_co)%r81d, & + rio_efstem_co => this%rvars(ir_efstem_co)%r81d, & rio_isnew_co => this%rvars(ir_isnew_co)%int1d, & rio_gnd_alb_dif_pasb => this%rvars(ir_gnd_alb_dif_pasb)%r81d, & rio_gnd_alb_dir_pasb => this%rvars(ir_gnd_alb_dir_pasb)%r81d, & @@ -1804,7 +1852,14 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_agesinceanthrodist_pa => this%rvars(ir_agesinceanthrodist_pa)%r81d, & rio_nocomp_pft_label_pa => this%rvars(ir_nocomp_pft_label_pa)%int1d, & rio_area_pa => this%rvars(ir_area_pa)%r81d, & - rio_watermem_siwm => this%rvars(ir_watermem_siwm)%r81d, & + rio_dd_status_sift => this%rvars(ir_dd_status_sift)%int1d, & + rio_dleafondate_sift => this%rvars(ir_dleafondate_sift)%int1d, & + rio_dleafoffdate_sift => this%rvars(ir_dleafoffdate_sift)%int1d, & + rio_dndaysleafon_sift => this%rvars(ir_dndaysleafon_sift)%int1d, & + rio_dndaysleafoff_sift => this%rvars(ir_dndaysleafoff_sift)%int1d, & + rio_elong_factor_sift => this%rvars(ir_elong_factor_sift)%r81d, & + rio_liqvolmem_siwmft => this%rvars(ir_liqvolmem_siwmft)%r81d, & + rio_smpmem_siwmft => this%rvars(ir_smpmem_siwmft)%r81d, & rio_vegtempmem_sitm => this%rvars(ir_vegtempmem_sitm)%r81d, & rio_recrate_sift => this%rvars(ir_recrate_sift)%r81d, & rio_use_this_pft_sift => this%rvars(ir_use_this_pft_sift)%int1d, & @@ -2030,6 +2085,9 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_resp_tstep_co(io_idx_co) = ccohort%resp_tstep rio_pft_co(io_idx_co) = ccohort%pft rio_status_co(io_idx_co) = ccohort%status_coh + rio_efleaf_co(io_idx_co) = ccohort%efleaf_coh + rio_effnrt_co(io_idx_co) = ccohort%effnrt_coh + rio_efstem_co(io_idx_co) = ccohort%efstem_coh if ( ccohort%isnew ) then rio_isnew_co(io_idx_co) = new_cohort else @@ -2223,17 +2281,31 @@ subroutine set_restart_vectors(this,nc,nsites,sites) io_idx_si_pft = io_idx_si_pft + 1 end do - rio_cd_status_si(io_idx_si) = sites(s)%cstatus - rio_dd_status_si(io_idx_si) = sites(s)%dstatus - rio_nchill_days_si(io_idx_si) = sites(s)%nchilldays - rio_ncold_days_si(io_idx_si) = sites(s)%ncolddays - rio_cleafondate_si(io_idx_si) = sites(s)%cleafondate - rio_cleafoffdate_si(io_idx_si) = sites(s)%cleafoffdate - rio_phenmodeldate_si(io_idx_si)= sites(s)%phen_model_date - rio_dleafondate_si(io_idx_si) = sites(s)%dleafondate - rio_dleafoffdate_si(io_idx_si) = sites(s)%dleafoffdate + rio_cd_status_si(io_idx_si) = sites(s)%cstatus + rio_nchill_days_si(io_idx_si) = sites(s)%nchilldays + rio_ncold_days_si(io_idx_si) = sites(s)%ncolddays + rio_cleafondate_si(io_idx_si) = sites(s)%cleafondate + rio_cleafoffdate_si(io_idx_si) = sites(s)%cleafoffdate + rio_cndaysleafon_si(io_idx_si) = sites(s)%cndaysleafon + rio_cndaysleafoff_si(io_idx_si) = sites(s)%cndaysleafoff + rio_gdd_si(io_idx_si) = sites(s)%grow_deg_days + rio_phenmodeldate_si(io_idx_si) = sites(s)%phen_model_date + + ! Drought-deciduous phenology are now PFT dependent + io_idx_si_pft = io_idx_co_1st + do i_pft = 1,numpft + rio_dd_status_sift(io_idx_si_pft) = sites(s)%dstatus(i_pft) + rio_dleafondate_sift(io_idx_si_pft) = sites(s)%dleafondate(i_pft) + rio_dleafoffdate_sift(io_idx_si_pft) = sites(s)%dleafoffdate(i_pft) + rio_dndaysleafon_sift(io_idx_si_pft) = sites(s)%dndaysleafon(i_pft) + rio_dndaysleafoff_sift(io_idx_si_pft) = sites(s)%dndaysleafoff(i_pft) + rio_elong_factor_sift(io_idx_si_pft) = sites(s)%elong_factor(i_pft) + + io_idx_si_pft = io_idx_si_pft + 1 + end do + + rio_acc_ni_si(io_idx_si) = sites(s)%acc_NI - rio_gdd_si(io_idx_si) = sites(s)%grow_deg_days rio_snow_depth_si(io_idx_si) = sites(s)%snow_depth ! Accumulated trunk product @@ -2243,8 +2315,11 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_npatch_si(io_idx_si) = patchespersite do i = 1,numWaterMem ! numWaterMem currently 10 - rio_watermem_siwm( io_idx_si_wmem ) = sites(s)%water_memory(i) - io_idx_si_wmem = io_idx_si_wmem + 1 + do i_pft=1,numpft + rio_liqvolmem_siwmft( io_idx_si_wmem ) = sites(s)%liqvol_memory(i,i_pft) + rio_smpmem_siwmft( io_idx_si_wmem ) = sites(s)%smp_memory(i,i_pft) + io_idx_si_wmem = io_idx_si_wmem + 1 + end do end do do i = 1, num_vegtemp_mem @@ -2571,13 +2646,12 @@ subroutine get_restart_vectors(this, nc, nsites, sites) associate( rio_npatch_si => this%rvars(ir_npatch_si)%int1d, & rio_cd_status_si => this%rvars(ir_cd_status_si)%int1d, & - rio_dd_status_si => this%rvars(ir_dd_status_si)%int1d, & rio_nchill_days_si => this%rvars(ir_nchill_days_si)%int1d, & rio_ncold_days_si => this%rvars(ir_ncold_days_si)%int1d, & rio_cleafondate_si => this%rvars(ir_cleafondate_si)%int1d, & rio_cleafoffdate_si => this%rvars(ir_cleafoffdate_si)%int1d, & - rio_dleafondate_si => this%rvars(ir_dleafondate_si)%int1d, & - rio_dleafoffdate_si => this%rvars(ir_dleafoffdate_si)%int1d, & + rio_cndaysleafon_si => this%rvars(ir_cndaysleafon_si)%int1d, & + rio_cndaysleafoff_si => this%rvars(ir_cndaysleafoff_si)%int1d, & rio_phenmodeldate_si => this%rvars(ir_phenmodeldate_si)%int1d, & rio_acc_ni_si => this%rvars(ir_acc_ni_si)%r81d, & rio_gdd_si => this%rvars(ir_gdd_si)%r81d, & @@ -2627,6 +2701,9 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_resp_tstep_co => this%rvars(ir_resp_tstep_co)%r81d, & rio_pft_co => this%rvars(ir_pft_co)%int1d, & rio_status_co => this%rvars(ir_status_co)%int1d, & + rio_efleaf_co => this%rvars(ir_efleaf_co)%r81d, & + rio_effnrt_co => this%rvars(ir_effnrt_co)%r81d, & + rio_efstem_co => this%rvars(ir_efstem_co)%r81d, & rio_isnew_co => this%rvars(ir_isnew_co)%int1d, & rio_gnd_alb_dif_pasb => this%rvars(ir_gnd_alb_dif_pasb)%r81d, & rio_gnd_alb_dir_pasb => this%rvars(ir_gnd_alb_dir_pasb)%r81d, & @@ -2637,7 +2714,14 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_agesinceanthrodist_pa => this%rvars(ir_agesinceanthrodist_pa)%r81d, & rio_nocomp_pft_label_pa => this%rvars(ir_nocomp_pft_label_pa)%int1d, & rio_area_pa => this%rvars(ir_area_pa)%r81d, & - rio_watermem_siwm => this%rvars(ir_watermem_siwm)%r81d, & + rio_dd_status_sift => this%rvars(ir_dd_status_sift)%int1d, & + rio_dleafondate_sift => this%rvars(ir_dleafondate_sift)%int1d, & + rio_dleafoffdate_sift => this%rvars(ir_dleafoffdate_sift)%int1d, & + rio_dndaysleafon_sift => this%rvars(ir_dndaysleafon_sift)%int1d, & + rio_dndaysleafoff_sift => this%rvars(ir_dndaysleafoff_sift)%int1d, & + rio_elong_factor_sift => this%rvars(ir_elong_factor_sift)%r81d, & + rio_liqvolmem_siwmft => this%rvars(ir_liqvolmem_siwmft)%r81d, & + rio_smpmem_siwmft => this%rvars(ir_smpmem_siwmft)%r81d, & rio_vegtempmem_sitm => this%rvars(ir_vegtempmem_sitm)%r81d, & rio_recrate_sift => this%rvars(ir_recrate_sift)%r81d, & rio_use_this_pft_sift => this%rvars(ir_use_this_pft_sift)%int1d, & @@ -2842,6 +2926,9 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ccohort%resp_tstep = rio_resp_tstep_co(io_idx_co) ccohort%pft = rio_pft_co(io_idx_co) ccohort%status_coh = rio_status_co(io_idx_co) + ccohort%efleaf_coh = rio_efleaf_co(io_idx_co) + ccohort%effnrt_coh = rio_effnrt_co(io_idx_co) + ccohort%efstem_coh = rio_efstem_co(io_idx_co) ccohort%isnew = ( rio_isnew_co(io_idx_co) .eq. new_cohort ) call UpdateCohortBioPhysRates(ccohort) @@ -3016,8 +3103,11 @@ subroutine get_restart_vectors(this, nc, nsites, sites) end if do i = 1,numWaterMem - sites(s)%water_memory(i) = rio_watermem_siwm( io_idx_si_wmem ) - io_idx_si_wmem = io_idx_si_wmem + 1 + do i_pft=1,numpft + sites(s)%liqvol_memory(i,i_pft) = rio_liqvolmem_siwmft( io_idx_si_wmem ) + sites(s)%smp_memory(i,i_pft) = rio_smpmem_siwmft( io_idx_si_wmem ) + io_idx_si_wmem = io_idx_si_wmem + 1 + end do end do do i = 1, num_vegtemp_mem @@ -3093,16 +3183,28 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ! Site level phenology status flags sites(s)%cstatus = rio_cd_status_si(io_idx_si) - sites(s)%dstatus = rio_dd_status_si(io_idx_si) sites(s)%nchilldays = rio_nchill_days_si(io_idx_si) sites(s)%ncolddays = rio_ncold_days_si(io_idx_si) sites(s)%cleafondate = rio_cleafondate_si(io_idx_si) sites(s)%cleafoffdate = rio_cleafoffdate_si(io_idx_si) - sites(s)%dleafondate = rio_dleafondate_si(io_idx_si) - sites(s)%dleafoffdate = rio_dleafoffdate_si(io_idx_si) - sites(s)%acc_NI = rio_acc_ni_si(io_idx_si) + sites(s)%cndaysleafon = rio_cndaysleafon_si(io_idx_si) + sites(s)%cndaysleafoff = rio_cndaysleafoff_si(io_idx_si) sites(s)%grow_deg_days = rio_gdd_si(io_idx_si) sites(s)%phen_model_date= rio_phenmodeldate_si(io_idx_si) + + ! Fill drought-deciduous variables, which are now PFT variables. + io_idx_si_pft = io_idx_co_1st + do i_pft = 1,numpft + sites(s)%dstatus(i_pft) = rio_dd_status_sift(io_idx_si_pft) + sites(s)%dleafondate(i_pft) = rio_dleafondate_sift(io_idx_si_pft) + sites(s)%dleafoffdate(i_pft) = rio_dleafoffdate_sift(io_idx_si_pft) + sites(s)%dndaysleafon(i_pft) = rio_dndaysleafon_sift(io_idx_si_pft) + sites(s)%dndaysleafoff(i_pft) = rio_dndaysleafoff_sift(io_idx_si_pft) + sites(s)%elong_factor(i_pft) = rio_elong_factor_sift(io_idx_si_pft) + io_idx_si_pft = io_idx_si_pft + 1 + end do + + sites(s)%acc_NI = rio_acc_ni_si(io_idx_si) sites(s)%snow_depth = rio_snow_depth_si(io_idx_si) sites(s)%resources_management%trunk_product_site = rio_trunk_product_si(io_idx_si) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 569e6a1ab6..726060351f 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -432,12 +432,12 @@ variables: double fates_phen_evergreen(fates_pft) ; fates_phen_evergreen:units = "logical flag" ; fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; + double fates_phen_fnrt_drop_fraction(fates_pft) ; + fates_phen_fnrt_drop_fraction:units = "fraction" ; + fates_phen_fnrt_drop_fraction:long_name = "fraction of fine roots to drop during drought/cold" ; double fates_phen_flush_fraction(fates_pft) ; fates_phen_flush_fraction:units = "fraction" ; fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; - double fates_phen_fnrt_drop_frac(fates_pft) ; - fates_phen_fnrt_drop_frac:units = "fraction" ; - fates_phen_fnrt_drop_frac:long_name = "fraction of fine roots to drop during drought or cold" ; double fates_phen_season_decid(fates_pft) ; fates_phen_season_decid:units = "logical flag" ; fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; @@ -744,12 +744,9 @@ variables: double fates_phen_coldtemp ; fates_phen_coldtemp:units = "degrees C" ; fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; - double fates_phen_drought_model ; - fates_phen_drought_model:units = "unitless" ; - fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; double fates_phen_drought_threshold ; fates_phen_drought_threshold:units = "m3/m3 or mm" ; - fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold for semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; double fates_phen_gddthresh_a ; fates_phen_gddthresh_a:units = "none" ; fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; @@ -767,7 +764,7 @@ variables: fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; double fates_phen_moist_threshold ; fates_phen_moist_threshold:units = "m3/m3 or mm" ; - fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for drought semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; double fates_phen_ncolddayslim ; fates_phen_ncolddayslim:units = "days" ; fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; @@ -1248,7 +1245,7 @@ data: fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_phen_fnrt_drop_frac = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_phen_fnrt_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; @@ -1508,8 +1505,6 @@ data: fates_phen_coldtemp = 7.5 ; - fates_phen_drought_model = 0 ; - fates_phen_drought_threshold = 0.15 ; fates_phen_gddthresh_a = -68 ; diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 2a18d6d370..83fc5f8ed8 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -55,7 +55,7 @@ module PRTAllometricCNPMod use FatesConstantsMod , only : fates_unset_int use FatesConstantsMod , only : sec_per_day use PRTParametersMod , only : prt_params - use EDTypesMod , only : leaves_on,leaves_off + use EDTypesMod , only : leaves_on,leaves_off,leaves_pshed implicit none private @@ -145,16 +145,17 @@ module PRTAllometricCNPMod ! Input only Boundary Indices (These are public) ! ------------------------------------------------------------------------------------- - integer, public, parameter :: acnp_bc_in_id_pft = 1 ! Index for the PFT input BC - integer, public, parameter :: acnp_bc_in_id_ctrim = 2 ! Index for the canopy trim function - integer, public, parameter :: acnp_bc_in_id_lstat = 3 ! phenology status logical - integer, public, parameter :: acnp_bc_in_id_netdc = 4 ! Index for the net daily C input BC - integer, public, parameter :: acnp_bc_in_id_netdnh4 = 5 ! Index for the net daily NH4 input BC - integer, public, parameter :: acnp_bc_in_id_netdno3 = 6 ! Index for the net daily NO3 input BC - integer, public, parameter :: acnp_bc_in_id_netdp = 7 ! Index for the net daily P input BC - - ! 0=leaf off, 1=leaf on - integer, parameter :: num_bc_in = 7 + integer, public, parameter :: acnp_bc_in_id_pft = 1 ! Index for the PFT input BC + integer, public, parameter :: acnp_bc_in_id_ctrim = 2 ! Index for the canopy trim function + integer, public, parameter :: acnp_bc_in_id_lstat = 3 ! phenology status logical + integer, public, parameter :: acnp_bc_in_id_netdc = 4 ! Index for the net daily C input BC + integer, public, parameter :: acnp_bc_in_id_netdnh4 = 5 ! Index for the net daily NH4 input BC + integer, public, parameter :: acnp_bc_in_id_netdno3 = 6 ! Index for the net daily NO3 input BC + integer, public, parameter :: acnp_bc_in_id_netdp = 7 ! Index for the net daily P input BC + integer, public, parameter :: acnp_bc_in_id_efleaf = 8 ! Leaf elongation factor + integer, public, parameter :: acnp_bc_in_id_effnrt = 9 ! Fine-root "elongation factor" + integer, public, parameter :: acnp_bc_in_id_efstem = 10 ! Stem "elongation factor" + integer, parameter :: num_bc_in = 10 ! ------------------------------------------------------------------------------------- ! Output Boundary Indices (These are public) @@ -336,7 +337,10 @@ subroutine DailyPRTAllometricCNP(this) real(r8) :: n_gain ! Daily nitrogen uptake through fine-roots [kgN] real(r8) :: p_gain ! Daily phosphorus uptake through fine-roots [kgN] real(r8) :: canopy_trim ! The canopy trimming function [0-1] - + real(r8) :: elongf_leaf ! Leaf elongation factor [0-1] + real(r8) :: elongf_fnrt ! Fine-root "elongation factor" [0-1] + real(r8) :: elongf_stem ! Stem "elongation factor" [0-1] + ! Pointers to output bcs real(r8),pointer :: c_efflux ! Total plant efflux of carbon (kgC) real(r8),pointer :: n_efflux ! Total plant efflux of nitrogen (kgN) @@ -398,6 +402,9 @@ subroutine DailyPRTAllometricCNP(this) p_gain = this%bc_in(acnp_bc_in_id_netdp)%rval; p_gain0 = p_gain canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival + elongf_leaf = this%bc_in(acnp_bc_in_id_efleaf)%rval + elongf_fnrt = this%bc_in(acnp_bc_in_id_effnrt)%rval + elongf_stem = this%bc_in(acnp_bc_in_id_efstem)%rval ! Output only boundary conditions c_efflux => this%bc_out(acnp_bc_out_id_cefflux)%rval; c_efflux = 0._r8 @@ -443,6 +450,17 @@ subroutine DailyPRTAllometricCNP(this) target_c(repro_id) = 0._r8 target_dcdd(repro_id) = 0._r8 + ! Correct tissue targets based on the elongation factor + target_c(leaf_id) = elongf_leaf * target_c(leaf_id) + target_c(fnrt_id) = elongf_fnrt * target_c(fnrt_id) + target_c(sapw_id) = elongf_stem * target_c(sapw_id) + target_c(struct_id) = elongf_stem * target_c(struct_id) + ! MLO - Need to check whether or not the multiplication for the growth is correct or not. + target_dcdd(leaf_id) = elongf_leaf * target_dcdd(leaf_id) + target_dcdd(fnrt_id) = elongf_fnrt * target_dcdd(fnrt_id) + target_dcdd(sapw_id) = elongf_stem * target_dcdd(sapw_id) + target_dcdd(struct_id) = elongf_stem * target_dcdd(struct_id) + ! Initialize the the state, and keep a record of this state ! as we may actuall run the allocation process twice, and ! will need this state to both reset, and measure total @@ -649,6 +667,9 @@ subroutine CNPPrioritizedReplacement(this, & real(r8) :: target_n ! Target mass of N for a given organ [kg] real(r8) :: target_p ! Target mass of P for a given organ [kg] real(r8) :: c_gain0 + real(r8) :: elongf_leaf ! Leaf elongation factor + real(r8) :: elongf_fnrt ! Fine-root "elongation factor" + real(r8) :: elongf_stem ! Stem "elongation factor" integer :: priority_code ! Index for priority level of each organ real(r8) :: sum_c_demand ! Carbon demanded to bring tissues up to allometry (kg) real(r8) :: sum_n_deficit ! The nitrogen deficit of all pools for given priority level (kg) @@ -676,6 +697,9 @@ subroutine CNPPrioritizedReplacement(this, & c_gain0 = c_gain leaf_status = this%bc_in(acnp_bc_in_id_lstat)%ival + elongf_leaf = this%bc_in(acnp_bc_in_id_efleaf)%rval + elongf_fnrt = this%bc_in(acnp_bc_in_id_effnrt)%rval + elongf_stem = this%bc_in(acnp_bc_in_id_efstem)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval @@ -702,8 +726,9 @@ subroutine CNPPrioritizedReplacement(this, & ! Don't allow allocation to leaves if they are in an "off" status. ! Also, dont allocate to replace turnover if this is not evergreen ! (this prevents accidental re-flushing on the day they drop) - if( ((leaf_status.eq.leaves_off) .or. (prt_params%evergreen(ipft) .ne. itrue)) & - .and. (organ_list(ii).eq.leaf_organ)) cycle + if( ( any(leaf_status == [leaves_off,leaves_pshed]) .or. & + (prt_params%evergreen(ipft) /= itrue) ) & + .and. (organ_list(ii) == leaf_organ)) cycle ! 1 is the highest priority code possible if( priority_code == 1 ) then @@ -867,7 +892,8 @@ subroutine CNPPrioritizedReplacement(this, & ! Don't allow allocation to leaves if they are in an "off" status. ! (this prevents accidental re-flushing on the day they drop) - if((leaf_status.eq.leaves_off) .and. (organ_list(ii).eq.leaf_organ)) cycle + if( any(leaf_status == [leaves_off,leaves_pshed]) .and. & + (organ_list(ii) == leaf_organ) ) cycle ! 1 is the highest priority code possible if( priority_code == i_pri ) then @@ -1012,7 +1038,10 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & integer :: ipft real(r8) :: canopy_trim real(r8) :: leaf_status - + real(r8) :: elongf_leaf + real(r8) :: elongf_fnrt + real(r8) :: elongf_stem + integer :: i, ii ! organ index loops (masked and unmasked) integer :: istep ! outer step iteration loop real(r8) :: grow_c_from_c ! carbon transferred into tissues @@ -1090,6 +1119,9 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & integer, parameter :: p_limited = 3 leaf_status = this%bc_in(acnp_bc_in_id_lstat)%ival + elongf_leaf = this%bc_in(acnp_bc_in_id_efleaf)%rval + elongf_fnrt = this%bc_in(acnp_bc_in_id_effnrt)%rval + elongf_stem = this%bc_in(acnp_bc_in_id_efstem)%rval dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval @@ -1107,16 +1139,20 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & if( c_gain <= calloc_abs_error .or. & n_gain <= 0.1_r8*calloc_abs_error .or. & p_gain <= 0.02_r8*calloc_abs_error .or. & - leaf_status.eq.leaves_off ) then + any(leaf_status == [leaves_off,leaves_pshed]) ) then return end if - - + + intgr_params(:) = fates_unset_r8 intgr_params(acnp_bc_in_id_ctrim) = this%bc_in(acnp_bc_in_id_ctrim)%rval - intgr_params(acnp_bc_in_id_pft) = real(this%bc_in(acnp_bc_in_id_pft)%ival) - - + intgr_params(acnp_bc_in_id_pft) = real(this%bc_in(acnp_bc_in_id_pft)%ival,r8) + intgr_params(acnp_bc_in_id_lstat) = real(this%bc_in(acnp_bc_in_id_lstat)%ival,r8) + intgr_params(acnp_bc_in_id_efleaf) = this%bc_in(acnp_bc_in_id_efleaf)%rval + intgr_params(acnp_bc_in_id_effnrt) = this%bc_in(acnp_bc_in_id_effnrt)%rval + intgr_params(acnp_bc_in_id_efstem) = this%bc_in(acnp_bc_in_id_efstem)%rval + + state_mask(:) = .false. mask_organs(:) = fates_unset_int @@ -1360,6 +1396,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & end do call CheckIntegratedAllometries(state_array_out(dbh_id),ipft,canopy_trim, & + elongf_leaf, elongf_fnrt, elongf_stem, & leafc_tp1, state_array_out(fnrt_id), state_array_out(sapw_id), & state_array_out(store_id), state_array_out(struct_id), & state_mask(leaf_id), state_mask(fnrt_id), state_mask(sapw_id), & @@ -1436,6 +1473,9 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & write(fates_log(),*) 'totalC',totalC write(fates_log(),*) 'pft: ',ipft write(fates_log(),*) 'dbh: ',dbh + write(fates_log(),*) 'elongf_leaf: ',elongf_leaf + write(fates_log(),*) 'elongf_fnrt: ',elongf_fnrt + write(fates_log(),*) 'elongf_stem: ',elongf_stem write(fates_log(),*) 'dCleaf_dd: ',target_dcdd(leaf_id) write(fates_log(),*) 'dCfnrt_dd: ',target_dcdd(fnrt_id) write(fates_log(),*) 'dCstore_dd: ',target_dcdd(store_id) @@ -1456,7 +1496,13 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & call bbgw_allom(dbh_tp1,ipft,bgw_c_target_tp1) call bdead_allom(agw_c_target_tp1,bgw_c_target_tp1, sapw_c_target_tp1, ipft, struct_c_target_tp1) call bstore_allom(dbh_tp1,ipft,canopy_trim,store_c_target_tp1) - + + ! Correct the targets based on the elongation factors + leaf_c_target_tp1 = elongf_leaf * leaf_c_target_tp1 + fnrt_c_target_tp1 = elongf_fnrt * fnrt_c_target_tp1 + sapw_c_target_tp1 = elongf_stem * sapw_c_target_tp1 + struct_c_target_tp1 = elongf_stem * struct_c_target_tp1 + write(fates_log(),*) 'leaf_c: ',leafc_tp1, leaf_c_target_tp1,leafc_tp1-leaf_c_target_tp1 write(fates_log(),*) 'fnrt_c: ',fnrtc_tp1, fnrt_c_target_tp1,fnrtc_tp1- fnrt_c_target_tp1 write(fates_log(),*) 'sapw_c: ',sapwc_tp1, sapw_c_target_tp1 ,sapwc_tp1- sapw_c_target_tp1 @@ -1712,13 +1758,17 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe real(r8) :: leaf_c_target,fnrt_c_target real(r8) :: sapw_c_target,agw_c_target real(r8) :: bgw_c_target,struct_c_target + real(r8) :: elongf_leaf + real(r8) :: elongf_fnrt + real(r8) :: elongf_stem + - - - dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval ipft = this%bc_in(acnp_bc_in_id_pft)%ival + elongf_leaf = this%bc_in(acnp_bc_in_id_efleaf)%rval + elongf_fnrt = this%bc_in(acnp_bc_in_id_effnrt)%rval + elongf_stem = this%bc_in(acnp_bc_in_id_efstem)%rval i_cvar = prt_global%sp_organ_map(organ_id,carbon12_element) ! Storage of nutrients are assumed to have different compartments than @@ -1735,6 +1785,12 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe call bbgw_allom(dbh,ipft,bgw_c_target) call bdead_allom(agw_c_target,bgw_c_target, sapw_c_target, ipft, struct_c_target) + ! Correct the targets based on the elongation factors + leaf_c_target = elongf_leaf * leaf_c_target + fnrt_c_target = elongf_fnrt * fnrt_c_target + sapw_c_target = elongf_stem * sapw_c_target + struct_c_target = elongf_stem * struct_c_target + ! Target for storage is a fraction of the sum target of all ! non-reproductive organs @@ -2108,7 +2164,10 @@ function AllomCNPGrowthDeriv(l_state_array,l_state_mask,cbalance,intgr_params) r real(r8) :: total_dcdd_target ! target total (not reproductive) biomass derivative wrt d, (kgC/cm) real(r8) :: repro_fraction ! fraction of carbon balance directed towards reproduction (kgC/kgC) real(r8) :: total_dcostdd ! carbon cost for non-reproductive pools per unit increment of dbh - + real(r8) :: elongf_leaf ! Leaf elongation factor (0-1) + real(r8) :: elongf_fnrt ! Fine-root "elongation factor" (0-1) + real(r8) :: elongf_stem ! Stem "elongation factor" (0-1) + associate( dbh => l_state_array(dbh_id), & leaf_c => l_state_array(leaf_id), & @@ -2128,6 +2187,9 @@ function AllomCNPGrowthDeriv(l_state_array,l_state_mask,cbalance,intgr_params) r canopy_trim = intgr_params(acnp_bc_in_id_ctrim) ipft = int(intgr_params(acnp_bc_in_id_pft)) + elongf_leaf = intgr_params(acnp_bc_in_id_efleaf) + elongf_fnrt = intgr_params(acnp_bc_in_id_effnrt) + elongf_stem = intgr_params(acnp_bc_in_id_efstem) call bleaf(dbh,ipft,canopy_trim,leaf_c_target,leaf_dcdd_target) call bfineroot(dbh,ipft,canopy_trim,fnrt_c_target,fnrt_dcdd_target) @@ -2138,6 +2200,17 @@ function AllomCNPGrowthDeriv(l_state_array,l_state_mask,cbalance,intgr_params) r agw_dcdd_target, bgw_dcdd_target, sapw_dcdd_target, struct_dcdd_target) call bstore_allom(dbh,ipft,canopy_trim,store_c_target,store_dcdd_target) + ! Apply correction for partially deciduous plants. + leaf_c_target = elongf_leaf * leaf_c_target + fnrt_c_target = elongf_fnrt * fnrt_c_target + sapw_c_target = elongf_stem * sapw_c_target + struct_c_target = elongf_stem * struct_c_target + ! MLO - Need to double check that it is correct to apply factor to both stocks and growth + leaf_dcdd_target = elongf_leaf * leaf_dcdd_target + fnrt_dcdd_target = elongf_fnrt * fnrt_dcdd_target + sapw_dcdd_target = elongf_stem * sapw_dcdd_target + struct_dcdd_target = elongf_stem * struct_dcdd_target + if (mask_repro) then ! fraction of carbon going towards reproduction if (dbh <= prt_params%dbh_repro_threshold(ipft)) then @@ -2231,7 +2304,8 @@ end function AllomCNPGrowthDeriv subroutine TargetAllometryCheck(b0_leaf,b0_fnrt,b0_sapw,b0_store,b0_struct, & bleaf,bfnrt,bsapw,bstore,bstruct, & bt_leaf,bt_fnrt,bt_sapw,bt_store,bt_struct, & - carbon_balance,ipft,leaf_status, & + carbon_balance,elongf_leaf,elongf_fnrt,elongf_stem, & + ipft,leaf_status, & grow_leaf,grow_fnrt,grow_sapw,grow_store,grow_struct) ! Arguments @@ -2251,6 +2325,9 @@ subroutine TargetAllometryCheck(b0_leaf,b0_fnrt,b0_sapw,b0_store,b0_struct, & real(r8),intent(in) :: bt_store real(r8),intent(in) :: bt_struct real(r8),intent(in) :: carbon_balance !remaining carbon balance + real(r8),intent(in) :: elongf_leaf !elongation factors + real(r8),intent(in) :: elongf_fnrt + real(r8),intent(in) :: elongf_stem integer,intent(in) :: ipft !Plant functional type integer,intent(in) :: leaf_status !Phenology status logical,intent(out) :: grow_leaf !growth flag @@ -2308,6 +2385,9 @@ subroutine TargetAllometryCheck(b0_leaf,b0_fnrt,b0_sapw,b0_store,b0_struct, & write(fates_log(),fmt=fmth) '------' write(fates_log(),fmt=fmti) ' PFT = ',ipft write(fates_log(),fmt=fmti) ' leaf_status = ',leaf_status + write(fates_log(),fmt=fmte) ' elongf_leaf = ',elongf_leaf + write(fates_log(),fmt=fmte) ' elongf_fnrt = ',elongf_fnrt + write(fates_log(),fmt=fmte) ' elongf_stem = ',elongf_stem write(fates_log(),fmt=fmte) ' carbon_balance = ',carbon_balance write(fates_log(),fmt=fmte) ' calloc_abs_error = ',calloc_abs_error write(fates_log(),fmt=fmth) '' diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index b5db420b43..1b1dacaf6f 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -53,6 +53,9 @@ module PRTAllometricCarbonMod use EDTypesMod , only : leaves_on use EDTypesMod , only : leaves_off + use EDTypesMod , only : leaves_pshed + use EDTypesMod , only : ihard_stress_decid + use EDTypesMod , only : isemi_stress_decid implicit none private @@ -95,8 +98,11 @@ module PRTAllometricCarbonMod integer, public, parameter :: ac_bc_in_id_pft = 1 ! Index for the PFT input BC integer, public, parameter :: ac_bc_in_id_ctrim = 2 ! Index for the canopy trim function - integer, public, parameter :: ac_bc_in_id_lstat = 3 ! Leaf status (on or off) - integer, parameter :: num_bc_in = 3 ! Number of input boundary conditions + integer, public, parameter :: ac_bc_in_id_lstat = 3 ! Leaf status (on, off, partial abscission) + integer, public, parameter :: ac_bc_in_id_efleaf = 4 ! Elongation factor (leaves) + integer, public, parameter :: ac_bc_in_id_effnrt = 5 ! "Elongation factor" (fine roots) + integer, public, parameter :: ac_bc_in_id_efstem = 6 ! "Elongation factor" (stem) + integer, parameter :: num_bc_in = 6 ! Number of input boundary conditions ! THere are no purely output boundary conditions integer, parameter :: num_bc_out = 0 ! Number of purely output boundary condtions @@ -344,6 +350,9 @@ subroutine DailyPRTAllometricCarbon(this) real(r8) :: repro_c0 ! "" real(r8) :: struct_c0 ! "" + logical :: is_hydecid_dormant ! Flag to signal that the cohort is drought deciduous and dormant + logical :: is_deciduous ! Flag to signal this is a deciduous PFT + logical :: grow_struct logical :: grow_leaf ! Are leaves at allometric target and should be grown? logical :: grow_fnrt ! Are fine-roots at allometric target and should be grown? @@ -364,6 +373,10 @@ subroutine DailyPRTAllometricCarbon(this) integer :: leaf_status ! are leaves on (2) or off (1) real(r8) :: leaf_age_flux ! carbon mass flux between leaf age classification pools + real(r8) :: elongf_leaf ! Leaf elongation factor + real(r8) :: elongf_fnrt ! Fine-root "elongation factor" + real(r8) :: elongf_stem ! Stem "elongation factor" + ! Integegrator variables c_pool is "mostly" carbon variables, it also includes ! dbh... @@ -412,12 +425,23 @@ subroutine DailyPRTAllometricCarbon(this) canopy_trim = this%bc_in(ac_bc_in_id_ctrim)%rval ipft = this%bc_in(ac_bc_in_id_pft)%ival leaf_status = this%bc_in(ac_bc_in_id_lstat)%ival - - intgr_params(:) = un_initialized - intgr_params(ac_bc_in_id_ctrim) = this%bc_in(ac_bc_in_id_ctrim)%rval - intgr_params(ac_bc_in_id_pft) = real(this%bc_in(ac_bc_in_id_pft)%ival) - - + elongf_leaf = this%bc_in(ac_bc_in_id_efleaf)%rval + elongf_fnrt = this%bc_in(ac_bc_in_id_effnrt)%rval + elongf_stem = this%bc_in(ac_bc_in_id_efstem)%rval + + intgr_params(:) = un_initialized + intgr_params(ac_bc_in_id_ctrim) = this%bc_in(ac_bc_in_id_ctrim)%rval + intgr_params(ac_bc_in_id_pft) = real(this%bc_in(ac_bc_in_id_pft)%ival,r8) + intgr_params(ac_bc_in_id_lstat) = real(this%bc_in(ac_bc_in_id_lstat)%ival,r8) + intgr_params(ac_bc_in_id_efleaf) = this%bc_in(ac_bc_in_id_efleaf)%rval + intgr_params(ac_bc_in_id_effnrt) = this%bc_in(ac_bc_in_id_effnrt)%rval + intgr_params(ac_bc_in_id_efstem) = this%bc_in(ac_bc_in_id_efstem)%rval + + ! Set some logical flags to simplify "if" blocks + is_hydecid_dormant = any(prt_params%stress_decid(ipft) == [ihard_stress_decid,isemi_stress_decid] ) & + .and. any(leaf_status == [leaves_off,leaves_pshed] ) + is_deciduous = ( prt_params%stress_decid(ipft) == itrue ) .or. & + any(prt_params%stress_decid(ipft) == [ihard_stress_decid,isemi_stress_decid] ) nleafage = prt_global%state_descriptor(leaf_c_id)%num_pos ! Number of leaf age class @@ -461,12 +485,7 @@ subroutine DailyPRTAllometricCarbon(this) call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, ipft, target_struct_c) ! Target leaf biomass according to allometry and trimming - select case (leaf_status) - case (leaves_on) - call bleaf(dbh,ipft,canopy_trim,target_leaf_c) - case (leaves_off) - target_leaf_c = 0._r8 - end select + call bleaf(dbh,ipft,canopy_trim,target_leaf_c) ! Target fine-root biomass and deriv. according to allometry and trimming [kgC, kgC/cm] call bfineroot(dbh,ipft,canopy_trim,target_fnrt_c) @@ -475,21 +494,60 @@ subroutine DailyPRTAllometricCarbon(this) call bstore_allom(dbh,ipft,canopy_trim,target_store_c) + + ! ----------------------------------------------------------------------------------- + ! II 1/2. Update target biomass based on the leaf elongation factor and the abscission + ! fraction for each non-leaf tissue. Elongation factor is binary for + ! cold-deciduous and original drought-deciduous, and always one for + ! evergreens. In case the plant is shedding leaves, we impose that any + ! positive carbon balance necessarily goes to storage, even if this causes + ! storage to go above allometry. + ! ----------------------------------------------------------------------------------- + if (is_hydecid_dormant) then + target_leaf_c = 0.0_r8 + target_fnrt_c = 0.0_r8 + target_sapw_c = 0.0_r8 + target_struct_c = 0.0_r8 + target_store_c = target_store_c + max(0.0_r8,carbon_balance) + else + target_leaf_c = elongf_leaf * target_leaf_c + target_fnrt_c = elongf_fnrt * target_fnrt_c + target_sapw_c = elongf_stem * target_sapw_c + target_struct_c = elongf_stem * target_struct_c + end if + + + ! ----------------------------------------------------------------------------------- ! III. Prioritize some amount of carbon to replace leaf/root turnover - ! Make sure it isn't a negative payment, and either pay what is available + ! Make sure it isnt a negative payment, and either pay what is available ! or forcefully pay from storage. + ! MLO. Added a few conditions to decide what to do in case plants are deciduous. + ! Specifically, drought deciduous with leaves off should not replace fine + ! roots. They will be in negative carbon balance, and unlike cold deciduous, + ! the turnover rates will be high during the dry season (turnover is + ! temperature-dependent, but not moisture-dependent). Allocating carbon + ! to high-maintanence tissues will drain the storage with little benefit for + ! these plants. ! ----------------------------------------------------------------------------------- - - if( prt_params%evergreen(ipft) == itrue ) then + if ( is_hydecid_dormant ) then + ! Drought deciduous, dormant state. Set demands to both leaves and roots to zero. + leaf_c_demand = 0.0_r8 + fnrt_c_demand = 0.0_r8 + elseif ( is_deciduous ) then + ! Either cold deciduous plant, or drought deciduous with leaves on. Maintain roots. + leaf_c_demand = 0.0_r8 + fnrt_c_demand = max(0.0_r8, & + prt_params%leaf_stor_priority(ipft)*this%variables(fnrt_c_id)%turnover(icd)) + else + ! Evergreen PFT. Try to meet demands for both leaves and fine roots. + ! If this is not evergreen, this PFT isn't expected by FATES, and we assume + ! evergreen. leaf_c_demand = max(0.0_r8, & prt_params%leaf_stor_priority(ipft)*sum(this%variables(leaf_c_id)%turnover(:))) - else - leaf_c_demand = 0.0_r8 + fnrt_c_demand = max(0.0_r8, & + prt_params%leaf_stor_priority(ipft)*this%variables(fnrt_c_id)%turnover(icd)) end if - - fnrt_c_demand = max(0.0_r8, & - prt_params%leaf_stor_priority(ipft)*this%variables(fnrt_c_id)%turnover(icd)) total_c_demand = leaf_c_demand + fnrt_c_demand @@ -628,6 +686,25 @@ subroutine DailyPRTAllometricCarbon(this) end if end if + + + + ! ----------------------------------------------------------------------------------- + ! VII 1/2: If plant is semi-deciduous, there will be cases in which plant's carbon + ! balance is positive but plant is losing leaves, in which case the plant + ! should not invest in growth. Likewise, when plants are flushing but the + ! elongation factor is small, we may have need to "shed" excess storage by + ! placing it as carbon_balance again (not the neatest solution, but other- + ! wise the solver may fail to find a solution). + ! ----------------------------------------------------------------------------------- + select_stash_grow: select case (leaf_status) + case (leaves_off,leaves_pshed) + ! There is carbon balance, but plant is shedding leaves. We stash the carbon + ! to storage even if it makes their storage too large. + store_c_flux = carbon_balance + carbon_balance = carbon_balance - store_c_flux + store_c = store_c + store_c_flux + end select select_stash_grow ! ----------------------------------------------------------------------------------- ! VIII. If carbon is yet still available ... @@ -657,7 +734,8 @@ subroutine DailyPRTAllometricCarbon(this) sum(leaf_c(1:nleafage)), fnrt_c, sapw_c,store_c, struct_c, & target_leaf_c, target_fnrt_c, target_sapw_c, & target_store_c, target_struct_c, & - carbon_balance,ipft,leaf_status, & + carbon_balance,elongf_leaf,elongf_fnrt,elongf_stem, & + ipft,leaf_status, & grow_leaf, grow_fnrt, grow_sapw, grow_store, grow_struct) ! -------------------------------------------------------------------------------- @@ -691,16 +769,26 @@ subroutine DailyPRTAllometricCarbon(this) c_pool(repro_c_id) = repro_c c_pool(dbh_id) = dbh - ! Only grow leaves if we are in a "leaf-on" status - select case (leaf_status) - case (leaves_on) - c_mask(leaf_c_id) = grow_leaf - case default - c_mask(leaf_c_id) = .false. - end select - c_mask(fnrt_c_id) = grow_fnrt - c_mask(sapw_c_id) = grow_sapw - c_mask(struct_c_id) = grow_struct + ! Only grow leaves if we are in a "leaf-on" status. For drought-deciduous, we + ! interrupt growth for all tissues when in dormant mode. + if (is_hydecid_dormant) then + c_mask(leaf_c_id) = .false. + c_mask(fnrt_c_id) = .false. + c_mask(sapw_c_id) = .false. + c_mask(struct_c_id) = .false. + + else + select case (leaf_status) + case (leaves_on) + c_mask(leaf_c_id) = grow_leaf + case default + c_mask(leaf_c_id) = .false. + end select + c_mask(fnrt_c_id) = grow_fnrt + c_mask(sapw_c_id) = grow_sapw + c_mask(struct_c_id) = grow_struct + + end if c_mask(store_c_id) = grow_store c_mask(repro_c_id) = .true. ! Always calculate reproduction on growth c_mask(dbh_id) = .true. ! Always increment dbh on growth step @@ -737,6 +825,7 @@ subroutine DailyPRTAllometricCarbon(this) ! we remember the current step size as a good next guess. call CheckIntegratedAllometries(c_pool_out(dbh_id),ipft,canopy_trim, & + elongf_leaf, elongf_fnrt, elongf_stem, & c_pool_out(leaf_c_id), c_pool_out(fnrt_c_id), c_pool_out(sapw_c_id), & c_pool_out(store_c_id), c_pool_out(struct_c_id), & c_mask(leaf_c_id), c_mask(fnrt_c_id), c_mask(sapw_c_id), & @@ -900,7 +989,10 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) ! locals integer :: ipft ! PFT index - real(r8) :: canopy_trim ! Canopy trimming function (boundary condition [0-1] + real(r8) :: canopy_trim ! Canopy trimming function (boundary condition) [0-1] + real(r8) :: elongf_leaf ! Leaf elongation factor (boundary condition) [0-1] + real(r8) :: elongf_fnrt ! Fine-root "elongation factor" (boundary condition) [0-1] + real(r8) :: elongf_stem ! Stem "elongation factor" (boundary condition) [0-1] real(r8) :: ct_leaf ! target leaf biomass, dummy var (kgC) real(r8) :: ct_fnrt ! target fine-root biomass, dummy var (kgC) real(r8) :: ct_sap ! target sapwood biomass, dummy var (kgC) @@ -937,7 +1029,10 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) canopy_trim = intgr_params(ac_bc_in_id_ctrim) ipft = int(intgr_params(ac_bc_in_id_pft)) - + elongf_leaf = intgr_params(ac_bc_in_id_efleaf) + elongf_fnrt = intgr_params(ac_bc_in_id_effnrt) + elongf_stem = intgr_params(ac_bc_in_id_efstem) + call bleaf(dbh,ipft,canopy_trim,ct_leaf,ct_dleafdd) call bfineroot(dbh,ipft,canopy_trim,ct_fnrt,ct_dfnrtdd) @@ -948,7 +1043,18 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) call bdead_allom(ct_agw,ct_bgw, ct_sap, ipft, ct_dead, & ct_dagwdd, ct_dbgwdd, ct_dsapdd, ct_ddeaddd) call bstore_allom(dbh,ipft,canopy_trim,ct_store,ct_dstoredd) - + + ! Apply elongation factor correction to targets + ct_leaf = elongf_leaf * ct_leaf + ct_fnrt = elongf_fnrt * ct_fnrt + ct_sap = elongf_stem * ct_sap + ct_dead = elongf_stem * ct_dead + ! MLO - Need to double check that it is correct to multiply derivatives too. + ct_dleafdd = elongf_leaf * ct_dleafdd + ct_dfnrtdd = elongf_fnrt * ct_dfnrtdd + ct_dsapdd = elongf_stem * ct_dsapdd + ct_ddeaddd = elongf_stem * ct_ddeaddd + ! fraction of carbon going towards reproduction if (dbh <= prt_params%dbh_repro_threshold(ipft)) then ! cap on leaf biomass repro_fraction = prt_params%seed_alloc(ipft) @@ -1021,7 +1127,8 @@ end function AllomCGrowthDeriv subroutine TargetAllometryCheck(b0_leaf,b0_fnrt,b0_sapw,b0_store,b0_struct, & bleaf,bfnrt,bsapw,bstore,bstruct, & bt_leaf,bt_fnrt,bt_sapw,bt_store,bt_struct, & - carbon_balance,ipft,leaf_status, & + carbon_balance,elongf_leaf,elongf_fnrt,elongf_stem, & + ipft,leaf_status, & grow_leaf,grow_fnrt,grow_sapw,grow_store,grow_struct) ! Arguments @@ -1041,6 +1148,9 @@ subroutine TargetAllometryCheck(b0_leaf,b0_fnrt,b0_sapw,b0_store,b0_struct, & real(r8),intent(in) :: bt_store real(r8),intent(in) :: bt_struct real(r8),intent(in) :: carbon_balance !remaining carbon balance + real(r8),intent(in) :: elongf_leaf !elongation factors + real(r8),intent(in) :: elongf_fnrt + real(r8),intent(in) :: elongf_stem integer,intent(in) :: ipft !Plant functional type integer,intent(in) :: leaf_status !Phenology status logical,intent(out) :: grow_leaf !growth flag @@ -1098,6 +1208,9 @@ subroutine TargetAllometryCheck(b0_leaf,b0_fnrt,b0_sapw,b0_store,b0_struct, & write(fates_log(),fmt=fmth) '------' write(fates_log(),fmt=fmti) ' PFT = ',ipft write(fates_log(),fmt=fmti) ' leaf_status = ',leaf_status + write(fates_log(),fmt=fmte) ' elongf_leaf = ',elongf_leaf + write(fates_log(),fmt=fmte) ' elongf_fnrt = ',elongf_fnrt + write(fates_log(),fmt=fmte) ' elongf_stem = ',elongf_stem write(fates_log(),fmt=fmte) ' carbon_balance = ',carbon_balance write(fates_log(),fmt=fmte) ' calloc_abs_error = ',calloc_abs_error write(fates_log(),fmt=fmth) '' diff --git a/parteh/PRTLossFluxesMod.F90 b/parteh/PRTLossFluxesMod.F90 index 6f23924d48..e5859bb3cf 100644 --- a/parteh/PRTLossFluxesMod.F90 +++ b/parteh/PRTLossFluxesMod.F90 @@ -104,15 +104,22 @@ subroutine PRTPhenologyFlush(prt, ipft, organ_id, c_store_transfer_frac) real(r8) :: sp_demand ! nutrient demand for element - ! We currently only allow the flushing and drop of leaves. - ! If other organs should be desired (like seasonality of fine-roots) - ! those parameters and clauses need to be added - - !if(organ_id .ne. leaf_organ) then - if(organ_id .ne. leaf_organ .AND. prt_params%woody(ipft) == itrue) then - write(fates_log(),*) 'Deciduous drop and re-flushing only allowed in leaves' + ! We currently allow the flushing and drop of leaves and fine roots (always) and + ! sapwood and heartwood (non-woody PFTs only). + ! If other organs should be desired, those parameters and clauses need to be added + + if( (.not. any(organ_id == [leaf_organ,fnrt_organ])) .and. & + prt_params%woody(ipft) == itrue ) then + write(fates_log(),*) ' When PFT is woody, deciduous drop and re-flushing are' + write(fates_log(),*) ' only allowed in leaves and fine roots:' + write(fates_log(),*) '' + write(fates_log(),*) ' PFT: ',ipft + write(fates_log(),*) ' Woody PFT: ',prt_params%woody(ipft) == itrue + write(fates_log(),*) '' + write(fates_log(),*) '' write(fates_log(),*) ' leaf_organ: ',leaf_organ - write(fates_log(),*) ' organ: ',organ_id + write(fates_log(),*) ' fnrt_organ: ',fnrt_organ + write(fates_log(),*) ' Attempted organ: ',organ_id write(fates_log(),*) 'Exiting' call endrun(msg=errMsg(__FILE__, __LINE__)) end if @@ -419,15 +426,22 @@ subroutine PRTDeciduousTurnover(prt,ipft,organ_id,mass_fraction) real(r8),intent(in) :: mass_fraction ! The fraction of mass in this organ that should ! leave the indicated organ. - ! We currently only allow the flushing and drop of leaves. - ! If other organs should be desired (like seasonality of fine-roots) - ! those parameters and clauses need to be added - - !if(organ_id .ne. leaf_organ) then - if(organ_id .ne. leaf_organ .AND. prt_params%woody(ipft) == itrue) then - write(fates_log(),*) 'Deciduous drop and re-flushing only allowed in leaves' + ! We currently allow the flushing and drop of leaves and fine roots (always) and + ! sapwood and heartwood (non-woody PFTs only). + ! If other organs should be desired, those parameters and clauses need to be added + + if( (.not. any(organ_id == [leaf_organ,fnrt_organ])) .and. & + prt_params%woody(ipft) == itrue ) then + write(fates_log(),*) ' When PFT is woody, deciduous drop and re-flushing are' + write(fates_log(),*) ' only allowed in leaves and fine roots:' + write(fates_log(),*) '' + write(fates_log(),*) ' PFT: ',ipft + write(fates_log(),*) ' Woody PFT: ',prt_params%woody(ipft) == itrue + write(fates_log(),*) '' + write(fates_log(),*) '' write(fates_log(),*) ' leaf_organ: ',leaf_organ - write(fates_log(),*) ' organ: ',organ_id + write(fates_log(),*) ' fnrt_organ: ',fnrt_organ + write(fates_log(),*) ' Attempted organ: ',organ_id write(fates_log(),*) 'Exiting' call endrun(msg=errMsg(__FILE__, __LINE__)) end if diff --git a/parteh/PRTParametersMod.F90 b/parteh/PRTParametersMod.F90 index 23e867a734..cc23e1b2b0 100644 --- a/parteh/PRTParametersMod.F90 +++ b/parteh/PRTParametersMod.F90 @@ -13,10 +13,22 @@ module PRTParametersMod ! The following three PFT classes ! are mutually exclusive - integer, allocatable :: stress_decid(:) ! Is the plant stress deciduous? (1=yes, 0=no) + ! MLO: perhaps we should replace these three parameters with a single + ! parameter (phenology(:)) that is assigned different indices? + integer, allocatable :: stress_decid(:) ! Is the plant stress deciduous? + ! 0 - No + ! 1 - Drought "hard" deciduous (i.e., PFT + ! sheds leaves all at once when stressed) + ! 2 - Drought semi-deciduous (i.e., PFT + ! sheds leaves gradually as drought + ! conditions deteriorate) integer, allocatable :: season_decid(:) ! Is the plant seasonally deciduous (1=yes, 0=no) integer, allocatable :: evergreen(:) ! Is the plant an evergreen (1=yes, 0=no) + ! Drop fraction for tissues other than leaves (PFT-dependent) + real(r8), allocatable :: phen_fnrt_drop_fraction(:) ! Abscission fraction of fine roots + real(r8), allocatable :: phen_stem_drop_fraction(:) ! Abscission fraction of stems + ! Growth and Turnover Parameters real(r8), allocatable :: senleaf_long_fdrought(:) ! Multiplication factor for leaf longevity of senescent diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index 66033a3194..f16475708b 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -32,6 +32,7 @@ module PRTInitParamsFatesMod use FatesAllometryMod, only : set_root_fraction use PRTGenericMod, only : StorageNutrientTarget use EDTypesMod, only : init_recruit_trim + use EDTypesMod, only : ihard_stress_decid, isemi_stress_decid ! ! !PUBLIC TYPES: @@ -811,6 +812,7 @@ subroutine FatesReportPFTParams(is_master) logical, intent(in) :: is_master ! Only log if this is the master proc logical, parameter :: debug_report = .false. + character(len=15),parameter :: fmti = '(a,100(I12,1X))' character(len=32),parameter :: fmt0 = '(a,100(F12.4,1X))' integer :: npft,ipft @@ -827,9 +829,9 @@ subroutine FatesReportPFTParams(is_master) end if write(fates_log(),*) '----------- FATES PARTEH Parameters -----------------' - write(fates_log(),fmt0) 'stress_decid = ',prt_params%stress_decid - write(fates_log(),fmt0) 'season_decid = ',prt_params%season_decid - write(fates_log(),fmt0) 'evergreen = ',prt_params%evergreen + write(fates_log(),fmti) 'stress_decid = ',prt_params%stress_decid + write(fates_log(),fmti) 'season_decid = ',prt_params%season_decid + write(fates_log(),fmti) 'evergreen = ',prt_params%evergreen write(fates_log(),fmt0) 'wood_density = ',prt_params%wood_density write(fates_log(),fmt0) 'dbh max height = ',prt_params%allom_dbh_maxheight write(fates_log(),fmt0) 'dbh mature = ',prt_params%dbh_repro_threshold @@ -886,7 +888,7 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'fnrt_prof_mode = ',prt_params%fnrt_prof_mode write(fates_log(),fmt0) 'turnover_nitr_retrans = ',prt_params%turnover_nitr_retrans write(fates_log(),fmt0) 'turnover_phos_retrans = ',prt_params%turnover_phos_retrans - write(fates_log(),fmt0) 'organ_id = ',prt_params%organ_id + write(fates_log(),fmti) 'organ_id = ',prt_params%organ_id write(fates_log(),fmt0) 'nitr_store_ratio = ',prt_params%nitr_store_ratio write(fates_log(),fmt0) 'phos_store_ratio = ',prt_params%phos_store_ratio write(fates_log(),*) '-------------------------------------------------' @@ -954,12 +956,15 @@ subroutine PRTCheckParams(is_master) character(len=32),parameter :: fmt0 = '(a,100(F12.4,1X))' - integer :: npft ! number of PFTs - integer :: ipft ! pft index - integer :: nleafage ! size of the leaf age class array - integer :: iage ! leaf age class index - integer :: norgans ! size of the plant organ dimension - integer :: i, io ! generic loop index and organ loop index + integer :: npft ! number of PFTs + integer :: ipft ! pft index + integer :: nleafage ! size of the leaf age class array + integer :: iage ! leaf age class index + integer :: norgans ! size of the plant organ dimension + integer :: i, io ! generic loop index and organ loop index + logical :: is_evergreen ! Is the PFT evergreen + logical :: is_season_decid ! Is the PFT cold-deciduous? + logical :: is_stress_decid ! Is the PFT drought-deciduous? npft = size(prt_params%evergreen,1) @@ -1011,14 +1016,22 @@ subroutine PRTCheckParams(is_master) pftloop: do ipft = 1,npft ! Check to see if evergreen, deciduous flags are mutually exclusive + ! MLO. Changed the check because season_decid can be 1 or 2. + ! By the way, if these are mutually exclusive, shouldn't we define a + ! single prt_params%leaf_phenology and a list of codes for the different + ! types (i.e., ievergreen, iseason_decid, istress_hard, istress_semi, etc.)? ! ---------------------------------------------------------------------------------- + is_evergreen = prt_params%evergreen(ipft) == itrue + is_season_decid = prt_params%season_decid(ipft) == itrue + is_stress_decid = any(prt_params%stress_decid(ipft) == [ihard_stress_decid,isemi_stress_decid]) + + if ( ( is_evergreen .and. is_season_decid ) .or. & + ( is_evergreen .and. is_stress_decid ) .or. & + ( is_season_decid .and. is_stress_decid ) ) then - if ( int(prt_params%evergreen(ipft) + & - prt_params%season_decid(ipft) + & - prt_params%stress_decid(ipft)) .ne. 1 ) then - write(fates_log(),*) 'PFT # ',ipft,' must be defined as having one of three' - write(fates_log(),*) 'phenology habits, ie == 1' + write(fates_log(),*) 'phenology habits, ie, only one of the flags below should' + write(fates_log(),*) 'be different than ',ifalse write(fates_log(),*) 'stress_decid: ',prt_params%stress_decid(ipft) write(fates_log(),*) 'season_decid: ',prt_params%season_decid(ipft) write(fates_log(),*) 'evergreen: ',prt_params%evergreen(ipft) From 40cd06be22660b19fd32d298b9f8f7a336bf3036 Mon Sep 17 00:00:00 2001 From: Marcos Longo Date: Sat, 3 Dec 2022 18:16:54 -0800 Subject: [PATCH 461/852] New option allometry for storage. Option 2 now scales storage with the untrimmed leaf biomass, which allows higher storage when canopy is trimmed. --- biogeochem/FatesAllometryMod.F90 | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index 1a2b16283e..39fe02cfee 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -1085,6 +1085,8 @@ subroutine bstore_allom(d,ipft,crowndamage, canopy_trim,bstore,dbstoredd) real(r8) :: bl ! Allometric target leaf biomass real(r8) :: dbldd ! Allometric target change in leaf biomass per cm + real(r8) :: blmax ! Allometric target leaf biomass (UNTRIMMED) + real(r8) :: dblmaxdd ! Allometric target change in leaf biomass per cm (UNTRIMMED) ! TODO: allom_stmode needs to be added to the parameter file @@ -1098,7 +1100,12 @@ subroutine bstore_allom(d,ipft,crowndamage, canopy_trim,bstore,dbstoredd) call bleaf(d,ipft, crowndamage, canopy_trim, bl, dbldd) call bstore_blcushion(d,bl,dbldd,cushion,ipft,bstore,dbstoredd) - + + case(2) ! Storage is constant proportionality of untrimmed maximum leaf + ! biomass (ie cushion * bleaf) + call blmax_allom(d,ipft,blmax,dblmaxdd) + call bstore_blcushion(d,blmax,dblmaxdd,cushion,ipft,bstore,dbstoredd) + case DEFAULT write(fates_log(),*) 'An undefined fine storage allometry was specified: ', & allom_stmode From f785cf0a2c95882372c3659f7244c0a92e6780fc Mon Sep 17 00:00:00 2001 From: Marcos Longo Date: Mon, 5 Dec 2022 19:48:56 -0800 Subject: [PATCH 462/852] Fix units for soil matric potential in the output. --- main/FatesHistoryInterfaceMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 5abcd3b051..0ea5aa0f35 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -75,7 +75,7 @@ module FatesHistoryInterfaceMod use FatesConstantsMod , only : m2_per_ha use FatesConstantsMod , only : ha_per_m2 use FatesConstantsMod , only : m_per_cm - use FatesConstantsMod , only : mm_per_m + use FatesConstantsMod , only : m_per_mm use FatesConstantsMod , only : sec_per_min use FatesConstantsMod , only : umol_per_mol,mol_per_umol use FatesConstantsMod , only : pa_per_mpa @@ -2542,7 +2542,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) ! Mean soil matric potential (Pa) used for drought phenology hio_meansmp_si_pft(io_si,i_pft) = & sum(sites(s)%smp_memory(1:numWaterMem,i_pft))/real(numWaterMem,r8) & - * dens_fresh_liquid_water * grav_earth * mm_per_m + * dens_fresh_liquid_water * grav_earth * m_per_mm end if end do From 9e48e86a11ad3de9fb34f05e4e2923f6c02d38d9 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 5 Dec 2022 23:19:25 -0800 Subject: [PATCH 463/852] refactor dispersal check function and add initialization --- main/FatesDispersalMod.F90 | 47 ++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index b0d0fe4742..b095efbe03 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -38,7 +38,7 @@ module FatesDispersalMod real(r8), allocatable :: outgoing_local(:,:) ! local gridcell array of outgoing seeds, gridcell x pft real(r8), allocatable :: outgoing_global(:,:) ! global accumulation array of outgoing seeds, gridcell x pft real(r8), allocatable :: incoming_global(:,:) ! - + contains procedure :: init @@ -49,9 +49,9 @@ module FatesDispersalMod public :: ProbabilityDensity public :: IsItDispersalTime - - integer :: prev_dispersal_date = 0 + integer :: dispersal_date = 0 ! Last date in which there was a dispersal + character(len=*), parameter, private :: sourcefile = __FILE__ contains @@ -84,6 +84,10 @@ subroutine init(this, numprocs, numpft) this%outgoing_global(:,:) = 0._r8 this%incoming_global(:,:) = 0._r8 + ! Set the dispersal date to the current date. Dispersal will start at the end of + ! current initial date + dispersal_date = GetDispersalDate() + end subroutine init ! ==================================================================================== @@ -186,6 +190,21 @@ logical function IsItDispersalTime() ! Determine if seeds should be dispersed across gridcells. This eventually could be ! driven by plant reproduction dynamics. For now this is based strictly on a calendar + + ! The default return value is false + IsItDispersalTime = .false. + + ! Determine if it is a new day, month, or year. If true update the previous date to the current value + if (GetDispersalDate() .ne. dispersal_date) then + IsItDispersalTime = .true. + dispersal_date = GetDispersalDate() + end if + + end function IsItDispersalTime + + ! ==================================================================================== + + integer function GetDispersalDate() use FatesInterfaceMod, only : hlm_current_day, & hlm_current_month, & @@ -196,32 +215,20 @@ logical function IsItDispersalTime() fates_dispersal_cadence_monthly, & fates_dispersal_cadence_yearly - ! LOCAL - integer :: check_date = 0 - - ! initialize the return value as false - IsItDispersalTime = .false. - ! Select the date type to check against based on the dispersal candence select case(fates_dispersal_cadence) case (fates_dispersal_cadence_daily) - check_date = hlm_current_day + GetDispersalDate = hlm_current_day case (fates_dispersal_cadence_monthly) - check_date = hlm_current_month + GetDispersalDate = hlm_current_month case (fates_dispersal_cadence_yearly) - check_date = hlm_current_year + GetDispersalDate = hlm_current_year case default write(fates_log(),*) 'ERROR: An undefined dispersal cadence was specified: ', fates_dispersal_cadence call endrun(msg=errMsg(sourcefile, __LINE__)) end select - - ! Determine if it is a new day, month, or year. If true update the previous date to the current value - if (check_date .ne. prev_dispersal_date) then - IsItDispersalTime = .true. - prev_dispersal_date = check_date - end if - - end function IsItDispersalTime + + end function GetDispersalDate end module FatesDispersalMod From ca7723a2ef86a2197f939c576e6883434a1fbf2c Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 6 Dec 2022 10:29:28 -0800 Subject: [PATCH 464/852] correct logic for setting new date --- main/FatesDispersalMod.F90 | 17 +++++++++++++++-- main/FatesInterfaceMod.F90 | 4 ++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index 1c88081393..b8db04ff7c 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -189,18 +189,31 @@ end function PD_logsech ! ==================================================================================== - logical function IsItDispersalTime() + logical function IsItDispersalTime(setflag) ! Determine if seeds should be dispersed across gridcells. This eventually could be ! driven by plant reproduction dynamics. For now this is based strictly on a calendar + ! Arguments + logical, optional :: setflag ! Set the dispersal date as the current date + + ! Local + logical :: setdateflag + ! The default return value is false IsItDispersalTime = .false. + ! Check if optional flag is provided. + if (present(setflag)) then + setdateflag = setflag + else + setdateflag = .false. + end if + ! Determine if it is a new day, month, or year. If true update the previous date to the current value if (GetDispersalDate() .ne. dispersal_date) then IsItDispersalTime = .true. - dispersal_date = GetDispersalDate() + if (setdateflag) dispersal_date = GetDispersalDate() end if end function IsItDispersalTime diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 952b87228b..12751381d3 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -897,8 +897,8 @@ subroutine SetFatesGlobalElements(use_fates) ! Set the fates dispersal cadence if seed dispersal parameters are set. ! This could be a parameter value setting as well. Currently hardcoded if(any(EDPftvarcon_inst%seed_dispersal_param_A .lt. fates_check_param_set)) then - ! fates_dispersal_cadence = fates_dispersal_cadence_daily - fates_dispersal_cadence = fates_dispersal_cadence_monthly + fates_dispersal_cadence = fates_dispersal_cadence_daily + !fates_dispersal_cadence = fates_dispersal_cadence_monthly ! fates_dispersal_cadence = fates_dispersal_cadence_yearly else fates_dispersal_cadence = 0 From b092904f81ccd54bd052325a1e22dada05ffefbc Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 6 Dec 2022 14:50:30 -0800 Subject: [PATCH 465/852] update isitdispersal function to avoid time lag of dispersal --- main/FatesDispersalMod.F90 | 68 ++++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 21 deletions(-) diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index b8db04ff7c..6ed52b072b 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -50,7 +50,8 @@ module FatesDispersalMod public :: ProbabilityDensity public :: IsItDispersalTime - integer :: dispersal_date = 0 ! Last date in which there was a dispersal + integer :: dispersal_date = 0 ! Last candence date in which there was a dispersal + logical :: dispersal_flag = .false. ! Have seeds been disperesed globally character(len=*), parameter, private :: sourcefile = __FILE__ @@ -86,7 +87,7 @@ subroutine init(this, numprocs, numpft) ! Set the dispersal date to the current date. Dispersal will start at the end of ! current initial date - dispersal_date = GetDispersalDate() + dispersal_date = GetCandenceDate() end subroutine init @@ -189,38 +190,63 @@ end function PD_logsech ! ==================================================================================== - logical function IsItDispersalTime(setflag) + logical function IsItDispersalTime(setdispersedflag) ! Determine if seeds should be dispersed across gridcells. This eventually could be - ! driven by plant reproduction dynamics. For now this is based strictly on a calendar + ! driven by plant reproduction dynamics. For now this is based strictly on a calendar. + ! This function attempts to wrap up all the logic for the dispersal code, which is + ! takes place at multiple points in the code, into a single function. + ! The logic for the function is as follows: + ! - If new date and seeds not globally dispersed, pass local seed to global bufffer + ! (see wrap_update_hlmfates_dyn) + ! - If new date and seeds not globally dispersed, globally disperse seeds (call WrapSeedGlobal) and + ! set dispersed flag to true. Note that since this must happen outside of threaded region, + ! this comes after fates dynamic_driv procedure. + ! - If new date or not and seeds have been globally dispersed, call wrap_seed_disperse + ! to pass dispersed seeds to fates. Set dispersed flag to false. Given that this must + ! happen after WrapSeedGlobal, but can be threaded this takes place at the top of the + ! dynamics_driv call. ! Arguments - logical, optional :: setflag ! Set the dispersal date as the current date + logical, optional :: setdispersedflag ! Has the global dispersal been completed? ! Local - logical :: setdateflag - + logical :: setflag + ! The default return value is false IsItDispersalTime = .false. - - ! Check if optional flag is provided. - if (present(setflag)) then - setdateflag = setflag + + ! Check if set dispersal flag is provided. This should be provided during a check + ! when the flag should be set to true after the global dispersal + if (present(setdispersedflag)) then + setflag = setdispersedflag else - setdateflag = .false. + setflag = .false. end if - - ! Determine if it is a new day, month, or year. If true update the previous date to the current value - if (GetDispersalDate() .ne. dispersal_date) then + + ! If dispersal flag is true, regardless of the date, pass dispersed seeds to fates and reset flag + ! If dispersal flag is false, check if it is time to disperse + ! If it's time to disperse, check to see if the dispersal flag should be set true and last + ! dispersal date updated + if (dispersal_flag) then IsItDispersalTime = .true. - if (setdateflag) dispersal_date = GetDispersalDate() + dispersal_flag = .false. + else + if (GetCandenceDate() .ne. dispersal_date) then + IsItDispersalTime = .true. + if (setflag) then + dispersal_flag = .true. + dispersal_date = GetCandenceDate() + end if + end if + end if end function IsItDispersalTime ! ==================================================================================== - integer function GetDispersalDate() + integer function GetCandenceDate() use FatesInterfaceTypesMod, only : hlm_current_day, & hlm_current_month, & @@ -234,17 +260,17 @@ integer function GetDispersalDate() ! Select the date type to check against based on the dispersal candence select case(fates_dispersal_cadence) case (fates_dispersal_cadence_daily) - GetDispersalDate = hlm_current_day + GetCandenceDate = hlm_current_day case (fates_dispersal_cadence_monthly) - GetDispersalDate = hlm_current_month + GetCandenceDate = hlm_current_month case (fates_dispersal_cadence_yearly) - GetDispersalDate = hlm_current_year + GetCandenceDate = hlm_current_year case default write(fates_log(),*) 'ERROR: An undefined dispersal cadence was specified: ', fates_dispersal_cadence call endrun(msg=errMsg(sourcefile, __LINE__)) end select - end function GetDispersalDate + end function GetCandenceDate end module FatesDispersalMod From 8b8b7dca65acddf920087c94fee1207e3b54115a Mon Sep 17 00:00:00 2001 From: Marcos Longo Date: Tue, 6 Dec 2022 15:58:22 -0800 Subject: [PATCH 466/852] Minor update to carbon allocation for deciduous PFTs. For now, semi-deciduous trees should not attempt to grow or reproduce if the conditions are deteriorating (in reality many drought deciduous trees do bloom during the dry season, but this would require seed phenology). --- parteh/PRTAllometricCarbonMod.F90 | 64 ++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 4a69ff46ba..e170d757e1 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -414,10 +414,25 @@ subroutine DailyPRTAllometricCarbon(this,phase) real(r8) :: intgr_params(num_bc_in) - ipft = this%bc_in(ac_bc_in_id_pft)%ival - + ! ----------------------------------------------------------------------------------- + ! 0. + ! Copy the boundary conditions into readable local variables. + ! We don't use pointers for bc's that ar "in" only, only "in-out" and "out" + ! ----------------------------------------------------------------------------------- + ipft = this%bc_in(ac_bc_in_id_pft)%ival + canopy_trim = this%bc_in(ac_bc_in_id_ctrim)%rval + leaf_status = this%bc_in(ac_bc_in_id_lstat)%ival + crowndamage = this%bc_in(ac_bc_in_id_cdamage)%ival + elongf_leaf = this%bc_in(ac_bc_in_id_efleaf)%rval + elongf_fnrt = this%bc_in(ac_bc_in_id_effnrt)%rval + elongf_stem = this%bc_in(ac_bc_in_id_efstem)%rval + + + ! ----------------------------------------------------------------------------------- + ! 1/2. Use pointers and associations to create simpler names inside the sub-routine. + ! MLO. Any reason to use associate for some variables and pointers for others? + ! ----------------------------------------------------------------------------------- associate( & - leaf_c => this%variables(leaf_c_id)%val, & fnrt_c => this%variables(fnrt_c_id)%val(icd), & sapw_c => this%variables(sapw_c_id)%val(icd), & @@ -426,26 +441,14 @@ subroutine DailyPRTAllometricCarbon(this,phase) struct_c => this%variables(struct_c_id)%val(icd), & l2fr => prt_params%allom_l2fr(ipft) ) + dbh => this%bc_inout(ac_bc_inout_id_dbh)%rval + carbon_balance => this%bc_inout(ac_bc_inout_id_netdc)%rval - ! ----------------------------------------------------------------------------------- - ! 0. - ! Copy the boundary conditions into readable local variables. - ! We don't use pointers for bc's that ar "in" only, only "in-out" and "out" - ! ----------------------------------------------------------------------------------- - dbh => this%bc_inout(ac_bc_inout_id_dbh)%rval - carbon_balance => this%bc_inout(ac_bc_inout_id_netdc)%rval - - canopy_trim = this%bc_in(ac_bc_in_id_ctrim)%rval - leaf_status = this%bc_in(ac_bc_in_id_lstat)%ival - crowndamage = this%bc_in(ac_bc_in_id_cdamage)%ival - elongf_leaf = this%bc_in(ac_bc_in_id_efleaf)%rval - elongf_fnrt = this%bc_in(ac_bc_in_id_effnrt)%rval - elongf_stem = this%bc_in(ac_bc_in_id_efstem)%rval - - - ! Set some logical flags to simplify "if" blocks + ! ----------------------------------------------------------------------------------- + ! 3/4. Set some logical flags to simplify "if" blocks + ! ----------------------------------------------------------------------------------- is_hydecid_dormant = ( prt_params%stress_decid(ipft) == 1 ) .and. & any(leaf_status == [leaves_off,leaves_pshed] ) is_deciduous = ( prt_params%stress_decid(ipft) == 1 ) .or. & @@ -453,6 +456,7 @@ subroutine DailyPRTAllometricCarbon(this,phase) nleafage = prt_global%state_descriptor(leaf_c_id)%num_pos ! Number of leaf age class + ! ----------------------------------------------------------------------------------- ! I. Remember the values for the state variables at the beginning of this ! routines. We will then use that to determine their net allocation and reactive @@ -525,6 +529,7 @@ subroutine DailyPRTAllometricCarbon(this,phase) ! ----------------------------------------------------------------------------------- + ! ----------------------------------------------------------------------------------- ! III. Prioritize some amount of carbon to replace leaf/root turnover ! Make sure it isn't a negative payment, and either pay what is available ! or forcefully pay from storage. @@ -696,6 +701,21 @@ subroutine DailyPRTAllometricCarbon(this,phase) end if case (3) + ! ----------------------------------------------------------------------------------- + ! VII 1/2: If plant is semi-deciduous, there will be cases in which plant's carbon + ! balance is positive but plant is losing leaves, in which case the plant + ! should not invest in growth. + ! ----------------------------------------------------------------------------------- + select_stash_grow: select case (leaf_status) + case (leaves_off,leaves_pshed) + ! There is carbon balance, but plant is shedding leaves. We stash the carbon + ! to storage even if it makes their storage too large. + store_c_flux = carbon_balance + carbon_balance = carbon_balance - store_c_flux + store_c = store_c + store_c_flux + end select select_stash_grow + + if_carbon_increment: if(carbon_balance > calloc_abs_error ) then @@ -716,8 +736,8 @@ subroutine DailyPRTAllometricCarbon(this,phase) intgr_params(:) = un_initialized intgr_params(ac_bc_in_id_ctrim) = this%bc_in(ac_bc_in_id_ctrim)%rval - intgr_params(ac_bc_in_id_pft) = real(this%bc_in(ac_bc_in_id_pft)%ival) - intgr_params(ac_bc_in_id_cdamage) = real(this%bc_in(ac_bc_in_id_cdamage)%ival) + intgr_params(ac_bc_in_id_pft) = real(this%bc_in(ac_bc_in_id_pft)%ival,r8) + intgr_params(ac_bc_in_id_cdamage) = real(this%bc_in(ac_bc_in_id_cdamage)%ival,r8) From 1638b6577f52ef403bc992739ff0de525fad4c87 Mon Sep 17 00:00:00 2001 From: Marcos Longo Date: Tue, 6 Dec 2022 16:23:21 -0800 Subject: [PATCH 467/852] Bug fixes in the revised carbon allocation. Some elongation factor parameters were missing when initialising intgr_params, which likely caused the elongation factors to be unrealistic. I also had forgotten to update one deciduous test to check for both hard and semi-deciduous. Some of --- parteh/PRTAllometricCarbonMod.F90 | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index e170d757e1..099387e96d 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -417,7 +417,7 @@ subroutine DailyPRTAllometricCarbon(this,phase) ! ----------------------------------------------------------------------------------- ! 0. ! Copy the boundary conditions into readable local variables. - ! We don't use pointers for bc's that ar "in" only, only "in-out" and "out" + ! We don't use pointers for bc's that are "in" only, only "in-out" and "out" ! ----------------------------------------------------------------------------------- ipft = this%bc_in(ac_bc_in_id_pft)%ival canopy_trim = this%bc_in(ac_bc_in_id_ctrim)%rval @@ -426,6 +426,13 @@ subroutine DailyPRTAllometricCarbon(this,phase) elongf_leaf = this%bc_in(ac_bc_in_id_efleaf)%rval elongf_fnrt = this%bc_in(ac_bc_in_id_effnrt)%rval elongf_stem = this%bc_in(ac_bc_in_id_efstem)%rval + !--- Set some logical flags to simplify "if" blocks + is_hydecid_dormant = any(prt_params%stress_decid(ipft) == [ihard_stress_decid,isemi_stress_decid] ) & + .and. any(leaf_status == [leaves_off,leaves_pshed] ) + is_deciduous = any(prt_params%stress_decid(ipft) == [ihard_stress_decid,isemi_stress_decid] ) & + .or. ( prt_params%season_decid(ipft) == itrue ) + + nleafage = prt_global%state_descriptor(leaf_c_id)%num_pos ! Number of leaf age class ! ----------------------------------------------------------------------------------- @@ -446,16 +453,6 @@ subroutine DailyPRTAllometricCarbon(this,phase) - ! ----------------------------------------------------------------------------------- - ! 3/4. Set some logical flags to simplify "if" blocks - ! ----------------------------------------------------------------------------------- - is_hydecid_dormant = ( prt_params%stress_decid(ipft) == 1 ) .and. & - any(leaf_status == [leaves_off,leaves_pshed] ) - is_deciduous = ( prt_params%stress_decid(ipft) == 1 ) .or. & - ( prt_params%season_decid(ipft) == 1 ) - - nleafage = prt_global%state_descriptor(leaf_c_id)%num_pos ! Number of leaf age class - ! ----------------------------------------------------------------------------------- ! I. Remember the values for the state variables at the beginning of this @@ -738,6 +735,10 @@ subroutine DailyPRTAllometricCarbon(this,phase) intgr_params(ac_bc_in_id_ctrim) = this%bc_in(ac_bc_in_id_ctrim)%rval intgr_params(ac_bc_in_id_pft) = real(this%bc_in(ac_bc_in_id_pft)%ival,r8) intgr_params(ac_bc_in_id_cdamage) = real(this%bc_in(ac_bc_in_id_cdamage)%ival,r8) + intgr_params(ac_bc_in_id_lstat) = real(this%bc_in(ac_bc_in_id_lstat)%ival,r8) + intgr_params(ac_bc_in_id_efleaf) = this%bc_in(ac_bc_in_id_efleaf)%rval + intgr_params(ac_bc_in_id_effnrt) = this%bc_in(ac_bc_in_id_effnrt)%rval + intgr_params(ac_bc_in_id_efstem) = this%bc_in(ac_bc_in_id_efstem)%rval From 846c8bcb57511e74a97975ff6c08c9f262941228 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 7 Dec 2022 14:56:10 -0800 Subject: [PATCH 468/852] correct getcadencedate function name --- main/FatesDispersalMod.F90 | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index 6ed52b072b..36ef7e9539 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -87,7 +87,7 @@ subroutine init(this, numprocs, numpft) ! Set the dispersal date to the current date. Dispersal will start at the end of ! current initial date - dispersal_date = GetCandenceDate() + dispersal_date = GetCadenceDate() end subroutine init @@ -232,11 +232,11 @@ logical function IsItDispersalTime(setdispersedflag) IsItDispersalTime = .true. dispersal_flag = .false. else - if (GetCandenceDate() .ne. dispersal_date) then + if (GetCadenceDate() .ne. dispersal_date) then IsItDispersalTime = .true. if (setflag) then dispersal_flag = .true. - dispersal_date = GetCandenceDate() + dispersal_date = GetCadenceDate() end if end if @@ -246,7 +246,7 @@ end function IsItDispersalTime ! ==================================================================================== - integer function GetCandenceDate() + integer function GetCadenceDate() use FatesInterfaceTypesMod, only : hlm_current_day, & hlm_current_month, & @@ -260,17 +260,17 @@ integer function GetCandenceDate() ! Select the date type to check against based on the dispersal candence select case(fates_dispersal_cadence) case (fates_dispersal_cadence_daily) - GetCandenceDate = hlm_current_day + GetCadenceDate = hlm_current_day case (fates_dispersal_cadence_monthly) - GetCandenceDate = hlm_current_month + GetCadenceDate = hlm_current_month case (fates_dispersal_cadence_yearly) - GetCandenceDate = hlm_current_year + GetCadenceDate = hlm_current_year case default write(fates_log(),*) 'ERROR: An undefined dispersal cadence was specified: ', fates_dispersal_cadence call endrun(msg=errMsg(sourcefile, __LINE__)) end select - end function GetCandenceDate + end function GetCadenceDate end module FatesDispersalMod From 6df29f81871eee377e45bbbe463e3e49af214edd Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 7 Dec 2022 15:12:00 -0800 Subject: [PATCH 469/852] convert dispersal fraction into a parameter file variable --- biogeochem/EDPhysiologyMod.F90 | 10 ++++----- main/EDPftvarcon.F90 | 22 +++++++++++++++++++ .../fates_params_seed-dispersal_api23.cdl | 6 +++++ 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index fb56464fc1..62a156802f 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1603,13 +1603,13 @@ subroutine SeedUpdate( currentSite, bc_in, bc_out) integer :: n_litt_types ! number of litter element types (c,n,p, etc) integer :: el ! loop counter for litter element types integer :: element_id ! element id consistent with parteh/PRTGenericMod.F90 - real(r8) :: disp_frac(maxpft) ! fraction of seed-rain among the site_seed_rain that's leaving the site [unitless] + real(r8) :: EDPftvarcon_inst%seed_dispersal_fraction(maxpft) ! fraction of seed-rain among the site_seed_rain that's leaving the site [unitless] do el = 1, num_elements site_seed_rain(:) = 0._r8 - disp_frac(:) = 0.2 ! to be specified in the parameter file or calculated using dispersal kernel + EDPftvarcon_inst%seed_dispersal_fraction(:) = 0.2 ! to be specified in the parameter file or calculated using dispersal kernel element_id = element_list(el) @@ -1679,7 +1679,7 @@ subroutine SeedUpdate( currentSite, bc_in, bc_out) if(currentSite%use_this_pft(pft).eq.itrue)then ! Seed input from local sources (within site) - litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)*(1-disp_frac(pft))/area ![kg/m2/day] + litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)*(1-EDPftvarcon_inst%seed_dispersal_fraction(pft))/area ![kg/m2/day] !write(fates_log(),*) 'pft, litt%seed_in_local(pft), site_seed_rain(pft): ', pft, litt%seed_in_local(pft), site_seed_rain(pft) ! If there is forced external seed rain, we calculate the input mass flux @@ -1716,14 +1716,14 @@ subroutine SeedUpdate( currentSite, bc_in, bc_out) enddo do pft = 1,numpft - site_mass%seed_out = site_mass%seed_out + site_seed_rain(pft)*disp_frac(pft) ![kg/site/day] + site_mass%seed_out = site_mass%seed_out + site_seed_rain(pft)*EDPftvarcon_inst%seed_dispersal_fraction(pft) ![kg/site/day] !write(fates_log(),*) 'pft, site_seed_rain(pft), site_mass%seed_out: ', pft, site_mass%seed_out end do end do do pft = 1,numpft - bc_out%seed_out(pft) = bc_out%seed_out(pft) + site_seed_rain(pft)*disp_frac(pft) ![kg/site/day] + bc_out%seed_out(pft) = bc_out%seed_out(pft) + site_seed_rain(pft)*EDPftvarcon_inst%seed_dispersal_fraction(pft) ![kg/site/day] write(fates_log(),*) 'pft, bc_in%seed_in(pft), bc_out%seed_out(pft): ', pft, bc_in%seed_in(pft), bc_out%seed_out(pft) end do diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 191248abcf..c1f9470199 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -102,6 +102,7 @@ module EDPftvarcon real(r8), allocatable :: seed_dispersal_param_A(:) ! Seed dispersal scale parameter, Bullock et al. (2017) real(r8), allocatable :: seed_dispersal_param_B(:) ! Seed dispersal shape parameter, Bullock et al. (2017) real(r8), allocatable :: seed_dispersal_max_dist(:) ! Maximum seed dispersal distance parameter (m) + real(r8), allocatable :: seed_dispersal_fraction(:) ! Fraction of seed rain to disperse, per pft real(r8), allocatable :: trim_limit(:) ! Limit to reductions in leaf area w stress (m2/m2) real(r8), allocatable :: trim_inc(:) ! Incremental change in trimming function (m2/m2) real(r8), allocatable :: rhol(:, :) @@ -551,6 +552,10 @@ subroutine Register_PFT(this, fates_params) name = 'fates_seed_dispersal_max_dist' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_seed_dispersal_fraction' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) name = 'fates_trim_limit' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & @@ -911,6 +916,10 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetrieveParameterAllocate(name=name, & data=this%seed_dispersal_max_dist) + name = 'fates_seed_dispersal_fraction' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%seed_dispersal_fraction) + name = 'fates_trim_limit' call fates_params%RetrieveParameterAllocate(name=name, & data=this%trim_limit) @@ -1454,6 +1463,7 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'seed_dispersal_param_A = ',EDPftvarcon_inst%seed_dispersal_param_A write(fates_log(),fmt0) 'seed_dispersal_param_B = ',EDPftvarcon_inst%seed_dispersal_param_B write(fates_log(),fmt0) 'seed_dispersal_max_dist = ',EDPftvarcon_inst%seed_dispersal_max_dist + write(fates_log(),fmt0) 'seed_dispersal_fraction = ',EDPftvarcon_inst%seed_dispersal_fraction write(fates_log(),fmt0) 'trim_limit = ',EDPftvarcon_inst%trim_limit write(fates_log(),fmt0) 'trim_inc = ',EDPftvarcon_inst%trim_inc write(fates_log(),fmt0) 'rhol = ',EDPftvarcon_inst%rhol @@ -1678,6 +1688,18 @@ subroutine FatesCheckParams(is_master) call endrun(msg=errMsg(sourcefile, __LINE__)) end if + ! Check that parameter ranges for the seed dispersal fraction make sense + !----------------------------------------------------------------------------------- + if (( EDPftvarcon_inst%seed_dispersal_fraction(ipft) < fates_check_param_set ) .and. & + (( EDPftvarcon_inst%seed_dispersal_fraction(ipft) > 1.0_r8 ) .or. & + ( EDPftvarcon_inst%seed_dispersal_fraction(ipft) < 0.0_r8 ))) then + + write(fates_log(),*) 'Seed dispersal is on per seed_dispersal_fraction being set' + write(fates_log(),*) 'Please make sure the fraction value is between 0 and 1' + write(fates_log(),*) 'Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + ! Check that parameter ranges for age-dependent mortality make sense !----------------------------------------------------------------------------------- if ( ( EDPftvarcon_inst%mort_ip_age_senescence(ipft) < fates_check_param_set ) .and. & diff --git a/parameter_files/fates_params_seed-dispersal_api23.cdl b/parameter_files/fates_params_seed-dispersal_api23.cdl index 0dd4df8b7e..4a8c1193b0 100644 --- a/parameter_files/fates_params_seed-dispersal_api23.cdl +++ b/parameter_files/fates_params_seed-dispersal_api23.cdl @@ -491,6 +491,10 @@ variables: fates_seed_dispersal_max_dist:units = "m" ; fates_seed_dispersal_max_dist:long_name = "maximum seed dispersal distance for a given pft" ; fates_seed_dispersal_max_dist:use_case = "undefined" ; + double fates_seed_dispersal_fraction(fates_pft) ; + fates_seed_dispersal_fraction:units = "fraction" ; + fates_seed_dispersal_fraction:long_name = "fraction of seed rain to be dispersed to other grid cells" ; + fates_seed_dispersal_fraction:use_case = "undefined" ; double fates_seed_dispersal_param_A(fates_pft) ; fates_seed_dispersal_param_A:units = "unitless" ; fates_seed_dispersal_param_A:long_name = "seed dispersal scale parameter" ; @@ -1285,6 +1289,8 @@ data: 0.51, 0.51, 0.51, 0.51 ; fates_seed_dispersal_max_dist = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_seed_dispersal_fraction = _, _, _, _, _, _, _, _, _, _, _, _ ; fates_seed_dispersal_param_A = _, _, _, _, _, _, _, _, _, _, _, _ ; From f5e115365ec2fa5871103e69bf093d25aff52bd7 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 8 Dec 2022 14:03:10 -0800 Subject: [PATCH 470/852] remove old local dispersal fraction defintion --- biogeochem/EDPhysiologyMod.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 62a156802f..53dc766adc 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1603,7 +1603,6 @@ subroutine SeedUpdate( currentSite, bc_in, bc_out) integer :: n_litt_types ! number of litter element types (c,n,p, etc) integer :: el ! loop counter for litter element types integer :: element_id ! element id consistent with parteh/PRTGenericMod.F90 - real(r8) :: EDPftvarcon_inst%seed_dispersal_fraction(maxpft) ! fraction of seed-rain among the site_seed_rain that's leaving the site [unitless] do el = 1, num_elements From 0eef9c0bb192ddcfeb0dafe88a4dfb68f2a77408 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 8 Dec 2022 14:09:53 -0800 Subject: [PATCH 471/852] comment out diagnostic write statment --- biogeochem/EDPhysiologyMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 53dc766adc..70d7bade04 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1723,7 +1723,7 @@ subroutine SeedUpdate( currentSite, bc_in, bc_out) do pft = 1,numpft bc_out%seed_out(pft) = bc_out%seed_out(pft) + site_seed_rain(pft)*EDPftvarcon_inst%seed_dispersal_fraction(pft) ![kg/site/day] - write(fates_log(),*) 'pft, bc_in%seed_in(pft), bc_out%seed_out(pft): ', pft, bc_in%seed_in(pft), bc_out%seed_out(pft) + ! write(fates_log(),*) 'pft, bc_in%seed_in(pft), bc_out%seed_out(pft): ', pft, bc_in%seed_in(pft), bc_out%seed_out(pft) end do return From 23ee93f0651c06eea7dc1c4c7899b9bbc61b92f0 Mon Sep 17 00:00:00 2001 From: Shijie Shu Date: Tue, 20 Dec 2022 13:30:53 -0800 Subject: [PATCH 472/852] Create subroutine to encapsulate the calculation of harvest debt. --- biogeochem/EDCanopyStructureMod.F90 | 2 +- biogeochem/EDLoggingMortalityMod.F90 | 65 ++++++++++++++++++++++++++++ biogeochem/EDPatchDynamicsMod.F90 | 46 +------------------- 3 files changed, 68 insertions(+), 45 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index a9c8740b6c..05c86c02f2 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1784,7 +1784,7 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) use EDTypesMod , only : ed_patch_type, ed_cohort_type, & ed_site_type, AREA - use FatesInterfaceTypesMod , only : bc_in_type, bc_out_type + use FatesInterfaceTypesMod , only : bc_out_type ! ! !ARGUMENTS diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index c70d880a2f..c695bc4f2e 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -97,6 +97,7 @@ module EDLoggingMortalityMod public :: get_harvest_rate_area public :: get_harvestable_carbon public :: get_harvest_rate_carbon + public :: get_harvest_debt public :: UpdateHarvestC contains @@ -1116,6 +1117,70 @@ subroutine UpdateHarvestC(currentSite,bc_out) AREA_INV * (1._r8 - pprodharv10_forest_mean) * unit_trans_factor return + end subroutine UpdateHarvestC + subroutine get_harvest_debt(site_in, bc_in, harvest_tag) + + ! + ! !DESCRIPTION: + ! + ! Calculate if we have harvest debt for primary and secondary land + ! Harvest debt is the accumulated total carbon + ! deficiency once the carbon amount available for harvest + ! is smaller than the harvest rate of forcing data. + ! Harvest debt is calculated on site level + ! TODO: we can define harvest debt as a fraction of the + ! harvest rate in the future + ! Note: Non-forest harvest is accounted for under forest + ! harvest, thus the harvest tag for non-forest is not applicable (= 2) + ! + ! !ARGUMENTS: + type(ed_site_type) , intent(inout), target :: site_in + type(bc_in_type), intent(in) :: bc_in + integer :: harvest_tag(hlm_num_lu_harvest_cats) + + ! !LOCAL VARIABLES: + integer :: h_index + real(r8) :: harvest_debt_pri + real(r8) :: harvest_debt_sec_mature + real(r8) :: harvest_debt_sec_young + + if(logging_time) then + ! First we need to get harvest rate for all three categories + do h_index = 1, hlm_num_lu_harvest_cats + ! Primary forest harvest rate + if(bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1" .or. & + bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_VH2" ) then + harvest_debt_pri = harvest_debt_pri + bc_in%hlm_harvest_rates(h_index) + else if(bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH1") then + harvest_debt_sec_mature = harvest_debt_sec_mature + bc_in%hlm_harvest_rates(h_index) + else if(bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2" .or. & + bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH3") then + harvest_debt_sec_young = harvest_debt_sec_young + bc_in%hlm_harvest_rates(h_index) + end if + end do + ! Next we get the harvest debt through the harvest tag + do h_index = 1, hlm_num_lu_harvest_cats + if (harvest_tag(h_index) .eq. 1) then + if(bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1") then + site_in%resources_management%harvest_debt = site_in%resources_management%harvest_debt + & + harvest_debt_pri + else if(bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH1") then + site_in%resources_management%harvest_debt = site_in%resources_management%harvest_debt + & + harvest_debt_sec_mature + site_in%resources_management%harvest_debt_sec = site_in%resources_management%harvest_debt_sec + & + harvest_debt_sec_mature + else if(bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2") then + site_in%resources_management%harvest_debt = site_in%resources_management%harvest_debt + & + harvest_debt_sec_young + site_in%resources_management%harvest_debt_sec = site_in%resources_management%harvest_debt_sec + & + harvest_debt_sec_young + end if + end if + end do + end if + + end subroutine get_harvest_debt + end module EDLoggingMortalityMod diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index e42a1ff9ae..0875151f51 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -60,6 +60,7 @@ module EDPatchDynamicsMod use EDLoggingMortalityMod, only : get_harvest_rate_area use EDLoggingMortalityMod, only : get_harvest_rate_carbon use EDLoggingMortalityMod, only : get_harvestable_carbon + use EDLoggingMortalityMod, only : get_harvest_debt use EDParamsMod , only : fates_mortality_disturbance_fraction use FatesAllometryMod , only : carea_allom use FatesAllometryMod , only : set_root_fraction @@ -268,50 +269,7 @@ subroutine disturbance_rates( site_in, bc_in) currentPatch => currentPatch%younger end do - ! Calculate if we have harvest debt for primary and secondary land - ! Harvest debt is the accumulated total carbon - ! deficiency once the carbon amount available for harvest - ! is smaller than the harvest rate of forcing data. - ! Harvest debt is calculated on site level - ! TODO: we can define harvest debt as a fraction of the - ! harvest rate in the future - ! Note: Non-forest harvest is accounted for under forest - ! harvest, thus the harvest tag for non-forest is not applicable (= 2) - - if(logging_time) then - ! First we need to get harvest rate for all three categories - do h_index = 1, hlm_num_lu_harvest_cats - ! Primary forest harvest rate - if(bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1" .or. & - bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_VH2" ) then - harvest_debt_pri = harvest_debt_pri + bc_in%hlm_harvest_rates(h_index) - else if(bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH1") then - harvest_debt_sec_mature = harvest_debt_sec_mature + bc_in%hlm_harvest_rates(h_index) - else if(bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2" .or. & - bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH3") then - harvest_debt_sec_mature = harvest_debt_sec_mature + bc_in%hlm_harvest_rates(h_index) - end if - end do - ! Next we get the harvest debt through the harvest tag - do h_index = 1, hlm_num_lu_harvest_cats - if (harvest_tag(h_index) .eq. 1) then - if(bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1") then - site_in%resources_management%harvest_debt = site_in%resources_management%harvest_debt + & - harvest_debt_pri - else if(bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH1") then - site_in%resources_management%harvest_debt = site_in%resources_management%harvest_debt + & - harvest_debt_sec_mature - site_in%resources_management%harvest_debt_sec = site_in%resources_management%harvest_debt_sec + & - harvest_debt_sec_mature - else if(bc_in%hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2") then - site_in%resources_management%harvest_debt = site_in%resources_management%harvest_debt + & - harvest_debt_sec_young - site_in%resources_management%harvest_debt_sec = site_in%resources_management%harvest_debt_sec + & - harvest_debt_sec_young - end if - end if - end do - end if + call get_harvest_debt(site_in, bc_in, harvest_tag) ! --------------------------------------------------------------------------------------------- ! Calculate Disturbance Rates based on the mortality rates just calculated From 74a5c6153a739da08e363d92a5eed3947b575e0a Mon Sep 17 00:00:00 2001 From: Marcos Longo Date: Tue, 20 Dec 2022 20:31:50 -0800 Subject: [PATCH 473/852] Drought thresholds are now PFT-specific. Also moved some phenology parameters from EDPftvarcon.F90 to PRTParametersMod following discussion with Ryan. --- biogeochem/EDPhysiologyMod.F90 | 54 +++++++--- main/EDInitMod.F90 | 4 +- main/EDParamsMod.F90 | 32 +----- main/EDPftvarcon.F90 | 89 +---------------- main/FatesInventoryInitMod.F90 | 4 +- parameter_files/fates_params_default.cdl | 38 +++---- parteh/PRTParametersMod.F90 | 17 +++- parteh/PRTParamsFATESMod.F90 | 121 ++++++++++++++++++++++- 8 files changed, 200 insertions(+), 159 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 43e4a3c650..2b1f37c6f2 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -869,9 +869,6 @@ subroutine phenology( currentSite, bc_in ) ! ! !USES: use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm - use EDParamsMod, only : ED_val_phen_drought_threshold - use EDParamsMod, only : ED_val_phen_moist_threshold - use EDParamsMod, only : ED_val_phen_doff_time use EDParamsMod, only : ED_val_phen_a, ED_val_phen_b, ED_val_phen_c use EDParamsMod, only : ED_val_phen_chiltemp use EDParamsMod, only : ED_val_phen_mindayson @@ -911,6 +908,25 @@ subroutine phenology( currentSite, bc_in ) ! This is the shortest between the PFT leaf lifespan ! and the maximum lifespan of drought deciduous ! (see canopy_leaf_lifespan below) + real(r8) :: phen_drought_threshold ! For drought hard-deciduous, this is the threshold + ! below which plants will abscise leaves, and + ! above which plants will flush leaves. For semi- + ! deciduous plants, this is the threshold below + ! which abscission will be complete. This depends + ! on the sign. If positive, these are soil + ! volumetric water content [m3/m3]. If negative, + ! the values are soil matric potential [mm]. Not + ! used for non-deciduous plants. Ignored for + ! non-deciduous plants. + real(r8) :: phen_moist_threshold ! For semi-deciduous, this is the threshold above + ! which flushing will be complete. This depends + ! on the sign. If positive, these are soil + ! volumetric water content [m3/m3]. If negative, + ! the values are soil matric potential [mm]. + ! Ignored for hard-deciduous and evergreen + ! plants. + real(r8) :: phen_doff_time ! Minimum number of days that plants must remain + ! leafless before flushing leaves again. ! Logical tests to make code more readable logical :: smoist_below_threshold ! Is soil moisture below threshold? @@ -1130,6 +1146,12 @@ subroutine phenology( currentSite, bc_in ) ! Add PFT look to account for different PFT rooting depth profiles. pft_elong_loop: do ipft=1,numpft + ! Copy values to a local variable to make code more legible. + phen_drought_threshold = prt_params%phen_drought_threshold(ipft) + phen_moist_threshold = prt_params%phen_moist_threshold (ipft) + phen_doff_time = prt_params%phen_doff_time (ipft) + + ! Update soil moisture information memory (we always track the last 10 days) do i_wmem = numWaterMem,2,-1 !shift memory to previous day, to make room for current day currentSite%liqvol_memory(i_wmem,ipft) = currentSite%liqvol_memory(i_wmem-1,ipft) @@ -1171,12 +1193,12 @@ subroutine phenology( currentSite, bc_in ) real(numWaterMem,r8) ! Compare the moisture with the threshold. - if ( ED_val_phen_drought_threshold >= 0. ) then + if ( phen_drought_threshold >= 0. ) then ! Liquid volume in reference layer (m3/m3) - smoist_below_threshold = mean_10day_liqvol < ED_val_phen_drought_threshold + smoist_below_threshold = mean_10day_liqvol < phen_drought_threshold else ! Soil matric potential in reference layer (mm) - smoist_below_threshold = mean_10day_smp < ED_val_phen_drought_threshold + smoist_below_threshold = mean_10day_smp < phen_drought_threshold end if ! Calculate days since last flushing and shedding event, but make a provision @@ -1241,7 +1263,7 @@ subroutine phenology( currentSite, bc_in ) ! was about one year ago (+/- tolerance). prolonged_off_period = & any( currentSite%dstatus(ipft) == [phen_dstat_timeoff,phen_dstat_moistoff] ) .and. & - ( currentSite%dndaysleafoff(ipft) > ED_val_phen_doff_time ) .and. & + ( currentSite%dndaysleafoff(ipft) > phen_doff_time ) .and. & ( currentSite%dndaysleafon(ipft) >= 365-dd_offon_toler ) .and. & ( currentSite%dndaysleafon(ipft) <= 365+dd_offon_toler ) ! Last flushing was a very long time ago. @@ -1324,14 +1346,14 @@ subroutine phenology( currentSite, bc_in ) ! First guess elongation factor - if (ED_val_phen_drought_threshold >= 0.) then + if (phen_drought_threshold >= 0.) then elongf_1st = elongf_min + (1.0_r8 - elongf_min ) * & - ( mean_10day_liqvol - ED_val_phen_drought_threshold ) / & - ( ED_val_phen_moist_threshold - ED_val_phen_drought_threshold ) + ( mean_10day_liqvol - phen_drought_threshold ) / & + ( phen_moist_threshold - phen_drought_threshold ) else elongf_1st = elongf_min + (1.0_r8 - elongf_min ) * & - ( mean_10day_smp - ED_val_phen_drought_threshold ) / & - ( ED_val_phen_moist_threshold - ED_val_phen_drought_threshold ) + ( mean_10day_smp - phen_drought_threshold ) / & + ( phen_moist_threshold - phen_drought_threshold ) end if elongf_1st = max(0.0_r8,min(1.0_r8,elongf_1st)) @@ -1517,8 +1539,8 @@ subroutine phenology_leafonoff(currentSite) sapw_c = currentCohort%prt%GetState(sapw_organ , carbon12_element) struct_c = currentCohort%prt%GetState(struct_organ, carbon12_element) - fnrt_drop_fraction = EDPftvarcon_inst%phen_fnrt_drop_fraction(ipft) - stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(ipft) + fnrt_drop_fraction = prt_params%phen_fnrt_drop_fraction(ipft) + stem_drop_fraction = prt_params%phen_stem_drop_fraction(ipft) l2fr = prt_params%allom_l2fr(ipft) ! MLO. To avoid duplicating code for drought and cold deciduous PFTs, we first @@ -2240,8 +2262,8 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) temp_cohort%pft = ft temp_cohort%hite = EDPftvarcon_inst%hgt_min(ft) temp_cohort%coage = 0.0_r8 - fnrt_drop_fraction = EDPftvarcon_inst%phen_fnrt_drop_fraction(ft) - stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(ft) + fnrt_drop_fraction = prt_params%phen_fnrt_drop_fraction(ft) + stem_drop_fraction = prt_params%phen_stem_drop_fraction(ft) temp_cohort%l2fr = currentSite%rec_l2fr(ft,currentPatch%NCL_p) temp_cohort%crowndamage = 1 ! new recruits are undamaged diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index cb7028ef38..0baddb1ef1 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -898,8 +898,8 @@ subroutine init_cohorts( site_in, patch_in, bc_in) elongf_fnrt = 1.0_r8 elongf_stem = 1.0_r8 - fnrt_drop_fraction = EDPftvarcon_inst%phen_fnrt_drop_fraction(temp_cohort%pft) - stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(temp_cohort%pft) + fnrt_drop_fraction = prt_params%phen_fnrt_drop_fraction(temp_cohort%pft) + stem_drop_fraction = prt_params%phen_stem_drop_fraction(temp_cohort%pft) if(hlm_use_sp.eq.ifalse)then ! do not override SP vales with phenology diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 4dacaecf5b..f1af675a1a 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -46,9 +46,6 @@ module EDParamsMod real(r8),protected, public :: ED_val_cwd_fcel real(r8),protected, public :: ED_val_cwd_flig real(r8),protected, public :: ED_val_base_mr_20 - real(r8),protected, public :: ED_val_phen_drought_threshold - real(r8),protected, public :: ED_val_phen_moist_threshold - real(r8),protected, public :: ED_val_phen_doff_time real(r8),protected, public :: ED_val_phen_a real(r8),protected, public :: ED_val_phen_b real(r8),protected, public :: ED_val_phen_c @@ -107,14 +104,11 @@ module EDParamsMod character(len=param_string_length),parameter,public :: ED_name_cwd_fcel= "fates_frag_cwd_fcel" character(len=param_string_length),parameter,public :: ED_name_cwd_flig= "fates_frag_cwd_flig" character(len=param_string_length),parameter,public :: ED_name_base_mr_20= "fates_base_mr_20" - character(len=param_string_length),parameter,public :: ED_name_phen_drought_threshold= "fates_phen_drought_threshold" - character(len=param_string_length),parameter,public :: ED_name_phen_moist_threshold= "fates_phen_moist_threshold" - character(len=param_string_length),parameter,public :: ED_name_phen_doff_time= "fates_phen_mindaysoff" character(len=param_string_length),parameter,public :: ED_name_phen_a= "fates_phen_gddthresh_a" character(len=param_string_length),parameter,public :: ED_name_phen_b= "fates_phen_gddthresh_b" character(len=param_string_length),parameter,public :: ED_name_phen_c= "fates_phen_gddthresh_c" character(len=param_string_length),parameter,public :: ED_name_phen_chiltemp= "fates_phen_chilltemp" - character(len=param_string_length),parameter,public :: ED_name_phen_mindayson= "fates_phen_mindayson" + character(len=param_string_length),parameter,public :: ED_name_phen_mindayson= "fates_phen_mindayson" character(len=param_string_length),parameter,public :: ED_name_phen_ncolddayslim= "fates_phen_ncolddayslim" character(len=param_string_length),parameter,public :: ED_name_phen_coldtemp= "fates_phen_coldtemp" character(len=param_string_length),parameter,public :: ED_name_cohort_size_fusion_tol= "fates_cohort_size_fusion_tol" @@ -277,9 +271,6 @@ subroutine FatesParamsInit() ED_val_cwd_fcel = nan ED_val_cwd_flig = nan ED_val_base_mr_20 = nan - ED_val_phen_drought_threshold = nan - ED_val_phen_moist_threshold = nan - ED_val_phen_doff_time = nan ED_val_phen_a = nan ED_val_phen_b = nan ED_val_phen_c = nan @@ -390,15 +381,6 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=ED_name_base_mr_20, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) - call fates_params%RegisterParameter(name=ED_name_phen_drought_threshold, dimension_shape=dimension_shape_scalar, & - dimension_names=dim_names_scalar) - - call fates_params%RegisterParameter(name=ED_name_phen_moist_threshold, dimension_shape=dimension_shape_scalar, & - dimension_names=dim_names_scalar) - - call fates_params%RegisterParameter(name=ED_name_phen_doff_time, dimension_shape=dimension_shape_scalar, & - dimension_names=dim_names_scalar) - call fates_params%RegisterParameter(name=ED_name_phen_a, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -592,15 +574,6 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetrieveParameter(name=ED_name_base_mr_20, & data=ED_val_base_mr_20) - call fates_params%RetrieveParameter(name=ED_name_phen_drought_threshold, & - data=ED_val_phen_drought_threshold) - - call fates_params%RetrieveParameter(name=ED_name_phen_moist_threshold, & - data=ED_val_phen_moist_threshold) - - call fates_params%RetrieveParameter(name=ED_name_phen_doff_time, & - data=ED_val_phen_doff_time) - call fates_params%RetrieveParameter(name=ED_name_phen_a, & data=ED_val_phen_a) @@ -788,9 +761,6 @@ subroutine FatesReportParams(is_master) write(fates_log(),fmt0) 'ED_val_cwd_fcel = ',ED_val_cwd_fcel write(fates_log(),fmt0) 'ED_val_cwd_flig = ',ED_val_cwd_flig write(fates_log(),fmt0) 'ED_val_base_mr_20 = ', ED_val_base_mr_20 - write(fates_log(),fmt0) 'ED_val_phen_drought_threshold = ',ED_val_phen_drought_threshold - write(fates_log(),fmt0) 'ED_val_phen_moist_threshold = ',ED_val_phen_moist_threshold - write(fates_log(),fmt0) 'ED_val_phen_doff_time = ',ED_val_phen_doff_time write(fates_log(),fmt0) 'ED_val_phen_a = ',ED_val_phen_a write(fates_log(),fmt0) 'ED_val_phen_b = ',ED_val_phen_b write(fates_log(),fmt0) 'ED_val_phen_c = ',ED_val_phen_c diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index d27ac4251b..c82d8d4352 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -179,15 +179,12 @@ module EDPftvarcon ! biochemical production, fraction based how much ! more in need a plant is for P versus N [/] - ! Turnover related things + ! Phenology related things real(r8), allocatable :: phenflush_fraction(:) ! Maximum fraction of storage carbon used to flush leaves ! on bud-burst [kgC/kgC] real(r8), allocatable :: phen_cold_size_threshold(:) ! stem/leaf drop occurs on DBH size of decidious non-woody ! (coastal grass) plants larger than the threshold value - real(r8), allocatable :: phen_fnrt_drop_fraction(:) ! Fraction of fine roots abscissed when leaves absciss - real(r8), allocatable :: phen_stem_drop_fraction(:) ! Fraction of stem abscissed when leaves absciss, for deciduous - ! non-woody (grass) plants ! Nutrient Aquisition parameters real(r8), allocatable :: prescribed_nuptake(:) ! If there is no soil BGC model active, @@ -599,13 +596,6 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_phen_stem_drop_fraction' - call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & - dimension_names=dim_names, lower_bounds=dim_lower_bound) - - name = 'fates_phen_fnrt_drop_fraction' - call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & - dimension_names=dim_names, lower_bounds=dim_lower_bound) ! Nutrient competition parameters @@ -961,14 +951,6 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetrieveParameterAllocate(name=name, & data=this%phen_cold_size_threshold) - name = 'fates_phen_stem_drop_fraction' - call fates_params%RetrieveParameterAllocate(name=name, & - data=this%phen_stem_drop_fraction) - - name = 'fates_phen_fnrt_drop_fraction' - call fates_params%RetrieveParameterAllocate(name=name, & - data=this%phen_fnrt_drop_fraction) - name = 'fates_cnp_prescribed_nuptake' call fates_params%RetrieveParameterAllocate(name=name, & data=this%prescribed_nuptake) @@ -1483,8 +1465,6 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'taus = ',EDPftvarcon_inst%taus write(fates_log(),fmt0) 'phen_flush_fraction',EDpftvarcon_inst%phenflush_fraction write(fates_log(),fmt0) 'phen_cold_size_threshold = ',EDPftvarcon_inst%phen_cold_size_threshold - write(fates_log(),fmt0) 'phen_fnrt_drop_fraction',EDpftvarcon_inst%phen_fnrt_drop_fraction - write(fates_log(),fmt0) 'phen_stem_drop_fraction',EDpftvarcon_inst%phen_stem_drop_fraction write(fates_log(),fmt0) 'fire_alpha_SH = ',EDPftvarcon_inst%fire_alpha_SH write(fates_log(),fmt0) 'allom_frbstor_repro = ',EDPftvarcon_inst%allom_frbstor_repro write(fates_log(),fmt0) 'hydro_p_taper = ',EDPftvarcon_inst%hydr_p_taper @@ -1531,9 +1511,6 @@ subroutine FatesCheckParams(is_master) use FatesConstantsMod , only : itrue, ifalse use EDParamsMod , only : logging_mechanical_frac, logging_collateral_frac use EDParamsMod , only : logging_direct_frac,logging_export_frac - use EDParamsMod , only : ED_val_phen_drought_threshold - use EDParamsMod , only : ED_val_phen_moist_threshold - use EDTypesMod , only : isemi_stress_decid use FatesInterfaceTypesMod, only : hlm_use_fixed_biogeog,hlm_use_sp, hlm_name ! Argument @@ -1715,7 +1692,6 @@ subroutine FatesCheckParams(is_master) ! Check if the fraction of storage used for flushing deciduous trees ! is greater than zero, and less than or equal to 1. - if (prt_params%evergreen(ipft) == ifalse) then if ( ( EDPftvarcon_inst%phenflush_fraction(ipft) < nearzero ) .or. & ( EDPFtvarcon_inst%phenflush_fraction(ipft) > 1 ) ) then @@ -1729,36 +1705,6 @@ subroutine FatesCheckParams(is_master) write(fates_log(),*) ' Aborting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if ( ( EDPftvarcon_inst%phen_fnrt_drop_fraction(ipft) < 0.0_r8 ) .or. & - ( EDPFtvarcon_inst%phen_fnrt_drop_fraction(ipft) > 1.0_r8 ) ) then - write(fates_log(),*) ' Abscission rate for fine roots must be between 0 and 1 for ' - write(fates_log(),*) ' deciduous PFTs.' - write(fates_log(),*) ' PFT#: ',ipft - write(fates_log(),*) ' evergreen flag: (should be 0):',int(prt_params%evergreen(ipft)) - write(fates_log(),*) ' phen_fnrt_drop_fraction: ', EDPFtvarcon_inst%phen_fnrt_drop_fraction(ipft) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - if ( ( EDPftvarcon_inst%phen_stem_drop_fraction(ipft) < 0.0_r8 ) .or. & - ( EDPFtvarcon_inst%phen_stem_drop_fraction(ipft) > 1.0_r8 ) ) then - write(fates_log(),*) ' Deciduous non-wood plants must keep 0-100% of their stems' - write(fates_log(),*) ' during the deciduous period.' - write(fates_log(),*) ' PFT#: ',ipft - write(fates_log(),*) ' evergreen flag: (should be 0):',int(prt_params%evergreen(ipft)) - write(fates_log(),*) ' phen_stem_drop_fraction: ', EDPFtvarcon_inst%phen_stem_drop_fraction(ipft) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - end if - - if( (prt_params%woody(ipft) == itrue) .and. & - (EDPftvarcon_inst%phen_stem_drop_fraction(ipft) > nearzero ) ) then - write(fates_log(),*) ' Non-zero stem-drop fractions are not allowed for woody plants' - write(fates_log(),*) ' PFT#: ',ipft - write(fates_log(),*) ' part_params%woody:',prt_params%woody(ipft) - write(fates_log(),*) ' phen_stem_drop_fraction: ', EDPFtvarcon_inst%phen_stem_drop_fraction(ipft) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) end if ! Check if freezing tolerance is within reasonable bounds @@ -1854,39 +1800,6 @@ subroutine FatesCheckParams(is_master) !! end if !! end do - - ! When using the the gradual (ED2-like) phenology, we must ensure that the lower - ! and upper thresholds are consistent (i.e., that both are based on either soil - ! water content or soil matric potential). - is_semi_decid: if (any(prt_params%stress_decid(:) == isemi_stress_decid)) then - - if (ED_val_phen_drought_threshold*ED_val_phen_moist_threshold < 0._r8) then - ! In case the product of the lower and upper thresholds is negative, the - ! thresholds are inconsistent as both should be defined using the same - ! quantity. - write(fates_log(),*) ' When using gradual (ED2-like) drought deciduous phenology,' - write(fates_log(),*) ' the moist threshold should be have the same sign as' - write(fates_log(),*) ' the dry threshold. Positive = soil water content [m3/m3],' - write(fates_log(),*) ' Negative = soil matric potential [mm].' - write(fates_log(),*) ' fates_phen_drought_threshold (dry threshold) = ',ED_val_phen_drought_threshold - write(fates_log(),*) ' fates_phen_moist_threshold (moist threshold) = ',ED_val_phen_moist_threshold - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) - - elseif ( ED_val_phen_drought_threshold >= ED_val_phen_moist_threshold) then - write(fates_log(),*) ' When using gradual (ED2-like) drought deciduous phenology,' - write(fates_log(),*) ' the moist threshold should be greater than the dry threshold.' - write(fates_log(),*) ' By greater we mean more positive or less negative, and' - write(fates_log(),*) ' they cannot be the identical.' - write(fates_log(),*) ' fates_phen_drought_threshold (dry threshold) = ',ED_val_phen_drought_threshold - write(fates_log(),*) ' fates_phen_moist_threshold (moist threshold) = ',ED_val_phen_moist_threshold - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - end if is_semi_decid - - return end subroutine FatesCheckParams diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index 52176a9f35..eaaaa75744 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -1057,8 +1057,8 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & elongf_fnrt = 1.0_r8 elongf_stem = 1.0_r8 - fnrt_drop_fraction = EDPftvarcon_inst%phen_fnrt_drop_fraction(temp_cohort%pft) - stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(temp_cohort%pft) + fnrt_drop_fraction = prt_params%phen_fnrt_drop_fraction(temp_cohort%pft) + stem_drop_fraction = prt_params%phen_stem_drop_fraction(temp_cohort%pft) if( prt_params%season_decid(temp_cohort%pft) == itrue .and. & any(csite%cstatus == [phen_cstat_nevercold,phen_cstat_iscold])) then diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 58b0e581e6..32c8db0418 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -431,15 +431,24 @@ variables: double fates_phen_cold_size_threshold(fates_pft) ; fates_phen_cold_size_threshold:units = "cm" ; fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; + double fates_phen_drought_threshold(fates_pft) ; + fates_phen_drought_threshold:units = "m3/m3 or mm" ; + fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold for semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; double fates_phen_evergreen(fates_pft) ; fates_phen_evergreen:units = "logical flag" ; fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; - double fates_phen_fnrt_drop_fraction(fates_pft) ; - fates_phen_fnrt_drop_fraction:units = "fraction" ; - fates_phen_fnrt_drop_fraction:long_name = "fraction of fine roots to drop during drought/cold" ; double fates_phen_flush_fraction(fates_pft) ; fates_phen_flush_fraction:units = "fraction" ; fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; + double fates_phen_fnrt_drop_fraction(fates_pft) ; + fates_phen_fnrt_drop_fraction:units = "fraction" ; + fates_phen_fnrt_drop_fraction:long_name = "fraction of fine roots to drop during drought/cold" ; + double fates_phen_doff_time(fates_pft) ; + fates_phen_mindaysoff:units = "days" ; + fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves abscised (shed)" ; + double fates_phen_moist_threshold(fates_pft) ; + fates_phen_moist_threshold:units = "m3/m3 or mm" ; + fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for drought semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; double fates_phen_season_decid(fates_pft) ; fates_phen_season_decid:units = "logical flag" ; fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; @@ -746,9 +755,6 @@ variables: double fates_phen_coldtemp ; fates_phen_coldtemp:units = "degrees C" ; fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; - double fates_phen_drought_threshold ; - fates_phen_drought_threshold:units = "m3/m3 or mm" ; - fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold for semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; double fates_phen_gddthresh_a ; fates_phen_gddthresh_a:units = "none" ; fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; @@ -758,15 +764,9 @@ variables: double fates_phen_gddthresh_c ; fates_phen_gddthresh_c:units = "none" ; fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_mindaysoff ; - fates_phen_mindaysoff:units = "days" ; - fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves became off-allometry" ; double fates_phen_mindayson ; fates_phen_mindayson:units = "days" ; fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; - double fates_phen_moist_threshold ; - fates_phen_moist_threshold:units = "m3/m3 or mm" ; - fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for drought semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; double fates_phen_ncolddayslim ; fates_phen_ncolddayslim:units = "days" ; fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; @@ -1243,6 +1243,9 @@ data: fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_phen_drought_threshold = 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, + 0.15, 0.15, 0.15, 0.15 ; + fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, @@ -1250,6 +1253,11 @@ data: fates_phen_fnrt_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_phen_mindaysoff = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 ; + + fates_phen_moist_threshold = 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, + 0.18, 0.18, 0.18, 0.18 ; + fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; @@ -1508,20 +1516,14 @@ data: fates_phen_coldtemp = 7.5 ; - fates_phen_drought_threshold = 0.15 ; - fates_phen_gddthresh_a = -68 ; fates_phen_gddthresh_b = 638 ; fates_phen_gddthresh_c = -0.01 ; - fates_phen_mindaysoff = 100 ; - fates_phen_mindayson = 90 ; - fates_phen_moist_threshold = 0.18 ; - fates_phen_ncolddayslim = 5 ; fates_q10_froz = 1.5 ; diff --git a/parteh/PRTParametersMod.F90 b/parteh/PRTParametersMod.F90 index 4d2721800b..97f9e2c3a2 100644 --- a/parteh/PRTParametersMod.F90 +++ b/parteh/PRTParametersMod.F90 @@ -28,8 +28,23 @@ module PRTParametersMod ! Drop fraction for tissues other than leaves (PFT-dependent) real(r8), allocatable :: phen_fnrt_drop_fraction(:) ! Abscission fraction of fine roots real(r8), allocatable :: phen_stem_drop_fraction(:) ! Abscission fraction of stems + real(r8), allocatable :: phen_drought_threshold(:) ! For obligate (hard) drought deciduous, this is the threshold + ! below which plants will abscise leaves, and + ! above which plants will flush leaves. For semi-deciduous + ! plants, this is the threshold below which abscission will + ! be complete. This depends on the sign. If positive, these + ! are soil volumetric water content [m3/m3]. If + ! negative, the values are soil matric potential [mm]. + ! Ignored for non-deciduous plants. + real(r8), allocatable :: phen_moist_threshold(:) ! For semi-deciduous, this is the threshold above which flushing + ! will be complete. This depends on the sign. If positive, these + ! are soil volumetric water content [m3/m3]. If + ! negative, the values are soil matric potential [mm]. + ! Ignored for non-deciduous plants. + real(r8), allocatable :: phen_doff_time(:) ! Minimum number of days that plants must remain leafless before + ! flushing leaves again. + - ! Growth and Turnover Parameters real(r8), allocatable :: senleaf_long_fdrought(:) ! Multiplication factor for leaf longevity of senescent ! leaves during drought( 1.0 indicates no change) diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index d88c13202a..ab42176146 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -165,6 +165,26 @@ subroutine PRTRegisterPFT(fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_phen_stem_drop_fraction' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_phen_fnrt_drop_fraction' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_phen_mindaysoff' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_phen_drought_threshold' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_phen_moist_threshold' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_allom_fnrt_prof_a' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -429,6 +449,22 @@ subroutine PRTReceivePFT(fates_params) call ArrayNint(tmpreal,prt_params%evergreen) deallocate(tmpreal) + name = 'fates_phen_stem_drop_fraction' + call fates_params%RetrieveParameterAllocate(name=name, & + data=prt_params%phen_stem_drop_fraction) + + name = 'fates_phen_fnrt_drop_fraction' + call fates_params%RetrieveParameterAllocate(name=name, & + data=prt_params%phen_fnrt_drop_fraction) + + name = 'fates_phen_drought_threshold' + call fates_params%RetrieveParameterAllocate(name=name, & + data=prt_params%phen_drought_threshold) + + name = 'fates_phen_mindaysoff' + call fates_params%RetrieveParameterAllocate(name=name, & + data=prt_params%phen_doff_time) + name = 'fates_leaf_slamax' call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%slamax) @@ -873,6 +909,11 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmti) 'stress_decid = ',prt_params%stress_decid write(fates_log(),fmti) 'season_decid = ',prt_params%season_decid write(fates_log(),fmti) 'evergreen = ',prt_params%evergreen + write(fates_log(),fmt0) 'phen_fnrt_drop_fraction = ',prt_params%phen_fnrt_drop_fraction + write(fates_log(),fmt0) 'phen_stem_drop_fraction = ',prt_params%phen_stem_drop_fraction + write(fates_log(),fmt0) 'phen_drought_threshold = ',prt_params%phen_drought_threshold + write(fates_log(),fmt0) 'phen_moist_threshold = ',prt_params%phen_moist_threshold + write(fates_log(),fmt0) 'phen_doff_time = ',prt_params%phen_doff_time write(fates_log(),fmt0) 'wood_density = ',prt_params%wood_density write(fates_log(),fmt0) 'dbh max height = ',prt_params%allom_dbh_maxheight write(fates_log(),fmt0) 'dbh mature = ',prt_params%dbh_repro_threshold @@ -996,6 +1037,7 @@ subroutine PRTCheckParams(is_master) logical :: is_evergreen ! Is the PFT evergreen logical :: is_season_decid ! Is the PFT cold-deciduous? logical :: is_stress_decid ! Is the PFT drought-deciduous? + logical :: is_semi_decid ! Is the PFT drought semi-deciduous? npft = size(prt_params%evergreen,1) @@ -1067,6 +1109,7 @@ subroutine PRTCheckParams(is_master) is_evergreen = prt_params%evergreen(ipft) == itrue is_season_decid = prt_params%season_decid(ipft) == itrue is_stress_decid = any(prt_params%stress_decid(ipft) == [ihard_stress_decid,isemi_stress_decid]) + is_semi_decid = prt_params%stress_decid(ipft) == isemi_stress_decid if ( ( is_evergreen .and. is_season_decid ) .or. & ( is_evergreen .and. is_stress_decid ) .or. & @@ -1080,10 +1123,86 @@ subroutine PRTCheckParams(is_master) write(fates_log(),*) 'evergreen: ',prt_params%evergreen(ipft) write(fates_log(),*) 'Aborting' call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + ! When using the the drought semi-deciduous phenology, we must ensure that the lower + ! and upper thresholds are consistent (i.e., that both are based on either soil + ! water content or soil matric potential). + if (is_semi_decid) then + if ( prt_params%phen_drought_threshold(ipft)*prt_params%phen_moist_threshold(ipft) < 0._r8 ) then + ! In case the product of the lower and upper thresholds is negative, the + ! thresholds are inconsistent as both should be defined using the same + ! quantity. + write(fates_log(),*) ' When using drought semi-deciduous phenology,' + write(fates_log(),*) ' the moist threshold must have the same sign as' + write(fates_log(),*) ' the dry threshold. Positive = soil water content [m3/m3],' + write(fates_log(),*) ' Negative = soil matric potential [mm].' + write(fates_log(),*) ' PFT = ',ipft + write(fates_log(),*) ' Stress_decid = ',prt_params%stress_decid(ipft) + write(fates_log(),*) ' fates_phen_drought_threshold = ',prt_params%phen_drought_threshold(ipft) + write(fates_log(),*) ' fates_phen_moist_threshold = ',prt_params%phen_moist_threshold (ipft) + write(fates_log(),*) ' Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + + elseif ( prt_params%phen_drought_threshold(ipft) >= prt_params%phen_moist_threshold(ipft) ) then + write(fates_log(),*) ' When using drought semi-deciduous phenology,' + write(fates_log(),*) ' the moist threshold must be greater than the dry threshold.' + write(fates_log(),*) ' By greater we mean more positive or less negative, and' + write(fates_log(),*) ' they cannot be the identical.' + write(fates_log(),*) ' PFT = ',ipft + write(fates_log(),*) ' Stress_decid = ',prt_params%stress_decid(ipft) + write(fates_log(),*) ' fates_phen_drought_threshold = ',prt_params%phen_drought_threshold(ipft) + write(fates_log(),*) ' fates_phen_moist_threshold = ',prt_params%phen_moist_threshold (ipft) + write(fates_log(),*) ' Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + end if + + ! For all deciduous PFTs, check that abscission fractions are all bounded. + if (prt_params%evergreen(ipft) == ifalse) then + ! Check if the fraction of fine roots to be actively abscised relative to leaf abscission + ! is bounded between 0 and 1 (exactly 0 and 1 are acceptable). + if ( ( prt_params%phen_fnrt_drop_fraction(ipft) < 0.0_r8 ) .or. & + ( prt_params%phen_fnrt_drop_fraction(ipft) > 1.0_r8 ) ) then + write(fates_log(),*) ' Abscission rate for fine roots must be between 0 and 1 for ' + write(fates_log(),*) ' deciduous PFTs.' + write(fates_log(),*) ' PFT#: ',ipft + write(fates_log(),*) ' evergreen flag: (should be 0):',prt_params%evergreen(ipft) + write(fates_log(),*) ' phen_fnrt_drop_fraction: ', prt_params%phen_fnrt_drop_fraction(ipft) + write(fates_log(),*) ' Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + + ! Check if the fraction of stems to be actively abscised relative to leaf abscission + ! is bounded between 0 and 1 (exactly 0 and 1 are acceptable) when PFTs are non-woody, and + ! that the fraction is zero for woody PFTs. Stem abscission is a solution to avoid hydraulic + ! problems when plant hydraulics is enabled. + if ( ( prt_params%woody(ipft) == itrue ) .and. & + ( ( prt_params%phen_stem_drop_fraction(ipft) < 0.0_r8 ) .or. & + ( prt_params%phen_stem_drop_fraction(ipft) > nearzero ) ) ) then + write(fates_log(),*) ' Non-zero stem-drop fractions are not allowed for woody plants' + write(fates_log(),*) ' PFT#: ',ipft + write(fates_log(),*) ' part_params%woody:',prt_params%woody(ipft) + write(fates_log(),*) ' phen_stem_drop_fraction: ', prt_params%phen_stem_drop_fraction(ipft) + write(fates_log(),*) ' Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + elseif ( ( prt_params%phen_stem_drop_fraction(ipft) < 0.0_r8 ) .or. & + ( prt_params%phen_stem_drop_fraction(ipft) > 1.0_r8 ) ) then + write(fates_log(),*) ' Deciduous non-wood plants must keep 0-100% of their stems' + write(fates_log(),*) ' during the deciduous period.' + write(fates_log(),*) ' PFT#: ',ipft + write(fates_log(),*) ' evergreen flag: (should be 0):',prt_params%evergreen(ipft) + write(fates_log(),*) ' phen_stem_drop_fraction: ', prt_params%phen_stem_drop_fraction(ipft) + write(fates_log(),*) ' Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + end if + + + + ! Check to see if mature and base seed allocation is greater than 1 ! ---------------------------------------------------------------------------------- if ( ( prt_params%seed_alloc(ipft) + & From b570b36f0badecbfd7533af7747cafb3194eb94a Mon Sep 17 00:00:00 2001 From: Marcos Longo Date: Tue, 20 Dec 2022 21:33:47 -0800 Subject: [PATCH 474/852] Bug fix in PRTParamsFATESMod.F90. Missing allocation of phen_moist_threshold is fixed. --- parteh/PRTParamsFATESMod.F90 | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index ab42176146..f658179212 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -457,13 +457,17 @@ subroutine PRTReceivePFT(fates_params) call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%phen_fnrt_drop_fraction) + name = 'fates_phen_mindaysoff' + call fates_params%RetrieveParameterAllocate(name=name, & + data=prt_params%phen_doff_time) + name = 'fates_phen_drought_threshold' call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%phen_drought_threshold) - name = 'fates_phen_mindaysoff' + name = 'fates_phen_moist_threshold' call fates_params%RetrieveParameterAllocate(name=name, & - data=prt_params%phen_doff_time) + data=prt_params%phen_moist_threshold) name = 'fates_leaf_slamax' call fates_params%RetrieveParameterAllocate(name=name, & @@ -911,9 +915,9 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmti) 'evergreen = ',prt_params%evergreen write(fates_log(),fmt0) 'phen_fnrt_drop_fraction = ',prt_params%phen_fnrt_drop_fraction write(fates_log(),fmt0) 'phen_stem_drop_fraction = ',prt_params%phen_stem_drop_fraction + write(fates_log(),fmt0) 'phen_doff_time = ',prt_params%phen_doff_time write(fates_log(),fmt0) 'phen_drought_threshold = ',prt_params%phen_drought_threshold write(fates_log(),fmt0) 'phen_moist_threshold = ',prt_params%phen_moist_threshold - write(fates_log(),fmt0) 'phen_doff_time = ',prt_params%phen_doff_time write(fates_log(),fmt0) 'wood_density = ',prt_params%wood_density write(fates_log(),fmt0) 'dbh max height = ',prt_params%allom_dbh_maxheight write(fates_log(),fmt0) 'dbh mature = ',prt_params%dbh_repro_threshold From eb609b595a1f5bb83f0e174fa80a19dac64d151a Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 6 Jan 2023 16:36:48 -0500 Subject: [PATCH 475/852] all_carbon to carbon12 --- biogeochem/EDLoggingMortalityMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index b42b90ddc9..f711f3bcef 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -480,8 +480,8 @@ subroutine get_harvestable_carbon (csite, site_area, hlm_harvest_catnames, harve ! only account for cohorts matching the following conditions if(int(prt_params%woody(pft)) == 1)then ! only set logging rates for trees - sapw_m = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) - struct_m = currentCohort%prt%GetState(struct_organ, all_carbon_elements) + sapw_m = currentCohort%prt%GetState(sapw_organ, carbon12_element) + struct_m = currentCohort%prt%GetState(struct_organ, carbon12_element) ! logging_direct_frac shall be 1 for LUH2 driven simulation and global simulation ! in site level study logging_direct_frac shall be surveyed ! unit: [kgC ] = [kgC/plant] * [plant/ha] * [ha/ 10k m2] * [ m2 area ] From 9e1c255a3d7cb062c4c63ff239a40dec3d3f8dbb Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Fri, 6 Jan 2023 15:27:15 -0800 Subject: [PATCH 476/852] Fix m3_mortality history variables. --- main/FatesHistoryInterfaceMod.F90 | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 836c532a02..9ae7a90be9 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2887,6 +2887,9 @@ subroutine update_history_dyn(this,nc,nsites,sites) (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & ccohort%n * sec_per_day * days_per_year / m2_per_ha + hio_m3_mortality_canopy_si_scpf(io_si,scpf) = hio_m3_mortality_canopy_si_scpf(io_si,scpf) + & + ccohort%cmort * ccohort%n / m2_per_ha + hio_nplant_canopy_si_scpf(io_si,scpf) = hio_nplant_canopy_si_scpf(io_si,scpf) + ccohort%n / m2_per_ha hio_nplant_canopy_si_scls(io_si,scls) = hio_nplant_canopy_si_scls(io_si,scls) + ccohort%n / m2_per_ha hio_lai_canopy_si_scls(io_si,scls) = hio_lai_canopy_si_scls(io_si,scls) + & @@ -2914,6 +2917,9 @@ subroutine update_history_dyn(this,nc,nsites,sites) (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & ccohort%n * sec_per_day * days_per_year / m2_per_ha + hio_m3_mortality_canopy_si_scls(io_si,scls) = hio_m3_mortality_canopy_si_scls(io_si,scls) + & + ccohort%cmort * ccohort%n / m2_per_ha + hio_canopy_mortality_carbonflux_si(io_si) = hio_canopy_mortality_carbonflux_si(io_si) + & (ccohort%bmort + ccohort%hmort + ccohort%cmort + & ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * & @@ -3025,6 +3031,9 @@ subroutine update_history_dyn(this,nc,nsites,sites) (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & ccohort%n * sec_per_day * days_per_year / m2_per_ha + hio_m3_mortality_understory_si_scpf(io_si,scpf) = hio_m3_mortality_understory_si_scpf(io_si,scpf) + & + ccohort%cmort * ccohort%n / m2_per_ha + hio_nplant_understory_si_scpf(io_si,scpf) = hio_nplant_understory_si_scpf(io_si,scpf) + ccohort%n / m2_per_ha hio_nplant_understory_si_scls(io_si,scls) = hio_nplant_understory_si_scls(io_si,scls) + ccohort%n / m2_per_ha hio_lai_understory_si_scls(io_si,scls) = hio_lai_understory_si_scls(io_si,scls) + & @@ -3053,6 +3062,9 @@ subroutine update_history_dyn(this,nc,nsites,sites) (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & ccohort%n * sec_per_day * days_per_year / m2_per_ha + hio_m3_mortality_understory_si_scls(io_si,scls) = hio_m3_mortality_understory_si_scls(io_si,scls) + & + ccohort%cmort * ccohort%n / m2_per_ha + hio_understory_mortality_carbonflux_si(io_si) = hio_understory_mortality_carbonflux_si(io_si) + & (ccohort%bmort + ccohort%hmort + ccohort%cmort + & ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * & From 57572d36919d2ce97e94ae2773634d4ccfe1250a Mon Sep 17 00:00:00 2001 From: ckoven Date: Thu, 12 Jan 2023 09:57:28 -0700 Subject: [PATCH 477/852] added history diagnostic for running-mean Tgrowth variable --- main/FatesHistoryInterfaceMod.F90 | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index db90a49650..6863c10c65 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -322,6 +322,7 @@ module FatesHistoryInterfaceMod ! Indices to (site) variables integer :: ih_tveg24_si + integer :: ih_tgrowth_si integer :: ih_tveg_si integer :: ih_nep_si integer :: ih_hr_si @@ -2428,6 +2429,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_dleafoff_si => this%hvars(ih_dleafoff_si)%r81d, & hio_dleafon_si => this%hvars(ih_dleafon_si)%r81d, & hio_tveg24 => this%hvars(ih_tveg24_si)%r81d, & + hio_tgrowth => this%hvars(ih_tgrowth_si)%r81d, & hio_meanliqvol_si => this%hvars(ih_meanliqvol_si)%r81d, & hio_cbal_err_fates_si => this%hvars(ih_cbal_err_fates_si)%r81d, & hio_err_fates_si => this%hvars(ih_err_fates_si)%r82d ) @@ -2593,6 +2595,10 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_tveg24(io_si) = hio_tveg24(io_si) + & (cpatch%tveg24%GetMean()- t_water_freeze_k_1atm)*cpatch%area*AREA_INV + ! long-term running mean veg temperature (tgrowth) + hio_tgrowth(io_si) = hio_tgrowth(io_si) + & + (cpatch%tveg_lpa%GetMean()- t_water_freeze_k_1atm)*cpatch%area*AREA_INV + ! Increment some patch-age-resolved diagnostics hio_lai_si_age(io_si,cpatch%age_class) = hio_lai_si_age(io_si,cpatch%age_class) & @@ -6047,6 +6053,12 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_tveg24_si ) + call this%set_history_var(vname='FATES_TGROWTH', units='degree_Celsius', & + long='fates long-term running mean vegetation temperature by site', & + use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_tgrowth_si ) + call this%set_history_var(vname='FATES_TVEG', units='degree_Celsius', & long='fates instantaneous mean vegetation temperature by site', & use_default='active', & From 9fcdfa8c740146e8634c94e274f6f6db07291a70 Mon Sep 17 00:00:00 2001 From: ckoven Date: Thu, 12 Jan 2023 10:14:30 -0700 Subject: [PATCH 478/852] added history diagnostic for unreduced maintenance respiration --- biogeochem/EDCohortDynamicsMod.F90 | 3 +++ biogeophys/FatesPlantRespPhotosynthMod.F90 | 3 +++ main/EDTypesMod.F90 | 1 + main/FatesHistoryInterfaceMod.F90 | 11 +++++++++++ 4 files changed, 18 insertions(+) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 70756393d8..c6d880e527 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -611,6 +611,7 @@ subroutine nan_cohort(cc_p) !RESPIRATION currentCohort%rdark = nan currentCohort%resp_m = nan ! Maintenance respiration. kGC/cohort/year + currentCohort%resp_m_unreduced = nan ! Diagnostic-only unreduced Maintenance respiration. kGC/cohort/year currentCohort%resp_excess = nan ! Respiration of excess (unallocatable) carbon (kg/indiv/day) currentCohort%livestem_mr = nan ! Live stem maintenance respiration. kgC/indiv/s-1 currentCohort%livecroot_mr = nan ! Coarse root maintenance respiration. kgC/indiv/s-1 @@ -668,6 +669,7 @@ subroutine zero_cohort(cc_p) currentCohort%status_coh = 0 currentCohort%rdark = 0._r8 currentCohort%resp_m = 0._r8 + currentCohort%resp_m_unreduced = 0._r8 currentCohort%resp_excess = 0._r8 currentCohort%resp_g_tstep = 0._r8 currentCohort%livestem_mr = 0._r8 @@ -1916,6 +1918,7 @@ subroutine copy_cohort( currentCohort,copyc ) !RESPIRATION n%rdark = o%rdark n%resp_m = o%resp_m + n%resp_m_unreduced= o%resp_m_unreduced n%resp_excess = o%resp_excess n%resp_g_tstep = o%resp_g_tstep n%livestem_mr = o%livestem_mr diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index f4aaa41d0c..3ce9286df2 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -837,6 +837,9 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) currentCohort%resp_m = currentCohort%resp_m + currentCohort%rdark + ! save as a diagnostic the un-throttled maintenance respiration to be able to know how strong this is + currentCohort%resp_m_unreduced = currentCohort%resp_m / maintresp_reduction_factor + ! convert from kgC/indiv/s to kgC/indiv/timestep currentCohort%resp_m = currentCohort%resp_m * dtime currentCohort%gpp_tstep = currentCohort%gpp_tstep * dtime diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 4f198d6708..8175910910 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -339,6 +339,7 @@ module EDTypesMod real(r8) :: resp_g_tstep ! Growth respiration: kgC/indiv/timestep real(r8) :: resp_m ! Maintenance respiration: kgC/indiv/timestep + real(r8) :: resp_m_unreduced ! Diagnostic-only unreduced maintenance respiration: kgC/indiv/timestep real(r8) :: resp_excess ! Respiration of excess carbon kgC/indiv/day real(r8) :: livestem_mr ! Live stem maintenance respiration: kgC/indiv/s ! (Above ground) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 6863c10c65..718b7cae6e 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -292,6 +292,7 @@ module FatesHistoryInterfaceMod integer :: ih_gpp_understory_si integer :: ih_canopy_biomass_si integer :: ih_understory_biomass_si + integer :: ih_maint_resp_unreduced_si integer :: ih_primaryland_fusion_error_si integer :: ih_disturbance_rate_p2p_si @@ -4257,6 +4258,7 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) hio_fabi_sha_top_si_can => this%hvars(ih_fabi_sha_top_si_can)%r82d, & hio_parsun_top_si_can => this%hvars(ih_parsun_top_si_can)%r82d, & hio_parsha_top_si_can => this%hvars(ih_parsha_top_si_can)%r82d, & + hio_maint_resp_unreduced_si => this%hvars(ih_maint_resp_unreduced_si)%r81d, & hio_tveg => this%hvars(ih_tveg_si)%r81d) ! Flush the relevant history variables @@ -4347,6 +4349,9 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) hio_maint_resp_si(io_si) = hio_maint_resp_si(io_si) + & ccohort%resp_m * n_perm2 * per_dt_tstep + hio_maint_resp_unreduced_si(io_si) = hio_maint_resp_unreduced_si(io_si) + & + ccohort%resp_m_unreduced * n_perm2 * per_dt_tstep + ! Add up the total Net Ecosystem Production ! for this timestep. [kgC/m2/s] hio_nep_si(io_si) = hio_nep_si(io_si) + & @@ -6102,6 +6107,12 @@ subroutine define_history_vars(this, initialize_variables) upfreq=2, ivar=ivar, initialize=initialize_variables, & index = ih_maint_resp_si) + call this%set_history_var(vname='FATES_MAINT_RESP_UNREDUCED', units='kg m-2 s-1', & + long='diagnostic maintenance respiration if the low-carbon-storage reduction is ignored', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, & + index = ih_maint_resp_unreduced_si) + call this%set_history_var(vname='FATES_EXCESS_RESP', units='kg m-2 s-1', & long='respiration of un-allocatable carbon gain', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & From feaa22c0c022bbb5b086f16f1d130074220b0c3c Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Thu, 12 Jan 2023 15:16:39 -0700 Subject: [PATCH 479/852] added adjusted paritioning of stem wood (struct and sapw) to cwd in EDPhysiologyMod --- biogeochem/EDPhysiologyMod.F90 | 97 ++++++++++++++++++++++++++++------ 1 file changed, 81 insertions(+), 16 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 5eacaf00aa..b738edc92c 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -145,7 +145,6 @@ module EDPhysiologyMod integer, parameter :: dleafon_drycheck = 100 ! Drought deciduous leaves max days on check parameter - ! ============================================================================ contains @@ -232,7 +231,7 @@ subroutine GenerateDamageAndLitterFluxes( csite, cpatch, bc_in ) real(r8) :: store_loss ! "" [kg] real(r8) :: struct_loss ! "" [kg] real(r8) :: dcmpy_frac ! fraction of mass going to each decomposition pool - + real(r8), allocatable :: SF_val_CWD_frac_adj(:) !SF_val_CWD_frac adjusted based on cohort dbh if(hlm_use_tree_damage .ne. itrue) return @@ -322,16 +321,18 @@ subroutine GenerateDamageAndLitterFluxes( csite, cpatch, bc_in ) flux_diags%leaf_litter_input(ipft) = & flux_diags%leaf_litter_input(ipft) + & (store_loss+leaf_loss+repro_loss) * ndcohort%n + + call adjust_SF_CWD_frac(currentCohort%dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) do c = 1,ncwd litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + & (sapw_loss + struct_loss) * & - SF_val_CWD_frac(c) * ndcohort%n / & + SF_val_CWD_frac_adj(c) * ndcohort%n / & cpatch%area flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & (struct_loss + sapw_loss) * & - SF_val_CWD_frac(c) * ndcohort%n + SF_val_CWD_frac_adj(c) * ndcohort%n end do end do do_element @@ -2347,6 +2348,8 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) integer :: pft integer :: dcmpy ! decomposability pool index integer :: numlevsoil ! Actual number of soil layers + + real(r8), allocatable :: SF_val_CWD_frac_adj(:) !SF_val_CWD_frac adjusted based on cohort dbh !---------------------------------------------------------------------- ! ----------------------------------------------------------------------------------- @@ -2365,6 +2368,7 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) currentCohort => currentPatch%shortest do while(associated(currentCohort)) + pft = currentCohort%pft call set_root_fraction(currentSite%rootfrac_scr, pft, currentSite%zi_soil, & bc_in%max_rooting_depth_index_col) @@ -2437,18 +2441,22 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) ! Assumption: turnover from deadwood and sapwood are lumped together in CWD pool + !update partitioning of stem wood (struct + sapw) to cwd based on cohort dbh + call adjust_SF_CWD_frac(currentCohort%dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) + + do c = 1,ncwd litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + & (sapw_m_turnover + struct_m_turnover) * & - SF_val_CWD_frac(c) * plant_dens * & + SF_val_CWD_frac_adj(c) * plant_dens * & prt_params%allom_agb_frac(pft) flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & - (struct_m_turnover + sapw_m_turnover) * SF_val_CWD_frac(c) * & + (struct_m_turnover + sapw_m_turnover) * SF_val_CWD_frac_adj(c) * & prt_params%allom_agb_frac(pft) * currentCohort%n bg_cwd_tot = (sapw_m_turnover + struct_m_turnover) * & - SF_val_CWD_frac(c) * plant_dens * & + SF_val_CWD_frac_adj(c) * plant_dens * & (1.0_r8-prt_params%allom_agb_frac(pft)) do ilyr = 1, numlevsoil @@ -2529,7 +2537,7 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) ! Below-ground bg_cwd_tot = (struct_m + sapw_m) * & - SF_val_CWD_frac(c) * dead_n * & + SF_val_CWD_frac_adj(c) * dead_n * & (1.0_r8-prt_params%allom_agb_frac(pft)) do ilyr = 1, numlevsoil @@ -2548,7 +2556,7 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) trunk_wood = (struct_m + sapw_m) * & - SF_val_CWD_frac(c) * dead_n_dlogging * & + SF_val_CWD_frac_adj(c) * dead_n_dlogging * & prt_params%allom_agb_frac(pft) site_mass%wood_product = site_mass%wood_product + & @@ -2566,21 +2574,21 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) ! Add AG wood to litter from indirect anthro sources litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + (struct_m + sapw_m) * & - SF_val_CWD_frac(c) * (dead_n_natural+dead_n_ilogging) * & + SF_val_CWD_frac_adj(c) * (dead_n_natural+dead_n_ilogging) * & prt_params%allom_agb_frac(pft) flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & - SF_val_CWD_frac(c) * (dead_n_natural+dead_n_ilogging) * & + SF_val_CWD_frac_adj(c) * (dead_n_natural+dead_n_ilogging) * & currentPatch%area * prt_params%allom_agb_frac(pft) else litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + (struct_m + sapw_m) * & - SF_val_CWD_frac(c) * dead_n * & + SF_val_CWD_frac_adj(c) * dead_n * & prt_params%allom_agb_frac(pft) flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & - SF_val_CWD_frac(c) * dead_n * (struct_m + sapw_m) * & + SF_val_CWD_frac_adj(c) * dead_n * (struct_m + sapw_m) * & currentPatch%area * prt_params%allom_agb_frac(pft) end if @@ -2610,13 +2618,13 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) currentSite%resources_management%delta_litter_stock = & currentSite%resources_management%delta_litter_stock + & (struct_m + sapw_m) * & - SF_val_CWD_frac(c) * (dead_n_natural+dead_n_ilogging) * & + SF_val_CWD_frac_adj(c) * (dead_n_natural+dead_n_ilogging) * & currentPatch%area currentSite%resources_management%delta_biomass_stock = & currentSite%resources_management%delta_biomass_stock + & (struct_m + sapw_m) * & - SF_val_CWD_frac(c) * dead_n * currentPatch%area + SF_val_CWD_frac_adj(c) * dead_n * currentPatch%area end do ! Update diagnostics that track resource management @@ -2918,5 +2926,62 @@ subroutine SetRecruitL2FR(csite) return end subroutine SetRecruitL2FR - + + ! ======================================================================= + subroutine adjust_SF_CWD_frac(dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) + + !DESCRIPTION + !Adjust the partitioning of struct + sawp into cwd pools based on + !cohort dbh. This avoids struct and sapw from small cohorts going to + !1,000 hr fuels. Instead, struct + sapw go to the appropriate cwd pools + !based on established fuel class diameter thresholds. + + !ARGUMENTS + real(r8), intent(in) :: dbh !dbh of cohort + type(integer), intent(in) :: ncwd !number of cwd pools + real(r8), intent(in) :: SF_val_CWD_frac + real(r8), intent(out) :: SF_val_CWD_frac_adj + ! + !LOCAL VARIABLES + !These diameter ranges are based on work by Fosberg et al., 1971 + ! + real(r8), parameter :: lb_max_diam = 7.6 !max diameter [cm] for large branch + real(r8), parameter :: sb_max_diam = 2.5 !max diameter [cm] for small branch + real(r8), parameter :: twig_max_diam = 0.6 !max diameter [cm] for twig + !------------------------------------------------------------------------------------ + + + SF_val_CWD_frac_adj = SF_val_CWD_frac + + !If dbh is larger than max size of a large branch then we don't change + !how biomass is partitioned among cwd classes. + if (dbh > lb_max_diam) then + return + + !When dbh is greater than the max size of a small branch but less than or + !equal to the max size of a large branch we send the biomass that would have + !gone to trunk fuel to large branch fuel instead. + else if (dbh > sb_max_diam .and. dbh .le. lb_max_diam) then + SF_val_CWD_frac_adj(ncwd) = 0.0_r8 + SF_val_CWD_frac_adj(ncwd-1) = sum(SF_val_CWD_frac(ncwd-1:ncwd)) + + !When dbh is greater than the max size of a twig but less than or + !equal to the max size of a small branch we send the biomass that would have + !gone to trunk fuel / larger branch to small branch fuel instead. + else if (dbh > twig_max_diam .and. dbh .le. sb_max_diam) then + SF_val_CWD_frac_adj(ncwd) = 0.0_r8 + SF_val_CWD_frac_adj(ncwd-1) = 0.0_r8 + SF_val_CWD_frac_adj(ncwd-2) = sum(SF_val_CWD_frac(ncwd-2:ncwd)) + + !If dbh is less than or equal to the max size of a twig we send all + !biomass to twigs + else if (dbh .le. twig_max_diam) then + SF_val_CWD_frac_adj(ncwd) = 0.0_r8 + SF_val_CWD_frac_adj(ncwd-1) = 0.0_r8 + SF_val_CWD_frac_adj(ncwd-2) = 0.0_r8 + SF_val_CWD_frac_adj(ncwd-3) = sum(SF_val_CWD_frac) + + endif + + end subroutine adjust_SF_CWD_frac end module EDPhysiologyMod From 96ef187fed7cceabd9bf226810c3ca702dd3e495 Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Thu, 12 Jan 2023 20:00:42 -0700 Subject: [PATCH 480/852] added fixes to partitioning of wood to CWD. Model is running. --- biogeochem/EDCohortDynamicsMod.F90 | 14 ++++-- biogeochem/EDLoggingMortalityMod.F90 | 42 ++++++++-------- biogeochem/EDPatchDynamicsMod.F90 | 34 ++++++++----- biogeochem/EDPhysiologyMod.F90 | 64 ++----------------------- biogeochem/FatesLitterMod.F90 | 72 +++++++++++++++++++++++++++- 5 files changed, 127 insertions(+), 99 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 70756393d8..3570b5a1a3 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -33,6 +33,7 @@ Module EDCohortDynamicsMod use FatesLitterMod , only : ncwd use FatesLitterMod , only : ndcmpy use FatesLitterMod , only : litter_type + use FatesLitterMod , only : adjust_SF_CWD_frac use EDParamsMod , only : max_cohort_per_patch use EDTypesMod , only : AREA use EDTypesMod , only : min_npm2, min_nppatch @@ -974,7 +975,7 @@ subroutine SendCohortToLitter(csite,cpatch,ccohort,nplant,bc_in) integer :: crowndamage ! the crown damage class of the cohort integer :: sl ! loop index for soil layers integer :: dcmpy ! loop index for decomposability - + real(r8) :: SF_val_CWD_frac_adj(4) !Updated wood partitioning to CWD based on dbh !---------------------------------------------------------------------- pft = ccohort%pft @@ -1004,29 +1005,32 @@ subroutine SendCohortToLitter(csite,cpatch,ccohort,nplant,bc_in) litt => cpatch%litter(el) flux_diags => csite%flux_diags(el) + !adjust how wood is partitioned between the cwd classes based on cohort dbh + call adjust_SF_CWD_frac(ccohort%dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) + do c=1,ncwd ! above ground CWD litt%ag_cwd(c) = litt%ag_cwd(c) + plant_dens * & - (struct_m+sapw_m) * SF_val_CWD_frac(c) * & + (struct_m+sapw_m) * SF_val_CWD_frac_adj(c) * & prt_params%allom_agb_frac(pft) ! below ground CWD do sl=1,csite%nlevsoil litt%bg_cwd(c,sl) = litt%bg_cwd(c,sl) + plant_dens * & - (struct_m+sapw_m) * SF_val_CWD_frac(c) * & + (struct_m+sapw_m) * SF_val_CWD_frac_adj(c) * & (1.0_r8 - prt_params%allom_agb_frac(pft)) * & csite%rootfrac_scr(sl) enddo ! above ground flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & - (struct_m+sapw_m) * SF_val_CWD_frac(c) * & + (struct_m+sapw_m) * SF_val_CWD_frac_adj(c) * & prt_params%allom_agb_frac(pft) * nplant ! below ground flux_diags%cwd_bg_input(c) = flux_diags%cwd_bg_input(c) + & - (struct_m + sapw_m) * SF_val_CWD_frac(c) * & + (struct_m + sapw_m) * SF_val_CWD_frac_adj(c) * & (1.0_r8 - prt_params%allom_agb_frac(pft)) * nplant enddo diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index ab0b77b737..603307d7d6 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -21,6 +21,7 @@ module EDLoggingMortalityMod use FatesLitterMod , only : ncwd use FatesLitterMod , only : ndcmpy use FatesLitterMod , only : litter_type + use FatesLitterMod , only : adjust_SF_CWD_frac use EDTypesMod , only : ed_site_type use EDTypesMod , only : ed_resources_management_type use EDTypesMod , only : dtype_ilog @@ -502,7 +503,7 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site integer :: nlevsoil ! number of soil layers integer :: ilyr ! soil layer loop index integer :: el ! elemend loop index - + real(r8) :: SF_val_CWD_frac_adj(4) !Updated wood partitioning to CWD based on dbh nlevsoil = currentSite%nlevsoil @@ -601,37 +602,40 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site prt_params%allom_agb_frac(currentCohort%pft) bg_wood = (direct_dead+indirect_dead) * (struct_m + sapw_m ) * & (1._r8 - prt_params%allom_agb_frac(currentCohort%pft)) - - do c = 1,ncwd-1 + + !adjust how wood is partitioned between the cwd classes based on cohort dbh + call adjust_SF_CWD_frac(currentCohort%dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) + + do c = 1,ncwd-1 new_litt%ag_cwd(c) = new_litt%ag_cwd(c) + & - ag_wood * SF_val_CWD_frac(c) * donate_frac/newPatch%area + ag_wood * SF_val_CWD_frac_adj(c) * donate_frac/newPatch%area cur_litt%ag_cwd(c) = cur_litt%ag_cwd(c) + & - ag_wood * SF_val_CWD_frac(c) * retain_frac/remainder_area + ag_wood * SF_val_CWD_frac_adj(c) * retain_frac/remainder_area do ilyr = 1,nlevsoil new_litt%bg_cwd(c,ilyr) = new_litt%bg_cwd(c,ilyr) + & bg_wood * currentSite%rootfrac_scr(ilyr) * & - SF_val_CWD_frac(c) * donate_frac/newPatch%area + SF_val_CWD_frac_adj(c) * donate_frac/newPatch%area cur_litt%bg_cwd(c,ilyr) = cur_litt%bg_cwd(c,ilyr) + & bg_wood * currentSite%rootfrac_scr(ilyr) * & - SF_val_CWD_frac(c) * retain_frac/remainder_area + SF_val_CWD_frac_adj(c) * retain_frac/remainder_area end do ! Diagnostics on fluxes into the AG and BG CWD pools flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & - SF_val_CWD_frac(c) * ag_wood + SF_val_CWD_frac_adj(c) * ag_wood flux_diags%cwd_bg_input(c) = flux_diags%cwd_bg_input(c) + & - SF_val_CWD_frac(c) * bg_wood + SF_val_CWD_frac_adj(c) * bg_wood ! Diagnostic specific to resource management code if( element_id .eq. carbon12_element) then delta_litter_stock = delta_litter_stock + & - (ag_wood + bg_wood) * SF_val_CWD_frac(c) + (ag_wood + bg_wood) * SF_val_CWD_frac_adj(c) end if enddo @@ -646,39 +650,39 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site (1._r8 - prt_params%allom_agb_frac(currentCohort%pft)) new_litt%ag_cwd(ncwd) = new_litt%ag_cwd(ncwd) + ag_wood * & - SF_val_CWD_frac(ncwd) * donate_frac/newPatch%area + SF_val_CWD_frac_adj(ncwd) * donate_frac/newPatch%area cur_litt%ag_cwd(ncwd) = cur_litt%ag_cwd(ncwd) + ag_wood * & - SF_val_CWD_frac(ncwd) * retain_frac/remainder_area + SF_val_CWD_frac_adj(ncwd) * retain_frac/remainder_area do ilyr = 1,nlevsoil new_litt%bg_cwd(ncwd,ilyr) = new_litt%bg_cwd(ncwd,ilyr) + & bg_wood * currentSite%rootfrac_scr(ilyr) * & - SF_val_CWD_frac(ncwd) * donate_frac/newPatch%area + SF_val_CWD_frac_adj(ncwd) * donate_frac/newPatch%area cur_litt%bg_cwd(ncwd,ilyr) = cur_litt%bg_cwd(ncwd,ilyr) + & bg_wood * currentSite%rootfrac_scr(ilyr) * & - SF_val_CWD_frac(ncwd) * retain_frac/remainder_area + SF_val_CWD_frac_adj(ncwd) * retain_frac/remainder_area end do flux_diags%cwd_ag_input(ncwd) = flux_diags%cwd_ag_input(ncwd) + & - SF_val_CWD_frac(ncwd) * ag_wood + SF_val_CWD_frac_adj(ncwd) * ag_wood flux_diags%cwd_bg_input(ncwd) = flux_diags%cwd_bg_input(ncwd) + & - SF_val_CWD_frac(ncwd) * bg_wood + SF_val_CWD_frac_adj(ncwd) * bg_wood if( element_id .eq. carbon12_element) then delta_litter_stock = delta_litter_stock + & - (ag_wood+bg_wood) * SF_val_CWD_frac(ncwd) + (ag_wood+bg_wood) * SF_val_CWD_frac_adj(ncwd) end if ! --------------------------------------------------------------------------------------- ! Handle below-ground trunk flux for directly logged trees (c = ncwd) ! ---------------------------------------------------------------------------------------- - bg_wood = direct_dead * (struct_m + sapw_m ) * SF_val_CWD_frac(ncwd) * & + bg_wood = direct_dead * (struct_m + sapw_m ) * SF_val_CWD_frac_adj(ncwd) * & (1._r8 - prt_params%allom_agb_frac(currentCohort%pft)) do ilyr = 1,nlevsoil @@ -705,7 +709,7 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site ag_wood = direct_dead * (struct_m + sapw_m ) * & prt_params%allom_agb_frac(currentCohort%pft) * & - SF_val_CWD_frac(ncwd) + SF_val_CWD_frac_adj(ncwd) trunk_product_site = trunk_product_site + & ag_wood * logging_export_frac diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index dba1a67d13..38e1c583c1 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -16,6 +16,7 @@ module EDPatchDynamicsMod use FatesLitterMod , only : ncwd use FatesLitterMod , only : ndcmpy use FatesLitterMod , only : litter_type + use FatesLitterMod , only : adjust_SF_CWD_frac use EDTypesMod , only : homogenize_seed_pfts use EDTypesMod , only : n_dbh_bins, area, patchfusion_dbhbin_loweredges use EDtypesMod , only : force_patchfuse_min_biomass @@ -90,7 +91,7 @@ module EDPatchDynamicsMod use EDParamsMod, only : maxpatch_secondary use EDParamsMod, only : maxpatch_total use FatesRunningMeanMod, only : ema_24hr, fixed_24hr, ema_lpa - + ! CIME globals use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) use shr_log_mod , only : errMsg => shr_log_errMsg @@ -1603,7 +1604,7 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & integer :: pft ! loop index for plant functional types integer :: dcmpy ! loop index for decomposability pool integer :: element_id ! parteh compatible global element index - + real(r8) :: SF_val_CWD_frac_adj(4) !Updated wood partitioning to CWD based on dbh !--------------------------------------------------------------------- ! Only do this if there was a fire in this actual patch. @@ -1736,9 +1737,13 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & bcroot = (sapw_m + struct_m) * (1.0_r8 - prt_params%allom_agb_frac(pft) ) ! below ground coarse woody debris from burned trees + + !adjust the how wood is partitioned between the cwd classes based on cohort dbh + call adjust_SF_CWD_frac(currentCohort%dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) + do c = 1,ncwd do sl = 1,currentSite%nlevsoil - donatable_mass = num_dead_trees * SF_val_CWD_frac(c) * & + donatable_mass = num_dead_trees * SF_val_CWD_frac_adj(c) * & bcroot * currentSite%rootfrac_scr(sl) new_litt%bg_cwd(c,sl) = new_litt%bg_cwd(c,sl) + & @@ -1759,10 +1764,10 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & ! Above ground coarse woody debris from twigs and small branches ! a portion of this pool may burn do c = 1,ncwd - donatable_mass = num_dead_trees * SF_val_CWD_frac(c) * bstem + donatable_mass = num_dead_trees * SF_val_CWD_frac_adj(c) * bstem if (c == 1 .or. c == 2) then donatable_mass = donatable_mass * (1.0_r8-currentCohort%fraction_crown_burned) - burned_mass = num_dead_trees * SF_val_CWD_frac(c) * bstem * & + burned_mass = num_dead_trees * SF_val_CWD_frac_adj(c) * bstem * & currentCohort%fraction_crown_burned site_mass%burn_flux_to_atm = site_mass%burn_flux_to_atm + burned_mass endif @@ -1835,7 +1840,8 @@ subroutine mortality_litter_fluxes(currentSite, currentPatch, & integer :: el ! element loop index integer :: sl ! soil layer index integer :: element_id ! parteh compatible global element index - real(r8) :: dcmpy_frac ! decomposability fraction + real(r8) :: dcmpy_frac ! decomposability fraction + real(r8) :: SF_val_CWD_frac_adj(4) !Updated wood partitioning to CWD based on dbh !--------------------------------------------------------------------- remainder_area = currentPatch%area - patch_site_areadis @@ -1933,24 +1939,26 @@ subroutine mortality_litter_fluxes(currentSite, currentPatch, & call set_root_fraction(currentSite%rootfrac_scr, pft, currentSite%zi_soil, & bc_in%max_rooting_depth_index_col) + ! Adjust how wood is partitioned between the cwd classes based on cohort dbh + call adjust_SF_CWD_frac(currentCohort%dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) do c=1,ncwd - + ! Transfer wood of dying trees to AG CWD pools new_litt%ag_cwd(c) = new_litt%ag_cwd(c) + ag_wood * & - SF_val_CWD_frac(c) * donate_m2 + SF_val_CWD_frac_adj(c) * donate_m2 curr_litt%ag_cwd(c) = curr_litt%ag_cwd(c) + ag_wood * & - SF_val_CWD_frac(c) * retain_m2 + SF_val_CWD_frac_adj(c) * retain_m2 ! Transfer wood of dying trees to BG CWD pools do sl = 1,currentSite%nlevsoil new_litt%bg_cwd(c,sl) = new_litt%bg_cwd(c,sl) + bg_wood * & - currentSite%rootfrac_scr(sl) * SF_val_CWD_frac(c) * & + currentSite%rootfrac_scr(sl) * SF_val_CWD_frac_adj(c) * & donate_m2 curr_litt%bg_cwd(c,sl) = curr_litt%bg_cwd(c,sl) + bg_wood * & - currentSite%rootfrac_scr(sl) * SF_val_CWD_frac(c) * & + currentSite%rootfrac_scr(sl) * SF_val_CWD_frac_adj(c) * & retain_m2 end do end do @@ -1986,10 +1994,10 @@ subroutine mortality_litter_fluxes(currentSite, currentPatch, & ! track diagnostic fluxes do c=1,ncwd flux_diags%cwd_ag_input(c) = & - flux_diags%cwd_ag_input(c) + SF_val_CWD_frac(c) * ag_wood + flux_diags%cwd_ag_input(c) + SF_val_CWD_frac_adj(c) * ag_wood flux_diags%cwd_bg_input(c) = & - flux_diags%cwd_bg_input(c) + SF_val_CWD_frac(c) * bg_wood + flux_diags%cwd_bg_input(c) + SF_val_CWD_frac_adj(c) * bg_wood end do flux_diags%leaf_litter_input(pft) = flux_diags%leaf_litter_input(pft) + & diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index b738edc92c..6d5fa103df 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -48,6 +48,7 @@ module EDPhysiologyMod use FatesLitterMod , only : ilabile use FatesLitterMod , only : ilignin use FatesLitterMod , only : icellulose + use FatesLitterMod , only : adjust_SF_CWD_frac use EDTypesMod , only : nclmax use EDTypesMod , only : AREA,AREA_INV use EDTypesMod , only : nlevleaf @@ -231,7 +232,7 @@ subroutine GenerateDamageAndLitterFluxes( csite, cpatch, bc_in ) real(r8) :: store_loss ! "" [kg] real(r8) :: struct_loss ! "" [kg] real(r8) :: dcmpy_frac ! fraction of mass going to each decomposition pool - real(r8), allocatable :: SF_val_CWD_frac_adj(:) !SF_val_CWD_frac adjusted based on cohort dbh + real(r8) :: SF_val_CWD_frac_adj(4) !SF_val_CWD_frac adjusted based on cohort dbh if(hlm_use_tree_damage .ne. itrue) return @@ -322,7 +323,7 @@ subroutine GenerateDamageAndLitterFluxes( csite, cpatch, bc_in ) flux_diags%leaf_litter_input(ipft) + & (store_loss+leaf_loss+repro_loss) * ndcohort%n - call adjust_SF_CWD_frac(currentCohort%dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) + call adjust_SF_CWD_frac(ndcohort%dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) do c = 1,ncwd litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + & @@ -2349,7 +2350,7 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) integer :: dcmpy ! decomposability pool index integer :: numlevsoil ! Actual number of soil layers - real(r8), allocatable :: SF_val_CWD_frac_adj(:) !SF_val_CWD_frac adjusted based on cohort dbh + real(r8) :: SF_val_CWD_frac_adj(4) !SF_val_CWD_frac adjusted based on cohort dbh !---------------------------------------------------------------------- ! ----------------------------------------------------------------------------------- @@ -2927,61 +2928,4 @@ subroutine SetRecruitL2FR(csite) return end subroutine SetRecruitL2FR - ! ======================================================================= - subroutine adjust_SF_CWD_frac(dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) - - !DESCRIPTION - !Adjust the partitioning of struct + sawp into cwd pools based on - !cohort dbh. This avoids struct and sapw from small cohorts going to - !1,000 hr fuels. Instead, struct + sapw go to the appropriate cwd pools - !based on established fuel class diameter thresholds. - - !ARGUMENTS - real(r8), intent(in) :: dbh !dbh of cohort - type(integer), intent(in) :: ncwd !number of cwd pools - real(r8), intent(in) :: SF_val_CWD_frac - real(r8), intent(out) :: SF_val_CWD_frac_adj - ! - !LOCAL VARIABLES - !These diameter ranges are based on work by Fosberg et al., 1971 - ! - real(r8), parameter :: lb_max_diam = 7.6 !max diameter [cm] for large branch - real(r8), parameter :: sb_max_diam = 2.5 !max diameter [cm] for small branch - real(r8), parameter :: twig_max_diam = 0.6 !max diameter [cm] for twig - !------------------------------------------------------------------------------------ - - - SF_val_CWD_frac_adj = SF_val_CWD_frac - - !If dbh is larger than max size of a large branch then we don't change - !how biomass is partitioned among cwd classes. - if (dbh > lb_max_diam) then - return - - !When dbh is greater than the max size of a small branch but less than or - !equal to the max size of a large branch we send the biomass that would have - !gone to trunk fuel to large branch fuel instead. - else if (dbh > sb_max_diam .and. dbh .le. lb_max_diam) then - SF_val_CWD_frac_adj(ncwd) = 0.0_r8 - SF_val_CWD_frac_adj(ncwd-1) = sum(SF_val_CWD_frac(ncwd-1:ncwd)) - - !When dbh is greater than the max size of a twig but less than or - !equal to the max size of a small branch we send the biomass that would have - !gone to trunk fuel / larger branch to small branch fuel instead. - else if (dbh > twig_max_diam .and. dbh .le. sb_max_diam) then - SF_val_CWD_frac_adj(ncwd) = 0.0_r8 - SF_val_CWD_frac_adj(ncwd-1) = 0.0_r8 - SF_val_CWD_frac_adj(ncwd-2) = sum(SF_val_CWD_frac(ncwd-2:ncwd)) - - !If dbh is less than or equal to the max size of a twig we send all - !biomass to twigs - else if (dbh .le. twig_max_diam) then - SF_val_CWD_frac_adj(ncwd) = 0.0_r8 - SF_val_CWD_frac_adj(ncwd-1) = 0.0_r8 - SF_val_CWD_frac_adj(ncwd-2) = 0.0_r8 - SF_val_CWD_frac_adj(ncwd-3) = sum(SF_val_CWD_frac) - - endif - - end subroutine adjust_SF_CWD_frac end module EDPhysiologyMod diff --git a/biogeochem/FatesLitterMod.F90 b/biogeochem/FatesLitterMod.F90 index be5ec48aa9..7198e1a92b 100644 --- a/biogeochem/FatesLitterMod.F90 +++ b/biogeochem/FatesLitterMod.F90 @@ -44,6 +44,7 @@ module FatesLitterMod implicit none private + public :: adjust_SF_CWD_frac integer, public, parameter :: ncwd = 4 ! number of coarse woody debris pools ! (twig,s branch,l branch, trunk) @@ -57,7 +58,6 @@ module FatesLitterMod type, public :: litter_type - ! This object is allocated for each element (C, N, P, etc) that we wish to track. @@ -424,6 +424,74 @@ function GetTotalLitterMass(this) result(total_mass) return end function GetTotalLitterMass - + + ! ===================================================== + + subroutine adjust_SF_CWD_frac(dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) + + !DESCRIPTION + !Adjust the partitioning of struct + sawp into cwd pools based on + !cohort dbh. This avoids struct and sapw from small cohorts going to + !1,000 hr fuels. Instead, struct + sapw go to the appropriate cwd pools + !based on established fuel class diameter thresholds. + + !ARGUMENTS + real(r8), intent(in) :: dbh !dbh of cohort + type(integer), intent(in) :: ncwd !number of cwd pools + real(r8), intent(in) :: SF_val_CWD_frac(:) + real(r8), intent(out) :: SF_val_CWD_frac_adj(:) + ! + !LOCAL VARIABLES + !These diameter ranges are based on work by Fosberg et al., 1971 + ! + real(r8), parameter :: lb_max_diam = 7.6 !max diameter [cm] for large branch + real(r8), parameter :: sb_max_diam = 2.5 !max diameter [cm] for small branch + real(r8), parameter :: twig_max_diam = 0.6 !max diameter [cm] for twig + !------------------------------------------------------------------------------------ + + + write(fates_log(),*) "SFvalCWDFrac:",SF_val_CWD_frac + write(fates_log(),*) "SFvalCWDFrac sum:",sum(SF_val_CWD_frac(2:4)) + write(fates_log(),*) "ncwd:",ncwd + !write(fates_log(),*) "SFvalCWDFrac:",SF_val_CWD_frac + + SF_val_CWD_frac_adj = SF_val_CWD_frac + + !If dbh is larger than max size of a large branch then we don't change + !how biomass is partitioned among cwd classes. + if (dbh > lb_max_diam) then + return + + !When dbh is greater than the max size of a small branch but less than or + !equal to the max size of a large branch we send the biomass that would have + !gone to trunk fuel to large branch fuel instead. + else if (dbh > sb_max_diam .and. dbh .le. lb_max_diam) then + SF_val_CWD_frac_adj(4) = 0.0 + !SF_val_CWD_frac_adj(ncwd-1) = sum(SF_val_CWD_frac((ncwd-1):ncwd)) + SF_val_CWD_frac_adj(3) = sum(SF_val_CWD_frac(3:4)) + + write(fates_log(),*) "using ahb trunk fuel fix", SF_val_CWD_frac_adj + + !When dbh is greater than the max size of a twig but less than or + !equal to the max size of a small branch we send the biomass that would have + !gone to trunk fuel / larger branch to small branch fuel instead. + else if (dbh > twig_max_diam .and. dbh .le. sb_max_diam) then + !SF_val_CWD_frac_adj(ncwd) = 0.0_r8 + SF_val_CWD_frac_adj(4) = 0.0 + !SF_val_CWD_frac_adj(ncwd-1) = 0.0_r8 + SF_val_CWD_frac_adj(3) = 0.0 + !SF_val_CWD_frac_adj(ncwd-2) = sum(SF_val_CWD_frac((ncwd-2):ncwd)) + SF_val_CWD_frac_adj(2) = sum(SF_val_CWD_frac(2:4)) + + !If dbh is less than or equal to the max size of a twig we send all + !biomass to twigs + else if (dbh .le. twig_max_diam) then + SF_val_CWD_frac_adj(ncwd) = 0.0 + SF_val_CWD_frac_adj(ncwd-1) = 0.0 + SF_val_CWD_frac_adj(ncwd-2) = 0.0 + SF_val_CWD_frac_adj(ncwd-3) = sum(SF_val_CWD_frac) + + endif + end subroutine adjust_SF_CWD_frac end module FatesLitterMod From f1f855d7e0ecdab32625f3b5cca15628c4507b86 Mon Sep 17 00:00:00 2001 From: Shijie Shu <92333861+sshu88@users.noreply.github.com> Date: Wed, 18 Jan 2023 11:33:41 -0800 Subject: [PATCH 481/852] Update EDPatchDynamicsMod.F90 --- biogeochem/EDPatchDynamicsMod.F90 | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 31557c1cf3..387ed5760c 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -195,12 +195,8 @@ subroutine disturbance_rates( site_in, bc_in) real(r8) :: frac_site_primary real(r8) :: harvest_rate real(r8) :: tempsum - real(r8) :: harvest_debt_pri - real(r8) :: harvest_debt_sec_mature - real(r8) :: harvest_debt_sec_young real(r8) :: harvestable_forest_c(hlm_num_lu_harvest_cats) integer :: harvest_tag(hlm_num_lu_harvest_cats) - integer :: patch_no_secondary !---------------------------------------------------------------------------------------------- ! Calculate Mortality Rates (these were previously calculated during growth derivatives) @@ -213,12 +209,6 @@ subroutine disturbance_rates( site_in, bc_in) ! get available biomass for harvest for all patches call get_harvestable_carbon(site_in, bc_in%site_area, bc_in%hlm_harvest_catnames, harvestable_forest_c) - ! Initialize local variables - patch_no_secondary = 0 - harvest_debt_pri = 0._r8 - harvest_debt_sec_mature = 0._r8 - harvest_debt_sec_young = 0._r8 - currentPatch => site_in%oldest_patch do while (associated(currentPatch)) @@ -260,11 +250,6 @@ subroutine disturbance_rates( site_in, bc_in) currentCohort => currentCohort%taller end do - ! ! Counter of secondary patch used in logging debt calculation - ! if ( currentPatch%anthro_disturbance_label .eq. secondaryforest ) then - ! patch_no_secondary = patch_no_secondary + 1 - ! end if - currentPatch => currentPatch%younger end do From 184c80f03b7d933cc3d5b7a63a4e8487367f28ca Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 18 Jan 2023 14:30:58 -0800 Subject: [PATCH 482/852] add check for fbg mode when setting site_area_veg and bareground initialization for area_pft --- main/EDInitMod.F90 | 6 ++---- main/FatesHistoryInterfaceMod.F90 | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 404e08b2ba..57f64c08cb 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -168,7 +168,7 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) allocate(site_in%dz_soil(site_in%nlevsoil)) allocate(site_in%z_soil(site_in%nlevsoil)) - if (hlm_use_nocomp .eq. itrue) then + if (hlm_use_nocomp .eq. itrue .and. hlm_use_fixed_biogeog .eq. itrue) then allocate(site_in%area_pft(0:numpft)) else ! SP and nocomp require a bare-ground patch. allocate(site_in%area_pft(1:numpft)) @@ -384,6 +384,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) sites(s)%acc_NI = acc_NI sites(s)%NF = 0.0_r8 sites(s)%NF_successful = 0.0_r8 + sites(s)%area_pft(:) = 0.0_r8 do ft = 1,numpft sites(s)%rec_l2fr(ft,:) = prt_params%allom_l2fr(ft) @@ -399,7 +400,6 @@ subroutine set_site_properties( nsites, sites,bc_in ) ! where pft_areafrac is the area of land in each HLM PFT and (from surface dataset) ! hlm_pft_map is the area of that land in each FATES PFT (from param file) - sites(s)%area_pft(1:numpft) = 0._r8 do hlm_pft = 1,size( EDPftvarcon_inst%hlm_pft_map,2) do fates_pft = 1,numpft ! loop round all fates pfts for all hlm pfts sites(s)%area_pft(fates_pft) = sites(s)%area_pft(fates_pft) + & @@ -453,8 +453,6 @@ subroutine set_site_properties( nsites, sites,bc_in ) if(sumarea.lt.area)then !make some bare ground sites(s)%area_pft(0) = area - sumarea - else - sites(s)%area_pft(0) = 0.0_r8 end if end if !sp mode end if !fixed biogeog diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index db90a49650..e9185a3da9 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -4273,7 +4273,7 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) canopy_area_by_age(1:nlevage) = 0._r8 ! Calculate the site-level total vegetated area (i.e. non-bareground) - if (hlm_use_nocomp .eq. itrue) then + if (hlm_use_nocomp .eq. itrue .and. hlm_use_fixed_biogeog .eq. itrue) then site_area_veg = area - sites(s)%area_pft(0) else site_area_veg = area From 98a46ace7294423f380aaa9071aaedd25894dff4 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 18 Jan 2023 15:34:44 -0800 Subject: [PATCH 483/852] add missing fbg use statement to history mod --- main/FatesHistoryInterfaceMod.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index e9185a3da9..cb3f9f38f8 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -52,6 +52,7 @@ module FatesHistoryInterfaceMod use FatesInterfaceTypesMod , only : hlm_model_day use FatesInterfaceTypesMod , only : nlevcoage use FatesInterfaceTypesMod , only : hlm_use_nocomp + use FatesInterfaceTypesMod , only : hlm_use_fixed_biogeog use FatesAllometryMod , only : CrownDepth use FatesAllometryMod , only : bstore_allom use FatesAllometryMod , only : set_root_fraction From 3a7320f29b91f0a32152c76e3f80e1ca49f196ab Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 18 Jan 2023 15:50:18 -0800 Subject: [PATCH 484/852] move site_area_veg outside of the logic check to default to area --- main/FatesHistoryInterfaceMod.F90 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index cb3f9f38f8..6c12a78a06 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -4274,10 +4274,9 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) canopy_area_by_age(1:nlevage) = 0._r8 ! Calculate the site-level total vegetated area (i.e. non-bareground) + site_area_veg = area if (hlm_use_nocomp .eq. itrue .and. hlm_use_fixed_biogeog .eq. itrue) then site_area_veg = area - sites(s)%area_pft(0) - else - site_area_veg = area end if cpatch => sites(s)%oldest_patch From b5cadd5703f37920b1c19d656d4603f691e021cb Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 19 Jan 2023 11:20:36 -0800 Subject: [PATCH 485/852] change sp mode check to broader and inclusive fbp+nocomp check --- biogeochem/EDPatchDynamicsMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index dba1a67d13..a6619b55d9 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1282,7 +1282,7 @@ subroutine set_patchno( currentSite ) currentPatch => currentPatch%younger enddo - if(hlm_use_sp.eq.itrue)then + if(hlm_use_fixed_biogeog.eq.itrue .and. hlm_use_nocomp.eq.itrue)then patchno = 1 currentPatch => currentSite%oldest_patch do while(associated(currentPatch)) From e27dd998b95b2be55d87cc0313e02075f7d9e357 Mon Sep 17 00:00:00 2001 From: Marcos Longo Date: Mon, 23 Jan 2023 12:44:34 -0800 Subject: [PATCH 486/852] Added comments on the different allom_stmode flags. --- biogeochem/FatesAllometryMod.F90 | 4 +--- parameter_files/fates_params_default.cdl | 2 +- parteh/PRTParametersMod.F90 | 6 +++++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index 39fe02cfee..7973d2e3bf 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -1089,8 +1089,6 @@ subroutine bstore_allom(d,ipft,crowndamage, canopy_trim,bstore,dbstoredd) real(r8) :: dblmaxdd ! Allometric target change in leaf biomass per cm (UNTRIMMED) - ! TODO: allom_stmode needs to be added to the parameter file - associate( allom_stmode => prt_params%allom_stmode(ipft), & cushion => prt_params%cushion(ipft) ) @@ -1102,7 +1100,7 @@ subroutine bstore_allom(d,ipft,crowndamage, canopy_trim,bstore,dbstoredd) call bstore_blcushion(d,bl,dbldd,cushion,ipft,bstore,dbstoredd) case(2) ! Storage is constant proportionality of untrimmed maximum leaf - ! biomass (ie cushion * bleaf) + ! biomass (ie cushion * bleaf_max) call blmax_allom(d,ipft,blmax,dblmaxdd) call bstore_blcushion(d,blmax,dblmaxdd,cushion,ipft,bstore,dbstoredd) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index d1fcd4c9a3..c5ddba36c6 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -148,7 +148,7 @@ variables: fates_allom_smode:long_name = "sapwood allometry function index." ; double fates_allom_stmode(fates_pft) ; fates_allom_stmode:units = "index" ; - fates_allom_stmode:long_name = "storage allometry function index." ; + fates_allom_stmode:long_name = "storage allometry function index: 1) Storage proportional to leaf biomass (with trimming), 2) Storage proportional to maximum leaf biomass (not trimmed)" ; double fates_allom_zroot_k(fates_pft) ; fates_allom_zroot_k:units = "unitless" ; fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; diff --git a/parteh/PRTParametersMod.F90 b/parteh/PRTParametersMod.F90 index 0346009745..1bd611edff 100644 --- a/parteh/PRTParametersMod.F90 +++ b/parteh/PRTParametersMod.F90 @@ -98,7 +98,11 @@ module PRTParametersMod real(r8), allocatable :: allom_amode(:) ! AGB allometry function type real(r8), allocatable :: allom_cmode(:) ! Coarse root allometry function type real(r8), allocatable :: allom_smode(:) ! sapwood allometry function type - real(r8), allocatable :: allom_stmode(:) ! storage allometry functional type + real(r8), allocatable :: allom_stmode(:) ! storage allometry functional type + ! 0 - storage is proportional to maximum leaf biomass + ! (considering trimmed) + ! 1 - storage is proportional to maximum leaf biomass + ! (untrimmed) ! (HARD-CODED FOR TIME BEING, RGK 11-2017) real(r8), allocatable :: allom_la_per_sa_int(:) ! Leaf area to sap area conversion, intercept ! (sapwood area / leaf area) [cm2/m2] From 9281b1c07fb99d667c385536a3099277097aa6e0 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 23 Jan 2023 17:28:55 -0700 Subject: [PATCH 487/852] add bareground checks for spitfire during nocomp+fbg mode --- fire/SFMainMod.F90 | 49 +++++++++++++++++++++++++++++++++++++++------- main/EDMainMod.F90 | 10 +++++++++- 2 files changed, 51 insertions(+), 8 deletions(-) diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index fdb3501bd2..0b6b098cdf 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -87,7 +87,7 @@ subroutine fire_model( currentSite, bc_in) type (ed_patch_type), pointer :: currentPatch !zero fire things - currentPatch => currentSite%youngest_patch + currentPatch => currentSite%oldest_patch do while(associated(currentPatch)) currentPatch%frac_burnt = 0.0_r8 currentPatch%fire = 0 @@ -140,9 +140,9 @@ subroutine fire_danger_index ( currentSite, bc_in) ! is simply using the values associated with the first patch. ! which probably won't have much inpact, unless we decide to ever calculated the NI for each patch. - iofp = currentSite%oldest_patch%patchno + iofp = currentSite%youngest_patch%patchno - temp_in_C = currentSite%oldest_patch%tveg24%GetMean() - tfrz + temp_in_C = currentSite%youngest_patch%tveg24%GetMean() - tfrz rainfall = bc_in%precip24_pa(iofp)*sec_per_day rh = bc_in%relhumid24_pa(iofp) @@ -185,6 +185,8 @@ subroutine charecteristics_of_fuel ( currentSite ) currentPatch => currentSite%oldest_patch; do while(associated(currentPatch)) + if(currentPatch%nocomp_pft_label .ne. 0)then + litt_c => currentPatch%litter(element_pos(carbon12_element)) ! How much live grass is there? @@ -325,7 +327,7 @@ subroutine charecteristics_of_fuel ( currentSite ) 0.0_r8.or.currentPatch%fuel_mef <= 0.0_r8.or.currentPatch%fuel_eff_moist <= 0.0_r8)then if ( hlm_masterproc == itrue ) write(fates_log(),*) 'problem with spitfire fuel averaging' endif - + endif !nocomp_pft_label check currentPatch => currentPatch%younger enddo !end patch loop @@ -359,7 +361,7 @@ subroutine wind_effect ( currentSite, bc_in) ! note - this is a patch level temperature, which probably won't have much inpact, ! unless we decide to ever calculated the NI for each patch. - iofp = currentSite%oldest_patch%patchno + iofp = currentSite%youngest_patch%patchno currentSite%wind = bc_in%wind24_pa(iofp) * sec_per_min !Convert to m/min for SPITFIRE if(write_SF == itrue)then @@ -372,6 +374,9 @@ subroutine wind_effect ( currentSite, bc_in) grass_fraction = 0.0_r8 currentPatch=>currentSite%oldest_patch; do while(associated(currentPatch)) + + if(currentPatch%nocomp_pft_label .ne. 0)then + currentPatch%total_tree_area = 0.0_r8 total_grass_area = 0.0_r8 currentCohort => currentPatch%tallest @@ -394,6 +399,8 @@ subroutine wind_effect ( currentSite, bc_in) write(fates_log(),*) 'SF total_grass_area ',tree_fraction,grass_fraction write(fates_log(),*) 'SF AREA ',AREA endif + + endif !nocomp_pft_label check currentPatch => currentPatch%younger enddo !currentPatch loop @@ -409,9 +416,13 @@ subroutine wind_effect ( currentSite, bc_in) currentPatch=>currentSite%oldest_patch; do while(associated(currentPatch)) + if(currentPatch%nocomp_pft_label .ne. 0)then + currentPatch%total_tree_area = min(currentPatch%total_tree_area,currentPatch%area) ! effect_wspeed in units m/min currentPatch%effect_wspeed = currentSite%wind * (tree_fraction*0.4_r8+(grass_fraction+bare_fraction)*0.6_r8) + + endif ! nocomp_pft_label check currentPatch => currentPatch%younger enddo !end patch loop @@ -450,6 +461,8 @@ subroutine rate_of_spread ( currentSite ) currentPatch=>currentSite%oldest_patch; do while(associated(currentPatch)) + + if(currentPatch%nocomp_pft_label .ne. 0)then ! remove mineral content from net fuel load per Thonicke 2010 for ir calculation currentPatch%sum_fuel = currentPatch%sum_fuel * (1.0_r8 - SF_val_miner_total) !net of minerals @@ -555,6 +568,7 @@ subroutine rate_of_spread ( currentSite ) ! backward ROS wind not changed by vegetation currentPatch%ROS_back = currentPatch%ROS_front*exp(-0.012_r8*currentSite%wind) + end if ! nocomp_pft_label check currentPatch => currentPatch%younger enddo !end patch loop @@ -583,6 +597,9 @@ subroutine ground_fuel_consumption ( currentSite ) currentPatch => currentSite%oldest_patch; do while(associated(currentPatch)) + + if(currentPatch%nocomp_pft_label .ne. 0)then + currentPatch%burnt_frac_litter(:) = 1.0_r8 ! Calculate fraction of litter is burnt for all classes. ! Equation B1 in Thonicke et al. 2010--- @@ -642,6 +659,8 @@ subroutine ground_fuel_consumption ( currentSite ) ! ignore 1000hr fuels. Just interested in fuels affecting ROS currentPatch%TFC_ROS = sum(FC_ground)-FC_ground(tr_sf) + end if ! nocomp_pft_label check + currentPatch=>currentPatch%younger; enddo !end patch loop @@ -703,7 +722,7 @@ subroutine area_burnt_intensity ( currentSite, bc_in ) end if !NF = number of lighting strikes per day per km2 scaled by cloud to ground strikes - iofp = currentSite%oldest_patch%patchno + iofp = currentSite%youngest_patch%patchno if (hlm_spitfire_mode == hlm_sf_scalar_lightning_def ) then currentSite%NF = ED_val_nignitions * years_per_day * cloud_to_ground_strikes else ! use external daily lightning ignition data @@ -726,6 +745,9 @@ subroutine area_burnt_intensity ( currentSite, bc_in ) currentPatch => currentSite%oldest_patch; do while(associated(currentPatch)) + + if(currentPatch%nocomp_pft_label .ne. 0)then + ! ---initialize patch parameters to zero--- currentPatch%FI = 0._r8 currentPatch%fire = 0 @@ -829,7 +851,8 @@ subroutine area_burnt_intensity ( currentSite, bc_in ) currentPatch%frac_burnt = 0.0_r8 endif - endif! NF ignitions check + endif ! NF ignitions check + endif ! nocomp_pft_label check currentPatch => currentPatch%younger @@ -861,6 +884,8 @@ subroutine crown_scorching ( currentSite ) currentPatch => currentSite%oldest_patch; do while(associated(currentPatch)) + + if(currentPatch%nocomp_pft_label .ne. 0)then tree_ag_biomass = 0.0_r8 if (currentPatch%fire == 1) then @@ -894,6 +919,7 @@ subroutine crown_scorching ( currentSite ) end do endif !fire + endif !nocomp_pft_label currentPatch => currentPatch%younger; enddo !end patch loop @@ -916,6 +942,8 @@ subroutine crown_damage ( currentSite ) currentPatch => currentSite%oldest_patch do while(associated(currentPatch)) + + if(currentPatch%nocomp_pft_label .ne. 0)then if (currentPatch%fire == 1) then currentCohort=>currentPatch%tallest @@ -957,6 +985,7 @@ subroutine crown_damage ( currentSite ) enddo !end cohort loop endif !fire? + endif !nocomp_pft_label check currentPatch => currentPatch%younger; @@ -983,6 +1012,8 @@ subroutine cambial_damage_kill ( currentSite ) do while(associated(currentPatch)) + if(currentPatch%nocomp_pft_label .ne. 0)then + if (currentPatch%fire == 1) then currentCohort => currentPatch%tallest; do while(associated(currentCohort)) @@ -1007,6 +1038,7 @@ subroutine cambial_damage_kill ( currentSite ) enddo !end cohort loop endif !fire? + endif !nocomp_pft_label check currentPatch=>currentPatch%younger; @@ -1033,6 +1065,8 @@ subroutine post_fire_mortality ( currentSite ) do while(associated(currentPatch)) + if(currentPatch%nocomp_pft_label .ne. 0)then + if (currentPatch%fire == 1) then currentCohort => currentPatch%tallest do while(associated(currentCohort)) @@ -1052,6 +1086,7 @@ subroutine post_fire_mortality ( currentSite ) enddo !end cohort loop endif !fire? + endif !nocomp_pft_label check currentPatch => currentPatch%younger diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 025969b07a..a3bf63c419 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -208,7 +208,15 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) if (hlm_use_ed_st3.eq.ifalse.and.hlm_use_sp.eq.ifalse) then ! Bypass if ST3 - call fire_model(currentSite, bc_in) + + ! Check that the site doesn't consist solely of a single bareground patch. + ! If so, skip the fire model. Since the bareground patch should be the + ! oldest patch per set_patchno, we check that the youngest patch isn't zero. + ! If there are multiple patches on the site, the bareground patch is avoided + ! at the level of the fire_model subroutines. + if (currentSite%youngest_patch%patchno .ne. 0) then + call fire_model(currentSite, bc_in) + end if ! Calculate disturbance and mortality based on previous timestep vegetation. ! disturbance_rates calls logging mortality and other mortalities, Yi Xu From 1cd0751ab3bf4b055f7901e6f003ef686fc7d90f Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 24 Jan 2023 11:15:57 -0700 Subject: [PATCH 488/852] fix patch loop start --- fire/SFMainMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index 0b6b098cdf..018487d47f 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -87,7 +87,7 @@ subroutine fire_model( currentSite, bc_in) type (ed_patch_type), pointer :: currentPatch !zero fire things - currentPatch => currentSite%oldest_patch + currentPatch => currentSite%youngest_patch do while(associated(currentPatch)) currentPatch%frac_burnt = 0.0_r8 currentPatch%fire = 0 From d19ba6bbefb0e14f0054a5eadb598644451efc37 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 24 Jan 2023 10:39:31 -0800 Subject: [PATCH 489/852] add more descriptive language to the nocomp_pft_label comments --- biogeochem/EDPatchDynamicsMod.F90 | 2 +- main/EDTypesMod.F90 | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index a6619b55d9..fb1bdf82f0 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -2027,7 +2027,7 @@ subroutine create_patch(currentSite, new_patch, age, areap, label,nocomp_pft) real(r8), intent(in) :: age ! notional age of this patch in years real(r8), intent(in) :: areap ! initial area of this patch in m2. integer, intent(in) :: label ! anthropogenic disturbance label - integer, intent(in) :: nocomp_pft + integer, intent(in) :: nocomp_pft ! no competition mode pft label ! Until bc's are pointed to by sites give veg a default temp [K] diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 4f198d6708..0e5308d0e8 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -440,7 +440,10 @@ module EDTypesMod class(rmean_type), pointer :: tveg_lpa ! Running mean of vegetation temperature at the ! leaf photosynthesis acclimation timescale [K] - integer :: nocomp_pft_label ! where nocomp is active, use this label for patch ID. + integer :: nocomp_pft_label ! Where nocomp is active, use this label for patch ID. + ! If nocomp is not active this is set to unset. + ! This is set in create_patch as an argument + ! to that procedure. ! LEAF ORGANIZATION From 7e3250fa5599296d9f821b7c41bc9f03391deccb Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 24 Jan 2023 11:00:25 -0800 Subject: [PATCH 490/852] convert bareground check to a public parameter --- biogeochem/EDCanopyStructureMod.F90 | 7 ++++--- biogeochem/EDPatchDynamicsMod.F90 | 3 ++- biogeochem/EDPhysiologyMod.F90 | 3 ++- biogeophys/EDAccumulateFluxesMod.F90 | 3 ++- biogeophys/EDBtranMod.F90 | 3 ++- biogeophys/EDSurfaceAlbedoMod.F90 | 5 +++-- biogeophys/FatesPlantHydraulicsMod.F90 | 3 ++- biogeophys/FatesPlantRespPhotosynthMod.F90 | 3 ++- fire/SFMainMod.F90 | 21 +++++++++++---------- main/EDTypesMod.F90 | 3 +++ main/FatesConstantsMod.F90 | 2 ++ 11 files changed, 35 insertions(+), 21 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 094a105c20..5c003600f4 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -10,6 +10,7 @@ module EDCanopyStructureMod use FatesConstantsMod , only : tinyr8 use FatesConstantsMod , only : nearzero use FatesConstantsMod , only : rsnbl_math_prec + use FatesConstantsMod , only : nocomp_bareground use FatesGlobals , only : fates_log use EDPftvarcon , only : EDPftvarcon_inst use PRTParametersMod , only : prt_params @@ -1369,7 +1370,7 @@ subroutine canopy_summarization( nsites, sites, bc_in ) endif ! adding checks for SP and NOCOMP modes. - if(currentPatch%nocomp_pft_label.eq.0)then + if(currentPatch%nocomp_pft_label.eq.nocomp_bareground)then write(fates_log(),*) 'cohorts in barepatch',currentPatch%total_canopy_area,currentPatch%nocomp_pft_label call endrun(msg=errMsg(sourcefile, __LINE__)) end if @@ -1828,7 +1829,7 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) c = fcolumn(s) do while(associated(currentPatch)) - if(currentPatch%nocomp_pft_label.ne.0)then ! ignore the bare-ground-PFT patch entirely for these BC outs + if(currentPatch%nocomp_pft_label.ne.nocomp_bareground)then ! ignore the bare-ground-PFT patch entirely for these BC outs ifp = ifp+1 @@ -1970,7 +1971,7 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) currentPatch => sites(s)%oldest_patch ifp = 0 do while(associated(currentPatch)) - if(currentPatch%nocomp_pft_label.ne.0)then ! for vegetated patches only + if(currentPatch%nocomp_pft_label.ne.nocomp_bareground)then ! for vegetated patches only ifp = ifp+1 bc_out(s)%canopy_fraction_pa(ifp) = bc_out(s)%canopy_fraction_pa(ifp)/total_patch_area endif ! veg patch diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index fb1bdf82f0..a5c2202430 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -39,6 +39,7 @@ module EDPatchDynamicsMod use EDTypesMod , only : AREA_INV use FatesConstantsMod , only : rsnbl_math_prec use FatesConstantsMod , only : fates_tiny + use FatesConstantsMod , only : nocomp_bareground use FatesInterfaceTypesMod , only : hlm_use_planthydro use FatesInterfaceTypesMod , only : hlm_numSWb use FatesInterfaceTypesMod , only : bc_in_type @@ -1286,7 +1287,7 @@ subroutine set_patchno( currentSite ) patchno = 1 currentPatch => currentSite%oldest_patch do while(associated(currentPatch)) - if(currentPatch%nocomp_pft_label.eq.0)then + if(currentPatch%nocomp_pft_label.eq.nocomp_bareground)then ! for bareground patch, we make the patch number 0 ! we also do not count this in the veg. patch numbering scheme. currentPatch%patchno = 0 diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 5eacaf00aa..778a02a84d 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -23,6 +23,7 @@ module EDPhysiologyMod use FatesInterfaceTypesMod, only : hlm_use_tree_damage use FatesConstantsMod, only : r8 => fates_r8 use FatesConstantsMod, only : nearzero + use FatesConstantsMod, only : nocomp_bareground use EDPftvarcon , only : EDPftvarcon_inst use PRTParametersMod , only : prt_params use EDPftvarcon , only : GetDecompyFrac @@ -2668,7 +2669,7 @@ subroutine fragmentation_scaler( currentPatch, bc_in) catanf(t1) = 11.75_r8 +(29.7_r8 / pi) * atan( pi * 0.031_r8 * ( t1 - 15.4_r8 )) catanf_30 = catanf(30._r8) - if(currentPatch%nocomp_pft_label.ne.0)then + if(currentPatch%nocomp_pft_label.ne.nocomp_bareground)then ! Use the hlm temp and moisture decomp fractions by default if ( use_hlm_soil_scalar ) then diff --git a/biogeophys/EDAccumulateFluxesMod.F90 b/biogeophys/EDAccumulateFluxesMod.F90 index 559fa5b0af..9756c743f0 100644 --- a/biogeophys/EDAccumulateFluxesMod.F90 +++ b/biogeophys/EDAccumulateFluxesMod.F90 @@ -13,6 +13,7 @@ module EDAccumulateFluxesMod use FatesGlobals, only : fates_log use shr_log_mod , only : errMsg => shr_log_errMsg use FatesConstantsMod , only : r8 => fates_r8 + use FatesConstantsMod , only : nocomp_bareground implicit none @@ -64,7 +65,7 @@ subroutine AccumulateFluxes_ED(nsites, sites, bc_in, bc_out, dt_time) cpatch => sites(s)%oldest_patch do while (associated(cpatch)) - if(cpatch%nocomp_pft_label.ne.0)then + if(cpatch%nocomp_pft_label.ne.nocomp_bareground)then ifp = ifp+1 if( bc_in(s)%filter_photo_pa(ifp) == 3 ) then diff --git a/biogeophys/EDBtranMod.F90 b/biogeophys/EDBtranMod.F90 index 52577b1b92..7b803469e5 100644 --- a/biogeophys/EDBtranMod.F90 +++ b/biogeophys/EDBtranMod.F90 @@ -8,6 +8,7 @@ module EDBtranMod use EDPftvarcon , only : EDPftvarcon_inst use FatesConstantsMod , only : tfrz => t_water_freeze_k_1atm use FatesConstantsMod , only : itrue,ifalse,nearzero + use FatesConstantsMod , only : nocomp_bareground use EDTypesMod , only : ed_site_type, & ed_patch_type, & ed_cohort_type, & @@ -138,7 +139,7 @@ subroutine btran_ed( nsites, sites, bc_in, bc_out) ifp = 0 cpatch => sites(s)%oldest_patch do while (associated(cpatch)) - if(cpatch%nocomp_pft_label.ne.0)then ! only for veg patches + if(cpatch%nocomp_pft_label.ne.nocomp_bareground)then ! only for veg patches ifp=ifp+1 ! THIS SHOULD REALLY BE A COHORT LOOP ONCE WE HAVE rootfr_ft FOR COHORTS (RGK) diff --git a/biogeophys/EDSurfaceAlbedoMod.F90 b/biogeophys/EDSurfaceAlbedoMod.F90 index ddb25f08a4..48b9d1e448 100644 --- a/biogeophys/EDSurfaceAlbedoMod.F90 +++ b/biogeophys/EDSurfaceAlbedoMod.F90 @@ -15,6 +15,7 @@ module EDSurfaceRadiationMod use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : itrue use FatesConstantsMod , only : pi_const + use FatesConstantsMod , only : nocomp_bareground use FatesInterfaceTypesMod , only : bc_in_type use FatesInterfaceTypesMod , only : bc_out_type use FatesInterfaceTypesMod , only : hlm_numSWb @@ -100,7 +101,7 @@ subroutine ED_Norman_Radiation (nsites, sites, bc_in, bc_out ) ifp = 0 currentpatch => sites(s)%oldest_patch do while (associated(currentpatch)) - if(currentpatch%nocomp_pft_label.ne.0)then + if(currentpatch%nocomp_pft_label.ne.nocomp_bareground)then ! do not do albedo calculations for bare ground patch in SP mode ! and (more impotantly) do not iterate ifp or it will mess up the indexing wherein ! ifp=1 is the first vegetated patch. @@ -1147,7 +1148,7 @@ subroutine ED_SunShadeFracs(nsites, sites,bc_in,bc_out) cpatch => sites(s)%oldest_patch do while (associated(cpatch)) - if(cpatch%nocomp_pft_label.ne.0)then !only for veg patches + if(cpatch%nocomp_pft_label.ne.nocomp_bareground)then !only for veg patches ! do not do albedo calculations for bare ground patch in SP mode ! and (more impotantly) do not iterate ifp or it will mess up the indexing wherein ! ifp=1 is the first vegetated patch. diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 752c903b03..f1e391fe8f 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -42,6 +42,7 @@ module FatesPlantHydraulicsMod use FatesConstantsMod, only : cm3_per_m3 use FatesConstantsMod, only : kg_per_g use FatesConstantsMod, only : fates_unset_r8 + use FatesConstantsMod, only : nocomp_bareground use EDParamsMod , only : hydr_kmax_rsurf1 use EDParamsMod , only : hydr_kmax_rsurf2 @@ -2546,7 +2547,7 @@ subroutine hydraulics_bc ( nsites, sites, bc_in, bc_out, dtime) ifp = 0 cpatch => sites(s)%oldest_patch do while (associated(cpatch)) - if(cpatch%nocomp_pft_label.ne.0)then + if(cpatch%nocomp_pft_label.ne.nocomp_bareground)then ifp = ifp + 1 ! ---------------------------------------------------------------------------- diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index d313ac9ce2..01ceb3ac17 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -31,6 +31,7 @@ module FATESPlantRespPhotosynthMod use FatesConstantsMod, only : rgas_J_K_mol use FatesConstantsMod, only : fates_unset_r8 use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm + use FatesConstantsMod, only : nocomp_bareground use FatesInterfaceTypesMod, only : hlm_use_planthydro use FatesInterfaceTypesMod, only : hlm_parteh_mode use FatesInterfaceTypesMod, only : numpft @@ -324,7 +325,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ifp = 0 currentpatch => sites(s)%oldest_patch do while (associated(currentpatch)) - if(currentpatch%nocomp_pft_label.ne.0)then + if(currentpatch%nocomp_pft_label.ne.nocomp_bareground)then ifp = ifp+1 NCL_p = currentPatch%NCL_p diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index 018487d47f..4f54dbdc2a 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -8,6 +8,7 @@ module SFMainMod use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : itrue, ifalse use FatesConstantsMod , only : pi_const + use FatesConstantsMod , only : nocomp_bareground use FatesInterfaceTypesMod , only : hlm_masterproc ! 1= master process, 0=not master process use EDTypesMod , only : numWaterMem use FatesGlobals , only : fates_log @@ -185,7 +186,7 @@ subroutine charecteristics_of_fuel ( currentSite ) currentPatch => currentSite%oldest_patch; do while(associated(currentPatch)) - if(currentPatch%nocomp_pft_label .ne. 0)then + if(currentPatch%nocomp_pft_label .ne. nocomp_bareground)then litt_c => currentPatch%litter(element_pos(carbon12_element)) @@ -375,7 +376,7 @@ subroutine wind_effect ( currentSite, bc_in) currentPatch=>currentSite%oldest_patch; do while(associated(currentPatch)) - if(currentPatch%nocomp_pft_label .ne. 0)then + if(currentPatch%nocomp_pft_label .ne. nocomp_bareground)then currentPatch%total_tree_area = 0.0_r8 total_grass_area = 0.0_r8 @@ -416,7 +417,7 @@ subroutine wind_effect ( currentSite, bc_in) currentPatch=>currentSite%oldest_patch; do while(associated(currentPatch)) - if(currentPatch%nocomp_pft_label .ne. 0)then + if(currentPatch%nocomp_pft_label .ne. nocomp_bareground)then currentPatch%total_tree_area = min(currentPatch%total_tree_area,currentPatch%area) ! effect_wspeed in units m/min @@ -462,7 +463,7 @@ subroutine rate_of_spread ( currentSite ) do while(associated(currentPatch)) - if(currentPatch%nocomp_pft_label .ne. 0)then + if(currentPatch%nocomp_pft_label .ne. nocomp_bareground)then ! remove mineral content from net fuel load per Thonicke 2010 for ir calculation currentPatch%sum_fuel = currentPatch%sum_fuel * (1.0_r8 - SF_val_miner_total) !net of minerals @@ -598,7 +599,7 @@ subroutine ground_fuel_consumption ( currentSite ) do while(associated(currentPatch)) - if(currentPatch%nocomp_pft_label .ne. 0)then + if(currentPatch%nocomp_pft_label .ne. nocomp_bareground)then currentPatch%burnt_frac_litter(:) = 1.0_r8 ! Calculate fraction of litter is burnt for all classes. @@ -746,7 +747,7 @@ subroutine area_burnt_intensity ( currentSite, bc_in ) currentPatch => currentSite%oldest_patch; do while(associated(currentPatch)) - if(currentPatch%nocomp_pft_label .ne. 0)then + if(currentPatch%nocomp_pft_label .ne. nocomp_bareground)then ! ---initialize patch parameters to zero--- currentPatch%FI = 0._r8 @@ -885,7 +886,7 @@ subroutine crown_scorching ( currentSite ) currentPatch => currentSite%oldest_patch; do while(associated(currentPatch)) - if(currentPatch%nocomp_pft_label .ne. 0)then + if(currentPatch%nocomp_pft_label .ne. nocomp_bareground)then tree_ag_biomass = 0.0_r8 if (currentPatch%fire == 1) then @@ -943,7 +944,7 @@ subroutine crown_damage ( currentSite ) do while(associated(currentPatch)) - if(currentPatch%nocomp_pft_label .ne. 0)then + if(currentPatch%nocomp_pft_label .ne. nocomp_bareground)then if (currentPatch%fire == 1) then currentCohort=>currentPatch%tallest @@ -1012,7 +1013,7 @@ subroutine cambial_damage_kill ( currentSite ) do while(associated(currentPatch)) - if(currentPatch%nocomp_pft_label .ne. 0)then + if(currentPatch%nocomp_pft_label .ne. nocomp_bareground)then if (currentPatch%fire == 1) then currentCohort => currentPatch%tallest; @@ -1065,7 +1066,7 @@ subroutine post_fire_mortality ( currentSite ) do while(associated(currentPatch)) - if(currentPatch%nocomp_pft_label .ne. 0)then + if(currentPatch%nocomp_pft_label .ne. nocomp_bareground)then if (currentPatch%fire == 1) then currentCohort => currentPatch%tallest diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 0e5308d0e8..6c27c2aa72 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -441,6 +441,9 @@ module EDTypesMod ! leaf photosynthesis acclimation timescale [K] integer :: nocomp_pft_label ! Where nocomp is active, use this label for patch ID. + ! Each patch ID corresponds to a pft number since each + ! patch has only one pft. Bareground patches are given + ! a zero integer as a label. ! If nocomp is not active this is set to unset. ! This is set in create_patch as an argument ! to that procedure. diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index ee3bd6cfb3..66a9c56d8d 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -35,6 +35,8 @@ module FatesConstantsMod integer, parameter, public :: primaryforest = 1 integer, parameter, public :: secondaryforest = 2 + ! Bareground label for no competition mode + integer, parameter, public :: nocomp_bareground = 0 ! Flags specifying how phosphorous uptake and turnover interacts ! with the host model. From 03d7c38d24ce778510942bac055b2446004ff46c Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 24 Jan 2023 14:29:32 -0800 Subject: [PATCH 491/852] refactor the bareground check to make sure that modes with no bareground still use the oldest patch to maintain b4bness --- fire/SFMainMod.F90 | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index 4f54dbdc2a..de8177c307 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -127,6 +127,8 @@ subroutine fire_danger_index ( currentSite, bc_in) type(ed_site_type) , intent(inout), target :: currentSite type(bc_in_type) , intent(in) :: bc_in + type(ed_patch_type), pointer :: currentPatch + real(r8) :: temp_in_C ! daily averaged temperature in celcius real(r8) :: rainfall ! daily precip in mm/day real(r8) :: rh ! daily rh @@ -141,9 +143,17 @@ subroutine fire_danger_index ( currentSite, bc_in) ! is simply using the values associated with the first patch. ! which probably won't have much inpact, unless we decide to ever calculated the NI for each patch. - iofp = currentSite%youngest_patch%patchno + currentPatch => currentSite%oldest_patch + + ! If the oldest patch is a bareground patch (i.e. nocomp mode is on) use the first vegetated patch + ! for the iofp index (i.e. the next younger patch) + if(currentPatch%nocomp_pft_label .eq. nocomp_bareground)then + currentPatch => currentPatch%younger + endif + + iofp = currentPatch%patchno - temp_in_C = currentSite%youngest_patch%tveg24%GetMean() - tfrz + temp_in_C = currentSite%currentPatch%tveg24%GetMean() - tfrz rainfall = bc_in%precip24_pa(iofp)*sec_per_day rh = bc_in%relhumid24_pa(iofp) @@ -181,8 +191,6 @@ subroutine charecteristics_of_fuel ( currentSite ) fuel_moisture(:) = 0.0_r8 - - currentPatch => currentSite%oldest_patch; do while(associated(currentPatch)) @@ -359,10 +367,17 @@ subroutine wind_effect ( currentSite, bc_in) integer :: iofp ! index of oldest fates patch + currentPatch => currentSite%oldest_patch + + ! If the oldest patch is a bareground patch (i.e. nocomp mode is on) use the first vegetated patch + ! for the iofp index (i.e. the next younger patch) + if(currentPatch%nocomp_pft_label .eq. nocomp_bareground)then + currentPatch => currentPatch%younger + endif + ! note - this is a patch level temperature, which probably won't have much inpact, ! unless we decide to ever calculated the NI for each patch. - - iofp = currentSite%youngest_patch%patchno + iofp = currentPatch%patchno currentSite%wind = bc_in%wind24_pa(iofp) * sec_per_min !Convert to m/min for SPITFIRE if(write_SF == itrue)then @@ -722,8 +737,16 @@ subroutine area_burnt_intensity ( currentSite, bc_in ) cloud_to_ground_strikes = cg_strikes end if + currentPatch => currentSite%oldest_patch + + ! If the oldest patch is a bareground patch (i.e. nocomp mode is on) use the first vegetated patch + ! for the iofp index (i.e. the next younger patch) + if(currentPatch%nocomp_pft_label .eq. nocomp_bareground)then + currentPatch => currentPatch%younger + endif + !NF = number of lighting strikes per day per km2 scaled by cloud to ground strikes - iofp = currentSite%youngest_patch%patchno + iofp = currentPatch%patchno if (hlm_spitfire_mode == hlm_sf_scalar_lightning_def ) then currentSite%NF = ED_val_nignitions * years_per_day * cloud_to_ground_strikes else ! use external daily lightning ignition data From fc02012ccdb20afdb46c921f00a259ff2c614cf9 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 24 Jan 2023 16:06:24 -0700 Subject: [PATCH 492/852] fix currentPatch error --- fire/SFMainMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index de8177c307..16aca5d243 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -153,7 +153,7 @@ subroutine fire_danger_index ( currentSite, bc_in) iofp = currentPatch%patchno - temp_in_C = currentSite%currentPatch%tveg24%GetMean() - tfrz + temp_in_C = currentPatch%tveg24%GetMean() - tfrz rainfall = bc_in%precip24_pa(iofp)*sec_per_day rh = bc_in%relhumid24_pa(iofp) From f0136449acfe34a933d9aee3281958da1f87c8cc Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 25 Jan 2023 16:49:14 -0500 Subject: [PATCH 493/852] Update to warning message text --- biogeochem/EDCohortDynamicsMod.F90 | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index c1bb4294c6..62e2b88ed7 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -842,9 +842,8 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_ if (debug_dealloc) write(fates_log(),*) 'dealloc001: fail on terminate_cohorts:deallocate(currentCohort):'//trim(smsg) nullify(currentCohort) else - if (debug_dealloc) write(fates_log(),*) 'dealloc001: pass on terminate_cohorts:deallocate(currentCohort)'//trim(smsg) + if (debug_dealloc) write(fates_log(),*) 'dealloc001: pass on terminate_cohorts:deallocate(currentCohort)' endif - endif currentCohort => tallerCohort enddo @@ -1099,7 +1098,7 @@ subroutine DeallocateCohort(currentCohort) if (debug_dealloc) write(fates_log(),*) 'dealloc002: fail in deallocate(currentCohort%prt):'//trim(smsg) nullify(currentCohort%prt) else - if (debug_dealloc) write(fates_log(),*) 'dealloc002: pass in deallocate(currentCohort%prt):'//trim(smsg) + if (debug_dealloc) write(fates_log(),*) 'dealloc002: pass in deallocate(currentCohort%prt):' endif return @@ -1584,9 +1583,9 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) call DeallocateCohort(nextc) deallocate(nextc, stat=istat, errmsg=smsg) if (istat/=0) then - if (debug_alloc) write(fates_log(),*) 'dealloc003: fail on deallocate(nextc):'//trim(smsg) + if (debug_dealloc) write(fates_log(),*) 'dealloc003: fail on deallocate(nextc):'//trim(smsg) else - if (debug_alloc) write(fates_log(),*) 'dealloc003: pass on deallocate(nextc):'//trim(smsg) + if (debug_dealloc) write(fates_log(),*) 'dealloc003: pass on deallocate(nextc):' endif nullify(nextc) From 30352b166bc343f3890667165cf41a96be41cec1 Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Wed, 25 Jan 2023 18:18:27 -0700 Subject: [PATCH 494/852] cleaned up the cwd adjust subroutine --- biogeochem/FatesLitterMod.F90 | 47 ++++++++++++++++------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/biogeochem/FatesLitterMod.F90 b/biogeochem/FatesLitterMod.F90 index 7198e1a92b..1bb03e99fd 100644 --- a/biogeochem/FatesLitterMod.F90 +++ b/biogeochem/FatesLitterMod.F90 @@ -432,8 +432,9 @@ subroutine adjust_SF_CWD_frac(dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) !DESCRIPTION !Adjust the partitioning of struct + sawp into cwd pools based on !cohort dbh. This avoids struct and sapw from small cohorts going to - !1,000 hr fuels. Instead, struct + sapw go to the appropriate cwd pools - !based on established fuel class diameter thresholds. + !fuel classes that are too large. Instead, struct + sapw go to the cwd + !class based on established fuel class diameter thresholds (Fosberg et al., 1971; + !Rothermel, 1983) !ARGUMENTS real(r8), intent(in) :: dbh !dbh of cohort @@ -443,45 +444,41 @@ subroutine adjust_SF_CWD_frac(dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) ! !LOCAL VARIABLES !These diameter ranges are based on work by Fosberg et al., 1971 - ! + real(r8), parameter :: lb_max_diam = 7.6 !max diameter [cm] for large branch real(r8), parameter :: sb_max_diam = 2.5 !max diameter [cm] for small branch real(r8), parameter :: twig_max_diam = 0.6 !max diameter [cm] for twig !------------------------------------------------------------------------------------ - write(fates_log(),*) "SFvalCWDFrac:",SF_val_CWD_frac - write(fates_log(),*) "SFvalCWDFrac sum:",sum(SF_val_CWD_frac(2:4)) - write(fates_log(),*) "ncwd:",ncwd - !write(fates_log(),*) "SFvalCWDFrac:",SF_val_CWD_frac - SF_val_CWD_frac_adj = SF_val_CWD_frac - !If dbh is larger than max size of a large branch then we don't change + !If dbh is larger than max size of a large branch (1,000 hr) then we don't change !how biomass is partitioned among cwd classes. if (dbh > lb_max_diam) then return - !When dbh is greater than the max size of a small branch but less than or + !When dbh is greater than the max size of a small branch (10 hr) but less than or !equal to the max size of a large branch we send the biomass that would have - !gone to trunk fuel to large branch fuel instead. + !gone to trunk fuel to large branch fuel (100 hr) instead. else if (dbh > sb_max_diam .and. dbh .le. lb_max_diam) then - SF_val_CWD_frac_adj(4) = 0.0 - !SF_val_CWD_frac_adj(ncwd-1) = sum(SF_val_CWD_frac((ncwd-1):ncwd)) - SF_val_CWD_frac_adj(3) = sum(SF_val_CWD_frac(3:4)) - - write(fates_log(),*) "using ahb trunk fuel fix", SF_val_CWD_frac_adj + SF_val_CWD_frac_adj(ncwd) = 0.0 + SF_val_CWD_frac_adj(ncwd-1) = sum(SF_val_CWD_frac((ncwd-1):ncwd)) + + + !SF_val_CWD_frac_adj(3) = sum(SF_val_CWD_frac(3:4)) + !write(fates_log(),*) "using ahb trunk fuel fix", SF_val_CWD_frac_adj - !When dbh is greater than the max size of a twig but less than or - !equal to the max size of a small branch we send the biomass that would have + !When dbh is greater than the max size of a twig (1 hr) but less than or + !equal to the max size of a small branch (10 hr) we send the biomass that would have !gone to trunk fuel / larger branch to small branch fuel instead. else if (dbh > twig_max_diam .and. dbh .le. sb_max_diam) then - !SF_val_CWD_frac_adj(ncwd) = 0.0_r8 - SF_val_CWD_frac_adj(4) = 0.0 - !SF_val_CWD_frac_adj(ncwd-1) = 0.0_r8 - SF_val_CWD_frac_adj(3) = 0.0 - !SF_val_CWD_frac_adj(ncwd-2) = sum(SF_val_CWD_frac((ncwd-2):ncwd)) - SF_val_CWD_frac_adj(2) = sum(SF_val_CWD_frac(2:4)) + SF_val_CWD_frac_adj(ncwd) = 0.0 + !SF_val_CWD_frac_adj(4) = 0.0 + SF_val_CWD_frac_adj(ncwd-1) = 0.0 + !SF_val_CWD_frac_adj(3) = 0.0 + SF_val_CWD_frac_adj(ncwd-2) = sum(SF_val_CWD_frac((ncwd-2):ncwd)) + !SF_val_CWD_frac_adj(2) = sum(SF_val_CWD_frac(2:4)) !If dbh is less than or equal to the max size of a twig we send all !biomass to twigs @@ -491,7 +488,7 @@ subroutine adjust_SF_CWD_frac(dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) SF_val_CWD_frac_adj(ncwd-2) = 0.0 SF_val_CWD_frac_adj(ncwd-3) = sum(SF_val_CWD_frac) - endif + endif end subroutine adjust_SF_CWD_frac end module FatesLitterMod From edebec907e1984aa1adc1c6025b12011a967903d Mon Sep 17 00:00:00 2001 From: Azamat Mametjanov Date: Thu, 13 Jan 2022 18:58:31 -0500 Subject: [PATCH 495/852] Add return status checks in cohort deallocations --- biogeochem/EDCohortDynamicsMod.F90 | 32 ++++++++++++++++++++------ parteh/PRTAllometricCNPMod.F90 | 36 +++++++++++++++++------------- parteh/PRTGenericMod.F90 | 28 ++++++++++++++--------- 3 files changed, 63 insertions(+), 33 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 4948f68129..e66b300438 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -749,6 +749,10 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_ real(r8) :: repro_c ! reproductive carbon [kg] real(r8) :: struct_c ! structural carbon [kg] integer :: terminate ! do we terminate (itrue) or not (ifalse) + integer :: c ! counter for litter size class. + integer :: levcan ! canopy level + integer :: istat ! return status code + character(len=255) :: smsg !---------------------------------------------------------------------- currentCohort => currentPatch%shortest @@ -816,7 +820,11 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_ if (terminate == itrue) then call terminate_cohort(currentSite, currentPatch, currentCohort, bc_in) - deallocate(currentCohort) + deallocate(currentCohort, stat=istat, errmsg=smsg) + if (istat/=0) then + if (debug) write(fates_log(),*) 'warning: stat/=0 in deallocate(currentCohort):'//trim(smsg) + nullify(currentCohort) + endif endif currentCohort => tallerCohort enddo @@ -1045,7 +1053,9 @@ subroutine DeallocateCohort(currentCohort) ! ---------------------------------------------------------------------------------- type(ed_cohort_type),intent(inout) :: currentCohort - + integer :: istat ! return status code + character(len=255) :: smsg + ! (Keeping as an example) ! Remove the running mean structure ! deallocate(currentCohort%tveg_lpa) @@ -1057,8 +1067,12 @@ subroutine DeallocateCohort(currentCohort) call currentCohort%prt%DeallocatePRTVartypes() ! Deallocate the PRT object - deallocate(currentCohort%prt) - + deallocate(currentCohort%prt, stat=istat, errmsg=smsg) + if (istat/=0) then + if (debug) write(fates_log(),*) 'warning: stat/=0 in deallocate(currentCohort%prt):'//trim(smsg) + nullify(currentCohort%prt) + endif + return end subroutine DeallocateCohort @@ -1113,6 +1127,8 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) logical, parameter :: fuse_debug = .false. ! This debug is over-verbose ! and gets its own flag + integer :: istat ! return status code + character(len=255) :: smsg !---------------------------------------------------------------------- @@ -1527,9 +1543,11 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) endif call DeallocateCohort(nextc) - deallocate(nextc) - nullify(nextc) - + deallocate(nextc, stat=istat, errmsg=smsg) + if (istat/=0) then + if (debug) write(fates_log(),*) 'warning: stat/=0 on deallocate(nextc):'//trim(smsg) + nullify(nextc) + endif endif ! if( currentCohort%isnew.eqv.nextc%isnew ) then endif !canopy layer diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 2a18d6d370..03b0ffd7a1 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -256,10 +256,13 @@ subroutine InitPRTGlobalAllometricCNP() ! waste memory on it. ! ----------------------------------------------------------------------------------- - integer :: nleafage + integer :: nleafage, istat + character(len=255) :: smsg - allocate(prt_global_acnp) - allocate(prt_global_acnp%state_descriptor(num_vars)) + allocate(prt_global_acnp, stat=istat) + if (istat/=0) call endrun(msg='allocate stat/=0:'//trim(smsg)//errMsg(sourcefile, __LINE__)) + allocate(prt_global_acnp%state_descriptor(num_vars), stat=istat) + if (istat/=0) call endrun(msg='allocate stat/=0:'//trim(smsg)//errMsg(sourcefile, __LINE__)) prt_global_acnp%hyp_name = 'Allometric Flexible C+N+P' @@ -343,13 +346,12 @@ subroutine DailyPRTAllometricCNP(this) real(r8),pointer :: p_efflux ! Total plant efflux of phosphorus (kgP) real(r8),pointer :: n_need ! N need (algorithm dependant) (kgN) real(r8),pointer :: p_need ! P need (algorithm dependant) (kgP) - real(r8),pointer :: growth_r ! Total plant growth respiration this step (kgC) ! These are pointers to the state variables, rearranged in organ dimensioned ! arrays. This is useful because we loop through organs so often - type(parray_type),pointer :: state_c(:) ! State array for carbon, by organ [kg] - type(parray_type),pointer :: state_n(:) ! State array for N, by organ [kg] - type(parray_type),pointer :: state_p(:) ! State array for P, by organ [kg] + type(parray_type), dimension(num_organs) :: state_c ! State array for carbon, by organ [kg] + type(parray_type), dimension(num_organs) :: state_n ! State array for N, by organ [kg] + type(parray_type), dimension(num_organs) :: state_p ! State array for P, by organ [kg] integer :: i_org ! organ index integer :: i_var ! variable index @@ -425,10 +427,6 @@ subroutine DailyPRTAllometricCNP(this) ! point to that bin. However, we need to account for all bins ! when we calculate the deficit - allocate(state_c(num_organs)) - allocate(state_n(num_organs)) - allocate(state_p(num_organs)) - ! Set carbon targets based on the plant's current stature target_c(:) = fates_unset_r8 target_dcdd(:) = fates_unset_r8 @@ -605,9 +603,10 @@ subroutine DailyPRTAllometricCNP(this) n_need = target_n - state_n(store_id)%ptr p_need = target_p - state_p(store_id)%ptr - deallocate(state_c) - deallocate(state_n) - deallocate(state_p) + do i_org = 1,num_organs + nullify(state_c(i_org)%ptr, state_n(i_org)%ptr, state_p(i_org)%ptr) + end do + nullify(dbh, maint_r_def, c_efflux, n_efflux, p_efflux, n_need, p_need) return end subroutine DailyPRTAllometricCNP @@ -1000,7 +999,6 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & real(r8), intent(inout) :: c_gain real(r8), intent(inout) :: n_gain real(r8), intent(inout) :: p_gain - real(r8), pointer :: maint_r_deficit type(parray_type) :: state_c(:) ! State array for carbon, by organ [kg] type(parray_type) :: state_n(:) ! State array for N, by organ [kg] type(parray_type) :: state_p(:) ! State array for P, by organ [kg] @@ -1530,6 +1528,8 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & end if if_stature_growth + + nullify(dbh) return end subroutine CNPStatureGrowth @@ -1648,6 +1648,8 @@ subroutine CNPAllocateRemainder(this,c_gain, n_gain, p_gain, & ! n_gain = 0.0_r8 ! p_gain = 0.0_r8 + nullify(dbh) + return end subroutine CNPAllocateRemainder @@ -1801,7 +1803,9 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe call endrun(msg=errMsg(sourcefile, __LINE__)) end if end if - + + nullify(dbh) + return end function GetNutrientTargetCNP diff --git a/parteh/PRTGenericMod.F90 b/parteh/PRTGenericMod.F90 index 35488bd8cc..dbf9726df5 100644 --- a/parteh/PRTGenericMod.F90 +++ b/parteh/PRTGenericMod.F90 @@ -861,31 +861,39 @@ subroutine DeallocatePRTVartypes(this) ! --------------------------------------------------------------------------------- class(prt_vartypes) :: this - integer :: i_var + integer :: i_var, istat + character(len=255) :: smsg ! Check to see if there is any value in these pools? ! SHould not deallocate if there is any carbon left do i_var = 1, prt_global%num_vars - deallocate(this%variables(i_var)%val) - deallocate(this%variables(i_var)%val0) - deallocate(this%variables(i_var)%net_alloc) - deallocate(this%variables(i_var)%turnover) - deallocate(this%variables(i_var)%burned) + deallocate( & + & this%variables(i_var)%val, & + & this%variables(i_var)%val0, & + & this%variables(i_var)%net_alloc, & + & this%variables(i_var)%turnover, & + & this%variables(i_var)%burned, & + & stat=istat, errmsg=smsg ) + if (istat/=0) call endrun(msg='deallocate stat/=0:'//trim(smsg)//errMsg(sourcefile, __LINE__)) end do - deallocate(this%variables) + deallocate(this%variables, stat=istat, errmsg=smsg) + if (istat/=0) call endrun(msg='deallocate stat/=0:'//trim(smsg)//errMsg(sourcefile, __LINE__)) if(allocated(this%bc_in))then - deallocate(this%bc_in) + deallocate(this%bc_in, stat=istat, errmsg=smsg) + if (istat/=0) call endrun(msg='deallocate stat/=0:'//trim(smsg)//errMsg(sourcefile, __LINE__)) end if if(allocated(this%bc_out))then - deallocate(this%bc_out) + deallocate(this%bc_out, stat=istat, errmsg=smsg) + if (istat/=0) call endrun(msg='deallocate stat/=0:'//trim(smsg)//errMsg(sourcefile, __LINE__)) end if if(allocated(this%bc_inout))then - deallocate(this%bc_inout) + deallocate(this%bc_inout, stat=istat, errmsg=smsg) + if (istat/=0) call endrun(msg='deallocate stat/=0:'//trim(smsg)//errMsg(sourcefile, __LINE__)) end if return From f371bd1193cdffa1d0f522034bc4771c1a7dd971 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 26 Jan 2023 12:02:11 -0500 Subject: [PATCH 496/852] Expanded deallocation statements to pass status and then perform checks. Removed target designations where unnecessary. --- biogeochem/EDCanopyStructureMod.F90 | 17 ++++-- biogeochem/EDCohortDynamicsMod.F90 | 35 +++++------ biogeochem/EDPatchDynamicsMod.F90 | 92 ++++++++++++++++++----------- biogeochem/EDPhysiologyMod.F90 | 15 +++-- main/EDInitMod.F90 | 20 ++++--- 5 files changed, 109 insertions(+), 70 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 094a105c20..c75c6b9956 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -62,6 +62,9 @@ module EDCanopyStructureMod character(len=*), parameter, private :: sourcefile = & __FILE__ + integer :: istat ! return status code + character(len=255) :: smsg ! Message string for deallocation errors + real(r8), parameter :: area_target_precision = 1.0E-11_r8 ! Area conservation ! will attempt to reduce errors ! below this level @@ -336,10 +339,10 @@ subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr,bc_in) use SFParamsMod, only : SF_val_CWD_frac ! !ARGUMENTS - type(ed_site_type), intent(inout), target :: currentSite - type(ed_patch_type), intent(inout), target :: currentPatch - integer, intent(in) :: i_lyr ! Current canopy layer of interest - type(bc_in_type), intent(in) :: bc_in + type(ed_site_type), intent(inout) :: currentSite + type(ed_patch_type), intent(inout) :: currentPatch + integer, intent(in) :: i_lyr ! Current canopy layer of interest + type(bc_in_type), intent(in) :: bc_in ! !LOCAL VARIABLES: type(ed_cohort_type), pointer :: currentCohort @@ -733,7 +736,11 @@ subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr,bc_in) ! put the litter from the terminated cohorts ! straight into the fragmenting pools call terminate_cohort(currentSite,currentPatch,currentCohort,bc_in) - deallocate(currentCohort) + deallocate(currentCohort, stat=istat, errmsg=smsg) + if (istat/=0) then + write(fates_log(),*) 'dealloc012: fail on deallocate(currentCohort):'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif else call carea_allom(currentCohort%dbh,currentCohort%n, & currentSite%spread,currentCohort%pft,currentCohort%crowndamage, & diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 62e2b88ed7..b6285f3fd2 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -134,7 +134,6 @@ Module EDCohortDynamicsMod public :: DamageRecovery logical, parameter :: debug = .false. ! local debug flag - logical, parameter :: debug_dealloc = .true. character(len=*), parameter, private :: sourcefile = & __FILE__ @@ -741,11 +740,11 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_ ! ! !ARGUMENTS - type (ed_site_type) , intent(inout), target :: currentSite - type (ed_patch_type), intent(inout), target :: currentPatch - integer , intent(in) :: level - integer :: call_index - type(bc_in_type), intent(in) :: bc_in + type (ed_site_type) , intent(inout) :: currentSite + type (ed_patch_type), intent(inout) :: currentPatch + integer , intent(in) :: level + integer :: call_index + type(bc_in_type), intent(in) :: bc_in ! Important point regarding termination levels. Termination is typically ! called after fusion. We do this so that we can re-capture the biomass that would @@ -839,10 +838,8 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_ call terminate_cohort(currentSite, currentPatch, currentCohort, bc_in) deallocate(currentCohort, stat=istat, errmsg=smsg) if (istat/=0) then - if (debug_dealloc) write(fates_log(),*) 'dealloc001: fail on terminate_cohorts:deallocate(currentCohort):'//trim(smsg) - nullify(currentCohort) - else - if (debug_dealloc) write(fates_log(),*) 'dealloc001: pass on terminate_cohorts:deallocate(currentCohort)' + write(fates_log(),*) 'dealloc001: fail on terminate_cohorts:deallocate(currentCohort):'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) endif endif currentCohort => tallerCohort @@ -1095,10 +1092,8 @@ subroutine DeallocateCohort(currentCohort) deallocate(currentCohort%prt, stat=istat, errmsg=smsg) if (istat/=0) then - if (debug_dealloc) write(fates_log(),*) 'dealloc002: fail in deallocate(currentCohort%prt):'//trim(smsg) - nullify(currentCohort%prt) - else - if (debug_dealloc) write(fates_log(),*) 'dealloc002: pass in deallocate(currentCohort%prt):' + write(fates_log(),*) 'dealloc002: fail in deallocate(currentCohort%prt):'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) endif return @@ -1120,9 +1115,9 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) ! ! !ARGUMENTS - type (ed_site_type), intent(inout), target :: currentSite - type (ed_patch_type), intent(inout), target :: currentPatch - type (bc_in_type), intent(in) :: bc_in + type (ed_site_type), intent(inout) :: currentSite + type (ed_patch_type), intent(inout), pointer :: currentPatch + type (bc_in_type), intent(in) :: bc_in ! ! !LOCAL VARIABLES: @@ -1583,11 +1578,9 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) call DeallocateCohort(nextc) deallocate(nextc, stat=istat, errmsg=smsg) if (istat/=0) then - if (debug_dealloc) write(fates_log(),*) 'dealloc003: fail on deallocate(nextc):'//trim(smsg) - else - if (debug_dealloc) write(fates_log(),*) 'dealloc003: pass on deallocate(nextc):' + write(fates_log(),*) 'dealloc003: fail on deallocate(nextc):'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) endif - nullify(nextc) endif ! if( currentCohort%isnew.eqv.nextc%isnew ) then endif !canopy layer diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index dba1a67d13..f6c7fc1a6e 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -135,6 +135,8 @@ module EDPatchDynamicsMod real(r8), parameter :: treefall_localization = 0.0_r8 real(r8), parameter :: burn_localization = 0.0_r8 + integer :: istat ! return status code + character(len=255) :: smsg ! Message string for deallocation errors character(len=512) :: msg ! Message string for warnings and logging ! 10/30/09: Created by Rosie Fisher @@ -162,7 +164,7 @@ subroutine disturbance_rates( site_in, bc_in) ! !ARGUMENTS: - type(ed_site_type) , intent(inout), target :: site_in + type(ed_site_type) , intent(inout) :: site_in type(bc_in_type) , intent(in) :: bc_in ! ! !LOCAL VARIABLES: @@ -374,8 +376,8 @@ subroutine spawn_patches( currentSite, bc_in) ! ! !ARGUMENTS: - type (ed_site_type), intent(inout), target :: currentSite - type (bc_in_type), intent(in) :: bc_in + type (ed_site_type), intent(inout) :: currentSite + type (bc_in_type), intent(in) :: bc_in ! ! !LOCAL VARIABLES: type (ed_patch_type) , pointer :: new_patch @@ -1056,8 +1058,11 @@ subroutine spawn_patches( currentSite, bc_in) ! Get rid of the new temporary cohort call DeallocateCohort(nc) - deallocate(nc) - + deallocate(nc, stat=istat, errmsg=smsg) + if (istat/=0) then + write(fates_log(),*) 'dealloc005: fail on deallocate(nc):'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif endif currentCohort => currentCohort%taller @@ -1195,7 +1200,7 @@ subroutine check_patch_area( currentSite ) ! !USES: ! ! !ARGUMENTS: - type(ed_site_type), intent(inout), target :: currentSite + type(ed_site_type), intent(inout) :: currentSite ! ! !LOCAL VARIABLES: real(r8) :: areatot @@ -1267,7 +1272,7 @@ subroutine set_patchno( currentSite ) ! !USES: ! ! !ARGUMENTS: - type(ed_site_type),intent(in), target :: currentSite + type(ed_site_type),intent(in) :: currentSite ! ! !LOCAL VARIABLES: type(ed_patch_type), pointer :: currentPatch @@ -1349,11 +1354,11 @@ subroutine TransLitterNewPatch(currentSite, & ! !USES: ! ! !ARGUMENTS: - type(ed_site_type) , intent(in), target :: currentSite ! site - type(ed_patch_type) , intent(in), target :: currentPatch ! Donor patch - type(ed_patch_type) , intent(inout) :: newPatch ! New patch - real(r8) , intent(in) :: patch_site_areadis ! Area being donated - ! by current patch + type(ed_site_type) , intent(in) :: currentSite ! site + type(ed_patch_type) , intent(in) :: currentPatch ! Donor patch + type(ed_patch_type) , intent(inout) :: newPatch ! New patch + real(r8) , intent(in) :: patch_site_areadis ! Area being donated + ! by current patch ! locals @@ -2713,8 +2718,11 @@ subroutine fuse_2_patches(csite, dp, rp) ! We have no need for the dp pointer anymore, we have passed on it's legacy call dealloc_patch(dp) - deallocate(dp) - + deallocate(dp, stat=istat, errmsg=smsg) + if (istat/=0) then + write(fates_log(),*) 'dealloc006: fail on deallocate(dp):'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif if(associated(youngerp))then ! Update the younger patch's new older patch (because it isn't dp anymore) @@ -2953,7 +2961,7 @@ subroutine dealloc_patch(cpatch) ! to via the patch structure. This subroutine DOES NOT deallocate the patch ! structure itself. - type(ed_patch_type), target :: cpatch + type(ed_patch_type) :: cpatch type(ed_cohort_type), pointer :: ccohort ! current type(ed_cohort_type), pointer :: ncohort ! next @@ -2967,7 +2975,12 @@ subroutine dealloc_patch(cpatch) ncohort => ccohort%taller call DeallocateCohort(ccohort) - deallocate(ccohort) + deallocate(ccohort, stat=istat, errmsg=smsg) + if (istat/=0) then + write(fates_log(),*) 'dealloc007: fail on deallocate(cchort):'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + ccohort => ncohort end do @@ -2976,25 +2989,38 @@ subroutine dealloc_patch(cpatch) do el=1,num_elements call cpatch%litter(el)%DeallocateLitt() end do - deallocate(cpatch%litter) - - ! Secondly, and lastly, deallocate the allocatable vector spaces in the patch - if(allocated(cpatch%tr_soil_dir))then - deallocate(cpatch%tr_soil_dir) - deallocate(cpatch%tr_soil_dif) - deallocate(cpatch%tr_soil_dir_dif) - deallocate(cpatch%fab) - deallocate(cpatch%fabd) - deallocate(cpatch%fabi) - deallocate(cpatch%sabs_dir) - deallocate(cpatch%sabs_dif) - deallocate(cpatch%fragmentation_scaler) - end if - + deallocate(cpatch%litter, stat=istat, errmsg=smsg) + if (istat/=0) then + write(fates_log(),*) 'dealloc008: fail on deallocate(cpatch%litter):'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + + ! Secondly, deallocate the allocatable vector spaces in the patch + deallocate(cpatch%tr_soil_dir, & + cpatch%tr_soil_dif, & + cpatch%tr_soil_dir_dif, & + cpatch%fab, & + cpatch%fabd, & + cpatch%fabi, & + cpatch%sabs_dir, & + cpatch%sabs_dif, & + cpatch%fragmentation_scaler, stat=istat, errmsg=smsg) + if (istat/=0) then + write(fates_log(),*) 'dealloc009: fail on deallocate patch vectors:'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif ! Deallocate any running means - deallocate(cpatch%tveg24) - deallocate(cpatch%tveg_lpa) + deallocate(cpatch%tveg24, stat=istat, errmsg=smsg) + if (istat/=0) then + write(fates_log(),*) 'dealloc010: fail on deallocate(cpatch%tveg24):'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + deallocate(cpatch%tveg_lpa, stat=istat, errmsg=smsg) + if (istat/=0) then + write(fates_log(),*) 'dealloc011: fail on deallocate(cpatch%tveg_lpa):'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif return end subroutine dealloc_patch diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 5eacaf00aa..fc46c301cb 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -143,6 +143,8 @@ module EDPhysiologyMod character(len=*), parameter, private :: sourcefile = & __FILE__ + integer :: istat ! return status code + character(len=255) :: smsg ! Message string for deallocation errors integer, parameter :: dleafon_drycheck = 100 ! Drought deciduous leaves max days on check parameter @@ -1983,9 +1985,9 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) ! ! !ARGUMENTS - type(ed_site_type), intent(inout), target :: currentSite - type(ed_patch_type), intent(inout), pointer :: currentPatch - type(bc_in_type), intent(in) :: bc_in + type(ed_site_type), intent(inout) :: currentSite + type(ed_patch_type), intent(inout),pointer :: currentPatch + type(bc_in_type), intent(in) :: bc_in ! ! !LOCAL VARIABLES: class(prt_vartypes), pointer :: prt @@ -2285,8 +2287,13 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) endif !use_this_pft enddo !pft loop - deallocate(temp_cohort) ! delete temporary cohort + deallocate(temp_cohort, stat=istat, errmsg=smsg) + if (istat/=0) then + write(fates_log(),*) 'dealloc013: fail on deallocate(temp_cohort):'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + end subroutine recruitment ! ============================================================================ diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 404e08b2ba..88fda94fd7 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -88,6 +88,8 @@ module EDInitMod logical :: debug = .false. + integer :: istat ! return status code + character(len=255) :: smsg ! Message string for deallocation errors character(len=*), parameter, private :: sourcefile = & __FILE__ @@ -111,8 +113,8 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) ! ! !ARGUMENTS type(ed_site_type), intent(inout) :: site_in - type(bc_in_type),intent(in),target :: bc_in - type(bc_out_type),intent(in),target :: bc_out + type(bc_in_type),intent(in) :: bc_in + type(bc_out_type),intent(in) :: bc_out ! ! !LOCAL VARIABLES: !---------------------------------------------------------------------- @@ -323,9 +325,9 @@ subroutine set_site_properties( nsites, sites,bc_in ) ! ! !ARGUMENTS - integer, intent(in) :: nsites - type(ed_site_type) , intent(inout), target :: sites(nsites) - type(bc_in_type), intent(in) :: bc_in(nsites) + integer, intent(in) :: nsites + type(ed_site_type) , intent(inout) :: sites(nsites) + type(bc_in_type), intent(in) :: bc_in(nsites) ! ! !LOCAL VARIABLES: integer :: s @@ -958,8 +960,12 @@ subroutine init_cohorts( site_in, patch_in, bc_in) temp_cohort%coage, temp_cohort%dbh, prt_obj, cstatus, rstatus, & temp_cohort%canopy_trim, temp_cohort%c_area,1,temp_cohort%crowndamage, site_in%spread, bc_in) - deallocate(temp_cohort) ! get rid of temporary cohort - + deallocate(temp_cohort, stat=istat, errmsg=smsg) + if (istat/=0) then + write(fates_log(),*) 'dealloc014: fail on deallocate(temp_cohort):'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + endif endif !use_this_pft enddo !numpft From 25047167fddd3708b407c775f2660890ea25487e Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 26 Jan 2023 10:31:52 -0800 Subject: [PATCH 497/852] manually reinstate tveg history variable --- main/FatesHistoryInterfaceMod.F90 | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 4380ef63bc..54be8b6e98 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -331,7 +331,7 @@ module FatesHistoryInterfaceMod ! Indices to (site) variables integer :: ih_tveg24_si - !integer :: ih_tveg_si + integer :: ih_tveg_si integer :: ih_nep_si integer :: ih_hr_si @@ -4370,8 +4370,8 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) hio_fabi_sun_top_si_can => this%hvars(ih_fabi_sun_top_si_can)%r82d, & hio_fabi_sha_top_si_can => this%hvars(ih_fabi_sha_top_si_can)%r82d, & hio_parsun_top_si_can => this%hvars(ih_parsun_top_si_can)%r82d, & - hio_parsha_top_si_can => this%hvars(ih_parsha_top_si_can)%r82d)!, & - !hio_tveg => this%hvars(ih_tveg_si)%r81d) + hio_parsha_top_si_can => this%hvars(ih_parsha_top_si_can)%r82d, & + hio_tveg => this%hvars(ih_tveg_si)%r81d) ! Flush the relevant history variables call this%flush_hvars(nc,upfreq_in=2) @@ -4425,12 +4425,12 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) hio_rad_error_si(io_si) = hio_rad_error_si(io_si) + & cpatch%radiation_error * cpatch%area * AREA_INV - ! ! Only accumulate the instantaneous vegetation temperature for vegetated patches - ! if (cpatch%patchno .ne. 0) then - ! hio_tveg(io_si) = hio_tveg(io_si) + & - ! (bc_in(s)%t_veg_pa(cpatch%patchno) - t_water_freeze_k_1atm) * & - ! cpatch%area / site_area_veg - ! end if + ! Only accumulate the instantaneous vegetation temperature for vegetated patches + if (cpatch%patchno .ne. 0) then + hio_tveg(io_si) = hio_tveg(io_si) + & + (bc_in(s)%t_veg_pa(cpatch%patchno) - t_water_freeze_k_1atm) * & + cpatch%area / site_area_veg + end if ccohort => cpatch%shortest do while(associated(ccohort)) @@ -6223,11 +6223,11 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_tveg24_si ) - ! call this%set_history_var(vname='FATES_TVEG', units='degree_Celsius', & - ! long='fates instantaneous mean vegetation temperature by site', & - ! use_default='active', & - ! avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ! ivar=ivar, initialize=initialize_variables, index = ih_tveg_si ) + call this%set_history_var(vname='FATES_TVEG', units='degree_Celsius', & + long='fates instantaneous mean vegetation temperature by site', & + use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & + ivar=ivar, initialize=initialize_variables, index = ih_tveg_si ) ! radiation error From d80ef2083419929ced7e1fa151238bd45bd258c8 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 26 Jan 2023 13:10:01 -0700 Subject: [PATCH 498/852] add local variable initialization for get_harvest_debt --- biogeochem/EDLoggingMortalityMod.F90 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index f711f3bcef..73ea7231e7 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -1147,6 +1147,12 @@ subroutine get_harvest_debt(site_in, bc_in, harvest_tag) real(r8) :: harvest_debt_sec_young if(logging_time) then + + ! Initialize the local variables + harvest_debt_pri = 0._r8 + harvest_debt_sec_mature = 0._r8 + harvest_debt_sec_young = 0._r8 + ! First we need to get harvest rate for all three categories do h_index = 1, hlm_num_lu_harvest_cats ! Primary forest harvest rate From 7a2e63905ff11be35b79a882b922664f2eebc5d0 Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Fri, 27 Jan 2023 09:44:41 -0800 Subject: [PATCH 499/852] Delete double m3_mortality_canopy_si_scls --- main/FatesHistoryInterfaceMod.F90 | 3 --- 1 file changed, 3 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 74fa621f62..00b72e2682 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -3247,9 +3247,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & ccohort%c_area * sec_per_day * days_per_year - hio_m3_mortality_canopy_si_scls(io_si,scls) = hio_m3_mortality_canopy_si_scls(io_si,scls) + & - ccohort%cmort * ccohort%n - hio_carbon_balance_canopy_si_scls(io_si,scls) = hio_carbon_balance_canopy_si_scls(io_si,scls) + & ccohort%n * ccohort%npp_acc_hold / m2_per_ha / days_per_year / sec_per_day From 27d0c688e4e32ea8605c135773aaf5da2df52c04 Mon Sep 17 00:00:00 2001 From: ckoven Date: Mon, 30 Jan 2023 11:41:19 -0700 Subject: [PATCH 500/852] make Tgrowth and maintenance respiration reduction diagnostics inactive by default --- main/FatesHistoryInterfaceMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 718b7cae6e..24659f280e 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -6060,7 +6060,7 @@ subroutine define_history_vars(this, initialize_variables) call this%set_history_var(vname='FATES_TGROWTH', units='degree_Celsius', & long='fates long-term running mean vegetation temperature by site', & - use_default='active', & + use_default='inactive', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_tgrowth_si ) @@ -6109,7 +6109,7 @@ subroutine define_history_vars(this, initialize_variables) call this%set_history_var(vname='FATES_MAINT_RESP_UNREDUCED', units='kg m-2 s-1', & long='diagnostic maintenance respiration if the low-carbon-storage reduction is ignored', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + use_default='inactive', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=2, ivar=ivar, initialize=initialize_variables, & index = ih_maint_resp_unreduced_si) From 46fa7642a110764d98bccacb642af775690d0e7f Mon Sep 17 00:00:00 2001 From: ckoven Date: Mon, 30 Jan 2023 12:25:53 -0700 Subject: [PATCH 501/852] reorganized C3/C4 logic to use separate subroutines --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 131 ++++++++++++++------- 1 file changed, 89 insertions(+), 42 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 3ce9286df2..adeaf0d1f5 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -523,31 +523,44 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) end select ! Part VII: Calculate dark respiration (leaf maintenance) for this layer - select case (maintresp_model) - case (lmrmodel_ryan_1991) + ! C3 plants + if_c3: if ( nint(EDPftvarcon_inst%c3psn(ft)) == 1 ) then + select case (maintresp_model) - call LeafLayerMaintenanceRespiration_Ryan_1991( lnc_top, & ! in - nscaler, & ! in - ft, & ! in - bc_in(s)%t_veg_pa(ifp), & ! in - lmr_z(iv,ft,cl)) ! out + case (lmrmodel_ryan_1991) - case (lmrmodel_atkin_etal_2017) + call LeafLayerMaintenanceRespiration_Ryan_1991( lnc_top, & ! in + nscaler, & ! in + ft, & ! in + bc_in(s)%t_veg_pa(ifp), & ! in + lmr_z(iv,ft,cl)) ! out - call LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & ! in - nscaler, & ! in - ft, & ! in - bc_in(s)%t_veg_pa(ifp), & ! in - currentPatch%tveg_lpa%GetMean(), & ! in - lmr_z(iv,ft,cl)) ! out + case (lmrmodel_atkin_etal_2017) - case default + call LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & ! in + nscaler, & ! in + ft, & ! in + bc_in(s)%t_veg_pa(ifp), & ! in + currentPatch%tveg_lpa%GetMean(), & ! in + lmr_z(iv,ft,cl)) ! out - write (fates_log(),*)'error, incorrect leaf respiration model specified' - call endrun(msg=errMsg(sourcefile, __LINE__)) + case default - end select + write (fates_log(),*)'error, incorrect leaf respiration model specified' + call endrun(msg=errMsg(sourcefile, __LINE__)) + + end select + + else ! C4 plants + + call LeafLayerMaintenanceRespiration_C4( lnc_top, & ! in + nscaler, & ! in + ft, & ! in + bc_in(s)%t_veg_pa(ifp), & ! in + lmr_z(iv,ft,cl)) ! out + + endif if_c3 ! Part VII: Calculate (1) maximum rate of carboxylation (vcmax), ! (2) maximum electron transport rate, (3) triose phosphate @@ -2069,7 +2082,7 @@ subroutine LeafLayerMaintenanceRespiration_Ryan_1991(lnc_top, & use FatesConstantsMod, only : umolC_to_kgC use FatesConstantsMod, only : g_per_kg use EDPftvarcon , only : EDPftvarcon_inst - + ! ----------------------------------------------------------------------- ! Base maintenance respiration rate for plant tissues base_mr_20 ! M. Ryan, 1991. Effects of climate change on plant respiration. @@ -2096,9 +2109,9 @@ subroutine LeafLayerMaintenanceRespiration_Ryan_1991(lnc_top, & real(r8), parameter :: lmrc = 1.15912391_r8 ! scaling factor for high ! temperature inhibition (25 C = 1.0) + real(r8), parameter :: basal_resp_rate_perunit_N_ryan1991 = 2.525e-6_r8 ! gC/(gN s) - ! MLO - Shouldn't these numbers be parameters too? - lmr25top = 2.525e-6_r8 * (1.5_r8 ** ((25._r8 - 20._r8)/10._r8)) + lmr25top = basal_resp_rate_perunit_N_ryan1991 * (1.5_r8 ** ((25._r8 - 20._r8)/10._r8)) lmr25top = lmr25top * lnc_top / (umolC_to_kgC * g_per_kg) @@ -2106,13 +2119,8 @@ subroutine LeafLayerMaintenanceRespiration_Ryan_1991(lnc_top, & ! ---------------------------------------------------------------------------------- lmr25 = lmr25top * nscaler - if ( nint(EDPftvarcon_inst%c3psn(ft)) == 1)then - lmr = lmr25 * ft1_f(veg_tempk, lmrha) * & - fth_f(veg_tempk, lmrhd, lmrse, lmrc) - else - lmr = lmr25 * 2._r8**((veg_tempk-(tfrz+25._r8))/10._r8) - lmr = lmr / (1._r8 + exp( 1.3_r8*(veg_tempk-(tfrz+55._r8)) )) - end if + lmr = lmr25 * ft1_f(veg_tempk, lmrha) * & + fth_f(veg_tempk, lmrhd, lmrse, lmrc) ! Any hydrodynamic limitations could go here, currently none ! lmr = lmr * (nothing) @@ -2166,26 +2174,65 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & ! note that this code uses the relationship between leaf N and respiration from Atkin et al ! for the top of the canopy, but then assumes proportionality with N through the canopy. - if ( nint(EDPftvarcon_inst%c3psn(ft)) == 1)then + ! r_0 currently put into the EDPftvarcon_inst%dev_arbitrary_pft + ! all figs in Atkin et al 2017 stop at zero Celsius so we will assume acclimation is fixed below that + r_0 = EDPftvarcon_inst%dev_arbitrary_pft(ft) + r_t_ref = nscaler * (r_0 + r_1 * lnc_top + r_2 * max(0._r8, (tgrowth - tfrz) )) - ! r_0 currently put into the EDPftvarcon_inst%dev_arbitrary_pft - ! all figs in Atkin et al 2017 stop at zero Celsius so we will assume acclimation is fixed below that - r_0 = EDPftvarcon_inst%dev_arbitrary_pft(ft) - r_t_ref = nscaler * (r_0 + r_1 * lnc_top + r_2 * max(0._r8, (tgrowth - tfrz) )) + lmr = r_t_ref * exp(b * (veg_tempk - tfrz - TrefC) + c * ((veg_tempk-tfrz)**2 - TrefC**2)) - lmr = r_t_ref * exp(b * (veg_tempk - tfrz - TrefC) + c * ((veg_tempk-tfrz)**2 - TrefC**2)) +end subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017 - else - ! revert to Q10 model for C4 plants, parameter values as described above in Ryan 1991 method +! ==================================================================================== - lmr25top = 2.525e-6_r8 * (1.5_r8 ** ((25._r8 - 20._r8)/10._r8)) - lmr25 = lmr25top * lnc_top * nscaler / (umolC_to_kgC * g_per_kg) +subroutine LeafLayerMaintenanceRespiration_C4(lnc_top, & + nscaler, & + ft, & + veg_tempk, & + lmr) - lmr = lmr25 * 2._r8**((veg_tempk-(tfrz+25._r8))/10._r8) - lmr = lmr / (1._r8 + exp( 1.3_r8*(veg_tempk-(tfrz+55._r8)) )) - end if + use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm + use FatesConstantsMod, only : umolC_to_kgC + use FatesConstantsMod, only : g_per_kg + use EDPftvarcon , only : EDPftvarcon_inst -end subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017 + ! ----------------------------------------------------------------------- + ! Base maintenance respiration rate for plant tissues base_mr_20 + ! M. Ryan, 1991. Effects of climate change on plant respiration. + ! Ecological Applications, 1(2), 157-167. + ! Original expression is br = 0.0106 molC/(molN h) + ! Conversion by molecular weights of C and N gives 2.525e-6 gC/(gN s) + + ! This contains the original C4 dark respiraiton logic from CLM, which uses a different + ! temperature scaling than for C3 plants + + ! Arguments + real(r8), intent(in) :: lnc_top ! Leaf nitrogen content per unit area at canopy top [gN/m2] + + 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 + real(r8), intent(out) :: lmr ! Leaf Maintenance Respiration (umol CO2/m**2/s) + + ! Locals + real(r8) :: lmr25 ! leaf layer: leaf maintenance respiration rate at 25C (umol CO2/m**2/s) + real(r8) :: lmr25top ! canopy top leaf maint resp rate at 25C for this pft (umol CO2/m**2/s) + + ! Parameters + real(r8), parameter :: basal_resp_rate_perunit_N_ryan1991 = 2.525e-6_r8 ! gC/(gN s) + + lmr25top = basal_resp_rate_perunit_N_ryan1991 * (1.5_r8 ** ((25._r8 - 20._r8)/10._r8)) + lmr25top = lmr25top * lnc_top / (umolC_to_kgC * g_per_kg) + + + ! Part I: Leaf Maintenance respiration: umol CO2 / m**2 [leaf] / s + ! ---------------------------------------------------------------------------------- + lmr25 = lmr25top * nscaler + + lmr = lmr25 * 2._r8**((veg_tempk-(tfrz+25._r8))/10._r8) + lmr = lmr / (1._r8 + exp( 1.3_r8*(veg_tempk-(tfrz+55._r8)) )) + +end subroutine LeafLayerMaintenanceRespiration_C4 ! ==================================================================================== From f5f1c9a74582b6581b2a7f001b350a6c7a78001d Mon Sep 17 00:00:00 2001 From: ckoven Date: Mon, 30 Jan 2023 12:39:26 -0700 Subject: [PATCH 502/852] revert dark respiration model to the Ryan 1991 model --- 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 58754de36a..c3f24ea1c3 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1494,7 +1494,7 @@ data: fates_leaf_theta_cj_c4 = 0.999 ; - fates_maintresp_model = 2 ; + fates_maintresp_model = 1 ; fates_maxcohort = 100 ; From 10db8b92373e766cfd0bcfe5b433fedb6de11bc4 Mon Sep 17 00:00:00 2001 From: ckoven Date: Mon, 30 Jan 2023 14:49:13 -0700 Subject: [PATCH 503/852] swapping hard-coded basal respiration rate in Ryan 1991 model with value of fates_base_mr_20 in fates_params_default.cdl, and updating number in fates_params_default.cdl --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 10 ++++------ parameter_files/fates_params_default.cdl | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index adeaf0d1f5..58c6c6e09c 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -2089,6 +2089,7 @@ subroutine LeafLayerMaintenanceRespiration_Ryan_1991(lnc_top, & ! Ecological Applications, 1(2), 157-167. ! Original expression is br = 0.0106 molC/(molN h) ! Conversion by molecular weights of C and N gives 2.525e-6 gC/(gN s) + ! Which is the default value of ED_val_base_mr_20 ! Arguments real(r8), intent(in) :: lnc_top ! Leaf nitrogen content per unit area at canopy top [gN/m2] @@ -2109,9 +2110,7 @@ subroutine LeafLayerMaintenanceRespiration_Ryan_1991(lnc_top, & real(r8), parameter :: lmrc = 1.15912391_r8 ! scaling factor for high ! temperature inhibition (25 C = 1.0) - real(r8), parameter :: basal_resp_rate_perunit_N_ryan1991 = 2.525e-6_r8 ! gC/(gN s) - - lmr25top = basal_resp_rate_perunit_N_ryan1991 * (1.5_r8 ** ((25._r8 - 20._r8)/10._r8)) + lmr25top = ED_val_base_mr_20 * (1.5_r8 ** ((25._r8 - 20._r8)/10._r8)) lmr25top = lmr25top * lnc_top / (umolC_to_kgC * g_per_kg) @@ -2202,6 +2201,7 @@ subroutine LeafLayerMaintenanceRespiration_C4(lnc_top, & ! Ecological Applications, 1(2), 157-167. ! Original expression is br = 0.0106 molC/(molN h) ! Conversion by molecular weights of C and N gives 2.525e-6 gC/(gN s) + ! Which is the default value of ED_val_base_mr_20 ! This contains the original C4 dark respiraiton logic from CLM, which uses a different ! temperature scaling than for C3 plants @@ -2218,10 +2218,8 @@ subroutine LeafLayerMaintenanceRespiration_C4(lnc_top, & real(r8) :: lmr25 ! leaf layer: leaf maintenance respiration rate at 25C (umol CO2/m**2/s) real(r8) :: lmr25top ! canopy top leaf maint resp rate at 25C for this pft (umol CO2/m**2/s) - ! Parameters - real(r8), parameter :: basal_resp_rate_perunit_N_ryan1991 = 2.525e-6_r8 ! gC/(gN s) - lmr25top = basal_resp_rate_perunit_N_ryan1991 * (1.5_r8 ** ((25._r8 - 20._r8)/10._r8)) + lmr25top = ED_val_base_mr_20 * (1.5_r8 ** ((25._r8 - 20._r8)/10._r8)) lmr25top = lmr25top * lnc_top / (umolC_to_kgC * g_per_kg) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index c3f24ea1c3..ae3a77684d 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1402,7 +1402,7 @@ data: fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; - fates_base_mr_20 = 2.52e-06 ; + fates_base_mr_20 = 2.525e-06 ; fates_canopy_closure_thresh = 0.8 ; From 27c5e78604b19368a17953a454640da91370e268 Mon Sep 17 00:00:00 2001 From: ckoven Date: Mon, 30 Jan 2023 17:18:15 -0700 Subject: [PATCH 504/852] removing PFT argument to Ryan 1991 respiration models as no longer needed --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 6 ------ 1 file changed, 6 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 58c6c6e09c..6b5e18043a 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -532,7 +532,6 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) call LeafLayerMaintenanceRespiration_Ryan_1991( lnc_top, & ! in nscaler, & ! in - ft, & ! in bc_in(s)%t_veg_pa(ifp), & ! in lmr_z(iv,ft,cl)) ! out @@ -556,7 +555,6 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) call LeafLayerMaintenanceRespiration_C4( lnc_top, & ! in nscaler, & ! in - ft, & ! in bc_in(s)%t_veg_pa(ifp), & ! in lmr_z(iv,ft,cl)) ! out @@ -2074,7 +2072,6 @@ end subroutine GetCanopyGasParameters subroutine LeafLayerMaintenanceRespiration_Ryan_1991(lnc_top, & nscaler, & - ft, & veg_tempk, & lmr) @@ -2094,7 +2091,6 @@ subroutine LeafLayerMaintenanceRespiration_Ryan_1991(lnc_top, & ! Arguments real(r8), intent(in) :: lnc_top ! Leaf nitrogen content per unit area at canopy top [gN/m2] - 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 real(r8), intent(out) :: lmr ! Leaf Maintenance Respiration (umol CO2/m**2/s) @@ -2186,7 +2182,6 @@ end subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017 subroutine LeafLayerMaintenanceRespiration_C4(lnc_top, & nscaler, & - ft, & veg_tempk, & lmr) @@ -2209,7 +2204,6 @@ subroutine LeafLayerMaintenanceRespiration_C4(lnc_top, & ! Arguments real(r8), intent(in) :: lnc_top ! Leaf nitrogen content per unit area at canopy top [gN/m2] - 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 real(r8), intent(out) :: lmr ! Leaf Maintenance Respiration (umol CO2/m**2/s) From d83805d48b05f26961fb6ceec05730883c235478 Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Tue, 31 Jan 2023 08:48:07 -0800 Subject: [PATCH 505/852] Add total LAI as a history variable for use in ILAMB --- main/FatesHistoryInterfaceMod.F90 | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 00b72e2682..85c0cf2785 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -363,7 +363,8 @@ module FatesHistoryInterfaceMod integer :: ih_h2oveg_recruit_si integer :: ih_h2oveg_growturn_err_si integer :: ih_h2oveg_hydro_err_si - + integer :: ih_lai_si + integer :: ih_site_cstatus_si integer :: ih_site_dstatus_si integer :: ih_gdd_si @@ -2430,7 +2431,8 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_tveg24 => this%hvars(ih_tveg24_si)%r81d, & hio_meanliqvol_si => this%hvars(ih_meanliqvol_si)%r81d, & hio_cbal_err_fates_si => this%hvars(ih_cbal_err_fates_si)%r81d, & - hio_err_fates_si => this%hvars(ih_err_fates_si)%r82d ) + hio_err_fates_si => this%hvars(ih_err_fates_si)%r82d, & + hio_lai_si => this%hvars(ih_lai_si)%r81d ) ! If we don't have dynamics turned on, we just abort these diagnostics if (hlm_use_ed_st3.eq.itrue) return @@ -2601,6 +2603,8 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) + cpatch%ncl_p * cpatch%area hio_npatches_si_age(io_si,cpatch%age_class) = hio_npatches_si_age(io_si,cpatch%age_class) + 1._r8 + hio_lai_si(io_si) = hio_lai_si(io_si) + sum(cpatch%tlai_profile(:,:,:)) * cpatch%area * AREA_INV + if ( ED_val_comp_excln .lt. 0._r8 ) then ! only valid when "strict ppa" enabled hio_zstar_si_age(io_si,cpatch%age_class) = hio_zstar_si_age(io_si,cpatch%age_class) & + cpatch%zstar * cpatch%area * AREA_INV @@ -5184,6 +5188,12 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_canopy_spread_si) + call this%set_history_var(vname='FATES_LAI', units='m2 m-2', & + long='leaf area index per m2 land area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_lai_si) + call this%set_history_var(vname='FATES_VEGC_PF', units='kg m-2', & long='total PFT-level biomass in kg of carbon per land area', & use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & From 47c539a7e34ecf5045c6771cc3d4ce918fce4aa2 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 31 Jan 2023 09:21:52 -0800 Subject: [PATCH 506/852] remove extra closing paranthesis in associate statement --- main/FatesRestartInterfaceMod.F90 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 4741af0526..a115aee798 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -1978,8 +1978,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_fmortcflux_usto_sipft => this%rvars(ir_fmortcflux_usto_sipft)%r81d, & rio_abg_imort_flux_siscpf => this%rvars(ir_abg_imort_flux_siscpf)%r81d, & rio_abg_fmort_flux_siscpf => this%rvars(ir_abg_fmort_flux_siscpf)%r81d, & - rio_abg_term_flux_siscpf => this%rvars(ir_abg_term_flux_siscpf)%r81d ) - + rio_abg_term_flux_siscpf => this%rvars(ir_abg_term_flux_siscpf)%r81d rio_imortrate_sicdpf => this%rvars(ir_imortrate_sicdpf)%r81d, & rio_imortcflux_sicdsc => this%rvars(ir_imortcflux_sicdsc)%r81d, & From ce2c30404b50376cfd8836c1d16798fc38b46d32 Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Tue, 31 Jan 2023 11:30:48 -0800 Subject: [PATCH 507/852] Change calculation of total LAI history variable to get m2 leaf per m2 patch --- main/FatesHistoryInterfaceMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 85c0cf2785..09b9e3a2c6 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2603,7 +2603,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) + cpatch%ncl_p * cpatch%area hio_npatches_si_age(io_si,cpatch%age_class) = hio_npatches_si_age(io_si,cpatch%age_class) + 1._r8 - hio_lai_si(io_si) = hio_lai_si(io_si) + sum(cpatch%tlai_profile(:,:,:)) * cpatch%area * AREA_INV + hio_lai_si(io_si) = hio_lai_si(io_si) + sum(cpatch%tlai_profile(:,:,:)) * sum(cpatch%canopy_area_profile(:,:,:)) * AREA_INV if ( ED_val_comp_excln .lt. 0._r8 ) then ! only valid when "strict ppa" enabled hio_zstar_si_age(io_si,cpatch%age_class) = hio_zstar_si_age(io_si,cpatch%age_class) & From 28654b1e3cf4a43b2b77c8012d97e4ff2ddedfcc Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Tue, 31 Jan 2023 12:58:14 -0800 Subject: [PATCH 508/852] Fix total lai units --- main/FatesHistoryInterfaceMod.F90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 09b9e3a2c6..0124003d8f 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2603,7 +2603,8 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) + cpatch%ncl_p * cpatch%area hio_npatches_si_age(io_si,cpatch%age_class) = hio_npatches_si_age(io_si,cpatch%age_class) + 1._r8 - hio_lai_si(io_si) = hio_lai_si(io_si) + sum(cpatch%tlai_profile(:,:,:)) * sum(cpatch%canopy_area_profile(:,:,:)) * AREA_INV + hio_lai_si(io_si) = hio_lai_si(io_si) + sum( cpatch%canopy_area_profile(:,:,:) * cpatch%elai_profile(:,:,:) ) * & + cpatch%total_canopy_area / cpatch%area if ( ED_val_comp_excln .lt. 0._r8 ) then ! only valid when "strict ppa" enabled hio_zstar_si_age(io_si,cpatch%age_class) = hio_zstar_si_age(io_si,cpatch%age_class) & From 669ba80f6e0daa1357b0572683d642b6f68ed997 Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Tue, 31 Jan 2023 17:06:18 -0800 Subject: [PATCH 509/852] Account for patch averaging in total LAI units --- main/FatesHistoryInterfaceMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 69280c5491..ddb9769747 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2653,7 +2653,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_npatches_si_age(io_si,cpatch%age_class) = hio_npatches_si_age(io_si,cpatch%age_class) + 1._r8 hio_lai_si(io_si) = hio_lai_si(io_si) + sum( cpatch%canopy_area_profile(:,:,:) * cpatch%elai_profile(:,:,:) ) * & - cpatch%total_canopy_area / cpatch%area + cpatch%total_canopy_area * AREA_INV if ( ED_val_comp_excln .lt. 0._r8 ) then ! only valid when "strict ppa" enabled hio_zstar_si_age(io_si,cpatch%age_class) = hio_zstar_si_age(io_si,cpatch%age_class) & From 64226688962473cf2dad17d3aad3c157d18ddf7b Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 31 Jan 2023 17:07:17 -0800 Subject: [PATCH 510/852] add missing line continuation in restart --- main/FatesRestartInterfaceMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index a115aee798..a0509ac015 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -1978,7 +1978,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_fmortcflux_usto_sipft => this%rvars(ir_fmortcflux_usto_sipft)%r81d, & rio_abg_imort_flux_siscpf => this%rvars(ir_abg_imort_flux_siscpf)%r81d, & rio_abg_fmort_flux_siscpf => this%rvars(ir_abg_fmort_flux_siscpf)%r81d, & - rio_abg_term_flux_siscpf => this%rvars(ir_abg_term_flux_siscpf)%r81d + rio_abg_term_flux_siscpf => this%rvars(ir_abg_term_flux_siscpf)%r81d, & rio_imortrate_sicdpf => this%rvars(ir_imortrate_sicdpf)%r81d, & rio_imortcflux_sicdsc => this%rvars(ir_imortcflux_sicdsc)%r81d, & From 94853939a7f746cd2ad6e2e09d1ff788c1dd8395 Mon Sep 17 00:00:00 2001 From: ckoven Date: Thu, 2 Feb 2023 22:42:26 -0700 Subject: [PATCH 511/852] added patch-level exponential moving average methods to Kumarathunge 2019 parameterization --- biogeochem/EDPatchDynamicsMod.F90 | 7 ++- biogeophys/FatesPlantRespPhotosynthMod.F90 | 50 +++++++++++----------- main/EDTypesMod.F90 | 2 + main/FatesConstantsMod.F90 | 4 ++ main/FatesInterfaceMod.F90 | 5 +++ main/FatesRestartInterfaceMod.F90 | 7 +++ main/FatesRunningMeanMod.F90 | 1 + 7 files changed, 50 insertions(+), 26 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 07be08a6b0..3be366b322 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -95,7 +95,7 @@ module EDPatchDynamicsMod use EDParamsMod, only : maxpatch_primary use EDParamsMod, only : maxpatch_secondary use EDParamsMod, only : maxpatch_total - use FatesRunningMeanMod, only : ema_24hr, fixed_24hr, ema_lpa + use FatesRunningMeanMod, only : ema_24hr, fixed_24hr, ema_lpa, ema_longterm ! CIME globals use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) @@ -655,6 +655,7 @@ subroutine spawn_patches( currentSite, bc_in) ! -------------------------------------------------------------------------- call new_patch%tveg24%CopyFromDonor(currentPatch%tveg24) call new_patch%tveg_lpa%CopyFromDonor(currentPatch%tveg_lpa) + call new_patch%tveg_longterm%CopyFromDonor(currentPatch%tveg_longterm) ! -------------------------------------------------------------------------- @@ -2087,6 +2088,8 @@ subroutine create_patch(currentSite, new_patch, age, areap, label,nocomp_pft) call new_patch%tveg24%InitRMean(fixed_24hr,init_value=temp_init_veg,init_offset=real(hlm_current_tod,r8) ) allocate(new_patch%tveg_lpa) call new_patch%tveg_lpa%InitRmean(ema_lpa,init_value=temp_init_veg) + allocate(new_patch%tveg_longterm) + call new_patch%tveg_longterm%InitRmean(ema_longterm,init_value=temp_init_veg) ! Litter ! Allocate, Zero Fluxes, and Initialize to "unset" values @@ -2661,6 +2664,7 @@ subroutine fuse_2_patches(csite, dp, rp) ! Weighted mean of the running means call rp%tveg24%FuseRMean(dp%tveg24,rp%area*inv_sum_area) call rp%tveg_lpa%FuseRMean(dp%tveg_lpa,rp%area*inv_sum_area) + call rp%tveg_longterm%FuseRMean(dp%tveg_longterm,rp%area*inv_sum_area) rp%fuel_eff_moist = (dp%fuel_eff_moist*dp%area + rp%fuel_eff_moist*rp%area) * inv_sum_area rp%livegrass = (dp%livegrass*dp%area + rp%livegrass*rp%area) * inv_sum_area @@ -3032,6 +3036,7 @@ subroutine dealloc_patch(cpatch) ! Deallocate any running means deallocate(cpatch%tveg24) deallocate(cpatch%tveg_lpa) + deallocate(cpatch%tveg_longterm) return end subroutine dealloc_patch diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 511ea36c96..b9c3aa4629 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -32,6 +32,8 @@ module FATESPlantRespPhotosynthMod use FatesConstantsMod, only : fates_unset_r8 use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm use FatesConstantsMod, only : nocomp_bareground + use FatesConstantsMod, only : photosynth_acclim_model_none + use FatesConstantsMod, only : photosynth_acclim_model_kumarathunge_etal_2019 use FatesInterfaceTypesMod, only : hlm_use_planthydro use FatesInterfaceTypesMod, only : hlm_parteh_mode use FatesInterfaceTypesMod, only : numpft @@ -562,6 +564,8 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime, temp currentCohort%kp25top, & ! in nscaler, & ! in bc_in(s)%t_veg_pa(ifp), & ! in + currentPatch%tveg_lpa%GetMean(), & ! in + currentPatch%tveg_longterm%GetMean(),& ! in btran_eff, & ! in vcmax_z, & ! out jmax_z, & ! out @@ -2201,6 +2205,8 @@ subroutine LeafLayerBiophysicalRates( parsun_lsl, & 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) :: 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) real(r8), intent(out) :: vcmax ! maximum rate of carboxylation (umol co2/m**2/s) @@ -2226,43 +2232,37 @@ subroutine LeafLayerBiophysicalRates( parsun_lsl, & real(r8) :: jmaxhd ! deactivation energy for jmax (J/mol) real(r8) :: vcmaxse ! entropy term for vcmax (J/mol/K) real(r8) :: jmaxse ! entropy term for jmax (J/mol/K) - real(r8) :: tgrowth ! average growing temperature - real(r8) :: thome ! average home temperature - real(r8) :: jvr ! ratio of Jmax25 / Vcmax25 + real(r8) :: tgrowth ! average growing temperature + real(r8) :: thome ! average home temperature + real(r8) :: jvr ! ratio of Jmax25 / Vcmax25 real(r8) :: vcmaxc ! scaling factor for high temperature inhibition (25 C = 1.0) real(r8) :: jmaxc ! scaling factor for high temperature inhibition (25 C = 1.0) associate( t10 => temperature_inst%t_a10_patch, & ! Input: [real(r8) (:) ] 10-day running mean of the 2 m temperature (K) t30 => temperature_inst%t_a30_patch) ! Input: [real(r8) (:) ] 30-day running mean of the 2 m temperature (K) - if (temp_acclim == 0) then !No temperature acclimation + select case(temp_acclim) + case (photosynth_acclim_model_none) !No temperature acclimation vcmaxha = EDPftvarcon_inst%vcmaxha(FT) jmaxha = EDPftvarcon_inst%jmaxha(FT) vcmaxhd = EDPftvarcon_inst%vcmaxhd(FT) jmaxhd = EDPftvarcon_inst%jmaxhd(FT) vcmaxse = EDPftvarcon_inst%vcmaxse(FT) jmaxse = EDPftvarcon_inst%jmaxse(FT) - else if (temp_acclim == 1) then !Kumarathunge et al. temperature acclimation, Thome=Tgrowth - tgrowth = t30(1)-tfrz - thome = t30(1)-tfrz - vcmaxha = (42.6 + (1.14*tgrowth))*1000 !J/mol - jmaxha = 40.71*1000 !J/mol - vcmaxhd = 200*1000 !J/mol - jmaxhd = 200*1000 !J/mol - vcmaxse = (645.13 - (0.38*tgrowth)) - jmaxse = 658.77 - (0.84*thome) - 0.52*(tgrowth-thome) - jvr = 2.56 - (0.0375*thome)-(0.0202*(tgrowth-thome)) - else if (temp_acclim == 2) then !Kumarathunge et al. temperature acclimation, Thome=25C - tgrowth = t30(1)-tfrz - thome = 25 !degrees C - vcmaxha = (42.6 + (1.14*tgrowth))*1000 !J/mol - jmaxha = 40.71*1000 !J/mol - vcmaxhd = 200*1000 !J/mol - jmaxhd = 200*1000 !J/mol - vcmaxse = (645.13 - (0.38*tgrowth)) - jmaxse = 658.77 - (0.84*thome) - 0.52*(tgrowth-thome) - jvr = 2.56 - (0.0375*thome)-(0.0202*(tgrowth-thome)) - end if + case (photosynth_acclim_model_kumarathunge_etal_2019) !Kumarathunge et al. temperature acclimation, Thome=30-year running mean + t_growth_celsius = t_growth-tfrz + t_home_celsius = t_home-tfrz + vcmaxha = (42.6_r8 + (1.14_r8*t_growth_celsius))*1e3_r8 !J/mol + jmaxha = 40.71_r8*1e3._r8 !J/mol + vcmaxhd = 200._r8*1e3._r8 !J/mol + jmaxhd = 200._r8*1e3._r8 !J/mol + vcmaxse = (645.13_r8 - (0.38_r8*t_growth_celsius)) + jmaxse = 658.77_r8 - (0.84_r8*t_home_celsius) - 0.52_r8*(t_growth_celsius-t_home_celsius) + jvr = 2.56_r8 - (0.0375_r8*t_home_celsius)-(0.0202_r8*(t_growth_celsius-t_home_celsius)) + case default + write (fates_log(),*)'error, incorrect leaf photosynthesis temperature acclimation model specified' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select vcmaxc = fth25_f(vcmaxhd, vcmaxse) jmaxc = fth25_f(jmaxhd, jmaxse) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 5fa8006101..242fa65b0d 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -443,6 +443,8 @@ module EDTypesMod class(rmean_type), pointer :: tveg24 ! 24-hour mean vegetation temperature (K) class(rmean_type), pointer :: tveg_lpa ! Running mean of vegetation temperature at the ! leaf photosynthesis acclimation timescale [K] + class(rmean_type), pointer :: tveg_longterm ! Long-Term Running mean of vegetation temperature at the + ! leaf photosynthesis acclimation timescale [K] (i.e T_home) integer :: nocomp_pft_label ! Where nocomp is active, use this label for patch ID. ! Each patch ID corresponds to a pft number since each diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index 66a9c56d8d..ef05154bd3 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -65,6 +65,10 @@ module FatesConstantsMod ! based on average age of global ! secondary 1900s land in hurtt-2011 + ! integer labels for specifying harvest units + integer, parameter, public :: photosynth_acclim_model_none = 0 + integer, parameter, public :: photosynth_acclim_model_kumarathunge_etal_2019 = 1 + ! integer labels for specifying harvest units integer, parameter, public :: hlm_harvest_area_fraction = 1 ! Code for harvesting by area integer, parameter, public :: hlm_harvest_carbon = 2 ! Code for harvesting based on carbon extracted. diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index b314073e60..5e89fed4d6 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -84,6 +84,7 @@ module FatesInterfaceMod use FatesRunningMeanMod , only : ema_24hr use FatesRunningMeanMod , only : fixed_24hr use FatesRunningMeanMod , only : ema_lpa + use FatesRunningMeanMod , only : ema_longterm use FatesRunningMeanMod , only : ema_60day use FatesRunningMeanMod , only : moving_ema_window use FatesRunningMeanMod , only : fixed_window @@ -989,6 +990,9 @@ subroutine InitTimeAveragingGlobals() allocate(ema_lpa) call ema_lpa%define(photo_temp_acclim_timescale*sec_per_day, & hlm_stepsize,moving_ema_window) + allocate(ema_longterm) ! for now just fix this as a 30-year exponential moving average + call ema_lpa%define(30._r8*365._r8*sec_per_day, & + hlm_stepsize,moving_ema_window) !allocate(ema_60day) !call ema_60day%define(prt_params%fnrt_adapt_tscl*sec_per_day,sec_per_day,moving_ema_window) @@ -1949,6 +1953,7 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) ifp=ifp+1 call cpatch%tveg24%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) call cpatch%tveg_lpa%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) + call cpatch%tveg_longterm%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) !ccohort => cpatch%tallest diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 040af0400b..80ced2d42c 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -158,6 +158,7 @@ module FatesRestartInterfaceMod ! Running Means integer :: ir_tveg24_pa integer :: ir_tveglpa_pa + integer :: ir_tveglongterm_pa ! (Keeping as an example) !!integer :: ir_tveglpa_co @@ -1389,6 +1390,10 @@ subroutine define_restart_vars(this, initialize_variables) long_name='running average (EMA) of patch veg temp for photo acclim', & units='K', initialize=initialize_variables,ivar=ivar, index = ir_tveglpa_pa) + call this%DefineRMeanRestartVar(vname='fates_tveglongtermpatch',vtype=cohort_r8, & + long_name='long-term (T_home) running average (EMA) of patch veg temp for photo acclim', & + units='K', initialize=initialize_variables,ivar=ivar, index = ir_tveglongterm_pa) + ! (Keeping as an example) !call this%DefineRMeanRestartVar(vname='fates_tveglpacohort',vtype=cohort_r8, & ! long_name='running average (EMA) of cohort veg temp for photo acclim', & @@ -2205,6 +2210,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) ! Patch level running means call this%SetRMeanRestartVar(cpatch%tveg24, ir_tveg24_pa, io_idx_co_1st) call this%SetRMeanRestartVar(cpatch%tveg_lpa, ir_tveglpa_pa, io_idx_co_1st) + call this%SetRMeanRestartVar(cpatch%tveg_longterm, ir_tveglongterm_pa, io_idx_co_1st) ! set cohorts per patch for IO rio_ncohort_pa( io_idx_co_1st ) = cohortsperpatch @@ -3091,6 +3097,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) call this%GetRMeanRestartVar(cpatch%tveg24, ir_tveg24_pa, io_idx_co_1st) call this%GetRMeanRestartVar(cpatch%tveg_lpa, ir_tveglpa_pa, io_idx_co_1st) + call this%GetRMeanRestartVar(cpatch%tveg_longterm, ir_tveglongterm_pa, io_idx_co_1st) ! set cohorts per patch for IO diff --git a/main/FatesRunningMeanMod.F90 b/main/FatesRunningMeanMod.F90 index a1c51f6abf..bf3d0b0bfb 100644 --- a/main/FatesRunningMeanMod.F90 +++ b/main/FatesRunningMeanMod.F90 @@ -91,6 +91,7 @@ module FatesRunningMeanMod class(rmean_def_type), public, pointer :: ema_24hr ! Exponential moving average - 24hr window class(rmean_def_type), public, pointer :: fixed_24hr ! Fixed, 24-hour window class(rmean_def_type), public, pointer :: ema_lpa ! Exponential moving average - leaf photo acclimation + class(rmean_def_type), public, pointer :: ema_longterm ! Exponential moving average - long-term leaf photo acclimation class(rmean_def_type), public, pointer :: ema_60day ! Exponential moving average, 60 day ! Updated daily class(rmean_def_type), public, pointer :: ema_storemem ! EMA used for smoothing N/C and P/C storage From 157720bc3267ce57ac3f19649e7554556253f087 Mon Sep 17 00:00:00 2001 From: ckoven Date: Thu, 2 Feb 2023 22:46:48 -0700 Subject: [PATCH 512/852] removed temperature_inst method of getting average temperatures --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index b9c3aa4629..6f1c8a93fc 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -108,7 +108,7 @@ module FATESPlantRespPhotosynthMod !-------------------------------------------------------------------------------------- - subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime, temperature_inst) + subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! ----------------------------------------------------------------------------------- ! !DESCRIPTION: @@ -152,7 +152,6 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime, temp type(bc_in_type),intent(in) :: bc_in(nsites) type(bc_out_type),intent(inout) :: bc_out(nsites) real(r8),intent(in) :: dtime - type(temperature_type) , intent(in) :: temperature_inst ! LOCAL VARIABLES: @@ -557,7 +556,6 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime, temp call LeafLayerBiophysicalRates(currentPatch%ed_parsun_z(cl,ft,iv), & ! in - temperature_inst, & !in ft, & ! in currentCohort%vcmax25top, & ! in currentCohort%jmax25top, & ! in @@ -2164,7 +2162,6 @@ end subroutine LeafLayerMaintenanceRespiration ! ==================================================================================== subroutine LeafLayerBiophysicalRates( parsun_lsl, & - temperature_inst, & ft, & vcmax25top_ft, & jmax25top_ft, & @@ -2195,7 +2192,6 @@ subroutine LeafLayerBiophysicalRates( parsun_lsl, & ! ------------------------------------------------------------------------------ real(r8), intent(in) :: parsun_lsl ! PAR absorbed in sunlit leaves for this layer - type(temperature_type) , intent(in) :: temperature_inst integer, intent(in) :: ft ! (plant) Functional Type Index real(r8), intent(in) :: nscaler ! Scale for leaf nitrogen profile real(r8), intent(in) :: vcmax25top_ft ! canopy top maximum rate of carboxylation at 25C @@ -2238,10 +2234,7 @@ subroutine LeafLayerBiophysicalRates( parsun_lsl, & real(r8) :: vcmaxc ! scaling factor for high temperature inhibition (25 C = 1.0) real(r8) :: jmaxc ! scaling factor for high temperature inhibition (25 C = 1.0) - associate( t10 => temperature_inst%t_a10_patch, & ! Input: [real(r8) (:) ] 10-day running mean of the 2 m temperature (K) - t30 => temperature_inst%t_a30_patch) ! Input: [real(r8) (:) ] 30-day running mean of the 2 m temperature (K) - - select case(temp_acclim) + select case(temp_acclim) case (photosynth_acclim_model_none) !No temperature acclimation vcmaxha = EDPftvarcon_inst%vcmaxha(FT) jmaxha = EDPftvarcon_inst%jmaxha(FT) From bb170fe6cd1c3944788bdd82356cfd7cebb00c04 Mon Sep 17 00:00:00 2001 From: ckoven Date: Thu, 2 Feb 2023 22:50:06 -0700 Subject: [PATCH 513/852] more cleanup of FatesHistoryInterfaceMod.F90 merge --- main/FatesHistoryInterfaceMod.F90 | 41 ++++++++++++++----------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index c6b876236c..075eea9509 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -6373,34 +6373,31 @@ subroutine define_history_vars(this, initialize_variables) index = ih_excess_resp_si) ! Canopy resistance - -<<<<<<< HEAD call this%set_history_var(vname='FATES_STOMATAL_COND_AP', & units='mol m-2 s-1', long='mean stomatal conductance - by patch age', & use_default='inactive', avgflag='A', vtype=site_age_r8, & hlms='CLM:ALM', upfreq=2, ivar=ivar, initialize=initialize_variables, & index = ih_c_stomata_si_age) -======= - call this%set_history_var(vname='AJ_CANOPY', units='gC/m^2/s', & + + call this%set_history_var(vname='FATES_AJ_CANOPY', units='gC/m^2/s', & long='RuBP-limited gross primary production of canopy plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=2, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & ivar=ivar, initialize=initialize_variables, index = ih_aj_canopy_si ) - call this%set_history_var(vname='AC_CANOPY', units='gC/m^2/s', & + call this%set_history_var(vname='FATES_AC_CANOPY', units='gC/m^2/s', & long='Rubisco-limited gross primary production of canopy plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=2, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & ivar=ivar, initialize=initialize_variables, index = ih_ac_canopy_si ) - call this%set_history_var(vname='AP_CANOPY', units='gC/m^2/s', & + call this%set_history_var(vname='FATES_AP_CANOPY', units='gC/m^2/s', & long='Product-limited gross primary production of canopy plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=2, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & ivar=ivar, initialize=initialize_variables, index = ih_ap_canopy_si ) - call this%set_history_var(vname='AR_CANOPY', units='gC/m^2/s', & + call this%set_history_var(vname='FATES_AR_CANOPY', units='gC/m^2/s', & long='autotrophic respiration of canopy plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=2, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & ivar=ivar, initialize=initialize_variables, index = ih_ar_canopy_si ) ->>>>>>> temp_acclim_photosynth call this%set_history_var(vname='FATES_LBLAYER_COND_AP', & units='mol m-2 s-1', & @@ -6409,7 +6406,6 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=2, ivar=ivar, & initialize=initialize_variables, index = ih_c_lblayer_si_age) -<<<<<<< HEAD ! fast fluxes by age bin call this%set_history_var(vname='FATES_NPP_AP', units='kg m-2 s-1', & long='net primary productivity by age bin in kg carbon per m2 per second', & @@ -6422,27 +6418,26 @@ subroutine define_history_vars(this, initialize_variables) use_default='inactive', avgflag='A', vtype=site_age_r8, & hlms='CLM:ALM', upfreq=2, ivar=ivar, initialize=initialize_variables, & index = ih_gpp_si_age) -======= - call this%set_history_var(vname='AJ_UNDERSTORY', units='gC/m^2/s', & + + call this%set_history_var(vname='FATES_AJ_UNDERSTORY', units='gC/m^2/s', & long='RuBP-limited gross primary production of understory plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=2, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & ivar=ivar, initialize=initialize_variables, index = ih_aj_understory_si ) - call this%set_history_var(vname='AC_UNDERSTORY', units='gC/m^2/s', & + call this%set_history_var(vname='FATES_AC_UNDERSTORY', units='gC/m^2/s', & long='Rubisco-limited gross primary production of understory plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=2, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & ivar=ivar, initialize=initialize_variables, index = ih_ac_understory_si ) - call this%set_history_var(vname='AP_UNDERSTORY', units='gC/m^2/s', & + call this%set_history_var(vname='FATES_AP_UNDERSTORY', units='gC/m^2/s', & long='Product-limited gross primary production of understory plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=2, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & ivar=ivar, initialize=initialize_variables, index = ih_ap_understory_si ) - call this%set_history_var(vname='AR_UNDERSTORY', units='gC/m^2/s', & + call this%set_history_var(vname='FATES_AR_UNDERSTORY', units='gC/m^2/s', & long='autotrophic respiration of understory plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=2, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & ivar=ivar, initialize=initialize_variables, index = ih_ar_understory_si ) ->>>>>>> temp_acclim_photosynth ! fast fluxes separated canopy/understory call this%set_history_var(vname='FATES_GPP_CANOPY', units='kg m-2 s-1', & From 62ca51684b2a10f5b3b08e13af0f7be378d4ea43 Mon Sep 17 00:00:00 2001 From: ckoven Date: Fri, 3 Feb 2023 11:31:16 -0700 Subject: [PATCH 514/852] various compile-time and runtime bugfixes --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 29 ++++++++++++---------- main/EDParamsMod.F90 | 15 ++--------- main/FatesConstantsMod.F90 | 4 +-- main/FatesInterfaceMod.F90 | 2 +- 4 files changed, 21 insertions(+), 29 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 6f1c8a93fc..403370c2ae 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -54,7 +54,7 @@ module FATESPlantRespPhotosynthMod use PRTGenericMod, only : store_organ use PRTGenericMod, only : repro_organ use PRTGenericMod, only : struct_organ - use EDParamsMod, only : ED_val_base_mr_20, stomatal_model, stomatal_assim_model, temp_acclim + use EDParamsMod, only : ED_val_base_mr_20, stomatal_model, stomatal_assim_model, photo_tempsens_model use PRTParametersMod, only : prt_params use EDPftvarcon , only : EDPftvarcon_inst @@ -2168,6 +2168,8 @@ subroutine LeafLayerBiophysicalRates( parsun_lsl, & co2_rcurve_islope25top_ft, & nscaler, & veg_tempk, & + t_growth, & + t_home, & btran, & vcmax, & jmax, & @@ -2228,13 +2230,13 @@ subroutine LeafLayerBiophysicalRates( parsun_lsl, & real(r8) :: jmaxhd ! deactivation energy for jmax (J/mol) real(r8) :: vcmaxse ! entropy term for vcmax (J/mol/K) real(r8) :: jmaxse ! entropy term for jmax (J/mol/K) - real(r8) :: tgrowth ! average growing temperature - real(r8) :: thome ! average home temperature + real(r8) :: t_growth_celsius ! average growing temperature + real(r8) :: t_home_celsius ! average home temperature real(r8) :: jvr ! ratio of Jmax25 / Vcmax25 real(r8) :: vcmaxc ! scaling factor for high temperature inhibition (25 C = 1.0) real(r8) :: jmaxc ! scaling factor for high temperature inhibition (25 C = 1.0) - select case(temp_acclim) + select case(photo_tempsens_model) case (photosynth_acclim_model_none) !No temperature acclimation vcmaxha = EDPftvarcon_inst%vcmaxha(FT) jmaxha = EDPftvarcon_inst%jmaxha(FT) @@ -2246,9 +2248,9 @@ subroutine LeafLayerBiophysicalRates( parsun_lsl, & t_growth_celsius = t_growth-tfrz t_home_celsius = t_home-tfrz vcmaxha = (42.6_r8 + (1.14_r8*t_growth_celsius))*1e3_r8 !J/mol - jmaxha = 40.71_r8*1e3._r8 !J/mol - vcmaxhd = 200._r8*1e3._r8 !J/mol - jmaxhd = 200._r8*1e3._r8 !J/mol + jmaxha = 40.71_r8*1e3_r8 !J/mol + vcmaxhd = 200._r8*1e3_r8 !J/mol + jmaxhd = 200._r8*1e3_r8 !J/mol vcmaxse = (645.13_r8 - (0.38_r8*t_growth_celsius)) jmaxse = 658.77_r8 - (0.84_r8*t_home_celsius) - 0.52_r8*(t_growth_celsius-t_home_celsius) jvr = 2.56_r8 - (0.0375_r8*t_home_celsius)-(0.0202_r8*(t_growth_celsius-t_home_celsius)) @@ -2268,13 +2270,15 @@ subroutine LeafLayerBiophysicalRates( parsun_lsl, & ! Vcmax25top was already calculated to derive the nscaler function vcmax25 = vcmax25top_ft * nscaler - if (temp_acclim == 0) then + select case(photo_tempsens_model) + case (photosynth_acclim_model_none) jmax25 = jmax25top_ft * nscaler - else if (temp_acclim == 1) then + case (photosynth_acclim_model_kumarathunge_etal_2019) jmax25 = vcmax25*jvr - else if (temp_acclim == 2) then - jmax25 = vcmax25*jvr - end if + case default + write (fates_log(),*)'error, incorrect leaf photosynthesis temperature acclimation model specified' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select co2_rcurve_islope25 = co2_rcurve_islope25top_ft * nscaler @@ -2295,7 +2299,6 @@ subroutine LeafLayerBiophysicalRates( parsun_lsl, & vcmax = vcmax * btran return - end associate end subroutine LeafLayerBiophysicalRates diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 30390cf341..b29b6463b3 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -35,7 +35,7 @@ module EDParamsMod ! respiration model. 1=Ryan (1991) (NOT YET IMPLEMENTED) integer,protected, public :: photo_tempsens_model ! switch for choosing the model that defines the temperature ! sensitivity of photosynthetic parameters (vcmax, jmax). - ! 1=non-acclimating (NOT YET IMPLEMENTED) + ! 1=non-acclimating, 2=Kumarathunge et al., 2019 real(r8),protected, public :: fates_mortality_disturbance_fraction ! the fraction of canopy mortality that results in disturbance real(r8),protected, public :: ED_val_comp_excln @@ -60,7 +60,6 @@ module EDParamsMod real(r8),protected, public :: ED_val_patch_fusion_tol 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 :: temp_acclim !switch for turning on and off temperature acclimation, 0 for off, 1 for Kumarathunge et al. temperature acclimation logical,protected, public :: active_crown_fire ! flag, 1=active crown fire 0=no active crown fire character(len=param_string_length),parameter :: fates_name_active_crown_fire = "fates_fire_active_crown_fire" @@ -121,7 +120,6 @@ 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_temp_acclim= "fates_leaf_temp_acclim" character(len=param_string_length),parameter,public :: name_theta_cj_c3 = "fates_leaf_theta_cj_c3" character(len=param_string_length),parameter,public :: name_theta_cj_c4 = "fates_leaf_theta_cj_c4" @@ -295,7 +293,6 @@ subroutine FatesParamsInit() maxpatch_primary = -9 maxpatch_secondary = -9 max_cohort_per_patch = -9 - temp_acclim = 0 hydr_kmax_rsurf1 = nan hydr_kmax_rsurf2 = nan hydr_psi0 = nan @@ -447,9 +444,6 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=hydr_name_solver, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) - call fates_params%RegisterParameter(name=ED_name_temp_acclim, dimension_shape=dimension_shape_scalar, & - dimension_names=dim_names_scalar) - call fates_params%RegisterParameter(name=hydr_name_kmax_rsurf1, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -653,11 +647,7 @@ subroutine FatesReceiveParams(fates_params) data=tmpreal) max_cohort_per_patch = nint(tmpreal) - call fates_params%RetreiveParameter(name=ED_name_temp_acclim, & - data=tmpreal) - temp_acclim = nint(tmpreal) - - call fates_params%RetreiveParameter(name=hydr_name_kmax_rsurf1, & + call fates_params%RetrieveParameter(name=hydr_name_kmax_rsurf1, & data=hydr_kmax_rsurf1) call fates_params%RetrieveParameter(name=hydr_name_kmax_rsurf2, & @@ -809,7 +799,6 @@ subroutine FatesReportParams(is_master) write(fates_log(),fmt0) 'hydro_psi0 = ',hydr_psi0 write(fates_log(),fmt0) 'hydro_psicap = ',hydr_psicap write(fates_log(),fmt0) 'hydro_solver = ',hydr_solver - write(fates_log(),fmt0) 'temp_acclim = ',temp_acclim write(fates_log(),fmt0) 'bgc_soil_salinity = ', bgc_soil_salinity write(fates_log(),fmt0) 'logging_dbhmin = ',logging_dbhmin write(fates_log(),fmt0) 'logging_dbhmax = ',logging_dbhmax diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index ef05154bd3..6b795a2f0a 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -66,8 +66,8 @@ module FatesConstantsMod ! secondary 1900s land in hurtt-2011 ! integer labels for specifying harvest units - integer, parameter, public :: photosynth_acclim_model_none = 0 - integer, parameter, public :: photosynth_acclim_model_kumarathunge_etal_2019 = 1 + integer, parameter, public :: photosynth_acclim_model_none = 1 + integer, parameter, public :: photosynth_acclim_model_kumarathunge_etal_2019 = 2 ! integer labels for specifying harvest units integer, parameter, public :: hlm_harvest_area_fraction = 1 ! Code for harvesting by area diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 5e89fed4d6..170cff8fff 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -991,7 +991,7 @@ subroutine InitTimeAveragingGlobals() call ema_lpa%define(photo_temp_acclim_timescale*sec_per_day, & hlm_stepsize,moving_ema_window) allocate(ema_longterm) ! for now just fix this as a 30-year exponential moving average - call ema_lpa%define(30._r8*365._r8*sec_per_day, & + call ema_longterm%define(30._r8*365._r8*sec_per_day, & hlm_stepsize,moving_ema_window) !allocate(ema_60day) From 6e9941abd7024fc0de97bd2df2817dedb30fd67a Mon Sep 17 00:00:00 2001 From: ckoven Date: Fri, 3 Feb 2023 11:31:48 -0700 Subject: [PATCH 515/852] updating metadata to reflect inclusion of Kumarathunge model --- parameter_files/fates_params_default.cdl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index c5ddba36c6..dc5b609d90 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -343,13 +343,13 @@ variables: fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; double fates_leaf_jmaxha(fates_pft) ; fates_leaf_jmaxha:units = "J/mol" ; - fates_leaf_jmaxha:long_name = "activation energy for jmax" ; + fates_leaf_jmaxha:long_name = "activation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; double fates_leaf_jmaxhd(fates_pft) ; fates_leaf_jmaxhd:units = "J/mol" ; - fates_leaf_jmaxhd:long_name = "deactivation energy for jmax" ; + fates_leaf_jmaxhd:long_name = "deactivation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; double fates_leaf_jmaxse(fates_pft) ; fates_leaf_jmaxse:units = "J/mol/K" ; - fates_leaf_jmaxse:long_name = "entropy term for jmax" ; + fates_leaf_jmaxse:long_name = "entropy term for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; double fates_leaf_slamax(fates_pft) ; fates_leaf_slamax:units = "m^2/gC" ; fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; @@ -370,13 +370,13 @@ variables: fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; double fates_leaf_vcmaxha(fates_pft) ; fates_leaf_vcmaxha:units = "J/mol" ; - fates_leaf_vcmaxha:long_name = "activation energy for vcmax" ; + fates_leaf_vcmaxha:long_name = "activation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; double fates_leaf_vcmaxhd(fates_pft) ; fates_leaf_vcmaxhd:units = "J/mol" ; - fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax" ; + fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; double fates_leaf_vcmaxse(fates_pft) ; fates_leaf_vcmaxse:units = "J/mol/K" ; - fates_leaf_vcmaxse:long_name = "entropy term for vcmax" ; + fates_leaf_vcmaxse:long_name = "entropy term for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; double fates_maintresp_reduction_curvature(fates_pft) ; fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; @@ -706,7 +706,7 @@ variables: fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; double fates_leaf_photo_tempsens_model ; fates_leaf_photo_tempsens_model:units = "unitless" ; - fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; + fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating; 2=Kumarathunge et al 2019" ; double fates_leaf_stomatal_assim_model ; fates_leaf_stomatal_assim_model:units = "unitless" ; fates_leaf_stomatal_assim_model:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; From dfa40ecb862666d1052ed57981f07df75d201701 Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Fri, 3 Feb 2023 13:38:15 -0700 Subject: [PATCH 516/852] updated cwd paritioning to send more to the smaller fuel classes --- biogeochem/FatesLitterMod.F90 | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/biogeochem/FatesLitterMod.F90 b/biogeochem/FatesLitterMod.F90 index 1bb03e99fd..1b779be374 100644 --- a/biogeochem/FatesLitterMod.F90 +++ b/biogeochem/FatesLitterMod.F90 @@ -463,22 +463,18 @@ subroutine adjust_SF_CWD_frac(dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) !gone to trunk fuel to large branch fuel (100 hr) instead. else if (dbh > sb_max_diam .and. dbh .le. lb_max_diam) then SF_val_CWD_frac_adj(ncwd) = 0.0 - SF_val_CWD_frac_adj(ncwd-1) = sum(SF_val_CWD_frac((ncwd-1):ncwd)) - - - !SF_val_CWD_frac_adj(3) = sum(SF_val_CWD_frac(3:4)) - !write(fates_log(),*) "using ahb trunk fuel fix", SF_val_CWD_frac_adj - + SF_val_CWD_frac_adj(ncwd-1) = SF_val_CWD_frac(ncwd) + SF_val_CWD_frac_adj(ncwd-2) = SF_val_CWD_frac(ncwd-1) + SF_val_CWD_frac_adj(ncwd-3) = sum(SF_val_CWD_frac((ncwd-3):(ncwd-2))) + !When dbh is greater than the max size of a twig (1 hr) but less than or !equal to the max size of a small branch (10 hr) we send the biomass that would have - !gone to trunk fuel / larger branch to small branch fuel instead. + !gone to trunk fuel and large branch fuel to small branch fuel instead. else if (dbh > twig_max_diam .and. dbh .le. sb_max_diam) then SF_val_CWD_frac_adj(ncwd) = 0.0 - !SF_val_CWD_frac_adj(4) = 0.0 SF_val_CWD_frac_adj(ncwd-1) = 0.0 - !SF_val_CWD_frac_adj(3) = 0.0 - SF_val_CWD_frac_adj(ncwd-2) = sum(SF_val_CWD_frac((ncwd-2):ncwd)) - !SF_val_CWD_frac_adj(2) = sum(SF_val_CWD_frac(2:4)) + SF_val_CWD_frac_adj(ncwd-2) = SF_val_CWD_frac(ncwd) + SF_val_CWD_frac_adj(ncwd-3) = sum(SF_val_CWD_frac((ncwd-3):(ncwd-1))) !If dbh is less than or equal to the max size of a twig we send all !biomass to twigs From b3d48fe49f87b96da31e7951d01a48f4e3de1338 Mon Sep 17 00:00:00 2001 From: ckoven Date: Fri, 3 Feb 2023 13:49:45 -0700 Subject: [PATCH 517/852] removed Aj, Ac, Ap -limited pohotosynthesis diagnostics --- biogeochem/EDPatchDynamicsMod.F90 | 3 - biogeophys/FatesPlantRespPhotosynthMod.F90 | 62 ---------------- main/EDTypesMod.F90 | 7 -- main/FatesHistoryInterfaceMod.F90 | 84 ---------------------- 4 files changed, 156 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 3be366b322..5702d17f8d 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -2218,9 +2218,6 @@ subroutine zero_patch(cp_p) currentPatch%ed_parsun_z(:,:,:) = nan currentPatch%ed_parsha_z(:,:,:) = nan currentPatch%psn_z(:,:,:) = 0._r8 - currentPatch%aj_z(:,:,:) = 0._r8 - currentPatch%ac_z(:,:,:) = 0._r8 - currentPatch%ap_z(:,:,:) = 0._r8 currentPatch%f_sun(:,:,:) = nan currentPatch%tr_soil_dir(:) = nan ! fraction of incoming direct radiation that is transmitted to the soil as direct diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 403370c2ae..827e92e804 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -599,9 +599,6 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) leaf_psi, & ! in bc_in(s)%rb_pa(ifp), & ! in currentPatch%psn_z(cl,ft,iv), & ! out - currentPatch%aj_z(cl,ft,iv), & ! out - currentPatch%ac_z(cl,ft,iv), & ! out - currentPatch%ap_z(cl,ft,iv), & ! out rs_z(iv,ft,cl), & ! out anet_av_z(iv,ft,cl), & ! out c13disc_z(cl,ft,iv)) ! out @@ -615,9 +612,6 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) currentCohort%npp_tstep = 0.0_r8 currentCohort%resp_tstep = 0.0_r8 currentCohort%gpp_tstep = 0.0_r8 - currentCohort%aj_sum_tstep = 0.0_r8 - currentCohort%ac_sum_tstep = 0.0_r8 - currentCohort%ap_sum_tstep = 0.0_r8 currentCohort%rdark = 0.0_r8 currentCohort%resp_m = 0.0_r8 currentCohort%ts_net_uptake = 0.0_r8 @@ -633,9 +627,6 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) nv = currentCohort%nv call ScaleLeafLayerFluxToCohort(nv, & !in currentPatch%psn_z(cl,ft,1:nv), & !in - currentPatch%aj_z(cl,ft,1:nv), & !in - currentPatch%ac_z(cl,ft,1:nv), & !in - currentPatch%ap_z(cl,ft,1:nv), & !in lmr_z(1:nv,ft,cl), & !in rs_z(1:nv,ft,cl), & !in currentPatch%elai_profile(cl,ft,1:nv), & !in @@ -646,9 +637,6 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) maintresp_reduction_factor, & !in currentCohort%g_sb_laweight, & !out currentCohort%gpp_tstep, & !out - currentCohort%aj_sum_tstep, & !out - currentCohort%ac_sum_tstep, & !out - currentCohort%ap_sum_tstep, & !out currentCohort%rdark, & !out currentCohort%c13disc_clm, & !out cohort_eleaf_area) !out @@ -663,9 +651,6 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! or dark respiration cohort_eleaf_area = 0.0_r8 currentCohort%gpp_tstep = 0.0_r8 - currentCohort%aj_sum_tstep = 0.0_r8 - currentCohort%ac_sum_tstep = 0.0_r8 - currentCohort%ap_sum_tstep = 0.0_r8 currentCohort%rdark = 0.0_r8 currentCohort%g_sb_laweight = 0.0_r8 currentCohort%ts_net_uptake(:) = 0.0_r8 @@ -851,9 +836,6 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! convert from kgC/indiv/s to kgC/indiv/timestep currentCohort%resp_m = currentCohort%resp_m * dtime currentCohort%gpp_tstep = currentCohort%gpp_tstep * dtime - currentCohort%aj_sum_tstep = currentCohort%aj_sum_tstep * dtime - currentCohort%ac_sum_tstep = currentCohort%ac_sum_tstep * dtime - currentCohort%ap_sum_tstep = currentCohort%ap_sum_tstep * dtime currentCohort%ts_net_uptake = currentCohort%ts_net_uptake * dtime if ( debug ) write(fates_log(),*) 'EDPhoto 911 ', currentCohort%gpp_tstep @@ -1048,9 +1030,6 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in leaf_psi, & ! in rb, & ! in psn_out, & ! out - aj_out, & ! out - ac_out, & ! out - ap_out, & ! out rstoma_out, & ! out anet_av_out, & ! out c13disc_z) ! out @@ -1109,9 +1088,6 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in real(r8), intent(in) :: rb ! Boundary Layer resistance of leaf [s/m] real(r8), intent(out) :: psn_out ! carbon assimilated in this leaf layer umolC/m2/s - real(r8), intent(out) :: aj_out ! RuBP-limited gross photosynthesis (umol CO2/m2/s) - real(r8), intent(out) :: ac_out ! Rubisco-limited gross photosynthesis (umol CO2/m2/s) - real(r8), intent(out) :: ap_out ! Product-limited gross photosynthesis (umol CO2/m2/s) real(r8), intent(out) :: rstoma_out ! stomatal resistance (1/gs_lsl) (s/m) real(r8), intent(out) :: anet_av_out ! net leaf photosynthesis (umol CO2/m**2/s) ! averaged over sun and shade leaves. @@ -1196,9 +1172,6 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in anet_av_out = -lmr psn_out = 0._r8 - aj_out = 0._r8 - ac_out = 0._r8 - ap_out = 0._r8 ! The cuticular conductance already factored in maximum resistance as a bound ! no need to re-bound it @@ -1215,9 +1188,6 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in !Loop aroun shaded and unshaded leaves psn_out = 0._r8 ! psn is accumulated across sun and shaded leaves. - aj_out = 0._r8 - ac_out = 0._r8 - ap_out = 0._r8 rstoma_out = 0._r8 ! 1/rs is accumulated across sun and shaded leaves. anet_av_out = 0._r8 gstoma = 0._r8 @@ -1414,16 +1384,10 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in ! weight per unit sun and sha leaves. if(sunsha == 1)then !sunlit psn_out = psn_out + agross * f_sun_lsl - aj_out = aj_out + aj * f_sun_lsl - ac_out = ac_out + ac * f_sun_lsl - ap_out = ap_out + ap * f_sun_lsl anet_av_out = anet_av_out + anet * f_sun_lsl gstoma = gstoma + 1._r8/(min(1._r8/gs, rsmax0)) * f_sun_lsl else psn_out = psn_out + agross * (1.0_r8-f_sun_lsl) - aj_out = aj_out + aj * (1.0_r8-f_sun_lsl) - ac_out = ac_out + ac * (1.0_r8-f_sun_lsl) - ap_out = ap_out + ap * (1.0_r8-f_sun_lsl) anet_av_out = anet_av_out + anet * (1.0_r8-f_sun_lsl) gstoma = gstoma + & 1._r8/(min(1._r8/gs, rsmax0)) * (1.0_r8-f_sun_lsl) @@ -1469,9 +1433,6 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in ! (leaves are off, or have reduced to 0) psn_out = 0._r8 - aj_out = 0._r8 - ac_out = 0._r8 - ap_out = 0._r8 anet_av_out = 0._r8 rstoma_out = min(rsmax0,cf/(stem_cuticle_loss_frac*stomatal_intercept(ft))) @@ -1586,9 +1547,6 @@ end function LeafHumidityStomaResis subroutine ScaleLeafLayerFluxToCohort(nv, & ! in currentCohort%nv psn_llz, & ! in %psn_z(1:currentCohort%nv,ft,cl) - aj_llz, & ! in %aj_z(1:currentCohort%nv,ft,cl) - ac_llz, & ! in %ac_z(1:currentCohort%nv,ft,cl) - ap_llz, & ! in %ap_z(1:currentCohort%nv,ft,cl) lmr_llz, & ! in lmr_z(1:currentCohort%nv,ft,cl) rs_llz, & ! in rs_z(1:currentCohort%nv,ft,cl) elai_llz, & ! in %elai_profile(cl,ft,1:currentCohort%nv) @@ -1599,9 +1557,6 @@ subroutine ScaleLeafLayerFluxToCohort(nv, & ! in currentCohort%nv maintresp_reduction_factor, & ! in g_sb_laweight, & ! out currentCohort%g_sb_laweight [m/s] [m2-leaf] gpp, & ! out currentCohort%gpp_tstep - aj_sum, & ! out currentCohort%aj_sum_tstep - ac_sum, & ! out currentCohort%ac_sum_tstep - ap_sum, & ! out currentCohort%ap_sum_tstep rdark, & ! out currentCohort%rdark c13disc_clm, & ! out currentCohort%c13disc_clm cohort_eleaf_area ) ! out [m2] @@ -1619,9 +1574,6 @@ subroutine ScaleLeafLayerFluxToCohort(nv, & ! in currentCohort%nv ! Arguments integer, intent(in) :: nv ! number of active leaf layers real(r8), intent(in) :: psn_llz(nv) ! layer photosynthesis rate (GPP) [umolC/m2leaf/s] - real(r8), intent(in) :: aj_llz(nv) ! layer RuBP-limited photosynthesis rate [umolC/m2leaf/s] - real(r8), intent(in) :: ac_llz(nv) ! layer Rubisco-limited photosynthesis rate [umolC/m2leaf/s] - real(r8), intent(in) :: ap_llz(nv) ! layer Product-limited photosynthesis rate [umolC/m2leaf/s] real(r8), intent(in) :: lmr_llz(nv) ! layer dark respiration rate [umolC/m2leaf/s] real(r8), intent(in) :: rs_llz(nv) ! leaf layer stomatal resistance [s/m] real(r8), intent(in) :: elai_llz(nv) ! exposed LAI per layer [m2 leaf/ m2 pft footprint] @@ -1633,9 +1585,6 @@ subroutine ScaleLeafLayerFluxToCohort(nv, & ! in currentCohort%nv real(r8), intent(out) :: g_sb_laweight ! Combined conductance (stomatal + boundary layer) for the cohort ! weighted by leaf area [m/s]*[m2] real(r8), intent(out) :: gpp ! GPP (kgC/indiv/s) - real(r8), intent(out) :: aj_sum ! RuBP-limited GPP (kgC/indiv/s) - real(r8), intent(out) :: ac_sum ! Rubisco-limited GPP (kgC/indiv/s) - real(r8), intent(out) :: ap_sum ! Product-limited GPP (kgC/indiv/s) real(r8), intent(out) :: rdark ! Dark Leaf Respiration (kgC/indiv/s) real(r8), intent(out) :: cohort_eleaf_area ! Effective leaf area of the cohort [m2] real(r8), intent(out) :: c13disc_clm ! unpacked Cohort level c13 discrimination @@ -1652,9 +1601,6 @@ subroutine ScaleLeafLayerFluxToCohort(nv, & ! in currentCohort%nv cohort_eleaf_area = 0.0_r8 g_sb_laweight = 0.0_r8 gpp = 0.0_r8 - aj_sum = 0.0_r8 - ac_sum = 0.0_r8 - ap_sum = 0.0_r8 rdark = 0.0_r8 do il = 1, nv ! Loop over the leaf layers this cohort participates in @@ -1680,11 +1626,6 @@ subroutine ScaleLeafLayerFluxToCohort(nv, & ! in currentCohort%nv ! GPP [umolC/m2leaf/s] * [m2 leaf ] -> [umolC/s] (This is cohort group sum) gpp = gpp + psn_llz(il) * cohort_layer_eleaf_area - ! RuBP-, rubisco-, and product-limited GPP - aj_sum = aj_sum + aj_llz(il) * cohort_layer_eleaf_area - ac_sum = ac_sum + ac_llz(il) * cohort_layer_eleaf_area - ap_sum = ap_sum + ap_llz(il) * cohort_layer_eleaf_area - ! Dark respiration ! [umolC/m2leaf/s] * [m2 leaf] (This is the cohort group sum) rdark = rdark + lmr_llz(il) * cohort_layer_eleaf_area @@ -1719,9 +1660,6 @@ subroutine ScaleLeafLayerFluxToCohort(nv, & ! in currentCohort%nv rdark = rdark * umolC_to_kgC * maintresp_reduction_factor / nplant gpp = gpp * umolC_to_kgC / nplant - aj_sum = aj_sum * umolC_to_kgC / nplant - ac_sum = ac_sum * umolC_to_kgC / nplant - ap_sum = ap_sum * umolC_to_kgC / nplant if ( debug ) then write(fates_log(),*) 'EDPhoto 816 ', gpp diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 242fa65b0d..2bf3d670e3 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -273,10 +273,6 @@ module EDTypesMod real(r8) :: gpp_acc real(r8) :: gpp_acc_hold - real(r8) :: aj_sum_tstep ! RuBP-limited gross Primary Production (see above *) - real(r8) :: ac_sum_tstep ! Rubisco-limited gross Primary Production (see above *) - real(r8) :: ap_sum_tstep ! Product-limited gross Primary Production (see above *) - real(r8) :: npp_tstep ! Net Primary Production (see above *) real(r8) :: npp_acc real(r8) :: npp_acc_hold @@ -551,9 +547,6 @@ module EDTypesMod ! PHOTOSYNTHESIS real(r8) :: psn_z(nclmax,maxpft,nlevleaf) ! carbon assimilation in each canopy layer, pft, and leaf layer. umolC/m2/s - real(r8) :: aj_z(nclmax,maxpft,nlevleaf) ! RuBP-limited carbon assimilation in each canopy layer, pft, and leaf layer. umolC/m2/s - real(r8) :: ac_z(nclmax,maxpft,nlevleaf) ! Rubisco-limited carbon assimilation in each canopy layer, pft, and leaf layer. umolC/m2/s - real(r8) :: ap_z(nclmax,maxpft,nlevleaf) ! Product-limited carbon assimilation in each canopy layer, pft, and leaf layer. umolC/m2/s ! ROOTS real(r8) :: btran_ft(maxpft) ! btran calculated seperately for each PFT:- diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 075eea9509..189cab5be1 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -283,23 +283,14 @@ module FatesHistoryInterfaceMod integer :: ih_agb_si integer :: ih_npp_si integer :: ih_gpp_si - integer :: ih_aj_si - integer :: ih_ac_si - integer :: ih_ap_si integer :: ih_aresp_si integer :: ih_maint_resp_si integer :: ih_growth_resp_si integer :: ih_excess_resp_si integer :: ih_ar_canopy_si integer :: ih_gpp_canopy_si - integer :: ih_aj_canopy_si - integer :: ih_ac_canopy_si - integer :: ih_ap_canopy_si integer :: ih_ar_understory_si integer :: ih_gpp_understory_si - integer :: ih_aj_understory_si - integer :: ih_ac_understory_si - integer :: ih_ap_understory_si integer :: ih_canopy_biomass_si integer :: ih_understory_biomass_si @@ -4307,10 +4298,6 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) associate( hio_gpp_si => this%hvars(ih_gpp_si)%r81d, & hio_gpp_secondary_si => this%hvars(ih_gpp_secondary_si)%r81d, & - hio_aj_si => this%hvars(ih_aj_si)%r81d, & - hio_ac_si => this%hvars(ih_ac_si)%r81d, & - hio_ap_si => this%hvars(ih_ap_si)%r81d, & - hio_npp_si => this%hvars(ih_npp_si)%r81d, & hio_npp_secondary_si => this%hvars(ih_npp_secondary_si)%r81d, & hio_aresp_si => this%hvars(ih_aresp_si)%r81d, & @@ -4332,14 +4319,8 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) hio_ar_crootm_si_scpf => this%hvars(ih_ar_crootm_si_scpf)%r82d, & hio_ar_frootm_si_scpf => this%hvars(ih_ar_frootm_si_scpf)%r82d, & hio_gpp_canopy_si => this%hvars(ih_gpp_canopy_si)%r81d, & - hio_aj_canopy_si => this%hvars(ih_aj_canopy_si)%r81d, & - hio_ac_canopy_si => this%hvars(ih_ac_canopy_si)%r81d, & - hio_ap_canopy_si => this%hvars(ih_ap_canopy_si)%r81d, & hio_ar_canopy_si => this%hvars(ih_ar_canopy_si)%r81d, & hio_gpp_understory_si => this%hvars(ih_gpp_understory_si)%r81d, & - hio_aj_understory_si => this%hvars(ih_aj_understory_si)%r81d, & - hio_ac_understory_si => this%hvars(ih_ac_understory_si)%r81d, & - hio_ap_understory_si => this%hvars(ih_ap_understory_si)%r81d, & hio_ar_understory_si => this%hvars(ih_ar_understory_si)%r81d, & hio_rdark_canopy_si_scls => this%hvars(ih_rdark_canopy_si_scls)%r82d, & hio_livestem_mr_canopy_si_scls => this%hvars(ih_livestem_mr_canopy_si_scls)%r82d, & @@ -4473,13 +4454,6 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) hio_gpp_si(io_si) = hio_gpp_si(io_si) + & ccohort%gpp_tstep * n_perm2 * per_dt_tstep - hio_aj_si(io_si) = hio_aj_si(io_si) + & - ccohort%aj_sum_tstep * g_per_kg * n_perm2 * per_dt_tstep - hio_ac_si(io_si) = hio_ac_si(io_si) + & - ccohort%ac_sum_tstep * g_per_kg * n_perm2 * per_dt_tstep - hio_ap_si(io_si) = hio_ap_si(io_si) + & - ccohort%ap_sum_tstep * g_per_kg * n_perm2 * per_dt_tstep - hio_aresp_si(io_si) = hio_aresp_si(io_si) + & aresp * n_perm2 * per_dt_tstep hio_growth_resp_si(io_si) = hio_growth_resp_si(io_si) + & @@ -4559,13 +4533,6 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) hio_gpp_canopy_si(io_si) = hio_gpp_canopy_si(io_si) + & ccohort%gpp_tstep * n_perm2 * per_dt_tstep - hio_aj_canopy_si(io_si) = hio_aj_canopy_si(io_si) + & - ccohort%aj_sum_tstep * g_per_kg * n_perm2 * per_dt_tstep - hio_ac_canopy_si(io_si) = hio_ac_canopy_si(io_si) + & - ccohort%ac_sum_tstep * g_per_kg * n_perm2 * per_dt_tstep - hio_ap_canopy_si(io_si) = hio_ap_canopy_si(io_si) + & - ccohort%ap_sum_tstep * g_per_kg * n_perm2 * per_dt_tstep - hio_ar_canopy_si(io_si) = hio_ar_canopy_si(io_si) + & aresp * n_perm2 * per_dt_tstep @@ -4590,12 +4557,6 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) hio_gpp_understory_si(io_si) = hio_gpp_understory_si(io_si) + & ccohort%gpp_tstep * n_perm2 * per_dt_tstep - hio_aj_understory_si(io_si) = hio_aj_understory_si(io_si) + & - ccohort%aj_sum_tstep * g_per_kg * n_perm2 * per_dt_tstep - hio_ac_understory_si(io_si) = hio_ac_understory_si(io_si) + & - ccohort%ac_sum_tstep * g_per_kg * n_perm2 * per_dt_tstep - hio_ap_understory_si(io_si) = hio_ap_understory_si(io_si) + & - ccohort%ap_sum_tstep * g_per_kg * n_perm2 * per_dt_tstep hio_ar_understory_si(io_si) = hio_ar_understory_si(io_si) + & aresp * n_perm2 * per_dt_tstep @@ -6278,21 +6239,6 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & ivar=ivar, initialize=initialize_variables, index = ih_rad_error_si) - call this%set_history_var(vname='FATES_AJ', units='gC/m^2/s', & - long='RuBP-limited gross primary production', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_aj_si ) - - call this%set_history_var(vname='FATES_AC', units='gC/m^2/s', & - long='Rubisco-limited gross primary production', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_ac_si ) - - call this%set_history_var(vname='FATES_AP', units='gC/m^2/s', & - long='Product-limited gross primary production', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_ap_si ) - call this%set_history_var(vname='FATES_AR', units='gC/m^2/s', & long='autotrophic respiration', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & @@ -6379,21 +6325,6 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=2, ivar=ivar, initialize=initialize_variables, & index = ih_c_stomata_si_age) - call this%set_history_var(vname='FATES_AJ_CANOPY', units='gC/m^2/s', & - long='RuBP-limited gross primary production of canopy plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_aj_canopy_si ) - - call this%set_history_var(vname='FATES_AC_CANOPY', units='gC/m^2/s', & - long='Rubisco-limited gross primary production of canopy plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_ac_canopy_si ) - - call this%set_history_var(vname='FATES_AP_CANOPY', units='gC/m^2/s', & - long='Product-limited gross primary production of canopy plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_ap_canopy_si ) - call this%set_history_var(vname='FATES_AR_CANOPY', units='gC/m^2/s', & long='autotrophic respiration of canopy plants', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & @@ -6419,21 +6350,6 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=2, ivar=ivar, initialize=initialize_variables, & index = ih_gpp_si_age) - call this%set_history_var(vname='FATES_AJ_UNDERSTORY', units='gC/m^2/s', & - long='RuBP-limited gross primary production of understory plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_aj_understory_si ) - - call this%set_history_var(vname='FATES_AC_UNDERSTORY', units='gC/m^2/s', & - long='Rubisco-limited gross primary production of understory plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_ac_understory_si ) - - call this%set_history_var(vname='FATES_AP_UNDERSTORY', units='gC/m^2/s', & - long='Product-limited gross primary production of understory plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_ap_understory_si ) - call this%set_history_var(vname='FATES_AR_UNDERSTORY', units='gC/m^2/s', & long='autotrophic respiration of understory plants', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & From 924f59a6723cbb9183383dd18057575c88a14878 Mon Sep 17 00:00:00 2001 From: ckoven Date: Thu, 9 Feb 2023 12:21:20 -0700 Subject: [PATCH 518/852] added long-term tveg as a history variable --- main/FatesHistoryInterfaceMod.F90 | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index dd8621b5fc..7d5cf8a0dc 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -331,6 +331,7 @@ module FatesHistoryInterfaceMod ! Indices to (site) variables integer :: ih_tveg24_si + integer :: ih_tlongterm_si integer :: ih_tveg_si integer :: ih_nep_si integer :: ih_hr_si @@ -2479,6 +2480,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_dleafoff_si => this%hvars(ih_dleafoff_si)%r81d, & hio_dleafon_si => this%hvars(ih_dleafon_si)%r81d, & hio_tveg24 => this%hvars(ih_tveg24_si)%r81d, & + hio_tlongterm => this%hvars(ih_tlongterm_si)%r81d, & hio_meanliqvol_si => this%hvars(ih_meanliqvol_si)%r81d, & hio_cbal_err_fates_si => this%hvars(ih_cbal_err_fates_si)%r81d, & hio_err_fates_si => this%hvars(ih_err_fates_si)%r82d, & @@ -2650,6 +2652,10 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_tveg24(io_si) = hio_tveg24(io_si) + & (cpatch%tveg24%GetMean()- t_water_freeze_k_1atm)*cpatch%area*AREA_INV + ! long-term veg temperature + hio_tlongterm(io_si) = hio_tlongterm(io_si) + & + (cpatch%tveg_longterm%GetMean()- t_water_freeze_k_1atm)*cpatch%area*AREA_INV + ! Increment some patch-age-resolved diagnostics hio_lai_si_age(io_si,cpatch%age_class) = hio_lai_si_age(io_si,cpatch%age_class) & + sum(cpatch%tlai_profile(:,:,:)) * cpatch%area @@ -6290,6 +6296,12 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & ivar=ivar, initialize=initialize_variables, index = ih_tveg24_si ) + call this%set_history_var(vname='FATES_TLONGTERM', units='degree_Celsius', & + long='fates 30-year running mean vegetation temperature by site', & + use_default='inactive', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_tlongterm_si ) + call this%set_history_var(vname='FATES_TVEG', units='degree_Celsius', & long='fates instantaneous mean vegetation temperature by site', & use_default='active', & From 068ac1d344760cc241c2044338c44871b0cb18ae Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 10 Feb 2023 17:56:53 -0500 Subject: [PATCH 519/852] Remove target attribute from parteh and cohort input arguments --- biogeochem/EDCohortDynamicsMod.F90 | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 4948f68129..38485ef5a3 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -179,7 +179,8 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & real(r8), intent(in) :: hite ! height: meters real(r8), intent(in) :: coage ! cohort age in years real(r8), intent(in) :: dbh ! dbh: cm - class(prt_vartypes),target :: prt ! The allocated PARTEH + class(prt_vartypes),intent(inout), pointer :: prt ! The allocated PARTEH + !class(prt_vartypes),target :: prt ! The allocated PARTEH ! object real(r8), intent(in) :: leafmemory ! target leaf biomass- set from ! previous year: kGC per indiv @@ -1680,9 +1681,9 @@ subroutine insert_cohort(pcc, ptall, pshort, tnull, snull, storebigcohort, store ! !USES: ! ! !ARGUMENTS - type(ed_cohort_type) , intent(inout), target :: pcc - type(ed_cohort_type) , intent(inout), target :: ptall - type(ed_cohort_type) , intent(inout), target :: pshort + type(ed_cohort_type) , intent(inout), pointer :: pcc + type(ed_cohort_type) , intent(inout), pointer :: ptall + type(ed_cohort_type) , intent(inout), pointer :: pshort integer , intent(in) :: tnull integer , intent(in) :: snull type(ed_cohort_type) , intent(inout),pointer,optional :: storesmallcohort ! storage of the smallest cohort for insertion routine From 645fcbf0c6e3dfd8bde3597976264be3b2193d28 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 13 Feb 2023 16:47:49 -0800 Subject: [PATCH 520/852] add check to return dispersal time check as being off if dispersal mode is not true --- main/FatesDispersalMod.F90 | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index 36ef7e9539..17a59bdbfb 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -206,6 +206,9 @@ logical function IsItDispersalTime(setdispersedflag) ! to pass dispersed seeds to fates. Set dispersed flag to false. Given that this must ! happen after WrapSeedGlobal, but can be threaded this takes place at the top of the ! dynamics_driv call. + + use FatesInterfaceTypesMod, only : fates_dispersal_kernel_mode + use FatesInterfaceTypesMod, only : fates_dispersal_kernel_none ! Arguments logical, optional :: setdispersedflag ! Has the global dispersal been completed? @@ -215,6 +218,10 @@ logical function IsItDispersalTime(setdispersedflag) ! The default return value is false IsItDispersalTime = .false. + + ! Check if seed dispersal mode is 'turned on' by checking the parameter values + ! If it is off, return false by default + if (fates_dispersal_kernel_mode .eq. fates_dispersal_kernel_none) return ! Check if set dispersal flag is provided. This should be provided during a check ! when the flag should be set to true after the global dispersal From dcfcbd3aa67cd18095fcb41c2405b9eab912d5c9 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 13 Feb 2023 16:55:54 -0800 Subject: [PATCH 521/852] add local dispersal fraction variable that depends on the dispersal kernal flag --- biogeochem/EDPhysiologyMod.F90 | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 70d7bade04..ba42b7400a 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1582,6 +1582,8 @@ subroutine SeedUpdate( currentSite, bc_in, bc_out) ! !USES: use EDTypesMod, only : area use EDTypesMod, only : homogenize_seed_pfts + use FatesInterfaceTypesMod, only : fates_dispersal_kernel_mode + use FatesInterfaceTypesMod, only : fates_dispersal_kernel_none !use FatesInterfaceTypesMod, only : hlm_use_fixed_biogeog ! For future reduced complexity? ! ! !ARGUMENTS @@ -1597,6 +1599,7 @@ subroutine SeedUpdate( currentSite, bc_in, bc_out) integer :: pft real(r8) :: store_m_to_repro ! mass sent from storage to reproduction upon death [kg/plant] real(r8) :: site_seed_rain(maxpft) ! This is the sum of seed-rain for the site [kg/site/day] + real(r8) :: site_disp_frac(maxpft) ! Fraction of seeds to disperse out to other sites real(r8) :: seed_in_external ! Mass of externally generated seeds [kg/m2/day] real(r8) :: seed_stoich ! Mass ratio of nutrient per C12 in seeds [kg/kg] real(r8) :: seed_prod ! Seed produced in this dynamics step [kg/day] @@ -1607,8 +1610,12 @@ subroutine SeedUpdate( currentSite, bc_in, bc_out) do el = 1, num_elements site_seed_rain(:) = 0._r8 + site_disp_frac(:) = 0._r8 - EDPftvarcon_inst%seed_dispersal_fraction(:) = 0.2 ! to be specified in the parameter file or calculated using dispersal kernel + ! If the dispersal kernel is not turned on, set the dispersal fraction to zero + if (fates_dispersal_kernel_mode .ne. fates_dispersal_kernel_none) then + site_disp_frac(:) = EDPftvarcon_inst%seed_dispersal_fraction(:) + end if element_id = element_list(el) @@ -1678,7 +1685,7 @@ subroutine SeedUpdate( currentSite, bc_in, bc_out) if(currentSite%use_this_pft(pft).eq.itrue)then ! Seed input from local sources (within site) - litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)*(1-EDPftvarcon_inst%seed_dispersal_fraction(pft))/area ![kg/m2/day] + litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)*(1-site_disp_frac(pft))/area ![kg/m2/day] !write(fates_log(),*) 'pft, litt%seed_in_local(pft), site_seed_rain(pft): ', pft, litt%seed_in_local(pft), site_seed_rain(pft) ! If there is forced external seed rain, we calculate the input mass flux @@ -1715,14 +1722,14 @@ subroutine SeedUpdate( currentSite, bc_in, bc_out) enddo do pft = 1,numpft - site_mass%seed_out = site_mass%seed_out + site_seed_rain(pft)*EDPftvarcon_inst%seed_dispersal_fraction(pft) ![kg/site/day] + site_mass%seed_out = site_mass%seed_out + site_seed_rain(pft)*site_disp_frac(pft) ![kg/site/day] !write(fates_log(),*) 'pft, site_seed_rain(pft), site_mass%seed_out: ', pft, site_mass%seed_out end do end do do pft = 1,numpft - bc_out%seed_out(pft) = bc_out%seed_out(pft) + site_seed_rain(pft)*EDPftvarcon_inst%seed_dispersal_fraction(pft) ![kg/site/day] + bc_out%seed_out(pft) = bc_out%seed_out(pft) + site_seed_rain(pft)*site_disp_frac(pft) ![kg/site/day] ! write(fates_log(),*) 'pft, bc_in%seed_in(pft), bc_out%seed_out(pft): ', pft, bc_in%seed_in(pft), bc_out%seed_out(pft) end do From 5d90def53edf4f0977d1a4f7a4758176dce02797 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 14 Feb 2023 10:08:57 -0800 Subject: [PATCH 522/852] update parameter file checks for all seed_dispersal params --- main/EDPftvarcon.F90 | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index c1f9470199..16b38ff736 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1649,45 +1649,56 @@ subroutine FatesCheckParams(is_master) do ipft = 1,npft - ! Check that parameter ranges for the seed dispersal scale parameter make sense + ! Check that the seed dispersal parameters are all set if one of them is set !----------------------------------------------------------------------------------- if (( EDPftvarcon_inst%seed_dispersal_param_A(ipft) < fates_check_param_set ) .and. & - (( EDPftvarcon_inst%seed_dispersal_max_dist(ipft) > fates_check_param_set ) .or. & - ( EDPftvarcon_inst%seed_dispersal_param_B(ipft) > fates_check_param_set )) ) then + (( EDPftvarcon_inst%seed_dispersal_max_dist(ipft) > fates_check_param_set ) .or. & + ( EDPftvarcon_inst%seed_dispersal_param_B(ipft) > fates_check_param_set ) .or. & + ( EDPftvarcon_inst%seed_dispersal_fraction(ipft) > fates_check_param_set ))) then write(fates_log(),*) 'Seed dispersal is on per fates_seed_dispersal_param_A being set' - write(fates_log(),*) 'Please also set fates_seed_dispersal_param_B and fates_seed_dispersal_max_dist' + write(fates_log(),*) 'Please provide values for all other seed_dispersal parameters' write(fates_log(),*) 'See Bullock et al. (2017) for reasonable values' write(fates_log(),*) 'Aborting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if - ! Check that parameter ranges for the seed dispersal shape parameter make sense - !----------------------------------------------------------------------------------- if (( EDPftvarcon_inst%seed_dispersal_param_B(ipft) < fates_check_param_set ) .and. & - (( EDPftvarcon_inst%seed_dispersal_max_dist(ipft) > fates_check_param_set ) .or. & - ( EDPftvarcon_inst%seed_dispersal_param_A(ipft) > fates_check_param_set ))) then + (( EDPftvarcon_inst%seed_dispersal_max_dist(ipft) > fates_check_param_set ) .or. & + ( EDPftvarcon_inst%seed_dispersal_param_A(ipft) > fates_check_param_set ) .or. & + ( EDPftvarcon_inst%seed_dispersal_fraction(ipft) > fates_check_param_set ))) then write(fates_log(),*) 'Seed dispersal is on per fates_seed_dispersal_param_B being set' - write(fates_log(),*) 'Please also set fates_seed_dispersal_param_A and fates_seed_dispersal_max_dist' + write(fates_log(),*) 'Please provide values for all other seed_dispersal parameters' write(fates_log(),*) 'See Bullock et al. (2017) for reasonable values' write(fates_log(),*) 'Aborting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if - ! Check that parameter ranges for the seed dispersal shape parameter make sense - !----------------------------------------------------------------------------------- if (( EDPftvarcon_inst%seed_dispersal_max_dist(ipft) < fates_check_param_set ) .and. & - (( EDPftvarcon_inst%seed_dispersal_param_B(ipft) > fates_check_param_set ) .or. & - ( EDPftvarcon_inst%seed_dispersal_param_A(ipft) > fates_check_param_set ))) then + (( EDPftvarcon_inst%seed_dispersal_param_B(ipft) > fates_check_param_set ) .or. & + ( EDPftvarcon_inst%seed_dispersal_param_A(ipft) > fates_check_param_set ) .or. & + ( EDPftvarcon_inst%seed_dispersal_fraction(ipft) > fates_check_param_set ))) then write(fates_log(),*) 'Seed dispersal is on per seed_dispersal_max_dist being set' - write(fates_log(),*) 'Please also set fates_seed_dispersal_param_A and fates_seed_dispersal_param_B' + write(fates_log(),*) 'Please provide values for all other seed_dispersal parameters' write(fates_log(),*) 'See Bullock et al. (2017) for reasonable values' write(fates_log(),*) 'Aborting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if + if (( EDPftvarcon_inst%seed_dispersal_fraction(ipft) < fates_check_param_set ) .and. & + (( EDPftvarcon_inst%seed_dispersal_param_B(ipft) > fates_check_param_set ) .or. & + ( EDPftvarcon_inst%seed_dispersal_param_A(ipft) > fates_check_param_set ) .or. & + ( EDPftvarcon_inst%seed_dispersal_max_dist(ipft) > fates_check_param_set ))) then + + write(fates_log(),*) 'Seed dispersal is on per seed_dispersal_fraction being set' + write(fates_log(),*) 'Please provide values for all other seed_dispersal parameters' + write(fates_log(),*) 'See Bullock et al. (2017) for reasonable values' + write(fates_log(),*) 'Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + ! Check that parameter ranges for the seed dispersal fraction make sense !----------------------------------------------------------------------------------- if (( EDPftvarcon_inst%seed_dispersal_fraction(ipft) < fates_check_param_set ) .and. & From db945984d134a133a6b3ee8d83aa59cd2cd3815f Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 14 Feb 2023 10:17:58 -0800 Subject: [PATCH 523/852] comment clarification --- biogeochem/EDPhysiologyMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index ba42b7400a..3d76b8a64d 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1612,7 +1612,7 @@ subroutine SeedUpdate( currentSite, bc_in, bc_out) site_seed_rain(:) = 0._r8 site_disp_frac(:) = 0._r8 - ! If the dispersal kernel is not turned on, set the dispersal fraction to zero + ! If the dispersal kernel is not turned on, keep the dispersal fraction at zero if (fates_dispersal_kernel_mode .ne. fates_dispersal_kernel_none) then site_disp_frac(:) = EDPftvarcon_inst%seed_dispersal_fraction(:) end if From 530afce45a92fb3b32f3f22a57b7abfc5521d7c5 Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Thu, 16 Feb 2023 15:30:47 -0700 Subject: [PATCH 524/852] updated the cwd partitioning to keep the proportions the same among the burnable classes --- biogeochem/FatesLitterMod.F90 | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/biogeochem/FatesLitterMod.F90 b/biogeochem/FatesLitterMod.F90 index 1b779be374..c19857473a 100644 --- a/biogeochem/FatesLitterMod.F90 +++ b/biogeochem/FatesLitterMod.F90 @@ -459,23 +459,26 @@ subroutine adjust_SF_CWD_frac(dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) return !When dbh is greater than the max size of a small branch (10 hr) but less than or - !equal to the max size of a large branch we send the biomass that would have - !gone to trunk fuel to large branch fuel (100 hr) instead. + !equal to the max size of a large branch we redistribute the biomass among the smaller + !pools, keeping the biomass proportions the same among the combustible classes. else if (dbh > sb_max_diam .and. dbh .le. lb_max_diam) then SF_val_CWD_frac_adj(ncwd) = 0.0 - SF_val_CWD_frac_adj(ncwd-1) = SF_val_CWD_frac(ncwd) - SF_val_CWD_frac_adj(ncwd-2) = SF_val_CWD_frac(ncwd-1) - SF_val_CWD_frac_adj(ncwd-3) = sum(SF_val_CWD_frac((ncwd-3):(ncwd-2))) + SF_val_CWD_frac_adj(ncwd-1) = SF_val_CWD_frac(ncwd-1) / (1.0_r - SF_val_CWD_frac(ncwd) ) + SF_val_CWD_frac_adj(ncwd-2) = SF_val_CWD_frac(ncwd-2) / (1.0_r - SF_val_CWD_frac(ncwd) ) + SF_val_CWD_frac_adj(ncwd-3) = SF_val_CWD_frac(ncwd-3) / (1.0_r - SF_val_CWD_frac(ncwd) ) + !When dbh is greater than the max size of a twig (1 hr) but less than or - !equal to the max size of a small branch (10 hr) we send the biomass that would have - !gone to trunk fuel and large branch fuel to small branch fuel instead. + !equal to the max size of a small branch (10 hr) we redistribute the biomass among the smaller + !pools, keeping the biomass proportions the same among the combustible classes. else if (dbh > twig_max_diam .and. dbh .le. sb_max_diam) then SF_val_CWD_frac_adj(ncwd) = 0.0 SF_val_CWD_frac_adj(ncwd-1) = 0.0 - SF_val_CWD_frac_adj(ncwd-2) = SF_val_CWD_frac(ncwd) - SF_val_CWD_frac_adj(ncwd-3) = sum(SF_val_CWD_frac((ncwd-3):(ncwd-1))) - + SF_val_CWD_frac_adj(ncwd-2) = SF_val_CWD_frac(ncwd-2) / (1.0_r - (SF_val_CWD_frac(ncwd) + & + SF_val_CWD_frac(ncwd-1))) + SF_val_CWD_frac_adj(ncwd-3) = SF_val_CWD_frac(ncwd-3) / (1.0_r - (SF_val_CWD_frac(ncwd) + & + SF_val_CWD_frac(ncwd-1))) + !If dbh is less than or equal to the max size of a twig we send all !biomass to twigs else if (dbh .le. twig_max_diam) then From c2a1dd84bac6a64fd11cb2548710dc210eb9e61a Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 16 Feb 2023 14:37:28 -0800 Subject: [PATCH 525/852] add xml patch file for update to api25.1.1 --- .../api25.1.0_021623_fates_params_default.cdl | 1541 +++++++++++++++++ .../archive/api25.1.1_021623_pr931.xml | 15 + parameter_files/fates_params_default.cdl | 530 +++--- 3 files changed, 1822 insertions(+), 264 deletions(-) create mode 100644 parameter_files/archive/api25.1.0_021623_fates_params_default.cdl create mode 100644 parameter_files/archive/api25.1.1_021623_pr931.xml diff --git a/parameter_files/archive/api25.1.0_021623_fates_params_default.cdl b/parameter_files/archive/api25.1.0_021623_fates_params_default.cdl new file mode 100644 index 0000000000..c5ddba36c6 --- /dev/null +++ b/parameter_files/archive/api25.1.0_021623_fates_params_default.cdl @@ -0,0 +1,1541 @@ +netcdf fates_params_default { +dimensions: + fates_NCWD = 4 ; + fates_history_age_bins = 7 ; + fates_history_coage_bins = 2 ; + fates_history_damage_bins = 2 ; + fates_history_height_bins = 6 ; + fates_history_size_bins = 13 ; + fates_hlm_pftno = 14 ; + fates_hydr_organs = 4 ; + fates_leafage_class = 1 ; + fates_litterclass = 6 ; + fates_pft = 12 ; + fates_plant_organs = 4 ; + fates_string_length = 60 ; +variables: + double fates_history_ageclass_bin_edges(fates_history_age_bins) ; + fates_history_ageclass_bin_edges:units = "yr" ; + fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; + double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; + fates_history_coageclass_bin_edges:units = "years" ; + fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; + double fates_history_height_bin_edges(fates_history_height_bins) ; + fates_history_height_bin_edges:units = "m" ; + fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; + double fates_history_damage_bin_edges(fates_history_damage_bins) ; + fates_history_damage_bin_edges:units = "% crown loss" ; + fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; + double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; + fates_history_sizeclass_bin_edges:units = "cm" ; + fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; + double fates_alloc_organ_id(fates_plant_organs) ; + fates_alloc_organ_id:units = "unitless" ; + fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; + double fates_hydro_htftype_node(fates_hydr_organs) ; + fates_hydro_htftype_node:units = "unitless" ; + fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; + char fates_pftname(fates_pft, fates_string_length) ; + fates_pftname:units = "unitless - string" ; + fates_pftname:long_name = "Description of plant type" ; + char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; + fates_hydro_organ_name:units = "unitless - string" ; + fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; + char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; + fates_alloc_organ_name:units = "unitless - string" ; + fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; + 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" ; + 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" ; + double fates_alloc_storage_cushion(fates_pft) ; + fates_alloc_storage_cushion:units = "fraction" ; + fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; + double fates_alloc_store_priority_frac(fates_pft) ; + fates_alloc_store_priority_frac:units = "unitless" ; + fates_alloc_store_priority_frac:long_name = "for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage" ; + double fates_allom_agb1(fates_pft) ; + fates_allom_agb1:units = "variable" ; + fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; + double fates_allom_agb2(fates_pft) ; + fates_allom_agb2:units = "variable" ; + fates_allom_agb2:long_name = "Parameter 2 for agb allometry" ; + double fates_allom_agb3(fates_pft) ; + fates_allom_agb3:units = "variable" ; + fates_allom_agb3:long_name = "Parameter 3 for agb allometry" ; + double fates_allom_agb4(fates_pft) ; + fates_allom_agb4:units = "variable" ; + fates_allom_agb4:long_name = "Parameter 4 for agb allometry" ; + double fates_allom_agb_frac(fates_pft) ; + fates_allom_agb_frac:units = "fraction" ; + fates_allom_agb_frac:long_name = "Fraction of woody biomass that is above ground" ; + double fates_allom_amode(fates_pft) ; + fates_allom_amode:units = "index" ; + fates_allom_amode:long_name = "AGB allometry function index." ; + double fates_allom_blca_expnt_diff(fates_pft) ; + fates_allom_blca_expnt_diff:units = "unitless" ; + fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; + double fates_allom_cmode(fates_pft) ; + fates_allom_cmode:units = "index" ; + fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; + double fates_allom_crown_depth_frac(fates_pft) ; + fates_allom_crown_depth_frac:units = "fraction" ; + fates_allom_crown_depth_frac:long_name = "the depth of a cohort crown as a fraction of its height" ; + double fates_allom_d2bl1(fates_pft) ; + fates_allom_d2bl1:units = "variable" ; + fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; + double fates_allom_d2bl2(fates_pft) ; + fates_allom_d2bl2:units = "variable" ; + fates_allom_d2bl2:long_name = "Parameter 2 for d2bl allometry" ; + double fates_allom_d2bl3(fates_pft) ; + fates_allom_d2bl3:units = "unitless" ; + fates_allom_d2bl3:long_name = "Parameter 3 for d2bl allometry" ; + double fates_allom_d2ca_coefficient_max(fates_pft) ; + fates_allom_d2ca_coefficient_max:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_max:long_name = "max (savanna) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2ca_coefficient_min(fates_pft) ; + fates_allom_d2ca_coefficient_min:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_min:long_name = "min (forest) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2h1(fates_pft) ; + fates_allom_d2h1:units = "variable" ; + fates_allom_d2h1:long_name = "Parameter 1 for d2h allometry (intercept, or c)" ; + double fates_allom_d2h2(fates_pft) ; + fates_allom_d2h2:units = "variable" ; + fates_allom_d2h2:long_name = "Parameter 2 for d2h allometry (slope, or m)" ; + double fates_allom_d2h3(fates_pft) ; + fates_allom_d2h3:units = "variable" ; + fates_allom_d2h3:long_name = "Parameter 3 for d2h allometry (optional)" ; + double fates_allom_dbh_maxheight(fates_pft) ; + fates_allom_dbh_maxheight:units = "cm" ; + fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; + double fates_allom_fmode(fates_pft) ; + fates_allom_fmode:units = "index" ; + fates_allom_fmode:long_name = "fine root biomass allometry function index." ; + double fates_allom_fnrt_prof_a(fates_pft) ; + fates_allom_fnrt_prof_a:units = "unitless" ; + fates_allom_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; + double fates_allom_fnrt_prof_b(fates_pft) ; + fates_allom_fnrt_prof_b:units = "unitless" ; + fates_allom_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; + double fates_allom_fnrt_prof_mode(fates_pft) ; + fates_allom_fnrt_prof_mode:units = "index" ; + fates_allom_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; + double fates_allom_frbstor_repro(fates_pft) ; + fates_allom_frbstor_repro:units = "fraction" ; + fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; + double fates_allom_hmode(fates_pft) ; + fates_allom_hmode:units = "index" ; + fates_allom_hmode:long_name = "height allometry function index." ; + double fates_allom_l2fr(fates_pft) ; + fates_allom_l2fr:units = "gC/gC" ; + fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; + double fates_allom_la_per_sa_int(fates_pft) ; + fates_allom_la_per_sa_int:units = "m2/cm2" ; + fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; + double fates_allom_la_per_sa_slp(fates_pft) ; + fates_allom_la_per_sa_slp:units = "m2/cm2/m" ; + fates_allom_la_per_sa_slp:long_name = "Leaf area per sapwood area rate of change with height, slope (optional)" ; + double fates_allom_lmode(fates_pft) ; + fates_allom_lmode:units = "index" ; + fates_allom_lmode:long_name = "leaf biomass allometry function index." ; + double fates_allom_sai_scaler(fates_pft) ; + fates_allom_sai_scaler:units = "m2/m2" ; + fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; + double fates_allom_smode(fates_pft) ; + fates_allom_smode:units = "index" ; + fates_allom_smode:long_name = "sapwood allometry function index." ; + double fates_allom_stmode(fates_pft) ; + fates_allom_stmode:units = "index" ; + fates_allom_stmode:long_name = "storage allometry function index: 1) Storage proportional to leaf biomass (with trimming), 2) Storage proportional to maximum leaf biomass (not trimmed)" ; + double fates_allom_zroot_k(fates_pft) ; + fates_allom_zroot_k:units = "unitless" ; + fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; + double fates_allom_zroot_max_dbh(fates_pft) ; + fates_allom_zroot_max_dbh:units = "cm" ; + fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; + double fates_allom_zroot_max_z(fates_pft) ; + fates_allom_zroot_max_z:units = "m" ; + fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_allom_zroot_min_dbh(fates_pft) ; + fates_allom_zroot_min_dbh:units = "cm" ; + fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; + double fates_allom_zroot_min_z(fates_pft) ; + fates_allom_zroot_min_z:units = "m" ; + fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_c2b(fates_pft) ; + fates_c2b:units = "ratio" ; + fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; + double fates_cnp_eca_alpha_ptase(fates_pft) ; + fates_cnp_eca_alpha_ptase:units = "g/m3" ; + fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; + double fates_cnp_eca_decompmicc(fates_pft) ; + fates_cnp_eca_decompmicc:units = "gC/m3" ; + fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; + double fates_cnp_eca_km_nh4(fates_pft) ; + fates_cnp_eca_km_nh4:units = "gN/m3" ; + fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; + double fates_cnp_eca_km_no3(fates_pft) ; + fates_cnp_eca_km_no3:units = "gN/m3" ; + fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; + double fates_cnp_eca_km_p(fates_pft) ; + fates_cnp_eca_km_p:units = "gP/m3" ; + fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; + double fates_cnp_eca_km_ptase(fates_pft) ; + fates_cnp_eca_km_ptase:units = "gP/m3" ; + fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; + double fates_cnp_eca_lambda_ptase(fates_pft) ; + fates_cnp_eca_lambda_ptase:units = "g/m3" ; + fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; + double fates_cnp_eca_vmax_ptase(fates_pft) ; + fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; + fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; + double fates_cnp_nfix1(fates_pft) ; + fates_cnp_nfix1:units = "fraction" ; + fates_cnp_nfix1:long_name = "fractional surcharge added to maintenance respiration that drives symbiotic fixation" ; + double fates_cnp_nitr_store_ratio(fates_pft) ; + fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; + fates_cnp_nitr_store_ratio:long_name = "storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code)" ; + double fates_cnp_phos_store_ratio(fates_pft) ; + fates_cnp_phos_store_ratio:units = "(gP/gP)" ; + fates_cnp_phos_store_ratio:long_name = "storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code)" ; + double fates_cnp_pid_kd(fates_pft) ; + fates_cnp_pid_kd:units = "unknown" ; + fates_cnp_pid_kd:long_name = "derivative constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_pid_ki(fates_pft) ; + fates_cnp_pid_ki:units = "unknown" ; + fates_cnp_pid_ki:long_name = "integral constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_pid_kp(fates_pft) ; + fates_cnp_pid_kp:units = "unknown" ; + fates_cnp_pid_kp:long_name = "proportional constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_prescribed_nuptake(fates_pft) ; + fates_cnp_prescribed_nuptake:units = "fraction" ; + fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; + double fates_cnp_prescribed_puptake(fates_pft) ; + fates_cnp_prescribed_puptake:units = "fraction" ; + fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; + double fates_cnp_store_ovrflw_frac(fates_pft) ; + fates_cnp_store_ovrflw_frac:units = "fraction" ; + fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; + double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_nitr_retrans:units = "fraction" ; + fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; + double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_phos_retrans:units = "fraction" ; + fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; + double fates_cnp_vmax_nh4(fates_pft) ; + fates_cnp_vmax_nh4:units = "gN/gC/s" ; + fates_cnp_vmax_nh4:long_name = "maximum (potential) uptake rate of NH4 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_nh4 for usage)" ; + double fates_cnp_vmax_no3(fates_pft) ; + fates_cnp_vmax_no3:units = "gN/gC/s" ; + fates_cnp_vmax_no3:long_name = "maximum (potential) uptake rate of NO3 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_no3 for usage)" ; + double fates_cnp_vmax_p(fates_pft) ; + fates_cnp_vmax_p:units = "gP/gC/s" ; + fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; + double fates_damage_frac(fates_pft) ; + fates_damage_frac:units = "fraction" ; + fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; + double fates_damage_mort_p1(fates_pft) ; + fates_damage_mort_p1:units = "fraction" ; + fates_damage_mort_p1:long_name = "inflection point of damage mortality function, a value of 0.8 means 50% mortality with 80% loss of crown, turn off with a large number" ; + double fates_damage_mort_p2(fates_pft) ; + fates_damage_mort_p2:units = "unitless" ; + fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; + 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_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" ; + double fates_fire_alpha_SH(fates_pft) ; + fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; + fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; + double fates_fire_bark_scaler(fates_pft) ; + fates_fire_bark_scaler:units = "fraction" ; + fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; + double fates_fire_crown_kill(fates_pft) ; + fates_fire_crown_kill:units = "NA" ; + fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; + double fates_frag_fnrt_fcel(fates_pft) ; + fates_frag_fnrt_fcel:units = "fraction" ; + fates_frag_fnrt_fcel:long_name = "Fine root litter cellulose fraction" ; + double fates_frag_fnrt_flab(fates_pft) ; + fates_frag_fnrt_flab:units = "fraction" ; + fates_frag_fnrt_flab:long_name = "Fine root litter labile fraction" ; + double fates_frag_fnrt_flig(fates_pft) ; + fates_frag_fnrt_flig:units = "fraction" ; + fates_frag_fnrt_flig:long_name = "Fine root litter lignin fraction" ; + double fates_frag_leaf_fcel(fates_pft) ; + fates_frag_leaf_fcel:units = "fraction" ; + fates_frag_leaf_fcel:long_name = "Leaf litter cellulose fraction" ; + double fates_frag_leaf_flab(fates_pft) ; + fates_frag_leaf_flab:units = "fraction" ; + fates_frag_leaf_flab:long_name = "Leaf litter labile fraction" ; + double fates_frag_leaf_flig(fates_pft) ; + fates_frag_leaf_flig:units = "fraction" ; + fates_frag_leaf_flig:long_name = "Leaf litter lignin fraction" ; + double fates_frag_seed_decay_rate(fates_pft) ; + fates_frag_seed_decay_rate:units = "yr-1" ; + fates_frag_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; + double fates_grperc(fates_pft) ; + fates_grperc:units = "unitless" ; + fates_grperc:long_name = "Growth respiration factor" ; + double fates_hydro_avuln_gs(fates_pft) ; + fates_hydro_avuln_gs:units = "unitless" ; + fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; + double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; + fates_hydro_avuln_node:units = "unitless" ; + fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; + double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; + fates_hydro_epsil_node:units = "MPa" ; + fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; + double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; + fates_hydro_fcap_node:units = "unitless" ; + fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; + double fates_hydro_k_lwp(fates_pft) ; + fates_hydro_k_lwp:units = "unitless" ; + fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; + double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; + fates_hydro_kmax_node:units = "kg/MPa/m/s" ; + fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; + double fates_hydro_p50_gs(fates_pft) ; + fates_hydro_p50_gs:units = "MPa" ; + fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; + double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; + fates_hydro_p50_node:units = "MPa" ; + fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; + double fates_hydro_p_taper(fates_pft) ; + fates_hydro_p_taper:units = "unitless" ; + fates_hydro_p_taper:long_name = "xylem taper exponent" ; + double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pinot_node:units = "MPa" ; + fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; + double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pitlp_node:units = "MPa" ; + fates_hydro_pitlp_node:long_name = "turgor loss point" ; + double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; + fates_hydro_resid_node:units = "cm3/cm3" ; + fates_hydro_resid_node:long_name = "residual water conent" ; + double fates_hydro_rfrac_stem(fates_pft) ; + fates_hydro_rfrac_stem:units = "fraction" ; + fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; + double fates_hydro_rs2(fates_pft) ; + fates_hydro_rs2:units = "m" ; + fates_hydro_rs2:long_name = "absorbing root radius" ; + double fates_hydro_srl(fates_pft) ; + fates_hydro_srl:units = "m g-1" ; + fates_hydro_srl:long_name = "specific root length" ; + double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; + fates_hydro_thetas_node:units = "cm3/cm3" ; + fates_hydro_thetas_node:long_name = "saturated water content" ; + double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_alpha_node:units = "MPa-1" ; + fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; + double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_m_node:units = "unitless" ; + fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; + 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_leaf_c3psn(fates_pft) ; + fates_leaf_c3psn:units = "flag" ; + fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; + double fates_leaf_jmaxha(fates_pft) ; + fates_leaf_jmaxha:units = "J/mol" ; + fates_leaf_jmaxha:long_name = "activation energy for jmax" ; + double fates_leaf_jmaxhd(fates_pft) ; + fates_leaf_jmaxhd:units = "J/mol" ; + fates_leaf_jmaxhd:long_name = "deactivation energy for jmax" ; + double fates_leaf_jmaxse(fates_pft) ; + fates_leaf_jmaxse:units = "J/mol/K" ; + fates_leaf_jmaxse:long_name = "entropy term for jmax" ; + double fates_leaf_slamax(fates_pft) ; + fates_leaf_slamax:units = "m^2/gC" ; + fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; + double fates_leaf_slatop(fates_pft) ; + fates_leaf_slatop:units = "m^2/gC" ; + fates_leaf_slatop:long_name = "Specific Leaf Area (SLA) at top of canopy, projected area basis" ; + double fates_leaf_stomatal_intercept(fates_pft) ; + fates_leaf_stomatal_intercept:units = "umol H2O/m**2/s" ; + fates_leaf_stomatal_intercept:long_name = "Minimum unstressed stomatal conductance for Ball-Berry model and Medlyn model" ; + double fates_leaf_stomatal_slope_ballberry(fates_pft) ; + fates_leaf_stomatal_slope_ballberry:units = "unitless" ; + fates_leaf_stomatal_slope_ballberry:long_name = "stomatal slope parameter, as per Ball-Berry" ; + double fates_leaf_stomatal_slope_medlyn(fates_pft) ; + fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; + fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; + double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; + fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; + fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; + double fates_leaf_vcmaxha(fates_pft) ; + fates_leaf_vcmaxha:units = "J/mol" ; + fates_leaf_vcmaxha:long_name = "activation energy for vcmax" ; + double fates_leaf_vcmaxhd(fates_pft) ; + fates_leaf_vcmaxhd:units = "J/mol" ; + fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax" ; + double fates_leaf_vcmaxse(fates_pft) ; + fates_leaf_vcmaxse:units = "J/mol/K" ; + fates_leaf_vcmaxse:long_name = "entropy term for vcmax" ; + double fates_maintresp_reduction_curvature(fates_pft) ; + fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; + fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; + double fates_maintresp_reduction_intercept(fates_pft) ; + fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; + fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; + double fates_mort_bmort(fates_pft) ; + fates_mort_bmort:units = "1/yr" ; + fates_mort_bmort:long_name = "background mortality rate" ; + double fates_mort_freezetol(fates_pft) ; + fates_mort_freezetol:units = "degrees C" ; + fates_mort_freezetol:long_name = "minimum temperature tolerance" ; + double fates_mort_hf_flc_threshold(fates_pft) ; + fates_mort_hf_flc_threshold:units = "fraction" ; + fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; + double fates_mort_hf_sm_threshold(fates_pft) ; + fates_mort_hf_sm_threshold:units = "unitless" ; + fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; + double fates_mort_ip_age_senescence(fates_pft) ; + fates_mort_ip_age_senescence:units = "years" ; + fates_mort_ip_age_senescence:long_name = "Mortality cohort age senescence inflection point. If _ this mortality term is off. Setting this value turns on age dependent mortality. " ; + double fates_mort_ip_size_senescence(fates_pft) ; + fates_mort_ip_size_senescence:units = "dbh cm" ; + fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; + double fates_mort_prescribed_canopy(fates_pft) ; + fates_mort_prescribed_canopy:units = "1/yr" ; + fates_mort_prescribed_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; + double fates_mort_prescribed_understory(fates_pft) ; + fates_mort_prescribed_understory:units = "1/yr" ; + fates_mort_prescribed_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; + double fates_mort_r_age_senescence(fates_pft) ; + fates_mort_r_age_senescence:units = "mortality rate year^-1" ; + fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; + double fates_mort_r_size_senescence(fates_pft) ; + fates_mort_r_size_senescence:units = "mortality rate dbh^-1" ; + fates_mort_r_size_senescence:long_name = "Mortality dbh senescence rate of change. Sensible range is around 0.03-0.06. Larger values give steeper mortality curves." ; + double fates_mort_scalar_coldstress(fates_pft) ; + fates_mort_scalar_coldstress:units = "1/yr" ; + fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; + double fates_mort_scalar_cstarvation(fates_pft) ; + fates_mort_scalar_cstarvation:units = "1/yr" ; + fates_mort_scalar_cstarvation:long_name = "maximum mortality rate from carbon starvation" ; + double fates_mort_scalar_hydrfailure(fates_pft) ; + fates_mort_scalar_hydrfailure:units = "1/yr" ; + fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; + double fates_nonhydro_smpsc(fates_pft) ; + fates_nonhydro_smpsc:units = "mm" ; + fates_nonhydro_smpsc:long_name = "Soil water potential at full stomatal closure" ; + double fates_nonhydro_smpso(fates_pft) ; + fates_nonhydro_smpso:units = "mm" ; + fates_nonhydro_smpso:long_name = "Soil water potential at full stomatal opening" ; + double fates_phen_cold_size_threshold(fates_pft) ; + fates_phen_cold_size_threshold:units = "cm" ; + fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; + double fates_phen_evergreen(fates_pft) ; + fates_phen_evergreen:units = "logical flag" ; + fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; + double fates_phen_flush_fraction(fates_pft) ; + fates_phen_flush_fraction:units = "fraction" ; + fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; + double fates_phen_fnrt_drop_frac(fates_pft) ; + fates_phen_fnrt_drop_frac:units = "fraction" ; + fates_phen_fnrt_drop_frac:long_name = "fraction of fine roots to drop during drought or cold" ; + double fates_phen_season_decid(fates_pft) ; + fates_phen_season_decid:units = "logical flag" ; + fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; + double fates_phen_stem_drop_fraction(fates_pft) ; + fates_phen_stem_drop_fraction:units = "fraction" ; + fates_phen_stem_drop_fraction:long_name = "fraction of stems to drop for non-woody species during drought/cold" ; + double fates_phen_stress_decid(fates_pft) ; + fates_phen_stress_decid:units = "logical flag" ; + fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; + double fates_prescribed_npp_canopy(fates_pft) ; + fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; + double fates_prescribed_npp_understory(fates_pft) ; + fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; + double fates_rad_leaf_clumping_index(fates_pft) ; + fates_rad_leaf_clumping_index:units = "fraction (0-1)" ; + fates_rad_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; + double fates_rad_leaf_rhonir(fates_pft) ; + fates_rad_leaf_rhonir:units = "fraction" ; + fates_rad_leaf_rhonir:long_name = "Leaf reflectance: near-IR" ; + double fates_rad_leaf_rhovis(fates_pft) ; + fates_rad_leaf_rhovis:units = "fraction" ; + fates_rad_leaf_rhovis:long_name = "Leaf reflectance: visible" ; + double fates_rad_leaf_taunir(fates_pft) ; + fates_rad_leaf_taunir:units = "fraction" ; + fates_rad_leaf_taunir:long_name = "Leaf transmittance: near-IR" ; + double fates_rad_leaf_tauvis(fates_pft) ; + fates_rad_leaf_tauvis:units = "fraction" ; + fates_rad_leaf_tauvis:long_name = "Leaf transmittance: visible" ; + double fates_rad_leaf_xl(fates_pft) ; + fates_rad_leaf_xl:units = "unitless" ; + fates_rad_leaf_xl:long_name = "Leaf/stem orientation index" ; + double fates_rad_stem_rhonir(fates_pft) ; + fates_rad_stem_rhonir:units = "fraction" ; + fates_rad_stem_rhonir:long_name = "Stem reflectance: near-IR" ; + double fates_rad_stem_rhovis(fates_pft) ; + fates_rad_stem_rhovis:units = "fraction" ; + fates_rad_stem_rhovis:long_name = "Stem reflectance: visible" ; + double fates_rad_stem_taunir(fates_pft) ; + fates_rad_stem_taunir:units = "fraction" ; + fates_rad_stem_taunir:long_name = "Stem transmittance: near-IR" ; + double fates_rad_stem_tauvis(fates_pft) ; + fates_rad_stem_tauvis:units = "fraction" ; + fates_rad_stem_tauvis:long_name = "Stem transmittance: visible" ; + double fates_recruit_height_min(fates_pft) ; + fates_recruit_height_min:units = "m" ; + fates_recruit_height_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; + double fates_recruit_init_density(fates_pft) ; + fates_recruit_init_density:units = "stems/m2" ; + fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation" ; + double fates_recruit_prescribed_rate(fates_pft) ; + fates_recruit_prescribed_rate:units = "n/yr" ; + fates_recruit_prescribed_rate:long_name = "recruitment rate for prescribed physiology mode" ; + double fates_recruit_seed_alloc(fates_pft) ; + fates_recruit_seed_alloc:units = "fraction" ; + fates_recruit_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; + double fates_recruit_seed_alloc_mature(fates_pft) ; + fates_recruit_seed_alloc_mature:units = "fraction" ; + fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; + double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; + fates_recruit_seed_dbh_repro_threshold:units = "cm" ; + fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter where the plant will increase allocation to the seed pool by fraction: fates_recruit_seed_alloc_mature" ; + double fates_recruit_seed_germination_rate(fates_pft) ; + fates_recruit_seed_germination_rate:units = "yr-1" ; + fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; + double fates_recruit_seed_supplement(fates_pft) ; + fates_recruit_seed_supplement:units = "KgC/m2/yr" ; + fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; + double fates_stoich_nitr(fates_plant_organs, fates_pft) ; + fates_stoich_nitr:units = "gN/gC" ; + fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; + double fates_stoich_phos(fates_plant_organs, fates_pft) ; + fates_stoich_phos:units = "gP/gC" ; + fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; + double fates_trim_inc(fates_pft) ; + fates_trim_inc:units = "m2/m2" ; + fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; + double fates_trim_limit(fates_pft) ; + fates_trim_limit:units = "m2/m2" ; + fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; + double fates_turb_displar(fates_pft) ; + fates_turb_displar:units = "unitless" ; + fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; + double fates_turb_leaf_diameter(fates_pft) ; + fates_turb_leaf_diameter:units = "m" ; + fates_turb_leaf_diameter:long_name = "Characteristic leaf dimension" ; + double fates_turb_z0mr(fates_pft) ; + fates_turb_z0mr:units = "unitless" ; + fates_turb_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; + double fates_turnover_branch(fates_pft) ; + fates_turnover_branch:units = "yr" ; + fates_turnover_branch:long_name = "turnover time of branches" ; + double fates_turnover_fnrt(fates_pft) ; + fates_turnover_fnrt:units = "yr" ; + fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; + double fates_turnover_leaf(fates_leafage_class, fates_pft) ; + fates_turnover_leaf:units = "yr" ; + fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; + double fates_turnover_senleaf_fdrought(fates_pft) ; + fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; + fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; + double fates_wood_density(fates_pft) ; + fates_wood_density:units = "g/cm3" ; + fates_wood_density:long_name = "mean density of woody tissue in plant" ; + double fates_woody(fates_pft) ; + fates_woody:units = "logical flag" ; + fates_woody:long_name = "Binary woody lifeform flag" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_fire_FBD(fates_litterclass) ; + fates_fire_FBD:units = "kg Biomass/m3" ; + fates_fire_FBD:long_name = "fuel bulk density" ; + double fates_fire_low_moisture_Coeff(fates_litterclass) ; + fates_fire_low_moisture_Coeff:units = "NA" ; + fates_fire_low_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_low_moisture_Slope(fates_litterclass) ; + fates_fire_low_moisture_Slope:units = "NA" ; + fates_fire_low_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture(fates_litterclass) ; + fates_fire_mid_moisture:units = "NA" ; + fates_fire_mid_moisture:long_name = "spitfire litter moisture threshold to be considered medium dry" ; + double fates_fire_mid_moisture_Coeff(fates_litterclass) ; + fates_fire_mid_moisture_Coeff:units = "NA" ; + fates_fire_mid_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture_Slope(fates_litterclass) ; + fates_fire_mid_moisture_Slope:units = "NA" ; + fates_fire_mid_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_min_moisture(fates_litterclass) ; + fates_fire_min_moisture:units = "NA" ; + fates_fire_min_moisture:long_name = "spitfire litter moisture threshold to be considered very dry" ; + double fates_fire_SAV(fates_litterclass) ; + fates_fire_SAV:units = "cm-1" ; + fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; + double fates_frag_maxdecomp(fates_litterclass) ; + fates_frag_maxdecomp:units = "yr-1" ; + fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; + 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_base_mr_20 ; + fates_base_mr_20:units = "gC/gN/s" ; + fates_base_mr_20:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; + 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" ; + double fates_cnp_eca_plant_escalar ; + fates_cnp_eca_plant_escalar:units = "" ; + fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; + double fates_cohort_age_fusion_tol ; + fates_cohort_age_fusion_tol:units = "unitless" ; + fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; + double fates_cohort_size_fusion_tol ; + fates_cohort_size_fusion_tol:units = "unitless" ; + fates_cohort_size_fusion_tol:long_name = "minimum fraction in difference in dbh between cohorts" ; + double fates_comp_excln ; + fates_comp_excln:units = "none" ; + fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; + double fates_damage_canopy_layer_code ; + fates_damage_canopy_layer_code:units = "unitless" ; + fates_damage_canopy_layer_code:long_name = "Integer code that decides whether damage affects canopy trees (1), understory trees (2)" ; + double fates_damage_event_code ; + fates_damage_event_code:units = "unitless" ; + fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; + double fates_dev_arbitrary ; + fates_dev_arbitrary:units = "unknown" ; + fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; + double fates_fire_active_crown_fire ; + fates_fire_active_crown_fire:units = "0 or 1" ; + fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; + double fates_fire_cg_strikes ; + fates_fire_cg_strikes:units = "fraction (0-1)" ; + fates_fire_cg_strikes:long_name = "fraction of cloud to ground lightning strikes" ; + double fates_fire_drying_ratio ; + fates_fire_drying_ratio:units = "NA" ; + fates_fire_drying_ratio:long_name = "spitfire parameter, fire drying ratio for fuel moisture, alpha_FMC EQ 6 Thonicke et al 2010" ; + double fates_fire_durat_slope ; + fates_fire_durat_slope:units = "NA" ; + fates_fire_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; + double fates_fire_fdi_a ; + fates_fire_fdi_a:units = "NA" ; + fates_fire_fdi_a:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010" ; + double fates_fire_fdi_alpha ; + fates_fire_fdi_alpha:units = "NA" ; + fates_fire_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; + double fates_fire_fdi_b ; + fates_fire_fdi_b:units = "NA" ; + fates_fire_fdi_b:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010 " ; + double fates_fire_fuel_energy ; + fates_fire_fuel_energy:units = "kJ/kg" ; + fates_fire_fuel_energy:long_name = "spitfire parameter, heat content of fuel" ; + double fates_fire_max_durat ; + fates_fire_max_durat:units = "minutes" ; + fates_fire_max_durat:long_name = "spitfire parameter, fire maximum duration, Equation 14 Thonicke et al 2010" ; + double fates_fire_miner_damp ; + fates_fire_miner_damp:units = "NA" ; + fates_fire_miner_damp:long_name = "spitfire parameter, mineral-dampening coefficient EQ A1 Thonicke et al 2010 " ; + double fates_fire_miner_total ; + fates_fire_miner_total:units = "fraction" ; + fates_fire_miner_total:long_name = "spitfire parameter, total mineral content, Table A1 Thonicke et al 2010" ; + double fates_fire_nignitions ; + fates_fire_nignitions:units = "ignitions per year per km2" ; + fates_fire_nignitions:long_name = "number of annual ignitions per square km" ; + double fates_fire_part_dens ; + fates_fire_part_dens:units = "kg/m2" ; + fates_fire_part_dens:long_name = "spitfire parameter, oven dry particle density, Table A1 Thonicke et al 2010" ; + double fates_fire_threshold ; + fates_fire_threshold:units = "kW/m" ; + fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; + double fates_frag_cwd_fcel ; + fates_frag_cwd_fcel:units = "unitless" ; + fates_frag_cwd_fcel:long_name = "Cellulose fraction for CWD" ; + double fates_frag_cwd_flig ; + fates_frag_cwd_flig:units = "unitless" ; + fates_frag_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; + double fates_hydro_kmax_rsurf1 ; + fates_hydro_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; + double fates_hydro_kmax_rsurf2 ; + fates_hydro_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; + double fates_hydro_psi0 ; + fates_hydro_psi0:units = "MPa" ; + fates_hydro_psi0:long_name = "sapwood water potential at saturation" ; + double fates_hydro_psicap ; + fates_hydro_psicap:units = "MPa" ; + fates_hydro_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; + 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_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" ; + double fates_landuse_logging_collateral_frac ; + fates_landuse_logging_collateral_frac:units = "fraction" ; + fates_landuse_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; + double fates_landuse_logging_dbhmax ; + fates_landuse_logging_dbhmax:units = "cm" ; + fates_landuse_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; + double fates_landuse_logging_dbhmax_infra ; + fates_landuse_logging_dbhmax_infra:units = "cm" ; + fates_landuse_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; + double fates_landuse_logging_dbhmin ; + fates_landuse_logging_dbhmin:units = "cm" ; + fates_landuse_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; + double fates_landuse_logging_direct_frac ; + fates_landuse_logging_direct_frac:units = "fraction" ; + fates_landuse_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; + double fates_landuse_logging_event_code ; + fates_landuse_logging_event_code:units = "unitless" ; + fates_landuse_logging_event_code:long_name = "Integer code that options how logging events are structured" ; + double fates_landuse_logging_export_frac ; + fates_landuse_logging_export_frac:units = "fraction" ; + fates_landuse_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; + double fates_landuse_logging_mechanical_frac ; + fates_landuse_logging_mechanical_frac:units = "fraction" ; + fates_landuse_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; + double fates_landuse_pprodharv10_forest_mean ; + fates_landuse_pprodharv10_forest_mean:units = "fraction" ; + fates_landuse_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; + double fates_leaf_photo_temp_acclim_timescale ; + fates_leaf_photo_temp_acclim_timescale:units = "days" ; + fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; + double fates_leaf_photo_tempsens_model ; + fates_leaf_photo_tempsens_model:units = "unitless" ; + fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; + double fates_leaf_stomatal_assim_model ; + fates_leaf_stomatal_assim_model:units = "unitless" ; + fates_leaf_stomatal_assim_model:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; + double fates_leaf_stomatal_model ; + fates_leaf_stomatal_model:units = "unitless" ; + fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; + double fates_leaf_theta_cj_c3 ; + fates_leaf_theta_cj_c3:units = "unitless" ; + fates_leaf_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; + double fates_leaf_theta_cj_c4 ; + fates_leaf_theta_cj_c4:units = "unitless" ; + fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; + double fates_maintresp_model ; + fates_maintresp_model:units = "unitless" ; + fates_maintresp_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991) (NOT USED)" ; + double fates_maxcohort ; + fates_maxcohort:units = "count" ; + fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; + double fates_maxpatch_primary ; + fates_maxpatch_primary:units = "count" ; + fates_maxpatch_primary:long_name = "maximum number of primary vegetation patches per site" ; + double fates_maxpatch_secondary ; + fates_maxpatch_secondary:units = "count" ; + fates_maxpatch_secondary:long_name = "maximum number of secondary vegetation patches per site" ; + double fates_mort_disturb_frac ; + fates_mort_disturb_frac:units = "fraction" ; + fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; + double fates_mort_understorey_death ; + fates_mort_understorey_death:units = "fraction" ; + fates_mort_understorey_death:long_name = "fraction of plants in understorey cohort impacted by overstorey tree-fall" ; + double fates_patch_fusion_tol ; + fates_patch_fusion_tol:units = "unitless" ; + fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; + double fates_phen_chilltemp ; + fates_phen_chilltemp:units = "degrees C" ; + fates_phen_chilltemp:long_name = "chilling day counting threshold for vegetation" ; + double fates_phen_coldtemp ; + fates_phen_coldtemp:units = "degrees C" ; + fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; + double fates_phen_drought_model ; + fates_phen_drought_model:units = "unitless" ; + fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; + double fates_phen_drought_threshold ; + fates_phen_drought_threshold:units = "m3/m3 or mm" ; + fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_gddthresh_a ; + fates_phen_gddthresh_a:units = "none" ; + fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_b ; + fates_phen_gddthresh_b:units = "none" ; + fates_phen_gddthresh_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_c ; + fates_phen_gddthresh_c:units = "none" ; + fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_mindaysoff ; + fates_phen_mindaysoff:units = "days" ; + fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves became off-allometry" ; + double fates_phen_mindayson ; + fates_phen_mindayson:units = "days" ; + fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; + double fates_phen_moist_threshold ; + fates_phen_moist_threshold:units = "m3/m3 or mm" ; + fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_ncolddayslim ; + fates_phen_ncolddayslim:units = "days" ; + fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; + double fates_q10_froz ; + fates_q10_froz:units = "unitless" ; + fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; + double fates_q10_mr ; + fates_q10_mr:units = "unitless" ; + fates_q10_mr:long_name = "Q10 for maintenance respiration" ; + double fates_soil_salinity ; + fates_soil_salinity:units = "ppt" ; + fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; + double fates_vai_top_bin_width ; + fates_vai_top_bin_width:units = "m2/m2" ; + fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; + double fates_vai_width_increase_factor ; + fates_vai_width_increase_factor:units = "unitless" ; + fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; + +// global attributes: + :history = "This file was generated by BatchPatchParams.py:\nCDL Base File = archive/api24.1.0_101722_fates_params_default.cdl\nXML patch file = archive/api24.1.0_101722_patch_params.xml" ; +data: + + fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; + + fates_history_coageclass_bin_edges = 0, 5 ; + + fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; + + fates_history_damage_bin_edges = 0, 80 ; + + fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, + 80, 90, 100 ; + + fates_alloc_organ_id = 1, 2, 3, 6 ; + + fates_hydro_htftype_node = 1, 1, 1, 1 ; + + fates_pftname = + "broadleaf_evergreen_tropical_tree ", + "needleleaf_evergreen_extratrop_tree ", + "needleleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_tree ", + "broadleaf_hydrodecid_tropical_tree ", + "broadleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_shrub ", + "broadleaf_hydrodecid_extratrop_shrub ", + "broadleaf_colddecid_extratrop_shrub ", + "arctic_c3_grass ", + "cool_c3_grass ", + "c4_grass " ; + + fates_hydro_organ_name = + "leaf ", + "stem ", + "transporting root ", + "absorbing root " ; + + fates_alloc_organ_name = + "leaf", + "fine root", + "sapwood", + "structure" ; + + fates_litterclass_name = + "twig ", + "small branch ", + "large branch ", + "trunk ", + "dead leaves ", + "live grass " ; + + 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, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; + + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + 1.2, 1.2, 1.2 ; + + fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8, 0.8 ; + + fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, + 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; + + fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, + 0.572, 0.572, 0.572, 0.572 ; + + fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, + 1.94, 1.94, 1.94 ; + + fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, + 0.931, 0.931, 0.931, 0.931 ; + + fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6 ; + + fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, + 0.95, 1, 1, 1 ; + + fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07 ; + + fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, + 1.3 ; + + fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, + 0.55, 0.55, 0.55 ; + + fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464 ; + + fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119 ; + + fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, + 0.64, 0.64, 0.64 ; + + fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, + 0.37, 0.37, 0.37 ; + + fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, + -999.9, -999.9, -999.9, -999.9, -999.9 ; + + fates_allom_dbh_maxheight = 90, 80, 80, 80, 90, 80, 3, 3, 2, 0.35, 0.35, 0.35 ; + + fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; + + fates_allom_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; + + fates_allom_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8 ; + + fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_zroot_k = 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 ; + + fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; + + fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + + fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 280, 280 ; + + fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, + 0.14, 0.14, 0.14 ; + + fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, + 0.27, 0.27, 0.27 ; + + fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_nfix1 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_pid_kd = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; + + fates_cnp_pid_ki = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_pid_kp = 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005 ; + + fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_turnover_nitr_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_turnover_phos_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_vmax_nh4 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, + 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; + + fates_cnp_vmax_no3 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, + 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; + + fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, + 5e-10, 5e-10, 5e-10, 5e-10 ; + + fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01 ; + + fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; + + fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, + 5.5, 5.5 ; + + fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2 ; + + fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07, 0.07 ; + + fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, + 0.775, 0.775, 0.775, 0.775, 0.775 ; + + fates_frag_fnrt_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_fnrt_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_fnrt_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_leaf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, + 0.51, 0.51, 0.51, 0.51 ; + + fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, + 0.11, 0.11 ; + + fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + 2.5, 2.5 ; + + fates_hydro_avuln_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_hydro_epsil_node = + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_hydro_fcap_node = + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_kmax_node = + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; + + fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + -1.5, -1.5, -1.5 ; + + fates_hydro_p50_node = + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25 ; + + fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, + 0.333, 0.333, 0.333, 0.333, 0.333 ; + + fates_hydro_pinot_node = + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; + + fates_hydro_pitlp_node = + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + -1.67, -1.67, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; + + fates_hydro_resid_node = + 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; + + fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + 0.625, 0.625, 0.625, 0.625, 0.625 ; + + fates_hydro_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, + 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; + + fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; + + fates_hydro_thetas_node = + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; + + fates_hydro_vg_alpha_node = + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005 ; + + fates_hydro_vg_m_node = + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_hydro_vg_n_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_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, + 43540, 43540, 43540, 43540 ; + + fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, + 152040, 152040, 152040, 152040, 152040 ; + + fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, + 495 ; + + fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, + 0.03, 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_slatop = 0.012, 0.005, 0.024, 0.009, 0.03, 0.03, 0.012, 0.03, + 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, + 10000, 10000, 10000, 10000, 10000, 40000 ; + + fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, + 4.7, 2.2, 5.3, 1.6 ; + + fates_leaf_vcmax25top = + 50, 62, 39, 61, 41, 58, 62, 54, 54, 78, 78, 78 ; + + fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, + 65330, 65330, 65330, 65330 ; + + fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, + 149250, 149250, 149250, 149250, 149250 ; + + fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, + 485 ; + + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; + + fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, + 0.014, 0.014, 0.014, 0.014 ; + + fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -80, -60, -10, -80, -80, + -20, 2.5 ; + + fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, + 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; + + fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_prescribed_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, + 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; + + fates_mort_prescribed_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, + 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; + + fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_nonhydro_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, + -255000, -255000, -255000, -255000, -255000, -255000 ; + + fates_nonhydro_smpso = -66000, -66000, -66000, -66000, -66000, -66000, + -66000, -66000, -66000, -66000, -66000, -66000 ; + + fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; + + fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, + 0.5 ; + + fates_phen_fnrt_drop_frac = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; + + fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; + + fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, + 0.4, 0.4, 0.4 ; + + fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, + 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; + + fates_rad_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, + 0.9, 0.75, 0.75, 0.75 ; + + fates_rad_leaf_rhonir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, + 0.41, 0.28, 0.28, 0.28 ; + + fates_rad_leaf_rhovis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, + 0.08, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_taunir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, + 0.43, 0.4, 0.4, 0.4 ; + + fates_rad_leaf_tauvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, + 0.06, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, + -0.23, -0.23, -0.23 ; + + fates_rad_stem_rhonir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, + 0.49, 0.53, 0.53, 0.53 ; + + fates_rad_stem_rhovis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.31, 0.31, 0.31 ; + + fates_rad_stem_taunir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.25, 0.25, 0.25 ; + + fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.12, 0.12, 0.12 ; + + fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.2, 0.2, 0.2, + 0.125, 0.125, 0.125 ; + + fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2, 0.2, 0.2 ; + + fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, + 0.02, 0.02, 0.02, 0.02, 0.02 ; + + fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, + 0.9 ; + + fates_recruit_seed_dbh_repro_threshold = 90, 80, 80, 80, 90, 80, 3, 3, 2, + 0.35, 0.35, 0.35 ; + + fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_stoich_nitr = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; + + fates_stoich_phos = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; + + fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, + 0.03, 0.03 ; + + fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; + + fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, + 0.67, 0.67, 0.67 ; + + fates_turb_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.04, 0.04, 0.04, 0.04 ; + + fates_turb_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, + 0.055, 0.055, 0.055, 0.055 ; + + fates_turnover_branch = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; + + fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_leaf = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_wood_density = 0.7, 0.4, 0.7, 0.53, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, + 0.7 ; + + fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; + + fates_hlm_pft_map = + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + + fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; + + fates_fire_low_moisture_Coeff = 1.12, 1.09, 0.98, 0.8, 1.15, 1.15 ; + + fates_fire_low_moisture_Slope = 0.62, 0.72, 0.85, 0.8, 0.62, 0.62 ; + + fates_fire_mid_moisture = 0.72, 0.51, 0.38, 1, 0.8, 0.8 ; + + fates_fire_mid_moisture_Coeff = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_mid_moisture_Slope = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_min_moisture = 0.18, 0.12, 0, 0, 0.24, 0.24 ; + + fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; + + fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; + + fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; + + fates_base_mr_20 = 2.52e-06 ; + + fates_canopy_closure_thresh = 0.8 ; + + fates_cnp_eca_plant_escalar = 1.25e-05 ; + + fates_cohort_age_fusion_tol = 0.08 ; + + fates_cohort_size_fusion_tol = 0.08 ; + + fates_comp_excln = 3 ; + + fates_damage_canopy_layer_code = 1 ; + + fates_damage_event_code = 1 ; + + fates_dev_arbitrary = _ ; + + fates_fire_active_crown_fire = 0 ; + + fates_fire_cg_strikes = 0.2 ; + + fates_fire_drying_ratio = 66000 ; + + fates_fire_durat_slope = -11.06 ; + + fates_fire_fdi_a = 17.62 ; + + fates_fire_fdi_alpha = 0.00037 ; + + fates_fire_fdi_b = 243.12 ; + + fates_fire_fuel_energy = 18000 ; + + fates_fire_max_durat = 240 ; + + fates_fire_miner_damp = 0.41739 ; + + fates_fire_miner_total = 0.055 ; + + fates_fire_nignitions = 15 ; + + fates_fire_part_dens = 513 ; + + fates_fire_threshold = 50 ; + + fates_frag_cwd_fcel = 0.76 ; + + fates_frag_cwd_flig = 0.24 ; + + fates_hydro_kmax_rsurf1 = 20 ; + + fates_hydro_kmax_rsurf2 = 0.0001 ; + + fates_hydro_psi0 = 0 ; + + fates_hydro_psicap = -0.6 ; + + fates_hydro_solver = 1 ; + + fates_landuse_logging_coll_under_frac = 0.55983 ; + + fates_landuse_logging_collateral_frac = 0.05 ; + + fates_landuse_logging_dbhmax = _ ; + + fates_landuse_logging_dbhmax_infra = 35 ; + + fates_landuse_logging_dbhmin = 50 ; + + fates_landuse_logging_direct_frac = 0.15 ; + + fates_landuse_logging_event_code = -30 ; + + fates_landuse_logging_export_frac = 0.8 ; + + fates_landuse_logging_mechanical_frac = 0.05 ; + + fates_landuse_pprodharv10_forest_mean = 0.8125 ; + + fates_leaf_photo_temp_acclim_timescale = 30 ; + + fates_leaf_photo_tempsens_model = 1 ; + + fates_leaf_stomatal_assim_model = 1 ; + + fates_leaf_stomatal_model = 1 ; + + fates_leaf_theta_cj_c3 = 0.999 ; + + fates_leaf_theta_cj_c4 = 0.999 ; + + fates_maintresp_model = 1 ; + + fates_maxcohort = 100 ; + + fates_maxpatch_primary = 10 ; + + fates_maxpatch_secondary = 4 ; + + fates_mort_disturb_frac = 1 ; + + fates_mort_understorey_death = 0.55983 ; + + fates_patch_fusion_tol = 0.05 ; + + fates_phen_chilltemp = 5 ; + + fates_phen_coldtemp = 7.5 ; + + fates_phen_drought_model = 0 ; + + fates_phen_drought_threshold = 0.15 ; + + fates_phen_gddthresh_a = -68 ; + + fates_phen_gddthresh_b = 638 ; + + fates_phen_gddthresh_c = -0.01 ; + + fates_phen_mindaysoff = 100 ; + + fates_phen_mindayson = 90 ; + + fates_phen_moist_threshold = 0.18 ; + + fates_phen_ncolddayslim = 5 ; + + fates_q10_froz = 1.5 ; + + fates_q10_mr = 1.5 ; + + fates_soil_salinity = 0.4 ; + + fates_vai_top_bin_width = 1 ; + + fates_vai_width_increase_factor = 1 ; +} diff --git a/parameter_files/archive/api25.1.1_021623_pr931.xml b/parameter_files/archive/api25.1.1_021623_pr931.xml new file mode 100644 index 0000000000..e327776be7 --- /dev/null +++ b/parameter_files/archive/api25.1.1_021623_pr931.xml @@ -0,0 +1,15 @@ + + + This change is associated with FATES PR #931 + archive/api25.1.0_021623_fates_params_default.cdl + fates_params_default.cdl + 1,2,3,4,5,6,7,8,9,10,11,12 + + + 1.7560, 1.4995, 1.4995, 1.7560, 1.7560, 1.7560, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956 + + + 2.52e-06 + + + diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index e635e9f141..98d8e02a72 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -14,42 +14,15 @@ dimensions: fates_plant_organs = 4 ; fates_string_length = 60 ; variables: - double fates_history_ageclass_bin_edges(fates_history_age_bins) ; - fates_history_ageclass_bin_edges:units = "yr" ; - fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; - double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; - fates_history_coageclass_bin_edges:units = "years" ; - fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; - double fates_history_height_bin_edges(fates_history_height_bins) ; - fates_history_height_bin_edges:units = "m" ; - fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; - double fates_history_damage_bin_edges(fates_history_damage_bins) ; - fates_history_damage_bin_edges:units = "% crown loss" ; - fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; fates_history_sizeclass_bin_edges:units = "cm" ; fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; - double fates_alloc_organ_id(fates_plant_organs) ; - fates_alloc_organ_id:units = "unitless" ; - fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; - double fates_hydro_htftype_node(fates_hydr_organs) ; - fates_hydro_htftype_node:units = "unitless" ; - fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; char fates_pftname(fates_pft, fates_string_length) ; fates_pftname:units = "unitless - string" ; fates_pftname:long_name = "Description of plant type" ; - char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; - fates_hydro_organ_name:units = "unitless - string" ; - fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; - char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; - fates_alloc_organ_name:units = "unitless - string" ; - fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; - 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" ; - 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" ; double fates_alloc_storage_cushion(fates_pft) ; fates_alloc_storage_cushion:units = "fraction" ; fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; @@ -218,12 +191,6 @@ variables: double fates_cnp_store_ovrflw_frac(fates_pft) ; fates_cnp_store_ovrflw_frac:units = "fraction" ; fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; - double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; - fates_cnp_turnover_nitr_retrans:units = "fraction" ; - fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; - double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; - fates_cnp_turnover_phos_retrans:units = "fraction" ; - fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; double fates_cnp_vmax_nh4(fates_pft) ; fates_cnp_vmax_nh4:units = "gN/gC/s" ; fates_cnp_vmax_nh4:long_name = "maximum (potential) uptake rate of NH4 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_nh4 for usage)" ; @@ -284,39 +251,15 @@ variables: double fates_hydro_avuln_gs(fates_pft) ; fates_hydro_avuln_gs:units = "unitless" ; fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; - double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; - fates_hydro_avuln_node:units = "unitless" ; - fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; - double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; - fates_hydro_epsil_node:units = "MPa" ; - fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; - double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; - fates_hydro_fcap_node:units = "unitless" ; - fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; double fates_hydro_k_lwp(fates_pft) ; fates_hydro_k_lwp:units = "unitless" ; fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; - double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; - fates_hydro_kmax_node:units = "kg/MPa/m/s" ; - fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; double fates_hydro_p50_gs(fates_pft) ; fates_hydro_p50_gs:units = "MPa" ; fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; - double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; - fates_hydro_p50_node:units = "MPa" ; - fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; double fates_hydro_p_taper(fates_pft) ; fates_hydro_p_taper:units = "unitless" ; fates_hydro_p_taper:long_name = "xylem taper exponent" ; - double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; - fates_hydro_pinot_node:units = "MPa" ; - fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; - double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; - fates_hydro_pitlp_node:units = "MPa" ; - fates_hydro_pitlp_node:long_name = "turgor loss point" ; - double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; - fates_hydro_resid_node:units = "cm3/cm3" ; - fates_hydro_resid_node:long_name = "residual water conent" ; double fates_hydro_rfrac_stem(fates_pft) ; fates_hydro_rfrac_stem:units = "fraction" ; fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; @@ -326,18 +269,6 @@ variables: double fates_hydro_srl(fates_pft) ; fates_hydro_srl:units = "m g-1" ; fates_hydro_srl:long_name = "specific root length" ; - double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; - fates_hydro_thetas_node:units = "cm3/cm3" ; - fates_hydro_thetas_node:long_name = "saturated water content" ; - double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; - fates_hydro_vg_alpha_node:units = "MPa-1" ; - fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; - double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; - fates_hydro_vg_m_node:units = "unitless" ; - fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; - 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_leaf_c3psn(fates_pft) ; fates_leaf_c3psn:units = "flag" ; fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; @@ -365,9 +296,6 @@ variables: double fates_leaf_stomatal_slope_medlyn(fates_pft) ; fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; - double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; - fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; - fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; double fates_leaf_vcmaxha(fates_pft) ; fates_leaf_vcmaxha:units = "J/mol" ; fates_leaf_vcmaxha:long_name = "activation energy for vcmax" ; @@ -509,12 +437,6 @@ variables: double fates_recruit_seed_supplement(fates_pft) ; fates_recruit_seed_supplement:units = "KgC/m2/yr" ; fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; - double fates_stoich_nitr(fates_plant_organs, fates_pft) ; - fates_stoich_nitr:units = "gN/gC" ; - fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; - double fates_stoich_phos(fates_plant_organs, fates_pft) ; - fates_stoich_phos:units = "gP/gC" ; - fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; double fates_trim_inc(fates_pft) ; fates_trim_inc:units = "m2/m2" ; fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; @@ -536,9 +458,6 @@ variables: double fates_turnover_fnrt(fates_pft) ; fates_turnover_fnrt:units = "yr" ; fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; - double fates_turnover_leaf(fates_leafage_class, fates_pft) ; - fates_turnover_leaf:units = "yr" ; - fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; double fates_turnover_senleaf_fdrought(fates_pft) ; fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; @@ -548,9 +467,15 @@ variables: double fates_woody(fates_pft) ; fates_woody:units = "logical flag" ; fates_woody:long_name = "Binary woody lifeform flag" ; - double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; - fates_hlm_pft_map:units = "area fraction" ; - fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_history_ageclass_bin_edges(fates_history_age_bins) ; + fates_history_ageclass_bin_edges:units = "yr" ; + fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; + 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" ; + double fates_history_height_bin_edges(fates_history_height_bins) ; + fates_history_height_bin_edges:units = "m" ; + fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; double fates_fire_FBD(fates_litterclass) ; fates_fire_FBD:units = "kg Biomass/m3" ; fates_fire_FBD:long_name = "fuel bulk density" ; @@ -578,9 +503,84 @@ variables: double fates_frag_maxdecomp(fates_litterclass) ; fates_frag_maxdecomp:units = "yr-1" ; fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; + char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; + fates_hydro_organ_name:units = "unitless - string" ; + fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; + char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; + fates_alloc_organ_name:units = "unitless - string" ; + fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; + 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" ; + double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_nitr_retrans:units = "fraction" ; + fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; + double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_phos_retrans:units = "fraction" ; + fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; + double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; + fates_hydro_avuln_node:units = "unitless" ; + fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; + double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; + fates_hydro_epsil_node:units = "MPa" ; + fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; + double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; + fates_hydro_fcap_node:units = "unitless" ; + fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; + double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; + fates_hydro_kmax_node:units = "kg/MPa/m/s" ; + fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; + double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; + fates_hydro_p50_node:units = "MPa" ; + fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; + double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pinot_node:units = "MPa" ; + fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; + double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pitlp_node:units = "MPa" ; + fates_hydro_pitlp_node:long_name = "turgor loss point" ; + double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; + fates_hydro_resid_node:units = "cm3/cm3" ; + fates_hydro_resid_node:long_name = "residual water conent" ; + double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; + fates_hydro_thetas_node:units = "cm3/cm3" ; + fates_hydro_thetas_node:long_name = "saturated water content" ; + double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_alpha_node:units = "MPa-1" ; + fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; + double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_m_node:units = "unitless" ; + fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; + 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_stoich_nitr(fates_plant_organs, fates_pft) ; + fates_stoich_nitr:units = "gN/gC" ; + fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; + double fates_stoich_phos(fates_plant_organs, fates_pft) ; + fates_stoich_phos:units = "gP/gC" ; + fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; + double fates_alloc_organ_id(fates_plant_organs) ; + fates_alloc_organ_id:units = "unitless" ; + fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; + double fates_hydro_htftype_node(fates_hydr_organs) ; + fates_hydro_htftype_node:units = "unitless" ; + fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; 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_history_coageclass_bin_edges(fates_history_coage_bins) ; + fates_history_coageclass_bin_edges:units = "years" ; + fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; + double fates_history_damage_bin_edges(fates_history_damage_bins) ; + fates_history_damage_bin_edges:units = "% crown loss" ; + fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; + double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; + fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; + fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; + double fates_turnover_leaf(fates_leafage_class, fates_pft) ; + fates_turnover_leaf:units = "yr" ; + fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; double fates_base_mr_20 ; fates_base_mr_20:units = "gC/gN/s" ; fates_base_mr_20:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; @@ -790,24 +790,30 @@ variables: fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; // global attributes: - :history = "This file was generated by BatchPatchParams.py:\nCDL Base File = archive/api24.1.0_101722_fates_params_default.cdl\nXML patch file = archive/api24.1.0_101722_patch_params.xml" ; + :history = "This file was generated by BatchPatchParams.py:\n", + "CDL Base File = archive/api25.1.0_021623_fates_params_default.cdl\n", + "XML patch file = archive/api25.1.1_021623_pr931.xml" ; data: - fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; - - fates_history_coageclass_bin_edges = 0, 5 ; - - fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; - - fates_history_damage_bin_edges = 0, 80 ; + fates_hlm_pft_map = + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100 ; - fates_alloc_organ_id = 1, 2, 3, 6 ; - - fates_hydro_htftype_node = 1, 1, 1, 1 ; - fates_pftname = "broadleaf_evergreen_tropical_tree ", "needleleaf_evergreen_extratrop_tree ", @@ -822,32 +828,6 @@ data: "cool_c3_grass ", "c4_grass " ; - fates_hydro_organ_name = - "leaf ", - "stem ", - "transporting root ", - "absorbing root " ; - - fates_alloc_organ_name = - "leaf", - "fine root", - "sapwood", - "structure" ; - - fates_litterclass_name = - "twig ", - "small branch ", - "large branch ", - "trunk ", - "dead leaves ", - "live grass " ; - - 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, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; - fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 ; @@ -992,18 +972,6 @@ data: fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_cnp_turnover_nitr_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_turnover_phos_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_cnp_vmax_nh4 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; @@ -1023,7 +991,7 @@ data: fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_dev_arbitrary_pft = 1.7560, 1.4995, 1.4995, 1.7560, 1.7560, 1.7560, + fates_dev_arbitrary_pft = 1.756, 1.4995, 1.4995, 1.756, 1.756, 1.756, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956, _ ; fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, @@ -1062,71 +1030,14 @@ data: fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5 ; - fates_hydro_avuln_node = - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 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_hydro_epsil_node = - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - - fates_hydro_fcap_node = - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, - 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_hydro_kmax_node = - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; - fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5 ; - fates_hydro_p50_node = - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25 ; - fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333 ; - fates_hydro_pinot_node = - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; - - fates_hydro_pitlp_node = - -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, - -1.67, -1.67, - -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, - -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, - -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; - - fates_hydro_resid_node = - 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, - 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625 ; @@ -1135,34 +1046,6 @@ data: fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; - fates_hydro_thetas_node = - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; - - fates_hydro_vg_alpha_node = - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005 ; - - fates_hydro_vg_m_node = - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_hydro_vg_n_node = - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 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_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, @@ -1188,9 +1071,6 @@ data: fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, 4.7, 2.2, 5.3, 1.6 ; - fates_leaf_vcmax25top = - 50, 62, 39, 61, 41, 58, 62, 54, 54, 78, 78, 78 ; - fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330 ; @@ -1319,25 +1199,6 @@ data: fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_stoich_nitr = - 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, - 0.0047, 0.0047, 0.0047 ; - - fates_stoich_phos = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, - 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, - 0.00047, 0.00047, 0.00047, 0.00047 ; - fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03 ; @@ -1356,9 +1217,6 @@ data: fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - fates_turnover_leaf = - 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_wood_density = 0.7, 0.4, 0.7, 0.53, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, @@ -1366,21 +1224,17 @@ data: fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; - fates_hlm_pft_map = - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; + + fates_litterclass_name = + "twig ", + "small branch ", + "large branch ", + "trunk ", + "dead leaves ", + "live grass " ; + + fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; @@ -1400,9 +1254,157 @@ data: fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; + fates_hydro_organ_name = + "leaf ", + "stem ", + "transporting root ", + "absorbing root " ; + + fates_alloc_organ_name = + "leaf", + "fine root", + "sapwood", + "structure" ; + + 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, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; + + fates_cnp_turnover_nitr_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_turnover_phos_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_avuln_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_hydro_epsil_node = + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_hydro_fcap_node = + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_kmax_node = + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; + + fates_hydro_p50_node = + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25 ; + + fates_hydro_pinot_node = + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; + + fates_hydro_pitlp_node = + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + -1.67, -1.67, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; + + fates_hydro_resid_node = + 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; + + fates_hydro_thetas_node = + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; + + fates_hydro_vg_alpha_node = + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005 ; + + fates_hydro_vg_m_node = + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_hydro_vg_n_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_stoich_nitr = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; + + fates_stoich_phos = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; + + fates_alloc_organ_id = 1, 2, 3, 6 ; + + fates_hydro_htftype_node = 1, 1, 1, 1 ; + fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; - fates_base_mr_20 = 2.525e-06 ; + fates_history_coageclass_bin_edges = 0, 5 ; + + fates_history_damage_bin_edges = 0, 80 ; + + fates_leaf_vcmax25top = + 50, 62, 39, 61, 41, 58, 62, 54, 54, 78, 78, 78 ; + + fates_turnover_leaf = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_base_mr_20 = 2.52e-06 ; fates_canopy_closure_thresh = 0.8 ; From 5c3fe606fcf9e945cae6726a904772bf99421f16 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 16 Feb 2023 15:36:42 -0800 Subject: [PATCH 526/852] fix missing third decimal place value in fates_base_mr_20 --- parameter_files/archive/api25.1.1_021623_pr931.xml | 2 +- parameter_files/fates_params_default.cdl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/parameter_files/archive/api25.1.1_021623_pr931.xml b/parameter_files/archive/api25.1.1_021623_pr931.xml index e327776be7..b07fefb2d5 100644 --- a/parameter_files/archive/api25.1.1_021623_pr931.xml +++ b/parameter_files/archive/api25.1.1_021623_pr931.xml @@ -9,7 +9,7 @@ 1.7560, 1.4995, 1.4995, 1.7560, 1.7560, 1.7560, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956 - 2.52e-06 + 2.525e-06 diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 98d8e02a72..34cffccf01 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1404,7 +1404,7 @@ data: fates_turnover_leaf = 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - fates_base_mr_20 = 2.52e-06 ; + fates_base_mr_20 = 2.525e-06 ; fates_canopy_closure_thresh = 0.8 ; From ddc8a421f729903278f937bc2ea1955b42c68ecd Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Wed, 22 Feb 2023 14:19:15 -0800 Subject: [PATCH 527/852] New initialisation mode - using initd to mean initial dbh. --- biogeochem/FatesAllometryMod.F90 | 1 + main/EDInitMod.F90 | 332 ++++++++++++++++-------------- main/EDTypesMod.F90 | 2 +- main/FatesHistoryInterfaceMod.F90 | 19 +- 4 files changed, 198 insertions(+), 156 deletions(-) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index a6d7126e4a..0c94d71f92 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -116,6 +116,7 @@ module FatesAllometryMod public :: bfineroot ! Generic actual fine root biomass wrapper public :: bdead_allom ! Generic bdead wrapper public :: carea_allom ! Generic crown area wrapper + public :: carea_2pwr ! crown area of single plant public :: bstore_allom ! Generic maximum storage carbon wrapper public :: decay_coeff_kn public :: ForceDBH ! Method to set DBH to sync with structure diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 79d5974042..b93947471b 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -62,6 +62,7 @@ module EDInitMod use FatesAllometryMod , only : bsap_allom use FatesAllometryMod , only : bdead_allom use FatesAllometryMod , only : bstore_allom + use FatesAllometryMod , only : carea_2pwr use PRTGenericMod , only : StorageNutrientTarget use FatesInterfaceTypesMod, only : hlm_parteh_mode use PRTGenericMod, only : prt_carbon_allom_hyp @@ -79,7 +80,7 @@ module EDInitMod use PRTGenericMod, only : SetState use FatesSizeAgeTypeIndicesMod,only : get_age_class_index use DamageMainMod, only : undamaged_class - + ! CIME GLOBALS use shr_log_mod , only : errMsg => shr_log_errMsg @@ -161,11 +162,11 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) allocate(site_in%imort_carbonflux(1:numpft)) allocate(site_in%fmort_carbonflux_canopy(1:numpft)) allocate(site_in%fmort_carbonflux_ustory(1:numpft)) - + allocate(site_in%term_abg_flux(1:nlevsclass,1:numpft)) allocate(site_in%imort_abg_flux(1:nlevsclass,1:numpft)) allocate(site_in%fmort_abg_flux(1:nlevsclass,1:numpft)) - + site_in%nlevsoil = bc_in%nlevsoil allocate(site_in%rootfrac_scr(site_in%nlevsoil)) allocate(site_in%zi_soil(0:site_in%nlevsoil)) @@ -184,8 +185,8 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) ! for CNP dynamics, track the mean l2fr of recruits ! for different pfts and canopy positions allocate(site_in%rec_l2fr(1:numpft,nclmax)) - - + + ! SP mode allocate(site_in%sp_tlai(1:numpft)) allocate(site_in%sp_tsai(1:numpft)) @@ -309,7 +310,7 @@ subroutine zero_site( site_in ) site_in%fmort_rate_ustory_damage(:,:,:) = 0._r8 site_in%fmort_cflux_canopy_damage(:,:) = 0._r8 site_in%fmort_cflux_ustory_damage(:,:) = 0._r8 - + ! Resources management (logging/harvesting, etc) site_in%resources_management%harvest_debt = 0.0_r8 site_in%resources_management%harvest_debt_sec = 0.0_r8 @@ -321,7 +322,7 @@ subroutine zero_site( site_in ) site_in%area_pft(:) = 0._r8 site_in%use_this_pft(:) = fates_unset_int site_in%area_by_age(:) = 0._r8 - + end subroutine zero_site ! ============================================================================ @@ -375,9 +376,9 @@ subroutine set_site_properties( nsites, sites,bc_in ) do s = 1,nsites sites(s)%nchilldays = 0 sites(s)%ncolddays = 0 ! recalculated in phenology - ! immediately, so yes this - ! is memory-less, but needed - ! for first value in history file + ! immediately, so yes this + ! is memory-less, but needed + ! for first value in history file sites(s)%phen_model_date = 0 sites(s)%cleafondate = cleafon - hlm_day_of_year sites(s)%cleafoffdate = cleafoff - hlm_day_of_year @@ -399,11 +400,11 @@ subroutine set_site_properties( nsites, sites,bc_in ) do ft = 1,numpft sites(s)%rec_l2fr(ft,:) = prt_params%allom_l2fr(ft) end do - + ! Its difficult to come up with a resonable starting smoothing value, so ! we initialize on a cold-start to -1 sites(s)%ema_npp = -9999._r8 - + if(hlm_use_fixed_biogeog.eq.itrue)then ! MAPPING OF FATES PFTs on to HLM_PFTs ! add up the area associated with each FATES PFT @@ -450,16 +451,16 @@ subroutine set_site_properties( nsites, sites,bc_in ) end do !ft else ! for sp and nocomp mode, assert a bare ground patch if needed sumarea = sum(sites(s)%area_pft(1:numpft)) - - ! In all the other FATES modes, bareground is the area in which plants - ! do not grow of their own accord. In SP mode we assert that the canopy is full for - ! each PFT patch. Thus, we also need to assert a bare ground area in - ! order to not have all of the ground filled by leaves. - ! Further to that, one could calculate bare ground as the remaining area when - ! all fhe canopies are accounted for, but this means we don't pass balance checks - ! on canopy are inside FATES, and so in SP mode, we define the bare groud - ! patch as having a PFT identifier as zero. + ! In all the other FATES modes, bareground is the area in which plants + ! do not grow of their own accord. In SP mode we assert that the canopy is full for + ! each PFT patch. Thus, we also need to assert a bare ground area in + ! order to not have all of the ground filled by leaves. + + ! Further to that, one could calculate bare ground as the remaining area when + ! all fhe canopies are accounted for, but this means we don't pass balance checks + ! on canopy are inside FATES, and so in SP mode, we define the bare groud + ! patch as having a PFT identifier as zero. if(sumarea.lt.area)then !make some bare ground sites(s)%area_pft(0) = area - sumarea @@ -508,7 +509,7 @@ subroutine init_patches( nsites, sites, bc_in) integer :: el real(r8) :: age !notional age of this patch integer :: ageclass - + ! dummy locals real(r8) :: biomass_stock real(r8) :: litter_stock @@ -688,34 +689,34 @@ subroutine init_patches( nsites, sites, bc_in) enddo !s end if - ! zero all the patch fire variables for the first timestep + ! zero all the patch fire variables for the first timestep do s = 1, nsites - currentPatch => sites(s)%youngest_patch - do while(associated(currentPatch)) - - currentPatch%litter_moisture(:) = 0._r8 - currentPatch%fuel_eff_moist = 0._r8 - currentPatch%livegrass = 0._r8 - currentPatch%sum_fuel = 0._r8 - currentPatch%fuel_bulkd = 0._r8 - currentPatch%fuel_sav = 0._r8 - currentPatch%fuel_mef = 0._r8 - currentPatch%ros_front = 0._r8 - currentPatch%effect_wspeed = 0._r8 - currentPatch%tau_l = 0._r8 - currentPatch%fuel_frac(:) = 0._r8 - currentPatch%tfc_ros = 0._r8 - currentPatch%fi = 0._r8 - currentPatch%fire = 0 - currentPatch%fd = 0._r8 - currentPatch%ros_back = 0._r8 - currentPatch%scorch_ht(:) = 0._r8 - currentPatch%frac_burnt = 0._r8 - currentPatch%burnt_frac_litter(:) = 0._r8 - - currentPatch => currentPatch%older - enddo - enddo + currentPatch => sites(s)%youngest_patch + do while(associated(currentPatch)) + + currentPatch%litter_moisture(:) = 0._r8 + currentPatch%fuel_eff_moist = 0._r8 + currentPatch%livegrass = 0._r8 + currentPatch%sum_fuel = 0._r8 + currentPatch%fuel_bulkd = 0._r8 + currentPatch%fuel_sav = 0._r8 + currentPatch%fuel_mef = 0._r8 + currentPatch%ros_front = 0._r8 + currentPatch%effect_wspeed = 0._r8 + currentPatch%tau_l = 0._r8 + currentPatch%fuel_frac(:) = 0._r8 + currentPatch%tfc_ros = 0._r8 + currentPatch%fi = 0._r8 + currentPatch%fire = 0 + currentPatch%fd = 0._r8 + currentPatch%ros_back = 0._r8 + currentPatch%scorch_ht(:) = 0._r8 + currentPatch%frac_burnt = 0._r8 + currentPatch%burnt_frac_litter(:) = 0._r8 + + currentPatch => currentPatch%older + enddo + enddo ! This sets the rhizosphere shells based on the plant initialization ! The initialization of the plant-relevant hydraulics variables @@ -729,7 +730,7 @@ subroutine init_patches( nsites, sites, bc_in) return end subroutine init_patches - + ! ============================================================================ subroutine init_cohorts( site_in, patch_in, bc_in) ! @@ -737,7 +738,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) ! initialize new cohorts on bare ground ! ! !USES: - + ! ! !ARGUMENTS type(ed_site_type), intent(inout), pointer :: site_in @@ -772,6 +773,10 @@ subroutine init_cohorts( site_in, patch_in, bc_in) integer, parameter :: rstatus = 0 integer init + + logical :: do_inverse + real(r8) :: c_area + !---------------------------------------------------------------------- patch_in%tallest => null() @@ -801,16 +806,24 @@ subroutine init_cohorts( site_in, patch_in, bc_in) use_pft_local(pft) = ifalse ! Case 4 endif endif - end do + + do pft = 1,numpft + if(use_pft_local(pft).eq.itrue)then - if(EDPftvarcon_inst%initd(pft)>nearzero) then - allocate(temp_cohort) ! temporary cohort + allocate(temp_cohort) ! temporary cohort + temp_cohort%pft = pft + temp_cohort%l2fr = prt_params%allom_l2fr(pft) + temp_cohort%canopy_trim = 1.0_r8 + ! Assume no damage to begin with + temp_cohort%crowndamage = 1 + + if(EDPftvarcon_inst%initd(pft)>nearzero) then ! interpret as initial density and calculate diameter - temp_cohort%pft = pft temp_cohort%n = EDPftvarcon_inst%initd(pft) * patch_in%area + if(hlm_use_nocomp.eq.itrue)then !in nocomp mode we only have one PFT per patch ! as opposed to numpft's. So we should up the initial density ! to compensate (otherwise runs are very hard to compare) @@ -820,12 +833,6 @@ subroutine init_cohorts( site_in, patch_in, bc_in) temp_cohort%n = temp_cohort%n * sum(site_in%use_this_pft) endif - temp_cohort%canopy_trim = 1.0_r8 - temp_cohort%l2fr = prt_params%allom_l2fr(pft) - - ! Assume no damage to begin with - since we assume no damage - ! we do not need to initialise branch frac just yet. - temp_cohort%crowndamage = 1 ! h,dbh,leafc,n from SP values or from small initial size. if(hlm_use_sp.eq.itrue)then @@ -837,7 +844,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) else temp_cohort%hite = EDPftvarcon_inst%hgt_min(pft) - + ! Calculate the plant diameter from height call h2d_allom(temp_cohort%hite,pft,temp_cohort%dbh) @@ -845,130 +852,147 @@ subroutine init_cohorts( site_in, patch_in, bc_in) ! (calculates a maximum first, then applies canopy trim) call bleaf(temp_cohort%dbh,pft,temp_cohort%crowndamage, & temp_cohort%canopy_trim,c_leaf) - end if ! sp mode + endif ! sp mode - ! Calculate total above-ground biomass from allometry - call bagw_allom(temp_cohort%dbh,pft,temp_cohort%crowndamage,c_agw) + else ! interpret as initial diameter and calculate density - ! Calculate coarse root biomass from allometry - call bbgw_allom(temp_cohort%dbh,pft,c_bgw) + temp_cohort%dbh = abs(EDPftvarcon_inst%initd(pft)) - ! Calculate fine root biomass from allometry - ! (calculates a maximum and then trimming value) - call bfineroot(temp_cohort%dbh,pft,temp_cohort%canopy_trim,temp_cohort%l2fr,c_fnrt) + ! calculate crown area of a single plant + do_inverse = .false. - ! Calculate sapwood biomass - call bsap_allom(temp_cohort%dbh,pft,temp_cohort%crowndamage, & - temp_cohort%canopy_trim,a_sapw,c_sapw) + call carea_2pwr(temp_cohort%dbh, site_in%spread, prt_params%allom_d2bl2(pft), & + prt_params%allom_blca_expnt_diff(pft), prt_params%allom_d2ca_coefficient_min(pft), & + prt_params%allom_d2ca_coefficient_max(pft), temp_cohort%crowndamage, & + c_area, do_inverse) - call bdead_allom( c_agw, c_bgw, c_sapw, pft, c_struct ) + ! calculate initial density required to close canopy + temp_cohort%n = patch_in%area / c_area + endif - call bstore_allom(temp_cohort%dbh, pft, temp_cohort%crowndamage, & - temp_cohort%canopy_trim, c_store) - cstatus = leaves_on + ! Calculate total above-ground biomass from allometry + call bagw_allom(temp_cohort%dbh,pft,temp_cohort%crowndamage,c_agw) - stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(temp_cohort%pft) + ! Calculate coarse root biomass from allometry + call bbgw_allom(temp_cohort%dbh,pft,c_bgw) - if(hlm_use_sp.eq.ifalse)then ! do not override SP vales with phenology + ! Calculate fine root biomass from allometry + ! (calculates a maximum and then trimming value) + call bfineroot(temp_cohort%dbh,pft,temp_cohort%canopy_trim,temp_cohort%l2fr,c_fnrt) - if( prt_params%season_decid(pft) == itrue .and. & - any(site_in%cstatus == [phen_cstat_nevercold,phen_cstat_iscold])) then - c_leaf = 0._r8 - c_sapw = (1.0_r8-stem_drop_fraction) * c_sapw - c_struct = (1.0_r8-stem_drop_fraction) * c_struct - cstatus = leaves_off - endif + ! Calculate sapwood biomass + call bsap_allom(temp_cohort%dbh,pft,temp_cohort%crowndamage, & + temp_cohort%canopy_trim,a_sapw,c_sapw) - if ( prt_params%stress_decid(pft) == itrue .and. & - any(site_in%dstatus == [phen_dstat_timeoff,phen_dstat_moistoff])) then - c_leaf = 0._r8 - c_sapw = (1.0_r8-stem_drop_fraction) * c_sapw - c_struct = (1.0_r8-stem_drop_fraction) * c_struct - cstatus = leaves_off - endif + call bdead_allom( c_agw, c_bgw, c_sapw, pft, c_struct ) - end if ! SP mode + call bstore_allom(temp_cohort%dbh, pft, temp_cohort%crowndamage, & + temp_cohort%canopy_trim, c_store) - if ( debug ) write(fates_log(),*) 'EDInitMod.F90 call create_cohort ' + cstatus = leaves_on - temp_cohort%coage = 0.0_r8 + stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(temp_cohort%pft) + if(hlm_use_sp.eq.ifalse)then ! do not override SP vales with phenology - ! -------------------------------------------------------------------------------- - ! Initialize the mass of every element in every organ of the organ - ! -------------------------------------------------------------------------------- + if( prt_params%season_decid(pft) == itrue .and. & + any(site_in%cstatus == [phen_cstat_nevercold,phen_cstat_iscold])) then + c_leaf = 0._r8 + c_sapw = (1.0_r8-stem_drop_fraction) * c_sapw + c_struct = (1.0_r8-stem_drop_fraction) * c_struct + cstatus = leaves_off + endif - prt_obj => null() - call InitPRTObject(prt_obj) + if ( prt_params%stress_decid(pft) == itrue .and. & + any(site_in%dstatus == [phen_dstat_timeoff,phen_dstat_moistoff])) then + c_leaf = 0._r8 + c_sapw = (1.0_r8-stem_drop_fraction) * c_sapw + c_struct = (1.0_r8-stem_drop_fraction) * c_struct + cstatus = leaves_off + endif - do el = 1,num_elements + end if ! SP mode - element_id = element_list(el) + if ( debug ) write(fates_log(),*) 'EDInitMod.F90 call create_cohort ' - ! If this is carbon12, then the initialization is straight forward - ! otherwise, we use stoichiometric ratios - select case(element_id) - case(carbon12_element) + temp_cohort%coage = 0.0_r8 - m_struct = c_struct - m_leaf = c_leaf - m_fnrt = c_fnrt - m_sapw = c_sapw - m_store = c_store - m_repro = 0._r8 - case(nitrogen_element) + ! -------------------------------------------------------------------------------- + ! Initialize the mass of every element in every organ of the organ + ! -------------------------------------------------------------------------------- - m_struct = c_struct*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(struct_organ)) - m_leaf = c_leaf*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(leaf_organ)) - m_fnrt = c_fnrt*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(fnrt_organ)) - m_sapw = c_sapw*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(sapw_organ)) - m_repro = 0._r8 - m_store = StorageNutrientTarget(pft,element_id,m_leaf,m_fnrt,m_sapw,m_struct) + prt_obj => null() + call InitPRTObject(prt_obj) - case(phosphorus_element) + do el = 1,num_elements - m_struct = c_struct*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(struct_organ)) - m_leaf = c_leaf*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(leaf_organ)) - m_fnrt = c_fnrt*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(fnrt_organ)) - m_sapw = c_sapw*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(sapw_organ)) - m_repro = 0._r8 - m_store = StorageNutrientTarget(pft,element_id,m_leaf,m_fnrt,m_sapw,m_struct) + element_id = element_list(el) - end select + ! If this is carbon12, then the initialization is straight forward + ! otherwise, we use stoichiometric ratios + select case(element_id) + case(carbon12_element) - select case(hlm_parteh_mode) - case (prt_carbon_allom_hyp,prt_cnp_flex_allom_hyp ) + m_struct = c_struct + m_leaf = c_leaf + m_fnrt = c_fnrt + m_sapw = c_sapw + m_store = c_store + m_repro = 0._r8 - ! Put all of the leaf mass into the first bin - call SetState(prt_obj,leaf_organ, element_id,m_leaf,1) - do iage = 2,nleafage - call SetState(prt_obj,leaf_organ, element_id,0._r8,iage) - end do + case(nitrogen_element) - call SetState(prt_obj,fnrt_organ, element_id, m_fnrt) - call SetState(prt_obj,sapw_organ, element_id, m_sapw) - call SetState(prt_obj,store_organ, element_id, m_store) - call SetState(prt_obj,struct_organ, element_id, m_struct) - call SetState(prt_obj,repro_organ, element_id, m_repro) + m_struct = c_struct*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(struct_organ)) + m_leaf = c_leaf*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(leaf_organ)) + m_fnrt = c_fnrt*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(fnrt_organ)) + m_sapw = c_sapw*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(sapw_organ)) + m_repro = 0._r8 + m_store = StorageNutrientTarget(pft,element_id,m_leaf,m_fnrt,m_sapw,m_struct) - case default - write(fates_log(),*) 'Unspecified PARTEH module during create_cohort' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end select + case(phosphorus_element) - end do + m_struct = c_struct*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(struct_organ)) + m_leaf = c_leaf*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(leaf_organ)) + m_fnrt = c_fnrt*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(fnrt_organ)) + m_sapw = c_sapw*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(sapw_organ)) + m_repro = 0._r8 + m_store = StorageNutrientTarget(pft,element_id,m_leaf,m_fnrt,m_sapw,m_struct) - call prt_obj%CheckInitialConditions() - - call create_cohort(site_in, patch_in, pft, temp_cohort%n, temp_cohort%hite, & - temp_cohort%coage, temp_cohort%dbh, prt_obj, cstatus, rstatus, & - temp_cohort%canopy_trim, temp_cohort%c_area,1,temp_cohort%crowndamage, site_in%spread, bc_in) + end select + + select case(hlm_parteh_mode) + case (prt_carbon_allom_hyp,prt_cnp_flex_allom_hyp ) + + ! Put all of the leaf mass into the first bin + call SetState(prt_obj,leaf_organ, element_id,m_leaf,1) + do iage = 2,nleafage + call SetState(prt_obj,leaf_organ, element_id,0._r8,iage) + end do + + call SetState(prt_obj,fnrt_organ, element_id, m_fnrt) + call SetState(prt_obj,sapw_organ, element_id, m_sapw) + call SetState(prt_obj,store_organ, element_id, m_store) + call SetState(prt_obj,struct_organ, element_id, m_struct) + call SetState(prt_obj,repro_organ, element_id, m_repro) + + case default + write(fates_log(),*) 'Unspecified PARTEH module during create_cohort' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select + + end do + + call prt_obj%CheckInitialConditions() + + call create_cohort(site_in, patch_in, pft, temp_cohort%n, temp_cohort%hite, & + temp_cohort%coage, temp_cohort%dbh, prt_obj, cstatus, rstatus, & + temp_cohort%canopy_trim, temp_cohort%c_area,1,temp_cohort%crowndamage, site_in%spread, bc_in) + + deallocate(temp_cohort) ! get rid of temporary cohort - deallocate(temp_cohort) ! get rid of temporary cohort - endif endif !use_this_pft enddo !numpft @@ -976,8 +1000,8 @@ subroutine init_cohorts( site_in, patch_in, bc_in) ! Pass patch level temperature to the new cohorts (this is a nominal 15C right now) !temp_cohort => patch_in%tallest !do while(associated(temp_cohort)) - !call temp_cohort%tveg_lpa%UpdateRmean(patch_in%tveg_lpa%GetMean()) - !temp_cohort => temp_cohort%shorter + !call temp_cohort%tveg_lpa%UpdateRmean(patch_in%tveg_lpa%GetMean()) + !temp_cohort => temp_cohort%shorter !end do call fuse_cohorts(site_in, patch_in,bc_in) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index dcc6ea7bc6..e7d4f337b7 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -54,7 +54,7 @@ module EDTypesMod integer, parameter, public :: idiffuse = 2 ! This is the array index for diffuse radiation ! parameters that govern the VAI (LAI+SAI) bins used in radiative transfer code - integer, parameter, public :: nlevleaf = 30 ! number of leaf+stem layers in canopy layer + integer, parameter, public :: nlevleaf = 36 ! number of leaf+stem layers in canopy layer real(r8), public :: dinc_vai(nlevleaf) = fates_unset_r8 ! VAI bin widths array real(r8), public :: dlower_vai(nlevleaf) = fates_unset_r8 ! lower edges of VAI bins diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index f9f99300f9..41e95896b7 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -687,6 +687,7 @@ module FatesHistoryInterfaceMod integer :: ih_fabi_sha_si_cnlfpft integer :: ih_parprof_dir_si_cnlfpft integer :: ih_parprof_dif_si_cnlfpft + integer :: ih_ts_net_uptake_si_cnlfpft ! indices to site x crown damage variables ! site x crown damage x pft x sizeclass @@ -4402,6 +4403,7 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) hio_parsun_z_si_cnlf => this%hvars(ih_parsun_z_si_cnlf)%r82d, & hio_parsha_z_si_cnlf => this%hvars(ih_parsha_z_si_cnlf)%r82d, & hio_ts_net_uptake_si_cnlf => this%hvars(ih_ts_net_uptake_si_cnlf)%r82d, & + hio_ts_net_uptake_si_cnlfpft => this%hvars(ih_ts_net_uptake_si_cnlfpft)%r82d, & hio_parsun_z_si_cnlfpft => this%hvars(ih_parsun_z_si_cnlfpft)%r82d, & hio_parsha_z_si_cnlfpft => this%hvars(ih_parsha_z_si_cnlfpft)%r82d, & hio_laisun_z_si_cnlf => this%hvars(ih_laisun_z_si_cnlf)%r82d, & @@ -4631,13 +4633,21 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) endif end associate endif - + !!! canopy leaf carbon balance ican = ccohort%canopy_layer do ileaf=1,ccohort%nv cnlf_indx = ileaf + (ican-1) * nlevleaf hio_ts_net_uptake_si_cnlf(io_si, cnlf_indx) = hio_ts_net_uptake_si_cnlf(io_si, cnlf_indx) + & ccohort%ts_net_uptake(ileaf) * per_dt_tstep * ccohort%c_area * area_inv + + do ipft=1,numpft + ! calculate where we are on multiplexed dimensions + cnlfpft_indx = ileaf + (ican-1) * nlevleaf + (ipft-1) * nlevleaf * nclmax + hio_ts_net_uptake_si_cnlfpft(io_si, cnlfpft_indx) = & + hio_ts_net_uptake_si_cnlfpft(io_si, cnlfpft_indx) + & + ccohort%ts_net_uptake(ileaf) * per_dt_tstep * ccohort%c_area * area_inv + end do end do ccohort => ccohort%taller @@ -6608,6 +6618,13 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=2, ivar=ivar, initialize=initialize_variables, & index = ih_ts_net_uptake_si_cnlf) +call this%set_history_var(vname='FATES_NET_C_UPTAKE_CLLL', & + units='kg m-2 s-1', & + long='net carbon uptake in kg carbon per m2 per second by each canopy and leaf layer per unit ground area (i.e. divide by CROWNAREA_CLLL to make per leaf area)', & + use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & + hlms='CLM:ALM', upfreq=2, ivar=ivar, initialize=initialize_variables, & + index = ih_ts_net_uptake_si_cnlf) + call this%set_history_var(vname='FATES_CROWNAREA_CLLL', units='m2 m-2', & long='total crown area that is occupied by leaves in each canopy and leaf layer', & use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & From 56b32667bae1df09b50c4a72333c0aae5fe03078 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 22 Feb 2023 14:38:51 -0800 Subject: [PATCH 528/852] Update xml file to old format to add new parameter value --- .../archive/api25.1.1_021623_pr931.xml | 38 +- parameter_files/fates_params_default.cdl | 553 +++++++++--------- 2 files changed, 305 insertions(+), 286 deletions(-) diff --git a/parameter_files/archive/api25.1.1_021623_pr931.xml b/parameter_files/archive/api25.1.1_021623_pr931.xml index b07fefb2d5..ba22a0dffa 100644 --- a/parameter_files/archive/api25.1.1_021623_pr931.xml +++ b/parameter_files/archive/api25.1.1_021623_pr931.xml @@ -1,15 +1,31 @@ - This change is associated with FATES PR #931 - archive/api25.1.0_021623_fates_params_default.cdl + + + + + + + + archive/api25.1.0_021623_fates_params_default.cdl fates_params_default.cdl - 1,2,3,4,5,6,7,8,9,10,11,12 - - - 1.7560, 1.4995, 1.4995, 1.7560, 1.7560, 1.7560, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956 - - - 2.525e-06 - - + 1,2,3,4,5,6,7,8,9,10,11,12 + + + fates_maintresp_atkinetal2017model_baserate + fates_pft + umol CO2/m^2/s + Leaf maintenance respiration base rate parameter (r0) per Atkin et al 2017 + 1.7560, 1.4995, 1.4995, 1.7560, 1.7560, 1.7560, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956, 0.0 + + + 2.525e-06 + + diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 34cffccf01..a10803ee95 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1,4 +1,4 @@ -netcdf fates_params_default { +netcdf tmp { dimensions: fates_NCWD = 4 ; fates_history_age_bins = 7 ; @@ -14,15 +14,42 @@ dimensions: fates_plant_organs = 4 ; fates_string_length = 60 ; variables: - double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; - fates_hlm_pft_map:units = "area fraction" ; - fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_history_ageclass_bin_edges(fates_history_age_bins) ; + fates_history_ageclass_bin_edges:units = "yr" ; + fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; + double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; + fates_history_coageclass_bin_edges:units = "years" ; + fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; + double fates_history_height_bin_edges(fates_history_height_bins) ; + fates_history_height_bin_edges:units = "m" ; + fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; + double fates_history_damage_bin_edges(fates_history_damage_bins) ; + fates_history_damage_bin_edges:units = "% crown loss" ; + fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; fates_history_sizeclass_bin_edges:units = "cm" ; fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; + double fates_alloc_organ_id(fates_plant_organs) ; + fates_alloc_organ_id:units = "unitless" ; + fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; + double fates_hydro_htftype_node(fates_hydr_organs) ; + fates_hydro_htftype_node:units = "unitless" ; + fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; char fates_pftname(fates_pft, fates_string_length) ; fates_pftname:units = "unitless - string" ; fates_pftname:long_name = "Description of plant type" ; + char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; + fates_hydro_organ_name:units = "unitless - string" ; + fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; + char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; + fates_alloc_organ_name:units = "unitless - string" ; + fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; + 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" ; + 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" ; double fates_alloc_storage_cushion(fates_pft) ; fates_alloc_storage_cushion:units = "fraction" ; fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; @@ -191,6 +218,12 @@ variables: double fates_cnp_store_ovrflw_frac(fates_pft) ; fates_cnp_store_ovrflw_frac:units = "fraction" ; fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; + double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_nitr_retrans:units = "fraction" ; + fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; + double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_phos_retrans:units = "fraction" ; + fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; double fates_cnp_vmax_nh4(fates_pft) ; fates_cnp_vmax_nh4:units = "gN/gC/s" ; fates_cnp_vmax_nh4:long_name = "maximum (potential) uptake rate of NH4 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_nh4 for usage)" ; @@ -251,15 +284,39 @@ variables: double fates_hydro_avuln_gs(fates_pft) ; fates_hydro_avuln_gs:units = "unitless" ; fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; + double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; + fates_hydro_avuln_node:units = "unitless" ; + fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; + double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; + fates_hydro_epsil_node:units = "MPa" ; + fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; + double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; + fates_hydro_fcap_node:units = "unitless" ; + fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; double fates_hydro_k_lwp(fates_pft) ; fates_hydro_k_lwp:units = "unitless" ; fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; + double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; + fates_hydro_kmax_node:units = "kg/MPa/m/s" ; + fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; double fates_hydro_p50_gs(fates_pft) ; fates_hydro_p50_gs:units = "MPa" ; fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; + double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; + fates_hydro_p50_node:units = "MPa" ; + fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; double fates_hydro_p_taper(fates_pft) ; fates_hydro_p_taper:units = "unitless" ; fates_hydro_p_taper:long_name = "xylem taper exponent" ; + double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pinot_node:units = "MPa" ; + fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; + double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pitlp_node:units = "MPa" ; + fates_hydro_pitlp_node:long_name = "turgor loss point" ; + double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; + fates_hydro_resid_node:units = "cm3/cm3" ; + fates_hydro_resid_node:long_name = "residual water conent" ; double fates_hydro_rfrac_stem(fates_pft) ; fates_hydro_rfrac_stem:units = "fraction" ; fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; @@ -269,6 +326,18 @@ variables: double fates_hydro_srl(fates_pft) ; fates_hydro_srl:units = "m g-1" ; fates_hydro_srl:long_name = "specific root length" ; + double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; + fates_hydro_thetas_node:units = "cm3/cm3" ; + fates_hydro_thetas_node:long_name = "saturated water content" ; + double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_alpha_node:units = "MPa-1" ; + fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; + double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_m_node:units = "unitless" ; + fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; + 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_leaf_c3psn(fates_pft) ; fates_leaf_c3psn:units = "flag" ; fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; @@ -296,6 +365,9 @@ variables: double fates_leaf_stomatal_slope_medlyn(fates_pft) ; fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; + double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; + fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; + fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; double fates_leaf_vcmaxha(fates_pft) ; fates_leaf_vcmaxha:units = "J/mol" ; fates_leaf_vcmaxha:long_name = "activation energy for vcmax" ; @@ -305,6 +377,9 @@ variables: double fates_leaf_vcmaxse(fates_pft) ; fates_leaf_vcmaxse:units = "J/mol/K" ; fates_leaf_vcmaxse:long_name = "entropy term for vcmax" ; + double fates_maintresp_atkinetal2017model_baserate(fates_pft) ; + fates_maintresp_atkinetal2017model_baserate:units = "umol CO2/m^2/s" ; + fates_maintresp_atkinetal2017model_baserate:long_name = "Leaf maintenance respiration base rate parameter (r0) per Atkin et al 2017" ; double fates_maintresp_reduction_curvature(fates_pft) ; fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; @@ -437,6 +512,12 @@ variables: double fates_recruit_seed_supplement(fates_pft) ; fates_recruit_seed_supplement:units = "KgC/m2/yr" ; fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; + double fates_stoich_nitr(fates_plant_organs, fates_pft) ; + fates_stoich_nitr:units = "gN/gC" ; + fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; + double fates_stoich_phos(fates_plant_organs, fates_pft) ; + fates_stoich_phos:units = "gP/gC" ; + fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; double fates_trim_inc(fates_pft) ; fates_trim_inc:units = "m2/m2" ; fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; @@ -458,6 +539,9 @@ variables: double fates_turnover_fnrt(fates_pft) ; fates_turnover_fnrt:units = "yr" ; fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; + double fates_turnover_leaf(fates_leafage_class, fates_pft) ; + fates_turnover_leaf:units = "yr" ; + fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; double fates_turnover_senleaf_fdrought(fates_pft) ; fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; @@ -467,15 +551,9 @@ variables: double fates_woody(fates_pft) ; fates_woody:units = "logical flag" ; fates_woody:long_name = "Binary woody lifeform flag" ; - double fates_history_ageclass_bin_edges(fates_history_age_bins) ; - fates_history_ageclass_bin_edges:units = "yr" ; - fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; - 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" ; - double fates_history_height_bin_edges(fates_history_height_bins) ; - fates_history_height_bin_edges:units = "m" ; - fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; double fates_fire_FBD(fates_litterclass) ; fates_fire_FBD:units = "kg Biomass/m3" ; fates_fire_FBD:long_name = "fuel bulk density" ; @@ -503,84 +581,9 @@ variables: double fates_frag_maxdecomp(fates_litterclass) ; fates_frag_maxdecomp:units = "yr-1" ; fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; - char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; - fates_hydro_organ_name:units = "unitless - string" ; - fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; - char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; - fates_alloc_organ_name:units = "unitless - string" ; - fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; - 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" ; - double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; - fates_cnp_turnover_nitr_retrans:units = "fraction" ; - fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; - double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; - fates_cnp_turnover_phos_retrans:units = "fraction" ; - fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; - double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; - fates_hydro_avuln_node:units = "unitless" ; - fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; - double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; - fates_hydro_epsil_node:units = "MPa" ; - fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; - double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; - fates_hydro_fcap_node:units = "unitless" ; - fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; - double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; - fates_hydro_kmax_node:units = "kg/MPa/m/s" ; - fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; - double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; - fates_hydro_p50_node:units = "MPa" ; - fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; - double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; - fates_hydro_pinot_node:units = "MPa" ; - fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; - double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; - fates_hydro_pitlp_node:units = "MPa" ; - fates_hydro_pitlp_node:long_name = "turgor loss point" ; - double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; - fates_hydro_resid_node:units = "cm3/cm3" ; - fates_hydro_resid_node:long_name = "residual water conent" ; - double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; - fates_hydro_thetas_node:units = "cm3/cm3" ; - fates_hydro_thetas_node:long_name = "saturated water content" ; - double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; - fates_hydro_vg_alpha_node:units = "MPa-1" ; - fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; - double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; - fates_hydro_vg_m_node:units = "unitless" ; - fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; - 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_stoich_nitr(fates_plant_organs, fates_pft) ; - fates_stoich_nitr:units = "gN/gC" ; - fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; - double fates_stoich_phos(fates_plant_organs, fates_pft) ; - fates_stoich_phos:units = "gP/gC" ; - fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; - double fates_alloc_organ_id(fates_plant_organs) ; - fates_alloc_organ_id:units = "unitless" ; - fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; - double fates_hydro_htftype_node(fates_hydr_organs) ; - fates_hydro_htftype_node:units = "unitless" ; - fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; 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_history_coageclass_bin_edges(fates_history_coage_bins) ; - fates_history_coageclass_bin_edges:units = "years" ; - fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; - double fates_history_damage_bin_edges(fates_history_damage_bins) ; - fates_history_damage_bin_edges:units = "% crown loss" ; - fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; - double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; - fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; - fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; - double fates_turnover_leaf(fates_leafage_class, fates_pft) ; - fates_turnover_leaf:units = "yr" ; - fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; double fates_base_mr_20 ; fates_base_mr_20:units = "gC/gN/s" ; fates_base_mr_20:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; @@ -790,30 +793,24 @@ variables: fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; // global attributes: - :history = "This file was generated by BatchPatchParams.py:\n", - "CDL Base File = archive/api25.1.0_021623_fates_params_default.cdl\n", - "XML patch file = archive/api25.1.1_021623_pr931.xml" ; + :history = "This file was generated by BatchPatchParams.py:\nCDL Base File = archive/api24.1.0_101722_fates_params_default.cdl\nXML patch file = archive/api24.1.0_101722_patch_params.xml" ; data: - fates_hlm_pft_map = - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; + + fates_history_coageclass_bin_edges = 0, 5 ; + + fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; + + fates_history_damage_bin_edges = 0, 80 ; fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100 ; + fates_alloc_organ_id = 1, 2, 3, 6 ; + + fates_hydro_htftype_node = 1, 1, 1, 1 ; + fates_pftname = "broadleaf_evergreen_tropical_tree ", "needleleaf_evergreen_extratrop_tree ", @@ -828,6 +825,32 @@ data: "cool_c3_grass ", "c4_grass " ; + fates_hydro_organ_name = + "leaf ", + "stem ", + "transporting root ", + "absorbing root " ; + + fates_alloc_organ_name = + "leaf", + "fine root", + "sapwood", + "structure" ; + + fates_litterclass_name = + "twig ", + "small branch ", + "large branch ", + "trunk ", + "dead leaves ", + "live grass " ; + + 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, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 ; @@ -972,6 +995,18 @@ data: fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_cnp_turnover_nitr_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_turnover_phos_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_cnp_vmax_nh4 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; @@ -991,8 +1026,7 @@ data: fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_dev_arbitrary_pft = 1.756, 1.4995, 1.4995, 1.756, 1.756, 1.756, - 2.0749, 2.0749, 2.0749, 2.1956, 2.1956, _ ; + fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 ; @@ -1030,22 +1064,107 @@ data: fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5 ; - fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, - -1.5, -1.5, -1.5 ; + fates_hydro_avuln_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, - 0.333, 0.333, 0.333, 0.333, 0.333 ; + fates_hydro_epsil_node = + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, - 0.625, 0.625, 0.625, 0.625, 0.625 ; + fates_hydro_fcap_node = + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_kmax_node = + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; + + fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + -1.5, -1.5, -1.5 ; + + fates_hydro_p50_node = + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25 ; + + fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, + 0.333, 0.333, 0.333, 0.333, 0.333 ; + + fates_hydro_pinot_node = + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; + + fates_hydro_pitlp_node = + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + -1.67, -1.67, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; + + fates_hydro_resid_node = + 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; + + fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + 0.625, 0.625, 0.625, 0.625, 0.625 ; fates_hydro_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; + fates_hydro_thetas_node = + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; + + fates_hydro_vg_alpha_node = + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005 ; + + fates_hydro_vg_m_node = + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_hydro_vg_n_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_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, @@ -1071,6 +1190,9 @@ data: fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, 4.7, 2.2, 5.3, 1.6 ; + fates_leaf_vcmax25top = + 50, 62, 39, 61, 41, 58, 62, 54, 54, 78, 78, 78 ; + fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330 ; @@ -1080,6 +1202,9 @@ data: fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485 ; + fates_maintresp_atkinetal2017model_baserate = 1.756, 1.4995, 1.4995, 1.756, + 1.756, 1.756, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956, 0 ; + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; @@ -1199,6 +1324,25 @@ data: fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_stoich_nitr = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; + + fates_stoich_phos = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; + fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03 ; @@ -1217,6 +1361,9 @@ data: fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + fates_turnover_leaf = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_wood_density = 0.7, 0.4, 0.7, 0.53, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, @@ -1224,17 +1371,21 @@ data: fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; - fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; - - fates_litterclass_name = - "twig ", - "small branch ", - "large branch ", - "trunk ", - "dead leaves ", - "live grass " ; - - fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; + fates_hlm_pft_map = + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; @@ -1254,156 +1405,8 @@ data: fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; - fates_hydro_organ_name = - "leaf ", - "stem ", - "transporting root ", - "absorbing root " ; - - fates_alloc_organ_name = - "leaf", - "fine root", - "sapwood", - "structure" ; - - 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, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; - - fates_cnp_turnover_nitr_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_turnover_phos_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_hydro_avuln_node = - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 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_hydro_epsil_node = - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - - fates_hydro_fcap_node = - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, - 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_hydro_kmax_node = - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; - - fates_hydro_p50_node = - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25 ; - - fates_hydro_pinot_node = - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; - - fates_hydro_pitlp_node = - -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, - -1.67, -1.67, - -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, - -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, - -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; - - fates_hydro_resid_node = - 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, - 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - - fates_hydro_thetas_node = - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; - - fates_hydro_vg_alpha_node = - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005 ; - - fates_hydro_vg_m_node = - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_hydro_vg_n_node = - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 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_stoich_nitr = - 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, - 0.0047, 0.0047, 0.0047 ; - - fates_stoich_phos = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, - 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, - 0.00047, 0.00047, 0.00047, 0.00047 ; - - fates_alloc_organ_id = 1, 2, 3, 6 ; - - fates_hydro_htftype_node = 1, 1, 1, 1 ; - fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; - fates_history_coageclass_bin_edges = 0, 5 ; - - fates_history_damage_bin_edges = 0, 80 ; - - fates_leaf_vcmax25top = - 50, 62, 39, 61, 41, 58, 62, 54, 54, 78, 78, 78 ; - - fates_turnover_leaf = - 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - fates_base_mr_20 = 2.525e-06 ; fates_canopy_closure_thresh = 0.8 ; From 90bf6464729ef57d14fb7202f4599d1d3776fc46 Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Wed, 22 Feb 2023 16:05:27 -0700 Subject: [PATCH 529/852] cleaned up fix to cwd change --- biogeochem/FatesLitterMod.F90 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/biogeochem/FatesLitterMod.F90 b/biogeochem/FatesLitterMod.F90 index c19857473a..ddb7a7689b 100644 --- a/biogeochem/FatesLitterMod.F90 +++ b/biogeochem/FatesLitterMod.F90 @@ -463,9 +463,9 @@ subroutine adjust_SF_CWD_frac(dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) !pools, keeping the biomass proportions the same among the combustible classes. else if (dbh > sb_max_diam .and. dbh .le. lb_max_diam) then SF_val_CWD_frac_adj(ncwd) = 0.0 - SF_val_CWD_frac_adj(ncwd-1) = SF_val_CWD_frac(ncwd-1) / (1.0_r - SF_val_CWD_frac(ncwd) ) - SF_val_CWD_frac_adj(ncwd-2) = SF_val_CWD_frac(ncwd-2) / (1.0_r - SF_val_CWD_frac(ncwd) ) - SF_val_CWD_frac_adj(ncwd-3) = SF_val_CWD_frac(ncwd-3) / (1.0_r - SF_val_CWD_frac(ncwd) ) + SF_val_CWD_frac_adj(ncwd-1) = SF_val_CWD_frac(ncwd-1) / (1.0_r8 - SF_val_CWD_frac(ncwd) ) + SF_val_CWD_frac_adj(ncwd-2) = SF_val_CWD_frac(ncwd-2) / (1.0_r8 - SF_val_CWD_frac(ncwd) ) + SF_val_CWD_frac_adj(ncwd-3) = SF_val_CWD_frac(ncwd-3) / (1.0_r8 - SF_val_CWD_frac(ncwd) ) !When dbh is greater than the max size of a twig (1 hr) but less than or @@ -474,9 +474,9 @@ subroutine adjust_SF_CWD_frac(dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) else if (dbh > twig_max_diam .and. dbh .le. sb_max_diam) then SF_val_CWD_frac_adj(ncwd) = 0.0 SF_val_CWD_frac_adj(ncwd-1) = 0.0 - SF_val_CWD_frac_adj(ncwd-2) = SF_val_CWD_frac(ncwd-2) / (1.0_r - (SF_val_CWD_frac(ncwd) + & + SF_val_CWD_frac_adj(ncwd-2) = SF_val_CWD_frac(ncwd-2) / (1.0_r8 - (SF_val_CWD_frac(ncwd) + & SF_val_CWD_frac(ncwd-1))) - SF_val_CWD_frac_adj(ncwd-3) = SF_val_CWD_frac(ncwd-3) / (1.0_r - (SF_val_CWD_frac(ncwd) + & + SF_val_CWD_frac_adj(ncwd-3) = SF_val_CWD_frac(ncwd-3) / (1.0_r8 - (SF_val_CWD_frac(ncwd) + & SF_val_CWD_frac(ncwd-1))) !If dbh is less than or equal to the max size of a twig we send all From 457522b856fc8d8052081aa129aba3d31c34d6c4 Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Wed, 22 Feb 2023 16:09:56 -0700 Subject: [PATCH 530/852] flag --- main/EDMainMod.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 025969b07a..dc4775b833 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -185,6 +185,7 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) !FIX(SPM,032414) take this out. On startup these values are all zero and on restart it !zeros out values read in the restart file + write(fates_log(),*) 'cwd fix 02223' ! Zero turnover rates and growth diagnostics call ZeroAllocationRates(currentSite) From 3d56c69aa04f8cfc305504e3b3eec4cddb7c36cb Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Wed, 22 Feb 2023 15:44:12 -0800 Subject: [PATCH 531/852] Fix bug in net_c_uptake by leaf layer and pft history variable --- main/FatesHistoryInterfaceMod.F90 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 41e95896b7..56d1ce1a61 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -6618,12 +6618,12 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=2, ivar=ivar, initialize=initialize_variables, & index = ih_ts_net_uptake_si_cnlf) -call this%set_history_var(vname='FATES_NET_C_UPTAKE_CLLL', & +call this%set_history_var(vname='FATES_NET_C_UPTAKE_CLLLPF', & units='kg m-2 s-1', & - long='net carbon uptake in kg carbon per m2 per second by each canopy and leaf layer per unit ground area (i.e. divide by CROWNAREA_CLLL to make per leaf area)', & - use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & + long='net carbon uptake in kg carbon per m2 per second by each canopy and leaf layer and PFT per unit ground area (i.e. divide by CROWNAREA_CLLL to make per leaf area)', & + use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & hlms='CLM:ALM', upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_ts_net_uptake_si_cnlf) + index = ih_ts_net_uptake_si_cnlfpft) call this%set_history_var(vname='FATES_CROWNAREA_CLLL', units='m2 m-2', & long='total crown area that is occupied by leaves in each canopy and leaf layer', & From 397a574c380f5580b40df15f07e1f05e784151f2 Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Thu, 23 Feb 2023 11:41:01 -0700 Subject: [PATCH 532/852] removed flags --- main/EDMainMod.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index dc4775b833..025969b07a 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -185,7 +185,6 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) !FIX(SPM,032414) take this out. On startup these values are all zero and on restart it !zeros out values read in the restart file - write(fates_log(),*) 'cwd fix 02223' ! Zero turnover rates and growth diagnostics call ZeroAllocationRates(currentSite) From 10d686a7a5d0e60cb7d297b7a5e3533ea910454d Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 23 Feb 2023 15:29:39 -0800 Subject: [PATCH 533/852] Update xml patch file for api25.1.1 This commit creates two xml patch files to facilitate this update. The file names are to be applied in the order denoted by the number suffix on the xml file name. The first file is used to create the new Atkin parameter as well as update the mortality rate typo. The UpdateAPI.py tool is modified to allow for variables to be added that are undefined. The second file updates the new Atkin parameter using BatchPatchParams.py. The update intentionally leaves the final pft as undefined. Modifying and creating new variables with mixed values, in this case leaving one undefined, is what necessitated the update to the tooling and the sequential tool calls. --- ...pr931.xml => api25.1.1_021623_pr931-1.xml} | 9 +- .../archive/api25.1.1_021623_pr931-2.xml | 12 + parameter_files/fates_params_default.cdl | 530 +++++++++--------- tools/UpdateParamAPI.py | 53 +- 4 files changed, 313 insertions(+), 291 deletions(-) rename parameter_files/archive/{api25.1.1_021623_pr931.xml => api25.1.1_021623_pr931-1.xml} (71%) create mode 100644 parameter_files/archive/api25.1.1_021623_pr931-2.xml diff --git a/parameter_files/archive/api25.1.1_021623_pr931.xml b/parameter_files/archive/api25.1.1_021623_pr931-1.xml similarity index 71% rename from parameter_files/archive/api25.1.1_021623_pr931.xml rename to parameter_files/archive/api25.1.1_021623_pr931-1.xml index ba22a0dffa..9d4e998aa7 100644 --- a/parameter_files/archive/api25.1.1_021623_pr931.xml +++ b/parameter_files/archive/api25.1.1_021623_pr931-1.xml @@ -1,8 +1,13 @@ - + + + + + + - - - - - - - - - - - - archive/api25.1.0_021623_fates_params_default.cdl - fates_params_default.cdl - 1,2,3,4,5,6,7,8,9,10,11,12 - - - fates_maintresp_atkinetal2017model_baserate - fates_pft - umol CO2/m^2/s - Leaf maintenance respiration base rate parameter (r0) per Atkin et al 2017 - - - - 2.525e-06 - - - diff --git a/parameter_files/archive/api25.1.1_021623_pr931-2.xml b/parameter_files/archive/api25.1.1_021623_pr931-2.xml deleted file mode 100644 index eb867f5d63..0000000000 --- a/parameter_files/archive/api25.1.1_021623_pr931-2.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - This is PR 931 - fates_params_default.cdl - fates_params_default.cdl - 1,2,3,4,5,6,7,8,9,10,11,12 - - - 1.7560, 1.4995, 1.4995, 1.7560, 1.7560, 1.7560, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956 - - - diff --git a/parameter_files/archive/api25.1.1_021623_pr931.xml b/parameter_files/archive/api25.1.1_021623_pr931.xml new file mode 100644 index 0000000000..2315fbef8c --- /dev/null +++ b/parameter_files/archive/api25.1.1_021623_pr931.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + archive/api25.1.0_021623_fates_params_default.cdl + fates_params_default.cdl + 1,2,3,4,5,6,7,8,9,10,11,12 + + + fates_maintresp_leaf_atkin2017_baserate + fates_pft + umol CO2/m^2/s + Leaf maintenance respiration base rate parameter (r0) per Atkin et al 2017 + 1.7560, 1.4995, 1.4995, 1.7560, 1.7560, 1.7560, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956, 2.1956 + + + fates_maintresp_leaf_ryan1991_baserate + fates_pft + gC/gN/s + Leaf maintenance respiration base rate per Ryan et al 1991 + 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06 + + + fates_maintresp_nonleaf_baserate + 2.525e-06 + + + fates_maintresp_leaf_model + + + diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 988e9785e2..958fb46241 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1,4 +1,4 @@ -netcdf fates_params_default { +netcdf tmp { dimensions: fates_NCWD = 4 ; fates_history_age_bins = 7 ; @@ -377,9 +377,12 @@ variables: double fates_leaf_vcmaxse(fates_pft) ; fates_leaf_vcmaxse:units = "J/mol/K" ; fates_leaf_vcmaxse:long_name = "entropy term for vcmax" ; - double fates_maintresp_atkinetal2017model_baserate(fates_pft) ; - fates_maintresp_atkinetal2017model_baserate:units = "umol CO2/m^2/s" ; - fates_maintresp_atkinetal2017model_baserate:long_name = "Leaf maintenance respiration base rate parameter (r0) per Atkin et al 2017" ; + double fates_maintresp_leaf_atkin2017_baserate(fates_pft) ; + fates_maintresp_leaf_atkin2017_baserate:units = "umol CO2/m^2/s" ; + fates_maintresp_leaf_atkin2017_baserate:long_name = "Leaf maintenance respiration base rate parameter (r0) per Atkin et al 2017" ; + double fates_maintresp_leaf_ryan1991_baserate(fates_pft) ; + fates_maintresp_leaf_ryan1991_baserate:units = "gC/gN/s" ; + fates_maintresp_leaf_ryan1991_baserate:long_name = "Leaf maintenance respiration base rate per Ryan et al 1991" ; double fates_maintresp_reduction_curvature(fates_pft) ; fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; @@ -584,9 +587,6 @@ 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_base_mr_20 ; - fates_base_mr_20:units = "gC/gN/s" ; - fates_base_mr_20:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; 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" ; @@ -722,9 +722,12 @@ variables: double fates_leaf_theta_cj_c4 ; fates_leaf_theta_cj_c4:units = "unitless" ; fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; - double fates_maintresp_model ; - fates_maintresp_model:units = "unitless" ; - fates_maintresp_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991) (NOT USED)" ; + double fates_maintresp_leaf_model ; + fates_maintresp_leaf_model:units = "unitless" ; + fates_maintresp_leaf_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991) (NOT USED)" ; + double fates_maintresp_nonleaf_baserate ; + fates_maintresp_nonleaf_baserate:units = "gC/gN/s" ; + fates_maintresp_nonleaf_baserate:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; double fates_maxcohort ; fates_maxcohort:units = "count" ; fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; @@ -793,7 +796,7 @@ variables: fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; // global attributes: - :history = "This file was generated by BatchPatchParams.py:\nCDL Base File = fates_params_default.cdl\nXML patch file = archive/api25.1.1_021623_pr931-2.xml" ; + :history = "This file was generated by BatchPatchParams.py:\nCDL Base File = archive/api24.1.0_101722_fates_params_default.cdl\nXML patch file = archive/api24.1.0_101722_patch_params.xml" ; data: fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; @@ -1202,8 +1205,12 @@ data: fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485 ; - fates_maintresp_atkinetal2017model_baserate = 1.756, 1.4995, 1.4995, 1.756, - 1.756, 1.756, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956, _ ; + fates_maintresp_leaf_atkin2017_baserate = 1.756, 1.4995, 1.4995, 1.756, + 1.756, 1.756, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956, 2.1956 ; + + fates_maintresp_leaf_ryan1991_baserate = 2.525e-06, 2.525e-06, 2.525e-06, + 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, + 2.525e-06, 2.525e-06, 2.525e-06 ; fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; @@ -1407,8 +1414,6 @@ data: fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; - fates_base_mr_20 = 2.525e-06 ; - fates_canopy_closure_thresh = 0.8 ; fates_cnp_eca_plant_escalar = 1.25e-05 ; @@ -1499,7 +1504,9 @@ data: fates_leaf_theta_cj_c4 = 0.999 ; - fates_maintresp_model = 1 ; + fates_maintresp_leaf_model = 1 ; + + fates_maintresp_nonleaf_baserate = 2.525e-06 ; fates_maxcohort = 100 ; From aa0375db25e7c8807f969341b076577140e2da8f Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 27 Feb 2023 17:18:22 -0800 Subject: [PATCH 541/852] fix default param file name --- 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 958fb46241..7cf0fe3135 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1,4 +1,4 @@ -netcdf tmp { +netcdf fates_params_default { dimensions: fates_NCWD = 4 ; fates_history_age_bins = 7 ; From 59a865f2e181acab7a67822e79d6e527fbaa3589 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 27 Feb 2023 17:21:55 -0800 Subject: [PATCH 542/852] fix leaf model name assignment --- main/EDParamsMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 14db66805b..34e638d4e6 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -95,7 +95,7 @@ module EDParamsMod character(len=param_string_length),parameter,public :: ED_name_photo_temp_acclim_timescale = "fates_leaf_photo_temp_acclim_timescale" character(len=param_string_length),parameter,public :: name_photo_tempsens_model = "fates_leaf_photo_tempsens_model" - character(len=param_string_length),parameter,public :: name_maintresp_model = "fates_maintresp_model" + character(len=param_string_length),parameter,public :: name_maintresp_model = "fates_maintresp_leaf_model" character(len=param_string_length),parameter,public :: ED_name_hydr_htftype_node = "fates_hydro_htftype_node" character(len=param_string_length),parameter,public :: ED_name_mort_disturb_frac = "fates_mort_disturb_frac" character(len=param_string_length),parameter,public :: ED_name_comp_excln = "fates_comp_excln" From 0f011ed361f9d323a3ff670a2a11bde229c25fc3 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 28 Feb 2023 08:52:48 -0500 Subject: [PATCH 543/852] Restart albedo fix --- main/FatesRestartInterfaceMod.F90 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 6750308b6c..65e67c7311 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -3447,10 +3447,8 @@ subroutine update_3dpatch_radiation(this, nsites, sites, bc_out) bc_out(s)%fabi_parb(ifp,:) = 0.0_r8 do ib = 1,hlm_numSWb - ! REQUIRES A FIX HERE albd vs albi - bc_out(s)%albd_parb(ifp,ib) = currentPatch%gnd_alb_dir(ib) - bc_out(s)%albd_parb(ifp,ib) = currentPatch%gnd_alb_dif(ib) + bc_out(s)%albi_parb(ifp,ib) = currentPatch%gnd_alb_dif(ib) bc_out(s)%ftdd_parb(ifp,ib)= 1.0_r8 bc_out(s)%ftid_parb(ifp,ib)= 1.0_r8 bc_out(s)%ftii_parb(ifp,ib)= 1.0_r8 From 75372955e27e53a70978afad955811d8db7a03eb Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 28 Feb 2023 08:56:50 -0500 Subject: [PATCH 544/852] Reverting bug-fix on restart bg albedo, moved to other PR --- main/FatesRestartInterfaceMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index a9cc07e914..e1e64252b5 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -3463,7 +3463,7 @@ subroutine update_3dpatch_radiation(this, nsites, sites, bc_out) do ib = 1,hlm_numSWb bc_out(s)%albd_parb(ifp,ib) = currentPatch%gnd_alb_dir(ib) - bc_out(s)%albi_parb(ifp,ib) = currentPatch%gnd_alb_dif(ib) + bc_out(s)%albd_parb(ifp,ib) = currentPatch%gnd_alb_dif(ib) bc_out(s)%ftdd_parb(ifp,ib)= 1.0_r8 bc_out(s)%ftid_parb(ifp,ib)= 1.0_r8 bc_out(s)%ftii_parb(ifp,ib)= 1.0_r8 From 2395e6f24bb8ccec0a4d66cf16ad4744c1536f61 Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Tue, 28 Feb 2023 12:00:25 -0800 Subject: [PATCH 545/852] Incrase nlevleaf to prevent errors from vai param updates --- main/EDTypesMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index dcc6ea7bc6..e7d4f337b7 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -54,7 +54,7 @@ module EDTypesMod integer, parameter, public :: idiffuse = 2 ! This is the array index for diffuse radiation ! parameters that govern the VAI (LAI+SAI) bins used in radiative transfer code - integer, parameter, public :: nlevleaf = 30 ! number of leaf+stem layers in canopy layer + integer, parameter, public :: nlevleaf = 36 ! number of leaf+stem layers in canopy layer real(r8), public :: dinc_vai(nlevleaf) = fates_unset_r8 ! VAI bin widths array real(r8), public :: dlower_vai(nlevleaf) = fates_unset_r8 ! lower edges of VAI bins From a453cbacf1620ea1fcfd9a6140f1b456967c9a5b Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 28 Feb 2023 16:14:02 -0800 Subject: [PATCH 546/852] Add luh2 module and conda environment yaml file --- tools/conda-luh2.yml | 10 ++++++++++ tools/luh2.py | 23 +++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 tools/conda-luh2.yml create mode 100644 tools/luh2.py diff --git a/tools/conda-luh2.yml b/tools/conda-luh2.yml new file mode 100644 index 0000000000..a0f1dea53f --- /dev/null +++ b/tools/conda-luh2.yml @@ -0,0 +1,10 @@ +name: luh2 +channels: + - conda-forge + - defaults +dependencies: + - python=3.7.9 + - xarray + - netcdf4 + - scipy +prefix: /home/glemieux/local/conda/miniconda3/envs/luh2 diff --git a/tools/luh2.py b/tools/luh2.py new file mode 100644 index 0000000000..70d40c6a1f --- /dev/null +++ b/tools/luh2.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +# +import xarray as xr +import pynco + +def importdata(inputarg): + + # Open files + # Check to see if a ValueError is raised which is likely due + # to the LUH2 time units being undecodable by cftime module + try: + ds = xr.open_dataset(inputarg) + except ValueError as err: + print("ValueError:", err) + errmsg = "User direction: If error is due to units being 'years since ...' " \ + "update the input data file to change to 'common_years since...'. " \ + "This can be done using the NCO tool `ncatted`." + print() + print(errmsg) + # exit(2) + +# Close files +# management_ds.close() From b324212f5423fe7b147b2e942e235473531d5f45 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 1 Mar 2023 15:25:23 -0500 Subject: [PATCH 547/852] Keeping N litter flux bc_outs on for all modes, which suits clm --- main/FatesInterfaceMod.F90 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index c322fc5a6a..5286626549 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -313,6 +313,9 @@ subroutine zero_bcs(fates,s) fates%bc_out(s)%litt_flux_cel_c_si(:) = 0._r8 fates%bc_out(s)%litt_flux_lig_c_si(:) = 0._r8 fates%bc_out(s)%litt_flux_lab_c_si(:) = 0._r8 + fates%bc_out(s)%litt_flux_cel_n_si(:) = 0._r8 + fates%bc_out(s)%litt_flux_lig_n_si(:) = 0._r8 + fates%bc_out(s)%litt_flux_lab_n_si(:) = 0._r8 case(prt_cnp_flex_allom_hyp) fates%bc_in(s)%plant_nh4_uptake_flux(:,:) = 0._r8 @@ -636,8 +639,10 @@ subroutine allocate_bcout(bc_out, nlevsoil_in, nlevdecomp_in) allocate(bc_out%litt_flux_cel_c_si(nlevdecomp_in)) allocate(bc_out%litt_flux_lig_c_si(nlevdecomp_in)) allocate(bc_out%litt_flux_lab_c_si(nlevdecomp_in)) + allocate(bc_out%litt_flux_cel_n_si(nlevdecomp_in)) + allocate(bc_out%litt_flux_lig_n_si(nlevdecomp_in)) + allocate(bc_out%litt_flux_lab_n_si(nlevdecomp_in)) case(prt_cnp_flex_allom_hyp) - allocate(bc_out%litt_flux_cel_c_si(nlevdecomp_in)) allocate(bc_out%litt_flux_lig_c_si(nlevdecomp_in)) From fda4aff84f0d0c0173e39ccfaa808255dc5c7b17 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 1 Mar 2023 13:57:52 -0800 Subject: [PATCH 548/852] Add function to update luh2 time units --- tools/luh2.py | 46 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/tools/luh2.py b/tools/luh2.py index 70d40c6a1f..d86d5800ba 100644 --- a/tools/luh2.py +++ b/tools/luh2.py @@ -1,23 +1,59 @@ #!/usr/bin/env python3 -# + +import re import xarray as xr -import pynco +from nco import Nco +from nco.custom import Atted -def importdata(inputarg): +# Import luh2 data +def importdata(inputarg,datasetout): # Open files # Check to see if a ValueError is raised which is likely due # to the LUH2 time units being undecodable by cftime module try: - ds = xr.open_dataset(inputarg) + datasetout = xr.open_dataset(inputarg) except ValueError as err: print("ValueError:", err) errmsg = "User direction: If error is due to units being 'years since ...' " \ "update the input data file to change to 'common_years since...'. " \ - "This can be done using the NCO tool `ncatted`." + "This can be done using the luh2.attribupdate function." print() print(errmsg) # exit(2) +# Modify the luh2 metadata to enable xarray to read in data +# This issue here is that the luh2 time units start prior to +# +def attribupdate(inputarg,outputarg): + + nco = Nco() + + # Get the 'time:units' string from the input using ncks + timeunitstr = nco.ncks(input=inputarg,variable="time",options=["-m"]).decode() + + # Grab the units string and replace "years" with "common_years" + substr = re.search('time:units.*".*"',timeunitstr) + newstr = substr.group().replace("time:units = \"years","\"common_years") + + # Use ncatted to update the time units + att = "units" + var = "time" + att_type = "c" + opts = [" -a {0},{1},o,{2},{3}".format(att, var, att_type, newstr)] + nco.ncatted(input=inputarg, output=outputarg, options=opts) + + # The following is fixed with PR #62 for pynco but isn't in that latest update yet + # on conda + # nco.ncatted(input=inputarg,output=outputarg,options=[ + # Atted(mode="overwrite", + # att_name="units", + # var_name="time", + # value=newstr + # stype="c" + # ), + # ]) + + # Close files # management_ds.close() From 5c97f6af5b8610d3ad9ca7833e964b963b71d5d1 Mon Sep 17 00:00:00 2001 From: ckoven Date: Wed, 1 Mar 2023 15:29:54 -0700 Subject: [PATCH 549/852] reverted C3/C4 logic to now use same model for all PFTs and same Atkin base rate for C3 and C4 --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 113 ++++++--------------- parameter_files/fates_params_default.cdl | 2 +- 2 files changed, 33 insertions(+), 82 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 4fd45a5ee4..585084e8d0 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -525,41 +525,31 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! Part VII: Calculate dark respiration (leaf maintenance) for this layer - ! C3 plants - if_c3: if ( nint(EDPftvarcon_inst%c3psn(ft)) == 1 ) then - select case (maintresp_model) + select case (maintresp_model) - case (lmrmodel_ryan_1991) + case (lmrmodel_ryan_1991) - call LeafLayerMaintenanceRespiration_Ryan_1991( lnc_top, & ! in - nscaler, & ! in - bc_in(s)%t_veg_pa(ifp), & ! in - lmr_z(iv,ft,cl)) ! out - - case (lmrmodel_atkin_etal_2017) - - call LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & ! in - nscaler, & ! in - ft, & ! in - bc_in(s)%t_veg_pa(ifp), & ! in - currentPatch%tveg_lpa%GetMean(), & ! in - lmr_z(iv,ft,cl)) ! out + call LeafLayerMaintenanceRespiration_Ryan_1991( lnc_top, & ! in + nscaler, & ! in + ft, & ! in + bc_in(s)%t_veg_pa(ifp), & ! in + lmr_z(iv,ft,cl)) ! out - case default + case (lmrmodel_atkin_etal_2017) - write (fates_log(),*)'error, incorrect leaf respiration model specified' - call endrun(msg=errMsg(sourcefile, __LINE__)) + call LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & ! in + nscaler, & ! in + ft, & ! in + bc_in(s)%t_veg_pa(ifp), & ! in + currentPatch%tveg_lpa%GetMean(), & ! in + lmr_z(iv,ft,cl)) ! out - end select + case default - else ! C4 plants + write (fates_log(),*)'error, incorrect leaf respiration model specified' + call endrun(msg=errMsg(sourcefile, __LINE__)) - call LeafLayerMaintenanceRespiration_C4( lnc_top, & ! in - nscaler, & ! in - bc_in(s)%t_veg_pa(ifp), & ! in - lmr_z(iv,ft,cl)) ! out - - endif if_c3 + end select ! Part VII: Calculate (1) maximum rate of carboxylation (vcmax), ! (2) maximum electron transport rate, (3) triose phosphate @@ -2072,7 +2062,8 @@ end subroutine GetCanopyGasParameters ! ==================================================================================== subroutine LeafLayerMaintenanceRespiration_Ryan_1991(lnc_top, & - nscaler, & + nscaler, & + ft, & veg_tempk, & lmr) @@ -2090,8 +2081,8 @@ subroutine LeafLayerMaintenanceRespiration_Ryan_1991(lnc_top, & ! Which is the default value of ED_val_base_mr_20 ! Arguments - real(r8), intent(in) :: lnc_top ! Leaf nitrogen content per unit area at canopy top [gN/m2] - + real(r8), intent(in) :: lnc_top ! Leaf nitrogen content per unit area at canopy top [gN/m2] + 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 real(r8), intent(out) :: lmr ! Leaf Maintenance Respiration (umol CO2/m**2/s) @@ -2115,8 +2106,15 @@ subroutine LeafLayerMaintenanceRespiration_Ryan_1991(lnc_top, & ! ---------------------------------------------------------------------------------- lmr25 = lmr25top * nscaler - lmr = lmr25 * ft1_f(veg_tempk, lmrha) * & - fth_f(veg_tempk, lmrhd, lmrse, lmrc) + if (nint(EDPftvarcon_inst%c3psn(ft)) /= 1) then + ! temperature sensitivity of C3 plants + lmr = lmr25 * ft1_f(veg_tempk, lmrha) * & + fth_f(veg_tempk, lmrhd, lmrse, lmrc) + else + ! temperature sensitivity of C4 plants + lmr = lmr25 * 2._r8**((veg_tempk-(tfrz+25._r8))/10._r8) + lmr = lmr / (1._r8 + exp( 1.3_r8*(veg_tempk-(tfrz+55._r8)) )) + endif ! Any hydrodynamic limitations could go here, currently none ! lmr = lmr * (nothing) @@ -2166,6 +2164,7 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & ! Needle-leaf trees 1.4995 ! Shrubs 2.0749 ! C3 herbs/grasses 2.1956 + ! In the absence of better information, we use the same value for C4 grasses as C3 grasses. ! note that this code uses the relationship between leaf N and respiration from Atkin et al ! for the top of the canopy, but then assumes proportionality with N through the canopy. @@ -2181,54 +2180,6 @@ end subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017 ! ==================================================================================== -subroutine LeafLayerMaintenanceRespiration_C4(lnc_top, & - nscaler, & - veg_tempk, & - lmr) - - use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm - use FatesConstantsMod, only : umolC_to_kgC - use FatesConstantsMod, only : g_per_kg - use EDPftvarcon , only : EDPftvarcon_inst - - ! ----------------------------------------------------------------------- - ! Base maintenance respiration rate for plant tissues base_mr_20 - ! M. Ryan, 1991. Effects of climate change on plant respiration. - ! Ecological Applications, 1(2), 157-167. - ! Original expression is br = 0.0106 molC/(molN h) - ! Conversion by molecular weights of C and N gives 2.525e-6 gC/(gN s) - ! Which is the default value of ED_val_base_mr_20 - - ! This contains the original C4 dark respiraiton logic from CLM, which uses a different - ! temperature scaling than for C3 plants - - ! Arguments - real(r8), intent(in) :: lnc_top ! Leaf nitrogen content per unit area at canopy top [gN/m2] - - real(r8), intent(in) :: nscaler ! Scale for leaf nitrogen profile - real(r8), intent(in) :: veg_tempk ! vegetation temperature - real(r8), intent(out) :: lmr ! Leaf Maintenance Respiration (umol CO2/m**2/s) - - ! Locals - real(r8) :: lmr25 ! leaf layer: leaf maintenance respiration rate at 25C (umol CO2/m**2/s) - real(r8) :: lmr25top ! canopy top leaf maint resp rate at 25C for this pft (umol CO2/m**2/s) - - - lmr25top = ED_val_base_mr_20 * (1.5_r8 ** ((25._r8 - 20._r8)/10._r8)) - lmr25top = lmr25top * lnc_top / (umolC_to_kgC * g_per_kg) - - - ! Part I: Leaf Maintenance respiration: umol CO2 / m**2 [leaf] / s - ! ---------------------------------------------------------------------------------- - lmr25 = lmr25top * nscaler - - lmr = lmr25 * 2._r8**((veg_tempk-(tfrz+25._r8))/10._r8) - lmr = lmr / (1._r8 + exp( 1.3_r8*(veg_tempk-(tfrz+55._r8)) )) - -end subroutine LeafLayerMaintenanceRespiration_C4 - -! ==================================================================================== - subroutine LeafLayerBiophysicalRates( parsun_lsl, & ft, & vcmax25top_ft, & diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 988e9785e2..347d78a943 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1203,7 +1203,7 @@ data: 485 ; fates_maintresp_atkinetal2017model_baserate = 1.756, 1.4995, 1.4995, 1.756, - 1.756, 1.756, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956, _ ; + 1.756, 1.756, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956, 2.1956 ; fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; From c7871a913d27212a69ae020f14111951b36338e1 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 1 Mar 2023 14:51:06 -0800 Subject: [PATCH 550/852] Update conda environment for luh2 tools --- tools/conda-luh2.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/conda-luh2.yml b/tools/conda-luh2.yml index a0f1dea53f..7ac42e9f24 100644 --- a/tools/conda-luh2.yml +++ b/tools/conda-luh2.yml @@ -7,4 +7,6 @@ dependencies: - xarray - netcdf4 - scipy + - nco + - pynco prefix: /home/glemieux/local/conda/miniconda3/envs/luh2 From ac8d58fb9c48500beff7be75ef739d53d4a4ad01 Mon Sep 17 00:00:00 2001 From: ckoven Date: Wed, 1 Mar 2023 16:24:37 -0700 Subject: [PATCH 551/852] fixed bug from merge --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index eec9761278..2e8bc0b3d6 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -525,7 +525,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! Part VII: Calculate dark respiration (leaf maintenance) for this layer - select case (maintresp_model) + select case (maintresp_leaf_model) case (lmrmodel_ryan_1991) From f464b7bdb544caaa6f3576313be751d1b754da62 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 2 Mar 2023 09:10:44 -0800 Subject: [PATCH 552/852] Adding functionality notes --- tools/luh2.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tools/luh2.py b/tools/luh2.py index d86d5800ba..e3dfb9be8c 100644 --- a/tools/luh2.py +++ b/tools/luh2.py @@ -6,7 +6,7 @@ from nco.custom import Atted # Import luh2 data -def importdata(inputarg,datasetout): +def importdata(inputarg): # Open files # Check to see if a ValueError is raised which is likely due @@ -22,6 +22,8 @@ def importdata(inputarg,datasetout): print(errmsg) # exit(2) + return(datasetout) + # Modify the luh2 metadata to enable xarray to read in data # This issue here is that the luh2 time units start prior to # @@ -54,6 +56,14 @@ def attribupdate(inputarg,outputarg): # ), # ]) - -# Close files -# management_ds.close() +# General functionality needed +# - collect data for specific user-defined time period +# - collect subset of the data variables (e.g. pasture, rangeland, etc) +# - write the subset to the necessary format to pass to regridding tools +# - This may need to be specific to the particular hlm tooling +# - call regridding tooling in hlm model +# - this will need to point at existing mapping data files, which are external to hlm +# - this may need a new mksurf_xxxx module if it can't conform to existing modules due +# to needing to use new fields +# future functionality: +# - importdata function for aforestation and other data to add to luh2 data From 49743687c047402171b6cc69d6b154d63b183c52 Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Thu, 2 Mar 2023 12:20:54 -0800 Subject: [PATCH 553/852] Remove non-dbh init changes --- biogeochem/FatesAllometryMod.F90 | 1 - main/EDInitMod.F90 | 6 ++---- main/EDTypesMod.F90 | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index 0c94d71f92..a6d7126e4a 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -116,7 +116,6 @@ module FatesAllometryMod public :: bfineroot ! Generic actual fine root biomass wrapper public :: bdead_allom ! Generic bdead wrapper public :: carea_allom ! Generic crown area wrapper - public :: carea_2pwr ! crown area of single plant public :: bstore_allom ! Generic maximum storage carbon wrapper public :: decay_coeff_kn public :: ForceDBH ! Method to set DBH to sync with structure diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index bc798bd0e1..25fe416337 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -817,12 +817,11 @@ subroutine init_cohorts( site_in, patch_in, bc_in) temp_cohort%pft = pft temp_cohort%l2fr = prt_params%allom_l2fr(pft) temp_cohort%canopy_trim = 1.0_r8 - ! Assume no damage to begin with - temp_cohort%crowndamage = 1 + temp_cohort%crowndamage = 1 ! Assume no damage to begin with if(EDPftvarcon_inst%initd(pft)>nearzero) then ! interpret as initial density and calculate diameter - + temp_cohort%n = EDPftvarcon_inst%initd(pft) * patch_in%area if(hlm_use_nocomp.eq.itrue)then !in nocomp mode we only have one PFT per patch ! as opposed to numpft's. So we should up the initial density ! to compensate (otherwise runs are very hard to compare) @@ -842,7 +841,6 @@ subroutine init_cohorts( site_in, patch_in, bc_in) else temp_cohort%hite = EDPftvarcon_inst%hgt_min(pft) - ! Calculate the plant diameter from height call h2d_allom(temp_cohort%hite,pft,temp_cohort%dbh) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index e7d4f337b7..dcc6ea7bc6 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -54,7 +54,7 @@ module EDTypesMod integer, parameter, public :: idiffuse = 2 ! This is the array index for diffuse radiation ! parameters that govern the VAI (LAI+SAI) bins used in radiative transfer code - integer, parameter, public :: nlevleaf = 36 ! number of leaf+stem layers in canopy layer + integer, parameter, public :: nlevleaf = 30 ! number of leaf+stem layers in canopy layer real(r8), public :: dinc_vai(nlevleaf) = fates_unset_r8 ! VAI bin widths array real(r8), public :: dlower_vai(nlevleaf) = fates_unset_r8 ! lower edges of VAI bins From 31212302e45863fa0f816c066c3987e56db17dba Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Thu, 2 Mar 2023 12:55:37 -0800 Subject: [PATCH 554/852] Revert "Fix bug in net_c_uptake by leaf layer and pft history variable" This reverts commit 3d56c69aa04f8cfc305504e3b3eec4cddb7c36cb. --- main/FatesHistoryInterfaceMod.F90 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 56d1ce1a61..41e95896b7 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -6618,12 +6618,12 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=2, ivar=ivar, initialize=initialize_variables, & index = ih_ts_net_uptake_si_cnlf) -call this%set_history_var(vname='FATES_NET_C_UPTAKE_CLLLPF', & +call this%set_history_var(vname='FATES_NET_C_UPTAKE_CLLL', & units='kg m-2 s-1', & - long='net carbon uptake in kg carbon per m2 per second by each canopy and leaf layer and PFT per unit ground area (i.e. divide by CROWNAREA_CLLL to make per leaf area)', & - use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & + long='net carbon uptake in kg carbon per m2 per second by each canopy and leaf layer per unit ground area (i.e. divide by CROWNAREA_CLLL to make per leaf area)', & + use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & hlms='CLM:ALM', upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_ts_net_uptake_si_cnlfpft) + index = ih_ts_net_uptake_si_cnlf) call this%set_history_var(vname='FATES_CROWNAREA_CLLL', units='m2 m-2', & long='total crown area that is occupied by leaves in each canopy and leaf layer', & From db3107ac5b881f7a0485b69c12eb382ef984d98c Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Thu, 2 Mar 2023 13:00:52 -0800 Subject: [PATCH 555/852] Remove history variable not part of this PR --- main/FatesHistoryInterfaceMod.F90 | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 41e95896b7..e955a96123 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -687,7 +687,6 @@ module FatesHistoryInterfaceMod integer :: ih_fabi_sha_si_cnlfpft integer :: ih_parprof_dir_si_cnlfpft integer :: ih_parprof_dif_si_cnlfpft - integer :: ih_ts_net_uptake_si_cnlfpft ! indices to site x crown damage variables ! site x crown damage x pft x sizeclass @@ -4403,7 +4402,6 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) hio_parsun_z_si_cnlf => this%hvars(ih_parsun_z_si_cnlf)%r82d, & hio_parsha_z_si_cnlf => this%hvars(ih_parsha_z_si_cnlf)%r82d, & hio_ts_net_uptake_si_cnlf => this%hvars(ih_ts_net_uptake_si_cnlf)%r82d, & - hio_ts_net_uptake_si_cnlfpft => this%hvars(ih_ts_net_uptake_si_cnlfpft)%r82d, & hio_parsun_z_si_cnlfpft => this%hvars(ih_parsun_z_si_cnlfpft)%r82d, & hio_parsha_z_si_cnlfpft => this%hvars(ih_parsha_z_si_cnlfpft)%r82d, & hio_laisun_z_si_cnlf => this%hvars(ih_laisun_z_si_cnlf)%r82d, & @@ -4641,13 +4639,6 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) hio_ts_net_uptake_si_cnlf(io_si, cnlf_indx) = hio_ts_net_uptake_si_cnlf(io_si, cnlf_indx) + & ccohort%ts_net_uptake(ileaf) * per_dt_tstep * ccohort%c_area * area_inv - do ipft=1,numpft - ! calculate where we are on multiplexed dimensions - cnlfpft_indx = ileaf + (ican-1) * nlevleaf + (ipft-1) * nlevleaf * nclmax - hio_ts_net_uptake_si_cnlfpft(io_si, cnlfpft_indx) = & - hio_ts_net_uptake_si_cnlfpft(io_si, cnlfpft_indx) + & - ccohort%ts_net_uptake(ileaf) * per_dt_tstep * ccohort%c_area * area_inv - end do end do ccohort => ccohort%taller @@ -6618,13 +6609,6 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=2, ivar=ivar, initialize=initialize_variables, & index = ih_ts_net_uptake_si_cnlf) -call this%set_history_var(vname='FATES_NET_C_UPTAKE_CLLL', & - units='kg m-2 s-1', & - long='net carbon uptake in kg carbon per m2 per second by each canopy and leaf layer per unit ground area (i.e. divide by CROWNAREA_CLLL to make per leaf area)', & - use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & - hlms='CLM:ALM', upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_ts_net_uptake_si_cnlf) - call this%set_history_var(vname='FATES_CROWNAREA_CLLL', units='m2 m-2', & long='total crown area that is occupied by leaves in each canopy and leaf layer', & use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & From 3816fe139037d6968131b02357bbcf19748c4f26 Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Thu, 2 Mar 2023 13:07:57 -0800 Subject: [PATCH 556/852] Tidying --- main/EDTypesMod.F90 | 2 +- main/FatesHistoryInterfaceMod.F90 | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index e7d4f337b7..dcc6ea7bc6 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -54,7 +54,7 @@ module EDTypesMod integer, parameter, public :: idiffuse = 2 ! This is the array index for diffuse radiation ! parameters that govern the VAI (LAI+SAI) bins used in radiative transfer code - integer, parameter, public :: nlevleaf = 36 ! number of leaf+stem layers in canopy layer + integer, parameter, public :: nlevleaf = 30 ! number of leaf+stem layers in canopy layer real(r8), public :: dinc_vai(nlevleaf) = fates_unset_r8 ! VAI bin widths array real(r8), public :: dlower_vai(nlevleaf) = fates_unset_r8 ! lower edges of VAI bins diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index e955a96123..f9f99300f9 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -4631,14 +4631,13 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) endif end associate endif - + !!! canopy leaf carbon balance ican = ccohort%canopy_layer do ileaf=1,ccohort%nv cnlf_indx = ileaf + (ican-1) * nlevleaf hio_ts_net_uptake_si_cnlf(io_si, cnlf_indx) = hio_ts_net_uptake_si_cnlf(io_si, cnlf_indx) + & ccohort%ts_net_uptake(ileaf) * per_dt_tstep * ccohort%c_area * area_inv - end do ccohort => ccohort%taller From 188a4fca65264f636ce48c47881b9309a7c5982b Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Thu, 2 Mar 2023 13:35:09 -0800 Subject: [PATCH 557/852] Add errors if user tries to use dbh initialisation outside of nocomp mode --- main/EDInitMod.F90 | 22 +++++++++++++--------- parameter_files/fates_params_default.cdl | 2 +- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index b7fb45ef57..4f77c55ad7 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -849,18 +849,22 @@ subroutine init_cohorts( site_in, patch_in, bc_in) endif ! sp mode else ! interpret as initial diameter and calculate density + if(hlm_use_nocomp .eq. itrue)then + temp_cohort%dbh = abs(EDPftvarcon_inst%initd(pft)) - temp_cohort%dbh = abs(EDPftvarcon_inst%initd(pft)) + ! calculate crown area of a single plant + dummy_n = 1.0_r8 ! make n=1 to get area of one tree + spread = 1.0_r8 ! fix this to 0 to remove dynamics of canopy clousre, assuming a closed canopy. - ! calculate crown area of a single plant - dummy_n = 1.0_r8 ! make n=1 to get area of one tree - spread = 1.0_r8 ! fix this to 0 to remove dynamics of canopy clousre, assuming a closed canopy. + call carea_allom(temp_cohort%dbh, dummy_n, spread, temp_cohort%pft, & + temp_cohort%crowndamage, temp_cohort%c_area) - call carea_allom(temp_cohort%dbh, dummy_n, spread, temp_cohort%pft, & - temp_cohort%crowndamage, temp_cohort%c_area) - - ! calculate initial density required to close canopy - temp_cohort%n = patch_in%area / temp_cohort%c_area + ! calculate initial density required to close canopy + temp_cohort%n = patch_in%area / temp_cohort%c_area + else + write(fates_log()*) 'Negative fates_recruit_init_density can only be used in no comp mode' + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif endif ! Calculate the leaf biomass from allometry diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index c5ddba36c6..e96eb02c25 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -490,7 +490,7 @@ variables: fates_recruit_height_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; double fates_recruit_init_density(fates_pft) ; fates_recruit_init_density:units = "stems/m2" ; - fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation" ; + fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation. If negative sets initial tree dbh - only to be used in nocomp mode" ; double fates_recruit_prescribed_rate(fates_pft) ; fates_recruit_prescribed_rate:units = "n/yr" ; fates_recruit_prescribed_rate:long_name = "recruitment rate for prescribed physiology mode" ; From c30ec70196d4fe3a5807dbd76d087f9674d757b6 Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Thu, 2 Mar 2023 15:49:00 -0800 Subject: [PATCH 558/852] Fix typo --- main/EDInitMod.F90 | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 4f77c55ad7..1af65bc71e 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -810,7 +810,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) endif end do - + do pft = 1,numpft if(use_pft_local(pft).eq.itrue)then @@ -862,7 +862,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) ! calculate initial density required to close canopy temp_cohort%n = patch_in%area / temp_cohort%c_area else - write(fates_log()*) 'Negative fates_recruit_init_density can only be used in no comp mode' + write(fates_log(),*) 'Negative fates_recruit_init_density can only be used in no comp mode' call endrun(msg=errMsg(sourcefile, __LINE__)) endif endif @@ -871,7 +871,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) ! (calculates a maximum first, then applies canopy trim) call bleaf(temp_cohort%dbh,pft,temp_cohort%crowndamage, & temp_cohort%canopy_trim,c_leaf) - + ! Calculate total above-ground biomass from allometry call bagw_allom(temp_cohort%dbh,pft,temp_cohort%crowndamage,c_agw) @@ -996,13 +996,12 @@ subroutine init_cohorts( site_in, patch_in, bc_in) deallocate(temp_cohort) ! get rid of temporary cohort - deallocate(temp_cohort, stat=istat, errmsg=smsg) - if (istat/=0) then - write(fates_log(),*) 'dealloc014: fail on deallocate(temp_cohort):'//trim(smsg) - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - + deallocate(temp_cohort, stat=istat, errmsg=smsg) + if (istat/=0) then + write(fates_log(),*) 'dealloc014: fail on deallocate(temp_cohort):'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) endif + endif !use_this_pft enddo !numpft From 931700e45cc61e4d3181201986c6288f2510ced9 Mon Sep 17 00:00:00 2001 From: walkeranthonyp Date: Mon, 30 Jan 2023 17:29:48 -0500 Subject: [PATCH 559/852] bugfix logging event NaN error in mass balance check bugfix logging: remove potential for divide by zero in logging_litter_fluxes bugfix logging: catch when newPatch area is zero bugfix logging: align naming with other litter flux routines --- biogeochem/EDLoggingMortalityMod.F90 | 123 +++++++++++++++------------ 1 file changed, 68 insertions(+), 55 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index ab0b77b737..db7ce3756f 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -192,6 +192,7 @@ subroutine IsItLoggingTime(is_master,currentSite) return end subroutine IsItLoggingTime + ! ====================================================================================== subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & @@ -332,6 +333,7 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & end subroutine LoggingMortality_frac + ! ============================================================================ subroutine get_harvest_rate_area (patch_anthro_disturbance_label, hlm_harvest_catnames, hlm_harvest_rates, & @@ -409,13 +411,14 @@ subroutine get_harvest_rate_area (patch_anthro_disturbance_label, hlm_harvest_ca harvest_rate = harvest_rate / hlm_days_per_year else if(icode .eq. 4) then ! logging event once a month - if(hlm_current_day.eq.1 ) then + if(hlm_current_day.eq.1) then harvest_rate = harvest_rate / months_per_year end if end if end subroutine get_harvest_rate_area + ! ============================================================================ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site_areadis, bc_in) @@ -451,12 +454,13 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site !USES: - use SFParamsMod, only : SF_val_cwd_frac - use EDtypesMod, only : area - use EDtypesMod, only : ed_site_type - use EDtypesMod, only : ed_patch_type - use EDtypesMod, only : ed_cohort_type - use FatesAllometryMod , only : carea_allom + use SFParamsMod, only : SF_val_cwd_frac + use EDtypesMod, only : area + use EDtypesMod, only : ed_site_type + use EDtypesMod, only : ed_patch_type + use EDtypesMod, only : ed_cohort_type + use FatesConstantsMod, only : rsnbl_math_prec + use FatesAllometryMod, only : carea_allom ! !ARGUMENTS: @@ -474,34 +478,36 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site type(litter_type),pointer :: new_litt type(litter_type),pointer :: cur_litt - real(r8) :: direct_dead ! Mortality count through direct logging - real(r8) :: indirect_dead ! Mortality count through: impacts, infrastructure and collateral damage - real(r8) :: trunk_product_site ! flux of carbon in trunk products exported off site [ kgC/site ] - ! (note we are accumulating over the patch, but scale is site level) - real(r8) :: delta_litter_stock ! flux of carbon in total litter flux [ kgC/site ] - real(r8) :: delta_biomass_stock ! total flux of carbon through mortality (litter+product) [ kgC/site ] - real(r8) :: delta_individual ! change in plant number through mortality [ plants/site ] - real(r8) :: leaf_litter ! Leafy biomass transferred through mortality [kgC/site] - real(r8) :: root_litter ! Rooty + storage biomass transferred through mort [kgC/site] - real(r8) :: ag_wood ! above ground wood mass [kg] - real(r8) :: bg_wood ! below ground wood mass [kg] - real(r8) :: remainder_area ! current patch's remaining area after donation [m2] - real(r8) :: leaf_m ! leaf element mass [kg] - real(r8) :: fnrt_m ! fineroot element mass [kg] - real(r8) :: sapw_m ! sapwood element mass [kg] - real(r8) :: store_m ! storage element mass [kg] - real(r8) :: struct_m ! structure element mass [kg] - real(r8) :: repro_m ! reproductive mass [kg] - real(r8) :: retain_frac ! fraction of litter retained in the donor patch - real(r8) :: donate_frac ! fraction of litter sent to newly formed patch - real(r8) :: dcmpy_frac ! fraction going into each decomposability pool - integer :: dcmpy ! index for decomposability pools - integer :: element_id ! parteh global element index - integer :: pft ! pft index - integer :: c ! cwd index - integer :: nlevsoil ! number of soil layers - integer :: ilyr ! soil layer loop index - integer :: el ! elemend loop index + real(r8) :: direct_dead ! Mortality count through direct logging + real(r8) :: indirect_dead ! Mortality count through: impacts, infrastructure and collateral damage + real(r8) :: trunk_product_site ! flux of carbon in trunk products exported off site [ kgC/site ] + ! (note we are accumulating over the patch, but scale is site level) + real(r8) :: delta_litter_stock ! flux of carbon in total litter flux [ kgC/site ] + real(r8) :: delta_biomass_stock ! total flux of carbon through mortality (litter+product) [ kgC/site ] + real(r8) :: delta_individual ! change in plant number through mortality [ plants/site ] + real(r8) :: leaf_litter ! Leafy biomass transferred through mortality [kgC/site] + real(r8) :: root_litter ! Rooty + storage biomass transferred through mort [kgC/site] + real(r8) :: ag_wood ! above ground wood mass [kg] + real(r8) :: bg_wood ! below ground wood mass [kg] + real(r8) :: remainder_area ! current patch's remaining area after donation [m2] + real(r8) :: leaf_m ! leaf element mass [kg] + real(r8) :: fnrt_m ! fineroot element mass [kg] + real(r8) :: sapw_m ! sapwood element mass [kg] + real(r8) :: store_m ! storage element mass [kg] + real(r8) :: struct_m ! structure element mass [kg] + real(r8) :: repro_m ! reproductive mass [kg] + real(r8) :: retain_frac ! fraction of litter retained in the donor patch + real(r8) :: donate_frac ! fraction of litter sent to newly formed patch + real(r8) :: retain_m2 ! area normalization for litter mass destined to old patch [m-2] + real(r8) :: donate_m2 ! area normalization for litter mass destined to new patch [m-2] + real(r8) :: dcmpy_frac ! fraction going into each decomposability pool + integer :: dcmpy ! index for decomposability pools + integer :: element_id ! parteh global element index + integer :: pft ! pft index + integer :: c ! cwd index + integer :: nlevsoil ! number of soil layers + integer :: ilyr ! soil layer loop index + integer :: el ! elemend loop index nlevsoil = currentSite%nlevsoil @@ -510,17 +516,23 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site ! mass sent to that patch, by the area it will have remaining ! after it donates area. ! i.e. subtract the area it is donating. - remainder_area = currentPatch%area - patch_site_areadis - ! Calculate the fraction of litter to be retained versus donated ! vis-a-vis the new and donor patch - retain_frac = (1.0_r8-harvest_litter_localization) * & remainder_area/(newPatch%area+remainder_area) donate_frac = 1.0_r8-retain_frac + if(remainder_area > rsnbl_math_prec) then + retain_m2 = retain_frac/remainder_area + donate_m2 = (1.0_r8-retain_frac)/newPatch%area + else + retain_m2 = 0._r8 + donate_m2 = 1._r8/newPatch%area + end if + + do el = 1,num_elements element_id = element_list(el) @@ -529,13 +541,13 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site cur_litt => currentPatch%litter(el) ! Litter pool of "current" patch new_litt => newPatch%litter(el) ! Litter pool of "new" patch - ! Zero some site level accumulator diagnsotics trunk_product_site = 0.0_r8 delta_litter_stock = 0.0_r8 delta_biomass_stock = 0.0_r8 delta_individual = 0.0_r8 + ! ----------------------------------------------------------------------------- ! Part 1: Send parts of dying plants to the litter pool. ! ----------------------------------------------------------------------------- @@ -605,19 +617,19 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site do c = 1,ncwd-1 new_litt%ag_cwd(c) = new_litt%ag_cwd(c) + & - ag_wood * SF_val_CWD_frac(c) * donate_frac/newPatch%area + ag_wood * SF_val_CWD_frac(c) * donate_m2 cur_litt%ag_cwd(c) = cur_litt%ag_cwd(c) + & - ag_wood * SF_val_CWD_frac(c) * retain_frac/remainder_area + ag_wood * SF_val_CWD_frac(c) * retain_m2 do ilyr = 1,nlevsoil new_litt%bg_cwd(c,ilyr) = new_litt%bg_cwd(c,ilyr) + & bg_wood * currentSite%rootfrac_scr(ilyr) * & - SF_val_CWD_frac(c) * donate_frac/newPatch%area + SF_val_CWD_frac(c) * donate_m2 cur_litt%bg_cwd(c,ilyr) = cur_litt%bg_cwd(c,ilyr) + & bg_wood * currentSite%rootfrac_scr(ilyr) * & - SF_val_CWD_frac(c) * retain_frac/remainder_area + SF_val_CWD_frac(c) * retain_m2 end do @@ -646,20 +658,20 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site (1._r8 - prt_params%allom_agb_frac(currentCohort%pft)) new_litt%ag_cwd(ncwd) = new_litt%ag_cwd(ncwd) + ag_wood * & - SF_val_CWD_frac(ncwd) * donate_frac/newPatch%area + SF_val_CWD_frac(ncwd) * donate_m2 cur_litt%ag_cwd(ncwd) = cur_litt%ag_cwd(ncwd) + ag_wood * & - SF_val_CWD_frac(ncwd) * retain_frac/remainder_area + SF_val_CWD_frac(ncwd) * retain_m2 do ilyr = 1,nlevsoil new_litt%bg_cwd(ncwd,ilyr) = new_litt%bg_cwd(ncwd,ilyr) + & bg_wood * currentSite%rootfrac_scr(ilyr) * & - SF_val_CWD_frac(ncwd) * donate_frac/newPatch%area + SF_val_CWD_frac(ncwd) * donate_m2 cur_litt%bg_cwd(ncwd,ilyr) = cur_litt%bg_cwd(ncwd,ilyr) + & bg_wood * currentSite%rootfrac_scr(ilyr) * & - SF_val_CWD_frac(ncwd) * retain_frac/remainder_area + SF_val_CWD_frac(ncwd) * retain_m2 end do @@ -684,11 +696,11 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site do ilyr = 1,nlevsoil new_litt%bg_cwd(ncwd,ilyr) = new_litt%bg_cwd(ncwd,ilyr) + & bg_wood * currentSite%rootfrac_scr(ilyr) * & - donate_frac/newPatch%area + donate_m2 cur_litt%bg_cwd(ncwd,ilyr) = cur_litt%bg_cwd(ncwd,ilyr) + & bg_wood * currentSite%rootfrac_scr(ilyr) * & - retain_frac/remainder_area + retain_m2 end do flux_diags%cwd_bg_input(ncwd) = flux_diags%cwd_bg_input(ncwd) + & @@ -715,10 +727,10 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site ag_wood * logging_export_frac new_litt%ag_cwd(ncwd) = new_litt%ag_cwd(ncwd) + ag_wood * & - (1._r8-logging_export_frac)*donate_frac/newPatch%area + (1._r8-logging_export_frac)*donate_m2 cur_litt%ag_cwd(ncwd) = cur_litt%ag_cwd(ncwd) + ag_wood * & - (1._r8-logging_export_frac)*retain_frac/remainder_area + (1._r8-logging_export_frac)*retain_m2 ! --------------------------------------------------------------------------- ! Handle fluxes of leaf, root and storage carbon into litter pools. @@ -734,20 +746,20 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site dcmpy_frac = GetDecompyFrac(pft,leaf_organ,dcmpy) new_litt%leaf_fines(dcmpy) = new_litt%leaf_fines(dcmpy) + & - leaf_litter * donate_frac/newPatch%area * dcmpy_frac + leaf_litter * donate_m2 * dcmpy_frac cur_litt%leaf_fines(dcmpy) = cur_litt%leaf_fines(dcmpy) + & - leaf_litter * retain_frac/remainder_area * dcmpy_frac + leaf_litter * retain_m2 * dcmpy_frac dcmpy_frac = GetDecompyFrac(pft,fnrt_organ,dcmpy) do ilyr = 1,nlevsoil new_litt%root_fines(dcmpy,ilyr) = new_litt%root_fines(dcmpy,ilyr) + & root_litter * currentSite%rootfrac_scr(ilyr) * dcmpy_frac * & - donate_frac/newPatch%area + donate_m2 cur_litt%root_fines(dcmpy,ilyr) = cur_litt%root_fines(dcmpy,ilyr) + & root_litter * currentSite%rootfrac_scr(ilyr) * dcmpy_frac * & - retain_frac/remainder_area + retain_m2 end do end do @@ -819,6 +831,7 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site return end subroutine logging_litter_fluxes + ! ===================================================================================== subroutine UpdateHarvestC(currentSite,bc_out) From 95c4a07c59af49e9d2c11e84413f294e8d78ea91 Mon Sep 17 00:00:00 2001 From: Marcos Longo Date: Mon, 6 Mar 2023 08:51:45 -0800 Subject: [PATCH 560/852] Documented and fixed the additional meaning of leaf life span for drought deciduous. Added the description that the leaf longevity parameter is also the maximum time that leaves can be "on" when running drought-deciduous PFT, and fixed the check in sub-routine "phenology" to compare the length with the growing season with the sum of leaf longevities across ages (as opposed to the maximum value). --- biogeochem/EDPhysiologyMod.F90 | 10 +++++----- parameter_files/fates_params_default.cdl | 2 +- parteh/PRTParametersMod.F90 | 4 ++++ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 2b1f37c6f2..58b0f84957 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1220,12 +1220,12 @@ subroutine phenology( currentSite, bc_in ) elongf_prev = currentSite%elong_factor(ipft) - ! PFT leaf lifespan in days. This is the shortest between the leaf longevity - ! (defined as a PFT parameter) and the maximum canopy leaf life span allowed - ! for drought deciduous (local parameter). - ! MLO: Need to double check that this will not cause unintended problems + ! PFT leaf lifespan in days. This is the shortest between the leaf longevity + ! (defined as a PFT parameter) and the maximum canopy leaf life span allowed + ! for drought deciduous (local parameter). The sum term accounts for the + ! total leaf life span of this cohort. pft_leaf_lifespan = min( canopy_leaf_lifespan, & - nint(365*maxval(prt_params%leaf_long(ipft,:))) ) + nint(365*sum(prt_params%leaf_long(ipft,:))) ) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 32c8db0418..64a118cacf 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -547,7 +547,7 @@ variables: fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; double fates_turnover_leaf(fates_leafage_class, fates_pft) ; fates_turnover_leaf:units = "yr" ; - fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; + fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale). For drought-deciduous PFTs, this also indicates the maximum length of the growing (i.e., leaves on) season." ; double fates_turnover_senleaf_fdrought(fates_pft) ; fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; diff --git a/parteh/PRTParametersMod.F90 b/parteh/PRTParametersMod.F90 index 97f9e2c3a2..35fa1caa91 100644 --- a/parteh/PRTParametersMod.F90 +++ b/parteh/PRTParametersMod.F90 @@ -51,6 +51,10 @@ module PRTParametersMod real(r8), allocatable :: leaf_long(:,:) ! Leaf turnover time (longevity) (pft x age-class) ! If there is >1 class, it is the longevity from ! one class to the next [yr] + ! For drought-deciduous PFTs, the sum of leaf + ! longevity across all leaf age classes is also + ! the maximum length of the growing (i.e., leaves on) + ! season. real(r8), allocatable :: root_long(:) ! root turnover time (longevity) (pft) [yr] real(r8), allocatable :: branch_long(:) ! Turnover time for branchfall on live trees (pft) [yr] real(r8), allocatable :: turnover_nitr_retrans(:,:) ! nitrogen re-translocation fraction (pft x organ) From 202b09c420f5324733153450802c75b208a47137 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 6 Mar 2023 16:12:41 -0800 Subject: [PATCH 561/852] Start bringing in Charlie's xesmf code --- tools/luh2.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/luh2.py b/tools/luh2.py index e3dfb9be8c..d7a0f2d2bb 100644 --- a/tools/luh2.py +++ b/tools/luh2.py @@ -1,10 +1,14 @@ #!/usr/bin/env python3 import re +import numpy as np import xarray as xr +import xesmf as xe from nco import Nco from nco.custom import Atted +# Add version checking here in case environment.yml not used + # Import luh2 data def importdata(inputarg): @@ -26,7 +30,8 @@ def importdata(inputarg): # Modify the luh2 metadata to enable xarray to read in data # This issue here is that the luh2 time units start prior to -# +# year 1672, which cftime should be able to handle, but it +# appears to need a specific unit name convention "common_years" def attribupdate(inputarg,outputarg): nco = Nco() @@ -56,6 +61,9 @@ def attribupdate(inputarg,outputarg): # ), # ]) +# Update the formatting to meet HLM needs +# def clmformatter(): + # General functionality needed # - collect data for specific user-defined time period # - collect subset of the data variables (e.g. pasture, rangeland, etc) From a20b462a56f211f0848262c218a4c00747bd7b36 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 6 Mar 2023 16:19:27 -0800 Subject: [PATCH 562/852] Rename the patch file api number Per precedent, the patch file api number should be the api number of the file to which it is being applied. --- .../{api25.1.1_021623_pr931.xml => api25.1.0_021623_pr931.xml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename parameter_files/archive/{api25.1.1_021623_pr931.xml => api25.1.0_021623_pr931.xml} (100%) diff --git a/parameter_files/archive/api25.1.1_021623_pr931.xml b/parameter_files/archive/api25.1.0_021623_pr931.xml similarity index 100% rename from parameter_files/archive/api25.1.1_021623_pr931.xml rename to parameter_files/archive/api25.1.0_021623_pr931.xml From 008f8f85f9b500c3a86a859485bf6acbf075886c Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 6 Mar 2023 16:49:55 -0800 Subject: [PATCH 563/852] Minor instruction update in patch file --- parameter_files/archive/api25.1.0_021623_pr931.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parameter_files/archive/api25.1.0_021623_pr931.xml b/parameter_files/archive/api25.1.0_021623_pr931.xml index 2315fbef8c..df4598fd14 100644 --- a/parameter_files/archive/api25.1.0_021623_pr931.xml +++ b/parameter_files/archive/api25.1.0_021623_pr931.xml @@ -12,7 +12,7 @@ - + From 93a02af0c9383e63d0b27e4061d5614c6f5223ae Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 7 Mar 2023 14:24:24 -0800 Subject: [PATCH 564/852] Manually revert phenology and parameter changes --- biogeochem/EDPhysiologyMod.F90 | 7 +++---- parameter_files/fates_params_default.cdl | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 65db791aee..a70523b404 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -815,8 +815,8 @@ subroutine phenology( currentSite, bc_in ) endif ! ! accumulate the GDD using daily mean temperatures - ! Don't accumulate GDD during the growing season (that wouldn't make sense) Junyan modified to adding nevercold - if (temp_in_C .gt. 0._r8 .and. (currentSite%cstatus == phen_cstat_iscold .or. currentSite%cstatus == phen_cstat_nevercold)) then + ! Don't accumulate GDD during the growing season (that wouldn't make sense) + if (temp_in_C .gt. 0._r8 .and. currentSite%cstatus == phen_cstat_iscold) then currentSite%grow_deg_days = currentSite%grow_deg_days + temp_in_C endif @@ -912,8 +912,7 @@ subroutine phenology( currentSite, bc_in ) ! plants from re-emerging in areas without at least some cold days if( (currentSite%cstatus == phen_cstat_notcold) .and. & - (dayssincecleafoff > 40000)) then ! remove leaves after a whole year, - !Junyan change dayssincecleafoff > 400 to 40000 to disable this function, so the condition will never be met + (dayssincecleafoff > 400)) then ! remove leaves after a whole year, ! when there is no 'off' period. currentSite%grow_deg_days = 0._r8 diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 244c3716f6..6d5fa2cb4e 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -769,7 +769,7 @@ data: fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100 ; - fates_hydr_htftype_node = 2, 2, 2, 2 ; + fates_hydr_htftype_node = 1, 1, 1, 1 ; fates_prt_organ_id = 1, 2, 3, 6 ; @@ -1445,7 +1445,7 @@ data: fates_maintresp_model = 1 ; - fates_mort_disturb_frac = 0 ; + fates_mort_disturb_frac = 1 ; fates_mort_understorey_death = 0.55983 ; From 0fc9de51431a0729dfbbcdf2b6d22f130cbbcc42 Mon Sep 17 00:00:00 2001 From: ckoven Date: Tue, 7 Mar 2023 19:35:25 -0700 Subject: [PATCH 565/852] moved T_home time constant to parameter file --- main/EDParamsMod.F90 | 21 +++++++++++++++------ main/FatesInterfaceMod.F90 | 8 +++++--- parameter_files/fates_params_default.cdl | 9 +++++++-- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 497b441405..40edc6a0b8 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -23,14 +23,14 @@ module EDParamsMod real(r8),protected, public :: vai_top_bin_width ! width in VAI units of uppermost leaf+stem ! layer scattering element in each canopy layer [m2/m2] - ! (NOT YET IMPLEMENTED) real(r8),protected, public :: vai_width_increase_factor ! factor by which each leaf+stem scattering element ! increases in VAI width (1 = uniform spacing) - ! (NOT YET IMPLEMENTED) real(r8),protected, public :: photo_temp_acclim_timescale ! Length of the window for the exponential moving average (ema) - ! of vegetation temperature used in photosynthesis - ! temperature acclimation (NOT YET IMPLEMENTED) - + ! of vegetation temperature used in photosynthesis and respiration + ! temperature acclimation [days] + real(r8),protected, public :: photo_temp_acclim_thome_time ! Length of the window for the long-term exponential moving average (ema) + ! of vegetation temperature used in photosynthesis + ! T_home term in Kumarathunge parameterization [years] integer,protected, public :: maintresp_leaf_model ! switch for choosing between leaf maintenance ! respiration model. 1=Ryan (1991), 2=Atkin et al (2017) integer,protected, public :: photo_tempsens_model ! switch for choosing the model that defines the temperature @@ -94,6 +94,7 @@ module EDParamsMod integer, protected,allocatable,public :: hydr_htftype_node(:) character(len=param_string_length),parameter,public :: ED_name_photo_temp_acclim_timescale = "fates_leaf_photo_temp_acclim_timescale" + character(len=param_string_length),parameter,public :: ED_name_photo_temp_acclim_thome_time = "fates_leaf_photo_temp_acclim_thome_time" character(len=param_string_length),parameter,public :: name_photo_tempsens_model = "fates_leaf_photo_tempsens_model" character(len=param_string_length),parameter,public :: name_maintresp_model = "fates_maintresp_leaf_model" character(len=param_string_length),parameter,public :: ED_name_hydr_htftype_node = "fates_hydro_htftype_node" @@ -264,6 +265,7 @@ subroutine FatesParamsInit() vai_top_bin_width = nan vai_width_increase_factor = nan photo_temp_acclim_timescale = nan + photo_temp_acclim_thome_time = nan photo_tempsens_model = -9 maintresp_leaf_model = -9 fates_mortality_disturbance_fraction = nan @@ -348,6 +350,9 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=ED_name_photo_temp_acclim_timescale, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=ED_name_photo_temp_acclim_thome_time, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=name_photo_tempsens_model,dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -551,6 +556,9 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetrieveParameter(name=ED_name_photo_temp_acclim_timescale, & data=photo_temp_acclim_timescale) + call fates_params%RetrieveParameter(name=ED_name_photo_temp_acclim_thome_time, & + data=photo_temp_acclim_thome_time) + call fates_params%RetrieveParameter(name=name_photo_tempsens_model, & data=tmpreal) photo_tempsens_model = nint(tmpreal) @@ -768,7 +776,8 @@ subroutine FatesReportParams(is_master) write(fates_log(),*) '----------- FATES Scalar Parameters -----------------' write(fates_log(),fmt0) 'vai_top_bin_width = ',vai_top_bin_width write(fates_log(),fmt0) 'vai_width_increase_factor = ',vai_width_increase_factor - write(fates_log(),fmt0) 'photo_temp_acclim_timescale = ',photo_temp_acclim_timescale + write(fates_log(),fmt0) 'photo_temp_acclim_timescale (days) = ',photo_temp_acclim_timescale + write(fates_log(),fmt0) 'photo_temp_acclim_thome_time (years) = ',photo_temp_acclim_thome_time write(fates_log(),fmti) 'hydr_htftype_node = ',hydr_htftype_node write(fates_log(),fmt0) 'fates_mortality_disturbance_fraction = ',fates_mortality_disturbance_fraction write(fates_log(),fmt0) 'ED_val_comp_excln = ',ED_val_comp_excln diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 170cff8fff..4fc365ce62 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -36,6 +36,7 @@ module FatesInterfaceMod use FatesConstantsMod , only : itrue,ifalse use FatesConstantsMod , only : nearzero use FatesConstantsMod , only : sec_per_day + use FatesConstantsMod , only : days_per_year use FatesGlobals , only : fates_global_verbose use FatesGlobals , only : fates_log use FatesGlobals , only : endrun => fates_endrun @@ -50,6 +51,7 @@ module FatesInterfaceMod use EDParamsMod , only : bgc_soil_salinity use FatesPlantHydraulicsMod , only : InitHydroGlobals use EDParamsMod , only : photo_temp_acclim_timescale + use EDParamsMod , only : photo_temp_acclim_thome_time use EDParamsMod , only : ED_val_history_sizeclass_bin_edges use EDParamsMod , only : ED_val_history_ageclass_bin_edges use EDParamsMod , only : ED_val_history_height_bin_edges @@ -987,11 +989,11 @@ subroutine InitTimeAveragingGlobals() call ema_24hr%define(sec_per_day, hlm_stepsize, moving_ema_window) allocate(fixed_24hr) call fixed_24hr%define(sec_per_day, hlm_stepsize, fixed_window) - allocate(ema_lpa) + allocate(ema_lpa) ! note that this parameter has units of days call ema_lpa%define(photo_temp_acclim_timescale*sec_per_day, & hlm_stepsize,moving_ema_window) - allocate(ema_longterm) ! for now just fix this as a 30-year exponential moving average - call ema_longterm%define(30._r8*365._r8*sec_per_day, & + allocate(ema_longterm) ! note that this parameter has units of years + call ema_longterm%define(photo_temp_acclim_thome_time*days_per_year*sec_per_day, & hlm_stepsize,moving_ema_window) !allocate(ema_60day) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 2e68a596c1..769b742c2c 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -705,9 +705,12 @@ variables: double fates_landuse_pprodharv10_forest_mean ; fates_landuse_pprodharv10_forest_mean:units = "fraction" ; fates_landuse_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; + double fates_leaf_photo_temp_acclim_thome_time ; + fates_leaf_photo_temp_acclim_thome_time:units = "years" ; + fates_leaf_photo_temp_acclim_thome_time:long_name = "Length of the window for the long-term (i.e. T_home in Kumarathunge et al 2019) exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_leaf_photo_tempsens_model = 2)" ; double fates_leaf_photo_temp_acclim_timescale ; fates_leaf_photo_temp_acclim_timescale:units = "days" ; - fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; + fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_maintresp_leaf_model=2 or fates_leaf_photo_tempsens_model = 2)" ; double fates_leaf_photo_tempsens_model ; fates_leaf_photo_tempsens_model:units = "unitless" ; fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating; 2=Kumarathunge et al 2019" ; @@ -725,7 +728,7 @@ variables: fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; double fates_maintresp_leaf_model ; fates_maintresp_leaf_model:units = "unitless" ; - fates_maintresp_leaf_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991) (NOT USED)" ; + fates_maintresp_leaf_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991), 2=Atkin et al., (2017)" ; double fates_maintresp_nonleaf_baserate ; fates_maintresp_nonleaf_baserate:units = "gC/gN/s" ; fates_maintresp_nonleaf_baserate:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; @@ -1493,6 +1496,8 @@ data: fates_landuse_pprodharv10_forest_mean = 0.8125 ; + fates_leaf_photo_temp_acclim_thome_time = 30 ; + fates_leaf_photo_temp_acclim_timescale = 30 ; fates_leaf_photo_tempsens_model = 1 ; From 0402f5733624ff04f8822b3ac87c8a8e1525ddea Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 9 Mar 2023 15:11:57 -0500 Subject: [PATCH 566/852] Moved parameter checking complaint to CNP side of code --- main/EDPftvarcon.F90 | 49 +++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index b3ec36ecc7..9b5848edfc 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1580,7 +1580,31 @@ subroutine FatesCheckParams(is_master) end if end if - + + ! If any PFTs are specified as either prescribed N or P uptake + ! then they all must be ! + + if (any(EDPftvarcon_inst%prescribed_nuptake(:) < -nearzero ) .or. & + any(EDPftvarcon_inst%prescribed_nuptake(:) > 10._r8 ) ) then + write(fates_log(),*) 'Negative values for EDPftvarcon_inst%prescribed_nuptake(:)' + write(fates_log(),*) 'are not allowed. Reasonable ranges for this parameter are zero' + write(fates_log(),*) 'to something slightly larger than 1, so we set a cap at 10.' + write(fates_log(),*) 'Set to zero to turn off and use coupled nutrients.' + write(fates_log(),*) ' Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + elseif (any(abs(EDPftvarcon_inst%prescribed_nuptake(:)) > nearzero )) then + if(.not.all(abs(EDPftvarcon_inst%prescribed_nuptake(:)) > nearzero )) then + write(fates_log(),*) 'If any PFTs are specified as having prescribed N' + write(fates_log(),*) 'uptake, then they must all. Note, prescribed' + write(fates_log(),*) 'rates are associated with any value abs(x)>nearzero' + write(fates_log(),*) 'EDPftvarcon_inst%prescribed_nuptake(:):', & + EDPftvarcon_inst%prescribed_nuptake(:) + write(fates_log(),*) ' Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + end if + + case (prt_carbon_allom_hyp) ! No additional checks needed for now. continue @@ -1594,28 +1618,7 @@ subroutine FatesCheckParams(is_master) call endrun(msg=errMsg(sourcefile, __LINE__)) end select - ! If any PFTs are specified as either prescribed N or P uptake - ! then they all must be ! - - if (any(EDPftvarcon_inst%prescribed_nuptake(:) < -nearzero ) .or. & - any(EDPftvarcon_inst%prescribed_nuptake(:) > 10._r8 ) ) then - write(fates_log(),*) 'Negative values for EDPftvarcon_inst%prescribed_nuptake(:)' - write(fates_log(),*) 'are not allowed. Reasonable ranges for this parameter are zero' - write(fates_log(),*) 'to something slightly larger than 1, so we set a cap at 10.' - write(fates_log(),*) 'Set to zero to turn off and use coupled nutrients.' - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) - elseif (any(abs(EDPftvarcon_inst%prescribed_nuptake(:)) > nearzero )) then - if(.not.all(abs(EDPftvarcon_inst%prescribed_nuptake(:)) > nearzero )) then - write(fates_log(),*) 'If any PFTs are specified as having prescribed N' - write(fates_log(),*) 'uptake, then they must all. Note, prescribed' - write(fates_log(),*) 'rates are associated with any value abs(x)>nearzero' - write(fates_log(),*) 'EDPftvarcon_inst%prescribed_nuptake(:):', & - EDPftvarcon_inst%prescribed_nuptake(:) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - end if + ! logging parameters, make sure they make sense if ( (logging_mechanical_frac + logging_collateral_frac + logging_direct_frac) .gt. 1._r8) then From c45e43ea7845891e1063206cf14e54a763e81fa5 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 9 Mar 2023 15:33:41 -0500 Subject: [PATCH 567/852] Fixed units and long name on germinated litter, and removed an external module call from hydro --- biogeophys/FatesPlantHydraulicsMod.F90 | 23 +---------------------- main/FatesHistoryInterfaceMod.F90 | 8 ++++---- 2 files changed, 5 insertions(+), 26 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index f1e391fe8f..a236981615 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -98,8 +98,6 @@ module FatesPlantHydraulicsMod use PRTGenericMod, only : num_elements use PRTGenericMod, only : element_list - use clm_time_manager , only : get_step_size, get_nstep - use EDPftvarcon, only : EDPftvarcon_inst use PRTParametersMod, only : prt_params @@ -1097,7 +1095,6 @@ subroutine UpdateSizeDepPlantHydStates(currentSite,ccohort) real(r8) :: th_uncorr ! Uncorrected water content real(r8), parameter :: small_theta_num = 1.e-7_r8 ! avoids theta values equalling thr or ths [m3 m-3] - integer :: nstep !number of time steps !----------------------------------------------------------------------- ccohort_hydr => ccohort%co_hydr @@ -1774,12 +1771,8 @@ subroutine UpdateH2OVeg(csite,bc_out,prev_site_h2o,icall) type(ed_site_hydr_type), pointer :: csite_hydr integer :: s real(r8) :: balive_patch - integer :: nstep !number of time steps - - !for debug only - nstep = get_nstep() - bc_out%plant_stored_h2o_si = 0.0_r8 + bc_out%plant_stored_h2o_si = 0.0_r8 if( hlm_use_planthydro.eq.ifalse ) return @@ -1860,7 +1853,6 @@ subroutine RecruitWUptake(nsites,sites,bc_in,dtime,recruitflag) type(ed_cohort_hydr_type), pointer :: ccohort_hydr type(ed_site_hydr_type), pointer :: csite_hydr integer :: s, j, ft - integer :: nstep !number of time steps real(r8) :: rootfr !fraction of root in different soil layer real(r8) :: recruitw !water for newly recruited cohorts (kg water/m2/s) real(r8) :: recruitw_total ! total water for newly recruited cohorts (kg water/m2/s) @@ -4861,8 +4853,6 @@ subroutine MatSolve2D(csite_hydr,cohort,cohort_hydr, & integer :: kshell ! rhizosphere shell index, 1->nshell integer :: info - integer :: nstep !number of time steps - ! This is a convergence test. This is the maximum difference ! allowed between the flux balance and the change in storage @@ -4949,10 +4939,6 @@ subroutine MatSolve2D(csite_hydr,cohort,cohort_hydr, & ft => cohort%pft) - !for debug only - nstep = get_nstep() - - ! This NaN's the scratch arrays call csite_hydr%FlushSiteScratch(hydr_solver) @@ -5637,8 +5623,6 @@ subroutine PicardSolve2D(csite_hydr,cohort,cohort_hydr, & integer :: kshell ! rhizosphere shell index, 1->nshell integer :: info - integer :: nstep !number of time steps - ! This is a convergence test. This is the maximum difference ! allowed between the flux balance and the change in storage @@ -5731,11 +5715,6 @@ subroutine PicardSolve2D(csite_hydr,cohort,cohort_hydr, & dftc_dpsi_node => csite_hydr%dftc_dpsi_node, & ft => cohort%pft) - - !for debug only - nstep = get_nstep() - - ! This NaN's the scratch arrays call csite_hydr%FlushSiteScratch(hydr_solver) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index f9f99300f9..f3a8e790a5 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -3978,7 +3978,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) ! Sum up total seed bank (germinated and ungerminated) hio_seed_bank_si(io_si) = hio_seed_bank_si(io_si) + & (sum(litt%seed(:))+sum(litt%seed_germ(:))) * & - area_frac * days_per_sec + area_frac ! Sum up the input flux into the seed bank (local and external) hio_seeds_in_si(io_si) = hio_seeds_in_si(io_si) + & @@ -4066,7 +4066,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) sum(litt%seed(:)) * cpatch%area / m2_per_ha hio_seed_germ_elem(io_si,el) = hio_seed_germ_elem(io_si,el) + & - sum(litt%seed_germ(:)) * cpatch%area / m2_per_ha / sec_per_day + sum(litt%seed_germ(:)) * cpatch%area / m2_per_ha hio_seed_decay_elem(io_si,el) = hio_seed_decay_elem(io_si,el) + & sum(litt%seed_decay(:) + litt%seed_germ_decay(:) ) * & @@ -5783,8 +5783,8 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_seeds_in_extern_elem) - call this%set_history_var(vname='FATES_SEED_GERM_EL', units='kg m-2 s-1', & - long='seed mass converted into new cohorts in kg element per m2 per s', & + call this%set_history_var(vname='FATES_SEED_GERM_EL', units='kg m-2', & + long='element-level total germinated seed mass of all PFTs in kg element per m2', & use_default='active', avgflag='A', vtype=site_elem_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_seed_germ_elem) From 1b570d88c52d64bab2e952ac90ff7ffae9f11510 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 9 Mar 2023 19:20:32 -0500 Subject: [PATCH 568/852] comments on n litter fluxes added --- main/FatesInterfaceMod.F90 | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index c81053da3a..53daac0453 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -313,6 +313,9 @@ subroutine zero_bcs(fates,s) fates%bc_out(s)%litt_flux_cel_c_si(:) = 0._r8 fates%bc_out(s)%litt_flux_lig_c_si(:) = 0._r8 fates%bc_out(s)%litt_flux_lab_c_si(:) = 0._r8 + ! Yes, zero out N flux arrays for c-only runs. + ! This is because we want these on (and zero) + ! with CLM. fates%bc_out(s)%litt_flux_cel_n_si(:) = 0._r8 fates%bc_out(s)%litt_flux_lig_n_si(:) = 0._r8 fates%bc_out(s)%litt_flux_lab_n_si(:) = 0._r8 @@ -642,11 +645,13 @@ subroutine allocate_bcout(bc_out, nlevsoil_in, nlevdecomp_in) allocate(bc_out%litt_flux_cel_c_si(nlevdecomp_in)) allocate(bc_out%litt_flux_lig_c_si(nlevdecomp_in)) allocate(bc_out%litt_flux_lab_c_si(nlevdecomp_in)) + ! Yes, allocate N flux arrays for c-only runs. + ! This is because we want these on (and zero) + ! with CLM. allocate(bc_out%litt_flux_cel_n_si(nlevdecomp_in)) allocate(bc_out%litt_flux_lig_n_si(nlevdecomp_in)) allocate(bc_out%litt_flux_lab_n_si(nlevdecomp_in)) case(prt_cnp_flex_allom_hyp) - allocate(bc_out%litt_flux_cel_c_si(nlevdecomp_in)) allocate(bc_out%litt_flux_lig_c_si(nlevdecomp_in)) allocate(bc_out%litt_flux_lab_c_si(nlevdecomp_in)) @@ -656,10 +661,8 @@ subroutine allocate_bcout(bc_out, nlevsoil_in, nlevdecomp_in) allocate(bc_out%litt_flux_cel_p_si(nlevdecomp_in)) allocate(bc_out%litt_flux_lig_p_si(nlevdecomp_in)) allocate(bc_out%litt_flux_lab_p_si(nlevdecomp_in)) - allocate(bc_out%source_nh4(nlevdecomp_in)) allocate(bc_out%source_p(nlevdecomp_in)) - case default write(fates_log(), *) 'An unknown parteh hypothesis was passed' write(fates_log(), *) 'to the site level output boundary conditions' From 6ef45bbdddcf7220e8b30c857c61560a0081817c Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 13 Mar 2023 16:52:22 -0700 Subject: [PATCH 569/852] Update yml environment file --- tools/conda-luh2.yml | 1 + tools/luh2.py | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/tools/conda-luh2.yml b/tools/conda-luh2.yml index 7ac42e9f24..0be4e7b3b7 100644 --- a/tools/conda-luh2.yml +++ b/tools/conda-luh2.yml @@ -9,4 +9,5 @@ dependencies: - scipy - nco - pynco + - xesmf prefix: /home/glemieux/local/conda/miniconda3/envs/luh2 diff --git a/tools/luh2.py b/tools/luh2.py index d7a0f2d2bb..04e064c871 100644 --- a/tools/luh2.py +++ b/tools/luh2.py @@ -24,7 +24,6 @@ def importdata(inputarg): "This can be done using the luh2.attribupdate function." print() print(errmsg) - # exit(2) return(datasetout) @@ -61,6 +60,22 @@ def attribupdate(inputarg,outputarg): # ), # ]) +# Make necessary (?) changes to metadata for XESMF conservative regrid +# Any LUH2 data set should work as the input dataset, but +# we should have some sort of check to make sure that the +# data sets being used are consistent in the final calling script +def metadatachange(inputdataset,outputdataset): + + # Drop the invalid lat, lon label names + outputdatatset = inputdataset.drop(labels=['lat_bounds','lon_bounds']) + outputdatatset["lat_b"] = np.insert(inputdataset.lat_bounds[:,1].data,0,inputdataset.lat_bounds[0,0].data) + outputdatatset["lon_b"] = np.insert(inputdataset.lon_bounds[:,1].data,0,inputdataset.lon_bounds[0,0].data) + # outputdatatset["time"] = np.arange(len(fin["time"]), dtype=np.int16) + 850 + # outputdatatset["YEAR"] = xr.DataArray(np.arange(len(fin["time"]), dtype=np.int16) + 850, dims=("time")) + + # make mask of LUH2 data + outputdatatset["mask"] = xr.where(~np.isnan(inputdataset["primf_to_range"].isel(time=0)), 1, 0) + # Update the formatting to meet HLM needs # def clmformatter(): From 41928188d9a16cdb1cf0036babd8580f7256954e Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Mon, 13 Mar 2023 17:01:02 -0700 Subject: [PATCH 570/852] Fix canopy spread to 0 for large tree initialization --- main/EDInitMod.F90 | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 1af65bc71e..7b3fc344ec 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -777,8 +777,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) integer init real(r8) :: dummy_n ! set cohort n to a dummy value of 1 - real(r8) :: spread ! dummy value of canopy spread to estimate c_area - + !---------------------------------------------------------------------- patch_in%tallest => null() @@ -854,9 +853,8 @@ subroutine init_cohorts( site_in, patch_in, bc_in) ! calculate crown area of a single plant dummy_n = 1.0_r8 ! make n=1 to get area of one tree - spread = 1.0_r8 ! fix this to 0 to remove dynamics of canopy clousre, assuming a closed canopy. - - call carea_allom(temp_cohort%dbh, dummy_n, spread, temp_cohort%pft, & + + call carea_allom(temp_cohort%dbh, dummy_n, init_spread_inventory, temp_cohort%pft, & temp_cohort%crowndamage, temp_cohort%c_area) ! calculate initial density required to close canopy @@ -994,8 +992,6 @@ subroutine init_cohorts( site_in, patch_in, bc_in) write(fates_log(),*) 'c_area: ', temp_cohort%c_area write(fates_log(),*) 'p_area: ', patch_in%area - deallocate(temp_cohort) ! get rid of temporary cohort - deallocate(temp_cohort, stat=istat, errmsg=smsg) if (istat/=0) then write(fates_log(),*) 'dealloc014: fail on deallocate(temp_cohort):'//trim(smsg) From 4c9a47fa85d2c9acfe55200aaa3822f292f70cdc Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 13 Mar 2023 17:10:16 -0700 Subject: [PATCH 571/852] Continue converting Charlie's script --- tools/luh2.py | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/tools/luh2.py b/tools/luh2.py index 04e064c871..f5511dc63b 100644 --- a/tools/luh2.py +++ b/tools/luh2.py @@ -64,17 +64,44 @@ def attribupdate(inputarg,outputarg): # Any LUH2 data set should work as the input dataset, but # we should have some sort of check to make sure that the # data sets being used are consistent in the final calling script -def metadatachange(inputdataset,outputdataset): +def MetadataUpdateLUH2(inputdataset,outputdataset): - # Drop the invalid lat, lon label names + # if this is LUH2 data + # Drop the invalid lat, lon variable labels and replace with "lat_b" and "lon_b" + # This is only necessary for the conservative method (?) per xESMF docs outputdatatset = inputdataset.drop(labels=['lat_bounds','lon_bounds']) outputdatatset["lat_b"] = np.insert(inputdataset.lat_bounds[:,1].data,0,inputdataset.lat_bounds[0,0].data) outputdatatset["lon_b"] = np.insert(inputdataset.lon_bounds[:,1].data,0,inputdataset.lon_bounds[0,0].data) # outputdatatset["time"] = np.arange(len(fin["time"]), dtype=np.int16) + 850 # outputdatatset["YEAR"] = xr.DataArray(np.arange(len(fin["time"]), dtype=np.int16) + 850, dims=("time")) +def definemask(inputdataset,outputdataset,label_to_mask): # make mask of LUH2 data outputdatatset["mask"] = xr.where(~np.isnan(inputdataset["primf_to_range"].isel(time=0)), 1, 0) + # make mask of surface data file + fin2b["mask"] = fin2b["PCT_NATVEG"]> 0. + +# load CLM surface data file +def MetadataUpdateSurfDS(inputdataset,outputdataset): + + # Move this out to be handled by opening function + # fin2 = xr.open_dataset('surfdata_4x5_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc') + + # make soem chagnes to metadata + fin2b = fin2.rename_dims(dims_dict={'lsmlat':'latitude','lsmlon':'longitude'}) + fin2b['longitude'] = fin2b.LONGXY.isel(latitude=0) + fin2b['latitude'] = fin2b.LATIXY.isel(longitude=0) + +def RegridConservative(datasets_in,datasets_out,regridder): + # define the regridder transformation + regridder = xe.Regridder(dataset_in, dataset_out, "conservative") + + #regrid the various LUH2 datasets, from smallest to largest + fin_states_regrid = regridder(finb_states) + fin_management_regrid = regridder(finb_management) + + ### memory crashes on the transition data + #fin_transitions_regrid = regridder(finb) # Update the formatting to meet HLM needs # def clmformatter(): From 134ed79b55d4c80bbbf9520f7587abc0a06b4b34 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 14 Mar 2023 12:01:11 -0700 Subject: [PATCH 572/852] Update notes --- tools/luh2.py | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/tools/luh2.py b/tools/luh2.py index f5511dc63b..2fbd1a5026 100644 --- a/tools/luh2.py +++ b/tools/luh2.py @@ -10,13 +10,13 @@ # Add version checking here in case environment.yml not used # Import luh2 data -def importdata(inputarg): +def importdata(inputfile): # Open files # Check to see if a ValueError is raised which is likely due # to the LUH2 time units being undecodable by cftime module try: - datasetout = xr.open_dataset(inputarg) + datasetout = xr.open_dataset(inputfile) except ValueError as err: print("ValueError:", err) errmsg = "User direction: If error is due to units being 'years since ...' " \ @@ -31,12 +31,16 @@ def importdata(inputarg): # This issue here is that the luh2 time units start prior to # year 1672, which cftime should be able to handle, but it # appears to need a specific unit name convention "common_years" -def attribupdate(inputarg,outputarg): +def attribupdate(inputfile,output_append="modified"): + + # Define the output filename + index = inputfile.find(".nc") + outputfile = inputfile[:index] + "_" + output_append + inputfile[index:] nco = Nco() # Get the 'time:units' string from the input using ncks - timeunitstr = nco.ncks(input=inputarg,variable="time",options=["-m"]).decode() + timeunitstr = nco.ncks(input=inputfile,variable="time",options=["-m"]).decode() # Grab the units string and replace "years" with "common_years" substr = re.search('time:units.*".*"',timeunitstr) @@ -47,11 +51,15 @@ def attribupdate(inputarg,outputarg): var = "time" att_type = "c" opts = [" -a {0},{1},o,{2},{3}".format(att, var, att_type, newstr)] - nco.ncatted(input=inputarg, output=outputarg, options=opts) + nco.ncatted(input=inputfile, output=outputfile, options=opts) + + print("Generated modified output file: {}".format(outputfile)) + + return(outputfile) # The following is fixed with PR #62 for pynco but isn't in that latest update yet # on conda - # nco.ncatted(input=inputarg,output=outputarg,options=[ + # nco.ncatted(input=inputfile,output=outputfile,options=[ # Atted(mode="overwrite", # att_name="units", # var_name="time", @@ -64,12 +72,19 @@ def attribupdate(inputarg,outputarg): # Any LUH2 data set should work as the input dataset, but # we should have some sort of check to make sure that the # data sets being used are consistent in the final calling script -def MetadataUpdateLUH2(inputdataset,outputdataset): +def MetadataUpdateLUH2(inputdataset): # if this is LUH2 data # Drop the invalid lat, lon variable labels and replace with "lat_b" and "lon_b" # This is only necessary for the conservative method (?) per xESMF docs + + # Is dropping these variables really necessary? Will xESMF get confused or is this + # for the users's sake? outputdatatset = inputdataset.drop(labels=['lat_bounds','lon_bounds']) + + # Create lat and lon bounds as a single dimension array out of the LUH2 two dimensional + # _bounds array. + # xESMF needs these variable names for bounding the conservative regridding outputdatatset["lat_b"] = np.insert(inputdataset.lat_bounds[:,1].data,0,inputdataset.lat_bounds[0,0].data) outputdatatset["lon_b"] = np.insert(inputdataset.lon_bounds[:,1].data,0,inputdataset.lon_bounds[0,0].data) # outputdatatset["time"] = np.arange(len(fin["time"]), dtype=np.int16) + 850 @@ -87,8 +102,12 @@ def MetadataUpdateSurfDS(inputdataset,outputdataset): # Move this out to be handled by opening function # fin2 = xr.open_dataset('surfdata_4x5_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc') - # make soem chagnes to metadata + # Rename the surface dataset dimensions to something recognizable by xESMF. + # That said, since regridder just needs the values, I'm not sure this is necessary. + # We might just be able to rename t fin2b = fin2.rename_dims(dims_dict={'lsmlat':'latitude','lsmlon':'longitude'}) + + # Populate the new surface dataset with the actual lat/lon values fin2b['longitude'] = fin2b.LONGXY.isel(latitude=0) fin2b['latitude'] = fin2b.LATIXY.isel(longitude=0) From 8700189c41849065a32ae9e77429c772622670a4 Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Tue, 14 Mar 2023 15:55:17 -0700 Subject: [PATCH 573/852] Add param checks to ensure initd isn't zero. Remove old write statements. --- main/EDInitMod.F90 | 5 +---- main/EDPftvarcon.F90 | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 7b3fc344ec..cc859ff125 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -831,7 +831,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) ! n.b. that this is the same as currentcohort%n = %initd(pft) &AREA temp_cohort%n = temp_cohort%n * sum(site_in%use_this_pft) endif - + ! h,dbh,leafc,n from SP values or from small initial size. if(hlm_use_sp.eq.itrue)then init = itrue @@ -989,9 +989,6 @@ subroutine init_cohorts( site_in, patch_in, bc_in) temp_cohort%coage, temp_cohort%dbh, prt_obj, cstatus, rstatus, & temp_cohort%canopy_trim, temp_cohort%c_area,1,temp_cohort%crowndamage, site_in%spread, bc_in) - write(fates_log(),*) 'c_area: ', temp_cohort%c_area - write(fates_log(),*) 'p_area: ', patch_in%area - deallocate(temp_cohort, stat=istat, errmsg=smsg) if (istat/=0) then write(fates_log(),*) 'dealloc014: fail on deallocate(temp_cohort):'//trim(smsg) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index b3ec36ecc7..9d225438cc 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1522,6 +1522,7 @@ subroutine FatesCheckParams(is_master) use EDParamsMod , only : logging_mechanical_frac, logging_collateral_frac use EDParamsMod , only : logging_direct_frac,logging_export_frac use FatesInterfaceTypesMod, only : hlm_use_fixed_biogeog,hlm_use_sp, hlm_name + use FatesInterfaceTypesMod, only : hlm_use_inventory_init ! Argument logical, intent(in) :: is_master ! Only log if this is the master proc @@ -1755,7 +1756,22 @@ subroutine FatesCheckParams(is_master) end if - + ! Check that in initial density is not equal to zero in a cold-start run + !----------------------------------------------------------------------------------- + + if ( hlm_use_inventory_init == ifalse .and. & + abs( EDPftvarcon_inst%initd(ipft) ) < nearzero ) then + + write(fates_log(),*) ' In a cold start run initial density cannot be zero.' + write(fates_log(),*) ' For a bare ground run set to initial recruit density.' + write(fates_log(),*) ' If no-comp is on it is possible to initialize with larger ' + write(fates_log(),*) ' plants by setting fates_recruit_init_density to a negative number' + write(fates_log(),*) ' which will be interpreted as (absolute) initial dbh. ' + write(fates_log(),*) ' Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + + end if + ! Check if fraction of storage to reproduction is between 0-1 From da4a06dd2882ae5c4383a5ebb62286f01ee6bb77 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 16 Mar 2023 10:43:43 -0700 Subject: [PATCH 574/852] Update comments --- tools/luh2.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/luh2.py b/tools/luh2.py index 2fbd1a5026..7416f16018 100644 --- a/tools/luh2.py +++ b/tools/luh2.py @@ -68,6 +68,13 @@ def attribupdate(inputfile,output_append="modified"): # ), # ]) +# Fix the boundaries of the LUH2 data +# Each lat/lon boundary array is a 2D array corresponding to the bounds of each +# coordinate position (e.g. lat_boundary would be 90.0 and 89.75 for lat coordinate +# of 89.875). +def BoundsFixLUH2(): + + # Make necessary (?) changes to metadata for XESMF conservative regrid # Any LUH2 data set should work as the input dataset, but # we should have some sort of check to make sure that the @@ -80,7 +87,7 @@ def MetadataUpdateLUH2(inputdataset): # Is dropping these variables really necessary? Will xESMF get confused or is this # for the users's sake? - outputdatatset = inputdataset.drop(labels=['lat_bounds','lon_bounds']) + # outputdatatset = inputdataset.drop(labels=['lat_bounds','lon_bounds']) # Create lat and lon bounds as a single dimension array out of the LUH2 two dimensional # _bounds array. From b2ce3ee86a8e7849e425687f33d499bf39f30365 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 16 Mar 2023 12:38:17 -0700 Subject: [PATCH 575/852] Removed unused donate_frac local variable --- biogeochem/EDLoggingMortalityMod.F90 | 2 -- 1 file changed, 2 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index db7ce3756f..8328cb6b23 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -497,7 +497,6 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site real(r8) :: struct_m ! structure element mass [kg] real(r8) :: repro_m ! reproductive mass [kg] real(r8) :: retain_frac ! fraction of litter retained in the donor patch - real(r8) :: donate_frac ! fraction of litter sent to newly formed patch real(r8) :: retain_m2 ! area normalization for litter mass destined to old patch [m-2] real(r8) :: donate_m2 ! area normalization for litter mass destined to new patch [m-2] real(r8) :: dcmpy_frac ! fraction going into each decomposability pool @@ -522,7 +521,6 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site ! vis-a-vis the new and donor patch retain_frac = (1.0_r8-harvest_litter_localization) * & remainder_area/(newPatch%area+remainder_area) - donate_frac = 1.0_r8-retain_frac if(remainder_area > rsnbl_math_prec) then retain_m2 = retain_frac/remainder_area From 1f58adb5f5eb0ee67cbd09199a023206c2806146 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 17 Mar 2023 11:04:26 -0700 Subject: [PATCH 576/852] Add xml patch file for parameter file update This commit also removes a redundant long name --- .../api25.2.0_031723_fates_params_default.cdl | 1554 +++++++++++++++++ .../archive/api25.2.0_031723_pr984.xml | 69 + parameter_files/fates_params_default.cdl | 1 - 3 files changed, 1623 insertions(+), 1 deletion(-) create mode 100644 parameter_files/archive/api25.2.0_031723_fates_params_default.cdl create mode 100644 parameter_files/archive/api25.2.0_031723_pr984.xml diff --git a/parameter_files/archive/api25.2.0_031723_fates_params_default.cdl b/parameter_files/archive/api25.2.0_031723_fates_params_default.cdl new file mode 100644 index 0000000000..7cf0fe3135 --- /dev/null +++ b/parameter_files/archive/api25.2.0_031723_fates_params_default.cdl @@ -0,0 +1,1554 @@ +netcdf fates_params_default { +dimensions: + fates_NCWD = 4 ; + fates_history_age_bins = 7 ; + fates_history_coage_bins = 2 ; + fates_history_damage_bins = 2 ; + fates_history_height_bins = 6 ; + fates_history_size_bins = 13 ; + fates_hlm_pftno = 14 ; + fates_hydr_organs = 4 ; + fates_leafage_class = 1 ; + fates_litterclass = 6 ; + fates_pft = 12 ; + fates_plant_organs = 4 ; + fates_string_length = 60 ; +variables: + double fates_history_ageclass_bin_edges(fates_history_age_bins) ; + fates_history_ageclass_bin_edges:units = "yr" ; + fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; + double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; + fates_history_coageclass_bin_edges:units = "years" ; + fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; + double fates_history_height_bin_edges(fates_history_height_bins) ; + fates_history_height_bin_edges:units = "m" ; + fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; + double fates_history_damage_bin_edges(fates_history_damage_bins) ; + fates_history_damage_bin_edges:units = "% crown loss" ; + fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; + double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; + fates_history_sizeclass_bin_edges:units = "cm" ; + fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; + double fates_alloc_organ_id(fates_plant_organs) ; + fates_alloc_organ_id:units = "unitless" ; + fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; + double fates_hydro_htftype_node(fates_hydr_organs) ; + fates_hydro_htftype_node:units = "unitless" ; + fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; + char fates_pftname(fates_pft, fates_string_length) ; + fates_pftname:units = "unitless - string" ; + fates_pftname:long_name = "Description of plant type" ; + char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; + fates_hydro_organ_name:units = "unitless - string" ; + fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; + char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; + fates_alloc_organ_name:units = "unitless - string" ; + fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; + 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" ; + 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" ; + double fates_alloc_storage_cushion(fates_pft) ; + fates_alloc_storage_cushion:units = "fraction" ; + fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; + double fates_alloc_store_priority_frac(fates_pft) ; + fates_alloc_store_priority_frac:units = "unitless" ; + fates_alloc_store_priority_frac:long_name = "for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage" ; + double fates_allom_agb1(fates_pft) ; + fates_allom_agb1:units = "variable" ; + fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; + double fates_allom_agb2(fates_pft) ; + fates_allom_agb2:units = "variable" ; + fates_allom_agb2:long_name = "Parameter 2 for agb allometry" ; + double fates_allom_agb3(fates_pft) ; + fates_allom_agb3:units = "variable" ; + fates_allom_agb3:long_name = "Parameter 3 for agb allometry" ; + double fates_allom_agb4(fates_pft) ; + fates_allom_agb4:units = "variable" ; + fates_allom_agb4:long_name = "Parameter 4 for agb allometry" ; + double fates_allom_agb_frac(fates_pft) ; + fates_allom_agb_frac:units = "fraction" ; + fates_allom_agb_frac:long_name = "Fraction of woody biomass that is above ground" ; + double fates_allom_amode(fates_pft) ; + fates_allom_amode:units = "index" ; + fates_allom_amode:long_name = "AGB allometry function index." ; + double fates_allom_blca_expnt_diff(fates_pft) ; + fates_allom_blca_expnt_diff:units = "unitless" ; + fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; + double fates_allom_cmode(fates_pft) ; + fates_allom_cmode:units = "index" ; + fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; + double fates_allom_crown_depth_frac(fates_pft) ; + fates_allom_crown_depth_frac:units = "fraction" ; + fates_allom_crown_depth_frac:long_name = "the depth of a cohort crown as a fraction of its height" ; + double fates_allom_d2bl1(fates_pft) ; + fates_allom_d2bl1:units = "variable" ; + fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; + double fates_allom_d2bl2(fates_pft) ; + fates_allom_d2bl2:units = "variable" ; + fates_allom_d2bl2:long_name = "Parameter 2 for d2bl allometry" ; + double fates_allom_d2bl3(fates_pft) ; + fates_allom_d2bl3:units = "unitless" ; + fates_allom_d2bl3:long_name = "Parameter 3 for d2bl allometry" ; + double fates_allom_d2ca_coefficient_max(fates_pft) ; + fates_allom_d2ca_coefficient_max:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_max:long_name = "max (savanna) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2ca_coefficient_min(fates_pft) ; + fates_allom_d2ca_coefficient_min:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_min:long_name = "min (forest) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2h1(fates_pft) ; + fates_allom_d2h1:units = "variable" ; + fates_allom_d2h1:long_name = "Parameter 1 for d2h allometry (intercept, or c)" ; + double fates_allom_d2h2(fates_pft) ; + fates_allom_d2h2:units = "variable" ; + fates_allom_d2h2:long_name = "Parameter 2 for d2h allometry (slope, or m)" ; + double fates_allom_d2h3(fates_pft) ; + fates_allom_d2h3:units = "variable" ; + fates_allom_d2h3:long_name = "Parameter 3 for d2h allometry (optional)" ; + double fates_allom_dbh_maxheight(fates_pft) ; + fates_allom_dbh_maxheight:units = "cm" ; + fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; + double fates_allom_fmode(fates_pft) ; + fates_allom_fmode:units = "index" ; + fates_allom_fmode:long_name = "fine root biomass allometry function index." ; + double fates_allom_fnrt_prof_a(fates_pft) ; + fates_allom_fnrt_prof_a:units = "unitless" ; + fates_allom_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; + double fates_allom_fnrt_prof_b(fates_pft) ; + fates_allom_fnrt_prof_b:units = "unitless" ; + fates_allom_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; + double fates_allom_fnrt_prof_mode(fates_pft) ; + fates_allom_fnrt_prof_mode:units = "index" ; + fates_allom_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; + double fates_allom_frbstor_repro(fates_pft) ; + fates_allom_frbstor_repro:units = "fraction" ; + fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; + double fates_allom_hmode(fates_pft) ; + fates_allom_hmode:units = "index" ; + fates_allom_hmode:long_name = "height allometry function index." ; + double fates_allom_l2fr(fates_pft) ; + fates_allom_l2fr:units = "gC/gC" ; + fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; + double fates_allom_la_per_sa_int(fates_pft) ; + fates_allom_la_per_sa_int:units = "m2/cm2" ; + fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; + double fates_allom_la_per_sa_slp(fates_pft) ; + fates_allom_la_per_sa_slp:units = "m2/cm2/m" ; + fates_allom_la_per_sa_slp:long_name = "Leaf area per sapwood area rate of change with height, slope (optional)" ; + double fates_allom_lmode(fates_pft) ; + fates_allom_lmode:units = "index" ; + fates_allom_lmode:long_name = "leaf biomass allometry function index." ; + double fates_allom_sai_scaler(fates_pft) ; + fates_allom_sai_scaler:units = "m2/m2" ; + fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; + double fates_allom_smode(fates_pft) ; + fates_allom_smode:units = "index" ; + fates_allom_smode:long_name = "sapwood allometry function index." ; + double fates_allom_stmode(fates_pft) ; + fates_allom_stmode:units = "index" ; + fates_allom_stmode:long_name = "storage allometry function index: 1) Storage proportional to leaf biomass (with trimming), 2) Storage proportional to maximum leaf biomass (not trimmed)" ; + double fates_allom_zroot_k(fates_pft) ; + fates_allom_zroot_k:units = "unitless" ; + fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; + double fates_allom_zroot_max_dbh(fates_pft) ; + fates_allom_zroot_max_dbh:units = "cm" ; + fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; + double fates_allom_zroot_max_z(fates_pft) ; + fates_allom_zroot_max_z:units = "m" ; + fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_allom_zroot_min_dbh(fates_pft) ; + fates_allom_zroot_min_dbh:units = "cm" ; + fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; + double fates_allom_zroot_min_z(fates_pft) ; + fates_allom_zroot_min_z:units = "m" ; + fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_c2b(fates_pft) ; + fates_c2b:units = "ratio" ; + fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; + double fates_cnp_eca_alpha_ptase(fates_pft) ; + fates_cnp_eca_alpha_ptase:units = "g/m3" ; + fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; + double fates_cnp_eca_decompmicc(fates_pft) ; + fates_cnp_eca_decompmicc:units = "gC/m3" ; + fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; + double fates_cnp_eca_km_nh4(fates_pft) ; + fates_cnp_eca_km_nh4:units = "gN/m3" ; + fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; + double fates_cnp_eca_km_no3(fates_pft) ; + fates_cnp_eca_km_no3:units = "gN/m3" ; + fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; + double fates_cnp_eca_km_p(fates_pft) ; + fates_cnp_eca_km_p:units = "gP/m3" ; + fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; + double fates_cnp_eca_km_ptase(fates_pft) ; + fates_cnp_eca_km_ptase:units = "gP/m3" ; + fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; + double fates_cnp_eca_lambda_ptase(fates_pft) ; + fates_cnp_eca_lambda_ptase:units = "g/m3" ; + fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; + double fates_cnp_eca_vmax_ptase(fates_pft) ; + fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; + fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; + double fates_cnp_nfix1(fates_pft) ; + fates_cnp_nfix1:units = "fraction" ; + fates_cnp_nfix1:long_name = "fractional surcharge added to maintenance respiration that drives symbiotic fixation" ; + double fates_cnp_nitr_store_ratio(fates_pft) ; + fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; + fates_cnp_nitr_store_ratio:long_name = "storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code)" ; + double fates_cnp_phos_store_ratio(fates_pft) ; + fates_cnp_phos_store_ratio:units = "(gP/gP)" ; + fates_cnp_phos_store_ratio:long_name = "storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code)" ; + double fates_cnp_pid_kd(fates_pft) ; + fates_cnp_pid_kd:units = "unknown" ; + fates_cnp_pid_kd:long_name = "derivative constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_pid_ki(fates_pft) ; + fates_cnp_pid_ki:units = "unknown" ; + fates_cnp_pid_ki:long_name = "integral constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_pid_kp(fates_pft) ; + fates_cnp_pid_kp:units = "unknown" ; + fates_cnp_pid_kp:long_name = "proportional constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_prescribed_nuptake(fates_pft) ; + fates_cnp_prescribed_nuptake:units = "fraction" ; + fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; + double fates_cnp_prescribed_puptake(fates_pft) ; + fates_cnp_prescribed_puptake:units = "fraction" ; + fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; + double fates_cnp_store_ovrflw_frac(fates_pft) ; + fates_cnp_store_ovrflw_frac:units = "fraction" ; + fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; + double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_nitr_retrans:units = "fraction" ; + fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; + double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_phos_retrans:units = "fraction" ; + fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; + double fates_cnp_vmax_nh4(fates_pft) ; + fates_cnp_vmax_nh4:units = "gN/gC/s" ; + fates_cnp_vmax_nh4:long_name = "maximum (potential) uptake rate of NH4 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_nh4 for usage)" ; + double fates_cnp_vmax_no3(fates_pft) ; + fates_cnp_vmax_no3:units = "gN/gC/s" ; + fates_cnp_vmax_no3:long_name = "maximum (potential) uptake rate of NO3 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_no3 for usage)" ; + double fates_cnp_vmax_p(fates_pft) ; + fates_cnp_vmax_p:units = "gP/gC/s" ; + fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; + double fates_damage_frac(fates_pft) ; + fates_damage_frac:units = "fraction" ; + fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; + double fates_damage_mort_p1(fates_pft) ; + fates_damage_mort_p1:units = "fraction" ; + fates_damage_mort_p1:long_name = "inflection point of damage mortality function, a value of 0.8 means 50% mortality with 80% loss of crown, turn off with a large number" ; + double fates_damage_mort_p2(fates_pft) ; + fates_damage_mort_p2:units = "unitless" ; + fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; + 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_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" ; + double fates_fire_alpha_SH(fates_pft) ; + fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; + fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; + double fates_fire_bark_scaler(fates_pft) ; + fates_fire_bark_scaler:units = "fraction" ; + fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; + double fates_fire_crown_kill(fates_pft) ; + fates_fire_crown_kill:units = "NA" ; + fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; + double fates_frag_fnrt_fcel(fates_pft) ; + fates_frag_fnrt_fcel:units = "fraction" ; + fates_frag_fnrt_fcel:long_name = "Fine root litter cellulose fraction" ; + double fates_frag_fnrt_flab(fates_pft) ; + fates_frag_fnrt_flab:units = "fraction" ; + fates_frag_fnrt_flab:long_name = "Fine root litter labile fraction" ; + double fates_frag_fnrt_flig(fates_pft) ; + fates_frag_fnrt_flig:units = "fraction" ; + fates_frag_fnrt_flig:long_name = "Fine root litter lignin fraction" ; + double fates_frag_leaf_fcel(fates_pft) ; + fates_frag_leaf_fcel:units = "fraction" ; + fates_frag_leaf_fcel:long_name = "Leaf litter cellulose fraction" ; + double fates_frag_leaf_flab(fates_pft) ; + fates_frag_leaf_flab:units = "fraction" ; + fates_frag_leaf_flab:long_name = "Leaf litter labile fraction" ; + double fates_frag_leaf_flig(fates_pft) ; + fates_frag_leaf_flig:units = "fraction" ; + fates_frag_leaf_flig:long_name = "Leaf litter lignin fraction" ; + double fates_frag_seed_decay_rate(fates_pft) ; + fates_frag_seed_decay_rate:units = "yr-1" ; + fates_frag_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; + double fates_grperc(fates_pft) ; + fates_grperc:units = "unitless" ; + fates_grperc:long_name = "Growth respiration factor" ; + double fates_hydro_avuln_gs(fates_pft) ; + fates_hydro_avuln_gs:units = "unitless" ; + fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; + double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; + fates_hydro_avuln_node:units = "unitless" ; + fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; + double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; + fates_hydro_epsil_node:units = "MPa" ; + fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; + double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; + fates_hydro_fcap_node:units = "unitless" ; + fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; + double fates_hydro_k_lwp(fates_pft) ; + fates_hydro_k_lwp:units = "unitless" ; + fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; + double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; + fates_hydro_kmax_node:units = "kg/MPa/m/s" ; + fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; + double fates_hydro_p50_gs(fates_pft) ; + fates_hydro_p50_gs:units = "MPa" ; + fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; + double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; + fates_hydro_p50_node:units = "MPa" ; + fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; + double fates_hydro_p_taper(fates_pft) ; + fates_hydro_p_taper:units = "unitless" ; + fates_hydro_p_taper:long_name = "xylem taper exponent" ; + double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pinot_node:units = "MPa" ; + fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; + double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pitlp_node:units = "MPa" ; + fates_hydro_pitlp_node:long_name = "turgor loss point" ; + double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; + fates_hydro_resid_node:units = "cm3/cm3" ; + fates_hydro_resid_node:long_name = "residual water conent" ; + double fates_hydro_rfrac_stem(fates_pft) ; + fates_hydro_rfrac_stem:units = "fraction" ; + fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; + double fates_hydro_rs2(fates_pft) ; + fates_hydro_rs2:units = "m" ; + fates_hydro_rs2:long_name = "absorbing root radius" ; + double fates_hydro_srl(fates_pft) ; + fates_hydro_srl:units = "m g-1" ; + fates_hydro_srl:long_name = "specific root length" ; + double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; + fates_hydro_thetas_node:units = "cm3/cm3" ; + fates_hydro_thetas_node:long_name = "saturated water content" ; + double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_alpha_node:units = "MPa-1" ; + fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; + double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_m_node:units = "unitless" ; + fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; + 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_leaf_c3psn(fates_pft) ; + fates_leaf_c3psn:units = "flag" ; + fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; + double fates_leaf_jmaxha(fates_pft) ; + fates_leaf_jmaxha:units = "J/mol" ; + fates_leaf_jmaxha:long_name = "activation energy for jmax" ; + double fates_leaf_jmaxhd(fates_pft) ; + fates_leaf_jmaxhd:units = "J/mol" ; + fates_leaf_jmaxhd:long_name = "deactivation energy for jmax" ; + double fates_leaf_jmaxse(fates_pft) ; + fates_leaf_jmaxse:units = "J/mol/K" ; + fates_leaf_jmaxse:long_name = "entropy term for jmax" ; + double fates_leaf_slamax(fates_pft) ; + fates_leaf_slamax:units = "m^2/gC" ; + fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; + double fates_leaf_slatop(fates_pft) ; + fates_leaf_slatop:units = "m^2/gC" ; + fates_leaf_slatop:long_name = "Specific Leaf Area (SLA) at top of canopy, projected area basis" ; + double fates_leaf_stomatal_intercept(fates_pft) ; + fates_leaf_stomatal_intercept:units = "umol H2O/m**2/s" ; + fates_leaf_stomatal_intercept:long_name = "Minimum unstressed stomatal conductance for Ball-Berry model and Medlyn model" ; + double fates_leaf_stomatal_slope_ballberry(fates_pft) ; + fates_leaf_stomatal_slope_ballberry:units = "unitless" ; + fates_leaf_stomatal_slope_ballberry:long_name = "stomatal slope parameter, as per Ball-Berry" ; + double fates_leaf_stomatal_slope_medlyn(fates_pft) ; + fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; + fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; + double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; + fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; + fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; + double fates_leaf_vcmaxha(fates_pft) ; + fates_leaf_vcmaxha:units = "J/mol" ; + fates_leaf_vcmaxha:long_name = "activation energy for vcmax" ; + double fates_leaf_vcmaxhd(fates_pft) ; + fates_leaf_vcmaxhd:units = "J/mol" ; + fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax" ; + double fates_leaf_vcmaxse(fates_pft) ; + fates_leaf_vcmaxse:units = "J/mol/K" ; + fates_leaf_vcmaxse:long_name = "entropy term for vcmax" ; + double fates_maintresp_leaf_atkin2017_baserate(fates_pft) ; + fates_maintresp_leaf_atkin2017_baserate:units = "umol CO2/m^2/s" ; + fates_maintresp_leaf_atkin2017_baserate:long_name = "Leaf maintenance respiration base rate parameter (r0) per Atkin et al 2017" ; + double fates_maintresp_leaf_ryan1991_baserate(fates_pft) ; + fates_maintresp_leaf_ryan1991_baserate:units = "gC/gN/s" ; + fates_maintresp_leaf_ryan1991_baserate:long_name = "Leaf maintenance respiration base rate per Ryan et al 1991" ; + double fates_maintresp_reduction_curvature(fates_pft) ; + fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; + fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; + double fates_maintresp_reduction_intercept(fates_pft) ; + fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; + fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; + double fates_mort_bmort(fates_pft) ; + fates_mort_bmort:units = "1/yr" ; + fates_mort_bmort:long_name = "background mortality rate" ; + double fates_mort_freezetol(fates_pft) ; + fates_mort_freezetol:units = "degrees C" ; + fates_mort_freezetol:long_name = "minimum temperature tolerance" ; + double fates_mort_hf_flc_threshold(fates_pft) ; + fates_mort_hf_flc_threshold:units = "fraction" ; + fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; + double fates_mort_hf_sm_threshold(fates_pft) ; + fates_mort_hf_sm_threshold:units = "unitless" ; + fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; + double fates_mort_ip_age_senescence(fates_pft) ; + fates_mort_ip_age_senescence:units = "years" ; + fates_mort_ip_age_senescence:long_name = "Mortality cohort age senescence inflection point. If _ this mortality term is off. Setting this value turns on age dependent mortality. " ; + double fates_mort_ip_size_senescence(fates_pft) ; + fates_mort_ip_size_senescence:units = "dbh cm" ; + fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; + double fates_mort_prescribed_canopy(fates_pft) ; + fates_mort_prescribed_canopy:units = "1/yr" ; + fates_mort_prescribed_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; + double fates_mort_prescribed_understory(fates_pft) ; + fates_mort_prescribed_understory:units = "1/yr" ; + fates_mort_prescribed_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; + double fates_mort_r_age_senescence(fates_pft) ; + fates_mort_r_age_senescence:units = "mortality rate year^-1" ; + fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; + double fates_mort_r_size_senescence(fates_pft) ; + fates_mort_r_size_senescence:units = "mortality rate dbh^-1" ; + fates_mort_r_size_senescence:long_name = "Mortality dbh senescence rate of change. Sensible range is around 0.03-0.06. Larger values give steeper mortality curves." ; + double fates_mort_scalar_coldstress(fates_pft) ; + fates_mort_scalar_coldstress:units = "1/yr" ; + fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; + double fates_mort_scalar_cstarvation(fates_pft) ; + fates_mort_scalar_cstarvation:units = "1/yr" ; + fates_mort_scalar_cstarvation:long_name = "maximum mortality rate from carbon starvation" ; + double fates_mort_scalar_hydrfailure(fates_pft) ; + fates_mort_scalar_hydrfailure:units = "1/yr" ; + fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; + double fates_nonhydro_smpsc(fates_pft) ; + fates_nonhydro_smpsc:units = "mm" ; + fates_nonhydro_smpsc:long_name = "Soil water potential at full stomatal closure" ; + double fates_nonhydro_smpso(fates_pft) ; + fates_nonhydro_smpso:units = "mm" ; + fates_nonhydro_smpso:long_name = "Soil water potential at full stomatal opening" ; + double fates_phen_cold_size_threshold(fates_pft) ; + fates_phen_cold_size_threshold:units = "cm" ; + fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; + double fates_phen_evergreen(fates_pft) ; + fates_phen_evergreen:units = "logical flag" ; + fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; + double fates_phen_flush_fraction(fates_pft) ; + fates_phen_flush_fraction:units = "fraction" ; + fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; + double fates_phen_fnrt_drop_frac(fates_pft) ; + fates_phen_fnrt_drop_frac:units = "fraction" ; + fates_phen_fnrt_drop_frac:long_name = "fraction of fine roots to drop during drought or cold" ; + double fates_phen_season_decid(fates_pft) ; + fates_phen_season_decid:units = "logical flag" ; + fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; + double fates_phen_stem_drop_fraction(fates_pft) ; + fates_phen_stem_drop_fraction:units = "fraction" ; + fates_phen_stem_drop_fraction:long_name = "fraction of stems to drop for non-woody species during drought/cold" ; + double fates_phen_stress_decid(fates_pft) ; + fates_phen_stress_decid:units = "logical flag" ; + fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; + double fates_prescribed_npp_canopy(fates_pft) ; + fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; + double fates_prescribed_npp_understory(fates_pft) ; + fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; + double fates_rad_leaf_clumping_index(fates_pft) ; + fates_rad_leaf_clumping_index:units = "fraction (0-1)" ; + fates_rad_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; + double fates_rad_leaf_rhonir(fates_pft) ; + fates_rad_leaf_rhonir:units = "fraction" ; + fates_rad_leaf_rhonir:long_name = "Leaf reflectance: near-IR" ; + double fates_rad_leaf_rhovis(fates_pft) ; + fates_rad_leaf_rhovis:units = "fraction" ; + fates_rad_leaf_rhovis:long_name = "Leaf reflectance: visible" ; + double fates_rad_leaf_taunir(fates_pft) ; + fates_rad_leaf_taunir:units = "fraction" ; + fates_rad_leaf_taunir:long_name = "Leaf transmittance: near-IR" ; + double fates_rad_leaf_tauvis(fates_pft) ; + fates_rad_leaf_tauvis:units = "fraction" ; + fates_rad_leaf_tauvis:long_name = "Leaf transmittance: visible" ; + double fates_rad_leaf_xl(fates_pft) ; + fates_rad_leaf_xl:units = "unitless" ; + fates_rad_leaf_xl:long_name = "Leaf/stem orientation index" ; + double fates_rad_stem_rhonir(fates_pft) ; + fates_rad_stem_rhonir:units = "fraction" ; + fates_rad_stem_rhonir:long_name = "Stem reflectance: near-IR" ; + double fates_rad_stem_rhovis(fates_pft) ; + fates_rad_stem_rhovis:units = "fraction" ; + fates_rad_stem_rhovis:long_name = "Stem reflectance: visible" ; + double fates_rad_stem_taunir(fates_pft) ; + fates_rad_stem_taunir:units = "fraction" ; + fates_rad_stem_taunir:long_name = "Stem transmittance: near-IR" ; + double fates_rad_stem_tauvis(fates_pft) ; + fates_rad_stem_tauvis:units = "fraction" ; + fates_rad_stem_tauvis:long_name = "Stem transmittance: visible" ; + double fates_recruit_height_min(fates_pft) ; + fates_recruit_height_min:units = "m" ; + fates_recruit_height_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; + double fates_recruit_init_density(fates_pft) ; + fates_recruit_init_density:units = "stems/m2" ; + fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation" ; + double fates_recruit_prescribed_rate(fates_pft) ; + fates_recruit_prescribed_rate:units = "n/yr" ; + fates_recruit_prescribed_rate:long_name = "recruitment rate for prescribed physiology mode" ; + double fates_recruit_seed_alloc(fates_pft) ; + fates_recruit_seed_alloc:units = "fraction" ; + fates_recruit_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; + double fates_recruit_seed_alloc_mature(fates_pft) ; + fates_recruit_seed_alloc_mature:units = "fraction" ; + fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; + double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; + fates_recruit_seed_dbh_repro_threshold:units = "cm" ; + fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter where the plant will increase allocation to the seed pool by fraction: fates_recruit_seed_alloc_mature" ; + double fates_recruit_seed_germination_rate(fates_pft) ; + fates_recruit_seed_germination_rate:units = "yr-1" ; + fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; + double fates_recruit_seed_supplement(fates_pft) ; + fates_recruit_seed_supplement:units = "KgC/m2/yr" ; + fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; + double fates_stoich_nitr(fates_plant_organs, fates_pft) ; + fates_stoich_nitr:units = "gN/gC" ; + fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; + double fates_stoich_phos(fates_plant_organs, fates_pft) ; + fates_stoich_phos:units = "gP/gC" ; + fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; + double fates_trim_inc(fates_pft) ; + fates_trim_inc:units = "m2/m2" ; + fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; + double fates_trim_limit(fates_pft) ; + fates_trim_limit:units = "m2/m2" ; + fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; + double fates_turb_displar(fates_pft) ; + fates_turb_displar:units = "unitless" ; + fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; + double fates_turb_leaf_diameter(fates_pft) ; + fates_turb_leaf_diameter:units = "m" ; + fates_turb_leaf_diameter:long_name = "Characteristic leaf dimension" ; + double fates_turb_z0mr(fates_pft) ; + fates_turb_z0mr:units = "unitless" ; + fates_turb_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; + double fates_turnover_branch(fates_pft) ; + fates_turnover_branch:units = "yr" ; + fates_turnover_branch:long_name = "turnover time of branches" ; + double fates_turnover_fnrt(fates_pft) ; + fates_turnover_fnrt:units = "yr" ; + fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; + double fates_turnover_leaf(fates_leafage_class, fates_pft) ; + fates_turnover_leaf:units = "yr" ; + fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; + double fates_turnover_senleaf_fdrought(fates_pft) ; + fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; + fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; + double fates_wood_density(fates_pft) ; + fates_wood_density:units = "g/cm3" ; + fates_wood_density:long_name = "mean density of woody tissue in plant" ; + double fates_woody(fates_pft) ; + fates_woody:units = "logical flag" ; + fates_woody:long_name = "Binary woody lifeform flag" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_fire_FBD(fates_litterclass) ; + fates_fire_FBD:units = "kg Biomass/m3" ; + fates_fire_FBD:long_name = "fuel bulk density" ; + double fates_fire_low_moisture_Coeff(fates_litterclass) ; + fates_fire_low_moisture_Coeff:units = "NA" ; + fates_fire_low_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_low_moisture_Slope(fates_litterclass) ; + fates_fire_low_moisture_Slope:units = "NA" ; + fates_fire_low_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture(fates_litterclass) ; + fates_fire_mid_moisture:units = "NA" ; + fates_fire_mid_moisture:long_name = "spitfire litter moisture threshold to be considered medium dry" ; + double fates_fire_mid_moisture_Coeff(fates_litterclass) ; + fates_fire_mid_moisture_Coeff:units = "NA" ; + fates_fire_mid_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture_Slope(fates_litterclass) ; + fates_fire_mid_moisture_Slope:units = "NA" ; + fates_fire_mid_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_min_moisture(fates_litterclass) ; + fates_fire_min_moisture:units = "NA" ; + fates_fire_min_moisture:long_name = "spitfire litter moisture threshold to be considered very dry" ; + double fates_fire_SAV(fates_litterclass) ; + fates_fire_SAV:units = "cm-1" ; + fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; + double fates_frag_maxdecomp(fates_litterclass) ; + fates_frag_maxdecomp:units = "yr-1" ; + fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; + 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_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" ; + double fates_cnp_eca_plant_escalar ; + fates_cnp_eca_plant_escalar:units = "" ; + fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; + double fates_cohort_age_fusion_tol ; + fates_cohort_age_fusion_tol:units = "unitless" ; + fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; + double fates_cohort_size_fusion_tol ; + fates_cohort_size_fusion_tol:units = "unitless" ; + fates_cohort_size_fusion_tol:long_name = "minimum fraction in difference in dbh between cohorts" ; + double fates_comp_excln ; + fates_comp_excln:units = "none" ; + fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; + double fates_damage_canopy_layer_code ; + fates_damage_canopy_layer_code:units = "unitless" ; + fates_damage_canopy_layer_code:long_name = "Integer code that decides whether damage affects canopy trees (1), understory trees (2)" ; + double fates_damage_event_code ; + fates_damage_event_code:units = "unitless" ; + fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; + double fates_dev_arbitrary ; + fates_dev_arbitrary:units = "unknown" ; + fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; + double fates_fire_active_crown_fire ; + fates_fire_active_crown_fire:units = "0 or 1" ; + fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; + double fates_fire_cg_strikes ; + fates_fire_cg_strikes:units = "fraction (0-1)" ; + fates_fire_cg_strikes:long_name = "fraction of cloud to ground lightning strikes" ; + double fates_fire_drying_ratio ; + fates_fire_drying_ratio:units = "NA" ; + fates_fire_drying_ratio:long_name = "spitfire parameter, fire drying ratio for fuel moisture, alpha_FMC EQ 6 Thonicke et al 2010" ; + double fates_fire_durat_slope ; + fates_fire_durat_slope:units = "NA" ; + fates_fire_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; + double fates_fire_fdi_a ; + fates_fire_fdi_a:units = "NA" ; + fates_fire_fdi_a:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010" ; + double fates_fire_fdi_alpha ; + fates_fire_fdi_alpha:units = "NA" ; + fates_fire_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; + double fates_fire_fdi_b ; + fates_fire_fdi_b:units = "NA" ; + fates_fire_fdi_b:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010 " ; + double fates_fire_fuel_energy ; + fates_fire_fuel_energy:units = "kJ/kg" ; + fates_fire_fuel_energy:long_name = "spitfire parameter, heat content of fuel" ; + double fates_fire_max_durat ; + fates_fire_max_durat:units = "minutes" ; + fates_fire_max_durat:long_name = "spitfire parameter, fire maximum duration, Equation 14 Thonicke et al 2010" ; + double fates_fire_miner_damp ; + fates_fire_miner_damp:units = "NA" ; + fates_fire_miner_damp:long_name = "spitfire parameter, mineral-dampening coefficient EQ A1 Thonicke et al 2010 " ; + double fates_fire_miner_total ; + fates_fire_miner_total:units = "fraction" ; + fates_fire_miner_total:long_name = "spitfire parameter, total mineral content, Table A1 Thonicke et al 2010" ; + double fates_fire_nignitions ; + fates_fire_nignitions:units = "ignitions per year per km2" ; + fates_fire_nignitions:long_name = "number of annual ignitions per square km" ; + double fates_fire_part_dens ; + fates_fire_part_dens:units = "kg/m2" ; + fates_fire_part_dens:long_name = "spitfire parameter, oven dry particle density, Table A1 Thonicke et al 2010" ; + double fates_fire_threshold ; + fates_fire_threshold:units = "kW/m" ; + fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; + double fates_frag_cwd_fcel ; + fates_frag_cwd_fcel:units = "unitless" ; + fates_frag_cwd_fcel:long_name = "Cellulose fraction for CWD" ; + double fates_frag_cwd_flig ; + fates_frag_cwd_flig:units = "unitless" ; + fates_frag_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; + double fates_hydro_kmax_rsurf1 ; + fates_hydro_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; + double fates_hydro_kmax_rsurf2 ; + fates_hydro_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; + double fates_hydro_psi0 ; + fates_hydro_psi0:units = "MPa" ; + fates_hydro_psi0:long_name = "sapwood water potential at saturation" ; + double fates_hydro_psicap ; + fates_hydro_psicap:units = "MPa" ; + fates_hydro_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; + 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_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" ; + double fates_landuse_logging_collateral_frac ; + fates_landuse_logging_collateral_frac:units = "fraction" ; + fates_landuse_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; + double fates_landuse_logging_dbhmax ; + fates_landuse_logging_dbhmax:units = "cm" ; + fates_landuse_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; + double fates_landuse_logging_dbhmax_infra ; + fates_landuse_logging_dbhmax_infra:units = "cm" ; + fates_landuse_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; + double fates_landuse_logging_dbhmin ; + fates_landuse_logging_dbhmin:units = "cm" ; + fates_landuse_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; + double fates_landuse_logging_direct_frac ; + fates_landuse_logging_direct_frac:units = "fraction" ; + fates_landuse_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; + double fates_landuse_logging_event_code ; + fates_landuse_logging_event_code:units = "unitless" ; + fates_landuse_logging_event_code:long_name = "Integer code that options how logging events are structured" ; + double fates_landuse_logging_export_frac ; + fates_landuse_logging_export_frac:units = "fraction" ; + fates_landuse_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; + double fates_landuse_logging_mechanical_frac ; + fates_landuse_logging_mechanical_frac:units = "fraction" ; + fates_landuse_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; + double fates_landuse_pprodharv10_forest_mean ; + fates_landuse_pprodharv10_forest_mean:units = "fraction" ; + fates_landuse_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; + double fates_leaf_photo_temp_acclim_timescale ; + fates_leaf_photo_temp_acclim_timescale:units = "days" ; + fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; + double fates_leaf_photo_tempsens_model ; + fates_leaf_photo_tempsens_model:units = "unitless" ; + fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; + double fates_leaf_stomatal_assim_model ; + fates_leaf_stomatal_assim_model:units = "unitless" ; + fates_leaf_stomatal_assim_model:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; + double fates_leaf_stomatal_model ; + fates_leaf_stomatal_model:units = "unitless" ; + fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; + double fates_leaf_theta_cj_c3 ; + fates_leaf_theta_cj_c3:units = "unitless" ; + fates_leaf_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; + double fates_leaf_theta_cj_c4 ; + fates_leaf_theta_cj_c4:units = "unitless" ; + fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; + double fates_maintresp_leaf_model ; + fates_maintresp_leaf_model:units = "unitless" ; + fates_maintresp_leaf_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991) (NOT USED)" ; + double fates_maintresp_nonleaf_baserate ; + fates_maintresp_nonleaf_baserate:units = "gC/gN/s" ; + fates_maintresp_nonleaf_baserate:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; + double fates_maxcohort ; + fates_maxcohort:units = "count" ; + fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; + double fates_maxpatch_primary ; + fates_maxpatch_primary:units = "count" ; + fates_maxpatch_primary:long_name = "maximum number of primary vegetation patches per site" ; + double fates_maxpatch_secondary ; + fates_maxpatch_secondary:units = "count" ; + fates_maxpatch_secondary:long_name = "maximum number of secondary vegetation patches per site" ; + double fates_mort_disturb_frac ; + fates_mort_disturb_frac:units = "fraction" ; + fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; + double fates_mort_understorey_death ; + fates_mort_understorey_death:units = "fraction" ; + fates_mort_understorey_death:long_name = "fraction of plants in understorey cohort impacted by overstorey tree-fall" ; + double fates_patch_fusion_tol ; + fates_patch_fusion_tol:units = "unitless" ; + fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; + double fates_phen_chilltemp ; + fates_phen_chilltemp:units = "degrees C" ; + fates_phen_chilltemp:long_name = "chilling day counting threshold for vegetation" ; + double fates_phen_coldtemp ; + fates_phen_coldtemp:units = "degrees C" ; + fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; + double fates_phen_drought_model ; + fates_phen_drought_model:units = "unitless" ; + fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; + double fates_phen_drought_threshold ; + fates_phen_drought_threshold:units = "m3/m3 or mm" ; + fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_gddthresh_a ; + fates_phen_gddthresh_a:units = "none" ; + fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_b ; + fates_phen_gddthresh_b:units = "none" ; + fates_phen_gddthresh_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_c ; + fates_phen_gddthresh_c:units = "none" ; + fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_mindaysoff ; + fates_phen_mindaysoff:units = "days" ; + fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves became off-allometry" ; + double fates_phen_mindayson ; + fates_phen_mindayson:units = "days" ; + fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; + double fates_phen_moist_threshold ; + fates_phen_moist_threshold:units = "m3/m3 or mm" ; + fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_ncolddayslim ; + fates_phen_ncolddayslim:units = "days" ; + fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; + double fates_q10_froz ; + fates_q10_froz:units = "unitless" ; + fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; + double fates_q10_mr ; + fates_q10_mr:units = "unitless" ; + fates_q10_mr:long_name = "Q10 for maintenance respiration" ; + double fates_soil_salinity ; + fates_soil_salinity:units = "ppt" ; + fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; + double fates_vai_top_bin_width ; + fates_vai_top_bin_width:units = "m2/m2" ; + fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; + double fates_vai_width_increase_factor ; + fates_vai_width_increase_factor:units = "unitless" ; + fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; + +// global attributes: + :history = "This file was generated by BatchPatchParams.py:\nCDL Base File = archive/api24.1.0_101722_fates_params_default.cdl\nXML patch file = archive/api24.1.0_101722_patch_params.xml" ; +data: + + fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; + + fates_history_coageclass_bin_edges = 0, 5 ; + + fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; + + fates_history_damage_bin_edges = 0, 80 ; + + fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, + 80, 90, 100 ; + + fates_alloc_organ_id = 1, 2, 3, 6 ; + + fates_hydro_htftype_node = 1, 1, 1, 1 ; + + fates_pftname = + "broadleaf_evergreen_tropical_tree ", + "needleleaf_evergreen_extratrop_tree ", + "needleleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_tree ", + "broadleaf_hydrodecid_tropical_tree ", + "broadleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_shrub ", + "broadleaf_hydrodecid_extratrop_shrub ", + "broadleaf_colddecid_extratrop_shrub ", + "arctic_c3_grass ", + "cool_c3_grass ", + "c4_grass " ; + + fates_hydro_organ_name = + "leaf ", + "stem ", + "transporting root ", + "absorbing root " ; + + fates_alloc_organ_name = + "leaf", + "fine root", + "sapwood", + "structure" ; + + fates_litterclass_name = + "twig ", + "small branch ", + "large branch ", + "trunk ", + "dead leaves ", + "live grass " ; + + 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, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; + + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + 1.2, 1.2, 1.2 ; + + fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8, 0.8 ; + + fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, + 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; + + fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, + 0.572, 0.572, 0.572, 0.572 ; + + fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, + 1.94, 1.94, 1.94 ; + + fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, + 0.931, 0.931, 0.931, 0.931 ; + + fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6 ; + + fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, + 0.95, 1, 1, 1 ; + + fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07 ; + + fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, + 1.3 ; + + fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, + 0.55, 0.55, 0.55 ; + + fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464 ; + + fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119 ; + + fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, + 0.64, 0.64, 0.64 ; + + fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, + 0.37, 0.37, 0.37 ; + + fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, + -999.9, -999.9, -999.9, -999.9, -999.9 ; + + fates_allom_dbh_maxheight = 90, 80, 80, 80, 90, 80, 3, 3, 2, 0.35, 0.35, 0.35 ; + + fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; + + fates_allom_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; + + fates_allom_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8 ; + + fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_zroot_k = 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 ; + + fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; + + fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + + fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 280, 280 ; + + fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, + 0.14, 0.14, 0.14 ; + + fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, + 0.27, 0.27, 0.27 ; + + fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_nfix1 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_pid_kd = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; + + fates_cnp_pid_ki = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_pid_kp = 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005 ; + + fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_turnover_nitr_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_turnover_phos_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_vmax_nh4 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, + 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; + + fates_cnp_vmax_no3 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, + 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; + + fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, + 5e-10, 5e-10, 5e-10, 5e-10 ; + + fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01 ; + + fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; + + fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, + 5.5, 5.5 ; + + fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2 ; + + fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07, 0.07 ; + + fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, + 0.775, 0.775, 0.775, 0.775, 0.775 ; + + fates_frag_fnrt_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_fnrt_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_fnrt_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_leaf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, + 0.51, 0.51, 0.51, 0.51 ; + + fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, + 0.11, 0.11 ; + + fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + 2.5, 2.5 ; + + fates_hydro_avuln_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_hydro_epsil_node = + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_hydro_fcap_node = + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_kmax_node = + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; + + fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + -1.5, -1.5, -1.5 ; + + fates_hydro_p50_node = + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25 ; + + fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, + 0.333, 0.333, 0.333, 0.333, 0.333 ; + + fates_hydro_pinot_node = + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; + + fates_hydro_pitlp_node = + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + -1.67, -1.67, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; + + fates_hydro_resid_node = + 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; + + fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + 0.625, 0.625, 0.625, 0.625, 0.625 ; + + fates_hydro_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, + 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; + + fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; + + fates_hydro_thetas_node = + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; + + fates_hydro_vg_alpha_node = + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005 ; + + fates_hydro_vg_m_node = + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_hydro_vg_n_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_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, + 43540, 43540, 43540, 43540 ; + + fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, + 152040, 152040, 152040, 152040, 152040 ; + + fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, + 495 ; + + fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, + 0.03, 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_slatop = 0.012, 0.005, 0.024, 0.009, 0.03, 0.03, 0.012, 0.03, + 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, + 10000, 10000, 10000, 10000, 10000, 40000 ; + + fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, + 4.7, 2.2, 5.3, 1.6 ; + + fates_leaf_vcmax25top = + 50, 62, 39, 61, 41, 58, 62, 54, 54, 78, 78, 78 ; + + fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, + 65330, 65330, 65330, 65330 ; + + fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, + 149250, 149250, 149250, 149250, 149250 ; + + fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, + 485 ; + + fates_maintresp_leaf_atkin2017_baserate = 1.756, 1.4995, 1.4995, 1.756, + 1.756, 1.756, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956, 2.1956 ; + + fates_maintresp_leaf_ryan1991_baserate = 2.525e-06, 2.525e-06, 2.525e-06, + 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, + 2.525e-06, 2.525e-06, 2.525e-06 ; + + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; + + fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, + 0.014, 0.014, 0.014, 0.014 ; + + fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -80, -60, -10, -80, -80, + -20, 2.5 ; + + fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, + 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; + + fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_prescribed_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, + 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; + + fates_mort_prescribed_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, + 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; + + fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_nonhydro_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, + -255000, -255000, -255000, -255000, -255000, -255000 ; + + fates_nonhydro_smpso = -66000, -66000, -66000, -66000, -66000, -66000, + -66000, -66000, -66000, -66000, -66000, -66000 ; + + fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; + + fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, + 0.5 ; + + fates_phen_fnrt_drop_frac = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; + + fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; + + fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, + 0.4, 0.4, 0.4 ; + + fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, + 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; + + fates_rad_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, + 0.9, 0.75, 0.75, 0.75 ; + + fates_rad_leaf_rhonir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, + 0.41, 0.28, 0.28, 0.28 ; + + fates_rad_leaf_rhovis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, + 0.08, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_taunir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, + 0.43, 0.4, 0.4, 0.4 ; + + fates_rad_leaf_tauvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, + 0.06, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, + -0.23, -0.23, -0.23 ; + + fates_rad_stem_rhonir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, + 0.49, 0.53, 0.53, 0.53 ; + + fates_rad_stem_rhovis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.31, 0.31, 0.31 ; + + fates_rad_stem_taunir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.25, 0.25, 0.25 ; + + fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.12, 0.12, 0.12 ; + + fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.2, 0.2, 0.2, + 0.125, 0.125, 0.125 ; + + fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2, 0.2, 0.2 ; + + fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, + 0.02, 0.02, 0.02, 0.02, 0.02 ; + + fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, + 0.9 ; + + fates_recruit_seed_dbh_repro_threshold = 90, 80, 80, 80, 90, 80, 3, 3, 2, + 0.35, 0.35, 0.35 ; + + fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_stoich_nitr = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; + + fates_stoich_phos = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; + + fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, + 0.03, 0.03 ; + + fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; + + fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, + 0.67, 0.67, 0.67 ; + + fates_turb_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.04, 0.04, 0.04, 0.04 ; + + fates_turb_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, + 0.055, 0.055, 0.055, 0.055 ; + + fates_turnover_branch = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; + + fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_leaf = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_wood_density = 0.7, 0.4, 0.7, 0.53, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, + 0.7 ; + + fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; + + fates_hlm_pft_map = + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + + fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; + + fates_fire_low_moisture_Coeff = 1.12, 1.09, 0.98, 0.8, 1.15, 1.15 ; + + fates_fire_low_moisture_Slope = 0.62, 0.72, 0.85, 0.8, 0.62, 0.62 ; + + fates_fire_mid_moisture = 0.72, 0.51, 0.38, 1, 0.8, 0.8 ; + + fates_fire_mid_moisture_Coeff = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_mid_moisture_Slope = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_min_moisture = 0.18, 0.12, 0, 0, 0.24, 0.24 ; + + fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; + + fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; + + fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; + + fates_canopy_closure_thresh = 0.8 ; + + fates_cnp_eca_plant_escalar = 1.25e-05 ; + + fates_cohort_age_fusion_tol = 0.08 ; + + fates_cohort_size_fusion_tol = 0.08 ; + + fates_comp_excln = 3 ; + + fates_damage_canopy_layer_code = 1 ; + + fates_damage_event_code = 1 ; + + fates_dev_arbitrary = _ ; + + fates_fire_active_crown_fire = 0 ; + + fates_fire_cg_strikes = 0.2 ; + + fates_fire_drying_ratio = 66000 ; + + fates_fire_durat_slope = -11.06 ; + + fates_fire_fdi_a = 17.62 ; + + fates_fire_fdi_alpha = 0.00037 ; + + fates_fire_fdi_b = 243.12 ; + + fates_fire_fuel_energy = 18000 ; + + fates_fire_max_durat = 240 ; + + fates_fire_miner_damp = 0.41739 ; + + fates_fire_miner_total = 0.055 ; + + fates_fire_nignitions = 15 ; + + fates_fire_part_dens = 513 ; + + fates_fire_threshold = 50 ; + + fates_frag_cwd_fcel = 0.76 ; + + fates_frag_cwd_flig = 0.24 ; + + fates_hydro_kmax_rsurf1 = 20 ; + + fates_hydro_kmax_rsurf2 = 0.0001 ; + + fates_hydro_psi0 = 0 ; + + fates_hydro_psicap = -0.6 ; + + fates_hydro_solver = 1 ; + + fates_landuse_logging_coll_under_frac = 0.55983 ; + + fates_landuse_logging_collateral_frac = 0.05 ; + + fates_landuse_logging_dbhmax = _ ; + + fates_landuse_logging_dbhmax_infra = 35 ; + + fates_landuse_logging_dbhmin = 50 ; + + fates_landuse_logging_direct_frac = 0.15 ; + + fates_landuse_logging_event_code = -30 ; + + fates_landuse_logging_export_frac = 0.8 ; + + fates_landuse_logging_mechanical_frac = 0.05 ; + + fates_landuse_pprodharv10_forest_mean = 0.8125 ; + + fates_leaf_photo_temp_acclim_timescale = 30 ; + + fates_leaf_photo_tempsens_model = 1 ; + + fates_leaf_stomatal_assim_model = 1 ; + + fates_leaf_stomatal_model = 1 ; + + fates_leaf_theta_cj_c3 = 0.999 ; + + fates_leaf_theta_cj_c4 = 0.999 ; + + fates_maintresp_leaf_model = 1 ; + + fates_maintresp_nonleaf_baserate = 2.525e-06 ; + + fates_maxcohort = 100 ; + + fates_maxpatch_primary = 10 ; + + fates_maxpatch_secondary = 4 ; + + fates_mort_disturb_frac = 1 ; + + fates_mort_understorey_death = 0.55983 ; + + fates_patch_fusion_tol = 0.05 ; + + fates_phen_chilltemp = 5 ; + + fates_phen_coldtemp = 7.5 ; + + fates_phen_drought_model = 0 ; + + fates_phen_drought_threshold = 0.15 ; + + fates_phen_gddthresh_a = -68 ; + + fates_phen_gddthresh_b = 638 ; + + fates_phen_gddthresh_c = -0.01 ; + + fates_phen_mindaysoff = 100 ; + + fates_phen_mindayson = 90 ; + + fates_phen_moist_threshold = 0.18 ; + + fates_phen_ncolddayslim = 5 ; + + fates_q10_froz = 1.5 ; + + fates_q10_mr = 1.5 ; + + fates_soil_salinity = 0.4 ; + + fates_vai_top_bin_width = 1 ; + + fates_vai_width_increase_factor = 1 ; +} diff --git a/parameter_files/archive/api25.2.0_031723_pr984.xml b/parameter_files/archive/api25.2.0_031723_pr984.xml new file mode 100644 index 0000000000..3d9c617446 --- /dev/null +++ b/parameter_files/archive/api25.2.0_031723_pr984.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + archive/api25.2.0_031723_fates_params_default.cdl + fates_params_default.cdl + 1,2,3,4,5,6,7,8,9,10,11,12 + + + fates_leaf_photo_temp_acclim_thome_time + scalar + years + Length of the window for the long-term (i.e. T_home in Kumarathunge et al 2019) exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_leaf_photo_tempsens_model = 2) + 30 + + + activation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED + + + deactivation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED + + + entropy term for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED + + + activation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED + + + deactivation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED + + + entropy term for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED + + + Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_maintresp_leaf_model=2 or fates_leaf_photo_tempsens_model = 2) + + + switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating; 2=Kumarathunge et al 2019 + + + switch for choosing between maintenance respiration models. 1=Ryan (1991), 2=Atkin et al., (2017) + + + diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 769b742c2c..91cc81f62c 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -377,7 +377,6 @@ variables: double fates_leaf_vcmaxse(fates_pft) ; fates_leaf_vcmaxse:units = "J/mol/K" ; fates_leaf_vcmaxse:long_name = "entropy term for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; - fates_leaf_vcmaxse:long_name = "entropy term for vcmax" ; double fates_maintresp_leaf_atkin2017_baserate(fates_pft) ; fates_maintresp_leaf_atkin2017_baserate:units = "umol CO2/m^2/s" ; fates_maintresp_leaf_atkin2017_baserate:long_name = "Leaf maintenance respiration base rate parameter (r0) per Atkin et al 2017" ; From 2b7364e6e709089e5f59d0a7b53fe5f02b82b296 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 20 Mar 2023 16:09:34 -0700 Subject: [PATCH 577/852] Renamed luh2 module and added primary script --- tools/luh2.py | 163 +++++++++------------------------------------- tools/luh2mod.py | 164 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 193 insertions(+), 134 deletions(-) create mode 100644 tools/luh2mod.py diff --git a/tools/luh2.py b/tools/luh2.py index 7416f16018..5facc30ea4 100644 --- a/tools/luh2.py +++ b/tools/luh2.py @@ -1,145 +1,40 @@ #!/usr/bin/env python3 -import re -import numpy as np -import xarray as xr -import xesmf as xe -from nco import Nco -from nco.custom import Atted +import luh2mod as luh2 -# Add version checking here in case environment.yml not used +# Location of luh2 data - move this to input +# file_states = "/home/glemieux/Data/luh2/orig/states.nc" +# file_management = "/home/glemieux/Data/luh2/orig/management.nc" +# file_transitions = "/home/glemieux/Data/luh2/orig/transitions.nc" -# Import luh2 data -def importdata(inputfile): +# # Modify the files +# mod_file_states = luh2.attribupdate(file_states) +# mod_file_management = luh2.attribupdate(file_management) +# mod_file_transitions = luh2.attribupdate(file_transitions) +mod_file_states = "/home/glemieux/Data/luh2/states_modified.nc" +mod_file_management = "/home/glemieux/Data/luh2/management_modified.nc" +mod_file_transitions = "/home/glemieux/Data/luh2/transitions_modified.nc" - # Open files - # Check to see if a ValueError is raised which is likely due - # to the LUH2 time units being undecodable by cftime module - try: - datasetout = xr.open_dataset(inputfile) - except ValueError as err: - print("ValueError:", err) - errmsg = "User direction: If error is due to units being 'years since ...' " \ - "update the input data file to change to 'common_years since...'. " \ - "This can be done using the luh2.attribupdate function." - print() - print(errmsg) +# Open modified files +ds_states = luh2.importdata(mod_file_states) +ds_management = luh2.importdata(mod_file_management) +ds_transitions = luh2.importdata(mod_file_transitions) - return(datasetout) +# Fix the bounds +ds_states = luh2.BoundsFixLUH2(ds_states) +ds_management= luh2.BoundsFixLUH2(ds_management) +ds_transitions = luh2.BoundsFixLUH2(ds_transitions) -# Modify the luh2 metadata to enable xarray to read in data -# This issue here is that the luh2 time units start prior to -# year 1672, which cftime should be able to handle, but it -# appears to need a specific unit name convention "common_years" -def attribupdate(inputfile,output_append="modified"): +# Grab surface data set to use as regrid "target" +# Import the surface dataset +file_surfdata = "/home/glemieux/Data/luh2/surfdata_4x5_16pfts_Irrig_CMIP6_simyr2000_c170824.nc" - # Define the output filename - index = inputfile.find(".nc") - outputfile = inputfile[:index] + "_" + output_append + inputfile[index:] +# modify the surface data set to enable xesmf regridder to find necessary data +ds_surfdata = luh2.DimensionFixSurfData(file_surfdata) - nco = Nco() +print("done") - # Get the 'time:units' string from the input using ncks - timeunitstr = nco.ncks(input=inputfile,variable="time",options=["-m"]).decode() - # Grab the units string and replace "years" with "common_years" - substr = re.search('time:units.*".*"',timeunitstr) - newstr = substr.group().replace("time:units = \"years","\"common_years") - - # Use ncatted to update the time units - att = "units" - var = "time" - att_type = "c" - opts = [" -a {0},{1},o,{2},{3}".format(att, var, att_type, newstr)] - nco.ncatted(input=inputfile, output=outputfile, options=opts) - - print("Generated modified output file: {}".format(outputfile)) - - return(outputfile) - - # The following is fixed with PR #62 for pynco but isn't in that latest update yet - # on conda - # nco.ncatted(input=inputfile,output=outputfile,options=[ - # Atted(mode="overwrite", - # att_name="units", - # var_name="time", - # value=newstr - # stype="c" - # ), - # ]) - -# Fix the boundaries of the LUH2 data -# Each lat/lon boundary array is a 2D array corresponding to the bounds of each -# coordinate position (e.g. lat_boundary would be 90.0 and 89.75 for lat coordinate -# of 89.875). -def BoundsFixLUH2(): - - -# Make necessary (?) changes to metadata for XESMF conservative regrid -# Any LUH2 data set should work as the input dataset, but -# we should have some sort of check to make sure that the -# data sets being used are consistent in the final calling script -def MetadataUpdateLUH2(inputdataset): - - # if this is LUH2 data - # Drop the invalid lat, lon variable labels and replace with "lat_b" and "lon_b" - # This is only necessary for the conservative method (?) per xESMF docs - - # Is dropping these variables really necessary? Will xESMF get confused or is this - # for the users's sake? - # outputdatatset = inputdataset.drop(labels=['lat_bounds','lon_bounds']) - - # Create lat and lon bounds as a single dimension array out of the LUH2 two dimensional - # _bounds array. - # xESMF needs these variable names for bounding the conservative regridding - outputdatatset["lat_b"] = np.insert(inputdataset.lat_bounds[:,1].data,0,inputdataset.lat_bounds[0,0].data) - outputdatatset["lon_b"] = np.insert(inputdataset.lon_bounds[:,1].data,0,inputdataset.lon_bounds[0,0].data) - # outputdatatset["time"] = np.arange(len(fin["time"]), dtype=np.int16) + 850 - # outputdatatset["YEAR"] = xr.DataArray(np.arange(len(fin["time"]), dtype=np.int16) + 850, dims=("time")) - -def definemask(inputdataset,outputdataset,label_to_mask): - # make mask of LUH2 data - outputdatatset["mask"] = xr.where(~np.isnan(inputdataset["primf_to_range"].isel(time=0)), 1, 0) - # make mask of surface data file - fin2b["mask"] = fin2b["PCT_NATVEG"]> 0. - -# load CLM surface data file -def MetadataUpdateSurfDS(inputdataset,outputdataset): - - # Move this out to be handled by opening function - # fin2 = xr.open_dataset('surfdata_4x5_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc') - - # Rename the surface dataset dimensions to something recognizable by xESMF. - # That said, since regridder just needs the values, I'm not sure this is necessary. - # We might just be able to rename t - fin2b = fin2.rename_dims(dims_dict={'lsmlat':'latitude','lsmlon':'longitude'}) - - # Populate the new surface dataset with the actual lat/lon values - fin2b['longitude'] = fin2b.LONGXY.isel(latitude=0) - fin2b['latitude'] = fin2b.LATIXY.isel(longitude=0) - -def RegridConservative(datasets_in,datasets_out,regridder): - # define the regridder transformation - regridder = xe.Regridder(dataset_in, dataset_out, "conservative") - - #regrid the various LUH2 datasets, from smallest to largest - fin_states_regrid = regridder(finb_states) - fin_management_regrid = regridder(finb_management) - - ### memory crashes on the transition data - #fin_transitions_regrid = regridder(finb) - -# Update the formatting to meet HLM needs -# def clmformatter(): - -# General functionality needed -# - collect data for specific user-defined time period -# - collect subset of the data variables (e.g. pasture, rangeland, etc) -# - write the subset to the necessary format to pass to regridding tools -# - This may need to be specific to the particular hlm tooling -# - call regridding tooling in hlm model -# - this will need to point at existing mapping data files, which are external to hlm -# - this may need a new mksurf_xxxx module if it can't conform to existing modules due -# to needing to use new fields -# future functionality: -# - importdata function for aforestation and other data to add to luh2 data +# def main(): +# if __name__ == "__main__": +# main() diff --git a/tools/luh2mod.py b/tools/luh2mod.py new file mode 100644 index 0000000000..65cf029c34 --- /dev/null +++ b/tools/luh2mod.py @@ -0,0 +1,164 @@ +#!/usr/bin/env python3 + +import re +import numpy as np +import xarray as xr +import xesmf as xe +from nco import Nco +from nco.custom import Atted + +# Add version checking here in case environment.yml not used + +# Import luh2 data +def importdata(inputfile): + + # Open files + # Check to see if a ValueError is raised which is likely due + # to the LUH2 time units being undecodable by cftime module + try: + datasetout = xr.open_dataset(inputfile) + print("Input file dataset opened: {}".format(inputfile)) + return(datasetout) + except ValueError as err: + print("ValueError:", err) + errmsg = "User direction: If error is due to units being 'years since ...' " \ + "update the input data file to change to 'common_years since...'. " \ + "This can be done using the luh2.attribupdate function." + print() + print(errmsg) + + +# Modify the luh2 metadata to enable xarray to read in data +# This issue here is that the luh2 time units start prior to +# year 1672, which cftime should be able to handle, but it +# appears to need a specific unit name convention "common_years" +def attribupdate(inputfile,output_append="modified"): + + # Define the output filename + index = inputfile.find(".nc") + outputfile = inputfile[:index] + "_" + output_append + inputfile[index:] + + nco = Nco() + + # Get the 'time:units' string from the input using ncks + timeunitstr = nco.ncks(input=inputfile,variable="time",options=["-m"]).decode() + + # Grab the units string and replace "years" with "common_years" + substr = re.search('time:units.*".*"',timeunitstr) + newstr = substr.group().replace("time:units = \"years","\"common_years") + + # Use ncatted to update the time units + att = "units" + var = "time" + att_type = "c" + opts = [" -a {0},{1},o,{2},{3}".format(att, var, att_type, newstr)] + nco.ncatted(input=inputfile, output=outputfile, options=opts) + + print("Generated modified output file: {}".format(outputfile)) + + return(outputfile) + + # The following is fixed with PR #62 for pynco but isn't in that latest update yet + # on conda + # nco.ncatted(input=inputfile,output=outputfile,options=[ + # Atted(mode="overwrite", + # att_name="units", + # var_name="time", + # value=newstr + # stype="c" + # ), + # ]) + +# Fix the boundaries of the LUH2 data +# Each lat/lon boundary array is a 2D array corresponding to the bounds of each +# coordinate position (e.g. lat_boundary would be 90.0 and 89.75 for lat coordinate +# of 89.875). +def BoundsFixLUH2(inputdataset): + + # Create lat and lon bounds as a single dimension array out of the LUH2 two dimensional + # _bounds array. + # xESMF needs these variable names for bounding the conservative regridding + outputdataset = inputdataset.drop(labels=['lat_bounds','lon_bounds']) + outputdataset["lat_b"] = np.insert(inputdataset.lat_bounds[:,1].data,0,inputdataset.lat_bounds[0,0].data) + outputdataset["lon_b"] = np.insert(inputdataset.lon_bounds[:,1].data,0,inputdataset.lon_bounds[0,0].data) + print("LUH2 dataset bounds fixed") + + return(outputdataset) + +def DimensionFixSurfData(inputfile): + + # Move this out to be handled by opening function + surfdataset = xr.open_dataset(inputfile) + + # Rename the surface dataset dimensions to something recognizable by xESMF. + outputdataset = surfdataset.rename_dims(dims_dict={'lsmlat':'latitude','lsmlon':'longitude'}) + + # Populate the new surface dataset with the actual lat/lon values + outputdataset['longitude'] = outputdataset.LONGXY.isel(latitude=0) + outputdataset['latitude'] = outputdataset.LATIXY.isel(longitude=0) + + print("Surface dataset regrid target loaded: {}".format(inputfile)) + + return(outputdataset, surfdataset) + +def setmask(inputdataset,label_to_mask): + + # note that the label will depend on the type of input file + + # check what sort of inputdata is being provided; surface dataset or luh2 + # make mask of LUH2 data "primf_to_range" + if(inputdataset.source.find("LUH2") != -1): + # Add check of variables to use as mask + inputdataset["mask"] = xr.where(~np.isnan(inputdataset[label_to_mask].isel(time=0)), 1, 0) + elif(inpudataset.source.version.find("mksurf") != -1): + inputdataset["mask"] = inputdatatset["PCT_NATVEG"]> 0 + else: + print("Incorrect dataset provided") + inputdataset["mask"] = None + + return(inputdataset) + +def RegridConservative(dataset_from,dataset_to): + # define the regridder transformation + regridder = xe.Regridder(dataset_from, dataset_to, "conservative") + + regrid_states = regridder(finb_states) + regrid_management= regridder(finb_management) + regrid_transitions= regridder(finb_management) + + ### memory crashes on the transition data + #fin_transitions_regrid = regridder(finb) + # +# Make necessary (?) changes to metadata for XESMF conservative regrid +# Any LUH2 data set should work as the input dataset, but +# we should have some sort of check to make sure that the +# data sets being used are consistent in the final calling script +#def MetadataUpdateLUH2(inputdataset): + + # if this is LUH2 data + # Drop the invalid lat, lon variable labels and replace with "lat_b" and "lon_b" + # This is only necessary for the conservative method (?) per xESMF docs + + # Is dropping these variables really necessary? Will xESMF get confused or is this + # for the users's sake? + # outputdatatset = inputdataset.drop(labels=['lat_bounds','lon_bounds']) + + # outputdatatset["lat_b"] = np.insert(inputdataset.lat_bounds[:,1].data,0,inputdataset.lat_bounds[0,0].data) + # outputdatatset["lon_b"] = np.insert(inputdataset.lon_bounds[:,1].data,0,inputdataset.lon_bounds[0,0].data) + # outputdatatset["time"] = np.arange(len(fin["time"]), dtype=np.int16) + 850 + # outputdatatset["YEAR"] = xr.DataArray(np.arange(len(fin["time"]), dtype=np.int16) + 850, dims=("time")) + +# Update the formatting to meet HLM needs +# def clmformatter(): + +# General functionality needed +# - collect data for specific user-defined time period +# - collect subset of the data variables (e.g. pasture, rangeland, etc) +# - write the subset to the necessary format to pass to regridding tools +# - This may need to be specific to the particular hlm tooling +# - call regridding tooling in hlm model +# - this will need to point at existing mapping data files, which are external to hlm +# - this may need a new mksurf_xxxx module if it can't conform to existing modules due +# to needing to use new fields +# future functionality: +# - importdata function for aforestation and other data to add to luh2 data From 95d9db3be495f540a17cf0b1e4aaa13233632b4d Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Mon, 20 Mar 2023 16:12:29 -0700 Subject: [PATCH 578/852] Add more comments describing dbh-initialization and the dual functionality of the initd parameter. --- main/EDInitMod.F90 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index cc859ff125..7fa7dc4206 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -819,6 +819,12 @@ subroutine init_cohorts( site_in, patch_in, bc_in) temp_cohort%l2fr = prt_params%allom_l2fr(pft) temp_cohort%canopy_trim = 1.0_r8 temp_cohort%crowndamage = 1 ! Assume no damage to begin with + + ! If positive EDPftvarcon_inst%initd is interpreted as initial recruit density. + ! If negative EDPftvarcon_inst%initd is interpreted as initial dbh. + ! Dbh-initialization can only be used in nocomp mode. + ! In the dbh-initialization case, we calculate crown area for a single tree and then calculate + ! the density of plants needed for a full canopy. if(EDPftvarcon_inst%initd(pft)>nearzero) then ! interpret as initial density and calculate diameter From f625694d5647207671fdada1e53534af7779621d Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 21 Mar 2023 09:04:23 -0700 Subject: [PATCH 579/852] Updating patch xml file comments --- .../archive/api25.2.0_031723_pr984.xml | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/parameter_files/archive/api25.2.0_031723_pr984.xml b/parameter_files/archive/api25.2.0_031723_pr984.xml index 3d9c617446..e9ae2bee39 100644 --- a/parameter_files/archive/api25.2.0_031723_pr984.xml +++ b/parameter_files/archive/api25.2.0_031723_pr984.xml @@ -1,20 +1,22 @@ - + - - - - - + + + + + + + - - - - - + + + + + - + From df7dd3fd482326c5f86ecb5bea04c8471462fda9 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 22 Mar 2023 14:49:02 -0700 Subject: [PATCH 581/852] Add xml patch parameter file --- .../api25.3.0_032223_fates_params_default.cdl | 1559 +++++++++++++++++ .../archive/api25.3.0_032223_pr995.xml | 33 + parameter_files/fates_params_default.cdl | 2 +- 3 files changed, 1593 insertions(+), 1 deletion(-) create mode 100644 parameter_files/archive/api25.3.0_032223_fates_params_default.cdl create mode 100644 parameter_files/archive/api25.3.0_032223_pr995.xml diff --git a/parameter_files/archive/api25.3.0_032223_fates_params_default.cdl b/parameter_files/archive/api25.3.0_032223_fates_params_default.cdl new file mode 100644 index 0000000000..fd5f0d6dd3 --- /dev/null +++ b/parameter_files/archive/api25.3.0_032223_fates_params_default.cdl @@ -0,0 +1,1559 @@ +netcdf fates_params_default { +dimensions: + fates_NCWD = 4 ; + fates_history_age_bins = 7 ; + fates_history_coage_bins = 2 ; + fates_history_damage_bins = 2 ; + fates_history_height_bins = 6 ; + fates_history_size_bins = 13 ; + fates_hlm_pftno = 14 ; + fates_hydr_organs = 4 ; + fates_leafage_class = 1 ; + fates_litterclass = 6 ; + fates_pft = 12 ; + fates_plant_organs = 4 ; + fates_string_length = 60 ; +variables: + double fates_history_ageclass_bin_edges(fates_history_age_bins) ; + fates_history_ageclass_bin_edges:units = "yr" ; + fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; + double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; + fates_history_coageclass_bin_edges:units = "years" ; + fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; + double fates_history_height_bin_edges(fates_history_height_bins) ; + fates_history_height_bin_edges:units = "m" ; + fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; + double fates_history_damage_bin_edges(fates_history_damage_bins) ; + fates_history_damage_bin_edges:units = "% crown loss" ; + fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; + double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; + fates_history_sizeclass_bin_edges:units = "cm" ; + fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; + double fates_alloc_organ_id(fates_plant_organs) ; + fates_alloc_organ_id:units = "unitless" ; + fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; + double fates_hydro_htftype_node(fates_hydr_organs) ; + fates_hydro_htftype_node:units = "unitless" ; + fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; + char fates_pftname(fates_pft, fates_string_length) ; + fates_pftname:units = "unitless - string" ; + fates_pftname:long_name = "Description of plant type" ; + char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; + fates_hydro_organ_name:units = "unitless - string" ; + fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; + char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; + fates_alloc_organ_name:units = "unitless - string" ; + fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; + 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" ; + 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" ; + double fates_alloc_storage_cushion(fates_pft) ; + fates_alloc_storage_cushion:units = "fraction" ; + fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; + double fates_alloc_store_priority_frac(fates_pft) ; + fates_alloc_store_priority_frac:units = "unitless" ; + fates_alloc_store_priority_frac:long_name = "for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage" ; + double fates_allom_agb1(fates_pft) ; + fates_allom_agb1:units = "variable" ; + fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; + double fates_allom_agb2(fates_pft) ; + fates_allom_agb2:units = "variable" ; + fates_allom_agb2:long_name = "Parameter 2 for agb allometry" ; + double fates_allom_agb3(fates_pft) ; + fates_allom_agb3:units = "variable" ; + fates_allom_agb3:long_name = "Parameter 3 for agb allometry" ; + double fates_allom_agb4(fates_pft) ; + fates_allom_agb4:units = "variable" ; + fates_allom_agb4:long_name = "Parameter 4 for agb allometry" ; + double fates_allom_agb_frac(fates_pft) ; + fates_allom_agb_frac:units = "fraction" ; + fates_allom_agb_frac:long_name = "Fraction of woody biomass that is above ground" ; + double fates_allom_amode(fates_pft) ; + fates_allom_amode:units = "index" ; + fates_allom_amode:long_name = "AGB allometry function index." ; + double fates_allom_blca_expnt_diff(fates_pft) ; + fates_allom_blca_expnt_diff:units = "unitless" ; + fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; + double fates_allom_cmode(fates_pft) ; + fates_allom_cmode:units = "index" ; + fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; + double fates_allom_crown_depth_frac(fates_pft) ; + fates_allom_crown_depth_frac:units = "fraction" ; + fates_allom_crown_depth_frac:long_name = "the depth of a cohort crown as a fraction of its height" ; + double fates_allom_d2bl1(fates_pft) ; + fates_allom_d2bl1:units = "variable" ; + fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; + double fates_allom_d2bl2(fates_pft) ; + fates_allom_d2bl2:units = "variable" ; + fates_allom_d2bl2:long_name = "Parameter 2 for d2bl allometry" ; + double fates_allom_d2bl3(fates_pft) ; + fates_allom_d2bl3:units = "unitless" ; + fates_allom_d2bl3:long_name = "Parameter 3 for d2bl allometry" ; + double fates_allom_d2ca_coefficient_max(fates_pft) ; + fates_allom_d2ca_coefficient_max:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_max:long_name = "max (savanna) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2ca_coefficient_min(fates_pft) ; + fates_allom_d2ca_coefficient_min:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_min:long_name = "min (forest) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2h1(fates_pft) ; + fates_allom_d2h1:units = "variable" ; + fates_allom_d2h1:long_name = "Parameter 1 for d2h allometry (intercept, or c)" ; + double fates_allom_d2h2(fates_pft) ; + fates_allom_d2h2:units = "variable" ; + fates_allom_d2h2:long_name = "Parameter 2 for d2h allometry (slope, or m)" ; + double fates_allom_d2h3(fates_pft) ; + fates_allom_d2h3:units = "variable" ; + fates_allom_d2h3:long_name = "Parameter 3 for d2h allometry (optional)" ; + double fates_allom_dbh_maxheight(fates_pft) ; + fates_allom_dbh_maxheight:units = "cm" ; + fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; + double fates_allom_fmode(fates_pft) ; + fates_allom_fmode:units = "index" ; + fates_allom_fmode:long_name = "fine root biomass allometry function index." ; + double fates_allom_fnrt_prof_a(fates_pft) ; + fates_allom_fnrt_prof_a:units = "unitless" ; + fates_allom_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; + double fates_allom_fnrt_prof_b(fates_pft) ; + fates_allom_fnrt_prof_b:units = "unitless" ; + fates_allom_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; + double fates_allom_fnrt_prof_mode(fates_pft) ; + fates_allom_fnrt_prof_mode:units = "index" ; + fates_allom_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; + double fates_allom_frbstor_repro(fates_pft) ; + fates_allom_frbstor_repro:units = "fraction" ; + fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; + double fates_allom_hmode(fates_pft) ; + fates_allom_hmode:units = "index" ; + fates_allom_hmode:long_name = "height allometry function index." ; + double fates_allom_l2fr(fates_pft) ; + fates_allom_l2fr:units = "gC/gC" ; + fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; + double fates_allom_la_per_sa_int(fates_pft) ; + fates_allom_la_per_sa_int:units = "m2/cm2" ; + fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; + double fates_allom_la_per_sa_slp(fates_pft) ; + fates_allom_la_per_sa_slp:units = "m2/cm2/m" ; + fates_allom_la_per_sa_slp:long_name = "Leaf area per sapwood area rate of change with height, slope (optional)" ; + double fates_allom_lmode(fates_pft) ; + fates_allom_lmode:units = "index" ; + fates_allom_lmode:long_name = "leaf biomass allometry function index." ; + double fates_allom_sai_scaler(fates_pft) ; + fates_allom_sai_scaler:units = "m2/m2" ; + fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; + double fates_allom_smode(fates_pft) ; + fates_allom_smode:units = "index" ; + fates_allom_smode:long_name = "sapwood allometry function index." ; + double fates_allom_stmode(fates_pft) ; + fates_allom_stmode:units = "index" ; + fates_allom_stmode:long_name = "storage allometry function index: 1) Storage proportional to leaf biomass (with trimming), 2) Storage proportional to maximum leaf biomass (not trimmed)" ; + double fates_allom_zroot_k(fates_pft) ; + fates_allom_zroot_k:units = "unitless" ; + fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; + double fates_allom_zroot_max_dbh(fates_pft) ; + fates_allom_zroot_max_dbh:units = "cm" ; + fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; + double fates_allom_zroot_max_z(fates_pft) ; + fates_allom_zroot_max_z:units = "m" ; + fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_allom_zroot_min_dbh(fates_pft) ; + fates_allom_zroot_min_dbh:units = "cm" ; + fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; + double fates_allom_zroot_min_z(fates_pft) ; + fates_allom_zroot_min_z:units = "m" ; + fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_c2b(fates_pft) ; + fates_c2b:units = "ratio" ; + fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; + double fates_cnp_eca_alpha_ptase(fates_pft) ; + fates_cnp_eca_alpha_ptase:units = "g/m3" ; + fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; + double fates_cnp_eca_decompmicc(fates_pft) ; + fates_cnp_eca_decompmicc:units = "gC/m3" ; + fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; + double fates_cnp_eca_km_nh4(fates_pft) ; + fates_cnp_eca_km_nh4:units = "gN/m3" ; + fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; + double fates_cnp_eca_km_no3(fates_pft) ; + fates_cnp_eca_km_no3:units = "gN/m3" ; + fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; + double fates_cnp_eca_km_p(fates_pft) ; + fates_cnp_eca_km_p:units = "gP/m3" ; + fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; + double fates_cnp_eca_km_ptase(fates_pft) ; + fates_cnp_eca_km_ptase:units = "gP/m3" ; + fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; + double fates_cnp_eca_lambda_ptase(fates_pft) ; + fates_cnp_eca_lambda_ptase:units = "g/m3" ; + fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; + double fates_cnp_eca_vmax_ptase(fates_pft) ; + fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; + fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; + double fates_cnp_nfix1(fates_pft) ; + fates_cnp_nfix1:units = "fraction" ; + fates_cnp_nfix1:long_name = "fractional surcharge added to maintenance respiration that drives symbiotic fixation" ; + double fates_cnp_nitr_store_ratio(fates_pft) ; + fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; + fates_cnp_nitr_store_ratio:long_name = "storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code)" ; + double fates_cnp_phos_store_ratio(fates_pft) ; + fates_cnp_phos_store_ratio:units = "(gP/gP)" ; + fates_cnp_phos_store_ratio:long_name = "storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code)" ; + double fates_cnp_pid_kd(fates_pft) ; + fates_cnp_pid_kd:units = "unknown" ; + fates_cnp_pid_kd:long_name = "derivative constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_pid_ki(fates_pft) ; + fates_cnp_pid_ki:units = "unknown" ; + fates_cnp_pid_ki:long_name = "integral constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_pid_kp(fates_pft) ; + fates_cnp_pid_kp:units = "unknown" ; + fates_cnp_pid_kp:long_name = "proportional constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_prescribed_nuptake(fates_pft) ; + fates_cnp_prescribed_nuptake:units = "fraction" ; + fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; + double fates_cnp_prescribed_puptake(fates_pft) ; + fates_cnp_prescribed_puptake:units = "fraction" ; + fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; + double fates_cnp_store_ovrflw_frac(fates_pft) ; + fates_cnp_store_ovrflw_frac:units = "fraction" ; + fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; + double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_nitr_retrans:units = "fraction" ; + fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; + double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_phos_retrans:units = "fraction" ; + fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; + double fates_cnp_vmax_nh4(fates_pft) ; + fates_cnp_vmax_nh4:units = "gN/gC/s" ; + fates_cnp_vmax_nh4:long_name = "maximum (potential) uptake rate of NH4 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_nh4 for usage)" ; + double fates_cnp_vmax_no3(fates_pft) ; + fates_cnp_vmax_no3:units = "gN/gC/s" ; + fates_cnp_vmax_no3:long_name = "maximum (potential) uptake rate of NO3 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_no3 for usage)" ; + double fates_cnp_vmax_p(fates_pft) ; + fates_cnp_vmax_p:units = "gP/gC/s" ; + fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; + double fates_damage_frac(fates_pft) ; + fates_damage_frac:units = "fraction" ; + fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; + double fates_damage_mort_p1(fates_pft) ; + fates_damage_mort_p1:units = "fraction" ; + fates_damage_mort_p1:long_name = "inflection point of damage mortality function, a value of 0.8 means 50% mortality with 80% loss of crown, turn off with a large number" ; + double fates_damage_mort_p2(fates_pft) ; + fates_damage_mort_p2:units = "unitless" ; + fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; + 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_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" ; + double fates_fire_alpha_SH(fates_pft) ; + fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; + fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; + double fates_fire_bark_scaler(fates_pft) ; + fates_fire_bark_scaler:units = "fraction" ; + fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; + double fates_fire_crown_kill(fates_pft) ; + fates_fire_crown_kill:units = "NA" ; + fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; + double fates_frag_fnrt_fcel(fates_pft) ; + fates_frag_fnrt_fcel:units = "fraction" ; + fates_frag_fnrt_fcel:long_name = "Fine root litter cellulose fraction" ; + double fates_frag_fnrt_flab(fates_pft) ; + fates_frag_fnrt_flab:units = "fraction" ; + fates_frag_fnrt_flab:long_name = "Fine root litter labile fraction" ; + double fates_frag_fnrt_flig(fates_pft) ; + fates_frag_fnrt_flig:units = "fraction" ; + fates_frag_fnrt_flig:long_name = "Fine root litter lignin fraction" ; + double fates_frag_leaf_fcel(fates_pft) ; + fates_frag_leaf_fcel:units = "fraction" ; + fates_frag_leaf_fcel:long_name = "Leaf litter cellulose fraction" ; + double fates_frag_leaf_flab(fates_pft) ; + fates_frag_leaf_flab:units = "fraction" ; + fates_frag_leaf_flab:long_name = "Leaf litter labile fraction" ; + double fates_frag_leaf_flig(fates_pft) ; + fates_frag_leaf_flig:units = "fraction" ; + fates_frag_leaf_flig:long_name = "Leaf litter lignin fraction" ; + double fates_frag_seed_decay_rate(fates_pft) ; + fates_frag_seed_decay_rate:units = "yr-1" ; + fates_frag_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; + double fates_grperc(fates_pft) ; + fates_grperc:units = "unitless" ; + fates_grperc:long_name = "Growth respiration factor" ; + double fates_hydro_avuln_gs(fates_pft) ; + fates_hydro_avuln_gs:units = "unitless" ; + fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; + double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; + fates_hydro_avuln_node:units = "unitless" ; + fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; + double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; + fates_hydro_epsil_node:units = "MPa" ; + fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; + double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; + fates_hydro_fcap_node:units = "unitless" ; + fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; + double fates_hydro_k_lwp(fates_pft) ; + fates_hydro_k_lwp:units = "unitless" ; + fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; + double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; + fates_hydro_kmax_node:units = "kg/MPa/m/s" ; + fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; + double fates_hydro_p50_gs(fates_pft) ; + fates_hydro_p50_gs:units = "MPa" ; + fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; + double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; + fates_hydro_p50_node:units = "MPa" ; + fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; + double fates_hydro_p_taper(fates_pft) ; + fates_hydro_p_taper:units = "unitless" ; + fates_hydro_p_taper:long_name = "xylem taper exponent" ; + double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pinot_node:units = "MPa" ; + fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; + double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pitlp_node:units = "MPa" ; + fates_hydro_pitlp_node:long_name = "turgor loss point" ; + double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; + fates_hydro_resid_node:units = "cm3/cm3" ; + fates_hydro_resid_node:long_name = "residual water conent" ; + double fates_hydro_rfrac_stem(fates_pft) ; + fates_hydro_rfrac_stem:units = "fraction" ; + fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; + double fates_hydro_rs2(fates_pft) ; + fates_hydro_rs2:units = "m" ; + fates_hydro_rs2:long_name = "absorbing root radius" ; + double fates_hydro_srl(fates_pft) ; + fates_hydro_srl:units = "m g-1" ; + fates_hydro_srl:long_name = "specific root length" ; + double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; + fates_hydro_thetas_node:units = "cm3/cm3" ; + fates_hydro_thetas_node:long_name = "saturated water content" ; + double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_alpha_node:units = "MPa-1" ; + fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; + double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_m_node:units = "unitless" ; + fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; + 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_leaf_c3psn(fates_pft) ; + fates_leaf_c3psn:units = "flag" ; + fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; + double fates_leaf_jmaxha(fates_pft) ; + fates_leaf_jmaxha:units = "J/mol" ; + fates_leaf_jmaxha:long_name = "activation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_jmaxhd(fates_pft) ; + fates_leaf_jmaxhd:units = "J/mol" ; + fates_leaf_jmaxhd:long_name = "deactivation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_jmaxse(fates_pft) ; + fates_leaf_jmaxse:units = "J/mol/K" ; + fates_leaf_jmaxse:long_name = "entropy term for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_slamax(fates_pft) ; + fates_leaf_slamax:units = "m^2/gC" ; + fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; + double fates_leaf_slatop(fates_pft) ; + fates_leaf_slatop:units = "m^2/gC" ; + fates_leaf_slatop:long_name = "Specific Leaf Area (SLA) at top of canopy, projected area basis" ; + double fates_leaf_stomatal_intercept(fates_pft) ; + fates_leaf_stomatal_intercept:units = "umol H2O/m**2/s" ; + fates_leaf_stomatal_intercept:long_name = "Minimum unstressed stomatal conductance for Ball-Berry model and Medlyn model" ; + double fates_leaf_stomatal_slope_ballberry(fates_pft) ; + fates_leaf_stomatal_slope_ballberry:units = "unitless" ; + fates_leaf_stomatal_slope_ballberry:long_name = "stomatal slope parameter, as per Ball-Berry" ; + double fates_leaf_stomatal_slope_medlyn(fates_pft) ; + fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; + fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; + double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; + fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; + fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; + double fates_leaf_vcmaxha(fates_pft) ; + fates_leaf_vcmaxha:units = "J/mol" ; + fates_leaf_vcmaxha:long_name = "activation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_vcmaxhd(fates_pft) ; + fates_leaf_vcmaxhd:units = "J/mol" ; + fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_vcmaxse(fates_pft) ; + fates_leaf_vcmaxse:units = "J/mol/K" ; + fates_leaf_vcmaxse:long_name = "entropy term for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_maintresp_leaf_atkin2017_baserate(fates_pft) ; + fates_maintresp_leaf_atkin2017_baserate:units = "umol CO2/m^2/s" ; + fates_maintresp_leaf_atkin2017_baserate:long_name = "Leaf maintenance respiration base rate parameter (r0) per Atkin et al 2017" ; + double fates_maintresp_leaf_ryan1991_baserate(fates_pft) ; + fates_maintresp_leaf_ryan1991_baserate:units = "gC/gN/s" ; + fates_maintresp_leaf_ryan1991_baserate:long_name = "Leaf maintenance respiration base rate per Ryan et al 1991" ; + double fates_maintresp_reduction_curvature(fates_pft) ; + fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; + fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; + double fates_maintresp_reduction_intercept(fates_pft) ; + fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; + fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; + double fates_mort_bmort(fates_pft) ; + fates_mort_bmort:units = "1/yr" ; + fates_mort_bmort:long_name = "background mortality rate" ; + double fates_mort_freezetol(fates_pft) ; + fates_mort_freezetol:units = "degrees C" ; + fates_mort_freezetol:long_name = "minimum temperature tolerance" ; + double fates_mort_hf_flc_threshold(fates_pft) ; + fates_mort_hf_flc_threshold:units = "fraction" ; + fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; + double fates_mort_hf_sm_threshold(fates_pft) ; + fates_mort_hf_sm_threshold:units = "unitless" ; + fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; + double fates_mort_ip_age_senescence(fates_pft) ; + fates_mort_ip_age_senescence:units = "years" ; + fates_mort_ip_age_senescence:long_name = "Mortality cohort age senescence inflection point. If _ this mortality term is off. Setting this value turns on age dependent mortality. " ; + double fates_mort_ip_size_senescence(fates_pft) ; + fates_mort_ip_size_senescence:units = "dbh cm" ; + fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; + double fates_mort_prescribed_canopy(fates_pft) ; + fates_mort_prescribed_canopy:units = "1/yr" ; + fates_mort_prescribed_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; + double fates_mort_prescribed_understory(fates_pft) ; + fates_mort_prescribed_understory:units = "1/yr" ; + fates_mort_prescribed_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; + double fates_mort_r_age_senescence(fates_pft) ; + fates_mort_r_age_senescence:units = "mortality rate year^-1" ; + fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; + double fates_mort_r_size_senescence(fates_pft) ; + fates_mort_r_size_senescence:units = "mortality rate dbh^-1" ; + fates_mort_r_size_senescence:long_name = "Mortality dbh senescence rate of change. Sensible range is around 0.03-0.06. Larger values give steeper mortality curves." ; + double fates_mort_scalar_coldstress(fates_pft) ; + fates_mort_scalar_coldstress:units = "1/yr" ; + fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; + double fates_mort_scalar_cstarvation(fates_pft) ; + fates_mort_scalar_cstarvation:units = "1/yr" ; + fates_mort_scalar_cstarvation:long_name = "maximum mortality rate from carbon starvation" ; + double fates_mort_scalar_hydrfailure(fates_pft) ; + fates_mort_scalar_hydrfailure:units = "1/yr" ; + fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; + double fates_nonhydro_smpsc(fates_pft) ; + fates_nonhydro_smpsc:units = "mm" ; + fates_nonhydro_smpsc:long_name = "Soil water potential at full stomatal closure" ; + double fates_nonhydro_smpso(fates_pft) ; + fates_nonhydro_smpso:units = "mm" ; + fates_nonhydro_smpso:long_name = "Soil water potential at full stomatal opening" ; + double fates_phen_cold_size_threshold(fates_pft) ; + fates_phen_cold_size_threshold:units = "cm" ; + fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; + double fates_phen_evergreen(fates_pft) ; + fates_phen_evergreen:units = "logical flag" ; + fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; + double fates_phen_flush_fraction(fates_pft) ; + fates_phen_flush_fraction:units = "fraction" ; + fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; + double fates_phen_fnrt_drop_frac(fates_pft) ; + fates_phen_fnrt_drop_frac:units = "fraction" ; + fates_phen_fnrt_drop_frac:long_name = "fraction of fine roots to drop during drought or cold" ; + double fates_phen_season_decid(fates_pft) ; + fates_phen_season_decid:units = "logical flag" ; + fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; + double fates_phen_stem_drop_fraction(fates_pft) ; + fates_phen_stem_drop_fraction:units = "fraction" ; + fates_phen_stem_drop_fraction:long_name = "fraction of stems to drop for non-woody species during drought/cold" ; + double fates_phen_stress_decid(fates_pft) ; + fates_phen_stress_decid:units = "logical flag" ; + fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; + double fates_prescribed_npp_canopy(fates_pft) ; + fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; + double fates_prescribed_npp_understory(fates_pft) ; + fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; + double fates_rad_leaf_clumping_index(fates_pft) ; + fates_rad_leaf_clumping_index:units = "fraction (0-1)" ; + fates_rad_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; + double fates_rad_leaf_rhonir(fates_pft) ; + fates_rad_leaf_rhonir:units = "fraction" ; + fates_rad_leaf_rhonir:long_name = "Leaf reflectance: near-IR" ; + double fates_rad_leaf_rhovis(fates_pft) ; + fates_rad_leaf_rhovis:units = "fraction" ; + fates_rad_leaf_rhovis:long_name = "Leaf reflectance: visible" ; + double fates_rad_leaf_taunir(fates_pft) ; + fates_rad_leaf_taunir:units = "fraction" ; + fates_rad_leaf_taunir:long_name = "Leaf transmittance: near-IR" ; + double fates_rad_leaf_tauvis(fates_pft) ; + fates_rad_leaf_tauvis:units = "fraction" ; + fates_rad_leaf_tauvis:long_name = "Leaf transmittance: visible" ; + double fates_rad_leaf_xl(fates_pft) ; + fates_rad_leaf_xl:units = "unitless" ; + fates_rad_leaf_xl:long_name = "Leaf/stem orientation index" ; + double fates_rad_stem_rhonir(fates_pft) ; + fates_rad_stem_rhonir:units = "fraction" ; + fates_rad_stem_rhonir:long_name = "Stem reflectance: near-IR" ; + double fates_rad_stem_rhovis(fates_pft) ; + fates_rad_stem_rhovis:units = "fraction" ; + fates_rad_stem_rhovis:long_name = "Stem reflectance: visible" ; + double fates_rad_stem_taunir(fates_pft) ; + fates_rad_stem_taunir:units = "fraction" ; + fates_rad_stem_taunir:long_name = "Stem transmittance: near-IR" ; + double fates_rad_stem_tauvis(fates_pft) ; + fates_rad_stem_tauvis:units = "fraction" ; + fates_rad_stem_tauvis:long_name = "Stem transmittance: visible" ; + double fates_recruit_height_min(fates_pft) ; + fates_recruit_height_min:units = "m" ; + fates_recruit_height_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; + double fates_recruit_init_density(fates_pft) ; + fates_recruit_init_density:units = "stems/m2" ; + fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation. If negative sets initial tree dbh - only to be used in nocomp mode" ; + double fates_recruit_prescribed_rate(fates_pft) ; + fates_recruit_prescribed_rate:units = "n/yr" ; + fates_recruit_prescribed_rate:long_name = "recruitment rate for prescribed physiology mode" ; + double fates_recruit_seed_alloc(fates_pft) ; + fates_recruit_seed_alloc:units = "fraction" ; + fates_recruit_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; + double fates_recruit_seed_alloc_mature(fates_pft) ; + fates_recruit_seed_alloc_mature:units = "fraction" ; + fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; + double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; + fates_recruit_seed_dbh_repro_threshold:units = "cm" ; + fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter where the plant will increase allocation to the seed pool by fraction: fates_recruit_seed_alloc_mature" ; + double fates_recruit_seed_germination_rate(fates_pft) ; + fates_recruit_seed_germination_rate:units = "yr-1" ; + fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; + double fates_recruit_seed_supplement(fates_pft) ; + fates_recruit_seed_supplement:units = "KgC/m2/yr" ; + fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; + double fates_stoich_nitr(fates_plant_organs, fates_pft) ; + fates_stoich_nitr:units = "gN/gC" ; + fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; + double fates_stoich_phos(fates_plant_organs, fates_pft) ; + fates_stoich_phos:units = "gP/gC" ; + fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; + double fates_trim_inc(fates_pft) ; + fates_trim_inc:units = "m2/m2" ; + fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; + double fates_trim_limit(fates_pft) ; + fates_trim_limit:units = "m2/m2" ; + fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; + double fates_turb_displar(fates_pft) ; + fates_turb_displar:units = "unitless" ; + fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; + double fates_turb_leaf_diameter(fates_pft) ; + fates_turb_leaf_diameter:units = "m" ; + fates_turb_leaf_diameter:long_name = "Characteristic leaf dimension" ; + double fates_turb_z0mr(fates_pft) ; + fates_turb_z0mr:units = "unitless" ; + fates_turb_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; + double fates_turnover_branch(fates_pft) ; + fates_turnover_branch:units = "yr" ; + fates_turnover_branch:long_name = "turnover time of branches" ; + double fates_turnover_fnrt(fates_pft) ; + fates_turnover_fnrt:units = "yr" ; + fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; + double fates_turnover_leaf(fates_leafage_class, fates_pft) ; + fates_turnover_leaf:units = "yr" ; + fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; + double fates_turnover_senleaf_fdrought(fates_pft) ; + fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; + fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; + double fates_wood_density(fates_pft) ; + fates_wood_density:units = "g/cm3" ; + fates_wood_density:long_name = "mean density of woody tissue in plant" ; + double fates_woody(fates_pft) ; + fates_woody:units = "logical flag" ; + fates_woody:long_name = "Binary woody lifeform flag" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_fire_FBD(fates_litterclass) ; + fates_fire_FBD:units = "kg Biomass/m3" ; + fates_fire_FBD:long_name = "fuel bulk density" ; + double fates_fire_low_moisture_Coeff(fates_litterclass) ; + fates_fire_low_moisture_Coeff:units = "NA" ; + fates_fire_low_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_low_moisture_Slope(fates_litterclass) ; + fates_fire_low_moisture_Slope:units = "NA" ; + fates_fire_low_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture(fates_litterclass) ; + fates_fire_mid_moisture:units = "NA" ; + fates_fire_mid_moisture:long_name = "spitfire litter moisture threshold to be considered medium dry" ; + double fates_fire_mid_moisture_Coeff(fates_litterclass) ; + fates_fire_mid_moisture_Coeff:units = "NA" ; + fates_fire_mid_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture_Slope(fates_litterclass) ; + fates_fire_mid_moisture_Slope:units = "NA" ; + fates_fire_mid_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_min_moisture(fates_litterclass) ; + fates_fire_min_moisture:units = "NA" ; + fates_fire_min_moisture:long_name = "spitfire litter moisture threshold to be considered very dry" ; + double fates_fire_SAV(fates_litterclass) ; + fates_fire_SAV:units = "cm-1" ; + fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; + double fates_frag_maxdecomp(fates_litterclass) ; + fates_frag_maxdecomp:units = "yr-1" ; + fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; + 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_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" ; + double fates_cnp_eca_plant_escalar ; + fates_cnp_eca_plant_escalar:units = "" ; + fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; + double fates_cohort_age_fusion_tol ; + fates_cohort_age_fusion_tol:units = "unitless" ; + fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; + double fates_cohort_size_fusion_tol ; + fates_cohort_size_fusion_tol:units = "unitless" ; + fates_cohort_size_fusion_tol:long_name = "minimum fraction in difference in dbh between cohorts" ; + double fates_comp_excln ; + fates_comp_excln:units = "none" ; + fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; + double fates_damage_canopy_layer_code ; + fates_damage_canopy_layer_code:units = "unitless" ; + fates_damage_canopy_layer_code:long_name = "Integer code that decides whether damage affects canopy trees (1), understory trees (2)" ; + double fates_damage_event_code ; + fates_damage_event_code:units = "unitless" ; + fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; + double fates_dev_arbitrary ; + fates_dev_arbitrary:units = "unknown" ; + fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; + double fates_fire_active_crown_fire ; + fates_fire_active_crown_fire:units = "0 or 1" ; + fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; + double fates_fire_cg_strikes ; + fates_fire_cg_strikes:units = "fraction (0-1)" ; + fates_fire_cg_strikes:long_name = "fraction of cloud to ground lightning strikes" ; + double fates_fire_drying_ratio ; + fates_fire_drying_ratio:units = "NA" ; + fates_fire_drying_ratio:long_name = "spitfire parameter, fire drying ratio for fuel moisture, alpha_FMC EQ 6 Thonicke et al 2010" ; + double fates_fire_durat_slope ; + fates_fire_durat_slope:units = "NA" ; + fates_fire_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; + double fates_fire_fdi_a ; + fates_fire_fdi_a:units = "NA" ; + fates_fire_fdi_a:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010" ; + double fates_fire_fdi_alpha ; + fates_fire_fdi_alpha:units = "NA" ; + fates_fire_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; + double fates_fire_fdi_b ; + fates_fire_fdi_b:units = "NA" ; + fates_fire_fdi_b:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010 " ; + double fates_fire_fuel_energy ; + fates_fire_fuel_energy:units = "kJ/kg" ; + fates_fire_fuel_energy:long_name = "spitfire parameter, heat content of fuel" ; + double fates_fire_max_durat ; + fates_fire_max_durat:units = "minutes" ; + fates_fire_max_durat:long_name = "spitfire parameter, fire maximum duration, Equation 14 Thonicke et al 2010" ; + double fates_fire_miner_damp ; + fates_fire_miner_damp:units = "NA" ; + fates_fire_miner_damp:long_name = "spitfire parameter, mineral-dampening coefficient EQ A1 Thonicke et al 2010 " ; + double fates_fire_miner_total ; + fates_fire_miner_total:units = "fraction" ; + fates_fire_miner_total:long_name = "spitfire parameter, total mineral content, Table A1 Thonicke et al 2010" ; + double fates_fire_nignitions ; + fates_fire_nignitions:units = "ignitions per year per km2" ; + fates_fire_nignitions:long_name = "number of annual ignitions per square km" ; + double fates_fire_part_dens ; + fates_fire_part_dens:units = "kg/m2" ; + fates_fire_part_dens:long_name = "spitfire parameter, oven dry particle density, Table A1 Thonicke et al 2010" ; + double fates_fire_threshold ; + fates_fire_threshold:units = "kW/m" ; + fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; + double fates_frag_cwd_fcel ; + fates_frag_cwd_fcel:units = "unitless" ; + fates_frag_cwd_fcel:long_name = "Cellulose fraction for CWD" ; + double fates_frag_cwd_flig ; + fates_frag_cwd_flig:units = "unitless" ; + fates_frag_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; + double fates_hydro_kmax_rsurf1 ; + fates_hydro_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; + double fates_hydro_kmax_rsurf2 ; + fates_hydro_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; + double fates_hydro_psi0 ; + fates_hydro_psi0:units = "MPa" ; + fates_hydro_psi0:long_name = "sapwood water potential at saturation" ; + double fates_hydro_psicap ; + fates_hydro_psicap:units = "MPa" ; + fates_hydro_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; + 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_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" ; + double fates_landuse_logging_collateral_frac ; + fates_landuse_logging_collateral_frac:units = "fraction" ; + fates_landuse_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; + double fates_landuse_logging_dbhmax ; + fates_landuse_logging_dbhmax:units = "cm" ; + fates_landuse_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; + double fates_landuse_logging_dbhmax_infra ; + fates_landuse_logging_dbhmax_infra:units = "cm" ; + fates_landuse_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; + double fates_landuse_logging_dbhmin ; + fates_landuse_logging_dbhmin:units = "cm" ; + fates_landuse_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; + double fates_landuse_logging_direct_frac ; + fates_landuse_logging_direct_frac:units = "fraction" ; + fates_landuse_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; + double fates_landuse_logging_event_code ; + fates_landuse_logging_event_code:units = "unitless" ; + fates_landuse_logging_event_code:long_name = "Integer code that options how logging events are structured" ; + double fates_landuse_logging_export_frac ; + fates_landuse_logging_export_frac:units = "fraction" ; + fates_landuse_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; + double fates_landuse_logging_mechanical_frac ; + fates_landuse_logging_mechanical_frac:units = "fraction" ; + fates_landuse_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; + double fates_landuse_pprodharv10_forest_mean ; + fates_landuse_pprodharv10_forest_mean:units = "fraction" ; + fates_landuse_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; + double fates_leaf_photo_temp_acclim_thome_time ; + fates_leaf_photo_temp_acclim_thome_time:units = "years" ; + fates_leaf_photo_temp_acclim_thome_time:long_name = "Length of the window for the long-term (i.e. T_home in Kumarathunge et al 2019) exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_leaf_photo_tempsens_model = 2)" ; + double fates_leaf_photo_temp_acclim_timescale ; + fates_leaf_photo_temp_acclim_timescale:units = "days" ; + fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_maintresp_leaf_model=2 or fates_leaf_photo_tempsens_model = 2)" ; + double fates_leaf_photo_tempsens_model ; + fates_leaf_photo_tempsens_model:units = "unitless" ; + fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating; 2=Kumarathunge et al 2019" ; + double fates_leaf_stomatal_assim_model ; + fates_leaf_stomatal_assim_model:units = "unitless" ; + fates_leaf_stomatal_assim_model:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; + double fates_leaf_stomatal_model ; + fates_leaf_stomatal_model:units = "unitless" ; + fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; + double fates_leaf_theta_cj_c3 ; + fates_leaf_theta_cj_c3:units = "unitless" ; + fates_leaf_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; + double fates_leaf_theta_cj_c4 ; + fates_leaf_theta_cj_c4:units = "unitless" ; + fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; + double fates_maintresp_leaf_model ; + fates_maintresp_leaf_model:units = "unitless" ; + fates_maintresp_leaf_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991), 2=Atkin et al., (2017)" ; + double fates_maintresp_nonleaf_baserate ; + fates_maintresp_nonleaf_baserate:units = "gC/gN/s" ; + fates_maintresp_nonleaf_baserate:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; + double fates_maxcohort ; + fates_maxcohort:units = "count" ; + fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; + double fates_maxpatch_primary ; + fates_maxpatch_primary:units = "count" ; + fates_maxpatch_primary:long_name = "maximum number of primary vegetation patches per site" ; + double fates_maxpatch_secondary ; + fates_maxpatch_secondary:units = "count" ; + fates_maxpatch_secondary:long_name = "maximum number of secondary vegetation patches per site" ; + double fates_mort_disturb_frac ; + fates_mort_disturb_frac:units = "fraction" ; + fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; + double fates_mort_understorey_death ; + fates_mort_understorey_death:units = "fraction" ; + fates_mort_understorey_death:long_name = "fraction of plants in understorey cohort impacted by overstorey tree-fall" ; + double fates_patch_fusion_tol ; + fates_patch_fusion_tol:units = "unitless" ; + fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; + double fates_phen_chilltemp ; + fates_phen_chilltemp:units = "degrees C" ; + fates_phen_chilltemp:long_name = "chilling day counting threshold for vegetation" ; + double fates_phen_coldtemp ; + fates_phen_coldtemp:units = "degrees C" ; + fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; + double fates_phen_drought_model ; + fates_phen_drought_model:units = "unitless" ; + fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; + double fates_phen_drought_threshold ; + fates_phen_drought_threshold:units = "m3/m3 or mm" ; + fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_gddthresh_a ; + fates_phen_gddthresh_a:units = "none" ; + fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_b ; + fates_phen_gddthresh_b:units = "none" ; + fates_phen_gddthresh_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_c ; + fates_phen_gddthresh_c:units = "none" ; + fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_mindaysoff ; + fates_phen_mindaysoff:units = "days" ; + fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves became off-allometry" ; + double fates_phen_mindayson ; + fates_phen_mindayson:units = "days" ; + fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; + double fates_phen_moist_threshold ; + fates_phen_moist_threshold:units = "m3/m3 or mm" ; + fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_ncolddayslim ; + fates_phen_ncolddayslim:units = "days" ; + fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; + double fates_q10_froz ; + fates_q10_froz:units = "unitless" ; + fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; + double fates_q10_mr ; + fates_q10_mr:units = "unitless" ; + fates_q10_mr:long_name = "Q10 for maintenance respiration" ; + double fates_soil_salinity ; + fates_soil_salinity:units = "ppt" ; + fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; + double fates_vai_top_bin_width ; + fates_vai_top_bin_width:units = "m2/m2" ; + fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; + double fates_vai_width_increase_factor ; + fates_vai_width_increase_factor:units = "unitless" ; + fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; + +// global attributes: + :history = "This file was generated by BatchPatchParams.py:\nCDL Base File = archive/api24.1.0_101722_fates_params_default.cdl\nXML patch file = archive/api24.1.0_101722_patch_params.xml" ; +data: + + fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; + + fates_history_coageclass_bin_edges = 0, 5 ; + + fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; + + fates_history_damage_bin_edges = 0, 80 ; + + fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, + 80, 90, 100 ; + + fates_alloc_organ_id = 1, 2, 3, 6 ; + + fates_hydro_htftype_node = 1, 1, 1, 1 ; + + fates_pftname = + "broadleaf_evergreen_tropical_tree ", + "needleleaf_evergreen_extratrop_tree ", + "needleleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_tree ", + "broadleaf_hydrodecid_tropical_tree ", + "broadleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_shrub ", + "broadleaf_hydrodecid_extratrop_shrub ", + "broadleaf_colddecid_extratrop_shrub ", + "arctic_c3_grass ", + "cool_c3_grass ", + "c4_grass " ; + + fates_hydro_organ_name = + "leaf ", + "stem ", + "transporting root ", + "absorbing root " ; + + fates_alloc_organ_name = + "leaf", + "fine root", + "sapwood", + "structure" ; + + fates_litterclass_name = + "twig ", + "small branch ", + "large branch ", + "trunk ", + "dead leaves ", + "live grass " ; + + 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, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; + + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + 1.2, 1.2, 1.2 ; + + fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8, 0.8 ; + + fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, + 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; + + fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, + 0.572, 0.572, 0.572, 0.572 ; + + fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, + 1.94, 1.94, 1.94 ; + + fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, + 0.931, 0.931, 0.931, 0.931 ; + + fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6 ; + + fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, + 0.95, 1, 1, 1 ; + + fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07 ; + + fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, + 1.3 ; + + fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, + 0.55, 0.55, 0.55 ; + + fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464 ; + + fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119 ; + + fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, + 0.64, 0.64, 0.64 ; + + fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, + 0.37, 0.37, 0.37 ; + + fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, + -999.9, -999.9, -999.9, -999.9, -999.9 ; + + fates_allom_dbh_maxheight = 90, 80, 80, 80, 90, 80, 3, 3, 2, 0.35, 0.35, 0.35 ; + + fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; + + fates_allom_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; + + fates_allom_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8 ; + + fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_zroot_k = 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 ; + + fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; + + fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + + fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 280, 280 ; + + fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, + 0.14, 0.14, 0.14 ; + + fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, + 0.27, 0.27, 0.27 ; + + fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_nfix1 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_pid_kd = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; + + fates_cnp_pid_ki = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_pid_kp = 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005 ; + + fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_turnover_nitr_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_turnover_phos_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_vmax_nh4 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, + 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; + + fates_cnp_vmax_no3 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, + 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; + + fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, + 5e-10, 5e-10, 5e-10, 5e-10 ; + + fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01 ; + + fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; + + fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, + 5.5, 5.5 ; + + fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2 ; + + fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07, 0.07 ; + + fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, + 0.775, 0.775, 0.775, 0.775, 0.775 ; + + fates_frag_fnrt_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_fnrt_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_fnrt_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_leaf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, + 0.51, 0.51, 0.51, 0.51 ; + + fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, + 0.11, 0.11 ; + + fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + 2.5, 2.5 ; + + fates_hydro_avuln_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_hydro_epsil_node = + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_hydro_fcap_node = + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_kmax_node = + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; + + fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + -1.5, -1.5, -1.5 ; + + fates_hydro_p50_node = + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25 ; + + fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, + 0.333, 0.333, 0.333, 0.333, 0.333 ; + + fates_hydro_pinot_node = + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; + + fates_hydro_pitlp_node = + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + -1.67, -1.67, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; + + fates_hydro_resid_node = + 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; + + fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + 0.625, 0.625, 0.625, 0.625, 0.625 ; + + fates_hydro_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, + 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; + + fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; + + fates_hydro_thetas_node = + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; + + fates_hydro_vg_alpha_node = + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005 ; + + fates_hydro_vg_m_node = + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_hydro_vg_n_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_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, + 43540, 43540, 43540, 43540 ; + + fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, + 152040, 152040, 152040, 152040, 152040 ; + + fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, + 495 ; + + fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, + 0.03, 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_slatop = 0.012, 0.005, 0.024, 0.009, 0.03, 0.03, 0.012, 0.03, + 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, + 10000, 10000, 10000, 10000, 10000, 40000 ; + + fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, + 4.7, 2.2, 5.3, 1.6 ; + + fates_leaf_vcmax25top = + 50, 62, 39, 61, 41, 58, 62, 54, 54, 78, 78, 78 ; + + fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, + 65330, 65330, 65330, 65330 ; + + fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, + 149250, 149250, 149250, 149250, 149250 ; + + fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, + 485 ; + + fates_maintresp_leaf_atkin2017_baserate = 1.756, 1.4995, 1.4995, 1.756, + 1.756, 1.756, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956, 2.1956 ; + + fates_maintresp_leaf_ryan1991_baserate = 2.525e-06, 2.525e-06, 2.525e-06, + 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, + 2.525e-06, 2.525e-06, 2.525e-06 ; + + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; + + fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, + 0.014, 0.014, 0.014, 0.014 ; + + fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -80, -60, -10, -80, -80, + -20, 2.5 ; + + fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, + 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; + + fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_prescribed_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, + 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; + + fates_mort_prescribed_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, + 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; + + fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_nonhydro_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, + -255000, -255000, -255000, -255000, -255000, -255000 ; + + fates_nonhydro_smpso = -66000, -66000, -66000, -66000, -66000, -66000, + -66000, -66000, -66000, -66000, -66000, -66000 ; + + fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; + + fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, + 0.5 ; + + fates_phen_fnrt_drop_frac = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; + + fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; + + fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, + 0.4, 0.4, 0.4 ; + + fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, + 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; + + fates_rad_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, + 0.9, 0.75, 0.75, 0.75 ; + + fates_rad_leaf_rhonir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, + 0.41, 0.28, 0.28, 0.28 ; + + fates_rad_leaf_rhovis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, + 0.08, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_taunir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, + 0.43, 0.4, 0.4, 0.4 ; + + fates_rad_leaf_tauvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, + 0.06, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, + -0.23, -0.23, -0.23 ; + + fates_rad_stem_rhonir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, + 0.49, 0.53, 0.53, 0.53 ; + + fates_rad_stem_rhovis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.31, 0.31, 0.31 ; + + fates_rad_stem_taunir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.25, 0.25, 0.25 ; + + fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.12, 0.12, 0.12 ; + + fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.2, 0.2, 0.2, + 0.125, 0.125, 0.125 ; + + fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2, 0.2, 0.2 ; + + fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, + 0.02, 0.02, 0.02, 0.02, 0.02 ; + + fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, + 0.9 ; + + fates_recruit_seed_dbh_repro_threshold = 90, 80, 80, 80, 90, 80, 3, 3, 2, + 0.35, 0.35, 0.35 ; + + fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_stoich_nitr = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; + + fates_stoich_phos = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; + + fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, + 0.03, 0.03 ; + + fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; + + fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, + 0.67, 0.67, 0.67 ; + + fates_turb_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.04, 0.04, 0.04, 0.04 ; + + fates_turb_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, + 0.055, 0.055, 0.055, 0.055 ; + + fates_turnover_branch = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; + + fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_leaf = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_wood_density = 0.7, 0.4, 0.7, 0.53, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, + 0.7 ; + + fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; + + fates_hlm_pft_map = + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + + fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; + + fates_fire_low_moisture_Coeff = 1.12, 1.09, 0.98, 0.8, 1.15, 1.15 ; + + fates_fire_low_moisture_Slope = 0.62, 0.72, 0.85, 0.8, 0.62, 0.62 ; + + fates_fire_mid_moisture = 0.72, 0.51, 0.38, 1, 0.8, 0.8 ; + + fates_fire_mid_moisture_Coeff = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_mid_moisture_Slope = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_min_moisture = 0.18, 0.12, 0, 0, 0.24, 0.24 ; + + fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; + + fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; + + fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; + + fates_canopy_closure_thresh = 0.8 ; + + fates_cnp_eca_plant_escalar = 1.25e-05 ; + + fates_cohort_age_fusion_tol = 0.08 ; + + fates_cohort_size_fusion_tol = 0.08 ; + + fates_comp_excln = 3 ; + + fates_damage_canopy_layer_code = 1 ; + + fates_damage_event_code = 1 ; + + fates_dev_arbitrary = _ ; + + fates_fire_active_crown_fire = 0 ; + + fates_fire_cg_strikes = 0.2 ; + + fates_fire_drying_ratio = 66000 ; + + fates_fire_durat_slope = -11.06 ; + + fates_fire_fdi_a = 17.62 ; + + fates_fire_fdi_alpha = 0.00037 ; + + fates_fire_fdi_b = 243.12 ; + + fates_fire_fuel_energy = 18000 ; + + fates_fire_max_durat = 240 ; + + fates_fire_miner_damp = 0.41739 ; + + fates_fire_miner_total = 0.055 ; + + fates_fire_nignitions = 15 ; + + fates_fire_part_dens = 513 ; + + fates_fire_threshold = 50 ; + + fates_frag_cwd_fcel = 0.76 ; + + fates_frag_cwd_flig = 0.24 ; + + fates_hydro_kmax_rsurf1 = 20 ; + + fates_hydro_kmax_rsurf2 = 0.0001 ; + + fates_hydro_psi0 = 0 ; + + fates_hydro_psicap = -0.6 ; + + fates_hydro_solver = 1 ; + + fates_landuse_logging_coll_under_frac = 0.55983 ; + + fates_landuse_logging_collateral_frac = 0.05 ; + + fates_landuse_logging_dbhmax = _ ; + + fates_landuse_logging_dbhmax_infra = 35 ; + + fates_landuse_logging_dbhmin = 50 ; + + fates_landuse_logging_direct_frac = 0.15 ; + + fates_landuse_logging_event_code = -30 ; + + fates_landuse_logging_export_frac = 0.8 ; + + fates_landuse_logging_mechanical_frac = 0.05 ; + + fates_landuse_pprodharv10_forest_mean = 0.8125 ; + + fates_leaf_photo_temp_acclim_thome_time = 30 ; + + fates_leaf_photo_temp_acclim_timescale = 30 ; + + fates_leaf_photo_tempsens_model = 1 ; + + fates_leaf_stomatal_assim_model = 1 ; + + fates_leaf_stomatal_model = 1 ; + + fates_leaf_theta_cj_c3 = 0.999 ; + + fates_leaf_theta_cj_c4 = 0.999 ; + + fates_maintresp_leaf_model = 1 ; + + fates_maintresp_nonleaf_baserate = 2.525e-06 ; + + fates_maxcohort = 100 ; + + fates_maxpatch_primary = 10 ; + + fates_maxpatch_secondary = 4 ; + + fates_mort_disturb_frac = 1 ; + + fates_mort_understorey_death = 0.55983 ; + + fates_patch_fusion_tol = 0.05 ; + + fates_phen_chilltemp = 5 ; + + fates_phen_coldtemp = 7.5 ; + + fates_phen_drought_model = 0 ; + + fates_phen_drought_threshold = 0.15 ; + + fates_phen_gddthresh_a = -68 ; + + fates_phen_gddthresh_b = 638 ; + + fates_phen_gddthresh_c = -0.01 ; + + fates_phen_mindaysoff = 100 ; + + fates_phen_mindayson = 90 ; + + fates_phen_moist_threshold = 0.18 ; + + fates_phen_ncolddayslim = 5 ; + + fates_q10_froz = 1.5 ; + + fates_q10_mr = 1.5 ; + + fates_soil_salinity = 0.4 ; + + fates_vai_top_bin_width = 1 ; + + fates_vai_width_increase_factor = 1 ; +} diff --git a/parameter_files/archive/api25.3.0_032223_pr995.xml b/parameter_files/archive/api25.3.0_032223_pr995.xml new file mode 100644 index 0000000000..e68fb782cc --- /dev/null +++ b/parameter_files/archive/api25.3.0_032223_pr995.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + archive/api25.3.0_032223_fates_params_default.cdl + fates_params_default.cdl + 1,2,3,4,5,6,7,8,9,10,11,12 + + + initial seedling density for a cold-start near-bare-ground simulation. If negative sets initial tree dbh - only to be used in nocomp mode + + + diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index fd5f0d6dd3..d461cb6fbb 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -496,7 +496,7 @@ variables: fates_recruit_height_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; double fates_recruit_init_density(fates_pft) ; fates_recruit_init_density:units = "stems/m2" ; - fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation. If negative sets initial tree dbh - only to be used in nocomp mode" ; + fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation. If negative sets initial tree dbh - only to be used in nocomp mode" ; double fates_recruit_prescribed_rate(fates_pft) ; fates_recruit_prescribed_rate:units = "n/yr" ; fates_recruit_prescribed_rate:long_name = "recruitment rate for prescribed physiology mode" ; From e50b27bc6e10f1b4d235cebde7e9aa687f8cc9a0 Mon Sep 17 00:00:00 2001 From: Jessica F Needham Date: Wed, 22 Mar 2023 17:15:58 -0700 Subject: [PATCH 582/852] move call to bleaf so it is avoided by sp mode --- main/EDInitMod.F90 | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 7fa7dc4206..45b3ac7551 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -851,6 +851,11 @@ subroutine init_cohorts( site_in, patch_in, bc_in) ! Calculate the plant diameter from height call h2d_allom(temp_cohort%hite,pft,temp_cohort%dbh) + ! Calculate the leaf biomass from allometry + ! (calculates a maximum first, then applies canopy trim) + call bleaf(temp_cohort%dbh,pft,temp_cohort%crowndamage, & + temp_cohort%canopy_trim,c_leaf) + endif ! sp mode else ! interpret as initial diameter and calculate density @@ -865,16 +870,18 @@ subroutine init_cohorts( site_in, patch_in, bc_in) ! calculate initial density required to close canopy temp_cohort%n = patch_in%area / temp_cohort%c_area + + ! Calculate the leaf biomass from allometry + ! (calculates a maximum first, then applies canopy trim) + call bleaf(temp_cohort%dbh,pft,temp_cohort%crowndamage, & + temp_cohort%canopy_trim,c_leaf) + else write(fates_log(),*) 'Negative fates_recruit_init_density can only be used in no comp mode' call endrun(msg=errMsg(sourcefile, __LINE__)) endif endif - ! Calculate the leaf biomass from allometry - ! (calculates a maximum first, then applies canopy trim) - call bleaf(temp_cohort%dbh,pft,temp_cohort%crowndamage, & - temp_cohort%canopy_trim,c_leaf) ! Calculate total above-ground biomass from allometry call bagw_allom(temp_cohort%dbh,pft,temp_cohort%crowndamage,c_agw) From a61a28de04d8961146114f36ef0a3f72a3056458 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 23 Mar 2023 14:28:36 -0700 Subject: [PATCH 583/852] Fix minor bad-merge issue --- biogeochem/EDPhysiologyMod.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 6835ec92f6..7f3daa4d03 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -140,7 +140,6 @@ module EDPhysiologyMod public :: UpdateRecruitStoicH public :: SetRecruitL2FR ->>>>>>> sci.1.65.2_api.25.4.0 logical, parameter :: debug = .false. ! local debug flag character(len=*), parameter, private :: sourcefile = & __FILE__ From de9376f7c68aa37cd1f477379fa729e6ab3fff06 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 23 Mar 2023 15:41:38 -0700 Subject: [PATCH 584/852] Add xmlpatch file with dispersal variables This also renames the dispersal parameters from Bullock et al 2016 to a more correct, descriptive name --- main/EDPftvarcon.F90 | 40 +- main/FatesDispersalMod.F90 | 10 +- main/FatesInterfaceMod.F90 | 4 +- .../api25.4.0_032323_fates_params_default.cdl | 1559 +++++++++++++++++ .../archive/api25.4.0_032323_pr1005.xml | 63 + parameter_files/fates_params_default.cdl | 20 + 6 files changed, 1669 insertions(+), 27 deletions(-) create mode 100644 parameter_files/archive/api25.4.0_032323_fates_params_default.cdl create mode 100644 parameter_files/archive/api25.4.0_032323_pr1005.xml diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 7f0b94a4b8..c8dcfea8de 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -105,8 +105,8 @@ module EDPftvarcon real(r8), allocatable :: germination_rate(:) ! Fraction of seed mass germinating per year (yr-1) real(r8), allocatable :: seed_decay_rate(:) ! Fraction of seed mass (both germinated and ! ungerminated), decaying per year (yr-1) - real(r8), allocatable :: seed_dispersal_param_A(:) ! Seed dispersal scale parameter, Bullock et al. (2017) - real(r8), allocatable :: seed_dispersal_param_B(:) ! Seed dispersal shape parameter, Bullock et al. (2017) + real(r8), allocatable :: seed_dispersal_pdf_scale(:) ! Seed dispersal scale parameter, Bullock et al. (2017) + real(r8), allocatable :: seed_dispersal_pdf_shape(:) ! Seed dispersal shape parameter, Bullock et al. (2017) real(r8), allocatable :: seed_dispersal_max_dist(:) ! Maximum seed dispersal distance parameter (m) real(r8), allocatable :: seed_dispersal_fraction(:) ! Fraction of seed rain to disperse, per pft real(r8), allocatable :: trim_limit(:) ! Limit to reductions in leaf area w stress (m2/m2) @@ -587,11 +587,11 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_seed_dispersal_param_A' + name = 'fates_seed_dispersal_pdf_scale' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_seed_dispersal_param_B' + name = 'fates_seed_dispersal_pdf_shape' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -969,13 +969,13 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetrieveParameterAllocate(name=name, & data=this%seed_decay_rate) - name = 'fates_seed_dispersal_param_A' + name = 'fates_seed_dispersal_pdf_scale' call fates_params%RetrieveParameterAllocate(name=name, & - data=this%seed_dispersal_param_A) + data=this%seed_dispersal_pdf_scale) - name = 'fates_seed_dispersal_param_B' + name = 'fates_seed_dispersal_pdf_shape' call fates_params%RetrieveParameterAllocate(name=name, & - data=this%seed_dispersal_param_B) + data=this%seed_dispersal_pdf_shape) name = 'fates_seed_dispersal_max_dist' call fates_params%RetrieveParameterAllocate(name=name, & @@ -1523,8 +1523,8 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'jmaxse = ',EDPftvarcon_inst%jmaxse write(fates_log(),fmt0) 'germination_timescale = ',EDPftvarcon_inst%germination_rate write(fates_log(),fmt0) 'seed_decay_turnover = ',EDPftvarcon_inst%seed_decay_rate - write(fates_log(),fmt0) 'seed_dispersal_param_A = ',EDPftvarcon_inst%seed_dispersal_param_A - write(fates_log(),fmt0) 'seed_dispersal_param_B = ',EDPftvarcon_inst%seed_dispersal_param_B + write(fates_log(),fmt0) 'seed_dispersal_pdf_scale = ',EDPftvarcon_inst%seed_dispersal_pdf_scale + write(fates_log(),fmt0) 'seed_dispersal_pdf_shape = ',EDPftvarcon_inst%seed_dispersal_pdf_shape write(fates_log(),fmt0) 'seed_dispersal_max_dist = ',EDPftvarcon_inst%seed_dispersal_max_dist write(fates_log(),fmt0) 'seed_dispersal_fraction = ',EDPftvarcon_inst%seed_dispersal_fraction write(fates_log(),fmt0) 'trim_limit = ',EDPftvarcon_inst%trim_limit @@ -1716,24 +1716,24 @@ subroutine FatesCheckParams(is_master) ! Check that the seed dispersal parameters are all set if one of them is set !----------------------------------------------------------------------------------- - if (( EDPftvarcon_inst%seed_dispersal_param_A(ipft) < fates_check_param_set ) .and. & + if (( EDPftvarcon_inst%seed_dispersal_pdf_scale(ipft) < fates_check_param_set ) .and. & (( EDPftvarcon_inst%seed_dispersal_max_dist(ipft) > fates_check_param_set ) .or. & - ( EDPftvarcon_inst%seed_dispersal_param_B(ipft) > fates_check_param_set ) .or. & + ( EDPftvarcon_inst%seed_dispersal_pdf_shape(ipft) > fates_check_param_set ) .or. & ( EDPftvarcon_inst%seed_dispersal_fraction(ipft) > fates_check_param_set ))) then - write(fates_log(),*) 'Seed dispersal is on per fates_seed_dispersal_param_A being set' + write(fates_log(),*) 'Seed dispersal is on per fates_seed_dispersal_pdf_scale being set' write(fates_log(),*) 'Please provide values for all other seed_dispersal parameters' write(fates_log(),*) 'See Bullock et al. (2017) for reasonable values' write(fates_log(),*) 'Aborting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if (( EDPftvarcon_inst%seed_dispersal_param_B(ipft) < fates_check_param_set ) .and. & + if (( EDPftvarcon_inst%seed_dispersal_pdf_shape(ipft) < fates_check_param_set ) .and. & (( EDPftvarcon_inst%seed_dispersal_max_dist(ipft) > fates_check_param_set ) .or. & - ( EDPftvarcon_inst%seed_dispersal_param_A(ipft) > fates_check_param_set ) .or. & + ( EDPftvarcon_inst%seed_dispersal_pdf_scale(ipft) > fates_check_param_set ) .or. & ( EDPftvarcon_inst%seed_dispersal_fraction(ipft) > fates_check_param_set ))) then - write(fates_log(),*) 'Seed dispersal is on per fates_seed_dispersal_param_B being set' + write(fates_log(),*) 'Seed dispersal is on per fates_seed_dispersal_pdf_shape being set' write(fates_log(),*) 'Please provide values for all other seed_dispersal parameters' write(fates_log(),*) 'See Bullock et al. (2017) for reasonable values' write(fates_log(),*) 'Aborting' @@ -1741,8 +1741,8 @@ subroutine FatesCheckParams(is_master) end if if (( EDPftvarcon_inst%seed_dispersal_max_dist(ipft) < fates_check_param_set ) .and. & - (( EDPftvarcon_inst%seed_dispersal_param_B(ipft) > fates_check_param_set ) .or. & - ( EDPftvarcon_inst%seed_dispersal_param_A(ipft) > fates_check_param_set ) .or. & + (( EDPftvarcon_inst%seed_dispersal_pdf_shape(ipft) > fates_check_param_set ) .or. & + ( EDPftvarcon_inst%seed_dispersal_pdf_scale(ipft) > fates_check_param_set ) .or. & ( EDPftvarcon_inst%seed_dispersal_fraction(ipft) > fates_check_param_set ))) then write(fates_log(),*) 'Seed dispersal is on per seed_dispersal_max_dist being set' @@ -1753,8 +1753,8 @@ subroutine FatesCheckParams(is_master) end if if (( EDPftvarcon_inst%seed_dispersal_fraction(ipft) < fates_check_param_set ) .and. & - (( EDPftvarcon_inst%seed_dispersal_param_B(ipft) > fates_check_param_set ) .or. & - ( EDPftvarcon_inst%seed_dispersal_param_A(ipft) > fates_check_param_set ) .or. & + (( EDPftvarcon_inst%seed_dispersal_pdf_shape(ipft) > fates_check_param_set ) .or. & + ( EDPftvarcon_inst%seed_dispersal_pdf_scale(ipft) > fates_check_param_set ) .or. & ( EDPftvarcon_inst%seed_dispersal_max_dist(ipft) > fates_check_param_set ))) then write(fates_log(),*) 'Seed dispersal is on per seed_dispersal_fraction being set' diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index 17a59bdbfb..cda56e212e 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -140,7 +140,7 @@ real(r8) function PD_exponential(dist, ipft) ! Assuming simple exponential decay. In the future perhaps this could be an interface ! for different weight calculations (and could be held only in fates) - PD_exponential = exp(-EDPftvarcon_inst%seed_dispersal_param_A(ipft)*dist) + PD_exponential = exp(-EDPftvarcon_inst%seed_dispersal_pdf_scale(ipft)*dist) write(fates_log(),*) 'ipft,dist,PD_exp: ', ipft, dist, PD_exponential end function PD_exponential @@ -156,8 +156,8 @@ real(r8) function PD_exppower(dist, ipft) integer, intent(in) :: ipft associate(& - param_a => EDPftvarcon_inst%seed_dispersal_param_A(ipft), & - param_b => EDPftvarcon_inst%seed_dispersal_param_B(ipft)) + param_a => EDPftvarcon_inst%seed_dispersal_pdf_scale(ipft), & + param_b => EDPftvarcon_inst%seed_dispersal_pdf_shape(ipft)) PD_exppower = (param_b / (2*pi_const*gamma(2/param_b))) * & exp(-(dist**param_b)/(param_a**param_b)) @@ -177,8 +177,8 @@ real(r8) function PD_logsech(dist, ipft) integer, intent(in) :: ipft associate(& - param_a => EDPftvarcon_inst%seed_dispersal_param_A(ipft), & - param_b => EDPftvarcon_inst%seed_dispersal_param_B(ipft)) + param_a => EDPftvarcon_inst%seed_dispersal_pdf_scale(ipft), & + param_b => EDPftvarcon_inst%seed_dispersal_pdf_shape(ipft)) PD_logsech = (1/(pi_const**2 * param_b * dist**2)) / & ((dist/param_a)**(1/param_b) + & diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 6cc7abd40b..f5fc5ccb44 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -954,7 +954,7 @@ subroutine SetFatesGlobalElements2(use_fates) ! Set the fates dispersal kernel mode if there are any seed dispersal parameters set. ! The validation of the parameter values is check in FatesCheckParams prior to this check. ! This is currently hard coded. - if(any(EDPftvarcon_inst%seed_dispersal_param_A .lt. fates_check_param_set)) then + if(any(EDPftvarcon_inst%seed_dispersal_pdf_scale .lt. fates_check_param_set)) then fates_dispersal_kernel_mode = fates_dispersal_kernel_exponential ! fates_dispersal_kernel_mode = fates_dispersal_kernel_exppower ! fates_dispersal_kernel_mode = fates_dispersal_kernel_logsech @@ -964,7 +964,7 @@ subroutine SetFatesGlobalElements2(use_fates) ! Set the fates dispersal cadence if seed dispersal parameters are set. ! This could be a parameter value setting as well. Currently hardcoded - if(any(EDPftvarcon_inst%seed_dispersal_param_A .lt. fates_check_param_set)) then + if(any(EDPftvarcon_inst%seed_dispersal_pdf_scale .lt. fates_check_param_set)) then fates_dispersal_cadence = fates_dispersal_cadence_daily !fates_dispersal_cadence = fates_dispersal_cadence_monthly ! fates_dispersal_cadence = fates_dispersal_cadence_yearly diff --git a/parameter_files/archive/api25.4.0_032323_fates_params_default.cdl b/parameter_files/archive/api25.4.0_032323_fates_params_default.cdl new file mode 100644 index 0000000000..d461cb6fbb --- /dev/null +++ b/parameter_files/archive/api25.4.0_032323_fates_params_default.cdl @@ -0,0 +1,1559 @@ +netcdf fates_params_default { +dimensions: + fates_NCWD = 4 ; + fates_history_age_bins = 7 ; + fates_history_coage_bins = 2 ; + fates_history_damage_bins = 2 ; + fates_history_height_bins = 6 ; + fates_history_size_bins = 13 ; + fates_hlm_pftno = 14 ; + fates_hydr_organs = 4 ; + fates_leafage_class = 1 ; + fates_litterclass = 6 ; + fates_pft = 12 ; + fates_plant_organs = 4 ; + fates_string_length = 60 ; +variables: + double fates_history_ageclass_bin_edges(fates_history_age_bins) ; + fates_history_ageclass_bin_edges:units = "yr" ; + fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; + double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; + fates_history_coageclass_bin_edges:units = "years" ; + fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; + double fates_history_height_bin_edges(fates_history_height_bins) ; + fates_history_height_bin_edges:units = "m" ; + fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; + double fates_history_damage_bin_edges(fates_history_damage_bins) ; + fates_history_damage_bin_edges:units = "% crown loss" ; + fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; + double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; + fates_history_sizeclass_bin_edges:units = "cm" ; + fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; + double fates_alloc_organ_id(fates_plant_organs) ; + fates_alloc_organ_id:units = "unitless" ; + fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; + double fates_hydro_htftype_node(fates_hydr_organs) ; + fates_hydro_htftype_node:units = "unitless" ; + fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; + char fates_pftname(fates_pft, fates_string_length) ; + fates_pftname:units = "unitless - string" ; + fates_pftname:long_name = "Description of plant type" ; + char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; + fates_hydro_organ_name:units = "unitless - string" ; + fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; + char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; + fates_alloc_organ_name:units = "unitless - string" ; + fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; + 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" ; + 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" ; + double fates_alloc_storage_cushion(fates_pft) ; + fates_alloc_storage_cushion:units = "fraction" ; + fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; + double fates_alloc_store_priority_frac(fates_pft) ; + fates_alloc_store_priority_frac:units = "unitless" ; + fates_alloc_store_priority_frac:long_name = "for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage" ; + double fates_allom_agb1(fates_pft) ; + fates_allom_agb1:units = "variable" ; + fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; + double fates_allom_agb2(fates_pft) ; + fates_allom_agb2:units = "variable" ; + fates_allom_agb2:long_name = "Parameter 2 for agb allometry" ; + double fates_allom_agb3(fates_pft) ; + fates_allom_agb3:units = "variable" ; + fates_allom_agb3:long_name = "Parameter 3 for agb allometry" ; + double fates_allom_agb4(fates_pft) ; + fates_allom_agb4:units = "variable" ; + fates_allom_agb4:long_name = "Parameter 4 for agb allometry" ; + double fates_allom_agb_frac(fates_pft) ; + fates_allom_agb_frac:units = "fraction" ; + fates_allom_agb_frac:long_name = "Fraction of woody biomass that is above ground" ; + double fates_allom_amode(fates_pft) ; + fates_allom_amode:units = "index" ; + fates_allom_amode:long_name = "AGB allometry function index." ; + double fates_allom_blca_expnt_diff(fates_pft) ; + fates_allom_blca_expnt_diff:units = "unitless" ; + fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; + double fates_allom_cmode(fates_pft) ; + fates_allom_cmode:units = "index" ; + fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; + double fates_allom_crown_depth_frac(fates_pft) ; + fates_allom_crown_depth_frac:units = "fraction" ; + fates_allom_crown_depth_frac:long_name = "the depth of a cohort crown as a fraction of its height" ; + double fates_allom_d2bl1(fates_pft) ; + fates_allom_d2bl1:units = "variable" ; + fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; + double fates_allom_d2bl2(fates_pft) ; + fates_allom_d2bl2:units = "variable" ; + fates_allom_d2bl2:long_name = "Parameter 2 for d2bl allometry" ; + double fates_allom_d2bl3(fates_pft) ; + fates_allom_d2bl3:units = "unitless" ; + fates_allom_d2bl3:long_name = "Parameter 3 for d2bl allometry" ; + double fates_allom_d2ca_coefficient_max(fates_pft) ; + fates_allom_d2ca_coefficient_max:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_max:long_name = "max (savanna) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2ca_coefficient_min(fates_pft) ; + fates_allom_d2ca_coefficient_min:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_min:long_name = "min (forest) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2h1(fates_pft) ; + fates_allom_d2h1:units = "variable" ; + fates_allom_d2h1:long_name = "Parameter 1 for d2h allometry (intercept, or c)" ; + double fates_allom_d2h2(fates_pft) ; + fates_allom_d2h2:units = "variable" ; + fates_allom_d2h2:long_name = "Parameter 2 for d2h allometry (slope, or m)" ; + double fates_allom_d2h3(fates_pft) ; + fates_allom_d2h3:units = "variable" ; + fates_allom_d2h3:long_name = "Parameter 3 for d2h allometry (optional)" ; + double fates_allom_dbh_maxheight(fates_pft) ; + fates_allom_dbh_maxheight:units = "cm" ; + fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; + double fates_allom_fmode(fates_pft) ; + fates_allom_fmode:units = "index" ; + fates_allom_fmode:long_name = "fine root biomass allometry function index." ; + double fates_allom_fnrt_prof_a(fates_pft) ; + fates_allom_fnrt_prof_a:units = "unitless" ; + fates_allom_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; + double fates_allom_fnrt_prof_b(fates_pft) ; + fates_allom_fnrt_prof_b:units = "unitless" ; + fates_allom_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; + double fates_allom_fnrt_prof_mode(fates_pft) ; + fates_allom_fnrt_prof_mode:units = "index" ; + fates_allom_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; + double fates_allom_frbstor_repro(fates_pft) ; + fates_allom_frbstor_repro:units = "fraction" ; + fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; + double fates_allom_hmode(fates_pft) ; + fates_allom_hmode:units = "index" ; + fates_allom_hmode:long_name = "height allometry function index." ; + double fates_allom_l2fr(fates_pft) ; + fates_allom_l2fr:units = "gC/gC" ; + fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; + double fates_allom_la_per_sa_int(fates_pft) ; + fates_allom_la_per_sa_int:units = "m2/cm2" ; + fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; + double fates_allom_la_per_sa_slp(fates_pft) ; + fates_allom_la_per_sa_slp:units = "m2/cm2/m" ; + fates_allom_la_per_sa_slp:long_name = "Leaf area per sapwood area rate of change with height, slope (optional)" ; + double fates_allom_lmode(fates_pft) ; + fates_allom_lmode:units = "index" ; + fates_allom_lmode:long_name = "leaf biomass allometry function index." ; + double fates_allom_sai_scaler(fates_pft) ; + fates_allom_sai_scaler:units = "m2/m2" ; + fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; + double fates_allom_smode(fates_pft) ; + fates_allom_smode:units = "index" ; + fates_allom_smode:long_name = "sapwood allometry function index." ; + double fates_allom_stmode(fates_pft) ; + fates_allom_stmode:units = "index" ; + fates_allom_stmode:long_name = "storage allometry function index: 1) Storage proportional to leaf biomass (with trimming), 2) Storage proportional to maximum leaf biomass (not trimmed)" ; + double fates_allom_zroot_k(fates_pft) ; + fates_allom_zroot_k:units = "unitless" ; + fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; + double fates_allom_zroot_max_dbh(fates_pft) ; + fates_allom_zroot_max_dbh:units = "cm" ; + fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; + double fates_allom_zroot_max_z(fates_pft) ; + fates_allom_zroot_max_z:units = "m" ; + fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_allom_zroot_min_dbh(fates_pft) ; + fates_allom_zroot_min_dbh:units = "cm" ; + fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; + double fates_allom_zroot_min_z(fates_pft) ; + fates_allom_zroot_min_z:units = "m" ; + fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_c2b(fates_pft) ; + fates_c2b:units = "ratio" ; + fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; + double fates_cnp_eca_alpha_ptase(fates_pft) ; + fates_cnp_eca_alpha_ptase:units = "g/m3" ; + fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; + double fates_cnp_eca_decompmicc(fates_pft) ; + fates_cnp_eca_decompmicc:units = "gC/m3" ; + fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; + double fates_cnp_eca_km_nh4(fates_pft) ; + fates_cnp_eca_km_nh4:units = "gN/m3" ; + fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; + double fates_cnp_eca_km_no3(fates_pft) ; + fates_cnp_eca_km_no3:units = "gN/m3" ; + fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; + double fates_cnp_eca_km_p(fates_pft) ; + fates_cnp_eca_km_p:units = "gP/m3" ; + fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; + double fates_cnp_eca_km_ptase(fates_pft) ; + fates_cnp_eca_km_ptase:units = "gP/m3" ; + fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; + double fates_cnp_eca_lambda_ptase(fates_pft) ; + fates_cnp_eca_lambda_ptase:units = "g/m3" ; + fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; + double fates_cnp_eca_vmax_ptase(fates_pft) ; + fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; + fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; + double fates_cnp_nfix1(fates_pft) ; + fates_cnp_nfix1:units = "fraction" ; + fates_cnp_nfix1:long_name = "fractional surcharge added to maintenance respiration that drives symbiotic fixation" ; + double fates_cnp_nitr_store_ratio(fates_pft) ; + fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; + fates_cnp_nitr_store_ratio:long_name = "storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code)" ; + double fates_cnp_phos_store_ratio(fates_pft) ; + fates_cnp_phos_store_ratio:units = "(gP/gP)" ; + fates_cnp_phos_store_ratio:long_name = "storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code)" ; + double fates_cnp_pid_kd(fates_pft) ; + fates_cnp_pid_kd:units = "unknown" ; + fates_cnp_pid_kd:long_name = "derivative constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_pid_ki(fates_pft) ; + fates_cnp_pid_ki:units = "unknown" ; + fates_cnp_pid_ki:long_name = "integral constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_pid_kp(fates_pft) ; + fates_cnp_pid_kp:units = "unknown" ; + fates_cnp_pid_kp:long_name = "proportional constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_prescribed_nuptake(fates_pft) ; + fates_cnp_prescribed_nuptake:units = "fraction" ; + fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; + double fates_cnp_prescribed_puptake(fates_pft) ; + fates_cnp_prescribed_puptake:units = "fraction" ; + fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; + double fates_cnp_store_ovrflw_frac(fates_pft) ; + fates_cnp_store_ovrflw_frac:units = "fraction" ; + fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; + double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_nitr_retrans:units = "fraction" ; + fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; + double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_phos_retrans:units = "fraction" ; + fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; + double fates_cnp_vmax_nh4(fates_pft) ; + fates_cnp_vmax_nh4:units = "gN/gC/s" ; + fates_cnp_vmax_nh4:long_name = "maximum (potential) uptake rate of NH4 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_nh4 for usage)" ; + double fates_cnp_vmax_no3(fates_pft) ; + fates_cnp_vmax_no3:units = "gN/gC/s" ; + fates_cnp_vmax_no3:long_name = "maximum (potential) uptake rate of NO3 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_no3 for usage)" ; + double fates_cnp_vmax_p(fates_pft) ; + fates_cnp_vmax_p:units = "gP/gC/s" ; + fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; + double fates_damage_frac(fates_pft) ; + fates_damage_frac:units = "fraction" ; + fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; + double fates_damage_mort_p1(fates_pft) ; + fates_damage_mort_p1:units = "fraction" ; + fates_damage_mort_p1:long_name = "inflection point of damage mortality function, a value of 0.8 means 50% mortality with 80% loss of crown, turn off with a large number" ; + double fates_damage_mort_p2(fates_pft) ; + fates_damage_mort_p2:units = "unitless" ; + fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; + 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_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" ; + double fates_fire_alpha_SH(fates_pft) ; + fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; + fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; + double fates_fire_bark_scaler(fates_pft) ; + fates_fire_bark_scaler:units = "fraction" ; + fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; + double fates_fire_crown_kill(fates_pft) ; + fates_fire_crown_kill:units = "NA" ; + fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; + double fates_frag_fnrt_fcel(fates_pft) ; + fates_frag_fnrt_fcel:units = "fraction" ; + fates_frag_fnrt_fcel:long_name = "Fine root litter cellulose fraction" ; + double fates_frag_fnrt_flab(fates_pft) ; + fates_frag_fnrt_flab:units = "fraction" ; + fates_frag_fnrt_flab:long_name = "Fine root litter labile fraction" ; + double fates_frag_fnrt_flig(fates_pft) ; + fates_frag_fnrt_flig:units = "fraction" ; + fates_frag_fnrt_flig:long_name = "Fine root litter lignin fraction" ; + double fates_frag_leaf_fcel(fates_pft) ; + fates_frag_leaf_fcel:units = "fraction" ; + fates_frag_leaf_fcel:long_name = "Leaf litter cellulose fraction" ; + double fates_frag_leaf_flab(fates_pft) ; + fates_frag_leaf_flab:units = "fraction" ; + fates_frag_leaf_flab:long_name = "Leaf litter labile fraction" ; + double fates_frag_leaf_flig(fates_pft) ; + fates_frag_leaf_flig:units = "fraction" ; + fates_frag_leaf_flig:long_name = "Leaf litter lignin fraction" ; + double fates_frag_seed_decay_rate(fates_pft) ; + fates_frag_seed_decay_rate:units = "yr-1" ; + fates_frag_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; + double fates_grperc(fates_pft) ; + fates_grperc:units = "unitless" ; + fates_grperc:long_name = "Growth respiration factor" ; + double fates_hydro_avuln_gs(fates_pft) ; + fates_hydro_avuln_gs:units = "unitless" ; + fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; + double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; + fates_hydro_avuln_node:units = "unitless" ; + fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; + double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; + fates_hydro_epsil_node:units = "MPa" ; + fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; + double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; + fates_hydro_fcap_node:units = "unitless" ; + fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; + double fates_hydro_k_lwp(fates_pft) ; + fates_hydro_k_lwp:units = "unitless" ; + fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; + double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; + fates_hydro_kmax_node:units = "kg/MPa/m/s" ; + fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; + double fates_hydro_p50_gs(fates_pft) ; + fates_hydro_p50_gs:units = "MPa" ; + fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; + double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; + fates_hydro_p50_node:units = "MPa" ; + fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; + double fates_hydro_p_taper(fates_pft) ; + fates_hydro_p_taper:units = "unitless" ; + fates_hydro_p_taper:long_name = "xylem taper exponent" ; + double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pinot_node:units = "MPa" ; + fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; + double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pitlp_node:units = "MPa" ; + fates_hydro_pitlp_node:long_name = "turgor loss point" ; + double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; + fates_hydro_resid_node:units = "cm3/cm3" ; + fates_hydro_resid_node:long_name = "residual water conent" ; + double fates_hydro_rfrac_stem(fates_pft) ; + fates_hydro_rfrac_stem:units = "fraction" ; + fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; + double fates_hydro_rs2(fates_pft) ; + fates_hydro_rs2:units = "m" ; + fates_hydro_rs2:long_name = "absorbing root radius" ; + double fates_hydro_srl(fates_pft) ; + fates_hydro_srl:units = "m g-1" ; + fates_hydro_srl:long_name = "specific root length" ; + double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; + fates_hydro_thetas_node:units = "cm3/cm3" ; + fates_hydro_thetas_node:long_name = "saturated water content" ; + double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_alpha_node:units = "MPa-1" ; + fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; + double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_m_node:units = "unitless" ; + fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; + 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_leaf_c3psn(fates_pft) ; + fates_leaf_c3psn:units = "flag" ; + fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; + double fates_leaf_jmaxha(fates_pft) ; + fates_leaf_jmaxha:units = "J/mol" ; + fates_leaf_jmaxha:long_name = "activation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_jmaxhd(fates_pft) ; + fates_leaf_jmaxhd:units = "J/mol" ; + fates_leaf_jmaxhd:long_name = "deactivation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_jmaxse(fates_pft) ; + fates_leaf_jmaxse:units = "J/mol/K" ; + fates_leaf_jmaxse:long_name = "entropy term for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_slamax(fates_pft) ; + fates_leaf_slamax:units = "m^2/gC" ; + fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; + double fates_leaf_slatop(fates_pft) ; + fates_leaf_slatop:units = "m^2/gC" ; + fates_leaf_slatop:long_name = "Specific Leaf Area (SLA) at top of canopy, projected area basis" ; + double fates_leaf_stomatal_intercept(fates_pft) ; + fates_leaf_stomatal_intercept:units = "umol H2O/m**2/s" ; + fates_leaf_stomatal_intercept:long_name = "Minimum unstressed stomatal conductance for Ball-Berry model and Medlyn model" ; + double fates_leaf_stomatal_slope_ballberry(fates_pft) ; + fates_leaf_stomatal_slope_ballberry:units = "unitless" ; + fates_leaf_stomatal_slope_ballberry:long_name = "stomatal slope parameter, as per Ball-Berry" ; + double fates_leaf_stomatal_slope_medlyn(fates_pft) ; + fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; + fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; + double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; + fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; + fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; + double fates_leaf_vcmaxha(fates_pft) ; + fates_leaf_vcmaxha:units = "J/mol" ; + fates_leaf_vcmaxha:long_name = "activation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_vcmaxhd(fates_pft) ; + fates_leaf_vcmaxhd:units = "J/mol" ; + fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_vcmaxse(fates_pft) ; + fates_leaf_vcmaxse:units = "J/mol/K" ; + fates_leaf_vcmaxse:long_name = "entropy term for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_maintresp_leaf_atkin2017_baserate(fates_pft) ; + fates_maintresp_leaf_atkin2017_baserate:units = "umol CO2/m^2/s" ; + fates_maintresp_leaf_atkin2017_baserate:long_name = "Leaf maintenance respiration base rate parameter (r0) per Atkin et al 2017" ; + double fates_maintresp_leaf_ryan1991_baserate(fates_pft) ; + fates_maintresp_leaf_ryan1991_baserate:units = "gC/gN/s" ; + fates_maintresp_leaf_ryan1991_baserate:long_name = "Leaf maintenance respiration base rate per Ryan et al 1991" ; + double fates_maintresp_reduction_curvature(fates_pft) ; + fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; + fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; + double fates_maintresp_reduction_intercept(fates_pft) ; + fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; + fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; + double fates_mort_bmort(fates_pft) ; + fates_mort_bmort:units = "1/yr" ; + fates_mort_bmort:long_name = "background mortality rate" ; + double fates_mort_freezetol(fates_pft) ; + fates_mort_freezetol:units = "degrees C" ; + fates_mort_freezetol:long_name = "minimum temperature tolerance" ; + double fates_mort_hf_flc_threshold(fates_pft) ; + fates_mort_hf_flc_threshold:units = "fraction" ; + fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; + double fates_mort_hf_sm_threshold(fates_pft) ; + fates_mort_hf_sm_threshold:units = "unitless" ; + fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; + double fates_mort_ip_age_senescence(fates_pft) ; + fates_mort_ip_age_senescence:units = "years" ; + fates_mort_ip_age_senescence:long_name = "Mortality cohort age senescence inflection point. If _ this mortality term is off. Setting this value turns on age dependent mortality. " ; + double fates_mort_ip_size_senescence(fates_pft) ; + fates_mort_ip_size_senescence:units = "dbh cm" ; + fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; + double fates_mort_prescribed_canopy(fates_pft) ; + fates_mort_prescribed_canopy:units = "1/yr" ; + fates_mort_prescribed_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; + double fates_mort_prescribed_understory(fates_pft) ; + fates_mort_prescribed_understory:units = "1/yr" ; + fates_mort_prescribed_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; + double fates_mort_r_age_senescence(fates_pft) ; + fates_mort_r_age_senescence:units = "mortality rate year^-1" ; + fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; + double fates_mort_r_size_senescence(fates_pft) ; + fates_mort_r_size_senescence:units = "mortality rate dbh^-1" ; + fates_mort_r_size_senescence:long_name = "Mortality dbh senescence rate of change. Sensible range is around 0.03-0.06. Larger values give steeper mortality curves." ; + double fates_mort_scalar_coldstress(fates_pft) ; + fates_mort_scalar_coldstress:units = "1/yr" ; + fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; + double fates_mort_scalar_cstarvation(fates_pft) ; + fates_mort_scalar_cstarvation:units = "1/yr" ; + fates_mort_scalar_cstarvation:long_name = "maximum mortality rate from carbon starvation" ; + double fates_mort_scalar_hydrfailure(fates_pft) ; + fates_mort_scalar_hydrfailure:units = "1/yr" ; + fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; + double fates_nonhydro_smpsc(fates_pft) ; + fates_nonhydro_smpsc:units = "mm" ; + fates_nonhydro_smpsc:long_name = "Soil water potential at full stomatal closure" ; + double fates_nonhydro_smpso(fates_pft) ; + fates_nonhydro_smpso:units = "mm" ; + fates_nonhydro_smpso:long_name = "Soil water potential at full stomatal opening" ; + double fates_phen_cold_size_threshold(fates_pft) ; + fates_phen_cold_size_threshold:units = "cm" ; + fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; + double fates_phen_evergreen(fates_pft) ; + fates_phen_evergreen:units = "logical flag" ; + fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; + double fates_phen_flush_fraction(fates_pft) ; + fates_phen_flush_fraction:units = "fraction" ; + fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; + double fates_phen_fnrt_drop_frac(fates_pft) ; + fates_phen_fnrt_drop_frac:units = "fraction" ; + fates_phen_fnrt_drop_frac:long_name = "fraction of fine roots to drop during drought or cold" ; + double fates_phen_season_decid(fates_pft) ; + fates_phen_season_decid:units = "logical flag" ; + fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; + double fates_phen_stem_drop_fraction(fates_pft) ; + fates_phen_stem_drop_fraction:units = "fraction" ; + fates_phen_stem_drop_fraction:long_name = "fraction of stems to drop for non-woody species during drought/cold" ; + double fates_phen_stress_decid(fates_pft) ; + fates_phen_stress_decid:units = "logical flag" ; + fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; + double fates_prescribed_npp_canopy(fates_pft) ; + fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; + double fates_prescribed_npp_understory(fates_pft) ; + fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; + double fates_rad_leaf_clumping_index(fates_pft) ; + fates_rad_leaf_clumping_index:units = "fraction (0-1)" ; + fates_rad_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; + double fates_rad_leaf_rhonir(fates_pft) ; + fates_rad_leaf_rhonir:units = "fraction" ; + fates_rad_leaf_rhonir:long_name = "Leaf reflectance: near-IR" ; + double fates_rad_leaf_rhovis(fates_pft) ; + fates_rad_leaf_rhovis:units = "fraction" ; + fates_rad_leaf_rhovis:long_name = "Leaf reflectance: visible" ; + double fates_rad_leaf_taunir(fates_pft) ; + fates_rad_leaf_taunir:units = "fraction" ; + fates_rad_leaf_taunir:long_name = "Leaf transmittance: near-IR" ; + double fates_rad_leaf_tauvis(fates_pft) ; + fates_rad_leaf_tauvis:units = "fraction" ; + fates_rad_leaf_tauvis:long_name = "Leaf transmittance: visible" ; + double fates_rad_leaf_xl(fates_pft) ; + fates_rad_leaf_xl:units = "unitless" ; + fates_rad_leaf_xl:long_name = "Leaf/stem orientation index" ; + double fates_rad_stem_rhonir(fates_pft) ; + fates_rad_stem_rhonir:units = "fraction" ; + fates_rad_stem_rhonir:long_name = "Stem reflectance: near-IR" ; + double fates_rad_stem_rhovis(fates_pft) ; + fates_rad_stem_rhovis:units = "fraction" ; + fates_rad_stem_rhovis:long_name = "Stem reflectance: visible" ; + double fates_rad_stem_taunir(fates_pft) ; + fates_rad_stem_taunir:units = "fraction" ; + fates_rad_stem_taunir:long_name = "Stem transmittance: near-IR" ; + double fates_rad_stem_tauvis(fates_pft) ; + fates_rad_stem_tauvis:units = "fraction" ; + fates_rad_stem_tauvis:long_name = "Stem transmittance: visible" ; + double fates_recruit_height_min(fates_pft) ; + fates_recruit_height_min:units = "m" ; + fates_recruit_height_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; + double fates_recruit_init_density(fates_pft) ; + fates_recruit_init_density:units = "stems/m2" ; + fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation. If negative sets initial tree dbh - only to be used in nocomp mode" ; + double fates_recruit_prescribed_rate(fates_pft) ; + fates_recruit_prescribed_rate:units = "n/yr" ; + fates_recruit_prescribed_rate:long_name = "recruitment rate for prescribed physiology mode" ; + double fates_recruit_seed_alloc(fates_pft) ; + fates_recruit_seed_alloc:units = "fraction" ; + fates_recruit_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; + double fates_recruit_seed_alloc_mature(fates_pft) ; + fates_recruit_seed_alloc_mature:units = "fraction" ; + fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; + double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; + fates_recruit_seed_dbh_repro_threshold:units = "cm" ; + fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter where the plant will increase allocation to the seed pool by fraction: fates_recruit_seed_alloc_mature" ; + double fates_recruit_seed_germination_rate(fates_pft) ; + fates_recruit_seed_germination_rate:units = "yr-1" ; + fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; + double fates_recruit_seed_supplement(fates_pft) ; + fates_recruit_seed_supplement:units = "KgC/m2/yr" ; + fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; + double fates_stoich_nitr(fates_plant_organs, fates_pft) ; + fates_stoich_nitr:units = "gN/gC" ; + fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; + double fates_stoich_phos(fates_plant_organs, fates_pft) ; + fates_stoich_phos:units = "gP/gC" ; + fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; + double fates_trim_inc(fates_pft) ; + fates_trim_inc:units = "m2/m2" ; + fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; + double fates_trim_limit(fates_pft) ; + fates_trim_limit:units = "m2/m2" ; + fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; + double fates_turb_displar(fates_pft) ; + fates_turb_displar:units = "unitless" ; + fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; + double fates_turb_leaf_diameter(fates_pft) ; + fates_turb_leaf_diameter:units = "m" ; + fates_turb_leaf_diameter:long_name = "Characteristic leaf dimension" ; + double fates_turb_z0mr(fates_pft) ; + fates_turb_z0mr:units = "unitless" ; + fates_turb_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; + double fates_turnover_branch(fates_pft) ; + fates_turnover_branch:units = "yr" ; + fates_turnover_branch:long_name = "turnover time of branches" ; + double fates_turnover_fnrt(fates_pft) ; + fates_turnover_fnrt:units = "yr" ; + fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; + double fates_turnover_leaf(fates_leafage_class, fates_pft) ; + fates_turnover_leaf:units = "yr" ; + fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; + double fates_turnover_senleaf_fdrought(fates_pft) ; + fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; + fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; + double fates_wood_density(fates_pft) ; + fates_wood_density:units = "g/cm3" ; + fates_wood_density:long_name = "mean density of woody tissue in plant" ; + double fates_woody(fates_pft) ; + fates_woody:units = "logical flag" ; + fates_woody:long_name = "Binary woody lifeform flag" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_fire_FBD(fates_litterclass) ; + fates_fire_FBD:units = "kg Biomass/m3" ; + fates_fire_FBD:long_name = "fuel bulk density" ; + double fates_fire_low_moisture_Coeff(fates_litterclass) ; + fates_fire_low_moisture_Coeff:units = "NA" ; + fates_fire_low_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_low_moisture_Slope(fates_litterclass) ; + fates_fire_low_moisture_Slope:units = "NA" ; + fates_fire_low_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture(fates_litterclass) ; + fates_fire_mid_moisture:units = "NA" ; + fates_fire_mid_moisture:long_name = "spitfire litter moisture threshold to be considered medium dry" ; + double fates_fire_mid_moisture_Coeff(fates_litterclass) ; + fates_fire_mid_moisture_Coeff:units = "NA" ; + fates_fire_mid_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture_Slope(fates_litterclass) ; + fates_fire_mid_moisture_Slope:units = "NA" ; + fates_fire_mid_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_min_moisture(fates_litterclass) ; + fates_fire_min_moisture:units = "NA" ; + fates_fire_min_moisture:long_name = "spitfire litter moisture threshold to be considered very dry" ; + double fates_fire_SAV(fates_litterclass) ; + fates_fire_SAV:units = "cm-1" ; + fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; + double fates_frag_maxdecomp(fates_litterclass) ; + fates_frag_maxdecomp:units = "yr-1" ; + fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; + 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_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" ; + double fates_cnp_eca_plant_escalar ; + fates_cnp_eca_plant_escalar:units = "" ; + fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; + double fates_cohort_age_fusion_tol ; + fates_cohort_age_fusion_tol:units = "unitless" ; + fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; + double fates_cohort_size_fusion_tol ; + fates_cohort_size_fusion_tol:units = "unitless" ; + fates_cohort_size_fusion_tol:long_name = "minimum fraction in difference in dbh between cohorts" ; + double fates_comp_excln ; + fates_comp_excln:units = "none" ; + fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; + double fates_damage_canopy_layer_code ; + fates_damage_canopy_layer_code:units = "unitless" ; + fates_damage_canopy_layer_code:long_name = "Integer code that decides whether damage affects canopy trees (1), understory trees (2)" ; + double fates_damage_event_code ; + fates_damage_event_code:units = "unitless" ; + fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; + double fates_dev_arbitrary ; + fates_dev_arbitrary:units = "unknown" ; + fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; + double fates_fire_active_crown_fire ; + fates_fire_active_crown_fire:units = "0 or 1" ; + fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; + double fates_fire_cg_strikes ; + fates_fire_cg_strikes:units = "fraction (0-1)" ; + fates_fire_cg_strikes:long_name = "fraction of cloud to ground lightning strikes" ; + double fates_fire_drying_ratio ; + fates_fire_drying_ratio:units = "NA" ; + fates_fire_drying_ratio:long_name = "spitfire parameter, fire drying ratio for fuel moisture, alpha_FMC EQ 6 Thonicke et al 2010" ; + double fates_fire_durat_slope ; + fates_fire_durat_slope:units = "NA" ; + fates_fire_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; + double fates_fire_fdi_a ; + fates_fire_fdi_a:units = "NA" ; + fates_fire_fdi_a:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010" ; + double fates_fire_fdi_alpha ; + fates_fire_fdi_alpha:units = "NA" ; + fates_fire_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; + double fates_fire_fdi_b ; + fates_fire_fdi_b:units = "NA" ; + fates_fire_fdi_b:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010 " ; + double fates_fire_fuel_energy ; + fates_fire_fuel_energy:units = "kJ/kg" ; + fates_fire_fuel_energy:long_name = "spitfire parameter, heat content of fuel" ; + double fates_fire_max_durat ; + fates_fire_max_durat:units = "minutes" ; + fates_fire_max_durat:long_name = "spitfire parameter, fire maximum duration, Equation 14 Thonicke et al 2010" ; + double fates_fire_miner_damp ; + fates_fire_miner_damp:units = "NA" ; + fates_fire_miner_damp:long_name = "spitfire parameter, mineral-dampening coefficient EQ A1 Thonicke et al 2010 " ; + double fates_fire_miner_total ; + fates_fire_miner_total:units = "fraction" ; + fates_fire_miner_total:long_name = "spitfire parameter, total mineral content, Table A1 Thonicke et al 2010" ; + double fates_fire_nignitions ; + fates_fire_nignitions:units = "ignitions per year per km2" ; + fates_fire_nignitions:long_name = "number of annual ignitions per square km" ; + double fates_fire_part_dens ; + fates_fire_part_dens:units = "kg/m2" ; + fates_fire_part_dens:long_name = "spitfire parameter, oven dry particle density, Table A1 Thonicke et al 2010" ; + double fates_fire_threshold ; + fates_fire_threshold:units = "kW/m" ; + fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; + double fates_frag_cwd_fcel ; + fates_frag_cwd_fcel:units = "unitless" ; + fates_frag_cwd_fcel:long_name = "Cellulose fraction for CWD" ; + double fates_frag_cwd_flig ; + fates_frag_cwd_flig:units = "unitless" ; + fates_frag_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; + double fates_hydro_kmax_rsurf1 ; + fates_hydro_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; + double fates_hydro_kmax_rsurf2 ; + fates_hydro_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; + double fates_hydro_psi0 ; + fates_hydro_psi0:units = "MPa" ; + fates_hydro_psi0:long_name = "sapwood water potential at saturation" ; + double fates_hydro_psicap ; + fates_hydro_psicap:units = "MPa" ; + fates_hydro_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; + 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_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" ; + double fates_landuse_logging_collateral_frac ; + fates_landuse_logging_collateral_frac:units = "fraction" ; + fates_landuse_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; + double fates_landuse_logging_dbhmax ; + fates_landuse_logging_dbhmax:units = "cm" ; + fates_landuse_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; + double fates_landuse_logging_dbhmax_infra ; + fates_landuse_logging_dbhmax_infra:units = "cm" ; + fates_landuse_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; + double fates_landuse_logging_dbhmin ; + fates_landuse_logging_dbhmin:units = "cm" ; + fates_landuse_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; + double fates_landuse_logging_direct_frac ; + fates_landuse_logging_direct_frac:units = "fraction" ; + fates_landuse_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; + double fates_landuse_logging_event_code ; + fates_landuse_logging_event_code:units = "unitless" ; + fates_landuse_logging_event_code:long_name = "Integer code that options how logging events are structured" ; + double fates_landuse_logging_export_frac ; + fates_landuse_logging_export_frac:units = "fraction" ; + fates_landuse_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; + double fates_landuse_logging_mechanical_frac ; + fates_landuse_logging_mechanical_frac:units = "fraction" ; + fates_landuse_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; + double fates_landuse_pprodharv10_forest_mean ; + fates_landuse_pprodharv10_forest_mean:units = "fraction" ; + fates_landuse_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; + double fates_leaf_photo_temp_acclim_thome_time ; + fates_leaf_photo_temp_acclim_thome_time:units = "years" ; + fates_leaf_photo_temp_acclim_thome_time:long_name = "Length of the window for the long-term (i.e. T_home in Kumarathunge et al 2019) exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_leaf_photo_tempsens_model = 2)" ; + double fates_leaf_photo_temp_acclim_timescale ; + fates_leaf_photo_temp_acclim_timescale:units = "days" ; + fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_maintresp_leaf_model=2 or fates_leaf_photo_tempsens_model = 2)" ; + double fates_leaf_photo_tempsens_model ; + fates_leaf_photo_tempsens_model:units = "unitless" ; + fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating; 2=Kumarathunge et al 2019" ; + double fates_leaf_stomatal_assim_model ; + fates_leaf_stomatal_assim_model:units = "unitless" ; + fates_leaf_stomatal_assim_model:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; + double fates_leaf_stomatal_model ; + fates_leaf_stomatal_model:units = "unitless" ; + fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; + double fates_leaf_theta_cj_c3 ; + fates_leaf_theta_cj_c3:units = "unitless" ; + fates_leaf_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; + double fates_leaf_theta_cj_c4 ; + fates_leaf_theta_cj_c4:units = "unitless" ; + fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; + double fates_maintresp_leaf_model ; + fates_maintresp_leaf_model:units = "unitless" ; + fates_maintresp_leaf_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991), 2=Atkin et al., (2017)" ; + double fates_maintresp_nonleaf_baserate ; + fates_maintresp_nonleaf_baserate:units = "gC/gN/s" ; + fates_maintresp_nonleaf_baserate:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; + double fates_maxcohort ; + fates_maxcohort:units = "count" ; + fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; + double fates_maxpatch_primary ; + fates_maxpatch_primary:units = "count" ; + fates_maxpatch_primary:long_name = "maximum number of primary vegetation patches per site" ; + double fates_maxpatch_secondary ; + fates_maxpatch_secondary:units = "count" ; + fates_maxpatch_secondary:long_name = "maximum number of secondary vegetation patches per site" ; + double fates_mort_disturb_frac ; + fates_mort_disturb_frac:units = "fraction" ; + fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; + double fates_mort_understorey_death ; + fates_mort_understorey_death:units = "fraction" ; + fates_mort_understorey_death:long_name = "fraction of plants in understorey cohort impacted by overstorey tree-fall" ; + double fates_patch_fusion_tol ; + fates_patch_fusion_tol:units = "unitless" ; + fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; + double fates_phen_chilltemp ; + fates_phen_chilltemp:units = "degrees C" ; + fates_phen_chilltemp:long_name = "chilling day counting threshold for vegetation" ; + double fates_phen_coldtemp ; + fates_phen_coldtemp:units = "degrees C" ; + fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; + double fates_phen_drought_model ; + fates_phen_drought_model:units = "unitless" ; + fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; + double fates_phen_drought_threshold ; + fates_phen_drought_threshold:units = "m3/m3 or mm" ; + fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_gddthresh_a ; + fates_phen_gddthresh_a:units = "none" ; + fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_b ; + fates_phen_gddthresh_b:units = "none" ; + fates_phen_gddthresh_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_c ; + fates_phen_gddthresh_c:units = "none" ; + fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_mindaysoff ; + fates_phen_mindaysoff:units = "days" ; + fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves became off-allometry" ; + double fates_phen_mindayson ; + fates_phen_mindayson:units = "days" ; + fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; + double fates_phen_moist_threshold ; + fates_phen_moist_threshold:units = "m3/m3 or mm" ; + fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_ncolddayslim ; + fates_phen_ncolddayslim:units = "days" ; + fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; + double fates_q10_froz ; + fates_q10_froz:units = "unitless" ; + fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; + double fates_q10_mr ; + fates_q10_mr:units = "unitless" ; + fates_q10_mr:long_name = "Q10 for maintenance respiration" ; + double fates_soil_salinity ; + fates_soil_salinity:units = "ppt" ; + fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; + double fates_vai_top_bin_width ; + fates_vai_top_bin_width:units = "m2/m2" ; + fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; + double fates_vai_width_increase_factor ; + fates_vai_width_increase_factor:units = "unitless" ; + fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; + +// global attributes: + :history = "This file was generated by BatchPatchParams.py:\nCDL Base File = archive/api24.1.0_101722_fates_params_default.cdl\nXML patch file = archive/api24.1.0_101722_patch_params.xml" ; +data: + + fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; + + fates_history_coageclass_bin_edges = 0, 5 ; + + fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; + + fates_history_damage_bin_edges = 0, 80 ; + + fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, + 80, 90, 100 ; + + fates_alloc_organ_id = 1, 2, 3, 6 ; + + fates_hydro_htftype_node = 1, 1, 1, 1 ; + + fates_pftname = + "broadleaf_evergreen_tropical_tree ", + "needleleaf_evergreen_extratrop_tree ", + "needleleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_tree ", + "broadleaf_hydrodecid_tropical_tree ", + "broadleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_shrub ", + "broadleaf_hydrodecid_extratrop_shrub ", + "broadleaf_colddecid_extratrop_shrub ", + "arctic_c3_grass ", + "cool_c3_grass ", + "c4_grass " ; + + fates_hydro_organ_name = + "leaf ", + "stem ", + "transporting root ", + "absorbing root " ; + + fates_alloc_organ_name = + "leaf", + "fine root", + "sapwood", + "structure" ; + + fates_litterclass_name = + "twig ", + "small branch ", + "large branch ", + "trunk ", + "dead leaves ", + "live grass " ; + + 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, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; + + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + 1.2, 1.2, 1.2 ; + + fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8, 0.8 ; + + fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, + 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; + + fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, + 0.572, 0.572, 0.572, 0.572 ; + + fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, + 1.94, 1.94, 1.94 ; + + fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, + 0.931, 0.931, 0.931, 0.931 ; + + fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6 ; + + fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, + 0.95, 1, 1, 1 ; + + fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07 ; + + fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, + 1.3 ; + + fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, + 0.55, 0.55, 0.55 ; + + fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464 ; + + fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119 ; + + fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, + 0.64, 0.64, 0.64 ; + + fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, + 0.37, 0.37, 0.37 ; + + fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, + -999.9, -999.9, -999.9, -999.9, -999.9 ; + + fates_allom_dbh_maxheight = 90, 80, 80, 80, 90, 80, 3, 3, 2, 0.35, 0.35, 0.35 ; + + fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; + + fates_allom_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; + + fates_allom_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8 ; + + fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_zroot_k = 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 ; + + fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; + + fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + + fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 280, 280 ; + + fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, + 0.14, 0.14, 0.14 ; + + fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, + 0.27, 0.27, 0.27 ; + + fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_nfix1 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_pid_kd = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; + + fates_cnp_pid_ki = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_pid_kp = 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005 ; + + fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_turnover_nitr_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_turnover_phos_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_vmax_nh4 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, + 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; + + fates_cnp_vmax_no3 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, + 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; + + fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, + 5e-10, 5e-10, 5e-10, 5e-10 ; + + fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01 ; + + fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; + + fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, + 5.5, 5.5 ; + + fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2 ; + + fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07, 0.07 ; + + fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, + 0.775, 0.775, 0.775, 0.775, 0.775 ; + + fates_frag_fnrt_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_fnrt_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_fnrt_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_leaf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, + 0.51, 0.51, 0.51, 0.51 ; + + fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, + 0.11, 0.11 ; + + fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + 2.5, 2.5 ; + + fates_hydro_avuln_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_hydro_epsil_node = + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_hydro_fcap_node = + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_kmax_node = + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; + + fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + -1.5, -1.5, -1.5 ; + + fates_hydro_p50_node = + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25 ; + + fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, + 0.333, 0.333, 0.333, 0.333, 0.333 ; + + fates_hydro_pinot_node = + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; + + fates_hydro_pitlp_node = + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + -1.67, -1.67, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; + + fates_hydro_resid_node = + 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; + + fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + 0.625, 0.625, 0.625, 0.625, 0.625 ; + + fates_hydro_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, + 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; + + fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; + + fates_hydro_thetas_node = + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; + + fates_hydro_vg_alpha_node = + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005 ; + + fates_hydro_vg_m_node = + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_hydro_vg_n_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_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, + 43540, 43540, 43540, 43540 ; + + fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, + 152040, 152040, 152040, 152040, 152040 ; + + fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, + 495 ; + + fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, + 0.03, 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_slatop = 0.012, 0.005, 0.024, 0.009, 0.03, 0.03, 0.012, 0.03, + 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, + 10000, 10000, 10000, 10000, 10000, 40000 ; + + fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, + 4.7, 2.2, 5.3, 1.6 ; + + fates_leaf_vcmax25top = + 50, 62, 39, 61, 41, 58, 62, 54, 54, 78, 78, 78 ; + + fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, + 65330, 65330, 65330, 65330 ; + + fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, + 149250, 149250, 149250, 149250, 149250 ; + + fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, + 485 ; + + fates_maintresp_leaf_atkin2017_baserate = 1.756, 1.4995, 1.4995, 1.756, + 1.756, 1.756, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956, 2.1956 ; + + fates_maintresp_leaf_ryan1991_baserate = 2.525e-06, 2.525e-06, 2.525e-06, + 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, + 2.525e-06, 2.525e-06, 2.525e-06 ; + + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; + + fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, + 0.014, 0.014, 0.014, 0.014 ; + + fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -80, -60, -10, -80, -80, + -20, 2.5 ; + + fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, + 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; + + fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_prescribed_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, + 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; + + fates_mort_prescribed_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, + 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; + + fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_nonhydro_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, + -255000, -255000, -255000, -255000, -255000, -255000 ; + + fates_nonhydro_smpso = -66000, -66000, -66000, -66000, -66000, -66000, + -66000, -66000, -66000, -66000, -66000, -66000 ; + + fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; + + fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, + 0.5 ; + + fates_phen_fnrt_drop_frac = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; + + fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; + + fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, + 0.4, 0.4, 0.4 ; + + fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, + 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; + + fates_rad_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, + 0.9, 0.75, 0.75, 0.75 ; + + fates_rad_leaf_rhonir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, + 0.41, 0.28, 0.28, 0.28 ; + + fates_rad_leaf_rhovis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, + 0.08, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_taunir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, + 0.43, 0.4, 0.4, 0.4 ; + + fates_rad_leaf_tauvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, + 0.06, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, + -0.23, -0.23, -0.23 ; + + fates_rad_stem_rhonir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, + 0.49, 0.53, 0.53, 0.53 ; + + fates_rad_stem_rhovis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.31, 0.31, 0.31 ; + + fates_rad_stem_taunir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.25, 0.25, 0.25 ; + + fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.12, 0.12, 0.12 ; + + fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.2, 0.2, 0.2, + 0.125, 0.125, 0.125 ; + + fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2, 0.2, 0.2 ; + + fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, + 0.02, 0.02, 0.02, 0.02, 0.02 ; + + fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, + 0.9 ; + + fates_recruit_seed_dbh_repro_threshold = 90, 80, 80, 80, 90, 80, 3, 3, 2, + 0.35, 0.35, 0.35 ; + + fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_stoich_nitr = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; + + fates_stoich_phos = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; + + fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, + 0.03, 0.03 ; + + fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; + + fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, + 0.67, 0.67, 0.67 ; + + fates_turb_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.04, 0.04, 0.04, 0.04 ; + + fates_turb_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, + 0.055, 0.055, 0.055, 0.055 ; + + fates_turnover_branch = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; + + fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_leaf = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_wood_density = 0.7, 0.4, 0.7, 0.53, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, + 0.7 ; + + fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; + + fates_hlm_pft_map = + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + + fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; + + fates_fire_low_moisture_Coeff = 1.12, 1.09, 0.98, 0.8, 1.15, 1.15 ; + + fates_fire_low_moisture_Slope = 0.62, 0.72, 0.85, 0.8, 0.62, 0.62 ; + + fates_fire_mid_moisture = 0.72, 0.51, 0.38, 1, 0.8, 0.8 ; + + fates_fire_mid_moisture_Coeff = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_mid_moisture_Slope = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_min_moisture = 0.18, 0.12, 0, 0, 0.24, 0.24 ; + + fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; + + fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; + + fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; + + fates_canopy_closure_thresh = 0.8 ; + + fates_cnp_eca_plant_escalar = 1.25e-05 ; + + fates_cohort_age_fusion_tol = 0.08 ; + + fates_cohort_size_fusion_tol = 0.08 ; + + fates_comp_excln = 3 ; + + fates_damage_canopy_layer_code = 1 ; + + fates_damage_event_code = 1 ; + + fates_dev_arbitrary = _ ; + + fates_fire_active_crown_fire = 0 ; + + fates_fire_cg_strikes = 0.2 ; + + fates_fire_drying_ratio = 66000 ; + + fates_fire_durat_slope = -11.06 ; + + fates_fire_fdi_a = 17.62 ; + + fates_fire_fdi_alpha = 0.00037 ; + + fates_fire_fdi_b = 243.12 ; + + fates_fire_fuel_energy = 18000 ; + + fates_fire_max_durat = 240 ; + + fates_fire_miner_damp = 0.41739 ; + + fates_fire_miner_total = 0.055 ; + + fates_fire_nignitions = 15 ; + + fates_fire_part_dens = 513 ; + + fates_fire_threshold = 50 ; + + fates_frag_cwd_fcel = 0.76 ; + + fates_frag_cwd_flig = 0.24 ; + + fates_hydro_kmax_rsurf1 = 20 ; + + fates_hydro_kmax_rsurf2 = 0.0001 ; + + fates_hydro_psi0 = 0 ; + + fates_hydro_psicap = -0.6 ; + + fates_hydro_solver = 1 ; + + fates_landuse_logging_coll_under_frac = 0.55983 ; + + fates_landuse_logging_collateral_frac = 0.05 ; + + fates_landuse_logging_dbhmax = _ ; + + fates_landuse_logging_dbhmax_infra = 35 ; + + fates_landuse_logging_dbhmin = 50 ; + + fates_landuse_logging_direct_frac = 0.15 ; + + fates_landuse_logging_event_code = -30 ; + + fates_landuse_logging_export_frac = 0.8 ; + + fates_landuse_logging_mechanical_frac = 0.05 ; + + fates_landuse_pprodharv10_forest_mean = 0.8125 ; + + fates_leaf_photo_temp_acclim_thome_time = 30 ; + + fates_leaf_photo_temp_acclim_timescale = 30 ; + + fates_leaf_photo_tempsens_model = 1 ; + + fates_leaf_stomatal_assim_model = 1 ; + + fates_leaf_stomatal_model = 1 ; + + fates_leaf_theta_cj_c3 = 0.999 ; + + fates_leaf_theta_cj_c4 = 0.999 ; + + fates_maintresp_leaf_model = 1 ; + + fates_maintresp_nonleaf_baserate = 2.525e-06 ; + + fates_maxcohort = 100 ; + + fates_maxpatch_primary = 10 ; + + fates_maxpatch_secondary = 4 ; + + fates_mort_disturb_frac = 1 ; + + fates_mort_understorey_death = 0.55983 ; + + fates_patch_fusion_tol = 0.05 ; + + fates_phen_chilltemp = 5 ; + + fates_phen_coldtemp = 7.5 ; + + fates_phen_drought_model = 0 ; + + fates_phen_drought_threshold = 0.15 ; + + fates_phen_gddthresh_a = -68 ; + + fates_phen_gddthresh_b = 638 ; + + fates_phen_gddthresh_c = -0.01 ; + + fates_phen_mindaysoff = 100 ; + + fates_phen_mindayson = 90 ; + + fates_phen_moist_threshold = 0.18 ; + + fates_phen_ncolddayslim = 5 ; + + fates_q10_froz = 1.5 ; + + fates_q10_mr = 1.5 ; + + fates_soil_salinity = 0.4 ; + + fates_vai_top_bin_width = 1 ; + + fates_vai_width_increase_factor = 1 ; +} diff --git a/parameter_files/archive/api25.4.0_032323_pr1005.xml b/parameter_files/archive/api25.4.0_032323_pr1005.xml new file mode 100644 index 0000000000..46c3c778c7 --- /dev/null +++ b/parameter_files/archive/api25.4.0_032323_pr1005.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + archive/api25.4.0_032323_fates_params_default.cdl + fates_params_default.cdl + 1,2,3,4,5,6,7,8,9,10,11,12 + + + fates_seed_dispersal_max_dist + fates_pft + m + maximum seed dispersal distance for a given pft + + + + fates_seed_dispersal_fraction + fates_pft + fraction + fraction of seed rain to be dispersed to other grid cells + + + + fates_seed_dispersal_pdf_scale + fates_pft + unitless + seed dispersal probability density function scale parameter, A, Table 1 Bullock et al 2016 + + + + fates_seed_dispersal_pdf_shape + fates_pft + unitless + seed dispersal probability density function shape parameter, B, Table 1 Bullock et al 2016 + + + + diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index d461cb6fbb..2603de5670 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -515,6 +515,18 @@ variables: double fates_recruit_seed_supplement(fates_pft) ; fates_recruit_seed_supplement:units = "KgC/m2/yr" ; fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; + double fates_seed_dispersal_fraction(fates_pft) ; + fates_seed_dispersal_fraction:units = "fraction" ; + fates_seed_dispersal_fraction:long_name = "fraction of seed rain to be dispersed to other grid cells" ; + double fates_seed_dispersal_max_dist(fates_pft) ; + fates_seed_dispersal_max_dist:units = "m" ; + fates_seed_dispersal_max_dist:long_name = "maximum seed dispersal distance for a given pft" ; + double fates_seed_dispersal_pdf_scale(fates_pft) ; + fates_seed_dispersal_pdf_scale:units = "unitless" ; + fates_seed_dispersal_pdf_scale:long_name = "seed dispersal probability density function scale parameter, A, Table 1 Bullock et al 2016" ; + double fates_seed_dispersal_pdf_shape(fates_pft) ; + fates_seed_dispersal_pdf_shape:units = "unitless" ; + fates_seed_dispersal_pdf_shape:long_name = "seed dispersal probability density function shape parameter, B, Table 1 Bullock et al 2016" ; double fates_stoich_nitr(fates_plant_organs, fates_pft) ; fates_stoich_nitr:units = "gN/gC" ; fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; @@ -1334,6 +1346,14 @@ data: fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_seed_dispersal_fraction = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_seed_dispersal_max_dist = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_seed_dispersal_pdf_scale = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_seed_dispersal_pdf_shape = _, _, _, _, _, _, _, _, _, _, _, _ ; + fates_stoich_nitr = 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, From e5cef9c39106519426c1650dd342b97c1c5557dc Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 23 Mar 2023 15:54:30 -0700 Subject: [PATCH 585/852] Remove redundant parameter file These updates have been made to the default parameter file via the xmlpatch file --- .../fates_params_seed-dispersal_api23.cdl | 1512 ----------------- 1 file changed, 1512 deletions(-) delete mode 100644 parameter_files/fates_params_seed-dispersal_api23.cdl diff --git a/parameter_files/fates_params_seed-dispersal_api23.cdl b/parameter_files/fates_params_seed-dispersal_api23.cdl deleted file mode 100644 index 4a8c1193b0..0000000000 --- a/parameter_files/fates_params_seed-dispersal_api23.cdl +++ /dev/null @@ -1,1512 +0,0 @@ -netcdf tmp { -dimensions: - fates_NCWD = 4 ; - fates_history_age_bins = 7 ; - fates_history_height_bins = 6 ; - fates_history_size_bins = 13 ; - fates_history_coage_bins = 2 ; - fates_hydr_organs = 4 ; - fates_leafage_class = 1 ; - fates_litterclass = 6 ; - fates_pft = 12 ; - fates_prt_organs = 4 ; - fates_string_length = 60 ; - fates_hlm_pftno = 14 ; -variables: - double fates_history_ageclass_bin_edges(fates_history_age_bins) ; - fates_history_ageclass_bin_edges:units = "yr" ; - fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; - double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; - fates_history_coageclass_bin_edges:units = "years" ; - fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; - double fates_history_height_bin_edges(fates_history_height_bins) ; - fates_history_height_bin_edges:units = "m" ; - fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; - double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; - fates_history_sizeclass_bin_edges:units = "cm" ; - fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; - double fates_hydr_htftype_node(fates_hydr_organs) ; - fates_hydr_htftype_node:units = "unitless" ; - fates_hydr_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; - fates_hydr_htftype_node:possible_values = "1: Christofferson et al. 2016 (TFS); 2: Van Genuchten 1980" ; - double fates_prt_organ_id(fates_prt_organs) ; - fates_prt_organ_id:units = "index, unitless" ; - fates_prt_organ_id:long_name = "This is the global index the organ in this file is associated with in PRTGenericMod.F90" ; - char fates_pftname(fates_pft, fates_string_length) ; - fates_pftname:units = "unitless - string" ; - fates_pftname:long_name = "Description of plant type" ; - char fates_hydr_organname_node(fates_hydr_organs, fates_string_length) ; - fates_hydr_organname_node:units = "unitless - string" ; - fates_hydr_organname_node:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; - 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_prt_organ_name(fates_prt_organs, fates_string_length) ; - fates_prt_organ_name:units = "unitless - string" ; - fates_prt_organ_name:long_name = "Name of plant organs (order must match PRTGenericMod.F90)" ; - double fates_alloc_storage_cushion(fates_pft) ; - fates_alloc_storage_cushion:units = "fraction" ; - fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; - double fates_allom_agb1(fates_pft) ; - fates_allom_agb1:units = "variable" ; - fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; - double fates_allom_agb2(fates_pft) ; - fates_allom_agb2:units = "variable" ; - fates_allom_agb2:long_name = "Parameter 2 for agb allometry" ; - double fates_allom_agb3(fates_pft) ; - fates_allom_agb3:units = "variable" ; - fates_allom_agb3:long_name = "Parameter 3 for agb allometry" ; - double fates_allom_agb4(fates_pft) ; - fates_allom_agb4:units = "variable" ; - fates_allom_agb4:long_name = "Parameter 4 for agb allometry" ; - double fates_allom_agb_frac(fates_pft) ; - fates_allom_agb_frac:units = "fraction" ; - fates_allom_agb_frac:long_name = "Fraction of woody biomass that is above ground" ; - double fates_allom_amode(fates_pft) ; - fates_allom_amode:units = "index" ; - fates_allom_amode:long_name = "AGB allometry function index." ; - fates_allom_amode:possible_values = "1: Saldarriaga 1998; 2: 2 parameter power law; 3: Chave 2014" ; - double fates_allom_blca_expnt_diff(fates_pft) ; - fates_allom_blca_expnt_diff:units = "unitless" ; - fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; - double fates_allom_cmode(fates_pft) ; - fates_allom_cmode:units = "index" ; - fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; - fates_allom_cmode:possible_values = "1: Constant fraction on AGB" ; - double fates_allom_d2bl1(fates_pft) ; - fates_allom_d2bl1:units = "variable" ; - fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; - double fates_allom_d2bl2(fates_pft) ; - fates_allom_d2bl2:units = "variable" ; - fates_allom_d2bl2:long_name = "Parameter 2 for d2bl allometry" ; - double fates_allom_d2bl3(fates_pft) ; - fates_allom_d2bl3:units = "unitless" ; - fates_allom_d2bl3:long_name = "Parameter 3 for d2bl allometry" ; - double fates_allom_d2ca_coefficient_max(fates_pft) ; - fates_allom_d2ca_coefficient_max:units = "m2 cm^(-1/beta)" ; - fates_allom_d2ca_coefficient_max:long_name = "max (savanna) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; - double fates_allom_d2ca_coefficient_min(fates_pft) ; - fates_allom_d2ca_coefficient_min:units = "m2 cm^(-1/beta)" ; - fates_allom_d2ca_coefficient_min:long_name = "min (forest) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; - double fates_allom_d2h1(fates_pft) ; - fates_allom_d2h1:units = "variable" ; - fates_allom_d2h1:long_name = "Parameter 1 for d2h allometry (intercept, or c)" ; - double fates_allom_d2h2(fates_pft) ; - fates_allom_d2h2:units = "variable" ; - fates_allom_d2h2:long_name = "Parameter 2 for d2h allometry (slope, or m)" ; - double fates_allom_d2h3(fates_pft) ; - fates_allom_d2h3:units = "variable" ; - fates_allom_d2h3:long_name = "Parameter 3 for d2h allometry (optional)" ; - double fates_allom_dbh_maxheight(fates_pft) ; - fates_allom_dbh_maxheight:units = "cm" ; - fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; - double fates_allom_fmode(fates_pft) ; - fates_allom_fmode:units = "index" ; - fates_allom_fmode:long_name = "fine root biomass allometry function index." ; - fates_allom_fmode:possible_values = "1: constant fraction of trimmed bleaf; 2: constant fraction of untrimmed bleaf." ; - double fates_allom_frbstor_repro(fates_pft) ; - fates_allom_frbstor_repro:units = "fraction" ; - fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; - double fates_allom_hmode(fates_pft) ; - fates_allom_hmode:units = "index" ; - fates_allom_hmode:long_name = "height allometry function index." ; - fates_allom_hmode:possible_values = "1: OBrien 1995; 2: Poorter 2006; 3: 2 parameter power law; 4: Chave 2014; 5: Martinez-Cano 2019." ; - double fates_allom_l2fr(fates_pft) ; - fates_allom_l2fr:units = "gC/gC" ; - fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; - double fates_allom_la_per_sa_int(fates_pft) ; - fates_allom_la_per_sa_int:units = "m2/cm2" ; - fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; - double fates_allom_la_per_sa_slp(fates_pft) ; - fates_allom_la_per_sa_slp:units = "m2/cm2/m" ; - fates_allom_la_per_sa_slp:long_name = "Leaf area per sapwood area rate of change with height, slope (optional)" ; - double fates_allom_lmode(fates_pft) ; - fates_allom_lmode:units = "index" ; - fates_allom_lmode:long_name = "leaf biomass allometry function index." ; - fates_allom_lmode:possible_values = "1: Saldarriaga 1998 (capped-dbh power law); 2: generic power law; 3: generic capped-dbh power law." ; - double fates_allom_sai_scaler(fates_pft) ; - fates_allom_sai_scaler:units = "m2/m2" ; - fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; - double fates_allom_smode(fates_pft) ; - fates_allom_smode:units = "index" ; - fates_allom_smode:long_name = "sapwood allometry function index." ; - fates_allom_smode:possible_values = "1: sapwood area proportional to leaf area based on target leaf biomass" ; - double fates_allom_stmode(fates_pft) ; - fates_allom_stmode:units = "index" ; - fates_allom_stmode:long_name = "storage allometry function index." ; - fates_allom_stmode:possible_values = "1: target storage proportional to trimmed maximum leaf biomass." ; - double fates_allom_zroot_k(fates_pft) ; - fates_allom_zroot_k:units = "unitless" ; - fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; - double fates_allom_zroot_max_dbh(fates_pft) ; - fates_allom_zroot_max_dbh:units = "cm" ; - fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; - double fates_allom_zroot_max_z(fates_pft) ; - fates_allom_zroot_max_z:units = "m" ; - fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; - double fates_allom_zroot_min_dbh(fates_pft) ; - fates_allom_zroot_min_dbh:units = "cm" ; - fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; - double fates_allom_zroot_min_z(fates_pft) ; - fates_allom_zroot_min_z:units = "m" ; - fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; - double fates_branch_turnover(fates_pft) ; - fates_branch_turnover:units = "yr" ; - fates_branch_turnover:long_name = "turnover time of branches" ; - double fates_c2b(fates_pft) ; - fates_c2b:units = "ratio" ; - fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; - 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" ; - double fates_displar(fates_pft) ; - fates_displar:units = "unitless" ; - fates_displar:long_name = "Ratio of displacement height to canopy top height" ; - double fates_eca_alpha_ptase(fates_pft) ; - fates_eca_alpha_ptase:units = "g/m3" ; - fates_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; - double fates_eca_decompmicc(fates_pft) ; - fates_eca_decompmicc:units = "gC/m3" ; - fates_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; - double fates_eca_km_nh4(fates_pft) ; - fates_eca_km_nh4:units = "gN/m3" ; - fates_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; - double fates_eca_km_no3(fates_pft) ; - fates_eca_km_no3:units = "gN/m3" ; - fates_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; - double fates_eca_km_p(fates_pft) ; - fates_eca_km_p:units = "gP/m3" ; - fates_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; - double fates_eca_km_ptase(fates_pft) ; - fates_eca_km_ptase:units = "gP/m3" ; - fates_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; - double fates_eca_lambda_ptase(fates_pft) ; - fates_eca_lambda_ptase:units = "g/m3" ; - fates_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; - double fates_eca_vmax_nh4(fates_pft) ; - fates_eca_vmax_nh4:units = "gN/gC/s" ; - fates_eca_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA)" ; - double fates_eca_vmax_no3(fates_pft) ; - fates_eca_vmax_no3:units = "gN/gC/s" ; - fates_eca_vmax_no3:long_name = "maximum production rate for plant no3 uptake (ECA)" ; - double fates_eca_vmax_p(fates_pft) ; - fates_eca_vmax_p:units = "gP/gC/s" ; - fates_eca_vmax_p:long_name = "maximum production rate for plant p uptake (ECA)" ; - double fates_eca_vmax_ptase(fates_pft) ; - fates_eca_vmax_ptase:units = "gP/m2/s" ; - fates_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; - double fates_fire_alpha_SH(fates_pft) ; - fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; - fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; - double fates_fire_bark_scaler(fates_pft) ; - fates_fire_bark_scaler:units = "fraction" ; - fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; - double fates_fire_crown_depth_frac(fates_pft) ; - fates_fire_crown_depth_frac:units = "fraction" ; - fates_fire_crown_depth_frac:long_name = "the depth of a cohorts crown as a fraction of its height" ; - double fates_fire_crown_kill(fates_pft) ; - fates_fire_crown_kill:units = "NA" ; - fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; - double fates_fnrt_prof_a(fates_pft) ; - fates_fnrt_prof_a:units = "unitless" ; - fates_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; - double fates_fnrt_prof_b(fates_pft) ; - fates_fnrt_prof_b:units = "unitless" ; - fates_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; - double fates_fnrt_prof_mode(fates_pft) ; - fates_fnrt_prof_mode:units = "index" ; - fates_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; - double fates_fr_fcel(fates_pft) ; - fates_fr_fcel:units = "fraction" ; - fates_fr_fcel:long_name = "Fine root litter cellulose fraction" ; - double fates_fr_flab(fates_pft) ; - fates_fr_flab:units = "fraction" ; - fates_fr_flab:long_name = "Fine root litter labile fraction" ; - double fates_fr_flig(fates_pft) ; - fates_fr_flig:units = "fraction" ; - fates_fr_flig:long_name = "Fine root litter lignin fraction" ; - double fates_grperc(fates_pft) ; - fates_grperc:units = "unitless" ; - fates_grperc:long_name = "Growth respiration factor" ; - double fates_hydr_avuln_gs(fates_pft) ; - fates_hydr_avuln_gs:units = "unitless" ; - fates_hydr_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; - double fates_hydr_avuln_node(fates_hydr_organs, fates_pft) ; - fates_hydr_avuln_node:units = "unitless" ; - fates_hydr_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; - double fates_hydr_epsil_node(fates_hydr_organs, fates_pft) ; - fates_hydr_epsil_node:units = "MPa" ; - fates_hydr_epsil_node:long_name = "bulk elastic modulus" ; - double fates_hydr_fcap_node(fates_hydr_organs, fates_pft) ; - fates_hydr_fcap_node:units = "unitless" ; - fates_hydr_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; - double fates_hydr_k_lwp(fates_pft) ; - fates_hydr_k_lwp:units = "unitless" ; - fates_hydr_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; - fates_hydr_k_lwp:possible_values = "0: turns off leaf humidity effects on conductance. 1-10 activates humidity effects" ; - double fates_hydr_kmax_node(fates_hydr_organs, fates_pft) ; - fates_hydr_kmax_node:units = "kg/MPa/m/s" ; - fates_hydr_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; - double fates_hydr_p50_gs(fates_pft) ; - fates_hydr_p50_gs:units = "MPa" ; - fates_hydr_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; - double fates_hydr_p50_node(fates_hydr_organs, fates_pft) ; - fates_hydr_p50_node:units = "MPa" ; - fates_hydr_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; - double fates_hydr_p_taper(fates_pft) ; - fates_hydr_p_taper:units = "unitless" ; - fates_hydr_p_taper:long_name = "xylem taper exponent" ; - double fates_hydr_pinot_node(fates_hydr_organs, fates_pft) ; - fates_hydr_pinot_node:units = "MPa" ; - fates_hydr_pinot_node:long_name = "osmotic potential at full turgor" ; - double fates_hydr_pitlp_node(fates_hydr_organs, fates_pft) ; - fates_hydr_pitlp_node:units = "MPa" ; - fates_hydr_pitlp_node:long_name = "turgor loss point" ; - double fates_hydr_resid_node(fates_hydr_organs, fates_pft) ; - fates_hydr_resid_node:units = "cm3/cm3" ; - fates_hydr_resid_node:long_name = "residual water conent" ; - double fates_hydr_rfrac_stem(fates_pft) ; - fates_hydr_rfrac_stem:units = "fraction" ; - fates_hydr_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; - double fates_hydr_rs2(fates_pft) ; - fates_hydr_rs2:units = "m" ; - fates_hydr_rs2:long_name = "absorbing root radius" ; - double fates_hydr_srl(fates_pft) ; - fates_hydr_srl:units = "m g-1" ; - fates_hydr_srl:long_name = "specific root length" ; - double fates_hydr_thetas_node(fates_hydr_organs, fates_pft) ; - fates_hydr_thetas_node:units = "cm3/cm3" ; - fates_hydr_thetas_node:long_name = "saturated water content" ; - double fates_hydr_vg_alpha_node(fates_hydr_organs, fates_pft) ; - fates_hydr_vg_alpha_node:units = "MPa-1" ; - fates_hydr_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; - double fates_hydr_vg_m_node(fates_hydr_organs, fates_pft) ; - fates_hydr_vg_m_node:units = "unitless" ; - fates_hydr_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; - double fates_hydr_vg_n_node(fates_hydr_organs, fates_pft) ; - fates_hydr_vg_n_node:units = "unitless" ; - fates_hydr_vg_n_node:long_name = "(used if hydr_htftype_node = 2),n in van Genuchten 1980 model, pore size distribution parameter" ; - double fates_leaf_c3psn(fates_pft) ; - fates_leaf_c3psn:units = "flag" ; - fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; - double fates_leaf_clumping_index(fates_pft) ; - fates_leaf_clumping_index:units = "fraction (0-1)" ; - fates_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; - double fates_leaf_diameter(fates_pft) ; - fates_leaf_diameter:units = "m" ; - fates_leaf_diameter:long_name = "Characteristic leaf dimension" ; - double fates_leaf_jmaxha(fates_pft) ; - fates_leaf_jmaxha:units = "J/mol" ; - fates_leaf_jmaxha:long_name = "activation energy for jmax" ; - double fates_leaf_jmaxhd(fates_pft) ; - fates_leaf_jmaxhd:units = "J/mol" ; - fates_leaf_jmaxhd:long_name = "deactivation energy for jmax" ; - double fates_leaf_jmaxse(fates_pft) ; - fates_leaf_jmaxse:units = "J/mol/K" ; - fates_leaf_jmaxse:long_name = "entropy term for jmax" ; - double fates_leaf_long(fates_leafage_class, fates_pft) ; - fates_leaf_long:units = "yr" ; - fates_leaf_long:long_name = "Leaf longevity (ie turnover timescale)" ; - double fates_leaf_slamax(fates_pft) ; - fates_leaf_slamax:units = "m^2/gC" ; - fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; - double fates_leaf_slatop(fates_pft) ; - fates_leaf_slatop:units = "m^2/gC" ; - fates_leaf_slatop:long_name = "Specific Leaf Area (SLA) at top of canopy, projected area basis" ; - double fates_leaf_stomatal_intercept(fates_pft) ; - fates_leaf_stomatal_intercept:units = "umol H2O/m**2/s" ; - fates_leaf_stomatal_intercept:long_name = "Minimum unstressed stomatal conductance for Ball-Berry model and Medlyn model" ; - double fates_leaf_stomatal_slope_ballberry(fates_pft) ; - fates_leaf_stomatal_slope_ballberry:units = "unitless" ; - fates_leaf_stomatal_slope_ballberry:long_name = "stomatal slope parameter, as per Ball-Berry" ; - double fates_leaf_stomatal_slope_medlyn(fates_pft) ; - fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; - fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; - double fates_leaf_stor_priority(fates_pft) ; - fates_leaf_stor_priority:units = "unitless" ; - fates_leaf_stor_priority:long_name = "factor governing priority of replacing storage with NPP" ; - double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; - fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; - fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; - double fates_leaf_vcmaxha(fates_pft) ; - fates_leaf_vcmaxha:units = "J/mol" ; - fates_leaf_vcmaxha:long_name = "activation energy for vcmax" ; - double fates_leaf_vcmaxhd(fates_pft) ; - fates_leaf_vcmaxhd:units = "J/mol" ; - fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax" ; - double fates_leaf_vcmaxse(fates_pft) ; - fates_leaf_vcmaxse:units = "J/mol/K" ; - fates_leaf_vcmaxse:long_name = "entropy term for vcmax" ; - double fates_leaf_xl(fates_pft) ; - fates_leaf_xl:units = "unitless" ; - fates_leaf_xl:long_name = "Leaf/stem orientation index" ; - double fates_lf_fcel(fates_pft) ; - fates_lf_fcel:units = "fraction" ; - fates_lf_fcel:long_name = "Leaf litter cellulose fraction" ; - double fates_lf_flab(fates_pft) ; - fates_lf_flab:units = "fraction" ; - fates_lf_flab:long_name = "Leaf litter labile fraction" ; - double fates_lf_flig(fates_pft) ; - fates_lf_flig:units = "fraction" ; - fates_lf_flig:long_name = "Leaf litter lignin fraction" ; - double fates_maintresp_reduction_curvature(fates_pft) ; - fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; - fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; - double fates_maintresp_reduction_intercept(fates_pft) ; - fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; - fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; - double fates_mort_bmort(fates_pft) ; - fates_mort_bmort:units = "1/yr" ; - fates_mort_bmort:long_name = "background mortality rate" ; - double fates_mort_freezetol(fates_pft) ; - fates_mort_freezetol:units = "degrees C" ; - fates_mort_freezetol:long_name = "minimum temperature tolerance" ; - double fates_mort_hf_flc_threshold(fates_pft) ; - fates_mort_hf_flc_threshold:units = "fraction" ; - fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; - double fates_mort_hf_sm_threshold(fates_pft) ; - fates_mort_hf_sm_threshold:units = "unitless" ; - fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; - double fates_mort_ip_age_senescence(fates_pft) ; - fates_mort_ip_age_senescence:units = "years" ; - fates_mort_ip_age_senescence:long_name = "Mortality cohort age senescence inflection point. If _ this mortality term is off. Setting this value turns on age dependent mortality. " ; - double fates_mort_ip_size_senescence(fates_pft) ; - fates_mort_ip_size_senescence:units = "dbh cm" ; - fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; - double fates_mort_r_age_senescence(fates_pft) ; - fates_mort_r_age_senescence:units = "mortality rate year^-1" ; - fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; - double fates_mort_r_size_senescence(fates_pft) ; - fates_mort_r_size_senescence:units = "mortality rate dbh^-1" ; - fates_mort_r_size_senescence:long_name = "Mortality dbh senescence rate of change. Sensible range is around 0.03-0.06. Larger values give steeper mortality curves." ; - double fates_mort_scalar_coldstress(fates_pft) ; - fates_mort_scalar_coldstress:units = "1/yr" ; - fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; - double fates_mort_scalar_cstarvation(fates_pft) ; - fates_mort_scalar_cstarvation:units = "1/yr" ; - fates_mort_scalar_cstarvation:long_name = "maximum mortality rate from carbon starvation" ; - double fates_mort_scalar_hydrfailure(fates_pft) ; - fates_mort_scalar_hydrfailure:units = "1/yr" ; - fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; - double fates_nfix1(fates_pft) ; - fates_nfix1:units = "NA" ; - fates_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; - double fates_nfix2(fates_pft) ; - fates_nfix2:units = "NA" ; - fates_nfix2:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; - double fates_nitr_store_ratio(fates_pft) ; - fates_nitr_store_ratio:units = "(gN/gN)" ; - fates_nitr_store_ratio:long_name = "ratio of storeable N, to functional N bound in cell structures of leaf,root,sap" ; - double fates_phen_cold_size_threshold(fates_pft) ; - fates_phen_cold_size_threshold:units = "cm" ; - fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; - double fates_phen_evergreen(fates_pft) ; - fates_phen_evergreen:units = "logical flag" ; - fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; - double fates_phen_season_decid(fates_pft) ; - fates_phen_season_decid:units = "logical flag" ; - fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; - double fates_phen_stem_drop_fraction(fates_pft) ; - fates_phen_stem_drop_fraction:units = "fraction" ; - fates_phen_stem_drop_fraction:long_name = "fraction of stems to drop for non-woody species during drought/cold" ; - double fates_phen_stress_decid(fates_pft) ; - fates_phen_stress_decid:units = "logical flag" ; - fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; - double fates_phenflush_fraction(fates_pft) ; - fates_phenflush_fraction:units = "fraction" ; - fates_phenflush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; - double fates_phos_store_ratio(fates_pft) ; - fates_phos_store_ratio:units = "(gP/gP)" ; - fates_phos_store_ratio:long_name = "ratio of storeable P, to functional P bound in cell structures of leaf,root,sap" ; - double fates_prescribed_mortality_canopy(fates_pft) ; - fates_prescribed_mortality_canopy:units = "1/yr" ; - fates_prescribed_mortality_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; - double fates_prescribed_mortality_understory(fates_pft) ; - fates_prescribed_mortality_understory:units = "1/yr" ; - fates_prescribed_mortality_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; - double fates_prescribed_npp_canopy(fates_pft) ; - fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; - fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; - double fates_prescribed_npp_understory(fates_pft) ; - fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; - fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; - double fates_prescribed_nuptake(fates_pft) ; - fates_prescribed_nuptake:units = "fraction" ; - fates_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; - double fates_prescribed_puptake(fates_pft) ; - fates_prescribed_puptake:units = "fraction" ; - fates_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; - double fates_prescribed_recruitment(fates_pft) ; - fates_prescribed_recruitment:units = "n/yr" ; - fates_prescribed_recruitment:long_name = "recruitment rate for prescribed physiology mode" ; - double fates_prt_alloc_priority(fates_prt_organs, fates_pft) ; - fates_prt_alloc_priority:units = "index (0-fates_prt_organs)" ; - fates_prt_alloc_priority:long_name = "Priority order for allocation (C storage=2)" ; - double fates_prt_nitr_stoich_p1(fates_prt_organs, fates_pft) ; - fates_prt_nitr_stoich_p1:units = "(gN/gC)" ; - fates_prt_nitr_stoich_p1:long_name = "nitrogen stoichiometry, parameter 1" ; - double fates_prt_nitr_stoich_p2(fates_prt_organs, fates_pft) ; - fates_prt_nitr_stoich_p2:units = "(gN/gC)" ; - fates_prt_nitr_stoich_p2:long_name = "nitrogen stoichiometry, parameter 2" ; - double fates_prt_phos_stoich_p1(fates_prt_organs, fates_pft) ; - fates_prt_phos_stoich_p1:units = "(gP/gC)" ; - fates_prt_phos_stoich_p1:long_name = "phosphorous stoichiometry, parameter 1" ; - double fates_prt_phos_stoich_p2(fates_prt_organs, fates_pft) ; - fates_prt_phos_stoich_p2:units = "(gP/gC)" ; - fates_prt_phos_stoich_p2:long_name = "phosphorous stoichiometry, parameter 2" ; - double fates_recruit_hgt_min(fates_pft) ; - fates_recruit_hgt_min:units = "m" ; - fates_recruit_hgt_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; - double fates_recruit_initd(fates_pft) ; - fates_recruit_initd:units = "stems/m2" ; - fates_recruit_initd:long_name = "initial seedling density for a cold-start near-bare-ground simulation" ; - double fates_rholnir(fates_pft) ; - fates_rholnir:units = "fraction" ; - fates_rholnir:long_name = "Leaf reflectance: near-IR" ; - double fates_rholvis(fates_pft) ; - fates_rholvis:units = "fraction" ; - fates_rholvis:long_name = "Leaf reflectance: visible" ; - double fates_rhosnir(fates_pft) ; - fates_rhosnir:units = "fraction" ; - fates_rhosnir:long_name = "Stem reflectance: near-IR" ; - double fates_rhosvis(fates_pft) ; - fates_rhosvis:units = "fraction" ; - fates_rhosvis:long_name = "Stem reflectance: visible" ; - double fates_root_long(fates_pft) ; - fates_root_long:units = "yr" ; - fates_root_long:long_name = "root longevity (alternatively, turnover time)" ; - double fates_seed_alloc(fates_pft) ; - fates_seed_alloc:units = "fraction" ; - fates_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; - double fates_seed_alloc_mature(fates_pft) ; - fates_seed_alloc_mature:units = "fraction" ; - fates_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; - double fates_seed_dbh_repro_threshold(fates_pft) ; - fates_seed_dbh_repro_threshold:units = "cm" ; - fates_seed_dbh_repro_threshold:long_name = "the diameter (if any) where the plant will start extra clonal allocation to the seed pool" ; - double fates_seed_decay_rate(fates_pft) ; - fates_seed_decay_rate:units = "yr-1" ; - fates_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; - double fates_seed_dispersal_max_dist(fates_pft) ; - fates_seed_dispersal_max_dist:units = "m" ; - fates_seed_dispersal_max_dist:long_name = "maximum seed dispersal distance for a given pft" ; - fates_seed_dispersal_max_dist:use_case = "undefined" ; - double fates_seed_dispersal_fraction(fates_pft) ; - fates_seed_dispersal_fraction:units = "fraction" ; - fates_seed_dispersal_fraction:long_name = "fraction of seed rain to be dispersed to other grid cells" ; - fates_seed_dispersal_fraction:use_case = "undefined" ; - double fates_seed_dispersal_param_A(fates_pft) ; - fates_seed_dispersal_param_A:units = "unitless" ; - fates_seed_dispersal_param_A:long_name = "seed dispersal scale parameter" ; - double fates_seed_dispersal_param_B(fates_pft) ; - fates_seed_dispersal_param_B:units = "unitless" ; - fates_seed_dispersal_param_B:long_name = "seed dispersal scale parameter" ; - double fates_seed_germination_rate(fates_pft) ; - fates_seed_germination_rate:units = "yr-1" ; - fates_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; - double fates_seed_suppl(fates_pft) ; - fates_seed_suppl:units = "KgC/m2/yr" ; - fates_seed_suppl:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; - double fates_senleaf_long_fdrought(fates_pft) ; - fates_senleaf_long_fdrought:units = "unitless[0-1]" ; - fates_senleaf_long_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; - double fates_smpsc(fates_pft) ; - fates_smpsc:units = "mm" ; - fates_smpsc:long_name = "Soil water potential at full stomatal closure" ; - double fates_smpso(fates_pft) ; - fates_smpso:units = "mm" ; - fates_smpso:long_name = "Soil water potential at full stomatal opening" ; - double fates_taulnir(fates_pft) ; - fates_taulnir:units = "fraction" ; - fates_taulnir:long_name = "Leaf transmittance: near-IR" ; - double fates_taulvis(fates_pft) ; - fates_taulvis:units = "fraction" ; - fates_taulvis:long_name = "Leaf transmittance: visible" ; - double fates_tausnir(fates_pft) ; - fates_tausnir:units = "fraction" ; - fates_tausnir:long_name = "Stem transmittance: near-IR" ; - double fates_tausvis(fates_pft) ; - fates_tausvis:units = "fraction" ; - fates_tausvis:long_name = "Stem transmittance: visible" ; - double fates_trim_inc(fates_pft) ; - fates_trim_inc:units = "m2/m2" ; - fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; - double fates_trim_limit(fates_pft) ; - fates_trim_limit:units = "m2/m2" ; - fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; - double fates_turnover_carb_retrans(fates_prt_organs, fates_pft) ; - fates_turnover_carb_retrans:units = "-" ; - fates_turnover_carb_retrans:long_name = "retranslocation fraction of carbon in turnover" ; - double fates_turnover_nitr_retrans(fates_prt_organs, fates_pft) ; - fates_turnover_nitr_retrans:units = "-" ; - fates_turnover_nitr_retrans:long_name = "retranslocation fraction of nitrogen in turnover" ; - double fates_turnover_phos_retrans(fates_prt_organs, fates_pft) ; - fates_turnover_phos_retrans:units = "-" ; - fates_turnover_phos_retrans:long_name = "retranslocation fraction of phosphorous in turnover, parameter 1" ; - double fates_turnover_retrans_mode(fates_pft) ; - fates_turnover_retrans_mode:units = "index" ; - fates_turnover_retrans_mode:long_name = "retranslocation method for leaf/fineroot turnover." ; - fates_turnover_retrans_mode:possible_values = "1: constant fraction." ; - double fates_wood_density(fates_pft) ; - fates_wood_density:units = "g/cm3" ; - fates_wood_density:long_name = "mean density of woody tissue in plant" ; - double fates_woody(fates_pft) ; - fates_woody:units = "logical flag" ; - fates_woody:long_name = "Binary woody lifeform flag" ; - double fates_z0mr(fates_pft) ; - fates_z0mr:units = "unitless" ; - fates_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; - double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; - fates_hlm_pft_map:units = "area fraction" ; - fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; - double fates_fire_FBD(fates_litterclass) ; - fates_fire_FBD:units = "kg Biomass/m3" ; - fates_fire_FBD:long_name = "fuel bulk density" ; - double fates_fire_low_moisture_Coeff(fates_litterclass) ; - fates_fire_low_moisture_Coeff:units = "NA" ; - fates_fire_low_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_low_moisture_Slope(fates_litterclass) ; - fates_fire_low_moisture_Slope:units = "NA" ; - fates_fire_low_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_mid_moisture(fates_litterclass) ; - fates_fire_mid_moisture:units = "NA" ; - fates_fire_mid_moisture:long_name = "spitfire litter moisture threshold to be considered medium dry" ; - double fates_fire_mid_moisture_Coeff(fates_litterclass) ; - fates_fire_mid_moisture_Coeff:units = "NA" ; - fates_fire_mid_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_mid_moisture_Slope(fates_litterclass) ; - fates_fire_mid_moisture_Slope:units = "NA" ; - fates_fire_mid_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_min_moisture(fates_litterclass) ; - fates_fire_min_moisture:units = "NA" ; - fates_fire_min_moisture:long_name = "spitfire litter moisture threshold to be considered very dry" ; - double fates_fire_SAV(fates_litterclass) ; - fates_fire_SAV:units = "cm-1" ; - fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; - double fates_max_decomp(fates_litterclass) ; - fates_max_decomp:units = "yr-1" ; - fates_max_decomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; - double fates_CWD_frac(fates_NCWD) ; - fates_CWD_frac:units = "fraction" ; - fates_CWD_frac:long_name = "fraction of woody (bdead+bsw) biomass destined for CWD pool" ; - double fates_base_mr_20 ; - fates_base_mr_20:units = "gC/gN/s" ; - fates_base_mr_20:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; - 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" ; - double fates_cohort_age_fusion_tol ; - fates_cohort_age_fusion_tol:units = "unitless" ; - fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; - double fates_cohort_size_fusion_tol ; - fates_cohort_size_fusion_tol:units = "unitless" ; - fates_cohort_size_fusion_tol:long_name = "minimum fraction in difference in dbh between cohorts" ; - double fates_comp_excln ; - fates_comp_excln:units = "none" ; - fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; - double fates_cwd_fcel ; - fates_cwd_fcel:units = "unitless" ; - fates_cwd_fcel:long_name = "Cellulose fraction for CWD" ; - double fates_cwd_flig ; - fates_cwd_flig:units = "unitless" ; - fates_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; - double fates_dev_arbitrary ; - fates_dev_arbitrary:units = "unknown" ; - fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; - double fates_eca_plant_escalar ; - fates_eca_plant_escalar:units = "" ; - fates_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; - double fates_fire_active_crown_fire ; - fates_fire_active_crown_fire:units = "0 or 1" ; - fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; - double fates_fire_cg_strikes ; - fates_fire_cg_strikes:units = "fraction (0-1)" ; - fates_fire_cg_strikes:long_name = "fraction of cloud to ground lightning strikes" ; - double fates_fire_drying_ratio ; - fates_fire_drying_ratio:units = "NA" ; - fates_fire_drying_ratio:long_name = "spitfire parameter, fire drying ratio for fuel moisture, alpha_FMC EQ 6 Thonicke et al 2010" ; - double fates_fire_durat_slope ; - fates_fire_durat_slope:units = "NA" ; - fates_fire_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; - double fates_fire_fdi_a ; - fates_fire_fdi_a:units = "NA" ; - fates_fire_fdi_a:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010" ; - double fates_fire_fdi_alpha ; - fates_fire_fdi_alpha:units = "NA" ; - fates_fire_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; - double fates_fire_fdi_b ; - fates_fire_fdi_b:units = "NA" ; - fates_fire_fdi_b:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010 " ; - double fates_fire_fuel_energy ; - fates_fire_fuel_energy:units = "kJ/kg" ; - fates_fire_fuel_energy:long_name = "spitfire parameter, heat content of fuel" ; - double fates_fire_max_durat ; - fates_fire_max_durat:units = "minutes" ; - fates_fire_max_durat:long_name = "spitfire parameter, fire maximum duration, Equation 14 Thonicke et al 2010" ; - double fates_fire_miner_damp ; - fates_fire_miner_damp:units = "NA" ; - fates_fire_miner_damp:long_name = "spitfire parameter, mineral-dampening coefficient EQ A1 Thonicke et al 2010 " ; - double fates_fire_miner_total ; - fates_fire_miner_total:units = "fraction" ; - fates_fire_miner_total:long_name = "spitfire parameter, total mineral content, Table A1 Thonicke et al 2010" ; - double fates_fire_nignitions ; - fates_fire_nignitions:units = "ignitions per year per km2" ; - fates_fire_nignitions:long_name = "number of annual ignitions per square km" ; - double fates_fire_part_dens ; - fates_fire_part_dens:units = "kg/m2" ; - fates_fire_part_dens:long_name = "spitfire parameter, oven dry particle density, Table A1 Thonicke et al 2010" ; - double fates_fire_threshold ; - fates_fire_threshold:units = "kW/m" ; - fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; - double fates_hydr_kmax_rsurf1 ; - fates_hydr_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; - fates_hydr_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; - double fates_hydr_kmax_rsurf2 ; - fates_hydr_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; - fates_hydr_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; - double fates_hydr_psi0 ; - fates_hydr_psi0:units = "MPa" ; - fates_hydr_psi0:long_name = "sapwood water potential at saturation" ; - double fates_hydr_psicap ; - fates_hydr_psicap:units = "MPa" ; - fates_hydr_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; - double fates_init_litter ; - fates_init_litter:units = "NA" ; - fates_init_litter:long_name = "Initialization value for litter pool in cold-start (NOT USED)" ; - double fates_leaf_stomatal_model ; - fates_leaf_stomatal_model:units = "unitless" ; - fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; - double fates_logging_coll_under_frac ; - fates_logging_coll_under_frac:units = "fraction" ; - fates_logging_coll_under_frac:long_name = "Fraction of stems killed in the understory when logging generates disturbance" ; - double fates_logging_collateral_frac ; - fates_logging_collateral_frac:units = "fraction" ; - fates_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; - double fates_logging_dbhmax ; - fates_logging_dbhmax:units = "cm" ; - fates_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; - double fates_logging_dbhmax_infra ; - fates_logging_dbhmax_infra:units = "cm" ; - fates_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; - double fates_logging_dbhmin ; - fates_logging_dbhmin:units = "cm" ; - fates_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; - double fates_logging_direct_frac ; - fates_logging_direct_frac:units = "fraction" ; - fates_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; - double fates_logging_event_code ; - fates_logging_event_code:units = "unitless" ; - fates_logging_event_code:long_name = "Integer code that options how logging events are structured" ; - double fates_logging_export_frac ; - fates_logging_export_frac:units = "fraction" ; - fates_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; - double fates_logging_mechanical_frac ; - fates_logging_mechanical_frac:units = "fraction" ; - fates_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; - double fates_maintresp_model ; - fates_maintresp_model:units = "unitless" ; - fates_maintresp_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991) (NOT USED)" ; - double fates_mort_disturb_frac ; - fates_mort_disturb_frac:units = "fraction" ; - fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; - double fates_mort_understorey_death ; - fates_mort_understorey_death:units = "fraction" ; - fates_mort_understorey_death:long_name = "fraction of plants in understorey cohort impacted by overstorey tree-fall" ; - double fates_patch_fusion_tol ; - fates_patch_fusion_tol:units = "unitless" ; - fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; - double fates_phen_a ; - fates_phen_a:units = "none" ; - fates_phen_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_b ; - fates_phen_b:units = "none" ; - fates_phen_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_c ; - fates_phen_c:units = "none" ; - fates_phen_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_chiltemp ; - fates_phen_chiltemp:units = "degrees C" ; - fates_phen_chiltemp:long_name = "chilling day counting threshold for vegetation" ; - double fates_phen_coldtemp ; - fates_phen_coldtemp:units = "degrees C" ; - fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; - double fates_phen_doff_time ; - fates_phen_doff_time:units = "days" ; - fates_phen_doff_time:long_name = "day threshold compared against days since leaves became off-allometry" ; - double fates_phen_drought_threshold ; - fates_phen_drought_threshold:units = "m3/m3" ; - fates_phen_drought_threshold:long_name = "liquid volume in soil layer, threashold for drought phenology" ; - double fates_phen_mindayson ; - fates_phen_mindayson:units = "days" ; - fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; - double fates_phen_ncolddayslim ; - fates_phen_ncolddayslim:units = "days" ; - fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; - double fates_photo_temp_acclim_timescale ; - fates_photo_temp_acclim_timescale:units = "days" ; - fates_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; - double fates_photo_tempsens_model ; - fates_photo_tempsens_model:units = "unitless" ; - fates_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; - double fates_q10_froz ; - fates_q10_froz:units = "unitless" ; - fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; - double fates_q10_mr ; - fates_q10_mr:units = "unitless" ; - fates_q10_mr:long_name = "Q10 for maintenance respiration" ; - double fates_soil_salinity ; - fates_soil_salinity:units = "ppt" ; - fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; - double fates_theta_cj_c3 ; - fates_theta_cj_c3:units = "unitless" ; - fates_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; - double fates_theta_cj_c4 ; - fates_theta_cj_c4:units = "unitless" ; - fates_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; - double fates_vai_top_bin_width ; - fates_vai_top_bin_width:units = "m2/m2" ; - fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer (NOT USED)" ; - double fates_vai_width_increase_factor ; - fates_vai_width_increase_factor:units = "unitless" ; - fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing) (NOT USED)" ; - -// global attributes: - :history = "This parameter file is maintained in version control\nSee https://github.com/NGEET/fates/blob/master/parameter_files/fates_params_default.cdl \nFor changes, use git blame \n" ; -data: - - fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; - - fates_history_coageclass_bin_edges = 0, 5 ; - - fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; - - fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, - 80, 90, 100 ; - - fates_hydr_htftype_node = 1, 1, 1, 1 ; - - fates_prt_organ_id = 1, 2, 3, 6 ; - - fates_pftname = - "broadleaf_evergreen_tropical_tree ", - "needleleaf_evergreen_extratrop_tree ", - "needleleaf_colddecid_extratrop_tree ", - "broadleaf_evergreen_extratrop_tree ", - "broadleaf_hydrodecid_tropical_tree ", - "broadleaf_colddecid_extratrop_tree ", - "broadleaf_evergreen_extratrop_shrub ", - "broadleaf_hydrodecid_extratrop_shrub ", - "broadleaf_colddecid_extratrop_shrub ", - "arctic_c3_grass ", - "cool_c3_grass ", - "c4_grass " ; - - fates_hydr_organname_node = - "leaf ", - "stem ", - "transporting root ", - "absorbing root " ; - - fates_litterclass_name = - "twig ", - "small branch ", - "large branch ", - "trunk ", - "dead leaves ", - "live grass " ; - - fates_prt_organ_name = - "leaf ", - "fine root ", - "sapwood ", - "structure " ; - - fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, - 1.2, 1.2, 1.2 ; - - fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, - 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; - - fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, - 0.572, 0.572, 0.572, 0.572 ; - - fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, - 1.94, 1.94, 1.94 ; - - fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, - 0.931, 0.931, 0.931, 0.931 ; - - fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6 ; - - fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, - 0.07, 0.07, 0.07 ; - - fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, - 1.3 ; - - fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, - 0.55, 0.55, 0.55 ; - - fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464 ; - - fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119 ; - - fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, - 0.64, 0.64, 0.64 ; - - fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, - 0.37, 0.37, 0.37 ; - - fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, - -999.9, -999.9, -999.9, -999.9, -999.9 ; - - fates_allom_dbh_maxheight = 90, 90, 90, 90, 90, 90, 3, 3, 2, 0.35, 0.35, 0.35 ; - - fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, - 0.8, 0.8, 0.8 ; - - fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1, 0.1 ; - - fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_zroot_k = 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 ; - - fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; - - fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100 ; - - fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1 ; - - fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100 ; - - fates_branch_turnover = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; - - fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; - - fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, - 0.67, 0.67 ; - - fates_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5 ; - - fates_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, - 280, 280 ; - - fates_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, - 0.14, 0.14, 0.14 ; - - fates_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, - 0.27, 0.27, 0.27 ; - - fates_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; - - fates_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_eca_vmax_nh4 = 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, - 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07 ; - - fates_eca_vmax_no3 = 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, - 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08 ; - - fates_eca_vmax_p = 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, - 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09 ; - - fates_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, - 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - - fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, - 0.2 ; - - fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, - 0.07, 0.07, 0.07, 0.07 ; - - fates_fire_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, - 0.95, 1, 1, 1 ; - - fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, - 0.775, 0.775, 0.775, 0.775, 0.775 ; - - fates_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; - - fates_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; - - fates_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - - fates_fr_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_fr_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25 ; - - fates_fr_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25 ; - - fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, - 0.11, 0.11 ; - - fates_hydr_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, - 2.5 ; - - fates_hydr_avuln_node = - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 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_hydr_epsil_node = - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - - fates_hydr_fcap_node = - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, - 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_hydr_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_hydr_kmax_node = - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; - - fates_hydr_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, - -1.5, -1.5, -1.5 ; - - fates_hydr_p50_node = - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25 ; - - fates_hydr_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, - 0.333, 0.333, 0.333, 0.333 ; - - fates_hydr_pinot_node = - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; - - fates_hydr_pitlp_node = - -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, - -1.67, -1.67, - -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, - -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, - -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; - - fates_hydr_resid_node = - 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, - 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - - fates_hydr_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, - 0.625, 0.625, 0.625, 0.625, 0.625 ; - - fates_hydr_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, - 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; - - fates_hydr_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; - - fates_hydr_thetas_node = - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; - - fates_hydr_vg_alpha_node = - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005 ; - - fates_hydr_vg_m_node = - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_hydr_vg_n_node = - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 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_leaf_c3psn = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ; - - fates_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, - 0.9, 0.75, 0.75, 0.75 ; - - fates_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.04, 0.04, 0.04 ; - - fates_leaf_jmaxha = 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, - 43540, 43540, 43540, 43540 ; - - fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, - 152040, 152040, 152040, 152040, 152040 ; - - fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, - 495 ; - - fates_leaf_long = - 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - - fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, - 0.03, 0.03, 0.03, 0.03, 0.03 ; - - fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, - 0.03, 0.03, 0.03, 0.03 ; - - fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, - 10000, 10000, 10000, 10000, 10000, 40000 ; - - fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - - fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, - 4.7, 2.2, 5.3, 1.6 ; - - fates_leaf_stor_priority = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, - 0.8, 0.8 ; - - fates_leaf_vcmax25top = - 50, 65, 39, 62, 41, 58, 62, 54, 54, 78, 78, 78 ; - - fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, - 65330, 65330, 65330, 65330 ; - - fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, - 149250, 149250, 149250, 149250, 149250 ; - - fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, - 485 ; - - fates_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, -0.23, - -0.23, -0.23 ; - - fates_lf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_lf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25 ; - - fates_lf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25 ; - - fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, - 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; - - fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, - 0.014, 0.014, 0.014, 0.014 ; - - fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -60, -10, -80, -80, - -20, 2.5 ; - - fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5 ; - - fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, - 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; - - fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - - fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6, 0.6 ; - - fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6, 0.6 ; - - fates_nfix1 = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_nfix2 = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5 ; - - fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; - - fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; - - fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; - - fates_phenflush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5 ; - - fates_prescribed_mortality_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, - 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; - - fates_prescribed_mortality_understory = 0.025, 0.025, 0.025, 0.025, 0.025, - 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; - - fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, - 0.4, 0.4, 0.4 ; - - fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, - 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; - - fates_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_prescribed_recruitment = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, - 0.02, 0.02, 0.02, 0.02, 0.02 ; - - fates_prt_alloc_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, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; - - fates_prt_nitr_stoich_p1 = - 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, - 0.0047, 0.0047, 0.0047 ; - - fates_prt_nitr_stoich_p2 = - 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, - 0.0047, 0.0047, 0.0047 ; - - fates_prt_phos_stoich_p1 = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, - 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, - 0.00047, 0.00047, 0.00047, 0.00047 ; - - fates_prt_phos_stoich_p2 = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, - 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, - 0.00047, 0.00047, 0.00047, 0.00047 ; - - fates_recruit_hgt_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, - 0.125, 0.125, 0.125 ; - - fates_recruit_initd = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, - 0.2 ; - - fates_rholnir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, 0.41, 0.28, - 0.28, 0.28 ; - - fates_rholvis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, 0.08, 0.05, - 0.05, 0.05 ; - - fates_rhosnir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, 0.49, 0.53, - 0.53, 0.53 ; - - fates_rhosvis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.31, - 0.31, 0.31 ; - - fates_root_long = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - - fates_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; - - fates_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9 ; - - fates_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, 1.47, - 1.47, 1.47 ; - - fates_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, - 0.51, 0.51, 0.51, 0.51 ; - - fates_seed_dispersal_max_dist = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_seed_dispersal_fraction = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_seed_dispersal_param_A = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_seed_dispersal_param_B = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5 ; - - fates_seed_suppl = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_senleaf_long_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, -255000, - -255000, -255000, -255000, -255000, -255000 ; - - fates_smpso = -66000, -66000, -66000, -66000, -66000, -66000, -66000, - -66000, -66000, -66000, -66000, -66000 ; - - fates_taulnir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, 0.43, 0.4, - 0.4, 0.4 ; - - fates_taulvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.05, - 0.05, 0.05 ; - - fates_tausnir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, - 0.001, 0.25, 0.25, 0.25 ; - - fates_tausvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, - 0.001, 0.12, 0.12, 0.12 ; - - fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, - 0.03, 0.03 ; - - fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; - - fates_turnover_carb_retrans = - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_turnover_nitr_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_turnover_phos_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_turnover_retrans_mode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_wood_density = 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, - 0.7 ; - - fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; - - fates_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, - 0.055, 0.055, 0.055 ; - - fates_hlm_pft_map = - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; - - fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; - - fates_fire_low_moisture_Coeff = 1.12, 1.09, 0.98, 0.8, 1.15, 1.15 ; - - fates_fire_low_moisture_Slope = 0.62, 0.72, 0.85, 0.8, 0.62, 0.62 ; - - fates_fire_mid_moisture = 0.72, 0.51, 0.38, 1, 0.8, 0.8 ; - - fates_fire_mid_moisture_Coeff = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; - - fates_fire_mid_moisture_Slope = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; - - fates_fire_min_moisture = 0.18, 0.12, 0, 0, 0.24, 0.24 ; - - fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; - - fates_max_decomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; - - fates_CWD_frac = 0.045, 0.075, 0.21, 0.67 ; - - fates_base_mr_20 = 2.52e-06 ; - - fates_canopy_closure_thresh = 0.8 ; - - fates_cohort_age_fusion_tol = 0.08 ; - - fates_cohort_size_fusion_tol = 0.08 ; - - fates_comp_excln = 3 ; - - fates_cwd_fcel = 0.76 ; - - fates_cwd_flig = 0.24 ; - - fates_dev_arbitrary = _ ; - - fates_eca_plant_escalar = 1.25e-05 ; - - fates_fire_active_crown_fire = 0 ; - - fates_fire_cg_strikes = 0.2 ; - - fates_fire_drying_ratio = 66000 ; - - fates_fire_durat_slope = -11.06 ; - - fates_fire_fdi_a = 17.62 ; - - fates_fire_fdi_alpha = 0.00037 ; - - fates_fire_fdi_b = 243.12 ; - - fates_fire_fuel_energy = 18000 ; - - fates_fire_max_durat = 240 ; - - fates_fire_miner_damp = 0.41739 ; - - fates_fire_miner_total = 0.055 ; - - fates_fire_nignitions = 15 ; - - fates_fire_part_dens = 513 ; - - fates_fire_threshold = 50 ; - - fates_hydr_kmax_rsurf1 = 20 ; - - fates_hydr_kmax_rsurf2 = 0.0001 ; - - fates_hydr_psi0 = 0 ; - - fates_hydr_psicap = -0.6 ; - - fates_init_litter = 0.05 ; - - fates_leaf_stomatal_model = 1 ; - - fates_logging_coll_under_frac = 0.55983 ; - - fates_logging_collateral_frac = 0.05 ; - - fates_logging_dbhmax = _ ; - - fates_logging_dbhmax_infra = 35 ; - - fates_logging_dbhmin = 50 ; - - fates_logging_direct_frac = 0.15 ; - - fates_logging_event_code = -30 ; - - fates_logging_export_frac = 0.8 ; - - fates_logging_mechanical_frac = 0.05 ; - - fates_maintresp_model = 1 ; - - fates_mort_disturb_frac = 1 ; - - fates_mort_understorey_death = 0.55983 ; - - fates_patch_fusion_tol = 0.05 ; - - fates_phen_a = -68 ; - - fates_phen_b = 638 ; - - fates_phen_c = -0.01 ; - - fates_phen_chiltemp = 5 ; - - fates_phen_coldtemp = 7.5 ; - - fates_phen_doff_time = 100 ; - - fates_phen_drought_threshold = 0.15 ; - - fates_phen_mindayson = 90 ; - - fates_phen_ncolddayslim = 5 ; - - fates_photo_temp_acclim_timescale = 30 ; - - fates_photo_tempsens_model = 1 ; - - fates_q10_froz = 1.5 ; - - fates_q10_mr = 1.5 ; - - fates_soil_salinity = 0.4 ; - - fates_theta_cj_c3 = 0.999 ; - - fates_theta_cj_c4 = 0.999 ; - - fates_vai_top_bin_width = 1 ; - - fates_vai_width_increase_factor = 1 ; -} From 1d8090a365fda01d79a42088e4ab8d59f63ec4a4 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 23 Mar 2023 16:53:20 -0700 Subject: [PATCH 586/852] Fixing additional dropped commits from merge --- biogeochem/EDPhysiologyMod.F90 | 1 + main/FatesInterfaceMod.F90 | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 7f3daa4d03..5cb0faeb05 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1755,6 +1755,7 @@ subroutine SeedUpdate( currentSite, bc_in, bc_out) use EDTypesMod, only : area use EDTypesMod, only : homogenize_seed_pfts use FatesInterfaceTypesMod, only : fates_dispersal_kernel_mode + use FatesInterfaceTypesMod, only : fates_dispersal_kernel_none ! ! !ARGUMENTS type(ed_site_type), intent(inout), target :: currentSite diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index f5fc5ccb44..f9f6ca08bf 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -740,8 +740,6 @@ subroutine SetFatesGlobalElements1(use_fates,surf_numpft,surf_numcft) ! spmode,biogeog and nocomp mode flags have been passed prior to this call ! -------------------------------------------------------------------------------- - use FatesConstantsMod, only : fates_check_param_set - implicit none logical,intent(in) :: use_fates ! Is fates turned on? @@ -811,6 +809,8 @@ subroutine SetFatesGlobalElements2(use_fates) ! ! -------------------------------------------------------------------------------- + use FatesConstantsMod, only : fates_check_param_set + logical,intent(in) :: use_fates ! Is fates turned on? integer :: i @@ -2018,8 +2018,7 @@ subroutine DetermineGridCellNeighbors(neighbors) use FatesDispersalMod , only : neighborhood_type, neighbor_type, ProbabilityDensity use FatesUtilsMod , only : GetNeighborDistance use EDPftvarcon , only : EDPftvarcon_inst - use FatesConstantsMod , only : fates_check_param_set - + ! Arguments type(neighborhood_type), intent(inout), pointer :: neighbors(:) From 5e5a04af905934dabe2245c5bec73c441af89eaa Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Tue, 28 Mar 2023 15:08:58 -0600 Subject: [PATCH 587/852] cleaned up comments in cwd_partitioning_adj subroutine --- biogeochem/FatesLitterMod.F90 | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/biogeochem/FatesLitterMod.F90 b/biogeochem/FatesLitterMod.F90 index ddb7a7689b..d50e942134 100644 --- a/biogeochem/FatesLitterMod.F90 +++ b/biogeochem/FatesLitterMod.F90 @@ -432,15 +432,17 @@ subroutine adjust_SF_CWD_frac(dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) !DESCRIPTION !Adjust the partitioning of struct + sawp into cwd pools based on !cohort dbh. This avoids struct and sapw from small cohorts going to - !fuel classes that are too large. Instead, struct + sapw go to the cwd - !class based on established fuel class diameter thresholds (Fosberg et al., 1971; + !fuel classes that are larger than their dbh. Here, struct + sapw are sent to the cwd + !class consistent with fuel class diameter thresholds (Fosberg et al., 1971; !Rothermel, 1983) !ARGUMENTS - real(r8), intent(in) :: dbh !dbh of cohort + real(r8), intent(in) :: dbh !dbh of cohort [cm] type(integer), intent(in) :: ncwd !number of cwd pools - real(r8), intent(in) :: SF_val_CWD_frac(:) - real(r8), intent(out) :: SF_val_CWD_frac_adj(:) + real(r8), intent(in) :: SF_val_CWD_frac(:) !fates parameter specifying the + !fraction of struct + sapw going + !to each CWD class + real(r8), intent(out) :: SF_val_CWD_frac_adj(:) !Updated cwd paritions ! !LOCAL VARIABLES !These diameter ranges are based on work by Fosberg et al., 1971 @@ -453,14 +455,16 @@ subroutine adjust_SF_CWD_frac(dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) SF_val_CWD_frac_adj = SF_val_CWD_frac - !If dbh is larger than max size of a large branch (1,000 hr) then we don't change + !If dbh is larger than max size of a large branch (1,000 hr fuel) then we don't change !how biomass is partitioned among cwd classes. if (dbh > lb_max_diam) then return - !When dbh is greater than the max size of a small branch (10 hr) but less than or - !equal to the max size of a large branch we redistribute the biomass among the smaller - !pools, keeping the biomass proportions the same among the combustible classes. + !When dbh is greater than the max size of a small branch (10 hr fuel) but less than or + !equal to the max size of a large branch (e.g. saplings where dbh > 2.5 cm and < 7.5 cm) + !we redistribute the biomass that would have gone to 1,000 hr fuel among the smaller cwd classes. + !This keeps the biomass proportions among the combustible classes the same as the scenario + !where a fraction of struct + sawp goes to 1,000 hr fuel. else if (dbh > sb_max_diam .and. dbh .le. lb_max_diam) then SF_val_CWD_frac_adj(ncwd) = 0.0 SF_val_CWD_frac_adj(ncwd-1) = SF_val_CWD_frac(ncwd-1) / (1.0_r8 - SF_val_CWD_frac(ncwd) ) @@ -468,9 +472,9 @@ subroutine adjust_SF_CWD_frac(dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) SF_val_CWD_frac_adj(ncwd-3) = SF_val_CWD_frac(ncwd-3) / (1.0_r8 - SF_val_CWD_frac(ncwd) ) - !When dbh is greater than the max size of a twig (1 hr) but less than or - !equal to the max size of a small branch (10 hr) we redistribute the biomass among the smaller - !pools, keeping the biomass proportions the same among the combustible classes. + !When dbh is greater than the max size of a twig (1 hr fuel) but less than or + !equal to the max size of a small branch (10 hr fuel) we redistribute the biomass among the smaller + !pools. else if (dbh > twig_max_diam .and. dbh .le. sb_max_diam) then SF_val_CWD_frac_adj(ncwd) = 0.0 SF_val_CWD_frac_adj(ncwd-1) = 0.0 @@ -480,7 +484,7 @@ subroutine adjust_SF_CWD_frac(dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) SF_val_CWD_frac(ncwd-1))) !If dbh is less than or equal to the max size of a twig we send all - !biomass to twigs + !biomass to twigs. else if (dbh .le. twig_max_diam) then SF_val_CWD_frac_adj(ncwd) = 0.0 SF_val_CWD_frac_adj(ncwd-1) = 0.0 From a9cbc6205509f9a81494cba28b6b68cb53a16beb Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Tue, 28 Mar 2023 15:42:30 -0600 Subject: [PATCH 588/852] added testing print statements --- biogeochem/FatesLitterMod.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/biogeochem/FatesLitterMod.F90 b/biogeochem/FatesLitterMod.F90 index d50e942134..aa559fe2c6 100644 --- a/biogeochem/FatesLitterMod.F90 +++ b/biogeochem/FatesLitterMod.F90 @@ -471,6 +471,7 @@ subroutine adjust_SF_CWD_frac(dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) SF_val_CWD_frac_adj(ncwd-2) = SF_val_CWD_frac(ncwd-2) / (1.0_r8 - SF_val_CWD_frac(ncwd) ) SF_val_CWD_frac_adj(ncwd-3) = SF_val_CWD_frac(ncwd-3) / (1.0_r8 - SF_val_CWD_frac(ncwd) ) + write(fates_log(),*) 'Using CWD scheme ahb 032823' !When dbh is greater than the max size of a twig (1 hr fuel) but less than or !equal to the max size of a small branch (10 hr fuel) we redistribute the biomass among the smaller From 0f2ec37656e0f043450f8d2c2665a24ab0451938 Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Tue, 28 Mar 2023 16:43:04 -0600 Subject: [PATCH 589/852] deleted diagnostic print statements --- biogeochem/FatesLitterMod.F90 | 2 -- 1 file changed, 2 deletions(-) diff --git a/biogeochem/FatesLitterMod.F90 b/biogeochem/FatesLitterMod.F90 index aa559fe2c6..21a459b61f 100644 --- a/biogeochem/FatesLitterMod.F90 +++ b/biogeochem/FatesLitterMod.F90 @@ -471,8 +471,6 @@ subroutine adjust_SF_CWD_frac(dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) SF_val_CWD_frac_adj(ncwd-2) = SF_val_CWD_frac(ncwd-2) / (1.0_r8 - SF_val_CWD_frac(ncwd) ) SF_val_CWD_frac_adj(ncwd-3) = SF_val_CWD_frac(ncwd-3) / (1.0_r8 - SF_val_CWD_frac(ncwd) ) - write(fates_log(),*) 'Using CWD scheme ahb 032823' - !When dbh is greater than the max size of a twig (1 hr fuel) but less than or !equal to the max size of a small branch (10 hr fuel) we redistribute the biomass among the smaller !pools. From 68f178943ea54584f04e7aee655acfc2e21e3924 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 30 Mar 2023 18:28:10 -0400 Subject: [PATCH 590/852] Fix grid cell neighbor indexing This also fixes an issue where local arrays should have been using numpft instead of maxpft. This also cleans up some old diagnostic write statements. --- biogeochem/EDPhysiologyMod.F90 | 4 ++-- main/FatesDispersalMod.F90 | 3 --- main/FatesInterfaceMod.F90 | 19 ++++--------------- main/FatesUtilsMod.F90 | 2 +- 4 files changed, 7 insertions(+), 21 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 5cb0faeb05..1ae6fe9abf 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1769,8 +1769,8 @@ subroutine SeedUpdate( currentSite, bc_in, bc_out) integer :: pft real(r8) :: store_m_to_repro ! mass sent from storage to reproduction upon death [kg/plant] - real(r8) :: site_seed_rain(maxpft) ! This is the sum of seed-rain for the site [kg/site/day] - real(r8) :: site_disp_frac(maxpft) ! Fraction of seeds to disperse out to other sites + real(r8) :: site_seed_rain(numpft) ! This is the sum of seed-rain for the site [kg/site/day] + real(r8) :: site_disp_frac(numpft) ! Fraction of seeds to disperse out to other sites real(r8) :: seed_in_external ! Mass of externally generated seeds [kg/m2/day] real(r8) :: seed_stoich ! Mass ratio of nutrient per C12 in seeds [kg/kg] real(r8) :: seed_prod ! Seed produced in this dynamics step [kg/day] diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index cda56e212e..806f710824 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -123,8 +123,6 @@ subroutine ProbabilityDensity(pd, ipft, dist) call endrun(msg=errMsg(sourcefile, __LINE__)) end select - write(fates_log(),*) 'ipft,dist,pd: ', ipft, dist, pd - end subroutine ProbabilityDensity ! ==================================================================================== @@ -141,7 +139,6 @@ real(r8) function PD_exponential(dist, ipft) ! for different weight calculations (and could be held only in fates) PD_exponential = exp(-EDPftvarcon_inst%seed_dispersal_pdf_scale(ipft)*dist) - write(fates_log(),*) 'ipft,dist,PD_exp: ', ipft, dist, PD_exponential end function PD_exponential diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index f9f6ca08bf..302a3fa934 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -2049,13 +2049,8 @@ subroutine DetermineGridCellNeighbors(neighbors) ! Allocate array neighbor type numg = size(ldecomp%gdc2glo) - ! call get_proc_global(ng=ngcheck,np=numproc) - - ! write(fates_log(),*)'DGCN: numg, ngcheck: ', numg, ngcheck - ! write(fates_log(),*)'DGCN: npes, numproc: ', npes, numproc allocate(neighbors(numg), stat=ier) - ! neighbors(:)%density_prob_tot = nan neighbors(:)%neighbor_count = 0 allocate(gclat(numg)) @@ -2068,10 +2063,8 @@ subroutine DetermineGridCellNeighbors(neighbors) ncells_array = -999 begg_array = -999 - write(fates_log(),*)'DGCN: procinfo%ncells: ', procinfo%ncells - write(fates_log(),*)'DGCN: procinfo%begg: ', procinfo%begg - call t_startf('fates-seed-init-allgather') + ! Gather the sizes of the ldomain that each mpi rank is passing call MPI_Allgather(procinfo%ncells,1,MPI_INTEGER,ncells_array,1,MPI_INTEGER,mpicom,mpierr) @@ -2079,6 +2072,7 @@ subroutine DetermineGridCellNeighbors(neighbors) call MPI_Allgather(procinfo%begg-1,1,MPI_INTEGER,begg_array,1,MPI_INTEGER,mpicom,mpierr) ! Gather the domain information together into the neighbor type + ! Note that MPI_Allgatherv is only gathering a subset of ldomain call MPI_Allgatherv(ldomain%latc,procinfo%ncells,MPI_REAL8,gclat,ncells_array,begg_array,MPI_REAL8,mpicom,mpierr) call MPI_Allgatherv(ldomain%lonc,procinfo%ncells,MPI_REAL8,gclon,ncells_array,begg_array,MPI_REAL8,mpicom,mpierr) @@ -2086,9 +2080,6 @@ subroutine DetermineGridCellNeighbors(neighbors) write(fates_log(),*)'DGCN: ncells_array: ', ncells_array write(fates_log(),*)'DGCN: begg_array: ', begg_array write(fates_log(),*)'DGCN: sum(gclat):, sum(gclon): ', sum(gclat), sum(gclon) - do i = 1,numg - write(fates_log(),*)'DGCN: i, gclat, gclon: ', i, gclat(i), gclon(i) - end do end if call t_stopf('fates-seed-init-allgather') @@ -2110,8 +2101,7 @@ subroutine DetermineGridCellNeighbors(neighbors) allocate(current_neighbor) current_neighbor%next_neighbor => null() - ! ldomain and ldecomp indices match per initGridCells - current_neighbor%gindex = ldecomp%gdc2glo(gj) + current_neighbor%gindex = gj current_neighbor%gc_dist = g2g_dist @@ -2136,8 +2126,7 @@ subroutine DetermineGridCellNeighbors(neighbors) allocate(another_neighbor) another_neighbor%next_neighbor => null() - ! ldomain and ldecomp indices match per initGridCells - another_neighbor%gindex = ldecomp%gdc2glo(gi) + another_neighbor%gindex = gi another_neighbor%gc_dist = current_neighbor%gc_dist allocate(another_neighbor%density_prob(numpft)) diff --git a/main/FatesUtilsMod.F90 b/main/FatesUtilsMod.F90 index 779ded76e9..3310b5d6a4 100644 --- a/main/FatesUtilsMod.F90 +++ b/main/FatesUtilsMod.F90 @@ -132,7 +132,7 @@ end function GreatCircleDist function GetNeighborDistance(gi,gj,latc,lonc) result(gcd) - integer, intent(in) :: gi,gj ! indices of gridcells + integer, intent(in) :: gi,gj ! indices of gridcells real(r8), intent(in) :: latc(:),lonc(:) ! lat/lon of gridcells real(r8) :: gcd From 6a32ff0a79be4043ee0bf5ad51017a13ed83a736 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 30 Mar 2023 17:02:08 -0700 Subject: [PATCH 591/852] Moving script into module function --- tools/luh2.py | 18 +++---- tools/luh2mod.py | 136 +++++++++++++++++++++++++++++------------------ 2 files changed, 93 insertions(+), 61 deletions(-) diff --git a/tools/luh2.py b/tools/luh2.py index 5facc30ea4..44cd0d1e9a 100644 --- a/tools/luh2.py +++ b/tools/luh2.py @@ -16,21 +16,21 @@ mod_file_transitions = "/home/glemieux/Data/luh2/transitions_modified.nc" # Open modified files -ds_states = luh2.importdata(mod_file_states) -ds_management = luh2.importdata(mod_file_management) -ds_transitions = luh2.importdata(mod_file_transitions) +ds_states = luh2.ImportData(mod_file_states) +# ds_management = luh2.importdata(mod_file_management) +# ds_transitions = luh2.importdata(mod_file_transitions) -# Fix the bounds -ds_states = luh2.BoundsFixLUH2(ds_states) -ds_management= luh2.BoundsFixLUH2(ds_management) -ds_transitions = luh2.BoundsFixLUH2(ds_transitions) +# Fix the bounds of the LUH2 variable for xESMF +ds_states = luh2.BoundsVariableFixLUH2(ds_states) +# ds_management= luh2.BoundsFixLUH2(ds_management) +# ds_transitions = luh2.BoundsFixLUH2(ds_transitions) # Grab surface data set to use as regrid "target" # Import the surface dataset file_surfdata = "/home/glemieux/Data/luh2/surfdata_4x5_16pfts_Irrig_CMIP6_simyr2000_c170824.nc" - +ds_surfdata = luh2.ImportData(file_surfdata) # modify the surface data set to enable xesmf regridder to find necessary data -ds_surfdata = luh2.DimensionFixSurfData(file_surfdata) + = luh2.DimensionFixSurfData(file_surfdata) print("done") diff --git a/tools/luh2mod.py b/tools/luh2mod.py index 65cf029c34..c7548cc2dc 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -9,8 +9,32 @@ # Add version checking here in case environment.yml not used -# Import luh2 data -def importdata(inputfile): + + +# Primary function to regrid luh2 data +# +# Prepare the +def PrepDataSet(inputfile_luh2,inputfile_surface): + + # Import the data + ds_luh2 = ImportData(inputfile_luh2) + ds_surfdata = ImportData(inputfile_surface) + + # Correct the necessary variables for both datasets + ds_luh2 = BoundsVariableFixLUH2(ds_luh2) + ds_surfdata = DimensionFixSurfData(ds_surfdata) + + # Set dataset masks + ds_luh2 = SetMask(ds_luh2) + ds_surfdata = SetMask(ds_surfdata) + + # Define the xESMF regridder if necessary + regridder = RegridConservative(ds_luh2,ds_surfdata) + + return(ds_luh2,ds_surfdata,regridder) + +# Import luh2 or surface data sets +def ImportData(inputfile): # Open files # Check to see if a ValueError is raised which is likely due @@ -32,7 +56,7 @@ def importdata(inputfile): # This issue here is that the luh2 time units start prior to # year 1672, which cftime should be able to handle, but it # appears to need a specific unit name convention "common_years" -def attribupdate(inputfile,output_append="modified"): +def AttribUpdateLUH2(inputfile,output_append="modified"): # Define the output filename index = inputfile.find(".nc") @@ -69,26 +93,27 @@ def attribupdate(inputfile,output_append="modified"): # ), # ]) -# Fix the boundaries of the LUH2 data +# Create the necessary variable "lat_b" and "lon_b" for xESMF conservative regridding # Each lat/lon boundary array is a 2D array corresponding to the bounds of each # coordinate position (e.g. lat_boundary would be 90.0 and 89.75 for lat coordinate # of 89.875). -def BoundsFixLUH2(inputdataset): +def BoundsVariableFixLUH2(inputdataset): - # Create lat and lon bounds as a single dimension array out of the LUH2 two dimensional - # _bounds array. - # xESMF needs these variable names for bounding the conservative regridding + # Drop the old boundary names to avoid confusion outputdataset = inputdataset.drop(labels=['lat_bounds','lon_bounds']) + + # Create lat and lon bounds as a single dimension array out of the LUH2 two dimensional_bounds array. + # Future todo: is it possible to have xESMF recognize and use the original 2D array? outputdataset["lat_b"] = np.insert(inputdataset.lat_bounds[:,1].data,0,inputdataset.lat_bounds[0,0].data) outputdataset["lon_b"] = np.insert(inputdataset.lon_bounds[:,1].data,0,inputdataset.lon_bounds[0,0].data) - print("LUH2 dataset bounds fixed") - return(outputdataset) + print("LUH2 dataset lat/lon boundary variables formatted and added as new variable for xESMF") -def DimensionFixSurfData(inputfile): + return(outputdataset) - # Move this out to be handled by opening function - surfdataset = xr.open_dataset(inputfile) +# The user will need to use a surface data set to regrid from, but the surface datasets +# need to have their dimensions renamed to something recognizable by xESMF +def DimensionFixSurfData(surfdataset): # Rename the surface dataset dimensions to something recognizable by xESMF. outputdataset = surfdataset.rename_dims(dims_dict={'lsmlat':'latitude','lsmlon':'longitude'}) @@ -97,59 +122,66 @@ def DimensionFixSurfData(inputfile): outputdataset['longitude'] = outputdataset.LONGXY.isel(latitude=0) outputdataset['latitude'] = outputdataset.LATIXY.isel(longitude=0) - print("Surface dataset regrid target loaded: {}".format(inputfile)) + print("Surface dataset dimensions renamed for xESMF") - return(outputdataset, surfdataset) - -def setmask(inputdataset,label_to_mask): + return(outputdataset) - # note that the label will depend on the type of input file +def SetMask(inputdataset): # check what sort of inputdata is being provided; surface dataset or luh2 # make mask of LUH2 data "primf_to_range" - if(inputdataset.source.find("LUH2") != -1): - # Add check of variables to use as mask - inputdataset["mask"] = xr.where(~np.isnan(inputdataset[label_to_mask].isel(time=0)), 1, 0) - elif(inpudataset.source.version.find("mksurf") != -1): - inputdataset["mask"] = inputdatatset["PCT_NATVEG"]> 0 - else: - print("Incorrect dataset provided") - inputdataset["mask"] = None + try: + dsflag = CheckDataSet(inputdataset) + if(dsflag == "LUH2"): + SetMaskLUH2(inputdataset,'primf_to_range') # temporary test + elif(dsflag == "Surface"): + SetMaskSurfData(inputdataset) + else: + raise + print("mask added") + except: + print("nope") + +# Check which dataset we're working with +def CheckDataSet(inputdataset): - return(inputdataset) + try: + if(inputdataset.source.find("LUH2") != -1): + dsflag = 'LUH2' + elif(inpudataset.Version.find("mksurf") != -1): + dsflag = 'Surface' + else: + raise + return(dsflag) + except: + print("Unrecognized dataset provided") + +# LUH2 specific masking sub-function +def SetMaskLUH2(inputdataset,label_to_mask): + # Instead of passing the label_to_mask, loop through this for all labels? + inputdataset["mask"] = xr.where(~np.isnan(inputdataset[label_to_mask].isel(time=0)), 1, 0) + # return(outputdataset) + +# Surface dataset specific masking sub-function +def SetMaskSurfData(inputdataset): + # Instead of passing the label_to_mask, loop through this for all labels? + inputdataset["mask"] = inputdatatset["PCT_NATVEG"]> 0 + # return(outputdataset) def RegridConservative(dataset_from,dataset_to): # define the regridder transformation regridder = xe.Regridder(dataset_from, dataset_to, "conservative") - regrid_states = regridder(finb_states) - regrid_management= regridder(finb_management) - regrid_transitions= regridder(finb_management) + return(regridder) + + + # Apply regridder + # regrid_states = regridder(finb_states) + # regrid_management= regridder(finb_management) + # regrid_transitions= regridder(finb_management) ### memory crashes on the transition data #fin_transitions_regrid = regridder(finb) - # -# Make necessary (?) changes to metadata for XESMF conservative regrid -# Any LUH2 data set should work as the input dataset, but -# we should have some sort of check to make sure that the -# data sets being used are consistent in the final calling script -#def MetadataUpdateLUH2(inputdataset): - - # if this is LUH2 data - # Drop the invalid lat, lon variable labels and replace with "lat_b" and "lon_b" - # This is only necessary for the conservative method (?) per xESMF docs - - # Is dropping these variables really necessary? Will xESMF get confused or is this - # for the users's sake? - # outputdatatset = inputdataset.drop(labels=['lat_bounds','lon_bounds']) - - # outputdatatset["lat_b"] = np.insert(inputdataset.lat_bounds[:,1].data,0,inputdataset.lat_bounds[0,0].data) - # outputdatatset["lon_b"] = np.insert(inputdataset.lon_bounds[:,1].data,0,inputdataset.lon_bounds[0,0].data) - # outputdatatset["time"] = np.arange(len(fin["time"]), dtype=np.int16) + 850 - # outputdatatset["YEAR"] = xr.DataArray(np.arange(len(fin["time"]), dtype=np.int16) + 850, dims=("time")) - -# Update the formatting to meet HLM needs -# def clmformatter(): # General functionality needed # - collect data for specific user-defined time period From 7164ce78a81025bb6ce21a7e3c5efa1d1019fdc6 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 31 Mar 2023 11:10:43 -0600 Subject: [PATCH 592/852] Split associate statement The nag compiler has a limit on the number of line continuations --- main/FatesHistoryInterfaceMod.F90 | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index cf66408133..106acdeb34 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2473,8 +2473,10 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_mortality_canopy_si_scag => this%hvars(ih_mortality_canopy_si_scag)%r82d, & hio_mortality_understory_si_scag => this%hvars(ih_mortality_understory_si_scag)%r82d, & hio_site_cstatus_si => this%hvars(ih_site_cstatus_si)%r81d, & - hio_site_dstatus_si => this%hvars(ih_site_dstatus_si)%r81d, & - hio_gdd_si => this%hvars(ih_gdd_si)%r81d, & + hio_site_dstatus_si => this%hvars(ih_site_dstatus_si)%r81d ) + + ! Split up the associate statement as the nag compiler has a limit on line continuation + associate( hio_gdd_si => this%hvars(ih_gdd_si)%r81d, & hio_site_ncolddays_si => this%hvars(ih_site_ncolddays_si)%r81d, & hio_site_nchilldays_si => this%hvars(ih_site_nchilldays_si)%r81d, & hio_cleafoff_si => this%hvars(ih_cleafoff_si)%r81d, & @@ -4323,6 +4325,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) enddo siteloop ! site loop + end associate end associate return From d3e347f630866323dcd537b0fa5b2f1d1b1abfe6 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 31 Mar 2023 13:56:48 -0700 Subject: [PATCH 593/852] Intermediate improvements --- tools/luh2mod.py | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/tools/luh2mod.py b/tools/luh2mod.py index c7548cc2dc..d698bc3573 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -129,32 +129,32 @@ def DimensionFixSurfData(surfdataset): def SetMask(inputdataset): # check what sort of inputdata is being provided; surface dataset or luh2 - # make mask of LUH2 data "primf_to_range" - try: - dsflag = CheckDataSet(inputdataset) - if(dsflag == "LUH2"): - SetMaskLUH2(inputdataset,'primf_to_range') # temporary test - elif(dsflag == "Surface"): + # LUH2 data will need to be masked based on the variable input to mask + dsflag,dstype = CheckDataSet(inputdataset) + if (dsflag): + if(dstype == "LUH2"): + SetMaskLUH2(inputdataset,'primf') # temporary test + elif(dstype == "Surface"): SetMaskSurfData(inputdataset) - else: - raise print("mask added") - except: - print("nope") # Check which dataset we're working with def CheckDataSet(inputdataset): - try: - if(inputdataset.source.find("LUH2") != -1): - dsflag = 'LUH2' - elif(inpudataset.Version.find("mksurf") != -1): - dsflag = 'Surface' - else: - raise - return(dsflag) - except: - print("Unrecognized dataset provided") + dsflag = False + if('primf' in list(inputdataset.variables)): + dstype = 'LUH2' + dsflag = True + print("LUH2") + elif('natpft' in list(inputdataset.variables)): + dstype = 'Surface' + dsflag = True + print("Surface") + else: + dstype = 'Unknown' + print("Unrecognize data set") + + return(dsflag,dstype) # LUH2 specific masking sub-function def SetMaskLUH2(inputdataset,label_to_mask): @@ -165,7 +165,7 @@ def SetMaskLUH2(inputdataset,label_to_mask): # Surface dataset specific masking sub-function def SetMaskSurfData(inputdataset): # Instead of passing the label_to_mask, loop through this for all labels? - inputdataset["mask"] = inputdatatset["PCT_NATVEG"]> 0 + inputdataset["mask"] = inputdataset["PCT_NATVEG"]> 0 # return(outputdataset) def RegridConservative(dataset_from,dataset_to): From f334f2291dfd990e3862d66a633880c1ba0d5c4e Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 31 Mar 2023 16:33:24 -0700 Subject: [PATCH 594/852] Fixup --- tools/luh2mod.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tools/luh2mod.py b/tools/luh2mod.py index d698bc3573..f30116e5a0 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -29,9 +29,10 @@ def PrepDataSet(inputfile_luh2,inputfile_surface): ds_surfdata = SetMask(ds_surfdata) # Define the xESMF regridder if necessary - regridder = RegridConservative(ds_luh2,ds_surfdata) + # regridder = RegridConservative(ds_luh2,ds_surfdata) - return(ds_luh2,ds_surfdata,regridder) + # return(ds_luh2,ds_surfdata,regridder) + return(ds_luh2,ds_surfdata) # Import luh2 or surface data sets def ImportData(inputfile): @@ -133,11 +134,13 @@ def SetMask(inputdataset): dsflag,dstype = CheckDataSet(inputdataset) if (dsflag): if(dstype == "LUH2"): - SetMaskLUH2(inputdataset,'primf') # temporary test + SetMaskLUH2(inputdataset,'primf') # temporary elif(dstype == "Surface"): SetMaskSurfData(inputdataset) print("mask added") + return(inputdataset) + # Check which dataset we're working with def CheckDataSet(inputdataset): @@ -161,12 +164,14 @@ def SetMaskLUH2(inputdataset,label_to_mask): # Instead of passing the label_to_mask, loop through this for all labels? inputdataset["mask"] = xr.where(~np.isnan(inputdataset[label_to_mask].isel(time=0)), 1, 0) # return(outputdataset) + return(inputdataset) # Surface dataset specific masking sub-function def SetMaskSurfData(inputdataset): # Instead of passing the label_to_mask, loop through this for all labels? inputdataset["mask"] = inputdataset["PCT_NATVEG"]> 0 # return(outputdataset) + return(inputdataset) def RegridConservative(dataset_from,dataset_to): # define the regridder transformation From e1dec5d516805fdbdf2cd2c9703a3a135ecefb34 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 3 Apr 2023 09:52:45 -0700 Subject: [PATCH 595/852] Correct bsap variable description comments --- biogeochem/FatesAllometryMod.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index a6d7126e4a..0c4e6ced63 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -905,9 +905,9 @@ subroutine bsap_allom(d,ipft,crowndamage,canopy_trim,sapw_area,bsap,dbsapdd) real(r8),intent(in) :: canopy_trim real(r8),intent(out) :: sapw_area ! cross section area of ! plant sapwood at reference [m2] - real(r8),intent(out) :: bsap ! plant leaf biomass [kgC] - real(r8),intent(out),optional :: dbsapdd ! change leaf biomass - ! per d [kgC/cm] + real(r8),intent(out) :: bsap ! sapwood biomass [kgC] + real(r8),intent(out),optional :: dbsapdd ! change in sapwood biomass + ! per d [kgC/cm] real(r8) :: h ! Plant height [m] real(r8) :: dhdd From 080afb80fc6a2ed91a4a4f1fd7ae20a4e96bb68c Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 3 Apr 2023 10:22:32 -0700 Subject: [PATCH 596/852] Update bleaf output comment state KgC --- biogeochem/FatesAllometryMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index 0c4e6ced63..a1a8b41137 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -553,7 +553,7 @@ subroutine bleaf(d,ipft,crowndamage,canopy_trim,bl,dbldd) integer(i4),intent(in) :: ipft ! PFT index integer(i4),intent(in) :: crowndamage ! crown damage class [1: undamaged, >1: damaged] real(r8),intent(in) :: canopy_trim ! trimming function - real(r8),intent(out) :: bl ! plant leaf biomass [kg] + real(r8),intent(out) :: bl ! plant leaf biomass [kgC] real(r8),intent(out),optional :: dbldd ! change leaf bio per diameter [kgC/cm] real(r8) :: blmax From 00bd270095dbc9476b4ff08f1653a8d48a57fded Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 3 Apr 2023 10:32:17 -0700 Subject: [PATCH 597/852] Correct warning statements The user should be directed to update the HLM specific name for the namelist variable, not the intermediate variable that is used to pass the setting value from the hlm to fates. See clm_varctl.F90 for definitions. --- main/FatesInterfaceMod.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 4fc365ce62..e2ab8bb7f5 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1464,7 +1464,7 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) (hlm_use_cohort_age_tracking .eq.0 ) ) then write(fates_log(),*) 'Age dependent mortality cannot be on if' write(fates_log(),*) 'cohort age tracking is off.' - write(fates_log(),*) 'Set hlm_use_cohort_age_tracking = .true.' + write(fates_log(),*) 'Set use_fates_cohort_age_tracking = .true.' write(fates_log(),*) 'in FATES namelist options' write(fates_log(),*) 'Aborting' call endrun(msg=errMsg(sourcefile, __LINE__)) @@ -1488,7 +1488,7 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) if ( hlm_use_inventory_init.eq.1 .and. hlm_use_cohort_age_tracking .eq.1) then write(fates_log(), *) 'Fates inventory init cannot be used with age dependent mortality' - write(fates_log(), *) 'Set hlm_use_cohort_age_tracking to 0 or turn off inventory init' + write(fates_log(), *) 'Set use_fates_cohort_age_tracking to 0 or turn off inventory init' call endrun(msg=errMsg(sourcefile, __LINE__)) end if @@ -1636,7 +1636,7 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) if(hlm_use_fixed_biogeog.eq.unset_int) then if(fates_global_verbose()) then - write(fates_log(), *) 'switch for fixed biogeog unset: him_use_fixed_biogeog, exiting' + write(fates_log(), *) 'switch for fixed biogeog unset: hlm_use_fixed_biogeog, exiting' end if call endrun(msg=errMsg(sourcefile, __LINE__)) end if From b6193220042a193812c7faf1370f897cbc4ce14d Mon Sep 17 00:00:00 2001 From: adrifoster Date: Mon, 3 Apr 2023 15:55:14 -0600 Subject: [PATCH 598/852] move cohort to its own module --- biogeochem/EDCohortDynamicsMod.F90 | 878 +++++++++++------------------ main/EDTypesMod.F90 | 352 +----------- main/FatesCohortMod.F90 | 624 ++++++++++++++++++++ main/FatesConstantsMod.F90 | 7 + main/FatesInventoryInitMod.F90 | 11 +- parteh/PRTAllometricCarbonMod.F90 | 5 +- 6 files changed, 976 insertions(+), 901 deletions(-) create mode 100644 main/FatesCohortMod.F90 diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 1385f846cb..6f14ce4e66 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -26,7 +26,8 @@ Module EDCohortDynamicsMod use EDPftvarcon , only : GetDecompyFrac use PRTParametersMod , only : prt_params use FatesParameterDerivedMod, only : param_derived - use EDTypesMod , only : ed_site_type, ed_patch_type, ed_cohort_type + use EDTypesMod , only : ed_site_type, ed_patch_type + use FatesCohortMod , only : fates_cohort_type use EDTypesMod , only : nclmax use PRTGenericMod , only : element_list use PRTGenericMod , only : StorageNutrientTarget @@ -85,7 +86,6 @@ Module EDCohortDynamicsMod use PRTGenericMod, only : repro_organ use PRTGenericMod, only : struct_organ use PRTGenericMod, only : SetState - use PRTAllometricCarbonMod, only : callom_prt_vartypes use PRTAllometricCarbonMod, only : ac_bc_inout_id_netdc use PRTAllometricCarbonMod, only : ac_bc_in_id_pft @@ -117,7 +117,6 @@ Module EDCohortDynamicsMod ! public :: create_cohort public :: zero_cohort - public :: nan_cohort public :: terminate_cohorts public :: terminate_cohort public :: fuse_cohorts @@ -150,316 +149,225 @@ Module EDCohortDynamicsMod contains !-------------------------------------------------------------------------------------! - subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & - prt, status, recruitstatus,ctrim, carea, clayer, crowndamage, spread, bc_in) - - ! - ! !DESCRIPTION: - ! create new cohort - ! There are 4 places this is called - ! 1) Initializing new cohorts at the beginning of a cold-start simulation - ! 2) Initializing new recruits during dynamics - ! 3) Initializing new cohorts at the beginning of a inventory read - ! 4) Initializing new cohorts during restart - ! - ! It is assumed that in the first 3, this is called with a reasonable amount of starter information. - ! - ! !USES: - ! - ! !ARGUMENTS - - type(ed_site_type), intent(inout), target :: currentSite - type(ed_patch_type), intent(inout), pointer :: patchptr - - integer, intent(in) :: pft ! Cohort Plant Functional Type - integer, intent(in) :: crowndamage ! Cohort damage class - integer, intent(in) :: clayer ! canopy status of cohort - ! (1 = canopy, 2 = understorey, etc.) - integer, intent(in) :: status ! growth status of plant - ! (2 = leaves on , 1 = leaves off) - integer, intent(in) :: recruitstatus ! recruit status of plant - ! (1 = recruitment , 0 = other) - real(r8), intent(in) :: nn ! number of individuals in cohort - ! per 'area' (10000m2 default) - real(r8), intent(in) :: hite ! height: meters - real(r8), intent(in) :: coage ! cohort age in years - real(r8), intent(in) :: dbh ! dbh: cm - class(prt_vartypes),intent(inout), pointer :: prt ! The allocated PARTEH - !class(prt_vartypes),target :: prt ! The allocated PARTEH - ! object - real(r8), intent(in) :: ctrim ! What is the fraction of the maximum - ! leaf biomass that we are targeting? - real(r8), intent(in) :: spread ! The community assembly effects how - ! spread crowns are in horizontal space - real(r8), intent(in) :: carea ! area of cohort ONLY USED IN SP MODE. - type(bc_in_type), intent(in) :: bc_in ! External boundary conditions - - - ! !LOCAL VARIABLES: - type(ed_cohort_type), pointer :: new_cohort ! Pointer to New Cohort structure. - type(ed_cohort_type), pointer :: storesmallcohort - type(ed_cohort_type), pointer :: storebigcohort - integer :: iage ! loop counter for leaf age classes - real(r8) :: leaf_c ! total leaf carbon - integer :: tnull,snull ! are the tallest and shortest cohorts allocate - integer :: nlevrhiz ! number of rhizosphere layers - - !---------------------------------------------------------------------- - - allocate(new_cohort) - - call nan_cohort(new_cohort) ! Make everything in the cohort not-a-number - call zero_cohort(new_cohort) ! Zero things that need to be zeroed. - - ! Point to the PARTEH object - new_cohort%prt => prt - - ! The PARTEH cohort object should be allocated and already - ! initialized in this routine. - call new_cohort%prt%CheckInitialConditions() - - !**********************/ - ! Define cohort state variable - !**********************/ - - new_cohort%indexnumber = fates_unset_int ! Cohort indexing was not thread-safe, setting - ! bogus value for the time being (RGK-012017) - - new_cohort%patchptr => patchptr - - new_cohort%pft = pft - new_cohort%crowndamage = crowndamage - new_cohort%status_coh = status - new_cohort%n = nn - new_cohort%hite = hite - new_cohort%dbh = dbh - new_cohort%coage = coage - new_cohort%canopy_trim = ctrim - new_cohort%canopy_layer = clayer - new_cohort%canopy_layer_yesterday = real(clayer, r8) - - ! Initialize the leaf to fineroot biomass ratio - ! for C-only, this will stay constant, for nutrient enabled - ! this will be dynamic. In both cases, new cohorts are - ! initialized with the minimum. This works in the nutrient - ! enabled case, because cohorts are also initialized with - ! full stores, which match with minimum fr biomass - - new_cohort%l2fr = prt_params%allom_l2fr(pft) - - if(hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) then - new_cohort%cx_int = 0._r8 ! Assume balanced N,P/C stores ie log(1) = 0 - new_cohort%cx0 = 0._r8 ! Assume balanced N,P/C stores ie log(1) = 0 - new_cohort%ema_dcxdt = 0._r8 ! Assume unchanged dCX/dt - new_cohort%cnp_limiter = 0 ! Assume limitations are unknown - end if - - ! This sets things like vcmax25top, that depend on the - ! leaf age fractions (which are defined by PARTEH) - call UpdateCohortBioPhysRates(new_cohort) - - call sizetype_class_index(new_cohort%dbh, new_cohort%pft, & - new_cohort%size_class,new_cohort%size_by_pft_class) - - ! If cohort age trackign is off we call this here once - ! just so everythin is in the first bin - - ! this makes it easier to copy and terminate cohorts later - ! we don't need to update this ever if cohort age tracking is off - call coagetype_class_index(new_cohort%coage, new_cohort%pft, & - new_cohort%coage_class,new_cohort%coage_by_pft_class) - - ! This routine may be called during restarts, and at this point in the call sequence - ! the actual cohort data is unknown, as this is really only used for allocation - ! In these cases, testing if things like biomass are reasonable is pre-mature - ! However, in this part of the code, we will pass in nominal values for size, number and type - - if (new_cohort%dbh <= 0._r8 .or. new_cohort%n == 0._r8 .or. new_cohort%pft == 0 ) then - write(fates_log(),*) 'ED: something is zero in create_cohort', & - new_cohort%dbh,new_cohort%n, & - new_cohort%pft - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - - ! Assign canopy extent and depth - if(hlm_use_sp.eq.ifalse)then - call carea_allom(new_cohort%dbh,new_cohort%n,spread,new_cohort%pft, & - new_cohort%crowndamage,new_cohort%c_area) - else - new_cohort%c_area = carea ! set this from previously precision-controlled value in SP mode - endif - ! Query PARTEH for the leaf carbon [kg] - leaf_c = new_cohort%prt%GetState(leaf_organ,carbon12_element) - - new_cohort%treelai = tree_lai(leaf_c, new_cohort%pft, new_cohort%c_area, & - new_cohort%n, new_cohort%canopy_layer, & - patchptr%canopy_layer_tlai,new_cohort%vcmax25top ) - - if(hlm_use_sp.eq.ifalse)then - new_cohort%treesai = tree_sai(new_cohort%pft, new_cohort%dbh, & - new_cohort%crowndamage, new_cohort%canopy_trim, & - new_cohort%c_area, new_cohort%n, new_cohort%canopy_layer, & - patchptr%canopy_layer_tlai, new_cohort%treelai,new_cohort%vcmax25top,2 ) - end if - - - ! Put cohort at the right place in the linked list - storebigcohort => patchptr%tallest - storesmallcohort => patchptr%shortest - - if (associated(patchptr%tallest)) then - tnull = 0 - else - tnull = 1 - patchptr%tallest => new_cohort - endif - - if (associated(patchptr%shortest)) then - snull = 0 - else - snull = 1 - patchptr%shortest => new_cohort - endif - - ! Allocate running mean functions - - ! (Keeping as an example) - !! allocate(new_cohort%tveg_lpa) - !! call new_cohort%tveg_lpa%InitRMean(ema_lpa,init_value=patchptr%tveg_lpa%GetMean()) - - call InitPRTBoundaryConditions(new_cohort) - - - ! Recuits do not have mortality rates, nor have they moved any - ! carbon when they are created. They will bias our statistics - ! until they have experienced a full day. We need a newly recruited flag. - ! This flag will be set to false after it has experienced - ! growth, disturbance and mortality. - new_cohort%isnew = .true. - - if( hlm_use_planthydro.eq.itrue ) then - - nlevrhiz = currentSite%si_hydr%nlevrhiz - - ! This allocates array spaces - call InitHydrCohort(currentSite,new_cohort) - - ! zero out the water balance error - new_cohort%co_hydr%errh2o = 0._r8 - - ! This calculates node heights - call UpdatePlantHydrNodes(new_cohort,new_cohort%pft, & - new_cohort%hite,currentSite%si_hydr) - - ! This calculates volumes and lengths - call UpdatePlantHydrLenVol(new_cohort,currentSite%si_hydr) - - ! This updates the Kmax's of the plant's compartments - call UpdatePlantKmax(new_cohort%co_hydr,new_cohort,currentSite%si_hydr) - - ! Since this is a newly initialized plant, we set the previous compartment-size - ! equal to the ones we just calculated. - call SavePreviousCompartmentVolumes(new_cohort%co_hydr) - - ! This comes up with starter suctions and then water contents - ! based on the soil values - call InitPlantHydStates(currentSite,new_cohort) - - if(recruitstatus==1)then - - new_cohort%co_hydr%is_newly_recruited = .true. - - ! If plant hydraulics is active, we must constrain the - ! number density of the new recruits based on the moisture - ! available to be subsumed in the new plant tissues. - ! So we go through the process of pre-initializing the hydraulic - ! states in the temporary cohort, to calculate this new number density - - call ConstrainRecruitNumber(currentSite,new_cohort, bc_in) - - endif - - endif - - call insert_cohort(new_cohort, patchptr%tallest, patchptr%shortest, tnull, snull, & - storebigcohort, storesmallcohort) - - patchptr%tallest => storebigcohort - patchptr%shortest => storesmallcohort - - end subroutine create_cohort - - ! ------------------------------------------------------------------------------------- - - subroutine InitPRTBoundaryConditions(new_cohort) - - ! Set the boundary conditions that flow in an out of the PARTEH - ! allocation hypotheses. Each of these calls to "RegsterBC" are simply - ! setting pointers. - ! For instance, if the hypothesis wants to know what - ! the DBH of the plant is, then we pass in the dbh as an argument (new_cohort%dbh), - ! and also tell it which boundary condition we are talking about (which is - ! defined by an integer index (ac_bc_inout_id_dbh) - ! - ! Again, elaborated Example: - ! "ac_bc_inout_id_dbh" is the unique integer that defines the object index - ! for the allometric carbon "ac" boundary condition "bc" for DBH "dbh" - ! that is classified as input and output "inout". - ! See PRTAllometricCarbonMod.F90 to track its usage. - ! bc_rval is used as the optional argument identifyer to specify a real - ! value boundary condition. - ! bc_ival is used as the optional argument identifyer to specify an integer - ! value boundary condition. - - type(ed_cohort_type), intent(inout), target :: new_cohort - - select case(hlm_parteh_mode) - case (prt_carbon_allom_hyp) +subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & + prt, status, recruitstatus,ctrim, carea, clayer, crowndamage, spread, bc_in) + +! +! !DESCRIPTION: +! create new cohort +! There are 4 places this is called +! 1) Initializing new cohorts at the beginning of a cold-start simulation +! 2) Initializing new recruits during dynamics +! 3) Initializing new cohorts at the beginning of a inventory read +! 4) Initializing new cohorts during restart +! +! It is assumed that in the first 3, this is called with a reasonable amount of starter information. +! +! !USES: +! +! !ARGUMENTS + +type(ed_site_type), intent(inout), target :: currentSite +type(ed_patch_type), intent(inout), pointer :: patchptr + +integer, intent(in) :: pft ! Cohort Plant Functional Type +integer, intent(in) :: crowndamage ! Cohort damage class +integer, intent(in) :: clayer ! canopy status of cohort + ! (1 = canopy, 2 = understorey, etc.) +integer, intent(in) :: status ! growth status of plant + ! (2 = leaves on , 1 = leaves off) +integer, intent(in) :: recruitstatus ! recruit status of plant + ! (1 = recruitment , 0 = other) +real(r8), intent(in) :: nn ! number of individuals in cohort + ! per 'area' (10000m2 default) +real(r8), intent(in) :: hite ! height: meters +real(r8), intent(in) :: coage ! cohort age in years +real(r8), intent(in) :: dbh ! dbh: cm +class(prt_vartypes),intent(inout), pointer :: prt ! The allocated PARTEH +!class(prt_vartypes),target :: prt ! The allocated PARTEH + ! object +real(r8), intent(in) :: ctrim ! What is the fraction of the maximum + ! leaf biomass that we are targeting? +real(r8), intent(in) :: spread ! The community assembly effects how + ! spread crowns are in horizontal space +real(r8), intent(in) :: carea ! area of cohort ONLY USED IN SP MODE. +type(bc_in_type), intent(in) :: bc_in ! External boundary conditions + + +! !LOCAL VARIABLES: +type(fates_cohort_type), pointer :: new_cohort ! Pointer to New Cohort structure. +type(fates_cohort_type), pointer :: storesmallcohort +type(fates_cohort_type), pointer :: storebigcohort +integer :: iage ! loop counter for leaf age classes +real(r8) :: leaf_c ! total leaf carbon +integer :: tnull,snull ! are the tallest and shortest cohorts allocate +integer :: nlevrhiz ! number of rhizosphere layers + +!---------------------------------------------------------------------- + +allocate(new_cohort) + +new_cohort%init(prt) + +!**********************/ +! Define cohort state variable +!**********************/ + +new_cohort%indexnumber = fates_unset_int ! Cohort indexing was not thread-safe, setting + ! bogus value for the time being (RGK-012017) + +new_cohort%patchptr => patchptr + +new_cohort%pft = pft +new_cohort%crowndamage = crowndamage +new_cohort%status_coh = status +new_cohort%n = nn +new_cohort%hite = hite +new_cohort%dbh = dbh +new_cohort%coage = coage +new_cohort%canopy_trim = ctrim +new_cohort%canopy_layer = clayer +new_cohort%canopy_layer_yesterday = real(clayer, r8) + +! Initialize the leaf to fineroot biomass ratio +! for C-only, this will stay constant, for nutrient enabled +! this will be dynamic. In both cases, new cohorts are +! initialized with the minimum. This works in the nutrient +! enabled case, because cohorts are also initialized with +! full stores, which match with minimum fr biomass + +new_cohort%l2fr = prt_params%allom_l2fr(pft) + +if(hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) then + new_cohort%cx_int = 0._r8 ! Assume balanced N,P/C stores ie log(1) = 0 + new_cohort%cx0 = 0._r8 ! Assume balanced N,P/C stores ie log(1) = 0 + new_cohort%ema_dcxdt = 0._r8 ! Assume unchanged dCX/dt + new_cohort%cnp_limiter = 0 ! Assume limitations are unknown +end if + +! This sets things like vcmax25top, that depend on the +! leaf age fractions (which are defined by PARTEH) +call UpdateCohortBioPhysRates(new_cohort) + +call sizetype_class_index(new_cohort%dbh, new_cohort%pft, & + new_cohort%size_class,new_cohort%size_by_pft_class) + +! If cohort age trackign is off we call this here once +! just so everythin is in the first bin - +! this makes it easier to copy and terminate cohorts later +! we don't need to update this ever if cohort age tracking is off +call coagetype_class_index(new_cohort%coage, new_cohort%pft, & + new_cohort%coage_class,new_cohort%coage_by_pft_class) + +! This routine may be called during restarts, and at this point in the call sequence +! the actual cohort data is unknown, as this is really only used for allocation +! In these cases, testing if things like biomass are reasonable is pre-mature +! However, in this part of the code, we will pass in nominal values for size, number and type + +if (new_cohort%dbh <= 0._r8 .or. new_cohort%n == 0._r8 .or. new_cohort%pft == 0 ) then + write(fates_log(),*) 'ED: something is zero in create_cohort', & + new_cohort%dbh,new_cohort%n, & + new_cohort%pft + call endrun(msg=errMsg(sourcefile, __LINE__)) +endif + +! Assign canopy extent and depth +if(hlm_use_sp.eq.ifalse)then + call carea_allom(new_cohort%dbh,new_cohort%n,spread,new_cohort%pft, & + new_cohort%crowndamage,new_cohort%c_area) +else + new_cohort%c_area = carea ! set this from previously precision-controlled value in SP mode +endif +! Query PARTEH for the leaf carbon [kg] +leaf_c = new_cohort%prt%GetState(leaf_organ,carbon12_element) + +new_cohort%treelai = tree_lai(leaf_c, new_cohort%pft, new_cohort%c_area, & + new_cohort%n, new_cohort%canopy_layer, & + patchptr%canopy_layer_tlai,new_cohort%vcmax25top ) + +if(hlm_use_sp.eq.ifalse)then + new_cohort%treesai = tree_sai(new_cohort%pft, new_cohort%dbh, & + new_cohort%crowndamage, new_cohort%canopy_trim, & + new_cohort%c_area, new_cohort%n, new_cohort%canopy_layer, & + patchptr%canopy_layer_tlai, new_cohort%treelai,new_cohort%vcmax25top,2 ) +end if + + +! Put cohort at the right place in the linked list +storebigcohort => patchptr%tallest +storesmallcohort => patchptr%shortest + +if (associated(patchptr%tallest)) then + tnull = 0 +else + tnull = 1 + patchptr%tallest => new_cohort +endif + +if (associated(patchptr%shortest)) then + snull = 0 +else + snull = 1 + patchptr%shortest => new_cohort +endif + +! Allocate running mean functions + +! (Keeping as an example) +!! allocate(new_cohort%tveg_lpa) +!! call new_cohort%tveg_lpa%InitRMean(ema_lpa,init_value=patchptr%tveg_lpa%GetMean()) + +if( hlm_use_planthydro.eq.itrue ) then + + nlevrhiz = currentSite%si_hydr%nlevrhiz + + ! This allocates array spaces + call InitHydrCohort(currentSite,new_cohort) + + ! zero out the water balance error + new_cohort%co_hydr%errh2o = 0._r8 + + ! This calculates node heights + call UpdatePlantHydrNodes(new_cohort,new_cohort%pft, & + new_cohort%hite,currentSite%si_hydr) + + ! This calculates volumes and lengths + call UpdatePlantHydrLenVol(new_cohort,currentSite%si_hydr) + + ! This updates the Kmax's of the plant's compartments + call UpdatePlantKmax(new_cohort%co_hydr,new_cohort,currentSite%si_hydr) + + ! Since this is a newly initialized plant, we set the previous compartment-size + ! equal to the ones we just calculated. + call SavePreviousCompartmentVolumes(new_cohort%co_hydr) + + ! This comes up with starter suctions and then water contents + ! based on the soil values + call InitPlantHydStates(currentSite,new_cohort) + + if(recruitstatus==1)then - ! Register boundary conditions for the Carbon Only Allometric Hypothesis + new_cohort%co_hydr%is_newly_recruited = .true. - call new_cohort%prt%RegisterBCInOut(ac_bc_inout_id_dbh,bc_rval = new_cohort%dbh) - call new_cohort%prt%RegisterBCInOut(ac_bc_inout_id_netdc,bc_rval = new_cohort%npp_acc) - call new_cohort%prt%RegisterBCIn(ac_bc_in_id_cdamage,bc_ival = new_cohort%crowndamage) - call new_cohort%prt%RegisterBCIn(ac_bc_in_id_pft,bc_ival = new_cohort%pft) - call new_cohort%prt%RegisterBCIn(ac_bc_in_id_ctrim,bc_rval = new_cohort%canopy_trim) - call new_cohort%prt%RegisterBCIn(ac_bc_in_id_lstat,bc_ival = new_cohort%status_coh) - - case (prt_cnp_flex_allom_hyp) + ! If plant hydraulics is active, we must constrain the + ! number density of the new recruits based on the moisture + ! available to be subsumed in the new plant tissues. + ! So we go through the process of pre-initializing the hydraulic + ! states in the temporary cohort, to calculate this new number density - call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_pft,bc_ival = new_cohort%pft) - call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_ctrim,bc_rval = new_cohort%canopy_trim) - call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_lstat,bc_ival = new_cohort%status_coh) - call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdc, bc_rval = new_cohort%npp_acc) + call ConstrainRecruitNumber(currentSite,new_cohort, bc_in) - call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_nc_repro,bc_rval = new_cohort%nc_repro) - call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_pc_repro,bc_rval = new_cohort%pc_repro) - call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_cdamage,bc_ival = new_cohort%crowndamage) - - call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_dbh,bc_rval = new_cohort%dbh) - call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_resp_excess,bc_rval = new_cohort%resp_excess) - call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_l2fr,bc_rval = new_cohort%l2fr) - call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_cx_int,bc_rval = new_cohort%cx_int) - call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_emadcxdt,bc_rval = new_cohort%ema_dcxdt) - call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_cx0,bc_rval = new_cohort%cx0) - - call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_netdn, bc_rval = new_cohort%daily_n_gain) - call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_netdp, bc_rval = new_cohort%daily_p_gain) - - call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_cefflux, bc_rval = new_cohort%daily_c_efflux) - call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_nefflux, bc_rval = new_cohort%daily_n_efflux) - call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_pefflux, bc_rval = new_cohort%daily_p_efflux) - call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_limiter, bc_ival = new_cohort%cnp_limiter) - - case DEFAULT + endif - write(fates_log(),*) 'You specified an unknown PRT module' - write(fates_log(),*) 'Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) +endif - end select +call insert_cohort(new_cohort, patchptr%tallest, patchptr%shortest, tnull, snull, & + storebigcohort, storesmallcohort) +patchptr%tallest => storebigcohort +patchptr%shortest => storesmallcohort - end subroutine InitPRTBoundaryConditions +end subroutine create_cohort ! ------------------------------------------------------------------------------------! @@ -517,223 +425,6 @@ end subroutine InitPRTObject !-------------------------------------------------------------------------------------! - subroutine nan_cohort(cc_p) - ! - ! !DESCRIPTION: - ! Make all the cohort variables NaN so they aren't used before defined. - ! - ! !USES: - - use FatesConstantsMod, only : fates_unset_int - - ! - ! !ARGUMENTS - type (ed_cohort_type), intent(inout), target :: cc_p - ! - ! !LOCAL VARIABLES: - type (ed_cohort_type) , pointer :: currentCohort - !---------------------------------------------------------------------- - - currentCohort => cc_p - - currentCohort%taller => null() ! pointer to next tallest cohort - currentCohort%shorter => null() ! pointer to next shorter cohort - currentCohort%patchptr => null() ! pointer to patch that cohort is in - - nullify(currentCohort%taller) - nullify(currentCohort%shorter) - nullify(currentCohort%patchptr) - - ! VEGETATION STRUCTURE - currentCohort%pft = fates_unset_int ! pft number - currentCohort%crowndamage = fates_unset_int ! Crown damage class - currentCohort%indexnumber = fates_unset_int ! unique number for each cohort. (within clump?) - currentCohort%canopy_layer = fates_unset_int ! canopy status of cohort (1 = canopy, 2 = understorey, etc.) - currentCohort%canopy_layer_yesterday = nan ! recent canopy status of cohort (1 = canopy, 2 = understorey, etc.) - currentCohort%NV = fates_unset_int ! Number of leaf layers: - - currentCohort%status_coh = fates_unset_int ! growth status of plant (2 = leaves on , 1 = leaves off) - currentCohort%size_class = fates_unset_int ! size class index - currentCohort%size_class_lasttimestep = fates_unset_int ! size class index - currentCohort%size_by_pft_class = fates_unset_int ! size by pft classification index - currentCohort%coage_class = fates_unset_int ! cohort age class index - currentCohort%coage_by_pft_class = fates_unset_int ! cohort age by pft class index - - currentCohort%n = nan ! number of individuals in cohort per 'area' (10000m2 default) - currentCohort%dbh = nan ! 'diameter at breast height' in cm - currentCohort%coage = nan ! age of the cohort in years - currentCohort%hite = nan ! height: meters - currentCohort%g_sb_laweight = nan ! Total leaf conductance of cohort (stomata+blayer) weighted by leaf-area [m/s]*[m2] - currentCohort%canopy_trim = nan ! What is the fraction of the maximum leaf biomass that we are targeting? :- - currentCohort%leaf_cost = nan ! How much does it cost to maintain leaves: kgC/m2/year-1 - currentCohort%excl_weight = nan ! How much of this cohort is demoted each year, as a proportion of all cohorts:- - currentCohort%prom_weight = nan ! How much of this cohort is promoted each year, as a proportion of all cohorts:- - currentCohort%c_area = nan ! areal extent of canopy (m2) - currentCohort%treelai = nan ! lai of tree (total leaf area (m2) / canopy area (m2) - currentCohort%treesai = nan ! stem area index of tree (total stem area (m2) / canopy area (m2) - currentCohort%seed_prod = nan - currentCohort%vcmax25top = nan - currentCohort%jmax25top = nan - currentCohort%tpu25top = nan - currentCohort%kp25top = nan - - ! CARBON FLUXES - currentCohort%gpp_acc_hold = nan ! GPP: kgC/indiv/year - currentCohort%gpp_tstep = nan ! GPP: kgC/indiv/timestep - currentCohort%gpp_acc = nan ! GPP: kgC/indiv/day - currentCohort%npp_acc_hold = nan ! NPP: kgC/indiv/year - currentCohort%npp_tstep = nan ! NPP: kGC/indiv/timestep - currentCohort%npp_acc = nan ! NPP: kgC/indiv/day - currentCohort%year_net_uptake(:) = nan ! Net uptake of individual leaf layers kgC/m2/year - currentCohort%ts_net_uptake(:) = nan ! Net uptake of individual leaf layers kgC/m2/s - currentCohort%resp_acc_hold = nan ! RESP: kgC/indiv/year - currentCohort%resp_tstep = nan ! RESP: kgC/indiv/timestep - currentCohort%resp_acc = nan ! RESP: kGC/cohort/day - - ! Fluxes from nutrient allocation - currentCohort%daily_nh4_uptake = nan - currentCohort%daily_no3_uptake = nan - currentCohort%daily_n_gain = nan - currentCohort%sym_nfix_daily = nan - currentCohort%sym_nfix_tstep = nan - currentCohort%daily_p_gain = nan - currentCohort%daily_c_efflux = nan - currentCohort%daily_n_efflux = nan - currentCohort%daily_p_efflux = nan - currentCohort%daily_n_demand = nan - currentCohort%daily_p_demand = nan - currentCohort%cx_int = nan - currentCohort%cx0 = nan - currentCohort%ema_dcxdt = nan - currentCohort%cnp_limiter = fates_unset_int - - currentCohort%c13disc_clm = nan ! C13 discrimination, per mil at indiv/timestep - currentCohort%c13disc_acc = nan ! C13 discrimination, per mil at indiv/timestep at indiv/daily at the end of a day - - !RESPIRATION - currentCohort%rdark = nan - currentCohort%resp_m = nan ! Maintenance respiration. kGC/cohort/year - currentCohort%resp_m_unreduced = nan ! Diagnostic-only unreduced Maintenance respiration. kGC/cohort/year - currentCohort%resp_excess = nan ! Respiration of excess (unallocatable) carbon (kg/indiv/day) - currentCohort%livestem_mr = nan ! Live stem maintenance respiration. kgC/indiv/s-1 - currentCohort%livecroot_mr = nan ! Coarse root maintenance respiration. kgC/indiv/s-1 - currentCohort%froot_mr = nan ! Fine root maintenance respiration. kgC/indiv/s-1 - currentCohort%resp_g_tstep = nan ! Growth respiration. kGC/indiv/timestep - - - ! ALLOCATION - currentCohort%dmort = nan ! proportional mortality rate. (year-1) - - ! logging - currentCohort%lmort_direct = nan - currentCohort%lmort_infra = nan - currentCohort%lmort_collateral = nan - currentCohort%l_degrad = nan - - currentCohort%c_area = nan ! areal extent of canopy (m2) - currentCohort%treelai = nan ! lai of tree (total leaf area (m2) / canopy area (m2) - currentCohort%treesai = nan ! stem area index of tree (total stem area (m2) / canopy area (m2) - - - ! VARIABLES NEEDED FOR INTEGRATION - currentCohort%dndt = nan ! time derivative of cohort size - currentCohort%dhdt = nan ! time derivative of height - currentCohort%ddbhdt = nan ! time derivative of dbh - - ! FIRE - currentCohort%fraction_crown_burned = nan ! proportion of crown affected by fire - currentCohort%cambial_mort = nan ! probability that trees dies due to cambial char P&R (1986) - currentCohort%crownfire_mort = nan ! probability of tree post-fire mortality due to crown scorch - currentCohort%fire_mort = nan ! post-fire mortality from cambial and crown damage assuming two are independent - - end subroutine nan_cohort - - !-------------------------------------------------------------------------------------! - - subroutine zero_cohort(cc_p) - ! - ! !DESCRIPTION: - ! Zero variables that need to be accounted for if - ! this cohort is altered before they are defined. - ! - ! !USES: - ! - ! !ARGUMENTS - type (ed_cohort_type), intent(inout), target :: cc_p - ! - ! !LOCAL VARIABLES: - type (ed_cohort_type) , pointer :: currentCohort - !---------------------------------------------------------------------- - - currentCohort => cc_p - - currentCohort%NV = 0 - currentCohort%status_coh = 0 - currentCohort%rdark = 0._r8 - currentCohort%resp_m = 0._r8 - currentCohort%resp_m_unreduced = 0._r8 - currentCohort%resp_excess = 0._r8 - currentCohort%resp_g_tstep = 0._r8 - currentCohort%livestem_mr = 0._r8 - currentCohort%livecroot_mr = 0._r8 - currentCohort%froot_mr = 0._r8 - currentCohort%fire_mort = 0._r8 - currentcohort%npp_acc = 0._r8 - currentcohort%gpp_acc = 0._r8 - currentcohort%resp_acc = 0._r8 - currentcohort%npp_tstep = 0._r8 - currentcohort%gpp_tstep = 0._r8 - currentcohort%resp_tstep = 0._r8 - currentcohort%resp_acc_hold = 0._r8 - - currentcohort%year_net_uptake(:) = 999._r8 ! this needs to be 999, or trimming of new cohorts will break. - currentcohort%ts_net_uptake(:) = 0._r8 - currentcohort%fraction_crown_burned = 0._r8 - currentCohort%size_class = 1 - currentCohort%coage_class = 1 - currentCohort%seed_prod = 0._r8 - currentCohort%size_class_lasttimestep = 0 - currentcohort%npp_acc_hold = 0._r8 - currentcohort%gpp_acc_hold = 0._r8 - currentcohort%dmort = 0._r8 - currentcohort%g_sb_laweight = 0._r8 - currentcohort%treesai = 0._r8 - currentCohort%lmort_direct = 0._r8 - currentCohort%lmort_infra = 0._r8 - currentCohort%lmort_collateral = 0._r8 - currentCohort%l_degrad = 0._r8 - currentCohort%leaf_cost = 0._r8 - currentcohort%excl_weight = 0._r8 - currentcohort%prom_weight = 0._r8 - currentcohort%crownfire_mort = 0._r8 - currentcohort%cambial_mort = 0._r8 - currentCohort%c13disc_clm = 0._r8 - currentCohort%c13disc_acc = 0._r8 - - ! Daily nutrient fluxes are INTEGRATED over the course of the - ! day. This variable MUST be zerod upon creation AND - ! after allocation. These variables exist in - ! carbon-only mode but are not used. - - currentCohort%daily_nh4_uptake = 0._r8 - currentCohort%daily_no3_uptake = 0._r8 - currentCohort%daily_p_gain = 0._r8 - - currentCohort%daily_c_efflux = 0._r8 - currentCohort%daily_n_efflux = 0._r8 - currentCohort%daily_p_efflux = 0._r8 - - ! Initialize these as negative - currentCohort%daily_p_demand = -9._r8 - currentCohort%daily_n_demand = -9._r8 - - ! Fixation is also integrated over the course of the day - ! and must be zeroed upon creation and after plant - ! resource allocation - currentCohort%sym_nfix_daily = 0._r8 - - end subroutine zero_cohort - - !-------------------------------------------------------------------------------------! subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_in) ! ! !DESCRIPTION: @@ -759,9 +450,9 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_ ! ! !LOCAL VARIABLES: - type (ed_cohort_type) , pointer :: currentCohort - type (ed_cohort_type) , pointer :: shorterCohort - type (ed_cohort_type) , pointer :: tallerCohort + type (fates_cohort_type) , pointer :: currentCohort + type (fates_cohort_type) , pointer :: shorterCohort + type (fates_cohort_type) , pointer :: tallerCohort real(r8) :: leaf_c ! leaf carbon [kg] real(r8) :: store_c ! storage carbon [kg] @@ -862,12 +553,12 @@ subroutine terminate_cohort(currentSite, currentPatch, currentCohort, bc_in) ! !ARGUMENTS type (ed_site_type) , intent(inout), target :: currentSite type (ed_patch_type) , intent(inout), target :: currentPatch - type (ed_cohort_type), intent(inout), target :: currentCohort + type (fates_cohort_type), intent(inout), target :: currentCohort type(bc_in_type), intent(in) :: bc_in ! !LOCAL VARIABLES: - type (ed_cohort_type) , pointer :: shorterCohort - type (ed_cohort_type) , pointer :: tallerCohort + type (fates_cohort_type) , pointer :: shorterCohort + type (fates_cohort_type) , pointer :: tallerCohort real(r8) :: leaf_c ! leaf carbon [kg] real(r8) :: store_c ! storage carbon [kg] @@ -968,7 +659,7 @@ subroutine SendCohortToLitter(csite,cpatch,ccohort,nplant,bc_in) ! Arguments type (ed_site_type) , target :: csite type (ed_patch_type) , target :: cpatch - type (ed_cohort_type) , target :: ccohort + type (fates_cohort_type) , target :: ccohort real(r8) :: nplant ! Number (absolute) ! of plants to transfer type(bc_in_type), intent(in) :: bc_in @@ -1087,7 +778,7 @@ subroutine DeallocateCohort(currentCohort) ! the cohort structure itself. ! ---------------------------------------------------------------------------------- - type(ed_cohort_type),intent(inout) :: currentCohort + type(fates_cohort_type),intent(inout) :: currentCohort integer :: istat ! return status code character(len=255) :: smsg @@ -1130,12 +821,12 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) ! ! !LOCAL VARIABLES: - type (ed_cohort_type) , pointer :: currentCohort - type (ed_cohort_type) , pointer :: nextc - type (ed_cohort_type) , pointer :: nextnextc + type (fates_cohort_type) , pointer :: currentCohort + type (fates_cohort_type) , pointer :: nextc + type (fates_cohort_type) , pointer :: nextnextc - type (ed_cohort_type) , pointer :: shorterCohort - type (ed_cohort_type) , pointer :: tallerCohort + type (fates_cohort_type) , pointer :: shorterCohort + type (fates_cohort_type) , pointer :: tallerCohort integer :: i integer :: fusion_took_place @@ -1691,10 +1382,10 @@ subroutine sort_cohorts(patchptr) type(ed_patch_type) , intent(inout), target :: patchptr type(ed_patch_type) , pointer :: current_patch - type(ed_cohort_type), pointer :: current_c, next_c - type(ed_cohort_type), pointer :: shortestc, tallestc - type(ed_cohort_type), pointer :: storesmallcohort - type(ed_cohort_type), pointer :: storebigcohort + type(fates_cohort_type), pointer :: current_c, next_c + type(fates_cohort_type), pointer :: shortestc, tallestc + type(fates_cohort_type), pointer :: storesmallcohort + type(fates_cohort_type), pointer :: storebigcohort integer :: snull,tnull current_patch => patchptr @@ -1741,19 +1432,19 @@ subroutine insert_cohort(pcc, ptall, pshort, tnull, snull, storebigcohort, store ! !USES: ! ! !ARGUMENTS - type(ed_cohort_type) , intent(inout), pointer :: pcc - type(ed_cohort_type) , intent(inout), pointer :: ptall - type(ed_cohort_type) , intent(inout), pointer :: pshort + type(fates_cohort_type) , intent(inout), pointer :: pcc + type(fates_cohort_type) , intent(inout), pointer :: ptall + type(fates_cohort_type) , intent(inout), pointer :: pshort integer , intent(in) :: tnull integer , intent(in) :: snull - type(ed_cohort_type) , intent(inout),pointer,optional :: storesmallcohort ! storage of the smallest cohort for insertion routine - type(ed_cohort_type) , intent(inout),pointer,optional :: storebigcohort ! storage of the largest cohort for insertion routine + type(fates_cohort_type) , intent(inout),pointer,optional :: storesmallcohort ! storage of the smallest cohort for insertion routine + type(fates_cohort_type) , intent(inout),pointer,optional :: storebigcohort ! storage of the largest cohort for insertion routine ! ! !LOCAL VARIABLES: type(ed_patch_type), pointer :: currentPatch - type(ed_cohort_type), pointer :: current - type(ed_cohort_type), pointer :: tallptr, shortptr, icohort - type(ed_cohort_type), pointer :: ptallest, pshortest + type(fates_cohort_type), pointer :: current + type(fates_cohort_type), pointer :: tallptr, shortptr, icohort + type(fates_cohort_type), pointer :: ptallest, pshortest real(r8) :: tsp integer :: tallptrnull,exitloop !---------------------------------------------------------------------- @@ -1853,11 +1544,11 @@ subroutine copy_cohort( currentCohort,copyc ) ! !USES: ! ! !ARGUMENTS - type(ed_cohort_type), intent(inout) , target :: copyc ! New cohort argument. - type(ed_cohort_type), intent(in) , target :: currentCohort ! Old cohort argument. + type(fates_cohort_type), intent(inout) , target :: copyc ! New cohort argument. + type(fates_cohort_type), intent(in) , target :: currentCohort ! Old cohort argument. ! ! !LOCAL VARIABLES: - type(ed_cohort_type), pointer :: n,o ! New and old cohort pointers + type(fates_cohort_type), pointer :: n,o ! New and old cohort pointers !---------------------------------------------------------------------- o => currentCohort @@ -2021,7 +1712,7 @@ subroutine count_cohorts( currentPatch ) type(ed_patch_type), intent(inout), target :: currentPatch !new site ! ! !LOCAL VARIABLES: - type(ed_cohort_type), pointer :: currentCohort !new patch + type(fates_cohort_type), pointer :: currentCohort !new patch integer :: backcount !---------------------------------------------------------------------- @@ -2063,7 +1754,7 @@ subroutine UpdateCohortBioPhysRates(currentCohort) ! of different age classes are unchanged until the next day. ! -------------------------------------------------------------------------------- - type(ed_cohort_type),intent(inout) :: currentCohort + type(fates_cohort_type),intent(inout) :: currentCohort real(r8) :: frac_leaf_aclass(max_nleafage) ! Fraction of leaves in each age-class @@ -2136,7 +1827,7 @@ subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) ! ----------------------------------------------------------------------------------- ! argument - type(ed_cohort_type),intent(inout) :: currentCohort + type(fates_cohort_type),intent(inout) :: currentCohort real(r8),intent(out) :: delta_dbh real(r8),intent(out) :: delta_hite @@ -2234,11 +1925,11 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) type(ed_site_type) :: csite ! Site of the current cohort type(ed_patch_type) :: cpatch ! patch of the current cohort - type(ed_cohort_type),pointer :: ccohort ! Current (damaged) cohort + type(fates_cohort_type),pointer :: ccohort ! Current (damaged) cohort logical :: newly_recovered ! true if we create a new cohort ! locals - type(ed_cohort_type), pointer :: rcohort ! New cohort that recovers by + type(fates_cohort_type), pointer :: rcohort ! New cohort that recovers by ! having a lower damage class real(r8) :: sapw_area ! sapwood area real(r8) :: target_sapw_c,target_sapw_m ! sapwood mass, C and N/P @@ -2442,6 +2133,83 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) return end subroutine DamageRecovery + + + subroutine InitPRTBoundaryConditions(this) + ! + ! DESCRIPTION: + ! Set the boundary conditions that flow in an out of the PARTEH + ! allocation hypotheses. Each of these calls to "RegsterBC" are simply + ! setting pointers. + ! For instance, if the hypothesis wants to know what + ! the DBH of the plant is, then we pass in the dbh as an argument (this%dbh), + ! and also tell it which boundary condition we are talking about (which is + ! defined by an integer index (ac_bc_inout_id_dbh) + ! + ! Again, elaborated Example: + ! "ac_bc_inout_id_dbh" is the unique integer that defines the object index + ! for the allometric carbon "ac" boundary condition "bc" for DBH "dbh" + ! that is classified as input and output "inout". + ! See PRTAllometricCarbonMod.F90 to track its usage. + ! bc_rval is used as the optional argument identifyer to specify a real + ! value boundary condition. + ! bc_ival is used as the optional argument identifyer to specify an integer + ! value boundary condition. + ! + + ! ARGUMENTS: + type(fates_cohort_type), intent(inout) :: this + + select case(hlm_parteh_mode) + + case (prt_carbon_allom_hyp) + + ! register boundary conditions for the Carbon Only Allometric Hypothesis + call this%prt%RegisterBCInOut(ac_bc_inout_id_dbh, bc_rval=this%dbh) + call this%prt%RegisterBCInOut(ac_bc_inout_id_netdc, bc_rval=this%npp_acc) + call this%prt%RegisterBCIn(ac_bc_in_id_cdamage, bc_ival=this%crowndamage) + call this%prt%RegisterBCIn(ac_bc_in_id_pft, bc_ival=this%pft) + call this%prt%RegisterBCIn(ac_bc_in_id_ctrim, bc_rval=this%canopy_trim) + call this%prt%RegisterBCIn(ac_bc_in_id_lstat, bc_ival=this%status_coh) + + case (prt_cnp_flex_allom_hyp) + + call this%prt%RegisterBCIn(acnp_bc_in_id_pft, bc_ival=this%pft) + call this%prt%RegisterBCIn(acnp_bc_in_id_ctrim, bc_rval=this%canopy_trim) + call this%prt%RegisterBCIn(acnp_bc_in_id_lstat, bc_ival=this%status_coh) + call this%prt%RegisterBCIn(acnp_bc_in_id_netdc, bc_rval=this%npp_acc) + + call this%prt%RegisterBCIn(acnp_bc_in_id_nc_repro, bc_rval=this%nc_repro) + call this%prt%RegisterBCIn(acnp_bc_in_id_pc_repro, bc_rval=this%pc_repro) + call this%prt%RegisterBCIn(acnp_bc_in_id_cdamage, bc_ival=this%crowndamage) + + call this%prt%RegisterBCInOut(acnp_bc_inout_id_dbh, bc_rval=this%dbh) + call this%prt%RegisterBCInOut(acnp_bc_inout_id_resp_excess, bc_rval=this%resp_excess) + call this%prt%RegisterBCInOut(acnp_bc_inout_id_l2fr, bc_rval=this%l2fr) + call this%prt%RegisterBCInOut(acnp_bc_inout_id_cx_int, bc_rval=this%cx_int) + call this%prt%RegisterBCInOut(acnp_bc_inout_id_emadcxdt, bc_rval=this%ema_dcxdt) + call this%prt%RegisterBCInOut(acnp_bc_inout_id_cx0, bc_rval=this%cx0) + + call this%prt%RegisterBCInOut(acnp_bc_inout_id_netdn, bc_rval=this%daily_n_gain) + call this%prt%RegisterBCInOut(acnp_bc_inout_id_netdp, bc_rval=this%daily_p_gain) + + call this%prt%RegisterBCOut(acnp_bc_out_id_cefflux, bc_rval=this%daily_c_efflux) + call this%prt%RegisterBCOut(acnp_bc_out_id_nefflux, bc_rval=this%daily_n_efflux) + call this%prt%RegisterBCOut(acnp_bc_out_id_pefflux, bc_rval=this%daily_p_efflux) + call this%prt%RegisterBCOut(acnp_bc_out_id_limiter, bc_ival=this%cnp_limiter) + + case DEFAULT + + write(fates_log(),*) 'You specified an unknown PRT module' + write(fates_log(),*) 'Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + + end select + + end subroutine InitPRTBoundaryConditions + +!:.........................................................................: + end module EDCohortDynamicsMod diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 834561deaa..258849c066 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -4,6 +4,8 @@ module EDTypesMod use FatesConstantsMod, only : ifalse use FatesConstantsMod, only : itrue use FatesGlobals, only : fates_log + use FatesCohortMod, only : fates_cohort_type + use FatesCohortMod, only : nlevleaf use FatesHydraulicsMemMod, only : ed_cohort_hydr_type use FatesHydraulicsMemMod, only : ed_site_hydr_type use PRTGenericMod, only : prt_vartypes @@ -22,16 +24,15 @@ module EDTypesMod use FatesRunningMeanMod, only : rmean_type use FatesInterfaceTypesMod,only : bc_in_type use FatesInterfaceTypesMod,only : bc_out_type + implicit none private ! By default everything is private save integer, parameter, public :: nclmax = 2 ! Maximum number of canopy layers - integer, parameter, public :: ican_upper = 1 ! Nominal index for the upper canopy - integer, parameter, public :: ican_ustory = 2 ! Nominal index for diagnostics that refer - ! to understory layers (all layers that - ! are not the top canopy layer) + + integer, parameter, public :: maxpft = 16 ! maximum number of PFTs allowed ! the parameter file may determine that fewer @@ -53,8 +54,7 @@ module EDTypesMod integer, parameter, public :: idirect = 1 ! This is the array index for direct radiation integer, parameter, public :: idiffuse = 2 ! This is the array index for diffuse radiation - ! parameters that govern the VAI (LAI+SAI) bins used in radiative transfer code - integer, parameter, public :: nlevleaf = 30 ! number of leaf+stem layers in canopy layer + real(r8), public :: dinc_vai(nlevleaf) = fates_unset_r8 ! VAI bin widths array real(r8), public :: dlower_vai(nlevleaf) = fates_unset_r8 ! lower edges of VAI bins @@ -83,11 +83,6 @@ module EDTypesMod ! can be approximated to be equal to the visible band - integer, parameter, public :: leaves_on = 2 ! Flag specifying that a deciduous plant has leaves - ! and should be allocating to them as well - integer, parameter, public :: leaves_off = 1 ! Flag specifying that a deciduous plant has dropped - ! its leaves and should not be trying to allocate - ! towards any growth. ! Flag to turn on/off salinity effects on the effective "btran" ! btran stress function. @@ -186,230 +181,6 @@ module EDTypesMod integer, public :: n_uptake_mode integer, public :: p_uptake_mode - - !************************************ - !** COHORT type structure ** - !************************************ - type, public :: ed_cohort_type - - ! POINTERS - type (ed_cohort_type) , pointer :: taller => null() ! pointer to next tallest cohort - type (ed_cohort_type) , pointer :: shorter => null() ! pointer to next shorter cohort - type (ed_patch_type) , pointer :: patchptr => null() ! pointer to patch that cohort is in - - - - ! Multi-species, multi-organ Plant Reactive Transport (PRT) - ! Contains carbon and nutrient state variables for various plant organs - - class(prt_vartypes), pointer :: prt - - real(r8) :: l2fr ! leaf to fineroot biomass ratio (this is constant - ! in carbon only simulationss, and is set by the - ! allom_l2fr_min parameter. In nutrient - ! enabled simulations, this is dynamic, will - ! vary between allom_l2fr_min and allom_l2fr_max - ! parameters, with a tendency driven by - ! nutrient storage) [kg root / kg leaf] - - - - - - ! VEGETATION STRUCTURE - integer :: pft ! pft number - real(r8) :: n ! number of individuals in cohort per 'area' (10000m2 default) - real(r8) :: dbh ! dbh: cm - real(r8) :: coage ! cohort age in years - real(r8) :: hite ! height: meters - integer :: indexnumber ! unique number for each cohort. (within clump?) - integer :: canopy_layer ! canopy status of cohort (1 = canopy, 2 = understorey, etc.) - integer :: crowndamage ! crown damage class of the cohort [1: undamaged, >1: damaged] - real(r8) :: canopy_layer_yesterday ! recent canopy status of cohort - ! (1 = canopy, 2 = understorey, etc.) - ! real to be conservative during fusion - real(r8) :: g_sb_laweight ! Total conductance (stomata+boundary layer) of the cohort, weighted by its leaf area [m/s]*[m2] - real(r8) :: canopy_trim ! What is the fraction of the maximum leaf biomass that we are targeting? :- - real(r8) :: leaf_cost ! How much does it cost to maintain leaves: kgC/m2/year-1 - real(r8) :: excl_weight ! How much of this cohort is demoted each year, as a proportion of all cohorts:- - real(r8) :: prom_weight ! How much of this cohort is promoted each year, as a proportion of all cohorts:- - integer :: nv ! Number of leaf layers: - - integer :: status_coh ! growth status of plant (2 = leaves on , 1 = leaves off) - real(r8) :: c_area ! areal extent of canopy (m2) - real(r8) :: treelai ! lai of an individual within cohort leaf area (m2) / crown area (m2) - real(r8) :: treesai ! stem area index of an indiv. within cohort: stem area (m2) / crown area (m2) - logical :: isnew ! flag to signify a new cohort, new cohorts have not experienced - ! npp or mortality and should therefore not be fused or averaged - integer :: size_class ! An index that indicates which diameter size bin the cohort currently resides in - ! this is used for history output. We maintain this in the main cohort memory - ! because we don't want to continually re-calculate the cohort's position when - ! performing size diagnostics at high-frequency calls - integer :: coage_class ! An index that indicates which age bin the cohort currently resides in - ! used for history output. - integer :: size_by_pft_class ! An index that indicates the cohorts position of the joint size-class x functional - ! type classification. We also maintain this in the main cohort memory - ! because we don't want to continually re-calculate the cohort's position when - ! performing size diagnostics at high-frequency calls - integer :: coage_by_pft_class ! An index that indicates the cohorts position of the join cohort age class x PFT - integer :: size_class_lasttimestep ! size class of the cohort at the last time step - - ! CARBON FLUXES - - ! ---------------------------------------------------------------------------------- - ! NPP, GPP and RESP: Instantaneous, accumulated and accumulated-hold types.* - ! - ! _tstep: The instantaneous estimate that is calculated at each rapid plant biophysics - ! time-step (ie photosynthesis, sub-hourly). (kgC/indiv/timestep) - ! _acc: The accumulation of the _tstep variable from the beginning to ending of - ! the dynamics time-scale. This variable is zero'd during initialization and - ! after the dynamics call-sequence is completed. (kgC/indiv/day) - ! _acc_hold: While _acc is zero'd after the dynamics call sequence and then integrated, - ! _acc_hold "holds" the integrated value until the next time dynamics is - ! called. This is necessary for restarts. This variable also has units - ! converted to a useful rate (kgC/indiv/yr) - ! ---------------------------------------------------------------------------------- - - real(r8) :: gpp_tstep ! Gross Primary Production (see above *) - real(r8) :: gpp_acc - real(r8) :: gpp_acc_hold - - real(r8) :: npp_tstep ! Net Primary Production (see above *) - real(r8) :: npp_acc - real(r8) :: npp_acc_hold - - real(r8) :: resp_tstep ! Autotrophic respiration (see above *) - real(r8) :: resp_acc - real(r8) :: resp_acc_hold - - ! carbon 13c discrimination - real(r8) :: c13disc_clm ! carbon 13 discrimination in new synthesized carbon: part-per-mil, at each indiv/timestep - real(r8) :: c13disc_acc ! carbon 13 discrimination in new synthesized carbon: part-per-mil, at each indiv/day, at the end of a day - - - ! Used for CNP - integer :: cnp_limiter ! Which element is limiting growth? ! 0=none,1=C,2=N,3=P - real(r8) :: cx_int ! The time integration of the log of the relative carbon storage over relative nutrient - real(r8) :: ema_dcxdt ! The derivative of the log of the relative carbon storage over relative nutrient - real(r8) :: cx0 ! The value on the previous time-step of log of the relative carbon - ! storage over relative nutrient - real(r8) :: nc_repro ! The NC ratio of a new recruit, used also for defining reproductive stoich - real(r8) :: pc_repro ! The PC ratio of a new recruit - - ! Nutrient Fluxes (if N, P, etc. are turned on) - - real(r8) :: daily_nh4_uptake ! integrated daily uptake of mineralized ammonium through competitive acquisition in soil [kg N / plant/ day] - real(r8) :: daily_no3_uptake ! integrated daily uptake of mineralized nitrate through competitive acquisition in soil [kg N / plant/ day] - - real(r8) :: sym_nfix_daily ! Accumulated symbiotic N fixation from the roots [kgN/indiv/day] - real(r8) :: sym_nfix_tstep ! Symbiotic N fixation from the roots for the time-step[kgN/indiv/tstep] - - real(r8) :: daily_n_gain ! sum of fixation and uptake of mineralized nh4/no3 in solution as well as symbiotic fixation - real(r8) :: daily_p_gain ! integrated daily uptake of mineralized P through competitive acquisition in soil [kg P / plant/ day] - - real(r8) :: daily_c_efflux ! daily mean efflux of excess carbon from roots into labile pool [kg C/plant/day] - real(r8) :: daily_n_efflux ! daily mean efflux of excess nitrogen from roots into labile pool [kg N/plant/day] - real(r8) :: daily_p_efflux ! daily mean efflux of excess phophorus from roots into labile pool [kg P/plant/day] - - real(r8) :: daily_n_demand ! The daily amount of N demanded by the plant [kgN/plant/day] - real(r8) :: daily_p_demand ! The daily amount of P demanded by the plant [kgN/plant/day] - - - ! The following four biophysical rates are assumed to be - ! at the canopy top, at reference temp 25C, and based on the - ! leaf age weighted average of the PFT parameterized values. The last - ! condition is why it is dynamic and tied to the cohort - - real(r8) :: vcmax25top ! Maximum carboxylation at the cohort's top - ! at reference temperature (25C). - real(r8) :: jmax25top ! canopy top: maximum electron transport - ! rate at 25C (umol electrons/m**2/s) - real(r8) :: tpu25top ! canopy top: triose phosphate utilization - ! rate at 25C (umol CO2/m**2/s) - real(r8) :: kp25top ! canopy top: initial slope of CO2 response - ! curve (C4 plants) at 25C - - - - real(r8) :: ts_net_uptake(nlevleaf) ! Net uptake of leaf layers: kgC/m2/timestep - real(r8) :: year_net_uptake(nlevleaf) ! Net uptake of leaf layers: kgC/m2/year - - - ! RESPIRATION COMPONENTS - real(r8) :: rdark ! Dark respiration: kgC/indiv/s - - real(r8) :: resp_g_tstep ! Growth respiration: kgC/indiv/timestep - real(r8) :: resp_m ! Maintenance respiration: kgC/indiv/timestep - real(r8) :: resp_m_unreduced ! Diagnostic-only unreduced maintenance respiration: kgC/indiv/timestep - real(r8) :: resp_excess ! Respiration of excess carbon kgC/indiv/day - real(r8) :: livestem_mr ! Live stem maintenance respiration: kgC/indiv/s - ! (Above ground) - real(r8) :: livecroot_mr ! Live stem maintenance respiration: kgC/indiv/s - ! (below ground) - real(r8) :: froot_mr ! Live fine root maintenance respiration: kgC/indiv/s - - !DAMAGE - real(r8) :: branch_frac ! Fraction of aboveground woody biomass in branches - - !MORTALITY - real(r8) :: dmort ! proportional mortality rate. (year-1) - - ! Mortality Rate Partitions - real(r8) :: bmort ! background mortality rate n/year - real(r8) :: cmort ! carbon starvation mortality rate n/year - real(r8) :: hmort ! hydraulic failure mortality rate n/year - real(r8) :: frmort ! freezing mortality n/year - real(r8) :: smort ! senesence mortality n/year - real(r8) :: asmort ! age senescence mortality n/year - real(r8) :: dgmort ! damage mortality n/year - - ! Logging Mortality Rate - ! Yi Xu & M. Huang - real(r8) :: lmort_direct ! directly logging rate fraction /per logging activity - real(r8) :: lmort_collateral ! collaterally damaged rate fraction /per logging activity - real(r8) :: lmort_infra ! mechanically damaged rate fraction /per logging activity - real(r8) :: l_degrad ! rate of trees that are not killed but suffer from forest degradation - ! (i.e. they are moved to newly-anthro-disturbed secondary - ! forest patch). fraction /per logging activity - - real(r8) :: seed_prod ! diagnostic seed production rate [kgC/plant/day] - - ! NITROGEN POOLS - ! ---------------------------------------------------------------------------------- - ! Nitrogen pools are not prognostic in the current implementation. - ! They are diagnosed during photosynthesis using a simple C2N parameter. Local values - ! used in that routine. - ! ---------------------------------------------------------------------------------- - - ! GROWTH DERIVIATIVES - real(r8) :: dndt ! time derivative of cohort size : n/year - real(r8) :: dhdt ! time derivative of height : m/year - real(r8) :: ddbhdt ! time derivative of dbh : cm/year - real(r8) :: dbdeaddt ! time derivative of dead biomass : KgC/year - - - - - ! FIRE - real(r8) :: fraction_crown_burned ! proportion of crown affected by fire:- - real(r8) :: cambial_mort ! probability that trees dies due to cambial char - ! (conditional on the tree being subjected to the fire) - real(r8) :: crownfire_mort ! probability of tree post-fire mortality - ! due to crown scorch (conditional on the tree being subjected to the fire) - real(r8) :: fire_mort ! post-fire mortality from cambial and crown damage assuming two are independent:- - - ! Hydraulics - type(ed_cohort_hydr_type), pointer :: co_hydr ! All cohort hydraulics data, see FatesHydraulicsMemMod.F90 - - - ! Running means - - ! (keeping this in-code as an example) - !class(rmean_type), pointer :: tveg_lpa ! exponential moving average of leaf temperature at the - ! leaf photosynthetic acclimation time-scale [K] - - - end type ed_cohort_type - !************************************ !** Patch type structure ** !************************************ @@ -417,8 +188,8 @@ module EDTypesMod type, public :: ed_patch_type ! POINTERS - type (ed_cohort_type), pointer :: tallest => null() ! pointer to patch's tallest cohort - type (ed_cohort_type), pointer :: shortest => null() ! pointer to patch's shortest cohort + type (fates_cohort_type), pointer :: tallest => null() ! pointer to patch's tallest cohort + type (fates_cohort_type), pointer :: shortest => null() ! pointer to patch's shortest cohort type (ed_patch_type), pointer :: older => null() ! pointer to next older patch type (ed_patch_type), pointer :: younger => null() ! pointer to next younger patch @@ -907,33 +678,13 @@ module EDTypesMod public :: val_check_ed_vars public :: dump_site public :: dump_patch - public :: dump_cohort public :: dump_cohort_hydr public :: CanUpperUnder contains ! ===================================================================================== - function CanUpperUnder(ccohort) result(can_position) - - ! This simple function is used to determine if a - ! cohort's crown position is in the upper portion (ie the canopy) - ! or the understory. This differentiation is only used for - ! diagnostic purposes. Functionally, the model uses - ! the canopy layer position, which may have more than two layers - ! at any given time. Utlimately, every plant that is not in the - ! top layer (canopy), is considered understory. - - type(ed_cohort_type) :: ccohort ! Current cohort of interest - integer :: can_position - - if(ccohort%canopy_layer == 1)then - can_position = ican_upper - else - can_position = ican_ustory - end if - - end function CanUpperUnder + ! ===================================================================================== @@ -1002,7 +753,7 @@ subroutine val_check_ed_vars(currentPatch,var_aliases,return_code) ! return 10+ if an overflow ! return 100% if an underflow ! Locals - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort ! Check through a registry of variables to check @@ -1116,95 +867,14 @@ end subroutine dump_patch ! ===================================================================================== - subroutine dump_cohort(ccohort) - type(ed_cohort_type),intent(in),target :: ccohort - - write(fates_log(),*) '----------------------------------------' - write(fates_log(),*) ' Dumping Cohort Information ' - write(fates_log(),*) '----------------------------------------' - write(fates_log(),*) 'co%pft = ', ccohort%pft - write(fates_log(),*) 'co%n = ', ccohort%n - write(fates_log(),*) 'co%dbh = ', ccohort%dbh - write(fates_log(),*) 'co%hite = ', ccohort%hite - write(fates_log(),*) 'co%crowndamage = ', ccohort%crowndamage - write(fates_log(),*) 'co%coage = ', ccohort%coage - write(fates_log(),*) 'co%l2fr = ', ccohort%l2fr - write(fates_log(),*) 'leaf carbon = ', ccohort%prt%GetState(leaf_organ,carbon12_element) - write(fates_log(),*) 'fineroot carbon = ', ccohort%prt%GetState(fnrt_organ,carbon12_element) - write(fates_log(),*) 'sapwood carbon = ', ccohort%prt%GetState(sapw_organ,carbon12_element) - write(fates_log(),*) 'structural (dead) carbon = ', ccohort%prt%GetState(struct_organ,carbon12_element) - write(fates_log(),*) 'storage carbon = ', ccohort%prt%GetState(store_organ,carbon12_element) - write(fates_log(),*) 'reproductive carbon = ', ccohort%prt%GetState(repro_organ,carbon12_element) - write(fates_log(),*) 'co%g_sb_laweight = ', ccohort%g_sb_laweight - write(fates_log(),*) 'co%leaf_cost = ', ccohort%leaf_cost - write(fates_log(),*) 'co%canopy_layer = ', ccohort%canopy_layer - write(fates_log(),*) 'co%canopy_layer_yesterday = ', ccohort%canopy_layer_yesterday - write(fates_log(),*) 'co%nv = ', ccohort%nv - write(fates_log(),*) 'co%status_coh = ', ccohort%status_coh - write(fates_log(),*) 'co%canopy_trim = ', ccohort%canopy_trim - write(fates_log(),*) 'co%excl_weight = ', ccohort%excl_weight - write(fates_log(),*) 'co%prom_weight = ', ccohort%prom_weight - write(fates_log(),*) 'co%size_class = ', ccohort%size_class - write(fates_log(),*) 'co%size_by_pft_class = ', ccohort%size_by_pft_class - write(fates_log(),*) 'co%coage_class = ', ccohort%coage_class - write(fates_log(),*) 'co%coage_by_pft_class = ', ccohort%coage_by_pft_class - write(fates_log(),*) 'co%gpp_acc_hold = ', ccohort%gpp_acc_hold - write(fates_log(),*) 'co%gpp_acc = ', ccohort%gpp_acc - write(fates_log(),*) 'co%gpp_tstep = ', ccohort%gpp_tstep - write(fates_log(),*) 'co%npp_acc_hold = ', ccohort%npp_acc_hold - write(fates_log(),*) 'co%npp_tstep = ', ccohort%npp_tstep - write(fates_log(),*) 'co%npp_acc = ', ccohort%npp_acc - write(fates_log(),*) 'co%resp_tstep = ', ccohort%resp_tstep - write(fates_log(),*) 'co%resp_acc = ', ccohort%resp_acc - write(fates_log(),*) 'co%resp_acc_hold = ', ccohort%resp_acc_hold - write(fates_log(),*) 'co%rdark = ', ccohort%rdark - write(fates_log(),*) 'co%resp_m = ', ccohort%resp_m - write(fates_log(),*) 'co%resp_g_tstep = ', ccohort%resp_g_tstep - write(fates_log(),*) 'co%livestem_mr = ', ccohort%livestem_mr - write(fates_log(),*) 'co%livecroot_mr = ', ccohort%livecroot_mr - write(fates_log(),*) 'co%froot_mr = ', ccohort%froot_mr - write(fates_log(),*) 'co%dgmort = ', ccohort%dgmort - write(fates_log(),*) 'co%treelai = ', ccohort%treelai - write(fates_log(),*) 'co%treesai = ', ccohort%treesai - write(fates_log(),*) 'co%c_area = ', ccohort%c_area - write(fates_log(),*) 'co%cmort = ', ccohort%cmort - write(fates_log(),*) 'co%bmort = ', ccohort%bmort - write(fates_log(),*) 'co%smort = ', ccohort%smort - write(fates_log(),*) 'co%asmort = ', ccohort%asmort - write(fates_log(),*) 'co%dgmort = ', ccohort%dgmort - write(fates_log(),*) 'co%hmort = ', ccohort%hmort - write(fates_log(),*) 'co%frmort = ', ccohort%frmort - write(fates_log(),*) 'co%asmort = ', ccohort%asmort - write(fates_log(),*) 'co%lmort_direct = ', ccohort%lmort_direct - write(fates_log(),*) 'co%lmort_collateral = ', ccohort%lmort_collateral - write(fates_log(),*) 'co%lmort_infra = ', ccohort%lmort_infra - write(fates_log(),*) 'co%isnew = ', ccohort%isnew - write(fates_log(),*) 'co%dndt = ', ccohort%dndt - write(fates_log(),*) 'co%dhdt = ', ccohort%dhdt - write(fates_log(),*) 'co%ddbhdt = ', ccohort%ddbhdt - write(fates_log(),*) 'co%dbdeaddt = ', ccohort%dbdeaddt - write(fates_log(),*) 'co%fraction_crown_burned = ', ccohort%fraction_crown_burned - write(fates_log(),*) 'co%fire_mort = ', ccohort%fire_mort - write(fates_log(),*) 'co%crownfire_mort = ', ccohort%crownfire_mort - write(fates_log(),*) 'co%cambial_mort = ', ccohort%cambial_mort - write(fates_log(),*) 'co%size_class = ', ccohort%size_class - write(fates_log(),*) 'co%size_by_pft_class = ', ccohort%size_by_pft_class - - if (associated(ccohort%co_hydr) ) then - call dump_cohort_hydr(ccohort) - endif - write(fates_log(),*) '----------------------------------------' - return - end subroutine dump_cohort - ! ===================================================================================== subroutine dump_cohort_hydr(ccohort) - type(ed_cohort_type),intent(in),target :: ccohort + type(fates_cohort_type),intent(in),target :: ccohort type(ed_cohort_hydr_type), pointer :: ccohort_hydr ccohort_hydr => ccohort%co_hydr diff --git a/main/FatesCohortMod.F90 b/main/FatesCohortMod.F90 new file mode 100644 index 0000000000..5d1ffa89a7 --- /dev/null +++ b/main/FatesCohortMod.F90 @@ -0,0 +1,624 @@ +module FatesCohortMod + + use FatesConstantsMod, only : r8 => fates_r8 + use FatesGlobals, only : fates_log + use PRTGenericMod, only : prt_vartypes + use FatesHydraulicsMemMod, only : ed_cohort_hydr_type + use FatesInterfaceTypesMod, only : hlm_parteh_mode + + implicit none + private + + ! PARAMETERS + + ! parameters that govern the VAI (LAI+SAI) bins used in radiative transfer code + integer, parameter, public :: nlevleaf = 30 ! number of leaf+stem layers in each canopy layer + + integer, parameter, public :: ican_upper = 1 ! nominal index for the upper canopy + integer, parameter, public :: ican_ustory = 2 ! nominal index for diagnostics that refer to understory layers + ! (all layers that are not the top canopy layer) + + type, public :: fates_cohort_type + + ! POINTERS + type (fates_cohort_type), pointer :: taller => null() ! pointer to next tallest cohort + type (fates_cohort_type), pointer :: shorter => null() ! pointer to next shorter cohort + + !:.........................................................................: + + ! Multi-species, multi-organ Plant Reactive Transport (PRT) + ! Contains carbon and nutrient state variables for various plant organs + class(prt_vartypes), pointer :: prt + real(r8) :: l2fr ! leaf to fineroot biomass ratio (this is constant + ! in carbon only simulationss, and is set by the + ! allom_l2fr_min parameter. In nutrient + ! enabled simulations, this is dynamic, will + ! vary between allom_l2fr_min and allom_l2fr_max + ! parameters, with a tendency driven by + ! nutrient storage) [kg root / kg leaf] + + !:.........................................................................: + + ! VEGETATION STRUCTURE + + integer :: pft ! pft index + real(r8) :: n ! number of individuals in cohort per 'area' (10000m2 default) [/m2] + real(r8) :: dbh ! diameter at breast height [cm] + real(r8) :: coage ! age [years] + real(r8) :: hite ! height [m] + integer :: indexnumber ! unique number for each cohort (within clump?) + integer :: canopy_layer ! canopy status of cohort [1 = canopy, 2 = understorey, etc.] + real(r8) :: canopy_layer_yesterday ! recent canopy status of cohort [1 = canopy, 2 = understorey, etc.] + ! real to be conservative during fusion + integer :: crowndamage ! crown damage class of the cohort [1 = undamaged, >1 = damaged] + real(r8) :: g_sb_laweight ! total conductance (stomata + boundary layer) of the cohort + ! weighted by its leaf area [m/s]*[m2] + real(r8) :: canopy_trim ! fraction of the maximum leaf biomass that we are targeting [0-1] + real(r8) :: leaf_cost ! how much does it cost to maintain leaves [kgC/m2/year] + real(r8) :: excl_weight ! how much of this cohort is demoted each year, as a proportion of all cohorts + real(r8) :: prom_weight ! how much of this cohort is promoted each year, as a proportion of all cohorts + integer :: nv ! number of leaf layers + integer :: status_coh ! growth status of plant [2 = leaves on , 1 = leaves off] + real(r8) :: c_area ! areal extent of canopy [m2] + real(r8) :: treelai ! lai of an individual within cohort leaf area [m2 leaf area/m2 crown area] + real(r8) :: treesai ! stem area index of an individual within cohort [m2 stem area/m2 crown area] + logical :: isnew ! flag to signify a new cohort - new cohorts have not experienced + ! npp or mortality and should therefore not be fused or averaged + integer :: size_class ! index that indicates which diameter size bin the cohort currently resides in + ! this is used for history output. We maintain this in the main cohort memory + ! because we don't want to continually re-calculate the cohort's position when + ! performing size diagnostics at high-frequency calls + integer :: coage_class ! index that indicates which age bin the cohort currently resides in + ! (used for history output) + integer :: size_by_pft_class ! index that indicates the cohorts position of the joint size-class x functional + ! type classification. We also maintain this in the main cohort memory + ! because we don't want to continually re-calculate the cohort's position when + ! performing size diagnostics at high-frequency calls + integer :: coage_by_pft_class ! index that indicates the cohorts position of the join cohort age class x PFT + integer :: size_class_lasttimestep ! size class of the cohort at the last time step + + !:.........................................................................: + + ! CARBON AND NUTRIENT FLUXES + + ! -------------------------------------------------------------------------- + ! NPP, GPP and RESP: Instantaneous, accumulated and accumulated-hold types* + ! + ! _tstep: The instantaneous estimate that is calculated at each rapid plant biophysics + ! time-step (ie photosynthesis, sub-hourly) [kgC/indiv/timestep] + ! _acc: The accumulation of the _tstep variable from the beginning to ending of + ! the dynamics time-scale. This variable is zero'd during initialization and + ! after the dynamics call-sequence is completed. [kgC/indiv/day] + ! _acc_hold: While _acc is zero'd after the dynamics call sequence and then integrated, + ! _acc_hold "holds" the integrated value until the next time dynamics is + ! called. This is necessary for restarts. This variable also has units + ! converted to a useful rate [kgC/indiv/yr] + ! -------------------------------------------------------------------------- + + real(r8) :: gpp_tstep ! Gross Primary Production (see above *) + real(r8) :: gpp_acc + real(r8) :: gpp_acc_hold + + real(r8) :: npp_tstep ! Net Primary Production (see above *) + real(r8) :: npp_acc + real(r8) :: npp_acc_hold + + real(r8) :: resp_tstep ! Autotrophic respiration (see above *) + real(r8) :: resp_acc + real(r8) :: resp_acc_hold + + real(r8) :: c13disc_clm ! carbon 13 discrimination in new synthesized carbon at each indiv/timestep [ppm] + real(r8) :: c13disc_acc ! carbon 13 discrimination in new synthesized carbon at each indiv/day + ! at the end of a day [ppm] + + ! The following four biophysical rates are assumed to be at the canopy top, at reference temp 25degC, + ! and based on the leaf age weighted average of the PFT parameterized values. + ! The last condition is why it is dynamic and tied to the cohort + + real(r8) :: vcmax25top ! maximum carboxylation at canopy top and 25degC [umol CO2/m2/s] + real(r8) :: jmax25top ! maximum electron transport rate at canopy top and 25degC [umol electrons/m2/s] + real(r8) :: tpu25top ! triose phosphate utilization rate at canopy top and 25degC [umol CO2/m2/s] + real(r8) :: kp25top ! initial slope of CO2 response curve (C4 plants) at 25C + + real(r8) :: ts_net_uptake(nlevleaf) ! net uptake of leaf layers [kgC/m2/timestep] + real(r8) :: year_net_uptake(nlevleaf) ! net uptake of leaf layers [kgC/m2/year] + + ! used for CNP + integer :: cnp_limiter ! which element is limiting growth [0 = none, 1 = C, 2 = N, 3 = P] + real(r8) :: cx_int ! time integration of the log of the relative carbon storage over relative nutrient + real(r8) :: ema_dcxdt ! derivative of the log of the relative carbon storage over relative nutrient + real(r8) :: cx0 ! value on the previous time-step of log of the relative carbon storage over + ! relative nutrient + real(r8) :: nc_repro ! N:C ratio of a new recruit, used also for defining reproductive stoich + real(r8) :: pc_repro ! P:C ratio of a new recruit + + ! Nutrient Fluxes (if N, P, etc. are turned on) + real(r8) :: daily_nh4_uptake ! integrated daily uptake of mineralized ammonium through competitive acquisition + ! in soil [kgN/plant/day] + real(r8) :: daily_no3_uptake ! integrated daily uptake of mineralized nitrate through competitive acquisition + ! in soil [kgN/plant/day] + + real(r8) :: sym_nfix_daily ! accumulated symbiotic N fixation from the roots [kgN/indiv/day] + real(r8) :: sym_nfix_tstep ! symbiotic N fixation from the roots for the time-step [kgN/indiv/timestep] + + real(r8) :: daily_n_gain ! sum of fixation and uptake of mineralized NH4/NO3 in solution as well as + ! symbiotic fixation + real(r8) :: daily_p_gain ! integrated daily uptake of mineralized P through competitive acquisition + ! in soil [kgP/plant/day] + + real(r8) :: daily_c_efflux ! daily mean efflux of excess carbon from roots into labile pool [kgC/plant/day] + real(r8) :: daily_n_efflux ! daily mean efflux of excess nitrogen from roots into labile pool [kgN/plant/day] + real(r8) :: daily_p_efflux ! daily mean efflux of excess phophorus from roots into labile pool [kgP/plant/day] + + real(r8) :: daily_n_demand ! daily amount of N demanded by the plant [kgN/plant/day] + real(r8) :: daily_p_demand ! daily amount of P demanded by the plant [kgN/plant/day] + + real(r8) :: seed_prod ! diagnostic seed production rate [kgC/plant/day] + + !:.........................................................................: + + ! RESPIRATION COMPONENTS + real(r8) :: rdark ! dark respiration [kgC/indiv/s] + real(r8) :: resp_g_tstep ! growth respiration [kgC/indiv/timestep] + real(r8) :: resp_m ! maintenance respiration [kgC/indiv/timestep] + real(r8) :: resp_m_unreduced ! diagnostic-only unreduced maintenance respiration [kgC/indiv/timestep] + real(r8) :: resp_excess ! respiration of excess carbon [kgC/indiv/day] + real(r8) :: livestem_mr ! aboveground live stem maintenance respiration [kgC/indiv/s] + real(r8) :: livecroot_mr ! belowground live stem maintenance respiration [kgC/indiv/s] + real(r8) :: froot_mr ! live fine root maintenance respiration [kgC/indiv/s] + + !:.........................................................................: + + ! DAMAGE + real(r8) :: branch_frac ! fraction of aboveground woody biomass in branches [0-1] + + !:.........................................................................: + + ! MORTALITY + real(r8) :: dmort ! proportional mortality rate [/year] + + ! Mortality Rate Partitions + real(r8) :: bmort ! background mortality rate [indiv/year] + real(r8) :: cmort ! carbon starvation mortality rate [indiv/year] + real(r8) :: hmort ! hydraulic failure mortality rate [indiv/year] + real(r8) :: frmort ! freezing mortality rate [indiv/year] + real(r8) :: smort ! senesence mortality [indiv/year] + real(r8) :: asmort ! age senescence mortality [indiv/year] + real(r8) :: dgmort ! damage mortality [indiv/year] + + ! Logging Mortality Rate + ! Yi Xu & M. Huang + real(r8) :: lmort_direct ! directly logging rate [fraction/logging activity] + real(r8) :: lmort_collateral ! collaterally damaged rate [fraction/logging activity] + real(r8) :: lmort_infra ! mechanically damaged rate [fraction/logging activity] + real(r8) :: l_degrad ! rate of trees that are not killed but suffer from forest degradation + ! (i.e. they are moved to newly-anthro-disturbed secondary + ! forest patch) [fraction/logging activity] + + !:.........................................................................: + + ! NITROGEN POOLS + ! -------------------------------------------------------------------------- + ! Nitrogen pools are not prognostic in the current implementation. + ! They are diagnosed during photosynthesis using a simple C2N parameter. + ! Local values are used in that routine. + ! -------------------------------------------------------------------------- + + !:.........................................................................: + + ! GROWTH DERIVIATIVES + real(r8) :: dndt ! time derivative of cohort size [n/year] + real(r8) :: dhdt ! time derivative of height [m/year] + real(r8) :: ddbhdt ! time derivative of dbh [cm/year] + real(r8) :: dbdeaddt ! time derivative of dead biomass [kgC/year] + + !:.........................................................................: + + ! FIRE + real(r8) :: fraction_crown_burned ! proportion of crown affected by fire [0-1] + real(r8) :: cambial_mort ! probability that trees dies due to cambial charring [0-1] + ! (conditional on the tree being subjected to the fire) + real(r8) :: crownfire_mort ! probability of tree post-fire mortality from crown scorch [0-1] + ! (conditional on the tree being subjected to the fire) + real(r8) :: fire_mort ! post-fire mortality from cambial and crown damage assuming two are independent [0-1] + + !:.........................................................................: + + ! HYDRAULICS + type(ed_cohort_hydr_type), pointer :: co_hydr ! all cohort hydraulics data, see FatesHydraulicsMemMod.F90 + + !:.........................................................................: + + contains + + procedure :: init + procedure :: dump + procedure :: nan_values + procedure :: zero_values + procedure :: CanUpperUnder + + end type fates_cohort_type + + !:...........................................................................: + + contains + + subroutine init(this, prt) + ! + ! DESCRIPTION: + ! Create new cohort and set default values for all variables + ! + + ! ARGUMENTS: + type(fates_cohort_type), intent(inout), target :: this + class(prt_vartypes), intent(inout), pointer :: prt ! allocated PARTEH object + + call this%nan_cohort() ! make everything in the cohort not-a-number + call this%zero_cohort() ! zero things that need to be zeroed + + ! point to the PARTEH object + this%prt => prt + + ! The PARTEH cohort object should be allocated and already + ! initialized in this routine. + call this%prt%CheckInitialConditions() + + call this%InitPRTBoundaryConditions() + + ! new cohorts do not have mortality rates, nor have they moved any + ! carbon when they are created. They will bias our statistics + ! until they have experienced a full day. We need a newly recruited flag. + ! This flag will be set to false after it has experienced + ! growth, disturbance and mortality. + this%isnew = .true. + + end subroutine init + + !:.........................................................................: + + subroutine nan_values(this) + ! + ! DESCRIPTION: + ! make all the cohort variables NaN or unset so they aren't used before defined + ! + + ! USES: + use FatesConstantsMod, only : fates_unset_int + use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) + + ! ARGUMENTS: + type(fates_cohort_type), intent(inout) :: this + + ! set pointers to null + this%taller => null() + this%shorter => null() + this%prt => null() + this%co_hydr => null() + nullify(this%taller) + nullify(this%shorter) + nullify(this%prt) + nullify(this%co_hydr) + + ! VEGETATION STRUCTURE + this%l2fr = nan + this%pft = fates_unset_int + this%n = nan + this%dbh = nan + this%coage = nan + this%hite = nan + this%indexnumber = fates_unset_int + this%canopy_layer = fates_unset_int + this%canopy_layer_yesterday = nan + this%crowndamage = fates_unset_int + this%g_sb_laweight = nan + this%canopy_trim = nan + this%leaf_cost = nan + this%excl_weight = nan + this%prom_weight = nan + this%nv = fates_unset_int + this%status_coh = fates_unset_int + this%c_area = nan + this%treelai = nan + this%treesai = nan + this%isnew = .false. + this%size_class = fates_unset_int + this%coage_class = fates_unset_int + this%size_by_pft_class = fates_unset_int + this%coage_by_pft_class = fates_unset_int + this%size_class_lasttimestep = fates_unset_int + + ! CARBON AND NUTRIENT FLUXES + this%gpp_tstep = nan + this%gpp_acc = nan + this%gpp_acc_hold = nan + this%npp_tstep = nan + this%npp_acc = nan + this%npp_acc_hold = nan + this%resp_tstep = nan + this%resp_acc = nan + this%resp_acc_hold = nan + this%c13disc_clm = nan + this%c13disc_acc = nan + this%vcmax25top = nan + this%jmax25top = nan + this%tpu25top = nan + this%kp25top = nan + this%year_net_uptake(:) = nan + this%ts_net_uptake(:) = nan + this%cnp_limiter = fates_unset_int + this%cx_int = nan + this%ema_dcxdt = nan + this%cx0 = nan + this%nc_repro = nan + this%pc_repro = nan + this%daily_nh4_uptake = nan + this%daily_no3_uptake = nan + this%sym_nfix_daily = nan + this%sym_nfix_tstep = nan + this%daily_n_gain = nan + this%daily_p_gain = nan + this%daily_c_efflux = nan + this%daily_n_efflux = nan + this%daily_p_efflux = nan + this%daily_n_demand = nan + this%daily_p_demand = nan + this%seed_prod = nan + + ! RESPIRATION COMPONENTS + this%rdark = nan + this%resp_g_tstep = nan + this%resp_m = nan + this%resp_m_unreduced = nan + this%resp_excess = nan + this%livestem_mr = nan + this%livecroot_mr = nan + this%froot_mr = nan + + ! DAMAGE + this%branch_frac = nan + + ! MORTALITY + this%dmort = nan + this%bmort = nan + this%cmort = nan + this%frmort = nan + this%smort = nan + this%asmort = nan + this%dgmort = nan + this%lmort_direct = nan + this%lmort_collateral = nan + this%lmort_infra = nan + this%l_degrad = nan + + ! GROWTH DERIVATIVES + this%dndt = nan + this%dhdt = nan + this%ddbhdt = nan + this%dbdeaddt = nan + + ! FIRE + this%fraction_crown_burned = nan + this%cambial_mort = nan + this%crownfire_mort = nan + this%fire_mort = nan + + end subroutine nan_values + + !:.........................................................................: + + subroutine zero_cohort(this) + ! + ! DESCRIPTION: + ! Zero variables that need to be accounted for if this cohort is altered + ! before they are defined. + ! + ! ARGUMENTS + type (fates_cohort_type), intent(inout) :: this + + !this%l2fr + !this%pft + !this%n + !this%dbh + !this%coage + !this%hite + !this%indexnumber + !this%canopy_layer + !this%canopy_layer_yesterday + !this%crowndamage + this%g_sb_laweight = 0._r8 + !this%canopy_trim + this%leaf_cost = 0._r8 + this%excl_weight = 0._r8 + this%prom_weight = 0._r8 + this%nv = 0 + this%status_coh = 0 + !this%c_area + !this%treelai + this%treesai = 0._r8 + this%size_class = 1 + this%coage_class = 1 + !this%size_by_pft_class + !this%coage_by_pft_class + this%size_class_lasttimestep = 0 + this%gpp_tstep = 0._r8 + this%gpp_acc = 0._r8 + this%gpp_acc_hold = 0._r8 + this%npp_tstep = 0._r8 + this%npp_acc = 0._r8 + this%npp_acc_hold = 0._r8 + this%resp_tstep = 0._r8 + this%resp_acc = 0._r8 + this%resp_acc_hold = 0._r8 + this%c13disc_clm = 0._r8 + this%c13disc_acc = 0._r8 + !this%vcmax25top + !this%jmax25top + !this%tpu25top + !this%kp25top + this%ts_net_uptake(:) = 0._r8 + this%year_net_uptake(:) = 999._r8 ! this needs to be 999, or trimming of new cohorts will break. + !this%cnp_limiter + !this%cx_int + !this%ema_dcxdt + !this%cx0 + !this%nc_repro + !this%pc_repro + this%daily_nh4_uptake = 0._r8 + this%daily_no3_uptake = 0._r8 + + ! fixation is also integrated over the course of the day and must be + ! zeroed upon creation and after plant resource allocation + this%sym_nfix_daily = 0._r8 + !this%daily_n_gain + this%daily_p_gain = 0._r8 + + ! daily nutrient fluxes are INTEGRATED over the course of the day. + ! These variables MUST be zerod upon creation AND after allocation. + ! These variables exist in carbon-only mode but are not used. + this%daily_c_efflux = 0._r8 + this%daily_n_efflux = 0._r8 + this%daily_p_efflux = 0._r8 + + ! initialize these as negative + this%daily_n_demand = -9._r8 + this%daily_p_demand = -9._r8 + this%seed_prod = 0._r8 + this%rdark = 0._r8 + this%resp_g_tstep = 0._r8 + this%resp_m = 0._r8 + this%resp_m_unreduced = 0._r8 + this%resp_excess = 0._r8 + this%livestem_mr = 0._r8 + this%livecroot_mr = 0._r8 + this%froot_mr = 0._r8 + !this%branch_frac + this%dmort = 0._r8 + this%lmort_direct = 0._r8 + this%lmort_collateral = 0._r8 + this%lmort_infra = 0._r8 + this%l_degrad = 0._r8 + this%fraction_crown_burned = 0._r8 + this%cambial_mort = 0._r8 + this%crownfire_mort = 0._r8 + this%fire_mort = 0._r8 + + end subroutine zero_cohort + + !:.........................................................................: + + function CanUpperUnder(this) result(can_position) + ! + ! DESCRIPTION: + ! This simple function is used to determine if a cohort's crown position + ! is in the upper portion (ie the canopy) or the understory. This + ! differentiation is only used for diagnostic purposes. Functionally, + ! the model uses the canopy layer position, which may have more than + ! two layers at any given time. Utlimately, every plant that is not in + ! the top layer (canopy), is considered understory. + ! + + ! ARGUMENTS: + type(fates_cohort_type) :: this ! current cohort of interest + integer :: can_position ! canopy position + + if (this%canopy_layer == 1)then + can_position = ican_upper + else + can_position = ican_ustory + end if + + end function CanUpperUnder + + !:.........................................................................: + + subroutine dump(this) + ! + ! DESCRIPTION: + ! Print out attributes of a cohort + ! + + ! ARGUMENTS: + type(fates_cohort_type), intent(in), target :: this + + write(fates_log(),*) '----------------------------------------' + write(fates_log(),*) ' Dumping Cohort Information ' + write(fates_log(),*) '----------------------------------------' + write(fates_log(),*) 'co%pft = ', this%pft + write(fates_log(),*) 'co%n = ', this%n + write(fates_log(),*) 'co%dbh = ', this%dbh + write(fates_log(),*) 'co%hite = ', this%hite + write(fates_log(),*) 'co%crowndamage = ', this%crowndamage + write(fates_log(),*) 'co%coage = ', this%coage + write(fates_log(),*) 'co%l2fr = ', this%l2fr + write(fates_log(),*) 'leaf carbon = ', this%prt%GetState(leaf_organ,carbon12_element) + write(fates_log(),*) 'fineroot carbon = ', this%prt%GetState(fnrt_organ,carbon12_element) + write(fates_log(),*) 'sapwood carbon = ', this%prt%GetState(sapw_organ,carbon12_element) + write(fates_log(),*) 'structural (dead) carbon = ', this%prt%GetState(struct_organ,carbon12_element) + write(fates_log(),*) 'storage carbon = ', this%prt%GetState(store_organ,carbon12_element) + write(fates_log(),*) 'reproductive carbon = ', this%prt%GetState(repro_organ,carbon12_element) + write(fates_log(),*) 'co%g_sb_laweight = ', this%g_sb_laweight + write(fates_log(),*) 'co%leaf_cost = ', this%leaf_cost + write(fates_log(),*) 'co%canopy_layer = ', this%canopy_layer + write(fates_log(),*) 'co%canopy_layer_yesterday = ', this%canopy_layer_yesterday + write(fates_log(),*) 'co%nv = ', this%nv + write(fates_log(),*) 'co%status_coh = ', this%status_coh + write(fates_log(),*) 'co%canopy_trim = ', this%canopy_trim + write(fates_log(),*) 'co%excl_weight = ', this%excl_weight + write(fates_log(),*) 'co%prom_weight = ', this%prom_weight + write(fates_log(),*) 'co%size_class = ', this%size_class + write(fates_log(),*) 'co%size_by_pft_class = ', this%size_by_pft_class + write(fates_log(),*) 'co%coage_class = ', this%coage_class + write(fates_log(),*) 'co%coage_by_pft_class = ', this%coage_by_pft_class + write(fates_log(),*) 'co%gpp_acc_hold = ', this%gpp_acc_hold + write(fates_log(),*) 'co%gpp_acc = ', this%gpp_acc + write(fates_log(),*) 'co%gpp_tstep = ', this%gpp_tstep + write(fates_log(),*) 'co%npp_acc_hold = ', this%npp_acc_hold + write(fates_log(),*) 'co%npp_tstep = ', this%npp_tstep + write(fates_log(),*) 'co%npp_acc = ', this%npp_acc + write(fates_log(),*) 'co%resp_tstep = ', this%resp_tstep + write(fates_log(),*) 'co%resp_acc = ', this%resp_acc + write(fates_log(),*) 'co%resp_acc_hold = ', this%resp_acc_hold + write(fates_log(),*) 'co%rdark = ', this%rdark + write(fates_log(),*) 'co%resp_m = ', this%resp_m + write(fates_log(),*) 'co%resp_g_tstep = ', this%resp_g_tstep + write(fates_log(),*) 'co%livestem_mr = ', this%livestem_mr + write(fates_log(),*) 'co%livecroot_mr = ', this%livecroot_mr + write(fates_log(),*) 'co%froot_mr = ', this%froot_mr + write(fates_log(),*) 'co%dgmort = ', this%dgmort + write(fates_log(),*) 'co%treelai = ', this%treelai + write(fates_log(),*) 'co%treesai = ', this%treesai + write(fates_log(),*) 'co%c_area = ', this%c_area + write(fates_log(),*) 'co%cmort = ', this%cmort + write(fates_log(),*) 'co%bmort = ', this%bmort + write(fates_log(),*) 'co%smort = ', this%smort + write(fates_log(),*) 'co%asmort = ', this%asmort + write(fates_log(),*) 'co%dgmort = ', this%dgmort + write(fates_log(),*) 'co%hmort = ', this%hmort + write(fates_log(),*) 'co%frmort = ', this%frmort + write(fates_log(),*) 'co%asmort = ', this%asmort + write(fates_log(),*) 'co%lmort_direct = ', this%lmort_direct + write(fates_log(),*) 'co%lmort_collateral = ', this%lmort_collateral + write(fates_log(),*) 'co%lmort_infra = ', this%lmort_infra + write(fates_log(),*) 'co%isnew = ', this%isnew + write(fates_log(),*) 'co%dndt = ', this%dndt + write(fates_log(),*) 'co%dhdt = ', this%dhdt + write(fates_log(),*) 'co%ddbhdt = ', this%ddbhdt + write(fates_log(),*) 'co%dbdeaddt = ', this%dbdeaddt + write(fates_log(),*) 'co%fraction_crown_burned = ', this%fraction_crown_burned + write(fates_log(),*) 'co%fire_mort = ', this%fire_mort + write(fates_log(),*) 'co%crownfire_mort = ', this%crownfire_mort + write(fates_log(),*) 'co%cambial_mort = ', this%cambial_mort + write(fates_log(),*) 'co%size_class = ', this%size_class + write(fates_log(),*) 'co%size_by_pft_class = ', this%size_by_pft_class + + if (associated(this%co_hydr)) call dump_cohort_hydr(this) + + write(fates_log(),*) '----------------------------------------' + + return + + end subroutine dump + + !:...........................................................................: + +end module FatesCohortMod \ No newline at end of file diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index ea413ca901..d865187294 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -35,6 +35,13 @@ module FatesConstantsMod integer, parameter, public :: primaryforest = 1 integer, parameter, public :: secondaryforest = 2 + + integer, parameter, public :: leaves_on = 2 ! Flag specifying that a deciduous plant has leaves + ! and should be allocating to them as well + integer, parameter, public :: leaves_off = 1 ! Flag specifying that a deciduous plant has dropped + ! its leaves and should not be trying to allocate + ! towards any growth. + ! Bareground label for no competition mode integer, parameter, public :: nocomp_bareground = 0 diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index a0304f2935..58156dd3fb 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -65,6 +65,7 @@ module FatesInventoryInitMod use FatesRunningMeanMod, only : ema_lpa use PRTGenericMod, only : StorageNutrientTarget use FatesConstantsMod, only : fates_unset_int + use EDCanopyStructureMod, only : canopy_summarization, canopy_structure implicit none private @@ -94,7 +95,7 @@ module FatesInventoryInitMod ! defined in model memory and a physical ! site listed in the file - logical, parameter :: do_inventory_out = .false. + logical, parameter :: do_inventory_out = .true. public :: initialize_sites_by_inventory @@ -141,6 +142,7 @@ subroutine initialize_sites_by_inventory(nsites,sites,bc_in) real(r8) :: area_init ! dummy value for creating a patch integer :: s ! site index integer :: ipa ! patch index + integer :: iv, ft, ic integer :: total_cohorts ! cohort counter for error checking integer, allocatable :: inv_format_list(:) ! list of format specs character(len=path_strlen), allocatable :: inv_css_list(:) ! list of css file names @@ -518,6 +520,7 @@ subroutine initialize_sites_by_inventory(nsites,sites,bc_in) ! Report Basal Area (as a check on if things were read in) ! ---------------------------------------------------------------------------------------- + !call canopy_structure(sites(s),bc_in(s)) basal_area_postf = 0.0_r8 currentpatch => sites(s)%youngest_patch do while(associated(currentpatch)) @@ -527,9 +530,12 @@ subroutine initialize_sites_by_inventory(nsites,sites,bc_in) currentcohort%n*0.25*((currentcohort%dbh/100.0_r8)**2.0_r8)*pi_const currentcohort => currentcohort%shorter end do + currentPatch => currentpatch%older enddo + + write(fates_log(),*) '-------------------------------------------------------' write(fates_log(),*) 'Basal Area from inventory, AFTER fusion' write(fates_log(),*) 'Lat: ',sites(s)%lat,' Lon: ',sites(s)%lon @@ -538,11 +544,14 @@ subroutine initialize_sites_by_inventory(nsites,sites,bc_in) ! If this is flagged as true, the post-fusion inventory will be written to file ! in the run directory. + if(do_inventory_out)then call write_inventory_type1(sites(s)) end if end do + !call canopy_summarization(nsites, sites, bc_in) + deallocate(inv_format_list, inv_pss_list, inv_css_list, inv_lat_list, inv_lon_list) return diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 91c685fa22..9f34e39e9c 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -48,11 +48,8 @@ module PRTAllometricCarbonMod use FatesConstantsMod , only : nearzero use FatesConstantsMod , only : itrue use FatesConstantsMod , only : years_per_day - use PRTParametersMod , only : prt_params - - use EDTypesMod , only : leaves_on - use EDTypesMod , only : leaves_off + use FatesConstantsMod , only : leaves_on, leaves_off implicit none private From 4ef09488283150500953837b068e95b7219d9eca Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 3 Apr 2023 15:23:45 -0700 Subject: [PATCH 599/852] Add long names as comment to EDParamsMod --- main/EDParamsMod.F90 | 51 ++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 40edc6a0b8..bfbbcc27e3 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -38,39 +38,38 @@ module EDParamsMod ! 1=non-acclimating, 2=Kumarathunge et al., 2019 real(r8),protected, public :: fates_mortality_disturbance_fraction ! the fraction of canopy mortality that results in disturbance - real(r8),protected, public :: ED_val_comp_excln - real(r8),protected, public :: ED_val_vai_top_bin_width - real(r8),protected, public :: ED_val_vai_width_increase_factor - real(r8),protected, public :: ED_val_nignitions - real(r8),protected, public :: ED_val_understorey_death - real(r8),protected, public :: ED_val_cwd_fcel - real(r8),protected, public :: ED_val_cwd_flig - real(r8),protected, public :: maintresp_nonleaf_baserate - real(r8),protected, public :: ED_val_phen_drought_threshold - real(r8),protected, public :: ED_val_phen_doff_time - real(r8),protected, public :: ED_val_phen_a - real(r8),protected, public :: ED_val_phen_b - real(r8),protected, public :: ED_val_phen_c - real(r8),protected, public :: ED_val_phen_chiltemp - real(r8),protected, public :: ED_val_phen_mindayson - real(r8),protected, public :: ED_val_phen_ncolddayslim - real(r8),protected, public :: ED_val_phen_coldtemp - real(r8),protected, public :: ED_val_cohort_size_fusion_tol - real(r8),protected, public :: ED_val_cohort_age_fusion_tol - real(r8),protected, public :: ED_val_patch_fusion_tol - 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 + real(r8),protected, public :: ED_val_comp_excln ! weighting factor for canopy layer exclusion and promotion + real(r8),protected, public :: ED_val_vai_top_bin_width ! width in VAI units of uppermost leaf+stem layer scattering element + real(r8),protected, public :: ED_val_vai_width_increase_factor ! factor by which each leaf+stem scattering element increases in VAI width + real(r8),protected, public :: ED_val_nignitions ! number of annual ignitions per square km + real(r8),protected, public :: ED_val_understorey_death ! fraction of plants in understorey cohort impacted by overstorey tree-fall + real(r8),protected, public :: ED_val_cwd_fcel ! Cellulose fraction for CWD + real(r8),protected, public :: ED_val_cwd_flig ! Lignin fraction of coarse woody debris + real(r8),protected, public :: maintresp_nonleaf_baserate ! Base maintenance respiration rate for plant tissues + real(r8),protected, public :: ED_val_phen_drought_threshold ! threshold for drought phenology + real(r8),protected, public :: ED_val_phen_doff_time ! day threshold compared against days since leaves became off-allometry + real(r8),protected, public :: ED_val_phen_a ! GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd) + real(r8),protected, public :: ED_val_phen_b ! GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd) + real(r8),protected, public :: ED_val_phen_c ! GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd) + real(r8),protected, public :: ED_val_phen_chiltemp ! chilling day counting threshold for vegetation + real(r8),protected, public :: ED_val_phen_mindayson ! day threshold compared against days since leaves became on-allometry + real(r8),protected, public :: ED_val_phen_ncolddayslim ! day threshold exceedance for temperature leaf-drop + real(r8),protected, public :: ED_val_phen_coldtemp ! vegetation temperature exceedance that flags a cold-day for leaf-drop + real(r8),protected, public :: ED_val_cohort_size_fusion_tol ! minimum fraction in difference in dbh between cohorts + real(r8),protected, public :: ED_val_cohort_age_fusion_tol ! minimum fraction in differece in cohort age between cohorts + 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 logical,protected, public :: active_crown_fire ! flag, 1=active crown fire 0=no active crown fire character(len=param_string_length),parameter :: fates_name_active_crown_fire = "fates_fire_active_crown_fire" - real(r8), protected, public :: cg_strikes ! fraction of cloud to ground lightning strikes (0-1) character(len=param_string_length),parameter :: fates_name_cg_strikes="fates_fire_cg_strikes" ! empirical curvature parameters for ac, aj photosynthesis co-limitation, c3 and c4 plants respectively - real(r8),protected,public :: theta_cj_c3 - real(r8),protected,public :: theta_cj_c4 + real(r8),protected,public :: theta_cj_c3 ! Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants + real(r8),protected,public :: theta_cj_c4 ! Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants 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) @@ -78,7 +77,7 @@ module EDParamsMod ! 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) - real(r8),protected,public :: dev_arbitrary + real(r8),protected,public :: dev_arbitrary ! Unassociated free parameter that developers can use for testing arbitrary new hypotheses character(len=param_string_length),parameter,public :: name_dev_arbitrary = "fates_dev_arbitrary" ! parameters whose size is defined in the parameter file From cc20604db54157b6c9e96434561637eaae6534eb Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 3 Apr 2023 15:43:00 -0700 Subject: [PATCH 600/852] Add parameter long names to EDPftvarcon.F90 --- main/EDPftvarcon.F90 | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 96c3fddf93..faf0e78bb7 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -87,31 +87,31 @@ module EDPftvarcon real(r8), allocatable :: maintresp_leaf_ryan1991_baserate(:) ! leaf maintenance respiration per Ryan et al 1991 real(r8), allocatable :: bmort(:) - real(r8), allocatable :: mort_ip_size_senescence(:) ! inflection point of dbh dependent senescence - real(r8), allocatable :: mort_r_size_senescence(:) ! rate of change in mortality with dbh - real(r8), allocatable :: mort_ip_age_senescence(:) ! inflection point of age dependent senescence - real(r8), allocatable :: mort_r_age_senescence(:) ! rate of change in mortality with age - real(r8), allocatable :: mort_scalar_coldstress(:) - real(r8), allocatable :: mort_scalar_cstarvation(:) - real(r8), allocatable :: mort_scalar_hydrfailure(:) - real(r8), allocatable :: hf_sm_threshold(:) - real(r8), allocatable :: hf_flc_threshold(:) - real(r8), allocatable :: vcmaxha(:) - real(r8), allocatable :: jmaxha(:) - real(r8), allocatable :: vcmaxhd(:) - real(r8), allocatable :: jmaxhd(:) - real(r8), allocatable :: vcmaxse(:) - real(r8), allocatable :: jmaxse(:) + real(r8), allocatable :: mort_ip_size_senescence(:) ! inflection point of dbh dependent senescence + real(r8), allocatable :: mort_r_size_senescence(:) ! rate of change in mortality with dbh + real(r8), allocatable :: mort_ip_age_senescence(:) ! inflection point of age dependent senescence + real(r8), allocatable :: mort_r_age_senescence(:) ! rate of change in mortality with age + real(r8), allocatable :: mort_scalar_coldstress(:) ! maximum mortality rate from cold stress + real(r8), allocatable :: mort_scalar_cstarvation(:) ! maximum mortality rate from carbon starvation + real(r8), allocatable :: mort_scalar_hydrfailure(:) ! maximum mortality rate from hydraulic failure + real(r8), allocatable :: hf_sm_threshold(:) ! soil moisture (btran units) at which drought mortality begins for non-hydraulic model + real(r8), allocatable :: hf_flc_threshold(:) ! plant fractional loss of conductivity at which drought mortality begins for hydraulic model + real(r8), allocatable :: vcmaxha(:) ! activation energy for vcmax + real(r8), allocatable :: jmaxha(:) ! activation energy for jmax + real(r8), allocatable :: vcmaxhd(:) ! deactivation energy for vcmax + real(r8), allocatable :: jmaxhd(:) ! deactivation energy for jmax + real(r8), allocatable :: vcmaxse(:) ! entropy term for vcmax + real(r8), allocatable :: jmaxse(:) ! entropy term for jmax real(r8), allocatable :: germination_rate(:) ! Fraction of seed mass germinating per year (yr-1) real(r8), allocatable :: seed_decay_rate(:) ! Fraction of seed mass (both germinated and ! ungerminated), decaying per year (yr-1) real(r8), allocatable :: trim_limit(:) ! Limit to reductions in leaf area w stress (m2/m2) real(r8), allocatable :: trim_inc(:) ! Incremental change in trimming function (m2/m2) - real(r8), allocatable :: rhol(:, :) - real(r8), allocatable :: rhos(:, :) - real(r8), allocatable :: taul(:, :) - real(r8), allocatable :: taus(:, :) + real(r8), allocatable :: rhol(:, :) ! Leaf reflectance; second dim: 1 = vis, 2 = nir + real(r8), allocatable :: rhos(:, :) ! Stem reflectance; second dim: 1 = vis, 2 = nir + real(r8), allocatable :: taul(:, :) ! Leaf transmittance; second dim: 1 = vis, 2 = nir + real(r8), allocatable :: taus(:, :) ! Stem transmittance; second dim: 1 = vis, 2 = nir ! Fire Parameters (No PFT vector capabilities in their own routines) ! See fire/SFParamsMod.F90 for bulk of fire parameters From 010d95a15451dddc07e0497bcebe2fa1b0c42731 Mon Sep 17 00:00:00 2001 From: Marcos Longo Date: Mon, 3 Apr 2023 17:17:30 -0700 Subject: [PATCH 601/852] Multiple updates following PR revision. 1. Elongation factors are now passed to allometric equations 2. Flag for partial shedding is now leaf_shedding 3. "continue" statement replaced with nested "if" statement. 4. Revised comments to clarify steps. 5. Updated default parameter values for drought phenology thresholds to be given in pressure head units instead of soil water content. --- biogeochem/EDCanopyStructureMod.F90 | 2 +- biogeochem/EDCohortDynamicsMod.F90 | 66 +++-- biogeochem/EDMortalityFunctionsMod.F90 | 6 +- biogeochem/EDPhysiologyMod.F90 | 271 +++++++++++---------- biogeochem/FatesAllometryMod.F90 | 146 +++++++---- biogeophys/FatesPlantHydraulicsMod.F90 | 6 +- biogeophys/FatesPlantRespPhotosynthMod.F90 | 5 +- main/EDInitMod.F90 | 125 +++++----- main/EDTypesMod.F90 | 8 +- main/FatesInventoryInitMod.F90 | 96 ++++---- parameter_files/fates_params_default.cdl | 8 +- parteh/PRTAllometricCNPMod.F90 | 92 +++---- parteh/PRTAllometricCarbonMod.F90 | 85 +++---- parteh/PRTGenericMod.F90 | 10 +- parteh/PRTParamsFATESMod.F90 | 12 +- 15 files changed, 476 insertions(+), 462 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 094a105c20..62558b56b3 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -2189,7 +2189,7 @@ subroutine UpdateCohortLAI(currentCohort, canopy_layer_tlai, total_canopy_area) if (hlm_use_sp .eq. ifalse) then currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%crowndamage, & - currentCohort%canopy_trim, & + currentCohort%canopy_trim, currentCohort%efstem_coh, & currentCohort%c_area, currentCohort%n, currentCohort%canopy_layer, & canopy_layer_tlai, currentCohort%treelai , & currentCohort%vcmax25top,4) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 28e0ac6ff5..2d9154dd64 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -311,7 +311,7 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & if(hlm_use_sp.eq.ifalse)then new_cohort%treesai = tree_sai(new_cohort%pft, new_cohort%dbh, & - new_cohort%crowndamage, new_cohort%canopy_trim, & + new_cohort%crowndamage, new_cohort%canopy_trim, new_cohort%efstem_coh, & new_cohort%c_area, new_cohort%n, new_cohort%canopy_layer, & patchptr%canopy_layer_tlai, new_cohort%treelai,new_cohort%vcmax25top,2 ) end if @@ -1356,6 +1356,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) call ForceDBH( currentCohort%pft, currentCohort%crowndamage, & currentCohort%canopy_trim, & + currentCohort%efleaf_coh, currentCohort%efstem_coh, & currentCohort%dbh, currentCohort%hite, & bdead = currentCohort%prt%GetState(struct_organ,carbon12_element)) @@ -1394,6 +1395,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) if( prt_params%woody(currentCohort%pft) == itrue ) then call ForceDBH( currentCohort%pft, currentCohort%crowndamage, & currentCohort%canopy_trim, & + currentCohort%efleaf_coh, currentCohort%efstem_coh, & currentCohort%dbh, currentCohort%hite, & bdead = currentCohort%prt%GetState(struct_organ,carbon12_element)) @@ -2158,11 +2160,15 @@ subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) real(r8) :: hite_out real(r8) :: leaf_c real(r8) :: crown_reduction + real(r8) :: elongf_leaf + real(r8) :: elongf_stem dbh = currentCohort%dbh ipft = currentCohort%pft icrowndamage = currentCohort%crowndamage canopy_trim = currentCohort%canopy_trim + elongf_leaf = currentCohort%efleaf_coh + elongf_stem = currentCohort%efstem_coh delta_dbh = 0._r8 delta_hite = 0._r8 @@ -2171,14 +2177,16 @@ subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) struct_c = currentCohort%prt%GetState(struct_organ, carbon12_element) - ! Target sapwood biomass according to allometry and trimming [kgC] - call bsap_allom(dbh,ipft,icrowndamage,canopy_trim,sapw_area,target_sapw_c) + ! Target sapwood biomass according to allometry, trimming and phenology [kgC] + call bsap_allom(dbh,ipft,icrowndamage,canopy_trim, elongf_stem, sapw_area,target_sapw_c) - ! Target total above ground biomass in woody/fibrous tissues [kgC] - call bagw_allom(dbh,ipft, icrowndamage,target_agw_c) + ! Target total above ground biomass in woody/fibrous tissues + ! according to allometry, trimming and phenology [kgC] + call bagw_allom(dbh,ipft, icrowndamage, elongf_stem, target_agw_c) - ! Target total below ground biomass in woody/fibrous tissues [kgC] - call bbgw_allom(dbh,ipft,target_bgw_c) + ! Target total below ground biomass in woody/fibrous tissues + ! according to allometry, trimming and phenology [kgC] + call bbgw_allom(dbh,ipft, elongf_stem, target_bgw_c) ! Target total dead (structrual) biomass [kgC] call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, ipft, target_struct_c) @@ -2191,7 +2199,8 @@ subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) if( (struct_c - target_struct_c ) > calloc_abs_error ) then - call ForceDBH( ipft,icrowndamage,canopy_trim, dbh, hite_out, bdead=struct_c) + call ForceDBH( ipft,icrowndamage,canopy_trim, elongf_leaf, elongf_stem, & + dbh, hite_out, bdead=struct_c) delta_dbh = dbh - currentCohort%dbh delta_hite = hite_out - currentCohort%hite @@ -2204,11 +2213,12 @@ subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) ! This returns the sum of leaf carbon over all (age) bins leaf_c = currentCohort%prt%GetState(leaf_organ, carbon12_element) - ! Target leaf biomass according to allometry and trimming - call bleaf(dbh,ipft,icrowndamage, canopy_trim,target_leaf_c) + ! Target leaf biomass according to allometry, trimming and phenology + call bleaf(dbh,ipft,icrowndamage, canopy_trim, elongf_leaf, target_leaf_c) if( ( leaf_c - target_leaf_c ) > calloc_abs_error ) then - call ForceDBH( ipft, icrowndamage, canopy_trim, dbh, hite_out, bl=leaf_c ) + call ForceDBH( ipft, icrowndamage, canopy_trim, elongf_leaf, elongf_stem, & + dbh, hite_out, bl=leaf_c ) delta_dbh = dbh - currentCohort%dbh delta_hite = hite_out - currentCohort%hite currentCohort%dbh = dbh @@ -2268,7 +2278,10 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) associate(dbh => ccohort%dbh, & ipft => ccohort%pft, & - canopy_trim => ccohort%canopy_trim) + canopy_trim => ccohort%canopy_trim, & + elongf_leaf => ccohort%efleaf_coh, & + elongf_fnrt => ccohort%effnrt_coh, & + elongf_stem => ccohort%efstem_coh) ! If we are currently undamaged, no recovery ! necessary, do nothing and return a null pointer @@ -2291,24 +2304,23 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) ! resources (C,N,P) are required to recover the plant to the target ! pool sizes of the next (less) damage class - ! Target sapwood biomass according to allometry and trimming [kgC] - call bsap_allom(dbh,ipft, ccohort%crowndamage-1, canopy_trim,sapw_area,target_sapw_c) - ! Target total above ground biomass in woody/fibrous tissues [kgC] - call bagw_allom(dbh,ipft, ccohort%crowndamage-1, target_agw_c) - ! Target total below ground biomass in woody/fibrous tissues [kgC] - call bbgw_allom(dbh,ipft,target_bgw_c) + ! Target sapwood biomass according to allometry, trimming and phenology [kgC] + call bsap_allom(dbh,ipft, ccohort%crowndamage-1, canopy_trim, elongf_stem, & + sapw_area,target_sapw_c) + ! Target total above ground biomass in woody/fibrous tissues + ! according to allometry, trimming and phenology [kgC] + call bagw_allom(dbh,ipft, ccohort%crowndamage-1, elongf_stem, target_agw_c) + ! Target total below ground biomass in woody/fibrous tissues + ! according to allometry, trimming and phenology [kgC] + call bbgw_allom(dbh,ipft, elongf_stem, target_bgw_c) ! Target total dead (structrual) biomass [kgC] call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, ipft, target_struct_c) - ! Target fine-root biomass and deriv. according to allometry and trimming [kgC, kgC/cm] - call bfineroot(dbh,ipft,canopy_trim,ccohort%l2fr,target_fnrt_c) - ! Target storage carbon [kgC,kgC/cm] + ! Target fine-root biomass according to allometry, trimming and phenology [kgC] + call bfineroot(dbh,ipft,canopy_trim,ccohort%l2fr, elongf_fnrt, target_fnrt_c) + ! Target storage carbon [kgC] call bstore_allom(dbh,ipft,ccohort%crowndamage-1, canopy_trim,target_store_c) - ! Target leaf biomass according to allometry and trimming - if(ccohort%status_coh==leaves_on) then - call bleaf(dbh,ipft,ccohort%crowndamage-1, canopy_trim,target_leaf_c) - else - target_leaf_c = 0._r8 - end if + ! Target leaf biomass according to allometry, trimming and phenology [kgC] + call bleaf(dbh,ipft,ccohort%crowndamage-1, canopy_trim, elongf_leaf, target_leaf_c) ! We will be taking the number of recovering plants ! based on minimum of available resources for C/N/P (initialize high) diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index 388d021003..e3baea2935 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -166,7 +166,11 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmor ! Carbon Starvation induced mortality. if ( cohort_in%dbh > 0._r8 ) then - call bleaf(cohort_in%dbh,cohort_in%pft,cohort_in%crowndamage,cohort_in%canopy_trim,target_leaf_c) + ! We compare storage with leaf biomass if plant were fully flushed, otherwise + ! mortality would be underestimated for plants that lost all leaves and have no + ! storage to flush new ones. + call bleaf(cohort_in%dbh,cohort_in%pft,cohort_in%crowndamage,cohort_in%canopy_trim, & + 1.0_r8, target_leaf_c) store_c = cohort_in%prt%GetState(store_organ,carbon12_element) call storage_fraction_of_target(target_leaf_c, store_c, frac) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 58b0f84957..c97b4d8992 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -56,7 +56,7 @@ module EDPhysiologyMod use EDTypesMod , only : ed_site_type, ed_patch_type, ed_cohort_type use EDTypesMod , only : leaves_on use EDTypesMod , only : leaves_off - use EDTypesMod , only : leaves_pshed + use EDTypesMod , only : leaves_shedding use EDTypesMod , only : ihard_stress_decid use EDTypesMod , only : isemi_stress_decid use EDTypesMod , only : min_n_safemath @@ -637,6 +637,7 @@ subroutine trim_canopy( currentSite ) ! Save off the incoming trim initial_trim = currentCohort%canopy_trim + ! Add debug diagnstic output to determine which cohort if (debug) then write(fates_log(),*) 'Current cohort:', icohort @@ -648,7 +649,6 @@ subroutine trim_canopy( currentSite ) call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread,currentCohort%pft,& currentCohort%crowndamage, currentCohort%c_area) - leaf_c = currentCohort%prt%GetState(leaf_organ, carbon12_element) currentCohort%treelai = tree_lai(leaf_c, currentCohort%pft, currentCohort%c_area, & @@ -659,6 +659,7 @@ subroutine trim_canopy( currentSite ) currentCohort%treesai = tree_sai(currentCohort%pft, & currentCohort%dbh, currentCohort%crowndamage, & currentCohort%canopy_trim, & + currentCohort%efstem_coh, & currentCohort%c_area, currentCohort%n,currentCohort%canopy_layer,& currentPatch%canopy_layer_tlai, currentCohort%treelai, & currentCohort%vcmax25top,0 ) @@ -672,12 +673,14 @@ subroutine trim_canopy( currentSite ) call endrun(msg=errMsg(sourcefile, __LINE__)) endif + call bleaf(currentcohort%dbh,ipft,& - currentCohort%crowndamage, currentcohort%canopy_trim,tar_bl) + currentCohort%crowndamage, currentcohort%canopy_trim,currentCohort%efleaf_coh, tar_bl) if ( int(prt_params%allom_fmode(ipft)) .eq. 1 ) then ! only query fine root biomass if using a fine root allometric model that takes leaf trim into account - call bfineroot(currentcohort%dbh,ipft,currentcohort%canopy_trim,currentcohort%l2fr,tar_bfr) + call bfineroot(currentcohort%dbh,ipft,currentcohort%canopy_trim,currentcohort%l2fr, & + currentCohort%effnrt_coh, tar_bfr) bfr_per_bleaf = tar_bfr/tar_bl endif @@ -1229,7 +1232,21 @@ subroutine phenology( currentSite, bc_in ) - ! Find elongation factor by comparing the moisture with the thresholds. + !---~--- + ! Find elongation factors by comparing the moisture with the thresholds. For each + ! tissue --- leaves, fine roots, and stems (sapwood+heartwood) --- elongation factor + ! is the maximum fraction of biomass (relative to maximum biomass given allometry) + ! that can be allocated to each tissue due to phenology. In this select case, we + ! define the elongation factor based on the PFT-specific phenology strategy of this + ! each PFT. Options are evergreen, "hard deciduous", or semi-deciduous: + ! - Evergreen: elongation factors shall be 1 at all times (fully flushed tissues). + ! - "Hard-deciduous": elongation factors are either 0 (fully abscised tissues) or + ! 1 (fully flushed tissues) + ! - Semi-deciduous: elongation factors can be any value between 0 and 1 (including + ! 0 and 1). For example, if elongation factor for leaves of a cohort is 0.4, then + ! the leaf biomass will be capped at 40% of the biomass the cohort would have if + ! it were in well-watered conditions. + !---~--- case_drought_phen: select case (prt_params%stress_decid(ipft)) case (ihard_stress_decid) !---~--- @@ -1274,78 +1291,82 @@ subroutine phenology( currentSite, bc_in ) !---~--- - ! Revision of the conditions to simplify nested if and added an if/elseif/else - ! structure to ensure only up to one change occurs at any given time (ML 20211120). - drought_smoist_ifelse: if (model_day_int <= numWaterMem) then - ! Too early in the simulation. Do not change phenology status as we need to - ! populate the soil moisture memory. - continue - - elseif ( prolonged_off_period .and. ( .not. smoist_below_threshold ) ) then - ! LEAF ON: DROUGHT DECIDUOUS WETNESS - ! Here, we used a window of oppurtunity to determine if we are - ! close to the time when then leaves came on last year - ! The following conditions must be met - ! a) a year, plus or minus 1 month since we last had leaf-on? - ! b) Has there also been at least a nominaly short amount of "leaf-off"? - ! c) Is the soil moisture sufficiently high? - currentSite%dstatus(ipft) = phen_dstat_moiston ! set status to leaf-on - currentSite%dleafondate(ipft) = model_day_int ! save the model day we start flushing - currentSite%dndaysleafon(ipft) = 0 - currentSite%elong_factor(ipft) = 1. - - elseif ( last_flush_long_ago ) then - ! LEAF ON: DROUGHT DECIDUOUS TIME EXCEEDANCE - ! If we still haven't done budburst by end of window, then force it - - ! If the status is "phen_dstat_moistoff", it means this site currently has - ! leaves off due to actual moisture limitations. - ! So we trigger bud-burst at the end of the month since - ! last year's bud-burst. If this is imposed, then we set the new - ! status to indicate bud-burst was forced by timing - currentSite%dstatus(ipft) = phen_dstat_timeon ! force budburst! - currentSite%dleafondate(ipft) = model_day_int ! record leaf on date - currentSite%dndaysleafon(ipft) = 0 - currentSite%elong_factor(ipft) = 1. - - elseif ( exceed_min_off_period ) then - ! LEAF ON: DROUGHT DECIDUOUS EXCEEDED MINIMUM OFF PERIOD - ! Leaves were off due to time, not really moisture, so we allow them to - ! flush again as soon as they exceed a minimum off time - ! This typically occurs in a perennially wet system. - currentSite%dstatus(ipft) = phen_dstat_timeon ! force budburst! - currentSite%dleafondate(ipft) = model_day_int ! record leaf on date - currentSite%dndaysleafon(ipft) = 0 - currentSite%elong_factor(ipft) = 1. - - elseif ( prolonged_on_period ) then - ! LEAF OFF: DROUGHT DECIDUOUS LIFESPAN - ! Are the leaves rouhgly at the end of their lives? If so, shed leaves - ! even if it is not dry. - currentSite%dstatus(ipft) = phen_dstat_timeoff !alter status of site to 'leaves off' - currentSite%dleafoffdate(ipft) = model_day_int !record leaf on date - currentSite%dndaysleafoff(ipft) = 0 - currentSite%elong_factor(ipft) = 0. - - elseif ( exceed_min_on_period .and. smoist_below_threshold ) then - ! LEAF OFF: DROUGHT DECIDUOUS DRYNESS - if the soil gets too dry, - ! and the leaves have already been on a while... - currentSite%dstatus(ipft) = phen_dstat_moistoff ! alter status of site to 'leaves off' - currentSite%dleafoffdate(ipft) = model_day_int ! record leaf on date - currentSite%dndaysleafoff(ipft) = 0 - currentSite%elong_factor(ipft) = 0. - end if drought_smoist_ifelse + ! Revision of the conditions, added an if/elseif/else structure to ensure only + ! up to one change occurs at any given time (ML 20211120) + !---~--- + past_spinup_ifelse: if (model_day_int > numWaterMem) then + drought_smoist_ifelse: if ( prolonged_off_period .and. & + ( .not. smoist_below_threshold ) ) then + ! LEAF ON: DROUGHT DECIDUOUS WETNESS + ! Here, we used a window of oppurtunity to determine if we are + ! close to the time when then leaves came on last year + ! The following conditions must be met + ! a) a year, plus or minus 1 month since we last had leaf-on? + ! b) Has there also been at least a nominaly short amount of "leaf-off"? + ! c) Is the soil moisture sufficiently high? + currentSite%dstatus(ipft) = phen_dstat_moiston ! set status to leaf-on + currentSite%dleafondate(ipft) = model_day_int ! save the model day we start flushing + currentSite%dndaysleafon(ipft) = 0 + currentSite%elong_factor(ipft) = 1. + + elseif ( last_flush_long_ago ) then + ! LEAF ON: DROUGHT DECIDUOUS TIME EXCEEDANCE + ! If we still haven't done budburst by end of window, then force it + + ! If the status is "phen_dstat_moistoff", it means this site currently has + ! leaves off due to actual moisture limitations. + ! So we trigger bud-burst at the end of the month since + ! last year's bud-burst. If this is imposed, then we set the new + ! status to indicate bud-burst was forced by timing + currentSite%dstatus(ipft) = phen_dstat_timeon ! force budburst! + currentSite%dleafondate(ipft) = model_day_int ! record leaf on date + currentSite%dndaysleafon(ipft) = 0 + currentSite%elong_factor(ipft) = 1. + + elseif ( exceed_min_off_period ) then + ! LEAF ON: DROUGHT DECIDUOUS EXCEEDED MINIMUM OFF PERIOD + ! Leaves were off due to time, not really moisture, so we allow them to + ! flush again as soon as they exceed a minimum off time + ! This typically occurs in a perennially wet system. + currentSite%dstatus(ipft) = phen_dstat_timeon ! force budburst! + currentSite%dleafondate(ipft) = model_day_int ! record leaf on date + currentSite%dndaysleafon(ipft) = 0 + currentSite%elong_factor(ipft) = 1. + + elseif ( prolonged_on_period ) then + ! LEAF OFF: DROUGHT DECIDUOUS LIFESPAN + ! Are the leaves rouhgly at the end of their lives? If so, shed leaves + ! even if it is not dry. + currentSite%dstatus(ipft) = phen_dstat_timeoff !alter status of site to 'leaves off' + currentSite%dleafoffdate(ipft) = model_day_int !record leaf on date + currentSite%dndaysleafoff(ipft) = 0 + currentSite%elong_factor(ipft) = 0. + + elseif ( exceed_min_on_period .and. smoist_below_threshold ) then + ! LEAF OFF: DROUGHT DECIDUOUS DRYNESS - if the soil gets too dry, + ! and the leaves have already been on a while... + currentSite%dstatus(ipft) = phen_dstat_moistoff ! alter status of site to 'leaves off' + currentSite%dleafoffdate(ipft) = model_day_int ! record leaf on date + currentSite%dndaysleafoff(ipft) = 0 + currentSite%elong_factor(ipft) = 0. + end if drought_smoist_ifelse + end if past_spinup_ifelse + !---~--- case (isemi_stress_decid) - !------ + !---~--- ! Semi-deciduous PFT, based on ED2. We compare the moisture with the lower ! and upper thresholds. If the moisture is in between the thresholds, we must ! also check whether or not the drought is developing or regressing. - !------ + !---~--- - ! First guess elongation factor + !---~--- + ! First guess elongation factor, solely based on rooting-zone moisture. + ! These values may be adjusted based on the time since last flushing and/or + ! abscising event. + !---~--- if (phen_drought_threshold >= 0.) then elongf_1st = elongf_min + (1.0_r8 - elongf_min ) * & ( mean_10day_liqvol - phen_drought_threshold ) / & @@ -1356,6 +1377,7 @@ subroutine phenology( currentSite, bc_in ) ( phen_moist_threshold - phen_drought_threshold ) end if elongf_1st = max(0.0_r8,min(1.0_r8,elongf_1st)) + !---~--- @@ -1371,7 +1393,7 @@ subroutine phenology( currentSite, bc_in ) ! Leaves have been flushing for longer than their time span. prolonged_on_period = all( [elongf_prev,elongf_1st] >= elongf_min ) .and. & ( currentSite%dndaysleafon(ipft) > pft_leaf_lifespan ) - ! It's been a long time since the + ! It's been a long time since the plants had flushed their leaves. last_flush_long_ago = all( [elongf_prev,elongf_1st] < elongf_min ) .and. & ( currentSite%dndaysleafon(ipft) > 365+dd_offon_toler ) !---~--- @@ -1561,11 +1583,11 @@ subroutine phenology_leafonoff(currentSite) ! A. Is this the time for DROUGHT LEAVES to switch to ON? is_flushing_time = any( currentSite%dstatus(ipft) == [phen_dstat_moiston,phen_dstat_timeon] ) .and. & ! Leaf flushing time (moisture or time) - any( currentCohort%status_coh == [leaves_off,leaves_pshed] ) + any( currentCohort%status_coh == [leaves_off,leaves_shedding] ) ! B. Is this the time for DROUGHT LEAVES to switch to OFF? ! This will be true when leaves are abscissing (partially or fully) due to moisture or time is_shedding_time = any( currentSite%dstatus(ipft) == [phen_dstat_moistoff,phen_dstat_timeoff,phen_dstat_pshed] ) .and. & - any( currentCohort%status_coh == [leaves_on,leaves_pshed] ) + any( currentCohort%status_coh == [leaves_on,leaves_shedding] ) else ! This PFT is not deciduous. is_flushing_time = .false. @@ -1579,33 +1601,29 @@ subroutine phenology_leafonoff(currentSite) ! PFTs, this value should be always 1.0. currentCohort%efleaf_coh = currentSite%elong_factor(ipft) - ! Find the effective "elongation factor" for fine roots and stems. The effective drop fraction is - ! a combination of the elongation factor (e) and the drop fraction (x), which will ensure - ! that the remaining tissue biomass will be exactly e when x=1, and exactly the original - ! biomass when x = 0. For leaves it is always assumed that the drop fraction is one. + ! Find the effective "elongation factor" for fine roots and stems. The effective elongation + ! factor is a combination of the PFT leaf elongation factor (efleaf_coh) and the tissue drop + ! fraction relative to leaves (xxxx_drop_fraction). When xxxx_drop_fraction is 0, the biomass + ! of tissue xxxx will not be impacted by phenology. If xxxx_drop_fraction is 1, the biomass + ! of tissue xxxx will be as impacted by phenology as leaf biomass. Intermediate values will + ! allow a more moderate impact of phenology in tissue xxxx relative to leaves. currentCohort%effnrt_coh = 1.0_r8 - (1.0_r8 - currentCohort%efleaf_coh ) * fnrt_drop_fraction currentCohort%efstem_coh = 1.0_r8 - (1.0_r8 - currentCohort%efleaf_coh ) * stem_drop_fraction - ! Find the target biomass for each tissue when tissues are fully flushed. + ! Find the target biomass for each tissue when accounting for elongation + ! factors. Note that the target works for both flushing and shedding leaves. call bleaf(currentCohort%dbh,currentCohort%pft,currentCohort%crowndamage, & - currentCohort%canopy_trim,target_leaf_c) + currentCohort%canopy_trim,currentCohort%efleaf_coh,target_leaf_c) call bfineroot(currentCohort%dbh,currentCohort%pft, & - currentCohort%canopy_trim,l2fr,target_fnrt_c) + currentCohort%canopy_trim,l2fr,currentCohort%effnrt_coh,target_fnrt_c) call bsap_allom(currentCohort%dbh,currentCohort%pft,currentCohort%crowndamage, & - currentCohort%canopy_trim,sapw_area,target_sapw_c) + currentCohort%canopy_trim,currentCohort%efstem_coh,sapw_area,target_sapw_c) call bagw_allom(currentCohort%dbh,currentCohort%pft,currentCohort%crowndamage,& - target_agw_c) - call bbgw_allom(currentCohort%dbh,currentCohort%pft,target_bgw_c) + currentCohort%efstem_coh,target_agw_c) + call bbgw_allom(currentCohort%dbh,currentCohort%pft,currentCohort%efstem_coh,target_bgw_c) call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, & currentCohort%pft, target_struct_c) - ! Correct the target biomass for each tissue when accounting for elongation - ! factors. Note that the target works for both flushing and shedding leaves. - target_leaf_c = currentCohort%efleaf_coh * target_leaf_c - target_fnrt_c = currentCohort%effnrt_coh * target_fnrt_c - target_sapw_c = currentCohort%efstem_coh * target_sapw_c - target_struct_c = currentCohort%efstem_coh * target_struct_c - ! A. This is time to switch to (COLD or DROUGHT) LEAF ON flush_block: if (is_flushing_time) then @@ -1660,7 +1678,7 @@ subroutine phenology_leafonoff(currentSite) shed_block: if (is_shedding_time) then if ( currentCohort%efleaf_coh > 0.0_r8 ) then ! Partial shedding - currentCohort%status_coh = leaves_pshed + currentCohort%status_coh = leaves_shedding else ! Complete abscission currentCohort%status_coh = leaves_off @@ -2211,7 +2229,6 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) type (ed_cohort_type) , pointer :: temp_cohort type (litter_type), pointer :: litt ! The litter object (carbon right now) type(site_massbal_type), pointer :: site_mass ! For accounting total in-out mass fluxes - integer :: cohortstatus integer :: el ! loop counter for element integer :: element_id ! element index consistent with definitions in PRTGenericMod integer :: iage ! age loop counter for leaf age bins @@ -2225,9 +2242,6 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) real(r8) :: c_bgw ! target Below ground biomass [kgC] real(r8) :: c_struct ! target Structural biomass [kgc] real(r8) :: c_store ! target Storage biomass [kgC] - real(r8) :: elongf_leaf ! leaf elongation factor [fraction] - real(r8) :: elongf_fnrt ! fine-root "elongation factor" [fraction] - real(r8) :: elongf_stem ! stem "elongation factor" [fraction] real(r8) :: m_leaf ! leaf mass (element agnostic) [kg] real(r8) :: m_fnrt ! fine-root mass (element agnostic) [kg] real(r8) :: m_sapw ! sapwood mass (element agnostic) [kg] @@ -2269,39 +2283,20 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) call h2d_allom(temp_cohort%hite,ft,temp_cohort%dbh) - - ! Initialize live pools - call bleaf(temp_cohort%dbh,ft,temp_cohort%crowndamage,& - temp_cohort%canopy_trim,c_leaf) - call bfineroot(temp_cohort%dbh,ft,temp_cohort%canopy_trim,temp_cohort%l2fr,c_fnrt) - call bsap_allom(temp_cohort%dbh,ft,temp_cohort%crowndamage, & - temp_cohort%canopy_trim,a_sapw, c_sapw) - call bagw_allom(temp_cohort%dbh,ft,temp_cohort%crowndamage, c_agw) - call bbgw_allom(temp_cohort%dbh,ft,c_bgw) - call bdead_allom(c_agw,c_bgw,c_sapw,ft,c_struct) - call bstore_allom(temp_cohort%dbh,ft, temp_cohort%crowndamage, & - temp_cohort%canopy_trim,c_store) - ! Default assumption is that leaves are on and fully flushed - cohortstatus = leaves_on - elongf_leaf = 1.0_r8 - elongf_fnrt = 1.0_r8 - elongf_stem = 1.0_r8 + temp_cohort%efleaf_coh = 1.0_r8 + temp_cohort%effnrt_coh = 1.0_r8 + temp_cohort%efstem_coh = 1.0_r8 + temp_cohort%status_coh = leaves_on ! But if the plant is seasonally (cold) deciduous, and the site status is flagged ! as "cold", then set the cohort's status to leaves_off, and remember the leaf biomass if ((prt_params%season_decid(ft) == itrue) .and. & (any(currentSite%cstatus == [phen_cstat_nevercold,phen_cstat_iscold]))) then - elongf_leaf = 0.0_r8 - elongf_fnrt = 1.0_r8 - fnrt_drop_fraction - elongf_stem = 1.0_r8 - stem_drop_fraction - - c_leaf = elongf_leaf * c_leaf - c_fnrt = elongf_fnrt * c_fnrt - c_sapw = elongf_stem * c_sapw - c_struct = elongf_stem * c_struct - - cohortstatus = leaves_off + temp_cohort%efleaf_coh = 0.0_r8 + temp_cohort%effnrt_coh = 1.0_r8 - fnrt_drop_fraction + temp_cohort%efstem_coh = 1.0_r8 - stem_drop_fraction + temp_cohort%status_coh = leaves_off endif @@ -2312,25 +2307,34 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) ! tissue biomass will be exactly e when x=1, and exactly the original biomass when x = 0. select case (prt_params%stress_decid(ft)) case (ihard_stress_decid,isemi_stress_decid) - elongf_leaf = currentSite%elong_factor(ft) - elongf_fnrt = 1.0_r8 - (1.0_r8 - elongf_leaf ) * fnrt_drop_fraction - elongf_stem = 1.0_r8 - (1.0_r8 - elongf_leaf ) * stem_drop_fraction - - c_leaf = elongf_leaf * c_leaf - c_fnrt = elongf_fnrt * c_fnrt - c_sapw = elongf_stem * c_sapw - c_struct = elongf_stem * c_struct + temp_cohort%efleaf_coh = currentSite%elong_factor(ft) + temp_cohort%effnrt_coh = 1.0_r8 - (1.0_r8 - temp_cohort%efleaf_coh ) * fnrt_drop_fraction + temp_cohort%efstem_coh = 1.0_r8 - (1.0_r8 - temp_cohort%efleaf_coh ) * stem_drop_fraction ! For the initial state, we always assume that leaves are flushing (instead of partially abscissing) ! whenever the elongation factor is non-zero. If the elongation factor is zero, then leaves are in ! the "off" state. - if ( elongf_leaf > 0.0_r8 ) then - cohortstatus = leaves_on + if ( temp_cohort%efleaf_coh > 0.0_r8 ) then + temp_cohort%status_coh = leaves_on else - cohortstatus = leaves_off + temp_cohort%status_coh = leaves_off end if end select + + ! Initialize live pools + call bleaf(temp_cohort%dbh,ft,temp_cohort%crowndamage,& + temp_cohort%canopy_trim, temp_cohort%efleaf_coh, c_leaf) + call bfineroot(temp_cohort%dbh,ft,temp_cohort%canopy_trim,temp_cohort%l2fr, & + temp_cohort%effnrt_coh, c_fnrt) + call bsap_allom(temp_cohort%dbh,ft,temp_cohort%crowndamage, & + temp_cohort%canopy_trim, temp_cohort%efstem_coh, a_sapw, c_sapw) + call bagw_allom(temp_cohort%dbh,ft,temp_cohort%crowndamage, temp_cohort%efstem_coh, c_agw) + call bbgw_allom(temp_cohort%dbh,ft, temp_cohort%efstem_coh, c_bgw) + call bdead_allom(c_agw,c_bgw,c_sapw,ft,c_struct) + call bstore_allom(temp_cohort%dbh,ft, temp_cohort%crowndamage, & + temp_cohort%canopy_trim,c_store) + ! Cycle through available carbon and nutrients, find the limiting element ! to dictate the total number of plants that can be generated @@ -2506,7 +2510,8 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) call create_cohort(currentSite,currentPatch, temp_cohort%pft, temp_cohort%n, & temp_cohort%hite, temp_cohort%coage, temp_cohort%dbh, prt, & - elongf_leaf, elongf_fnrt, elongf_stem, cohortstatus, recruitstatus, & + temp_cohort%efleaf_coh, temp_cohort%effnrt_coh, temp_cohort%efstem_coh, & + temp_cohort%status_coh, recruitstatus, & temp_cohort%canopy_trim,temp_cohort%c_area, & currentPatch%NCL_p, & temp_cohort%crowndamage, & diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index 9b81a8c0aa..baa8ce14d6 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -211,8 +211,7 @@ subroutine CheckIntegratedAllometries(dbh,ipft,crowndamage, & l_pass = .true. ! Default assumption is that step passed if (grow_leaf) then - call bleaf(dbh,ipft,crowndamage, canopy_trim,bl_diag) - bl_diag = bl_diag * elongf_leaf + call bleaf(dbh,ipft,crowndamage, canopy_trim, elongf_leaf, bl_diag) if( abs(bl_diag-bl) > max_err ) then if(verbose_logging) then write(fates_log(),*) 'disparity in integrated/diagnosed leaf carbon' @@ -226,8 +225,7 @@ subroutine CheckIntegratedAllometries(dbh,ipft,crowndamage, & end if if (grow_fr) then - call bfineroot(dbh,ipft,canopy_trim,l2fr,bfr_diag) - bfr_diag = bfr_diag * elongf_fnrt + call bfineroot(dbh,ipft,canopy_trim,l2fr, elongf_fnrt, bfr_diag) if( abs(bfr_diag-bfr) > max_err ) then if(verbose_logging) then write(fates_log(),*) 'disparity in integrated/diagnosed fineroot carbon' @@ -241,8 +239,7 @@ subroutine CheckIntegratedAllometries(dbh,ipft,crowndamage, & end if if (grow_sap) then - call bsap_allom(dbh,ipft,crowndamage, canopy_trim,asap_diag,bsap_diag) - bsap_diag = bsap_diag * elongf_stem + call bsap_allom(dbh,ipft,crowndamage, canopy_trim, elongf_stem, asap_diag,bsap_diag) if( abs(bsap_diag-bsap) > max_err ) then if(verbose_logging) then write(fates_log(),*) 'disparity in integrated/diagnosed sapwood carbon' @@ -270,11 +267,10 @@ subroutine CheckIntegratedAllometries(dbh,ipft,crowndamage, & end if if (grow_dead) then - call bsap_allom(dbh,ipft,crowndamage, canopy_trim,asap_diag,bsap_diag) - call bagw_allom(dbh,ipft,crowndamage, bagw_diag) - call bbgw_allom(dbh,ipft,bbgw_diag) - call bdead_allom( bagw_diag, bbgw_diag, bsap_diag, ipft, bdead_diag ) - bdead_diag = bdead_diag * elongf_stem + call bsap_allom(dbh,ipft,crowndamage, canopy_trim, elongf_stem,asap_diag,bsap_diag) + call bagw_allom(dbh,ipft,crowndamage, elongf_stem, bagw_diag) + call bbgw_allom(dbh,ipft, elongf_stem,bbgw_diag) + call bdead_allom( bagw_diag, bbgw_diag, bsap_diag, ipft, bdead_diag ) if( abs(bdead_diag-bdead) > max_err ) then if(verbose_logging) then @@ -373,7 +369,7 @@ end subroutine h_allom ! Generic AGB interface ! ============================================================================ - subroutine bagw_allom(d,ipft,crowndamage, bagw,dbagwdd) + subroutine bagw_allom(d,ipft,crowndamage, elongf_stem, bagw,dbagwdd) use DamageMainMod, only : GetCrownReduction use FatesParameterDerivedMod, only : param_derived @@ -381,6 +377,7 @@ subroutine bagw_allom(d,ipft,crowndamage, bagw,dbagwdd) real(r8),intent(in) :: d ! plant diameter [cm] integer(i4),intent(in) :: ipft ! PFT index integer(i4),intent(in) :: crowndamage ! crowndamage [1: undamaged, >1: damaged] + real(r8),intent(in) :: elongf_stem ! Stem elongation factor real(r8),intent(out) :: bagw ! biomass above ground woody tissues real(r8),intent(out),optional :: dbagwdd ! change in agbw per diameter [kgC/cm] @@ -416,15 +413,22 @@ subroutine bagw_allom(d,ipft,crowndamage, bagw,dbagwdd) call endrun(msg=errMsg(sourcefile, __LINE__)) end select + ! Potentially reduce AGB based on crown damage (crown_reduction) and/or + ! phenology (elongf_stem). if(crowndamage > 1) then call GetCrownReduction(crowndamage, crown_reduction) - bagw = bagw - (bagw * branch_frac * crown_reduction) + bagw = elongf_stem * ( bagw - (bagw * branch_frac * crown_reduction) ) if(present(dbagwdd))then - dbagwdd = dbagwdd - (dbagwdd * branch_frac * crown_reduction) + dbagwdd = elongf_stem * ( dbagwdd - (dbagwdd * branch_frac * crown_reduction) ) + end if + else + bagw = elongf_stem * bagw + if (present(dbagwdd)) then + dbagwdd = elongf_stem * dbagwdd end if end if - + end associate return end subroutine bagw_allom @@ -547,7 +551,7 @@ end subroutine carea_allom ! ===================================================================================== - subroutine bleaf(d,ipft,crowndamage,canopy_trim,bl,dbldd) + subroutine bleaf(d,ipft,crowndamage,canopy_trim,elongf_leaf,bl,dbldd) ! ------------------------------------------------------------------------- ! This subroutine calculates the actual target bleaf @@ -562,6 +566,7 @@ subroutine bleaf(d,ipft,crowndamage,canopy_trim,bl,dbldd) integer(i4),intent(in) :: ipft ! PFT index integer(i4),intent(in) :: crowndamage ! crown damage class [1: undamaged, >1: damaged] real(r8),intent(in) :: canopy_trim ! trimming function + real(r8),intent(in) :: elongf_leaf ! Leaf elongation factor (phenology) real(r8),intent(out) :: bl ! plant leaf biomass [kg] real(r8),intent(out),optional :: dbldd ! change leaf bio per diameter [kgC/cm] @@ -584,15 +589,23 @@ subroutine bleaf(d,ipft,crowndamage,canopy_trim,bl,dbldd) dbldd = dblmaxdd * canopy_trim end if + + ! Potentially reduce leaf biomass based on crown damage (crown_reduction) and/or + ! phenology (elongf_leaf). if ( crowndamage > 1 ) then call GetCrownReduction(crowndamage, crown_reduction) - bl = bl * (1.0_r8 - crown_reduction) + bl = elongf_leaf * bl * (1.0_r8 - crown_reduction) if(present(dbldd))then - dbldd = dblmaxdd * canopy_trim * (1.0_r8 - crown_reduction) + dbldd = elongf_leaf * dblmaxdd * canopy_trim * (1.0_r8 - crown_reduction) + end if + else + bl = elongf_leaf * bl + if (present(dbldd)) then + dbldd = elongf_leaf * dbldd end if end if - + return end subroutine bleaf @@ -749,8 +762,8 @@ end function tree_lai ! ============================================================================ - real(r8) function tree_sai(pft, dbh, crowndamage, canopy_trim, c_area, nplant, cl, & - canopy_lai, treelai, vcmax25top, call_id ) + real(r8) function tree_sai(pft, dbh, crowndamage, canopy_trim, elongf_stem, c_area, nplant, & + cl, canopy_lai, treelai, vcmax25top, call_id ) ! ============================================================================ ! SAI of individual trees is a function of the LAI of individual trees @@ -760,6 +773,7 @@ real(r8) function tree_sai(pft, dbh, crowndamage, canopy_trim, c_area, nplant, c real(r8), intent(in) :: dbh integer, intent(in) :: crowndamage real(r8), intent(in) :: canopy_trim ! trimming function (0-1) + real(r8), intent(in) :: elongf_stem ! Elongation factor for stems. real(r8), intent(in) :: c_area ! crown area (m2) real(r8), intent(in) :: nplant ! number of plants integer, intent(in) :: cl ! canopy layer index @@ -773,12 +787,14 @@ real(r8) function tree_sai(pft, dbh, crowndamage, canopy_trim, c_area, nplant, c real(r8) :: target_lai real(r8) :: target_bleaf - call bleaf(dbh, pft, crowndamage, canopy_trim, target_bleaf) - + ! Assume fully flushed leaves, so stem area index is independent on leaf phenology. + ! SAI can be downscaled by stem phenology (typically applied to grasses only). + call bleaf(dbh, pft, crowndamage, canopy_trim, 1.0_r8, target_bleaf) + target_lai = tree_lai(target_bleaf, pft, c_area, nplant, cl,& canopy_lai, vcmax25top) - tree_sai = prt_params%allom_sai_scaler(pft) * target_lai + tree_sai = elongf_stem * prt_params%allom_sai_scaler(pft) * target_lai if( (treelai + tree_sai) > (sum(dinc_vai)) )then @@ -903,7 +919,7 @@ end function leafc_from_treelai ! Generic sapwood biomass interface ! ============================================================================ - subroutine bsap_allom(d,ipft,crowndamage,canopy_trim,sapw_area,bsap,dbsapdd) + subroutine bsap_allom(d,ipft,crowndamage,canopy_trim,elongf_stem, sapw_area,bsap,dbsapdd) use DamageMainMod , only : GetCrownReduction use FatesParameterDerivedMod, only : param_derived @@ -912,6 +928,7 @@ subroutine bsap_allom(d,ipft,crowndamage,canopy_trim,sapw_area,bsap,dbsapdd) integer(i4),intent(in) :: ipft ! PFT index integer(i4),intent(in) :: crowndamage ! Crown damage class [1: undamaged, >1: damaged] real(r8),intent(in) :: canopy_trim + real(r8),intent(in) :: elongf_stem ! Elongation factor for stems (phenology) real(r8),intent(out) :: sapw_area ! cross section area of ! plant sapwood at reference [m2] real(r8),intent(out) :: bsap ! plant leaf biomass [kgC] @@ -950,8 +967,10 @@ subroutine bsap_allom(d,ipft,crowndamage,canopy_trim,sapw_area,bsap,dbsapdd) case(1) ! linearly related to leaf area based on target leaf biomass ! and slatop (no provisions for slamax) + ! We assume fully flushed leaves, so sapwood biomass is independent of leaf phenology + ! (but could be modulated by stem phenology). call h_allom(d,ipft,h,dhdd) - call bleaf(d,ipft,1,canopy_trim,bl,dbldd) + call bleaf(d,ipft,1,canopy_trim,1.0_r8,bl,dbldd) call bsap_ltarg_slatop(d,h,dhdd,bl,dbldd,ipft,sapw_area,bsap,dbsapdd) ! if trees are damaged reduce bsap by percent crown loss * @@ -959,16 +978,22 @@ subroutine bsap_allom(d,ipft,crowndamage,canopy_trim,sapw_area,bsap,dbsapdd) if(crowndamage > 1)then call GetCrownReduction(crowndamage, crown_reduction) - bsap = bsap - (bsap * agb_frac * branch_frac * crown_reduction) + bsap = elongf_stem * ( bsap - (bsap * agb_frac * branch_frac * crown_reduction) ) if(present(dbsapdd))then - dbsapdd = dbsapdd - (dbsapdd * agb_frac * branch_frac * crown_reduction) + dbsapdd = elongf_stem * & + ( dbsapdd - (dbsapdd * agb_frac * branch_frac * crown_reduction) ) + end if + else + bsap = elongf_stem * bsap + if (present(dbsapdd)) then + dbsapdd = elongf_stem * dbsapdd end if end if ! Perform a capping/check on total woody biomass - call bagw_allom(d,ipft,crowndamage, bagw,dbagwdd) - call bbgw_allom(d,ipft,bbgw,dbbgwdd) + call bagw_allom(d,ipft,crowndamage, elongf_stem, bagw,dbagwdd) + call bbgw_allom(d,ipft, elongf_stem,bbgw,dbbgwdd) ! Force sapwood to be less than a maximum fraction of total biomass ! We omit the sapwood area from this calculation @@ -997,20 +1022,24 @@ end subroutine bsap_allom ! non-fineroot biomass. ! ============================================================================ - subroutine bbgw_allom(d,ipft,bbgw,dbbgwdd) + subroutine bbgw_allom(d,ipft,elongf_stem,bbgw,dbbgwdd) - real(r8),intent(in) :: d ! plant diameter [cm] - integer(i4),intent(in) :: ipft ! PFT index - real(r8),intent(out) :: bbgw ! below ground woody biomass [kgC] - real(r8),intent(out),optional :: dbbgwdd ! change bbgw per diam [kgC/cm] + real(r8),intent(in) :: d ! plant diameter [cm] + integer(i4),intent(in) :: ipft ! PFT index + real(r8),intent(in) :: elongf_stem ! Elongation factor for stems (phenology) + real(r8),intent(out) :: bbgw ! below ground woody biomass [kgC] + real(r8),intent(out),optional :: dbbgwdd ! change bbgw per diam [kgC/cm] real(r8) :: bagw ! above ground biomass [kgC] real(r8) :: dbagwdd ! change in agb per diameter [kgC/cm] select case(int(prt_params%allom_cmode(ipft))) case(1) !"constant") - ! bbgw not affected by damage so use target allometry no damage - call bagw_allom(d,ipft,1, bagw,dbagwdd) + ! bbgw not affected by damage so use target allometry no damage. But note that bbgw + ! is affected by stem phenology (typically applied only to grasses). We do not need + ! to account for stem phenology in bbgw_const because bbgw will be proportional to + ! bagw, and bagw is downscaled due to stem phenology. + call bagw_allom(d,ipft,1, elongf_stem, bagw,dbagwdd) call bbgw_const(d,bagw,dbagwdd,ipft,bbgw,dbbgwdd) case DEFAULT write(fates_log(),*) 'An undefined coarse root allometry was specified: ', & @@ -1025,7 +1054,7 @@ end subroutine bbgw_allom ! Fine root biomass allometry wrapper ! ============================================================================ - subroutine bfineroot(d,ipft,canopy_trim,l2fr,bfr,dbfrdd) + subroutine bfineroot(d,ipft,canopy_trim,l2fr,elongf_fnrt,bfr,dbfrdd) ! ------------------------------------------------------------------------- ! This subroutine calculates the actual target fineroot biomass @@ -1039,6 +1068,7 @@ subroutine bfineroot(d,ipft,canopy_trim,l2fr,bfr,dbfrdd) ! this is either a PFT parameter ! constant (when no nutrient model) ! or dynamic (with nutrient model) + real(r8),intent(in) :: elongf_fnrt ! Elongation factor for fine roots real(r8),intent(out) :: bfr ! fine root biomass [kgC] real(r8),intent(out),optional :: dbfrdd ! change leaf bio per diameter [kgC/cm] @@ -1074,7 +1104,15 @@ subroutine bfineroot(d,ipft,canopy_trim,l2fr,bfr,dbfrdd) write(fates_log(),*) 'Aborting' call endrun(msg=errMsg(sourcefile, __LINE__)) end select - + + + ! Reduce fine-root biomass due to phenology. + bfr = elongf_fnrt * bfr + if (present(dbfrdd)) then + dbfrdd = elongf_fnrt * dbfrdd + end if + + return end subroutine bfineroot @@ -1103,9 +1141,8 @@ subroutine bstore_allom(d,ipft,crowndamage, canopy_trim,bstore,dbstoredd) select case(int(allom_stmode)) case(1) ! Storage is constant proportionality of trimmed maximum leaf - ! biomass (ie cushion * bleaf) - - call bleaf(d,ipft, crowndamage, canopy_trim, bl, dbldd) + ! biomass (ie cushion * bleaf), and thus leaf phenology is ignored. + call bleaf(d,ipft, crowndamage, canopy_trim, 1.0_r8, bl, dbldd) call bstore_blcushion(d,bl,dbldd,cushion,ipft,bstore,dbstoredd) case DEFAULT @@ -1520,7 +1557,7 @@ subroutine d2h_poorter2006(d,p1,p2,p3,dbh_maxh,h,dhdd) ! "d2h_poorter2006" ! "d to height via Poorter et al. 2006, these routines use natively - ! asymtotic functions" + ! asymtotic functions (Weibull function)" ! ! Poorter et al calculated height diameter allometries over a variety of ! species in Bolivia, including those that could be classified in guilds @@ -2394,13 +2431,13 @@ real(r8) function decay_coeff_kn(pft,vcmax25top) end function decay_coeff_kn ! ===================================================================================== -subroutine ForceDBH( ipft, crowndamage, canopy_trim, d, h, bdead, bl ) +subroutine ForceDBH( ipft, crowndamage, canopy_trim, elongf_leaf, elongf_stem, d, h, bdead, bl ) ! ========================================================================= ! This subroutine estimates the diameter based on either the structural biomass ! (if woody) or the leaf biomass using the allometric ! functions. Since allometry is specified with diameter - ! as the independant variable, we must do this through a search algorithm. + ! as the independent variable, we must do this through a search algorithm. ! Here, we keep searching until the difference between actual structure and ! the predicted structure based on the searched diameter is within a tolerance. ! ============================================================================ @@ -2411,6 +2448,8 @@ subroutine ForceDBH( ipft, crowndamage, canopy_trim, d, h, bdead, bl ) integer(i4),intent(in) :: ipft ! PFT index integer(i4),intent(in) :: crowndamage ! crowndamage [1: undamaged, >1: damaged] real(r8),intent(in) :: canopy_trim + real(r8),intent(in) :: elongf_leaf ! Elongation factor: leaves (phenology) + real(r8),intent(in) :: elongf_stem ! Elongation factor: stem (phenology) real(r8),intent(inout) :: d ! plant diameter [cm] real(r8),intent(out) :: h ! plant height real(r8),intent(in),optional :: bdead ! Structural biomass @@ -2444,9 +2483,9 @@ subroutine ForceDBH( ipft, crowndamage, canopy_trim, d, h, bdead, bl ) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - call bsap_allom(d,ipft,crowndamage, canopy_trim,at_sap,bt_sap,dbt_sap_dd) - call bagw_allom(d,ipft,crowndamage, bt_agw,dbt_agw_dd) - call bbgw_allom(d,ipft,bt_bgw,dbt_bgw_dd) + call bsap_allom(d,ipft,crowndamage, canopy_trim, elongf_stem,at_sap,bt_sap,dbt_sap_dd) + call bagw_allom(d,ipft,crowndamage, elongf_stem, bt_agw,dbt_agw_dd) + call bbgw_allom(d,ipft, elongf_stem,bt_bgw,dbt_bgw_dd) call bdead_allom(bt_agw,bt_bgw, bt_sap, ipft, bt_dead, dbt_agw_dd, & dbt_bgw_dd, dbt_sap_dd, dbt_dead_dd) @@ -2462,9 +2501,10 @@ subroutine ForceDBH( ipft, crowndamage, canopy_trim, d, h, bdead, bl ) dd = step_frac*(bdead-bt_dead)/dbt_dead_dd d_try = d + dd - call bsap_allom(d_try,ipft,crowndamage, canopy_trim,at_sap,bt_sap,dbt_sap_dd) - call bagw_allom(d_try,ipft,crowndamage, bt_agw,dbt_agw_dd) - call bbgw_allom(d_try,ipft, bt_bgw,dbt_bgw_dd) + call bsap_allom(d_try,ipft,crowndamage, canopy_trim, elongf_stem,at_sap, & + bt_sap,dbt_sap_dd) + call bagw_allom(d_try,ipft,crowndamage, elongf_stem, bt_agw,dbt_agw_dd) + call bbgw_allom(d_try,ipft, elongf_stem, bt_bgw,dbt_bgw_dd) call bdead_allom(bt_agw,bt_bgw, bt_sap, ipft, bt_dead_try, dbt_agw_dd, & @@ -2494,7 +2534,7 @@ subroutine ForceDBH( ipft, crowndamage, canopy_trim, d, h, bdead, bl ) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - call bleaf(d,ipft,crowndamage,canopy_trim,bt_leaf,dbt_leaf_dd) + call bleaf(d,ipft,crowndamage,canopy_trim,elongf_leaf,bt_leaf,dbt_leaf_dd) counter = 0 step_frac = step_frac0 @@ -2503,7 +2543,7 @@ subroutine ForceDBH( ipft, crowndamage, canopy_trim, d, h, bdead, bl ) dd = step_frac*(bl-bt_leaf)/dbt_leaf_dd d_try = d + dd - call bleaf(d_try,ipft,crowndamage,canopy_trim,bt_leaf_try,dbt_leaf_dd_try) + call bleaf(d_try,ipft,crowndamage,canopy_trim,elongf_stem,bt_leaf_try,dbt_leaf_dd_try) ! Prevent overshooting if(bt_leaf_try > (bl+calloc_abs_error)) then diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 752c903b03..bf8467323e 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -980,7 +980,7 @@ subroutine UpdatePlantHydrLenVol(ccohort,csite_hydr) ! Lets also avoid super-low targets that have very low trimming functions call bleaf(ccohort%dbh,ccohort%pft,ccohort%crowndamage, & - max(ccohort%canopy_trim,min_trim),leaf_c_target) + max(ccohort%canopy_trim,min_trim),ccohort%efleaf_coh, leaf_c_target) if( (ccohort%status_coh == leaves_on) .or. ccohort_hydr%is_newly_recruited ) then ccohort_hydr%v_ag(1:n_hypool_leaf) = max(leaf_c,min_leaf_frac*leaf_c_target) * & @@ -996,7 +996,7 @@ subroutine UpdatePlantHydrLenVol(ccohort,csite_hydr) ! calculate the sapwood cross-sectional area call bsap_allom(ccohort%dbh,ccohort%pft,ccohort%crowndamage, & - ccohort%canopy_trim,a_sapwood_target,sapw_c_target) + ccohort%canopy_trim, ccohort%efstem_coh, a_sapwood_target,sapw_c_target) ! uncomment this if you want to use ! the actual sapwood, which may be lower than target due to branchfall. @@ -2976,7 +2976,7 @@ subroutine UpdatePlantKmax(ccohort_hydr,ccohort,csite_hydr) ! Get the cross-section of the plant's sapwood area [m2] call bsap_allom(ccohort%dbh,pft,ccohort%crowndamage, & - ccohort%canopy_trim,a_sapwood,c_sap_dummy) + ccohort%canopy_trim, ccohort%efstem_coh, a_sapwood,c_sap_dummy) ! Leaf Maximum Hydraulic Conductance ! The starting hypothesis is that there is no resistance inside the diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index d313ac9ce2..3cb2ed3bae 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -410,8 +410,11 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ft = currentCohort%pft cl = currentCohort%canopy_layer + ! MLO. Assuming target to be related to leaf biomass when leaves are fully + ! flushed. But unsure whether this call is correct or not, shouldn't we get + ! the target value directly from the bstore_allom? call bleaf(currentCohort%dbh,currentCohort%pft,& - currentCohort%crowndamage,currentCohort%canopy_trim,store_c_target) + currentCohort%crowndamage,currentCohort%canopy_trim,1.0_r8,store_c_target) ! call bstore_allom(currentCohort%dbh,currentCohort%pft, & ! currentCohort%canopy_trim,store_c_target) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 0baddb1ef1..92ba1a2905 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -769,7 +769,6 @@ subroutine init_cohorts( site_in, patch_in, bc_in) ! !LOCAL VARIABLES: type(ed_cohort_type),pointer :: temp_cohort class(prt_vartypes),pointer :: prt_obj - integer :: cstatus integer :: pft integer :: crowndamage ! which crown damage class integer :: iage ! index for leaf age loop @@ -790,9 +789,6 @@ subroutine init_cohorts( site_in, patch_in, bc_in) real(r8) :: m_sapw ! Generic mass for sapwood [kg] real(r8) :: m_store ! Generic mass for storage [kg] real(r8) :: m_repro ! Generic mass for reproductive tissues [kg] - real(r8) :: elongf_leaf ! Leaf elongation factor - real(r8) :: elongf_fnrt ! Fine-root "elongation factor" - real(r8) :: elongf_stem ! Stem "elongation factor" real(r8) :: fnrt_drop_fraction ! Fraction of fine roots to absciss when leaves absciss real(r8) :: stem_drop_fraction ! Fraction of stems to absciss when leaves absciss @@ -853,6 +849,62 @@ subroutine init_cohorts( site_in, patch_in, bc_in) ! we do not need to initialise branch frac just yet. temp_cohort%crowndamage = 1 + + fnrt_drop_fraction = prt_params%phen_fnrt_drop_fraction(temp_cohort%pft) + stem_drop_fraction = prt_params%phen_stem_drop_fraction(temp_cohort%pft) + + + + ! Initialise phenology variables. + spmode_case: select case (hlm_use_sp) + case (itrue) + ! Satellite phenology: do not override SP values with built-in phenology + temp_cohort%efleaf_coh = 1.0_r8 + temp_cohort%effnrt_coh = 1.0_r8 + temp_cohort%efstem_coh = 1.0_r8 + + temp_cohort%status_coh = leaves_on + case (ifalse) + ! Use built-in phenology + + if( prt_params%season_decid(pft) == itrue .and. & + any(site_in%cstatus == [phen_cstat_nevercold,phen_cstat_iscold])) then + ! Cold deciduous, off season, assume complete abscission. + temp_cohort%efleaf_coh = 0._r8 + temp_cohort%effnrt_coh = 1.0_r8 - fnrt_drop_fraction + temp_cohort%efstem_coh = 1.0_r8 - stem_drop_fraction + + temp_cohort%status_coh = leaves_off + elseif ( any(prt_params%stress_decid(pft) == [ihard_stress_decid,isemi_stress_decid])) then + ! If the plant is drought deciduous, make sure leaf status is + ! always consistent with the leaf elongation factor. For tissues + ! other than leaves, the actual drop fraction is a combination of the + ! elongation factor (e) and the drop fraction (x), which will ensure + ! that the remaining tissue biomass will be exactly e when x=1, and + ! exactly the original biomass when x = 0. + temp_cohort%efleaf_coh = site_in%elong_factor(pft) + temp_cohort%effnrt_coh = 1.0_r8 - (1.0_r8 - temp_cohort%efleaf_coh ) * fnrt_drop_fraction + temp_cohort%efstem_coh = 1.0_r8 - (1.0_r8 - temp_cohort%efleaf_coh ) * stem_drop_fraction + + if (temp_cohort%efleaf_coh > 0.0_r8) then + temp_cohort%status_coh = leaves_on + else + temp_cohort%status_coh = leaves_off + end if + else + ! Evergreens, or deciduous during growing season. + ! Assume leaves are fully flushed. + temp_cohort%efleaf_coh = 1.0_r8 + temp_cohort%effnrt_coh = 1.0_r8 + temp_cohort%efstem_coh = 1.0_r8 + + temp_cohort%status_coh = leaves_on + end if + + end select spmode_case + + + ! h,dbh,leafc,n from SP values or from small initial size. if(hlm_use_sp.eq.itrue)then init = itrue @@ -870,77 +922,29 @@ subroutine init_cohorts( site_in, patch_in, bc_in) ! Calculate the leaf biomass from allometry ! (calculates a maximum first, then applies canopy trim) call bleaf(temp_cohort%dbh,pft,temp_cohort%crowndamage, & - temp_cohort%canopy_trim,c_leaf) + temp_cohort%canopy_trim, temp_cohort%efleaf_coh, c_leaf) end if ! sp mode ! Calculate total above-ground biomass from allometry - call bagw_allom(temp_cohort%dbh,pft,temp_cohort%crowndamage,c_agw) + call bagw_allom(temp_cohort%dbh,pft,temp_cohort%crowndamage, temp_cohort%efstem_coh, c_agw) ! Calculate coarse root biomass from allometry - call bbgw_allom(temp_cohort%dbh,pft,c_bgw) + call bbgw_allom(temp_cohort%dbh,pft, temp_cohort%efstem_coh, c_bgw) ! Calculate fine root biomass from allometry ! (calculates a maximum and then trimming value) - call bfineroot(temp_cohort%dbh,pft,temp_cohort%canopy_trim,temp_cohort%l2fr,c_fnrt) + call bfineroot(temp_cohort%dbh,pft,temp_cohort%canopy_trim,temp_cohort%l2fr, & + temp_cohort%effnrt_coh, c_fnrt) ! Calculate sapwood biomass call bsap_allom(temp_cohort%dbh,pft,temp_cohort%crowndamage, & - temp_cohort%canopy_trim,a_sapw,c_sapw) + temp_cohort%canopy_trim, temp_cohort%efstem_coh, a_sapw, c_sapw) call bdead_allom( c_agw, c_bgw, c_sapw, pft, c_struct ) call bstore_allom(temp_cohort%dbh, pft, temp_cohort%crowndamage, & temp_cohort%canopy_trim, c_store) - ! Assume leaves are fully flushed, and update if needed. - cstatus = leaves_on - elongf_leaf = 1.0_r8 - elongf_fnrt = 1.0_r8 - elongf_stem = 1.0_r8 - - fnrt_drop_fraction = prt_params%phen_fnrt_drop_fraction(temp_cohort%pft) - stem_drop_fraction = prt_params%phen_stem_drop_fraction(temp_cohort%pft) - - if(hlm_use_sp.eq.ifalse)then ! do not override SP vales with phenology - - if( prt_params%season_decid(pft) == itrue .and. & - any(site_in%cstatus == [phen_cstat_nevercold,phen_cstat_iscold])) then - elongf_leaf = 0._r8 - elongf_fnrt = 1.0_r8 - fnrt_drop_fraction - elongf_stem = 1.0_r8 - stem_drop_fraction - - c_leaf = elongf_leaf * c_leaf - c_fnrt = elongf_fnrt * c_fnrt - c_sapw = elongf_stem * c_sapw - c_struct = elongf_stem * c_struct - - cstatus = leaves_off - elseif ( any(prt_params%stress_decid(pft) == [ihard_stress_decid,isemi_stress_decid])) then - ! If the plant is drought deciduous, make sure leaf status is - ! always consistent with the leaf elongation factor. For tissues - ! other than leaves, the actual drop fraction is a combination of the - ! elongation factor (e) and the drop fraction (x), which will ensure - ! that the remaining tissue biomass will be exactly e when x=1, and - ! exactly the original biomass when x = 0. - elongf_leaf = site_in%elong_factor(pft) - elongf_fnrt = 1.0_r8 - (1.0_r8 - elongf_leaf ) * fnrt_drop_fraction - elongf_stem = 1.0_r8 - (1.0_r8 - elongf_leaf ) * stem_drop_fraction - - - c_leaf = elongf_leaf * c_leaf - c_fnrt = elongf_fnrt * c_fnrt - c_sapw = elongf_stem * c_sapw - c_struct = elongf_stem * c_struct - - if (elongf_leaf > 0.0_r8) then - cstatus = leaves_on - else - cstatus = leaves_off - end if - end if - - end if ! SP mode - if ( debug ) write(fates_log(),*) 'EDInitMod.F90 call create_cohort ' temp_cohort%coage = 0.0_r8 @@ -1014,8 +1018,9 @@ subroutine init_cohorts( site_in, patch_in, bc_in) call prt_obj%CheckInitialConditions() call create_cohort(site_in, patch_in, pft, temp_cohort%n, temp_cohort%hite, & - temp_cohort%coage, temp_cohort%dbh, prt_obj, elongf_leaf, elongf_fnrt, & - elongf_stem, cstatus, rstatus, temp_cohort%canopy_trim, & + temp_cohort%coage, temp_cohort%dbh, prt_obj, temp_cohort%efleaf_coh, & + temp_cohort%effnrt_coh, temp_cohort%efstem_coh, temp_cohort%status_coh, & + rstatus, temp_cohort%canopy_trim, & temp_cohort%c_area,1,temp_cohort%crowndamage, site_in%spread, bc_in) deallocate(temp_cohort) ! get rid of temporary cohort diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index fe3376e2fd..5125501866 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -83,10 +83,10 @@ module EDTypesMod ! can be approximated to be equal to the visible band - integer, parameter, public :: leaves_pshed = 3 ! Flag specifying that a deciduous plant has leaves - ! but is shedding them (partial shedding). This plant - ! should not allocate carbon towards growth or - ! reproduction. + integer, parameter, public :: leaves_shedding = 3 ! Flag specifying that a deciduous plant has leaves + ! but is shedding them (partial shedding). This plant + ! should not allocate carbon towards growth or + ! reproduction. integer, parameter, public :: leaves_on = 2 ! Flag specifying that a deciduous plant has leaves ! and should be allocating to them as well integer, parameter, public :: leaves_off = 1 ! Flag specifying that a deciduous plant has dropped diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index eaaaa75744..026989cd38 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -893,7 +893,6 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & real(r8) :: c_avgRG ! avg radial growth (NOT USED) real(r8) :: site_spread ! initial guess of site spread ! should be quickly re-calculated - integer :: cstatus ! cohort status integer,parameter :: rstatus = 0 ! recruit status type(ed_patch_type), pointer :: cpatch ! current patch pointer @@ -917,9 +916,6 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & real(r8) :: m_sapw ! Generic mass for sapwood [kg] real(r8) :: m_store ! Generic mass for storage [kg] real(r8) :: m_repro ! Generic mass for reproductive tissues [kg] - real(r8) :: elongf_leaf ! Leaf elongation factor - real(r8) :: elongf_fnrt ! Fine-root "elongation factor" - real(r8) :: elongf_stem ! Stem "elongation factor" real(r8) :: fnrt_drop_fraction ! Fine-root abscission fraction real(r8) :: stem_drop_fraction ! Stem abscission fraction integer :: i_pft, ncohorts_to_create @@ -1030,48 +1026,20 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & call h_allom(c_dbh,temp_cohort%pft,temp_cohort%hite) temp_cohort%canopy_trim = 1.0_r8 - call bagw_allom(temp_cohort%dbh,temp_cohort%pft, & - temp_cohort%crowndamage, c_agw) - ! Calculate coarse root biomass from allometry - call bbgw_allom(temp_cohort%dbh,temp_cohort%pft,c_bgw) - - ! Calculate the leaf biomass (calculates a maximum first, then applies canopy trim - ! and sla scaling factors) - call bleaf(temp_cohort%dbh,temp_cohort%pft,temp_cohort%crowndamage,& - temp_cohort%canopy_trim,c_leaf) - - ! Calculate fine root biomass - - temp_cohort%l2fr = prt_params%allom_l2fr(temp_cohort%pft) - call bfineroot(temp_cohort%dbh,temp_cohort%pft,temp_cohort%canopy_trim,temp_cohort%l2fr,c_fnrt) - - ! Calculate sapwood biomass - call bsap_allom(temp_cohort%dbh,temp_cohort%pft,temp_cohort%crowndamage, & - temp_cohort%canopy_trim, a_sapw, c_sapw) - - call bdead_allom( c_agw, c_bgw, c_sapw, temp_cohort%pft, c_struct ) - call bstore_allom(temp_cohort%dbh, temp_cohort%pft, temp_cohort%crowndamage,temp_cohort%canopy_trim, c_store) - - cstatus = leaves_on - elongf_leaf = 1.0_r8 - elongf_fnrt = 1.0_r8 - elongf_stem = 1.0_r8 - + ! Determine the phenology status and the elongation factors. fnrt_drop_fraction = prt_params%phen_fnrt_drop_fraction(temp_cohort%pft) stem_drop_fraction = prt_params%phen_stem_drop_fraction(temp_cohort%pft) if( prt_params%season_decid(temp_cohort%pft) == itrue .and. & any(csite%cstatus == [phen_cstat_nevercold,phen_cstat_iscold])) then - elongf_leaf = 0.0_r8 - elongf_fnrt = 1._r8 - fnrt_drop_fraction - elongf_stem = 1._r8 - stem_drop_fraction + ! Cold deciduous and season is for leaves off. Set leaf status and + ! elongation factors accordingly + temp_cohort%efleaf_coh = 0.0_r8 + temp_cohort%effnrt_coh = 1._r8 - fnrt_drop_fraction + temp_cohort%efstem_coh = 1._r8 - stem_drop_fraction - c_leaf = elongf_leaf * c_leaf - c_fnrt = elongf_fnrt * c_fnrt - c_sapw = elongf_stem * c_sapw - c_struct = elongf_stem * c_struct + temp_cohort%status_coh = leaves_off - cstatus = leaves_off elseif ( any(prt_params%stress_decid(temp_cohort%pft) == [ihard_stress_decid,isemi_stress_decid])) then ! Drought deciduous. For the default approach, elongation factor is either ! zero (full abscission) or one (fully flushed), but this can also be a @@ -1083,24 +1051,49 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & ! of the elongation factor (e) and the drop fraction (x), which will ensure ! that the remaining tissue biomass will be exactly e when x=1, and exactly ! the original biomass when x = 0. - elongf_leaf = csite%elong_factor(temp_cohort%pft) - elongf_fnrt = 1.0_r8 - (1.0_r8 - elongf_leaf ) * fnrt_drop_fraction - elongf_stem = 1.0_r8 - (1.0_r8 - elongf_leaf ) * stem_drop_fraction - + temp_cohort%efleaf_coh = csite%elong_factor(temp_cohort%pft) + temp_cohort%effnrt_coh = 1.0_r8 - (1.0_r8 - temp_cohort%efleaf_coh ) * fnrt_drop_fraction + temp_cohort%efstem_coh = 1.0_r8 - (1.0_r8 - temp_cohort%efleaf_coh ) * stem_drop_fraction - c_leaf = elongf_leaf * c_leaf - c_fnrt = elongf_fnrt * c_fnrt - c_sapw = elongf_stem * c_sapw - c_struct = elongf_stem * c_struct - if (elongf_leaf > 0.0_r8) then + if (temp_cohort%efleaf_coh > 0.0_r8) then ! Assume leaves are growing even if they are not fully flushed. - cstatus = leaves_on + temp_cohort%status_coh = leaves_on else ! Leaves are off (abscissing). - cstatus = leaves_off + temp_cohort%status_coh = leaves_off end if + else + ! Evergreen, or deciduous PFT during the growing season. Assume tissues are fully flushed. + temp_cohort%efleaf_coh = 1.0_r8 + temp_cohort%effnrt_coh = 1.0_r8 + temp_cohort%efstem_coh = 1.0_r8 + + temp_cohort%status_coh = leaves_on end if + call bagw_allom(temp_cohort%dbh,temp_cohort%pft, & + temp_cohort%crowndamage, temp_cohort%efstem_coh, c_agw) + ! Calculate coarse root biomass from allometry + call bbgw_allom(temp_cohort%dbh,temp_cohort%pft, temp_cohort%efstem_coh, c_bgw) + + ! Calculate the leaf biomass (calculates a maximum first, then applies canopy trim + ! and sla scaling factors) + call bleaf(temp_cohort%dbh,temp_cohort%pft,temp_cohort%crowndamage,& + temp_cohort%canopy_trim, temp_cohort%efleaf_coh, c_leaf) + + ! Calculate fine root biomass + + temp_cohort%l2fr = prt_params%allom_l2fr(temp_cohort%pft) + call bfineroot(temp_cohort%dbh,temp_cohort%pft,temp_cohort%canopy_trim,temp_cohort%l2fr, & + temp_cohort%effnrt_coh, c_fnrt) + + ! Calculate sapwood biomass + call bsap_allom(temp_cohort%dbh,temp_cohort%pft,temp_cohort%crowndamage, & + temp_cohort%canopy_trim, temp_cohort%efstem_coh, a_sapw, c_sapw) + + call bdead_allom( c_agw, c_bgw, c_sapw, temp_cohort%pft, c_struct ) + call bstore_allom(temp_cohort%dbh, temp_cohort%pft, temp_cohort%crowndamage,temp_cohort%canopy_trim, c_store) + prt_obj => null() call InitPRTObject(prt_obj) @@ -1189,7 +1182,8 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & call create_cohort(csite, cpatch, temp_cohort%pft, temp_cohort%n, temp_cohort%hite, & temp_cohort%coage, temp_cohort%dbh, & - prt_obj, elongf_leaf, elongf_fnrt, elongf_stem, cstatus, rstatus, & + prt_obj, temp_cohort%efleaf_coh, temp_cohort%effnrt_coh, & + temp_cohort%efstem_coh, temp_cohort%status_coh, rstatus, & temp_cohort%canopy_trim,temp_cohort%c_area, & 1, temp_cohort%crowndamage, csite%spread, bc_in) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 64a118cacf..e60c5d21da 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1243,8 +1243,8 @@ data: fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_phen_drought_threshold = 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, - 0.15, 0.15, 0.15, 0.15 ; + fates_phen_drought_threshold = -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, + -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4 ; fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; @@ -1255,8 +1255,8 @@ data: fates_phen_mindaysoff = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 ; - fates_phen_moist_threshold = 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, - 0.18, 0.18, 0.18, 0.18 ; + fates_phen_moist_threshold = -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, + -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9 ; fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index c8d6a8d0d4..4fbc2023f5 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -56,7 +56,7 @@ module PRTAllometricCNPMod use FatesConstantsMod , only : fates_unset_int use FatesConstantsMod , only : sec_per_day use PRTParametersMod , only : prt_params - use EDTypesMod , only : leaves_on,leaves_off,leaves_pshed + use EDTypesMod , only : leaves_on,leaves_off,leaves_shedding use EDTypesMod , only : p_uptake_mode use EDTypesMod , only : n_uptake_mode use FatesConstantsMod , only : prescribed_p_uptake @@ -471,28 +471,17 @@ subroutine DailyPRTAllometricCNP(this,phase) ! Set carbon targets based on the plant's current stature target_c(:) = fates_unset_r8 target_dcdd(:) = fates_unset_r8 - call bsap_allom(dbh,ipft,crown_damage,canopy_trim,sapw_area,target_c(sapw_organ),target_dcdd(sapw_organ)) - call bagw_allom(dbh,ipft,crown_damage,agw_c_target,agw_dcdd_target) - call bbgw_allom(dbh,ipft,bgw_c_target,bgw_dcdd_target) + call bsap_allom(dbh,ipft,crown_damage,canopy_trim,elongf_stem,sapw_area,target_c(sapw_organ),target_dcdd(sapw_organ)) + call bagw_allom(dbh,ipft,crown_damage,elongf_stem,agw_c_target,agw_dcdd_target) + call bbgw_allom(dbh,ipft,elongf_stem,bgw_c_target,bgw_dcdd_target) call bdead_allom(agw_c_target,bgw_c_target,target_c(sapw_organ),ipft,target_c(struct_organ), & agw_dcdd_target,bgw_dcdd_target,target_dcdd(sapw_organ),target_dcdd(struct_organ)) - call bleaf(dbh,ipft,crown_damage,canopy_trim, target_c(leaf_organ), target_dcdd(leaf_organ)) - call bfineroot(dbh,ipft,canopy_trim, l2fr, target_c(fnrt_organ), target_dcdd(fnrt_organ)) + call bleaf(dbh,ipft,crown_damage,canopy_trim, elongf_leaf, target_c(leaf_organ), target_dcdd(leaf_organ)) + call bfineroot(dbh,ipft,canopy_trim, l2fr, elongf_fnrt, target_c(fnrt_organ), target_dcdd(fnrt_organ)) call bstore_allom(dbh,ipft,crown_damage, canopy_trim, target_c(store_organ), target_dcdd(store_organ)) target_c(repro_organ) = 0._r8 target_dcdd(repro_organ) = 0._r8 - ! Correct tissue targets based on the elongation factor - target_c(leaf_id) = elongf_leaf * target_c(leaf_id) - target_c(fnrt_id) = elongf_fnrt * target_c(fnrt_id) - target_c(sapw_id) = elongf_stem * target_c(sapw_id) - target_c(struct_id) = elongf_stem * target_c(struct_id) - ! MLO - Need to check whether or not the multiplication for the growth is correct or not. - target_dcdd(leaf_id) = elongf_leaf * target_dcdd(leaf_id) - target_dcdd(fnrt_id) = elongf_fnrt * target_dcdd(fnrt_id) - target_dcdd(sapw_id) = elongf_stem * target_dcdd(sapw_id) - target_dcdd(struct_id) = elongf_stem * target_dcdd(struct_id) - ! =================================================================================== ! Step 1: Evaluate nutrient storage in the plant. Depending on how low ! these stores are, we will move proportionally more or less of the daily carbon @@ -738,6 +727,7 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd) real(r8) :: canopy_trim integer :: leaf_status integer, pointer :: limiter + real(r8) :: elongf_fnrt real(r8) :: store_c_max, store_c_act real(r8) :: store_nut_max, store_nut_act real(r8) :: l2fr_delta @@ -752,7 +742,8 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd) ! of the process function in the PID controller leaf_status = this%bc_in(acnp_bc_in_id_lstat)%ival - ipft = this%bc_in(acnp_bc_in_id_pft)%ival + ipft = this%bc_in(acnp_bc_in_id_pft)%ival + elongf_fnrt = this%bc_in(acnp_bc_in_id_effnrt)%rval l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval canopy_trim = this%bc_in(acnp_bc_in_id_ctrim)%rval @@ -760,7 +751,6 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd) cx0 => this%bc_inout(acnp_bc_inout_id_cx0)%rval ema_dcxdt => this%bc_inout(acnp_bc_inout_id_emadcxdt)%rval limiter => this%bc_out(acnp_bc_out_id_limiter)%ival - ! Abort if leaves are off if(leaf_status.eq.leaves_off) return @@ -863,7 +853,7 @@ subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd) l2fr = max(l2fr_min, l2fr + l2fr_delta) ! Find the updated target fineroot biomass - call bfineroot(dbh,ipft,canopy_trim, l2fr, target_c(fnrt_organ),target_dcdd(fnrt_organ)) + call bfineroot(dbh,ipft,canopy_trim, l2fr, elongf_fnrt, target_c(fnrt_organ),target_dcdd(fnrt_organ)) return end subroutine CNPAdjustFRootTargets @@ -898,10 +888,11 @@ subroutine TrimFineRoot(this) associate( ipft => this%bc_in(acnp_bc_in_id_pft)%ival, & l2fr => this%bc_inout(acnp_bc_inout_id_l2fr)%rval, & dbh => this%bc_inout(acnp_bc_inout_id_dbh)%rval, & + elongf_fnrt => this%bc_in(acnp_bc_in_id_effnrt)%rval, & canopy_trim => this%bc_in(acnp_bc_in_id_ctrim)%rval) ! Find the updated target fineroot biomass - call bfineroot(dbh,ipft,canopy_trim, l2fr, target_fnrt_c) + call bfineroot(dbh,ipft,canopy_trim, l2fr, elongf_fnrt, target_fnrt_c) fnrt_flux_c = max(0._r8,this%variables(fnrt_c_id)%val(1)*(1._r8-nday_buffer*(years_per_day / prt_params%root_long(ipft))) - target_fnrt_c ) @@ -1037,7 +1028,7 @@ subroutine CNPPrioritizedReplacement(this,c_gain, n_gain, p_gain, target_c) ! Don't allow allocation to leaves if they are in an "off" status. ! Also, dont allocate to replace turnover if this is not evergreen ! (this prevents accidental re-flushing on the day they drop) - if( ( any(leaf_status == [leaves_off,leaves_pshed]) .or. & + if( ( any(leaf_status == [leaves_off,leaves_shedding]) .or. & (prt_params%evergreen(ipft) /= itrue) ) & .and. (i_org == leaf_organ)) cycle @@ -1190,7 +1181,7 @@ subroutine CNPPrioritizedReplacement(this,c_gain, n_gain, p_gain, target_c) ! Don't allow allocation to leaves if they are in an "off" status. ! (this prevents accidental re-flushing on the day they drop) - if( any(leaf_status == [leaves_off,leaves_pshed]) .and. & + if( any(leaf_status == [leaves_off,leaves_shedding]) .and. & (i_org == leaf_organ) ) cycle if( priority_code == i_pri ) then @@ -1402,7 +1393,7 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & if( c_gain <= calloc_abs_error .or. & n_gain <= 0.1_r8*calloc_abs_error .or. & p_gain <= 0.02_r8*calloc_abs_error .or. & - any(leaf_status == [leaves_off,leaves_pshed]) ) then + any(leaf_status == [leaves_off,leaves_shedding]) ) then return end if @@ -1712,20 +1703,14 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & storec_tp1 = state_array_out(store_id) structc_tp1 = state_array_out(struct_id) - call bleaf(dbh_tp1,ipft,crown_damage,canopy_trim,leaf_c_target_tp1) - call bfineroot(dbh_tp1,ipft,canopy_trim,l2fr,fnrt_c_target_tp1) - call bsap_allom(dbh_tp1,ipft,crown_damage,canopy_trim,sapw_area,sapw_c_target_tp1) - call bagw_allom(dbh_tp1,ipft,crown_damage,agw_c_target_tp1) - call bbgw_allom(dbh_tp1,ipft,bgw_c_target_tp1) + call bleaf(dbh_tp1,ipft,crown_damage,canopy_trim, elongf_leaf, leaf_c_target_tp1) + call bfineroot(dbh_tp1,ipft,canopy_trim,l2fr, elongf_fnrt, fnrt_c_target_tp1) + call bsap_allom(dbh_tp1,ipft,crown_damage,canopy_trim, elongf_stem, sapw_area,sapw_c_target_tp1) + call bagw_allom(dbh_tp1,ipft,crown_damage, elongf_stem, agw_c_target_tp1) + call bbgw_allom(dbh_tp1,ipft, elongf_stem, bgw_c_target_tp1) call bdead_allom(agw_c_target_tp1,bgw_c_target_tp1, sapw_c_target_tp1, ipft, struct_c_target_tp1) call bstore_allom(dbh_tp1,ipft,crown_damage,canopy_trim,store_c_target_tp1) - ! Correct the targets based on the elongation factors - leaf_c_target_tp1 = elongf_leaf * leaf_c_target_tp1 - fnrt_c_target_tp1 = elongf_fnrt * fnrt_c_target_tp1 - sapw_c_target_tp1 = elongf_stem * sapw_c_target_tp1 - struct_c_target_tp1 = elongf_stem * struct_c_target_tp1 - write(fates_log(),*) 'leaf_c: ',leafc_tp1, leaf_c_target_tp1,leafc_tp1-leaf_c_target_tp1 write(fates_log(),*) 'fnrt_c: ',fnrtc_tp1, fnrt_c_target_tp1,fnrtc_tp1- fnrt_c_target_tp1 write(fates_log(),*) 'sapw_c: ',sapwc_tp1, sapw_c_target_tp1 ,sapwc_tp1- sapw_c_target_tp1 @@ -2063,19 +2048,13 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe if(organ_id == store_organ) then - call bleaf(dbh,ipft,crown_damage,canopy_trim,leaf_c_target) - call bfineroot(dbh,ipft,canopy_trim,l2fr,fnrt_c_target) - call bsap_allom(dbh,ipft,crown_damage,canopy_trim,sapw_area,sapw_c_target) - call bagw_allom(dbh,ipft,crown_damage,agw_c_target) - call bbgw_allom(dbh,ipft,bgw_c_target) + call bleaf(dbh,ipft,crown_damage,canopy_trim, elongf_leaf, leaf_c_target) + call bfineroot(dbh,ipft,canopy_trim,l2fr, elongf_fnrt, fnrt_c_target) + call bsap_allom(dbh,ipft,crown_damage,canopy_trim, elongf_stem, sapw_area,sapw_c_target) + call bagw_allom(dbh,ipft,crown_damage, elongf_stem, agw_c_target) + call bbgw_allom(dbh,ipft, elongf_stem, bgw_c_target) call bdead_allom(agw_c_target,bgw_c_target, sapw_c_target, ipft, struct_c_target) - ! Correct the targets based on the elongation factors - leaf_c_target = elongf_leaf * leaf_c_target - fnrt_c_target = elongf_fnrt * fnrt_c_target - sapw_c_target = elongf_stem * sapw_c_target - struct_c_target = elongf_stem * struct_c_target - ! Target for storage is a fraction of the sum target of all ! non-reproductive organs @@ -2300,26 +2279,15 @@ function AllomCNPGrowthDeriv(l_state_array,l_state_mask,cbalance,intgr_params) r elongf_fnrt = intgr_params(acnp_bc_in_id_effnrt) elongf_stem = intgr_params(acnp_bc_in_id_efstem) - call bleaf(dbh,ipft,crown_damage,canopy_trim,leaf_c_target,leaf_dcdd_target) - call bfineroot(dbh,ipft,canopy_trim,l2fr,fnrt_c_target,fnrt_dcdd_target) - call bsap_allom(dbh,ipft,crown_damage,canopy_trim,sapw_area,sapw_c_target,sapw_dcdd_target) - call bagw_allom(dbh,ipft,crown_damage,agw_c_target,agw_dcdd_target) - call bbgw_allom(dbh,ipft,bgw_c_target,bgw_dcdd_target) + call bleaf(dbh,ipft,crown_damage,canopy_trim, elongf_leaf, leaf_c_target,leaf_dcdd_target) + call bfineroot(dbh,ipft,canopy_trim,l2fr, elongf_fnrt, fnrt_c_target,fnrt_dcdd_target) + call bsap_allom(dbh,ipft,crown_damage,canopy_trim, elongf_stem, sapw_area,sapw_c_target,sapw_dcdd_target) + call bagw_allom(dbh,ipft,crown_damage, elongf_stem,agw_c_target,agw_dcdd_target) + call bbgw_allom(dbh,ipft, elongf_stem,bgw_c_target,bgw_dcdd_target) call bdead_allom(agw_c_target,bgw_c_target, sapw_c_target, ipft, struct_c_target, & agw_dcdd_target, bgw_dcdd_target, sapw_dcdd_target, struct_dcdd_target) call bstore_allom(dbh,ipft,crown_damage,canopy_trim,store_c_target,store_dcdd_target) - ! Apply correction for partially deciduous plants. - leaf_c_target = elongf_leaf * leaf_c_target - fnrt_c_target = elongf_fnrt * fnrt_c_target - sapw_c_target = elongf_stem * sapw_c_target - struct_c_target = elongf_stem * struct_c_target - ! MLO - Need to double check that it is correct to apply factor to both stocks and growth - leaf_dcdd_target = elongf_leaf * leaf_dcdd_target - fnrt_dcdd_target = elongf_fnrt * fnrt_dcdd_target - sapw_dcdd_target = elongf_stem * sapw_dcdd_target - struct_dcdd_target = elongf_stem * struct_dcdd_target - if (mask_repro) then ! fraction of carbon going towards reproduction if (dbh <= prt_params%dbh_repro_threshold(ipft)) then diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 099387e96d..96940660e7 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -34,7 +34,6 @@ module PRTAllometricCarbonMod use FatesAllometryMod , only : bagw_allom use FatesAllometryMod , only : h_allom use FatesAllometryMod , only : CheckIntegratedAllometries - use FatesAllometryMod , only : ForceDBH use FatesGlobals , only : endrun => fates_endrun use FatesGlobals , only : fates_log @@ -53,7 +52,7 @@ module PRTAllometricCarbonMod use EDTypesMod , only : leaves_on use EDTypesMod , only : leaves_off - use EDTypesMod , only : leaves_pshed + use EDTypesMod , only : leaves_shedding use EDTypesMod , only : ihard_stress_decid use EDTypesMod , only : isemi_stress_decid @@ -428,7 +427,7 @@ subroutine DailyPRTAllometricCarbon(this,phase) elongf_stem = this%bc_in(ac_bc_in_id_efstem)%rval !--- Set some logical flags to simplify "if" blocks is_hydecid_dormant = any(prt_params%stress_decid(ipft) == [ihard_stress_decid,isemi_stress_decid] ) & - .and. any(leaf_status == [leaves_off,leaves_pshed] ) + .and. any(leaf_status == [leaves_off,leaves_shedding] ) is_deciduous = any(prt_params%stress_decid(ipft) == [ihard_stress_decid,isemi_stress_decid] ) & .or. ( prt_params%season_decid(ipft) == itrue ) @@ -472,22 +471,22 @@ subroutine DailyPRTAllometricCarbon(this,phase) ! ----------------------------------------------------------------------------------- ! Target sapwood biomass according to allometry and trimming [kgC] - call bsap_allom(dbh,ipft, crowndamage, canopy_trim,sapw_area,target_sapw_c) + call bsap_allom(dbh,ipft, crowndamage, canopy_trim, elongf_stem, sapw_area,target_sapw_c) ! Target total above ground biomass in woody/fibrous tissues [kgC] - call bagw_allom(dbh,ipft, crowndamage, target_agw_c) + call bagw_allom(dbh,ipft, crowndamage, elongf_stem, target_agw_c) ! Target total below ground biomass in woody/fibrous tissues [kgC] - call bbgw_allom(dbh,ipft,target_bgw_c) + call bbgw_allom(dbh,ipft, elongf_stem, target_bgw_c) ! Target total dead (structrual) biomass [kgC] call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, ipft, target_struct_c) ! Target leaf biomass according to allometry and trimming - call bleaf(dbh,ipft,crowndamage,canopy_trim,target_leaf_c) + call bleaf(dbh,ipft,crowndamage,canopy_trim, elongf_leaf, target_leaf_c) ! Target fine-root biomass and deriv. according to allometry and trimming [kgC, kgC/cm] - call bfineroot(dbh,ipft,canopy_trim,l2fr,target_fnrt_c) + call bfineroot(dbh,ipft,canopy_trim,l2fr, elongf_fnrt, target_fnrt_c) ! Target storage carbon [kgC,kgC/cm] call bstore_allom(dbh,ipft,crowndamage,canopy_trim,target_store_c) @@ -507,11 +506,6 @@ subroutine DailyPRTAllometricCarbon(this,phase) target_sapw_c = 0.0_r8 target_struct_c = 0.0_r8 target_store_c = target_store_c + max(0.0_r8,carbon_balance) - else - target_leaf_c = elongf_leaf * target_leaf_c - target_fnrt_c = elongf_fnrt * target_fnrt_c - target_sapw_c = elongf_stem * target_sapw_c - target_struct_c = elongf_stem * target_struct_c end if @@ -704,7 +698,7 @@ subroutine DailyPRTAllometricCarbon(this,phase) ! should not invest in growth. ! ----------------------------------------------------------------------------------- select_stash_grow: select case (leaf_status) - case (leaves_off,leaves_pshed) + case (leaves_off,leaves_shedding) ! There is carbon balance, but plant is shedding leaves. We stash the carbon ! to storage even if it makes their storage too large. store_c_flux = carbon_balance @@ -1051,26 +1045,15 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) crowndamage = int(intgr_params(ac_bc_in_id_cdamage)) l2fr = prt_params%allom_l2fr(ipft) - call bleaf(dbh,ipft,crowndamage,canopy_trim,ct_leaf, dbldd=ct_dleafdd) - call bfineroot(dbh,ipft,canopy_trim,l2fr,ct_fnrt,ct_dfnrtdd) - call bsap_allom(dbh,ipft, crowndamage, canopy_trim,sapw_area,ct_sap,ct_dsapdd) - call bagw_allom(dbh,ipft,crowndamage, ct_agw,ct_dagwdd) - call bbgw_allom(dbh,ipft,ct_bgw, ct_dbgwdd) + call bleaf(dbh,ipft,crowndamage,canopy_trim, elongf_leaf, ct_leaf, dbldd=ct_dleafdd) + call bfineroot(dbh,ipft,canopy_trim,l2fr, elongf_fnrt, ct_fnrt,ct_dfnrtdd) + call bsap_allom(dbh,ipft, crowndamage, canopy_trim, elongf_stem, sapw_area,ct_sap,ct_dsapdd) + call bagw_allom(dbh,ipft,crowndamage, elongf_stem, ct_agw,ct_dagwdd) + call bbgw_allom(dbh,ipft, elongf_stem, ct_bgw, ct_dbgwdd) call bdead_allom(ct_agw,ct_bgw, ct_sap, ipft, ct_dead, & ct_dagwdd, ct_dbgwdd, ct_dsapdd, ct_ddeaddd) call bstore_allom(dbh,ipft,crowndamage, canopy_trim,ct_store,ct_dstoredd) - ! Apply elongation factor correction to targets - ct_leaf = elongf_leaf * ct_leaf - ct_fnrt = elongf_fnrt * ct_fnrt - ct_sap = elongf_stem * ct_sap - ct_dead = elongf_stem * ct_dead - ! MLO - Need to double check that it is correct to multiply derivatives too. - ct_dleafdd = elongf_leaf * ct_dleafdd - ct_dfnrtdd = elongf_fnrt * ct_dfnrtdd - ct_dsapdd = elongf_stem * ct_dsapdd - ct_ddeaddd = elongf_stem * ct_ddeaddd - ! fraction of carbon going towards reproduction if (dbh <= prt_params%dbh_repro_threshold(ipft)) then ! cap on leaf biomass repro_fraction = prt_params%seed_alloc(ipft) @@ -1141,7 +1124,7 @@ end function AllomCGrowthDeriv ! ==================================================================================== subroutine TargetAllometryCheck(b0_leaf,b0_fnrt,b0_sapw,b0_store,b0_struct, & - bleaf,bfnrt,bsapw,bstore,bstruct, & + ba_leaf,ba_fnrt,ba_sapw,ba_store,ba_struct, & bt_leaf,bt_fnrt,bt_sapw,bt_store,bt_struct, & carbon_balance,elongf_leaf,elongf_fnrt,elongf_stem, & ipft,leaf_status, & @@ -1153,11 +1136,11 @@ subroutine TargetAllometryCheck(b0_leaf,b0_fnrt,b0_sapw,b0_store,b0_struct, & real(r8),intent(in) :: b0_sapw real(r8),intent(in) :: b0_store real(r8),intent(in) :: b0_struct - real(r8),intent(in) :: bleaf !actual - real(r8),intent(in) :: bfnrt - real(r8),intent(in) :: bsapw - real(r8),intent(in) :: bstore - real(r8),intent(in) :: bstruct + real(r8),intent(in) :: ba_leaf !actual + real(r8),intent(in) :: ba_fnrt + real(r8),intent(in) :: ba_sapw + real(r8),intent(in) :: ba_store + real(r8),intent(in) :: ba_struct real(r8),intent(in) :: bt_leaf !target real(r8),intent(in) :: bt_fnrt real(r8),intent(in) :: bt_sapw @@ -1189,22 +1172,22 @@ subroutine TargetAllometryCheck(b0_leaf,b0_fnrt,b0_sapw,b0_store,b0_struct, & ! First test whether or not each pool looks reasonable. - fine_leaf = (bt_leaf - bleaf ) <= calloc_abs_error - fine_fnrt = (bt_fnrt - bfnrt ) <= calloc_abs_error - fine_sapw = (bt_sapw - bsapw ) <= calloc_abs_error - fine_store = (bt_store - bstore ) <= calloc_abs_error - fine_struct = (bt_struct - bstruct) <= calloc_abs_error + fine_leaf = (bt_leaf - ba_leaf ) <= calloc_abs_error + fine_fnrt = (bt_fnrt - ba_fnrt ) <= calloc_abs_error + fine_sapw = (bt_sapw - ba_sapw ) <= calloc_abs_error + fine_store = (bt_store - ba_store ) <= calloc_abs_error + fine_struct = (bt_struct - ba_struct) <= calloc_abs_error all_fine = fine_leaf .and. fine_fnrt .and. fine_sapw .and. & fine_store .and. fine_struct ! Decide whether or not to grow tissues (but only if all tissues look fine). ! We grow only when biomass is less than target biomass (with tolerance). if (all_fine) then - grow_leaf = ( bleaf - bt_leaf ) <= calloc_abs_error - grow_fnrt = ( bfnrt - bt_fnrt ) <= calloc_abs_error - grow_sapw = ( bsapw - bt_sapw ) <= calloc_abs_error - grow_store = ( bstore - bt_store ) <= calloc_abs_error - grow_struct = ( bstruct - bt_struct ) <= calloc_abs_error + grow_leaf = ( ba_leaf - bt_leaf ) <= calloc_abs_error + grow_fnrt = ( ba_fnrt - bt_fnrt ) <= calloc_abs_error + grow_sapw = ( ba_sapw - bt_sapw ) <= calloc_abs_error + grow_store = ( ba_store - bt_store ) <= calloc_abs_error + grow_struct = ( ba_struct - bt_struct ) <= calloc_abs_error else ! If anything looks not fine, write a detailed report write(fates_log(),fmt=fmth) '======' @@ -1214,11 +1197,11 @@ subroutine TargetAllometryCheck(b0_leaf,b0_fnrt,b0_sapw,b0_store,b0_struct, & write(fates_log(),fmt=fmth) ' Biomass and on-allometry test (''F'' means problem)' write(fates_log(),fmt=fmth) '------' write(fates_log(),fmt=fmth) ' Tissue | Initial | Current | Target | On-allometry' - write(fates_log(),fmt=fmtb) ' Leaf |',b0_leaf ,'|',bleaf ,'|',bt_leaf ,'|',fine_leaf - write(fates_log(),fmt=fmtb) ' Fine root |',b0_fnrt ,'|',bfnrt ,'|',bt_fnrt ,'|',fine_fnrt - write(fates_log(),fmt=fmtb) ' Sap wood |',b0_sapw ,'|',bsapw ,'|',bt_sapw ,'|',fine_sapw - write(fates_log(),fmt=fmtb) ' Storage |',b0_store ,'|',bstore ,'|',bt_store ,'|',fine_store - write(fates_log(),fmt=fmtb) ' Structural |',b0_struct ,'|',bstruct ,'|',bt_struct ,'|',fine_struct + write(fates_log(),fmt=fmtb) ' Leaf |',b0_leaf ,'|',ba_leaf ,'|',bt_leaf ,'|',fine_leaf + write(fates_log(),fmt=fmtb) ' Fine root |',b0_fnrt ,'|',ba_fnrt ,'|',bt_fnrt ,'|',fine_fnrt + write(fates_log(),fmt=fmtb) ' Sap wood |',b0_sapw ,'|',ba_sapw ,'|',bt_sapw ,'|',fine_sapw + write(fates_log(),fmt=fmtb) ' Storage |',b0_store ,'|',ba_store ,'|',bt_store ,'|',fine_store + write(fates_log(),fmt=fmtb) ' Structural |',b0_struct ,'|',ba_struct ,'|',bt_struct ,'|',fine_struct write(fates_log(),fmt=fmth) '' write(fates_log(),fmt=fmth) ' Ancillary information' write(fates_log(),fmt=fmth) '------' diff --git a/parteh/PRTGenericMod.F90 b/parteh/PRTGenericMod.F90 index 2075216da2..eec5990c9f 100644 --- a/parteh/PRTGenericMod.F90 +++ b/parteh/PRTGenericMod.F90 @@ -1398,12 +1398,12 @@ function StorageNutrientTarget(pft, element_id, leaf_target, fnrt_target, sapw_t elseif(store_prop==cstore_store_prop) then - !call bsap_allom(dbh,ipft,canopy_trim,sapw_area,target_sapw_c) - !call bagw_allom(dbh,ipft,agw_c_target) - !call bbgw_allom(dbh,ipft,bgw_c_target) + !call bsap_allom(dbh,ipft,canopy_trim,elongf_stem,sapw_area,target_sapw_c) + !call bagw_allom(dbh,ipft,elongf_stem,agw_c_target) + !call bbgw_allom(dbh,ipft,elongf_stem,bgw_c_target) !call bdead_allom(agw_c_target,bgw_c_target,target_sapw_c,ipft,target_struct_c) - !call bleaf(dbh,ipft,canopy_trim, target_leaf_c) - !call bfineroot(dbh,ipft,canopy_trim, l2fr, target_fnrt_c) + !call bleaf(dbh,ipft,canopy_trim, elongf_leaf, target_leaf_c) + !call bfineroot(dbh,ipft,canopy_trim, l2fr, elongf_fnrt, target_fnrt_c) !call bstore_allom(dbh,ipft,canopy_trim, target_store_c) ! Strategy, store as much nutrient as needed to match carbon's growth potential diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index f658179212..0acb2d4c91 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -1105,7 +1105,6 @@ subroutine PRTCheckParams(is_master) pftloop: do ipft = 1,npft ! Check to see if evergreen, deciduous flags are mutually exclusive - ! MLO. Changed the check because season_decid can be 1 or 2. ! By the way, if these are mutually exclusive, shouldn't we define a ! single prt_params%leaf_phenology and a list of codes for the different ! types (i.e., ievergreen, iseason_decid, istress_hard, istress_semi, etc.)? @@ -1559,12 +1558,13 @@ function NewRecruitTotalStoichiometry(ft,l2fr,element_id) result(recruit_stoich) integer, parameter :: not_damaged = 1 ! this is also in MainDamageMod, here for dependency purposes + ! For all tissues, assume tissues of new recruits will be fully flushed. call h2d_allom(EDPftvarcon_inst%hgt_min(ft),ft,dbh) - call bleaf(dbh,ft,not_damaged,init_recruit_trim,c_leaf) - call bfineroot(dbh,ft,init_recruit_trim,l2fr,c_fnrt) - call bsap_allom(dbh,ft,not_damaged,init_recruit_trim,a_sapw, c_sapw) - call bagw_allom(dbh,ft,not_damaged,c_agw) - call bbgw_allom(dbh,ft,c_bgw) + call bleaf(dbh,ft,not_damaged,init_recruit_trim, 1.0_r8, c_leaf) + call bfineroot(dbh,ft,init_recruit_trim,l2fr, 1.0_r8,c_fnrt) + call bsap_allom(dbh,ft,not_damaged,init_recruit_trim, 1.0_r8,a_sapw, c_sapw) + call bagw_allom(dbh,ft,not_damaged, 1.0_r8,c_agw) + call bbgw_allom(dbh,ft, 1.0_r8,c_bgw) call bdead_allom(c_agw,c_bgw,c_sapw,ft,c_struct) call bstore_allom(dbh,ft,not_damaged,init_recruit_trim,c_store) From 8f64de3aa31627512d437b6a6066fd36024479f2 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 4 Apr 2023 17:11:04 -0600 Subject: [PATCH 602/852] initial refactor of cohort type --- biogeochem/DamageMainMod.F90 | 9 +- biogeochem/EDCanopyStructureMod.F90 | 38 +- biogeochem/EDCohortDynamicsMod.F90 | 75 +- biogeochem/EDLoggingMortalityMod.F90 | 8 +- biogeochem/EDMortalityFunctionsMod.F90 | 8 +- biogeochem/EDPatchDynamicsMod.F90 | 32 +- biogeochem/EDPhysiologyMod.F90 | 32 +- biogeochem/FatesAllometryMod.F90 | 4 +- biogeochem/FatesLitterMod.F90 | 11 +- biogeochem/FatesSoilBGCFluxMod.F90 | 16 +- biogeophys/EDAccumulateFluxesMod.F90 | 4 +- biogeophys/EDBtranMod.F90 | 4 +- biogeophys/EDSurfaceAlbedoMod.F90 | 12 +- biogeophys/FatesBstressMod.F90 | 4 +- biogeophys/FatesPlantHydraulicsMod.F90 | 58 +- biogeophys/FatesPlantRespPhotosynthMod.F90 | 8 +- fire/SFMainMod.F90 | 26 +- fire/SFParamsMod.F90 | 2 +- .../parteh/f90src/FatesCohortWrapMod.F90 | 16 +- main/ChecksBalancesMod.F90 | 6 +- main/EDInitMod.F90 | 4 +- main/EDMainMod.F90 | 16 +- main/EDParamsMod.F90 | 41 + main/EDPftvarcon.F90 | 4 +- main/EDTypesMod.F90 | 751 ++++++++++++++++-- main/FatesCohortMod.F90 | 624 --------------- main/FatesHistoryInterfaceMod.F90 | 10 +- main/FatesInterfaceMod.F90 | 18 +- main/FatesInventoryInitMod.F90 | 8 +- main/FatesRestartInterfaceMod.F90 | 18 +- main/FatesSizeAgeTypeIndicesMod.F90 | 2 +- parteh/PRTAllometricCNPMod.F90 | 7 +- parteh/PRTAllometricCarbonMod.F90 | 2 +- 33 files changed, 936 insertions(+), 942 deletions(-) delete mode 100644 main/FatesCohortMod.F90 diff --git a/biogeochem/DamageMainMod.F90 b/biogeochem/DamageMainMod.F90 index f0a05f7ee6..f59b43d94d 100644 --- a/biogeochem/DamageMainMod.F90 +++ b/biogeochem/DamageMainMod.F90 @@ -11,10 +11,7 @@ module DamageMainMod use EDPftvarcon , only : EDPftvarcon_inst use EDParamsMod , only : damage_event_code use EDParamsMod , only : ED_val_history_damage_bin_edges - use EDTypesMod , only : ed_site_type - use EDTypesMod , only : ed_patch_type - use EDTypesMod , only : ed_cohort_type - use EDTypesMod , only : AREA + ! use EDTypesMod , only : ed_site_type use FatesInterfaceTypesMod, only : hlm_current_day use FatesInterfaceTypesMod, only : hlm_current_month use FatesInterfaceTypesMod, only : hlm_current_year @@ -54,7 +51,7 @@ module DamageMainMod - subroutine IsItDamageTime(is_master, currentSite) + subroutine IsItDamageTime(is_master) !---------------------------------------------------------------------------- ! This subroutine determines whether damage should occur (it is called daily) @@ -63,7 +60,7 @@ subroutine IsItDamageTime(is_master, currentSite) integer, intent(in) :: is_master - type(ed_site_type), intent(inout), target :: currentSite + !type(ed_site_type), intent(inout), target :: currentSite integer :: icode ! Integer equivalent of the event code (parameter file only allows reals) integer :: damage_date ! Day of month for damage extracted from event code diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 3ce5f38e29..692ffee47a 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -20,9 +20,9 @@ module EDCanopyStructureMod use EDCohortDynamicsMod , only : InitPRTBoundaryConditions use FatesAllometryMod , only : tree_lai use FatesAllometryMod , only : tree_sai - use EDtypesMod , only : ed_site_type, ed_patch_type, ed_cohort_type - use EDTypesMod , only : nclmax - use EDTypesMod , only : nlevleaf + use EDtypesMod , only : ed_site_type, ed_patch_type, fates_cohort_type + use EDParamsMod , only : nclmax + use EDParamsMod , only : nlevleaf use EDtypesMod , only : AREA use EDLoggingMortalityMod , only : UpdateHarvestC use FatesGlobals , only : endrun => fates_endrun @@ -137,7 +137,7 @@ subroutine canopy_structure( currentSite , bc_in ) ! ! !LOCAL VARIABLES: type(ed_patch_type) , pointer :: currentPatch - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort integer :: i_lyr ! current layer index integer :: z ! Current number of canopy layers. (1= canopy, 2 = understorey) integer :: ipft @@ -346,9 +346,9 @@ subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr,bc_in) type(bc_in_type), intent(in) :: bc_in ! !LOCAL VARIABLES: - type(ed_cohort_type), pointer :: currentCohort - type(ed_cohort_type), pointer :: copyc - type(ed_cohort_type), pointer :: nextc ! The next cohort in line + type(fates_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: copyc + type(fates_cohort_type), pointer :: nextc ! The next cohort in line integer :: i_cwd ! Index for CWD pool real(r8) :: cc_loss ! cohort crown area loss in demotion (m2) real(r8) :: leaf_c ! leaf carbon [kg] @@ -801,9 +801,9 @@ subroutine PromoteIntoLayer(currentSite,currentPatch,i_lyr) integer, intent(in) :: i_lyr ! Current canopy layer of interest ! !LOCAL VARIABLES: - type(ed_cohort_type), pointer :: currentCohort - type(ed_cohort_type), pointer :: copyc - type(ed_cohort_type), pointer :: nextc ! the next cohort, or used for looping + type(fates_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: copyc + type(fates_cohort_type), pointer :: nextc ! the next cohort, or used for looping ! cohorts against the current real(r8) :: scale_factor ! for prob. exclusion - scales weight to a fraction @@ -1243,7 +1243,7 @@ subroutine canopy_spread( currentSite ) type (ed_site_type), intent(inout), target :: currentSite ! ! !LOCAL VARIABLES: - type (ed_cohort_type), pointer :: currentCohort + type (fates_cohort_type), pointer :: currentCohort type (ed_patch_type) , pointer :: currentPatch real(r8) :: sitelevel_canopyarea ! Amount of canopy in top layer at the site level real(r8) :: inc ! Arbitrary daily incremental change in canopy area @@ -1309,7 +1309,7 @@ subroutine canopy_summarization( nsites, sites, bc_in ) ! ! !LOCAL VARIABLES: type (ed_patch_type) , pointer :: currentPatch - type (ed_cohort_type) , pointer :: currentCohort + type (fates_cohort_type) , pointer :: currentCohort integer :: s integer :: ft ! plant functional type integer :: ifp ! the number of the vegetated patch (1,2,3). In SP mode bareground patch is 0 @@ -1509,7 +1509,7 @@ subroutine leaf_area_profile( currentSite ) ! ! !LOCAL VARIABLES: type (ed_patch_type) , pointer :: currentPatch - type (ed_cohort_type) , pointer :: currentCohort + type (fates_cohort_type) , pointer :: currentCohort real(r8) :: remainder !Thickness of layer at bottom of canopy. real(r8) :: fleaf ! fraction of cohort incepting area that is leaves. integer :: ft ! Plant functional type index. @@ -1801,7 +1801,7 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) ! to vegetation coverage to the host land model. ! ---------------------------------------------------------------------------------- - use EDTypesMod , only : ed_patch_type, ed_cohort_type, & + use EDTypesMod , only : ed_patch_type, fates_cohort_type, & ed_site_type, AREA use FatesInterfaceTypesMod , only : bc_out_type @@ -1813,7 +1813,7 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) type(bc_out_type), intent(inout) :: bc_out(nsites) ! Locals - type (ed_cohort_type) , pointer :: currentCohort + type (fates_cohort_type) , pointer :: currentCohort integer :: s, ifp, c, p type (ed_patch_type) , pointer :: currentPatch real(r8) :: bare_frac_area @@ -2100,7 +2100,7 @@ subroutine CanopyLayerArea(currentPatch,site_spread,layer_index,layer_area) integer,intent(in) :: layer_index real(r8),intent(inout) :: layer_area - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort layer_area = 0.0_r8 @@ -2132,7 +2132,7 @@ subroutine UpdatePatchLAI(currentPatch) type(ed_patch_type),intent(inout), target :: currentPatch ! Local Variables - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort integer :: cl ! Canopy layer index integer :: ft ! Plant functional type index @@ -2178,7 +2178,7 @@ subroutine UpdateCohortLAI(currentCohort, canopy_layer_tlai, total_canopy_area) use EDtypesMod, only : dlower_vai ! Arguments - type(ed_cohort_type),intent(inout), target :: currentCohort + type(fates_cohort_type),intent(inout), target :: currentCohort real(r8), intent(in) :: canopy_layer_tlai(nclmax) ! total leaf area index of each canopy layer real(r8), intent(in) :: total_canopy_area ! either patch%total_canopy_area or patch%area @@ -2224,7 +2224,7 @@ function NumPotentialCanopyLayers(currentPatch,site_spread,include_substory) res real(r8),intent(in) :: site_spread logical :: include_substory - type(ed_cohort_type),pointer :: currentCohort + type(fates_cohort_type),pointer :: currentCohort integer :: z real(r8) :: c_area diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 6f14ce4e66..3d6296b6a7 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -27,8 +27,8 @@ Module EDCohortDynamicsMod use PRTParametersMod , only : prt_params use FatesParameterDerivedMod, only : param_derived use EDTypesMod , only : ed_site_type, ed_patch_type - use FatesCohortMod , only : fates_cohort_type - use EDTypesMod , only : nclmax + use EDTypesMod , only : fates_cohort_type + use EDParamsMod , only : nclmax use PRTGenericMod , only : element_list use PRTGenericMod , only : StorageNutrientTarget use FatesLitterMod , only : ncwd @@ -2135,78 +2135,7 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) end subroutine DamageRecovery - subroutine InitPRTBoundaryConditions(this) - ! - ! DESCRIPTION: - ! Set the boundary conditions that flow in an out of the PARTEH - ! allocation hypotheses. Each of these calls to "RegsterBC" are simply - ! setting pointers. - ! For instance, if the hypothesis wants to know what - ! the DBH of the plant is, then we pass in the dbh as an argument (this%dbh), - ! and also tell it which boundary condition we are talking about (which is - ! defined by an integer index (ac_bc_inout_id_dbh) - ! - ! Again, elaborated Example: - ! "ac_bc_inout_id_dbh" is the unique integer that defines the object index - ! for the allometric carbon "ac" boundary condition "bc" for DBH "dbh" - ! that is classified as input and output "inout". - ! See PRTAllometricCarbonMod.F90 to track its usage. - ! bc_rval is used as the optional argument identifyer to specify a real - ! value boundary condition. - ! bc_ival is used as the optional argument identifyer to specify an integer - ! value boundary condition. - ! - - ! ARGUMENTS: - type(fates_cohort_type), intent(inout) :: this - - select case(hlm_parteh_mode) - - case (prt_carbon_allom_hyp) - - ! register boundary conditions for the Carbon Only Allometric Hypothesis - call this%prt%RegisterBCInOut(ac_bc_inout_id_dbh, bc_rval=this%dbh) - call this%prt%RegisterBCInOut(ac_bc_inout_id_netdc, bc_rval=this%npp_acc) - call this%prt%RegisterBCIn(ac_bc_in_id_cdamage, bc_ival=this%crowndamage) - call this%prt%RegisterBCIn(ac_bc_in_id_pft, bc_ival=this%pft) - call this%prt%RegisterBCIn(ac_bc_in_id_ctrim, bc_rval=this%canopy_trim) - call this%prt%RegisterBCIn(ac_bc_in_id_lstat, bc_ival=this%status_coh) - - case (prt_cnp_flex_allom_hyp) - - call this%prt%RegisterBCIn(acnp_bc_in_id_pft, bc_ival=this%pft) - call this%prt%RegisterBCIn(acnp_bc_in_id_ctrim, bc_rval=this%canopy_trim) - call this%prt%RegisterBCIn(acnp_bc_in_id_lstat, bc_ival=this%status_coh) - call this%prt%RegisterBCIn(acnp_bc_in_id_netdc, bc_rval=this%npp_acc) - - call this%prt%RegisterBCIn(acnp_bc_in_id_nc_repro, bc_rval=this%nc_repro) - call this%prt%RegisterBCIn(acnp_bc_in_id_pc_repro, bc_rval=this%pc_repro) - call this%prt%RegisterBCIn(acnp_bc_in_id_cdamage, bc_ival=this%crowndamage) - - call this%prt%RegisterBCInOut(acnp_bc_inout_id_dbh, bc_rval=this%dbh) - call this%prt%RegisterBCInOut(acnp_bc_inout_id_resp_excess, bc_rval=this%resp_excess) - call this%prt%RegisterBCInOut(acnp_bc_inout_id_l2fr, bc_rval=this%l2fr) - call this%prt%RegisterBCInOut(acnp_bc_inout_id_cx_int, bc_rval=this%cx_int) - call this%prt%RegisterBCInOut(acnp_bc_inout_id_emadcxdt, bc_rval=this%ema_dcxdt) - call this%prt%RegisterBCInOut(acnp_bc_inout_id_cx0, bc_rval=this%cx0) - - call this%prt%RegisterBCInOut(acnp_bc_inout_id_netdn, bc_rval=this%daily_n_gain) - call this%prt%RegisterBCInOut(acnp_bc_inout_id_netdp, bc_rval=this%daily_p_gain) - - call this%prt%RegisterBCOut(acnp_bc_out_id_cefflux, bc_rval=this%daily_c_efflux) - call this%prt%RegisterBCOut(acnp_bc_out_id_nefflux, bc_rval=this%daily_n_efflux) - call this%prt%RegisterBCOut(acnp_bc_out_id_pefflux, bc_rval=this%daily_p_efflux) - call this%prt%RegisterBCOut(acnp_bc_out_id_limiter, bc_ival=this%cnp_limiter) - - case DEFAULT - - write(fates_log(),*) 'You specified an unknown PRT module' - write(fates_log(),*) 'Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) - - end select - end subroutine InitPRTBoundaryConditions !:.........................................................................: diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index a98dd055cf..53aa3be4dd 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -15,7 +15,7 @@ module EDLoggingMortalityMod use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : rsnbl_math_prec - use EDTypesMod , only : ed_cohort_type + use EDTypesMod , only : fates_cohort_type use EDTypesMod , only : ed_patch_type use EDTypesMod , only : site_massbal_type use EDTypesMod , only : site_fluxdiags_type @@ -461,7 +461,7 @@ subroutine get_harvestable_carbon (csite, site_area, hlm_harvest_catnames, harve ! Local Variables type(ed_patch_type), pointer :: currentPatch - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort real(r8) :: harvestable_patch_c ! patch level total carbon available for harvest, kgC site-1 real(r8) :: harvestable_cohort_c ! cohort level total carbon available for harvest, kgC site-1 real(r8) :: sapw_m ! Biomass of sap wood @@ -717,7 +717,7 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site use EDtypesMod, only : area use EDtypesMod, only : ed_site_type use EDtypesMod, only : ed_patch_type - use EDtypesMod, only : ed_cohort_type + use EDtypesMod, only : fates_cohort_type use FatesConstantsMod, only : rsnbl_math_prec use FatesAllometryMod, only : carea_allom @@ -731,7 +731,7 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site !LOCAL VARIABLES: - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort type(site_massbal_type), pointer :: site_mass type(site_fluxdiags_type), pointer :: flux_diags type(litter_type),pointer :: new_litt diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index db5122a8d9..c8c72f4de9 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -9,7 +9,7 @@ module EDMortalityFunctionsMod use FatesGlobals , only : endrun => fates_endrun use FatesGlobals , only : fates_log use EDPftvarcon , only : EDPftvarcon_inst - use EDTypesMod , only : ed_cohort_type + use EDTypesMod , only : fates_cohort_type use EDTypesMod , only : ed_site_type use EDTypesMod , only : ed_patch_type use FatesConstantsMod , only : itrue,ifalse @@ -62,7 +62,7 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmor use FatesConstantsMod, only : fates_check_param_set use DamageMainMod, only : GetDamageMortality - type (ed_cohort_type), intent(in) :: cohort_in + type (fates_cohort_type), intent(in) :: cohort_in type (bc_in_type), intent(in) :: bc_in real(r8),intent(out) :: bmort ! background mortality : Fraction per year real(r8),intent(out) :: cmort ! carbon starvation mortality @@ -239,7 +239,7 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_pr ! ! !ARGUMENTS type(ed_site_type), intent(inout), target :: currentSite - type(ed_cohort_type),intent(inout), target :: currentCohort + type(fates_cohort_type),intent(inout), target :: currentCohort type(bc_in_type), intent(in) :: bc_in real(r8), intent(in) :: frac_site_primary @@ -322,7 +322,7 @@ function ExemptTreefallDist(ccohort) result(is_exempt) ! ============================================================================ ! Arguments - type(ed_cohort_type),intent(in), target :: ccohort + type(fates_cohort_type),intent(in), target :: ccohort logical :: is_exempt ! if true, then treat all mortality from this cohort as non-disturbance-generating diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 4c4efca18f..ad4b6e898f 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -19,12 +19,12 @@ module EDPatchDynamicsMod use EDTypesMod , only : homogenize_seed_pfts use EDTypesMod , only : n_dbh_bins, area, patchfusion_dbhbin_loweredges use EDtypesMod , only : force_patchfuse_min_biomass - use EDTypesMod , only : ed_site_type, ed_patch_type, ed_cohort_type + use EDTypesMod , only : ed_site_type, ed_patch_type, fates_cohort_type use EDTypesMod , only : site_massbal_type use EDTypesMod , only : site_fluxdiags_type use EDTypesMod , only : min_patch_area use EDTypesMod , only : min_patch_area_forced - use EDTypesMod , only : nclmax + use EDParamsMod , only : nclmax use EDTypesMod , only : maxpft use EDTypesMod , only : dtype_ifall use EDTypesMod , only : dtype_ilog @@ -175,7 +175,7 @@ subroutine disturbance_rates( site_in, bc_in) ! ! !LOCAL VARIABLES: type (ed_patch_type) , pointer :: currentPatch - type (ed_cohort_type), pointer :: currentCohort + type (fates_cohort_type), pointer :: currentCohort real(r8) :: cmort real(r8) :: bmort @@ -418,10 +418,10 @@ subroutine spawn_patches( currentSite, bc_in) type (ed_patch_type) , pointer :: new_patch_primary type (ed_patch_type) , pointer :: new_patch_secondary type (ed_patch_type) , pointer :: currentPatch - type (ed_cohort_type), pointer :: currentCohort - type (ed_cohort_type), pointer :: nc - type (ed_cohort_type), pointer :: storesmallcohort - type (ed_cohort_type), pointer :: storebigcohort + type (fates_cohort_type), pointer :: currentCohort + type (fates_cohort_type), pointer :: nc + type (fates_cohort_type), pointer :: storesmallcohort + type (fates_cohort_type), pointer :: storebigcohort real(r8) :: site_areadis_primary ! total area disturbed (to primary forest) in m2 per site per day real(r8) :: site_areadis_secondary ! total area disturbed (to secondary forest) in m2 per site per day real(r8) :: patch_site_areadis ! total area disturbed in m2 per patch per day @@ -1627,7 +1627,7 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & ! ! !LOCAL VARIABLES: - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort type(litter_type), pointer :: new_litt type(litter_type), pointer :: curr_litt type(site_massbal_type), pointer :: site_mass @@ -1863,7 +1863,7 @@ subroutine mortality_litter_fluxes(currentSite, currentPatch, & type(bc_in_type) , intent(in) :: bc_in ! ! !LOCAL VARIABLES: - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort type(litter_type), pointer :: new_litt type(litter_type), pointer :: curr_litt type(site_massbal_type), pointer :: site_mass @@ -2640,10 +2640,10 @@ subroutine fuse_2_patches(csite, dp, rp) ! ! !LOCAL VARIABLES: - type (ed_cohort_type), pointer :: currentCohort ! Current Cohort - type (ed_cohort_type), pointer :: nextc ! Remembers next cohort in list - type (ed_cohort_type), pointer :: storesmallcohort - type (ed_cohort_type), pointer :: storebigcohort + type (fates_cohort_type), pointer :: currentCohort ! Current Cohort + type (fates_cohort_type), pointer :: nextc ! Remembers next cohort in list + type (fates_cohort_type), pointer :: storesmallcohort + type (fates_cohort_type), pointer :: storebigcohort integer :: c,p !counters for pft and litter size class. integer :: tnull,snull ! are the tallest and shortest cohorts associated? integer :: el ! loop counting index for elements @@ -3017,8 +3017,8 @@ subroutine dealloc_patch(cpatch) type(ed_patch_type) :: cpatch - type(ed_cohort_type), pointer :: ccohort ! current - type(ed_cohort_type), pointer :: ncohort ! next + type(fates_cohort_type), pointer :: ccohort ! current + type(fates_cohort_type), pointer :: ncohort ! next integer :: el ! loop counter for elements ! First Deallocate the cohort space @@ -3097,7 +3097,7 @@ subroutine patch_pft_size_profile(cp_pnt) ! ! !LOCAL VARIABLES: type(ed_patch_type) , pointer :: currentPatch - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort real(r8) :: mind(N_DBH_BINS) ! Bottom of DBH bin real(r8) :: maxd(N_DBH_BINS) ! Top of DBH bin real(r8) :: delta_dbh ! Size of DBH bin diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 5c63524ef0..8c8632d5db 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -49,12 +49,12 @@ module EDPhysiologyMod use FatesLitterMod , only : ilabile use FatesLitterMod , only : ilignin use FatesLitterMod , only : icellulose - use EDTypesMod , only : nclmax + use EDParamsMod , only : nclmax use EDTypesMod , only : AREA,AREA_INV - use EDTypesMod , only : nlevleaf + use EDParamsMod , only : nlevleaf use EDTypesMod , only : num_vegtemp_mem use EDTypesMod , only : maxpft - use EDTypesMod , only : ed_site_type, ed_patch_type, ed_cohort_type + use EDTypesMod , only : ed_site_type, ed_patch_type, fates_cohort_type use EDTypesMod , only : leaves_on use EDTypesMod , only : leaves_off use EDTypesMod , only : min_n_safemath @@ -186,7 +186,7 @@ subroutine ZeroAllocationRates( currentSite ) ! !ARGUMENTS type(ed_site_type), intent(inout), target :: currentSite type(ed_patch_type), pointer :: currentPatch - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort currentPatch => currentSite%youngest_patch do while(associated(currentPatch)) @@ -216,8 +216,8 @@ subroutine GenerateDamageAndLitterFluxes( csite, cpatch, bc_in ) ! Locals - type(ed_cohort_type), pointer :: ccohort ! Current cohort - type(ed_cohort_type), pointer :: ndcohort ! New damage-class cohort + type(fates_cohort_type), pointer :: ccohort ! Current cohort + type(fates_cohort_type), pointer :: ndcohort ! New damage-class cohort type(litter_type), pointer :: litt ! Points to the litter object type(site_fluxdiags_type), pointer :: flux_diags ! pointer to site level flux diagnostics object integer :: cd ! Damage class index @@ -558,7 +558,7 @@ subroutine trim_canopy( currentSite ) type (ed_site_type),intent(inout), target :: currentSite ! ! !LOCAL VARIABLES: - type (ed_cohort_type) , pointer :: currentCohort + type (fates_cohort_type) , pointer :: currentCohort type (ed_patch_type) , pointer :: currentPatch integer :: z ! leaf layer @@ -1255,7 +1255,7 @@ subroutine phenology_leafonoff(currentSite) ! ! !LOCAL VARIABLES: type(ed_patch_type) , pointer :: currentPatch - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort real(r8) :: leaf_c ! leaf carbon [kg] real(r8) :: sapw_c ! sapwood carbon [kg] @@ -1515,7 +1515,7 @@ subroutine satellite_phenology(currentSite, bc_in) ! !LOCAL VARIABLES: type(ed_patch_type) , pointer :: currentPatch - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort real(r8) :: spread ! dummy value of canopy spread to estimate c_area real(r8) :: leaf_c ! leaf carbon estimated to generate target tlai @@ -1630,7 +1630,7 @@ subroutine assign_cohort_SP_properties(currentCohort,htop,tlai,tsai,parea,init,l ! -----------------------------------------------------------------------------------! - type(ed_cohort_type), intent(inout), target :: currentCohort + type(fates_cohort_type), intent(inout), target :: currentCohort real(r8), intent(in) :: tlai ! target leaf area index from SP inputs real(r8), intent(in) :: tsai ! target stem area index from SP inputs @@ -1762,7 +1762,7 @@ subroutine SeedIn( currentSite, bc_in ) type(ed_patch_type), pointer :: currentPatch type(litter_type), pointer :: litt - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort type(site_massbal_type), pointer :: site_mass integer :: pft @@ -1993,7 +1993,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) class(prt_vartypes), pointer :: prt integer :: ft integer :: c - type (ed_cohort_type) , pointer :: temp_cohort + type (fates_cohort_type) , pointer :: temp_cohort type (litter_type), pointer :: litt ! The litter object (carbon right now) type(site_massbal_type), pointer :: site_mass ! For accounting total in-out mass fluxes integer :: cohortstatus @@ -2319,7 +2319,7 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) ! ! !LOCAL VARIABLES: - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort type(site_fluxdiags_type), pointer :: flux_diags type(site_massbal_type), pointer :: site_mass integer :: c @@ -2790,7 +2790,7 @@ subroutine UpdateRecruitL2FR(csite) type(ed_site_type) :: csite type(ed_patch_type), pointer :: cpatch - type(ed_cohort_type), pointer :: ccohort + type(fates_cohort_type), pointer :: ccohort real(r8) :: rec_n(maxpft,nclmax) ! plant count real(r8) :: rec_l2fr0(maxpft,nclmax) ! mean l2fr for this day @@ -2858,7 +2858,7 @@ subroutine UpdateRecruitStoich(csite) type(ed_site_type) :: csite type(ed_patch_type), pointer :: cpatch - type(ed_cohort_type), pointer :: ccohort + type(fates_cohort_type), pointer :: ccohort integer :: ft ! functional type index integer :: cl ! canopy layer index real(r8) :: rec_l2fr_pft ! Actual l2fr of a pft in it's patch @@ -2901,7 +2901,7 @@ subroutine SetRecruitL2FR(csite) type(ed_site_type) :: csite type(ed_patch_type), pointer :: cpatch - type(ed_cohort_type), pointer :: ccohort + type(fates_cohort_type), pointer :: ccohort integer :: ft,cl if(hlm_parteh_mode .ne. prt_cnp_flex_allom_hyp) return diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index a6d7126e4a..47fd652c30 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -96,8 +96,8 @@ module FatesAllometryMod use FatesGlobals , only : fates_log use FatesGlobals , only : endrun => fates_endrun use FatesGlobals , only : FatesWarn,N2S,A2S,I2S - use EDTypesMod , only : nlevleaf, dinc_vai - use EDTypesMod , only : nclmax + use EDParamsMod , only : nlevleaf, dinc_vai + use EDParamsMod , only : nclmax use DamageMainMod , only : GetCrownReduction implicit none diff --git a/biogeochem/FatesLitterMod.F90 b/biogeochem/FatesLitterMod.F90 index be5ec48aa9..5776324430 100644 --- a/biogeochem/FatesLitterMod.F90 +++ b/biogeochem/FatesLitterMod.F90 @@ -36,7 +36,6 @@ module FatesLitterMod use FatesConstantsMod, only : nearzero use FatesConstantsMod, only : calloc_abs_error use FatesConstantsMod, only : fates_unset_r8 - use FatesGlobals , only : endrun => fates_endrun use FatesGlobals , only : fates_log use shr_log_mod , only : errMsg => shr_log_errMsg @@ -55,6 +54,16 @@ module FatesLitterMod integer, public, parameter :: icellulose = 2 ! Array index for cellulose portion integer, public, parameter :: ilignin = 3 ! Array index for the lignin portion + ! SPITFIRE + + integer, parameter, public :: NFSC = NCWD+2 ! number fuel size classes (4 cwd size classes, leaf litter, and grass) + integer, parameter, public :: tw_sf = 1 ! array index of twig pool for spitfire + integer, parameter, public :: lb_sf = 3 ! array index of large branch pool for spitfire + integer, parameter, public :: tr_sf = 4 ! array index of dead trunk pool for spitfire + integer, parameter, public :: dl_sf = 5 ! array index of dead leaf pool for spitfire (dead grass and dead leaves) + integer, parameter, public :: lg_sf = 6 ! array index of live grass pool for spitfire + + type, public :: litter_type diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index ae01df7c93..e29a884fd2 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -41,11 +41,11 @@ module FatesSoilBGCFluxMod use FatesAllometryMod , only : bstore_allom use FatesAllometryMod , only : bbgw_allom use FatesAllometryMod , only : carea_allom - use EDTypesMod , only : p_uptake_mode - use EDTypesMod , only : n_uptake_mode + use EDParamsMod , only : p_uptake_mode + use EDParamsMod , only : n_uptake_mode use EDTypesMod , only : ed_site_type use EDTypesMod , only : ed_patch_type - use EDTypesMod , only : ed_cohort_type + use EDTypesMod , only : fates_cohort_type use EDTypesMod , only : AREA,AREA_INV use FatesInterfaceTypesMod, only : bc_in_type use FatesInterfaceTypesMod, only : bc_out_type @@ -127,7 +127,7 @@ subroutine UnPackNutrientAquisitionBCs(sites, bc_in) integer :: id ! decomp layer index integer :: pft ! pft index type(ed_patch_type), pointer :: cpatch ! current patch pointer - type(ed_cohort_type), pointer :: ccohort ! current cohort pointer + type(fates_cohort_type), pointer :: ccohort ! current cohort pointer real(r8) :: fnrt_c ! fine-root carbon [kg] nsites = size(sites,dim=1) @@ -250,7 +250,7 @@ subroutine PrepCH4BCs(csite,bc_in,bc_out) type(bc_out_type), intent(inout) :: bc_out type(bc_in_type), intent(in) :: bc_in type(ed_patch_type), pointer :: cpatch ! current patch pointer - type(ed_cohort_type), pointer :: ccohort ! current cohort pointer + type(fates_cohort_type), pointer :: ccohort ! current cohort pointer integer :: pft ! plant functional type integer :: fp ! patch index of the site real(r8) :: agnpp ! Above ground daily npp @@ -420,7 +420,7 @@ subroutine PrepNutrientAquisitionBCs(csite, bc_in, bc_out) integer :: id ! decomp index (might == j) integer :: pft ! plant functional type type(ed_patch_type), pointer :: cpatch ! current patch pointer - type(ed_cohort_type), pointer :: ccohort ! current cohort pointer + type(fates_cohort_type), pointer :: ccohort ! current cohort pointer real(r8) :: fnrt_c ! fine-root carbon [kg] real(r8) :: veg_rootc ! fine root carbon in each layer [g/m3] real(r8) :: decompmicc_layer ! Microbial dedcomposer biomass for current layer @@ -533,7 +533,7 @@ subroutine EffluxIntoLitterPools(csite, cpatch, ccohort, bc_in ) ! Arguments type(ed_site_type), intent(inout) :: csite type(ed_patch_type), intent(inout) :: cpatch - type(ed_cohort_type), intent(inout),target :: ccohort + type(fates_cohort_type), intent(inout),target :: ccohort type(bc_in_type), intent(in) :: bc_in ! locals @@ -632,7 +632,7 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) ! !LOCAL VARIABLES: type (ed_patch_type), pointer :: currentPatch - type (ed_cohort_type), pointer :: ccohort + type (fates_cohort_type), pointer :: ccohort real(r8), pointer :: flux_cel_si(:) real(r8), pointer :: flux_lab_si(:) real(r8), pointer :: flux_lig_si(:) diff --git a/biogeophys/EDAccumulateFluxesMod.F90 b/biogeophys/EDAccumulateFluxesMod.F90 index 9756c743f0..3ef45ac742 100644 --- a/biogeophys/EDAccumulateFluxesMod.F90 +++ b/biogeophys/EDAccumulateFluxesMod.F90 @@ -38,7 +38,7 @@ subroutine AccumulateFluxes_ED(nsites, sites, bc_in, bc_out, dt_time) ! ! !USES: - use EDTypesMod , only : ed_patch_type, ed_cohort_type, & + use EDTypesMod , only : ed_patch_type, fates_cohort_type, & ed_site_type, AREA use FatesInterfaceTypesMod , only : bc_in_type,bc_out_type @@ -51,7 +51,7 @@ subroutine AccumulateFluxes_ED(nsites, sites, bc_in, bc_out, dt_time) real(r8), intent(in) :: dt_time ! timestep interval ! ! !LOCAL VARIABLES: - type(ed_cohort_type), pointer :: ccohort ! current cohort + type(fates_cohort_type), pointer :: ccohort ! current cohort type(ed_patch_type) , pointer :: cpatch ! current patch integer :: iv !leaf layer integer :: c ! clm/alm column diff --git a/biogeophys/EDBtranMod.F90 b/biogeophys/EDBtranMod.F90 index 7b803469e5..89deb8c4d0 100644 --- a/biogeophys/EDBtranMod.F90 +++ b/biogeophys/EDBtranMod.F90 @@ -11,7 +11,7 @@ module EDBtranMod use FatesConstantsMod , only : nocomp_bareground use EDTypesMod , only : ed_site_type, & ed_patch_type, & - ed_cohort_type, & + fates_cohort_type, & maxpft use shr_kind_mod , only : r8 => shr_kind_r8 use FatesInterfaceTypesMod , only : bc_in_type, & @@ -111,7 +111,7 @@ subroutine btran_ed( nsites, sites, bc_in, bc_out) ! ! !LOCAL VARIABLES: type(ed_patch_type),pointer :: cpatch ! Current Patch Pointer - type(ed_cohort_type),pointer :: ccohort ! Current cohort pointer + type(fates_cohort_type),pointer :: ccohort ! Current cohort pointer integer :: s ! site integer :: j ! soil layer integer :: ifp ! patch vector index for the site diff --git a/biogeophys/EDSurfaceAlbedoMod.F90 b/biogeophys/EDSurfaceAlbedoMod.F90 index 48b9d1e448..360abf38cd 100644 --- a/biogeophys/EDSurfaceAlbedoMod.F90 +++ b/biogeophys/EDSurfaceAlbedoMod.F90 @@ -20,15 +20,15 @@ module EDSurfaceRadiationMod use FatesInterfaceTypesMod , only : bc_out_type use FatesInterfaceTypesMod , only : hlm_numSWb use FatesInterfaceTypesMod , only : numpft - use EDTypesMod , only : maxSWb - use EDTypesMod , only : nclmax - use EDTypesMod , only : nlevleaf + use EDParamsMod , only : maxSWb + use EDParamsMod , only : nclmax + use EDParamsMod , only : nlevleaf use EDTypesMod , only : n_rad_stream_types use EDTypesMod , only : idiffuse use EDTypesMod , only : idirect - use EDTypesMod , only : ivis - use EDTypesMod , only : inir - use EDTypesMod , only : ipar + use EDParamsMod , only : ivis + use EDParamsMod , only : inir + use EDParamsMod , only : ipar use EDCanopyStructureMod, only: calc_areaindex use FatesGlobals , only : fates_log use FatesGlobals, only : endrun => fates_endrun diff --git a/biogeophys/FatesBstressMod.F90 b/biogeophys/FatesBstressMod.F90 index c56b4930f5..f160612633 100644 --- a/biogeophys/FatesBstressMod.F90 +++ b/biogeophys/FatesBstressMod.F90 @@ -9,7 +9,7 @@ module FatesBstressMod use FatesConstantsMod , only : itrue,ifalse use EDTypesMod , only : ed_site_type, & ed_patch_type, & - ed_cohort_type, & + fates_cohort_type, & maxpft use shr_kind_mod , only : r8 => shr_kind_r8 use FatesInterfaceTypesMod , only : bc_in_type, & @@ -49,7 +49,7 @@ subroutine btran_sal_stress_fates( nsites, sites, bc_in) ! ! !LOCAL VARIABLES: type(ed_patch_type),pointer :: cpatch ! Current Patch Pointer - type(ed_cohort_type),pointer :: ccohort ! Current cohort pointer + type(fates_cohort_type),pointer :: ccohort ! Current cohort pointer integer :: s ! site integer :: j ! soil layer integer :: ft ! plant functional type index diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 285dc98702..4846336c9f 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -53,10 +53,10 @@ module FatesPlantHydraulicsMod use EDTypesMod , only : ed_site_type use EDTypesMod , only : ed_patch_type - use EDTypesMod , only : ed_cohort_type + use EDTypesMod , only : fates_cohort_type use EDTypesMod , only : AREA_INV use EDTypesMod , only : AREA - use EDTypesMod , only : leaves_on + use EDParamsMod , only : leaves_on use FatesInterfaceTypesMod , only : bc_in_type use FatesInterfaceTypesMod , only : bc_out_type @@ -337,7 +337,7 @@ subroutine RestartHydrStates(sites,nsites,bc_in,bc_out) ! ---------------------------------------------------------------------------------- ! LL pointers type(ed_patch_type),pointer :: cpatch ! current patch - type(ed_cohort_type),pointer :: ccohort ! current cohort + type(fates_cohort_type),pointer :: ccohort ! current cohort type(ed_cohort_hydr_type),pointer :: ccohort_hydr type(ed_site_hydr_type),pointer :: csite_hydr integer :: s ! site loop counter @@ -533,7 +533,7 @@ subroutine InitPlantHydStates(site, cohort) ! !ARGUMENTS: type(ed_site_type), intent(inout), target :: site ! current site pointer - type(ed_cohort_type), intent(inout), target :: cohort ! current cohort pointer + type(fates_cohort_type), intent(inout), target :: cohort ! current cohort pointer ! ! !LOCAL VARIABLES: type(ed_site_hydr_type), pointer :: csite_hydr @@ -682,7 +682,7 @@ subroutine UpdatePlantPsiFTCFromTheta(ccohort,csite_hydr) ! of total conductivity based on the relative water ! content ! Arguments - type(ed_cohort_type),intent(inout), target :: ccohort + type(fates_cohort_type),intent(inout), target :: ccohort type(ed_site_hydr_type),intent(in), target :: csite_hydr ! Locals @@ -742,7 +742,7 @@ subroutine UpdatePlantHydrNodes(ccohort,ft,plant_height,csite_hydr) ! -------------------------------------------------------------------------------- ! Arguments - type(ed_cohort_type), intent(inout) :: ccohort + type(fates_cohort_type), intent(inout) :: ccohort integer,intent(in) :: ft ! plant functional type index real(r8), intent(in) :: plant_height ! [m] type(ed_site_hydr_type), intent(in) :: csite_hydr @@ -845,7 +845,7 @@ subroutine UpdateSizeDepPlantHydProps(currentSite,ccohort,bc_in) ! ARGUMENTS: type(ed_site_type) , intent(in) :: currentSite ! Site stuff - type(ed_cohort_type) , intent(inout) :: ccohort ! current cohort pointer + type(fates_cohort_type) , intent(inout) :: ccohort ! current cohort pointer type(bc_in_type) , intent(in) :: bc_in ! Boundary Conditions ! Locals @@ -894,7 +894,7 @@ subroutine UpdatePlantHydrLenVol(ccohort,csite_hydr) ! ----------------------------------------------------------------------------------- ! Arguments - type(ed_cohort_type),intent(inout) :: ccohort + type(fates_cohort_type),intent(inout) :: ccohort type(ed_site_hydr_type),intent(in) :: csite_hydr type(ed_cohort_hydr_type),pointer :: ccohort_hydr ! Plant hydraulics structure @@ -1096,7 +1096,7 @@ subroutine UpdateSizeDepPlantHydStates(currentSite,ccohort) ! !ARGUMENTS: type(ed_site_type) , intent(in) :: currentSite ! Site stuff - type(ed_cohort_type) , intent(inout) :: ccohort + type(fates_cohort_type) , intent(inout) :: ccohort ! ! !LOCAL VARIABLES: type(ed_cohort_hydr_type), pointer :: ccohort_hydr @@ -1198,8 +1198,8 @@ end function constrain_water_contents subroutine CopyCohortHydraulics(newCohort, oldCohort) ! Arguments - type(ed_cohort_type), intent(inout), target :: newCohort - type(ed_cohort_type), intent(inout), target :: oldCohort + type(fates_cohort_type), intent(inout), target :: newCohort + type(fates_cohort_type), intent(inout), target :: oldCohort ! Locals type(ed_cohort_hydr_type), pointer :: ncohort_hydr @@ -1266,8 +1266,8 @@ end subroutine CopyCohortHydraulics subroutine FuseCohortHydraulics(currentSite,currentCohort, nextCohort, bc_in, newn) - type(ed_cohort_type), intent(inout), target :: currentCohort ! current cohort - type(ed_cohort_type), intent(inout), target :: nextCohort ! next (donor) cohort + type(fates_cohort_type), intent(inout), target :: currentCohort ! current cohort + type(fates_cohort_type), intent(inout), target :: nextCohort ! next (donor) cohort type(ed_site_type), intent(inout), target :: currentSite ! current site type(bc_in_type), intent(in) :: bc_in @@ -1372,7 +1372,7 @@ subroutine InitHydrCohort(currentSite,currentCohort) ! Arguments type(ed_site_type), target :: currentSite - type(ed_cohort_type), target :: currentCohort + type(fates_cohort_type), target :: currentCohort type(ed_cohort_hydr_type), pointer :: ccohort_hydr if ( hlm_use_planthydro.eq.ifalse ) return @@ -1388,7 +1388,7 @@ end subroutine InitHydrCohort subroutine DeallocateHydrCohort(currentCohort) ! Arguments - type(ed_cohort_type), target :: currentCohort + type(fates_cohort_type), target :: currentCohort type(ed_cohort_hydr_type), pointer :: ccohort_hydr if ( hlm_use_planthydro.eq.ifalse ) return @@ -1776,7 +1776,7 @@ subroutine UpdateH2OVeg(csite,bc_out,prev_site_h2o,icall) ! Locals - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort type(ed_patch_type), pointer :: currentPatch type(ed_cohort_hydr_type), pointer :: ccohort_hydr type(ed_site_hydr_type), pointer :: csite_hydr @@ -1859,7 +1859,7 @@ subroutine RecruitWUptake(nsites,sites,bc_in,dtime,recruitflag) logical, intent(out) :: recruitflag !flag to check if there is newly recruited cohorts ! Locals - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort type(ed_patch_type), pointer :: currentPatch type(ed_cohort_hydr_type), pointer :: ccohort_hydr type(ed_site_hydr_type), pointer :: csite_hydr @@ -1934,7 +1934,7 @@ subroutine ConstrainRecruitNumber(csite,ccohort, bc_in) ! Arguments type(ed_site_type), intent(inout), target :: csite - type(ed_cohort_type) , intent(inout), target :: ccohort + type(fates_cohort_type) , intent(inout), target :: ccohort type(bc_in_type) , intent(in) :: bc_in ! Locals @@ -2061,7 +2061,7 @@ subroutine UpdateSizeDepRhizVolLenCon(currentSite, bc_in) ! !LOCAL VARIABLES: type(ed_site_hydr_type), pointer :: csite_hydr type(ed_patch_type) , pointer :: cPatch - type(ed_cohort_type) , pointer :: cCohort + type(fates_cohort_type) , pointer :: cCohort type(ed_cohort_hydr_type), pointer :: ccohort_hydr real(r8) :: hksat_s ! hksat converted to units of 10^6sec ! which is equiv to [kg m-1 s-1 MPa-1] @@ -2198,7 +2198,7 @@ subroutine BTranForHLMDiagnosticsFromCohortHydr(nsites,sites,bc_out) integer :: ifp real(r8) :: balive_patch type(ed_patch_type),pointer :: cpatch - type(ed_cohort_type),pointer :: ccohort + type(fates_cohort_type),pointer :: ccohort do s = 1,nsites @@ -2428,7 +2428,7 @@ subroutine hydraulics_bc ( nsites, sites, bc_in, bc_out, dtime) !---------------------------------------------------------------------- type (ed_patch_type), pointer :: cpatch ! current patch pointer - type (ed_cohort_type), pointer :: ccohort ! current cohort pointer + type (fates_cohort_type), pointer :: ccohort ! current cohort pointer type(ed_site_hydr_type), pointer :: csite_hydr ! site hydraulics pointer type(ed_cohort_hydr_type), pointer :: ccohort_hydr ! cohort hydraulics pointer @@ -2943,7 +2943,7 @@ subroutine UpdatePlantKmax(ccohort_hydr,ccohort,csite_hydr) ! Arguments type(ed_cohort_hydr_type),intent(inout),target :: ccohort_hydr - type(ed_cohort_type),intent(in),target :: ccohort + type(fates_cohort_type),intent(in),target :: ccohort type(ed_site_hydr_type),intent(in),target :: csite_hydr ! Locals @@ -3153,7 +3153,7 @@ subroutine OrderLayersForSolve1D(csite_hydr,cohort,cohort_hydr,ordered, kbg_laye ! Arguments (IN) type(ed_site_hydr_type), intent(in),target :: csite_hydr - type(ed_cohort_type), intent(in),target :: cohort + type(fates_cohort_type), intent(in),target :: cohort type(ed_cohort_hydr_type),intent(in),target :: cohort_hydr @@ -3295,7 +3295,7 @@ subroutine ImTaylorSolve1D(slat, slon,recruitflag,csite_hydr,cohort,cohort_hydr, real(r8), intent(in) :: slat ! latitidue of the site real(r8), intent(in) :: slon ! longitidue of the site logical, intent(in) :: recruitflag - type(ed_cohort_type),intent(in),target :: cohort + type(fates_cohort_type),intent(in),target :: cohort type(ed_cohort_hydr_type),intent(inout),target :: cohort_hydr type(ed_site_hydr_type), intent(in),target :: csite_hydr real(r8), intent(in) :: dtime @@ -3988,7 +3988,7 @@ subroutine Report1DError(cohort, csite_hydr, ilayer, z_node, v_node, & ! like, and then quits. ! Arguments (IN) - type(ed_cohort_type),intent(in),target :: cohort + type(fates_cohort_type),intent(in),target :: cohort type(ed_site_hydr_type),intent(in), target :: csite_hydr integer, intent(in) :: ilayer ! soil layer index of interest real(r8), intent(in) :: z_node(:) ! elevation of nodes @@ -4301,7 +4301,7 @@ subroutine AccumulateMortalityWaterStorage(csite,ccohort,delta_n) ! Arguments type(ed_site_type), intent(inout), target :: csite - type(ed_cohort_type) , intent(inout), target :: ccohort + type(fates_cohort_type) , intent(inout), target :: ccohort real(r8), intent(in) :: delta_n ! Loss in number density ! for this cohort /ha/day @@ -4345,7 +4345,7 @@ subroutine RecruitWaterStorage(nsites,sites,bc_out) type(bc_out_type), intent(inout) :: bc_out(nsites) ! Locals - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort type(ed_patch_type), pointer :: currentPatch type(ed_cohort_hydr_type), pointer :: ccohort_hydr type(ed_site_hydr_type), pointer :: csite_hydr @@ -4795,7 +4795,7 @@ subroutine MatSolve2D(csite_hydr,cohort,cohort_hydr, & ! ----------------------------------------------------------------------------------- type(ed_site_hydr_type), intent(inout),target :: csite_hydr ! ED csite_hydr structure type(ed_cohort_hydr_type), target :: cohort_hydr - type(ed_cohort_type) , intent(inout), target :: cohort + type(fates_cohort_type) , intent(inout), target :: cohort real(r8),intent(in) :: tmx ! time interval to integrate over [s] real(r8),intent(in) :: qtop real(r8),intent(out) :: sapflow ! time integrated mass flux between transp-root and stem [kg] @@ -5564,7 +5564,7 @@ subroutine PicardSolve2D(csite_hydr,cohort,cohort_hydr, & ! ----------------------------------------------------------------------------------- type(ed_site_hydr_type), intent(inout),target :: csite_hydr ! ED csite_hydr structure type(ed_cohort_hydr_type), target :: cohort_hydr - type(ed_cohort_type) , intent(inout), target :: cohort + type(fates_cohort_type) , intent(inout), target :: cohort real(r8),intent(in) :: tmx ! time interval to integrate over [s] real(r8),intent(in) :: qtop integer :: nnode !total number of nodes diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index fa1228b733..74f93e67ce 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -127,7 +127,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) use FatesSynchronizedParamsMod , only : FatesSynchronizedParamsInst use EDTypesMod , only : ed_patch_type - use EDTypesMod , only : ed_cohort_type + use EDTypesMod , only : fates_cohort_type use EDTypesMod , only : ed_site_type use EDTypesMod , only : maxpft use EDTypesMod , only : dinc_vai @@ -161,7 +161,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! LOCAL VARIABLES: ! ----------------------------------------------------------------------------------- type (ed_patch_type) , pointer :: currentPatch - type (ed_cohort_type), pointer :: currentCohort + type (fates_cohort_type), pointer :: currentCohort ! ----------------------------------------------------------------------------------- ! These three arrays hold leaf-level biophysical rates that are calculated @@ -1893,11 +1893,11 @@ subroutine UpdateCanopyNCanNRadPresent(currentPatch) use EDTypesMod , only : ed_patch_type - use EDTypesMod , only : ed_cohort_type + use EDTypesMod , only : fates_cohort_type ! Arguments type(ed_patch_type), target :: currentPatch - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort ! Locals integer :: cl ! Canopy Layer Index diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index 16aca5d243..7090decc90 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -25,15 +25,15 @@ module SFMainMod use PRTGenericMod , only : element_pos use EDtypesMod , only : ed_site_type use EDtypesMod , only : ed_patch_type - use EDtypesMod , only : ed_cohort_type + use EDtypesMod , only : fates_cohort_type use EDtypesMod , only : AREA - use EDtypesMod , only : DL_SF - use EDTypesMod , only : TW_SF - use EDtypesMod , only : LB_SF - use EDtypesMod , only : LG_SF + use FatesLitterMod , only : DL_SF + use FatesLitterMod , only : TW_SF + use FatesLitterMod , only : LB_SF + use FatesLitterMod , only : LG_SF use FatesLitterMod , only : ncwd - use EDtypesMod , only : NFSC - use EDtypesMod , only : TR_SF + use FatesLitterMod , only : NFSC + use FatesLitterMod , only : TR_SF use FatesLitterMod , only : litter_type use PRTGenericMod, only : leaf_organ @@ -182,7 +182,7 @@ subroutine charecteristics_of_fuel ( currentSite ) type(ed_site_type), intent(in), target :: currentSite type(ed_patch_type), pointer :: currentPatch - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort type(litter_type), pointer :: litt_c real(r8) alpha_FMC(nfsc) ! Relative fuel moisture adjusted per drying ratio @@ -358,7 +358,7 @@ subroutine wind_effect ( currentSite, bc_in) type(bc_in_type) , intent(in) :: bc_in type(ed_patch_type) , pointer :: currentPatch - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort real(r8) :: total_grass_area ! per patch,in m2 real(r8) :: tree_fraction ! site level. no units @@ -896,7 +896,7 @@ subroutine crown_scorching ( currentSite ) type(ed_site_type), intent(in), target :: currentSite type(ed_patch_type), pointer :: currentPatch - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort real(r8) :: tree_ag_biomass ! total amount of above-ground tree biomass in patch. kgC/m2 real(r8) :: leaf_c ! leaf carbon [kg] @@ -960,7 +960,7 @@ subroutine crown_damage ( currentSite ) type(ed_site_type), intent(in), target :: currentSite type(ed_patch_type) , pointer :: currentPatch - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort real(r8) :: crown_depth ! Depth of crown in meters currentPatch => currentSite%oldest_patch @@ -1027,7 +1027,7 @@ subroutine cambial_damage_kill ( currentSite ) type(ed_site_type), intent(in), target :: currentSite type(ed_patch_type) , pointer :: currentPatch - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort real(r8) :: tau_c !critical time taken to kill cambium (minutes) real(r8) :: bt !bark thickness in cm. @@ -1083,7 +1083,7 @@ subroutine post_fire_mortality ( currentSite ) type(ed_site_type), intent(in), target :: currentSite type(ed_patch_type), pointer :: currentPatch - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort currentPatch => currentSite%oldest_patch diff --git a/fire/SFParamsMod.F90 b/fire/SFParamsMod.F90 index 65849f829d..306034a804 100644 --- a/fire/SFParamsMod.F90 +++ b/fire/SFParamsMod.F90 @@ -4,7 +4,7 @@ module SFParamsMod ! use FatesConstantsMod , only: r8 => fates_r8 use FatesConstantsMod , only: fates_check_param_set - use EDtypesMod , only: NFSC + use FatesLitterMod , only: NFSC use FatesLitterMod , only: ncwd use FatesParametersInterface, only : param_string_length use FatesGlobals, only : fates_log diff --git a/functional_unit_testing/parteh/f90src/FatesCohortWrapMod.F90 b/functional_unit_testing/parteh/f90src/FatesCohortWrapMod.F90 index 6238111e30..9f520593b3 100644 --- a/functional_unit_testing/parteh/f90src/FatesCohortWrapMod.F90 +++ b/functional_unit_testing/parteh/f90src/FatesCohortWrapMod.F90 @@ -78,7 +78,7 @@ module FatesCohortWrapMod implicit none private ! Modules are private by default - type, public :: ed_cohort_type + type, public :: fates_cohort_type integer :: pft ! pft number real(r8) :: dbh ! dbh: cm @@ -106,11 +106,11 @@ module FatesCohortWrapMod ! Multi-species, multi-pool Reactive Transport class(prt_vartypes), pointer :: prt - end type ed_cohort_type + end type fates_cohort_type ! Global Instances - type(ed_cohort_type), pointer, public :: cohort_array(:) + type(fates_cohort_type), pointer, public :: cohort_array(:) integer, public :: numcohort character(len=*), parameter, private :: sourcefile = __FILE__ @@ -132,7 +132,7 @@ subroutine CohortInitAlloc(numcohorts) ! Locals integer(i4) :: ico - type(ed_cohort_type), pointer :: ccohort + type(fates_cohort_type), pointer :: ccohort allocate(cohort_array(numcohorts)) @@ -189,7 +189,7 @@ subroutine CohortPySet(ipft,hgt_min,canopy_trim) ! Locals - type(ed_cohort_type), pointer :: ccohort ! Current cohort + type(fates_cohort_type), pointer :: ccohort ! Current cohort real(r8) :: leaf_c real(r8) :: fnrt_c real(r8) :: sapw_c @@ -376,7 +376,7 @@ subroutine WrapDailyPRT(ipft,daily_carbon_gain,canopy_trim,flush_c,drop_frac_c,l real(r8), intent(in), optional :: daily_phosphorus_gain real(r8), intent(in), optional :: daily_r_maint_demand - type(ed_cohort_type), pointer :: ccohort + type(fates_cohort_type), pointer :: ccohort logical, parameter :: is_drought = .false. ccohort => cohort_array(ipft) @@ -443,7 +443,7 @@ subroutine WrapQueryVars(ipft,crowndamage, leaf_area,crown_area,agb,store_c,targ real(r8),intent(out) :: target_leaf_c real(r8) :: leaf_c - type(ed_cohort_type), pointer :: ccohort + type(fates_cohort_type), pointer :: ccohort real(r8),parameter :: nplant = 1.0_r8 real(r8),parameter :: site_spread = 1.0_r8 @@ -540,7 +540,7 @@ subroutine WrapQueryDiagnostics(ipft, dbh, & real(r8),intent(out) :: growth_resp real(r8),intent(out) :: crown_area - type(ed_cohort_type), pointer :: ccohort + type(fates_cohort_type), pointer :: ccohort real(r8),parameter :: nplant = 1.0_r8 real(r8),parameter :: site_spread = 1.0_r8 diff --git a/main/ChecksBalancesMod.F90 b/main/ChecksBalancesMod.F90 index ab76715fe6..8c867219b1 100644 --- a/main/ChecksBalancesMod.F90 +++ b/main/ChecksBalancesMod.F90 @@ -4,7 +4,7 @@ module ChecksBalancesMod use shr_const_mod, only : SHR_CONST_CDAY use EDtypesMod, only : ed_site_type use EDTypesMod, only : ed_patch_type - use EDTypesMod, only : ed_cohort_type + use EDTypesMod, only : fates_cohort_type use EDTypesMod, only : AREA use EDTypesMod, only : site_massbal_type use PRTGenericMod, only : num_elements @@ -49,7 +49,7 @@ subroutine SiteMassStock(currentSite,el,total_stock,biomass_stock,litter_stock,s real(r8),intent(out) :: biomass_stock ! kg real(r8),intent(out) :: seed_stock ! kg type(ed_patch_type), pointer :: currentPatch - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort real(r8) :: patch_biomass ! kg real(r8) :: patch_seed ! kg real(r8) :: patch_litter ! kg @@ -88,7 +88,7 @@ subroutine PatchMassStock(currentPatch,el,live_stock,seed_stock,litter_stock) real(r8),intent(out) :: litter_stock type(litter_type), pointer :: litt ! litter object - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort integer :: element_id litt => currentPatch%litter(el) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 45b3ac7551..f02653ef5c 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -23,7 +23,7 @@ module EDInitMod use EDPhysiologyMod , only : assign_cohort_sp_properties use ChecksBalancesMod , only : SiteMassStock use FatesInterfaceTypesMod , only : hlm_day_of_year - use EDTypesMod , only : ed_site_type, ed_patch_type, ed_cohort_type + use EDTypesMod , only : ed_site_type, ed_patch_type, fates_cohort_type use EDTypesMod , only : numWaterMem use EDTypesMod , only : num_vegtemp_mem use EDTypesMod , only : maxpft @@ -748,7 +748,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) type(bc_in_type), intent(in) :: bc_in ! ! !LOCAL VARIABLES: - type(ed_cohort_type),pointer :: temp_cohort + type(fates_cohort_type),pointer :: temp_cohort class(prt_vartypes),pointer :: prt_obj integer :: cstatus integer :: pft diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 427a687f8c..0912b05655 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -66,7 +66,7 @@ module EDMainMod use FatesLitterMod , only : ncwd use EDtypesMod , only : ed_site_type use EDtypesMod , only : ed_patch_type - use EDtypesMod , only : ed_cohort_type + use EDtypesMod , only : fates_cohort_type use EDTypesMod , only : AREA use EDTypesMod , only : site_massbal_type use PRTGenericMod , only : num_elements @@ -178,7 +178,7 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) call IsItLoggingTime(hlm_masterproc,currentSite) ! Call a routine that identifies if damage should occur - call IsItDamageTime(hlm_masterproc, currentSite) + call IsItDamageTime(hlm_masterproc) !************************************************************************** ! Fire, growth, biogeochemistry. @@ -356,10 +356,10 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! !LOCAL VARIABLES: type(site_massbal_type), pointer :: site_cmass type(ed_patch_type) , pointer :: currentPatch - type(ed_cohort_type) , pointer :: currentCohort - type(ed_cohort_type) , pointer :: nc - type(ed_cohort_type) , pointer :: storesmallcohort - type(ed_cohort_type) , pointer :: storebigcohort + type(fates_cohort_type) , pointer :: currentCohort + type(fates_cohort_type) , pointer :: nc + type(fates_cohort_type) , pointer :: storesmallcohort + type(fates_cohort_type) , pointer :: storebigcohort integer :: snull integer :: tnull @@ -887,7 +887,7 @@ subroutine TotalBalanceCheck (currentSite, call_index ) ! we can account for the changing areas of patches. type(ed_patch_type) , pointer :: currentPatch - type(ed_cohort_type) , pointer :: currentCohort + type(fates_cohort_type) , pointer :: currentCohort type(litter_type), pointer :: litt logical, parameter :: print_cohorts = .true. ! Set to true if you want ! to print cohort data @@ -1042,7 +1042,7 @@ subroutine bypass_dynamics(currentSite) ! Locals type(ed_patch_type), pointer :: currentPatch - type(ed_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort currentPatch => currentSite%youngest_patch do while(associated(currentPatch)) diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 40edc6a0b8..a9bdf7ab59 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -9,6 +9,7 @@ module EDParamsMod use FatesParametersInterface, only : param_string_length use FatesGlobals , only : fates_log use FatesGlobals , only : endrun => fates_endrun + use FatesConstantsMod, only : fates_unset_r8 ! CIME Globals use shr_log_mod , only : errMsg => shr_log_errMsg @@ -71,6 +72,46 @@ module EDParamsMod ! empirical curvature parameters for ac, aj photosynthesis co-limitation, c3 and c4 plants respectively real(r8),protected,public :: theta_cj_c3 real(r8),protected,public :: theta_cj_c4 + + ! Global identifier of how nutrients interact with the host land model + ! either they are fully coupled, or they generate uptake rates synthetically + ! in prescribed mode. In the latter, there is both NO mass removed from the HLM's soil + ! BGC N and P pools, and there is also none removed. + + integer, public :: n_uptake_mode + integer, public :: p_uptake_mode + + integer, parameter, public :: nclmax = 2 ! Maximum number of canopy layers + + ! parameters that govern the VAI (LAI+SAI) bins used in radiative transfer code + integer, parameter, public :: nlevleaf = 30 ! number of leaf+stem layers in each canopy layer + + real(r8), public :: dinc_vai(nlevleaf) = fates_unset_r8 ! VAI bin widths array + real(r8), public :: dlower_vai(nlevleaf) = fates_unset_r8 ! lower edges of VAI bins + + ! TODO: we use this cp_maxSWb only because we have a static array q(size=2) of + ! land-ice abledo for vis and nir. This should be a parameter, which would + ! get us on track to start using multi-spectral or hyper-spectral (RGK 02-2017) + + integer, parameter, public :: maxSWb = 2 ! maximum number of broad-bands in the + ! shortwave spectrum cp_numSWb <= cp_maxSWb + ! this is just for scratch-array purposes + ! if cp_numSWb is larger than this value + ! simply bump this number up as needed + +integer, parameter, public :: ivis = 1 ! This is the array index for short-wave + ! radiation in the visible spectrum, as expected + ! in boundary condition files and parameter + ! files. This will be compared with + ! the HLM's expectation in FatesInterfaceMod +integer, parameter, public :: inir = 2 ! This is the array index for short-wave + ! radiation in the near-infrared spectrum, as expected + ! in boundary condition files and parameter + ! files. This will be compared with + ! the HLM's expectation in FatesInterfaceMod + +integer, parameter, public :: ipar = ivis ! The photosynthetically active band + ! can be approximated to be equal to the visible band 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) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 96c3fddf93..c55a6b955a 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -6,8 +6,8 @@ module EDPftvarcon ! read and initialize vegetation (PFT) constants. ! ! !USES: - use EDTypesMod , only : maxSWb, ivis, inir - use EDTypesMod , only : n_uptake_mode, p_uptake_mode + use EDParamsMod , only : maxSWb, ivis, inir + use EDParamsMod , only : n_uptake_mode, p_uptake_mode use FatesConstantsMod, only : r8 => fates_r8 use FatesConstantsMod, only : nearzero use FatesConstantsMod, only : itrue, ifalse diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 258849c066..a7f7b25fa1 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -1,39 +1,39 @@ module EDTypesMod use FatesConstantsMod, only : r8 => fates_r8 + use FatesGlobals, only : endrun => fates_endrun use FatesConstantsMod, only : ifalse use FatesConstantsMod, only : itrue use FatesGlobals, only : fates_log - use FatesCohortMod, only : fates_cohort_type - use FatesCohortMod, only : nlevleaf use FatesHydraulicsMemMod, only : ed_cohort_hydr_type use FatesHydraulicsMemMod, only : ed_site_hydr_type use PRTGenericMod, only : prt_vartypes use PRTGenericMod, only : leaf_organ, fnrt_organ, sapw_organ use PRTGenericMod, only : repro_organ, store_organ, struct_organ + use PRTGenericMod, only : prt_carbon_allom_hyp + use PRTGenericMod, only : prt_cnp_flex_allom_hyp use PRTGenericMod, only : num_organ_types use PRTGenericMod, only : num_elements use PRTGenericMod, only : element_list use PRTGenericMod, only : num_element_types use PRTGenericMod, only : carbon12_element use FatesLitterMod, only : litter_type - use FatesLitterMod, only : ncwd + use FatesLitterMod, only : ncwd, NFSC use FatesConstantsMod, only : n_anthro_disturbance_categories use FatesConstantsMod, only : days_per_year use FatesConstantsMod, only : fates_unset_r8 use FatesRunningMeanMod, only : rmean_type use FatesInterfaceTypesMod,only : bc_in_type use FatesInterfaceTypesMod,only : bc_out_type + use FatesInterfaceTypesMod,only : hlm_parteh_mode + use EDParamsMod, only : maxSWb, nclmax, nlevleaf + use shr_log_mod, only : errMsg => shr_log_errMsg implicit none private ! By default everything is private save - integer, parameter, public :: nclmax = 2 ! Maximum number of canopy layers - - - integer, parameter, public :: maxpft = 16 ! maximum number of PFTs allowed ! the parameter file may determine that fewer ! are used, but this helps allocate scratch @@ -49,42 +49,19 @@ module EDTypesMod ! ------------------------------------------------------------------------------------- + + integer, parameter, public :: ican_upper = 1 ! nominal index for the upper canopy + integer, parameter, public :: ican_ustory = 2 ! nominal index for diagnostics that refer to understory layers + ! (all layers that are not the top canopy layer) + + integer, parameter, public :: n_rad_stream_types = 2 ! The number of radiation streams used (direct/diffuse) integer, parameter, public :: idirect = 1 ! This is the array index for direct radiation integer, parameter, public :: idiffuse = 2 ! This is the array index for diffuse radiation - real(r8), public :: dinc_vai(nlevleaf) = fates_unset_r8 ! VAI bin widths array - real(r8), public :: dlower_vai(nlevleaf) = fates_unset_r8 ! lower edges of VAI bins - - ! TODO: we use this cp_maxSWb only because we have a static array q(size=2) of - ! land-ice abledo for vis and nir. This should be a parameter, which would - ! get us on track to start using multi-spectral or hyper-spectral (RGK 02-2017) - - integer, parameter, public :: maxSWb = 2 ! maximum number of broad-bands in the - ! shortwave spectrum cp_numSWb <= cp_maxSWb - ! this is just for scratch-array purposes - ! if cp_numSWb is larger than this value - ! simply bump this number up as needed - - integer, parameter, public :: ivis = 1 ! This is the array index for short-wave - ! radiation in the visible spectrum, as expected - ! in boundary condition files and parameter - ! files. This will be compared with - ! the HLM's expectation in FatesInterfaceMod - integer, parameter, public :: inir = 2 ! This is the array index for short-wave - ! radiation in the near-infrared spectrum, as expected - ! in boundary condition files and parameter - ! files. This will be compared with - ! the HLM's expectation in FatesInterfaceMod - - integer, parameter, public :: ipar = ivis ! The photosynthetically active band - ! can be approximated to be equal to the visible band - - - - ! Flag to turn on/off salinity effects on the effective "btran" + ! Flag to turn on/off salinity effects on the effective "btran" ! btran stress function. logical, parameter, public :: do_fates_salinity = .false. @@ -134,16 +111,6 @@ module EDTypesMod integer, parameter, public :: phen_dstat_moiston = 2 ! Leaves on due to moisture avail (drought phenology) integer, parameter, public :: phen_dstat_timeon = 3 ! Leaves on due to time exceedance (drought phenology) - - ! SPITFIRE - - integer, parameter, public :: NFSC = NCWD+2 ! number fuel size classes (4 cwd size classes, leaf litter, and grass) - integer, parameter, public :: tw_sf = 1 ! array index of twig pool for spitfire - integer, parameter, public :: lb_sf = 3 ! array index of large branch pool for spitfire - integer, parameter, public :: tr_sf = 4 ! array index of dead trunk pool for spitfire - integer, parameter, public :: dl_sf = 5 ! array index of dead leaf pool for spitfire (dead grass and dead leaves) - integer, parameter, public :: lg_sf = 6 ! array index of live grass pool for spitfire - ! PATCH FUSION real(r8), parameter, public :: force_patchfuse_min_biomass = 0.005_r8 ! min biomass (kg / m2 patch area) below which to force-fuse patches integer , parameter, public :: N_DBH_BINS = 6 ! no. of dbh bins used when comparing patches @@ -171,15 +138,229 @@ module EDTypesMod ! special mode to cause PFTs to create seed mass of all currently-existing PFTs logical, parameter, public :: homogenize_seed_pfts = .false. + character(len=*), parameter, private :: sourcefile = __FILE__ - ! Global identifier of how nutrients interact with the host land model - ! either they are fully coupled, or they generate uptake rates synthetically - ! in prescribed mode. In the latter, there is both NO mass removed from the HLM's soil - ! BGC N and P pools, and there is also none removed. + type, public :: fates_cohort_type + + ! POINTERS + type (fates_cohort_type), pointer :: taller => null() ! pointer to next tallest cohort + type (fates_cohort_type), pointer :: shorter => null() ! pointer to next shorter cohort + + !:.........................................................................: + + ! Multi-species, multi-organ Plant Reactive Transport (PRT) + ! Contains carbon and nutrient state variables for various plant organs + class(prt_vartypes), pointer :: prt + real(r8) :: l2fr ! leaf to fineroot biomass ratio (this is constant + ! in carbon only simulationss, and is set by the + ! allom_l2fr_min parameter. In nutrient + ! enabled simulations, this is dynamic, will + ! vary between allom_l2fr_min and allom_l2fr_max + ! parameters, with a tendency driven by + ! nutrient storage) [kg root / kg leaf] + + !:.........................................................................: + + ! VEGETATION STRUCTURE + + integer :: pft ! pft index + real(r8) :: n ! number of individuals in cohort per 'area' (10000m2 default) [/m2] + real(r8) :: dbh ! diameter at breast height [cm] + real(r8) :: coage ! age [years] + real(r8) :: hite ! height [m] + integer :: indexnumber ! unique number for each cohort (within clump?) + integer :: canopy_layer ! canopy status of cohort [1 = canopy, 2 = understorey, etc.] + real(r8) :: canopy_layer_yesterday ! recent canopy status of cohort [1 = canopy, 2 = understorey, etc.] + ! real to be conservative during fusion + integer :: crowndamage ! crown damage class of the cohort [1 = undamaged, >1 = damaged] + real(r8) :: g_sb_laweight ! total conductance (stomata + boundary layer) of the cohort + ! weighted by its leaf area [m/s]*[m2] + real(r8) :: canopy_trim ! fraction of the maximum leaf biomass that we are targeting [0-1] + real(r8) :: leaf_cost ! how much does it cost to maintain leaves [kgC/m2/year] + real(r8) :: excl_weight ! how much of this cohort is demoted each year, as a proportion of all cohorts + real(r8) :: prom_weight ! how much of this cohort is promoted each year, as a proportion of all cohorts + integer :: nv ! number of leaf layers + integer :: status_coh ! growth status of plant [2 = leaves on , 1 = leaves off] + real(r8) :: c_area ! areal extent of canopy [m2] + real(r8) :: treelai ! lai of an individual within cohort leaf area [m2 leaf area/m2 crown area] + real(r8) :: treesai ! stem area index of an individual within cohort [m2 stem area/m2 crown area] + logical :: isnew ! flag to signify a new cohort - new cohorts have not experienced + ! npp or mortality and should therefore not be fused or averaged + integer :: size_class ! index that indicates which diameter size bin the cohort currently resides in + ! this is used for history output. We maintain this in the main cohort memory + ! because we don't want to continually re-calculate the cohort's position when + ! performing size diagnostics at high-frequency calls + integer :: coage_class ! index that indicates which age bin the cohort currently resides in + ! (used for history output) + integer :: size_by_pft_class ! index that indicates the cohorts position of the joint size-class x functional + ! type classification. We also maintain this in the main cohort memory + ! because we don't want to continually re-calculate the cohort's position when + ! performing size diagnostics at high-frequency calls + integer :: coage_by_pft_class ! index that indicates the cohorts position of the join cohort age class x PFT + integer :: size_class_lasttimestep ! size class of the cohort at the last time step + + !:.........................................................................: + + ! CARBON AND NUTRIENT FLUXES + + ! -------------------------------------------------------------------------- + ! NPP, GPP and RESP: Instantaneous, accumulated and accumulated-hold types* + ! + ! _tstep: The instantaneous estimate that is calculated at each rapid plant biophysics + ! time-step (ie photosynthesis, sub-hourly) [kgC/indiv/timestep] + ! _acc: The accumulation of the _tstep variable from the beginning to ending of + ! the dynamics time-scale. This variable is zero'd during initialization and + ! after the dynamics call-sequence is completed. [kgC/indiv/day] + ! _acc_hold: While _acc is zero'd after the dynamics call sequence and then integrated, + ! _acc_hold "holds" the integrated value until the next time dynamics is + ! called. This is necessary for restarts. This variable also has units + ! converted to a useful rate [kgC/indiv/yr] + ! -------------------------------------------------------------------------- + + real(r8) :: gpp_tstep ! Gross Primary Production (see above *) + real(r8) :: gpp_acc + real(r8) :: gpp_acc_hold + + real(r8) :: npp_tstep ! Net Primary Production (see above *) + real(r8) :: npp_acc + real(r8) :: npp_acc_hold + + real(r8) :: resp_tstep ! Autotrophic respiration (see above *) + real(r8) :: resp_acc + real(r8) :: resp_acc_hold + + real(r8) :: c13disc_clm ! carbon 13 discrimination in new synthesized carbon at each indiv/timestep [ppm] + real(r8) :: c13disc_acc ! carbon 13 discrimination in new synthesized carbon at each indiv/day + ! at the end of a day [ppm] + + ! The following four biophysical rates are assumed to be at the canopy top, at reference temp 25degC, + ! and based on the leaf age weighted average of the PFT parameterized values. + ! The last condition is why it is dynamic and tied to the cohort + + real(r8) :: vcmax25top ! maximum carboxylation at canopy top and 25degC [umol CO2/m2/s] + real(r8) :: jmax25top ! maximum electron transport rate at canopy top and 25degC [umol electrons/m2/s] + real(r8) :: tpu25top ! triose phosphate utilization rate at canopy top and 25degC [umol CO2/m2/s] + real(r8) :: kp25top ! initial slope of CO2 response curve (C4 plants) at 25C + + real(r8) :: ts_net_uptake(nlevleaf) ! net uptake of leaf layers [kgC/m2/timestep] + real(r8) :: year_net_uptake(nlevleaf) ! net uptake of leaf layers [kgC/m2/year] + + ! used for CNP + integer :: cnp_limiter ! which element is limiting growth [0 = none, 1 = C, 2 = N, 3 = P] + real(r8) :: cx_int ! time integration of the log of the relative carbon storage over relative nutrient + real(r8) :: ema_dcxdt ! derivative of the log of the relative carbon storage over relative nutrient + real(r8) :: cx0 ! value on the previous time-step of log of the relative carbon storage over + ! relative nutrient + real(r8) :: nc_repro ! N:C ratio of a new recruit, used also for defining reproductive stoich + real(r8) :: pc_repro ! P:C ratio of a new recruit + + ! Nutrient Fluxes (if N, P, etc. are turned on) + real(r8) :: daily_nh4_uptake ! integrated daily uptake of mineralized ammonium through competitive acquisition + ! in soil [kgN/plant/day] + real(r8) :: daily_no3_uptake ! integrated daily uptake of mineralized nitrate through competitive acquisition + ! in soil [kgN/plant/day] + + real(r8) :: sym_nfix_daily ! accumulated symbiotic N fixation from the roots [kgN/indiv/day] + real(r8) :: sym_nfix_tstep ! symbiotic N fixation from the roots for the time-step [kgN/indiv/timestep] + + real(r8) :: daily_n_gain ! sum of fixation and uptake of mineralized NH4/NO3 in solution as well as + ! symbiotic fixation + real(r8) :: daily_p_gain ! integrated daily uptake of mineralized P through competitive acquisition + ! in soil [kgP/plant/day] + + real(r8) :: daily_c_efflux ! daily mean efflux of excess carbon from roots into labile pool [kgC/plant/day] + real(r8) :: daily_n_efflux ! daily mean efflux of excess nitrogen from roots into labile pool [kgN/plant/day] + real(r8) :: daily_p_efflux ! daily mean efflux of excess phophorus from roots into labile pool [kgP/plant/day] + + real(r8) :: daily_n_demand ! daily amount of N demanded by the plant [kgN/plant/day] + real(r8) :: daily_p_demand ! daily amount of P demanded by the plant [kgN/plant/day] + + real(r8) :: seed_prod ! diagnostic seed production rate [kgC/plant/day] + + !:.........................................................................: + + ! RESPIRATION COMPONENTS + real(r8) :: rdark ! dark respiration [kgC/indiv/s] + real(r8) :: resp_g_tstep ! growth respiration [kgC/indiv/timestep] + real(r8) :: resp_m ! maintenance respiration [kgC/indiv/timestep] + real(r8) :: resp_m_unreduced ! diagnostic-only unreduced maintenance respiration [kgC/indiv/timestep] + real(r8) :: resp_excess ! respiration of excess carbon [kgC/indiv/day] + real(r8) :: livestem_mr ! aboveground live stem maintenance respiration [kgC/indiv/s] + real(r8) :: livecroot_mr ! belowground live stem maintenance respiration [kgC/indiv/s] + real(r8) :: froot_mr ! live fine root maintenance respiration [kgC/indiv/s] + + !:.........................................................................: + + ! DAMAGE + real(r8) :: branch_frac ! fraction of aboveground woody biomass in branches [0-1] + + !:.........................................................................: + + ! MORTALITY + real(r8) :: dmort ! proportional mortality rate [/year] + + ! Mortality Rate Partitions + real(r8) :: bmort ! background mortality rate [indiv/year] + real(r8) :: cmort ! carbon starvation mortality rate [indiv/year] + real(r8) :: hmort ! hydraulic failure mortality rate [indiv/year] + real(r8) :: frmort ! freezing mortality rate [indiv/year] + real(r8) :: smort ! senesence mortality [indiv/year] + real(r8) :: asmort ! age senescence mortality [indiv/year] + real(r8) :: dgmort ! damage mortality [indiv/year] + + ! Logging Mortality Rate + ! Yi Xu & M. Huang + real(r8) :: lmort_direct ! directly logging rate [fraction/logging activity] + real(r8) :: lmort_collateral ! collaterally damaged rate [fraction/logging activity] + real(r8) :: lmort_infra ! mechanically damaged rate [fraction/logging activity] + real(r8) :: l_degrad ! rate of trees that are not killed but suffer from forest degradation + ! (i.e. they are moved to newly-anthro-disturbed secondary + ! forest patch) [fraction/logging activity] + + !:.........................................................................: + + ! NITROGEN POOLS + ! -------------------------------------------------------------------------- + ! Nitrogen pools are not prognostic in the current implementation. + ! They are diagnosed during photosynthesis using a simple C2N parameter. + ! Local values are used in that routine. + ! -------------------------------------------------------------------------- + + !:.........................................................................: + + ! GROWTH DERIVIATIVES + real(r8) :: dndt ! time derivative of cohort size [n/year] + real(r8) :: dhdt ! time derivative of height [m/year] + real(r8) :: ddbhdt ! time derivative of dbh [cm/year] + real(r8) :: dbdeaddt ! time derivative of dead biomass [kgC/year] + + !:.........................................................................: + + ! FIRE + real(r8) :: fraction_crown_burned ! proportion of crown affected by fire [0-1] + real(r8) :: cambial_mort ! probability that trees dies due to cambial charring [0-1] + ! (conditional on the tree being subjected to the fire) + real(r8) :: crownfire_mort ! probability of tree post-fire mortality from crown scorch [0-1] + ! (conditional on the tree being subjected to the fire) + real(r8) :: fire_mort ! post-fire mortality from cambial and crown damage assuming two are independent [0-1] + + !:.........................................................................: + + ! HYDRAULICS + type(ed_cohort_hydr_type), pointer :: co_hydr ! all cohort hydraulics data, see FatesHydraulicsMemMod.F90 + + !:.........................................................................: + + contains + + procedure :: init + procedure :: dump + procedure :: nan_values + procedure :: zero_values + procedure :: CanUpperUnder - integer, public :: n_uptake_mode - integer, public :: p_uptake_mode + end type fates_cohort_type !************************************ !** Patch type structure ** @@ -734,6 +915,470 @@ end subroutine ZeroMassBalFlux ! ===================================================================================== + subroutine init(this, prt) + ! + ! DESCRIPTION: + ! Create new cohort and set default values for all variables + ! + + ! ARGUMENTS: + class(fates_cohort_type), intent(inout), target :: this + class(prt_vartypes), intent(inout), pointer :: prt ! allocated PARTEH object + + call this%nan_values() ! make everything in the cohort not-a-number + call this%zero_values() ! zero things that need to be zeroed + + ! point to the PARTEH object + this%prt => prt + + ! The PARTEH cohort object should be allocated and already + ! initialized in this routine. + call this%prt%CheckInitialConditions() + + call InitPRTBoundaryConditions(this) + + ! new cohorts do not have mortality rates, nor have they moved any + ! carbon when they are created. They will bias our statistics + ! until they have experienced a full day. We need a newly recruited flag. + ! This flag will be set to false after it has experienced + ! growth, disturbance and mortality. + this%isnew = .true. + + end subroutine init + + !:.........................................................................: + + subroutine InitPRTBoundaryConditions(new_cohort) + + ! Set the boundary conditions that flow in an out of the PARTEH + ! allocation hypotheses. Each of these calls to "RegsterBC" are simply + ! setting pointers. + ! For instance, if the hypothesis wants to know what + ! the DBH of the plant is, then we pass in the dbh as an argument (new_cohort%dbh), + ! and also tell it which boundary condition we are talking about (which is + ! defined by an integer index (ac_bc_inout_id_dbh) + ! + ! Again, elaborated Example: + ! "ac_bc_inout_id_dbh" is the unique integer that defines the object index + ! for the allometric carbon "ac" boundary condition "bc" for DBH "dbh" + ! that is classified as input and output "inout". + ! See PRTAllometricCarbonMod.F90 to track its usage. + ! bc_rval is used as the optional argument identifyer to specify a real + ! value boundary condition. + ! bc_ival is used as the optional argument identifyer to specify an integer + ! value boundary condition. + + use PRTAllometricCarbonMod, only : ac_bc_inout_id_dbh, ac_bc_inout_id_netdc, & + ac_bc_in_id_cdamage, ac_bc_in_id_pft, & + ac_bc_in_id_ctrim, ac_bc_in_id_lstat + use PRTAllometricCNPMod, only : acnp_bc_in_id_pft, acnp_bc_in_id_ctrim, & + acnp_bc_in_id_lstat, acnp_bc_in_id_netdc, & + acnp_bc_in_id_netdc, acnp_bc_in_id_nc_repro, & + acnp_bc_in_id_pc_repro, acnp_bc_in_id_cdamage, & + acnp_bc_inout_id_dbh, acnp_bc_inout_id_resp_excess, & + acnp_bc_inout_id_l2fr, acnp_bc_inout_id_cx_int, & + acnp_bc_inout_id_emadcxdt, acnp_bc_inout_id_cx0, & + acnp_bc_inout_id_netdn, acnp_bc_inout_id_netdp, & + acnp_bc_out_id_cefflux, acnp_bc_out_id_nefflux, & + acnp_bc_out_id_pefflux, acnp_bc_out_id_limiter + + type(fates_cohort_type), intent(inout), target :: new_cohort + + select case(hlm_parteh_mode) + case (prt_carbon_allom_hyp) + + ! Register boundary conditions for the Carbon Only Allometric Hypothesis + + call new_cohort%prt%RegisterBCInOut(ac_bc_inout_id_dbh,bc_rval = new_cohort%dbh) + call new_cohort%prt%RegisterBCInOut(ac_bc_inout_id_netdc,bc_rval = new_cohort%npp_acc) + call new_cohort%prt%RegisterBCIn(ac_bc_in_id_cdamage,bc_ival = new_cohort%crowndamage) + call new_cohort%prt%RegisterBCIn(ac_bc_in_id_pft,bc_ival = new_cohort%pft) + call new_cohort%prt%RegisterBCIn(ac_bc_in_id_ctrim,bc_rval = new_cohort%canopy_trim) + call new_cohort%prt%RegisterBCIn(ac_bc_in_id_lstat,bc_ival = new_cohort%status_coh) + + case (prt_cnp_flex_allom_hyp) + + call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_pft,bc_ival = new_cohort%pft) + call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_ctrim,bc_rval = new_cohort%canopy_trim) + call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_lstat,bc_ival = new_cohort%status_coh) + call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdc, bc_rval = new_cohort%npp_acc) + + call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_nc_repro,bc_rval = new_cohort%nc_repro) + call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_pc_repro,bc_rval = new_cohort%pc_repro) + call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_cdamage,bc_ival = new_cohort%crowndamage) + + call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_dbh,bc_rval = new_cohort%dbh) + call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_resp_excess,bc_rval = new_cohort%resp_excess) + call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_l2fr,bc_rval = new_cohort%l2fr) + call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_cx_int,bc_rval = new_cohort%cx_int) + call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_emadcxdt,bc_rval = new_cohort%ema_dcxdt) + call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_cx0,bc_rval = new_cohort%cx0) + + call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_netdn, bc_rval = new_cohort%daily_n_gain) + call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_netdp, bc_rval = new_cohort%daily_p_gain) + + call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_cefflux, bc_rval = new_cohort%daily_c_efflux) + call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_nefflux, bc_rval = new_cohort%daily_n_efflux) + call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_pefflux, bc_rval = new_cohort%daily_p_efflux) + call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_limiter, bc_ival = new_cohort%cnp_limiter) + + case DEFAULT + + write(fates_log(),*) 'You specified an unknown PRT module' + write(fates_log(),*) 'Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + + end select + + + end subroutine InitPRTBoundaryConditions + + + subroutine nan_values(this) + ! + ! DESCRIPTION: + ! make all the cohort variables NaN or unset so they aren't used before defined + ! + + ! USES: + use FatesConstantsMod, only : fates_unset_int + use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) + + ! ARGUMENTS: + class(fates_cohort_type), intent(inout) :: this + + ! set pointers to null + this%taller => null() + this%shorter => null() + this%prt => null() + this%co_hydr => null() + nullify(this%taller) + nullify(this%shorter) + nullify(this%prt) + nullify(this%co_hydr) + + ! VEGETATION STRUCTURE + this%l2fr = nan + this%pft = fates_unset_int + this%n = nan + this%dbh = nan + this%coage = nan + this%hite = nan + this%indexnumber = fates_unset_int + this%canopy_layer = fates_unset_int + this%canopy_layer_yesterday = nan + this%crowndamage = fates_unset_int + this%g_sb_laweight = nan + this%canopy_trim = nan + this%leaf_cost = nan + this%excl_weight = nan + this%prom_weight = nan + this%nv = fates_unset_int + this%status_coh = fates_unset_int + this%c_area = nan + this%treelai = nan + this%treesai = nan + this%isnew = .false. + this%size_class = fates_unset_int + this%coage_class = fates_unset_int + this%size_by_pft_class = fates_unset_int + this%coage_by_pft_class = fates_unset_int + this%size_class_lasttimestep = fates_unset_int + + ! CARBON AND NUTRIENT FLUXES + this%gpp_tstep = nan + this%gpp_acc = nan + this%gpp_acc_hold = nan + this%npp_tstep = nan + this%npp_acc = nan + this%npp_acc_hold = nan + this%resp_tstep = nan + this%resp_acc = nan + this%resp_acc_hold = nan + this%c13disc_clm = nan + this%c13disc_acc = nan + this%vcmax25top = nan + this%jmax25top = nan + this%tpu25top = nan + this%kp25top = nan + this%year_net_uptake(:) = nan + this%ts_net_uptake(:) = nan + this%cnp_limiter = fates_unset_int + this%cx_int = nan + this%ema_dcxdt = nan + this%cx0 = nan + this%nc_repro = nan + this%pc_repro = nan + this%daily_nh4_uptake = nan + this%daily_no3_uptake = nan + this%sym_nfix_daily = nan + this%sym_nfix_tstep = nan + this%daily_n_gain = nan + this%daily_p_gain = nan + this%daily_c_efflux = nan + this%daily_n_efflux = nan + this%daily_p_efflux = nan + this%daily_n_demand = nan + this%daily_p_demand = nan + this%seed_prod = nan + + ! RESPIRATION COMPONENTS + this%rdark = nan + this%resp_g_tstep = nan + this%resp_m = nan + this%resp_m_unreduced = nan + this%resp_excess = nan + this%livestem_mr = nan + this%livecroot_mr = nan + this%froot_mr = nan + + ! DAMAGE + this%branch_frac = nan + + ! MORTALITY + this%dmort = nan + this%bmort = nan + this%cmort = nan + this%frmort = nan + this%smort = nan + this%asmort = nan + this%dgmort = nan + this%lmort_direct = nan + this%lmort_collateral = nan + this%lmort_infra = nan + this%l_degrad = nan + + ! GROWTH DERIVATIVES + this%dndt = nan + this%dhdt = nan + this%ddbhdt = nan + this%dbdeaddt = nan + + ! FIRE + this%fraction_crown_burned = nan + this%cambial_mort = nan + this%crownfire_mort = nan + this%fire_mort = nan + + end subroutine nan_values + + !:.........................................................................: + + subroutine zero_values(this) + ! + ! DESCRIPTION: + ! Zero variables that need to be accounted for if this cohort is altered + ! before they are defined. + ! + ! ARGUMENTS + class(fates_cohort_type), intent(inout) :: this + + !this%l2fr + !this%pft + !this%n + !this%dbh + !this%coage + !this%hite + !this%indexnumber + !this%canopy_layer + !this%canopy_layer_yesterday + !this%crowndamage + this%g_sb_laweight = 0._r8 + !this%canopy_trim + this%leaf_cost = 0._r8 + this%excl_weight = 0._r8 + this%prom_weight = 0._r8 + this%nv = 0 + this%status_coh = 0 + !this%c_area + !this%treelai + this%treesai = 0._r8 + this%size_class = 1 + this%coage_class = 1 + !this%size_by_pft_class + !this%coage_by_pft_class + this%size_class_lasttimestep = 0 + this%gpp_tstep = 0._r8 + this%gpp_acc = 0._r8 + this%gpp_acc_hold = 0._r8 + this%npp_tstep = 0._r8 + this%npp_acc = 0._r8 + this%npp_acc_hold = 0._r8 + this%resp_tstep = 0._r8 + this%resp_acc = 0._r8 + this%resp_acc_hold = 0._r8 + this%c13disc_clm = 0._r8 + this%c13disc_acc = 0._r8 + !this%vcmax25top + !this%jmax25top + !this%tpu25top + !this%kp25top + this%ts_net_uptake(:) = 0._r8 + this%year_net_uptake(:) = 999._r8 ! this needs to be 999, or trimming of new cohorts will break. + !this%cnp_limiter + !this%cx_int + !this%ema_dcxdt + !this%cx0 + !this%nc_repro + !this%pc_repro + this%daily_nh4_uptake = 0._r8 + this%daily_no3_uptake = 0._r8 + + ! fixation is also integrated over the course of the day and must be + ! zeroed upon creation and after plant resource allocation + this%sym_nfix_daily = 0._r8 + this%daily_n_gain = 0._r8 + this%daily_p_gain = 0._r8 + + ! daily nutrient fluxes are INTEGRATED over the course of the day. + ! These variables MUST be zerod upon creation AND after allocation. + ! These variables exist in carbon-only mode but are not used. + this%daily_c_efflux = 0._r8 + this%daily_n_efflux = 0._r8 + this%daily_p_efflux = 0._r8 + + ! initialize these as negative + this%daily_n_demand = -9._r8 + this%daily_p_demand = -9._r8 + this%seed_prod = 0._r8 + this%rdark = 0._r8 + this%resp_g_tstep = 0._r8 + this%resp_m = 0._r8 + this%resp_m_unreduced = 0._r8 + this%resp_excess = 0._r8 + this%livestem_mr = 0._r8 + this%livecroot_mr = 0._r8 + this%froot_mr = 0._r8 + !this%branch_frac + this%dmort = 0._r8 + this%lmort_direct = 0._r8 + this%lmort_collateral = 0._r8 + this%lmort_infra = 0._r8 + this%l_degrad = 0._r8 + this%fraction_crown_burned = 0._r8 + this%cambial_mort = 0._r8 + this%crownfire_mort = 0._r8 + this%fire_mort = 0._r8 + + end subroutine zero_values + + !:.........................................................................: + + function CanUpperUnder(this) result(can_position) + ! + ! DESCRIPTION: + ! This simple function is used to determine if a cohort's crown position + ! is in the upper portion (ie the canopy) or the understory. This + ! differentiation is only used for diagnostic purposes. Functionally, + ! the model uses the canopy layer position, which may have more than + ! two layers at any given time. Utlimately, every plant that is not in + ! the top layer (canopy), is considered understory. + ! + + ! ARGUMENTS: + class(fates_cohort_type) :: this ! current cohort of interest + integer :: can_position ! canopy position + + if (this%canopy_layer == 1)then + can_position = ican_upper + else + can_position = ican_ustory + end if + + end function CanUpperUnder + + !:.........................................................................: + + subroutine dump(this) + ! + ! DESCRIPTION: + ! Print out attributes of a cohort + ! + + ! ARGUMENTS: + class(fates_cohort_type), intent(in), target :: this + + write(fates_log(),*) '----------------------------------------' + write(fates_log(),*) ' Dumping Cohort Information ' + write(fates_log(),*) '----------------------------------------' + write(fates_log(),*) 'co%pft = ', this%pft + write(fates_log(),*) 'co%n = ', this%n + write(fates_log(),*) 'co%dbh = ', this%dbh + write(fates_log(),*) 'co%hite = ', this%hite + write(fates_log(),*) 'co%crowndamage = ', this%crowndamage + write(fates_log(),*) 'co%coage = ', this%coage + write(fates_log(),*) 'co%l2fr = ', this%l2fr + write(fates_log(),*) 'leaf carbon = ', this%prt%GetState(leaf_organ,carbon12_element) + write(fates_log(),*) 'fineroot carbon = ', this%prt%GetState(fnrt_organ,carbon12_element) + write(fates_log(),*) 'sapwood carbon = ', this%prt%GetState(sapw_organ,carbon12_element) + write(fates_log(),*) 'structural (dead) carbon = ', this%prt%GetState(struct_organ,carbon12_element) + write(fates_log(),*) 'storage carbon = ', this%prt%GetState(store_organ,carbon12_element) + write(fates_log(),*) 'reproductive carbon = ', this%prt%GetState(repro_organ,carbon12_element) + write(fates_log(),*) 'co%g_sb_laweight = ', this%g_sb_laweight + write(fates_log(),*) 'co%leaf_cost = ', this%leaf_cost + write(fates_log(),*) 'co%canopy_layer = ', this%canopy_layer + write(fates_log(),*) 'co%canopy_layer_yesterday = ', this%canopy_layer_yesterday + write(fates_log(),*) 'co%nv = ', this%nv + write(fates_log(),*) 'co%status_coh = ', this%status_coh + write(fates_log(),*) 'co%canopy_trim = ', this%canopy_trim + write(fates_log(),*) 'co%excl_weight = ', this%excl_weight + write(fates_log(),*) 'co%prom_weight = ', this%prom_weight + write(fates_log(),*) 'co%size_class = ', this%size_class + write(fates_log(),*) 'co%size_by_pft_class = ', this%size_by_pft_class + write(fates_log(),*) 'co%coage_class = ', this%coage_class + write(fates_log(),*) 'co%coage_by_pft_class = ', this%coage_by_pft_class + write(fates_log(),*) 'co%gpp_acc_hold = ', this%gpp_acc_hold + write(fates_log(),*) 'co%gpp_acc = ', this%gpp_acc + write(fates_log(),*) 'co%gpp_tstep = ', this%gpp_tstep + write(fates_log(),*) 'co%npp_acc_hold = ', this%npp_acc_hold + write(fates_log(),*) 'co%npp_tstep = ', this%npp_tstep + write(fates_log(),*) 'co%npp_acc = ', this%npp_acc + write(fates_log(),*) 'co%resp_tstep = ', this%resp_tstep + write(fates_log(),*) 'co%resp_acc = ', this%resp_acc + write(fates_log(),*) 'co%resp_acc_hold = ', this%resp_acc_hold + write(fates_log(),*) 'co%rdark = ', this%rdark + write(fates_log(),*) 'co%resp_m = ', this%resp_m + write(fates_log(),*) 'co%resp_g_tstep = ', this%resp_g_tstep + write(fates_log(),*) 'co%livestem_mr = ', this%livestem_mr + write(fates_log(),*) 'co%livecroot_mr = ', this%livecroot_mr + write(fates_log(),*) 'co%froot_mr = ', this%froot_mr + write(fates_log(),*) 'co%dgmort = ', this%dgmort + write(fates_log(),*) 'co%treelai = ', this%treelai + write(fates_log(),*) 'co%treesai = ', this%treesai + write(fates_log(),*) 'co%c_area = ', this%c_area + write(fates_log(),*) 'co%cmort = ', this%cmort + write(fates_log(),*) 'co%bmort = ', this%bmort + write(fates_log(),*) 'co%smort = ', this%smort + write(fates_log(),*) 'co%asmort = ', this%asmort + write(fates_log(),*) 'co%dgmort = ', this%dgmort + write(fates_log(),*) 'co%hmort = ', this%hmort + write(fates_log(),*) 'co%frmort = ', this%frmort + write(fates_log(),*) 'co%asmort = ', this%asmort + write(fates_log(),*) 'co%lmort_direct = ', this%lmort_direct + write(fates_log(),*) 'co%lmort_collateral = ', this%lmort_collateral + write(fates_log(),*) 'co%lmort_infra = ', this%lmort_infra + write(fates_log(),*) 'co%isnew = ', this%isnew + write(fates_log(),*) 'co%dndt = ', this%dndt + write(fates_log(),*) 'co%dhdt = ', this%dhdt + write(fates_log(),*) 'co%ddbhdt = ', this%ddbhdt + write(fates_log(),*) 'co%dbdeaddt = ', this%dbdeaddt + write(fates_log(),*) 'co%fraction_crown_burned = ', this%fraction_crown_burned + write(fates_log(),*) 'co%fire_mort = ', this%fire_mort + write(fates_log(),*) 'co%crownfire_mort = ', this%crownfire_mort + write(fates_log(),*) 'co%cambial_mort = ', this%cambial_mort + write(fates_log(),*) 'co%size_class = ', this%size_class + write(fates_log(),*) 'co%size_by_pft_class = ', this%size_by_pft_class + + if (associated(this%co_hydr)) call dump_cohort_hydr(this) + + write(fates_log(),*) '----------------------------------------' + + return + +end subroutine dump + +!:...........................................................................: + subroutine val_check_ed_vars(currentPatch,var_aliases,return_code) ! ---------------------------------------------------------------------------------- diff --git a/main/FatesCohortMod.F90 b/main/FatesCohortMod.F90 deleted file mode 100644 index 5d1ffa89a7..0000000000 --- a/main/FatesCohortMod.F90 +++ /dev/null @@ -1,624 +0,0 @@ -module FatesCohortMod - - use FatesConstantsMod, only : r8 => fates_r8 - use FatesGlobals, only : fates_log - use PRTGenericMod, only : prt_vartypes - use FatesHydraulicsMemMod, only : ed_cohort_hydr_type - use FatesInterfaceTypesMod, only : hlm_parteh_mode - - implicit none - private - - ! PARAMETERS - - ! parameters that govern the VAI (LAI+SAI) bins used in radiative transfer code - integer, parameter, public :: nlevleaf = 30 ! number of leaf+stem layers in each canopy layer - - integer, parameter, public :: ican_upper = 1 ! nominal index for the upper canopy - integer, parameter, public :: ican_ustory = 2 ! nominal index for diagnostics that refer to understory layers - ! (all layers that are not the top canopy layer) - - type, public :: fates_cohort_type - - ! POINTERS - type (fates_cohort_type), pointer :: taller => null() ! pointer to next tallest cohort - type (fates_cohort_type), pointer :: shorter => null() ! pointer to next shorter cohort - - !:.........................................................................: - - ! Multi-species, multi-organ Plant Reactive Transport (PRT) - ! Contains carbon and nutrient state variables for various plant organs - class(prt_vartypes), pointer :: prt - real(r8) :: l2fr ! leaf to fineroot biomass ratio (this is constant - ! in carbon only simulationss, and is set by the - ! allom_l2fr_min parameter. In nutrient - ! enabled simulations, this is dynamic, will - ! vary between allom_l2fr_min and allom_l2fr_max - ! parameters, with a tendency driven by - ! nutrient storage) [kg root / kg leaf] - - !:.........................................................................: - - ! VEGETATION STRUCTURE - - integer :: pft ! pft index - real(r8) :: n ! number of individuals in cohort per 'area' (10000m2 default) [/m2] - real(r8) :: dbh ! diameter at breast height [cm] - real(r8) :: coage ! age [years] - real(r8) :: hite ! height [m] - integer :: indexnumber ! unique number for each cohort (within clump?) - integer :: canopy_layer ! canopy status of cohort [1 = canopy, 2 = understorey, etc.] - real(r8) :: canopy_layer_yesterday ! recent canopy status of cohort [1 = canopy, 2 = understorey, etc.] - ! real to be conservative during fusion - integer :: crowndamage ! crown damage class of the cohort [1 = undamaged, >1 = damaged] - real(r8) :: g_sb_laweight ! total conductance (stomata + boundary layer) of the cohort - ! weighted by its leaf area [m/s]*[m2] - real(r8) :: canopy_trim ! fraction of the maximum leaf biomass that we are targeting [0-1] - real(r8) :: leaf_cost ! how much does it cost to maintain leaves [kgC/m2/year] - real(r8) :: excl_weight ! how much of this cohort is demoted each year, as a proportion of all cohorts - real(r8) :: prom_weight ! how much of this cohort is promoted each year, as a proportion of all cohorts - integer :: nv ! number of leaf layers - integer :: status_coh ! growth status of plant [2 = leaves on , 1 = leaves off] - real(r8) :: c_area ! areal extent of canopy [m2] - real(r8) :: treelai ! lai of an individual within cohort leaf area [m2 leaf area/m2 crown area] - real(r8) :: treesai ! stem area index of an individual within cohort [m2 stem area/m2 crown area] - logical :: isnew ! flag to signify a new cohort - new cohorts have not experienced - ! npp or mortality and should therefore not be fused or averaged - integer :: size_class ! index that indicates which diameter size bin the cohort currently resides in - ! this is used for history output. We maintain this in the main cohort memory - ! because we don't want to continually re-calculate the cohort's position when - ! performing size diagnostics at high-frequency calls - integer :: coage_class ! index that indicates which age bin the cohort currently resides in - ! (used for history output) - integer :: size_by_pft_class ! index that indicates the cohorts position of the joint size-class x functional - ! type classification. We also maintain this in the main cohort memory - ! because we don't want to continually re-calculate the cohort's position when - ! performing size diagnostics at high-frequency calls - integer :: coage_by_pft_class ! index that indicates the cohorts position of the join cohort age class x PFT - integer :: size_class_lasttimestep ! size class of the cohort at the last time step - - !:.........................................................................: - - ! CARBON AND NUTRIENT FLUXES - - ! -------------------------------------------------------------------------- - ! NPP, GPP and RESP: Instantaneous, accumulated and accumulated-hold types* - ! - ! _tstep: The instantaneous estimate that is calculated at each rapid plant biophysics - ! time-step (ie photosynthesis, sub-hourly) [kgC/indiv/timestep] - ! _acc: The accumulation of the _tstep variable from the beginning to ending of - ! the dynamics time-scale. This variable is zero'd during initialization and - ! after the dynamics call-sequence is completed. [kgC/indiv/day] - ! _acc_hold: While _acc is zero'd after the dynamics call sequence and then integrated, - ! _acc_hold "holds" the integrated value until the next time dynamics is - ! called. This is necessary for restarts. This variable also has units - ! converted to a useful rate [kgC/indiv/yr] - ! -------------------------------------------------------------------------- - - real(r8) :: gpp_tstep ! Gross Primary Production (see above *) - real(r8) :: gpp_acc - real(r8) :: gpp_acc_hold - - real(r8) :: npp_tstep ! Net Primary Production (see above *) - real(r8) :: npp_acc - real(r8) :: npp_acc_hold - - real(r8) :: resp_tstep ! Autotrophic respiration (see above *) - real(r8) :: resp_acc - real(r8) :: resp_acc_hold - - real(r8) :: c13disc_clm ! carbon 13 discrimination in new synthesized carbon at each indiv/timestep [ppm] - real(r8) :: c13disc_acc ! carbon 13 discrimination in new synthesized carbon at each indiv/day - ! at the end of a day [ppm] - - ! The following four biophysical rates are assumed to be at the canopy top, at reference temp 25degC, - ! and based on the leaf age weighted average of the PFT parameterized values. - ! The last condition is why it is dynamic and tied to the cohort - - real(r8) :: vcmax25top ! maximum carboxylation at canopy top and 25degC [umol CO2/m2/s] - real(r8) :: jmax25top ! maximum electron transport rate at canopy top and 25degC [umol electrons/m2/s] - real(r8) :: tpu25top ! triose phosphate utilization rate at canopy top and 25degC [umol CO2/m2/s] - real(r8) :: kp25top ! initial slope of CO2 response curve (C4 plants) at 25C - - real(r8) :: ts_net_uptake(nlevleaf) ! net uptake of leaf layers [kgC/m2/timestep] - real(r8) :: year_net_uptake(nlevleaf) ! net uptake of leaf layers [kgC/m2/year] - - ! used for CNP - integer :: cnp_limiter ! which element is limiting growth [0 = none, 1 = C, 2 = N, 3 = P] - real(r8) :: cx_int ! time integration of the log of the relative carbon storage over relative nutrient - real(r8) :: ema_dcxdt ! derivative of the log of the relative carbon storage over relative nutrient - real(r8) :: cx0 ! value on the previous time-step of log of the relative carbon storage over - ! relative nutrient - real(r8) :: nc_repro ! N:C ratio of a new recruit, used also for defining reproductive stoich - real(r8) :: pc_repro ! P:C ratio of a new recruit - - ! Nutrient Fluxes (if N, P, etc. are turned on) - real(r8) :: daily_nh4_uptake ! integrated daily uptake of mineralized ammonium through competitive acquisition - ! in soil [kgN/plant/day] - real(r8) :: daily_no3_uptake ! integrated daily uptake of mineralized nitrate through competitive acquisition - ! in soil [kgN/plant/day] - - real(r8) :: sym_nfix_daily ! accumulated symbiotic N fixation from the roots [kgN/indiv/day] - real(r8) :: sym_nfix_tstep ! symbiotic N fixation from the roots for the time-step [kgN/indiv/timestep] - - real(r8) :: daily_n_gain ! sum of fixation and uptake of mineralized NH4/NO3 in solution as well as - ! symbiotic fixation - real(r8) :: daily_p_gain ! integrated daily uptake of mineralized P through competitive acquisition - ! in soil [kgP/plant/day] - - real(r8) :: daily_c_efflux ! daily mean efflux of excess carbon from roots into labile pool [kgC/plant/day] - real(r8) :: daily_n_efflux ! daily mean efflux of excess nitrogen from roots into labile pool [kgN/plant/day] - real(r8) :: daily_p_efflux ! daily mean efflux of excess phophorus from roots into labile pool [kgP/plant/day] - - real(r8) :: daily_n_demand ! daily amount of N demanded by the plant [kgN/plant/day] - real(r8) :: daily_p_demand ! daily amount of P demanded by the plant [kgN/plant/day] - - real(r8) :: seed_prod ! diagnostic seed production rate [kgC/plant/day] - - !:.........................................................................: - - ! RESPIRATION COMPONENTS - real(r8) :: rdark ! dark respiration [kgC/indiv/s] - real(r8) :: resp_g_tstep ! growth respiration [kgC/indiv/timestep] - real(r8) :: resp_m ! maintenance respiration [kgC/indiv/timestep] - real(r8) :: resp_m_unreduced ! diagnostic-only unreduced maintenance respiration [kgC/indiv/timestep] - real(r8) :: resp_excess ! respiration of excess carbon [kgC/indiv/day] - real(r8) :: livestem_mr ! aboveground live stem maintenance respiration [kgC/indiv/s] - real(r8) :: livecroot_mr ! belowground live stem maintenance respiration [kgC/indiv/s] - real(r8) :: froot_mr ! live fine root maintenance respiration [kgC/indiv/s] - - !:.........................................................................: - - ! DAMAGE - real(r8) :: branch_frac ! fraction of aboveground woody biomass in branches [0-1] - - !:.........................................................................: - - ! MORTALITY - real(r8) :: dmort ! proportional mortality rate [/year] - - ! Mortality Rate Partitions - real(r8) :: bmort ! background mortality rate [indiv/year] - real(r8) :: cmort ! carbon starvation mortality rate [indiv/year] - real(r8) :: hmort ! hydraulic failure mortality rate [indiv/year] - real(r8) :: frmort ! freezing mortality rate [indiv/year] - real(r8) :: smort ! senesence mortality [indiv/year] - real(r8) :: asmort ! age senescence mortality [indiv/year] - real(r8) :: dgmort ! damage mortality [indiv/year] - - ! Logging Mortality Rate - ! Yi Xu & M. Huang - real(r8) :: lmort_direct ! directly logging rate [fraction/logging activity] - real(r8) :: lmort_collateral ! collaterally damaged rate [fraction/logging activity] - real(r8) :: lmort_infra ! mechanically damaged rate [fraction/logging activity] - real(r8) :: l_degrad ! rate of trees that are not killed but suffer from forest degradation - ! (i.e. they are moved to newly-anthro-disturbed secondary - ! forest patch) [fraction/logging activity] - - !:.........................................................................: - - ! NITROGEN POOLS - ! -------------------------------------------------------------------------- - ! Nitrogen pools are not prognostic in the current implementation. - ! They are diagnosed during photosynthesis using a simple C2N parameter. - ! Local values are used in that routine. - ! -------------------------------------------------------------------------- - - !:.........................................................................: - - ! GROWTH DERIVIATIVES - real(r8) :: dndt ! time derivative of cohort size [n/year] - real(r8) :: dhdt ! time derivative of height [m/year] - real(r8) :: ddbhdt ! time derivative of dbh [cm/year] - real(r8) :: dbdeaddt ! time derivative of dead biomass [kgC/year] - - !:.........................................................................: - - ! FIRE - real(r8) :: fraction_crown_burned ! proportion of crown affected by fire [0-1] - real(r8) :: cambial_mort ! probability that trees dies due to cambial charring [0-1] - ! (conditional on the tree being subjected to the fire) - real(r8) :: crownfire_mort ! probability of tree post-fire mortality from crown scorch [0-1] - ! (conditional on the tree being subjected to the fire) - real(r8) :: fire_mort ! post-fire mortality from cambial and crown damage assuming two are independent [0-1] - - !:.........................................................................: - - ! HYDRAULICS - type(ed_cohort_hydr_type), pointer :: co_hydr ! all cohort hydraulics data, see FatesHydraulicsMemMod.F90 - - !:.........................................................................: - - contains - - procedure :: init - procedure :: dump - procedure :: nan_values - procedure :: zero_values - procedure :: CanUpperUnder - - end type fates_cohort_type - - !:...........................................................................: - - contains - - subroutine init(this, prt) - ! - ! DESCRIPTION: - ! Create new cohort and set default values for all variables - ! - - ! ARGUMENTS: - type(fates_cohort_type), intent(inout), target :: this - class(prt_vartypes), intent(inout), pointer :: prt ! allocated PARTEH object - - call this%nan_cohort() ! make everything in the cohort not-a-number - call this%zero_cohort() ! zero things that need to be zeroed - - ! point to the PARTEH object - this%prt => prt - - ! The PARTEH cohort object should be allocated and already - ! initialized in this routine. - call this%prt%CheckInitialConditions() - - call this%InitPRTBoundaryConditions() - - ! new cohorts do not have mortality rates, nor have they moved any - ! carbon when they are created. They will bias our statistics - ! until they have experienced a full day. We need a newly recruited flag. - ! This flag will be set to false after it has experienced - ! growth, disturbance and mortality. - this%isnew = .true. - - end subroutine init - - !:.........................................................................: - - subroutine nan_values(this) - ! - ! DESCRIPTION: - ! make all the cohort variables NaN or unset so they aren't used before defined - ! - - ! USES: - use FatesConstantsMod, only : fates_unset_int - use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) - - ! ARGUMENTS: - type(fates_cohort_type), intent(inout) :: this - - ! set pointers to null - this%taller => null() - this%shorter => null() - this%prt => null() - this%co_hydr => null() - nullify(this%taller) - nullify(this%shorter) - nullify(this%prt) - nullify(this%co_hydr) - - ! VEGETATION STRUCTURE - this%l2fr = nan - this%pft = fates_unset_int - this%n = nan - this%dbh = nan - this%coage = nan - this%hite = nan - this%indexnumber = fates_unset_int - this%canopy_layer = fates_unset_int - this%canopy_layer_yesterday = nan - this%crowndamage = fates_unset_int - this%g_sb_laweight = nan - this%canopy_trim = nan - this%leaf_cost = nan - this%excl_weight = nan - this%prom_weight = nan - this%nv = fates_unset_int - this%status_coh = fates_unset_int - this%c_area = nan - this%treelai = nan - this%treesai = nan - this%isnew = .false. - this%size_class = fates_unset_int - this%coage_class = fates_unset_int - this%size_by_pft_class = fates_unset_int - this%coage_by_pft_class = fates_unset_int - this%size_class_lasttimestep = fates_unset_int - - ! CARBON AND NUTRIENT FLUXES - this%gpp_tstep = nan - this%gpp_acc = nan - this%gpp_acc_hold = nan - this%npp_tstep = nan - this%npp_acc = nan - this%npp_acc_hold = nan - this%resp_tstep = nan - this%resp_acc = nan - this%resp_acc_hold = nan - this%c13disc_clm = nan - this%c13disc_acc = nan - this%vcmax25top = nan - this%jmax25top = nan - this%tpu25top = nan - this%kp25top = nan - this%year_net_uptake(:) = nan - this%ts_net_uptake(:) = nan - this%cnp_limiter = fates_unset_int - this%cx_int = nan - this%ema_dcxdt = nan - this%cx0 = nan - this%nc_repro = nan - this%pc_repro = nan - this%daily_nh4_uptake = nan - this%daily_no3_uptake = nan - this%sym_nfix_daily = nan - this%sym_nfix_tstep = nan - this%daily_n_gain = nan - this%daily_p_gain = nan - this%daily_c_efflux = nan - this%daily_n_efflux = nan - this%daily_p_efflux = nan - this%daily_n_demand = nan - this%daily_p_demand = nan - this%seed_prod = nan - - ! RESPIRATION COMPONENTS - this%rdark = nan - this%resp_g_tstep = nan - this%resp_m = nan - this%resp_m_unreduced = nan - this%resp_excess = nan - this%livestem_mr = nan - this%livecroot_mr = nan - this%froot_mr = nan - - ! DAMAGE - this%branch_frac = nan - - ! MORTALITY - this%dmort = nan - this%bmort = nan - this%cmort = nan - this%frmort = nan - this%smort = nan - this%asmort = nan - this%dgmort = nan - this%lmort_direct = nan - this%lmort_collateral = nan - this%lmort_infra = nan - this%l_degrad = nan - - ! GROWTH DERIVATIVES - this%dndt = nan - this%dhdt = nan - this%ddbhdt = nan - this%dbdeaddt = nan - - ! FIRE - this%fraction_crown_burned = nan - this%cambial_mort = nan - this%crownfire_mort = nan - this%fire_mort = nan - - end subroutine nan_values - - !:.........................................................................: - - subroutine zero_cohort(this) - ! - ! DESCRIPTION: - ! Zero variables that need to be accounted for if this cohort is altered - ! before they are defined. - ! - ! ARGUMENTS - type (fates_cohort_type), intent(inout) :: this - - !this%l2fr - !this%pft - !this%n - !this%dbh - !this%coage - !this%hite - !this%indexnumber - !this%canopy_layer - !this%canopy_layer_yesterday - !this%crowndamage - this%g_sb_laweight = 0._r8 - !this%canopy_trim - this%leaf_cost = 0._r8 - this%excl_weight = 0._r8 - this%prom_weight = 0._r8 - this%nv = 0 - this%status_coh = 0 - !this%c_area - !this%treelai - this%treesai = 0._r8 - this%size_class = 1 - this%coage_class = 1 - !this%size_by_pft_class - !this%coage_by_pft_class - this%size_class_lasttimestep = 0 - this%gpp_tstep = 0._r8 - this%gpp_acc = 0._r8 - this%gpp_acc_hold = 0._r8 - this%npp_tstep = 0._r8 - this%npp_acc = 0._r8 - this%npp_acc_hold = 0._r8 - this%resp_tstep = 0._r8 - this%resp_acc = 0._r8 - this%resp_acc_hold = 0._r8 - this%c13disc_clm = 0._r8 - this%c13disc_acc = 0._r8 - !this%vcmax25top - !this%jmax25top - !this%tpu25top - !this%kp25top - this%ts_net_uptake(:) = 0._r8 - this%year_net_uptake(:) = 999._r8 ! this needs to be 999, or trimming of new cohorts will break. - !this%cnp_limiter - !this%cx_int - !this%ema_dcxdt - !this%cx0 - !this%nc_repro - !this%pc_repro - this%daily_nh4_uptake = 0._r8 - this%daily_no3_uptake = 0._r8 - - ! fixation is also integrated over the course of the day and must be - ! zeroed upon creation and after plant resource allocation - this%sym_nfix_daily = 0._r8 - !this%daily_n_gain - this%daily_p_gain = 0._r8 - - ! daily nutrient fluxes are INTEGRATED over the course of the day. - ! These variables MUST be zerod upon creation AND after allocation. - ! These variables exist in carbon-only mode but are not used. - this%daily_c_efflux = 0._r8 - this%daily_n_efflux = 0._r8 - this%daily_p_efflux = 0._r8 - - ! initialize these as negative - this%daily_n_demand = -9._r8 - this%daily_p_demand = -9._r8 - this%seed_prod = 0._r8 - this%rdark = 0._r8 - this%resp_g_tstep = 0._r8 - this%resp_m = 0._r8 - this%resp_m_unreduced = 0._r8 - this%resp_excess = 0._r8 - this%livestem_mr = 0._r8 - this%livecroot_mr = 0._r8 - this%froot_mr = 0._r8 - !this%branch_frac - this%dmort = 0._r8 - this%lmort_direct = 0._r8 - this%lmort_collateral = 0._r8 - this%lmort_infra = 0._r8 - this%l_degrad = 0._r8 - this%fraction_crown_burned = 0._r8 - this%cambial_mort = 0._r8 - this%crownfire_mort = 0._r8 - this%fire_mort = 0._r8 - - end subroutine zero_cohort - - !:.........................................................................: - - function CanUpperUnder(this) result(can_position) - ! - ! DESCRIPTION: - ! This simple function is used to determine if a cohort's crown position - ! is in the upper portion (ie the canopy) or the understory. This - ! differentiation is only used for diagnostic purposes. Functionally, - ! the model uses the canopy layer position, which may have more than - ! two layers at any given time. Utlimately, every plant that is not in - ! the top layer (canopy), is considered understory. - ! - - ! ARGUMENTS: - type(fates_cohort_type) :: this ! current cohort of interest - integer :: can_position ! canopy position - - if (this%canopy_layer == 1)then - can_position = ican_upper - else - can_position = ican_ustory - end if - - end function CanUpperUnder - - !:.........................................................................: - - subroutine dump(this) - ! - ! DESCRIPTION: - ! Print out attributes of a cohort - ! - - ! ARGUMENTS: - type(fates_cohort_type), intent(in), target :: this - - write(fates_log(),*) '----------------------------------------' - write(fates_log(),*) ' Dumping Cohort Information ' - write(fates_log(),*) '----------------------------------------' - write(fates_log(),*) 'co%pft = ', this%pft - write(fates_log(),*) 'co%n = ', this%n - write(fates_log(),*) 'co%dbh = ', this%dbh - write(fates_log(),*) 'co%hite = ', this%hite - write(fates_log(),*) 'co%crowndamage = ', this%crowndamage - write(fates_log(),*) 'co%coage = ', this%coage - write(fates_log(),*) 'co%l2fr = ', this%l2fr - write(fates_log(),*) 'leaf carbon = ', this%prt%GetState(leaf_organ,carbon12_element) - write(fates_log(),*) 'fineroot carbon = ', this%prt%GetState(fnrt_organ,carbon12_element) - write(fates_log(),*) 'sapwood carbon = ', this%prt%GetState(sapw_organ,carbon12_element) - write(fates_log(),*) 'structural (dead) carbon = ', this%prt%GetState(struct_organ,carbon12_element) - write(fates_log(),*) 'storage carbon = ', this%prt%GetState(store_organ,carbon12_element) - write(fates_log(),*) 'reproductive carbon = ', this%prt%GetState(repro_organ,carbon12_element) - write(fates_log(),*) 'co%g_sb_laweight = ', this%g_sb_laweight - write(fates_log(),*) 'co%leaf_cost = ', this%leaf_cost - write(fates_log(),*) 'co%canopy_layer = ', this%canopy_layer - write(fates_log(),*) 'co%canopy_layer_yesterday = ', this%canopy_layer_yesterday - write(fates_log(),*) 'co%nv = ', this%nv - write(fates_log(),*) 'co%status_coh = ', this%status_coh - write(fates_log(),*) 'co%canopy_trim = ', this%canopy_trim - write(fates_log(),*) 'co%excl_weight = ', this%excl_weight - write(fates_log(),*) 'co%prom_weight = ', this%prom_weight - write(fates_log(),*) 'co%size_class = ', this%size_class - write(fates_log(),*) 'co%size_by_pft_class = ', this%size_by_pft_class - write(fates_log(),*) 'co%coage_class = ', this%coage_class - write(fates_log(),*) 'co%coage_by_pft_class = ', this%coage_by_pft_class - write(fates_log(),*) 'co%gpp_acc_hold = ', this%gpp_acc_hold - write(fates_log(),*) 'co%gpp_acc = ', this%gpp_acc - write(fates_log(),*) 'co%gpp_tstep = ', this%gpp_tstep - write(fates_log(),*) 'co%npp_acc_hold = ', this%npp_acc_hold - write(fates_log(),*) 'co%npp_tstep = ', this%npp_tstep - write(fates_log(),*) 'co%npp_acc = ', this%npp_acc - write(fates_log(),*) 'co%resp_tstep = ', this%resp_tstep - write(fates_log(),*) 'co%resp_acc = ', this%resp_acc - write(fates_log(),*) 'co%resp_acc_hold = ', this%resp_acc_hold - write(fates_log(),*) 'co%rdark = ', this%rdark - write(fates_log(),*) 'co%resp_m = ', this%resp_m - write(fates_log(),*) 'co%resp_g_tstep = ', this%resp_g_tstep - write(fates_log(),*) 'co%livestem_mr = ', this%livestem_mr - write(fates_log(),*) 'co%livecroot_mr = ', this%livecroot_mr - write(fates_log(),*) 'co%froot_mr = ', this%froot_mr - write(fates_log(),*) 'co%dgmort = ', this%dgmort - write(fates_log(),*) 'co%treelai = ', this%treelai - write(fates_log(),*) 'co%treesai = ', this%treesai - write(fates_log(),*) 'co%c_area = ', this%c_area - write(fates_log(),*) 'co%cmort = ', this%cmort - write(fates_log(),*) 'co%bmort = ', this%bmort - write(fates_log(),*) 'co%smort = ', this%smort - write(fates_log(),*) 'co%asmort = ', this%asmort - write(fates_log(),*) 'co%dgmort = ', this%dgmort - write(fates_log(),*) 'co%hmort = ', this%hmort - write(fates_log(),*) 'co%frmort = ', this%frmort - write(fates_log(),*) 'co%asmort = ', this%asmort - write(fates_log(),*) 'co%lmort_direct = ', this%lmort_direct - write(fates_log(),*) 'co%lmort_collateral = ', this%lmort_collateral - write(fates_log(),*) 'co%lmort_infra = ', this%lmort_infra - write(fates_log(),*) 'co%isnew = ', this%isnew - write(fates_log(),*) 'co%dndt = ', this%dndt - write(fates_log(),*) 'co%dhdt = ', this%dhdt - write(fates_log(),*) 'co%ddbhdt = ', this%ddbhdt - write(fates_log(),*) 'co%dbdeaddt = ', this%dbdeaddt - write(fates_log(),*) 'co%fraction_crown_burned = ', this%fraction_crown_burned - write(fates_log(),*) 'co%fire_mort = ', this%fire_mort - write(fates_log(),*) 'co%crownfire_mort = ', this%crownfire_mort - write(fates_log(),*) 'co%cambial_mort = ', this%cambial_mort - write(fates_log(),*) 'co%size_class = ', this%size_class - write(fates_log(),*) 'co%size_by_pft_class = ', this%size_by_pft_class - - if (associated(this%co_hydr)) call dump_cohort_hydr(this) - - write(fates_log(),*) '----------------------------------------' - - return - - end subroutine dump - - !:...........................................................................: - -end module FatesCohortMod \ No newline at end of file diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index cf66408133..f984ed8365 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -19,7 +19,7 @@ module FatesHistoryInterfaceMod use PRTGenericMod , only : prt_cnp_flex_allom_hyp use EDTypesMod , only : site_fluxdiags_type use EDtypesMod , only : ed_site_type - use EDtypesMod , only : ed_cohort_type + use EDtypesMod , only : fates_cohort_type use EDtypesMod , only : ed_patch_type use EDtypesMod , only : AREA use EDtypesMod , only : AREA_INV @@ -1919,7 +1919,7 @@ subroutine update_history_nutrflux(this,csite) type(ed_site_type), intent(in) :: csite type(ed_patch_type), pointer :: cpatch - type(ed_cohort_type), pointer :: ccohort + type(fates_cohort_type), pointer :: ccohort integer :: iclscpf ! layer x size x pft class index integer :: iscpf ! Size x pft class index integer :: io_si ! site's global index in the history vector @@ -2205,7 +2205,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) integer :: return_code type(ed_patch_type),pointer :: cpatch - type(ed_cohort_type),pointer :: ccohort + type(fates_cohort_type),pointer :: ccohort real(r8), parameter :: reallytalltrees = 1000. ! some large number (m) @@ -4363,7 +4363,7 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) integer :: ipa2 ! patch incrementer integer :: cnlfpft_indx, cnlf_indx, ipft, ican, ileaf ! more iterators and indices type(ed_patch_type),pointer :: cpatch - type(ed_cohort_type),pointer :: ccohort + type(fates_cohort_type),pointer :: ccohort real(r8) :: per_dt_tstep ! Time step in frequency units (/s) associate( hio_gpp_si => this%hvars(ih_gpp_si)%r81d, & @@ -4855,7 +4855,7 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) real(r8) :: depth_frac ! fraction of rhizosphere layer depth occupied by current soil layer character(2) :: fmt_char type(ed_patch_type),pointer :: cpatch - type(ed_cohort_type),pointer :: ccohort + type(fates_cohort_type),pointer :: ccohort type(ed_cohort_hydr_type), pointer :: ccohort_hydr type(ed_site_hydr_type), pointer :: site_hydr real(r8) :: per_dt_tstep ! Time step in frequency units (/s) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 4fc365ce62..f922b4ee36 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -19,18 +19,18 @@ module FatesInterfaceMod use EDParamsMod , only : maxpatch_primary use EDParamsMod , only : maxpatch_secondary use EDParamsMod , only : max_cohort_per_patch - use EDTypesMod , only : maxSWb - use EDTypesMod , only : ivis - use EDTypesMod , only : inir - use EDTypesMod , only : nclmax - use EDTypesMod , only : nlevleaf + use EDParamsMod , only : maxSWb + use EDParamsMod , only : ivis + use EDParamsMod , only : inir + use EDParamsMod , only : nclmax + use EDParamsMod , only : nlevleaf use EDTypesMod , only : maxpft use EDTypesMod , only : do_fates_salinity use EDTypesMod , only : numWaterMem use EDTypesMod , only : numlevsoil_max use EDTypesMod , only : ed_site_type use EDTypesMod , only : ed_patch_type - use EDTypesMod , only : ed_cohort_type + use EDTypesMod , only : fates_cohort_type use EDTypesMod , only : area_inv use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : itrue,ifalse @@ -57,8 +57,8 @@ module FatesInterfaceMod use EDParamsMod , only : ED_val_history_height_bin_edges use EDParamsMod , only : ED_val_history_coageclass_bin_edges use CLMFatesParamInterfaceMod , only : FatesReadParameters - use EDTypesMod , only : p_uptake_mode - use EDTypesMod , only : n_uptake_mode + use EDParamsMod , only : p_uptake_mode + use EDParamsMod , only : n_uptake_mode use EDTypesMod , only : ed_site_type use FatesConstantsMod , only : prescribed_p_uptake use FatesConstantsMod , only : prescribed_n_uptake @@ -1943,7 +1943,7 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) type(bc_in_type), intent(in) :: bc_in(:) type(ed_patch_type), pointer :: cpatch - type(ed_cohort_type), pointer :: ccohort + type(fates_cohort_type), pointer :: ccohort integer :: s, ifp, io_si do s = 1,size(sites,dim=1) diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index 58156dd3fb..7cfe9d84e1 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -34,7 +34,7 @@ module FatesInventoryInitMod use FatesLitterMod , only : litter_type use EDTypesMod , only : ed_site_type use EDTypesMod , only : ed_patch_type - use EDTypesMod , only : ed_cohort_type + use EDTypesMod , only : fates_cohort_type use EDTypesMod , only : area use EDTypesMod , only : leaves_on use EDTypesMod , only : leaves_off @@ -125,7 +125,7 @@ subroutine initialize_sites_by_inventory(nsites,sites,bc_in) ! Locals type(ed_site_type), pointer :: currentSite type(ed_patch_type), pointer :: currentpatch - type(ed_cohort_type), pointer :: currentcohort + type(fates_cohort_type), pointer :: currentcohort type(ed_patch_type), pointer :: newpatch type(ed_patch_type), pointer :: olderpatch type(ed_patch_type), pointer :: head_of_unsorted_patch_list @@ -904,7 +904,7 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & integer,parameter :: rstatus = 0 ! recruit status type(ed_patch_type), pointer :: cpatch ! current patch pointer - type(ed_cohort_type), pointer :: temp_cohort ! temporary patch (needed for allom funcs) + type(fates_cohort_type), pointer :: temp_cohort ! temporary patch (needed for allom funcs) integer :: ipa ! patch idex integer :: iage integer :: el @@ -1193,7 +1193,7 @@ subroutine write_inventory_type1(currentSite) ! Locals type(ed_patch_type), pointer :: currentpatch - type(ed_cohort_type), pointer :: currentcohort + type(fates_cohort_type), pointer :: currentcohort character(len=128) :: pss_name_out ! output file string character(len=128) :: css_name_out ! output file string diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 4efe053627..beb3215dfa 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -1812,10 +1812,10 @@ subroutine set_restart_vectors(this,nc,nsites,sites) use FatesInterfaceTypesMod, only : fates_maxElementsPerPatch use FatesInterfaceTypesMod, only : numpft use EDTypesMod, only : ed_site_type - use EDTypesMod, only : ed_cohort_type + use EDTypesMod, only : fates_cohort_type use EDTypesMod, only : ed_patch_type - use EDTypesMod, only : maxSWb - use EDTypesMod, only : nclmax + use EDParamsMod, only : maxSWb + use EDParamsMod, only : nclmax use EDTypesMod, only : numWaterMem use EDTypesMod, only : num_vegtemp_mem use FatesInterfaceTypesMod, only : nlevdamage @@ -1885,7 +1885,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) type(fates_restart_variable_type) :: rvar type(ed_patch_type),pointer :: cpatch - type(ed_cohort_type),pointer :: ccohort + type(fates_cohort_type),pointer :: ccohort associate( rio_npatch_si => this%rvars(ir_npatch_si)%int1d, & @@ -2508,7 +2508,7 @@ subroutine create_patchcohort_structure(this, nc, nsites, sites, bc_in, bc_out) ! --------------------------------------------------------------------------------- use EDTypesMod, only : ed_site_type - use EDTypesMod, only : ed_cohort_type + use EDTypesMod, only : fates_cohort_type use EDTypesMod, only : ed_patch_type use EDTypesMod, only : maxSWb use FatesInterfaceTypesMod, only : fates_maxElementsPerPatch @@ -2534,8 +2534,8 @@ subroutine create_patchcohort_structure(this, nc, nsites, sites, bc_in, bc_out) ! local variables type(ed_patch_type) , pointer :: newp - type(ed_cohort_type), pointer :: new_cohort - type(ed_cohort_type), pointer :: prev_cohort + type(fates_cohort_type), pointer :: new_cohort + type(fates_cohort_type), pointer :: prev_cohort integer :: cohortstatus integer :: s ! site index integer :: idx_pa ! local patch index @@ -2708,7 +2708,7 @@ end subroutine create_patchcohort_structure subroutine get_restart_vectors(this, nc, nsites, sites) use EDTypesMod, only : ed_site_type - use EDTypesMod, only : ed_cohort_type + use EDTypesMod, only : fates_cohort_type use EDTypesMod, only : ed_patch_type use EDTypesMod, only : maxSWb use EDTypesMod, only : nclmax @@ -2729,7 +2729,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ! ---------------------------------------------------------------------------------- ! LL pointers type(ed_patch_type),pointer :: cpatch ! current patch - type(ed_cohort_type),pointer :: ccohort ! current cohort + type(fates_cohort_type),pointer :: ccohort ! current cohort type(litter_type), pointer :: litt ! litter object on the current patch ! loop indices integer :: s, i, j, k diff --git a/main/FatesSizeAgeTypeIndicesMod.F90 b/main/FatesSizeAgeTypeIndicesMod.F90 index 75eef6b6ad..7945bef035 100644 --- a/main/FatesSizeAgeTypeIndicesMod.F90 +++ b/main/FatesSizeAgeTypeIndicesMod.F90 @@ -6,7 +6,7 @@ module FatesSizeAgeTypeIndicesMod use FatesInterfaceTypesMod, only : nlevage use FatesInterfaceTypesMod, only : nlevheight use FatesInterfaceTypesMod, only : nlevcoage - use EDTypesMod, only : nclmax + use EDParamsMod, only : nclmax use FatesInterfaceTypesMod, only : nlevdamage use EDParamsMod, only : ED_val_history_sizeclass_bin_edges use EDParamsMod, only : ED_val_history_ageclass_bin_edges diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 0f4b29b4b6..03acfd8a77 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -56,9 +56,8 @@ module PRTAllometricCNPMod use FatesConstantsMod , only : fates_unset_int use FatesConstantsMod , only : sec_per_day use PRTParametersMod , only : prt_params - use EDTypesMod , only : leaves_on,leaves_off - use EDTypesMod , only : p_uptake_mode - use EDTypesMod , only : n_uptake_mode + use FatesConstantsMod , only : leaves_on, leaves_off + use EDParamsMod , only : p_uptake_mode, n_uptake_mode use FatesConstantsMod , only : prescribed_p_uptake use FatesConstantsMod , only : prescribed_n_uptake use EDPftvarcon, only : EDPftvarcon_inst @@ -2438,6 +2437,4 @@ subroutine EstimateGrowthNC(this,target_c,target_dcdd,state_mask,avg_nc,avg_pc) return end subroutine EstimateGrowthNC - - end module PRTAllometricCNPMod diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 9f34e39e9c..a52f69d8ee 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -1140,6 +1140,6 @@ subroutine FastPRTAllometricCarbon(this) return end subroutine FastPRTAllometricCarbon - + end module PRTAllometricCarbonMod From 6799bd1d23e8a5d1b4fcc414cba995f40b53c273 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Wed, 5 Apr 2023 14:19:59 -0600 Subject: [PATCH 603/852] more refactoring --- biogeochem/EDCanopyStructureMod.F90 | 9 ++--- biogeochem/EDCohortDynamicsMod.F90 | 35 +++++++++---------- biogeochem/EDMortalityFunctionsMod.F90 | 28 ++++++++++----- biogeochem/EDPatchDynamicsMod.F90 | 25 +++++++------ biogeochem/EDPhysiologyMod.F90 | 15 ++++---- biogeophys/FatesPlantHydraulicsMod.F90 | 10 +++--- biogeophys/FatesPlantRespPhotosynthMod.F90 | 8 ++--- .../parteh/f90src/FatesCohortWrapMod.F90 | 2 +- main/EDInitMod.F90 | 7 ++-- main/EDMainMod.F90 | 13 ++++--- main/EDTypesMod.F90 | 2 +- main/FatesHistoryInterfaceMod.F90 | 8 ++--- main/FatesInterfaceMod.F90 | 10 +++--- main/FatesInventoryInitMod.F90 | 3 +- main/FatesRestartInterfaceMod.F90 | 20 +++++------ 15 files changed, 105 insertions(+), 90 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 692ffee47a..0c8178e4f3 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -17,7 +17,7 @@ module EDCanopyStructureMod use FatesAllometryMod , only : carea_allom use EDCohortDynamicsMod , only : copy_cohort, terminate_cohorts, terminate_cohort, fuse_cohorts use EDCohortDynamicsMod , only : InitPRTObject - use EDCohortDynamicsMod , only : InitPRTBoundaryConditions + use EDTypesMod , only : InitPRTBoundaryConditions use FatesAllometryMod , only : tree_lai use FatesAllometryMod , only : tree_sai use EDtypesMod , only : ed_site_type, ed_patch_type, fates_cohort_type @@ -1499,7 +1499,8 @@ subroutine leaf_area_profile( currentSite ) ! !USES: - use EDtypesMod , only : area, dinc_vai, dlower_vai, hitemax, n_hite_bins + use EDtypesMod , only : area, hitemax, n_hite_bins + use EDParamsMod, only : dinc_vai, dlower_vai ! ! !ARGUMENTS @@ -2126,7 +2127,7 @@ subroutine UpdatePatchLAI(currentPatch) ! --------------------------------------------------------------------------------------------- ! Uses - use EDtypesMod, only : dlower_vai + use EDParamsMod, only : dlower_vai ! Arguments type(ed_patch_type),intent(inout), target :: currentPatch @@ -2175,7 +2176,7 @@ subroutine UpdateCohortLAI(currentCohort, canopy_layer_tlai, total_canopy_area) ! Update LAI and related variables for a given cohort ! Uses - use EDtypesMod, only : dlower_vai + use EDParamsMod, only : dlower_vai ! Arguments type(fates_cohort_type),intent(inout), target :: currentCohort diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 3d6296b6a7..f5b5bbe0a1 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -28,6 +28,7 @@ Module EDCohortDynamicsMod use FatesParameterDerivedMod, only : param_derived use EDTypesMod , only : ed_site_type, ed_patch_type use EDTypesMod , only : fates_cohort_type + use EDTypesMod , only : InitPRTBoundaryConditions use EDParamsMod , only : nclmax use PRTGenericMod , only : element_list use PRTGenericMod , only : StorageNutrientTarget @@ -38,12 +39,12 @@ Module EDCohortDynamicsMod use EDTypesMod , only : AREA use EDTypesMod , only : min_npm2, min_nppatch use EDTypesMod , only : min_n_safemath - use EDTypesMod , only : nlevleaf + use EDParamsMod , only : nlevleaf use PRTGenericMod , only : max_nleafage use EDTypesMod , only : ican_upper use EDTypesMod , only : site_fluxdiags_type use PRTGenericMod , only : num_elements - use EDTypesMod , only : leaves_on + use FatesConstantsMod , only : leaves_on use EDParamsMod , only : ED_val_cohort_age_fusion_tol use FatesInterfaceTypesMod , only : hlm_use_planthydro use FatesInterfaceTypesMod , only : hlm_parteh_mode @@ -116,7 +117,6 @@ Module EDCohortDynamicsMod private ! public :: create_cohort - public :: zero_cohort public :: terminate_cohorts public :: terminate_cohort public :: fuse_cohorts @@ -125,7 +125,6 @@ Module EDCohortDynamicsMod public :: copy_cohort public :: count_cohorts public :: InitPRTObject - public :: InitPRTBoundaryConditions public :: SendCohortToLitter public :: UpdateCohortBioPhysRates public :: DeallocateCohort @@ -200,6 +199,7 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & type(fates_cohort_type), pointer :: storebigcohort integer :: iage ! loop counter for leaf age classes real(r8) :: leaf_c ! total leaf carbon +real(r8) :: rmean_temp ! running mean temperature integer :: tnull,snull ! are the tallest and shortest cohorts allocate integer :: nlevrhiz ! number of rhizosphere layers @@ -207,7 +207,7 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & allocate(new_cohort) -new_cohort%init(prt) +call new_cohort%init(prt) !**********************/ ! Define cohort state variable @@ -215,9 +215,6 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & new_cohort%indexnumber = fates_unset_int ! Cohort indexing was not thread-safe, setting ! bogus value for the time being (RGK-012017) - -new_cohort%patchptr => patchptr - new_cohort%pft = pft new_cohort%crowndamage = crowndamage new_cohort%status_coh = status @@ -354,14 +351,15 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & ! available to be subsumed in the new plant tissues. ! So we go through the process of pre-initializing the hydraulic ! states in the temporary cohort, to calculate this new number density - - call ConstrainRecruitNumber(currentSite,new_cohort, bc_in) + rmean_temp = patchptr%tveg24%GetMean() + call ConstrainRecruitNumber(currentSite, new_cohort, patchptr, & + bc_in, rmean_temp) endif endif -call insert_cohort(new_cohort, patchptr%tallest, patchptr%shortest, tnull, snull, & +call insert_cohort(patchptr, new_cohort, patchptr%tallest, patchptr%shortest, tnull, snull, & storebigcohort, storesmallcohort) patchptr%tallest => storebigcohort @@ -1413,7 +1411,8 @@ subroutine sort_cohorts(patchptr) shortestc => current_c endif - call insert_cohort(current_c, tallestc, shortestc, tnull, snull, storebigcohort, storesmallcohort) + call insert_cohort(current_patch, current_c, tallestc, shortestc, & + tnull, snull, storebigcohort, storesmallcohort) current_patch%tallest => storebigcohort current_patch%shortest => storesmallcohort @@ -1424,7 +1423,7 @@ subroutine sort_cohorts(patchptr) end subroutine sort_cohorts !-------------------------------------------------------------------------------------! - subroutine insert_cohort(pcc, ptall, pshort, tnull, snull, storebigcohort, storesmallcohort) + subroutine insert_cohort(currentPatch, pcc, ptall, pshort, tnull, snull, storebigcohort, storesmallcohort) ! ! !DESCRIPTION: ! Insert cohort into linked list @@ -1432,6 +1431,7 @@ subroutine insert_cohort(pcc, ptall, pshort, tnull, snull, storebigcohort, store ! !USES: ! ! !ARGUMENTS + type(ed_patch_type), intent(inout), target :: currentPatch type(fates_cohort_type) , intent(inout), pointer :: pcc type(fates_cohort_type) , intent(inout), pointer :: ptall type(fates_cohort_type) , intent(inout), pointer :: pshort @@ -1441,7 +1441,7 @@ subroutine insert_cohort(pcc, ptall, pshort, tnull, snull, storebigcohort, store type(fates_cohort_type) , intent(inout),pointer,optional :: storebigcohort ! storage of the largest cohort for insertion routine ! ! !LOCAL VARIABLES: - type(ed_patch_type), pointer :: currentPatch + !type(ed_patch_type), pointer :: currentPatch type(fates_cohort_type), pointer :: current type(fates_cohort_type), pointer :: tallptr, shortptr, icohort type(fates_cohort_type), pointer :: ptallest, pshortest @@ -1449,7 +1449,6 @@ subroutine insert_cohort(pcc, ptall, pshort, tnull, snull, storebigcohort, store integer :: tallptrnull,exitloop !---------------------------------------------------------------------- - currentPatch => pcc%patchptr ptallest => ptall pshortest => pshort @@ -1498,7 +1497,7 @@ subroutine insert_cohort(pcc, ptall, pshort, tnull, snull, storebigcohort, store storebigcohort => icohort end if currentPatch%tallest => icohort - icohort%patchptr%tallest => icohort + !icohort%patchptr%tallest => icohort !new cohort is not tallest else !next shorter cohort to new cohort is the next shorter cohort @@ -1519,7 +1518,7 @@ subroutine insert_cohort(pcc, ptall, pshort, tnull, snull, storebigcohort, store storesmallcohort => icohort end if currentPatch%shortest => icohort - icohort%patchptr%shortest => icohort + !icohort%patchptr%shortest => icohort else !new cohort is not shortest and becomes next taller cohort !to the cohort just below it as defined in the previous block @@ -1694,7 +1693,7 @@ subroutine copy_cohort( currentCohort,copyc ) !Pointers n%taller => NULL() ! pointer to next tallest cohort n%shorter => NULL() ! pointer to next shorter cohort - n%patchptr => o%patchptr ! pointer to patch that cohort is in + !n%patchptr => o%patchptr ! pointer to patch that cohort is in diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index c8c72f4de9..669ad376a7 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -12,6 +12,7 @@ module EDMortalityFunctionsMod use EDTypesMod , only : fates_cohort_type use EDTypesMod , only : ed_site_type use EDTypesMod , only : ed_patch_type + use EDTypesMod , only : maxpft use FatesConstantsMod , only : itrue,ifalse use FatesAllometryMod , only : bleaf use FatesAllometryMod , only : storage_fraction_of_target @@ -50,7 +51,8 @@ module EDMortalityFunctionsMod - subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmort,dgmort ) + subroutine mortality_rates( cohort_in,bc_in,btran_ft, mean_temp, & + cmort,hmort,bmort, frmort,smort,asmort,dgmort ) ! ============================================================================ ! Calculate mortality rates from carbon storage, hydraulic cavitation, @@ -64,6 +66,8 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmor type (fates_cohort_type), intent(in) :: cohort_in type (bc_in_type), intent(in) :: bc_in + real(r8), intent(in) :: btran_ft(maxpft) + real(r8), intent(in) :: mean_temp real(r8),intent(out) :: bmort ! background mortality : Fraction per year real(r8),intent(out) :: cmort ! carbon starvation mortality real(r8),intent(out) :: hmort ! hydraulic failure mortality @@ -156,7 +160,7 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmor hmort = 0.0_r8 endif else - if(cohort_in%patchptr%btran_ft(cohort_in%pft) <= hf_sm_threshold)then + if(btran_ft(cohort_in%pft) <= hf_sm_threshold)then hmort = EDPftvarcon_inst%mort_scalar_hydrfailure(cohort_in%pft) else hmort = 0.0_r8 @@ -190,7 +194,7 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmor ! Eastern US carbon sink. Glob. Change Biol., 12, 2370-2390, ! doi: 10.1111/j.1365-2486.2006.01254.x - temp_in_C = cohort_in%patchptr%tveg24%GetMean() - tfrz + temp_in_C = mean_temp - tfrz temp_dep_fraction = max(0.0_r8, min(1.0_r8, 1.0_r8 - (temp_in_C - & EDPftvarcon_inst%freezetol(cohort_in%pft))/frost_mort_buffer) ) @@ -225,8 +229,9 @@ end subroutine mortality_rates ! ============================================================================ - subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_primary, & - harvestable_forest_c, harvest_tag) + subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, btran_ft, & + mean_temp, anthro_disturbance_label, age_since_anthro_disturbance, & + frac_site_primary, harvestable_forest_c, harvest_tag) ! ! !DESCRIPTION: @@ -241,7 +246,11 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_pr type(ed_site_type), intent(inout), target :: currentSite type(fates_cohort_type),intent(inout), target :: currentCohort type(bc_in_type), intent(in) :: bc_in - real(r8), intent(in) :: frac_site_primary + real(r8), intent(in) :: btran_ft(maxpft) + real(r8), intent(in) :: mean_temp + integer, intent(in) :: anthro_disturbance_label + real(r8), intent(in) :: age_since_anthro_disturbance + real(r8), intent(in) :: frac_site_primary real(r8), intent(in) :: harvestable_forest_c(:) ! total carbon available for logging, kgC site-1 integer, intent(out) :: harvest_tag(:) ! tag to record the harvest status @@ -268,7 +277,8 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_pr ! Mortality for trees in the understorey. !if trees are in the canopy, then their death is 'disturbance'. This probably needs a different terminology - call mortality_rates(currentCohort,bc_in,cmort,hmort,bmort,frmort,smort, asmort, dgmort) + call mortality_rates(currentCohort,bc_in,btran_ft, mean_temp, & + cmort,hmort,bmort,frmort, smort, asmort, dgmort) call LoggingMortality_frac(ipft, currentCohort%dbh, currentCohort%canopy_layer, & currentCohort%lmort_direct, & currentCohort%lmort_collateral, & @@ -277,8 +287,8 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_pr bc_in%hlm_harvest_rates, & bc_in%hlm_harvest_catnames, & bc_in%hlm_harvest_units, & - currentCohort%patchptr%anthro_disturbance_label, & - currentCohort%patchptr%age_since_anthro_disturbance, & + anthro_disturbance_label, & + age_since_anthro_disturbance, & frac_site_primary, harvestable_forest_c, harvest_tag) if (currentCohort%canopy_layer > 1)then diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index ad4b6e898f..77027d3dab 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -32,8 +32,8 @@ module EDPatchDynamicsMod use EDTypesMod , only : ican_upper use PRTGenericMod , only : num_elements use PRTGenericMod , only : element_list - use EDTypesMod , only : lg_sf - use EDTypesMod , only : dl_sf + use FatesLitterMod , only : lg_sf + use FatesLitterMod , only : dl_sf use EDTypesMod , only : dump_patch use EDTypesMod , only : N_DIST_TYPES use EDTypesMod , only : AREA_INV @@ -76,7 +76,7 @@ module EDPatchDynamicsMod use FatesConstantsMod , only : fates_unset_int use FatesConstantsMod , only : hlm_harvest_carbon use EDCohortDynamicsMod , only : InitPRTObject - use EDCohortDynamicsMod , only : InitPRTBoundaryConditions + use EDTypesMod , only : InitPRTBoundaryConditions use ChecksBalancesMod, only : SiteMassStock use PRTGenericMod, only : carbon12_element use PRTGenericMod, only : leaf_organ @@ -198,6 +198,7 @@ subroutine disturbance_rates( site_in, bc_in) real(r8) :: frac_site_primary real(r8) :: harvest_rate real(r8) :: tempsum + real(r8) :: mean_temp real(r8) :: harvestable_forest_c(hlm_num_lu_harvest_cats) integer :: harvest_tag(hlm_num_lu_harvest_cats) @@ -218,9 +219,10 @@ subroutine disturbance_rates( site_in, bc_in) currentCohort => currentPatch%shortest do while(associated(currentCohort)) ! Mortality for trees in the understorey. - currentCohort%patchptr => currentPatch - - call mortality_rates(currentCohort,bc_in,cmort,hmort,bmort,frmort,smort,asmort,dgmort) + !currentCohort%patchptr => currentPatch + mean_temp = currentPatch%tveg24%GetMean() + call mortality_rates(currentCohort,bc_in,currentPatch%btran_ft, & + mean_temp, cmort,hmort,bmort,frmort,smort,asmort,dgmort) currentCohort%dmort = cmort+hmort+bmort+frmort+smort+asmort+dgmort call carea_allom(currentCohort%dbh,currentCohort%n,site_in%spread,currentCohort%pft, & currentCohort%crowndamage,currentCohort%c_area) @@ -405,7 +407,7 @@ subroutine spawn_patches( currentSite, bc_in) ! !USES: use EDParamsMod , only : ED_val_understorey_death, logging_coll_under_frac - use EDCohortDynamicsMod , only : zero_cohort, copy_cohort, terminate_cohorts + use EDCohortDynamicsMod , only : copy_cohort, terminate_cohorts use FatesConstantsMod , only : rsnbl_math_prec ! @@ -1099,8 +1101,8 @@ subroutine spawn_patches( currentSite, bc_in) new_patch%shortest => nc nc%shorter => null() endif - nc%patchptr => new_patch - call insert_cohort(nc, new_patch%tallest, new_patch%shortest, & + !nc%patchptr => new_patch + call insert_cohort(new_patch, nc, new_patch%tallest, new_patch%shortest, & tnull, snull, storebigcohort, storesmallcohort) new_patch%tallest => storebigcohort @@ -2736,12 +2738,13 @@ subroutine fuse_2_patches(csite, dp, rp) rp%shortest => currentCohort endif - call insert_cohort(currentCohort, rp%tallest, rp%shortest, tnull, snull, storebigcohort, storesmallcohort) + call insert_cohort(rp, currentCohort, rp%tallest, rp%shortest, & + tnull, snull, storebigcohort, storesmallcohort) rp%tallest => storebigcohort rp%shortest => storesmallcohort - currentCohort%patchptr => rp + !currentCohort%patchptr => rp currentCohort => nextc diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 8c8632d5db..ecadf16c2a 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -29,10 +29,9 @@ module EDPhysiologyMod use EDPftvarcon , only : GetDecompyFrac use FatesInterfaceTypesMod, only : bc_in_type use FatesInterfaceTypesMod, only : bc_out_type - use EDCohortDynamicsMod , only : zero_cohort use EDCohortDynamicsMod , only : create_cohort, sort_cohorts use EDCohortDynamicsMod , only : InitPRTObject - use EDCohortDynamicsMod , only : InitPRTBoundaryConditions + use EDTypesMod, only : InitPRTBoundaryConditions use EDCohortDynamicsMod , only : copy_cohort use FatesAllometryMod , only : tree_lai use FatesAllometryMod , only : tree_sai @@ -42,7 +41,9 @@ module EDPhysiologyMod use EDTypesMod , only : site_massbal_type use EDTypesMod , only : numlevsoil_max use EDTypesMod , only : numWaterMem - use EDTypesMod , only : dl_sf, dinc_vai, dlower_vai, area_inv + use FatesLitterMod , only : dl_sf + use EDParamsMod , only : dinc_vai, dlower_vai + use EDTypesMod , only : area_inv use EDTypesMod , only : AREA use FatesLitterMod , only : ncwd use FatesLitterMod , only : ndcmpy @@ -55,8 +56,8 @@ module EDPhysiologyMod use EDTypesMod , only : num_vegtemp_mem use EDTypesMod , only : maxpft use EDTypesMod , only : ed_site_type, ed_patch_type, fates_cohort_type - use EDTypesMod , only : leaves_on - use EDTypesMod , only : leaves_off + use FatesConstantsMod , only : leaves_on + use FatesConstantsMod , only : leaves_off use EDTypesMod , only : min_n_safemath use PRTGenericMod , only : num_elements use PRTGenericMod , only : element_list @@ -272,7 +273,7 @@ subroutine GenerateDamageAndLitterFluxes( csite, cpatch, bc_in ) call InitPRTObject(ndcohort%prt) call InitPRTBoundaryConditions(ndcohort) - call zero_cohort(ndcohort) + call ndcohort%zero_values() ! nc_canopy_d is the new cohort that gets damaged call copy_cohort(ccohort, ndcohort) @@ -2026,7 +2027,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) !---------------------------------------------------------------------- allocate(temp_cohort) ! create temporary cohort - call zero_cohort(temp_cohort) + call temp_cohort%zero_values() do ft = 1,numpft diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 4846336c9f..9ed2ef630c 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -56,7 +56,7 @@ module FatesPlantHydraulicsMod use EDTypesMod , only : fates_cohort_type use EDTypesMod , only : AREA_INV use EDTypesMod , only : AREA - use EDParamsMod , only : leaves_on + use FatesConstantsMod , only : leaves_on use FatesInterfaceTypesMod , only : bc_in_type use FatesInterfaceTypesMod , only : bc_out_type @@ -1925,7 +1925,7 @@ end subroutine RecruitWUptake !===================================================================================== -subroutine ConstrainRecruitNumber(csite,ccohort, bc_in) +subroutine ConstrainRecruitNumber(csite,ccohort, cpatch, bc_in, mean_temp) ! --------------------------------------------------------------------------- ! This subroutine constrains the number of plants so that there is enought water @@ -1935,12 +1935,13 @@ subroutine ConstrainRecruitNumber(csite,ccohort, bc_in) ! Arguments type(ed_site_type), intent(inout), target :: csite type(fates_cohort_type) , intent(inout), target :: ccohort + type(ed_patch_type), intent(inout), target :: cpatch type(bc_in_type) , intent(in) :: bc_in + real(r8), intent(in) :: mean_temp ! Locals type(ed_cohort_hydr_type), pointer :: ccohort_hydr type(ed_site_hydr_type), pointer :: csite_hydr - type(ed_patch_type), pointer :: cpatch real(r8) :: tmp1 real(r8) :: watres_local ! minum water content [m3/m3] real(r8) :: total_water ! total water in rhizosphere at a specific layer (m^3 ha-1) @@ -1956,7 +1957,6 @@ subroutine ConstrainRecruitNumber(csite,ccohort, bc_in) real(r8) :: leaf_m, store_m, sapw_m ! Element mass in organ tissues real(r8) :: fnrt_m, struct_m, repro_m ! Element mass in organ tissues - cpatch => ccohort%patchptr csite_hydr => csite%si_hydr ccohort_hydr =>ccohort%co_hydr recruitw = (sum(ccohort_hydr%th_ag(:)*ccohort_hydr%v_ag(:)) + & @@ -1990,7 +1990,7 @@ subroutine ConstrainRecruitNumber(csite,ccohort, bc_in) end do ! Prevent recruitment when temperatures are freezing or below - if (cpatch%tveg24%GetMean() <= 273.15_r8) then + if (mean_temp <= 273.15_r8) then nmin = 0._r8 end if diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 74f93e67ce..44fd2abda3 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -39,8 +39,8 @@ module FATESPlantRespPhotosynthMod use FatesInterfaceTypesMod, only : numpft use FatesInterfaceTypesMod, only : nleafage use EDTypesMod, only : maxpft - use EDTypesMod, only : nlevleaf - use EDTypesMod, only : nclmax + use EDParamsMod, only : nlevleaf + use EDParamsMod, only : nclmax use PRTGenericMod, only : max_nleafage use EDTypesMod, only : do_fates_salinity use EDParamsMod, only : q10_mr @@ -130,8 +130,8 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) use EDTypesMod , only : fates_cohort_type use EDTypesMod , only : ed_site_type use EDTypesMod , only : maxpft - use EDTypesMod , only : dinc_vai - use EDTypesMod , only : dlower_vai + use EDParamsMod , only : dinc_vai + use EDParamsMod , only : dlower_vai use FatesInterfaceTypesMod , only : bc_in_type use FatesInterfaceTypesMod , only : bc_out_type use EDCanopyStructureMod, only : calc_areaindex diff --git a/functional_unit_testing/parteh/f90src/FatesCohortWrapMod.F90 b/functional_unit_testing/parteh/f90src/FatesCohortWrapMod.F90 index 9f520593b3..4d5efcf241 100644 --- a/functional_unit_testing/parteh/f90src/FatesCohortWrapMod.F90 +++ b/functional_unit_testing/parteh/f90src/FatesCohortWrapMod.F90 @@ -69,7 +69,7 @@ module FatesCohortWrapMod use FatesConstantsMod , only : nearzero - use EDTypesMod , only : nclmax + use EDParamsMod , only : nclmax use FatesGlobals , only : endrun => fates_endrun use FatesGlobals , only : fates_log diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index f02653ef5c..39d7222543 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -9,9 +9,9 @@ module EDInitMod use FatesConstantsMod , only : itrue use FatesConstantsMod , only : fates_unset_int use FatesConstantsMod , only : primaryforest - use FatesConstantsMod , only : nearzero + use FatesConstantsMod , only : nearzero use FatesGlobals , only : endrun => fates_endrun - use EDTypesMod , only : nclmax + use EDParamsMod , only : nclmax use FatesGlobals , only : fates_log use FatesInterfaceTypesMod , only : hlm_is_restart use EDPftvarcon , only : EDPftvarcon_inst @@ -30,8 +30,7 @@ module EDInitMod use EDTypesMod , only : AREA use EDTypesMod , only : init_spread_near_bare_ground use EDTypesMod , only : init_spread_inventory - use EDTypesMod , only : leaves_on - use EDTypesMod , only : leaves_off + use FatesConstantsMod , only : leaves_on, leaves_off use PRTGenericMod , only : num_elements use PRTGenericMod , only : element_list use EDTypesMod , only : phen_cstat_nevercold diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 0912b05655..79ce7eca6a 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -335,11 +335,11 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) use PRTGenericMod , only : fnrt_organ use FatesInterfaceTypesMod, only : hlm_use_cohort_age_tracking use FatesConstantsMod, only : itrue - use EDCohortDynamicsMod , only : zero_cohort, copy_cohort, insert_cohort + use EDCohortDynamicsMod , only : copy_cohort, insert_cohort use EDCohortDynamicsMod , only : DeallocateCohort use FatesPlantHydraulicsMod, only : InitHydrCohort use EDCohortDynamicsMod , only : InitPRTObject - use EDCohortDynamicsMod , only : InitPRTBoundaryConditions + use EDTypesMod , only : InitPRTBoundaryConditions use FatesConstantsMod , only : nearzero use EDCanopyStructureMod , only : canopy_structure use PRTLossFluxesMod , only : PRTDamageRecoveryFluxes @@ -375,6 +375,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) logical :: is_drought ! logical for if the plant (site) is in a drought state real(r8) :: delta_dbh ! correction for dbh real(r8) :: delta_hite ! correction for hite + real(r8) :: mean_temp logical :: newly_recovered ! If the current loop is dealing with a newly created cohort, which ! was created because it is a clone of the previous cohort in @@ -478,8 +479,12 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! Calculate the mortality derivatives - call Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_primary, & - harvestable_forest_c, harvest_tag ) + mean_temp = currentPatch%tveg24%GetMean() + call Mortality_Derivative(currentSite, currentCohort, bc_in, & + currentPatch%btran_ft, mean_temp, & + currentPatch%anthro_disturbance_label, & + currentPatch%age_since_anthro_disturbance, frac_site_primary, & + harvestable_forest_c, harvest_tag) ! ----------------------------------------------------------------------------- ! Apply Plant Allocation and Reactive Transport diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index a7f7b25fa1..917efe66ab 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -860,7 +860,7 @@ module EDTypesMod public :: dump_site public :: dump_patch public :: dump_cohort_hydr - public :: CanUpperUnder + public :: InitPRTBoundaryConditions contains ! ===================================================================================== diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index f984ed8365..d6ff9ac0ea 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -12,7 +12,7 @@ module FatesHistoryInterfaceMod use FatesConstantsMod , only : t_water_freeze_k_1atm use FatesGlobals , only : fates_log use FatesGlobals , only : endrun => fates_endrun - use EDTypesMod , only : nclmax + use EDParamsMod , only : nclmax use EDTypesMod , only : ican_upper use PRTGenericMod , only : element_pos use PRTGenericMod , only : num_elements @@ -2103,7 +2103,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) ! --------------------------------------------------------------------------------- - use EDtypesMod , only : nfsc + use FatesLitterMod , only : nfsc use FatesLitterMod , only : ncwd use EDtypesMod , only : ican_upper use EDtypesMod , only : ican_ustory @@ -2118,7 +2118,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) use FatesSizeAgeTypeIndicesMod, only : get_cdamagesizepft_class_index use FatesSizeAgeTypeIndicesMod, only : coagetype_class_index - use EDTypesMod , only : nlevleaf + use EDParamsMod , only : nlevleaf use EDParamsMod , only : ED_val_history_height_bin_edges use FatesInterfaceTypesMod , only : nlevdamage @@ -4335,7 +4335,7 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) ! after rapid timescale productivity calculations (gpp and respiration). ! --------------------------------------------------------------------------------- - use EDTypesMod , only : nclmax, nlevleaf + use EDParamsMod , only : nclmax, nlevleaf ! ! Arguments class(fates_history_interface_type) :: this diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index f922b4ee36..b8fd42ca38 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -10,8 +10,8 @@ module FatesInterfaceMod ! ------------------------------------------------------------------------------------ use EDTypesMod , only : ed_site_type - use EDTypesMod , only : dinc_vai - use EDTypesMod , only : dlower_vai + use EDParamsMod , only : dinc_vai + use EDParamsMod , only : dlower_vai use EDParamsMod , only : ED_val_vai_top_bin_width use EDParamsMod , only : ED_val_vai_width_increase_factor use EDParamsMod , only : ED_val_history_damage_bin_edges @@ -1057,9 +1057,9 @@ end subroutine InitPARTEHGlobals subroutine fates_history_maps - use EDTypesMod, only : NFSC - use EDTypesMod, only : nclmax - use EDTypesMod, only : nlevleaf + use FatesLitterMod, only : NFSC + use EDParamsMod, only : nclmax + use EDParamsMod, only : nlevleaf use EDParamsMod, only : ED_val_history_sizeclass_bin_edges use EDParamsMod, only : ED_val_history_ageclass_bin_edges use EDParamsMod, only : ED_val_history_height_bin_edges diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index 7cfe9d84e1..aba46250d6 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -36,8 +36,7 @@ module FatesInventoryInitMod use EDTypesMod , only : ed_patch_type use EDTypesMod , only : fates_cohort_type use EDTypesMod , only : area - use EDTypesMod , only : leaves_on - use EDTypesMod , only : leaves_off + use FatesConstantsMod, only : leaves_on, leaves_off use PRTGenericMod , only : num_elements use PRTGenericMod , only : element_list use EDTypesMod , only : phen_cstat_nevercold diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index beb3215dfa..246f988409 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -32,17 +32,16 @@ module FatesRestartInterfaceMod use FatesPlantHydraulicsMod, only : UpdatePlantPsiFTCFromTheta use PRTGenericMod, only : prt_global use PRTGenericMod, only : prt_cnp_flex_allom_hyp - use EDCohortDynamicsMod, only : nan_cohort - use EDCohortDynamicsMod, only : zero_cohort use EDCohortDynamicsMod, only : InitPRTObject - use EDCohortDynamicsMod, only : InitPRTBoundaryConditions + use EDTypesMod, only : InitPRTBoundaryConditions use FatesPlantHydraulicsMod, only : InitHydrCohort use FatesInterfaceTypesMod, only : nlevsclass use FatesInterfaceTypesMod, only : nlevdamage use FatesLitterMod, only : litter_type - use FatesLitterMod, only : ncwd + use FatesLitterMod, only : ncwd, nfsc use FatesLitterMod, only : ndcmpy - use EDTypesMod, only : nfsc, nlevleaf, area + use EDTypesMod, only : area + use EDParamsMod, only : nlevleaf use PRTGenericMod, only : prt_global use PRTGenericMod, only : num_elements use FatesRunningMeanMod, only : rmean_type @@ -2510,7 +2509,7 @@ subroutine create_patchcohort_structure(this, nc, nsites, sites, bc_in, bc_out) use EDTypesMod, only : ed_site_type use EDTypesMod, only : fates_cohort_type use EDTypesMod, only : ed_patch_type - use EDTypesMod, only : maxSWb + use EDParamsMod, only : maxSWb use FatesInterfaceTypesMod, only : fates_maxElementsPerPatch use EDTypesMod, only : maxpft @@ -2616,9 +2615,8 @@ subroutine create_patchcohort_structure(this, nc, nsites, sites, bc_in, bc_out) do fto = 1, rio_ncohort_pa( io_idx_co_1st ) allocate(new_cohort) - call nan_cohort(new_cohort) - call zero_cohort(new_cohort) - new_cohort%patchptr => newp + call new_cohort%nan_values() + call new_cohort%zero_values() ! If this is the first in the list, it is tallest if (.not.associated(newp%tallest)) then @@ -2710,8 +2708,8 @@ subroutine get_restart_vectors(this, nc, nsites, sites) use EDTypesMod, only : ed_site_type use EDTypesMod, only : fates_cohort_type use EDTypesMod, only : ed_patch_type - use EDTypesMod, only : maxSWb - use EDTypesMod, only : nclmax + use EDParamsMod, only : maxSWb + use EDParamsMod, only : nclmax use FatesInterfaceTypesMod, only : numpft use FatesInterfaceTypesMod, only : fates_maxElementsPerPatch use EDTypesMod, only : numWaterMem From a182e1d58f9c5d77483fda5831f5477756131bdf Mon Sep 17 00:00:00 2001 From: adrifoster Date: Wed, 5 Apr 2023 16:07:53 -0600 Subject: [PATCH 604/852] moving parameters around --- biogeochem/EDPatchDynamicsMod.F90 | 2 +- main/EDTypesMod.F90 | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 77027d3dab..d6c9c74591 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -687,7 +687,7 @@ subroutine spawn_patches( currentSite, bc_in) !allocate(nc%tveg_lpa) !call nc%tveg_lpa%InitRMean(ema_lpa,init_value=new_patch%tveg_lpa%GetMean()) - call zero_cohort(nc) + call nc%zero_values() ! nc is the new cohort that goes in the disturbed patch (new_patch)... currentCohort ! is the curent cohort that stays in the donor patch (currentPatch) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 917efe66ab..f5cf325db1 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -1410,7 +1410,7 @@ subroutine val_check_ed_vars(currentPatch,var_aliases,return_code) call check_var_real(currentCohort%n,'cohort%n',return_code) if(.not.(return_code.eq.0)) then call dump_patch(currentPatch) - call dump_cohort(currentCohort) + call currentCohort%dump() return end if currentCohort => currentCohort%taller @@ -1424,7 +1424,7 @@ subroutine val_check_ed_vars(currentPatch,var_aliases,return_code) call check_var_real(currentCohort%dbh,'cohort%dbh',return_code) if(.not.(return_code.eq.0)) then call dump_patch(currentPatch) - call dump_cohort(currentCohort) + call currentCohort%dump() return end if currentCohort => currentCohort%taller From f8fd35fedb2aca445bd88d14cabef929929f8d84 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 6 Apr 2023 13:11:27 -0700 Subject: [PATCH 605/852] Update to xarray 0.19.0 This incorporates an update to handle a pandas deprication issue when using cftime objects. See https://github.com/pydata/xarray/pull/5359 --- tools/conda-luh2.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/conda-luh2.yml b/tools/conda-luh2.yml index 0be4e7b3b7..b87f1c800a 100644 --- a/tools/conda-luh2.yml +++ b/tools/conda-luh2.yml @@ -3,8 +3,8 @@ channels: - conda-forge - defaults dependencies: - - python=3.7.9 - - xarray + - python + - xarray=0.19.0 - netcdf4 - scipy - nco From 04907488948478d0d6882236603725250da5f17e Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 6 Apr 2023 16:29:47 -0700 Subject: [PATCH 606/852] Truncate to the yml file and update prep function Having too many of the dependencies in the yml file was causing issue with the dependency order and limiting xesmf to an older version. --- tools/conda-luh2.yml | 7 ++---- tools/luh2mod.py | 58 ++++++++++++++++++++++++++------------------ 2 files changed, 36 insertions(+), 29 deletions(-) diff --git a/tools/conda-luh2.yml b/tools/conda-luh2.yml index b87f1c800a..4caf2e341b 100644 --- a/tools/conda-luh2.yml +++ b/tools/conda-luh2.yml @@ -3,11 +3,8 @@ channels: - conda-forge - defaults dependencies: - - python - - xarray=0.19.0 + - xesmf + # xarray which is autodownloaded as xesmf dependency, uses scipy, which needs netcdf4 to open datasets - netcdf4 - - scipy - - nco - pynco - - xesmf prefix: /home/glemieux/local/conda/miniconda3/envs/luh2 diff --git a/tools/luh2mod.py b/tools/luh2mod.py index f30116e5a0..78be603ac1 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -9,30 +9,40 @@ # Add version checking here in case environment.yml not used - - -# Primary function to regrid luh2 data -# -# Prepare the -def PrepDataSet(inputfile_luh2,inputfile_surface): +# Prepare the inputfile to be used for regridding +def PrepDataSet(inputfile,start,stop): # Import the data - ds_luh2 = ImportData(inputfile_luh2) - ds_surfdata = ImportData(inputfile_surface) + inputdataset = ImportData(inputfile) + + # Truncate the data to the user defined range + try: + inputdataset = inputdataset.sel(time=slice(start,stop)) + except TypeError as err: + print("TypeError:", err) + print("Input must be a string") # Correct the necessary variables for both datasets - ds_luh2 = BoundsVariableFixLUH2(ds_luh2) - ds_surfdata = DimensionFixSurfData(ds_surfdata) + PrepDataSet_ESMF(inputdataset) # Set dataset masks - ds_luh2 = SetMask(ds_luh2) - ds_surfdata = SetMask(ds_surfdata) + SetMask(inputdataset) - # Define the xESMF regridder if necessary - # regridder = RegridConservative(ds_luh2,ds_surfdata) + return(inputdataset) - # return(ds_luh2,ds_surfdata,regridder) - return(ds_luh2,ds_surfdata) +# Updating datasets to work with xESMF +def PrepDataSet_ESMF(inputdataset): + + # Check the dataset type + dsflag, dstype = CheckDataSet(inputdataset) + if (dsflag): + if(dstype == "LUH2"): + BoundsVariableFixLUH2(inputdataset) + elif(dstype == "Surface"): + DimensionFixSurfData(inputdataset) + print("data set updated for xESMF") + + return(inputdataset) # Import luh2 or surface data sets def ImportData(inputfile): @@ -101,31 +111,31 @@ def AttribUpdateLUH2(inputfile,output_append="modified"): def BoundsVariableFixLUH2(inputdataset): # Drop the old boundary names to avoid confusion - outputdataset = inputdataset.drop(labels=['lat_bounds','lon_bounds']) + # outputdataset = inputdataset.drop(labels=['lat_bounds','lon_bounds']) # Create lat and lon bounds as a single dimension array out of the LUH2 two dimensional_bounds array. # Future todo: is it possible to have xESMF recognize and use the original 2D array? - outputdataset["lat_b"] = np.insert(inputdataset.lat_bounds[:,1].data,0,inputdataset.lat_bounds[0,0].data) - outputdataset["lon_b"] = np.insert(inputdataset.lon_bounds[:,1].data,0,inputdataset.lon_bounds[0,0].data) + inputdataset["lat_b"] = np.insert(inputdataset.lat_bounds[:,1].data,0,inputdataset.lat_bounds[0,0].data) + inputdataset["lon_b"] = np.insert(inputdataset.lon_bounds[:,1].data,0,inputdataset.lon_bounds[0,0].data) print("LUH2 dataset lat/lon boundary variables formatted and added as new variable for xESMF") - return(outputdataset) + return(inputdataset) # The user will need to use a surface data set to regrid from, but the surface datasets # need to have their dimensions renamed to something recognizable by xESMF def DimensionFixSurfData(surfdataset): # Rename the surface dataset dimensions to something recognizable by xESMF. - outputdataset = surfdataset.rename_dims(dims_dict={'lsmlat':'latitude','lsmlon':'longitude'}) + inputdataset = surfdataset.rename_dims(dims_dict={'lsmlat':'latitude','lsmlon':'longitude'}) # Populate the new surface dataset with the actual lat/lon values - outputdataset['longitude'] = outputdataset.LONGXY.isel(latitude=0) - outputdataset['latitude'] = outputdataset.LATIXY.isel(longitude=0) + inputdataset['longitude'] = outputdataset.LONGXY.isel(latitude=0) + inputdataset['latitude'] = outputdataset.LATIXY.isel(longitude=0) print("Surface dataset dimensions renamed for xESMF") - return(outputdataset) + return(inputdataset) def SetMask(inputdataset): From 91ef322e1f504ea753b43201f295b75e159c0113 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 6 Apr 2023 17:12:10 -0700 Subject: [PATCH 607/852] more intermediate updates --- tools/luh2mod.py | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/tools/luh2mod.py b/tools/luh2mod.py index 78be603ac1..3e074c19e8 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -import re +import argparse, os, re import numpy as np import xarray as xr import xesmf as xe @@ -9,6 +9,38 @@ # Add version checking here in case environment.yml not used +def main(): + + # Add argument parser - subfunction? Seperate common module? + # inputfiles and range should be the only arguments + # Allow variable input files (state and/or transitions and/or management) + # parser = argparse.ArgumentParser() + # args = parser.parse_args() + + # Prep the LUH2 data + ds_luh2 = PrepDataSet(args.luh2file,args.start,args.stop) + + # Prep the regrid target (assuming surface dataset) + ds_regridtarget= PrepDataSet(args.regridtargetfile,args.start,args.stop) + + # Build regridder + regridder = xe.Regridder(ds_luh2, ds_regridtarget, "conservative") + + # Regrid the dataset(s) + regrid_luh2 = regridder(ds_states) + + # Rename the dimensions for the output + regrid_luh2 = regrid_luh2.rename_dims(dims_dict={'latitude':'lsmlat','longitude':'lsmlon'}) + regrid_luh2["LONGXY"] = ds_regridtarget["LONGXY"] + regrid_luh2["LATIXY"] = ds_regridtarget["LATIXY"] + + # Write the files + outputfile = os.path.join() + regrid_luh2.to_netcdf(outputfile) + +# write to netcdf +finb_luh2_all_regrid.to_netcdf('LUH2_historical_1850_2015_4x5_cdk_220302.nc') + # Prepare the inputfile to be used for regridding def PrepDataSet(inputfile,start,stop): @@ -16,6 +48,8 @@ def PrepDataSet(inputfile,start,stop): inputdataset = ImportData(inputfile) # Truncate the data to the user defined range + # This might need some more error handling for when + # the start/stop is out of range try: inputdataset = inputdataset.sel(time=slice(start,stop)) except TypeError as err: @@ -183,11 +217,11 @@ def SetMaskSurfData(inputdataset): # return(outputdataset) return(inputdataset) -def RegridConservative(dataset_from,dataset_to): +# def RegridConservative(dataset_from,dataset_to): # define the regridder transformation - regridder = xe.Regridder(dataset_from, dataset_to, "conservative") + # regridder = xe.Regridder(dataset_from, dataset_to, "conservative") - return(regridder) + # return(regridder) # Apply regridder From 5b65edd86899403e4506a150f87080d4396780c6 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 7 Apr 2023 09:51:04 -0700 Subject: [PATCH 608/852] Add command line argument parsing --- tools/luh2mod.py | 47 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/tools/luh2mod.py b/tools/luh2mod.py index 3e074c19e8..efb40ef752 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -14,17 +14,16 @@ def main(): # Add argument parser - subfunction? Seperate common module? # inputfiles and range should be the only arguments # Allow variable input files (state and/or transitions and/or management) - # parser = argparse.ArgumentParser() - # args = parser.parse_args() + args = CommandLineArgs() # Prep the LUH2 data - ds_luh2 = PrepDataSet(args.luh2file,args.start,args.stop) + ds_luh2 = PrepDataSet(args.luh2file,args.begin,args.end) # Prep the regrid target (assuming surface dataset) - ds_regridtarget= PrepDataSet(args.regridtargetfile,args.start,args.stop) + ds_regridtarget= PrepDataSet(args.regridtargetfile,args.begin,args.end) # Build regridder - regridder = xe.Regridder(ds_luh2, ds_regridtarget, "conservative") + regridder = RegridConservative(ds_luh2, ds_regridtarget, save=True) # Regrid the dataset(s) regrid_luh2 = regridder(ds_states) @@ -38,8 +37,30 @@ def main(): outputfile = os.path.join() regrid_luh2.to_netcdf(outputfile) -# write to netcdf -finb_luh2_all_regrid.to_netcdf('LUH2_historical_1850_2015_4x5_cdk_220302.nc') + # Example of file naming scheme + # finb_luh2_all_regrid.to_netcdf('LUH2_historical_1850_2015_4x5_cdk_220302.nc') + +def CommandLineArgs(): + + parser = argparse.ArgumentParser(description="placeholder desc") + + # Required input luh2 datafile + # TO DO: using the checking function to report back if invalid file input + parser.add_argument("-l","--luh2file", require=True) + + # Provide mutually exlusive arguments for regridding input selection + # Currently assuming that if a target is provided that a regridder file will be saved + regridtarget = parser.add_mutually_exclusive_group(required=True) + regridtarget.add_argument("-rf","--regridderfile") # use previously save regridder file + regridtarget.add_argument("-rt","--regriddertarget") # use a dataset to regrid to + + # Optional input to subset the time range of the data + parser.add_argument("-b","--begin") + parser.add_argument("-e","--end") + + args = parser.parse_args() + + return(args) # Prepare the inputfile to be used for regridding def PrepDataSet(inputfile,start,stop): @@ -217,11 +238,17 @@ def SetMaskSurfData(inputdataset): # return(outputdataset) return(inputdataset) -# def RegridConservative(dataset_from,dataset_to): +def RegridConservative(ds_to_regrid,ds_regrid_target,save=False): # define the regridder transformation - # regridder = xe.Regridder(dataset_from, dataset_to, "conservative") + regridder = xe.Regridder(ds_to_regrid, ds_regrid_target, "conservative") + + # If save flag is set, write regridder to a file + # TO DO: define a more useful name based on inputs + if(save): + filename = regridder.to_netcdf("regridder.nc") + print("regridder saved to file: ", filename) - # return(regridder) + return(regridder) # Apply regridder From 1171e824272da74ea2190ed4d5c818f7d2395067 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Fri, 7 Apr 2023 11:54:54 -0600 Subject: [PATCH 609/852] move cohort type into its own module --- biogeochem/EDCanopyStructureMod.F90 | 10 +- biogeochem/EDCohortDynamicsMod.F90 | 9 +- biogeochem/EDLoggingMortalityMod.F90 | 4 +- biogeochem/EDMortalityFunctionsMod.F90 | 2 +- biogeochem/EDPatchDynamicsMod.F90 | 8 +- biogeochem/EDPhysiologyMod.F90 | 6 +- biogeochem/FatesSoilBGCFluxMod.F90 | 2 +- biogeophys/EDAccumulateFluxesMod.F90 | 3 +- biogeophys/EDBtranMod.F90 | 2 +- biogeophys/FatesBstressMod.F90 | 2 +- biogeophys/FatesPlantHydraulicsMod.F90 | 2 +- biogeophys/FatesPlantRespPhotosynthMod.F90 | 8 +- fire/SFMainMod.F90 | 2 +- main/ChecksBalancesMod.F90 | 2 +- main/EDInitMod.F90 | 3 +- main/EDMainMod.F90 | 13 +- main/EDTypesMod.F90 | 721 +-------------------- main/FatesCohortMod.F90 | 693 ++++++++++++++++++++ main/FatesConstantsMod.F90 | 4 + main/FatesHistoryInterfaceMod.F90 | 8 +- main/FatesHydraulicsMemMod.F90 | 19 + main/FatesInterfaceMod.F90 | 2 +- main/FatesInventoryInitMod.F90 | 2 +- main/FatesRestartInterfaceMod.F90 | 9 +- 24 files changed, 760 insertions(+), 776 deletions(-) create mode 100644 main/FatesCohortMod.F90 diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 0c8178e4f3..09e53623a9 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -17,10 +17,10 @@ module EDCanopyStructureMod use FatesAllometryMod , only : carea_allom use EDCohortDynamicsMod , only : copy_cohort, terminate_cohorts, terminate_cohort, fuse_cohorts use EDCohortDynamicsMod , only : InitPRTObject - use EDTypesMod , only : InitPRTBoundaryConditions use FatesAllometryMod , only : tree_lai use FatesAllometryMod , only : tree_sai - use EDtypesMod , only : ed_site_type, ed_patch_type, fates_cohort_type + use EDtypesMod , only : ed_site_type, ed_patch_type + use FatesCohortMod, only : fates_cohort_type use EDParamsMod , only : nclmax use EDParamsMod , only : nlevleaf use EDtypesMod , only : AREA @@ -683,7 +683,7 @@ subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr,bc_in) endif call copy_cohort(currentCohort, copyc) - call InitPRTBoundaryConditions(copyc) + call copyc%InitPRTBoundaryConditions() newarea = currentCohort%c_area - cc_loss copyc%n = currentCohort%n*newarea/currentCohort%c_area @@ -1158,7 +1158,7 @@ subroutine PromoteIntoLayer(currentSite,currentPatch,i_lyr) ! init_value=currentPatch%tveg_lpa%GetMean()) call copy_cohort(currentCohort, copyc) !makes an identical copy... - call InitPRTBoundaryConditions(copyc) + call copyc%InitPRTBoundaryConditions() newarea = currentCohort%c_area - cc_gain !new area of existing cohort @@ -1802,7 +1802,7 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) ! to vegetation coverage to the host land model. ! ---------------------------------------------------------------------------------- - use EDTypesMod , only : ed_patch_type, fates_cohort_type, & + use EDTypesMod , only : ed_patch_type, & ed_site_type, AREA use FatesInterfaceTypesMod , only : bc_out_type diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index f5b5bbe0a1..e137441fc7 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -27,8 +27,7 @@ Module EDCohortDynamicsMod use PRTParametersMod , only : prt_params use FatesParameterDerivedMod, only : param_derived use EDTypesMod , only : ed_site_type, ed_patch_type - use EDTypesMod , only : fates_cohort_type - use EDTypesMod , only : InitPRTBoundaryConditions + use FatesCohortMod , only : fates_cohort_type use EDParamsMod , only : nclmax use PRTGenericMod , only : element_list use PRTGenericMod , only : StorageNutrientTarget @@ -41,7 +40,7 @@ Module EDCohortDynamicsMod use EDTypesMod , only : min_n_safemath use EDParamsMod , only : nlevleaf use PRTGenericMod , only : max_nleafage - use EDTypesMod , only : ican_upper + use FatesConstantsMod , only : ican_upper use EDTypesMod , only : site_fluxdiags_type use PRTGenericMod , only : num_elements use FatesConstantsMod , only : leaves_on @@ -367,7 +366,7 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & end subroutine create_cohort - ! ------------------------------------------------------------------------------------! +! ------------------------------------------------------------------------------------! subroutine InitPRTObject(prt) @@ -2095,7 +2094,7 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) ! correct boundary condition fields rcohort%prt => null() call InitPRTObject(rcohort%prt) - call InitPRTBoundaryConditions(rcohort) + call rcohort%InitPRTBoundaryConditions() call copy_cohort(ccohort, rcohort) rcohort%n = nplant_recover diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 53aa3be4dd..36882b87fb 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -15,7 +15,7 @@ module EDLoggingMortalityMod use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : rsnbl_math_prec - use EDTypesMod , only : fates_cohort_type + use FatesCohortMod , only : fates_cohort_type use EDTypesMod , only : ed_patch_type use EDTypesMod , only : site_massbal_type use EDTypesMod , only : site_fluxdiags_type @@ -717,7 +717,7 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site use EDtypesMod, only : area use EDtypesMod, only : ed_site_type use EDtypesMod, only : ed_patch_type - use EDtypesMod, only : fates_cohort_type + use FatesCohortMod, only : fates_cohort_type use FatesConstantsMod, only : rsnbl_math_prec use FatesAllometryMod, only : carea_allom diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index 669ad376a7..248064e367 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -9,7 +9,7 @@ module EDMortalityFunctionsMod use FatesGlobals , only : endrun => fates_endrun use FatesGlobals , only : fates_log use EDPftvarcon , only : EDPftvarcon_inst - use EDTypesMod , only : fates_cohort_type + use FatesCohortMod , only : fates_cohort_type use EDTypesMod , only : ed_site_type use EDTypesMod , only : ed_patch_type use EDTypesMod , only : maxpft diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index d6c9c74591..ea13822517 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -19,7 +19,8 @@ module EDPatchDynamicsMod use EDTypesMod , only : homogenize_seed_pfts use EDTypesMod , only : n_dbh_bins, area, patchfusion_dbhbin_loweredges use EDtypesMod , only : force_patchfuse_min_biomass - use EDTypesMod , only : ed_site_type, ed_patch_type, fates_cohort_type + use EDTypesMod , only : ed_site_type, ed_patch_type + use FatesCohortMod , only : fates_cohort_type use EDTypesMod , only : site_massbal_type use EDTypesMod , only : site_fluxdiags_type use EDTypesMod , only : min_patch_area @@ -29,7 +30,7 @@ module EDPatchDynamicsMod use EDTypesMod , only : dtype_ifall use EDTypesMod , only : dtype_ilog use EDTypesMod , only : dtype_ifire - use EDTypesMod , only : ican_upper + use FatesConstantsMod , only : ican_upper use PRTGenericMod , only : num_elements use PRTGenericMod , only : element_list use FatesLitterMod , only : lg_sf @@ -76,7 +77,6 @@ module EDPatchDynamicsMod use FatesConstantsMod , only : fates_unset_int use FatesConstantsMod , only : hlm_harvest_carbon use EDCohortDynamicsMod , only : InitPRTObject - use EDTypesMod , only : InitPRTBoundaryConditions use ChecksBalancesMod, only : SiteMassStock use PRTGenericMod, only : carbon12_element use PRTGenericMod, only : leaf_organ @@ -680,7 +680,7 @@ subroutine spawn_patches( currentSite, bc_in) ! correct boundary condition fields nc%prt => null() call InitPRTObject(nc%prt) - call InitPRTBoundaryConditions(nc) + call nc%InitPRTBoundaryConditions() ! (Keeping as an example) ! Allocate running mean functions diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index ecadf16c2a..cd1ba0ee3a 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -31,7 +31,6 @@ module EDPhysiologyMod use FatesInterfaceTypesMod, only : bc_out_type use EDCohortDynamicsMod , only : create_cohort, sort_cohorts use EDCohortDynamicsMod , only : InitPRTObject - use EDTypesMod, only : InitPRTBoundaryConditions use EDCohortDynamicsMod , only : copy_cohort use FatesAllometryMod , only : tree_lai use FatesAllometryMod , only : tree_sai @@ -55,7 +54,8 @@ module EDPhysiologyMod use EDParamsMod , only : nlevleaf use EDTypesMod , only : num_vegtemp_mem use EDTypesMod , only : maxpft - use EDTypesMod , only : ed_site_type, ed_patch_type, fates_cohort_type + use EDTypesMod , only : ed_site_type, ed_patch_type + use FatesCohortMod, only : fates_cohort_type use FatesConstantsMod , only : leaves_on use FatesConstantsMod , only : leaves_off use EDTypesMod , only : min_n_safemath @@ -272,7 +272,7 @@ subroutine GenerateDamageAndLitterFluxes( csite, cpatch, bc_in ) ndcohort%prt => null() call InitPRTObject(ndcohort%prt) - call InitPRTBoundaryConditions(ndcohort) + call ndcohort%InitPRTBoundaryConditions() call ndcohort%zero_values() ! nc_canopy_d is the new cohort that gets damaged diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index e29a884fd2..937fe81bb7 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -45,7 +45,7 @@ module FatesSoilBGCFluxMod use EDParamsMod , only : n_uptake_mode use EDTypesMod , only : ed_site_type use EDTypesMod , only : ed_patch_type - use EDTypesMod , only : fates_cohort_type + use FatesCohortMod , only : fates_cohort_type use EDTypesMod , only : AREA,AREA_INV use FatesInterfaceTypesMod, only : bc_in_type use FatesInterfaceTypesMod, only : bc_out_type diff --git a/biogeophys/EDAccumulateFluxesMod.F90 b/biogeophys/EDAccumulateFluxesMod.F90 index 3ef45ac742..071a1ad0a7 100644 --- a/biogeophys/EDAccumulateFluxesMod.F90 +++ b/biogeophys/EDAccumulateFluxesMod.F90 @@ -38,8 +38,9 @@ subroutine AccumulateFluxes_ED(nsites, sites, bc_in, bc_out, dt_time) ! ! !USES: - use EDTypesMod , only : ed_patch_type, fates_cohort_type, & + use EDTypesMod , only : ed_patch_type, & ed_site_type, AREA + use FatesCohortMod, only : fates_cohort_type use FatesInterfaceTypesMod , only : bc_in_type,bc_out_type ! diff --git a/biogeophys/EDBtranMod.F90 b/biogeophys/EDBtranMod.F90 index 89deb8c4d0..8063915ff3 100644 --- a/biogeophys/EDBtranMod.F90 +++ b/biogeophys/EDBtranMod.F90 @@ -11,8 +11,8 @@ module EDBtranMod use FatesConstantsMod , only : nocomp_bareground use EDTypesMod , only : ed_site_type, & ed_patch_type, & - fates_cohort_type, & maxpft + use FatesCohortMod, only : fates_cohort_type use shr_kind_mod , only : r8 => shr_kind_r8 use FatesInterfaceTypesMod , only : bc_in_type, & bc_out_type, & diff --git a/biogeophys/FatesBstressMod.F90 b/biogeophys/FatesBstressMod.F90 index f160612633..9beb3d5cd9 100644 --- a/biogeophys/FatesBstressMod.F90 +++ b/biogeophys/FatesBstressMod.F90 @@ -9,8 +9,8 @@ module FatesBstressMod use FatesConstantsMod , only : itrue,ifalse use EDTypesMod , only : ed_site_type, & ed_patch_type, & - fates_cohort_type, & maxpft + use FatesCohortMod , only : fates_cohort_type use shr_kind_mod , only : r8 => shr_kind_r8 use FatesInterfaceTypesMod , only : bc_in_type, & bc_out_type, & diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 9ed2ef630c..c008ae2f39 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -53,7 +53,7 @@ module FatesPlantHydraulicsMod use EDTypesMod , only : ed_site_type use EDTypesMod , only : ed_patch_type - use EDTypesMod , only : fates_cohort_type + use FatesCohortMod , only : fates_cohort_type use EDTypesMod , only : AREA_INV use EDTypesMod , only : AREA use FatesConstantsMod , only : leaves_on diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 44fd2abda3..22c3b0c491 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -44,6 +44,8 @@ module FATESPlantRespPhotosynthMod use PRTGenericMod, only : max_nleafage use EDTypesMod, only : do_fates_salinity use EDParamsMod, only : q10_mr + use EDTypesMod, only : ed_patch_type + use FatesCohortMod, only : fates_cohort_type use EDParamsMod, only : maintresp_leaf_model use FatesConstantsMod, only : lmrmodel_ryan_1991 use FatesConstantsMod, only : lmrmodel_atkin_etal_2017 @@ -126,8 +128,6 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! !USES: use FatesSynchronizedParamsMod , only : FatesSynchronizedParamsInst - use EDTypesMod , only : ed_patch_type - use EDTypesMod , only : fates_cohort_type use EDTypesMod , only : ed_site_type use EDTypesMod , only : maxpft use EDParamsMod , only : dinc_vai @@ -1891,10 +1891,6 @@ subroutine UpdateCanopyNCanNRadPresent(currentPatch) ! profile). ! --------------------------------------------------------------------------------- - - use EDTypesMod , only : ed_patch_type - use EDTypesMod , only : fates_cohort_type - ! Arguments type(ed_patch_type), target :: currentPatch type(fates_cohort_type), pointer :: currentCohort diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index 7090decc90..aa8716bf90 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -25,7 +25,7 @@ module SFMainMod use PRTGenericMod , only : element_pos use EDtypesMod , only : ed_site_type use EDtypesMod , only : ed_patch_type - use EDtypesMod , only : fates_cohort_type + use FatesCohortMod , only : fates_cohort_type use EDtypesMod , only : AREA use FatesLitterMod , only : DL_SF use FatesLitterMod , only : TW_SF diff --git a/main/ChecksBalancesMod.F90 b/main/ChecksBalancesMod.F90 index 8c867219b1..3d200a6f99 100644 --- a/main/ChecksBalancesMod.F90 +++ b/main/ChecksBalancesMod.F90 @@ -4,7 +4,7 @@ module ChecksBalancesMod use shr_const_mod, only : SHR_CONST_CDAY use EDtypesMod, only : ed_site_type use EDTypesMod, only : ed_patch_type - use EDTypesMod, only : fates_cohort_type + use FatesCohortMod, only : fates_cohort_type use EDTypesMod, only : AREA use EDTypesMod, only : site_massbal_type use PRTGenericMod, only : num_elements diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 39d7222543..18fa974c88 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -23,7 +23,8 @@ module EDInitMod use EDPhysiologyMod , only : assign_cohort_sp_properties use ChecksBalancesMod , only : SiteMassStock use FatesInterfaceTypesMod , only : hlm_day_of_year - use EDTypesMod , only : ed_site_type, ed_patch_type, fates_cohort_type + use EDTypesMod , only : ed_site_type, ed_patch_type + use FatesCohortMod , only : fates_cohort_type use EDTypesMod , only : numWaterMem use EDTypesMod , only : num_vegtemp_mem use EDTypesMod , only : maxpft diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 79ce7eca6a..c9cb3a8c84 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -66,7 +66,7 @@ module EDMainMod use FatesLitterMod , only : ncwd use EDtypesMod , only : ed_site_type use EDtypesMod , only : ed_patch_type - use EDtypesMod , only : fates_cohort_type + use FatesCohortMod , only : fates_cohort_type use EDTypesMod , only : AREA use EDTypesMod , only : site_massbal_type use PRTGenericMod , only : num_elements @@ -324,9 +324,6 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! ! !USES: use FatesInterfaceTypesMod, only : hlm_num_lu_harvest_cats - use FatesInterfaceTypesMod, only : nlevdamage - use FatesAllometryMod , only : bleaf - use FatesAllometryMod , only : carea_allom use PRTGenericMod , only : leaf_organ use PRTGenericMod , only : repro_organ use PRTGenericMod , only : sapw_organ @@ -335,16 +332,8 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) use PRTGenericMod , only : fnrt_organ use FatesInterfaceTypesMod, only : hlm_use_cohort_age_tracking use FatesConstantsMod, only : itrue - use EDCohortDynamicsMod , only : copy_cohort, insert_cohort - use EDCohortDynamicsMod , only : DeallocateCohort - use FatesPlantHydraulicsMod, only : InitHydrCohort - use EDCohortDynamicsMod , only : InitPRTObject - use EDTypesMod , only : InitPRTBoundaryConditions use FatesConstantsMod , only : nearzero use EDCanopyStructureMod , only : canopy_structure - use PRTLossFluxesMod , only : PRTDamageRecoveryFluxes - use PRTGenericMod , only : max_nleafage - use PRTGenericMod , only : prt_global ! !ARGUMENTS: diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index f5cf325db1..e9184cf40b 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -26,6 +26,7 @@ module EDTypesMod use FatesInterfaceTypesMod,only : bc_in_type use FatesInterfaceTypesMod,only : bc_out_type use FatesInterfaceTypesMod,only : hlm_parteh_mode + use FatesCohortMod, only : fates_cohort_type use EDParamsMod, only : maxSWb, nclmax, nlevleaf use shr_log_mod, only : errMsg => shr_log_errMsg @@ -48,13 +49,6 @@ module EDTypesMod ! this is ok for now. (RGK 04-2018) ! ------------------------------------------------------------------------------------- - - - integer, parameter, public :: ican_upper = 1 ! nominal index for the upper canopy - integer, parameter, public :: ican_ustory = 2 ! nominal index for diagnostics that refer to understory layers - ! (all layers that are not the top canopy layer) - - integer, parameter, public :: n_rad_stream_types = 2 ! The number of radiation streams used (direct/diffuse) integer, parameter, public :: idirect = 1 ! This is the array index for direct radiation @@ -140,228 +134,6 @@ module EDTypesMod logical, parameter, public :: homogenize_seed_pfts = .false. character(len=*), parameter, private :: sourcefile = __FILE__ - - type, public :: fates_cohort_type - - ! POINTERS - type (fates_cohort_type), pointer :: taller => null() ! pointer to next tallest cohort - type (fates_cohort_type), pointer :: shorter => null() ! pointer to next shorter cohort - - !:.........................................................................: - - ! Multi-species, multi-organ Plant Reactive Transport (PRT) - ! Contains carbon and nutrient state variables for various plant organs - class(prt_vartypes), pointer :: prt - real(r8) :: l2fr ! leaf to fineroot biomass ratio (this is constant - ! in carbon only simulationss, and is set by the - ! allom_l2fr_min parameter. In nutrient - ! enabled simulations, this is dynamic, will - ! vary between allom_l2fr_min and allom_l2fr_max - ! parameters, with a tendency driven by - ! nutrient storage) [kg root / kg leaf] - - !:.........................................................................: - - ! VEGETATION STRUCTURE - - integer :: pft ! pft index - real(r8) :: n ! number of individuals in cohort per 'area' (10000m2 default) [/m2] - real(r8) :: dbh ! diameter at breast height [cm] - real(r8) :: coage ! age [years] - real(r8) :: hite ! height [m] - integer :: indexnumber ! unique number for each cohort (within clump?) - integer :: canopy_layer ! canopy status of cohort [1 = canopy, 2 = understorey, etc.] - real(r8) :: canopy_layer_yesterday ! recent canopy status of cohort [1 = canopy, 2 = understorey, etc.] - ! real to be conservative during fusion - integer :: crowndamage ! crown damage class of the cohort [1 = undamaged, >1 = damaged] - real(r8) :: g_sb_laweight ! total conductance (stomata + boundary layer) of the cohort - ! weighted by its leaf area [m/s]*[m2] - real(r8) :: canopy_trim ! fraction of the maximum leaf biomass that we are targeting [0-1] - real(r8) :: leaf_cost ! how much does it cost to maintain leaves [kgC/m2/year] - real(r8) :: excl_weight ! how much of this cohort is demoted each year, as a proportion of all cohorts - real(r8) :: prom_weight ! how much of this cohort is promoted each year, as a proportion of all cohorts - integer :: nv ! number of leaf layers - integer :: status_coh ! growth status of plant [2 = leaves on , 1 = leaves off] - real(r8) :: c_area ! areal extent of canopy [m2] - real(r8) :: treelai ! lai of an individual within cohort leaf area [m2 leaf area/m2 crown area] - real(r8) :: treesai ! stem area index of an individual within cohort [m2 stem area/m2 crown area] - logical :: isnew ! flag to signify a new cohort - new cohorts have not experienced - ! npp or mortality and should therefore not be fused or averaged - integer :: size_class ! index that indicates which diameter size bin the cohort currently resides in - ! this is used for history output. We maintain this in the main cohort memory - ! because we don't want to continually re-calculate the cohort's position when - ! performing size diagnostics at high-frequency calls - integer :: coage_class ! index that indicates which age bin the cohort currently resides in - ! (used for history output) - integer :: size_by_pft_class ! index that indicates the cohorts position of the joint size-class x functional - ! type classification. We also maintain this in the main cohort memory - ! because we don't want to continually re-calculate the cohort's position when - ! performing size diagnostics at high-frequency calls - integer :: coage_by_pft_class ! index that indicates the cohorts position of the join cohort age class x PFT - integer :: size_class_lasttimestep ! size class of the cohort at the last time step - - !:.........................................................................: - - ! CARBON AND NUTRIENT FLUXES - - ! -------------------------------------------------------------------------- - ! NPP, GPP and RESP: Instantaneous, accumulated and accumulated-hold types* - ! - ! _tstep: The instantaneous estimate that is calculated at each rapid plant biophysics - ! time-step (ie photosynthesis, sub-hourly) [kgC/indiv/timestep] - ! _acc: The accumulation of the _tstep variable from the beginning to ending of - ! the dynamics time-scale. This variable is zero'd during initialization and - ! after the dynamics call-sequence is completed. [kgC/indiv/day] - ! _acc_hold: While _acc is zero'd after the dynamics call sequence and then integrated, - ! _acc_hold "holds" the integrated value until the next time dynamics is - ! called. This is necessary for restarts. This variable also has units - ! converted to a useful rate [kgC/indiv/yr] - ! -------------------------------------------------------------------------- - - real(r8) :: gpp_tstep ! Gross Primary Production (see above *) - real(r8) :: gpp_acc - real(r8) :: gpp_acc_hold - - real(r8) :: npp_tstep ! Net Primary Production (see above *) - real(r8) :: npp_acc - real(r8) :: npp_acc_hold - - real(r8) :: resp_tstep ! Autotrophic respiration (see above *) - real(r8) :: resp_acc - real(r8) :: resp_acc_hold - - real(r8) :: c13disc_clm ! carbon 13 discrimination in new synthesized carbon at each indiv/timestep [ppm] - real(r8) :: c13disc_acc ! carbon 13 discrimination in new synthesized carbon at each indiv/day - ! at the end of a day [ppm] - - ! The following four biophysical rates are assumed to be at the canopy top, at reference temp 25degC, - ! and based on the leaf age weighted average of the PFT parameterized values. - ! The last condition is why it is dynamic and tied to the cohort - - real(r8) :: vcmax25top ! maximum carboxylation at canopy top and 25degC [umol CO2/m2/s] - real(r8) :: jmax25top ! maximum electron transport rate at canopy top and 25degC [umol electrons/m2/s] - real(r8) :: tpu25top ! triose phosphate utilization rate at canopy top and 25degC [umol CO2/m2/s] - real(r8) :: kp25top ! initial slope of CO2 response curve (C4 plants) at 25C - - real(r8) :: ts_net_uptake(nlevleaf) ! net uptake of leaf layers [kgC/m2/timestep] - real(r8) :: year_net_uptake(nlevleaf) ! net uptake of leaf layers [kgC/m2/year] - - ! used for CNP - integer :: cnp_limiter ! which element is limiting growth [0 = none, 1 = C, 2 = N, 3 = P] - real(r8) :: cx_int ! time integration of the log of the relative carbon storage over relative nutrient - real(r8) :: ema_dcxdt ! derivative of the log of the relative carbon storage over relative nutrient - real(r8) :: cx0 ! value on the previous time-step of log of the relative carbon storage over - ! relative nutrient - real(r8) :: nc_repro ! N:C ratio of a new recruit, used also for defining reproductive stoich - real(r8) :: pc_repro ! P:C ratio of a new recruit - - ! Nutrient Fluxes (if N, P, etc. are turned on) - real(r8) :: daily_nh4_uptake ! integrated daily uptake of mineralized ammonium through competitive acquisition - ! in soil [kgN/plant/day] - real(r8) :: daily_no3_uptake ! integrated daily uptake of mineralized nitrate through competitive acquisition - ! in soil [kgN/plant/day] - - real(r8) :: sym_nfix_daily ! accumulated symbiotic N fixation from the roots [kgN/indiv/day] - real(r8) :: sym_nfix_tstep ! symbiotic N fixation from the roots for the time-step [kgN/indiv/timestep] - - real(r8) :: daily_n_gain ! sum of fixation and uptake of mineralized NH4/NO3 in solution as well as - ! symbiotic fixation - real(r8) :: daily_p_gain ! integrated daily uptake of mineralized P through competitive acquisition - ! in soil [kgP/plant/day] - - real(r8) :: daily_c_efflux ! daily mean efflux of excess carbon from roots into labile pool [kgC/plant/day] - real(r8) :: daily_n_efflux ! daily mean efflux of excess nitrogen from roots into labile pool [kgN/plant/day] - real(r8) :: daily_p_efflux ! daily mean efflux of excess phophorus from roots into labile pool [kgP/plant/day] - - real(r8) :: daily_n_demand ! daily amount of N demanded by the plant [kgN/plant/day] - real(r8) :: daily_p_demand ! daily amount of P demanded by the plant [kgN/plant/day] - - real(r8) :: seed_prod ! diagnostic seed production rate [kgC/plant/day] - - !:.........................................................................: - - ! RESPIRATION COMPONENTS - real(r8) :: rdark ! dark respiration [kgC/indiv/s] - real(r8) :: resp_g_tstep ! growth respiration [kgC/indiv/timestep] - real(r8) :: resp_m ! maintenance respiration [kgC/indiv/timestep] - real(r8) :: resp_m_unreduced ! diagnostic-only unreduced maintenance respiration [kgC/indiv/timestep] - real(r8) :: resp_excess ! respiration of excess carbon [kgC/indiv/day] - real(r8) :: livestem_mr ! aboveground live stem maintenance respiration [kgC/indiv/s] - real(r8) :: livecroot_mr ! belowground live stem maintenance respiration [kgC/indiv/s] - real(r8) :: froot_mr ! live fine root maintenance respiration [kgC/indiv/s] - - !:.........................................................................: - - ! DAMAGE - real(r8) :: branch_frac ! fraction of aboveground woody biomass in branches [0-1] - - !:.........................................................................: - - ! MORTALITY - real(r8) :: dmort ! proportional mortality rate [/year] - - ! Mortality Rate Partitions - real(r8) :: bmort ! background mortality rate [indiv/year] - real(r8) :: cmort ! carbon starvation mortality rate [indiv/year] - real(r8) :: hmort ! hydraulic failure mortality rate [indiv/year] - real(r8) :: frmort ! freezing mortality rate [indiv/year] - real(r8) :: smort ! senesence mortality [indiv/year] - real(r8) :: asmort ! age senescence mortality [indiv/year] - real(r8) :: dgmort ! damage mortality [indiv/year] - - ! Logging Mortality Rate - ! Yi Xu & M. Huang - real(r8) :: lmort_direct ! directly logging rate [fraction/logging activity] - real(r8) :: lmort_collateral ! collaterally damaged rate [fraction/logging activity] - real(r8) :: lmort_infra ! mechanically damaged rate [fraction/logging activity] - real(r8) :: l_degrad ! rate of trees that are not killed but suffer from forest degradation - ! (i.e. they are moved to newly-anthro-disturbed secondary - ! forest patch) [fraction/logging activity] - - !:.........................................................................: - - ! NITROGEN POOLS - ! -------------------------------------------------------------------------- - ! Nitrogen pools are not prognostic in the current implementation. - ! They are diagnosed during photosynthesis using a simple C2N parameter. - ! Local values are used in that routine. - ! -------------------------------------------------------------------------- - - !:.........................................................................: - - ! GROWTH DERIVIATIVES - real(r8) :: dndt ! time derivative of cohort size [n/year] - real(r8) :: dhdt ! time derivative of height [m/year] - real(r8) :: ddbhdt ! time derivative of dbh [cm/year] - real(r8) :: dbdeaddt ! time derivative of dead biomass [kgC/year] - - !:.........................................................................: - - ! FIRE - real(r8) :: fraction_crown_burned ! proportion of crown affected by fire [0-1] - real(r8) :: cambial_mort ! probability that trees dies due to cambial charring [0-1] - ! (conditional on the tree being subjected to the fire) - real(r8) :: crownfire_mort ! probability of tree post-fire mortality from crown scorch [0-1] - ! (conditional on the tree being subjected to the fire) - real(r8) :: fire_mort ! post-fire mortality from cambial and crown damage assuming two are independent [0-1] - - !:.........................................................................: - - ! HYDRAULICS - type(ed_cohort_hydr_type), pointer :: co_hydr ! all cohort hydraulics data, see FatesHydraulicsMemMod.F90 - - !:.........................................................................: - - contains - - procedure :: init - procedure :: dump - procedure :: nan_values - procedure :: zero_values - procedure :: CanUpperUnder - - end type fates_cohort_type - !************************************ !** Patch type structure ** !************************************ @@ -859,13 +631,7 @@ module EDTypesMod public :: val_check_ed_vars public :: dump_site public :: dump_patch - public :: dump_cohort_hydr - public :: InitPRTBoundaryConditions contains - - ! ===================================================================================== - - ! ===================================================================================== @@ -911,474 +677,9 @@ subroutine ZeroMassBalFlux(this) return end subroutine ZeroMassBalFlux - ! ===================================================================================== - - subroutine init(this, prt) - ! - ! DESCRIPTION: - ! Create new cohort and set default values for all variables - ! - - ! ARGUMENTS: - class(fates_cohort_type), intent(inout), target :: this - class(prt_vartypes), intent(inout), pointer :: prt ! allocated PARTEH object - - call this%nan_values() ! make everything in the cohort not-a-number - call this%zero_values() ! zero things that need to be zeroed - - ! point to the PARTEH object - this%prt => prt - - ! The PARTEH cohort object should be allocated and already - ! initialized in this routine. - call this%prt%CheckInitialConditions() - - call InitPRTBoundaryConditions(this) - - ! new cohorts do not have mortality rates, nor have they moved any - ! carbon when they are created. They will bias our statistics - ! until they have experienced a full day. We need a newly recruited flag. - ! This flag will be set to false after it has experienced - ! growth, disturbance and mortality. - this%isnew = .true. - - end subroutine init - - !:.........................................................................: - - subroutine InitPRTBoundaryConditions(new_cohort) - - ! Set the boundary conditions that flow in an out of the PARTEH - ! allocation hypotheses. Each of these calls to "RegsterBC" are simply - ! setting pointers. - ! For instance, if the hypothesis wants to know what - ! the DBH of the plant is, then we pass in the dbh as an argument (new_cohort%dbh), - ! and also tell it which boundary condition we are talking about (which is - ! defined by an integer index (ac_bc_inout_id_dbh) - ! - ! Again, elaborated Example: - ! "ac_bc_inout_id_dbh" is the unique integer that defines the object index - ! for the allometric carbon "ac" boundary condition "bc" for DBH "dbh" - ! that is classified as input and output "inout". - ! See PRTAllometricCarbonMod.F90 to track its usage. - ! bc_rval is used as the optional argument identifyer to specify a real - ! value boundary condition. - ! bc_ival is used as the optional argument identifyer to specify an integer - ! value boundary condition. - - use PRTAllometricCarbonMod, only : ac_bc_inout_id_dbh, ac_bc_inout_id_netdc, & - ac_bc_in_id_cdamage, ac_bc_in_id_pft, & - ac_bc_in_id_ctrim, ac_bc_in_id_lstat - use PRTAllometricCNPMod, only : acnp_bc_in_id_pft, acnp_bc_in_id_ctrim, & - acnp_bc_in_id_lstat, acnp_bc_in_id_netdc, & - acnp_bc_in_id_netdc, acnp_bc_in_id_nc_repro, & - acnp_bc_in_id_pc_repro, acnp_bc_in_id_cdamage, & - acnp_bc_inout_id_dbh, acnp_bc_inout_id_resp_excess, & - acnp_bc_inout_id_l2fr, acnp_bc_inout_id_cx_int, & - acnp_bc_inout_id_emadcxdt, acnp_bc_inout_id_cx0, & - acnp_bc_inout_id_netdn, acnp_bc_inout_id_netdp, & - acnp_bc_out_id_cefflux, acnp_bc_out_id_nefflux, & - acnp_bc_out_id_pefflux, acnp_bc_out_id_limiter - - type(fates_cohort_type), intent(inout), target :: new_cohort - - select case(hlm_parteh_mode) - case (prt_carbon_allom_hyp) - - ! Register boundary conditions for the Carbon Only Allometric Hypothesis - - call new_cohort%prt%RegisterBCInOut(ac_bc_inout_id_dbh,bc_rval = new_cohort%dbh) - call new_cohort%prt%RegisterBCInOut(ac_bc_inout_id_netdc,bc_rval = new_cohort%npp_acc) - call new_cohort%prt%RegisterBCIn(ac_bc_in_id_cdamage,bc_ival = new_cohort%crowndamage) - call new_cohort%prt%RegisterBCIn(ac_bc_in_id_pft,bc_ival = new_cohort%pft) - call new_cohort%prt%RegisterBCIn(ac_bc_in_id_ctrim,bc_rval = new_cohort%canopy_trim) - call new_cohort%prt%RegisterBCIn(ac_bc_in_id_lstat,bc_ival = new_cohort%status_coh) - - case (prt_cnp_flex_allom_hyp) - - call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_pft,bc_ival = new_cohort%pft) - call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_ctrim,bc_rval = new_cohort%canopy_trim) - call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_lstat,bc_ival = new_cohort%status_coh) - call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_netdc, bc_rval = new_cohort%npp_acc) - - call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_nc_repro,bc_rval = new_cohort%nc_repro) - call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_pc_repro,bc_rval = new_cohort%pc_repro) - call new_cohort%prt%RegisterBCIn(acnp_bc_in_id_cdamage,bc_ival = new_cohort%crowndamage) - - call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_dbh,bc_rval = new_cohort%dbh) - call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_resp_excess,bc_rval = new_cohort%resp_excess) - call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_l2fr,bc_rval = new_cohort%l2fr) - call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_cx_int,bc_rval = new_cohort%cx_int) - call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_emadcxdt,bc_rval = new_cohort%ema_dcxdt) - call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_cx0,bc_rval = new_cohort%cx0) - - call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_netdn, bc_rval = new_cohort%daily_n_gain) - call new_cohort%prt%RegisterBCInOut(acnp_bc_inout_id_netdp, bc_rval = new_cohort%daily_p_gain) - - call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_cefflux, bc_rval = new_cohort%daily_c_efflux) - call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_nefflux, bc_rval = new_cohort%daily_n_efflux) - call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_pefflux, bc_rval = new_cohort%daily_p_efflux) - call new_cohort%prt%RegisterBCOut(acnp_bc_out_id_limiter, bc_ival = new_cohort%cnp_limiter) - - case DEFAULT - - write(fates_log(),*) 'You specified an unknown PRT module' - write(fates_log(),*) 'Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) - - end select - - - end subroutine InitPRTBoundaryConditions - - - subroutine nan_values(this) - ! - ! DESCRIPTION: - ! make all the cohort variables NaN or unset so they aren't used before defined - ! - - ! USES: - use FatesConstantsMod, only : fates_unset_int - use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) - - ! ARGUMENTS: - class(fates_cohort_type), intent(inout) :: this - - ! set pointers to null - this%taller => null() - this%shorter => null() - this%prt => null() - this%co_hydr => null() - nullify(this%taller) - nullify(this%shorter) - nullify(this%prt) - nullify(this%co_hydr) - - ! VEGETATION STRUCTURE - this%l2fr = nan - this%pft = fates_unset_int - this%n = nan - this%dbh = nan - this%coage = nan - this%hite = nan - this%indexnumber = fates_unset_int - this%canopy_layer = fates_unset_int - this%canopy_layer_yesterday = nan - this%crowndamage = fates_unset_int - this%g_sb_laweight = nan - this%canopy_trim = nan - this%leaf_cost = nan - this%excl_weight = nan - this%prom_weight = nan - this%nv = fates_unset_int - this%status_coh = fates_unset_int - this%c_area = nan - this%treelai = nan - this%treesai = nan - this%isnew = .false. - this%size_class = fates_unset_int - this%coage_class = fates_unset_int - this%size_by_pft_class = fates_unset_int - this%coage_by_pft_class = fates_unset_int - this%size_class_lasttimestep = fates_unset_int - - ! CARBON AND NUTRIENT FLUXES - this%gpp_tstep = nan - this%gpp_acc = nan - this%gpp_acc_hold = nan - this%npp_tstep = nan - this%npp_acc = nan - this%npp_acc_hold = nan - this%resp_tstep = nan - this%resp_acc = nan - this%resp_acc_hold = nan - this%c13disc_clm = nan - this%c13disc_acc = nan - this%vcmax25top = nan - this%jmax25top = nan - this%tpu25top = nan - this%kp25top = nan - this%year_net_uptake(:) = nan - this%ts_net_uptake(:) = nan - this%cnp_limiter = fates_unset_int - this%cx_int = nan - this%ema_dcxdt = nan - this%cx0 = nan - this%nc_repro = nan - this%pc_repro = nan - this%daily_nh4_uptake = nan - this%daily_no3_uptake = nan - this%sym_nfix_daily = nan - this%sym_nfix_tstep = nan - this%daily_n_gain = nan - this%daily_p_gain = nan - this%daily_c_efflux = nan - this%daily_n_efflux = nan - this%daily_p_efflux = nan - this%daily_n_demand = nan - this%daily_p_demand = nan - this%seed_prod = nan - - ! RESPIRATION COMPONENTS - this%rdark = nan - this%resp_g_tstep = nan - this%resp_m = nan - this%resp_m_unreduced = nan - this%resp_excess = nan - this%livestem_mr = nan - this%livecroot_mr = nan - this%froot_mr = nan - - ! DAMAGE - this%branch_frac = nan - - ! MORTALITY - this%dmort = nan - this%bmort = nan - this%cmort = nan - this%frmort = nan - this%smort = nan - this%asmort = nan - this%dgmort = nan - this%lmort_direct = nan - this%lmort_collateral = nan - this%lmort_infra = nan - this%l_degrad = nan - - ! GROWTH DERIVATIVES - this%dndt = nan - this%dhdt = nan - this%ddbhdt = nan - this%dbdeaddt = nan - - ! FIRE - this%fraction_crown_burned = nan - this%cambial_mort = nan - this%crownfire_mort = nan - this%fire_mort = nan - - end subroutine nan_values - - !:.........................................................................: - - subroutine zero_values(this) - ! - ! DESCRIPTION: - ! Zero variables that need to be accounted for if this cohort is altered - ! before they are defined. - ! - ! ARGUMENTS - class(fates_cohort_type), intent(inout) :: this - - !this%l2fr - !this%pft - !this%n - !this%dbh - !this%coage - !this%hite - !this%indexnumber - !this%canopy_layer - !this%canopy_layer_yesterday - !this%crowndamage - this%g_sb_laweight = 0._r8 - !this%canopy_trim - this%leaf_cost = 0._r8 - this%excl_weight = 0._r8 - this%prom_weight = 0._r8 - this%nv = 0 - this%status_coh = 0 - !this%c_area - !this%treelai - this%treesai = 0._r8 - this%size_class = 1 - this%coage_class = 1 - !this%size_by_pft_class - !this%coage_by_pft_class - this%size_class_lasttimestep = 0 - this%gpp_tstep = 0._r8 - this%gpp_acc = 0._r8 - this%gpp_acc_hold = 0._r8 - this%npp_tstep = 0._r8 - this%npp_acc = 0._r8 - this%npp_acc_hold = 0._r8 - this%resp_tstep = 0._r8 - this%resp_acc = 0._r8 - this%resp_acc_hold = 0._r8 - this%c13disc_clm = 0._r8 - this%c13disc_acc = 0._r8 - !this%vcmax25top - !this%jmax25top - !this%tpu25top - !this%kp25top - this%ts_net_uptake(:) = 0._r8 - this%year_net_uptake(:) = 999._r8 ! this needs to be 999, or trimming of new cohorts will break. - !this%cnp_limiter - !this%cx_int - !this%ema_dcxdt - !this%cx0 - !this%nc_repro - !this%pc_repro - this%daily_nh4_uptake = 0._r8 - this%daily_no3_uptake = 0._r8 - - ! fixation is also integrated over the course of the day and must be - ! zeroed upon creation and after plant resource allocation - this%sym_nfix_daily = 0._r8 - this%daily_n_gain = 0._r8 - this%daily_p_gain = 0._r8 - - ! daily nutrient fluxes are INTEGRATED over the course of the day. - ! These variables MUST be zerod upon creation AND after allocation. - ! These variables exist in carbon-only mode but are not used. - this%daily_c_efflux = 0._r8 - this%daily_n_efflux = 0._r8 - this%daily_p_efflux = 0._r8 - - ! initialize these as negative - this%daily_n_demand = -9._r8 - this%daily_p_demand = -9._r8 - this%seed_prod = 0._r8 - this%rdark = 0._r8 - this%resp_g_tstep = 0._r8 - this%resp_m = 0._r8 - this%resp_m_unreduced = 0._r8 - this%resp_excess = 0._r8 - this%livestem_mr = 0._r8 - this%livecroot_mr = 0._r8 - this%froot_mr = 0._r8 - !this%branch_frac - this%dmort = 0._r8 - this%lmort_direct = 0._r8 - this%lmort_collateral = 0._r8 - this%lmort_infra = 0._r8 - this%l_degrad = 0._r8 - this%fraction_crown_burned = 0._r8 - this%cambial_mort = 0._r8 - this%crownfire_mort = 0._r8 - this%fire_mort = 0._r8 - - end subroutine zero_values - - !:.........................................................................: - - function CanUpperUnder(this) result(can_position) - ! - ! DESCRIPTION: - ! This simple function is used to determine if a cohort's crown position - ! is in the upper portion (ie the canopy) or the understory. This - ! differentiation is only used for diagnostic purposes. Functionally, - ! the model uses the canopy layer position, which may have more than - ! two layers at any given time. Utlimately, every plant that is not in - ! the top layer (canopy), is considered understory. - ! - - ! ARGUMENTS: - class(fates_cohort_type) :: this ! current cohort of interest - integer :: can_position ! canopy position - - if (this%canopy_layer == 1)then - can_position = ican_upper - else - can_position = ican_ustory - end if - - end function CanUpperUnder - - !:.........................................................................: - - subroutine dump(this) - ! - ! DESCRIPTION: - ! Print out attributes of a cohort - ! - - ! ARGUMENTS: - class(fates_cohort_type), intent(in), target :: this - - write(fates_log(),*) '----------------------------------------' - write(fates_log(),*) ' Dumping Cohort Information ' - write(fates_log(),*) '----------------------------------------' - write(fates_log(),*) 'co%pft = ', this%pft - write(fates_log(),*) 'co%n = ', this%n - write(fates_log(),*) 'co%dbh = ', this%dbh - write(fates_log(),*) 'co%hite = ', this%hite - write(fates_log(),*) 'co%crowndamage = ', this%crowndamage - write(fates_log(),*) 'co%coage = ', this%coage - write(fates_log(),*) 'co%l2fr = ', this%l2fr - write(fates_log(),*) 'leaf carbon = ', this%prt%GetState(leaf_organ,carbon12_element) - write(fates_log(),*) 'fineroot carbon = ', this%prt%GetState(fnrt_organ,carbon12_element) - write(fates_log(),*) 'sapwood carbon = ', this%prt%GetState(sapw_organ,carbon12_element) - write(fates_log(),*) 'structural (dead) carbon = ', this%prt%GetState(struct_organ,carbon12_element) - write(fates_log(),*) 'storage carbon = ', this%prt%GetState(store_organ,carbon12_element) - write(fates_log(),*) 'reproductive carbon = ', this%prt%GetState(repro_organ,carbon12_element) - write(fates_log(),*) 'co%g_sb_laweight = ', this%g_sb_laweight - write(fates_log(),*) 'co%leaf_cost = ', this%leaf_cost - write(fates_log(),*) 'co%canopy_layer = ', this%canopy_layer - write(fates_log(),*) 'co%canopy_layer_yesterday = ', this%canopy_layer_yesterday - write(fates_log(),*) 'co%nv = ', this%nv - write(fates_log(),*) 'co%status_coh = ', this%status_coh - write(fates_log(),*) 'co%canopy_trim = ', this%canopy_trim - write(fates_log(),*) 'co%excl_weight = ', this%excl_weight - write(fates_log(),*) 'co%prom_weight = ', this%prom_weight - write(fates_log(),*) 'co%size_class = ', this%size_class - write(fates_log(),*) 'co%size_by_pft_class = ', this%size_by_pft_class - write(fates_log(),*) 'co%coage_class = ', this%coage_class - write(fates_log(),*) 'co%coage_by_pft_class = ', this%coage_by_pft_class - write(fates_log(),*) 'co%gpp_acc_hold = ', this%gpp_acc_hold - write(fates_log(),*) 'co%gpp_acc = ', this%gpp_acc - write(fates_log(),*) 'co%gpp_tstep = ', this%gpp_tstep - write(fates_log(),*) 'co%npp_acc_hold = ', this%npp_acc_hold - write(fates_log(),*) 'co%npp_tstep = ', this%npp_tstep - write(fates_log(),*) 'co%npp_acc = ', this%npp_acc - write(fates_log(),*) 'co%resp_tstep = ', this%resp_tstep - write(fates_log(),*) 'co%resp_acc = ', this%resp_acc - write(fates_log(),*) 'co%resp_acc_hold = ', this%resp_acc_hold - write(fates_log(),*) 'co%rdark = ', this%rdark - write(fates_log(),*) 'co%resp_m = ', this%resp_m - write(fates_log(),*) 'co%resp_g_tstep = ', this%resp_g_tstep - write(fates_log(),*) 'co%livestem_mr = ', this%livestem_mr - write(fates_log(),*) 'co%livecroot_mr = ', this%livecroot_mr - write(fates_log(),*) 'co%froot_mr = ', this%froot_mr - write(fates_log(),*) 'co%dgmort = ', this%dgmort - write(fates_log(),*) 'co%treelai = ', this%treelai - write(fates_log(),*) 'co%treesai = ', this%treesai - write(fates_log(),*) 'co%c_area = ', this%c_area - write(fates_log(),*) 'co%cmort = ', this%cmort - write(fates_log(),*) 'co%bmort = ', this%bmort - write(fates_log(),*) 'co%smort = ', this%smort - write(fates_log(),*) 'co%asmort = ', this%asmort - write(fates_log(),*) 'co%dgmort = ', this%dgmort - write(fates_log(),*) 'co%hmort = ', this%hmort - write(fates_log(),*) 'co%frmort = ', this%frmort - write(fates_log(),*) 'co%asmort = ', this%asmort - write(fates_log(),*) 'co%lmort_direct = ', this%lmort_direct - write(fates_log(),*) 'co%lmort_collateral = ', this%lmort_collateral - write(fates_log(),*) 'co%lmort_infra = ', this%lmort_infra - write(fates_log(),*) 'co%isnew = ', this%isnew - write(fates_log(),*) 'co%dndt = ', this%dndt - write(fates_log(),*) 'co%dhdt = ', this%dhdt - write(fates_log(),*) 'co%ddbhdt = ', this%ddbhdt - write(fates_log(),*) 'co%dbdeaddt = ', this%dbdeaddt - write(fates_log(),*) 'co%fraction_crown_burned = ', this%fraction_crown_burned - write(fates_log(),*) 'co%fire_mort = ', this%fire_mort - write(fates_log(),*) 'co%crownfire_mort = ', this%crownfire_mort - write(fates_log(),*) 'co%cambial_mort = ', this%cambial_mort - write(fates_log(),*) 'co%size_class = ', this%size_class - write(fates_log(),*) 'co%size_by_pft_class = ', this%size_by_pft_class - - if (associated(this%co_hydr)) call dump_cohort_hydr(this) - - write(fates_log(),*) '----------------------------------------' - - return - -end subroutine dump - -!:...........................................................................: - + subroutine val_check_ed_vars(currentPatch,var_aliases,return_code) ! ---------------------------------------------------------------------------------- @@ -1512,24 +813,6 @@ end subroutine dump_patch ! ===================================================================================== - - - ! ===================================================================================== - subroutine dump_cohort_hydr(ccohort) - - - type(fates_cohort_type),intent(in),target :: ccohort - type(ed_cohort_hydr_type), pointer :: ccohort_hydr - ccohort_hydr => ccohort%co_hydr - - write(fates_log(),*) '--------------------------------------------' - write(fates_log(),*) ' Dumping Cohort Plant Hydraulic Information ' - write(fates_log(),*) 'ccohort_hydr%th_aroot(:) = ', ccohort_hydr%th_aroot(:) - write(fates_log(),*) 'ccohort_hydr%v_aroot_layer_init(:) = ', ccohort_hydr%v_aroot_layer_init(:) - write(fates_log(),*) 'ccohort_hydr%v_aroot_layer(:) = ', ccohort_hydr%v_aroot_layer(:) - write(fates_log(),*) '--------------------------------------------' - return - end subroutine dump_cohort_hydr end module EDTypesMod diff --git a/main/FatesCohortMod.F90 b/main/FatesCohortMod.F90 new file mode 100644 index 0000000000..9c7a1f5865 --- /dev/null +++ b/main/FatesCohortMod.F90 @@ -0,0 +1,693 @@ +module FatesCohortMod + + use FatesConstantsMod, only : r8 => fates_r8 + use FatesConstantsMod, only : fates_unset_int + use FatesConstantsMod, only : ican_upper, ican_ustory + use EDParamsMod, only : nlevleaf + use FatesGlobals, only : endrun => fates_endrun + use FatesGlobals, only : fates_log + use PRTGenericMod, only : prt_vartypes + use PRTGenericMod, only : prt_carbon_allom_hyp + use PRTGenericMod, only : prt_cnp_flex_allom_hyp + use PRTGenericMod, only : leaf_organ, fnrt_organ, sapw_organ + use PRTGenericMod, only : repro_organ, store_organ, struct_organ + use PRTGenericMod, only : carbon12_element + use FatesHydraulicsMemMod, only : ed_cohort_hydr_type + use FatesInterfaceTypesMod, only : hlm_parteh_mode + use PRTAllometricCarbonMod, only : ac_bc_inout_id_dbh, ac_bc_inout_id_netdc, & + ac_bc_in_id_cdamage, ac_bc_in_id_pft, & + ac_bc_in_id_ctrim, ac_bc_in_id_lstat + use PRTAllometricCNPMod, only : acnp_bc_in_id_pft, acnp_bc_in_id_ctrim, & + acnp_bc_in_id_lstat, acnp_bc_in_id_netdc, & + acnp_bc_in_id_netdc, acnp_bc_in_id_nc_repro, & + acnp_bc_in_id_pc_repro, acnp_bc_in_id_cdamage, & + acnp_bc_inout_id_dbh, acnp_bc_inout_id_resp_excess, & + acnp_bc_inout_id_l2fr, acnp_bc_inout_id_cx_int, & + acnp_bc_inout_id_emadcxdt, acnp_bc_inout_id_cx0, & + acnp_bc_inout_id_netdn, acnp_bc_inout_id_netdp, & + acnp_bc_out_id_cefflux, acnp_bc_out_id_nefflux, & + acnp_bc_out_id_pefflux, acnp_bc_out_id_limiter + + use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) + use shr_log_mod, only : errMsg => shr_log_errMsg + + implicit none + private + + ! PARAMETERS + character(len=*), parameter, private :: sourcefile = __FILE__ + + ! FATES COHORT TYPE + type, public :: fates_cohort_type + + ! POINTERS + type (fates_cohort_type), pointer :: taller => null() ! pointer to next tallest cohort + type (fates_cohort_type), pointer :: shorter => null() ! pointer to next shorter cohort + + !:.........................................................................: + + ! Multi-species, multi-organ Plant Reactive Transport (PRT) + ! Contains carbon and nutrient state variables for various plant organs + class(prt_vartypes), pointer :: prt + real(r8) :: l2fr ! leaf to fineroot biomass ratio (this is constant + ! in carbon only simulationss, and is set by the + ! allom_l2fr_min parameter. In nutrient + ! enabled simulations, this is dynamic, will + ! vary between allom_l2fr_min and allom_l2fr_max + ! parameters, with a tendency driven by + ! nutrient storage) [kg root / kg leaf] + + !:.........................................................................: + + ! VEGETATION STRUCTURE + + integer :: pft ! pft index + real(r8) :: n ! number of individuals in cohort per 'area' (10000m2 default) [/m2] + real(r8) :: dbh ! diameter at breast height [cm] + real(r8) :: coage ! age [years] + real(r8) :: hite ! height [m] + integer :: indexnumber ! unique number for each cohort (within clump?) + integer :: canopy_layer ! canopy status of cohort [1 = canopy, 2 = understorey, etc.] + real(r8) :: canopy_layer_yesterday ! recent canopy status of cohort [1 = canopy, 2 = understorey, etc.] + ! real to be conservative during fusion + integer :: crowndamage ! crown damage class of the cohort [1 = undamaged, >1 = damaged] + real(r8) :: g_sb_laweight ! total conductance (stomata + boundary layer) of the cohort + ! weighted by its leaf area [m/s]*[m2] + real(r8) :: canopy_trim ! fraction of the maximum leaf biomass that we are targeting [0-1] + real(r8) :: leaf_cost ! how much does it cost to maintain leaves [kgC/m2/year] + real(r8) :: excl_weight ! how much of this cohort is demoted each year, as a proportion of all cohorts + real(r8) :: prom_weight ! how much of this cohort is promoted each year, as a proportion of all cohorts + integer :: nv ! number of leaf layers + integer :: status_coh ! growth status of plant [2 = leaves on , 1 = leaves off] + real(r8) :: c_area ! areal extent of canopy [m2] + real(r8) :: treelai ! lai of an individual within cohort leaf area [m2 leaf area/m2 crown area] + real(r8) :: treesai ! stem area index of an individual within cohort [m2 stem area/m2 crown area] + logical :: isnew ! flag to signify a new cohort - new cohorts have not experienced + ! npp or mortality and should therefore not be fused or averaged + integer :: size_class ! index that indicates which diameter size bin the cohort currently resides in + ! this is used for history output. We maintain this in the main cohort memory + ! because we don't want to continually re-calculate the cohort's position when + ! performing size diagnostics at high-frequency calls + integer :: coage_class ! index that indicates which age bin the cohort currently resides in + ! (used for history output) + integer :: size_by_pft_class ! index that indicates the cohorts position of the joint size-class x functional + ! type classification. We also maintain this in the main cohort memory + ! because we don't want to continually re-calculate the cohort's position when + ! performing size diagnostics at high-frequency calls + integer :: coage_by_pft_class ! index that indicates the cohorts position of the join cohort age class x PFT + integer :: size_class_lasttimestep ! size class of the cohort at the last time step + + !:.........................................................................: + + ! CARBON AND NUTRIENT FLUXES + + ! -------------------------------------------------------------------------- + ! NPP, GPP and RESP: Instantaneous, accumulated and accumulated-hold types* + ! + ! _tstep: The instantaneous estimate that is calculated at each rapid plant biophysics + ! time-step (ie photosynthesis, sub-hourly) [kgC/indiv/timestep] + ! _acc: The accumulation of the _tstep variable from the beginning to ending of + ! the dynamics time-scale. This variable is zero'd during initialization and + ! after the dynamics call-sequence is completed. [kgC/indiv/day] + ! _acc_hold: While _acc is zero'd after the dynamics call sequence and then integrated, + ! _acc_hold "holds" the integrated value until the next time dynamics is + ! called. This is necessary for restarts. This variable also has units + ! converted to a useful rate [kgC/indiv/yr] + ! -------------------------------------------------------------------------- + + real(r8) :: gpp_tstep ! Gross Primary Production (see above *) + real(r8) :: gpp_acc + real(r8) :: gpp_acc_hold + + real(r8) :: npp_tstep ! Net Primary Production (see above *) + real(r8) :: npp_acc + real(r8) :: npp_acc_hold + + real(r8) :: resp_tstep ! Autotrophic respiration (see above *) + real(r8) :: resp_acc + real(r8) :: resp_acc_hold + + real(r8) :: c13disc_clm ! carbon 13 discrimination in new synthesized carbon at each indiv/timestep [ppm] + real(r8) :: c13disc_acc ! carbon 13 discrimination in new synthesized carbon at each indiv/day + ! at the end of a day [ppm] + + ! The following four biophysical rates are assumed to be at the canopy top, at reference temp 25degC, + ! and based on the leaf age weighted average of the PFT parameterized values. + ! The last condition is why it is dynamic and tied to the cohort + + real(r8) :: vcmax25top ! maximum carboxylation at canopy top and 25degC [umol CO2/m2/s] + real(r8) :: jmax25top ! maximum electron transport rate at canopy top and 25degC [umol electrons/m2/s] + real(r8) :: tpu25top ! triose phosphate utilization rate at canopy top and 25degC [umol CO2/m2/s] + real(r8) :: kp25top ! initial slope of CO2 response curve (C4 plants) at 25C + + real(r8) :: ts_net_uptake(nlevleaf) ! net uptake of leaf layers [kgC/m2/timestep] + real(r8) :: year_net_uptake(nlevleaf) ! net uptake of leaf layers [kgC/m2/year] + + ! used for CNP + integer :: cnp_limiter ! which element is limiting growth [0 = none, 1 = C, 2 = N, 3 = P] + real(r8) :: cx_int ! time integration of the log of the relative carbon storage over relative nutrient + real(r8) :: ema_dcxdt ! derivative of the log of the relative carbon storage over relative nutrient + real(r8) :: cx0 ! value on the previous time-step of log of the relative carbon storage over + ! relative nutrient + real(r8) :: nc_repro ! N:C ratio of a new recruit, used also for defining reproductive stoich + real(r8) :: pc_repro ! P:C ratio of a new recruit + + ! Nutrient Fluxes (if N, P, etc. are turned on) + real(r8) :: daily_nh4_uptake ! integrated daily uptake of mineralized ammonium through competitive acquisition + ! in soil [kgN/plant/day] + real(r8) :: daily_no3_uptake ! integrated daily uptake of mineralized nitrate through competitive acquisition + ! in soil [kgN/plant/day] + + real(r8) :: sym_nfix_daily ! accumulated symbiotic N fixation from the roots [kgN/indiv/day] + real(r8) :: sym_nfix_tstep ! symbiotic N fixation from the roots for the time-step [kgN/indiv/timestep] + + real(r8) :: daily_n_gain ! sum of fixation and uptake of mineralized NH4/NO3 in solution as well as + ! symbiotic fixation + real(r8) :: daily_p_gain ! integrated daily uptake of mineralized P through competitive acquisition + ! in soil [kgP/plant/day] + + real(r8) :: daily_c_efflux ! daily mean efflux of excess carbon from roots into labile pool [kgC/plant/day] + real(r8) :: daily_n_efflux ! daily mean efflux of excess nitrogen from roots into labile pool [kgN/plant/day] + real(r8) :: daily_p_efflux ! daily mean efflux of excess phophorus from roots into labile pool [kgP/plant/day] + + real(r8) :: daily_n_demand ! daily amount of N demanded by the plant [kgN/plant/day] + real(r8) :: daily_p_demand ! daily amount of P demanded by the plant [kgN/plant/day] + + real(r8) :: seed_prod ! diagnostic seed production rate [kgC/plant/day] + + !:.........................................................................: + + ! RESPIRATION COMPONENTS + real(r8) :: rdark ! dark respiration [kgC/indiv/s] + real(r8) :: resp_g_tstep ! growth respiration [kgC/indiv/timestep] + real(r8) :: resp_m ! maintenance respiration [kgC/indiv/timestep] + real(r8) :: resp_m_unreduced ! diagnostic-only unreduced maintenance respiration [kgC/indiv/timestep] + real(r8) :: resp_excess ! respiration of excess carbon [kgC/indiv/day] + real(r8) :: livestem_mr ! aboveground live stem maintenance respiration [kgC/indiv/s] + real(r8) :: livecroot_mr ! belowground live stem maintenance respiration [kgC/indiv/s] + real(r8) :: froot_mr ! live fine root maintenance respiration [kgC/indiv/s] + + !:.........................................................................: + + ! DAMAGE + real(r8) :: branch_frac ! fraction of aboveground woody biomass in branches [0-1] + + !:.........................................................................: + + ! MORTALITY + real(r8) :: dmort ! proportional mortality rate [/year] + + ! Mortality Rate Partitions + real(r8) :: bmort ! background mortality rate [indiv/year] + real(r8) :: cmort ! carbon starvation mortality rate [indiv/year] + real(r8) :: hmort ! hydraulic failure mortality rate [indiv/year] + real(r8) :: frmort ! freezing mortality rate [indiv/year] + real(r8) :: smort ! senesence mortality [indiv/year] + real(r8) :: asmort ! age senescence mortality [indiv/year] + real(r8) :: dgmort ! damage mortality [indiv/year] + + ! Logging Mortality Rate + ! Yi Xu & M. Huang + real(r8) :: lmort_direct ! directly logging rate [fraction/logging activity] + real(r8) :: lmort_collateral ! collaterally damaged rate [fraction/logging activity] + real(r8) :: lmort_infra ! mechanically damaged rate [fraction/logging activity] + real(r8) :: l_degrad ! rate of trees that are not killed but suffer from forest degradation + ! (i.e. they are moved to newly-anthro-disturbed secondary + ! forest patch) [fraction/logging activity] + + !:.........................................................................: + + ! NITROGEN POOLS + ! -------------------------------------------------------------------------- + ! Nitrogen pools are not prognostic in the current implementation. + ! They are diagnosed during photosynthesis using a simple C2N parameter. + ! Local values are used in that routine. + ! -------------------------------------------------------------------------- + + !:.........................................................................: + + ! GROWTH DERIVIATIVES + real(r8) :: dndt ! time derivative of cohort size [n/year] + real(r8) :: dhdt ! time derivative of height [m/year] + real(r8) :: ddbhdt ! time derivative of dbh [cm/year] + real(r8) :: dbdeaddt ! time derivative of dead biomass [kgC/year] + + !:.........................................................................: + + ! FIRE + real(r8) :: fraction_crown_burned ! proportion of crown affected by fire [0-1] + real(r8) :: cambial_mort ! probability that trees dies due to cambial charring [0-1] + ! (conditional on the tree being subjected to the fire) + real(r8) :: crownfire_mort ! probability of tree post-fire mortality from crown scorch [0-1] + ! (conditional on the tree being subjected to the fire) + real(r8) :: fire_mort ! post-fire mortality from cambial and crown damage assuming two are independent [0-1] + + !:.........................................................................: + + ! HYDRAULICS + type(ed_cohort_hydr_type), pointer :: co_hydr ! all cohort hydraulics data, see FatesHydraulicsMemMod.F90 + + !:.........................................................................: + + contains + + procedure :: init + procedure :: dump + procedure :: nan_values + procedure :: zero_values + procedure :: CanUpperUnder + procedure :: InitPRTBoundaryConditions + + end type fates_cohort_type + + contains + + subroutine init(this, prt) + ! + ! DESCRIPTION: + ! Create new cohort and set default values for all variables + ! + + ! ARGUMENTS: + class(fates_cohort_type), intent(inout), target :: this + class(prt_vartypes), intent(inout), pointer :: prt ! allocated PARTEH object + + call this%nan_values() ! make everything in the cohort not-a-number + call this%zero_values() ! zero things that need to be zeroed + + ! point to the PARTEH object + this%prt => prt + + ! The PARTEH cohort object should be allocated and already + ! initialized in this routine. + call this%prt%CheckInitialConditions() + + call this%InitPRTBoundaryConditions() + + ! new cohorts do not have mortality rates, nor have they moved any + ! carbon when they are created. They will bias our statistics + ! until they have experienced a full day. We need a newly recruited flag. + ! This flag will be set to false after it has experienced + ! growth, disturbance and mortality. + this%isnew = .true. + + end subroutine init + + !:.........................................................................: + + subroutine nan_values(this) + ! + ! DESCRIPTION: + ! make all the cohort variables NaN or unset so they aren't used before defined + ! + + ! ARGUMENTS: + class(fates_cohort_type), intent(inout) :: this + + ! set pointers to null + this%taller => null() + this%shorter => null() + this%prt => null() + this%co_hydr => null() + nullify(this%taller) + nullify(this%shorter) + nullify(this%prt) + nullify(this%co_hydr) + + ! VEGETATION STRUCTURE + this%l2fr = nan + this%pft = fates_unset_int + this%n = nan + this%dbh = nan + this%coage = nan + this%hite = nan + this%indexnumber = fates_unset_int + this%canopy_layer = fates_unset_int + this%canopy_layer_yesterday = nan + this%crowndamage = fates_unset_int + this%g_sb_laweight = nan + this%canopy_trim = nan + this%leaf_cost = nan + this%excl_weight = nan + this%prom_weight = nan + this%nv = fates_unset_int + this%status_coh = fates_unset_int + this%c_area = nan + this%treelai = nan + this%treesai = nan + this%isnew = .false. + this%size_class = fates_unset_int + this%coage_class = fates_unset_int + this%size_by_pft_class = fates_unset_int + this%coage_by_pft_class = fates_unset_int + this%size_class_lasttimestep = fates_unset_int + + ! CARBON AND NUTRIENT FLUXES + this%gpp_tstep = nan + this%gpp_acc = nan + this%gpp_acc_hold = nan + this%npp_tstep = nan + this%npp_acc = nan + this%npp_acc_hold = nan + this%resp_tstep = nan + this%resp_acc = nan + this%resp_acc_hold = nan + this%c13disc_clm = nan + this%c13disc_acc = nan + this%vcmax25top = nan + this%jmax25top = nan + this%tpu25top = nan + this%kp25top = nan + this%year_net_uptake(:) = nan + this%ts_net_uptake(:) = nan + this%cnp_limiter = fates_unset_int + this%cx_int = nan + this%ema_dcxdt = nan + this%cx0 = nan + this%nc_repro = nan + this%pc_repro = nan + this%daily_nh4_uptake = nan + this%daily_no3_uptake = nan + this%sym_nfix_daily = nan + this%sym_nfix_tstep = nan + this%daily_n_gain = nan + this%daily_p_gain = nan + this%daily_c_efflux = nan + this%daily_n_efflux = nan + this%daily_p_efflux = nan + this%daily_n_demand = nan + this%daily_p_demand = nan + this%seed_prod = nan + + ! RESPIRATION COMPONENTS + this%rdark = nan + this%resp_g_tstep = nan + this%resp_m = nan + this%resp_m_unreduced = nan + this%resp_excess = nan + this%livestem_mr = nan + this%livecroot_mr = nan + this%froot_mr = nan + + ! DAMAGE + this%branch_frac = nan + + ! MORTALITY + this%dmort = nan + this%bmort = nan + this%cmort = nan + this%frmort = nan + this%smort = nan + this%asmort = nan + this%dgmort = nan + this%lmort_direct = nan + this%lmort_collateral = nan + this%lmort_infra = nan + this%l_degrad = nan + + ! GROWTH DERIVATIVES + this%dndt = nan + this%dhdt = nan + this%ddbhdt = nan + this%dbdeaddt = nan + + ! FIRE + this%fraction_crown_burned = nan + this%cambial_mort = nan + this%crownfire_mort = nan + this%fire_mort = nan + + end subroutine nan_values + + !:.........................................................................: + + subroutine zero_values(this) + ! + ! DESCRIPTION: + ! Zero variables that need to be accounted for if this cohort is altered + ! before they are defined. + ! + ! ARGUMENTS + class(fates_cohort_type), intent(inout) :: this + + this%g_sb_laweight = 0._r8 + + this%leaf_cost = 0._r8 + this%excl_weight = 0._r8 + this%prom_weight = 0._r8 + this%nv = 0 + this%status_coh = 0 + + this%treesai = 0._r8 + this%size_class = 1 + this%coage_class = 1 + + this%size_class_lasttimestep = 0 + this%gpp_tstep = 0._r8 + this%gpp_acc = 0._r8 + this%gpp_acc_hold = 0._r8 + this%npp_tstep = 0._r8 + this%npp_acc = 0._r8 + this%npp_acc_hold = 0._r8 + this%resp_tstep = 0._r8 + this%resp_acc = 0._r8 + this%resp_acc_hold = 0._r8 + this%c13disc_clm = 0._r8 + this%c13disc_acc = 0._r8 + + this%ts_net_uptake(:) = 0._r8 + this%year_net_uptake(:) = 999._r8 ! this needs to be 999, or trimming of new cohorts will break. + + this%daily_nh4_uptake = 0._r8 + this%daily_no3_uptake = 0._r8 + + ! fixation is also integrated over the course of the day and must be + ! zeroed upon creation and after plant resource allocation + this%sym_nfix_daily = 0._r8 + this%daily_n_gain = 0._r8 + this%daily_p_gain = 0._r8 + + ! daily nutrient fluxes are INTEGRATED over the course of the day. + ! These variables MUST be zerod upon creation AND after allocation. + ! These variables exist in carbon-only mode but are not used. + this%daily_c_efflux = 0._r8 + this%daily_n_efflux = 0._r8 + this%daily_p_efflux = 0._r8 + + ! initialize these as negative + this%daily_n_demand = -9._r8 + this%daily_p_demand = -9._r8 + this%seed_prod = 0._r8 + this%rdark = 0._r8 + this%resp_g_tstep = 0._r8 + this%resp_m = 0._r8 + this%resp_m_unreduced = 0._r8 + this%resp_excess = 0._r8 + this%livestem_mr = 0._r8 + this%livecroot_mr = 0._r8 + this%froot_mr = 0._r8 + + this%dmort = 0._r8 + this%lmort_direct = 0._r8 + this%lmort_collateral = 0._r8 + this%lmort_infra = 0._r8 + this%l_degrad = 0._r8 + this%fraction_crown_burned = 0._r8 + this%cambial_mort = 0._r8 + this%crownfire_mort = 0._r8 + this%fire_mort = 0._r8 + + end subroutine zero_values + + !:.........................................................................: + + subroutine InitPRTBoundaryConditions(this) + + ! Set the boundary conditions that flow in an out of the PARTEH + ! allocation hypotheses. Each of these calls to "RegsterBC" are simply + ! setting pointers. + ! For instance, if the hypothesis wants to know what + ! the DBH of the plant is, then we pass in the dbh as an argument (new_cohort%dbh), + ! and also tell it which boundary condition we are talking about (which is + ! defined by an integer index (ac_bc_inout_id_dbh) + ! + ! Again, elaborated Example: + ! "ac_bc_inout_id_dbh" is the unique integer that defines the object index + ! for the allometric carbon "ac" boundary condition "bc" for DBH "dbh" + ! that is classified as input and output "inout". + ! See PRTAllometricCarbonMod.F90 to track its usage. + ! bc_rval is used as the optional argument identifyer to specify a real + ! value boundary condition. + ! bc_ival is used as the optional argument identifyer to specify an integer + ! value boundary condition. + + class(fates_cohort_type), intent(inout) :: this + + select case(hlm_parteh_mode) + case (prt_carbon_allom_hyp) + + ! Register boundary conditions for the Carbon Only Allometric Hypothesis + + call this%prt%RegisterBCInOut(ac_bc_inout_id_dbh, bc_rval=this%dbh) + call this%prt%RegisterBCInOut(ac_bc_inout_id_netdc, bc_rval=this%npp_acc) + call this%prt%RegisterBCIn(ac_bc_in_id_cdamage, bc_ival=this%crowndamage) + call this%prt%RegisterBCIn(ac_bc_in_id_pft, bc_ival=this%pft) + call this%prt%RegisterBCIn(ac_bc_in_id_ctrim, bc_rval=this%canopy_trim) + call this%prt%RegisterBCIn(ac_bc_in_id_lstat, bc_ival=this%status_coh) + + case (prt_cnp_flex_allom_hyp) + + ! Register boundary conditions for the CNP Allometric Hypothesis + + call this%prt%RegisterBCIn(acnp_bc_in_id_pft, bc_ival=this%pft) + call this%prt%RegisterBCIn(acnp_bc_in_id_ctrim, bc_rval=this%canopy_trim) + call this%prt%RegisterBCIn(acnp_bc_in_id_lstat, bc_ival=this%status_coh) + call this%prt%RegisterBCIn(acnp_bc_in_id_netdc, bc_rval=this%npp_acc) + + call this%prt%RegisterBCIn(acnp_bc_in_id_nc_repro, bc_rval=this%nc_repro) + call this%prt%RegisterBCIn(acnp_bc_in_id_pc_repro, bc_rval=this%pc_repro) + call this%prt%RegisterBCIn(acnp_bc_in_id_cdamage, bc_ival=this%crowndamage) + + call this%prt%RegisterBCInOut(acnp_bc_inout_id_dbh, bc_rval=this%dbh) + call this%prt%RegisterBCInOut(acnp_bc_inout_id_resp_excess, bc_rval=this%resp_excess) + call this%prt%RegisterBCInOut(acnp_bc_inout_id_l2fr, bc_rval=this%l2fr) + call this%prt%RegisterBCInOut(acnp_bc_inout_id_cx_int, bc_rval=this%cx_int) + call this%prt%RegisterBCInOut(acnp_bc_inout_id_emadcxdt, bc_rval=this%ema_dcxdt) + call this%prt%RegisterBCInOut(acnp_bc_inout_id_cx0, bc_rval=this%cx0) + + call this%prt%RegisterBCInOut(acnp_bc_inout_id_netdn, bc_rval=this%daily_n_gain) + call this%prt%RegisterBCInOut(acnp_bc_inout_id_netdp, bc_rval=this%daily_p_gain) + + call this%prt%RegisterBCOut(acnp_bc_out_id_cefflux, bc_rval=this%daily_c_efflux) + call this%prt%RegisterBCOut(acnp_bc_out_id_nefflux, bc_rval=this%daily_n_efflux) + call this%prt%RegisterBCOut(acnp_bc_out_id_pefflux, bc_rval=this%daily_p_efflux) + call this%prt%RegisterBCOut(acnp_bc_out_id_limiter, bc_ival=this%cnp_limiter) + + case DEFAULT + + write(fates_log(),*) 'You specified an unknown PRT module' + write(fates_log(),*) 'Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + + end select + + end subroutine InitPRTBoundaryConditions + + !:.........................................................................: + + function CanUpperUnder(this) result(can_position) + ! + ! DESCRIPTION: + ! This simple function is used to determine if a cohort's crown position + ! is in the upper portion (ie the canopy) or the understory. This + ! differentiation is only used for diagnostic purposes. Functionally, + ! the model uses the canopy layer position, which may have more than + ! two layers at any given time. Utlimately, every plant that is not in + ! the top layer (canopy), is considered understory. + ! + + ! ARGUMENTS: + class(fates_cohort_type) :: this ! current cohort of interest + integer :: can_position ! canopy position + + if (this%canopy_layer == 1)then + can_position = ican_upper + else + can_position = ican_ustory + end if + + end function CanUpperUnder + + !:.........................................................................: + + subroutine dump(this) + ! + ! DESCRIPTION: + ! Print out attributes of a cohort + ! + + ! ARGUMENTS: + class(fates_cohort_type), intent(in), target :: this + + write(fates_log(),*) '----------------------------------------' + write(fates_log(),*) ' Dumping Cohort Information ' + write(fates_log(),*) '----------------------------------------' + write(fates_log(),*) 'co%pft = ', this%pft + write(fates_log(),*) 'co%n = ', this%n + write(fates_log(),*) 'co%dbh = ', this%dbh + write(fates_log(),*) 'co%hite = ', this%hite + write(fates_log(),*) 'co%crowndamage = ', this%crowndamage + write(fates_log(),*) 'co%coage = ', this%coage + write(fates_log(),*) 'co%l2fr = ', this%l2fr + write(fates_log(),*) 'leaf carbon = ', this%prt%GetState(leaf_organ,carbon12_element) + write(fates_log(),*) 'fineroot carbon = ', this%prt%GetState(fnrt_organ,carbon12_element) + write(fates_log(),*) 'sapwood carbon = ', this%prt%GetState(sapw_organ,carbon12_element) + write(fates_log(),*) 'structural (dead) carbon = ', this%prt%GetState(struct_organ,carbon12_element) + write(fates_log(),*) 'storage carbon = ', this%prt%GetState(store_organ,carbon12_element) + write(fates_log(),*) 'reproductive carbon = ', this%prt%GetState(repro_organ,carbon12_element) + write(fates_log(),*) 'co%g_sb_laweight = ', this%g_sb_laweight + write(fates_log(),*) 'co%leaf_cost = ', this%leaf_cost + write(fates_log(),*) 'co%canopy_layer = ', this%canopy_layer + write(fates_log(),*) 'co%canopy_layer_yesterday = ', this%canopy_layer_yesterday + write(fates_log(),*) 'co%nv = ', this%nv + write(fates_log(),*) 'co%status_coh = ', this%status_coh + write(fates_log(),*) 'co%canopy_trim = ', this%canopy_trim + write(fates_log(),*) 'co%excl_weight = ', this%excl_weight + write(fates_log(),*) 'co%prom_weight = ', this%prom_weight + write(fates_log(),*) 'co%size_class = ', this%size_class + write(fates_log(),*) 'co%size_by_pft_class = ', this%size_by_pft_class + write(fates_log(),*) 'co%coage_class = ', this%coage_class + write(fates_log(),*) 'co%coage_by_pft_class = ', this%coage_by_pft_class + write(fates_log(),*) 'co%gpp_acc_hold = ', this%gpp_acc_hold + write(fates_log(),*) 'co%gpp_acc = ', this%gpp_acc + write(fates_log(),*) 'co%gpp_tstep = ', this%gpp_tstep + write(fates_log(),*) 'co%npp_acc_hold = ', this%npp_acc_hold + write(fates_log(),*) 'co%npp_tstep = ', this%npp_tstep + write(fates_log(),*) 'co%npp_acc = ', this%npp_acc + write(fates_log(),*) 'co%resp_tstep = ', this%resp_tstep + write(fates_log(),*) 'co%resp_acc = ', this%resp_acc + write(fates_log(),*) 'co%resp_acc_hold = ', this%resp_acc_hold + write(fates_log(),*) 'co%rdark = ', this%rdark + write(fates_log(),*) 'co%resp_m = ', this%resp_m + write(fates_log(),*) 'co%resp_g_tstep = ', this%resp_g_tstep + write(fates_log(),*) 'co%livestem_mr = ', this%livestem_mr + write(fates_log(),*) 'co%livecroot_mr = ', this%livecroot_mr + write(fates_log(),*) 'co%froot_mr = ', this%froot_mr + write(fates_log(),*) 'co%dgmort = ', this%dgmort + write(fates_log(),*) 'co%treelai = ', this%treelai + write(fates_log(),*) 'co%treesai = ', this%treesai + write(fates_log(),*) 'co%c_area = ', this%c_area + write(fates_log(),*) 'co%cmort = ', this%cmort + write(fates_log(),*) 'co%bmort = ', this%bmort + write(fates_log(),*) 'co%smort = ', this%smort + write(fates_log(),*) 'co%asmort = ', this%asmort + write(fates_log(),*) 'co%dgmort = ', this%dgmort + write(fates_log(),*) 'co%hmort = ', this%hmort + write(fates_log(),*) 'co%frmort = ', this%frmort + write(fates_log(),*) 'co%asmort = ', this%asmort + write(fates_log(),*) 'co%lmort_direct = ', this%lmort_direct + write(fates_log(),*) 'co%lmort_collateral = ', this%lmort_collateral + write(fates_log(),*) 'co%lmort_infra = ', this%lmort_infra + write(fates_log(),*) 'co%isnew = ', this%isnew + write(fates_log(),*) 'co%dndt = ', this%dndt + write(fates_log(),*) 'co%dhdt = ', this%dhdt + write(fates_log(),*) 'co%ddbhdt = ', this%ddbhdt + write(fates_log(),*) 'co%dbdeaddt = ', this%dbdeaddt + write(fates_log(),*) 'co%fraction_crown_burned = ', this%fraction_crown_burned + write(fates_log(),*) 'co%fire_mort = ', this%fire_mort + write(fates_log(),*) 'co%crownfire_mort = ', this%crownfire_mort + write(fates_log(),*) 'co%cambial_mort = ', this%cambial_mort + write(fates_log(),*) 'co%size_class = ', this%size_class + write(fates_log(),*) 'co%size_by_pft_class = ', this%size_by_pft_class + + if (associated(this%co_hydr)) call this%co_hydr%dump() + + write(fates_log(),*) '----------------------------------------' + + return + + end subroutine dump + + !:.........................................................................: + +end module FatesCohortMod \ No newline at end of file diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index d865187294..a6bc033027 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -42,6 +42,10 @@ module FatesConstantsMod ! its leaves and should not be trying to allocate ! towards any growth. + integer, parameter, public :: ican_upper = 1 ! nominal index for the upper canopy + integer, parameter, public :: ican_ustory = 2 ! nominal index for diagnostics that refer to understory layers + ! (all layers that are not the top canopy layer) + ! Bareground label for no competition mode integer, parameter, public :: nocomp_bareground = 0 diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 79026ec3af..77af891d91 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -13,13 +13,13 @@ module FatesHistoryInterfaceMod use FatesGlobals , only : fates_log use FatesGlobals , only : endrun => fates_endrun use EDParamsMod , only : nclmax - use EDTypesMod , only : ican_upper + use FatesConstantsMod , only : ican_upper use PRTGenericMod , only : element_pos use PRTGenericMod , only : num_elements use PRTGenericMod , only : prt_cnp_flex_allom_hyp use EDTypesMod , only : site_fluxdiags_type use EDtypesMod , only : ed_site_type - use EDtypesMod , only : fates_cohort_type + use FatesCohortMod , only : fates_cohort_type use EDtypesMod , only : ed_patch_type use EDtypesMod , only : AREA use EDtypesMod , only : AREA_INV @@ -2105,8 +2105,8 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) use FatesLitterMod , only : nfsc use FatesLitterMod , only : ncwd - use EDtypesMod , only : ican_upper - use EDtypesMod , only : ican_ustory + use FatesConstantsMod , only : ican_upper + use FatesConstantsMod , only : ican_ustory use FatesSizeAgeTypeIndicesMod, only : get_sizeage_class_index use FatesSizeAgeTypeIndicesMod, only : get_sizeagepft_class_index use FatesSizeAgeTypeIndicesMod, only : get_agepft_class_index diff --git a/main/FatesHydraulicsMemMod.F90 b/main/FatesHydraulicsMemMod.F90 index 23f3f75482..22ade5f9b6 100644 --- a/main/FatesHydraulicsMemMod.F90 +++ b/main/FatesHydraulicsMemMod.F90 @@ -2,6 +2,7 @@ module FatesHydraulicsMemMod use FatesConstantsMod, only : r8 => fates_r8 use FatesConstantsMod, only : fates_unset_r8 + use FatesGlobals, only : fates_log use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) use FatesConstantsMod, only : itrue,ifalse use FatesHydroWTFMod, only : wrf_arr_type @@ -314,6 +315,7 @@ module FatesHydraulicsMemMod procedure :: AllocateHydrCohortArrays procedure :: DeallocateHydrCohortArrays + procedure :: dump end type ed_cohort_hydr_type @@ -363,6 +365,23 @@ end subroutine DeallocateHydrCohortArrays ! =================================================================================== + subroutine dump(this) + + class(ed_cohort_hydr_type), intent(in) :: this + + write(fates_log(),*) '--------------------------------------------' + write(fates_log(),*) ' Dumping Cohort Plant Hydraulic Information ' + write(fates_log(),*) 'ccohort_hydr%th_aroot(:) = ', this%th_aroot(:) + write(fates_log(),*) 'ccohort_hydr%v_aroot_layer_init(:) = ', this%v_aroot_layer_init(:) + write(fates_log(),*) 'ccohort_hydr%v_aroot_layer(:) = ', this%v_aroot_layer(:) + write(fates_log(),*) '--------------------------------------------' + + return + + end subroutine dump + + !:..........................................................................: + subroutine InitHydrSite(this,numpft,numlevsclass,hydr_solver_type,nlevsoil) ! Arguments diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index a51ea560c0..00d46563ab 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -30,7 +30,7 @@ module FatesInterfaceMod use EDTypesMod , only : numlevsoil_max use EDTypesMod , only : ed_site_type use EDTypesMod , only : ed_patch_type - use EDTypesMod , only : fates_cohort_type + use FatesCohortMod , only : fates_cohort_type use EDTypesMod , only : area_inv use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : itrue,ifalse diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index aba46250d6..a703958734 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -34,7 +34,7 @@ module FatesInventoryInitMod use FatesLitterMod , only : litter_type use EDTypesMod , only : ed_site_type use EDTypesMod , only : ed_patch_type - use EDTypesMod , only : fates_cohort_type + use FatesCohortMod , only : fates_cohort_type use EDTypesMod , only : area use FatesConstantsMod, only : leaves_on, leaves_off use PRTGenericMod , only : num_elements diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 246f988409..345bfde3f2 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -33,7 +33,6 @@ module FatesRestartInterfaceMod use PRTGenericMod, only : prt_global use PRTGenericMod, only : prt_cnp_flex_allom_hyp use EDCohortDynamicsMod, only : InitPRTObject - use EDTypesMod, only : InitPRTBoundaryConditions use FatesPlantHydraulicsMod, only : InitHydrCohort use FatesInterfaceTypesMod, only : nlevsclass use FatesInterfaceTypesMod, only : nlevdamage @@ -1811,7 +1810,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) use FatesInterfaceTypesMod, only : fates_maxElementsPerPatch use FatesInterfaceTypesMod, only : numpft use EDTypesMod, only : ed_site_type - use EDTypesMod, only : fates_cohort_type + use FatesCohortMod, only : fates_cohort_type use EDTypesMod, only : ed_patch_type use EDParamsMod, only : maxSWb use EDParamsMod, only : nclmax @@ -2507,7 +2506,7 @@ subroutine create_patchcohort_structure(this, nc, nsites, sites, bc_in, bc_out) ! --------------------------------------------------------------------------------- use EDTypesMod, only : ed_site_type - use EDTypesMod, only : fates_cohort_type + use FatesCohortMod, only : fates_cohort_type use EDTypesMod, only : ed_patch_type use EDParamsMod, only : maxSWb use FatesInterfaceTypesMod, only : fates_maxElementsPerPatch @@ -2706,7 +2705,7 @@ end subroutine create_patchcohort_structure subroutine get_restart_vectors(this, nc, nsites, sites) use EDTypesMod, only : ed_site_type - use EDTypesMod, only : fates_cohort_type + use FatesCohortMod, only : fates_cohort_type use EDTypesMod, only : ed_patch_type use EDParamsMod, only : maxSWb use EDParamsMod, only : nclmax @@ -3064,7 +3063,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ccohort%status_coh = rio_status_co(io_idx_co) ccohort%isnew = ( rio_isnew_co(io_idx_co) .eq. new_cohort ) - call InitPRTBoundaryConditions(ccohort) + call ccohort%InitPRTBoundaryConditions() call UpdateCohortBioPhysRates(ccohort) ! Initialize Plant Hydraulics From a186683b3442d7fbe57e2f80ebdc7124fa949a50 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Fri, 7 Apr 2023 14:07:45 -0600 Subject: [PATCH 610/852] remove unused dependencies --- biogeochem/EDCanopyStructureMod.F90 | 4 ---- biogeochem/EDMortalityFunctionsMod.F90 | 3 +-- biogeochem/EDPatchDynamicsMod.F90 | 2 +- biogeochem/EDPhysiologyMod.F90 | 2 -- biogeochem/FatesSoilBGCFluxMod.F90 | 1 - biogeophys/EDSurfaceAlbedoMod.F90 | 1 - biogeophys/FatesPlantRespPhotosynthMod.F90 | 2 -- main/EDPftvarcon.F90 | 4 ++-- main/FatesInventoryInitMod.F90 | 1 - main/FatesRestartInterfaceMod.F90 | 1 - parteh/PRTAllometricCNPMod.F90 | 3 --- 11 files changed, 4 insertions(+), 20 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 09e53623a9..39c4c1c1d4 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -337,7 +337,6 @@ end subroutine canopy_structure subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr,bc_in) use EDParamsMod, only : ED_val_comp_excln - use SFParamsMod, only : SF_val_CWD_frac ! !ARGUMENTS type(ed_site_type), intent(inout) :: currentSite @@ -2126,9 +2125,6 @@ subroutine UpdatePatchLAI(currentPatch) ! and related variables ! --------------------------------------------------------------------------------------------- - ! Uses - use EDParamsMod, only : dlower_vai - ! Arguments type(ed_patch_type),intent(inout), target :: currentPatch diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index 248064e367..4fb2907305 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -59,8 +59,7 @@ subroutine mortality_rates( cohort_in,bc_in,btran_ft, mean_temp, & ! background and freezing and size and age dependent senescence ! ============================================================================ - use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm - use FatesInterfaceTypesMod , only : hlm_hio_ignore_val + use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm use FatesConstantsMod, only : fates_check_param_set use DamageMainMod, only : GetDamageMortality diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index ea13822517..6ba8877a12 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -2071,7 +2071,7 @@ end subroutine mortality_litter_fluxes subroutine create_patch(currentSite, new_patch, age, areap, label,nocomp_pft) - use FatesInterfaceTypesMod, only : hlm_current_tod,hlm_current_date,hlm_reference_date + use FatesInterfaceTypesMod, only : hlm_current_tod ! ! !DESCRIPTION: diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index cd1ba0ee3a..35def81bc0 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2652,8 +2652,6 @@ subroutine fragmentation_scaler( currentPatch, bc_in) ! currentPatch%fragmentation_scaler ! ! !USES: - - use FatesSynchronizedParamsMod , only : FatesSynchronizedParamsInst use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm use FatesConstantsMod, only : pi => pi_const ! diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index 937fe81bb7..67efc87aae 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -616,7 +616,6 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) use FatesInterfaceTypesMod, only : bc_in_type, bc_out_type - use FatesInterfaceTypesMod, only : hlm_use_vertsoilc use FatesConstantsMod, only : itrue use FatesGlobals, only : endrun => fates_endrun use EDParamsMod , only : ED_val_cwd_flig, ED_val_cwd_fcel diff --git a/biogeophys/EDSurfaceAlbedoMod.F90 b/biogeophys/EDSurfaceAlbedoMod.F90 index 360abf38cd..fb800ef80b 100644 --- a/biogeophys/EDSurfaceAlbedoMod.F90 +++ b/biogeophys/EDSurfaceAlbedoMod.F90 @@ -68,7 +68,6 @@ subroutine ED_Norman_Radiation (nsites, sites, bc_in, bc_out ) ! ! !USES: - use EDPftvarcon , only : EDPftvarcon_inst use EDtypesMod , only : ed_patch_type use EDTypesMod , only : ed_site_type diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 22c3b0c491..7f27bc6107 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -126,8 +126,6 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! !USES: - - use FatesSynchronizedParamsMod , only : FatesSynchronizedParamsInst use EDTypesMod , only : ed_site_type use EDTypesMod , only : maxpft use EDParamsMod , only : dinc_vai diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 5d28d29ca2..ad6c87c38c 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1542,8 +1542,8 @@ subroutine FatesCheckParams(is_master) use FatesConstantsMod , only : fates_check_param_set use FatesConstantsMod , only : itrue, ifalse use EDParamsMod , only : logging_mechanical_frac, logging_collateral_frac - use EDParamsMod , only : logging_direct_frac,logging_export_frac - use FatesInterfaceTypesMod, only : hlm_use_fixed_biogeog,hlm_use_sp, hlm_name + use EDParamsMod , only : logging_direct_frac + use FatesInterfaceTypesMod, only : hlm_use_fixed_biogeog use FatesInterfaceTypesMod, only : hlm_use_inventory_init ! Argument diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index a703958734..f62bccdff7 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -751,7 +751,6 @@ subroutine set_inventory_edpatch_type1(newpatch,pss_file_unit,ipa,ios,patch_name use FatesSizeAgeTypeIndicesMod, only: get_age_class_index use EDtypesMod, only: AREA - use SFParamsMod , only : SF_val_CWD_frac ! Arguments type(ed_patch_type),intent(inout), target :: newpatch ! Patch structure diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 345bfde3f2..17de63ca3b 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -2517,7 +2517,6 @@ subroutine create_patchcohort_structure(this, nc, nsites, sites, bc_in, bc_out) use EDInitMod, only : zero_site use EDInitMod, only : init_site_vars use EDPatchDynamicsMod, only : create_patch - use EDPftvarcon, only : EDPftvarcon_inst use FatesAllometryMod, only : h2d_allom diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 03acfd8a77..d959d14b90 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -707,9 +707,6 @@ end function SafeLog subroutine CNPAdjustFRootTargets(this, target_c, target_dcdd) - use FatesInterfaceTypesMod , only : hlm_day_of_year - use FatesInterfaceTypesMod , only : hlm_current_year - class(cnp_allom_prt_vartypes) :: this real(r8) :: target_c(:) real(r8) :: target_dcdd(:) From 166ba8a2f3ce9c6b866f41ee679f0db291a7bb53 Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Fri, 7 Apr 2023 14:10:01 -0600 Subject: [PATCH 611/852] fixed bugs related to the merge with fates main api 25 --- biogeochem/EDPatchDynamicsMod.F90 | 8 +++++--- main/EDTypesMod.F90 | 2 -- main/FatesRestartInterfaceMod.F90 | 1 - main/FatesRunningMeanMod.F90 | 16 ++++++---------- parteh/PRTAllometricCarbonMod.F90 | 2 +- 5 files changed, 12 insertions(+), 17 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index d75a1faece..f1194ee084 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -3115,14 +3115,17 @@ subroutine dealloc_patch(cpatch) deallocate(cpatch%seedling_layer_par24) deallocate(cpatch%sdlng_mort_par) deallocate(cpatch%sdlng2sap_par) - deallocate(cpatch%sdlng_mdd) - deallocate(cpatch%sdlng_emerg_smp) do pft = 1, maxpft deallocate(cpatch%sdlng_mdd(pft)%p) deallocate(cpatch%sdlng_emerg_smp(pft)%p) enddo + + deallocate(cpatch%sdlng_mdd) + deallocate(cpatch%sdlng_emerg_smp) + + deallocate(cpatch%tveg24, stat=istat, errmsg=smsg) if (istat/=0) then write(fates_log(),*) 'dealloc010: fail on deallocate(cpatch%tveg24):'//trim(smsg) @@ -3138,7 +3141,6 @@ subroutine dealloc_patch(cpatch) write(fates_log(),*) 'dealloc012: fail on deallocate(cpatch%tveg_longterm):'//trim(smsg) call endrun(msg=errMsg(sourcefile, __LINE__)) endif - return end subroutine dealloc_patch diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 4281ebfe18..2d38bd635f 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -471,8 +471,6 @@ module EDTypesMod ! to sapling transition timescale ! (sdlng2sap_par_timescale) - integer :: nocomp_pft_label ! where nocomp is active, use this label for patch ID. - ! LEAF ORGANIZATION real(r8) :: pft_agb_profile(maxpft,n_dbh_bins) ! binned above ground biomass, for patch fusion: KgC/m2 real(r8) :: canopy_layer_tlai(nclmax) ! total leaf area index of each canopy layer diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index e682e6d24e..96b4ad3ab4 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -1405,7 +1405,6 @@ subroutine define_restart_vars(this, initialize_variables) long_name='fates area lost from damage each year', & units='m2/ha/year', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_crownarea_usto_si) ->>>>>>> main call this%DefineRMeanRestartVar(vname='fates_tveg24patch',vtype=cohort_r8, & long_name='24-hour patch veg temp', & diff --git a/main/FatesRunningMeanMod.F90 b/main/FatesRunningMeanMod.F90 index 6ab59a43f0..7ef7866d62 100644 --- a/main/FatesRunningMeanMod.F90 +++ b/main/FatesRunningMeanMod.F90 @@ -79,12 +79,6 @@ module FatesRunningMeanMod end type rmean_type - - type, public :: rmean_arr_type - class(rmean_type), pointer :: p - end type rmean_arr_type - - logical, parameter :: debug = .true. character(len=*), parameter, private :: sourcefile = & @@ -100,18 +94,20 @@ module FatesRunningMeanMod class(rmean_def_type), public, pointer :: ema_60day ! Exponential moving average, 60 day ! Updated daily class(rmean_def_type), public, pointer :: ema_storemem ! EMA used for smoothing N/C and P/C storage - class(rmean_def_type), public, pointer :: ema_sdlng_emerg_h2o ! EMA for moisture-based seedling emergence class(rmean_def_type), public, pointer :: ema_sdlng_mort_par ! EMA for seedling mort from light stress - class(rmean_def_type), public, pointer :: ema_sdlng_mdd ! EMA for seedling moisture deficit days class(rmean_def_type), public, pointer :: ema_sdlng2sap_par ! EMA for seedling to sapling transition rates ! based in par - + class(rmean_def_type), public, pointer :: ema_sdlng_emerg_h2o ! EMA for moisture-based seedling emergence + class(rmean_def_type), public, pointer :: ema_sdlng_mdd ! EMA for seedling moisture deficit days + + ! If we want to have different running mean specs based on ! pft or other types of constants type, public :: rmean_arr_type - class(rmean_def_type), pointer :: p + class(rmean_type), pointer :: p end type rmean_arr_type + contains diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 153c3857ba..d51cedbd2d 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -974,8 +974,8 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) call bbgw_allom(dbh,ipft,ct_bgw, ct_dbgwdd) call bdead_allom(ct_agw,ct_bgw, ct_sap, ipft, ct_dead, & ct_dagwdd, ct_dbgwdd, ct_dsapdd, ct_ddeaddd) - call bstore_allom(dbh,ipft,canopy_trim,ct_store,ct_dstoredd) call bstore_allom(dbh,ipft,crowndamage, canopy_trim,ct_store,ct_dstoredd) + ! fraction of carbon going towards reproduction !START ahb's changes From f1dcd483cbe4533910d8e441d682e43d46b10c43 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Fri, 7 Apr 2023 15:36:31 -0600 Subject: [PATCH 612/852] move more subroutines to cohort type --- biogeochem/EDCohortDynamicsMod.F90 | 88 +------------ main/FatesCohortMod.F90 | 196 ++++++++++++++++++++++++++++- 2 files changed, 194 insertions(+), 90 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index e137441fc7..5a1983aded 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -196,98 +196,16 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & type(fates_cohort_type), pointer :: new_cohort ! Pointer to New Cohort structure. type(fates_cohort_type), pointer :: storesmallcohort type(fates_cohort_type), pointer :: storebigcohort -integer :: iage ! loop counter for leaf age classes -real(r8) :: leaf_c ! total leaf carbon real(r8) :: rmean_temp ! running mean temperature integer :: tnull,snull ! are the tallest and shortest cohorts allocate integer :: nlevrhiz ! number of rhizosphere layers !---------------------------------------------------------------------- +! create new cohort allocate(new_cohort) - -call new_cohort%init(prt) - -!**********************/ -! Define cohort state variable -!**********************/ - -new_cohort%indexnumber = fates_unset_int ! Cohort indexing was not thread-safe, setting - ! bogus value for the time being (RGK-012017) -new_cohort%pft = pft -new_cohort%crowndamage = crowndamage -new_cohort%status_coh = status -new_cohort%n = nn -new_cohort%hite = hite -new_cohort%dbh = dbh -new_cohort%coage = coage -new_cohort%canopy_trim = ctrim -new_cohort%canopy_layer = clayer -new_cohort%canopy_layer_yesterday = real(clayer, r8) - -! Initialize the leaf to fineroot biomass ratio -! for C-only, this will stay constant, for nutrient enabled -! this will be dynamic. In both cases, new cohorts are -! initialized with the minimum. This works in the nutrient -! enabled case, because cohorts are also initialized with -! full stores, which match with minimum fr biomass - -new_cohort%l2fr = prt_params%allom_l2fr(pft) - -if(hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) then - new_cohort%cx_int = 0._r8 ! Assume balanced N,P/C stores ie log(1) = 0 - new_cohort%cx0 = 0._r8 ! Assume balanced N,P/C stores ie log(1) = 0 - new_cohort%ema_dcxdt = 0._r8 ! Assume unchanged dCX/dt - new_cohort%cnp_limiter = 0 ! Assume limitations are unknown -end if - -! This sets things like vcmax25top, that depend on the -! leaf age fractions (which are defined by PARTEH) -call UpdateCohortBioPhysRates(new_cohort) - -call sizetype_class_index(new_cohort%dbh, new_cohort%pft, & - new_cohort%size_class,new_cohort%size_by_pft_class) - -! If cohort age trackign is off we call this here once -! just so everythin is in the first bin - -! this makes it easier to copy and terminate cohorts later -! we don't need to update this ever if cohort age tracking is off -call coagetype_class_index(new_cohort%coage, new_cohort%pft, & - new_cohort%coage_class,new_cohort%coage_by_pft_class) - -! This routine may be called during restarts, and at this point in the call sequence -! the actual cohort data is unknown, as this is really only used for allocation -! In these cases, testing if things like biomass are reasonable is pre-mature -! However, in this part of the code, we will pass in nominal values for size, number and type - -if (new_cohort%dbh <= 0._r8 .or. new_cohort%n == 0._r8 .or. new_cohort%pft == 0 ) then - write(fates_log(),*) 'ED: something is zero in create_cohort', & - new_cohort%dbh,new_cohort%n, & - new_cohort%pft - call endrun(msg=errMsg(sourcefile, __LINE__)) -endif - -! Assign canopy extent and depth -if(hlm_use_sp.eq.ifalse)then - call carea_allom(new_cohort%dbh,new_cohort%n,spread,new_cohort%pft, & - new_cohort%crowndamage,new_cohort%c_area) -else - new_cohort%c_area = carea ! set this from previously precision-controlled value in SP mode -endif -! Query PARTEH for the leaf carbon [kg] -leaf_c = new_cohort%prt%GetState(leaf_organ,carbon12_element) - -new_cohort%treelai = tree_lai(leaf_c, new_cohort%pft, new_cohort%c_area, & - new_cohort%n, new_cohort%canopy_layer, & - patchptr%canopy_layer_tlai,new_cohort%vcmax25top ) - -if(hlm_use_sp.eq.ifalse)then - new_cohort%treesai = tree_sai(new_cohort%pft, new_cohort%dbh, & - new_cohort%crowndamage, new_cohort%canopy_trim, & - new_cohort%c_area, new_cohort%n, new_cohort%canopy_layer, & - patchptr%canopy_layer_tlai, new_cohort%treelai,new_cohort%vcmax25top,2 ) -end if - +call new_cohort%create(pft, prt, nn, hite, coage, dbh, status, ctrim, carea, & + clayer, crowndamage, spread, patchptr%canopy_layer_tlai) ! Put cohort at the right place in the linked list storebigcohort => patchptr%tallest diff --git a/main/FatesCohortMod.F90 b/main/FatesCohortMod.F90 index 9c7a1f5865..714181a16f 100644 --- a/main/FatesCohortMod.F90 +++ b/main/FatesCohortMod.F90 @@ -6,14 +6,19 @@ module FatesCohortMod use EDParamsMod, only : nlevleaf use FatesGlobals, only : endrun => fates_endrun use FatesGlobals, only : fates_log + use PRTGenericMod, only : max_nleafage use PRTGenericMod, only : prt_vartypes use PRTGenericMod, only : prt_carbon_allom_hyp use PRTGenericMod, only : prt_cnp_flex_allom_hyp use PRTGenericMod, only : leaf_organ, fnrt_organ, sapw_organ use PRTGenericMod, only : repro_organ, store_organ, struct_organ use PRTGenericMod, only : carbon12_element + use PRTParametersMod, only : prt_params use FatesHydraulicsMemMod, only : ed_cohort_hydr_type use FatesInterfaceTypesMod, only : hlm_parteh_mode + use FatesInterfaceTypesMod, only : hlm_use_sp + use FatesInterfaceTypesMod, only : nleafage + use FatesAllometryMod, only : carea_allom, tree_lai, tree_sai use PRTAllometricCarbonMod, only : ac_bc_inout_id_dbh, ac_bc_inout_id_netdc, & ac_bc_in_id_cdamage, ac_bc_in_id_pft, & ac_bc_in_id_ctrim, ac_bc_in_id_lstat @@ -255,8 +260,10 @@ module FatesCohortMod procedure :: dump procedure :: nan_values procedure :: zero_values + procedure :: create procedure :: CanUpperUnder procedure :: InitPRTBoundaryConditions + procedure :: UpdateCohortBioPhysRates end type fates_cohort_type @@ -281,7 +288,6 @@ subroutine init(this, prt) ! The PARTEH cohort object should be allocated and already ! initialized in this routine. call this%prt%CheckInitialConditions() - call this%InitPRTBoundaryConditions() ! new cohorts do not have mortality rates, nor have they moved any @@ -501,8 +507,115 @@ end subroutine zero_values !:.........................................................................: - subroutine InitPRTBoundaryConditions(this) + subroutine create(this, prt, pft, nn, hite, coage, dbh, status, & + ctrim, carea, clayer, crowndamage, spread, can_tlai) + ! + ! DESCRIPTION: + ! set up values for a newly created cohort + + ! ARGUMENTS + class(fates_cohort_type), intent(inout) :: this ! cohort object + class(prt_vartypes), intent(inout), pointer :: prt ! The allocated PARTEH object + integer, intent(in) :: pft ! cohort Plant Functional Type + integer, intent(in) :: crowndamage ! cohort damage class + integer, intent(in) :: clayer ! canopy status of cohort [canopy/understory] + integer, intent(in) :: status ! growth status of cohort [leaves on/off] + real(r8), intent(in) :: nn ! number of individuals in cohort [/m2] + real(r8), intent(in) :: hite ! cohort height [m] + real(r8), intent(in) :: coage ! cohort age [yr] + real(r8), intent(in) :: dbh ! cohort diameter at breat height [cm] + real(r8), intent(in) :: ctrim ! fraction of the maximum leaf biomass + real(r8), intent(in) :: spread ! how spread crowns are in horizontal space + real(r8), intent(in) :: carea ! area of cohort, for SP mode [m2] + real(r8), intent(in) :: can_tlai(nclmax) ! patch-level total LAI of each leaf layer + + ! LOCAL VARIABLES: + integer :: iage ! loop counter for leaf age classes + real(r8) :: leaf_c ! total leaf carbon [kgC] + + ! initialize cohort + call this%init(prt) + + ! set values + this%pft = pft + this%crowndamage = crowndamage + this%canopy_layer = clayer + this%canopy_layer_yesterday = real(clayer, r8) + this%status_coh = status + this%n = nn + this%hite = hite + this%dbh = dbh + this%coage = coage + this%canopy_trim = ctrim + + ! This routine may be called during restarts, and at this point in the call sequence + ! the actual cohort data is unknown, as this is really only used for allocation + ! In these cases, testing if things like biomass are reasonable is premature + ! However, in this part of the code, we will pass in nominal values for size, number and type + if (this%dbh <= 0._r8 .or. this%n == 0._r8 .or. this%pft == 0) then + write(fates_log(),*) 'FATES: something is zero in cohort%create', & + this%dbh, this%n, this%pft + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + + ! Initialize the leaf to fineroot biomass ratio. + ! For C-only, this will stay constant, for nutrient-enabled this will be + ! dynamic. In both cases, new cohorts are initialized with the minimum. + ! This works in the nutrient enabled case because cohorts are also + ! initialized with full stores, which match with minimum fineroot biomass + new_cohort%l2fr = prt_params%allom_l2fr(pft) + + if (hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) then + new_cohort%cx_int = 0._r8 ! Assume balanced N,P/C stores ie log(1) = 0 + new_cohort%cx0 = 0._r8 ! Assume balanced N,P/C stores ie log(1) = 0 + new_cohort%ema_dcxdt = 0._r8 ! Assume unchanged dCX/dt + new_cohort%cnp_limiter = 0 ! Assume limitations are unknown + end if + + ! This sets things like vcmax25top, that depend on the leaf age fractions + ! (which are defined by PARTEH) + call this%UpdateCohortBioPhysRates() + + ! calculate size classes + call sizetype_class_index(this%dbh, this%pft, this%size_class, & + this%size_by_pft_class) + + ! If cohort age tracking is off we call this here once, just so everything + ! is in the first bin. This makes it easier to copy and terminate cohorts + ! later. + ! We don't need to update this ever if cohort age tracking is off + call coagetype_class_index(this%coage, this%pft, this%coage_class, & + this%coage_by_pft_class) + + ! asssign or calculate canopy extent and depth + if (hlm_use_sp .eq. ifalse) then + call carea_allom(this%dbh, this%n, spread, this%pft, this%crowndamage, & + this%c_area) + else + ! set this from previously precision-controlled value in SP mode + this%c_area = carea + endif + + ! Query PARTEH for the leaf carbon [kg] + leaf_c = this%prt%GetState(leaf_organ, carbon12_element) + + ! calculate tree lai + this%treelai = tree_lai(leaf_c, this%pft, this%c_area, this%n, & + this%canopy_layer, can_tlai, this%vcmax25top) + + if (hlm_use_sp .eq. ifalse) then + this%treesai = tree_sai(this%pft, this%dbh, this%crowndamage, & + this%canopy_trim, this%c_area, this%n, this%canopy_layer, can_tlai, & + this%treelai,this%vcmax25top, 2) + end if + + end subroutine create + + !:.........................................................................: + subroutine InitPRTBoundaryConditions(this) + ! + ! DESCRIPTION: ! Set the boundary conditions that flow in an out of the PARTEH ! allocation hypotheses. Each of these calls to "RegsterBC" are simply ! setting pointers. @@ -520,7 +633,8 @@ subroutine InitPRTBoundaryConditions(this) ! value boundary condition. ! bc_ival is used as the optional argument identifyer to specify an integer ! value boundary condition. - + + ! ARGUMENTS: class(fates_cohort_type), intent(inout) :: this select case(hlm_parteh_mode) @@ -574,7 +688,79 @@ subroutine InitPRTBoundaryConditions(this) end subroutine InitPRTBoundaryConditions !:.........................................................................: - + + subroutine UpdateCohortBioPhysRates(this) + ! + ! DESCRIPTION: + ! Update the four key biophysical rates of leaves based on the changes + ! in a cohort's leaf age proportions. + ! + ! This should be called after growth. Growth occurs + ! after turnover and damage states are applied to the tree. + ! Therefore, following growth, the leaf mass fractions + ! of different age classes are unchanged until the next day. + + ! ARGUMENTS + class(fates_cohort_type), intent(inout) :: this ! cohort object + + ! LOCAL VARIABLES + real(r8) :: frac_leaf_aclass(max_nleafage) ! fraction of leaves in each age-class + integer :: iage ! loop index for leaf ages + integer :: ipft ! plant functional type index + + ! First, calculate the fraction of leaves in each age class + ! It is assumed that each class has the same proportion across leaf layers + do iage = 1, nleafage + frac_leaf_aclass(iage) = this%prt%GetState(leaf_organ, & + carbon12_element, iage) + end do + + ! If there are leaves, then perform proportional weighting on the four rates + ! We assume that leaf age does not effect the specific leaf area, so the mass + ! fractions are applicable to these rates + + ipft = currentCohort%pft + + if (sum(frac_leaf_aclass(1:nleafage)) > nearzero .and. & + hlm_use_sp .eq. ifalse) then + + frac_leaf_aclass(1:nleafage) = frac_leaf_aclass(1:nleafage)/ & + sum(frac_leaf_aclass(1:nleafage)) + + this%vcmax25top = sum(EDPftvarcon_inst%vcmax25top(ipft, 1:nleafage)* & + frac_leaf_aclass(1:nleafage)) + + this%jmax25top = sum(param_derived%jmax25top(ipft, 1:nleafage)* & + frac_leaf_aclass(1:nleafage)) + + this%tpu25top = sum(param_derived%tpu25top(ipft, 1:nleafage)* & + frac_leaf_aclass(1:nleafage)) + + this%kp25top = sum(param_derived%kp25top(ipft, 1:nleafage)* & + frac_leaf_aclass(1:nleafage)) + + else if (hlm_use_sp .eq. itrue) then + + this%vcmax25top = EDPftvarcon_inst%vcmax25top(ipft, 1) + this%jmax25top = param_derived%jmax25top(ipft, 1) + this%tpu25top = param_derived%tpu25top(ipft, 1) + this%kp25top = param_derived%kp25top(ipft, 1) + + else + + this%vcmax25top = 0._r8 + this%jmax25top = 0._r8 + this%tpu25top = 0._r8 + this%kp25top = 0._r8 + + end if + + return + + end subroutine UpdateCohortBioPhysRates + + !:.........................................................................: + function CanUpperUnder(this) result(can_position) ! ! DESCRIPTION: @@ -588,7 +774,7 @@ function CanUpperUnder(this) result(can_position) ! ARGUMENTS: class(fates_cohort_type) :: this ! current cohort of interest - integer :: can_position ! canopy position + integer :: can_position ! canopy position if (this%canopy_layer == 1)then can_position = ican_upper From 443075b37e5871fac828045b023306c574c50e38 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Fri, 7 Apr 2023 15:57:45 -0600 Subject: [PATCH 613/852] move more methods to cohort type --- biogeochem/EDCohortDynamicsMod.F90 | 80 +----------------------------- main/EDMainMod.F90 | 3 +- main/EDTypesMod.F90 | 1 - main/FatesCohortMod.F90 | 69 ++++++++++++++------------ main/FatesRestartInterfaceMod.F90 | 3 +- 5 files changed, 42 insertions(+), 114 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 5a1983aded..a790ad1edb 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -125,7 +125,6 @@ Module EDCohortDynamicsMod public :: count_cohorts public :: InitPRTObject public :: SendCohortToLitter - public :: UpdateCohortBioPhysRates public :: DeallocateCohort public :: EvaluateAndCorrectDBH public :: DamageRecovery @@ -204,7 +203,7 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & ! create new cohort allocate(new_cohort) -call new_cohort%create(pft, prt, nn, hite, coage, dbh, status, ctrim, carea, & +call new_cohort%create(prt, pft, nn, hite, coage, dbh, status, ctrim, carea, & clayer, crowndamage, spread, patchptr%canopy_layer_tlai) ! Put cohort at the right place in the linked list @@ -891,7 +890,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) ! Leaf biophysical rates (use leaf mass weighting) ! ----------------------------------------------------------------- - call UpdateCohortBioPhysRates(currentCohort) + call currentCohort%UpdateCohortBioPhysRates() currentCohort%l2fr = (currentCohort%n*currentCohort%l2fr & + nextc%n*nextc%l2fr)/newn @@ -1658,81 +1657,6 @@ end subroutine count_cohorts ! =================================================================================== - subroutine UpdateCohortBioPhysRates(currentCohort) - - ! -------------------------------------------------------------------------------- - ! This routine updates the four key biophysical rates of leaves - ! based on the changes in a cohort's leaf age proportions - ! - ! This should be called after growth. Growth occurs - ! after turnover and damage states are applied to the tree. - ! Therefore, following growth, the leaf mass fractions - ! of different age classes are unchanged until the next day. - ! -------------------------------------------------------------------------------- - - type(fates_cohort_type),intent(inout) :: currentCohort - - - real(r8) :: frac_leaf_aclass(max_nleafage) ! Fraction of leaves in each age-class - integer :: iage ! loop index for leaf ages - integer :: ipft ! plant functional type index - - ! First, calculate the fraction of leaves in each age class - ! It is assumed that each class has the same proportion - ! across leaf layers - - do iage = 1, nleafage - frac_leaf_aclass(iage) = & - currentCohort%prt%GetState(leaf_organ, carbon12_element,iage) - end do - - ! If there are leaves, then perform proportional weighting on the four rates - ! We assume that leaf age does not effect the specific leaf area, so the mass - ! fractions are applicable to these rates - - ipft = currentCohort%pft - - if(sum(frac_leaf_aclass(1:nleafage))>nearzero .and. hlm_use_sp .eq. ifalse) then - - - frac_leaf_aclass(1:nleafage) = frac_leaf_aclass(1:nleafage) / & - sum(frac_leaf_aclass(1:nleafage)) - - currentCohort%vcmax25top = sum(EDPftvarcon_inst%vcmax25top(ipft,1:nleafage) * & - frac_leaf_aclass(1:nleafage)) - - currentCohort%jmax25top = sum(param_derived%jmax25top(ipft,1:nleafage) * & - frac_leaf_aclass(1:nleafage)) - - currentCohort%tpu25top = sum(param_derived%tpu25top(ipft,1:nleafage) * & - frac_leaf_aclass(1:nleafage)) - - currentCohort%kp25top = sum(param_derived%kp25top(ipft,1:nleafage) * & - frac_leaf_aclass(1:nleafage)) - - elseif (hlm_use_sp .eq. itrue) then - - currentCohort%vcmax25top = EDPftvarcon_inst%vcmax25top(ipft,1) - currentCohort%jmax25top = param_derived%jmax25top(ipft,1) - currentCohort%tpu25top = param_derived%tpu25top(ipft,1) - currentCohort%kp25top = param_derived%kp25top(ipft,1) - - else - - currentCohort%vcmax25top = 0._r8 - currentCohort%jmax25top = 0._r8 - currentCohort%tpu25top = 0._r8 - currentCohort%kp25top = 0._r8 - - end if - - - return - end subroutine UpdateCohortBioPhysRates - - - ! ============================================================================ - subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index c9cb3a8c84..386f788db8 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -56,7 +56,6 @@ module EDMainMod use EDPhysiologyMod , only : GenerateDamageAndLitterFluxes use FatesSoilBGCFluxMod , only : FluxIntoLitterPools use FatesSoilBGCFluxMod , only : EffluxIntoLitterPools - use EDCohortDynamicsMod , only : UpdateCohortBioPhysRates use FatesSoilBGCFluxMod , only : PrepNutrientAquisitionBCs use FatesSoilBGCFluxMod , only : PrepCH4BCs use SFMainMod , only : fire_model @@ -636,7 +635,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! mass in the different leaf age classes. Following growth ! and turnover, these proportions won't change again. This ! routine is also called following fusion - call UpdateCohortBioPhysRates(currentCohort) + call currentCohort%UpdateCohortBioPhysRates() ! This cohort has grown, it is no longer "new" currentCohort%isnew = .false. diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index e9184cf40b..9db76ff895 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -30,7 +30,6 @@ module EDTypesMod use EDParamsMod, only : maxSWb, nclmax, nlevleaf use shr_log_mod, only : errMsg => shr_log_errMsg - implicit none private ! By default everything is private save diff --git a/main/FatesCohortMod.F90 b/main/FatesCohortMod.F90 index 714181a16f..8073d70527 100644 --- a/main/FatesCohortMod.F90 +++ b/main/FatesCohortMod.F90 @@ -1,28 +1,35 @@ module FatesCohortMod - use FatesConstantsMod, only : r8 => fates_r8 - use FatesConstantsMod, only : fates_unset_int - use FatesConstantsMod, only : ican_upper, ican_ustory - use EDParamsMod, only : nlevleaf - use FatesGlobals, only : endrun => fates_endrun - use FatesGlobals, only : fates_log - use PRTGenericMod, only : max_nleafage - use PRTGenericMod, only : prt_vartypes - use PRTGenericMod, only : prt_carbon_allom_hyp - use PRTGenericMod, only : prt_cnp_flex_allom_hyp - use PRTGenericMod, only : leaf_organ, fnrt_organ, sapw_organ - use PRTGenericMod, only : repro_organ, store_organ, struct_organ - use PRTGenericMod, only : carbon12_element - use PRTParametersMod, only : prt_params - use FatesHydraulicsMemMod, only : ed_cohort_hydr_type - use FatesInterfaceTypesMod, only : hlm_parteh_mode - use FatesInterfaceTypesMod, only : hlm_use_sp - use FatesInterfaceTypesMod, only : nleafage - use FatesAllometryMod, only : carea_allom, tree_lai, tree_sai - use PRTAllometricCarbonMod, only : ac_bc_inout_id_dbh, ac_bc_inout_id_netdc, & - ac_bc_in_id_cdamage, ac_bc_in_id_pft, & - ac_bc_in_id_ctrim, ac_bc_in_id_lstat - use PRTAllometricCNPMod, only : acnp_bc_in_id_pft, acnp_bc_in_id_ctrim, & + use FatesConstantsMod, only : r8 => fates_r8 + use FatesConstantsMod, only : fates_unset_int + use FatesConstantsMod, only : ifalse, itrue + use FatesConstantsMod, only : nearzero + use FatesConstantsMod, only : ican_upper, ican_ustory + use EDParamsMod, only : nlevleaf + use EDParamsMod, only : nclmax + use FatesGlobals, only : endrun => fates_endrun + use FatesGlobals, only : fates_log + use PRTGenericMod, only : max_nleafage + use PRTGenericMod, only : prt_vartypes + use PRTGenericMod, only : prt_carbon_allom_hyp + use PRTGenericMod, only : prt_cnp_flex_allom_hyp + use PRTGenericMod, only : leaf_organ, fnrt_organ, sapw_organ + use PRTGenericMod, only : repro_organ, store_organ, struct_organ + use PRTGenericMod, only : carbon12_element + use PRTParametersMod, only : prt_params + use FatesParameterDerivedMod, only : param_derived + use FatesHydraulicsMemMod, only : ed_cohort_hydr_type + use FatesInterfaceTypesMod, only : hlm_parteh_mode + use FatesInterfaceTypesMod, only : hlm_use_sp + use FatesInterfaceTypesMod, only : nleafage + use EDPftvarcon, only : EDPftvarcon_inst + use FatesSizeAgeTypeIndicesMod, only : sizetype_class_index + use FatesSizeAgeTypeIndicesMod, only : coagetype_class_index + use FatesAllometryMod, only : carea_allom, tree_lai, tree_sai + use PRTAllometricCarbonMod, only : ac_bc_inout_id_dbh, ac_bc_inout_id_netdc, & + ac_bc_in_id_cdamage, ac_bc_in_id_pft, & + ac_bc_in_id_ctrim, ac_bc_in_id_lstat + use PRTAllometricCNPMod, only : acnp_bc_in_id_pft, acnp_bc_in_id_ctrim, & acnp_bc_in_id_lstat, acnp_bc_in_id_netdc, & acnp_bc_in_id_netdc, acnp_bc_in_id_nc_repro, & acnp_bc_in_id_pc_repro, acnp_bc_in_id_cdamage, & @@ -33,8 +40,8 @@ module FatesCohortMod acnp_bc_out_id_cefflux, acnp_bc_out_id_nefflux, & acnp_bc_out_id_pefflux, acnp_bc_out_id_limiter - use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) - use shr_log_mod, only : errMsg => shr_log_errMsg + use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) + use shr_log_mod, only : errMsg => shr_log_errMsg implicit none private @@ -563,13 +570,13 @@ subroutine create(this, prt, pft, nn, hite, coage, dbh, status, & ! dynamic. In both cases, new cohorts are initialized with the minimum. ! This works in the nutrient enabled case because cohorts are also ! initialized with full stores, which match with minimum fineroot biomass - new_cohort%l2fr = prt_params%allom_l2fr(pft) + this%l2fr = prt_params%allom_l2fr(pft) if (hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) then - new_cohort%cx_int = 0._r8 ! Assume balanced N,P/C stores ie log(1) = 0 - new_cohort%cx0 = 0._r8 ! Assume balanced N,P/C stores ie log(1) = 0 - new_cohort%ema_dcxdt = 0._r8 ! Assume unchanged dCX/dt - new_cohort%cnp_limiter = 0 ! Assume limitations are unknown + this%cx_int = 0._r8 ! Assume balanced N,P/C stores ie log(1) = 0 + this%cx0 = 0._r8 ! Assume balanced N,P/C stores ie log(1) = 0 + this%ema_dcxdt = 0._r8 ! Assume unchanged dCX/dt + this%cnp_limiter = 0 ! Assume limitations are unknown end if ! This sets things like vcmax25top, that depend on the leaf age fractions @@ -719,7 +726,7 @@ subroutine UpdateCohortBioPhysRates(this) ! We assume that leaf age does not effect the specific leaf area, so the mass ! fractions are applicable to these rates - ipft = currentCohort%pft + ipft = this%pft if (sum(frac_leaf_aclass(1:nleafage)) > nearzero .and. & hlm_use_sp .eq. ifalse) then diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 17de63ca3b..f9669b4c8a 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -24,7 +24,6 @@ module FatesRestartInterfaceMod use FatesInterfaceTypesMod, only : hlm_use_nocomp, hlm_use_fixed_biogeog use FatesInterfaceTypesMod, only : fates_maxElementsPerSite use FatesInterfaceTypesMod, only : hlm_use_tree_damage - use EDCohortDynamicsMod, only : UpdateCohortBioPhysRates use FatesHydraulicsMemMod, only : nshell use FatesHydraulicsMemMod, only : n_hypool_ag use FatesHydraulicsMemMod, only : n_hypool_troot @@ -3063,7 +3062,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ccohort%isnew = ( rio_isnew_co(io_idx_co) .eq. new_cohort ) call ccohort%InitPRTBoundaryConditions() - call UpdateCohortBioPhysRates(ccohort) + call ccohort%UpdateCohortBioPhysRates() ! Initialize Plant Hydraulics From b0fdcb4a5d0da04f48d2b11dfe2c7d3b97f206e4 Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Fri, 7 Apr 2023 17:16:22 -0600 Subject: [PATCH 614/852] adding regeneration switch --- biogeochem/EDPhysiologyMod.F90 | 4 ++-- main/FatesConstantsMod.F90 | 2 ++ parameter_files/fates_params_default.cdl | 4 ++-- parteh/PRTAllometricCarbonMod.F90 | 18 +++++++++--------- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 60097d4075..7536860599 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1861,7 +1861,7 @@ subroutine SeedIn( currentSite, bc_in ) litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)/area !START ahb's changes - if ( regeneration_model == TRS .and. & + if ( regeneration_model >= TRS .and. & prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees) then !Send a fraction of reproductive carbon to litter to account for @@ -1957,7 +1957,7 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day !If the TRS is switched on and the pft is a tree then use the TRS - else if ( regeneration_model == TRS .and. & + else if ( regeneration_model >= TRS .and. & prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees ) then !---------------------------------------------------------------------- diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index 6790845c3e..e324414eca 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -50,6 +50,8 @@ module FatesConstantsMod integer, public, parameter :: coupled_np_comp_scaling = 1 ! This flag signals that at least 1 chemical element (ie N or P) !Flags specifying how tree regeneration works + + integer, public, parameter :: TRS_no_seedling_dyn = 3 !Constant defining the Tree Recruitment Scheme switch integer, public, parameter :: TRS = 2 !Constant defining the Tree Recruitment Scheme switch integer, public, parameter :: default_regeneration = 1 !Constant defining FATES's default regeneration scheme switch real(fates_r8), public, parameter :: min_max_dbh_for_trees = 15._fates_r8 !cm; if pfts have a max dbh less diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 501095d9c9..8aa3c65217 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -775,7 +775,7 @@ variables: fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; double fates_regeneration_model ; fates_regeneration_model:units = "unitless" ; - fates_regeneration_model:long_name = "switch for choosing between FATES's default regeneration scheme (1) or the Tree Recruitment Scheme (Hanbury-Brown et al., 2022;2)" ; + fates_regeneration_model:long_name = "switch for choosing between FATES's default regeneration scheme (1), the full Tree Recruitment Scheme (2; Hanbury-Brown et al., 2022), or (3) the Tree Recruitment Scheme without seedling dynamics" ; double fates_leaf_theta_cj_c3 ; fates_leaf_theta_cj_c3:units = "unitless" ; fates_leaf_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; @@ -1603,7 +1603,7 @@ data: fates_landuse_logging_coll_under_frac = 0.55983 ; - fates_regeneration_model = 2 ; + fates_regeneration_model = 1 ; fates_landuse_logging_collateral_frac = 0.05 ; diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index d51cedbd2d..cc9b0d9af5 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -990,7 +990,7 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) repro_fraction = prt_params%seed_alloc(ipft) + prt_params%seed_alloc_mature(ipft) end if - else if ( regeneration_model == TRS .and. & + else if ( regeneration_model >= TRS .and. & prt_params%allom_dbh_maxheight(ipft) > min_max_dbh_for_trees ) then !------------------------------------------------------------------------------------- @@ -1011,16 +1011,16 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) !ahb diagnostic - if (debug_trs) then - if (hlm_day_of_year == 40 .OR. hlm_day_of_year == 270) then + !if (debug_trs) then + !if (hlm_day_of_year == 40 .OR. hlm_day_of_year == 270) then - write(fates_log(),*) 'day_of_year:', hlm_day_of_year - write(fates_log(),*) 'pft:', ipft - write(fates_log(),*) 'dbh (cm):', dbh - write(fates_log(),*) 'repro_fraction:', repro_fraction + ! write(fates_log(),*) 'day_of_year:', hlm_day_of_year + ! write(fates_log(),*) 'pft:', ipft + ! write(fates_log(),*) 'dbh (cm):', dbh + ! write(fates_log(),*) 'repro_fraction:', repro_fraction - end if !day condition - end if !debug condition + !end if !day condition + !end if !debug condition !end ahb diagnostic From e1f7b47c7ac4814fa74518f0f9554a7dd4a8e126 Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Fri, 7 Apr 2023 17:31:48 -0600 Subject: [PATCH 615/852] updated regen switch in Seed Decay subroutine --- biogeochem/EDPhysiologyMod.F90 | 53 +++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 7536860599..92de75b7ce 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1956,20 +1956,30 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) litt%seed_decay(pft) = litt%seed(pft) * & EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day - !If the TRS is switched on and the pft is a tree then use the TRS - else if ( regeneration_model >= TRS .and. & + end if !end default regeneration model + + ! If the TRS is fully switched on, or if it is switched on without seedling dynamics + ! (regeneration_model = TRS_no_seedling_dyn), + ! and the pft is a tree then make sure the non-seed reproductive biomass is added the + ! the seed decay flux. + if ( regeneration_model >= TRS .and. & prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees ) then !---------------------------------------------------------------------- !With respect to seed decay, the only difference with the TRS here is adding the flux !from non-seed reproductive biomass (which was sent to litt%seed_decay in the SeedIn subroutine) - litt%seed_decay(pft) = litt%seed_decay(pft) + &!from non-seed reproductive biomass; working? + litt%seed_decay(pft) = litt%seed_decay(pft) + &!from non-seed reproductive biomass. litt%seed(pft) * EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day - end if !regeneration model switch + end if !Send non-seed reproductive biomass to seed decay flux. + - ! 2. Seedling mortality (i.e. fluxes from seedling pool (seed_germ) to litter) + ! If the full TRS model is switch on (regeneration_model == TRS) then calculate seedling mortality. + if ( regeneration_model == TRS .and. & + prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees ) then + + !Seedling mortality (i.e. fluxes from seedling pool (seed_germ) to litter) !---------------------------------------------------------------------- !Step 1. Calculate the daily seedling mortality rate from light stress @@ -1982,15 +1992,10 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) seedling_light_mort_rate = exp( EDPftvarcon_inst%seedling_light_mort_a(pft) * & seedling_layer_par + EDPftvarcon_inst%seedling_light_mort_b(pft) ) - !TEMP - !write(fates_log(),*) 'seedling layer par ', seedling_layer_par - !write(fates_log(),*) 'seedling light mort rate ', seedling_light_mort_rate - !Step 3. Calculate the daily seedling mortality rate from moisture stress !Get the current seedling moisture deficit days !Calculated as (abs(seedling_psi_crit) - abs(seedling_layer_smp))* -1 * mddWindow - seedling_mdds = currentPatch%sdlng_mdd(pft)%p%GetMean() !Calculate seedling mortality as a function of moisture deficit days @@ -2000,26 +2005,28 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) if (seedling_mdds < EDPftvarcon_inst%seedling_mdd_crit(pft)) then seedling_h2o_mort_rate = 0.0_r8 - end if + end if !mdd threshold check !Step 4. Add background mortality and send dead seedling carbon to litter (i.e. to seed_germ_decay flux) litt%seed_germ_decay(pft) = (litt%seed_germ(pft) * seedling_light_mort_rate) + & (litt%seed_germ(pft) * seedling_h2o_mort_rate) + & (litt%seed_germ(pft) * EDPftvarcon_inst%background_seedling_mort(pft) & * years_per_day) - !ahb diagnostic - if (debug_trs) then - if (hlm_day_of_year == 40 .OR. hlm_day_of_year == 270) then - write(fates_log(),*) 'day_of_year:', hlm_day_of_year - write(fates_log(),*) 'patch_age:', currentPatch%age - write(fates_log(),*) 'pft', pft - write(fates_log(),*) 'seedling_light_mort_rate (day -1):', seedling_light_mort_rate - write(fates_log(),*) 'seedling_h2o_mort_rate (day -1):', seedling_h2o_mort_rate - write(fates_log(),*) 'seedling mdds ([0,1]):', seedling_mdds - end if + end if !Use full TRS - end if !debug flag - !end ahb diagnostic + !ahb diagnostic + ! if (debug_trs) then + ! if (hlm_day_of_year == 40 .OR. hlm_day_of_year == 270) then + ! write(fates_log(),*) 'day_of_year:', hlm_day_of_year + ! write(fates_log(),*) 'patch_age:', currentPatch%age + ! write(fates_log(),*) 'pft', pft + ! write(fates_log(),*) 'seedling_light_mort_rate (day -1):', seedling_light_mort_rate + ! write(fates_log(),*) 'seedling_h2o_mort_rate (day -1):', seedling_h2o_mort_rate + ! write(fates_log(),*) 'seedling mdds ([0,1]):', seedling_mdds + ! end if + + ! end if !debug flag + !end ahb diagnostic !----------------------------------------------------------------------- !END ahb's changes From 90ada144da51f3dc14cde42b35b8828b418fa120 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 10 Apr 2023 13:40:32 -0400 Subject: [PATCH 616/852] Update restart memory specs for hydro --- main/FatesHydraulicsMemMod.F90 | 2 +- main/FatesInterfaceMod.F90 | 36 ++++++++++++++++++++-------------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/main/FatesHydraulicsMemMod.F90 b/main/FatesHydraulicsMemMod.F90 index 57329921b4..23f3f75482 100644 --- a/main/FatesHydraulicsMemMod.F90 +++ b/main/FatesHydraulicsMemMod.F90 @@ -33,7 +33,7 @@ module FatesHydraulicsMemMod integer, parameter, public :: n_hypool_stem = 1 integer, parameter, public :: n_hypool_troot = 1 ! CANNOT BE CHANGED integer, parameter, public :: n_hypool_aroot = 1 ! THIS IS "PER-SOIL-LAYER" - integer, parameter, public :: nshell = 5 + integer, parameter, public :: nshell = 1 ! number of aboveground plant water storage nodes diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 24e425b6f1..aae6eade63 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -89,6 +89,8 @@ module FatesInterfaceMod use FatesRunningMeanMod , only : moving_ema_window use FatesRunningMeanMod , only : fixed_window use FatesHistoryInterfaceMod , only : fates_hist + use FatesHydraulicsMemMod , only : nshell + use FatesHydraulicsMemMod , only : nlevsoi_hyd_max ! CIME Globals use shr_log_mod , only : errMsg => shr_log_errMsg @@ -405,20 +407,20 @@ subroutine allocate_bcin(bc_in, nlevsoil_in, nlevdecomp_in, num_lu_harvest_cats, call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if( (nlevsoil_in*ndcmpy) > fates_maxElementsPerPatch .or. & - (nlevsoil_in*ncwd) > fates_maxElementsPerPatch) then - write(fates_log(), *) 'The restart files require that space is allocated' - write(fates_log(), *) 'to accomodate the multi-dimensional patch arrays' - write(fates_log(), *) 'that are nlevsoil*numpft and nlevsoil*ncwd' - write(fates_log(), *) 'fates_maxElementsPerPatch = ',fates_maxElementsPerPatch - write(fates_log(), *) 'nlevsoil = ',nlevsoil_in - write(fates_log(), *) 'dcmpy = ',ndcmpy - write(fates_log(), *) 'ncwd = ',ncwd - write(fates_log(), *) 'numpft*nlevsoil = ',nlevsoil_in*numpft - write(fates_log(), *) 'ncwd*nlevsoil = ',ncwd * nlevsoil_in - write(fates_log(), *) 'To increase max_elements, change numlevsoil_max' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + !if( (nlevsoil_in*ndcmpy) > fates_maxElementsPerPatch .or. & + ! (nlevsoil_in*ncwd) > fates_maxElementsPerPatch) then + ! write(fates_log(), *) 'The restart files require that space is allocated' + ! write(fates_log(), *) 'to accomodate the multi-dimensional patch arrays' + ! write(fates_log(), *) 'that are nlevsoil*numpft and nlevsoil*ncwd' + ! write(fates_log(), *) 'fates_maxElementsPerPatch = ',fates_maxElementsPerPatch + ! write(fates_log(), *) 'nlevsoil = ',nlevsoil_in + ! write(fates_log(), *) 'dcmpy = ',ndcmpy + ! write(fates_log(), *) 'ncwd = ',ncwd + ! write(fates_log(), *) 'numpft*nlevsoil = ',nlevsoil_in*numpft + ! write(fates_log(), *) 'ncwd*nlevsoil = ',ncwd * nlevsoil_in + ! write(fates_log(), *) 'To increase max_elements, change numlevsoil_max' + ! call endrun(msg=errMsg(sourcefile, __LINE__)) + !end if bc_in%nlevdecomp = nlevdecomp_in @@ -845,7 +847,11 @@ subroutine SetFatesGlobalElements2(use_fates) fates_maxElementsPerSite = max(fates_maxPatchesPerSite * fates_maxElementsPerPatch, & numWatermem, num_vegtemp_mem, num_elements, nlevsclass*numpft) - + if(hlm_use_planthydro==itrue)then + fates_maxElementsPerSite = max(fates_maxElementsPerSite, nshell*nlevsoi_hyd_max ) + end if + + ! Set the maximum number of nutrient aquisition competitors per site ! This is used to set array sizes for the boundary conditions. ! Note: since BGC code may be active even when no nutrients From 72d3a1406f47952a26d139cdbfb8b1617aec559b Mon Sep 17 00:00:00 2001 From: adrifoster Date: Mon, 10 Apr 2023 12:32:20 -0600 Subject: [PATCH 617/852] move patch type to its own module --- biogeochem/EDCanopyStructureMod.F90 | 29 +-- biogeochem/EDCohortDynamicsMod.F90 | 28 ++- biogeochem/EDLoggingMortalityMod.F90 | 9 +- biogeochem/EDMortalityFunctionsMod.F90 | 5 +- biogeochem/EDPatchDynamicsMod.F90 | 75 +++---- biogeochem/EDPhysiologyMod.F90 | 39 ++-- biogeochem/FatesPatchMod.F90 | 184 +++++++++++++++++ biogeochem/FatesSoilBGCFluxMod.F90 | 12 +- biogeophys/EDAccumulateFluxesMod.F90 | 6 +- biogeophys/EDBtranMod.F90 | 8 +- biogeophys/EDSurfaceAlbedoMod.F90 | 15 +- biogeophys/FatesBstressMod.F90 | 8 +- biogeophys/FatesPlantHydraulicsMod.F90 | 20 +- biogeophys/FatesPlantRespPhotosynthMod.F90 | 10 +- fire/SFMainMod.F90 | 24 +-- main/ChecksBalancesMod.F90 | 8 +- main/EDInitMod.F90 | 12 +- main/EDMainMod.F90 | 12 +- main/EDTypesMod.F90 | 221 +-------------------- main/FatesConstantsMod.F90 | 12 ++ main/FatesHistoryInterfaceMod.F90 | 14 +- main/FatesInterfaceMod.F90 | 6 +- main/FatesInventoryInitMod.F90 | 20 +- main/FatesRestartInterfaceMod.F90 | 18 +- 24 files changed, 391 insertions(+), 404 deletions(-) create mode 100644 biogeochem/FatesPatchMod.F90 diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 39c4c1c1d4..144dd14781 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -19,7 +19,8 @@ module EDCanopyStructureMod use EDCohortDynamicsMod , only : InitPRTObject use FatesAllometryMod , only : tree_lai use FatesAllometryMod , only : tree_sai - use EDtypesMod , only : ed_site_type, ed_patch_type + use EDtypesMod , only : ed_site_type + use FatesPatchMod, only : fates_patch_type use FatesCohortMod, only : fates_cohort_type use EDParamsMod , only : nclmax use EDParamsMod , only : nlevleaf @@ -136,7 +137,7 @@ subroutine canopy_structure( currentSite , bc_in ) ! ! !LOCAL VARIABLES: - type(ed_patch_type) , pointer :: currentPatch + type(fates_patch_type) , pointer :: currentPatch type(fates_cohort_type), pointer :: currentCohort integer :: i_lyr ! current layer index integer :: z ! Current number of canopy layers. (1= canopy, 2 = understorey) @@ -340,7 +341,7 @@ subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr,bc_in) ! !ARGUMENTS type(ed_site_type), intent(inout) :: currentSite - type(ed_patch_type), intent(inout) :: currentPatch + type(fates_patch_type), intent(inout) :: currentPatch integer, intent(in) :: i_lyr ! Current canopy layer of interest type(bc_in_type), intent(in) :: bc_in @@ -796,7 +797,7 @@ subroutine PromoteIntoLayer(currentSite,currentPatch,i_lyr) ! !ARGUMENTS type(ed_site_type), intent(inout), target :: currentSite - type(ed_patch_type), intent(inout), target :: currentPatch + type(fates_patch_type), intent(inout), target :: currentPatch integer, intent(in) :: i_lyr ! Current canopy layer of interest ! !LOCAL VARIABLES: @@ -1243,7 +1244,7 @@ subroutine canopy_spread( currentSite ) ! ! !LOCAL VARIABLES: type (fates_cohort_type), pointer :: currentCohort - type (ed_patch_type) , pointer :: currentPatch + type (fates_patch_type) , pointer :: currentPatch real(r8) :: sitelevel_canopyarea ! Amount of canopy in top layer at the site level real(r8) :: inc ! Arbitrary daily incremental change in canopy area integer :: z @@ -1307,7 +1308,7 @@ subroutine canopy_summarization( nsites, sites, bc_in ) type(bc_in_type) , intent(in) :: bc_in(nsites) ! ! !LOCAL VARIABLES: - type (ed_patch_type) , pointer :: currentPatch + type (fates_patch_type) , pointer :: currentPatch type (fates_cohort_type) , pointer :: currentCohort integer :: s integer :: ft ! plant functional type @@ -1508,7 +1509,7 @@ subroutine leaf_area_profile( currentSite ) ! ! !LOCAL VARIABLES: - type (ed_patch_type) , pointer :: currentPatch + type (fates_patch_type) , pointer :: currentPatch type (fates_cohort_type) , pointer :: currentCohort real(r8) :: remainder !Thickness of layer at bottom of canopy. real(r8) :: fleaf ! fraction of cohort incepting area that is leaves. @@ -1801,8 +1802,8 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) ! to vegetation coverage to the host land model. ! ---------------------------------------------------------------------------------- - use EDTypesMod , only : ed_patch_type, & - ed_site_type, AREA + use EDTypesMod , only : ed_site_type, AREA + use FatesPatchMod, only : fates_patch_type use FatesInterfaceTypesMod , only : bc_out_type ! @@ -1815,7 +1816,7 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) ! Locals type (fates_cohort_type) , pointer :: currentCohort integer :: s, ifp, c, p - type (ed_patch_type) , pointer :: currentPatch + type (fates_patch_type) , pointer :: currentPatch real(r8) :: bare_frac_area real(r8) :: total_patch_area real(r8) :: total_canopy_area @@ -2031,7 +2032,7 @@ function calc_areaindex(cpatch,ai_type) result(ai) ! ---------------------------------------------------------------------------------- ! Arguments - type(ed_patch_type),intent(in), target :: cpatch + type(fates_patch_type),intent(in), target :: cpatch character(len=*),intent(in) :: ai_type integer :: cl,ft @@ -2095,7 +2096,7 @@ subroutine CanopyLayerArea(currentPatch,site_spread,layer_index,layer_area) ! --------------------------------------------------------------------------------------------- ! Arguments - type(ed_patch_type),intent(inout), target :: currentPatch + type(fates_patch_type),intent(inout), target :: currentPatch real(r8),intent(in) :: site_spread integer,intent(in) :: layer_index real(r8),intent(inout) :: layer_area @@ -2126,7 +2127,7 @@ subroutine UpdatePatchLAI(currentPatch) ! --------------------------------------------------------------------------------------------- ! Arguments - type(ed_patch_type),intent(inout), target :: currentPatch + type(fates_patch_type),intent(inout), target :: currentPatch ! Local Variables type(fates_cohort_type), pointer :: currentCohort @@ -2217,7 +2218,7 @@ function NumPotentialCanopyLayers(currentPatch,site_spread,include_substory) res ! the understory in the event the understory has reached maximum allowable area. ! -------------------------------------------------------------------------------------------- - type(ed_patch_type),target :: currentPatch + type(fates_patch_type),target :: currentPatch real(r8),intent(in) :: site_spread logical :: include_substory diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index a790ad1edb..7ed68711f1 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -26,7 +26,8 @@ Module EDCohortDynamicsMod use EDPftvarcon , only : GetDecompyFrac use PRTParametersMod , only : prt_params use FatesParameterDerivedMod, only : param_derived - use EDTypesMod , only : ed_site_type, ed_patch_type + use EDTypesMod , only : ed_site_type + use FatesPatchMod, only : fates_patch_type use FatesCohortMod , only : fates_cohort_type use EDParamsMod , only : nclmax use PRTGenericMod , only : element_list @@ -165,7 +166,7 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & ! !ARGUMENTS type(ed_site_type), intent(inout), target :: currentSite -type(ed_patch_type), intent(inout), pointer :: patchptr +type(fates_patch_type), intent(inout), pointer :: patchptr integer, intent(in) :: pft ! Cohort Plant Functional Type integer, intent(in) :: crowndamage ! Cohort damage class @@ -349,7 +350,7 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_ ! ! !ARGUMENTS type (ed_site_type) , intent(inout) :: currentSite - type (ed_patch_type), intent(inout) :: currentPatch + type (fates_patch_type), intent(inout) :: currentPatch integer , intent(in) :: level integer :: call_index type(bc_in_type), intent(in) :: bc_in @@ -466,7 +467,7 @@ subroutine terminate_cohort(currentSite, currentPatch, currentCohort, bc_in) ! ! !ARGUMENTS type (ed_site_type) , intent(inout), target :: currentSite - type (ed_patch_type) , intent(inout), target :: currentPatch + type (fates_patch_type) , intent(inout), target :: currentPatch type (fates_cohort_type), intent(inout), target :: currentCohort type(bc_in_type), intent(in) :: bc_in @@ -572,7 +573,7 @@ subroutine SendCohortToLitter(csite,cpatch,ccohort,nplant,bc_in) ! Arguments type (ed_site_type) , target :: csite - type (ed_patch_type) , target :: cpatch + type (fates_patch_type) , target :: cpatch type (fates_cohort_type) , target :: ccohort real(r8) :: nplant ! Number (absolute) ! of plants to transfer @@ -679,11 +680,8 @@ subroutine SendCohortToLitter(csite,cpatch,ccohort,nplant,bc_in) return end subroutine SendCohortToLitter - !-------------------------------------------------------------------------------------- - - subroutine DeallocateCohort(currentCohort) ! ---------------------------------------------------------------------------------- @@ -730,7 +728,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) ! ! !ARGUMENTS type (ed_site_type), intent(inout) :: currentSite - type (ed_patch_type), intent(inout), pointer :: currentPatch + type (fates_patch_type), intent(inout), pointer :: currentPatch type (bc_in_type), intent(in) :: bc_in ! @@ -1293,9 +1291,9 @@ subroutine sort_cohorts(patchptr) ! sort cohorts into the correct order DO NOT CHANGE THIS IT WILL BREAK ! ============================================================================ - type(ed_patch_type) , intent(inout), target :: patchptr + type(fates_patch_type) , intent(inout), target :: patchptr - type(ed_patch_type) , pointer :: current_patch + type(fates_patch_type) , pointer :: current_patch type(fates_cohort_type), pointer :: current_c, next_c type(fates_cohort_type), pointer :: shortestc, tallestc type(fates_cohort_type), pointer :: storesmallcohort @@ -1347,7 +1345,7 @@ subroutine insert_cohort(currentPatch, pcc, ptall, pshort, tnull, snull, storebi ! !USES: ! ! !ARGUMENTS - type(ed_patch_type), intent(inout), target :: currentPatch + type(fates_patch_type), intent(inout), target :: currentPatch type(fates_cohort_type) , intent(inout), pointer :: pcc type(fates_cohort_type) , intent(inout), pointer :: ptall type(fates_cohort_type) , intent(inout), pointer :: pshort @@ -1357,7 +1355,7 @@ subroutine insert_cohort(currentPatch, pcc, ptall, pshort, tnull, snull, storebi type(fates_cohort_type) , intent(inout),pointer,optional :: storebigcohort ! storage of the largest cohort for insertion routine ! ! !LOCAL VARIABLES: - !type(ed_patch_type), pointer :: currentPatch + !type(fates_patch_type), pointer :: currentPatch type(fates_cohort_type), pointer :: current type(fates_cohort_type), pointer :: tallptr, shortptr, icohort type(fates_cohort_type), pointer :: ptallest, pshortest @@ -1624,7 +1622,7 @@ subroutine count_cohorts( currentPatch ) ! !USES: ! ! !ARGUMENTS - type(ed_patch_type), intent(inout), target :: currentPatch !new site + type(fates_patch_type), intent(inout), target :: currentPatch !new site ! ! !LOCAL VARIABLES: type(fates_cohort_type), pointer :: currentCohort !new patch @@ -1764,7 +1762,7 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) ! -------------------------------------------------------------------------- type(ed_site_type) :: csite ! Site of the current cohort - type(ed_patch_type) :: cpatch ! patch of the current cohort + type(fates_patch_type) :: cpatch ! patch of the current cohort type(fates_cohort_type),pointer :: ccohort ! Current (damaged) cohort logical :: newly_recovered ! true if we create a new cohort diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 36882b87fb..b971d96270 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -16,7 +16,7 @@ module EDLoggingMortalityMod use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : rsnbl_math_prec use FatesCohortMod , only : fates_cohort_type - use EDTypesMod , only : ed_patch_type + use FatesPatchMod , only : fates_patch_type use EDTypesMod , only : site_massbal_type use EDTypesMod , only : site_fluxdiags_type use FatesLitterMod , only : ncwd @@ -460,7 +460,7 @@ subroutine get_harvestable_carbon (csite, site_area, hlm_harvest_catnames, harve real(r8), intent(out) :: harvestable_forest_c(hlm_num_lu_harvest_cats) ! Local Variables - type(ed_patch_type), pointer :: currentPatch + type(fates_patch_type), pointer :: currentPatch type(fates_cohort_type), pointer :: currentCohort real(r8) :: harvestable_patch_c ! patch level total carbon available for harvest, kgC site-1 real(r8) :: harvestable_cohort_c ! cohort level total carbon available for harvest, kgC site-1 @@ -716,7 +716,6 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site use SFParamsMod, only : SF_val_cwd_frac use EDtypesMod, only : area use EDtypesMod, only : ed_site_type - use EDtypesMod, only : ed_patch_type use FatesCohortMod, only : fates_cohort_type use FatesConstantsMod, only : rsnbl_math_prec use FatesAllometryMod, only : carea_allom @@ -724,8 +723,8 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site ! !ARGUMENTS: type(ed_site_type) , intent(inout), target :: currentSite - type(ed_patch_type) , intent(inout), target :: currentPatch - type(ed_patch_type) , intent(inout), target :: newPatch + type(fates_patch_type) , intent(inout), target :: currentPatch + type(fates_patch_type) , intent(inout), target :: newPatch real(r8) , intent(in) :: patch_site_areadis type(bc_in_type) , intent(in) :: bc_in diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index 4fb2907305..b8977e1b30 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -11,8 +11,7 @@ module EDMortalityFunctionsMod use EDPftvarcon , only : EDPftvarcon_inst use FatesCohortMod , only : fates_cohort_type use EDTypesMod , only : ed_site_type - use EDTypesMod , only : ed_patch_type - use EDTypesMod , only : maxpft + use FatesConstantsMod, only : maxpft use FatesConstantsMod , only : itrue,ifalse use FatesAllometryMod , only : bleaf use FatesAllometryMod , only : storage_fraction_of_target @@ -49,8 +48,6 @@ module EDMortalityFunctionsMod contains - - subroutine mortality_rates( cohort_in,bc_in,btran_ft, mean_temp, & cmort,hmort,bmort, frmort,smort,asmort,dgmort ) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 6ba8877a12..2934948aab 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -16,17 +16,18 @@ module EDPatchDynamicsMod use FatesLitterMod , only : ncwd use FatesLitterMod , only : ndcmpy use FatesLitterMod , only : litter_type + use FatesConstantsMod, only : n_dbh_bins use EDTypesMod , only : homogenize_seed_pfts - use EDTypesMod , only : n_dbh_bins, area, patchfusion_dbhbin_loweredges + use EDTypesMod , only : area, patchfusion_dbhbin_loweredges use EDtypesMod , only : force_patchfuse_min_biomass - use EDTypesMod , only : ed_site_type, ed_patch_type + use EDTypesMod , only : ed_site_type + use FatesPatchMod, only : fates_patch_type use FatesCohortMod , only : fates_cohort_type use EDTypesMod , only : site_massbal_type use EDTypesMod , only : site_fluxdiags_type use EDTypesMod , only : min_patch_area use EDTypesMod , only : min_patch_area_forced - use EDParamsMod , only : nclmax - use EDTypesMod , only : maxpft + use EDParamsMod , only : nclmax use EDTypesMod , only : dtype_ifall use EDTypesMod , only : dtype_ilog use EDTypesMod , only : dtype_ifire @@ -36,7 +37,7 @@ module EDPatchDynamicsMod use FatesLitterMod , only : lg_sf use FatesLitterMod , only : dl_sf use EDTypesMod , only : dump_patch - use EDTypesMod , only : N_DIST_TYPES + use FatesConstantsMod , only : N_DIST_TYPES use EDTypesMod , only : AREA_INV use FatesConstantsMod , only : rsnbl_math_prec use FatesConstantsMod , only : fates_tiny @@ -174,7 +175,7 @@ subroutine disturbance_rates( site_in, bc_in) type(bc_in_type) , intent(in) :: bc_in ! ! !LOCAL VARIABLES: - type (ed_patch_type) , pointer :: currentPatch + type (fates_patch_type) , pointer :: currentPatch type (fates_cohort_type), pointer :: currentCohort real(r8) :: cmort @@ -416,10 +417,10 @@ subroutine spawn_patches( currentSite, bc_in) type (bc_in_type), intent(in) :: bc_in ! ! !LOCAL VARIABLES: - type (ed_patch_type) , pointer :: new_patch - type (ed_patch_type) , pointer :: new_patch_primary - type (ed_patch_type) , pointer :: new_patch_secondary - type (ed_patch_type) , pointer :: currentPatch + type (fates_patch_type) , pointer :: new_patch + type (fates_patch_type) , pointer :: new_patch_primary + type (fates_patch_type) , pointer :: new_patch_secondary + type (fates_patch_type) , pointer :: currentPatch type (fates_cohort_type), pointer :: currentCohort type (fates_cohort_type), pointer :: nc type (fates_cohort_type), pointer :: storesmallcohort @@ -1257,8 +1258,8 @@ subroutine check_patch_area( currentSite ) ! ! !LOCAL VARIABLES: real(r8) :: areatot - type(ed_patch_type), pointer :: currentPatch - type(ed_patch_type), pointer :: largestPatch + type(fates_patch_type), pointer :: currentPatch + type(fates_patch_type), pointer :: largestPatch real(r8) :: largest_area integer :: el real(r8) :: live_stock @@ -1328,7 +1329,7 @@ subroutine set_patchno( currentSite ) type(ed_site_type),intent(in) :: currentSite ! ! !LOCAL VARIABLES: - type(ed_patch_type), pointer :: currentPatch + type(fates_patch_type), pointer :: currentPatch integer patchno !--------------------------------------------------------------------- @@ -1408,8 +1409,8 @@ subroutine TransLitterNewPatch(currentSite, & ! ! !ARGUMENTS: type(ed_site_type) , intent(in) :: currentSite ! site - type(ed_patch_type) , intent(in) :: currentPatch ! Donor patch - type(ed_patch_type) , intent(inout) :: newPatch ! New patch + type(fates_patch_type) , intent(in) :: currentPatch ! Donor patch + type(fates_patch_type) , intent(inout) :: newPatch ! New patch real(r8) , intent(in) :: patch_site_areadis ! Area being donated ! by current patch @@ -1621,8 +1622,8 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & ! ! !ARGUMENTS: type(ed_site_type) , intent(inout), target :: currentSite - type(ed_patch_type) , intent(inout), target :: currentPatch ! Donor Patch - type(ed_patch_type) , intent(inout), target :: newPatch ! New Patch + type(fates_patch_type) , intent(inout), target :: currentPatch ! Donor Patch + type(fates_patch_type) , intent(inout), target :: newPatch ! New Patch real(r8) , intent(in) :: patch_site_areadis ! Area being donated type(bc_in_type) , intent(in) :: bc_in @@ -1859,8 +1860,8 @@ subroutine mortality_litter_fluxes(currentSite, currentPatch, & ! ! !ARGUMENTS: type(ed_site_type) , intent(inout), target :: currentSite - type(ed_patch_type) , intent(inout), target :: currentPatch - type(ed_patch_type) , intent(inout), target :: newPatch + type(fates_patch_type) , intent(inout), target :: currentPatch + type(fates_patch_type) , intent(inout), target :: newPatch real(r8) , intent(in) :: patch_site_areadis type(bc_in_type) , intent(in) :: bc_in ! @@ -2081,7 +2082,7 @@ subroutine create_patch(currentSite, new_patch, age, areap, label,nocomp_pft) ! ! !ARGUMENTS: type(ed_site_type) , intent(inout), target :: currentSite - type(ed_patch_type), intent(inout), target :: new_patch + type(fates_patch_type), intent(inout), target :: new_patch real(r8), intent(in) :: age ! notional age of this patch in years real(r8), intent(in) :: areap ! initial area of this patch in m2. integer, intent(in) :: label ! anthropogenic disturbance label @@ -2204,10 +2205,10 @@ subroutine zero_patch(cp_p) ! !USES: ! ! !ARGUMENTS: - type(ed_patch_type), intent(inout), target :: cp_p + type(fates_patch_type), intent(inout), target :: cp_p ! ! !LOCAL VARIABLES: - type(ed_patch_type), pointer :: currentPatch + type(fates_patch_type), pointer :: currentPatch !--------------------------------------------------------------------- currentPatch => cp_p @@ -2330,7 +2331,7 @@ subroutine fuse_patches( csite, bc_in ) ! ! !LOCAL VARIABLES: type(ed_site_type) , pointer :: currentSite - type(ed_patch_type), pointer :: currentPatch,tpp,tmpptr + type(fates_patch_type), pointer :: currentPatch,tpp,tmpptr integer :: ft,z !counters for pft and height class real(r8) :: norm !normalized difference between biomass profiles real(r8) :: profiletol !tolerance of patch fusion routine. Starts off high and is reduced if there are too many patches. @@ -2637,8 +2638,8 @@ subroutine fuse_2_patches(csite, dp, rp) ! ! !ARGUMENTS: type (ed_site_type), intent(inout),target :: csite ! Current site - type (ed_patch_type) , pointer :: dp ! Donor Patch - type (ed_patch_type) , target, intent(inout) :: rp ! Recipient Patch + type (fates_patch_type) , pointer :: dp ! Donor Patch + type (fates_patch_type) , target, intent(inout) :: rp ! Recipient Patch ! ! !LOCAL VARIABLES: @@ -2649,8 +2650,8 @@ subroutine fuse_2_patches(csite, dp, rp) integer :: c,p !counters for pft and litter size class. integer :: tnull,snull ! are the tallest and shortest cohorts associated? integer :: el ! loop counting index for elements - type(ed_patch_type), pointer :: youngerp ! pointer to the patch younger than donor - type(ed_patch_type), pointer :: olderp ! pointer to the patch older than donor + type(fates_patch_type), pointer :: youngerp ! pointer to the patch younger than donor + type(fates_patch_type), pointer :: olderp ! pointer to the patch older than donor real(r8) :: inv_sum_area ! Inverse of the sum of the two patches areas !----------------------------------------------------------------------------------------------- @@ -2819,10 +2820,10 @@ subroutine terminate_patches(currentSite) type(ed_site_type), target, intent(inout) :: currentSite ! ! !LOCAL VARIABLES: - type(ed_patch_type), pointer :: currentPatch - type(ed_patch_type), pointer :: olderPatch - type(ed_patch_type), pointer :: youngerPatch - type(ed_patch_type), pointer :: patchpointer + type(fates_patch_type), pointer :: currentPatch + type(fates_patch_type), pointer :: olderPatch + type(fates_patch_type), pointer :: youngerPatch + type(fates_patch_type), pointer :: patchpointer integer, parameter :: max_cycles = 10 ! After 10 loops through ! You should had fused integer :: count_cycles @@ -2988,7 +2989,7 @@ subroutine DistributeSeeds(currentSite,seed_mass,el,pft) integer, intent(in) :: pft ! pft index ! !LOCAL VARIABLES: - type(ed_patch_type), pointer :: currentPatch + type(fates_patch_type), pointer :: currentPatch type(litter_type), pointer :: litt @@ -3018,7 +3019,7 @@ subroutine dealloc_patch(cpatch) ! to via the patch structure. This subroutine DOES NOT deallocate the patch ! structure itself. - type(ed_patch_type) :: cpatch + type(fates_patch_type) :: cpatch type(fates_cohort_type), pointer :: ccohort ! current type(fates_cohort_type), pointer :: ncohort ! next @@ -3096,10 +3097,10 @@ subroutine patch_pft_size_profile(cp_pnt) ! !USES: ! ! !ARGUMENTS: - type(ed_patch_type), target, intent(inout) :: cp_pnt + type(fates_patch_type), target, intent(inout) :: cp_pnt ! ! !LOCAL VARIABLES: - type(ed_patch_type) , pointer :: currentPatch + type(fates_patch_type) , pointer :: currentPatch type(fates_cohort_type), pointer :: currentCohort real(r8) :: mind(N_DBH_BINS) ! Bottom of DBH bin real(r8) :: maxd(N_DBH_BINS) ! Top of DBH bin @@ -3156,7 +3157,7 @@ function countPatches( nsites, sites ) result ( totNumPatches ) type(ed_site_type) , intent(inout), target :: sites(nsites) ! ! !LOCAL VARIABLES: - type (ed_patch_type), pointer :: currentPatch + type (fates_patch_type), pointer :: currentPatch integer :: totNumPatches ! total number of patches. integer :: s !--------------------------------------------------------------------- @@ -3189,7 +3190,7 @@ subroutine get_frac_site_primary(site_in, frac_site_primary) real(r8) , intent(out) :: frac_site_primary ! !LOCAL VARIABLES: - type (ed_patch_type), pointer :: currentPatch + type (fates_patch_type), pointer :: currentPatch frac_site_primary = 0._r8 currentPatch => site_in%oldest_patch diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 35def81bc0..b1500736e8 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -51,10 +51,11 @@ module EDPhysiologyMod use FatesLitterMod , only : icellulose use EDParamsMod , only : nclmax use EDTypesMod , only : AREA,AREA_INV - use EDParamsMod , only : nlevleaf + use EDParamsMod , only : nlevleaf use EDTypesMod , only : num_vegtemp_mem - use EDTypesMod , only : maxpft - use EDTypesMod , only : ed_site_type, ed_patch_type + use FatesConstantsMod , only : maxpft + use EDTypesMod , only : ed_site_type + use FatesPatchMod, only : fates_patch_type use FatesCohortMod, only : fates_cohort_type use FatesConstantsMod , only : leaves_on use FatesConstantsMod , only : leaves_off @@ -164,7 +165,7 @@ subroutine ZeroLitterFluxes( currentSite ) ! !ARGUMENTS type(ed_site_type), intent(inout), target :: currentSite - type(ed_patch_type), pointer :: currentPatch + type(fates_patch_type), pointer :: currentPatch integer :: el @@ -186,7 +187,7 @@ subroutine ZeroAllocationRates( currentSite ) ! !ARGUMENTS type(ed_site_type), intent(inout), target :: currentSite - type(ed_patch_type), pointer :: currentPatch + type(fates_patch_type), pointer :: currentPatch type(fates_cohort_type), pointer :: currentCohort currentPatch => currentSite%youngest_patch @@ -212,7 +213,7 @@ subroutine GenerateDamageAndLitterFluxes( csite, cpatch, bc_in ) ! Arguments type(ed_site_type) :: csite - type(ed_patch_type) :: cpatch + type(fates_patch_type) :: cpatch type(bc_in_type), intent(in) :: bc_in @@ -399,7 +400,7 @@ subroutine PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in ) ! !ARGUMENTS type(ed_site_type), intent(inout) :: currentSite - type(ed_patch_type), intent(inout) :: currentPatch + type(fates_patch_type), intent(inout) :: currentPatch type(bc_in_type), intent(in) :: bc_in ! @@ -476,7 +477,7 @@ subroutine PreDisturbanceIntegrateLitter(currentPatch) ! ----------------------------------------------------------------------------------- ! Arguments - type(ed_patch_type),intent(inout),target :: currentPatch + type(fates_patch_type),intent(inout),target :: currentPatch ! Locals @@ -560,7 +561,7 @@ subroutine trim_canopy( currentSite ) ! ! !LOCAL VARIABLES: type (fates_cohort_type) , pointer :: currentCohort - type (ed_patch_type) , pointer :: currentPatch + type (fates_patch_type) , pointer :: currentPatch integer :: z ! leaf layer integer :: ipft ! pft index @@ -881,7 +882,7 @@ subroutine phenology( currentSite, bc_in ) ! ! !LOCAL VARIABLES: - type(ed_patch_type),pointer :: cpatch + type(fates_patch_type),pointer :: cpatch integer :: model_day_int ! integer model day 1 - inf integer :: ncolddays ! no days underneath the threshold for leaf drop integer :: i_wmem ! Loop counter for water mem days @@ -1255,7 +1256,7 @@ subroutine phenology_leafonoff(currentSite) type(ed_site_type), intent(inout), target :: currentSite ! ! !LOCAL VARIABLES: - type(ed_patch_type) , pointer :: currentPatch + type(fates_patch_type) , pointer :: currentPatch type(fates_cohort_type), pointer :: currentCohort real(r8) :: leaf_c ! leaf carbon [kg] @@ -1515,7 +1516,7 @@ subroutine satellite_phenology(currentSite, bc_in) class(prt_vartypes), pointer :: prt ! !LOCAL VARIABLES: - type(ed_patch_type) , pointer :: currentPatch + type(fates_patch_type) , pointer :: currentPatch type(fates_cohort_type), pointer :: currentCohort real(r8) :: spread ! dummy value of canopy spread to estimate c_area @@ -1761,7 +1762,7 @@ subroutine SeedIn( currentSite, bc_in ) type(ed_site_type), intent(inout), target :: currentSite type(bc_in_type), intent(in) :: bc_in - type(ed_patch_type), pointer :: currentPatch + type(fates_patch_type), pointer :: currentPatch type(litter_type), pointer :: litt type(fates_cohort_type), pointer :: currentCohort type(site_massbal_type), pointer :: site_mass @@ -1987,7 +1988,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) ! ! !ARGUMENTS type(ed_site_type), intent(inout) :: currentSite - type(ed_patch_type), intent(inout),pointer :: currentPatch + type(fates_patch_type), intent(inout),pointer :: currentPatch type(bc_in_type), intent(in) :: bc_in ! ! !LOCAL VARIABLES: @@ -2314,7 +2315,7 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) ! ! !ARGUMENTS type(ed_site_type), intent(inout), target :: currentSite - type(ed_patch_type),intent(inout), target :: currentPatch + type(fates_patch_type),intent(inout), target :: currentPatch type(litter_type),intent(inout),target :: litt type(bc_in_type),intent(in) :: bc_in @@ -2656,7 +2657,7 @@ subroutine fragmentation_scaler( currentPatch, bc_in) use FatesConstantsMod, only : pi => pi_const ! ! !ARGUMENTS - type(ed_patch_type), intent(inout) :: currentPatch + type(fates_patch_type), intent(inout) :: currentPatch type(bc_in_type), intent(in) :: bc_in ! @@ -2788,7 +2789,7 @@ subroutine UpdateRecruitL2FR(csite) ! and less than the max_count cohort. type(ed_site_type) :: csite - type(ed_patch_type), pointer :: cpatch + type(fates_patch_type), pointer :: cpatch type(fates_cohort_type), pointer :: ccohort real(r8) :: rec_n(maxpft,nclmax) ! plant count @@ -2856,7 +2857,7 @@ end subroutine UpdateRecruitL2FR subroutine UpdateRecruitStoich(csite) type(ed_site_type) :: csite - type(ed_patch_type), pointer :: cpatch + type(fates_patch_type), pointer :: cpatch type(fates_cohort_type), pointer :: ccohort integer :: ft ! functional type index integer :: cl ! canopy layer index @@ -2899,7 +2900,7 @@ subroutine SetRecruitL2FR(csite) type(ed_site_type) :: csite - type(ed_patch_type), pointer :: cpatch + type(fates_patch_type), pointer :: cpatch type(fates_cohort_type), pointer :: ccohort integer :: ft,cl diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 new file mode 100644 index 0000000000..8374324db4 --- /dev/null +++ b/biogeochem/FatesPatchMod.F90 @@ -0,0 +1,184 @@ +module FatesPatchMod + + use FatesConstantsMod, only : r8 => fates_r8 + use FatesCohortMod, only : fates_cohort_type + use FatesRunningMeanMod, only : rmean_type + use FatesLitterMod, only : nfsc + use FatesLitterMod, only : litter_type + use EDParamsMod, only : maxSWb, nlevleaf, nclmax + use FatesConstantsMod, only : n_dbh_bins, maxpft, n_dist_types + use FatesConstantsMod, only : n_rad_stream_types + + implicit none + private + + type, public :: fates_patch_type + + ! POINTERS + type (fates_cohort_type), pointer :: tallest => null() ! pointer to patch's tallest cohort + type (fates_cohort_type), pointer :: shortest => null() ! pointer to patch's shortest cohort + type (fates_patch_type), pointer :: older => null() ! pointer to next older patch + type (fates_patch_type), pointer :: younger => null() ! pointer to next younger patch + + !:.........................................................................: + + ! INDICES + integer :: patchno ! unique number given to each new patch created for tracking + integer :: nocomp_pft_label ! when nocomp is active, use this label for patch ID + ! each patch ID corresponds to a pft number since each + ! patch has only one pft. Bareground patches are given + ! a zero integer as a label. If nocomp is not active this + ! is set to unset. This is set in patch%create as an argument + ! to that procedure. + + !:.........................................................................: + + ! PATCH INFO + real(r8) :: age ! average patch age [years] + integer :: age_class ! age class of the patch for history binning purposes + real(r8) :: area ! patch area [m2] + integer :: countcohorts ! number of cohorts in patch + integer :: ncl_p ! number of occupied canopy layers + integer :: anthro_disturbance_label ! patch label for anthropogenic disturbance classification + real(r8) :: age_since_anthro_disturbance ! average age for secondary forest since last anthropogenic disturbance [years] + + !:.........................................................................: + + ! RUNNING MEANS + !class(rmean_type), pointer :: t2m ! place-holder for 2m air temperature (variable window-size) + class(rmean_type), pointer :: tveg24 ! 24-hour mean vegetation temperature [K] + class(rmean_type), pointer :: tveg_lpa ! running mean of vegetation temperature at the + ! leaf photosynthesis acclimation timescale [K] + class(rmean_type), pointer :: tveg_longterm ! long-term running mean of vegetation temperature at the + ! leaf photosynthesis acclimation timescale [K] (i.e T_home) + + !:.........................................................................: + + ! LEAF ORGANIZATION + real(r8) :: pft_agb_profile(maxpft,n_dbh_bins) ! binned aboveground biomass, for patch fusion [kgC/m2] + real(r8) :: canopy_layer_tlai(nclmax) ! total leaf area index of each canopy layer [m2 veg/m2 canopy area] + ! (patch without bare ground) + ! used to determine attenuation of parameters during photosynthesis + real(r8) :: total_canopy_area ! area that is covered by vegetation [m2] + real(r8) :: total_tree_area ! area that is covered by woody vegetation [m2] + real(r8) :: zstar ! height of smallest canopy tree, only meaningful in "strict PPA" mode [m] + real(r8) :: elai_profile(nclmax,maxpft,nlevleaf) ! exposed leaf area in each canopy layer, pft, and leaf layer [m2 leaf/m2 contributing crown area] + real(r8) :: esai_profile(nclmax,maxpft,nlevleaf) ! exposed stem area in each canopy layer, pft, and leaf layer [m2 leaf/m2 contributing crown area] + real(r8) :: tlai_profile(nclmax,maxpft,nlevleaf) + real(r8) :: tsai_profile(nclmax,maxpft,nlevleaf) + real(r8) :: canopy_area_profile(nclmax,maxpft,nlevleaf) ! fraction of crown area per canopy area in each layer + ! they will sum to 1.0 in the fully closed canopy layers + ! but only in leaf-layers that contain contributions + ! from all cohorts that donate to canopy_area + integer :: canopy_mask(nclmax,maxpft) ! is there any of this pft in this canopy layer? + integer :: nrad(nclmax,maxpft) ! number of exposed leaf layers for each canopy layer and pft + integer :: ncan(nclmax,maxpft) ! number of total leaf layers for each canopy layer and pft + real(r8) :: c_stomata ! mean stomatal conductance of all leaves in the patch [umol/m2/s] + real(r8) :: c_lblayer ! mean boundary layer conductance of all leaves in the patch [umol/m2/s] + real(r8) :: layer_height_profile(nclmax,maxpft,nlevleaf) + + !:.........................................................................: + + real(r8) :: psn_z(nclmax,maxpft,nlevleaf) + real(r8) :: nrmlzd_parprof_pft_dir_z(n_rad_stream_types,nclmax,maxpft,nlevleaf) + real(r8) :: nrmlzd_parprof_pft_dif_z(n_rad_stream_types,nclmax,maxpft,nlevleaf) + real(r8) :: nrmlzd_parprof_dir_z(n_rad_stream_types,nclmax,nlevleaf) + real(r8) :: nrmlzd_parprof_dif_z(n_rad_stream_types,nclmax,nlevleaf) + + !:.........................................................................: + + ! RADIATION + real(r8) :: radiation_error ! radiation error [W/m2] + real(r8) :: fcansno ! fraction of canopy covered in snow [0-1] + logical :: solar_zenith_flag ! integer flag specifying daylight (based on zenith angle) + real(r8) :: solar_zenith_angle ! solar zenith angle [radians] + real(r8) :: gnd_alb_dif(maxSWb) ! ground albedo for diffuse rad, both bands [0-1] + real(r8) :: gnd_alb_dir(maxSWb) ! ground albedo for direct rad, both bands [0-1] + + ! organized by canopy layer, pft, and leaf layer + real(r8) :: fabd_sun_z(nclmax,maxpft,nlevleaf) ! sun fraction of direct light absorbed [0-1] + real(r8) :: fabd_sha_z(nclmax,maxpft,nlevleaf) ! shade fraction of direct light absorbed [0-1] + real(r8) :: fabi_sun_z(nclmax,maxpft,nlevleaf) ! sun fraction of indirect light absorbed [0-1] + real(r8) :: fabi_sha_z(nclmax,maxpft,nlevleaf) ! shade fraction of indirect light absorbed [0-1] + real(r8) :: ed_parsun_z(nclmax,maxpft,nlevleaf) ! PAR absorbed in the sun [W/m2] + real(r8) :: ed_parsha_z(nclmax,maxpft,nlevleaf) ! PAR absorbed in the shade [W/m2] + real(r8) :: ed_laisun_z(nclmax,maxpft,nlevleaf) + real(r8) :: ed_laisha_z(nclmax,maxpft,nlevleaf) + real(r8) :: f_sun(nclmax,maxpft,nlevleaf) ! fraction of leaves in the sun [0-1] + + ! radiation profiles for comparison against observations + real(r8) :: parprof_pft_dir_z(nclmax,maxpft,nlevleaf) ! direct-beam PAR profile through canopy, by canopy, PFT, leaf level [W/m2] + real(r8) :: parprof_pft_dif_z(nclmax,maxpft,nlevleaf) ! diffuse PAR profile through canopy, by canopy, PFT, leaf level [W/m2] + real(r8) :: parprof_dir_z(nclmax,nlevleaf) ! direct-beam PAR profile through canopy, by canopy, leaf level [W/m2] + real(r8) :: parprof_dif_z(nclmax,nlevleaf) ! diffuse PAR profile through canopy, by canopy, leaf level [W/m2] + + real(r8), allocatable :: tr_soil_dir(:) ! fraction of incoming direct radiation transmitted to the soil as direct, by numSWB [0-1] + real(r8), allocatable :: tr_soil_dif(:) ! fraction of incoming diffuse radiation that is transmitted to the soil as diffuse [0-1] + real(r8), allocatable :: tr_soil_dir_dif(:) ! fraction of incoming direct radiation that is transmitted to the soil as diffuse [0-1] + real(r8), allocatable :: fab(:) ! fraction of incoming total radiation that is absorbed by the canopy + real(r8), allocatable :: fabd(:) ! fraction of incoming direct radiation that is absorbed by the canopy + real(r8), allocatable :: fabi(:) ! fraction of incoming diffuse radiation that is absorbed by the canopy + real(r8), allocatable :: sabs_dir(:) ! fraction of incoming direct radiation that is absorbed by the canopy + real(r8), allocatable :: sabs_dif(:) ! fraction of incoming diffuse radiation that is absorbed by the canopy + + !:.........................................................................: + + ! ROOTS + real(r8) :: btran_ft(maxpft) ! btran calculated seperately for each PFT + real(r8) :: bstress_sal_ft(maxpft) ! bstress from salinity calculated seperately for each PFT + + !:.........................................................................: + + ! EXTERNAL SEED RAIN + real(r8) :: nitr_repro_stoich(maxpft) ! The NC ratio of a new recruit in this patch + real(r8) :: phos_repro_stoich(maxpft) ! The PC ratio of a new recruit in this patch + + !:.........................................................................: + + ! DISTURBANCE + real(r8) :: disturbance_rates(n_dist_types) ! disturbance rate [0-1/day] from 1) mortality + ! 2) fire + ! 3) logging mortatliy + real(r8) :: fract_ldist_not_harvested ! fraction of logged area that is canopy trees that weren't harvested [0-1] + + !:.........................................................................: + + ! LITTER AND COARSE WOODY DEBRIS + type(litter_type), pointer :: litter(:) ! litter (leaf,fnrt,CWD and seeds) for different elements + real(r8), allocatable :: fragmentation_scaler(:) ! scale rate of litter fragmentation based on soil layer [0-1] + + !:.........................................................................: + + ! FUELS AND FIRE + ! fuel characteristics + real(r8) :: sum_fuel ! total ground fuel related to ROS (omits 1000 hr fuels) [kgC/m2] + real(r8) :: fuel_frac(nfsc) ! fraction of each litter class in the ros_fuel [0-1] + real(r8) :: livegrass ! total aboveground grass biomass in patch [kgC/m2] + real(r8) :: fuel_bulkd ! average fuel bulk density of the ground fuel. [kg/m3] + ! (incl. live grasses, omits 1000hr fuels) + real(r8) :: fuel_sav ! average surface area to volume ratio of the ground fuel [cm-1] + ! (incl. live grasses, omits 1000hr fuels) + real(r8) :: fuel_mef ! average moisture of extinction factor + ! of the ground fuel (incl. live grasses, omits 1000hr fuels) + real(r8) :: fuel_eff_moist ! effective avearage fuel moisture content of the ground fuel + ! (incl. live grasses. omits 1000hr fuels) + real(r8) :: litter_moisture(nfsc) ! moisture of litter [m3/m3] + + ! fire spread + real(r8) :: ros_front ! rate of forward spread of fire [m/min] + real(r8) :: ros_back ! rate of backward spread of fire [m/min] + real(r8) :: effect_wspeed ! windspeed modified by fraction of relative grass and tree cover [m/min] + real(r8) :: tau_l ! duration of lethal heating [min] + real(r8) :: fi ! average fire intensity of flaming front [kJ/m/s] or [kW/m] + integer :: fire ! is there a fire? [1=yes; 0=no] + real(r8) :: fd ! fire duration [min] + + ! fire effects + real(r8) :: scorch_ht(maxpft) ! scorch height [m] + real(r8) :: frac_burnt ! fraction burnt [0-1/day] + real(r8) :: tfc_ros ! total intensity-relevant fuel consumed - no trunks [kgC/m2 of burned ground/day] + real(r8) :: burnt_frac_litter(nfsc) ! fraction of each litter pool burned, conditional on it being burned [0-1] + + end type fates_patch_type + +end module FatesPatchMod \ No newline at end of file diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index 67efc87aae..50e7461395 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -44,7 +44,7 @@ module FatesSoilBGCFluxMod use EDParamsMod , only : p_uptake_mode use EDParamsMod , only : n_uptake_mode use EDTypesMod , only : ed_site_type - use EDTypesMod , only : ed_patch_type + use FatesPatchMod , only : fates_patch_type use FatesCohortMod , only : fates_cohort_type use EDTypesMod , only : AREA,AREA_INV use FatesInterfaceTypesMod, only : bc_in_type @@ -126,7 +126,7 @@ subroutine UnPackNutrientAquisitionBCs(sites, bc_in) integer :: icomp ! competitor index integer :: id ! decomp layer index integer :: pft ! pft index - type(ed_patch_type), pointer :: cpatch ! current patch pointer + type(fates_patch_type), pointer :: cpatch ! current patch pointer type(fates_cohort_type), pointer :: ccohort ! current cohort pointer real(r8) :: fnrt_c ! fine-root carbon [kg] @@ -249,7 +249,7 @@ subroutine PrepCH4BCs(csite,bc_in,bc_out) type(bc_out_type), intent(inout) :: bc_out type(bc_in_type), intent(in) :: bc_in - type(ed_patch_type), pointer :: cpatch ! current patch pointer + type(fates_patch_type), pointer :: cpatch ! current patch pointer type(fates_cohort_type), pointer :: ccohort ! current cohort pointer integer :: pft ! plant functional type integer :: fp ! patch index of the site @@ -419,7 +419,7 @@ subroutine PrepNutrientAquisitionBCs(csite, bc_in, bc_out) integer :: j ! soil layer index integer :: id ! decomp index (might == j) integer :: pft ! plant functional type - type(ed_patch_type), pointer :: cpatch ! current patch pointer + type(fates_patch_type), pointer :: cpatch ! current patch pointer type(fates_cohort_type), pointer :: ccohort ! current cohort pointer real(r8) :: fnrt_c ! fine-root carbon [kg] real(r8) :: veg_rootc ! fine root carbon in each layer [g/m3] @@ -532,7 +532,7 @@ subroutine EffluxIntoLitterPools(csite, cpatch, ccohort, bc_in ) ! Arguments type(ed_site_type), intent(inout) :: csite - type(ed_patch_type), intent(inout) :: cpatch + type(fates_patch_type), intent(inout) :: cpatch type(fates_cohort_type), intent(inout),target :: ccohort type(bc_in_type), intent(in) :: bc_in @@ -630,7 +630,7 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) type(bc_out_type) , intent(inout),target :: bc_out ! !LOCAL VARIABLES: - type (ed_patch_type), pointer :: currentPatch + type (fates_patch_type), pointer :: currentPatch type (fates_cohort_type), pointer :: ccohort real(r8), pointer :: flux_cel_si(:) real(r8), pointer :: flux_lab_si(:) diff --git a/biogeophys/EDAccumulateFluxesMod.F90 b/biogeophys/EDAccumulateFluxesMod.F90 index 071a1ad0a7..f32a2f0e6e 100644 --- a/biogeophys/EDAccumulateFluxesMod.F90 +++ b/biogeophys/EDAccumulateFluxesMod.F90 @@ -38,8 +38,8 @@ subroutine AccumulateFluxes_ED(nsites, sites, bc_in, bc_out, dt_time) ! ! !USES: - use EDTypesMod , only : ed_patch_type, & - ed_site_type, AREA + use EDTypesMod , only : ed_site_type, AREA + use FatesPatchMod, only : fates_patch_type use FatesCohortMod, only : fates_cohort_type use FatesInterfaceTypesMod , only : bc_in_type,bc_out_type @@ -53,7 +53,7 @@ subroutine AccumulateFluxes_ED(nsites, sites, bc_in, bc_out, dt_time) ! ! !LOCAL VARIABLES: type(fates_cohort_type), pointer :: ccohort ! current cohort - type(ed_patch_type) , pointer :: cpatch ! current patch + type(fates_patch_type) , pointer :: cpatch ! current patch integer :: iv !leaf layer integer :: c ! clm/alm column integer :: s ! ed site diff --git a/biogeophys/EDBtranMod.F90 b/biogeophys/EDBtranMod.F90 index 8063915ff3..ecdc1bb0c1 100644 --- a/biogeophys/EDBtranMod.F90 +++ b/biogeophys/EDBtranMod.F90 @@ -9,9 +9,9 @@ module EDBtranMod use FatesConstantsMod , only : tfrz => t_water_freeze_k_1atm use FatesConstantsMod , only : itrue,ifalse,nearzero use FatesConstantsMod , only : nocomp_bareground - use EDTypesMod , only : ed_site_type, & - ed_patch_type, & - maxpft + use EDTypesMod , only : ed_site_type + use FatesPatchMod, only : fates_patch_type + use FatesConstantsMod, only : maxpft use FatesCohortMod, only : fates_cohort_type use shr_kind_mod , only : r8 => shr_kind_r8 use FatesInterfaceTypesMod , only : bc_in_type, & @@ -110,7 +110,7 @@ subroutine btran_ed( nsites, sites, bc_in, bc_out) ! ! !LOCAL VARIABLES: - type(ed_patch_type),pointer :: cpatch ! Current Patch Pointer + type(fates_patch_type),pointer :: cpatch ! Current Patch Pointer type(fates_cohort_type),pointer :: ccohort ! Current cohort pointer integer :: s ! site integer :: j ! soil layer diff --git a/biogeophys/EDSurfaceAlbedoMod.F90 b/biogeophys/EDSurfaceAlbedoMod.F90 index fb800ef80b..267d130c17 100644 --- a/biogeophys/EDSurfaceAlbedoMod.F90 +++ b/biogeophys/EDSurfaceAlbedoMod.F90 @@ -10,8 +10,9 @@ module EDSurfaceRadiationMod #include "shr_assert.h" - use EDTypesMod , only : ed_patch_type, ed_site_type - use EDTypesMod , only : maxpft + use EDTypesMod , only : ed_site_type + use FatesPatchMod, only : fates_patch_type + use FatesConstantsMod, only : maxpft use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : itrue use FatesConstantsMod , only : pi_const @@ -68,7 +69,7 @@ subroutine ED_Norman_Radiation (nsites, sites, bc_in, bc_out ) ! ! !USES: - use EDtypesMod , only : ed_patch_type + use FatesPatchMod , only : fates_patch_type use EDTypesMod , only : ed_site_type @@ -84,7 +85,7 @@ subroutine ED_Norman_Radiation (nsites, sites, bc_in, bc_out ) integer :: s ! site loop counter integer :: ifp ! patch loop counter integer :: ib ! radiation broad band counter - type(ed_patch_type), pointer :: currentPatch ! patch pointer + type(fates_patch_type), pointer :: currentPatch ! patch pointer !----------------------------------------------------------------------- ! ------------------------------------------------------------------------------- @@ -196,13 +197,13 @@ subroutine PatchNormanRadiation (currentPatch, & ! ! !USES: use EDPftvarcon , only : EDPftvarcon_inst - use EDtypesMod , only : ed_patch_type + use FatesPatchMod , only : fates_patch_type ! ----------------------------------------------------------------------------------- ! !ARGUMENTS: ! ----------------------------------------------------------------------------------- - type(ed_patch_type), intent(inout), target :: currentPatch + type(fates_patch_type), intent(inout), target :: currentPatch real(r8), intent(inout) :: albd_parb_out(hlm_numSWb) real(r8), intent(inout) :: albi_parb_out(hlm_numSWb) real(r8), intent(inout) :: fabd_parb_out(hlm_numSWb) @@ -1130,7 +1131,7 @@ subroutine ED_SunShadeFracs(nsites, sites,bc_in,bc_out) ! locals - type (ed_patch_type),pointer :: cpatch ! c"urrent" patch + type (fates_patch_type),pointer :: cpatch ! c"urrent" patch real(r8) :: sunlai real(r8) :: shalai real(r8) :: elai diff --git a/biogeophys/FatesBstressMod.F90 b/biogeophys/FatesBstressMod.F90 index 9beb3d5cd9..825a886011 100644 --- a/biogeophys/FatesBstressMod.F90 +++ b/biogeophys/FatesBstressMod.F90 @@ -7,9 +7,9 @@ module FatesBstressMod ! use FatesConstantsMod , only : tfrz => t_water_freeze_k_1atm use FatesConstantsMod , only : itrue,ifalse - use EDTypesMod , only : ed_site_type, & - ed_patch_type, & - maxpft + use FatesConstantsMod, only : maxpft + use EDTypesMod , only : ed_site_type + use FatesPatchMod, only : fates_patch_type use FatesCohortMod , only : fates_cohort_type use shr_kind_mod , only : r8 => shr_kind_r8 use FatesInterfaceTypesMod , only : bc_in_type, & @@ -48,7 +48,7 @@ subroutine btran_sal_stress_fates( nsites, sites, bc_in) ! ! !LOCAL VARIABLES: - type(ed_patch_type),pointer :: cpatch ! Current Patch Pointer + type(fates_patch_type),pointer :: cpatch ! Current Patch Pointer type(fates_cohort_type),pointer :: ccohort ! Current cohort pointer integer :: s ! site integer :: j ! soil layer diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index c008ae2f39..4b52cea541 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -52,7 +52,7 @@ module FatesPlantHydraulicsMod use EDParamsMod , only : hydr_solver use EDTypesMod , only : ed_site_type - use EDTypesMod , only : ed_patch_type + use FatesPatchMod , only : fates_patch_type use FatesCohortMod , only : fates_cohort_type use EDTypesMod , only : AREA_INV use EDTypesMod , only : AREA @@ -336,8 +336,8 @@ subroutine RestartHydrStates(sites,nsites,bc_in,bc_out) ! locals ! ---------------------------------------------------------------------------------- ! LL pointers - type(ed_patch_type),pointer :: cpatch ! current patch - type(fates_cohort_type),pointer :: ccohort ! current cohort + type(fates_patch_type),pointer :: cpatch ! current patch + type(fates_cohort_type),pointer :: ccohort ! current cohort type(ed_cohort_hydr_type),pointer :: ccohort_hydr type(ed_site_hydr_type),pointer :: csite_hydr integer :: s ! site loop counter @@ -1777,7 +1777,7 @@ subroutine UpdateH2OVeg(csite,bc_out,prev_site_h2o,icall) ! Locals type(fates_cohort_type), pointer :: currentCohort - type(ed_patch_type), pointer :: currentPatch + type(fates_patch_type), pointer :: currentPatch type(ed_cohort_hydr_type), pointer :: ccohort_hydr type(ed_site_hydr_type), pointer :: csite_hydr integer :: s @@ -1860,7 +1860,7 @@ subroutine RecruitWUptake(nsites,sites,bc_in,dtime,recruitflag) ! Locals type(fates_cohort_type), pointer :: currentCohort - type(ed_patch_type), pointer :: currentPatch + type(fates_patch_type), pointer :: currentPatch type(ed_cohort_hydr_type), pointer :: ccohort_hydr type(ed_site_hydr_type), pointer :: csite_hydr integer :: s, j, ft @@ -1935,7 +1935,7 @@ subroutine ConstrainRecruitNumber(csite,ccohort, cpatch, bc_in, mean_temp) ! Arguments type(ed_site_type), intent(inout), target :: csite type(fates_cohort_type) , intent(inout), target :: ccohort - type(ed_patch_type), intent(inout), target :: cpatch + type(fates_patch_type), intent(inout), target :: cpatch type(bc_in_type) , intent(in) :: bc_in real(r8), intent(in) :: mean_temp @@ -2060,7 +2060,7 @@ subroutine UpdateSizeDepRhizVolLenCon(currentSite, bc_in) ! ! !LOCAL VARIABLES: type(ed_site_hydr_type), pointer :: csite_hydr - type(ed_patch_type) , pointer :: cPatch + type(fates_patch_type) , pointer :: cPatch type(fates_cohort_type) , pointer :: cCohort type(ed_cohort_hydr_type), pointer :: ccohort_hydr real(r8) :: hksat_s ! hksat converted to units of 10^6sec @@ -2197,7 +2197,7 @@ subroutine BTranForHLMDiagnosticsFromCohortHydr(nsites,sites,bc_out) integer :: s integer :: ifp real(r8) :: balive_patch - type(ed_patch_type),pointer :: cpatch + type(fates_patch_type),pointer :: cpatch type(fates_cohort_type),pointer :: ccohort do s = 1,nsites @@ -2427,7 +2427,7 @@ subroutine hydraulics_bc ( nsites, sites, bc_in, bc_out, dtime) !---------------------------------------------------------------------- - type (ed_patch_type), pointer :: cpatch ! current patch pointer + type (fates_patch_type), pointer :: cpatch ! current patch pointer type (fates_cohort_type), pointer :: ccohort ! current cohort pointer type(ed_site_hydr_type), pointer :: csite_hydr ! site hydraulics pointer type(ed_cohort_hydr_type), pointer :: ccohort_hydr ! cohort hydraulics pointer @@ -4346,7 +4346,7 @@ subroutine RecruitWaterStorage(nsites,sites,bc_out) ! Locals type(fates_cohort_type), pointer :: currentCohort - type(ed_patch_type), pointer :: currentPatch + type(fates_patch_type), pointer :: currentPatch type(ed_cohort_hydr_type), pointer :: ccohort_hydr type(ed_site_hydr_type), pointer :: csite_hydr integer :: s diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 7f27bc6107..09814b0c0a 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -38,13 +38,13 @@ module FATESPlantRespPhotosynthMod use FatesInterfaceTypesMod, only : hlm_parteh_mode use FatesInterfaceTypesMod, only : numpft use FatesInterfaceTypesMod, only : nleafage - use EDTypesMod, only : maxpft + use FatesConstantsMod, only : maxpft use EDParamsMod, only : nlevleaf use EDParamsMod, only : nclmax use PRTGenericMod, only : max_nleafage use EDTypesMod, only : do_fates_salinity use EDParamsMod, only : q10_mr - use EDTypesMod, only : ed_patch_type + use FatesPatchMod, only : fates_patch_type use FatesCohortMod, only : fates_cohort_type use EDParamsMod, only : maintresp_leaf_model use FatesConstantsMod, only : lmrmodel_ryan_1991 @@ -127,7 +127,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! !USES: use EDTypesMod , only : ed_site_type - use EDTypesMod , only : maxpft + use FatesConstantsMod , only : maxpft use EDParamsMod , only : dinc_vai use EDParamsMod , only : dlower_vai use FatesInterfaceTypesMod , only : bc_in_type @@ -158,7 +158,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! LOCAL VARIABLES: ! ----------------------------------------------------------------------------------- - type (ed_patch_type) , pointer :: currentPatch + type (fates_patch_type) , pointer :: currentPatch type (fates_cohort_type), pointer :: currentCohort ! ----------------------------------------------------------------------------------- @@ -1890,7 +1890,7 @@ subroutine UpdateCanopyNCanNRadPresent(currentPatch) ! --------------------------------------------------------------------------------- ! Arguments - type(ed_patch_type), target :: currentPatch + type(fates_patch_type), target :: currentPatch type(fates_cohort_type), pointer :: currentCohort ! Locals diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index aa8716bf90..797ca859b8 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -24,7 +24,7 @@ module SFMainMod use PRTGenericMod , only : element_pos use EDtypesMod , only : ed_site_type - use EDtypesMod , only : ed_patch_type + use FatesPatchMod , only : fates_patch_type use FatesCohortMod , only : fates_cohort_type use EDtypesMod , only : AREA use FatesLitterMod , only : DL_SF @@ -85,7 +85,7 @@ subroutine fire_model( currentSite, bc_in) type(bc_in_type) , intent(in) :: bc_in - type (ed_patch_type), pointer :: currentPatch + type (fates_patch_type), pointer :: currentPatch !zero fire things currentPatch => currentSite%youngest_patch @@ -127,7 +127,7 @@ subroutine fire_danger_index ( currentSite, bc_in) type(ed_site_type) , intent(inout), target :: currentSite type(bc_in_type) , intent(in) :: bc_in - type(ed_patch_type), pointer :: currentPatch + type(fates_patch_type), pointer :: currentPatch real(r8) :: temp_in_C ! daily averaged temperature in celcius real(r8) :: rainfall ! daily precip in mm/day @@ -181,7 +181,7 @@ subroutine charecteristics_of_fuel ( currentSite ) type(ed_site_type), intent(in), target :: currentSite - type(ed_patch_type), pointer :: currentPatch + type(fates_patch_type), pointer :: currentPatch type(fates_cohort_type), pointer :: currentCohort type(litter_type), pointer :: litt_c @@ -357,7 +357,7 @@ subroutine wind_effect ( currentSite, bc_in) type(ed_site_type) , intent(inout), target :: currentSite type(bc_in_type) , intent(in) :: bc_in - type(ed_patch_type) , pointer :: currentPatch + type(fates_patch_type) , pointer :: currentPatch type(fates_cohort_type), pointer :: currentCohort real(r8) :: total_grass_area ! per patch,in m2 @@ -458,7 +458,7 @@ subroutine rate_of_spread ( currentSite ) type(ed_site_type), intent(in), target :: currentSite - type(ed_patch_type), pointer :: currentPatch + type(fates_patch_type), pointer :: currentPatch ! Rothermal fire spread model parameters. real(r8) beta,beta_op ! weighted average of packing ratio (unitless) @@ -601,7 +601,7 @@ subroutine ground_fuel_consumption ( currentSite ) SF_val_mid_moisture_Coeff, SF_val_mid_moisture_Slope type(ed_site_type) , intent(in), target :: currentSite - type(ed_patch_type), pointer :: currentPatch + type(fates_patch_type), pointer :: currentPatch type(litter_type), pointer :: litt_c ! carbon 12 litter pool real(r8) :: moist !effective fuel moisture @@ -703,7 +703,7 @@ subroutine area_burnt_intensity ( currentSite, bc_in ) SF_val_max_durat, SF_val_durat_slope, SF_val_fire_threshold type(ed_site_type), intent(inout), target :: currentSite - type(ed_patch_type), pointer :: currentPatch + type(fates_patch_type), pointer :: currentPatch type(bc_in_type), intent(in) :: bc_in real(r8) ROS !m/s @@ -895,7 +895,7 @@ subroutine crown_scorching ( currentSite ) type(ed_site_type), intent(in), target :: currentSite - type(ed_patch_type), pointer :: currentPatch + type(fates_patch_type), pointer :: currentPatch type(fates_cohort_type), pointer :: currentCohort real(r8) :: tree_ag_biomass ! total amount of above-ground tree biomass in patch. kgC/m2 @@ -959,7 +959,7 @@ subroutine crown_damage ( currentSite ) type(ed_site_type), intent(in), target :: currentSite - type(ed_patch_type) , pointer :: currentPatch + type(fates_patch_type) , pointer :: currentPatch type(fates_cohort_type), pointer :: currentCohort real(r8) :: crown_depth ! Depth of crown in meters @@ -1026,7 +1026,7 @@ subroutine cambial_damage_kill ( currentSite ) type(ed_site_type), intent(in), target :: currentSite - type(ed_patch_type) , pointer :: currentPatch + type(fates_patch_type) , pointer :: currentPatch type(fates_cohort_type), pointer :: currentCohort real(r8) :: tau_c !critical time taken to kill cambium (minutes) @@ -1082,7 +1082,7 @@ subroutine post_fire_mortality ( currentSite ) type(ed_site_type), intent(in), target :: currentSite - type(ed_patch_type), pointer :: currentPatch + type(fates_patch_type), pointer :: currentPatch type(fates_cohort_type), pointer :: currentCohort currentPatch => currentSite%oldest_patch diff --git a/main/ChecksBalancesMod.F90 b/main/ChecksBalancesMod.F90 index 3d200a6f99..aa81b4fbae 100644 --- a/main/ChecksBalancesMod.F90 +++ b/main/ChecksBalancesMod.F90 @@ -3,7 +3,7 @@ module ChecksBalancesMod use shr_kind_mod, only : r8 => shr_kind_r8 use shr_const_mod, only : SHR_CONST_CDAY use EDtypesMod, only : ed_site_type - use EDTypesMod, only : ed_patch_type + use FatesPatchMod, only : fates_patch_type use FatesCohortMod, only : fates_cohort_type use EDTypesMod, only : AREA use EDTypesMod, only : site_massbal_type @@ -48,7 +48,7 @@ subroutine SiteMassStock(currentSite,el,total_stock,biomass_stock,litter_stock,s real(r8),intent(out) :: litter_stock ! kg real(r8),intent(out) :: biomass_stock ! kg real(r8),intent(out) :: seed_stock ! kg - type(ed_patch_type), pointer :: currentPatch + type(fates_patch_type), pointer :: currentPatch type(fates_cohort_type), pointer :: currentCohort real(r8) :: patch_biomass ! kg real(r8) :: patch_seed ! kg @@ -81,7 +81,7 @@ subroutine PatchMassStock(currentPatch,el,live_stock,seed_stock,litter_stock) ! --------------------------------------------------------------------------------- ! Sum up the mass of the different stocks on a patch for each element ! --------------------------------------------------------------------------------- - type(ed_patch_type),intent(inout),target :: currentPatch + type(fates_patch_type),intent(inout),target :: currentPatch integer,intent(in) :: el real(r8),intent(out) :: live_stock real(r8),intent(out) :: seed_stock @@ -146,7 +146,7 @@ subroutine CheckLitterPools(currentSite,bc_in) type(bc_in_type), intent(in) :: bc_in ! Local variables - type(ed_patch_type), pointer :: currentPatch + type(fates_patch_type), pointer :: currentPatch type(litter_type), pointer :: litt ! Litter object integer :: el ! Litter element loop index integer :: element_id ! parteh consistent litter index diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 18fa974c88..e9c6ea06d1 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -23,11 +23,11 @@ module EDInitMod use EDPhysiologyMod , only : assign_cohort_sp_properties use ChecksBalancesMod , only : SiteMassStock use FatesInterfaceTypesMod , only : hlm_day_of_year - use EDTypesMod , only : ed_site_type, ed_patch_type + use EDTypesMod , only : ed_site_type + use FatesPatchMod , only : fates_patch_type use FatesCohortMod , only : fates_cohort_type use EDTypesMod , only : numWaterMem use EDTypesMod , only : num_vegtemp_mem - use EDTypesMod , only : maxpft use EDTypesMod , only : AREA use EDTypesMod , only : init_spread_near_bare_ground use EDTypesMod , only : init_spread_inventory @@ -525,9 +525,9 @@ subroutine init_patches( nsites, sites, bc_in) integer :: is_first_patch type(ed_site_type), pointer :: sitep - type(ed_patch_type), pointer :: newppft(:) - type(ed_patch_type), pointer :: newp - type(ed_patch_type), pointer :: currentPatch + type(fates_patch_type), pointer :: newppft(:) + type(fates_patch_type), pointer :: newp + type(fates_patch_type), pointer :: currentPatch ! List out some nominal patch values that are used for Near Bear Ground initializations ! as well as initializing inventory @@ -744,7 +744,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) ! ! !ARGUMENTS type(ed_site_type), intent(inout), pointer :: site_in - type(ed_patch_type), intent(inout), pointer :: patch_in + type(fates_patch_type), intent(inout), pointer :: patch_in type(bc_in_type), intent(in) :: bc_in ! ! !LOCAL VARIABLES: diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 386f788db8..d5b2dcc687 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -64,7 +64,7 @@ module EDMainMod use FatesLitterMod , only : litter_type use FatesLitterMod , only : ncwd use EDtypesMod , only : ed_site_type - use EDtypesMod , only : ed_patch_type + use FatesPatchMod , only : fates_patch_type use FatesCohortMod , only : fates_cohort_type use EDTypesMod , only : AREA use EDTypesMod , only : site_massbal_type @@ -149,7 +149,7 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) type(bc_out_type) , intent(inout) :: bc_out ! ! !LOCAL VARIABLES: - type(ed_patch_type), pointer :: currentPatch + type(fates_patch_type), pointer :: currentPatch integer :: el ! Loop counter for variables integer :: do_patch_dynamics ! for some modes, we turn off patch dynamics @@ -343,7 +343,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! ! !LOCAL VARIABLES: type(site_massbal_type), pointer :: site_cmass - type(ed_patch_type) , pointer :: currentPatch + type(fates_patch_type) , pointer :: currentPatch type(fates_cohort_type) , pointer :: currentCohort type(fates_cohort_type) , pointer :: nc type(fates_cohort_type) , pointer :: storesmallcohort @@ -780,7 +780,7 @@ subroutine ed_update_site( currentSite, bc_in, bc_out ) type(bc_out_type) , intent(inout) :: bc_out ! ! !LOCAL VARIABLES: - type (ed_patch_type) , pointer :: currentPatch + type (fates_patch_type) , pointer :: currentPatch !----------------------------------------------------------------------- if(hlm_use_sp.eq.ifalse)then call canopy_spread(currentSite) @@ -879,7 +879,7 @@ subroutine TotalBalanceCheck (currentSite, call_index ) ! Also, the carbon pools are per site/gridcell, so that ! we can account for the changing areas of patches. - type(ed_patch_type) , pointer :: currentPatch + type(fates_patch_type) , pointer :: currentPatch type(fates_cohort_type) , pointer :: currentCohort type(litter_type), pointer :: litt logical, parameter :: print_cohorts = .true. ! Set to true if you want @@ -1034,7 +1034,7 @@ subroutine bypass_dynamics(currentSite) type(ed_site_type) , intent(inout), target :: currentSite ! Locals - type(ed_patch_type), pointer :: currentPatch + type(fates_patch_type), pointer :: currentPatch type(fates_cohort_type), pointer :: currentCohort currentPatch => currentSite%youngest_patch diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 9db76ff895..2394944368 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -27,18 +27,16 @@ module EDTypesMod use FatesInterfaceTypesMod,only : bc_out_type use FatesInterfaceTypesMod,only : hlm_parteh_mode use FatesCohortMod, only : fates_cohort_type + use FatesPatchMod, only : fates_patch_type use EDParamsMod, only : maxSWb, nclmax, nlevleaf + use FatesConstantsMod, only : maxpft + use FatesConstantsMod, only : n_dbh_bins, n_dist_types use shr_log_mod, only : errMsg => shr_log_errMsg implicit none private ! By default everything is private save - - integer, parameter, public :: maxpft = 16 ! maximum number of PFTs allowed - ! the parameter file may determine that fewer - ! are used, but this helps allocate scratch - ! space and output arrays. - + real(r8), parameter, public :: init_recruit_trim = 0.8_r8 ! This is the initial trimming value that ! new recruits start with @@ -87,7 +85,6 @@ module EDTypesMod ! BIOLOGY/BIOGEOCHEMISTRY integer , parameter, public :: num_vegtemp_mem = 10 ! Window of time over which we track temp for cold sensecence (days) - integer , parameter, public :: N_DIST_TYPES = 3 ! Disturbance Modes 1) tree-fall, 2) fire, 3) logging integer , parameter, public :: dtype_ifall = 1 ! index for naturally occuring tree-fall generated event integer , parameter, public :: dtype_ifire = 2 ! index for fire generated disturbance event integer , parameter, public :: dtype_ilog = 3 ! index for logging generated disturbance event @@ -106,7 +103,6 @@ module EDTypesMod ! PATCH FUSION real(r8), parameter, public :: force_patchfuse_min_biomass = 0.005_r8 ! min biomass (kg / m2 patch area) below which to force-fuse patches - integer , parameter, public :: N_DBH_BINS = 6 ! no. of dbh bins used when comparing patches real(r8), parameter, public :: patchfusion_dbhbin_loweredges(N_DBH_BINS) = & (/0._r8, 5._r8, 20._r8, 50._r8, 100._r8, 150._r8/) ! array of bin lower edges for comparing patches real(r8), parameter, public :: patch_fusion_tolerance_relaxation_increment = 1.1_r8 ! amount by which to increment patch fusion threshold @@ -133,205 +129,6 @@ module EDTypesMod logical, parameter, public :: homogenize_seed_pfts = .false. character(len=*), parameter, private :: sourcefile = __FILE__ - !************************************ - !** Patch type structure ** - !************************************ - - type, public :: ed_patch_type - - ! POINTERS - type (fates_cohort_type), pointer :: tallest => null() ! pointer to patch's tallest cohort - type (fates_cohort_type), pointer :: shortest => null() ! pointer to patch's shortest cohort - type (ed_patch_type), pointer :: older => null() ! pointer to next older patch - type (ed_patch_type), pointer :: younger => null() ! pointer to next younger patch - - !INDICES - integer :: patchno ! unique number given to each new patch created for tracking - - ! PATCH INFO - real(r8) :: age ! average patch age: years - integer :: age_class ! age class of the patch for history binning purposes - real(r8) :: area ! patch area: m2 - integer :: countcohorts ! Number of cohorts in patch - integer :: ncl_p ! Number of occupied canopy layers - integer :: anthro_disturbance_label ! patch label for anthropogenic disturbance classification - real(r8) :: age_since_anthro_disturbance ! average age for secondary forest since last anthropogenic disturbance - - - ! Running means - !class(rmean_type), pointer :: t2m ! Place-holder for 2m air temperature (variable window-size) - class(rmean_type), pointer :: tveg24 ! 24-hour mean vegetation temperature (K) - class(rmean_type), pointer :: tveg_lpa ! Running mean of vegetation temperature at the - ! leaf photosynthesis acclimation timescale [K] - class(rmean_type), pointer :: tveg_longterm ! Long-Term Running mean of vegetation temperature at the - ! leaf photosynthesis acclimation timescale [K] (i.e T_home) - - integer :: nocomp_pft_label ! Where nocomp is active, use this label for patch ID. - ! Each patch ID corresponds to a pft number since each - ! patch has only one pft. Bareground patches are given - ! a zero integer as a label. - ! If nocomp is not active this is set to unset. - ! This is set in create_patch as an argument - ! to that procedure. - - - ! LEAF ORGANIZATION - real(r8) :: pft_agb_profile(maxpft,n_dbh_bins) ! binned above ground biomass, for patch fusion: KgC/m2 - real(r8) :: canopy_layer_tlai(nclmax) ! total leaf area index of each canopy layer - ! used to determine attenuation of parameters during - ! photosynthesis m2 veg / m2 of canopy area (patch without bare ground) - real(r8) :: total_canopy_area ! area that is covered by vegetation : m2 - real(r8) :: total_tree_area ! area that is covered by woody vegetation : m2 - real(r8) :: zstar ! height of smallest canopy tree -- only meaningful in "strict PPA" mode - - real(r8) :: c_stomata ! Mean stomatal conductance of all leaves in the patch [umol/m2/s] - real(r8) :: c_lblayer ! Mean boundary layer conductance of all leaves in the patch [umol/m2/s] - - ! UNITS for the ai profiles - ! [ m2 leaf / m2 contributing crown footprints] - real(r8) :: tlai_profile(nclmax,maxpft,nlevleaf) ! total leaf area in each canopy layer, pft, and leaf layer. - real(r8) :: elai_profile(nclmax,maxpft,nlevleaf) ! exposed leaf area in each canopy layer, pft, and leaf layer - real(r8) :: tsai_profile(nclmax,maxpft,nlevleaf) ! total stem area in each canopy layer, pft, and leaf layer - real(r8) :: esai_profile(nclmax,maxpft,nlevleaf) ! exposed stem area in each canopy layer, pft, and leaf layer - real(r8) :: radiation_error ! radiation error (w/m2) - real(r8) :: layer_height_profile(nclmax,maxpft,nlevleaf) - real(r8) :: canopy_area_profile(nclmax,maxpft,nlevleaf) ! fraction of crown area per canopy area in each layer - ! they will sum to 1.0 in the fully closed canopy layers - ! but only in leaf-layers that contain contributions - ! from all cohorts that donate to canopy_area - - - ! layer, pft, and leaf layer:- - integer :: canopy_mask(nclmax,maxpft) ! is there any of this pft in this canopy layer? - integer :: nrad(nclmax,maxpft) ! number of exposed leaf layers for each canopy layer and pft - integer :: ncan(nclmax,maxpft) ! number of total leaf layers for each canopy layer and pft - - !RADIATION FLUXES - real(r8) :: fcansno ! Fraction of canopy covered in snow - - logical :: solar_zenith_flag ! integer flag specifying daylight (based on zenith angle) - real(r8) :: solar_zenith_angle ! solar zenith angle (radians) - - real(r8) :: gnd_alb_dif(maxSWb) ! ground albedo for diffuse rad, both bands (fraction) - real(r8) :: gnd_alb_dir(maxSWb) ! ground albedo for direct rad, both bands (fraction) - - real(r8) :: fabd_sun_z(nclmax,maxpft,nlevleaf) ! sun fraction of direct light absorbed by each canopy - ! layer, pft, and leaf layer:- - real(r8) :: fabd_sha_z(nclmax,maxpft,nlevleaf) ! shade fraction of direct light absorbed by each canopy - ! layer, pft, and leaf layer:- - real(r8) :: fabi_sun_z(nclmax,maxpft,nlevleaf) ! sun fraction of indirect light absorbed by each canopy - ! layer, pft, and leaf layer:- - real(r8) :: fabi_sha_z(nclmax,maxpft,nlevleaf) ! shade fraction of indirect light absorbed by each canopy - ! layer, pft, and leaf layer:- - - real(r8) :: ed_laisun_z(nclmax,maxpft,nlevleaf) ! amount of LAI in the sun in each canopy layer, - ! pft, and leaf layer. m2/m2 - real(r8) :: ed_laisha_z(nclmax,maxpft,nlevleaf) ! amount of LAI in the shade in each canopy layer, - real(r8) :: ed_parsun_z(nclmax,maxpft,nlevleaf) ! PAR absorbed in the sun in each canopy layer, - real(r8) :: ed_parsha_z(nclmax,maxpft,nlevleaf) ! PAR absorbed in the shade in each canopy layer, - real(r8) :: f_sun(nclmax,maxpft,nlevleaf) ! fraction of leaves in the sun in each canopy layer, pft, - - ! radiation profiles for comparison against observations - - ! normalized direct photosynthetically active radiation profiles by - ! incident type (direct/diffuse at top of canopy),leaf,pft,leaf (unitless) - real(r8) :: nrmlzd_parprof_pft_dir_z(n_rad_stream_types,nclmax,maxpft,nlevleaf) - - ! normalized diffuse photosynthetically active radiation profiles by - ! incident type (direct/diffuse at top of canopy),leaf,pft,leaf (unitless) - real(r8) :: nrmlzd_parprof_pft_dif_z(n_rad_stream_types,nclmax,maxpft,nlevleaf) - - ! normalized direct photosynthetically active radiation profiles by - ! incident type (direct/diffuse at top of canopy),leaf,leaf (unitless) - real(r8) :: nrmlzd_parprof_dir_z(n_rad_stream_types,nclmax,nlevleaf) - - ! normalized diffuse photosynthetically active radiation profiles by - ! incident type (direct/diffuse at top of canopy),leaf,leaf (unitless) - real(r8) :: nrmlzd_parprof_dif_z(n_rad_stream_types,nclmax,nlevleaf) - - real(r8) :: parprof_pft_dir_z(nclmax,maxpft,nlevleaf) ! direct-beam PAR profile through canopy, by canopy,PFT,leaf level (w/m2) - real(r8) :: parprof_pft_dif_z(nclmax,maxpft,nlevleaf) ! diffuse PAR profile through canopy, by canopy,PFT,leaf level (w/m2) - real(r8) :: parprof_dir_z(nclmax,nlevleaf) ! direct-beam PAR profile through canopy, by canopy,leaf level (w/m2) - real(r8) :: parprof_dif_z(nclmax,nlevleaf) ! diffuse PAR profile through canopy, by canopy,leaf level (w/m2) - - ! and leaf layer. m2/m2 - real(r8),allocatable :: tr_soil_dir(:) ! fraction of incoming direct radiation that (cm_numSWb) - ! is transmitted to the soil as direct - real(r8),allocatable :: tr_soil_dif(:) ! fraction of incoming diffuse radiation that - ! is transmitted to the soil as diffuse - real(r8),allocatable :: tr_soil_dir_dif(:) ! fraction of incoming direct radiation that - ! is transmitted to the soil as diffuse - real(r8),allocatable :: fab(:) ! fraction of incoming total radiation that is absorbed by the canopy - real(r8),allocatable :: fabd(:) ! fraction of incoming direct radiation that is absorbed by the canopy - real(r8),allocatable :: fabi(:) ! fraction of incoming diffuse radiation that is absorbed by the canopy - real(r8),allocatable :: sabs_dir(:) ! fraction of incoming direct radiation that is absorbed by the canopy - real(r8),allocatable :: sabs_dif(:) ! fraction of incoming diffuse radiation that is absorbed by the canopy - - - ! PHOTOSYNTHESIS - - real(r8) :: psn_z(nclmax,maxpft,nlevleaf) ! carbon assimilation in each canopy layer, pft, and leaf layer. umolC/m2/s - - ! ROOTS - real(r8) :: btran_ft(maxpft) ! btran calculated seperately for each PFT:- - real(r8) :: bstress_sal_ft(maxpft) ! bstress from salinity calculated seperately for each PFT:- - - - ! These two variables are only used for external seed rain currently. - real(r8) :: nitr_repro_stoich(maxpft) ! The NC ratio of a new recruit in this patch - real(r8) :: phos_repro_stoich(maxpft) ! The PC ratio of a new recruit in this patch - - - ! DISTURBANCE - real(r8) :: disturbance_rates(n_dist_types) ! disturbance rate from 1) mortality - ! 2) fire: fraction/day - ! 3) logging mortatliy - real(r8) :: fract_ldist_not_harvested ! fraction of logged area that is canopy trees that weren't harvested - - - ! Litter and Coarse Woody Debris - - type(litter_type), pointer :: litter(:) ! Litter (leaf,fnrt,CWD and seeds) for different elements - - real(r8),allocatable :: fragmentation_scaler(:) ! Scale rate of litter fragmentation based on soil layer. 0 to 1. - - !FUEL CHARECTERISTICS - real(r8) :: sum_fuel ! total ground fuel related to ros (omits 1000hr fuels): KgC/m2 - real(r8) :: fuel_frac(nfsc) ! fraction of each litter class in the ros_fuel:-. - real(r8) :: livegrass ! total aboveground grass biomass in patch. KgC/m2 - real(r8) :: fuel_bulkd ! average fuel bulk density of the ground fuel. kgBiomass/m3 - ! (incl. live grasses. omits 1000hr fuels). KgC/m3 - real(r8) :: fuel_sav ! average surface area to volume ratio of the ground fuel. cm-1 - ! (incl. live grasses. omits 1000hr fuels). - real(r8) :: fuel_mef ! average moisture of extinction factor - ! of the ground fuel (incl. live grasses. omits 1000hr fuels). - real(r8) :: fuel_eff_moist ! effective avearage fuel moisture content of the ground fuel - ! (incl. live grasses. omits 1000hr fuels) - real(r8) :: litter_moisture(nfsc) - - ! FIRE SPREAD - real(r8) :: ros_front ! rate of forward spread of fire: m/min - real(r8) :: ros_back ! rate of backward spread of fire: m/min - real(r8) :: effect_wspeed ! windspeed modified by fraction of relative grass and tree cover: m/min - real(r8) :: tau_l ! Duration of lethal heating: mins - real(r8) :: fi ! average fire intensity of flaming front: kj/m/s or kw/m - integer :: fire ! Is there a fire? 1=yes 0=no - real(r8) :: fd ! fire duration: mins - - ! FIRE EFFECTS - real(r8) :: scorch_ht(maxpft) ! scorch height: m - real(r8) :: frac_burnt ! fraction burnt: frac patch/day - real(r8) :: tfc_ros ! total intensity-relevant fuel consumed - no trunks. KgC/m2 of burned ground/day - real(r8) :: burnt_frac_litter(nfsc) ! fraction of each litter pool burned, conditional on it being burned - - - ! PLANT HYDRAULICS (not currently used in hydraulics RGK 03-2018) - ! type(ed_patch_hydr_type) , pointer :: pa_hydr ! All patch hydraulics data, see FatesHydraulicsMemMod.F90 - - - end type ed_patch_type - - !************************************ !** Resources management type ** ! YX @@ -436,8 +233,8 @@ module EDTypesMod type, public :: ed_site_type ! POINTERS - type (ed_patch_type), pointer :: oldest_patch => null() ! pointer to oldest patch at the site - type (ed_patch_type), pointer :: youngest_patch => null() ! pointer to yngest patch at the site + type (fates_patch_type), pointer :: oldest_patch => null() ! pointer to oldest patch at the site + type (fates_patch_type), pointer :: youngest_patch => null() ! pointer to yngest patch at the site ! Resource management type (ed_resources_management_type) :: resources_management ! resources_management at the site @@ -691,7 +488,7 @@ subroutine val_check_ed_vars(currentPatch,var_aliases,return_code) use FatesUtilsMod,only : check_var_real ! Arguments - type(ed_patch_type),intent(in), target :: currentPatch + type(fates_patch_type),intent(in), target :: currentPatch character(len=*),intent(in) :: var_aliases integer,intent(out) :: return_code ! return 0 for all fine ! return 1 if a nan detected @@ -769,7 +566,7 @@ end subroutine dump_site subroutine dump_patch(cpatch) - type(ed_patch_type),intent(in),target :: cpatch + type(fates_patch_type),intent(in),target :: cpatch ! locals integer :: el ! element loop counting index @@ -812,6 +609,4 @@ end subroutine dump_patch ! ===================================================================================== - - end module EDTypesMod diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index a6bc033027..925e29d967 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -30,6 +30,18 @@ module FatesConstantsMod ! Integer equivalent of false (in case come compilers dont auto convert) integer, parameter, public :: ifalse = 0 + integer , parameter, public :: N_DBH_BINS = 6 ! no. of dbh bins used when comparing patches + + integer, parameter, public :: maxpft = 16 ! maximum number of PFTs allowed + ! the parameter file may determine that fewer + ! are used, but this helps allocate scratch + ! space and output arrays. + + integer, parameter, public :: n_rad_stream_types = 2 ! The number of radiation streams used (direct/diffuse) + + + integer , parameter, public :: N_DIST_TYPES = 3 ! Disturbance Modes 1) tree-fall, 2) fire, 3) logging + ! Labels for patch disturbance history integer, parameter, public :: n_anthro_disturbance_categories = 2 integer, parameter, public :: primaryforest = 1 diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 77af891d91..9f7f9dd9e7 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -20,14 +20,14 @@ module FatesHistoryInterfaceMod use EDTypesMod , only : site_fluxdiags_type use EDtypesMod , only : ed_site_type use FatesCohortMod , only : fates_cohort_type - use EDtypesMod , only : ed_patch_type + use FatesPatchMod , only : fates_patch_type use EDtypesMod , only : AREA use EDtypesMod , only : AREA_INV use EDTypesMod , only : numWaterMem use EDTypesMod , only : num_vegtemp_mem use EDTypesMod , only : site_massbal_type use PRTGenericMod , only : element_list - use EDTypesMod , only : N_DIST_TYPES + use FatesConstantsMod , only : N_DIST_TYPES, maxpft use EDTypesMod , only : dtype_ifall use EDTypesMod , only : dtype_ifire use EDTypesMod , only : dtype_ilog @@ -1918,7 +1918,7 @@ subroutine update_history_nutrflux(this,csite) class(fates_history_interface_type) :: this type(ed_site_type), intent(in) :: csite - type(ed_patch_type), pointer :: cpatch + type(fates_patch_type), pointer :: cpatch type(fates_cohort_type), pointer :: ccohort integer :: iclscpf ! layer x size x pft class index integer :: iscpf ! Size x pft class index @@ -2204,7 +2204,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) integer :: return_code - type(ed_patch_type),pointer :: cpatch + type(fates_patch_type),pointer :: cpatch type(fates_cohort_type),pointer :: ccohort real(r8), parameter :: reallytalltrees = 1000. ! some large number (m) @@ -4365,7 +4365,7 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) real(r8) :: site_area_veg ! area of the site that is not bare-ground integer :: ipa2 ! patch incrementer integer :: cnlfpft_indx, cnlf_indx, ipft, ican, ileaf ! more iterators and indices - type(ed_patch_type),pointer :: cpatch + type(fates_patch_type),pointer :: cpatch type(fates_cohort_type),pointer :: ccohort real(r8) :: per_dt_tstep ! Time step in frequency units (/s) @@ -4812,8 +4812,6 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) use FatesHydraulicsMemMod, only : ed_cohort_hydr_type, nshell use FatesHydraulicsMemMod, only : ed_site_hydr_type - use EDTypesMod , only : maxpft - ! Arguments class(fates_history_interface_type) :: this @@ -4857,7 +4855,7 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) real(r8) :: psi ! matric potential of soil layer real(r8) :: depth_frac ! fraction of rhizosphere layer depth occupied by current soil layer character(2) :: fmt_char - type(ed_patch_type),pointer :: cpatch + type(fates_patch_type),pointer :: cpatch type(fates_cohort_type),pointer :: ccohort type(ed_cohort_hydr_type), pointer :: ccohort_hydr type(ed_site_hydr_type), pointer :: site_hydr diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 00d46563ab..41ae7798d0 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -24,12 +24,12 @@ module FatesInterfaceMod use EDParamsMod , only : inir use EDParamsMod , only : nclmax use EDParamsMod , only : nlevleaf - use EDTypesMod , only : maxpft + use FatesConstantsMod , only : maxpft use EDTypesMod , only : do_fates_salinity use EDTypesMod , only : numWaterMem use EDTypesMod , only : numlevsoil_max use EDTypesMod , only : ed_site_type - use EDTypesMod , only : ed_patch_type + use FatesPatchMod , only : fates_patch_type use FatesCohortMod , only : fates_cohort_type use EDTypesMod , only : area_inv use FatesConstantsMod , only : r8 => fates_r8 @@ -1942,7 +1942,7 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) type(ed_site_type), intent(inout) :: sites(:) type(bc_in_type), intent(in) :: bc_in(:) - type(ed_patch_type), pointer :: cpatch + type(fates_patch_type), pointer :: cpatch type(fates_cohort_type), pointer :: ccohort integer :: s, ifp, io_si diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index f62bccdff7..55b8ed3ed6 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -33,7 +33,7 @@ module FatesInventoryInitMod use FatesInterfaceTypesMod, only : nleafage use FatesLitterMod , only : litter_type use EDTypesMod , only : ed_site_type - use EDTypesMod , only : ed_patch_type + use FatesPatchMod , only : fates_patch_type use FatesCohortMod , only : fates_cohort_type use EDTypesMod , only : area use FatesConstantsMod, only : leaves_on, leaves_off @@ -75,7 +75,7 @@ module FatesInventoryInitMod ! with a patch. BY having a vector of patch pointers that lines up with the string ! identifier array, this can be done quickly. type pp_array - type(ed_patch_type), pointer :: cpatch + type(fates_patch_type), pointer :: cpatch end type pp_array character(len=*), parameter, private :: sourcefile = __FILE__ @@ -123,12 +123,12 @@ subroutine initialize_sites_by_inventory(nsites,sites,bc_in) ! Locals type(ed_site_type), pointer :: currentSite - type(ed_patch_type), pointer :: currentpatch + type(fates_patch_type), pointer :: currentpatch type(fates_cohort_type), pointer :: currentcohort - type(ed_patch_type), pointer :: newpatch - type(ed_patch_type), pointer :: olderpatch - type(ed_patch_type), pointer :: head_of_unsorted_patch_list - type(ed_patch_type), pointer :: next_in_unsorted_patch_list + type(fates_patch_type), pointer :: newpatch + type(fates_patch_type), pointer :: olderpatch + type(fates_patch_type), pointer :: head_of_unsorted_patch_list + type(fates_patch_type), pointer :: next_in_unsorted_patch_list integer :: sitelist_file_unit ! fortran file unit for site list integer :: pss_file_unit ! fortran file unit for the pss file integer :: css_file_unit ! fortran file unit for the css file @@ -753,7 +753,7 @@ subroutine set_inventory_edpatch_type1(newpatch,pss_file_unit,ipa,ios,patch_name use EDtypesMod, only: AREA ! Arguments - type(ed_patch_type),intent(inout), target :: newpatch ! Patch structure + type(fates_patch_type),intent(inout), target :: newpatch ! Patch structure integer,intent(in) :: pss_file_unit ! Self explanatory integer,intent(in) :: ipa ! Patch index (line number) integer,intent(out) :: ios ! Return flag @@ -901,7 +901,7 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & integer :: cstatus ! cohort status integer,parameter :: rstatus = 0 ! recruit status - type(ed_patch_type), pointer :: cpatch ! current patch pointer + type(fates_patch_type), pointer :: cpatch ! current patch pointer type(fates_cohort_type), pointer :: temp_cohort ! temporary patch (needed for allom funcs) integer :: ipa ! patch idex integer :: iage @@ -1190,7 +1190,7 @@ subroutine write_inventory_type1(currentSite) type(ed_site_type), target :: currentSite ! Locals - type(ed_patch_type), pointer :: currentpatch + type(fates_patch_type), pointer :: currentpatch type(fates_cohort_type), pointer :: currentcohort character(len=128) :: pss_name_out ! output file string diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index f9669b4c8a..efb13c4a80 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -1810,7 +1810,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) use FatesInterfaceTypesMod, only : numpft use EDTypesMod, only : ed_site_type use FatesCohortMod, only : fates_cohort_type - use EDTypesMod, only : ed_patch_type + use FatesPatchMod, only : fates_patch_type use EDParamsMod, only : maxSWb use EDParamsMod, only : nclmax use EDTypesMod, only : numWaterMem @@ -1881,7 +1881,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) integer :: icdj ! loop counter for damage type(fates_restart_variable_type) :: rvar - type(ed_patch_type),pointer :: cpatch + type(fates_patch_type),pointer :: cpatch type(fates_cohort_type),pointer :: ccohort @@ -2506,11 +2506,11 @@ subroutine create_patchcohort_structure(this, nc, nsites, sites, bc_in, bc_out) use EDTypesMod, only : ed_site_type use FatesCohortMod, only : fates_cohort_type - use EDTypesMod, only : ed_patch_type + use FatesPatchMod, only : fates_patch_type use EDParamsMod, only : maxSWb use FatesInterfaceTypesMod, only : fates_maxElementsPerPatch - use EDTypesMod, only : maxpft + use FatesConstantsMod, only : maxpft use EDTypesMod, only : area use EDPatchDynamicsMod, only : zero_patch use EDInitMod, only : zero_site @@ -2529,7 +2529,7 @@ subroutine create_patchcohort_structure(this, nc, nsites, sites, bc_in, bc_out) ! local variables - type(ed_patch_type) , pointer :: newp + type(fates_patch_type) , pointer :: newp type(fates_cohort_type), pointer :: new_cohort type(fates_cohort_type), pointer :: prev_cohort integer :: cohortstatus @@ -2704,7 +2704,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) use EDTypesMod, only : ed_site_type use FatesCohortMod, only : fates_cohort_type - use EDTypesMod, only : ed_patch_type + use FatesPatchMod, only : fates_patch_type use EDParamsMod, only : maxSWb use EDParamsMod, only : nclmax use FatesInterfaceTypesMod, only : numpft @@ -2723,7 +2723,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ! locals ! ---------------------------------------------------------------------------------- ! LL pointers - type(ed_patch_type),pointer :: cpatch ! current patch + type(fates_patch_type),pointer :: cpatch ! current patch type(fates_cohort_type),pointer :: ccohort ! current cohort type(litter_type), pointer :: litt ! litter object on the current patch ! loop indices @@ -3386,7 +3386,7 @@ subroutine update_3dpatch_radiation(this, nsites, sites, bc_out) ! ------------------------------------------------------------------------- use EDTypesMod, only : ed_site_type - use EDTypesMod, only : ed_patch_type + use FatesPatchMod, only : fates_patch_type use EDSurfaceRadiationMod, only : PatchNormanRadiation use FatesInterfaceTypesMod, only : hlm_numSWb @@ -3398,7 +3398,7 @@ subroutine update_3dpatch_radiation(this, nsites, sites, bc_out) ! locals ! ---------------------------------------------------------------------------------- - type(ed_patch_type),pointer :: currentPatch ! current patch + type(fates_patch_type),pointer :: currentPatch ! current patch integer :: s ! site counter integer :: ib ! radiation band counter integer :: ifp ! patch counter From 9ec7d625c63d5871e3b35ad8cb9b6974053e665e Mon Sep 17 00:00:00 2001 From: adrifoster Date: Mon, 10 Apr 2023 16:03:45 -0600 Subject: [PATCH 618/852] move create methods to patch type --- biogeochem/EDPatchDynamicsMod.F90 | 268 +----------------------- biogeochem/FatesPatchMod.F90 | 328 +++++++++++++++++++++++++++++- main/EDInitMod.F90 | 7 +- main/FatesInventoryInitMod.F90 | 18 +- main/FatesRestartInterfaceMod.F90 | 7 +- 5 files changed, 355 insertions(+), 273 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 2934948aab..aa6014f710 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -5,7 +5,8 @@ module EDPatchDynamicsMod ! ============================================================================ use FatesGlobals , only : fates_log use FatesGlobals , only : FatesWarn,N2S,A2S - use FatesInterfaceTypesMod , only : hlm_freq_day + use FatesInterfaceTypesMod, only : hlm_freq_day + use FatesInterfaceTypesMod, only : hlm_current_tod use EDPftvarcon , only : EDPftvarcon_inst use EDPftvarcon , only : GetDecompyFrac use PRTParametersMod , only : prt_params @@ -105,10 +106,8 @@ module EDPatchDynamicsMod ! implicit none private - ! - public :: create_patch + public :: spawn_patches - public :: zero_patch public :: fuse_patches public :: terminate_patches public :: patch_pft_size_profile @@ -540,9 +539,9 @@ subroutine spawn_patches( currentSite, bc_in) ! first create patch to receive primary forest area if ( site_areadis_primary .gt. nearzero ) then allocate(new_patch_primary) - - call create_patch(currentSite, new_patch_primary, age, & - site_areadis_primary, primaryforest, i_nocomp_pft) + call new_patch_primary%create(age, site_areadis_primary, & + primaryforest, i_nocomp_pft, hlm_numSWb, numpft, & + currentSite%nlevsoil, hlm_current_tod) ! Initialize the litter pools to zero, these ! pools will be populated by looping over the existing patches @@ -561,10 +560,10 @@ subroutine spawn_patches( currentSite, bc_in) endif ! next create patch to receive secondary forest area - if ( site_areadis_secondary .gt. nearzero) then - allocate(new_patch_secondary) - call create_patch(currentSite, new_patch_secondary, age, & - site_areadis_secondary, secondaryforest,i_nocomp_pft) + if (site_areadis_secondary .gt. nearzero) then + call new_patch_secondary%create(age, site_areadis_secondary, & + secondaryforest, i_nocomp_pft, hlm_numSWb, numpft, & + currentSite%nlevsoil, hlm_current_tod) ! Initialize the litter pools to zero, these ! pools will be populated by looping over the existing patches @@ -2069,252 +2068,7 @@ subroutine mortality_litter_fluxes(currentSite, currentPatch, & end subroutine mortality_litter_fluxes ! ============================================================================ - - subroutine create_patch(currentSite, new_patch, age, areap, label,nocomp_pft) - - use FatesInterfaceTypesMod, only : hlm_current_tod - - ! - ! !DESCRIPTION: - ! Set default values for creating a new patch - ! - ! !USES: - ! - ! !ARGUMENTS: - type(ed_site_type) , intent(inout), target :: currentSite - type(fates_patch_type), intent(inout), target :: new_patch - real(r8), intent(in) :: age ! notional age of this patch in years - real(r8), intent(in) :: areap ! initial area of this patch in m2. - integer, intent(in) :: label ! anthropogenic disturbance label - integer, intent(in) :: nocomp_pft ! no competition mode pft label - - - ! Until bc's are pointed to by sites give veg a default temp [K] - real(r8), parameter :: temp_init_veg = 15._r8+t_water_freeze_k_1atm - - - ! !LOCAL VARIABLES: - !--------------------------------------------------------------------- - integer :: el ! element loop index - - - allocate(new_patch%tr_soil_dir(hlm_numSWb)) - allocate(new_patch%tr_soil_dif(hlm_numSWb)) - allocate(new_patch%tr_soil_dir_dif(hlm_numSWb)) - allocate(new_patch%fab(hlm_numSWb)) - allocate(new_patch%fabd(hlm_numSWb)) - allocate(new_patch%fabi(hlm_numSWb)) - allocate(new_patch%sabs_dir(hlm_numSWb)) - allocate(new_patch%sabs_dif(hlm_numSWb)) - allocate(new_patch%fragmentation_scaler(currentSite%nlevsoil)) - - allocate(new_patch%tveg24) - call new_patch%tveg24%InitRMean(fixed_24hr,init_value=temp_init_veg,init_offset=real(hlm_current_tod,r8) ) - allocate(new_patch%tveg_lpa) - call new_patch%tveg_lpa%InitRmean(ema_lpa,init_value=temp_init_veg) - allocate(new_patch%tveg_longterm) - call new_patch%tveg_longterm%InitRmean(ema_longterm,init_value=temp_init_veg) - - ! Litter - ! Allocate, Zero Fluxes, and Initialize to "unset" values - - allocate(new_patch%litter(num_elements)) - do el=1,num_elements - call new_patch%litter(el)%InitAllocate(numpft,currentSite%nlevsoil,element_list(el)) - call new_patch%litter(el)%ZeroFlux() - call new_patch%litter(el)%InitConditions(init_leaf_fines = fates_unset_r8, & - init_root_fines = fates_unset_r8, & - init_ag_cwd = fates_unset_r8, & - init_bg_cwd = fates_unset_r8, & - init_seed = fates_unset_r8, & - init_seed_germ = fates_unset_r8) - end do - - call zero_patch(new_patch) !The nan value in here is not working?? - - new_patch%tallest => null() ! pointer to patch's tallest cohort - new_patch%shortest => null() ! pointer to patch's shortest cohort - new_patch%older => null() ! pointer to next older patch - new_patch%younger => null() ! pointer to next shorter patch - - ! assign known patch attributes - - new_patch%age = age - new_patch%age_class = 1 - new_patch%area = areap - - ! assign anthropgenic disturbance category and label - new_patch%anthro_disturbance_label = label - if (label .eq. secondaryforest) then - new_patch%age_since_anthro_disturbance = age - else - new_patch%age_since_anthro_disturbance = fates_unset_r8 - endif - new_patch%nocomp_pft_label = nocomp_pft - - ! This new value will be generated when the calculate disturbance - ! rates routine is called. This does not need to be remembered or in the restart file. - - new_patch%f_sun = 0._r8 - new_patch%ed_laisun_z(:,:,:) = 0._r8 - new_patch%ed_laisha_z(:,:,:) = 0._r8 - new_patch%ed_parsun_z(:,:,:) = 0._r8 - new_patch%ed_parsha_z(:,:,:) = 0._r8 - new_patch%fabi = 0._r8 - new_patch%fabd = 0._r8 - new_patch%tr_soil_dir(:) = 1._r8 - new_patch%tr_soil_dif(:) = 1._r8 - new_patch%tr_soil_dir_dif(:) = 0._r8 - new_patch%fabd_sun_z(:,:,:) = 0._r8 - new_patch%fabd_sha_z(:,:,:) = 0._r8 - new_patch%fabi_sun_z(:,:,:) = 0._r8 - new_patch%fabi_sha_z(:,:,:) = 0._r8 - new_patch%scorch_ht(:) = 0._r8 - new_patch%frac_burnt = 0._r8 - new_patch%litter_moisture(:) = 0._r8 - new_patch%fuel_eff_moist = 0._r8 - new_patch%livegrass = 0._r8 - new_patch%sum_fuel = 0._r8 - new_patch%fuel_bulkd = 0._r8 - new_patch%fuel_sav = 0._r8 - new_patch%fuel_mef = 0._r8 - new_patch%ros_front = 0._r8 - new_patch%effect_wspeed = 0._r8 - new_patch%tau_l = 0._r8 - new_patch%fuel_frac(:) = 0._r8 - new_patch%tfc_ros = 0._r8 - new_patch%fi = 0._r8 - new_patch%fd = 0._r8 - new_patch%ros_back = 0._r8 - new_patch%scorch_ht(:) = 0._r8 - new_patch%burnt_frac_litter(:) = 0._r8 - new_patch%total_tree_area = 0.0_r8 - new_patch%NCL_p = 1 - - - return - end subroutine create_patch - - ! ============================================================================ - subroutine zero_patch(cp_p) - ! - ! !DESCRIPTION: - ! Sets all the variables in the patch to nan or zero - ! (this needs to be two seperate routines, one for nan & one for zero - ! - ! !USES: - ! - ! !ARGUMENTS: - type(fates_patch_type), intent(inout), target :: cp_p - ! - ! !LOCAL VARIABLES: - type(fates_patch_type), pointer :: currentPatch - !--------------------------------------------------------------------- - - currentPatch => cp_p - - currentPatch%tallest => null() - currentPatch%shortest => null() - currentPatch%older => null() - currentPatch%younger => null() - - currentPatch%patchno = 999 - - currentPatch%age = nan - currentPatch%age_class = 1 - currentPatch%area = nan - currentPatch%canopy_layer_tlai(:) = nan - currentPatch%total_canopy_area = nan - - currentPatch%tlai_profile(:,:,:) = nan - currentPatch%elai_profile(:,:,:) = 0._r8 - currentPatch%tsai_profile(:,:,:) = nan - currentPatch%esai_profile(:,:,:) = nan - currentPatch%canopy_area_profile(:,:,:) = nan - - currentPatch%fabd_sun_z(:,:,:) = nan - currentPatch%fabd_sha_z(:,:,:) = nan - currentPatch%fabi_sun_z(:,:,:) = nan - currentPatch%fabi_sha_z(:,:,:) = nan - - currentPatch%ed_laisun_z(:,:,:) = nan - currentPatch%ed_laisha_z(:,:,:) = nan - currentPatch%ed_parsun_z(:,:,:) = nan - currentPatch%ed_parsha_z(:,:,:) = nan - currentPatch%psn_z(:,:,:) = 0._r8 - - currentPatch%f_sun(:,:,:) = nan - currentPatch%tr_soil_dir(:) = nan ! fraction of incoming direct radiation that is transmitted to the soil as direct - currentPatch%tr_soil_dif(:) = nan ! fraction of incoming diffuse radiation that is transmitted to the soil as diffuse - currentPatch%tr_soil_dir_dif(:) = nan ! fraction of incoming direct radiation that is transmitted to the soil as diffuse - currentPatch%fabd(:) = nan ! fraction of incoming direct radiation that is absorbed by the canopy - currentPatch%fabi(:) = nan ! fraction of incoming diffuse radiation that is absorbed by the canopy - - currentPatch%canopy_mask(:,:) = 999 ! is there any of this pft in this layer? - currentPatch%nrad(:,:) = 999 ! number of exposed leaf layers for each canopy layer and pft - currentPatch%ncan(:,:) = 999 ! number of total leaf layers for each canopy layer and pft - currentPatch%pft_agb_profile(:,:) = nan - - ! DISTURBANCE - currentPatch%disturbance_rates(:) = 0._r8 - currentPatch%fract_ldist_not_harvested = 0._r8 - - - ! FIRE - currentPatch%litter_moisture(:) = nan ! litter moisture - currentPatch%fuel_eff_moist = nan ! average fuel moisture content of the ground fuel - ! (incl. live grasses. omits 1000hr fuels) - currentPatch%livegrass = nan ! total ag grass biomass in patch. 1=c3 grass, 2=c4 grass. gc/m2 - currentPatch%sum_fuel = nan ! total ground fuel related to ros (omits 1000hr fuels). gc/m2 - currentPatch%fuel_bulkd = nan ! average fuel bulk density of the ground fuel - ! (incl. live grasses. omits 1000hr fuels). kgc/m3 - currentPatch%fuel_sav = nan ! average surface area to volume ratio of the ground fuel - ! (incl. live grasses. omits 1000hr fuels). - currentPatch%fuel_mef = nan ! average moisture of extinction factor of the ground fuel - ! (incl. live grasses. omits 1000hr fuels). - currentPatch%ros_front = nan ! average rate of forward spread of each fire in the patch. m/min. - currentPatch%effect_wspeed = nan ! dailywind modified by fraction of relative grass and tree cover. m/min. - currentPatch%tau_l = nan ! mins p&r(1986) - currentPatch%fuel_frac(:) = nan ! fraction of each litter class in the sum_fuel - !- for purposes of calculating weighted averages. - currentPatch%tfc_ros = nan ! used in fi calc - currentPatch%fi = nan ! average fire intensity of flaming front during day. - ! backward ros plays no role. kj/m/s or kw/m. - currentPatch%fire = 999 ! sr decide_fire.1=fire hot enough to proceed. 0=stop everything- no fires today - currentPatch%fd = nan ! fire duration (mins) - currentPatch%ros_back = nan ! backward ros (m/min) - currentPatch%scorch_ht(:) = nan ! scorch height of flames on a given PFT - currentPatch%frac_burnt = nan ! fraction burnt daily - currentPatch%burnt_frac_litter(:) = nan - currentPatch%btran_ft(:) = 0.0_r8 - - currentPatch%canopy_layer_tlai(:) = 0.0_r8 - - currentPatch%fab(:) = 0.0_r8 - currentPatch%sabs_dir(:) = 0.0_r8 - currentPatch%sabs_dif(:) = 0.0_r8 - currentPatch%zstar = 0.0_r8 - currentPatch%c_stomata = 0.0_r8 ! This is calculated immediately before use - currentPatch%c_lblayer = 0.0_r8 - currentPatch%fragmentation_scaler(:) = 0.0_r8 - currentPatch%radiation_error = 0.0_r8 - - ! diagnostic radiation profiles - currentPatch%nrmlzd_parprof_pft_dir_z(:,:,:,:) = 0._r8 - currentPatch%nrmlzd_parprof_pft_dif_z(:,:,:,:) = 0._r8 - currentPatch%nrmlzd_parprof_dir_z(:,:,:) = 0._r8 - currentPatch%nrmlzd_parprof_dif_z(:,:,:) = 0._r8 - - currentPatch%solar_zenith_flag = .false. - currentPatch%solar_zenith_angle = nan - currentPatch%fcansno = nan - - currentPatch%gnd_alb_dir(:) = nan - currentPatch%gnd_alb_dif(:) = nan - - end subroutine zero_patch - - ! ============================================================================ + subroutine fuse_patches( csite, bc_in ) ! ! !DESCRIPTION: diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 index 8374324db4..00b43bd436 100644 --- a/biogeochem/FatesPatchMod.F90 +++ b/biogeochem/FatesPatchMod.F90 @@ -1,13 +1,22 @@ module FatesPatchMod use FatesConstantsMod, only : r8 => fates_r8 + use FatesConstantsMod, only : fates_unset_r8 + use FatesConstantsMod, only : fates_unset_int + use FatesConstantsMod, only : primaryforest, secondaryforest use FatesCohortMod, only : fates_cohort_type use FatesRunningMeanMod, only : rmean_type use FatesLitterMod, only : nfsc use FatesLitterMod, only : litter_type + use PRTGenericMod, only : num_elements + use PRTGenericMod, only : element_list use EDParamsMod, only : maxSWb, nlevleaf, nclmax use FatesConstantsMod, only : n_dbh_bins, maxpft, n_dist_types use FatesConstantsMod, only : n_rad_stream_types + use FatesConstantsMod, only : t_water_freeze_k_1atm + use FatesRunningMeanMod, only : ema_24hr, fixed_24hr, ema_lpa, ema_longterm + + use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) implicit none private @@ -75,10 +84,9 @@ module FatesPatchMod integer :: ncan(nclmax,maxpft) ! number of total leaf layers for each canopy layer and pft real(r8) :: c_stomata ! mean stomatal conductance of all leaves in the patch [umol/m2/s] real(r8) :: c_lblayer ! mean boundary layer conductance of all leaves in the patch [umol/m2/s] - real(r8) :: layer_height_profile(nclmax,maxpft,nlevleaf) - !:.........................................................................: + real(r8) :: layer_height_profile(nclmax,maxpft,nlevleaf) real(r8) :: psn_z(nclmax,maxpft,nlevleaf) real(r8) :: nrmlzd_parprof_pft_dir_z(n_rad_stream_types,nclmax,maxpft,nlevleaf) real(r8) :: nrmlzd_parprof_pft_dif_z(n_rad_stream_types,nclmax,maxpft,nlevleaf) @@ -179,6 +187,322 @@ module FatesPatchMod real(r8) :: tfc_ros ! total intensity-relevant fuel consumed - no trunks [kgC/m2 of burned ground/day] real(r8) :: burnt_frac_litter(nfsc) ! fraction of each litter pool burned, conditional on it being burned [0-1] + !:.........................................................................: + + ! PLANT HYDRAULICS (not currently used in hydraulics RGK 03-2018) + ! type(ed_patch_hydr_type), pointer :: pa_hydr ! All patch hydraulics data, see FatesHydraulicsMemMod.F90 + + contains + + procedure :: init + procedure :: nan_values + procedure :: zero_values + procedure :: create + end type fates_patch_type + contains + + subroutine init(this, numSWb, numpft, nlevsoil, current_tod) + ! + ! DESCRIPTION: + ! Initialize a new patch + ! + + ! ARGUMENTS: + class(fates_patch_type), intent(inout) :: this ! patch object + integer, intent(in) :: numSWb ! number of shortwave broad-bands to track + integer, intent(in) :: numpft ! number of pfts to simulate + integer, intent(in) :: nlevsoil ! number of soil layers + integer, intent(in) :: current_tod ! time of day [seconds past 0Z] + + ! LOCAL VARIABLES: + integer :: el ! element loop index + + ! Until bc's are pointed to by sites give veg a default temp [K] + real(r8), parameter :: temp_init_veg = 15._r8 + t_water_freeze_k_1atm + + ! allocate arrays + allocate(this%tr_soil_dir(numSWb)) + allocate(this%tr_soil_dif(numSWb)) + allocate(this%tr_soil_dir_dif(numSWb)) + allocate(this%fab(numSWb)) + allocate(this%fabd(numSWb)) + allocate(this%fabi(numSWb)) + allocate(this%sabs_dir(numSWb)) + allocate(this%sabs_dif(numSWb)) + allocate(this%fragmentation_scaler(nlevsoil)) + allocate(this%tveg24) + allocate(this%tveg_lpa) + allocate(this%tveg_longterm) + allocate(this%litter(num_elements)) + + ! initialize values to nan + call this%nan_values() + + ! zero values that should be zeroed + call this%zero_values() + + ! set initial values for running means + call this%tveg24%InitRMean(fixed_24hr, init_value=temp_init_veg, & + init_offset=real(current_tod, r8)) + call this%tveg_lpa%InitRmean(ema_lpa, init_value=temp_init_veg) + call this%tveg_longterm%InitRmean(ema_longterm, init_value=temp_init_veg) + + ! set initial values for litter + do el = 1, num_elements + call this%litter(el)%InitAllocate(numpft, nlevsoil, element_list(el)) + call this%litter(el)%ZeroFlux() + call this%litter(el)%InitConditions(init_leaf_fines=fates_unset_r8, & + init_root_fines=fates_unset_r8, init_ag_cwd=fates_unset_r8, & + init_bg_cwd=fates_unset_r8, init_seed=fates_unset_r8, & + init_seed_germ=fates_unset_r8) + end do + + end subroutine init + + !:.........................................................................: + + subroutine nan_values(this) + ! + ! DESCRIPTION: + ! Sets all values in patch to nan + ! + + ! ARGUMENTS: + class(fates_patch_type), intent(inout) :: this ! patch object + + ! set pointers to null + this%tallest => null() + this%shortest => null() + this%older => null() + this%younger => null() + nullify(this%tallest) + nullify(this%shortest) + nullify(this%older) + nullify(this%younger) + + ! INDICES + this%patchno = fates_unset_int + this%nocomp_pft_label = fates_unset_int + + ! PATCH INFO + this%age = nan + this%age_class = fates_unset_int + this%area = nan + this%countcohorts = fates_unset_int + this%ncl_p = fates_unset_int + this%anthro_disturbance_label = fates_unset_int + this%age_since_anthro_disturbance = nan + + ! LEAF ORGANIZATION + this%pft_agb_profile(:,:) = nan + this%canopy_layer_tlai(:) = nan + this%total_canopy_area = nan + this%total_tree_area = nan + this%zstar = nan + this%elai_profile(:,:,:) = nan + this%esai_profile(:,:,:) = nan + this%tlai_profile(:,:,:) = nan + this%tsai_profile(:,:,:) = nan + this%canopy_area_profile(:,:,:) = nan + this%canopy_mask(:,:) = fates_unset_int + this%nrad(:,:) = fates_unset_int + this%ncan(:,:) = fates_unset_int + this%c_stomata = nan + this%c_lblayer = nan + this%layer_height_profile(:,:,:) = nan + + this%psn_z(:,:,:) = nan + this%nrmlzd_parprof_pft_dir_z(:,:,:,:) = nan + this%nrmlzd_parprof_pft_dif_z(:,:,:,:) = nan + this%nrmlzd_parprof_dir_z(:,:,:) = nan + this%nrmlzd_parprof_dir_z(:,:,:) = nan + + ! RADIATION + this%radiation_error = nan + this%fcansno = nan + this%solar_zenith_flag = .false. + this%solar_zenith_angle = nan + this%gnd_alb_dif(:) = nan + this%gnd_alb_dir(:) = nan + this%fabd_sun_z(:,:,:) = nan + this%fabd_sha_z(:,:,:) = nan + this%fabi_sun_z(:,:,:) = nan + this%fabi_sha_z(:,:,:) = nan + this%ed_laisun_z(:,:,:) = nan + this%ed_laisha_z(:,:,:) = nan + this%ed_parsun_z(:,:,:) = nan + this%ed_parsha_z(:,:,:) = nan + this%f_sun(:,:,:) = nan + this%parprof_pft_dir_z(:,:,:) = nan + this%parprof_pft_dif_z(:,:,:) = nan + this%parprof_dir_z(:,:) = nan + this%parprof_dif_z(:,:) = nan + this%tr_soil_dir(:) = nan + this%tr_soil_dif(:) = nan + this%tr_soil_dir_dif(:) = nan + this%fab(:) = nan + this%fabd(:) = nan + this%fabi(:) = nan + this%sabs_dir(:) = nan + this%sabs_dif(:) = nan + + ! ROOTS + this%btran_ft(:) = nan + this%bstress_sal_ft(:) = nan + + ! EXTERNAL SEED RAIN + this%nitr_repro_stoich(:) = nan + this%phos_repro_stoich(:) = nan + + ! DISTURBANCE + this%disturbance_rates(:) = nan + this%fract_ldist_not_harvested = nan + + ! LITTER AND COARSE WOODY DEBRIS + this%fragmentation_scaler(:) = nan + + ! FUELS AND FIRE + this%sum_fuel = nan + this%fuel_frac(:) = nan + this%livegrass = nan + this%fuel_bulkd = nan + this%fuel_sav = nan + this%fuel_mef = nan + this%fuel_eff_moist = nan + this%litter_moisture(:) = nan + this%ros_front = nan + this%ros_back = nan + this%effect_wspeed = nan + this%tau_l = nan + this%fi = nan + this%fire = fates_unset_int + this%fd = nan + this%scorch_ht(:) = nan + this%frac_burnt = nan + this%tfc_ros = nan + this%burnt_frac_litter(:) = nan + + end subroutine nan_values + + !:.........................................................................: + + subroutine zero_values(this) + ! + ! DESCRIPTION: + ! sets specific variables in patch to zero + ! these should only be values that are incremented, so that we can + ! catch all other uninitialized variables with nans + + ! ARGUMENTS: + class(fates_patch_type), intent(inout) :: this + + ! LEAF ORGANIZATION + this%canopy_layer_tlai(:) = 0.0_r8 + this%total_tree_area = 0.0_r8 + this%zstar = 0.0_r8 + this%elai_profile(:,:,:) = 0.0_r8 + this%c_stomata = 0.0_r8 + this%c_lblayer = 0.0_r8 + this%psn_z(:,:,:) = 0.0_r8 + this%nrmlzd_parprof_pft_dir_z(:,:,:,:) = 0.0_r8 + this%nrmlzd_parprof_pft_dif_z(:,:,:,:) = 0.0_r8 + this%nrmlzd_parprof_dir_z(:,:,:) = 0.0_r8 + this%nrmlzd_parprof_dif_z(:,:,:) = 0.0_r8 + + ! RADIATION + this%radiation_error = 0.0_r8 + this%fabd_sun_z(:,:,:) = 0.0_r8 + this%fabd_sha_z(:,:,:) = 0.0_r8 + this%fabi_sun_z(:,:,:) = 0.0_r8 + this%fabi_sha_z(:,:,:) = 0.0_r8 + this%ed_parsun_z(:,:,:) = 0.0_r8 + this%ed_parsha_z(:,:,:) = 0.0_r8 + this%ed_laisun_z(:,:,:) = 0.0_r8 + this%ed_laisha_z(:,:,:) = 0.0_r8 + this%f_sun = 0.0_r8 + this%tr_soil_dir_dif(:) = 0.0_r8 + this%fab(:) = 0.0_r8 + this%fabi(:) = 0.0_r8 + this%fabd(:) = 0.0_r8 + this%sabs_dir(:) = 0.0_r8 + this%sabs_dif(:) = 0.0_r8 + + ! ROOTS + this%btran_ft(:) = 0.0_r8 + + ! DISTURBANCE + this%disturbance_rates(:) = 0.0_r8 + this%fract_ldist_not_harvested = 0.0_r8 + + ! LITTER AND COARSE WOODY DEBRIS + this%fragmentation_scaler(:) = 0.0_r8 + + ! FIRE + this%sum_fuel = 0.0_r8 + this%fuel_frac(:) = 0.0_r8 + this%livegrass = 0.0_r8 + this%fuel_bulkd = 0.0_r8 + this%fuel_sav = 0.0_r8 + this%fuel_mef = 0.0_r8 + this%fuel_eff_moist = 0.0_r8 + this%litter_moisture(:) = 0.0_r8 + this%ros_front = 0.0_r8 + this%ros_back = 0.0_r8 + this%effect_wspeed = 0.0_r8 + this%tau_l = 0.0_r8 + this%fi = 0.0_r8 + this%fd = 0.0_r8 + this%scorch_ht(:) = 0.0_r8 + this%frac_burnt = 0.0_r8 + this%tfc_ros = 0.0_r8 + this%burnt_frac_litter(:) = 0.0_r8 + + end subroutine zero_values + + !:.........................................................................: + + subroutine create(this, age, areap, label, nocomp_pft, numSWb, numpft, & + nlevsoil, current_tod) + ! + ! DESCRIPTION: + ! create a new patch with input and default values + ! + + ! ARGUMENTS: + class(fates_patch_type), intent(inout) :: this ! patch object + real(r8), intent(in) :: age ! notional age of this patch in years + real(r8), intent(in) :: areap ! initial area of this patch in m2. + integer, intent(in) :: label ! anthropogenic disturbance label + integer, intent(in) :: nocomp_pft ! no-competition mode pft label + integer, intent(in) :: numSWb ! number of shortwave broad-bands to track + integer, intent(in) :: numpft ! number of pfts to simulate + integer, intent(in) :: nlevsoil ! number of soil layers + integer, intent(in) :: current_tod ! time of day [seconds past 0Z] + + ! initialize patch + ! also sets all values to nan, then some values to zero + call this%init(numSWb, numpft, nlevsoil, current_tod) + + ! assign known patch attributes + this%age = age + this%age_class = 1 + this%area = areap + + ! assign anthropgenic disturbance category and label + this%anthro_disturbance_label = label + if (label .eq. secondaryforest) then + this%age_since_anthro_disturbance = age + else + this%age_since_anthro_disturbance = fates_unset_r8 + endif + this%nocomp_pft_label = nocomp_pft + + this%tr_soil_dir(:) = 1.0_r8 + this%tr_soil_dif(:) = 1.0_r8 + this%NCL_p = 1 + + end subroutine create + end module FatesPatchMod \ No newline at end of file diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index e9c6ea06d1..8dd15a9a8d 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -14,11 +14,12 @@ module EDInitMod use EDParamsMod , only : nclmax use FatesGlobals , only : fates_log use FatesInterfaceTypesMod , only : hlm_is_restart + use FatesInterfaceTypesMod , only : hlm_current_tod + use FatesInterfaceTypesMod , only : hlm_numSWb use EDPftvarcon , only : EDPftvarcon_inst use PRTParametersMod , only : prt_params use EDCohortDynamicsMod , only : create_cohort, fuse_cohorts, sort_cohorts use EDCohortDynamicsMod , only : InitPRTObject - use EDPatchDynamicsMod , only : create_patch use EDPatchDynamicsMod , only : set_patchno use EDPhysiologyMod , only : assign_cohort_sp_properties use ChecksBalancesMod , only : SiteMassStock @@ -610,8 +611,8 @@ subroutine init_patches( nsites, sites, bc_in) if(newparea.gt.0._r8)then ! Stop patches being initilialized when PFT not present in nocomop mode allocate(newp) - - call create_patch(sites(s), newp, age, newparea, primaryforest, nocomp_pft) + call newp%create(age, newparea, primaryforest, nocomp_pft, & + hlm_numSWb, numpft, sites(s)%nlevsoil, hlm_current_tod) if(is_first_patch.eq.itrue)then !is this the first patch? ! set poointers for first patch (or only patch, if nocomp is false) diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index 55b8ed3ed6..1c9b0f9449 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -31,6 +31,9 @@ module FatesInventoryInitMod use FatesInterfaceTypesMod, only : bc_in_type use FatesInterfaceTypesMod, only : hlm_inventory_ctrl_file use FatesInterfaceTypesMod, only : nleafage + use FatesInterfaceTypesMod, only : hlm_current_tod + use FatesInterfaceTypesMod, only : hlm_numSWb + use FatesInterfaceTypesMod, only : numpft use FatesLitterMod , only : litter_type use EDTypesMod , only : ed_site_type use FatesPatchMod , only : fates_patch_type @@ -109,7 +112,6 @@ subroutine initialize_sites_by_inventory(nsites,sites,bc_in) use shr_file_mod, only : shr_file_getUnit use shr_file_mod, only : shr_file_freeUnit use FatesConstantsMod, only : nearzero - use EDPatchDynamicsMod, only : create_patch use EDPatchDynamicsMod, only : fuse_patches use EDCohortDynamicsMod, only : fuse_cohorts use EDCohortDynamicsMod, only : sort_cohorts @@ -266,12 +268,6 @@ subroutine initialize_sites_by_inventory(nsites,sites,bc_in) do ipa=1,npatches - allocate(newpatch) - - newpatch%patchno = ipa - newpatch%younger => null() - newpatch%older => null() - ! This call doesn't do much asside from initializing the patch with ! nominal values, NaNs, zero's and allocating some vectors. We should ! be able to get the following values from the patch files. But on @@ -279,8 +275,14 @@ subroutine initialize_sites_by_inventory(nsites,sites,bc_in) age_init = 0.0_r8 area_init = 0.0_r8 + allocate(newpatch) + call newpatch%create(age_init, area_init, primaryforest, & + fates_unset_int, hlm_numSWb, numpft, sites(s)%nlevsoil, & + hlm_current_tod) - call create_patch(sites(s), newpatch, age_init, area_init, primaryforest, fates_unset_int ) + newpatch%patchno = ipa + newpatch%younger => null() + newpatch%older => null() if( inv_format_list(invsite) == 1 ) then diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index efb13c4a80..a1a07b225d 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -2509,13 +2509,12 @@ subroutine create_patchcohort_structure(this, nc, nsites, sites, bc_in, bc_out) use FatesPatchMod, only : fates_patch_type use EDParamsMod, only : maxSWb use FatesInterfaceTypesMod, only : fates_maxElementsPerPatch + use FatesInterfaceTypesMod, only : hlm_current_tod, hlm_numSWb, numpft use FatesConstantsMod, only : maxpft use EDTypesMod, only : area - use EDPatchDynamicsMod, only : zero_patch use EDInitMod, only : zero_site use EDInitMod, only : init_site_vars - use EDPatchDynamicsMod, only : create_patch use FatesAllometryMod, only : h2d_allom @@ -2582,7 +2581,9 @@ subroutine create_patchcohort_structure(this, nc, nsites, sites, bc_in, bc_out) nocomp_pft = fates_unset_int ! the nocomp_pft label is set after patch creation has occured in 'get_restart_vectors' ! make new patch - call create_patch(sites(s), newp, fates_unset_r8, fates_unset_r8, primaryforest, nocomp_pft ) + call newp%create(fates_unset_r8, fates_unset_r8, primaryforest, & + nocomp_pft, hlm_numSWb, numpft, sites(s)%nlevsoil, & + hlm_current_tod) ! Initialize the litter pools to zero, these ! pools will be populated by looping over the existing patches From cfb5fb09f36a566a96680bcc6dcb243e681fea92 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Mon, 10 Apr 2023 16:30:10 -0600 Subject: [PATCH 619/852] move more methods to patch type --- biogeochem/DamageMainMod.F90 | 1 - biogeochem/EDPatchDynamicsMod.F90 | 3 +- biogeochem/FatesPatchMod.F90 | 117 ++++++++++++++++++++++++- main/EDTypesMod.F90 | 140 +++--------------------------- 4 files changed, 128 insertions(+), 133 deletions(-) diff --git a/biogeochem/DamageMainMod.F90 b/biogeochem/DamageMainMod.F90 index f59b43d94d..11de5d1799 100644 --- a/biogeochem/DamageMainMod.F90 +++ b/biogeochem/DamageMainMod.F90 @@ -11,7 +11,6 @@ module DamageMainMod use EDPftvarcon , only : EDPftvarcon_inst use EDParamsMod , only : damage_event_code use EDParamsMod , only : ED_val_history_damage_bin_edges - ! use EDTypesMod , only : ed_site_type use FatesInterfaceTypesMod, only : hlm_current_day use FatesInterfaceTypesMod, only : hlm_current_month use FatesInterfaceTypesMod, only : hlm_current_year diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index aa6014f710..16d090af7f 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -37,7 +37,6 @@ module EDPatchDynamicsMod use PRTGenericMod , only : element_list use FatesLitterMod , only : lg_sf use FatesLitterMod , only : dl_sf - use EDTypesMod , only : dump_patch use FatesConstantsMod , only : N_DIST_TYPES use EDTypesMod , only : AREA_INV use FatesConstantsMod , only : rsnbl_math_prec @@ -487,7 +486,7 @@ subroutine spawn_patches( currentSite, bc_in) if(disturbance_rate > (1.0_r8 + rsnbl_math_prec)) then write(fates_log(),*) 'patch disturbance rate > 1 ?',disturbance_rate - call dump_patch(currentPatch) + call currentPatch%dump() call endrun(msg=errMsg(sourcefile, __LINE__)) end if diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 index 00b43bd436..90dd592ad1 100644 --- a/biogeochem/FatesPatchMod.F90 +++ b/biogeochem/FatesPatchMod.F90 @@ -4,6 +4,9 @@ module FatesPatchMod use FatesConstantsMod, only : fates_unset_r8 use FatesConstantsMod, only : fates_unset_int use FatesConstantsMod, only : primaryforest, secondaryforest + use FatesGlobals, only : fates_log + use FatesUtilsMod, only : check_hlm_list + use FatesUtilsMod, only : check_var_real use FatesCohortMod, only : fates_cohort_type use FatesRunningMeanMod, only : rmean_type use FatesLitterMod, only : nfsc @@ -16,7 +19,7 @@ module FatesPatchMod use FatesConstantsMod, only : t_water_freeze_k_1atm use FatesRunningMeanMod, only : ema_24hr, fixed_24hr, ema_lpa, ema_longterm - use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) + use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) implicit none private @@ -198,6 +201,8 @@ module FatesPatchMod procedure :: nan_values procedure :: zero_values procedure :: create + procedure :: dump + procedure :: check_vars end type fates_patch_type @@ -503,6 +508,114 @@ subroutine create(this, age, areap, label, nocomp_pft, numSWb, numpft, & this%tr_soil_dif(:) = 1.0_r8 this%NCL_p = 1 - end subroutine create + end subroutine create + + !:.........................................................................: + + subroutine dump(this) + ! + ! DESCRIPTION: + ! print attributes of a patch + ! + + ! ARGUMENTS: + class(fates_patch_type), intent(in) :: this ! patch object + + ! LOCALS: + integer :: el ! element loop counting index + + write(fates_log(),*) '----------------------------------------' + write(fates_log(),*) ' Dumping Patch Information ' + write(fates_log(),*) ' (omitting arrays) ' + write(fates_log(),*) '----------------------------------------' + write(fates_log(),*) 'pa%patchno = ',this%patchno + write(fates_log(),*) 'pa%age = ',this%age + write(fates_log(),*) 'pa%age_class = ',this%age_class + write(fates_log(),*) 'pa%area = ',this%area + write(fates_log(),*) 'pa%countcohorts = ',this%countcohorts + write(fates_log(),*) 'pa%ncl_p = ',this%ncl_p + write(fates_log(),*) 'pa%total_canopy_area = ',this%total_canopy_area + write(fates_log(),*) 'pa%total_tree_area = ',this%total_tree_area + write(fates_log(),*) 'pa%zstar = ',this%zstar + write(fates_log(),*) 'pa%solar_zenith_flag = ',this%solar_zenith_flag + write(fates_log(),*) 'pa%solar_zenith_angle = ',this%solar_zenith_angle + write(fates_log(),*) 'pa%gnd_alb_dif = ',this%gnd_alb_dif(:) + write(fates_log(),*) 'pa%gnd_alb_dir = ',this%gnd_alb_dir(:) + write(fates_log(),*) 'pa%c_stomata = ',this%c_stomata + write(fates_log(),*) 'pa%c_lblayer = ',this%c_lblayer + write(fates_log(),*) 'pa%disturbance_rates = ',this%disturbance_rates(:) + write(fates_log(),*) 'pa%anthro_disturbance_label = ',this%anthro_disturbance_label + write(fates_log(),*) '----------------------------------------' + + do el = 1, num_elements + write(fates_log(),*) 'element id: ',element_list(el) + write(fates_log(),*) 'seed mass: ',sum(this%litter(el)%seed) + write(fates_log(),*) 'seed germ mass: ',sum(this%litter(el)%seed_germ) + write(fates_log(),*) 'leaf fines(pft): ',sum(this%litter(el)%leaf_fines) + write(fates_log(),*) 'root fines(pft,sl): ',sum(this%litter(el)%root_fines) + write(fates_log(),*) 'ag_cwd(c): ',sum(this%litter(el)%ag_cwd) + write(fates_log(),*) 'bg_cwd(c,sl): ',sum(this%litter(el)%bg_cwd) + end do + + end subroutine dump + + !:.........................................................................: + + subroutine check_vars(this, var_aliases, return_code) + ! + ! DESCRIPTION: + ! perform numerical checks on patch variables of interest + ! The input string is of the form: 'VAR1_NAME:VAR2_NAME:VAR3_NAME' + ! + + ! ARGUMENTS: + class(fates_patch_type), intent(in) :: this ! patch object + character(len=*), intent(in) :: var_aliases + integer, intent(out) :: return_code ! return 0 for all fine + ! return 1 if a nan detected + ! return 10+ if an overflow + ! return 100% if an underflow + ! LOCALS: + type(fates_cohort_type), pointer :: currentCohort + + ! Check through a registry of variables to check + + if (check_hlm_list(trim(var_aliases), 'co_n')) then + currentCohort => this%shortest + do while(associated(currentCohort)) + call check_var_real(currentCohort%n, 'cohort%n', return_code) + if (.not.(return_code .eq. 0)) then + call this%dump() + call currentCohort%dump() + return + end if + currentCohort => currentCohort%taller + end do + end if + if (check_hlm_list(trim(var_aliases), 'co_dbh')) then + currentCohort => this%shortest + do while(associated(currentCohort)) + call check_var_real(currentCohort%dbh, 'cohort%dbh', return_code) + if (.not. (return_code .eq. 0)) then + call this%dump() + call currentCohort%dump() + return + end if + currentCohort => currentCohort%taller + end do + end if + + if (check_hlm_list(trim(var_aliases), 'pa_area')) then + call check_var_real(this%area, 'patch%area', return_code) + if (.not. (return_code .eq. 0)) then + call this%dump() + return + end if + end if + +end subroutine check_vars + +!:.........................................................................: + end module FatesPatchMod \ No newline at end of file diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 2394944368..8e29ca3363 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -424,9 +424,8 @@ module EDTypesMod end type ed_site_type ! Make public necessary subroutines and functions - public :: val_check_ed_vars public :: dump_site - public :: dump_patch + contains ! ===================================================================================== @@ -474,139 +473,24 @@ subroutine ZeroMassBalFlux(this) return end subroutine ZeroMassBalFlux - ! ===================================================================================== - - subroutine val_check_ed_vars(currentPatch,var_aliases,return_code) - - ! ---------------------------------------------------------------------------------- - ! Perform numerical checks on variables of interest. - ! The input string is of the form: 'VAR1_NAME:VAR2_NAME:VAR3_NAME' - ! ---------------------------------------------------------------------------------- - - - use FatesUtilsMod,only : check_hlm_list - use FatesUtilsMod,only : check_var_real - - ! Arguments - type(fates_patch_type),intent(in), target :: currentPatch - character(len=*),intent(in) :: var_aliases - integer,intent(out) :: return_code ! return 0 for all fine - ! return 1 if a nan detected - ! return 10+ if an overflow - ! return 100% if an underflow - ! Locals - type(fates_cohort_type), pointer :: currentCohort - - - ! Check through a registry of variables to check - - if ( check_hlm_list(trim(var_aliases),'co_n') ) then - - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - call check_var_real(currentCohort%n,'cohort%n',return_code) - if(.not.(return_code.eq.0)) then - call dump_patch(currentPatch) - call currentCohort%dump() - return - end if - currentCohort => currentCohort%taller - end do - end if - - if ( check_hlm_list(trim(var_aliases),'co_dbh') ) then - - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - call check_var_real(currentCohort%dbh,'cohort%dbh',return_code) - if(.not.(return_code.eq.0)) then - call dump_patch(currentPatch) - call currentCohort%dump() - return - end if - currentCohort => currentCohort%taller - end do - end if - - if ( check_hlm_list(trim(var_aliases),'pa_area') ) then - - call check_var_real(currentPatch%area,'patch%area',return_code) - if(.not.(return_code.eq.0)) then - call dump_patch(currentPatch) - return - end if - end if - - - - return - end subroutine val_check_ed_vars - ! ===================================================================================== subroutine dump_site(csite) - type(ed_site_type),intent(in),target :: csite - + type(ed_site_type),intent(in),target :: csite - ! EDTypes is - write(fates_log(),*) '----------------------------------------' - write(fates_log(),*) ' Site Coordinates ' - write(fates_log(),*) '----------------------------------------' - write(fates_log(),*) 'latitude = ', csite%lat - write(fates_log(),*) 'longitude = ', csite%lon - write(fates_log(),*) '----------------------------------------' - return + ! EDTypes is - end subroutine dump_site + write(fates_log(),*) '----------------------------------------' + write(fates_log(),*) ' Site Coordinates ' + write(fates_log(),*) '----------------------------------------' + write(fates_log(),*) 'latitude = ', csite%lat + write(fates_log(),*) 'longitude = ', csite%lon + write(fates_log(),*) '----------------------------------------' + return - ! ===================================================================================== - - - subroutine dump_patch(cpatch) - - type(fates_patch_type),intent(in),target :: cpatch - - ! locals - integer :: el ! element loop counting index - - write(fates_log(),*) '----------------------------------------' - write(fates_log(),*) ' Dumping Patch Information ' - write(fates_log(),*) ' (omitting arrays) ' - write(fates_log(),*) '----------------------------------------' - write(fates_log(),*) 'pa%patchno = ',cpatch%patchno - write(fates_log(),*) 'pa%age = ',cpatch%age - write(fates_log(),*) 'pa%age_class = ',cpatch%age_class - write(fates_log(),*) 'pa%area = ',cpatch%area - write(fates_log(),*) 'pa%countcohorts = ',cpatch%countcohorts - write(fates_log(),*) 'pa%ncl_p = ',cpatch%ncl_p - write(fates_log(),*) 'pa%total_canopy_area = ',cpatch%total_canopy_area - write(fates_log(),*) 'pa%total_tree_area = ',cpatch%total_tree_area - write(fates_log(),*) 'pa%zstar = ',cpatch%zstar - write(fates_log(),*) 'pa%solar_zenith_flag = ',cpatch%solar_zenith_flag - write(fates_log(),*) 'pa%solar_zenith_angle = ',cpatch%solar_zenith_angle - write(fates_log(),*) 'pa%gnd_alb_dif = ',cpatch%gnd_alb_dif(:) - write(fates_log(),*) 'pa%gnd_alb_dir = ',cpatch%gnd_alb_dir(:) - write(fates_log(),*) 'pa%c_stomata = ',cpatch%c_stomata - write(fates_log(),*) 'pa%c_lblayer = ',cpatch%c_lblayer - write(fates_log(),*) 'pa%disturbance_rates = ',cpatch%disturbance_rates(:) - write(fates_log(),*) 'pa%anthro_disturbance_label = ',cpatch%anthro_disturbance_label - write(fates_log(),*) '----------------------------------------' - do el = 1,num_elements - write(fates_log(),*) 'element id: ',element_list(el) - write(fates_log(),*) 'seed mass: ',sum(cpatch%litter(el)%seed) - write(fates_log(),*) 'seed germ mass: ',sum(cpatch%litter(el)%seed_germ) - write(fates_log(),*) 'leaf fines(pft): ',sum(cpatch%litter(el)%leaf_fines) - write(fates_log(),*) 'root fines(pft,sl): ',sum(cpatch%litter(el)%root_fines) - write(fates_log(),*) 'ag_cwd(c): ',sum(cpatch%litter(el)%ag_cwd) - write(fates_log(),*) 'bg_cwd(c,sl): ',sum(cpatch%litter(el)%bg_cwd) - end do - - return - - end subroutine dump_patch - - ! ===================================================================================== +end subroutine dump_site + end module EDTypesMod From 3a391a72826423c83315687a4ffbdc0e56d6a75f Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 11 Apr 2023 06:44:32 -0600 Subject: [PATCH 620/852] add allocate statement --- biogeochem/EDPatchDynamicsMod.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 16d090af7f..5674857236 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -560,6 +560,7 @@ subroutine spawn_patches( currentSite, bc_in) ! next create patch to receive secondary forest area if (site_areadis_secondary .gt. nearzero) then + allocate(new_patch_secondary) call new_patch_secondary%create(age, site_areadis_secondary, & secondaryforest, i_nocomp_pft, hlm_numSWb, numpft, & currentSite%nlevsoil, hlm_current_tod) From 2b06387f680ea156544713e0f187c26eaac29350 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 11 Apr 2023 10:01:54 -0600 Subject: [PATCH 621/852] add unit testing folder --- unit_testing/FatesUnitTestIOMod.F90 | 312 ++++++++++++ unit_testing/FatesUnitTestOrbitalMod.F90 | 581 +++++++++++++++++++++++ unit_testing/test_norman.f90 | 81 ++++ 3 files changed, 974 insertions(+) create mode 100644 unit_testing/FatesUnitTestIOMod.F90 create mode 100644 unit_testing/FatesUnitTestOrbitalMod.F90 create mode 100644 unit_testing/test_norman.f90 diff --git a/unit_testing/FatesUnitTestIOMod.F90 b/unit_testing/FatesUnitTestIOMod.F90 new file mode 100644 index 0000000000..200517388e --- /dev/null +++ b/unit_testing/FatesUnitTestIOMod.F90 @@ -0,0 +1,312 @@ +module FatesUnitTestIOMod + use FatesConstantsMod, only : fates_r8 => r8 + use netcdf + + implicit none + +! LOCALS +integer, parameter :: BASE_UNIT = 10 ! Base unit for files the first time unit_number is called +integer, parameter :: MAX_PATH = 256 ! Maximum path length +integer, parameter :: MAX_CHAR = 80 ! Maximum length for messages +integer :: logf ! Unit number for output log file + +contains + + integer function unit_number() +! +! DESCRIPTION: +! Generates a unit number to be used in opening files +! The first time the function is called, it returns BASE_UNIT +! +! LOCALS: +integer :: iunit ! File unit (increments after first call) +logical :: first = .true. ! First time this has been called? +save + +if (first) then + ! Set first to false and iunit to base unit on first call + iunit = BASE_UNIT + first = .false. +else + ! Otherwise, increment + iunit = iunit + 1 +endif + +! Set to output +unit_number = iunit + + end function unit_number + + !:...........................................................................: + + integer function open_file(filename, mode) + ! + ! DESCRIPTION: + ! Opens the file filename if it can, returns a unit number for it. + ! The first time the function is called, it returns BASE_UNIT + + ! ARGUMENTS: + character(len = *), intent(in) :: filename ! Name of file to open + character(len = *), intent(in), optional :: mode ! Optional mode ('r', 'w', 'rw') + + ! LOCALS: + character(len = 9) :: fmode ! File open mode + logical :: file_exists ! Does the file exist? + character(len = MAX_PATH) :: fname ! Local filename (trimmed) + character(len = MAX_CHAR) :: message ! Error message + integer :: i ! Looping index + integer :: ios ! I/O status + integer :: iunit = BASE_UNIT ! File unit number + integer, dimension(MAX_PATH) :: farray ! Array of characters of file name + + ! Get mode of open (read, write, or read/write) + ! Defaults to read/write + if (present(mode)) then + select case(mode) + case ('r', 'R') + fmode = 'read' + case ('w', 'W') + fmode = 'write' + case ('rw', 'RW', 'wr', 'WR') + fmode = 'readwrite' + case DEFAULT + fmode = 'readwrite' + end select + else + fmode = 'readwrite' + endif + + ! trim filename of whitespace + fname = trim(adjustl(filename)) + + if (fmode == 'read' .or. fmode == 'readwrite') then + ! Check for valid name of file + farray = 0 + do i = 1, len_trim(fname) + farray(i) = ichar(fname(i:i)) + enddo + if (any(farray > 126)) then + write(*,*) "Invalid filename" + stop "Stopped" + endif + endif + + ! Does the file exist? + inquire(file = fname, exist = file_exists) + + ! Open file if conditions are correct + if (file_exists .and. fmode == 'write') then + write(message, '(A,A,A)') "File ", fname(1:len_trim(fname)), & + " exists. Cannot open write only." + write(*,*) message + stop "Stopped" + else if (.not. file_exists .and. fmode == 'read') then + write(message, '(A,A,A)') "File ", fname(1:len_trim(fname)), & + " does not exist. Can't read." + write(*,*) message + stop "Stopped" + else + iunit = unit_number() + open(iunit, file = fname, action = fmode, iostat = ios) + if (ios /= 0) then + write(message, '(A,A,A,I6)') "Problem opening", & + fname(1:len_trim(fname)), " ios: ", ios + write(*,*) message + stop "Stopped" + endif + endif + + open_file = iunit + + end function open_file + + !:...........................................................................: + + subroutine write_radiation_data(file, kdir, declin) + character(len=100), intent(in) :: file ! output file name + real(r8), intent(in) :: kdir(num_pft, 48) ! direct beam extinction coefficient + real(r8), intent(in) :: declin(48) + + integer :: ncid + integer :: pft_dimid, time_dimid + integer :: kdir_id, declin_id + integer :: dimids(2) + + ! Create the netCDF file. The nf90_clobber parameter tells netCDF to + ! overwrite this file, if it already exists. + call check(nf90_create(trim(file), NF90_CLOBBER, ncid)) + + ! define dimensions + call check(nf90_def_dim(ncid, "pft", num_pft, pft_dimid)) + call check(nf90_def_dim(ncid, "time", 48, time_dimid)) + + ! define the variables + dimids = (/ pft_dimid, time_dimid/) + call check(nf90_def_var(ncid, "kdir", NF90_REAL8, dimids, kdir_id)) + call check(nf90_def_var(ncid, "declin", NF90_REAL8, time_dimid, declin_id)) + + ! end define mode + call check(nf90_enddef(ncid)) + + ! write to file. + call check(nf90_put_var(ncid, kdir_id, kdir)) + call check(nf90_put_var(ncid, declin_id, declin)) + + ! close the file. + call check(nf90_close(ncid)) + + end subroutine write_radiation_data + + !:...........................................................................: + + subroutine check(status) + ! + ! DESCRIPTION: + ! Checks status of netcdf operations + + ! ARGUMENTS: + integer, intent (in) :: status ! return status code from a netcdf procedure + + if (status /= nf90_noerr) then + print *, trim(nf90_strerror(status)) + stop "Stopped" + end if + + end subroutine check + + !:...........................................................................: + + subroutine read_patch_data(file, canopy_area, elai, esai, nrad) + ! + ! DESCRIPTION: + ! Reads and return patch data + + ! ARGUMENTS: + character(len=100), intent(in) :: file ! patch file name + real(r8), intent(out) :: canopy_area(num_can,num_pft,nlevleaf) ! canopy area profile + real(r8), intent(out) :: elai(num_can,num_pft,nlevleaf) ! exposed lai profile + real(r8), intent(out) :: esai(num_can,num_pft,nlevleaf) ! exposed sai profile + real(r8), intent(out) :: nrad(num_can,num_pft) ! number of exposed leaf layers + + ! Data dictionary: declare variable types, definitions, and units + real(r8) :: nrad_r(num_can,num_pft) ! number of exposed leaf layers + integer :: fidA, varID + + ! open file + call check(nf90_open(trim(file), 0, fidA)) + + ! read patch data values + call check(nf90_inq_varid(fidA, "can_area", varID)) + call check(nf90_get_var(fidA, varID, canopy_area)) + + call check(nf90_inq_varid(fidA, "elai", varID)) + call check(nf90_get_var(fidA, varID, elai)) + + call check(nf90_inq_varid(fidA, "esai", varID)) + call check(nf90_get_var(fidA, varID, esai)) + + call check(nf90_inq_varid(fidA, "nrad", varID)) + call check(nf90_get_var(fidA, varID, nrad)) + + end subroutine read_patch_data + + !:...........................................................................: + + subroutine get_parameters(file, rhol, rhos, taul, taus, xl, ci) + ! + ! Purpose: + ! Returns parameter values + ! + ! Record of revisions: + ! Date Programmer Description of change + ! ======== ============= ===================== + ! 03/20/23 A. C. Foster Original code + ! + + ! Data dictionary: declare calling parameter types & definitions + character(len=100), intent(in) :: file ! parameter file name + real(r8), intent(out) :: rhol(num_pft,num_swb) ! leaf reflectance + real(r8), intent(out) :: rhos(num_pft,num_swb) ! stem reflectance + real(r8), intent(out) :: taul(num_pft,num_swb) ! leaf transmittance + real(r8), intent(out) :: taus(num_pft,num_swb) ! stem transmittance + real(r8), intent(out) :: xl(num_pft) ! leaf orientation index + real(r8), intent(out) :: ci(num_pft) ! clumping index + + ! read in all parameters + call read_param_netcdf(file, rhol(:,1), rhol(:,2), rhos(:,1), rhos(:,2), & + taul(:,1), taul(:,2), taus(:,1), taus(:,2), xl, ci) + + end subroutine get_parameters + + !:...........................................................................: + + subroutine read_param_netcdf(file, rholvis, rholnir, rhosvis, rhosnir, & + taulvis, taulnir, tausvis, tausnir, xl, ci) + ! + ! Purpose: + ! Reads a FATES netcdf parameter file + ! + ! Record of revisions: + ! Date Programmer Description of change + ! ======== ============= ===================== + ! 03/20/23 A. C. Foster Original code + ! + + ! Data dictionary: declare calling parameter types & definitions + character(len=100), intent(in) :: file ! parameter file name + real(r8), intent(out) :: rholvis(num_pft) ! vis leaf reflectance + real(r8), intent(out) :: rholnir(num_pft) ! nir leaf reflectance + real(r8), intent(out) :: rhosvis(num_pft) ! vis stem reflectance + real(r8), intent(out) :: rhosnir(num_pft) ! nir stem reflectance + real(r8), intent(out) :: taulvis(num_pft) ! vis leaf transmittance + real(r8), intent(out) :: taulnir(num_pft) ! nir leaf transmittance + real(r8), intent(out) :: tausvis(num_pft) ! vis stem transmittance + real(r8), intent(out) :: tausnir(num_pft) ! nir stem transmittance + real(r8), intent(out) :: xl(num_pft) ! leaf orientation index + real(r8), intent(out) :: ci(num_pft) ! clumping index + + ! Data dictionary: declare variable types, definitions, and units + integer :: fidA, paramID + + ! open file + call check(nf90_open(trim(file), 0, fidA)) + + ! read parameter values + call check(nf90_inq_varid(fidA, "fates_rad_leaf_rhovis", paramID)) + call check(nf90_get_var(fidA, paramID, rholvis)) + + call check(nf90_inq_varid(fidA, "fates_rad_leaf_rhonir", paramID)) + call check(nf90_get_var(fidA, paramID, rholnir)) + + call check(nf90_inq_varid(fidA, "fates_rad_stem_rhovis", paramID)) + call check(nf90_get_var(fidA, paramID, rhosvis)) + + call check(nf90_inq_varid(fidA, "fates_rad_stem_rhonir", paramID)) + call check(nf90_get_var(fidA, paramID, rhosnir)) + + call check(nf90_inq_varid(fidA, "fates_rad_leaf_tauvis", paramID)) + call check(nf90_get_var(fidA, paramID, taulvis)) + + call check(nf90_inq_varid(fidA, "fates_rad_leaf_taunir", paramID)) + call check(nf90_get_var(fidA, paramID, taulnir)) + + call check(nf90_inq_varid(fidA, "fates_rad_stem_tauvis", paramID)) + call check(nf90_get_var(fidA, paramID, tausvis)) + + call check(nf90_inq_varid(fidA, "fates_rad_stem_taunir", paramID)) + call check(nf90_get_var(fidA, paramID, tausnir)) + + call check(nf90_inq_varid(fidA, "fates_rad_leaf_xl", paramID)) + call check(nf90_get_var(fidA, paramID, xl)) + + call check(nf90_inq_varid(fidA, "fates_rad_leaf_clumping_index", paramID)) + call check(nf90_get_var(fidA, paramID, ci)) + + ! close file + call check(nf90_close(fidA)) + + end subroutine read_param_netcdf + + !:...........................................................................: + +end module FatesUnitTestIOMod \ No newline at end of file diff --git a/unit_testing/FatesUnitTestOrbitalMod.F90 b/unit_testing/FatesUnitTestOrbitalMod.F90 new file mode 100644 index 0000000000..545baf398c --- /dev/null +++ b/unit_testing/FatesUnitTestOrbitalMod.F90 @@ -0,0 +1,581 @@ +module OrbitalValsMod + ! + ! DESCRIPTION: + ! Helper procedures for getting orbital values + ! Copied from shr_orb_mod from https://github.com/ESCOMP/CESM_share + ! + ! + + use IOMod + + implicit none + + integer, parameter :: SHR_KIND_R8 = selected_real_kind(12) ! 8 byte real + integer, parameter :: SHR_KIND_IN = kind(1) ! native integer + real(SHR_KIND_R8), parameter :: pi = 3.14159265358979323846_SHR_KIND_R8 + real(SHR_KIND_R8), parameter :: SHR_ORB_ECCEN_MIN = 0.0_SHR_KIND_R8 ! min value for eccen + real(SHR_KIND_R8), parameter :: SHR_ORB_ECCEN_MAX = 0.1_SHR_KIND_R8 ! max value for eccen + real(SHR_KIND_R8), parameter :: SHR_ORB_OBLIQ_MIN = -90.0_SHR_KIND_R8 ! min value for obliq + real(SHR_KIND_R8), parameter :: SHR_ORB_OBLIQ_MAX = +90.0_SHR_KIND_R8 ! max value for obliq + real(SHR_KIND_R8), parameter :: SHR_ORB_MVELP_MIN = 0.0_SHR_KIND_R8 ! min value for mvelp + real(SHR_KIND_R8), parameter :: SHR_ORB_MVELP_MAX = 360.0_SHR_KIND_R8 ! max value for mvelp + integer(SHR_KIND_IN), parameter :: SHR_ORB_UNDEF_INT = 2000000000 ! undefined int + real(SHR_KIND_R8), parameter :: SHR_ORB_UNDEF_REAL = 1.e36_SHR_KIND_R8 ! undefined real + + contains + + subroutine get_orbital_vals(iyear_AD, s_logunit, eccen, mvelp, obliqr, & + lambm0, mvelpp) + ! + ! Gets orbital values for a specific day + ! + + ! Data dictionary: calling arguments + integer(SHR_KIND_IN), intent(in) :: iyear_AD ! Year to calculate orbit for + integer, intent(in) :: s_logunit ! log file unit number + real(SHR_KIND_R8), intent(out) :: eccen ! orbital eccentricity + real(SHR_KIND_R8), intent(out) :: mvelp ! moving vernal equinox long + real(SHR_KIND_R8), intent(out) :: obliqr ! Earths obliquity in rad + real(SHR_KIND_R8), intent(out) :: lambm0 ! Mean long of perihelion at vernal equinox (radians) + real(SHR_KIND_R8), intent(out) :: mvelpp ! moving vernal equinox long of perihelion plus pi (rad) + + real(SHR_KIND_R8) :: obliq ! obliquity in degrees + + obliq = SHR_ORB_UNDEF_REAL + eccen = SHR_ORB_UNDEF_REAL + mvelp = SHR_ORB_UNDEF_REAL + + call shr_orb_params(iyear_AD, eccen, obliq, mvelp, obliqr, lambm0, & + mvelpp, s_logunit) + + end subroutine get_orbital_vals + + !:.........................................................................: + + subroutine shr_orb_params(iyear_AD, eccen, obliq, mvelp, & + obliqr, lambm0, mvelpp, s_logunit) + + !--------------------------------------------------------------------------- + ! + ! Calculate earths orbital parameters using Dave Threshers formula which + ! came from Berger, Andre. 1978 "A Simple Algorithm to Compute Long-Term + ! Variations of Daily Insolation". Contribution 18, Institute of Astronomy + ! and Geophysics, Universite Catholique de Louvain, Louvain-la-Neuve, Belgium + ! + !------------------------------Code history--------------------------------- + ! + ! Original Author: Erik Kluzek + ! Date: Oct/97 + ! + !--------------------------------------------------------------------------- + + !----------------------------- Arguments ------------------------------------ + integer(SHR_KIND_IN), intent(in) :: iyear_AD ! Year to calculate orbit for + real(SHR_KIND_R8), intent(inout) :: eccen ! orbital eccentricity + real(SHR_KIND_R8), intent(inout) :: obliq ! obliquity in degrees + real(SHR_KIND_R8), intent(inout) :: mvelp ! moving vernal equinox long + real(SHR_KIND_R8), intent(out) :: obliqr ! Earths obliquity in rad + real(SHR_KIND_R8), intent(out) :: lambm0 ! Mean long of perihelion at vernal equinox (radians) + real(SHR_KIND_R8), intent(out) :: mvelpp ! moving vernal equinox long of perihelion plus pi (rad) + integer, intent(in) :: s_logunit ! log file unit number + + !------------------------------ Parameters ---------------------------------- + integer(SHR_KIND_IN), parameter :: poblen = 47 ! # of elements in series wrt obliquity + integer(SHR_KIND_IN), parameter :: pecclen = 19 ! # of elements in series wrt eccentricity + integer(SHR_KIND_IN), parameter :: pmvelen = 78 ! # of elements in series wrt vernal equinox + real(SHR_KIND_R8), parameter :: psecdeg = 1.0_SHR_KIND_R8/3600.0_SHR_KIND_R8 ! arc sec to deg conversion + + real(SHR_KIND_R8) :: degrad = pi/180._SHR_KIND_R8 ! degree to radian conversion factor + real(SHR_KIND_R8) :: yb4_1950AD ! number of years before 1950 AD + + ! Cosine series data for computation of obliquity: amplitude (arc seconds), + ! rate (arc seconds/year), phase (degrees). + + real (SHR_KIND_R8), parameter :: obamp(poblen) = & ! amplitudes for obliquity cos series + & (/ -2462.2214466_SHR_KIND_R8, -857.3232075_SHR_KIND_R8, -629.3231835_SHR_KIND_R8, & + & -414.2804924_SHR_KIND_R8, -311.7632587_SHR_KIND_R8, 308.9408604_SHR_KIND_R8, & + & -162.5533601_SHR_KIND_R8, -116.1077911_SHR_KIND_R8, 101.1189923_SHR_KIND_R8, & + & -67.6856209_SHR_KIND_R8, 24.9079067_SHR_KIND_R8, 22.5811241_SHR_KIND_R8, & + & -21.1648355_SHR_KIND_R8, -15.6549876_SHR_KIND_R8, 15.3936813_SHR_KIND_R8, & + & 14.6660938_SHR_KIND_R8, -11.7273029_SHR_KIND_R8, 10.2742696_SHR_KIND_R8, & + & 6.4914588_SHR_KIND_R8, 5.8539148_SHR_KIND_R8, -5.4872205_SHR_KIND_R8, & + & -5.4290191_SHR_KIND_R8, 5.1609570_SHR_KIND_R8, 5.0786314_SHR_KIND_R8, & + & -4.0735782_SHR_KIND_R8, 3.7227167_SHR_KIND_R8, 3.3971932_SHR_KIND_R8, & + & -2.8347004_SHR_KIND_R8, -2.6550721_SHR_KIND_R8, -2.5717867_SHR_KIND_R8, & + & -2.4712188_SHR_KIND_R8, 2.4625410_SHR_KIND_R8, 2.2464112_SHR_KIND_R8, & + & -2.0755511_SHR_KIND_R8, -1.9713669_SHR_KIND_R8, -1.8813061_SHR_KIND_R8, & + & -1.8468785_SHR_KIND_R8, 1.8186742_SHR_KIND_R8, 1.7601888_SHR_KIND_R8, & + & -1.5428851_SHR_KIND_R8, 1.4738838_SHR_KIND_R8, -1.4593669_SHR_KIND_R8, & + & 1.4192259_SHR_KIND_R8, -1.1818980_SHR_KIND_R8, 1.1756474_SHR_KIND_R8, & + & -1.1316126_SHR_KIND_R8, 1.0896928_SHR_KIND_R8/) + + real (SHR_KIND_R8), parameter :: obrate(poblen) = & ! rates for obliquity cosine series + & (/ 31.609974_SHR_KIND_R8, 32.620504_SHR_KIND_R8, 24.172203_SHR_KIND_R8, & + & 31.983787_SHR_KIND_R8, 44.828336_SHR_KIND_R8, 30.973257_SHR_KIND_R8, & + & 43.668246_SHR_KIND_R8, 32.246691_SHR_KIND_R8, 30.599444_SHR_KIND_R8, & + & 42.681324_SHR_KIND_R8, 43.836462_SHR_KIND_R8, 47.439436_SHR_KIND_R8, & + & 63.219948_SHR_KIND_R8, 64.230478_SHR_KIND_R8, 1.010530_SHR_KIND_R8, & + & 7.437771_SHR_KIND_R8, 55.782177_SHR_KIND_R8, 0.373813_SHR_KIND_R8, & + & 13.218362_SHR_KIND_R8, 62.583231_SHR_KIND_R8, 63.593761_SHR_KIND_R8, & + & 76.438310_SHR_KIND_R8, 45.815258_SHR_KIND_R8, 8.448301_SHR_KIND_R8, & + & 56.792707_SHR_KIND_R8, 49.747842_SHR_KIND_R8, 12.058272_SHR_KIND_R8, & + & 75.278220_SHR_KIND_R8, 65.241008_SHR_KIND_R8, 64.604291_SHR_KIND_R8, & + & 1.647247_SHR_KIND_R8, 7.811584_SHR_KIND_R8, 12.207832_SHR_KIND_R8, & + & 63.856665_SHR_KIND_R8, 56.155990_SHR_KIND_R8, 77.448840_SHR_KIND_R8, & + & 6.801054_SHR_KIND_R8, 62.209418_SHR_KIND_R8, 20.656133_SHR_KIND_R8, & + & 48.344406_SHR_KIND_R8, 55.145460_SHR_KIND_R8, 69.000539_SHR_KIND_R8, & + & 11.071350_SHR_KIND_R8, 74.291298_SHR_KIND_R8, 11.047742_SHR_KIND_R8, & + & 0.636717_SHR_KIND_R8, 12.844549_SHR_KIND_R8/) + + real (SHR_KIND_R8), parameter :: obphas(poblen) = & ! phases for obliquity cosine series + & (/ 251.9025_SHR_KIND_R8, 280.8325_SHR_KIND_R8, 128.3057_SHR_KIND_R8, & + & 292.7252_SHR_KIND_R8, 15.3747_SHR_KIND_R8, 263.7951_SHR_KIND_R8, & + & 308.4258_SHR_KIND_R8, 240.0099_SHR_KIND_R8, 222.9725_SHR_KIND_R8, & + & 268.7809_SHR_KIND_R8, 316.7998_SHR_KIND_R8, 319.6024_SHR_KIND_R8, & + & 143.8050_SHR_KIND_R8, 172.7351_SHR_KIND_R8, 28.9300_SHR_KIND_R8, & + & 123.5968_SHR_KIND_R8, 20.2082_SHR_KIND_R8, 40.8226_SHR_KIND_R8, & + & 123.4722_SHR_KIND_R8, 155.6977_SHR_KIND_R8, 184.6277_SHR_KIND_R8, & + & 267.2772_SHR_KIND_R8, 55.0196_SHR_KIND_R8, 152.5268_SHR_KIND_R8, & + & 49.1382_SHR_KIND_R8, 204.6609_SHR_KIND_R8, 56.5233_SHR_KIND_R8, & + & 200.3284_SHR_KIND_R8, 201.6651_SHR_KIND_R8, 213.5577_SHR_KIND_R8, & + & 17.0374_SHR_KIND_R8, 164.4194_SHR_KIND_R8, 94.5422_SHR_KIND_R8, & + & 131.9124_SHR_KIND_R8, 61.0309_SHR_KIND_R8, 296.2073_SHR_KIND_R8, & + & 135.4894_SHR_KIND_R8, 114.8750_SHR_KIND_R8, 247.0691_SHR_KIND_R8, & + & 256.6114_SHR_KIND_R8, 32.1008_SHR_KIND_R8, 143.6804_SHR_KIND_R8, & + & 16.8784_SHR_KIND_R8, 160.6835_SHR_KIND_R8, 27.5932_SHR_KIND_R8, & + & 348.1074_SHR_KIND_R8, 82.6496_SHR_KIND_R8/) + + ! Cosine/sine series data for computation of eccentricity and fixed vernal + ! equinox longitude of perihelion (fvelp): amplitude, + ! rate (arc seconds/year), phase (degrees). + + real (SHR_KIND_R8), parameter :: ecamp (pecclen) = & ! ampl for eccen/fvelp cos/sin series + & (/ 0.01860798_SHR_KIND_R8, 0.01627522_SHR_KIND_R8, -0.01300660_SHR_KIND_R8, & + & 0.00988829_SHR_KIND_R8, -0.00336700_SHR_KIND_R8, 0.00333077_SHR_KIND_R8, & + & -0.00235400_SHR_KIND_R8, 0.00140015_SHR_KIND_R8, 0.00100700_SHR_KIND_R8, & + & 0.00085700_SHR_KIND_R8, 0.00064990_SHR_KIND_R8, 0.00059900_SHR_KIND_R8, & + & 0.00037800_SHR_KIND_R8, -0.00033700_SHR_KIND_R8, 0.00027600_SHR_KIND_R8, & + & 0.00018200_SHR_KIND_R8, -0.00017400_SHR_KIND_R8, -0.00012400_SHR_KIND_R8, & + & 0.00001250_SHR_KIND_R8/) + + real (SHR_KIND_R8), parameter :: ecrate(pecclen) = & ! rates for eccen/fvelp cos/sin series + & (/ 4.2072050_SHR_KIND_R8, 7.3460910_SHR_KIND_R8, 17.8572630_SHR_KIND_R8, & + & 17.2205460_SHR_KIND_R8, 16.8467330_SHR_KIND_R8, 5.1990790_SHR_KIND_R8, & + & 18.2310760_SHR_KIND_R8, 26.2167580_SHR_KIND_R8, 6.3591690_SHR_KIND_R8, & + & 16.2100160_SHR_KIND_R8, 3.0651810_SHR_KIND_R8, 16.5838290_SHR_KIND_R8, & + & 18.4939800_SHR_KIND_R8, 6.1909530_SHR_KIND_R8, 18.8677930_SHR_KIND_R8, & + & 17.4255670_SHR_KIND_R8, 6.1860010_SHR_KIND_R8, 18.4174410_SHR_KIND_R8, & + & 0.6678630_SHR_KIND_R8/) + + real (SHR_KIND_R8), parameter :: ecphas(pecclen) = & ! phases for eccen/fvelp cos/sin series + & (/ 28.620089_SHR_KIND_R8, 193.788772_SHR_KIND_R8, 308.307024_SHR_KIND_R8, & + & 320.199637_SHR_KIND_R8, 279.376984_SHR_KIND_R8, 87.195000_SHR_KIND_R8, & + & 349.129677_SHR_KIND_R8, 128.443387_SHR_KIND_R8, 154.143880_SHR_KIND_R8, & + & 291.269597_SHR_KIND_R8, 114.860583_SHR_KIND_R8, 332.092251_SHR_KIND_R8, & + & 296.414411_SHR_KIND_R8, 145.769910_SHR_KIND_R8, 337.237063_SHR_KIND_R8, & + & 152.092288_SHR_KIND_R8, 126.839891_SHR_KIND_R8, 210.667199_SHR_KIND_R8, & + & 72.108838_SHR_KIND_R8/) + + ! Sine series data for computation of moving vernal equinox longitude of + ! perihelion: amplitude (arc seconds), rate (arc sec/year), phase (degrees). + + real (SHR_KIND_R8), parameter :: mvamp (pmvelen) = & ! amplitudes for mvelp sine series + & (/ 7391.0225890_SHR_KIND_R8, 2555.1526947_SHR_KIND_R8, 2022.7629188_SHR_KIND_R8, & + & -1973.6517951_SHR_KIND_R8, 1240.2321818_SHR_KIND_R8, 953.8679112_SHR_KIND_R8, & + & -931.7537108_SHR_KIND_R8, 872.3795383_SHR_KIND_R8, 606.3544732_SHR_KIND_R8, & + & -496.0274038_SHR_KIND_R8, 456.9608039_SHR_KIND_R8, 346.9462320_SHR_KIND_R8, & + & -305.8412902_SHR_KIND_R8, 249.6173246_SHR_KIND_R8, -199.1027200_SHR_KIND_R8, & + & 191.0560889_SHR_KIND_R8, -175.2936572_SHR_KIND_R8, 165.9068833_SHR_KIND_R8, & + & 161.1285917_SHR_KIND_R8, 139.7878093_SHR_KIND_R8, -133.5228399_SHR_KIND_R8, & + & 117.0673811_SHR_KIND_R8, 104.6907281_SHR_KIND_R8, 95.3227476_SHR_KIND_R8, & + & 86.7824524_SHR_KIND_R8, 86.0857729_SHR_KIND_R8, 70.5893698_SHR_KIND_R8, & + & -69.9719343_SHR_KIND_R8, -62.5817473_SHR_KIND_R8, 61.5450059_SHR_KIND_R8, & + & -57.9364011_SHR_KIND_R8, 57.1899832_SHR_KIND_R8, -57.0236109_SHR_KIND_R8, & + & -54.2119253_SHR_KIND_R8, 53.2834147_SHR_KIND_R8, 52.1223575_SHR_KIND_R8, & + & -49.0059908_SHR_KIND_R8, -48.3118757_SHR_KIND_R8, -45.4191685_SHR_KIND_R8, & + & -42.2357920_SHR_KIND_R8, -34.7971099_SHR_KIND_R8, 34.4623613_SHR_KIND_R8, & + & -33.8356643_SHR_KIND_R8, 33.6689362_SHR_KIND_R8, -31.2521586_SHR_KIND_R8, & + & -30.8798701_SHR_KIND_R8, 28.4640769_SHR_KIND_R8, -27.1960802_SHR_KIND_R8, & + & 27.0860736_SHR_KIND_R8, -26.3437456_SHR_KIND_R8, 24.7253740_SHR_KIND_R8, & + & 24.6732126_SHR_KIND_R8, 24.4272733_SHR_KIND_R8, 24.0127327_SHR_KIND_R8, & + & 21.7150294_SHR_KIND_R8, -21.5375347_SHR_KIND_R8, 18.1148363_SHR_KIND_R8, & + & -16.9603104_SHR_KIND_R8, -16.1765215_SHR_KIND_R8, 15.5567653_SHR_KIND_R8, & + & 15.4846529_SHR_KIND_R8, 15.2150632_SHR_KIND_R8, 14.5047426_SHR_KIND_R8, & + & -14.3873316_SHR_KIND_R8, 13.1351419_SHR_KIND_R8, 12.8776311_SHR_KIND_R8, & + & 11.9867234_SHR_KIND_R8, 11.9385578_SHR_KIND_R8, 11.7030822_SHR_KIND_R8, & + & 11.6018181_SHR_KIND_R8, -11.2617293_SHR_KIND_R8, -10.4664199_SHR_KIND_R8, & + & 10.4333970_SHR_KIND_R8, -10.2377466_SHR_KIND_R8, 10.1934446_SHR_KIND_R8, & + & -10.1280191_SHR_KIND_R8, 10.0289441_SHR_KIND_R8, -10.0034259_SHR_KIND_R8/) + + real (SHR_KIND_R8), parameter :: mvrate(pmvelen) = & ! rates for mvelp sine series + & (/ 31.609974_SHR_KIND_R8, 32.620504_SHR_KIND_R8, 24.172203_SHR_KIND_R8, & + & 0.636717_SHR_KIND_R8, 31.983787_SHR_KIND_R8, 3.138886_SHR_KIND_R8, & + & 30.973257_SHR_KIND_R8, 44.828336_SHR_KIND_R8, 0.991874_SHR_KIND_R8, & + & 0.373813_SHR_KIND_R8, 43.668246_SHR_KIND_R8, 32.246691_SHR_KIND_R8, & + & 30.599444_SHR_KIND_R8, 2.147012_SHR_KIND_R8, 10.511172_SHR_KIND_R8, & + & 42.681324_SHR_KIND_R8, 13.650058_SHR_KIND_R8, 0.986922_SHR_KIND_R8, & + & 9.874455_SHR_KIND_R8, 13.013341_SHR_KIND_R8, 0.262904_SHR_KIND_R8, & + & 0.004952_SHR_KIND_R8, 1.142024_SHR_KIND_R8, 63.219948_SHR_KIND_R8, & + & 0.205021_SHR_KIND_R8, 2.151964_SHR_KIND_R8, 64.230478_SHR_KIND_R8, & + & 43.836462_SHR_KIND_R8, 47.439436_SHR_KIND_R8, 1.384343_SHR_KIND_R8, & + & 7.437771_SHR_KIND_R8, 18.829299_SHR_KIND_R8, 9.500642_SHR_KIND_R8, & + & 0.431696_SHR_KIND_R8, 1.160090_SHR_KIND_R8, 55.782177_SHR_KIND_R8, & + & 12.639528_SHR_KIND_R8, 1.155138_SHR_KIND_R8, 0.168216_SHR_KIND_R8, & + & 1.647247_SHR_KIND_R8, 10.884985_SHR_KIND_R8, 5.610937_SHR_KIND_R8, & + & 12.658184_SHR_KIND_R8, 1.010530_SHR_KIND_R8, 1.983748_SHR_KIND_R8, & + & 14.023871_SHR_KIND_R8, 0.560178_SHR_KIND_R8, 1.273434_SHR_KIND_R8, & + & 12.021467_SHR_KIND_R8, 62.583231_SHR_KIND_R8, 63.593761_SHR_KIND_R8, & + & 76.438310_SHR_KIND_R8, 4.280910_SHR_KIND_R8, 13.218362_SHR_KIND_R8, & + & 17.818769_SHR_KIND_R8, 8.359495_SHR_KIND_R8, 56.792707_SHR_KIND_R8, & + & 8.448301_SHR_KIND_R8, 1.978796_SHR_KIND_R8, 8.863925_SHR_KIND_R8, & + & 0.186365_SHR_KIND_R8, 8.996212_SHR_KIND_R8, 6.771027_SHR_KIND_R8, & + & 45.815258_SHR_KIND_R8, 12.002811_SHR_KIND_R8, 75.278220_SHR_KIND_R8, & + & 65.241008_SHR_KIND_R8, 18.870667_SHR_KIND_R8, 22.009553_SHR_KIND_R8, & + & 64.604291_SHR_KIND_R8, 11.498094_SHR_KIND_R8, 0.578834_SHR_KIND_R8, & + & 9.237738_SHR_KIND_R8, 49.747842_SHR_KIND_R8, 2.147012_SHR_KIND_R8, & + & 1.196895_SHR_KIND_R8, 2.133898_SHR_KIND_R8, 0.173168_SHR_KIND_R8/) + + real (SHR_KIND_R8), parameter :: mvphas(pmvelen) = & ! phases for mvelp sine series + & (/ 251.9025_SHR_KIND_R8, 280.8325_SHR_KIND_R8, 128.3057_SHR_KIND_R8, & + & 348.1074_SHR_KIND_R8, 292.7252_SHR_KIND_R8, 165.1686_SHR_KIND_R8, & + & 263.7951_SHR_KIND_R8, 15.3747_SHR_KIND_R8, 58.5749_SHR_KIND_R8, & + & 40.8226_SHR_KIND_R8, 308.4258_SHR_KIND_R8, 240.0099_SHR_KIND_R8, & + & 222.9725_SHR_KIND_R8, 106.5937_SHR_KIND_R8, 114.5182_SHR_KIND_R8, & + & 268.7809_SHR_KIND_R8, 279.6869_SHR_KIND_R8, 39.6448_SHR_KIND_R8, & + & 126.4108_SHR_KIND_R8, 291.5795_SHR_KIND_R8, 307.2848_SHR_KIND_R8, & + & 18.9300_SHR_KIND_R8, 273.7596_SHR_KIND_R8, 143.8050_SHR_KIND_R8, & + & 191.8927_SHR_KIND_R8, 125.5237_SHR_KIND_R8, 172.7351_SHR_KIND_R8, & + & 316.7998_SHR_KIND_R8, 319.6024_SHR_KIND_R8, 69.7526_SHR_KIND_R8, & + & 123.5968_SHR_KIND_R8, 217.6432_SHR_KIND_R8, 85.5882_SHR_KIND_R8, & + & 156.2147_SHR_KIND_R8, 66.9489_SHR_KIND_R8, 20.2082_SHR_KIND_R8, & + & 250.7568_SHR_KIND_R8, 48.0188_SHR_KIND_R8, 8.3739_SHR_KIND_R8, & + & 17.0374_SHR_KIND_R8, 155.3409_SHR_KIND_R8, 94.1709_SHR_KIND_R8, & + & 221.1120_SHR_KIND_R8, 28.9300_SHR_KIND_R8, 117.1498_SHR_KIND_R8, & + & 320.5095_SHR_KIND_R8, 262.3602_SHR_KIND_R8, 336.2148_SHR_KIND_R8, & + & 233.0046_SHR_KIND_R8, 155.6977_SHR_KIND_R8, 184.6277_SHR_KIND_R8, & + & 267.2772_SHR_KIND_R8, 78.9281_SHR_KIND_R8, 123.4722_SHR_KIND_R8, & + & 188.7132_SHR_KIND_R8, 180.1364_SHR_KIND_R8, 49.1382_SHR_KIND_R8, & + & 152.5268_SHR_KIND_R8, 98.2198_SHR_KIND_R8, 97.4808_SHR_KIND_R8, & + & 221.5376_SHR_KIND_R8, 168.2438_SHR_KIND_R8, 161.1199_SHR_KIND_R8, & + & 55.0196_SHR_KIND_R8, 262.6495_SHR_KIND_R8, 200.3284_SHR_KIND_R8, & + & 201.6651_SHR_KIND_R8, 294.6547_SHR_KIND_R8, 99.8233_SHR_KIND_R8, & + & 213.5577_SHR_KIND_R8, 154.1631_SHR_KIND_R8, 232.7153_SHR_KIND_R8, & + & 138.3034_SHR_KIND_R8, 204.6609_SHR_KIND_R8, 106.5938_SHR_KIND_R8, & + & 250.4676_SHR_KIND_R8, 332.3345_SHR_KIND_R8, 27.3039_SHR_KIND_R8/) + + !---------------------------Local variables---------------------------------- + integer(SHR_KIND_IN) :: i ! Index for series summations + real (SHR_KIND_R8) :: obsum ! Obliquity series summation + real (SHR_KIND_R8) :: cossum ! Cos series summation for eccentricity/fvelp + real (SHR_KIND_R8) :: sinsum ! Sin series summation for eccentricity/fvelp + real (SHR_KIND_R8) :: fvelp ! Fixed vernal equinox long of perihelion + real (SHR_KIND_R8) :: mvsum ! mvelp series summation + real (SHR_KIND_R8) :: beta ! Intermediate argument for lambm0 + real (SHR_KIND_R8) :: years ! Years to time of interest ( pos <=> future) + real (SHR_KIND_R8) :: eccen2 ! eccentricity squared + real (SHR_KIND_R8) :: eccen3 ! eccentricity cubed + + !-------------------------- Formats ----------------------------------------- + character(len=*),parameter :: F00 = "('(shr_orb_params) ',4a)" + character(len=*),parameter :: F01 = "('(shr_orb_params) ',a,i9)" + character(len=*),parameter :: F02 = "('(shr_orb_params) ',a,f6.3)" + character(len=*),parameter :: F03 = "('(shr_orb_params) ',a,es14.6)" + + !---------------------------------------------------------------------------- + ! radinp and algorithms below will need a degree to radian conversion factor + + ! Check for flag to use input orbit parameters + + IF ( iyear_AD == SHR_ORB_UNDEF_INT ) THEN + + ! Check input obliq, eccen, and mvelp to ensure reasonable + + if( obliq == SHR_ORB_UNDEF_REAL )then + write(s_logunit,F00) ' Have to specify orbital parameters:' + write(s_logunit,F00) 'Either set: iyear_AD, OR [obliq, eccen, and mvelp]:' + write(s_logunit,F00) 'iyear_AD is the year to simulate orbit for (ie. 1950): ' + write(s_logunit,F00) 'obliq, eccen, mvelp specify the orbit directly:' + write(s_logunit,F00) 'The AMIP II settings (for a 1995 orbit) are: ' + write(s_logunit,F00) ' obliq = 23.4441' + write(s_logunit,F00) ' eccen = 0.016715' + write(s_logunit,F00) ' mvelp = 102.7' + stop "Stopped" + end if + if( (obliq < SHR_ORB_OBLIQ_MIN).or.(obliq > SHR_ORB_OBLIQ_MAX) ) then + write(s_logunit,F03) 'Input obliquity unreasonable: ', obliq + stop "Stopped" + end if + if( (eccen < SHR_ORB_ECCEN_MIN).or.(eccen > SHR_ORB_ECCEN_MAX) ) then + write(s_logunit,F03) 'Input eccentricity unreasonable: ', eccen + stop "Stopped" + end if + if( (mvelp < SHR_ORB_MVELP_MIN).or.(mvelp > SHR_ORB_MVELP_MAX) ) then + write(s_logunit,F03) 'Input mvelp unreasonable: ' , mvelp + stop "Stopped" + end if + eccen2 = eccen*eccen + eccen3 = eccen2*eccen + + ELSE ! Otherwise calculate based on years before present + + yb4_1950AD = 1950.0_SHR_KIND_R8 - real(iyear_AD,SHR_KIND_R8) + if ( abs(yb4_1950AD) .gt. 1000000.0_SHR_KIND_R8 )then + write(s_logunit,F00) 'orbit only valid for years+-1000000' + write(s_logunit,F00) 'Relative to 1950 AD' + write(s_logunit,F03) '# of years before 1950: ',yb4_1950AD + write(s_logunit,F01) 'Year to simulate was : ',iyear_AD + stop "Stopped" + end if + + ! The following calculates the earths obliquity, orbital eccentricity + ! (and various powers of it) and vernal equinox mean longitude of + ! perihelion for years in the past (future = negative of years past), + ! using constants (see parameter section) given in the program of: + ! + ! Berger, Andre. 1978 A Simple Algorithm to Compute Long-Term Variations + ! of Daily Insolation. Contribution 18, Institute of Astronomy and + ! Geophysics, Universite Catholique de Louvain, Louvain-la-Neuve, Belgium. + ! + ! and formulas given in the paper (where less precise constants are also + ! given): + ! + ! Berger, Andre. 1978. Long-Term Variations of Daily Insolation and + ! Quaternary Climatic Changes. J. of the Atmo. Sci. 35:2362-2367 + ! + ! The algorithm is valid only to 1,000,000 years past or hence. + ! For a solution valid to 5-10 million years past see the above author. + ! Algorithm below is better for years closer to present than is the + ! 5-10 million year solution. + ! + ! Years to time of interest must be negative of years before present + ! (1950) in formulas that follow. + + years = - yb4_1950AD + + ! In the summations below, cosine or sine arguments, which end up in + ! degrees, must be converted to radians via multiplication by degrad. + ! + ! Summation of cosine series for obliquity (epsilon in Berger 1978) in + ! degrees. Convert the amplitudes and rates, which are in arc secs, into + ! degrees via multiplication by psecdeg (arc seconds to degrees conversion + ! factor). For obliq, first term is Berger 1978 epsilon star; second + ! term is series summation in degrees. + + obsum = 0.0_SHR_KIND_R8 + do i = 1, poblen + obsum = obsum + obamp(i)*psecdeg*cos((obrate(i)*psecdeg*years + & + & obphas(i))*degrad) + end do + obliq = 23.320556_SHR_KIND_R8 + obsum + + ! Summation of cosine and sine series for computation of eccentricity + ! (eccen; e in Berger 1978) and fixed vernal equinox longitude of + ! perihelion (fvelp; pi in Berger 1978), which is used for computation + ! of moving vernal equinox longitude of perihelion. Convert the rates, + ! which are in arc seconds, into degrees via multiplication by psecdeg. + + cossum = 0.0_SHR_KIND_R8 + do i = 1, pecclen + cossum = cossum+ecamp(i)*cos((ecrate(i)*psecdeg*years+ecphas(i))*degrad) + end do + + sinsum = 0.0_SHR_KIND_R8 + do i = 1, pecclen + sinsum = sinsum+ecamp(i)*sin((ecrate(i)*psecdeg*years+ecphas(i))*degrad) + end do + + ! Use summations to calculate eccentricity + + eccen2 = cossum*cossum + sinsum*sinsum + eccen = sqrt(eccen2) + eccen3 = eccen2*eccen + + ! A series of cases for fvelp, which is in radians. + if (abs(cossum) .le. 1.0E-8_SHR_KIND_R8) then + if (sinsum .eq. 0.0_SHR_KIND_R8) then + fvelp = 0.0_SHR_KIND_R8 + else if (sinsum .lt. 0.0_SHR_KIND_R8) then + fvelp = 1.5_SHR_KIND_R8*pi + else if (sinsum .gt. 0.0_SHR_KIND_R8) then + fvelp = .5_SHR_KIND_R8*pi + endif + else if (cossum .lt. 0.0_SHR_KIND_R8) then + fvelp = atan(sinsum/cossum) + pi + else ! cossum > 1.0e-8 + if (sinsum .lt. 0.0_SHR_KIND_R8) then + fvelp = atan(sinsum/cossum) + 2.0_SHR_KIND_R8*pi + else + fvelp = atan(sinsum/cossum) + endif + endif + + ! Summation of sin series for computation of moving vernal equinox long + ! of perihelion (mvelp; omega bar in Berger 1978) in degrees. For mvelp, + ! first term is fvelp in degrees; second term is Berger 1978 psi bar + ! times years and in degrees; third term is Berger 1978 zeta; fourth + ! term is series summation in degrees. Convert the amplitudes and rates, + ! which are in arc seconds, into degrees via multiplication by psecdeg. + ! Series summation plus second and third terms constitute Berger 1978 + ! psi, which is the general precession. + + mvsum = 0.0_SHR_KIND_R8 + do i = 1, pmvelen + mvsum = mvsum + mvamp(i)*psecdeg*sin((mvrate(i)*psecdeg*years + & + & mvphas(i))*degrad) + end do + mvelp = fvelp/degrad + 50.439273_SHR_KIND_R8*psecdeg*years + 3.392506_SHR_KIND_R8 + mvsum + + ! Cases to make sure mvelp is between 0 and 360. + + do while (mvelp .lt. 0.0_SHR_KIND_R8) + mvelp = mvelp + 360.0_SHR_KIND_R8 + end do + do while (mvelp .ge. 360.0_SHR_KIND_R8) + mvelp = mvelp - 360.0_SHR_KIND_R8 + end do + + END IF ! end of test on whether to calculate or use input orbital params + + ! Orbit needs the obliquity in radians + + obliqr = obliq*degrad + + ! 180 degrees must be added to mvelp since observations are made from the + ! earth and the sun is considered (wrongly for the algorithm) to go around + ! the earth. For a more graphic explanation see Appendix B in: + ! + ! A. Berger, M. Loutre and C. Tricot. 1993. Insolation and Earth Orbital + ! Periods. J. of Geophysical Research 98:10,341-10,362. + ! + ! Additionally, orbit will need this value in radians. So mvelp becomes + ! mvelpp (mvelp plus pi) + + mvelpp = (mvelp + 180._SHR_KIND_R8)*degrad + + ! Set up an argument used several times in lambm0 calculation ahead. + + beta = sqrt(1._SHR_KIND_R8 - eccen2) + + ! The mean longitude at the vernal equinox (lambda m nought in Berger + ! 1978; in radians) is calculated from the following formula given in + ! Berger 1978. At the vernal equinox the true longitude (lambda in Berger + ! 1978) is 0. + + lambm0 = 2._SHR_KIND_R8*((.5_SHR_KIND_R8*eccen + .125_SHR_KIND_R8*eccen3)*(1._SHR_KIND_R8 + beta)*sin(mvelpp) & + & - .250_SHR_KIND_R8*eccen2*(.5_SHR_KIND_R8 + beta)*sin(2._SHR_KIND_R8*mvelpp) & + & + .125_SHR_KIND_R8*eccen3*(1._SHR_KIND_R8/3._SHR_KIND_R8 + beta)*sin(3._SHR_KIND_R8*mvelpp)) + + end subroutine shr_orb_params + + !:..........................................................................: + + subroutine shr_orb_decl(calday, eccen, mvelpp, lambm0, obliqr, delta, eccf) + + !------------------------------------------------------------------------- + ! + ! Compute earth/orbit parameters using formula suggested by + ! Duane Thresher. + ! + !---------------------------Code history---------------------------------- + ! + ! Original version: Erik Kluzek + ! Date: Oct/1997 + ! + !------------------------------------------------------------------------- + + !------------------------------Arguments-------------------------------- + real(SHR_KIND_R8), intent(in) :: calday ! Calendar day, including fraction + real(SHR_KIND_R8), intent(in) :: eccen ! Eccentricity + real(SHR_KIND_R8), intent(in) :: obliqr ! Earths obliquity in radians + real(SHR_KIND_R8), intent(in) :: lambm0 ! Mean long of perihelion at the vernal equinox (radians) + real(SHR_KIND_R8), intent(in) :: mvelpp ! moving vernal equinox longitude of perihelion plus pi (radians) + real(SHR_KIND_R8), intent(out) :: delta ! Solar declination angle in rad + real(SHR_KIND_R8), intent(out) :: eccf ! Earth-sun distance factor (ie. (1/r)**2) + + !---------------------------Local variables----------------------------- + real(SHR_KIND_R8), parameter :: dayspy = 365.0_SHR_KIND_R8 ! days per year + real(SHR_KIND_R8), parameter :: ve = 80.5_SHR_KIND_R8 ! Calday of vernal equinox assumes Jan 1 = calday 1 + + real(SHR_KIND_R8) :: lambm ! Lambda m, mean long of perihelion (rad) + real(SHR_KIND_R8) :: lmm ! Intermediate argument involving lambm + real(SHR_KIND_R8) :: lamb ! Lambda, the earths long of perihelion + real(SHR_KIND_R8) :: invrho ! Inverse normalized sun/earth distance + real(SHR_KIND_R8) :: sinl ! Sine of lmm + + ! Compute eccentricity factor and solar declination using + ! day value where a round day (such as 213.0) refers to 0z at + ! Greenwich longitude. + ! + ! Use formulas from Berger, Andre 1978: Long-Term Variations of Daily + ! Insolation and Quaternary Climatic Changes. J. of the Atmo. Sci. + ! 35:2362-2367. + ! + ! To get the earths true longitude (position in orbit; lambda in Berger + ! 1978) which is necessary to find the eccentricity factor and declination, + ! must first calculate the mean longitude (lambda m in Berger 1978) at + ! the present day. This is done by adding to lambm0 (the mean longitude + ! at the vernal equinox, set as March 21 at noon, when lambda=0; in radians) + ! an increment (delta lambda m in Berger 1978) that is the number of + ! days past or before (a negative increment) the vernal equinox divided by + ! the days in a model year times the 2*pi radians in a complete orbit. + + lambm = lambm0 + (calday - ve)*2._SHR_KIND_R8*pi/dayspy + lmm = lambm - mvelpp + + ! The earths true longitude, in radians, is then found from + ! the formula in Berger 1978: + + sinl = sin(lmm) + lamb = lambm + eccen*(2._SHR_KIND_R8*sinl + & + eccen*(1.25_SHR_KIND_R8*sin(2._SHR_KIND_R8*lmm) + & + eccen*((13.0_SHR_KIND_R8/12.0_SHR_KIND_R8)* & + sin(3._SHR_KIND_R8*lmm) - 0.25_SHR_KIND_R8*sinl))) + + ! Using the obliquity, eccentricity, moving vernal equinox longitude of + ! perihelion (plus), and earths true longitude, the declination (delta) + ! and the normalized earth/sun distance (rho in Berger 1978; actually inverse + ! rho will be used), and thus the eccentricity factor (eccf), can be + ! calculated from formulas given in Berger 1978. + + invrho = (1._SHR_KIND_R8 + eccen*cos(lamb - mvelpp))/ & + (1._SHR_KIND_R8 - eccen*eccen) + + ! Set solar declination and eccentricity factor + + delta = asin(sin(obliqr)*sin(lamb)) + eccf = invrho*invrho + + return + + end subroutine shr_orb_decl + + !:---------------------------------------------------------------------------- + + real(SHR_KIND_R8) pure function shr_orb_cosz(jday, lat, lon, declin) + + !------------------------------------------------------------------------- + ! + ! FUNCTION to return the cosine of the solar zenith angle. + ! Assumes 365.0 days/year. + ! + !--------------- Code History -------------------------------------------- + ! + ! Original Author: Brian Kauffman + ! Date: Jan/98 + ! History: adapted from statement FUNCTION in share/orb_cosz.h + ! + !------------------------------------------------------------------------- + + real(SHR_KIND_R8), intent(in) :: jday ! Julian cal day (1.xx to 365.xx) + real(SHR_KIND_R8), intent(in) :: lat ! Centered latitude (radians) + real(SHR_KIND_R8), intent(in) :: lon ! Centered longitude (radians) + real(SHR_KIND_R8), intent(in) :: declin ! Solar declination (radians) + + !------------------------------------------------------------------------- + + shr_orb_cosz = sin(lat)*sin(declin) - cos(lat)*cos(declin) * & + cos((jday-floor(jday))*2.0_SHR_KIND_R8*pi + lon) + + end function shr_orb_cosz + +end module OrbitalValsMod \ No newline at end of file diff --git a/unit_testing/test_norman.f90 b/unit_testing/test_norman.f90 new file mode 100644 index 0000000000..ab14f737bd --- /dev/null +++ b/unit_testing/test_norman.f90 @@ -0,0 +1,81 @@ +program test_norman + ! + ! DESCRIPTION: + ! Test the FATES radiation schemes + ! + + use IOMod + use OrbitalValsMod, only : SHR_KIND_R8, get_orbital_vals, shr_orb_cosz, & + shr_orb_decl + + implicit none + + ! Data dictionary: declare variable types, definitions, and units + real(r8) :: rhol(num_pft,num_swb) ! leaf reflectance (0-1) + real(r8) :: rhos(num_pft,num_swb) ! stem reflectance (0-1) + real(r8) :: taul(num_pft,num_swb) ! leaf transmittance (0-1) + real(r8) :: taus(num_pft,num_swb) ! stem transmittance (0-1) + real(r8) :: xl(num_pft) ! leaf/stem orientation index (-1-1) + real(r8) :: clumping_index(num_pft) ! clumping index (0-1) + real(r8) :: fcansno ! fraction of canopy covered by snow + real(r8) :: canopy_area_profile(num_can,num_pft,nlevleaf) ! fraction of crown area per canopy area in each layer + real(r8) :: elai_profile(num_can,num_pft,nlevleaf) ! exposed leaf area in each canopy layer, pft, and leaf layer + real(r8) :: esai_profile(num_can,num_pft,nlevleaf) ! exposed stem area in each canopy layer, pft, and leaf layer + real(r8) :: nrad_r(num_can,num_pft) ! number of exposed leaf layers for each canopy layer and pft + integer :: nrad(num_can,num_pft) ! number of exposed leaf layers for each canopy layer and pft + real(r8) :: k_dir(num_pft,48) ! direct beam extinction coefficient + real(SHR_KIND_R8) :: eccen ! orbital eccentricity + real(SHR_KIND_R8) :: mvelp ! moving vernal equinox long + real(SHR_KIND_R8) :: obliqr ! Earths obliquity in rad + real(SHR_KIND_R8) :: lambm0 ! Mean long of perihelion at vernal equinox (radians) + real(SHR_KIND_R8) :: mvelpp ! moving vernal equinox long of perihelion plus pi (rad) + real(SHR_KIND_R8) :: eccf ! Earth-sun distance factor (ie. (1/r)**2) + real(SHR_KIND_R8) :: calday ! calendar day (including fraction) + real(SHR_KIND_R8) :: declin ! solar declination (radians) + real(SHR_KIND_R8) :: cosz(48) ! cosine of solar zenith angle (radians) + real(r8) :: lat, lon + integer :: jday ! julian day + integer :: year ! year + integer :: i ! looping index + character(len=100) :: file_in, patch_file, out_file + + ! file_names + file_in = "fates_params.nc" + patch_file = "patch_data.nc" + out_file = "nrad_out.nc" + logf = open_file("log.txt") + + ! set julian day, year, and lat/lon here + jday = 165 + year = 2000 + lat = 45.76_r8*pi_const/180.0_r8 + lon = 237.67_r8*pi_const/180.0_r8 + fcansno = 0.0_r8 + + ! get patch and parameter values, as well as orbital parameters + call get_parameters(file_in, rhol, rhos, taul, taus, xl, clumping_index) + call read_patch_data(patch_file, canopy_area_profile, elai_profile, & + esai_profile, nrad_r) + nrad = int(nrad_r) + call get_orbital_vals(year, logf, eccen, mvelp, obliqr, lambm0, mvelpp) + + cosz(:) = 0.0 + k_dir(:,:) = 0.0 + + ! for each half-hourly time step in the day + do i = 0, 47 + calday = jday + i*0.02083333_SHR_KIND_R8 + call shr_orb_decl(calday, eccen, mvelpp, lambm0, obliqr, declin, eccf) + cosz(i) = shr_orb_cosz(calday, lat, lon, declin) + + if (cosz(i) > 0.0_r8) then + ! call norman radiation scheme + call PatchNormanRadiation(rhol, rhos, taul, taus, xl, clumping_index, & + canopy_area_profile, elai_profile, esai_profile, fcansno, & + cosz(i), nrad, 2, k_dir(:,i)) + end if + end do + + call write_radiation_data(out_file, k_dir, cosz) + +end program test_norman \ No newline at end of file From a1b971cc6c6cbb4401a24229e73a4b59ceb5e5e6 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 11 Apr 2023 10:46:02 -0600 Subject: [PATCH 622/852] update io methods for unit testing --- unit_testing/FatesUnitTestIOMod.F90 | 391 ++++++++++++----------- unit_testing/FatesUnitTestOrbitalMod.F90 | 4 +- unit_testing/FatesUnitTestRadiation.F90 | 145 +++++++++ unit_testing/test_norman.f90 | 81 ----- 4 files changed, 347 insertions(+), 274 deletions(-) create mode 100644 unit_testing/FatesUnitTestRadiation.F90 delete mode 100644 unit_testing/test_norman.f90 diff --git a/unit_testing/FatesUnitTestIOMod.F90 b/unit_testing/FatesUnitTestIOMod.F90 index 200517388e..899942a282 100644 --- a/unit_testing/FatesUnitTestIOMod.F90 +++ b/unit_testing/FatesUnitTestIOMod.F90 @@ -4,189 +4,198 @@ module FatesUnitTestIOMod implicit none -! LOCALS -integer, parameter :: BASE_UNIT = 10 ! Base unit for files the first time unit_number is called -integer, parameter :: MAX_PATH = 256 ! Maximum path length -integer, parameter :: MAX_CHAR = 80 ! Maximum length for messages -integer :: logf ! Unit number for output log file - -contains - - integer function unit_number() -! -! DESCRIPTION: -! Generates a unit number to be used in opening files -! The first time the function is called, it returns BASE_UNIT -! -! LOCALS: -integer :: iunit ! File unit (increments after first call) -logical :: first = .true. ! First time this has been called? -save - -if (first) then - ! Set first to false and iunit to base unit on first call - iunit = BASE_UNIT - first = .false. -else - ! Otherwise, increment - iunit = iunit + 1 -endif - -! Set to output -unit_number = iunit - - end function unit_number + ! LOCALS + integer, parameter :: BASE_UNIT = 10 ! Base unit for files the first time unit_number is called + integer, parameter :: MAX_PATH = 256 ! Maximum path length + integer, parameter :: MAX_CHAR = 80 ! Maximum length for messages + integer :: logf ! Unit number for output log file + + contains - !:...........................................................................: + integer function unit_number() + ! + ! DESCRIPTION: + ! Generates a unit number to be used in opening files + ! The first time the function is called, it returns BASE_UNIT + ! + ! LOCALS: + integer :: iunit ! File unit (increments after first call) + logical :: first = .true. ! First time this has been called? + save - integer function open_file(filename, mode) - ! - ! DESCRIPTION: - ! Opens the file filename if it can, returns a unit number for it. - ! The first time the function is called, it returns BASE_UNIT - - ! ARGUMENTS: - character(len = *), intent(in) :: filename ! Name of file to open - character(len = *), intent(in), optional :: mode ! Optional mode ('r', 'w', 'rw') - - ! LOCALS: - character(len = 9) :: fmode ! File open mode - logical :: file_exists ! Does the file exist? - character(len = MAX_PATH) :: fname ! Local filename (trimmed) - character(len = MAX_CHAR) :: message ! Error message - integer :: i ! Looping index - integer :: ios ! I/O status - integer :: iunit = BASE_UNIT ! File unit number - integer, dimension(MAX_PATH) :: farray ! Array of characters of file name - - ! Get mode of open (read, write, or read/write) - ! Defaults to read/write - if (present(mode)) then - select case(mode) - case ('r', 'R') - fmode = 'read' - case ('w', 'W') - fmode = 'write' - case ('rw', 'RW', 'wr', 'WR') - fmode = 'readwrite' - case DEFAULT - fmode = 'readwrite' - end select - else - fmode = 'readwrite' - endif - - ! trim filename of whitespace - fname = trim(adjustl(filename)) - - if (fmode == 'read' .or. fmode == 'readwrite') then - ! Check for valid name of file - farray = 0 - do i = 1, len_trim(fname) - farray(i) = ichar(fname(i:i)) - enddo - if (any(farray > 126)) then - write(*,*) "Invalid filename" - stop "Stopped" - endif - endif - - ! Does the file exist? - inquire(file = fname, exist = file_exists) - - ! Open file if conditions are correct - if (file_exists .and. fmode == 'write') then - write(message, '(A,A,A)') "File ", fname(1:len_trim(fname)), & - " exists. Cannot open write only." - write(*,*) message - stop "Stopped" - else if (.not. file_exists .and. fmode == 'read') then - write(message, '(A,A,A)') "File ", fname(1:len_trim(fname)), & - " does not exist. Can't read." - write(*,*) message - stop "Stopped" - else - iunit = unit_number() - open(iunit, file = fname, action = fmode, iostat = ios) - if (ios /= 0) then - write(message, '(A,A,A,I6)') "Problem opening", & - fname(1:len_trim(fname)), " ios: ", ios - write(*,*) message - stop "Stopped" - endif - endif + if (first) then + ! Set first to false and iunit to base unit on first call + iunit = BASE_UNIT + first = .false. + else + ! Otherwise, increment + iunit = iunit + 1 + endif - open_file = iunit + ! Set to output + unit_number = iunit - end function open_file + end function unit_number - !:...........................................................................: + !:.........................................................................: - subroutine write_radiation_data(file, kdir, declin) - character(len=100), intent(in) :: file ! output file name - real(r8), intent(in) :: kdir(num_pft, 48) ! direct beam extinction coefficient - real(r8), intent(in) :: declin(48) + integer function open_file(filename, mode) + ! + ! DESCRIPTION: + ! Opens the file filename if it can, returns a unit number for it. + ! The first time the function is called, it returns BASE_UNIT + ! - integer :: ncid - integer :: pft_dimid, time_dimid - integer :: kdir_id, declin_id - integer :: dimids(2) + ! ARGUMENTS: + character(len = *), intent(in) :: filename ! Name of file to open + character(len = *), intent(in), optional :: mode ! Optional mode ('r', 'w', 'rw') + + ! LOCALS: + character(len = 9) :: fmode ! File open mode + logical :: file_exists ! Does the file exist? + character(len = MAX_PATH) :: fname ! Local filename (trimmed) + character(len = MAX_CHAR) :: message ! Error message + integer :: i ! Looping index + integer :: ios ! I/O status + integer :: iunit = BASE_UNIT ! File unit number + integer, dimension(MAX_PATH) :: farray ! Array of characters of file name + + ! Get mode of open (read, write, or read/write) + ! Defaults to read/write + if (present(mode)) then + select case(mode) + case ('r', 'R') + fmode = 'read' + case ('w', 'W') + fmode = 'write' + case ('rw', 'RW', 'wr', 'WR') + fmode = 'readwrite' + case DEFAULT + fmode = 'readwrite' + end select + else + fmode = 'readwrite' + endif + + ! trim filename of whitespace + fname = trim(adjustl(filename)) + + if (fmode == 'read' .or. fmode == 'readwrite') then + ! Check for valid name of file + farray = 0 + do i = 1, len_trim(fname) + farray(i) = ichar(fname(i:i)) + enddo + if (any(farray > 126)) then + write(*,*) "Invalid filename" + stop "Stopped" + endif + endif + + ! Does the file exist? + inquire(file = fname, exist = file_exists) + + ! Open file if conditions are correct + if (file_exists .and. fmode == 'write') then + write(message, '(A,A,A)') "File ", fname(1:len_trim(fname)), & + " exists. Cannot open write only." + write(*,*) message + stop "Stopped" + else if (.not. file_exists .and. fmode == 'read') then + write(message, '(A,A,A)') "File ", fname(1:len_trim(fname)), & + " does not exist. Can't read." + write(*,*) message + stop "Stopped" + else + iunit = unit_number() + open(iunit, file=fname, action=fmode, iostat=ios) + if (ios /= 0) then + write(message, '(A,A,A,I6)') "Problem opening", & + fname(1:len_trim(fname)), " ios: ", ios + write(*,*) message + stop "Stopped" + endif + endif + + open_file = iunit + + end function open_file + + !:.........................................................................: + + subroutine write_radiation_data(file, kdir, declin) + ! + ! DESCRIPTION: + ! Opens the file filename if it can, returns a unit number for it. + ! The first time the function is called, it returns BASE_UNIT + ! + + ! ARGUMENTS: + character(len=MAX_PATH), intent(in) :: file ! output file name + real(r8), intent(in) :: kdir(num_pft,48) ! direct beam extinction coefficient + real(r8), intent(in) :: declin(48) - ! Create the netCDF file. The nf90_clobber parameter tells netCDF to - ! overwrite this file, if it already exists. - call check(nf90_create(trim(file), NF90_CLOBBER, ncid)) + ! LOCALS: + integer :: ncid + integer :: pft_dimid, time_dimid + integer :: kdir_id, declin_id + integer :: dimids(2) - ! define dimensions - call check(nf90_def_dim(ncid, "pft", num_pft, pft_dimid)) - call check(nf90_def_dim(ncid, "time", 48, time_dimid)) + ! Create the netCDF file. The nf90_clobber parameter tells netCDF to + ! overwrite this file, if it already exists. + call check(nf90_create(trim(file), NF90_CLOBBER, ncid)) - ! define the variables - dimids = (/ pft_dimid, time_dimid/) - call check(nf90_def_var(ncid, "kdir", NF90_REAL8, dimids, kdir_id)) - call check(nf90_def_var(ncid, "declin", NF90_REAL8, time_dimid, declin_id)) + ! define dimensions + call check(nf90_def_dim(ncid, "pft", num_pft, pft_dimid)) + call check(nf90_def_dim(ncid, "time", 48, time_dimid)) - ! end define mode - call check(nf90_enddef(ncid)) + ! define the variables + dimids = (/ pft_dimid, time_dimid/) + call check(nf90_def_var(ncid, "kdir", NF90_REAL8, dimids, kdir_id)) + call check(nf90_def_var(ncid, "declin", NF90_REAL8, time_dimid, declin_id)) - ! write to file. - call check(nf90_put_var(ncid, kdir_id, kdir)) - call check(nf90_put_var(ncid, declin_id, declin)) + ! end define mode + call check(nf90_enddef(ncid)) - ! close the file. - call check(nf90_close(ncid)) + ! write to file. + call check(nf90_put_var(ncid, kdir_id, kdir)) + call check(nf90_put_var(ncid, declin_id, declin)) - end subroutine write_radiation_data + ! close the file. + call check(nf90_close(ncid)) - !:...........................................................................: + end subroutine write_radiation_data - subroutine check(status) - ! - ! DESCRIPTION: - ! Checks status of netcdf operations - - ! ARGUMENTS: - integer, intent (in) :: status ! return status code from a netcdf procedure + !:.........................................................................: + + subroutine check(status) + ! + ! DESCRIPTION: + ! Checks status of netcdf operations - if (status /= nf90_noerr) then - print *, trim(nf90_strerror(status)) - stop "Stopped" - end if + ! ARGUMENTS: + integer, intent (in) :: status ! return status code from a netcdf procedure + + if (status /= nf90_noerr) then + print *, trim(nf90_strerror(status)) + stop "Stopped" + end if - end subroutine check + end subroutine check - !:...........................................................................: + !:.........................................................................: subroutine read_patch_data(file, canopy_area, elai, esai, nrad) - ! - ! DESCRIPTION: - ! Reads and return patch data - - ! ARGUMENTS: - character(len=100), intent(in) :: file ! patch file name - real(r8), intent(out) :: canopy_area(num_can,num_pft,nlevleaf) ! canopy area profile - real(r8), intent(out) :: elai(num_can,num_pft,nlevleaf) ! exposed lai profile - real(r8), intent(out) :: esai(num_can,num_pft,nlevleaf) ! exposed sai profile - real(r8), intent(out) :: nrad(num_can,num_pft) ! number of exposed leaf layers + ! + ! DESCRIPTION: + ! Reads and return patch data + + ! ARGUMENTS: + character(len=MAX_PATH), intent(in) :: file ! patch file name + real(r8), intent(out) :: canopy_area(num_can,num_pft,nlevleaf) ! canopy area profile + real(r8), intent(out) :: elai(num_can,num_pft,nlevleaf) ! exposed lai profile + real(r8), intent(out) :: esai(num_can,num_pft,nlevleaf) ! exposed sai profile + real(r8), intent(out) :: nrad(num_can,num_pft) ! number of exposed leaf layers ! Data dictionary: declare variable types, definitions, and units real(r8) :: nrad_r(num_can,num_pft) ! number of exposed leaf layers @@ -208,35 +217,35 @@ subroutine read_patch_data(file, canopy_area, elai, esai, nrad) call check(nf90_inq_varid(fidA, "nrad", varID)) call check(nf90_get_var(fidA, varID, nrad)) - end subroutine read_patch_data - - !:...........................................................................: - - subroutine get_parameters(file, rhol, rhos, taul, taus, xl, ci) - ! - ! Purpose: - ! Returns parameter values - ! - ! Record of revisions: - ! Date Programmer Description of change - ! ======== ============= ===================== - ! 03/20/23 A. C. Foster Original code - ! - - ! Data dictionary: declare calling parameter types & definitions - character(len=100), intent(in) :: file ! parameter file name - real(r8), intent(out) :: rhol(num_pft,num_swb) ! leaf reflectance - real(r8), intent(out) :: rhos(num_pft,num_swb) ! stem reflectance - real(r8), intent(out) :: taul(num_pft,num_swb) ! leaf transmittance - real(r8), intent(out) :: taus(num_pft,num_swb) ! stem transmittance - real(r8), intent(out) :: xl(num_pft) ! leaf orientation index - real(r8), intent(out) :: ci(num_pft) ! clumping index - - ! read in all parameters - call read_param_netcdf(file, rhol(:,1), rhol(:,2), rhos(:,1), rhos(:,2), & - taul(:,1), taul(:,2), taus(:,1), taus(:,2), xl, ci) - - end subroutine get_parameters + end subroutine read_patch_data + + !:.........................................................................: + + subroutine get_parameters(file, rhol, rhos, taul, taus, xl, ci) + ! + ! Purpose: + ! Returns parameter values + ! + ! Record of revisions: + ! Date Programmer Description of change + ! ======== ============= ===================== + ! 03/20/23 A. C. Foster Original code + ! + + ! Data dictionary: declare calling parameter types & definitions + character(len=100), intent(in) :: file ! parameter file name + real(r8), intent(out) :: rhol(num_pft,num_swb) ! leaf reflectance + real(r8), intent(out) :: rhos(num_pft,num_swb) ! stem reflectance + real(r8), intent(out) :: taul(num_pft,num_swb) ! leaf transmittance + real(r8), intent(out) :: taus(num_pft,num_swb) ! stem transmittance + real(r8), intent(out) :: xl(num_pft) ! leaf orientation index + real(r8), intent(out) :: ci(num_pft) ! clumping index + + ! read in all parameters + call read_param_netcdf(file, rhol(:,1), rhol(:,2), rhos(:,1), rhos(:,2), & + taul(:,1), taul(:,2), taus(:,1), taus(:,2), xl, ci) + + end subroutine get_parameters !:...........................................................................: diff --git a/unit_testing/FatesUnitTestOrbitalMod.F90 b/unit_testing/FatesUnitTestOrbitalMod.F90 index 545baf398c..b1e55591af 100644 --- a/unit_testing/FatesUnitTestOrbitalMod.F90 +++ b/unit_testing/FatesUnitTestOrbitalMod.F90 @@ -1,4 +1,4 @@ -module OrbitalValsMod +module FatesUnitTestOrbitalMod ! ! DESCRIPTION: ! Helper procedures for getting orbital values @@ -578,4 +578,4 @@ real(SHR_KIND_R8) pure function shr_orb_cosz(jday, lat, lon, declin) end function shr_orb_cosz -end module OrbitalValsMod \ No newline at end of file +end module FatesUnitTestOrbitalMod \ No newline at end of file diff --git a/unit_testing/FatesUnitTestRadiation.F90 b/unit_testing/FatesUnitTestRadiation.F90 new file mode 100644 index 0000000000..c260081198 --- /dev/null +++ b/unit_testing/FatesUnitTestRadiation.F90 @@ -0,0 +1,145 @@ +program FatesUnitTestRadiation + ! + ! DESCRIPTION: + ! Test the FATES radiation schemes + ! + + use FatesUnitTestIOMod, only : logf, MAX_PATH + use FatesUnitTestOrbitalMod, only : SHR_KIND_R8 + use FatesUnitTestOrbitalMod, only : get_orbital_vals, shr_orb_cosz + use FatesUnitTestOrbitalMod, only : shr_orb_decl + use EDParamsMod, only : nlevleaf, nclmax + + implicit none + + ! LOCALS: + character(len=MAX_PATH) :: param_file, patch_file, out_file ! file names + integer :: numpft, numSWb + ! real(r8) :: rhol(num_pft,num_swb) ! leaf reflectance (0-1) + ! real(r8) :: rhos(num_pft,num_swb) ! stem reflectance (0-1) + ! real(r8) :: taul(num_pft,num_swb) ! leaf transmittance (0-1) + ! real(r8) :: taus(num_pft,num_swb) ! stem transmittance (0-1) + ! real(r8) :: xl(num_pft) ! leaf/stem orientation index (-1-1) + ! real(r8) :: clumping_index(num_pft) ! clumping index (0-1) + ! real(r8) :: fcansno ! fraction of canopy covered by snow + ! real(r8) :: canopy_area_profile(num_can,num_pft,nlevleaf) ! fraction of crown area per canopy area in each layer + ! real(r8) :: elai_profile(num_can,num_pft,nlevleaf) ! exposed leaf area in each canopy layer, pft, and leaf layer + ! real(r8) :: esai_profile(num_can,num_pft,nlevleaf) ! exposed stem area in each canopy layer, pft, and leaf layer + ! real(r8) :: nrad_r(num_can,num_pft) ! number of exposed leaf layers for each canopy layer and pft + ! integer :: nrad(num_can,num_pft) ! number of exposed leaf layers for each canopy layer and pft + ! real(r8) :: k_dir(num_pft,48) ! direct beam extinction coefficient + ! real(SHR_KIND_R8) :: eccen ! orbital eccentricity + ! real(SHR_KIND_R8) :: mvelp ! moving vernal equinox long + ! real(SHR_KIND_R8) :: obliqr ! Earths obliquity in rad + ! real(SHR_KIND_R8) :: lambm0 ! Mean long of perihelion at vernal equinox (radians) + ! real(SHR_KIND_R8) :: mvelpp ! moving vernal equinox long of perihelion plus pi (rad) + ! real(SHR_KIND_R8) :: eccf ! Earth-sun distance factor (ie. (1/r)**2) + ! real(SHR_KIND_R8) :: calday ! calendar day (including fraction) + ! real(SHR_KIND_R8) :: declin ! solar declination (radians) + ! real(SHR_KIND_R8) :: cosz(48) ! cosine of solar zenith angle (radians) + ! real(r8) :: lat, lon + ! integer :: jday ! julian day + ! integer :: year ! year + ! integer :: i ! looping index + + interface + + subroutine read_radiation_namelist(numpft, numSWb, param_file, patch_file, & + out_file) + + use FatesUnitTestIOMod, only : MAX_PATH, MAX_CHAR, open_file + + implicit none + + character(len=MAX_PATH), intent(out) :: param_file, patch_file, out_file ! file names + integer, intent(out) :: numpft, numSWb + + + end subroutine read_radiation_namelist + + end interface + + ! file_names + ! logf = open_file("log.txt") + + ! ! set julian day, year, and lat/lon here + ! jday = 165 + ! year = 2000 + ! lat = 45.76_r8*pi_const/180.0_r8 + ! lon = 237.67_r8*pi_const/180.0_r8 + ! fcansno = 0.0_r8 + + ! ! get patch and parameter values, as well as orbital parameters + ! call get_parameters(file_in, rhol, rhos, taul, taus, xl, clumping_index) + ! call read_patch_data(patch_file, canopy_area_profile, elai_profile, & + ! esai_profile, nrad_r) + ! nrad = int(nrad_r) + ! call get_orbital_vals(year, logf, eccen, mvelp, obliqr, lambm0, mvelpp) + + ! cosz(:) = 0.0 + ! k_dir(:,:) = 0.0 + + ! ! for each half-hourly time step in the day + ! do i = 0, 47 + ! calday = jday + i*0.02083333_SHR_KIND_R8 + ! call shr_orb_decl(calday, eccen, mvelpp, lambm0, obliqr, declin, eccf) + ! cosz(i) = shr_orb_cosz(calday, lat, lon, declin) + + ! if (cosz(i) > 0.0_r8) then + ! ! call norman radiation scheme + ! call PatchNormanRadiation(rhol, rhos, taul, taus, xl, clumping_index, & + ! canopy_area_profile, elai_profile, esai_profile, fcansno, & + ! cosz(i), nrad, 2, k_dir(:,i)) + ! end if + ! end do + + ! call write_radiation_data(out_file, k_dir, cosz) + +end program FatesUnitTestRadiation + +!:.............................................................................: + +subroutine read_radiation_namelist(numpft, numSWb, param_file, patch_file, & + out_file) + + use FatesUnitTestIOMod, only : MAX_PATH, MAX_CHAR, open_file + + implicit none + + ! + ! DESCRIPTION: + ! read in the namelist associated with the radiation unit tests and + ! initialize values + ! + + ! ARGUMENTS: + character(len=MAX_PATH), intent(out) :: param_file, patch_file, out_file ! file names + integer, intent(out) :: numpft, numSWb + + ! LOCALS: + character(len=MAX_PATH) :: rad_nl = 'radiation_nl' ! radiation namelist name + character(len=MAX_CHAR) :: message ! Error message + character(len=MAX_CHAR) :: msg ! I/O Error message + integer :: rad_nl_file ! unit number for namelist + integer :: ios ! I/O status + + + ! Namelist of radiation parameters + namelist /radiation/ numpft, numSWb, param_file, patch_file, out_file + + + ! Now read parameters namelist + rad_nl_file = open_file(trim(rad_nl), 'r') + read(rad_nl_file, radiation, iostat=ios, iomsg=msg) + + if (ios /= 0) then + ! Problem reading file - tell user. + write(message, '(A, I6, A, A)') "Error reading radiation namelist file", & + ios, "IOMSG: ", msg + write(*,*) message + stop "Stopped" + end if + + close(rad_nl_file) + +end subroutine read_radiation_namelist \ No newline at end of file diff --git a/unit_testing/test_norman.f90 b/unit_testing/test_norman.f90 deleted file mode 100644 index ab14f737bd..0000000000 --- a/unit_testing/test_norman.f90 +++ /dev/null @@ -1,81 +0,0 @@ -program test_norman - ! - ! DESCRIPTION: - ! Test the FATES radiation schemes - ! - - use IOMod - use OrbitalValsMod, only : SHR_KIND_R8, get_orbital_vals, shr_orb_cosz, & - shr_orb_decl - - implicit none - - ! Data dictionary: declare variable types, definitions, and units - real(r8) :: rhol(num_pft,num_swb) ! leaf reflectance (0-1) - real(r8) :: rhos(num_pft,num_swb) ! stem reflectance (0-1) - real(r8) :: taul(num_pft,num_swb) ! leaf transmittance (0-1) - real(r8) :: taus(num_pft,num_swb) ! stem transmittance (0-1) - real(r8) :: xl(num_pft) ! leaf/stem orientation index (-1-1) - real(r8) :: clumping_index(num_pft) ! clumping index (0-1) - real(r8) :: fcansno ! fraction of canopy covered by snow - real(r8) :: canopy_area_profile(num_can,num_pft,nlevleaf) ! fraction of crown area per canopy area in each layer - real(r8) :: elai_profile(num_can,num_pft,nlevleaf) ! exposed leaf area in each canopy layer, pft, and leaf layer - real(r8) :: esai_profile(num_can,num_pft,nlevleaf) ! exposed stem area in each canopy layer, pft, and leaf layer - real(r8) :: nrad_r(num_can,num_pft) ! number of exposed leaf layers for each canopy layer and pft - integer :: nrad(num_can,num_pft) ! number of exposed leaf layers for each canopy layer and pft - real(r8) :: k_dir(num_pft,48) ! direct beam extinction coefficient - real(SHR_KIND_R8) :: eccen ! orbital eccentricity - real(SHR_KIND_R8) :: mvelp ! moving vernal equinox long - real(SHR_KIND_R8) :: obliqr ! Earths obliquity in rad - real(SHR_KIND_R8) :: lambm0 ! Mean long of perihelion at vernal equinox (radians) - real(SHR_KIND_R8) :: mvelpp ! moving vernal equinox long of perihelion plus pi (rad) - real(SHR_KIND_R8) :: eccf ! Earth-sun distance factor (ie. (1/r)**2) - real(SHR_KIND_R8) :: calday ! calendar day (including fraction) - real(SHR_KIND_R8) :: declin ! solar declination (radians) - real(SHR_KIND_R8) :: cosz(48) ! cosine of solar zenith angle (radians) - real(r8) :: lat, lon - integer :: jday ! julian day - integer :: year ! year - integer :: i ! looping index - character(len=100) :: file_in, patch_file, out_file - - ! file_names - file_in = "fates_params.nc" - patch_file = "patch_data.nc" - out_file = "nrad_out.nc" - logf = open_file("log.txt") - - ! set julian day, year, and lat/lon here - jday = 165 - year = 2000 - lat = 45.76_r8*pi_const/180.0_r8 - lon = 237.67_r8*pi_const/180.0_r8 - fcansno = 0.0_r8 - - ! get patch and parameter values, as well as orbital parameters - call get_parameters(file_in, rhol, rhos, taul, taus, xl, clumping_index) - call read_patch_data(patch_file, canopy_area_profile, elai_profile, & - esai_profile, nrad_r) - nrad = int(nrad_r) - call get_orbital_vals(year, logf, eccen, mvelp, obliqr, lambm0, mvelpp) - - cosz(:) = 0.0 - k_dir(:,:) = 0.0 - - ! for each half-hourly time step in the day - do i = 0, 47 - calday = jday + i*0.02083333_SHR_KIND_R8 - call shr_orb_decl(calday, eccen, mvelpp, lambm0, obliqr, declin, eccf) - cosz(i) = shr_orb_cosz(calday, lat, lon, declin) - - if (cosz(i) > 0.0_r8) then - ! call norman radiation scheme - call PatchNormanRadiation(rhol, rhos, taul, taus, xl, clumping_index, & - canopy_area_profile, elai_profile, esai_profile, fcansno, & - cosz(i), nrad, 2, k_dir(:,i)) - end if - end do - - call write_radiation_data(out_file, k_dir, cosz) - -end program test_norman \ No newline at end of file From 2d58d2433e3a9c0a203ca2e26a5289660cf50ed8 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 11 Apr 2023 11:33:51 -0600 Subject: [PATCH 623/852] adding makefile --- unit_testing/FatesUnitTestRadiation.F90 | 2 + unit_testing/Makefile | 64 +++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 unit_testing/Makefile diff --git a/unit_testing/FatesUnitTestRadiation.F90 b/unit_testing/FatesUnitTestRadiation.F90 index c260081198..56ce2d75ee 100644 --- a/unit_testing/FatesUnitTestRadiation.F90 +++ b/unit_testing/FatesUnitTestRadiation.F90 @@ -58,6 +58,8 @@ subroutine read_radiation_namelist(numpft, numSWb, param_file, patch_file, & end subroutine read_radiation_namelist end interface + + print *, 'Hello, unit test' ! file_names ! logf = open_file("log.txt") diff --git a/unit_testing/Makefile b/unit_testing/Makefile new file mode 100644 index 0000000000..5b9473ee1c --- /dev/null +++ b/unit_testing/Makefile @@ -0,0 +1,64 @@ +PROG = test_norman + +SRCS = FatesConstantsMod.F90 FatesGlobals.F90 log_mod.f90 \ + FatesHydraulicsMemMod.F90 FatesHydroWTFMod.F90 FatesLitterMod.F90 \ + CohortModule.f90 FatesRunningMeanMod.F90 PatchModule.f90 \ + PRTGenericMod.F90 PRTParametersMod.F90 norman_constants.f90 \ + IOMod.f90 norman_radiation.f90 test_norman.f90 OrbitalValsMod.f90 + + +OBJS = FatesConstantsMod.o FatesGlobals.o log_mod.o \ + FatesHydraulicsMemMod.o FatesHydroWTFMod.o FatesLitterMod.o \ + CohortModule.o FatesRunningMeanMod.o PatchModule.o \ + PRTGenericMod.o PRTParametersMod.o norman_constants.o \ + IOMod.o norman_radiation.o test_norman.o OrbitalValsMod.o + +## need both +LIBS = -L/usr/local/Cellar/netcdf/4.9.2/lib -lnetcdf -L/usr/local/Cellar/netcdf-fortran/4.6.0/lib -lnetcdff -lnetcdf + +INCLUDES = -I/usr/local/Cellar/netcdf-fortran/4.6.0/include + +F90 = gfortran + +##DBG = -g -fbacktrace -ffpe-trap=invalid,zero,overflow,underflow,denormal + +##OPT = -O2 -axcore-avx2 -xavx -align array64byte -ipo + +F90FLAGS = $(DBG) $(OPT) + +all: $(PROG) + +## link objects into a library (don't need includes?) +$(PROG): $(OBJS) + $(F90) -o $@ $(OBJS) $(LIBS) + +.PHONY: clean +clean: + rm -f $(PROG) $(OBJS) *.mod + +.SUFFIXES: $(SUFFIXES) .f90 .F90 .f95 .f + +# percent can stand for anything XX.o depends on XX.mod +%.o: %.mod + +# for each .o file, make it from a +.f90.o .f95.o .F90.o: + $(F90) $(F90FLAGS) $(INCLUDES) -c $< + +# dependencies (:) - if norman_constants.o gets updated, remake parameter_mod, etc. +FatesGlobals.o: FatesConstantsMod.o +FatesHydraulicsMemMod.o: FatesConstantsMod.o FatesHydroWTFMod.o norman_constants.o +FatesHydroWTFMod.o: FatesConstantsMod.o FatesGlobals.o log_mod.o +FatesLitterMod.o: FatesConstantsMod.o FatesGlobals.o log_mod.o +CohortModule.o: FatesConstantsMod.o PRTGenericMod.o FatesHydraulicsMemMod.o +FatesRunningMeanMod.o: FatesConstantsMod.o log_mod.o FatesGlobals.o norman_constants.o +PatchModule.o: CohortModule.o FatesLitterMod.o FatesRunningMeanMod.o FatesConstantsMod.o PRTGenericMod.o norman_constants.o +PRTGenericMod.o: FatesConstantsMod.o FatesGlobals.o log_mod.o PRTParametersMod.o +PRTParametersMod.o: FatesConstantsMod.o +IOMod.o: norman_constants.o +OrbitalValsMod.o: IOMod.o +norman_radiation.o: norman_constants.o +norman_constants.o: FatesConstantsMod.o +test_norman.o: norman_radiation.o norman_constants.o IOmod.o PatchModule.o OrbitalValsMod.o + + From 87ebac6d6d0d3f248b30e0d12259cf4860054c21 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 11 Apr 2023 12:06:25 -0600 Subject: [PATCH 624/852] move structure around to facilitate cmake --- unit_testing/Makefile | 64 ------------------- unit_testing/cmake_tests.py | 55 ++++++++++++++++ .../FatesUnitTestRadiation.F90 | 0 .../{ => utils}/FatesUnitTestIOMod.F90 | 0 .../{ => utils}/FatesUnitTestOrbitalMod.F90 | 0 5 files changed, 55 insertions(+), 64 deletions(-) delete mode 100644 unit_testing/Makefile create mode 100755 unit_testing/cmake_tests.py rename unit_testing/{ => radiation}/FatesUnitTestRadiation.F90 (100%) rename unit_testing/{ => utils}/FatesUnitTestIOMod.F90 (100%) rename unit_testing/{ => utils}/FatesUnitTestOrbitalMod.F90 (100%) diff --git a/unit_testing/Makefile b/unit_testing/Makefile deleted file mode 100644 index 5b9473ee1c..0000000000 --- a/unit_testing/Makefile +++ /dev/null @@ -1,64 +0,0 @@ -PROG = test_norman - -SRCS = FatesConstantsMod.F90 FatesGlobals.F90 log_mod.f90 \ - FatesHydraulicsMemMod.F90 FatesHydroWTFMod.F90 FatesLitterMod.F90 \ - CohortModule.f90 FatesRunningMeanMod.F90 PatchModule.f90 \ - PRTGenericMod.F90 PRTParametersMod.F90 norman_constants.f90 \ - IOMod.f90 norman_radiation.f90 test_norman.f90 OrbitalValsMod.f90 - - -OBJS = FatesConstantsMod.o FatesGlobals.o log_mod.o \ - FatesHydraulicsMemMod.o FatesHydroWTFMod.o FatesLitterMod.o \ - CohortModule.o FatesRunningMeanMod.o PatchModule.o \ - PRTGenericMod.o PRTParametersMod.o norman_constants.o \ - IOMod.o norman_radiation.o test_norman.o OrbitalValsMod.o - -## need both -LIBS = -L/usr/local/Cellar/netcdf/4.9.2/lib -lnetcdf -L/usr/local/Cellar/netcdf-fortran/4.6.0/lib -lnetcdff -lnetcdf - -INCLUDES = -I/usr/local/Cellar/netcdf-fortran/4.6.0/include - -F90 = gfortran - -##DBG = -g -fbacktrace -ffpe-trap=invalid,zero,overflow,underflow,denormal - -##OPT = -O2 -axcore-avx2 -xavx -align array64byte -ipo - -F90FLAGS = $(DBG) $(OPT) - -all: $(PROG) - -## link objects into a library (don't need includes?) -$(PROG): $(OBJS) - $(F90) -o $@ $(OBJS) $(LIBS) - -.PHONY: clean -clean: - rm -f $(PROG) $(OBJS) *.mod - -.SUFFIXES: $(SUFFIXES) .f90 .F90 .f95 .f - -# percent can stand for anything XX.o depends on XX.mod -%.o: %.mod - -# for each .o file, make it from a -.f90.o .f95.o .F90.o: - $(F90) $(F90FLAGS) $(INCLUDES) -c $< - -# dependencies (:) - if norman_constants.o gets updated, remake parameter_mod, etc. -FatesGlobals.o: FatesConstantsMod.o -FatesHydraulicsMemMod.o: FatesConstantsMod.o FatesHydroWTFMod.o norman_constants.o -FatesHydroWTFMod.o: FatesConstantsMod.o FatesGlobals.o log_mod.o -FatesLitterMod.o: FatesConstantsMod.o FatesGlobals.o log_mod.o -CohortModule.o: FatesConstantsMod.o PRTGenericMod.o FatesHydraulicsMemMod.o -FatesRunningMeanMod.o: FatesConstantsMod.o log_mod.o FatesGlobals.o norman_constants.o -PatchModule.o: CohortModule.o FatesLitterMod.o FatesRunningMeanMod.o FatesConstantsMod.o PRTGenericMod.o norman_constants.o -PRTGenericMod.o: FatesConstantsMod.o FatesGlobals.o log_mod.o PRTParametersMod.o -PRTParametersMod.o: FatesConstantsMod.o -IOMod.o: norman_constants.o -OrbitalValsMod.o: IOMod.o -norman_radiation.o: norman_constants.o -norman_constants.o: FatesConstantsMod.o -test_norman.o: norman_radiation.o norman_constants.o IOmod.o PatchModule.o OrbitalValsMod.o - - diff --git a/unit_testing/cmake_tests.py b/unit_testing/cmake_tests.py new file mode 100755 index 0000000000..4d7775ccb5 --- /dev/null +++ b/unit_testing/cmake_tests.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 + +import os +import sys +from shutil import rmtree + +def main(): + cmake_stage("radiation test", + "/Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing", + "test_pfunit_path") + +def cmake_stage( + name, + test_spec_dir, + pfunit_path, + cmake_args=None, + clean=False, +): + """Run cmake in the current working directory. + + Arguments: + name - Name for output messages. + test_spec_dir - Test specification directory to run CMake on. + """ + if clean: + if os.path.isfile("CMakeCache.txt"): + os.remove("CMakeCache.txt") + if os.path.isdir("CMakeFiles"): + rmtree("CMakeFiles") + + if not os.path.isfile("CMakeCache.txt"): + + print("Running cmake for " + name + ".") + + cmake_command = [ + "cmake", + "-C Macros.cmake", + test_spec_dir, + # "-DCIMEROOT=" + _CIMEROOT, + # "-DSRC_ROOT=" + get_src_root(), + # "-DCIME_CMAKE_MODULE_DIRECTORY=" + # + os.path.abspath(os.path.join(_CIMEROOT, "CIME", "non_py", "src", "CMake")), + # "-DCMAKE_BUILD_TYPE=" + build_type, + # "-DPFUNIT_MPIRUN='" + mpirun_command + "'", + # "-DPFUNIT_PATH=" + pfunit_path, + ] + + if cmake_args is not None: + cmake_command.extend(cmake_args.split(" ")) + + #run_cmd_no_fail(" ".join(cmake_command), combine_output=True) + print(" ".join(cmake_command)) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/unit_testing/FatesUnitTestRadiation.F90 b/unit_testing/radiation/FatesUnitTestRadiation.F90 similarity index 100% rename from unit_testing/FatesUnitTestRadiation.F90 rename to unit_testing/radiation/FatesUnitTestRadiation.F90 diff --git a/unit_testing/FatesUnitTestIOMod.F90 b/unit_testing/utils/FatesUnitTestIOMod.F90 similarity index 100% rename from unit_testing/FatesUnitTestIOMod.F90 rename to unit_testing/utils/FatesUnitTestIOMod.F90 diff --git a/unit_testing/FatesUnitTestOrbitalMod.F90 b/unit_testing/utils/FatesUnitTestOrbitalMod.F90 similarity index 100% rename from unit_testing/FatesUnitTestOrbitalMod.F90 rename to unit_testing/utils/FatesUnitTestOrbitalMod.F90 From 3f47c3106cd03794673eeaf3f952204c49e0009b Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Tue, 11 Apr 2023 12:27:25 -0600 Subject: [PATCH 625/852] added more organized parameter namespacing for trs parameters --- biogeochem/EDPhysiologyMod.F90 | 34 ++--- main/EDParamsMod.F90 | 8 +- main/EDPftvarcon.F90 | 64 ++++----- main/FatesConstantsMod.F90 | 8 +- parameter_files/fates_params_default.cdl | 176 +++++++++++------------ parteh/PRTParamsFATESMod.F90 | 8 +- 6 files changed, 151 insertions(+), 147 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 92de75b7ce..468ecda3af 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -24,8 +24,9 @@ module EDPhysiologyMod use FatesConstantsMod, only : r8 => fates_r8 use FatesConstantsMod, only : nearzero use FatesConstantsMod, only : sec_per_day - use FatesConstantsMod, only : TRS use FatesConstantsMod, only : default_regeneration + use FatesConstantsMod, only : TRS + use FatesConstantsMod, only : TRS_no_seedling_dyn use FatesConstantsMod, only : min_max_dbh_for_trees use FatesConstantsMod, only : megajoules_per_joule use FatesConstantsMod, only : mpa_per_mm_suction @@ -1785,8 +1786,6 @@ subroutine SeedIn( currentSite, bc_in ) integer :: n_litt_types ! number of litter element types (c,n,p, etc) integer :: el ! loop counter for litter element types integer :: element_id ! element id consistent with parteh/PRTGenericMod.F90 - integer, parameter :: TRS = 2 ! Switch option to use the Tree Recruitment Scheme - integer, parameter :: default_regeneration = 1 !Switch option to use FATES's default regeneration scheme !------------------------------------------------------------------------------------ do el = 1, num_elements @@ -2087,7 +2086,8 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) !============================================================================================== do pft = 1,numpft if ( regeneration_model == default_regeneration .or. & - prt_params%allom_dbh_maxheight(pft) < min_max_dbh_for_trees ) then + regeneration_model == TRS_no_seedling_dyn .or. & + prt_params%allom_dbh_maxheight(pft) < min_max_dbh_for_trees ) then !FATES default germination scheme litt%seed_germ_in(pft) = min(litt%seed(pft) * EDPftvarcon_inst%germination_rate(pft), & @@ -2141,19 +2141,20 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) !Step 4. Calculate the amount of carbon germinating out of the seed bank litt%seed_germ_in(pft) = litt%seed(pft) * seedling_emerg_rate - !ahb diagnostic - if (debug_trs) then - if (hlm_day_of_year == 40 .OR. hlm_day_of_year == 270) then - write(fates_log(),*) 'day_of_year:', hlm_day_of_year - write(fates_log(),*) 'patch_age:', currentPatch%age - write(fates_log(),*) 'pft', pft - write(fates_log(),*) 'seedling_layer_par (MJ m-2 day-1):', seedling_layer_par - write(fates_log(),*) 'seedling_layer_smp (mm h2o suction):', seedling_layer_smp - write(fates_log(),*) 'photoblastic_germ_modifier ([0,1]):', photoblastic_germ_modifier - write(fates_log(),*) 'seedling_emerg_rate (day-1):', seedling_emerg_rate - end if + ! !ahb diagnostic + ! if (debug_trs) then + ! if (hlm_day_of_year == 40 .OR. hlm_day_of_year == 270) then + ! write(fates_log(),*) 'day_of_year:', hlm_day_of_year + ! write(fates_log(),*) 'patch_age:', currentPatch%age + ! write(fates_log(),*) 'pft', pft + + ! write(fates_log(),*) 'seedling_layer_par (MJ m-2 day-1):', seedling_layer_par + ! write(fates_log(),*) 'seedling_layer_smp (mm h2o suction):', seedling_layer_smp + ! write(fates_log(),*) 'photoblastic_germ_modifier ([0,1]):', photoblastic_germ_modifier + ! write(fates_log(),*) 'seedling_emerg_rate (day-1):', seedling_emerg_rate + ! end if - end if !debug flag + ! end if !debug flag !end ahb diagnostic end if !regeneration model switch @@ -2386,6 +2387,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) !START ahb's changes !================================================================================= if ( regeneration_model == default_regeneration .or. & + regeneration_model == TRS_no_seedling_dyn .or. & prt_params%allom_dbh_maxheight(ft) < min_max_dbh_for_trees ) then mass_avail = currentPatch%area * currentPatch%litter(el)%seed_germ(ft) diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index eddbbcaed8..23e3b62170 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -104,10 +104,10 @@ module EDParamsMod ! to be used at each node (compartment/organ) ! 1 = Christofferson et al. 2016 (TFS), 2 = Van Genuchten 1980 - character(len=param_string_length),parameter,public :: ED_name_sdlng_emerg_h2o_timescale = "fates_sdlng_emerg_h2o_timescale" - character(len=param_string_length),parameter,public :: ED_name_sdlng_mort_par_timescale = "fates_sdlng_mort_par_timescale" - character(len=param_string_length),parameter,public :: ED_name_sdlng_mdd_timescale = "fates_sdlng_mdd_timescale" - character(len=param_string_length),parameter,public :: ED_name_sdlng2sap_par_timescale = "fates_sdlng2sap_par_timescale" + character(len=param_string_length),parameter,public :: ED_name_sdlng_emerg_h2o_timescale = "fates_trs_seedling_emerg_h2o_timescale" + character(len=param_string_length),parameter,public :: ED_name_sdlng_mort_par_timescale = "fates_trs_seedling_mort_par_timescale" + character(len=param_string_length),parameter,public :: ED_name_sdlng_mdd_timescale = "fates_trs_seedling_mdd_timescale" + character(len=param_string_length),parameter,public :: ED_name_sdlng2sap_par_timescale = "fates_trs_seedling2sap_par_timescale" integer, protected,allocatable,public :: hydr_htftype_node(:) character(len=param_string_length),parameter,public :: ED_name_photo_temp_acclim_timescale = "fates_leaf_photo_temp_acclim_timescale" character(len=param_string_length),parameter,public :: ED_name_photo_temp_acclim_thome_time = "fates_leaf_photo_temp_acclim_thome_time" diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 2ab3e5279c..041c80b92e 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -597,67 +597,67 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_repro_frac_seed' + name = 'fates_trs_repro_frac_seed' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_a_emerg' + name = 'fates_trs_seedling_a_emerg' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_b_emerg' + name = 'fates_trs_seedling_b_emerg' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_par_crit_germ' + name = 'fates_trs_seedling_par_crit_germ' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_seedling_psi_emerg' + name = 'fates_trs_seedling_psi_emerg' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_seedling_psi_crit' + name = 'fates_trs_seedling_psi_crit' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_seedling_light_rec_a' + name = 'fates_trs_seedling_light_rec_a' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_seedling_light_rec_b' + name = 'fates_trs_seedling_light_rec_b' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_seedling_mdd_crit' + name = 'fates_trs_seedling_mdd_crit' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_seedling_h2o_mort_a' + name = 'fates_trs_seedling_h2o_mort_a' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_seedling_h2o_mort_b' + name = 'fates_trs_seedling_h2o_mort_b' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_seedling_h2o_mort_c' + name = 'fates_trs_seedling_h2o_mort_c' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_seedling_root_depth' + name = 'fates_trs_seedling_root_depth' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_seedling_light_mort_a' + name = 'fates_trs_seedling_light_mort_a' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_seedling_light_mort_b' + name = 'fates_trs_seedling_light_mort_b' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_background_seedling_mort' + name = 'fates_trs_seedling_background_mort' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -1027,67 +1027,67 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetrieveParameterAllocate(name=name, & data=this%germination_rate) - name = 'fates_repro_frac_seed' + name = 'fates_trs_repro_frac_seed' call fates_params%RetrieveParameterAllocate(name=name, & data=this%repro_frac_seed) - name = 'fates_a_emerg' + name = 'fates_trs_seedling_a_emerg' call fates_params%RetrieveParameterAllocate(name=name, & data=this%a_emerg) - name = 'fates_b_emerg' + name = 'fates_trs_seedling_b_emerg' call fates_params%RetrieveParameterAllocate(name=name, & data=this%b_emerg) - name = 'fates_par_crit_germ' + name = 'fates_trs_seedling_par_crit_germ' call fates_params%RetrieveParameterAllocate(name=name, & data=this%par_crit_germ) - name = 'fates_seedling_psi_emerg' + name = 'fates_trs_seedling_psi_emerg' call fates_params%RetrieveParameterAllocate(name=name, & data=this%seedling_psi_emerg) - name = 'fates_seedling_psi_crit' + name = 'fates_trs_seedling_psi_crit' call fates_params%RetrieveParameterAllocate(name=name, & data=this%seedling_psi_crit) - name = 'fates_seedling_light_rec_a' + name = 'fates_trs_seedling_light_rec_a' call fates_params%RetrieveParameterAllocate(name=name, & data=this%seedling_light_rec_a) - name = 'fates_seedling_light_rec_b' + name = 'fates_trs_seedling_light_rec_b' call fates_params%RetrieveParameterAllocate(name=name, & data=this%seedling_light_rec_b) - name = 'fates_seedling_mdd_crit' + name = 'fates_trs_seedling_mdd_crit' call fates_params%RetrieveParameterAllocate(name=name, & data=this%seedling_mdd_crit) - name = 'fates_seedling_h2o_mort_a' + name = 'fates_trs_seedling_h2o_mort_a' call fates_params%RetrieveParameterAllocate(name=name, & data=this%seedling_h2o_mort_a) - name = 'fates_seedling_h2o_mort_b' + name = 'fates_trs_seedling_h2o_mort_b' call fates_params%RetrieveParameterAllocate(name=name, & data=this%seedling_h2o_mort_b) - name = 'fates_seedling_h2o_mort_c' + name = 'fates_trs_seedling_h2o_mort_c' call fates_params%RetrieveParameterAllocate(name=name, & data=this%seedling_h2o_mort_c) - name = 'fates_seedling_root_depth' + name = 'fates_trs_seedling_root_depth' call fates_params%RetrieveParameterAllocate(name=name, & data=this%seedling_root_depth) - name = 'fates_seedling_light_mort_a' + name = 'fates_trs_seedling_light_mort_a' call fates_params%RetrieveParameterAllocate(name=name, & data=this%seedling_light_mort_a) - name = 'fates_seedling_light_mort_b' + name = 'fates_trs_seedling_light_mort_b' call fates_params%RetrieveParameterAllocate(name=name, & data=this%seedling_light_mort_b) - name = 'fates_background_seedling_mort' + name = 'fates_trs_seedling_background_mort' call fates_params%RetrieveParameterAllocate(name=name, & data=this%background_seedling_mort) diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index e324414eca..ff35efef52 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -51,9 +51,11 @@ module FatesConstantsMod !Flags specifying how tree regeneration works - integer, public, parameter :: TRS_no_seedling_dyn = 3 !Constant defining the Tree Recruitment Scheme switch - integer, public, parameter :: TRS = 2 !Constant defining the Tree Recruitment Scheme switch - integer, public, parameter :: default_regeneration = 1 !Constant defining FATES's default regeneration scheme switch + integer, public, parameter :: TRS_no_seedling_dyn = 3 ! Constant defining the Tree Recruitment Scheme switch. This value + ! turns on size-based reproductive allocation and allocation to non-seed + ! reproductive biomass, but does not turn on seedling dynamics. + integer, public, parameter :: TRS = 2 !Constant defining the Tree Recruitment Scheme switch. This value turns on the full TRS. + integer, public, parameter :: default_regeneration = 1 !Constant defining FATES's default regeneration scheme switch. real(fates_r8), public, parameter :: min_max_dbh_for_trees = 15._fates_r8 !cm; if pfts have a max dbh less !than this value FATES !will use the default regeneration scheme. This is to avoid diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 8aa3c65217..74757c560b 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -461,60 +461,60 @@ variables: double fates_prescribed_npp_understory(fates_pft) ; fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; - double fates_repro_alloc_a(fates_pft) ; - fates_repro_alloc_a:units = "fraction" ; - fates_repro_alloc_a:long_name = "shape parameter for sigmoidal function relating dbh to reproductive allocation" ; - double fates_repro_alloc_b(fates_pft) ; - fates_repro_alloc_b:units = "fraction" ; - fates_repro_alloc_b:long_name = "intercept parameter for sigmoidal function relating dbh to reproductive allocation" ; - double fates_repro_frac_seed(fates_pft) ; - fates_repro_frac_seed:units = "fraction" ; - fates_repro_frac_seed:long_name = "fraction of reproductive mass that is seed" ; - double fates_a_emerg(fates_pft) ; - fates_a_emerg:units = "day -1" ; - fates_a_emerg:long_name = "mean fraction of seed bank emerging" ; - double fates_b_emerg(fates_pft) ; - fates_b_emerg:units = "day -1" ; - fates_b_emerg:long_name = "seedling emergence sensitivity to soil moisture" ; - double fates_par_crit_germ(fates_pft) ; - fates_par_crit_germ:units = "Megajoules m2-1 day-1 " ; - fates_par_crit_germ:long_name = "critical light level for germination" ; - double fates_seedling_root_depth(fates_pft) ; - fates_seedling_root_depth:units = "m" ; - fates_seedling_root_depth:long_name = "rooting depth of seedlings" ; - double fates_seedling_psi_emerg(fates_pft) ; - fates_seedling_psi_emerg:units = "mm h20 suction" ; - fates_seedling_psi_emerg:long_name = "critical soil moisture for seedling emergence" ; - double fates_seedling_psi_crit(fates_pft) ; - fates_seedling_psi_crit:units = "mm h20 suction" ; - fates_seedling_psi_crit:long_name = "critical soil moisture for seedling stress" ; - double fates_seedling_mdd_crit(fates_pft) ; - fates_seedling_mdd_crit:units = "moisture deficit days (mm h2o suction * days)" ; - fates_seedling_mdd_crit:long_name = "critical moisture deficit day accumulation for seedling moisture-based seedling mortality to begin" ; - double fates_seedling_h2o_mort_a(fates_pft) ; - fates_seedling_h2o_mort_a:units = "-" ; - fates_seedling_h2o_mort_a:long_name = "coefficient in moisture-based seedling mortality" ; - double fates_seedling_h2o_mort_b(fates_pft) ; - fates_seedling_h2o_mort_b:units = "-" ; - fates_seedling_h2o_mort_b:long_name = "coefficient in moisture-based seedling mortality" ; - double fates_seedling_h2o_mort_c(fates_pft) ; - fates_seedling_h2o_mort_c:units = "-" ; - fates_seedling_h2o_mort_c:long_name = "coefficient in moisture-based seedling mortality" ; - double fates_seedling_light_mort_a(fates_pft) ; - fates_seedling_light_mort_a:units = "-" ; - fates_seedling_light_mort_a:long_name = "light-based seedling mortality coefficient" ; - double fates_seedling_light_mort_b(fates_pft) ; - fates_seedling_light_mort_b:units = "-" ; - fates_seedling_light_mort_b:long_name = "light-based seedling mortality coefficient" ; - double fates_background_seedling_mort(fates_pft) ; - fates_background_seedling_mort:units = "yr-1" ; - fates_background_seedling_mort:long_name = "background seedling mortality rate" ; - double fates_seedling_light_rec_a(fates_pft) ; - fates_seedling_light_rec_a:units = "-" ; - fates_seedling_light_rec_a:long_name = "coefficient in light-based seedling to sapling transition" ; - double fates_seedling_light_rec_b(fates_pft) ; - fates_seedling_light_rec_b:units = "-" ; - fates_seedling_light_rec_b:long_name = "coefficient in light-based seedling to sapling transition" ; + double fates_trs_repro_alloc_a(fates_pft) ; + fates_trs_repro_alloc_a:units = "fraction" ; + fates_trs_repro_alloc_a:long_name = "shape parameter for sigmoidal function relating dbh to reproductive allocation" ; + double fates_trs_repro_alloc_b(fates_pft) ; + fates_trs_repro_alloc_b:units = "fraction" ; + fates_trs_repro_alloc_b:long_name = "intercept parameter for sigmoidal function relating dbh to reproductive allocation" ; + double fates_trs_repro_frac_seed(fates_pft) ; + fates_trs_repro_frac_seed:units = "fraction" ; + fates_trs_repro_frac_seed:long_name = "fraction of reproductive mass that is seed" ; + double fates_trs_seedling_a_emerg(fates_pft) ; + fates_trs_seedling_a_emerg:units = "day -1" ; + fates_trs_seedling_a_emerg:long_name = "mean fraction of seed bank emerging" ; + double fates_trs_seedling_b_emerg(fates_pft) ; + fates_trs_seedling_b_emerg:units = "day -1" ; + fates_trs_seedling_b_emerg:long_name = "seedling emergence sensitivity to soil moisture" ; + double fates_trs_seedling_par_crit_germ(fates_pft) ; + fates_trs_seedling_par_crit_germ:units = "Megajoules m2-1 day-1 " ; + fates_trs_seedling_par_crit_germ:long_name = "critical light level for germination" ; + double fates_trs_seedling_root_depth(fates_pft) ; + fates_trs_seedling_root_depth:units = "m" ; + fates_trs_seedling_root_depth:long_name = "rooting depth of seedlings" ; + double fates_trs_seedling_psi_emerg(fates_pft) ; + fates_trs_seedling_psi_emerg:units = "mm h20 suction" ; + fates_trs_seedling_psi_emerg:long_name = "critical soil moisture for seedling emergence" ; + double fates_trs_seedling_psi_crit(fates_pft) ; + fates_trs_seedling_psi_crit:units = "mm h20 suction" ; + fates_trs_seedling_psi_crit:long_name = "critical soil moisture for seedling stress" ; + double fates_trs_seedling_mdd_crit(fates_pft) ; + fates_trs_seedling_mdd_crit:units = "moisture deficit days (mm h2o suction * days)" ; + fates_trs_seedling_mdd_crit:long_name = "critical moisture deficit day accumulation for seedling moisture-based seedling mortality to begin" ; + double fates_trs_seedling_h2o_mort_a(fates_pft) ; + fates_trs_seedling_h2o_mort_a:units = "-" ; + fates_trs_seedling_h2o_mort_a:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_trs_seedling_h2o_mort_b(fates_pft) ; + fates_trs_seedling_h2o_mort_b:units = "-" ; + fates_trs_seedling_h2o_mort_b:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_trs_seedling_h2o_mort_c(fates_pft) ; + fates_trs_seedling_h2o_mort_c:units = "-" ; + fates_trs_seedling_h2o_mort_c:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_trs_seedling_light_mort_a(fates_pft) ; + fates_trs_seedling_light_mort_a:units = "-" ; + fates_trs_seedling_light_mort_a:long_name = "light-based seedling mortality coefficient" ; + double fates_trs_seedling_light_mort_b(fates_pft) ; + fates_trs_seedling_light_mort_b:units = "-" ; + fates_trs_seedling_light_mort_b:long_name = "light-based seedling mortality coefficient" ; + double fates_trs_seedling_background_mort(fates_pft) ; + fates_trs_seedling_background_mort:units = "yr-1" ; + fates_trs_seedling_background_mort:long_name = "background seedling mortality rate" ; + double fates_trs_seedling_light_rec_a(fates_pft) ; + fates_trs_seedling_light_rec_a:units = "-" ; + fates_trs_seedling_light_rec_a:long_name = "coefficient in light-based seedling to sapling transition" ; + double fates_trs_seedling_light_rec_b(fates_pft) ; + fates_trs_seedling_light_rec_b:units = "-" ; + fates_trs_seedling_light_rec_b:long_name = "coefficient in light-based seedling to sapling transition" ; double fates_rad_leaf_clumping_index(fates_pft) ; fates_rad_leaf_clumping_index:units = "fraction (0-1)" ; fates_rad_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; @@ -839,18 +839,18 @@ variables: double fates_phen_ncolddayslim ; fates_phen_ncolddayslim:units = "days" ; fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; - double fates_sdlng_emerg_h2o_timescale ; - fates_sdlng_emerg_h2o_timescale:units = "days" ; - fates_sdlng_emerg_h2o_timescale:long_name = "Length of the window for the exponential moving average of smp used to calculate seedling emergence" ; - double fates_sdlng_mort_par_timescale ; - fates_sdlng_mort_par_timescale:units = "days" ; - fates_sdlng_mort_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling mortality" ; - double fates_sdlng_mdd_timescale ; - fates_sdlng_mdd_timescale:units = "days" ; - fates_sdlng_mdd_timescale:long_name = "Length of the window for the exponential moving average of moisture deficit days used to calculate seedling mortality" ; - double fates_sdlng2sap_par_timescale ; - fates_sdlng2sap_par_timescale:units = "days" ; - fates_sdlng2sap_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling to sapling transition rates" ; + double fates_trs_seedling_emerg_h2o_timescale ; + fates_trs_seedling_emerg_h2o_timescale:units = "days" ; + fates_trs_seedling_emerg_h2o_timescale:long_name = "Length of the window for the exponential moving average of smp used to calculate seedling emergence" ; + double fates_trs_seedling_mort_par_timescale ; + fates_trs_seedling_mort_par_timescale:units = "days" ; + fates_trs_seedling_mort_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling mortality" ; + double fates_trs_seedling_mdd_timescale ; + fates_trs_seedling_mdd_timescale:units = "days" ; + fates_trs_seedling_mdd_timescale:long_name = "Length of the window for the exponential moving average of moisture deficit days used to calculate seedling mortality" ; + double fates_trs_seedling2sap_par_timescale ; + fates_trs_seedling2sap_par_timescale:units = "days" ; + fates_trs_seedling2sap_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling to sapling transition rates" ; double fates_q10_froz ; fates_q10_froz:units = "unitless" ; fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; @@ -1389,61 +1389,61 @@ data: fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02 ; - fates_repro_alloc_a = 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, + fates_trs_repro_alloc_a = 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049 ; - fates_repro_alloc_b = -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, + fates_trs_repro_alloc_b = -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171 ; - fates_repro_frac_seed = 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, + fates_trs_repro_frac_seed = 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24 ; - fates_a_emerg = 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, + fates_trs_seedling_a_emerg = 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003 ; - fates_b_emerg = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 ; + fates_trs_seedling_b_emerg = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 ; - fates_par_crit_germ = 0.656, 0.656, 0.656, 0.656, 0.656, 0.656, + fates_trs_seedling_par_crit_germ = 0.656, 0.656, 0.656, 0.656, 0.656, 0.656, 0.656, 0.656, 0.656, 0.656, 0.656, 0.656 ; - fates_seedling_psi_emerg = -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, + fates_trs_seedling_psi_emerg = -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65 ; - fates_seedling_psi_crit = -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, + fates_trs_seedling_psi_crit = -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7 ; - fates_seedling_mdd_crit = 1400000.0, 1400000.0, 1400000.0, 1400000.0, 1400000.0, + fates_trs_seedling_mdd_crit = 1400000.0, 1400000.0, 1400000.0, 1400000.0, 1400000.0, 1400000.0, 1400000.0, 1400000.0, 1400000.0, 1400000.0, 1400000.0, 1400000.0 ; - fates_seedling_h2o_mort_a = 4.070565e-17, 4.070565e-17, 4.070565e-17, + fates_trs_seedling_h2o_mort_a = 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17 ; - fates_seedling_h2o_mort_b = -6.390757e-11, -6.390757e-11, -6.390757e-11, + fates_trs_seedling_h2o_mort_b = -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11 ; - fates_seedling_h2o_mort_c = 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, + fates_trs_seedling_h2o_mort_c = 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05 ; - fates_seedling_light_mort_a = -0.009897694, -0.009897694, -0.009897694, -0.009897694, + fates_trs_seedling_light_mort_a = -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694 ; - fates_seedling_light_mort_b = -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, + fates_trs_seedling_light_mort_b = -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063 ; - fates_background_seedling_mort = 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, + fates_trs_seedling_background_mort = 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371 ; - fates_seedling_root_depth = 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, + fates_trs_seedling_root_depth = 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06 ; - fates_seedling_light_rec_a = 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, + fates_trs_seedling_light_rec_a = 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, 0.007 ; - fates_seedling_light_rec_b = 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, + fates_trs_seedling_light_rec_b = 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615 ; fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, @@ -1673,13 +1673,13 @@ data: fates_phen_moist_threshold = 0.18 ; - fates_sdlng_emerg_h2o_timescale = 7 ; + fates_trs_seedling_emerg_h2o_timescale = 7 ; - fates_sdlng_mort_par_timescale = 32 ; + fates_trs_seedling_mort_par_timescale = 32 ; - fates_sdlng_mdd_timescale = 126 ; + fates_trs_seedling_mdd_timescale = 126 ; - fates_sdlng2sap_par_timescale = 32 ; + fates_trs_seedling2sap_par_timescale = 32 ; fates_phen_ncolddayslim = 5 ; diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index 1f790eaf29..f525452fbc 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -230,11 +230,11 @@ subroutine PRTRegisterPFT(fates_params) !ahb added the params below !------------------------------------------------------------------------------------- - name = 'fates_repro_alloc_a' + name = 'fates_trs_repro_alloc_a' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_repro_alloc_b' + name = 'fates_trs_repro_alloc_b' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) !-------------------------------------------------------------------------------------- @@ -507,11 +507,11 @@ subroutine PRTReceivePFT(fates_params) !ahb added the code below !-------------------------------------------------------- - name = 'fates_repro_alloc_a' + name = 'fates_trs_repro_alloc_a' call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%repro_alloc_a) - name = 'fates_repro_alloc_b' + name = 'fates_trs_repro_alloc_b' call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%repro_alloc_b) !--------------------------------------------------------- From 89e5ae87f0cea097704c554911495c6353dbfee3 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 11 Apr 2023 14:09:30 -0600 Subject: [PATCH 626/852] updates for making --- unit_testing/radiation/FatesUnitTestRadiation.F90 | 15 +++++++-------- unit_testing/utils/FatesUnitTestOrbitalMod.F90 | 4 ++-- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/unit_testing/radiation/FatesUnitTestRadiation.F90 b/unit_testing/radiation/FatesUnitTestRadiation.F90 index 56ce2d75ee..21ca8c57df 100644 --- a/unit_testing/radiation/FatesUnitTestRadiation.F90 +++ b/unit_testing/radiation/FatesUnitTestRadiation.F90 @@ -8,12 +8,12 @@ program FatesUnitTestRadiation use FatesUnitTestOrbitalMod, only : SHR_KIND_R8 use FatesUnitTestOrbitalMod, only : get_orbital_vals, shr_orb_cosz use FatesUnitTestOrbitalMod, only : shr_orb_decl - use EDParamsMod, only : nlevleaf, nclmax + !use EDParamsMod, only : nlevleaf, nclmax implicit none ! LOCALS: - character(len=MAX_PATH) :: param_file, patch_file, out_file ! file names + character(len=256) :: param_file, patch_file, out_file ! file names integer :: numpft, numSWb ! real(r8) :: rhol(num_pft,num_swb) ! leaf reflectance (0-1) ! real(r8) :: rhos(num_pft,num_swb) ! stem reflectance (0-1) @@ -49,11 +49,10 @@ subroutine read_radiation_namelist(numpft, numSWb, param_file, patch_file, & use FatesUnitTestIOMod, only : MAX_PATH, MAX_CHAR, open_file - implicit none - - character(len=MAX_PATH), intent(out) :: param_file, patch_file, out_file ! file names - integer, intent(out) :: numpft, numSWb + implicit none + character(len=MAX_PATH), intent(out) :: param_file, patch_file, out_file ! file names + integer, intent(out) :: numpft, numSWb end subroutine read_radiation_namelist @@ -120,8 +119,8 @@ subroutine read_radiation_namelist(numpft, numSWb, param_file, patch_file, & ! LOCALS: character(len=MAX_PATH) :: rad_nl = 'radiation_nl' ! radiation namelist name - character(len=MAX_CHAR) :: message ! Error message - character(len=MAX_CHAR) :: msg ! I/O Error message + character(len=MAX_PATH) :: message ! Error message + character(len=MAX_PATH) :: msg ! I/O Error message integer :: rad_nl_file ! unit number for namelist integer :: ios ! I/O status diff --git a/unit_testing/utils/FatesUnitTestOrbitalMod.F90 b/unit_testing/utils/FatesUnitTestOrbitalMod.F90 index b1e55591af..843bf1e217 100644 --- a/unit_testing/utils/FatesUnitTestOrbitalMod.F90 +++ b/unit_testing/utils/FatesUnitTestOrbitalMod.F90 @@ -6,7 +6,7 @@ module FatesUnitTestOrbitalMod ! ! - use IOMod + use FatesUnitTestIOMod implicit none @@ -69,7 +69,7 @@ subroutine shr_orb_params(iyear_AD, eccen, obliq, mvelp, & ! !--------------------------------------------------------------------------- - !----------------------------- Arguments ------------------------------------ + !----------------------------- Arguments ----------------------------------- integer(SHR_KIND_IN), intent(in) :: iyear_AD ! Year to calculate orbit for real(SHR_KIND_R8), intent(inout) :: eccen ! orbital eccentricity real(SHR_KIND_R8), intent(inout) :: obliq ! obliquity in degrees From 925b257c16139212b0828bccadb3b97237247b31 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 11 Apr 2023 14:32:19 -0600 Subject: [PATCH 627/852] add Cmakelists --- unit_testing/CMakeLists.txt | 12 ++++++++++++ unit_testing/radiation/CMakeLists.txt | 10 ++++++++++ unit_testing/utils/CMakeLists.txt | 5 +++++ 3 files changed, 27 insertions(+) create mode 100644 unit_testing/CMakeLists.txt create mode 100644 unit_testing/radiation/CMakeLists.txt create mode 100644 unit_testing/utils/CMakeLists.txt diff --git a/unit_testing/CMakeLists.txt b/unit_testing/CMakeLists.txt new file mode 100644 index 0000000000..506036d449 --- /dev/null +++ b/unit_testing/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 2.8) + +list(APPEND CMAKE_MODULE_PATH ${CIME_CMAKE_MODULE_DIRECTORY}) +include(CIME_initial_setup) + +project(radiation_tests Fortran C) + +include(CIME_utils) + +add_subdirectory(radiation) + +add_subdirectory(utils) diff --git a/unit_testing/radiation/CMakeLists.txt b/unit_testing/radiation/CMakeLists.txt new file mode 100644 index 0000000000..54408798ec --- /dev/null +++ b/unit_testing/radiation/CMakeLists.txt @@ -0,0 +1,10 @@ +# Local files +set(test_sources FatesUnitTestRadiation.F90) + +# Add sources we need from other directories +set(sources_needed + FatesUnitTestIOMod.F90 + FatesUnitTestOrbitalMod.F90) +extract_sources("${sources_needed}" "${utils_sources}" test_sources) + +add_executable(FATES_rad_test ${test_sources}) diff --git a/unit_testing/utils/CMakeLists.txt b/unit_testing/utils/CMakeLists.txt new file mode 100644 index 0000000000..b5432bf9cd --- /dev/null +++ b/unit_testing/utils/CMakeLists.txt @@ -0,0 +1,5 @@ +# Append sources from this directory to the list. +list(APPEND utils_sources FatesUnitTestIOMod.F90 FatesUnitTestOrbitalMod.F90) + +# Export source list to parent +sourcelist_to_parent(circle_area_sources) \ No newline at end of file From c5d85126bb8790ff281422e66a54874147d22198 Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Tue, 11 Apr 2023 14:53:51 -0600 Subject: [PATCH 628/852] started adding recruitment_appf history variable --- biogeochem/EDPhysiologyMod.F90 | 1 - main/EDTypesMod.F90 | 1 - 2 files changed, 2 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 468ecda3af..8e90015032 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2571,7 +2571,6 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) ! keep track of how many individuals were recruited for passing to history currentSite%recruitment_rate(ft) = currentSite%recruitment_rate(ft) + temp_cohort%n - endif any_recruits endif !use_this_pft enddo !pft loop diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 2d38bd635f..c015ea86d4 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -624,7 +624,6 @@ module EDTypesMod ! PLANT HYDRAULICS (not currently used in hydraulics RGK 03-2018) ! type(ed_patch_hydr_type) , pointer :: pa_hydr ! All patch hydraulics data, see FatesHydraulicsMemMod.F90 - end type ed_patch_type From e5d45bfd62922306d17de5d5343e5e05d4a2577f Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Tue, 11 Apr 2023 17:23:30 -0600 Subject: [PATCH 629/852] cleaned up comments prior to pull request --- biogeochem/EDPatchDynamicsMod.F90 | 18 +- biogeochem/EDPhysiologyMod.F90 | 269 +-- biogeochem/EDPhysiologyMod.F90.save | 2396 --------------------------- biogeochem/FatesLitterMod.F90 | 8 - main/EDParamsMod.F90 | 6 +- main/EDPftvarcon.F90 | 33 +- main/FatesConstantsMod.F90 | 23 +- main/FatesInterfaceMod.F90 | 67 +- parteh/PRTAllometricCarbonMod.F90 | 50 +- 9 files changed, 173 insertions(+), 2697 deletions(-) delete mode 100644 biogeochem/EDPhysiologyMod.F90.save diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index f1194ee084..8b39565909 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -663,11 +663,10 @@ subroutine spawn_patches( currentSite, bc_in) call new_patch%seedling_layer_par24%CopyFromDonor(currentPatch%seedling_layer_par24) call new_patch%sdlng_mort_par%CopyFromDonor(currentPatch%sdlng_mort_par) call new_patch%sdlng2sap_par%CopyFromDonor(currentPatch%sdlng2sap_par) - do pft = 1,maxpft - call new_patch%sdlng_emerg_smp(pft)%p%CopyFromDonor(currentPatch%sdlng_emerg_smp(pft)%p) !ahb - call new_patch%sdlng_mdd(pft)%p%CopyFromDonor(currentPatch%sdlng_mdd(pft)%p) !ahb + call new_patch%sdlng_emerg_smp(pft)%p%CopyFromDonor(currentPatch%sdlng_emerg_smp(pft)%p) + call new_patch%sdlng_mdd(pft)%p%CopyFromDonor(currentPatch%sdlng_mdd(pft)%p) enddo call new_patch%tveg_longterm%CopyFromDonor(currentPatch%tveg_longterm) @@ -1482,9 +1481,6 @@ subroutine TransLitterNewPatch(currentSite, & new_litt%seed_decay(pft) = new_litt%seed_decay(pft) + & curr_litt%seed_decay(pft)*patch_site_areadis/newPatch%area - new_litt%non_seed_repro_mass_decay(pft) = new_litt%non_seed_repro_mass_decay(pft) + & !ahb added this - curr_litt%non_seed_repro_mass_decay(pft)*patch_site_areadis/newPatch%area !ahb added this - new_litt%seed_germ_decay(pft) = new_litt%seed_germ_decay(pft) + & curr_litt%seed_germ_decay(pft)*patch_site_areadis/newPatch%area @@ -2104,11 +2100,11 @@ subroutine create_patch(currentSite, new_patch, age, areap, label,nocomp_pft) ! Until bc's are pointed to by sites give veg a default temp [K] real(r8), parameter :: temp_init_veg = 15._r8+t_water_freeze_k_1atm - real(r8), parameter :: init_seedling_par = 5.0_r8 !arbtrary initialization, ahb + real(r8), parameter :: init_seedling_par = 5.0_r8 !arbtrary initialization for + !seedling layer PAR [MJ m-2 d-1] - real(r8), parameter :: init_seedling_smp = -26652.0_r8 !mean smp (mm) from prior ED2 - !simulation at BCI (arbitrary) - integer :: pft !pft index + real(r8), parameter :: init_seedling_smp = -26652.0_r8 !arbitrary initialization of smp [mm] + integer :: pft !pft index ! !LOCAL VARIABLES: !--------------------------------------------------------------------- @@ -2682,7 +2678,7 @@ subroutine fuse_2_patches(csite, dp, rp) type (ed_cohort_type), pointer :: nextc ! Remembers next cohort in list type (ed_cohort_type), pointer :: storesmallcohort type (ed_cohort_type), pointer :: storebigcohort - integer :: c,p,pft !counters for pft and litter size class. ahb added pft here. + integer :: c,p,pft ! counters for pft and litter size class integer :: tnull,snull ! are the tallest and shortest cohorts associated? integer :: el ! loop counting index for elements type(ed_patch_type), pointer :: youngerp ! pointer to the patch younger than donor diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 8e90015032..fdb112c439 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -150,7 +150,6 @@ module EDPhysiologyMod public :: SetRecruitL2FR logical, parameter :: debug = .false. ! local debug flag - logical, parameter :: debug_trs = .true. ! local debug flag character(len=*), parameter, private :: sourcefile = & __FILE__ @@ -436,7 +435,7 @@ subroutine PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in ) ! germination from occuring when the site is in a drought ! (for drought deciduous) or too cold (for cold deciduous) - call SeedGermination(litt, currentSite%cstatus, currentSite%dstatus, bc_in, currentPatch) !ahb added currentPatch + call SeedGermination(litt, currentSite%cstatus, currentSite%dstatus, bc_in, currentPatch) ! Send fluxes from newly created litter into the litter pools ! This litter flux is from non-disturbance inducing mortality, as well @@ -455,7 +454,6 @@ subroutine PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in ) site_mass%frag_out = site_mass%frag_out + currentPatch%area * & ( sum(litt%ag_cwd_frag) + sum(litt%bg_cwd_frag) + & sum(litt%leaf_fines_frag) + sum(litt%root_fines_frag) + & - !sum(litt%non_seed_repro_mass_decay) + & !ahb added this line on 7/8/2021 sum(litt%seed_decay) + sum(litt%seed_germ_decay)) end do @@ -1801,7 +1799,6 @@ subroutine SeedIn( currentSite, bc_in ) do while (associated(currentPatch)) currentCohort => currentPatch%tallest - !litt => currentPatch%litter(el) !added by ahb do while (associated(currentCohort)) pft = currentCohort%pft @@ -1856,24 +1853,21 @@ subroutine SeedIn( currentSite, bc_in ) do pft = 1,numpft if(currentSite%use_this_pft(pft).eq.itrue)then + ! Seed input from local sources (within site) litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)/area - !START ahb's changes + ! If we are using the Tree Recruitment Scheme (TRS) with or w/o seedling dynamics if ( regeneration_model >= TRS .and. & prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees) then - !Send a fraction of reproductive carbon to litter to account for - !non-seed reproductive carbon (e.g. flowers, fruit, etc.) - !If using default_regeneration then all reproductive carbon becomes seed - !This process will be more important if/when FATES fixes the structural issue - !that all carbon used to make recruits comes from reproductive carbon. + ! Send a fraction of reproductive carbon to litter to account for + ! non-seed reproductive carbon (e.g. flowers, fruit, etc.) litt%seed_decay(pft) = litt%seed_in_local(pft) * (1.0_r8 - EDPftvarcon_inst%repro_frac_seed(pft)) + ! Note: The default regeneration scheme sends all reproductive carbon to seed end if !Use TRS - !Default regeneration scheme sends all reproductive carbon to seed (i.e. do nothing here) - !END ahb's changes ! If there is forced external seed rain, we calculate the input mass flux ! from the different elements, using the mean stoichiometry of new @@ -1916,7 +1910,9 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) ! ! !DESCRIPTION: ! 1. Flux from seed pool into leaf litter pool - ! 2. (if TRS is on) Seedling mortality (i.e. flux from seedling pool into leaf litter pool) + ! 2. If the TRS with seedling dynamics is on (regeneration_model = 3) + ! then we calculate seedling mortality here (i.e. flux from seedling pool + ! (into leaf litter pool) ! ! !ARGUMENTS type(litter_type) :: litt @@ -1925,11 +1921,12 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) ! ! !LOCAL VARIABLES: integer :: pft - real(r8) :: seedling_layer_par !cumulative light at the seedling layer (MJ) over prior window of days - !(defined by 'light_mort_window' param) - real(r8) :: seedling_light_mort_rate !the daily seedling mortality rate from light stress - real(r8) :: seedling_h2o_mort_rate !the daily seedling mortality rate from moisture stress - real(r8) :: seedling_mdds !moisture deficit days accumulated in the seedling layer + real(r8) :: seedling_layer_par ! cumulative sum of PAR at the seedling layer (MJ) + ! over prior window of days defined by + ! fates_trs_seedling_mort_par_timescale + real(r8) :: seedling_light_mort_rate ! daily seedling mortality rate from light stress + real(r8) :: seedling_h2o_mort_rate ! daily seedling mortality rate from moisture stress + real(r8) :: seedling_mdds ! moisture deficit days accumulated in the seedling layer !---------------------------------------------------------------------- @@ -1942,93 +1939,76 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) ! seed_decay is kg/day ! Assume that decay rates are same for all chemical species - ! START ahb's changes !===================================================================================== do pft = 1,numpft - !If the TRS is switched off or the pft is not a tree then use the default - !regeneration scheme. + ! If the TRS is switched off or the pft can't get big enough to be considered a tree + ! then use FATES default regeneration. if ( regeneration_model == default_regeneration .or. & prt_params%allom_dbh_maxheight(pft) < min_max_dbh_for_trees ) then - !Default seed decay scheme (original code) + ! Default seed decay (TRS is off) litt%seed_decay(pft) = litt%seed(pft) * & EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day - end if !end default regeneration model + end if ! End default regeneration model - ! If the TRS is fully switched on, or if it is switched on without seedling dynamics - ! (regeneration_model = TRS_no_seedling_dyn), - ! and the pft is a tree then make sure the non-seed reproductive biomass is added the - ! the seed decay flux. + ! If the TRS is switched on and the pft is a tree then add non-seed reproductive biomass + ! to the seed decay flux. This was added to litt%seed_decay in the previously called SeedIn + ! subroutine if ( regeneration_model >= TRS .and. & prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees ) then - !---------------------------------------------------------------------- - !With respect to seed decay, the only difference with the TRS here is adding the flux - !from non-seed reproductive biomass (which was sent to litt%seed_decay in the SeedIn subroutine) - - litt%seed_decay(pft) = litt%seed_decay(pft) + &!from non-seed reproductive biomass. + litt%seed_decay(pft) = litt%seed_decay(pft) + &! From non-seed reproductive biomass (added in + ! in the SeedIn subroutine. litt%seed(pft) * EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day - end if !Send non-seed reproductive biomass to seed decay flux. + end if ! End use TRS - ! If the full TRS model is switch on (regeneration_model == TRS) then calculate seedling mortality. + ! If the TRS is switched on with seedling dynamics (regeneration_model = 3) + ! then calculate seedling mortality. if ( regeneration_model == TRS .and. & prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees ) then - !Seedling mortality (i.e. fluxes from seedling pool (seed_germ) to litter) !---------------------------------------------------------------------- - !Step 1. Calculate the daily seedling mortality rate from light stress - - !Calculate the cumulative light at the seedling layer over a prior number of - !days set by the "sdlng_mort_par_timescale" parameter + ! Seedling mortality (flux from seedling pool to litter) + ! Note: The TRS uses the litt%seed_germ data struture to track seedlings + + ! Step 1. Calculate the daily seedling mortality rate from light stress + ! Calculate the cumulative light at the seedling layer over a prior number of + ! days determined by the "fates_tres_seedling_mort_par_timescale" parameter. seedling_layer_par = currentPatch%sdlng_mort_par%GetMean() * megajoules_per_joule * & sec_per_day * sdlng_mort_par_timescale + ! Calculate daily seedling mortality rate from light seedling_light_mort_rate = exp( EDPftvarcon_inst%seedling_light_mort_a(pft) * & seedling_layer_par + EDPftvarcon_inst%seedling_light_mort_b(pft) ) - !Step 3. Calculate the daily seedling mortality rate from moisture stress + ! Step 2. Calculate the daily seedling mortality rate from moisture stress - !Get the current seedling moisture deficit days - !Calculated as (abs(seedling_psi_crit) - abs(seedling_layer_smp))* -1 * mddWindow + ! Get the current seedling moisture deficit days (tracked as a pft-specific exponential + ! average) seedling_mdds = currentPatch%sdlng_mdd(pft)%p%GetMean() - !Calculate seedling mortality as a function of moisture deficit days + ! Calculate seedling mortality as a function of moisture deficit days (mdd) seedling_h2o_mort_rate = EDPftvarcon_inst%seedling_h2o_mort_a(pft) * seedling_mdds**2 + & EDPftvarcon_inst%seedling_h2o_mort_b(pft) * seedling_mdds + & EDPftvarcon_inst%seedling_h2o_mort_c(pft) + ! If the seedling mmd value is below a critical threshold then moisture-based mortality is zero if (seedling_mdds < EDPftvarcon_inst%seedling_mdd_crit(pft)) then seedling_h2o_mort_rate = 0.0_r8 - end if !mdd threshold check + end if ! mdd threshold check - !Step 4. Add background mortality and send dead seedling carbon to litter (i.e. to seed_germ_decay flux) + ! Step 3. Sum modes of mortality (including background mortality) and send dead seedlings + ! to litter litt%seed_germ_decay(pft) = (litt%seed_germ(pft) * seedling_light_mort_rate) + & (litt%seed_germ(pft) * seedling_h2o_mort_rate) + & (litt%seed_germ(pft) * EDPftvarcon_inst%background_seedling_mort(pft) & * years_per_day) - end if !Use full TRS - - !ahb diagnostic - ! if (debug_trs) then - ! if (hlm_day_of_year == 40 .OR. hlm_day_of_year == 270) then - ! write(fates_log(),*) 'day_of_year:', hlm_day_of_year - ! write(fates_log(),*) 'patch_age:', currentPatch%age - ! write(fates_log(),*) 'pft', pft - ! write(fates_log(),*) 'seedling_light_mort_rate (day -1):', seedling_light_mort_rate - ! write(fates_log(),*) 'seedling_h2o_mort_rate (day -1):', seedling_h2o_mort_rate - ! write(fates_log(),*) 'seedling mdds ([0,1]):', seedling_mdds - ! end if - - ! end if !debug flag - !end ahb diagnostic - - !----------------------------------------------------------------------- - !END ahb's changes + end if ! End use TRS with seedling dynamics enddo @@ -2036,7 +2016,7 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) end subroutine SeedDecay ! ============================================================================ - subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) !ahb added currentPatch and bc_in + subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) ! ! !DESCRIPTION: ! Flux from seed bank into the seedling pool @@ -2048,8 +2028,8 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) type(litter_type) :: litt integer, intent(in) :: cold_stat ! Is the site in cold leaf-off status? integer, intent(in) :: drought_stat ! Is the site in drought leaf-off status? - type(bc_in_type), intent(in) :: bc_in ! ahb added this July 2021 - type(ed_patch_type), intent(in) :: currentPatch ! ahb added this July 2021 + type(bc_in_type), intent(in) :: bc_in + type(ed_patch_type), intent(in) :: currentPatch ! ! !LOCAL VARIABLES: integer :: pft @@ -2058,15 +2038,15 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) !Light and moisture-sensitive seedling emergence variables (ahb) !------------------------------------------------------------------------------------------------------------ - integer :: ilayer_seedling_root ! the soil layer at seedling rooting depth - real(r8) :: seedling_layer_smp ! soil matric potential at seedling rooting depth - real(r8) :: wetness_index ! a soil 'wetness index' (1 / - SoilMatricPotetial (MPa) ) - real(r8) :: seedling_layer_par ! par at the seedling layer (MJ m-2 day-1) - real(r8) :: slsmp_emerg !temp - real(r8) :: slparmort !temp - real(r8) :: slpartrans !temp - real(r8) :: photoblastic_germ_modifier ! seedling emergence rate modifier for light-sensitive germination - real(r8) :: seedling_emerg_rate ! the fraction of the seed bank emerging in the current time step + integer :: ilayer_seedling_root ! the soil layer at seedling rooting depth + real(r8) :: seedling_layer_smp ! soil matric potential at seedling rooting depth + real(r8) :: wetness_index ! a soil 'wetness index' (1 / - SoilMatricPotetial (MPa) ) + real(r8) :: seedling_layer_par ! par at the seedling layer (MJ m-2 day-1) + real(r8) :: slsmp_emerg ! temp + real(r8) :: slparmort ! temp + real(r8) :: slpartrans ! temp + real(r8) :: photoblastic_germ_modifier ! seedling emergence rate modifier for light-sensitive germination + real(r8) :: seedling_emerg_rate ! the fraction of the seed bank emerging in the current time step !------------------------------------------------------------------------------------------------------------- @@ -2082,53 +2062,49 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) ! and thus the mortality rate (in units of individuals) is the product of ! that times the ratio of (hypothetical) seed mass to recruit biomass - !START ahb's CHANGES !============================================================================================== do pft = 1,numpft + + ! If the TRS's seedling dynamics is switched off, then we use FATES's default approach + ! to germination if ( regeneration_model == default_regeneration .or. & regeneration_model == TRS_no_seedling_dyn .or. & prt_params%allom_dbh_maxheight(pft) < min_max_dbh_for_trees ) then - !FATES default germination scheme litt%seed_germ_in(pft) = min(litt%seed(pft) * EDPftvarcon_inst%germination_rate(pft), & max_germination)*years_per_day - !end FATES default germination scheme - !------------------------------------------------------------------------------------------- - !The Tree Recruitment Scheme calculates seedling emergence (i.e. germination) as a pft-specific - !function of understory light and soil moisture - + ! If TRS seedling dynamics is switched on we calculate seedling emergence (i.e. germination) + ! as a pft-specific function of understory light and soil moisture. else if ( regeneration_model == TRS .and. & prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees ) then - !Step 1. Calculate how germination rate is modified by understory light. - ! This applies to photoblastic germinators (e.g. many tropical pioneers) + ! Step 1. Calculate how germination rate is modified by understory light + ! This applies to photoblastic germinators (e.g. many tropical pioneers) - !Calculate par at the seedling layer (MJ m-2 day-1) - !The running mean variable is in W m-2 over prior 24 hours. It is converted to MJ m-2 day-1 - !to work with the TRS function. - + ! Calculate mean PAR at the seedling layer (MJ m-2 day-1) over the prior 24 hours seedling_layer_par = currentPatch%seedling_layer_par24%GetMean() * sec_per_day * megajoules_per_joule - !Calculate the photoblastic germination rate modifier (see eqn. 3 of Hanbury-Brown et al., 2022) + ! Calculate the photoblastic germination rate modifier (Eq. 3 Hanbury-Brown et al., 2022) photoblastic_germ_modifier = seedling_layer_par / & (seedling_layer_par + EDPftvarcon_inst%par_crit_germ(pft)) - !Step 2. Calculate the soil matric potential at the seedling rooting depth - - !Define soil layer based on pft-specific rooting depth - !ilayer_seedling_root = minloc(abs(bc_in%z_sisl(:)-EDPftvarcon_inst%seedling_root_depth(pft)),dim=1) + ! Step 2. Calculate how germination rate is modified by soil moisture in the rooting zone of + ! the seedlings. This is a pft-specific running mean based on pft-specific seedling rooting + ! depth. - !Get running mean of soil matric potential (mm of H2O suction) at the seedling rooting depth + ! Get running mean of soil matric potential (mm of H2O suction) at the seedling rooting depth + ! This running mean based on pft-specific seedling rooting depth. seedling_layer_smp = currentPatch%sdlng_emerg_smp(pft)%p%GetMean() - !Calculate a soil wetness index (1 / -soil matric pontential (MPa) ) used by the TRS moisture-based - !seedling mortality function + ! Calculate a soil wetness index (1 / -soil matric pontential (MPa) ) used by the TRS + ! to calculate seedling mortality from moisture stress. wetness_index = 1.0_r8 / (seedling_layer_smp * (-1.0_r8) * mpa_per_mm_suction) - !Step 3. Calculate the seedling emergence rate based on soil moisture and germination - ! rate modifier (i.e. Step 1). See eqn. 4 of Hanbury-Brown et al., 2022 + ! Step 3. Calculate the seedling emergence rate based on soil moisture and germination + ! rate modifier (Step 1). See Eq. 4 of Hanbury-Brown et al., 2022 + ! If SMP is below a pft-specific value, then no germination occurs if ( seedling_layer_smp .GE. EDPftvarcon_inst%seedling_psi_emerg(pft) ) then seedling_emerg_rate = photoblastic_germ_modifier * EDPftvarcon_inst%a_emerg(pft) * & wetness_index**EDPftvarcon_inst%b_emerg(pft) @@ -2136,47 +2112,13 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) seedling_emerg_rate = 0.0_r8 - end if !soil-moisture based seedling emergence rate + end if ! End soil-moisture based seedling emergence rate - !Step 4. Calculate the amount of carbon germinating out of the seed bank + ! Step 4. Calculate the amount of carbon germinating out of the seed bank litt%seed_germ_in(pft) = litt%seed(pft) * seedling_emerg_rate - - ! !ahb diagnostic - ! if (debug_trs) then - ! if (hlm_day_of_year == 40 .OR. hlm_day_of_year == 270) then - ! write(fates_log(),*) 'day_of_year:', hlm_day_of_year - ! write(fates_log(),*) 'patch_age:', currentPatch%age - ! write(fates_log(),*) 'pft', pft - - ! write(fates_log(),*) 'seedling_layer_par (MJ m-2 day-1):', seedling_layer_par - ! write(fates_log(),*) 'seedling_layer_smp (mm h2o suction):', seedling_layer_smp - ! write(fates_log(),*) 'photoblastic_germ_modifier ([0,1]):', photoblastic_germ_modifier - ! write(fates_log(),*) 'seedling_emerg_rate (day-1):', seedling_emerg_rate - ! end if - - ! end if !debug flag - !end ahb diagnostic - - end if !regeneration model switch - !-------------------------------------------------------------------------------------------- - !TEMP - !slsmp_emerg = currentPatch%sdlng_emerg_smp%GetMean() - !slparmort = currentPatch%sdlng_mort_par%GetMean() - !slpartrans = currentPatch%sdlng2sap_par%GetMean() - - ! write(fates_log(),*) 'nrm parprof', currentPatch%nrmlzd_parprof_dir_z(:,:,:) - ! write(fates_log(),*) 'parprof', currentPatch%parprof_dif_z(1,:) - ! write(fates_log(),*) 'number_leaf_layers_in_second_canopy_layer', maxval(currentPatch%ncan(currentPatch%ncl_p,:)) - - ! write(fates_log(),*) 'patchno', currentPatch%patchno - ! write(fates_log(),*) 'seedling_layer_par', seedling_layer_par - ! write(fates_log(),*) 'seedling_emerg_smp', slsmp_emerg - ! write(fates_log(),*) 'seedling_mort_par', slparmort - ! write(fates_log(),*) 'seedling2sap_trans_par', slpartrans - ! write(fates_log(),*) 'tveg_lpa', currentPatch%tveg_lpa%GetMean() - !================================================================================================ - !END ahb changes - + + end if !End use TRS with seedling dynamics + !set the germination only under the growing season...c.xu if ((prt_params%season_decid(pft) == itrue ) .and. & @@ -2277,15 +2219,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) temp_cohort%crowndamage = 1 ! new recruits are undamaged call h2d_allom(temp_cohort%hite,ft,temp_cohort%dbh) - - !ahb diagnostic - if (debug_trs) then - if (hlm_day_of_year == 40 .OR. hlm_day_of_year == 270) then - write(fates_log(),*) 'min_dbh:', temp_cohort%dbh - end if !day condition - end if !debug condition - !end ahb diagnostic - + ! Initialize live pools call bleaf(temp_cohort%dbh,ft,temp_cohort%crowndamage,& temp_cohort%canopy_trim,c_leaf) @@ -2347,12 +2281,6 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) mass_demand = c_struct+c_leaf+c_fnrt+c_sapw+c_store - !ahb diagnostic - if (hlm_day_of_year == 40) then - write(fates_log(),*) 'mass demand:', mass_demand - end if - !end ahb diagnostic - case(nitrogen_element) mass_demand = & @@ -2384,14 +2312,16 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) call endrun(msg=errMsg(sourcefile, __LINE__)) end select - !START ahb's changes - !================================================================================= + ! If TRS seedling dynamics is switched off then the available mass to make new recruits + ! is everything in the seed_germ pool. if ( regeneration_model == default_regeneration .or. & regeneration_model == TRS_no_seedling_dyn .or. & prt_params%allom_dbh_maxheight(ft) < min_max_dbh_for_trees ) then mass_avail = currentPatch%area * currentPatch%litter(el)%seed_germ(ft) - + + ! If TRS seedling dynamics is on then calculate the available mass to make new recruits + ! as a pft-specific function of light and soil moisture in the seedling layer. else if ( regeneration_model == TRS .and. & prt_params%allom_dbh_maxheight(ft) > min_max_dbh_for_trees ) then @@ -2401,24 +2331,9 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) EDPftvarcon_inst%seedling_light_rec_a(ft) * & sdlng2sap_par**EDPftvarcon_inst%seedling_light_rec_b(ft) - - !ahb diagnostic - if (debug_trs) then - if (hlm_day_of_year == 40 .OR. hlm_day_of_year == 270) then - write(fates_log(),*) 'day_of_year:', hlm_day_of_year - write(fates_log(),*) 'patch_age:', currentPatch%age - write(fates_log(),*) 'pft', ft - write(fates_log(),*) 'sdlng2sap_par (MJ m-2 day-1):', sdlng2sap_par - write(fates_log(),*) 'seedling_2_sapling_transition_rate (day -1):', & - EDPftvarcon_inst%seedling_light_rec_a(ft) * & - sdlng2sap_par**EDPftvarcon_inst%seedling_light_rec_b(ft) - end if - end if !debug flag - !end ahb diagnostic - - - - !If soil moisture is below the moisture stress threshold recruitment does not occur + + ! If soil moisture is below pft-specific seedling moisture stress threshold the + ! recruitment does not occur. ilayer_seedling_root = minloc(abs(bc_in%z_sisl(:)-EDPftvarcon_inst%seedling_root_depth(ft)),dim=1) seedling_layer_smp = bc_in%smp_sl(ilayer_seedling_root) @@ -2427,12 +2342,10 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) mass_avail = 0.0_r8 - end if !check on soil moisture + end if ! End check if soil moisture is sufficient for recruitment + + end if ! End use TRS with seedling dynamics - end if !regeneration model - - !================================================================================== - !END ahb's changes ! ------------------------------------------------------------------------ ! Update number density if this is the limiting mass ! ------------------------------------------------------------------------ diff --git a/biogeochem/EDPhysiologyMod.F90.save b/biogeochem/EDPhysiologyMod.F90.save deleted file mode 100644 index 9a068eb85c..0000000000 --- a/biogeochem/EDPhysiologyMod.F90.save +++ /dev/null @@ -1,2396 +0,0 @@ -module EDPhysiologyMod - -#include "shr_assert.h" - - ! ============================================================================ - ! Miscellaneous physiology routines from ED. - ! ============================================================================ - - use FatesGlobals, only : fates_log - use FatesInterfaceTypesMod, only : hlm_days_per_year - use FatesInterfaceTypesMod, only : hlm_model_day - use FatesInterfaceTypesMod, only : hlm_freq_day - use FatesInterfaceTypesMod, only : hlm_day_of_year - use FatesInterfaceTypesMod, only : numpft - use FatesInterfaceTypesMod, only : nleafage - use FatesInterfaceTypesMod, only : hlm_use_planthydro - use FatesInterfaceTypesMod, only : hlm_parteh_mode - use FatesInterfaceTypesMod, only : hlm_nitrogen_spec - use FatesInterfaceTypesMod, only : hlm_phosphorus_spec - use FatesConstantsMod, only : r8 => fates_r8 - use FatesConstantsMod, only : nearzero - use EDPftvarcon , only : EDPftvarcon_inst - use PRTParametersMod , only : prt_params - use EDPftvarcon , only : GetDecompyFrac - use FatesInterfaceTypesMod, only : bc_in_type - use FatesInterfaceTypesMod, only : bc_out_type - use EDCohortDynamicsMod , only : zero_cohort - use EDCohortDynamicsMod , only : create_cohort, sort_cohorts - use EDCohortDynamicsMod , only : InitPRTObject - use FatesAllometryMod , only : tree_lai - use FatesAllometryMod , only : tree_sai - use FatesAllometryMod , only : decay_coeff_kn - use FatesLitterMod , only : litter_type - use EDTypesMod , only : site_massbal_type - use EDTypesMod , only : numlevsoil_max - use EDTypesMod , only : numWaterMem - use EDTypesMod , only : dl_sf, dinc_ed, area_inv - use FatesLitterMod , only : ncwd - use FatesLitterMod , only : ndcmpy - use FatesLitterMod , only : ilabile - use FatesLitterMod , only : ilignin - use FatesLitterMod , only : icellulose - use EDTypesMod , only : AREA,AREA_INV - use EDTypesMod , only : nlevleaf - use EDTypesMod , only : num_vegtemp_mem - use EDTypesMod , only : maxpft - use EDTypesMod , only : ed_site_type, ed_patch_type, ed_cohort_type - use EDTypesMod , only : leaves_on - use EDTypesMod , only : leaves_off - use EDTypesMod , only : min_n_safemath - use PRTGenericMod , only : num_elements - use PRTGenericMod , only : element_list - use PRTGenericMod , only : element_pos - use EDTypesMod , only : site_fluxdiags_type - use EDTypesMod , only : phen_cstat_nevercold - use EDTypesMod , only : phen_cstat_iscold - use EDTypesMod , only : phen_cstat_notcold - use EDTypesMod , only : phen_dstat_timeoff - use EDTypesMod , only : phen_dstat_moistoff - use EDTypesMod , only : phen_dstat_moiston - use EDTypesMod , only : phen_dstat_timeon - use EDTypesMod , only : init_recruit_trim - use shr_log_mod , only : errMsg => shr_log_errMsg - use FatesGlobals , only : fates_log - use FatesGlobals , only : endrun => fates_endrun - use EDParamsMod , only : fates_mortality_disturbance_fraction - use EDParamsMod , only : q10_mr - use EDParamsMod , only : q10_froz - use EDParamsMod , only : logging_export_frac - use FatesPlantHydraulicsMod , only : AccumulateMortalityWaterStorage - use FatesConstantsMod , only : itrue,ifalse - use FatesConstantsMod , only : calloc_abs_error - use FatesConstantsMod , only : years_per_day - use FatesAllometryMod , only : h_allom - use FatesAllometryMod , only : h2d_allom - use FatesAllometryMod , only : bagw_allom - use FatesAllometryMod , only : bsap_allom - use FatesAllometryMod , only : bleaf - use FatesAllometryMod , only : bfineroot - use FatesAllometryMod , only : bdead_allom - use FatesAllometryMod , only : bstore_allom - use FatesAllometryMod , only : bbgw_allom - use FatesAllometryMod , only : carea_allom - use FatesAllometryMod , only : CheckIntegratedAllometries - use FatesAllometryMod, only : set_root_fraction - use PRTGenericMod, only : prt_carbon_allom_hyp - use PRTGenericMod, only : prt_cnp_flex_allom_hyp - use PRTGenericMod, only : prt_vartypes - use PRTGenericMod, only : leaf_organ - use PRTGenericMod, only : sapw_organ, struct_organ - use PRTGenericMod, only : all_carbon_elements - use PRTGenericMod, only : carbon12_element - use PRTGenericMod, only : nitrogen_element - use PRTGenericMod, only : phosphorus_element - use PRTGenericMod, only : leaf_organ - use PRTGenericMod, only : fnrt_organ - use PRTGenericMod, only : sapw_organ - use PRTGenericMod, only : store_organ - use PRTGenericMod, only : repro_organ - use PRTGenericMod, only : struct_organ - use PRTGenericMod, only : SetState - use PRTLossFluxesMod, only : PRTPhenologyFlush - use PRTLossFluxesMod, only : PRTDeciduousTurnover - use PRTLossFluxesMod, only : PRTReproRelease - use PRTGenericMod, only : StorageNutrientTarget - - implicit none - private - - public :: trim_canopy - public :: phenology - public :: recruitment - public :: ZeroLitterFluxes - - public :: ZeroAllocationRates - public :: PreDisturbanceLitterFluxes - public :: PreDisturbanceIntegrateLitter - public :: SeedIn - - logical, parameter :: debug = .false. ! local debug flag - character(len=*), parameter, private :: sourcefile = & - __FILE__ - - integer, parameter :: dleafon_drycheck = 100 ! Drought deciduous leaves max days on check parameter - - - ! ============================================================================ - -contains - - subroutine ZeroLitterFluxes( currentSite ) - - ! This routine loops through all patches in a site - ! and zero's the flux terms for the litter pools. - ! This is typically called at the beginning of the dynamics - ! call sequence. - - - ! !ARGUMENTS - type(ed_site_type), intent(inout), target :: currentSite - type(ed_patch_type), pointer :: currentPatch - - integer :: el - - currentPatch => currentSite%youngest_patch - do while(associated(currentPatch)) - do el=1,num_elements - call currentPatch%litter(el)%ZeroFlux() - end do - currentPatch => currentPatch%older - end do - - - return - end subroutine ZeroLitterFluxes - - ! ===================================================================================== - - subroutine ZeroAllocationRates( currentSite ) - - ! !ARGUMENTS - type(ed_site_type), intent(inout), target :: currentSite - type(ed_patch_type), pointer :: currentPatch - type(ed_cohort_type), pointer :: currentCohort - - currentPatch => currentSite%youngest_patch - do while(associated(currentPatch)) - - currentCohort => currentPatch%tallest - do while (associated(currentCohort)) - - ! This sets turnover and growth rates to zero - call currentCohort%prt%ZeroRates() - - currentCohort => currentCohort%shorter - enddo - currentPatch => currentPatch%older - end do - - return - end subroutine ZeroAllocationRates - - - ! ============================================================================ - - subroutine PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in ) - - ! ----------------------------------------------------------------------------------- - ! - ! This subroutine calculates all of the different litter input and output fluxes - ! associated with seed turnover, seed influx, litterfall from live and - ! dead plants, germination, and fragmentation. - ! - ! At this time we do not have explicit herbivory, and burning losses to litter - ! are handled elsewhere. - ! - ! Note: The processes conducted here DO NOT handle litter fluxes associated - ! with disturbance. Those fluxes are handled elsewhere (EDPatchDynamcisMod) - ! because the fluxes are potentially cross patch, and also dealing - ! patch areas that are changing. - ! - ! ----------------------------------------------------------------------------------- - - - ! !ARGUMENTS - type(ed_site_type), intent(inout) :: currentSite - type(ed_patch_type), intent(inout) :: currentPatch - type(bc_in_type), intent(in) :: bc_in - - ! - ! !LOCAL VARIABLES: - type(site_massbal_type), pointer :: site_mass - type(litter_type), pointer :: litt ! Points to the litter object for - ! the different element types - integer :: el ! Litter element loop index - integer :: nlev_eff_decomp ! Number of active layers over which - ! fragmentation fluxes are transfered - !------------------------------------------------------------------------------------ - - ! Calculate the fragmentation rates - call fragmentation_scaler(currentPatch, bc_in) - - - do el = 1, num_elements - - litt => currentPatch%litter(el) - - ! Calculate loss rate of viable seeds to litter - call SeedDecay(litt) - - ! Calculate seed germination rate, the status flags prevent - ! germination from occuring when the site is in a drought - ! (for drought deciduous) or too cold (for cold deciduous) - call SeedGermination(litt, currentSite%cstatus, currentSite%dstatus) - - ! Send fluxes from newly created litter into the litter pools - ! This litter flux is from non-disturbance inducing mortality, as well - ! as litter fluxes from live trees - call CWDInput(currentSite, currentPatch, litt,bc_in) - - - ! Only calculate fragmentation flux over layers that are active - ! (RGK-Mar2019) SHOULD WE MAX THIS AT 1? DONT HAVE TO - - nlev_eff_decomp = max(bc_in%max_rooting_depth_index_col, 1) - call CWDOut(litt,currentPatch%fragmentation_scaler,nlev_eff_decomp) - - - site_mass => currentSite%mass_balance(el) - - ! Fragmentation flux to soil decomposition model [kg/site/day] - site_mass%frag_out = site_mass%frag_out + currentPatch%area * & - ( sum(litt%ag_cwd_frag) + sum(litt%bg_cwd_frag) + & - sum(litt%leaf_fines_frag) + sum(litt%root_fines_frag) + & - !sum(litt%non_seed_repro_mass_decay) + & !ahb added this line on 7/8/2021 - sum(litt%seed_decay) + sum(litt%seed_germ_decay)) - - end do - - - return - end subroutine PreDisturbanceLitterFluxes - - ! ===================================================================================== - - subroutine PreDisturbanceIntegrateLitter(currentPatch) - - ! ----------------------------------------------------------------------------------- - ! - ! This step applies the litter fluxes to the prognostic state variables. - ! This procedure is called in response to fluxes generated from: - ! 1) seed rain, - ! 2) non-disturbance generating turnover - ! 3) litter fall from living plants - ! 4) fragmentation - ! - ! This routine does NOT accomodate the litter fluxes associated with - ! disturbance generation. That will happen after this call. - ! Fluxes associated with FIRE also happen after this step. - ! - ! All states are in units kg/m2 - ! All fluxes are in units kg/m2/day - ! The integration step is 1 day, thus time is implied - ! - ! ----------------------------------------------------------------------------------- - - ! Arguments - type(ed_patch_type),intent(inout),target :: currentPatch - - - ! Locals - type(litter_type), pointer :: litt - integer :: el ! Loop counter for litter element type - integer :: pft ! pft loop counter - integer :: c ! CWD loop counter - integer :: nlevsoil ! number of soil layers - integer :: ilyr ! soil layer loop counter - integer :: dcmpy ! decomposability index - - do el = 1, num_elements - - litt => currentPatch%litter(el) - - ! Update the bank of viable seeds - ! ----------------------------------------------------------------------------------- - - do pft = 1,numpft - litt%seed(pft) = litt%seed(pft) + & - litt%seed_in_local(pft) + & - litt%seed_in_extern(pft) - & - litt%seed_decay(pft) - & - litt%seed_germ_in(pft) - - ! Note that the recruitment scheme will use seed_germ - ! for its construction costs. - litt%seed_germ(pft) = litt%seed_germ(pft) + & - litt%seed_germ_in(pft) - & - litt%seed_germ_decay(pft) - - - enddo - - ! Update the Coarse Woody Debris pools (above and below) - ! ----------------------------------------------------------------------------------- - nlevsoil = size(litt%bg_cwd,dim=2) - do c = 1,ncwd - litt%ag_cwd(c) = litt%ag_cwd(c) + litt%ag_cwd_in(c) - litt%ag_cwd_frag(c) - do ilyr=1,nlevsoil - litt%bg_cwd(c,ilyr) = litt%bg_cwd(c,ilyr) & - + litt%bg_cwd_in(c,ilyr) & - - litt%bg_cwd_frag(c,ilyr) - enddo - end do - - ! Update the fine litter pools from leaves and fine-roots - ! ----------------------------------------------------------------------------------- - - do dcmpy = 1,ndcmpy - - litt%leaf_fines(dcmpy) = litt%leaf_fines(dcmpy) & - + litt%leaf_fines_in(dcmpy) & - - litt%leaf_fines_frag(dcmpy) - do ilyr=1,nlevsoil - litt%root_fines(dcmpy,ilyr) = litt%root_fines(dcmpy,ilyr) & - + litt%root_fines_in(dcmpy,ilyr) & - - litt%root_fines_frag(dcmpy,ilyr) - enddo - - end do - - end do ! litter element loop - - return - end subroutine PreDisturbanceIntegrateLitter - - - - ! ============================================================================ - - subroutine trim_canopy( currentSite ) - ! - ! !DESCRIPTION: - ! Canopy trimming / leaf optimisation. Removes leaves in negative annual carbon balance. - ! - ! !USES: - - ! !ARGUMENTS - type (ed_site_type),intent(inout), target :: currentSite - ! - ! !LOCAL VARIABLES: - type (ed_cohort_type) , pointer :: currentCohort - type (ed_patch_type) , pointer :: currentPatch - - integer :: z ! leaf layer - integer :: ipft ! pft index - logical :: trimmed ! was this layer trimmed in this year? If not expand the canopy. - real(r8) :: tar_bl ! target leaf biomass (leaves flushed, trimmed) - real(r8) :: tar_bfr ! target fine-root biomass (leaves flushed, trimmed) - real(r8) :: bfr_per_bleaf ! ratio of fine root per leaf biomass - real(r8) :: sla_levleaf ! sla at leaf level z - real(r8) :: nscaler_levleaf ! nscaler value at leaf level z - integer :: cl ! canopy layer index - real(r8) :: kn ! nitrogen decay coefficient - real(r8) :: sla_max ! Observational constraint on how large sla (m2/gC) can become - real(r8) :: leaf_c ! leaf carbon [kg] - real(r8) :: sapw_c ! sapwood carbon [kg] - real(r8) :: store_c ! storage carbon [kg] - real(r8) :: struct_c ! structure carbon [kg] - real(r8) :: leaf_inc ! LAI-only portion of the vegetation increment of dinc_ed - real(r8) :: lai_canopy_above ! the LAI in the canopy layers above the layer of interest - real(r8) :: lai_layers_above ! the LAI in the leaf layers, within the current canopy, - ! above the leaf layer of interest - real(r8) :: lai_current ! the LAI in the current leaf layer - real(r8) :: cumulative_lai ! whole canopy cumulative LAI, top down, to the leaf layer of interest - real(r8) :: cumulative_lai_cohort ! cumulative LAI within the current cohort only - - ! Temporary diagnostic ouptut - integer :: ipatch - integer :: icohort - - ! LAPACK linear least squares fit variables - ! The standard equation for a linear fit, y = mx + b, is converted to a linear system, AX=B and has - ! the form: [n sum(x); sum(x) sum(x^2)] * [b; m] = [sum(y); sum(x*y)] where - ! n is the number of leaf layers - ! x is yearly_net_uptake minus the leaf cost aka the net-net uptake - ! y is the cumulative lai for the current cohort - ! b is the y-intercept i.e. the cumulative lai that has zero net-net uptake - ! m is the slope of the linear fit - integer :: nll = 3 ! Number of leaf layers to fit a regression to for calculating the optimum lai - character(1) :: trans = 'N' ! Input matrix is not transposed - - integer, parameter :: m = 2, n = 2 ! Number of rows and columns, respectively, in matrix A - integer, parameter :: nrhs = 1 ! Number of columns in matrix B and X - integer, parameter :: workmax = 100 ! Maximum iterations to minimize work - - integer :: lda = m, ldb = n ! Leading dimension of A and B, respectively - integer :: lwork ! Dimension of work array - integer :: info ! Procedure diagnostic ouput - - real(r8) :: nnu_clai_a(m,n) ! LHS of linear least squares fit, A matrix - real(r8) :: nnu_clai_b(m,nrhs) ! RHS of linear least squares fit, B matrix - real(r8) :: work(workmax) ! work array - - real(r8) :: initial_trim ! Initial trim - real(r8) :: optimum_trim ! Optimum trim value - real(r8) :: initial_laimem ! Initial laimemory - real(r8) :: optimum_laimem ! Optimum laimemory - - !---------------------------------------------------------------------- - - ipatch = 1 ! Start counting patches - - currentPatch => currentSite%youngest_patch - do while(associated(currentPatch)) - - ! Add debug diagnstic output to determine which patch - if (debug) then - write(fates_log(),*) 'Current patch:', ipatch - write(fates_log(),*) 'Current patch cohorts:', currentPatch%countcohorts - endif - - icohort = 1 - - currentCohort => currentPatch%tallest - do while (associated(currentCohort)) - - ! Save off the incoming trim and laimemory - initial_trim = currentCohort%canopy_trim - initial_laimem = currentCohort%laimemory - - ! Add debug diagnstic output to determine which cohort - if (debug) then - write(fates_log(),*) 'Current cohort:', icohort - write(fates_log(),*) 'Starting canopy trim:', initial_trim - write(fates_log(),*) 'Starting laimemory:', currentCohort%laimemory - endif - - trimmed = .false. - ipft = currentCohort%pft - call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread,currentCohort%pft,currentCohort%c_area) - - leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) - - currentCohort%treelai = tree_lai(leaf_c, currentCohort%pft, currentCohort%c_area, & - currentCohort%n, currentCohort%canopy_layer, & - currentPatch%canopy_layer_tlai,currentCohort%vcmax25top ) - - currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_trim, & - currentCohort%c_area, currentCohort%n, currentCohort%canopy_layer, & - currentPatch%canopy_layer_tlai, currentCohort%treelai, & - currentCohort%vcmax25top,0 ) - - currentCohort%nv = ceiling((currentCohort%treelai+currentCohort%treesai)/dinc_ed) - - if (currentCohort%nv > nlevleaf)then - write(fates_log(),*) 'nv > nlevleaf',currentCohort%nv, & - currentCohort%treelai,currentCohort%treesai, & - currentCohort%c_area,currentCohort%n,leaf_c - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - - call bleaf(currentcohort%dbh,ipft,currentcohort%canopy_trim,tar_bl) - - if ( int(prt_params%allom_fmode(ipft)) .eq. 1 ) then - ! only query fine root biomass if using a fine root allometric model that takes leaf trim into account - call bfineroot(currentcohort%dbh,ipft,currentcohort%canopy_trim,tar_bfr) - bfr_per_bleaf = tar_bfr/tar_bl - endif - - ! Identify current canopy layer (cl) - cl = currentCohort%canopy_layer - - ! PFT-level maximum SLA value, even if under a thick canopy (same units as slatop) - sla_max = prt_params%slamax(ipft) - - ! Initialize nnu_clai_a - nnu_clai_a(:,:) = 0._r8 - nnu_clai_b(:,:) = 0._r8 - - !Leaf cost vs netuptake for each leaf layer. - do z = 1, currentCohort%nv - - ! Calculate the cumulative total vegetation area index (no snow occlusion, stems and leaves) - - leaf_inc = dinc_ed * & - currentCohort%treelai/(currentCohort%treelai+currentCohort%treesai) - - ! Now calculate the cumulative top-down lai of the current layer's midpoint within the current cohort - lai_layers_above = leaf_inc * (z-1) - lai_current = min(leaf_inc, currentCohort%treelai - lai_layers_above) - cumulative_lai_cohort = lai_layers_above + 0.5*lai_current - - ! Now add in the lai above the current cohort for calculating the sla leaf level - lai_canopy_above = sum(currentPatch%canopy_layer_tlai(1:cl-1)) - cumulative_lai = lai_canopy_above + cumulative_lai_cohort - - ! There was activity this year in this leaf layer. This should only occur for bottom most leaf layer - if (currentCohort%year_net_uptake(z) /= 999._r8)then - - ! Calculate sla_levleaf following the sla profile with overlying leaf area - ! Scale for leaf nitrogen profile - kn = decay_coeff_kn(ipft,currentCohort%vcmax25top) - ! Nscaler value at leaf level z - nscaler_levleaf = exp(-kn * cumulative_lai) - ! Sla value at leaf level z after nitrogen profile scaling (m2/gC) - sla_levleaf = prt_params%slatop(ipft)/nscaler_levleaf - - if(sla_levleaf > sla_max)then - sla_levleaf = sla_max - end if - - !Leaf Cost kgC/m2/year-1 - !decidous costs. - if (prt_params%season_decid(ipft) == itrue .or. & - prt_params%stress_decid(ipft) == itrue )then - - ! Leaf cost at leaf level z accounting for sla profile (kgC/m2) - currentCohort%leaf_cost = 1._r8/(sla_levleaf*1000.0_r8) - - if ( int(prt_params%allom_fmode(ipft)) .eq. 1 ) then - ! if using trimmed leaf for fine root biomass allometry, add the cost of the root increment - ! to the leaf increment; otherwise do not. - currentCohort%leaf_cost = currentCohort%leaf_cost + & - 1.0_r8/(sla_levleaf*1000.0_r8) * & - bfr_per_bleaf / prt_params%root_long(ipft) - endif - - currentCohort%leaf_cost = currentCohort%leaf_cost * & - (prt_params%grperc(ipft) + 1._r8) - else !evergreen costs - - ! Leaf cost at leaf level z accounting for sla profile - currentCohort%leaf_cost = 1.0_r8/(sla_levleaf* & - sum(prt_params%leaf_long(ipft,:))*1000.0_r8) !convert from sla in m2g-1 to m2kg-1 - - - if ( int(prt_params%allom_fmode(ipft)) .eq. 1 ) then - ! if using trimmed leaf for fine root biomass allometry, add the cost of the root increment - ! to the leaf increment; otherwise do not. - currentCohort%leaf_cost = currentCohort%leaf_cost + & - 1.0_r8/(sla_levleaf*1000.0_r8) * & - bfr_per_bleaf / prt_params%root_long(ipft) - endif - currentCohort%leaf_cost = currentCohort%leaf_cost * & - (prt_params%grperc(ipft) + 1._r8) - endif - - ! Construct the arrays for a least square fit of the net_net_uptake versus the cumulative lai - ! if at least nll leaf layers are present in the current cohort and only for the bottom nll - ! leaf layers. - if (currentCohort%nv > nll .and. currentCohort%nv - z < nll) then - - ! Build the A matrix for the LHS of the linear system. A = [n sum(x); sum(x) sum(x^2)] - ! where n = nll and x = yearly_net_uptake-leafcost - nnu_clai_a(1,1) = nnu_clai_a(1,1) + 1 ! Increment for each layer used - nnu_clai_a(1,2) = nnu_clai_a(1,2) + currentCohort%year_net_uptake(z) - currentCohort%leaf_cost - nnu_clai_a(2,1) = nnu_clai_a(1,2) - nnu_clai_a(2,2) = nnu_clai_a(2,2) + (currentCohort%year_net_uptake(z) - currentCohort%leaf_cost)**2 - - ! Build the B matrix for the RHS of the linear system. B = [sum(y); sum(x*y)] - ! where x = yearly_net_uptake-leafcost and y = cumulative_lai_cohort - nnu_clai_b(1,1) = nnu_clai_b(1,1) + cumulative_lai_cohort - nnu_clai_b(2,1) = nnu_clai_b(2,1) + (cumulative_lai_cohort * & - (currentCohort%year_net_uptake(z) - currentCohort%leaf_cost)) - end if - - ! Check leaf cost against the yearly net uptake for that cohort leaf layer - if (currentCohort%year_net_uptake(z) < currentCohort%leaf_cost) then - ! Make sure the cohort trim fraction is great than the pft trim limit - if (currentCohort%canopy_trim > EDPftvarcon_inst%trim_limit(ipft)) then - - ! if ( debug ) then - ! write(fates_log(),*) 'trimming leaves', & - ! currentCohort%canopy_trim,currentCohort%leaf_cost - ! endif - - ! keep trimming until none of the canopy is in negative carbon balance. - if (currentCohort%hite > EDPftvarcon_inst%hgt_min(ipft)) then - currentCohort%canopy_trim = currentCohort%canopy_trim - & - EDPftvarcon_inst%trim_inc(ipft) - if (prt_params%evergreen(ipft) /= 1)then - currentCohort%laimemory = currentCohort%laimemory * & - (1.0_r8 - EDPftvarcon_inst%trim_inc(ipft)) - endif - - trimmed = .true. - - endif ! hite check - endif ! trim limit check - endif ! net uptake check - endif ! leaf activity check - enddo ! z, leaf layer loop - - ! Compute the optimal cumulative lai based on the cohort net-net uptake profile if at least 2 leaf layers - if (nnu_clai_a(1,1) > 1) then - - ! Compute the optimum size of the work array - lwork = -1 ! Ask sgels to compute optimal number of entries for work - call dgels(trans, m, n, nrhs, nnu_clai_a, lda, nnu_clai_b, ldb, work, lwork, info) - lwork = int(work(1)) ! Pick the optimum. TBD, can work(1) come back with greater than work size? - - ! if (debug) then - ! write(fates_log(),*) 'LLSF lwork output (info, lwork):', info, lwork - ! endif - - ! Compute the minimum of 2-norm of of the least squares fit to solve for X - ! Note that dgels returns the solution by overwriting the nnu_clai_b array. - ! The result has the form: X = [b; m] - ! where b = y-intercept (i.e. the cohort lai that has zero yearly net-net uptake) - ! and m is the slope of the linear fit - call dgels(trans, m, n, nrhs, nnu_clai_a, lda, nnu_clai_b, ldb, work, lwork, info) - - if (info < 0) then - write(fates_log(),*) 'LLSF optimium LAI calculation returned illegal value' - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - - if (debug) then - write(fates_log(),*) 'LLSF optimium LAI (intercept,slope):', nnu_clai_b - write(fates_log(),*) 'LLSF optimium LAI:', nnu_clai_b(1,1) - write(fates_log(),*) 'LLSF optimium LAI info:', info - write(fates_log(),*) 'LAI fraction (optimum_lai/cumulative_lai):', nnu_clai_b(1,1) / cumulative_lai_cohort - endif - - ! Calculate the optimum trim based on the initial canopy trim value - if (cumulative_lai_cohort > 0._r8) then ! Sometime cumulative_lai comes in at 0.0? - - ! - optimum_trim = (nnu_clai_b(1,1) / cumulative_lai_cohort) * initial_trim - optimum_laimem = (nnu_clai_b(1,1) / cumulative_lai_cohort) * initial_laimem - - ! Determine if the optimum trim value makes sense. The smallest cohorts tend to have unrealistic fits. - if (optimum_trim > 0. .and. optimum_trim < 1.) then - currentCohort%canopy_trim = optimum_trim - - ! If the cohort pft is not evergreen we reduce the laimemory as well - if (prt_params%evergreen(ipft) /= 1) then - currentCohort%laimemory = optimum_laimem - endif - - trimmed = .true. - - endif - endif - endif - - ! Reset activity for the cohort for the start of the next year - currentCohort%year_net_uptake(:) = 999.0_r8 - - ! Add to trim fraction if cohort not trimmed at all - if ( (.not.trimmed) .and.currentCohort%canopy_trim < 1.0_r8)then - currentCohort%canopy_trim = currentCohort%canopy_trim + EDPftvarcon_inst%trim_inc(ipft) - endif - - if ( debug ) then - write(fates_log(),*) 'trimming:',currentCohort%canopy_trim - endif - - ! currentCohort%canopy_trim = 1.0_r8 !FIX(RF,032414) this turns off ctrim for now. - currentCohort => currentCohort%shorter - icohort = icohort + 1 - enddo - currentPatch => currentPatch%older - ipatch = ipatch + 1 - enddo - - end subroutine trim_canopy - - ! ============================================================================ - subroutine phenology( currentSite, bc_in ) - ! - ! !DESCRIPTION: - ! Phenology. - ! - ! !USES: - use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm - use EDParamsMod, only : ED_val_phen_drought_threshold, ED_val_phen_doff_time - use EDParamsMod, only : ED_val_phen_a, ED_val_phen_b, ED_val_phen_c, ED_val_phen_chiltemp - use EDParamsMod, only : ED_val_phen_mindayson, ED_val_phen_ncolddayslim, ED_val_phen_coldtemp - - - ! - ! !ARGUMENTS: - type(ed_site_type), intent(inout), target :: currentSite - type(bc_in_type), intent(in) :: bc_in - - ! - ! !LOCAL VARIABLES: - - type(ed_patch_type),pointer :: cpatch - integer :: model_day_int ! integer model day 1 - inf - integer :: ncolddays ! no days underneath the threshold for leaf drop - integer :: i_wmem ! Loop counter for water mem days - integer :: i_tmem ! Loop counter for veg temp mem days - integer :: dayssincedleafon ! Days since drought-decid leaf-on started - integer :: dayssincedleafoff ! Days since drought-decid leaf-off started - integer :: dayssincecleafon ! Days since cold-decid leaf-on started - integer :: dayssincecleafoff ! Days since cold-decid leaf-off started - real(r8) :: mean_10day_liqvol ! mean liquid volume (m3/m3) over last 10 days - real(r8) :: leaf_c ! leaf carbon [kg] - real(r8) :: fnrt_c ! fineroot carbon [kg] - real(r8) :: sapw_c ! sapwood carbon [kg] - real(r8) :: store_c ! storage carbon [kg] - real(r8) :: struct_c ! structure carbon [kg] - real(r8) :: gdd_threshold ! GDD accumulation function, - integer :: ilayer_swater ! Layer index for soil water - ! which also depends on chilling days. - integer :: ncdstart ! beginning of counting period for chilling degree days. - integer :: gddstart ! beginning of counting period for growing degree days. - real(r8) :: temp_in_C ! daily averaged temperature in celcius - - integer, parameter :: canopy_leaf_lifespan = 365 ! Maximum lifespan of drought decid leaves - - integer, parameter :: min_daysoff_dforcedflush = 30 ! THis is the number of days that must had elapsed - ! since leaves had dropped, in order to forcably - ! flush leaves again. This does not impact flushing - ! due to real moisture constraints, and will prevent - ! drought deciduous in perennially wet environments - ! that have been forced to drop their leaves, from - ! flushing them back immediately. - - real(r8),parameter :: dphen_soil_depth = 0.1 ! Use liquid soil water that is - ! closest to this depth [m] - - ! This is the integer model day. The first day of the simulation is 1, and it - ! continues monotonically, indefinitely - model_day_int = nint(hlm_model_day) - - - ! Use the following layer index to calculate drought conditions - ilayer_swater = minloc(abs(bc_in%z_sisl(:)-dphen_soil_depth),dim=1) - - - ! Parameter of drought decid leaf loss in mm in top layer...FIX(RF,032414) - ! - this is arbitrary and poorly understood. Needs work. ED_ - !Parameters: defaults from Botta et al. 2000 GCB,6 709-725 - !Parameters, default from from SDGVM model of senesence - - temp_in_C = 0._r8 - cpatch => CurrentSite%oldest_patch - do while(associated(cpatch)) - temp_in_C = temp_in_C + bc_in%t_veg24_pa(cpatch%patchno)*cpatch%area - cpatch => cpatch%younger - end do - temp_in_C = temp_in_C * area_inv - tfrz - - - !-----------------Cold Phenology--------------------! - - !Zero growing degree and chilling day counters - if (currentSite%lat > 0)then - ncdstart = 270 !Northern Hemisphere begining November - gddstart = 1 !Northern Hemisphere begining January - else - ncdstart = 120 !Southern Hemisphere beginning May - gddstart = 181 !Northern Hemisphere begining July - endif - - ! Count the number of chilling days over a seasonal window. - ! For comparing against GDD, we start calculating chilling - ! in the late autumn. - ! This value is used to determine the GDD exceedance threshold - if (hlm_day_of_year == ncdstart)then - currentSite%nchilldays = 0 - endif - - !Accumulate growing/chilling days after start of counting period - if (temp_in_C < ED_val_phen_chiltemp)then - currentSite%nchilldays = currentSite%nchilldays + 1 - endif - - !GDD accumulation function, which also depends on chilling days. - ! -68 + 638 * (-0.001 * ncd) - gdd_threshold = ED_val_phen_a + ED_val_phen_b*exp(ED_val_phen_c*real(currentSite%nchilldays,r8)) - - !Accumulate temperature of last 10 days. - currentSite%vegtemp_memory(2:num_vegtemp_mem) = currentSite%vegtemp_memory(1:num_vegtemp_mem-1) - currentSite%vegtemp_memory(1) = temp_in_C - - !count number of days for leaves off - ncolddays = 0 - do i_tmem = 1,num_vegtemp_mem - if (currentSite%vegtemp_memory(i_tmem) < ED_val_phen_coldtemp)then - ncolddays = ncolddays + 1 - endif - enddo - - ! Here is where we do the GDD accumulation calculation - ! - ! reset GDD on set dates - if (hlm_day_of_year == gddstart)then - currentSite%grow_deg_days = 0._r8 - endif - ! - ! accumulate the GDD using daily mean temperatures - ! Don't accumulate GDD during the growing season (that wouldn't make sense) - if (temp_in_C .gt. 0._r8 .and. currentSite%cstatus == phen_cstat_iscold) then - currentSite%grow_deg_days = currentSite%grow_deg_days + temp_in_C - endif - - !this logic is to prevent GDD accumulating after the leaves have fallen and before the - ! beginnning of the accumulation period, to prevend erroneous autumn leaf flushing. - if(model_day_int>365)then !only do this after the first year to prevent odd behaviour - - if(currentSite%lat .gt. 0.0_r8)then !Northern Hemisphere - ! In the north, don't accumulate when we are past the leaf fall date. - ! Accumulation starts on day 1 of year in NH. - ! The 180 is to prevent going into an 'always off' state after initialization - if( model_day_int .gt. currentSite%cleafoffdate.and.hlm_day_of_year.gt.180)then ! - currentSite%grow_deg_days = 0._r8 - endif - else !Southern Hemisphere - ! In the South, don't accumulate after the leaf off date, and before the start of - ! the accumulation phase (day 181). - if(model_day_int .gt. currentSite%cleafoffdate.and.hlm_day_of_year.lt.gddstart) then! - currentSite%grow_deg_days = 0._r8 - endif - endif - endif !year1 - - ! Calculate the number of days since the leaves last came on - ! and off. If this is the beginning of the simulation, that day might - ! not had occured yet, so set it to last year to get things rolling - - if (model_day_int < currentSite%cleafoffdate) then - dayssincecleafoff = model_day_int - (currentSite%cleafoffdate - 365) - else - dayssincecleafoff = model_day_int - currentSite%cleafoffdate - end if - - if (model_day_int < currentSite%cleafondate) then - dayssincecleafon = model_day_int - (currentSite%cleafondate-365) - else - dayssincecleafon = model_day_int - currentSite%cleafondate - end if - - - - !LEAF ON: COLD DECIDUOUS. Needs to - !1) have exceeded the growing degree day threshold - !2) The leaves should not be on already - !3) There should have been at least one chilling day in the counting period. - ! this prevents tropical or warm climate plants that are "cold-deciduous" - ! from ever re-flushing after they have reached their maximum age (thus - ! preventing them from competing - - if ( (currentSite%cstatus == phen_cstat_iscold .or. & - currentSite%cstatus == phen_cstat_nevercold) .and. & - (currentSite%grow_deg_days > gdd_threshold) .and. & - (dayssincecleafoff > ED_val_phen_mindayson) .and. & - (currentSite%nchilldays >= 1)) then - currentSite%cstatus = phen_cstat_notcold ! Set to not-cold status (leaves can come on) - currentSite%cleafondate = model_day_int - dayssincecleafon = 0 - currentSite%grow_deg_days = 0._r8 ! zero GDD for the rest of the year until counting season begins. - if ( debug ) write(fates_log(),*) 'leaves on' - endif !GDD - - - - - !LEAF OFF: COLD THRESHOLD - !Needs to: - !1) have exceeded the number of cold days threshold - !2) have exceeded the minimum leafon time. - !3) The leaves should not be off already - !4) The day of simulation should be larger than the counting period. - - - if ( (currentSite%cstatus == phen_cstat_notcold) .and. & - (model_day_int > num_vegtemp_mem) .and. & - (ncolddays > ED_val_phen_ncolddayslim) .and. & - (dayssincecleafon > ED_val_phen_mindayson) )then - - currentSite%grow_deg_days = 0._r8 ! The equations for Botta et al - ! are for calculations of - ! first flush, but if we dont - ! clear this value, it will cause - ! leaves to flush later in the year - currentSite%cstatus = phen_cstat_iscold ! alter status of site to 'leaves off' - currentSite%cleafoffdate = model_day_int ! record leaf off date - - if ( debug ) write(fates_log(),*) 'leaves off' - endif - - ! LEAF OFF: COLD LIFESPAN THRESHOLD - ! NOTE: Some areas of the planet will never generate a cold day - ! and thus %nchilldays will never go from zero to 1. The following logic - ! when coupled with this fact will essentially prevent cold-deciduous - ! plants from re-emerging in areas without at least some cold days - - if( (currentSite%cstatus == phen_cstat_notcold) .and. & - (dayssincecleafoff > 400)) then ! remove leaves after a whole year - ! when there is no 'off' period. - currentSite%grow_deg_days = 0._r8 - - currentSite%cstatus = phen_cstat_nevercold ! alter status of site to imply that this - ! site is never really cold enough - ! for cold deciduous - currentSite%cleafoffdate = model_day_int ! record leaf off date - - if ( debug ) write(fates_log(),*) 'leaves off' - endif - - !-----------------Drought Phenology--------------------! - ! Principles of drought-deciduos phenology model... - ! The 'is_drought' flag is false when leaves are on, and true when leaves area off. - ! The following sets those site-level flags, which are acted on in phenology_deciduos. - ! A* The leaves live for either the length of time the soil moisture is over the threshold - ! or the lifetime of the leaves, whichever is shorter. - ! B*: If the soil is only wet for a very short time, then the leaves stay on for 100 days - ! C*: The leaves are only permitted to come ON for a 60 day window around when they last came on, - ! to prevent 'flickering' on in response to wet season storms - ! D*: We don't allow anything to happen in the first ten days to allow the water memory window - ! to come into equlibirium. - ! E*: If the soil is always wet, the leaves come on at the beginning of the window, and then - ! last for their lifespan. - ! ISSUES - ! 1. It's not clear what water content we should track. Here we are tracking the top layer, - ! but we probably should track something like BTRAN, but BTRAN is defined for each PFT, - ! and there could potentially be more than one stress-dec PFT.... ? - ! 2. In the beginning, the window is set at an arbitrary time of the year, so the leaves - ! might come on in the dry season, using up stored reserves - ! for the stress-dec plants, and potentially killing them. To get around this, - ! we need to read in the 'leaf on' date from some kind of start-up file - ! but we would need that to happen for every resolution, etc. - ! 3. Will this methodology properly kill off the stress-dec trees where there is no - ! water stress? What about where the wet period coincides with the warm period? - ! We would just get them overlapping with the cold-dec trees, even though that isn't appropriate - ! Why don't the drought deciduous trees grow in the North? - ! Is cold decidousness maybe even the same as drought deciduosness there (and so does this - ! distinction actually matter??).... - - ! Accumulate surface water memory of last 10 days. - ! Liquid volume in ground layer (m3/m3) - do i_wmem = 1,numWaterMem-1 !shift memory along one - currentSite%water_memory(numWaterMem+1-i_wmem) = currentSite%water_memory(numWaterMem-i_wmem) - enddo - currentSite%water_memory(1) = bc_in%h2o_liqvol_sl(ilayer_swater) - - ! Calculate the mean water content over the last 10 days (m3/m3) - mean_10day_liqvol = sum(currentSite%water_memory(1:numWaterMem))/real(numWaterMem,r8) - - ! In drought phenology, we often need to force the leaves to stay - ! on or off as moisture fluctuates... - - ! Calculate days since leaves have come off, but make a provision - ! for the first year of simulation, we have to assume a leaf drop - ! date to start, so if that is in the future, set it to last year - - if (model_day_int < currentSite%dleafoffdate) then - dayssincedleafoff = model_day_int - (currentSite%dleafoffdate-365) - else - dayssincedleafoff = model_day_int - currentSite%dleafoffdate - endif - - ! the leaves are on. How long have they been on? - if (model_day_int < currentSite%dleafondate) then - dayssincedleafon = model_day_int - (currentSite%dleafondate-365) - else - dayssincedleafon = model_day_int - currentSite%dleafondate - endif - - ! LEAF ON: DROUGHT DECIDUOUS WETNESS - ! Here, we used a window of oppurtunity to determine if we are - ! close to the time when then leaves came on last year - - ! Has it been ... - ! a) a year, plus or minus 1 month since we last had leaf-on? - ! b) Has there also been at least a nominaly short amount of "leaf-off" - ! c) is the model day at least > 10 (let soil water spin-up) - ! Note that cold-starts begin in the "leaf-on" - ! status - if ( (currentSite%dstatus == phen_dstat_timeoff .or. & - currentSite%dstatus == phen_dstat_moistoff) .and. & - (model_day_int > numWaterMem) .and. & - (dayssincedleafon >= 365-30 .and. dayssincedleafon <= 365+30 ) .and. & - (dayssincedleafoff > ED_val_phen_doff_time) ) then - - ! If leaves are off, and have been off for at least a few days - ! and the time is consistent with the correct - ! time window... test if the moisture conditions allow for leaf-on - - if ( mean_10day_liqvol >= ED_val_phen_drought_threshold ) then - currentSite%dstatus = phen_dstat_moiston ! set status to leaf-on - currentSite%dleafondate = model_day_int ! save the model day we start flushing - dayssincedleafon = 0 - endif - endif - - ! LEAF ON: DROUGHT DECIDUOUS TIME EXCEEDANCE - ! If we still haven't done budburst by end of window, then force it - - ! If the status is "phen_dstat_moistoff", it means this site currently has - ! leaves off due to actual moisture limitations. - ! So we trigger bud-burst at the end of the month since - ! last year's bud-burst. If this is imposed, then we set the new - ! status to indicate bud-burst was forced by timing - - if( currentSite%dstatus == phen_dstat_moistoff ) then - if ( dayssincedleafon > 365+30 ) then - currentSite%dstatus = phen_dstat_timeon ! force budburst! - currentSite%dleafondate = model_day_int ! record leaf on date - dayssincedleafon = 0 - end if - end if - - ! But if leaves are off due to time, then we enforce - ! a longer cool-down (because this is a perrenially wet system) - - if(currentSite%dstatus == phen_dstat_timeoff ) then - if (dayssincedleafoff > min_daysoff_dforcedflush) then - currentSite%dstatus = phen_dstat_timeon ! force budburst! - currentSite%dleafondate = model_day_int ! record leaf on date - dayssincedleafon = 0 - end if - end if - - ! LEAF OFF: DROUGHT DECIDUOUS LIFESPAN - if the leaf gets to - ! the end of its useful life. A*, E* - ! i.e. Are the leaves rouhgly at the end of their lives? - - if ( (currentSite%dstatus == phen_dstat_moiston .or. & - currentSite%dstatus == phen_dstat_timeon ) .and. & - (dayssincedleafon > canopy_leaf_lifespan) )then - currentSite%dstatus = phen_dstat_timeoff !alter status of site to 'leaves off' - currentSite%dleafoffdate = model_day_int !record leaf on date - endif - - ! LEAF OFF: DROUGHT DECIDUOUS DRYNESS - if the soil gets too dry, - ! and the leaves have already been on a while... - - if ( (currentSite%dstatus == phen_dstat_moiston .or. & - currentSite%dstatus == phen_dstat_timeon ) .and. & - (model_day_int > numWaterMem) .and. & - (mean_10day_liqvol <= ED_val_phen_drought_threshold) .and. & - (dayssincedleafon > dleafon_drycheck ) ) then - currentSite%dstatus = phen_dstat_moistoff ! alter status of site to 'leaves off' - currentSite%dleafoffdate = model_day_int ! record leaf on date - endif - - call phenology_leafonoff(currentSite) - - end subroutine phenology - - ! ============================================================================ - subroutine phenology_leafonoff(currentSite) - ! - ! !DESCRIPTION: - ! Controls the leaf on and off economics - ! - ! !USES: - ! - ! !ARGUMENTS: - type(ed_site_type), intent(inout), target :: currentSite - ! - ! !LOCAL VARIABLES: - type(ed_patch_type) , pointer :: currentPatch - type(ed_cohort_type), pointer :: currentCohort - - real(r8) :: leaf_c ! leaf carbon [kg] - real(r8) :: sapw_c ! sapwood carbon [kg] - real(r8) :: struct_c ! structural wood carbon [kg] - real(r8) :: store_c ! storage carbon [kg] - real(r8) :: store_c_transfer_frac ! Fraction of storage carbon used to flush leaves - real(r8) :: totalmemory ! total memory of carbon [kg] - integer :: ipft - real(r8), parameter :: leaf_drop_fraction = 1.0_r8 - real(r8), parameter :: carbon_store_buffer = 0.10_r8 - real(r8) :: stem_drop_fraction - !------------------------------------------------------------------------ - - currentPatch => CurrentSite%oldest_patch - - do while(associated(currentPatch)) - currentCohort => currentPatch%tallest - do while(associated(currentCohort)) - - ipft = currentCohort%pft - - ! Retrieve existing leaf and storage carbon - - if(debug) call currentCohort%prt%CheckMassConservation(ipft,0) - - store_c = currentCohort%prt%GetState(store_organ, all_carbon_elements) - leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) - sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) - struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) - - stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(ipft) - - ! COLD LEAF ON - ! The site level flags signify that it is no-longer too cold - ! for leaves. Time to signal flushing - - if (prt_params%season_decid(ipft) == itrue)then - if ( currentSite%cstatus == phen_cstat_notcold )then ! we have just moved to leaves being on . - if (currentCohort%status_coh == leaves_off)then ! Are the leaves currently off? - currentCohort%status_coh = leaves_on ! Leaves are on, so change status to - ! stop flow of carbon out of bstore. - - if(store_c>nearzero) then - ! flush either the amount required from the laimemory, or -most- of the storage pool - ! RF: added a criterion to stop the entire store pool emptying and triggering termination mortality - ! n.b. this might not be necessary if we adopted a more gradual approach to leaf flushing... - store_c_transfer_frac = min((EDPftvarcon_inst%phenflush_fraction(ipft)* & - currentCohort%laimemory)/store_c,(1.0_r8-carbon_store_buffer)) - - if(prt_params%woody(ipft).ne.itrue)then - totalmemory=currentCohort%laimemory+currentCohort%sapwmemory+currentCohort%structmemory - store_c_transfer_frac = min((EDPftvarcon_inst%phenflush_fraction(ipft)* & - totalmemory)/store_c, (1.0_r8-carbon_store_buffer)) - endif - - else - store_c_transfer_frac = 0.0_r8 - end if - - ! This call will request that storage carbon will be transferred to - ! leaf tissues. It is specified as a fraction of the available storage - if(prt_params%woody(ipft) == itrue) then - - call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, store_c_transfer_frac) - currentCohort%laimemory = 0.0_r8 - - else - - ! Check that the stem drop fraction is set to non-zero amount otherwise flush all carbon store to leaves - if (stem_drop_fraction .gt. 0.0_r8) then - - call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & - store_c_transfer_frac*currentCohort%laimemory/totalmemory) - - call PRTPhenologyFlush(currentCohort%prt, ipft, sapw_organ, & - store_c_transfer_frac*currentCohort%sapwmemory/totalmemory) - - call PRTPhenologyFlush(currentCohort%prt, ipft, struct_organ, & - store_c_transfer_frac*currentCohort%structmemory/totalmemory) - - else - - call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & - store_c_transfer_frac) - - end if - - currentCohort%laimemory = 0.0_r8 - currentCohort%structmemory = 0.0_r8 - currentCohort%sapwmemory = 0.0_r8 - - endif - endif !pft phenology - endif ! growing season - - !COLD LEAF OFF - if (currentSite%cstatus == phen_cstat_nevercold .or. & - currentSite%cstatus == phen_cstat_iscold) then ! past leaf drop day? Leaves still on tree? - - if (currentCohort%status_coh == leaves_on) then ! leaves have not dropped - - ! leaf off occur on individuals bigger than specific size for grass - if (currentCohort%dbh > EDPftvarcon_inst%phen_cold_size_threshold(ipft) & - .or. prt_params%woody(ipft)==itrue) then - - ! This sets the cohort to the "leaves off" flag - currentCohort%status_coh = leaves_off - - ! Remember what the lai was (leaf mass actually) was for next year - ! the same amount back on in the spring... - - currentCohort%laimemory = leaf_c - - ! Drop Leaves (this routine will update the leaf state variables, - ! for carbon and any other element that are prognostic. It will - ! also track the turnover masses that will be sent to litter later on) - - call PRTDeciduousTurnover(currentCohort%prt,ipft, & - leaf_organ, leaf_drop_fraction) - - if(prt_params%woody(ipft).ne.itrue)then - - currentCohort%sapwmemory = sapw_c * stem_drop_fraction - - currentCohort%structmemory = struct_c * stem_drop_fraction - - call PRTDeciduousTurnover(currentCohort%prt,ipft, & - sapw_organ, stem_drop_fraction) - - call PRTDeciduousTurnover(currentCohort%prt,ipft, & - struct_organ, stem_drop_fraction) - - endif ! woody plant check - endif ! individual dbh size check - endif !leaf status - endif !currentSite status - endif !season_decid - - ! DROUGHT LEAF ON - ! Site level flag indicates it is no longer in drought condition - ! deciduous plants can flush - - if (prt_params%stress_decid(ipft) == itrue )then - - if (currentSite%dstatus == phen_dstat_moiston .or. & - currentSite%dstatus == phen_dstat_timeon )then - - ! we have just moved to leaves being on . - if (currentCohort%status_coh == leaves_off)then - - !is it the leaf-on day? Are the leaves currently off? - - currentCohort%status_coh = leaves_on ! Leaves are on, so change status to - ! stop flow of carbon out of bstore. - - if(store_c>nearzero) then - - store_c_transfer_frac = & - min((EDPftvarcon_inst%phenflush_fraction(ipft)*currentCohort%laimemory)/store_c, & - (1.0_r8-carbon_store_buffer)) - - if(prt_params%woody(ipft).ne.itrue)then - - totalmemory=currentCohort%laimemory+currentCohort%sapwmemory+currentCohort%structmemory - store_c_transfer_frac = min(EDPftvarcon_inst%phenflush_fraction(ipft)*totalmemory/store_c, & - (1.0_r8-carbon_store_buffer)) - - endif - - else - store_c_transfer_frac = 0.0_r8 - endif - - ! This call will request that storage carbon will be transferred to - ! leaf tissues. It is specified as a fraction of the available storage - if(prt_params%woody(ipft) == itrue) then - - call PRTPhenologyFlush(currentCohort%prt, ipft, & - leaf_organ, store_c_transfer_frac) - - currentCohort%laimemory = 0.0_r8 - - else - - ! Check that the stem drop fraction is set to non-zero amount otherwise flush all carbon store to leaves - if (stem_drop_fraction .gt. 0.0_r8) then - - call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & - store_c_transfer_frac*currentCohort%laimemory/totalmemory) - - call PRTPhenologyFlush(currentCohort%prt, ipft, sapw_organ, & - store_c_transfer_frac*currentCohort%sapwmemory/totalmemory) - - call PRTPhenologyFlush(currentCohort%prt, ipft, struct_organ, & - store_c_transfer_frac*currentCohort%structmemory/totalmemory) - - else - - call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & - store_c_transfer_frac) - - end if - - currentCohort%laimemory = 0.0_r8 - currentCohort%structmemory = 0.0_r8 - currentCohort%sapwmemory = 0.0_r8 - - endif ! woody plant check - endif !currentCohort status again? - endif !currentSite status - - !DROUGHT LEAF OFF - if (currentSite%dstatus == phen_dstat_moistoff .or. & - currentSite%dstatus == phen_dstat_timeoff) then - - if (currentCohort%status_coh == leaves_on) then ! leaves have not dropped - - ! This sets the cohort to the "leaves off" flag - currentCohort%status_coh = leaves_off - - ! Remember what the lai (leaf mass actually) was for next year - currentCohort%laimemory = leaf_c - - call PRTDeciduousTurnover(currentCohort%prt,ipft, & - leaf_organ, leaf_drop_fraction) - - if(prt_params%woody(ipft).ne.itrue)then - - currentCohort%sapwmemory = sapw_c * stem_drop_fraction - currentCohort%structmemory = struct_c * stem_drop_fraction - - call PRTDeciduousTurnover(currentCohort%prt,ipft, & - sapw_organ, stem_drop_fraction) - - call PRTDeciduousTurnover(currentCohort%prt,ipft, & - struct_organ, stem_drop_fraction) - endif - - endif - endif !status - endif !drought dec. - - if(debug) call currentCohort%prt%CheckMassConservation(ipft,1) - - currentCohort => currentCohort%shorter - enddo !currentCohort - - currentPatch => currentPatch%younger - - enddo !currentPatch - - end subroutine phenology_leafonoff - - - ! ===================================================================================== - - subroutine SeedIn( currentSite, bc_in ) - - ! ----------------------------------------------------------------------------------- - ! Flux from plants into the seed pool. - ! It is assumed that allocation to seed on living pools has already been calculated - ! at the daily time step. - ! Note: Some seed generation can occur during disturbance. It is assumed that - ! some plants use their storage upon death to create seeds, but this in only - ! triggered during non-fire and non-logging events. See - ! subroutine mortality_litter_fluxes() and DistributeSeeds(), look for - ! parameter allom_frbstor_repro - ! ----------------------------------------------------------------------------------- - - - ! !USES: - use EDTypesMod, only : area - use EDTypesMod, only : homogenize_seed_pfts - !use FatesInterfaceTypesMod, only : hlm_use_fixed_biogeog ! For future reduced complexity? - ! - ! !ARGUMENTS - type(ed_site_type), intent(inout), target :: currentSite - type(bc_in_type), intent(in) :: bc_in - - type(ed_patch_type), pointer :: currentPatch - type(litter_type), pointer :: litt - type(ed_cohort_type), pointer :: currentCohort - type(site_massbal_type), pointer :: site_mass - - integer :: pft - real(r8) :: store_m_to_repro ! mass sent from storage to reproduction upon death [kg/plant] - real(r8) :: site_seed_rain(maxpft) ! This is the sum of seed-rain for the site [kg/site/day] - real(r8) :: seed_in_external ! Mass of externally generated seeds [kg/m2/day] - real(r8) :: seed_stoich ! Mass ratio of nutrient per C12 in seeds [kg/kg] - real(r8) :: repro_mass_prod ! Mass of reproductive material produced [kg/day] ; added by ahb 7/8/2021 - real(r8), parameter :: repro_frac_seed = 0.5 !added by ahb 7/12/2021; move this to param file - real(r8) :: seed_prod ! Seed produced in this dynamics step [kg/day] - real(r8) :: non_seed_repro_prod ! Mass of non-seed reproductive material produced [kg/day] ; added by ahb 7/10/2021 - integer :: n_litt_types ! number of litter element types (c,n,p, etc) - integer :: el ! loop counter for litter element types - integer :: element_id ! element id consistent with parteh/PRTGenericMod.F90 - !------------------------------------------------------------------------------------ - - do el = 1, num_elements - - site_seed_rain(:) = 0._r8 - - element_id = element_list(el) - - site_mass => currentSite%mass_balance(el) - - ! Loop over all patches and sum up the seed input for each PFT - currentPatch => currentSite%oldest_patch - do while (associated(currentPatch)) - - currentCohort => currentPatch%tallest - !litt => currentPatch%litter(el) !added by ahb - do while (associated(currentCohort)) - - pft = currentCohort%pft - - ! a certain fraction of bstore might go to clonal reproduction when plants die - ! (since this is only applied to the dying portion of the cohort - ! we do not actually pair down the storage via PARTEH, instead - ! we just make sure that we don't send a portion of the storage - ! to the litter in CWDInput) - ! units = [kg/ha/day] = [kg] * [fraction] * [plants/ha/year] * [year/day] - store_m_to_repro = -currentCohort%prt%GetState(store_organ,element_id) * & - EDPftvarcon_inst%allom_frbstor_repro(pft)*currentCohort%dndt*years_per_day - - ! Transfer all reproductive tissues into seed production - ! The following call to PRTReproRelease, will return the mass - ! of seeds [kg] released by the plant, per the mass_fraction - ! specified as input. This routine will also remove the mass - ! from the parteh state-variable. - - - - - - !START ahb changes - - !-------------------------------------------------------------------------- - !original code - call PRTReproRelease(currentCohort%prt,repro_organ,element_id, & - 1.0_r8, seed_prod) - !-------------------------------------------------------------------------- - - !-------------------------------------------------------------------------- - !ahb's new code - !the original code sends all reproductive tissue to seed - !This new code, added by ahb, is designed to send some reproductive biomass - !straight to the leaf litter pool to account for non-seed reproductive - !biomass. For now, ahb does this after the call to the - !PRTReproRelease function, but a better solution would probably be to do - !this within the PRTReproRelease module in parteh/PRTLossFluxesMod.F90::L342 - !by adding new live reproductive organs (ahb needs help with this). - - !call PRTReproRelease(currentCohort%prt,repro_organ,element_id, & - ! 1.0_r8, repro_mass_prod) !ahb changed from seed_prod to repro_mass_prod - - !seed_prod = repro_mass_prod * repro_frac_seed ! seed production per ind. (ahb) - ! only a fraction of reproductive (ahb) - ! mass is seed (ahb) - - !non_seed_repro_prod = repro_mass_prod * (1.0_r8 - repro_frac_seed) !non-seed repro (ahb) - !mass per ind. (ahb) - - !litt%seed_decay(pft) = non_seed_repro_prod * currentCohort%n / area !send non-seed repro mass to seed decay pool - !--------------------------------------------------------------------------- - - !END ahb changes - - - - - - if(element_id==carbon12_element)then - currentcohort%seed_prod = seed_prod - end if - - site_seed_rain(pft) = site_seed_rain(pft) + & - (seed_prod * currentCohort%n + store_m_to_repro) - - currentCohort => currentCohort%shorter - enddo !cohort loop - - currentPatch => currentPatch%younger - enddo - - ! We can choose to homogenize seeds. This is simple, we just - ! add up all the seed from each pft at the site level, and then - ! equally distribute to the PFT pools - if ( homogenize_seed_pfts ) then - site_seed_rain(1:numpft) = sum(site_seed_rain(:))/real(numpft,r8) - end if - - - ! Loop over all patches again and disperse the mixed seeds into the input flux - ! arrays - - ! Loop over all patches and sum up the seed input for each PFT - currentPatch => currentSite%oldest_patch - do while (associated(currentPatch)) - - litt => currentPatch%litter(el) - do pft = 1,numpft - - if(currentSite%use_this_pft(pft).eq.itrue)then - ! Seed input from local sources (within site) - litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)/area - - !new code 7/14/2021 ahb - !-------------------------------- - litt%seed_decay(pft) = litt%seed_in_local(pft) * (1.0_r8 - repro_frac_seed) !ahb - !-------------------------------- - - ! If there is forced external seed rain, we calculate the input mass flux - ! from the different elements, usung the seed optimal stoichiometry - ! for non-carbon - select case(element_id) - case(carbon12_element) - seed_stoich = 1._r8 - case(nitrogen_element) - seed_stoich = prt_params%nitr_recr_stoich(pft) - case(phosphorus_element) - seed_stoich = prt_params%phos_recr_stoich(pft) - case default - write(fates_log(), *) 'undefined element specified' - write(fates_log(), *) 'while defining forced external seed mass flux' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end select - - ! Seed input from external sources (user param seed rain, or dispersal model) - seed_in_external = seed_stoich*EDPftvarcon_inst%seed_suppl(pft)*years_per_day - litt%seed_in_extern(pft) = litt%seed_in_extern(pft) + seed_in_external - - ! Seeds entering externally [kg/site/day] - site_mass%seed_in = site_mass%seed_in + seed_in_external*currentPatch%area - end if !use this pft - enddo - - - currentPatch => currentPatch%younger - enddo - - end do - - return - end subroutine SeedIn - - ! ============================================================================ - - subroutine SeedDecay( litt ) - ! - ! !DESCRIPTION: - ! Flux from seed pool into leaf litter pool - ! - ! !ARGUMENTS - type(litter_type) :: litt - ! - ! !LOCAL VARIABLES: - integer :: pft - !---------------------------------------------------------------------- - - ! default value from Liscke and Loffler 2006 ; making this a PFT-specific parameter - ! decays the seed pool according to exponential model - ! seed_decay_rate is in yr-1 - ! seed_decay is kg/day - ! Assume that decay rates are same for all chemical species - - do pft = 1,numpft - litt%seed_decay(pft) = litt%seed(pft) * & - EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day + & ! "+ &" added by ahb (7/10/2021) - litt%seed_decay(pft) ! line added by ahb so that the flux from non-seed reproductive - ! biomass (from SeedIn subroutine) is not lost (7/10/2021) - - litt%seed_germ_decay(pft) = litt%seed_germ(pft) * & - EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day - - enddo - - return - end subroutine SeedDecay - - ! ============================================================================ - subroutine SeedGermination( litt, cold_stat, drought_stat ) - ! - ! !DESCRIPTION: - ! Flux from seed pool into sapling pool - ! - ! !USES: - - ! - ! !ARGUMENTS - type(litter_type) :: litt - integer, intent(in) :: cold_stat ! Is the site in cold leaf-off status? - integer, intent(in) :: drought_stat ! Is the site in drought leaf-off status? - ! - ! !LOCAL VARIABLES: - integer :: pft - - - real(r8), parameter :: max_germination = 1.0_r8 ! Cap on germination rates. - ! KgC/m2/yr Lishcke et al. 2009 - - ! Turning of this cap? because the cap will impose changes on proportionality - ! of nutrients. (RGK 02-2019) - !real(r8), parameter :: max_germination = 1.e6_r8 ! Force to very high number - - !---------------------------------------------------------------------- - - ! germination_rate is being pulled to PFT parameter; units are 1/yr - ! thus the mortality rate of seed -> recruit (in units of carbon) - ! is seed_decay_rate(p)/germination_rate(p) - ! and thus the mortality rate (in units of individuals) is the product of - ! that times the ratio of (hypothetical) seed mass to recruit biomass - - do pft = 1,numpft - litt%seed_germ_in(pft) = min(litt%seed(pft) * EDPftvarcon_inst%germination_rate(pft), & - max_germination)*years_per_day - - !set the germination only under the growing season...c.xu - - if ((prt_params%season_decid(pft) == itrue ) .and. & - (any(cold_stat == [phen_cstat_nevercold,phen_cstat_iscold]))) then - litt%seed_germ_in(pft) = 0.0_r8 - endif - if ((prt_params%stress_decid(pft) == itrue ) .and. & - (any(drought_stat == [phen_dstat_timeoff,phen_dstat_moistoff]))) then - litt%seed_germ_in(pft) = 0.0_r8 - end if - - - enddo - - end subroutine SeedGermination - - ! ===================================================================================== - - - - - - ! ===================================================================================== - - subroutine recruitment( currentSite, currentPatch, bc_in ) - ! - ! !DESCRIPTION: - ! spawn new cohorts of juveniles of each PFT - ! - ! !USES: - use FatesInterfaceTypesMod, only : hlm_use_ed_prescribed_phys - ! - ! !ARGUMENTS - type(ed_site_type), intent(inout), target :: currentSite - type(ed_patch_type), intent(inout), pointer :: currentPatch - type(bc_in_type), intent(in) :: bc_in - ! - ! !LOCAL VARIABLES: - class(prt_vartypes), pointer :: prt - integer :: ft - type (ed_cohort_type) , pointer :: temp_cohort - type (litter_type), pointer :: litt ! The litter object (carbon right now) - type(site_massbal_type), pointer :: site_mass ! For accounting total in-out mass fluxes - integer :: cohortstatus - integer :: el ! loop counter for element - integer :: element_id ! element index consistent with definitions in PRTGenericMod - integer :: iage ! age loop counter for leaf age bins - integer,parameter :: recruitstatus = 1 !weather it the new created cohorts is recruited or initialized - real(r8) :: c_leaf ! target leaf biomass [kgC] - real(r8) :: c_fnrt ! target fine root biomass [kgC] - real(r8) :: c_sapw ! target sapwood biomass [kgC] - real(r8) :: a_sapw ! target sapwood cross section are [m2] (dummy) - real(r8) :: c_agw ! target Above ground biomass [kgC] - real(r8) :: c_bgw ! target Below ground biomass [kgC] - real(r8) :: c_struct ! target Structural biomass [kgc] - real(r8) :: c_store ! target Storage biomass [kgC] - real(r8) :: m_leaf ! leaf mass (element agnostic) [kg] - real(r8) :: m_fnrt ! fine-root mass (element agnostic) [kg] - real(r8) :: m_sapw ! sapwood mass (element agnostic) [kg] - real(r8) :: m_agw ! AG wood mass (element agnostic) [kg] - real(r8) :: m_bgw ! BG wood mass (element agnostic) [kg] - real(r8) :: m_struct ! structural mass (element agnostic) [kg] - real(r8) :: m_store ! storage mass (element agnostic) [kg] - real(r8) :: m_repro ! reproductive mass (element agnostic) [kg] - real(r8) :: mass_avail ! The mass of each nutrient/carbon available in the seed_germination pool [kg] - real(r8) :: mass_demand ! Total mass demanded by the plant to achieve the stoichiometric targets - ! of all the organs in the recruits. Used for both [kg per plant] and [kg per cohort] - real(r8) :: stem_drop_fraction - - !---------------------------------------------------------------------- - - allocate(temp_cohort) ! create temporary cohort - call zero_cohort(temp_cohort) - - - do ft = 1,numpft - if(currentSite%use_this_pft(ft).eq.itrue)then - temp_cohort%canopy_trim = init_recruit_trim - temp_cohort%pft = ft - temp_cohort%hite = EDPftvarcon_inst%hgt_min(ft) - temp_cohort%coage = 0.0_r8 - stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(ft) - - call h2d_allom(temp_cohort%hite,ft,temp_cohort%dbh) - - ! Initialize live pools - call bleaf(temp_cohort%dbh,ft,temp_cohort%canopy_trim,c_leaf) - call bfineroot(temp_cohort%dbh,ft,temp_cohort%canopy_trim,c_fnrt) - call bsap_allom(temp_cohort%dbh,ft,temp_cohort%canopy_trim,a_sapw, c_sapw) - call bagw_allom(temp_cohort%dbh,ft,c_agw) - call bbgw_allom(temp_cohort%dbh,ft,c_bgw) - call bdead_allom(c_agw,c_bgw,c_sapw,ft,c_struct) - call bstore_allom(temp_cohort%dbh,ft,temp_cohort%canopy_trim,c_store) - - ! Default assumption is that leaves are on - cohortstatus = leaves_on - temp_cohort%laimemory = 0.0_r8 - temp_cohort%sapwmemory = 0.0_r8 - temp_cohort%structmemory = 0.0_r8 - - - ! But if the plant is seasonally (cold) deciduous, and the site status is flagged - ! as "cold", then set the cohort's status to leaves_off, and remember the leaf biomass - if ((prt_params%season_decid(ft) == itrue) .and. & - (any(currentSite%cstatus == [phen_cstat_nevercold,phen_cstat_iscold]))) then - temp_cohort%laimemory = c_leaf - c_leaf = 0.0_r8 - - ! If plant is not woody then set sapwood and structural biomass as well - if (prt_params%woody(ft).ne.itrue) then - temp_cohort%sapwmemory = c_sapw * stem_drop_fraction - temp_cohort%structmemory = c_struct * stem_drop_fraction - c_sapw = (1.0_r8 - stem_drop_fraction) * c_sapw - c_struct = (1.0_r8 - stem_drop_fraction) * c_struct - endif - cohortstatus = leaves_off - endif - - ! Or.. if the plant is drought deciduous, and the site status is flagged as - ! "in a drought", then likewise, set the cohort's status to leaves_off, and remember leaf - ! biomass - if ((prt_params%stress_decid(ft) == itrue) .and. & - (any(currentSite%dstatus == [phen_dstat_timeoff,phen_dstat_moistoff]))) then - temp_cohort%laimemory = c_leaf - c_leaf = 0.0_r8 - - ! If plant is not woody then set sapwood and structural biomass as well - if(prt_params%woody(ft).ne.itrue)then - temp_cohort%sapwmemory = c_sapw * stem_drop_fraction - temp_cohort%structmemory = c_struct * stem_drop_fraction - c_sapw = (1.0_r8 - stem_drop_fraction) * c_sapw - c_struct = (1.0_r8 - stem_drop_fraction) * c_struct - endif - cohortstatus = leaves_off - endif - - - ! Cycle through available carbon and nutrients, find the limiting element - ! to dictate the total number of plants that can be generated - - if ( (hlm_use_ed_prescribed_phys .eq. ifalse) .or. & - (EDPftvarcon_inst%prescribed_recruitment(ft) .lt. 0._r8) ) then - - temp_cohort%n = 1.e20_r8 - - do el = 1,num_elements - - element_id = element_list(el) - select case(element_id) - case(carbon12_element) - - mass_demand = c_struct+c_leaf+c_fnrt+c_sapw+c_store - - case(nitrogen_element) - - mass_demand = & - c_struct*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(struct_organ)) + & - c_leaf*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)) + & - c_fnrt*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)) + & - c_sapw*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)) + & - StorageNutrientTarget(ft, element_id, & - c_leaf*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)), & - c_fnrt*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)), & - c_sapw*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)), & - c_struct*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(struct_organ))) - - case(phosphorus_element) - - mass_demand = & - c_struct*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(struct_organ)) + & - c_leaf*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)) + & - c_fnrt*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)) + & - c_sapw*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)) + & - StorageNutrientTarget(ft, element_id, & - c_leaf*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)), & - c_fnrt*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)), & - c_sapw*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)), & - c_struct*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(struct_organ))) - - case default - write(fates_log(),*) 'Undefined element type in recruitment' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end select - - mass_avail = currentPatch%area * currentPatch%litter(el)%seed_germ(ft) - - ! ------------------------------------------------------------------------ - ! Update number density if this is the limiting mass - ! ------------------------------------------------------------------------ - - temp_cohort%n = min(temp_cohort%n, mass_avail/mass_demand) - - end do - - - else - ! prescribed recruitment rates. number per sq. meter per year - temp_cohort%n = currentPatch%area * & - EDPftvarcon_inst%prescribed_recruitment(ft) * & - hlm_freq_day - endif - - ! Only bother allocating a new cohort if there is a reasonable amount of it - any_recruits: if (temp_cohort%n > min_n_safemath )then - - ! ----------------------------------------------------------------------------- - ! PART II. - ! Initialize the PARTEH object, and determine the initial masses of all - ! organs and elements. - ! ----------------------------------------------------------------------------- - prt => null() - call InitPRTObject(prt) - - do el = 1,num_elements - - element_id = element_list(el) - - ! If this is carbon12, then the initialization is straight forward - ! otherwise, we use stoichiometric ratios - select case(element_id) - case(carbon12_element) - - m_struct = c_struct - m_leaf = c_leaf - m_fnrt = c_fnrt - m_sapw = c_sapw - m_store = c_store - m_repro = 0._r8 - - case(nitrogen_element) - - m_struct = c_struct*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(struct_organ)) - m_leaf = c_leaf*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)) - m_fnrt = c_fnrt*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)) - m_sapw = c_sapw*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)) - m_store = StorageNutrientTarget(ft, element_id, m_leaf, m_fnrt, m_sapw, m_struct ) - m_repro = 0._r8 - - case(phosphorus_element) - - m_struct = c_struct*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(struct_organ)) - m_leaf = c_leaf*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)) - m_fnrt = c_fnrt*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)) - m_sapw = c_sapw*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)) - m_store = StorageNutrientTarget(ft, element_id, m_leaf, m_fnrt, m_sapw, m_struct ) - m_repro = 0._r8 - - end select - - select case(hlm_parteh_mode) - case (prt_carbon_allom_hyp,prt_cnp_flex_allom_hyp ) - - ! Put all of the leaf mass into the first bin - call SetState(prt,leaf_organ, element_id,m_leaf,1) - do iage = 2,nleafage - call SetState(prt,leaf_organ, element_id,0._r8,iage) - end do - - call SetState(prt,fnrt_organ, element_id, m_fnrt) - call SetState(prt,sapw_organ, element_id, m_sapw) - call SetState(prt,store_organ, element_id, m_store) - call SetState(prt,struct_organ, element_id, m_struct) - call SetState(prt,repro_organ, element_id, m_repro) - - case default - write(fates_log(),*) 'Unspecified PARTEH module during create_cohort' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end select - - site_mass => currentSite%mass_balance(el) - - ! Remove mass from the germination pool. However, if we are use prescribed physiology, - ! AND the forced recruitment model, then we are not realling using the prognostic - ! seed_germination model, so we have to short circuit things. We send all of the - ! seed germination mass to an outflux pool, and use an arbitrary generic input flux - ! to balance out the new recruits. - - if ( (hlm_use_ed_prescribed_phys .eq. itrue ) .and. & - (EDPftvarcon_inst%prescribed_recruitment(ft) .ge. 0._r8 )) then - - site_mass%flux_generic_in = site_mass%flux_generic_in + & - temp_cohort%n*(m_struct + m_leaf + m_fnrt + m_sapw + m_store + m_repro) - - site_mass%flux_generic_out = site_mass%flux_generic_out + & - currentPatch%area * currentPatch%litter(el)%seed_germ(ft) - - currentPatch%litter(el)%seed_germ(ft) = 0._r8 - - - else - - currentPatch%litter(el)%seed_germ(ft) = currentPatch%litter(el)%seed_germ(ft) - & - temp_cohort%n / currentPatch%area * & - (m_struct + m_leaf + m_fnrt + m_sapw + m_store + m_repro) - - end if - - - - end do - - ! This call cycles through the initial conditions, and makes sure that they - ! are all initialized. - ! ----------------------------------------------------------------------------------- - - call prt%CheckInitialConditions() - - ! This initializes the cohort - call create_cohort(currentSite,currentPatch, temp_cohort%pft, temp_cohort%n, & - temp_cohort%hite, temp_cohort%coage, temp_cohort%dbh, prt, & - temp_cohort%laimemory, temp_cohort%sapwmemory, temp_cohort%structmemory, & - cohortstatus, recruitstatus, & - temp_cohort%canopy_trim, currentPatch%NCL_p, currentSite%spread, bc_in) - - ! Note that if hydraulics is on, the number of cohorts may had - ! changed due to hydraulic constraints. - ! This constaint is applied during "create_cohort" subroutine. - - ! keep track of how many individuals were recruited for passing to history - currentSite%recruitment_rate(ft) = currentSite%recruitment_rate(ft) + temp_cohort%n - - - endif any_recruits - endif !use_this_pft - enddo !pft loop - - deallocate(temp_cohort) ! delete temporary cohort - - end subroutine recruitment - - ! ============================================================================ - - subroutine CWDInput( currentSite, currentPatch, litt, bc_in) - - ! - ! !DESCRIPTION: - ! Generate litter fields from turnover. - ! Note, that the when this is called, the number density of the plants - ! has not been reduced from non-mortal turnover yet. - ! Thus, we need to avoid double counting losses from dying trees - ! and turnover in dying trees. - ! - ! !USES: - use SFParamsMod , only : SF_val_CWD_frac - - ! - ! !ARGUMENTS - type(ed_site_type), intent(inout), target :: currentSite - type(ed_patch_type),intent(inout), target :: currentPatch - type(litter_type),intent(inout),target :: litt - type(bc_in_type),intent(in) :: bc_in - - ! - ! !LOCAL VARIABLES: - type(ed_cohort_type), pointer :: currentCohort - type(site_fluxdiags_type), pointer :: flux_diags - type(site_massbal_type), pointer :: site_mass - integer :: c - real(r8) :: dead_n ! total understorey dead tree density - real(r8) :: dead_n_dlogging ! direct logging understory dead-tree density - real(r8) :: dead_n_ilogging ! indirect understory dead-tree density (logging) - real(r8) :: dead_n_natural ! understory dead density not associated - ! with direct logging - real(r8) :: leaf_m ! mass of the element of interest in the - ! leaf [kg] - real(r8) :: fnrt_m ! fine-root [kg] - real(r8) :: sapw_m ! sapwood [kg] - real(r8) :: struct_m ! structural [kg] - real(r8) :: store_m ! storage [kg] - real(r8) :: repro_m ! reproductive [kg] - real(r8) :: leaf_m_turnover ! leaf turnover [kg] - real(r8) :: fnrt_m_turnover - real(r8) :: sapw_m_turnover - real(r8) :: struct_m_turnover - real(r8) :: store_m_turnover - real(r8) :: repro_m_turnover - real(r8) :: dcmpy_frac ! Fraction of mass sent to decomposability pool - real(r8) :: plant_dens ! Number of plants per m2 - real(r8) :: bg_cwd_tot ! Total below-ground coarse woody debris - ! input flux - real(r8) :: root_fines_tot ! Total below-ground fine root coarse - ! woody debris - integer :: element_id ! element id consistent with parteh/PRTGenericMod.F90 - - real(r8) :: trunk_wood ! carbon flux into trunk products kgC/day/site - integer :: ilyr - integer :: pft - integer :: dcmpy ! decomposability pool index - integer :: numlevsoil ! Actual number of soil layers - !---------------------------------------------------------------------- - - ! ----------------------------------------------------------------------------------- - ! Other direct litter fluxes happen in phenology and in spawn_patches. - ! ----------------------------------------------------------------------------------- - - numlevsoil = currentSite%nlevsoil - - element_id = litt%element_id - - ! Object tracking flux diagnostics for each element - flux_diags => currentSite%flux_diags(element_pos(element_id)) - - ! Object tracking site level mass balance for each element - site_mass => currentSite%mass_balance(element_pos(element_id)) - - currentCohort => currentPatch%shortest - do while(associated(currentCohort)) - pft = currentCohort%pft - - call set_root_fraction(currentSite%rootfrac_scr, pft, currentSite%zi_soil, & - bc_in%max_rooting_depth_index_col) - - leaf_m_turnover = currentCohort%prt%GetTurnover(leaf_organ,element_id) - store_m_turnover = currentCohort%prt%GetTurnover(store_organ,element_id) - fnrt_m_turnover = currentCohort%prt%GetTurnover(fnrt_organ,element_id) - sapw_m_turnover = currentCohort%prt%GetTurnover(sapw_organ,element_id) - struct_m_turnover = currentCohort%prt%GetTurnover(struct_organ,element_id) - repro_m_turnover = currentCohort%prt%GetTurnover(repro_organ,element_id) - - leaf_m = currentCohort%prt%GetState(leaf_organ,element_id) - store_m = currentCohort%prt%GetState(store_organ,element_id) - fnrt_m = currentCohort%prt%GetState(fnrt_organ,element_id) - sapw_m = currentCohort%prt%GetState(sapw_organ,element_id) - struct_m = currentCohort%prt%GetState(struct_organ,element_id) - repro_m = currentCohort%prt%GetState(repro_organ,element_id) - - plant_dens = currentCohort%n/currentPatch%area - - ! --------------------------------------------------------------------------------- - ! PART 1 Litter fluxes from non-mortal tissue turnovers Kg/m2/day - ! Important note: Turnover has already been removed from the cohorts. - ! So, in the next part of this algorithm, when we send the biomass - ! from dying trees to the litter pools, we don't have to worry - ! about double counting. - ! --------------------------------------------------------------------------------- - - flux_diags%leaf_litter_input(pft) = & - flux_diags%leaf_litter_input(pft) + & - leaf_m_turnover * currentCohort%n - - root_fines_tot = (fnrt_m_turnover + store_m_turnover ) * & - plant_dens - - 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 - - dcmpy_frac = GetDecompyFrac(pft,fnrt_organ,dcmpy) - do ilyr = 1, numlevsoil - litt%root_fines_in(dcmpy,ilyr) = litt%root_fines_in(dcmpy,ilyr) + & - currentSite%rootfrac_scr(ilyr) * root_fines_tot * dcmpy_frac - end do - end do - - flux_diags%root_litter_input(pft) = & - flux_diags%root_litter_input(pft) + & - (fnrt_m_turnover + store_m_turnover ) * currentCohort%n - - - ! Assumption: turnover from deadwood and sapwood are lumped together in CWD pool - - do c = 1,ncwd - litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + & - (sapw_m_turnover + struct_m_turnover) * & - SF_val_CWD_frac(c) * plant_dens * & - prt_params%allom_agb_frac(pft) - - flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & - (struct_m_turnover + sapw_m_turnover) * SF_val_CWD_frac(c) * & - prt_params%allom_agb_frac(pft) * currentCohort%n - - bg_cwd_tot = (sapw_m_turnover + struct_m_turnover) * & - SF_val_CWD_frac(c) * plant_dens * & - (1.0_r8-prt_params%allom_agb_frac(pft)) - - do ilyr = 1, numlevsoil - litt%bg_cwd_in(c,ilyr) = litt%bg_cwd_in(c,ilyr) + & - bg_cwd_tot * currentSite%rootfrac_scr(ilyr) - end do - - flux_diags%cwd_bg_input(c) = flux_diags%cwd_bg_input(c) + & - bg_cwd_tot*currentPatch%area - - enddo - - - ! --------------------------------------------------------------------------------- - ! PART 2 Litter fluxes from non-disturbance inducing mortality. Kg/m2/day - ! --------------------------------------------------------------------------------- - - ! Total number of dead (n/m2/day) - dead_n = -1.0_r8 * currentCohort%dndt/currentPatch%area*years_per_day - - if(currentCohort%canopy_layer > 1)then - - ! Total number of dead understory from direct logging - ! (it is possible that large harvestable trees are in the understory) - dead_n_dlogging = currentCohort%lmort_direct * & - currentCohort%n/currentPatch%area - - ! Total number of dead understory from indirect logging - dead_n_ilogging = (currentCohort%lmort_collateral + currentCohort%lmort_infra) * & - currentCohort%n/currentPatch%area - - else - - ! All mortality from logging in the canopy is - ! is disturbance generating - - dead_n_dlogging = 0._r8 - dead_n_ilogging = 0._r8 - - end if - - dead_n_natural = dead_n - dead_n_dlogging - dead_n_ilogging - - - flux_diags%leaf_litter_input(pft) = & - flux_diags%leaf_litter_input(pft) + & - leaf_m * dead_n*currentPatch%area - - - ! %n has not been updated due to mortality yet, thus - ! the litter flux has already been counted since it captured - ! the losses of live trees and those flagged for death - - root_fines_tot = dead_n * (fnrt_m + & - store_m*(1._r8-EDPftvarcon_inst%allom_frbstor_repro(pft)) ) - - do dcmpy=1,ndcmpy - - dcmpy_frac = GetDecompyFrac(pft,leaf_organ,dcmpy) - litt%leaf_fines_in(dcmpy) = litt%leaf_fines_in(dcmpy) + & - (leaf_m+repro_m) * dead_n * dcmpy_frac - - dcmpy_frac = GetDecompyFrac(pft,fnrt_organ,dcmpy) - do ilyr = 1, numlevsoil - litt%root_fines_in(dcmpy,ilyr) = litt%root_fines_in(dcmpy,ilyr) + & - root_fines_tot * currentSite%rootfrac_scr(ilyr) * dcmpy_frac - end do - end do - - flux_diags%root_litter_input(pft) = & - flux_diags%root_litter_input(pft) + & - root_fines_tot*currentPatch%area - - ! Track CWD inputs from dead plants - - do c = 1,ncwd - - ! Below-ground - - bg_cwd_tot = (struct_m + sapw_m) * & - SF_val_CWD_frac(c) * dead_n * & - (1.0_r8-prt_params%allom_agb_frac(pft)) - - do ilyr = 1, numlevsoil - litt%bg_cwd_in(c,ilyr) = litt%bg_cwd_in(c,ilyr) + & - currentSite%rootfrac_scr(ilyr) * bg_cwd_tot - end do - - flux_diags%cwd_bg_input(c) = flux_diags%cwd_bg_input(c) + & - bg_cwd_tot * currentPatch%area - - ! Send AGB component of boles from logging activities into the litter. - ! This includes fluxes from indirect modes of death, as well as the - ! non-exported boles due to direct harvesting. - - if (c==ncwd) then - - - trunk_wood = (struct_m + sapw_m) * & - SF_val_CWD_frac(c) * dead_n_dlogging * & - prt_params%allom_agb_frac(pft) - - site_mass%wood_product = site_mass%wood_product + & - trunk_wood * currentPatch%area * logging_export_frac - - ! Add AG wood to litter from the non-exported fraction of wood - ! from direct anthro sources - - litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + & - trunk_wood * (1._r8-logging_export_frac) - - flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & - trunk_wood * (1._r8-logging_export_frac) * currentPatch%area - - ! Add AG wood to litter from indirect anthro sources - - litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + (struct_m + sapw_m) * & - SF_val_CWD_frac(c) * (dead_n_natural+dead_n_ilogging) * & - prt_params%allom_agb_frac(pft) - - flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & - SF_val_CWD_frac(c) * (dead_n_natural+dead_n_ilogging) * & - currentPatch%area * prt_params%allom_agb_frac(pft) - - else - - litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + (struct_m + sapw_m) * & - SF_val_CWD_frac(c) * dead_n * & - prt_params%allom_agb_frac(pft) - - flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & - SF_val_CWD_frac(c) * dead_n * (struct_m + sapw_m) * & - currentPatch%area * prt_params%allom_agb_frac(pft) - - end if - - end do - - - ! Update diagnostics that track resource management - - if( element_id .eq. carbon12_element ) then - - currentSite%resources_management%delta_litter_stock = & - currentSite%resources_management%delta_litter_stock + & - (leaf_m + fnrt_m + store_m ) * & - (dead_n_ilogging+dead_n_dlogging) * currentPatch%area - - currentSite%resources_management%delta_biomass_stock = & - currentSite%resources_management%delta_biomass_stock + & - (leaf_m + fnrt_m + store_m ) * & - (dead_n_ilogging+dead_n_dlogging) *currentPatch%area - - currentSite%resources_management%trunk_product_site = & - currentSite%resources_management%trunk_product_site + & - trunk_wood * logging_export_frac * currentPatch%area - - do c = 1,ncwd - currentSite%resources_management%delta_litter_stock = & - currentSite%resources_management%delta_litter_stock + & - (struct_m + sapw_m) * & - SF_val_CWD_frac(c) * (dead_n_natural+dead_n_ilogging) * & - currentPatch%area - - currentSite%resources_management%delta_biomass_stock = & - currentSite%resources_management%delta_biomass_stock + & - (struct_m + sapw_m) * & - SF_val_CWD_frac(c) * dead_n * currentPatch%area - end do - - ! Update diagnostics that track resource management - currentSite%resources_management%delta_individual = & - currentSite%resources_management%delta_individual + & - (dead_n_dlogging+dead_n_ilogging) * hlm_freq_day * currentPatch%area - end if - - - currentCohort => currentCohort%taller - enddo ! end loop over cohorts - - - return - end subroutine CWDInput - - ! ===================================================================================== - - - subroutine fragmentation_scaler( currentPatch, bc_in) - ! - ! !DESCRIPTION: - ! Simple CWD fragmentation Model - ! FIX(SPM, 091914) this should be a function as it returns a value in - ! currentPatch%fragmentation_scaler - ! - ! !USES: - - use FatesSynchronizedParamsMod , only : FatesSynchronizedParamsInst - use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm - use FatesConstantsMod, only : pi => pi_const - ! - ! !ARGUMENTS - type(ed_patch_type), intent(inout) :: currentPatch - type(bc_in_type), intent(in) :: bc_in - - ! - ! !LOCAL VARIABLES: - logical :: use_century_tfunc = .false. - logical :: use_hlm_soil_scalar = .true. ! Use hlm input decomp fraction scalars - integer :: j - integer :: ifp ! Index of a FATES Patch "ifp" - real(r8) :: t_scalar ! temperature scalar - real(r8) :: w_scalar ! moisture scalar - real(r8) :: catanf ! hyperbolic temperature function from CENTURY - real(r8) :: catanf_30 ! hyperbolic temperature function from CENTURY - real(r8) :: t1 ! temperature argument - !---------------------------------------------------------------------- - - catanf(t1) = 11.75_r8 +(29.7_r8 / pi) * atan( pi * 0.031_r8 * ( t1 - 15.4_r8 )) - catanf_30 = catanf(30._r8) - - ifp = currentPatch%patchno - - ! Use the hlm temp and moisture decomp fractions by default - if ( use_hlm_soil_scalar ) then - - ! Calculate the fragmentation_scaler - currentPatch%fragmentation_scaler = min(1.0_r8,max(0.0_r8,bc_in%t_scalar_sisl * bc_in%w_scalar_sisl)) - - else - - if ( .not. use_century_tfunc ) then - !calculate rate constant scalar for soil temperature,assuming that the base rate constants - !are assigned for non-moisture limiting conditions at 25C. - if (bc_in%t_veg24_pa(ifp) >= tfrz) then - t_scalar = q10_mr**((bc_in%t_veg24_pa(ifp)-(tfrz+25._r8))/10._r8) - ! Q10**((t_soisno(c,j)-(tfrz+25._r8))/10._r8) - else - t_scalar = (q10_mr**(-25._r8/10._r8))*(q10_froz**((bc_in%t_veg24_pa(ifp)-tfrz)/10._r8)) - !Q10**(-25._r8/10._r8))*(froz_q10**((t_soisno(c,j)-tfrz)/10._r8) - endif - else - ! original century uses an arctangent function to calculate the - ! temperature dependence of decomposition - t_scalar = max(catanf(bc_in%t_veg24_pa(ifp)-tfrz)/catanf_30,0.01_r8) - endif - - !Moisture Limitations - !BTRAN APPROACH - is quite simple, but max's out decomp at all unstressed - !soil moisture values, which is not realistic. - !litter decomp is proportional to water limitation on average... - w_scalar = sum(currentPatch%btran_ft(1:numpft))/real(numpft,r8) - - ! Calculate the fragmentation_scaler - currentPatch%fragmentation_scaler(:) = min(1.0_r8,max(0.0_r8,t_scalar * w_scalar)) - - endif - - - end subroutine fragmentation_scaler - - ! ============================================================================ - - subroutine CWDOut( litt, fragmentation_scaler, nlev_eff_decomp ) - ! - ! !DESCRIPTION: - ! Simple CWD fragmentation Model - ! spawn new cohorts of juveniles of each PFT - ! - ! !USES: - use SFParamsMod, only : SF_val_max_decomp - - ! - ! !ARGUMENTS - type(litter_type),intent(inout),target :: litt - real(r8),intent(in) :: fragmentation_scaler(:) - - ! This is not necessarily every soil layer, this is the number - ! of effective layers that are active and can be sent - ! to the soil decomposition model - integer,intent(in) :: nlev_eff_decomp - - ! - ! !LOCAL VARIABLES: - integer :: c ! Fuel size class index - integer :: ilyr ! Soil layer index - integer :: dcmpy ! Decomposibility pool indexer - integer :: soil_layer_index = 1 ! Soil layer index associated with above ground litter - !---------------------------------------------------------------------- - - - ! Above ground litters are associated with the top soil layer temperature and - ! moisture scalars and fragmentation scalar associated with specified index value - ! is used for ag_cwd_frag and root_fines_frag calculations. - - do c = 1,ncwd - - litt%ag_cwd_frag(c) = litt%ag_cwd(c) * SF_val_max_decomp(c) * & - years_per_day * fragmentation_scaler(soil_layer_index) - - do ilyr = 1,nlev_eff_decomp - - litt%bg_cwd_frag(c,ilyr) = litt%bg_cwd(c,ilyr) * SF_val_max_decomp(c) * & - years_per_day * fragmentation_scaler(ilyr) - - enddo - end do - - ! this is the rate at which dropped leaves stop being part of the burnable pool - ! and begin to be part of the decomposing pool. This should probably be highly - ! sensitive to moisture, but also to the type of leaf thick leaves can dry out - ! before they are decomposed, for example. This section needs further scientific input. - - do dcmpy = 1,ndcmpy - - litt%leaf_fines_frag(dcmpy) = litt%leaf_fines(dcmpy) * & - years_per_day * SF_val_max_decomp(dl_sf) * fragmentation_scaler(soil_layer_index) - - do ilyr = 1,nlev_eff_decomp - litt%root_fines_frag(dcmpy,ilyr) = litt%root_fines(dcmpy,ilyr) * & - years_per_day * SF_val_max_decomp(dl_sf) * fragmentation_scaler(ilyr) - end do - enddo - - end subroutine CWDOut - -end module EDPhysiologyMod diff --git a/biogeochem/FatesLitterMod.F90 b/biogeochem/FatesLitterMod.F90 index dbcf05a9d4..be5ec48aa9 100644 --- a/biogeochem/FatesLitterMod.F90 +++ b/biogeochem/FatesLitterMod.F90 @@ -105,7 +105,6 @@ module FatesLitterMod real(r8),allocatable :: root_fines_frag(:,:) ! kg/m2/day real(r8), allocatable :: seed_decay(:) ! decay of viable seeds to litter [kg/m2/day] - real(r8), allocatable :: non_seed_repro_mass_decay(:) ! ahb, decay of non-seed reproductive mass [kg/m2/day] real(r8), allocatable :: seed_germ_decay(:) ! decay of germinated seeds to litter [kg/m2/day] real(r8), allocatable :: seed_germ_in(:) ! flux from viable to germinated seed [kg/m2/day] @@ -194,8 +193,6 @@ subroutine FuseLitter(this,self_area,donor_area,donor_litt) this%seed_decay(pft) = this%seed_decay(pft) * self_weight + & donor_litt%seed_decay(pft) * donor_weight - this%non_seed_repro_mass_decay(pft) = this%non_seed_repro_mass_decay(pft) * self_weight + & !ahb - donor_litt%non_seed_repro_mass_decay(pft) * donor_weight !ahb this%seed_germ_decay(pft) = this%seed_germ_decay(pft) * self_weight + & donor_litt%seed_germ_decay(pft) * donor_weight this%seed_germ_in(pft) = this%seed_germ_in(pft) * self_weight + & @@ -255,7 +252,6 @@ subroutine CopyLitter(this,donor_litt) this%leaf_fines_frag(:) = donor_litt%leaf_fines_frag(:) this%seed_decay(:) = donor_litt%seed_decay(:) - this%non_seed_repro_mass_decay(:) = donor_litt%non_seed_repro_mass_decay(:) !ahb this%seed_germ_decay(:) = donor_litt%seed_germ_decay(:) this%seed_germ_in(:) = donor_litt%seed_germ_in(:) this%root_fines(:,:) = donor_litt%root_fines(:,:) @@ -293,7 +289,6 @@ subroutine InitAllocate(this,numpft,numlevsoil,element_id) allocate(this%seed_germ(numpft)) allocate(this%seed_germ_in(numpft)) allocate(this%seed_germ_decay(numpft)) - allocate(this%non_seed_repro_mass_decay(numpft)) !ahb allocate(this%seed_decay(numpft)) ! Initialize everything to a nonsense flag @@ -317,7 +312,6 @@ subroutine InitAllocate(this,numpft,numlevsoil,element_id) this%root_fines_frag(:,:) = fates_unset_r8 this%seed_decay(:) = fates_unset_r8 - this%non_seed_repro_mass_decay(:) = fates_unset_r8 !ahb this%seed_germ_decay(:) = fates_unset_r8 this%seed_germ_in(:) = fates_unset_r8 @@ -382,7 +376,6 @@ subroutine DeallocateLitt(this) deallocate(this%root_fines_frag) deallocate(this%seed_decay) - deallocate(this%non_seed_repro_mass_decay) deallocate(this%seed_germ_decay) deallocate(this%seed_germ_in) @@ -409,7 +402,6 @@ subroutine ZeroFlux(this) this%seed_germ_in(:) = 0._r8 this%seed_decay(:) = 0._r8 - this%non_seed_repro_mass_decay = 0._r8 this%seed_germ_decay(:) = 0._r8 diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 23e3b62170..8ed8be696e 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -70,8 +70,10 @@ 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 :: regeneration_model ! switch for choosing between regeneration models, 1 for Fates basic, 2 for the Tree Recruitment Scheme - ! Hanbury-Brown et al., 2022 + 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) + ! (3) for the Tree Recruitment Scheme without seedling dynamics logical,protected, public :: active_crown_fire ! flag, 1=active crown fire 0=no active crown fire diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 041c80b92e..e8ff0e2791 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -106,22 +106,23 @@ module EDPftvarcon real(r8), allocatable :: seed_decay_rate(:) ! Fraction of seed mass (both germinated and ! ungerminated), decaying per year (yr-1) - real(r8), allocatable :: repro_frac_seed(:) ! added by ahb 7/15/2021 - real(r8), allocatable :: a_emerg(:) !added by ahb 7/19/2021 - real(r8), allocatable :: b_emerg(:) !added by ahb 7/19/2021 - real(r8), allocatable :: par_crit_germ(:) !added by ahb 7/19/2021 - real(r8), allocatable :: seedling_psi_emerg(:) !added by ahb 7/19/2021 - real(r8), allocatable :: seedling_psi_crit(:) !added by ahb 7/19/2021 - real(r8), allocatable :: seedling_light_rec_a(:) !added by ahb 7/19/2021 - real(r8), allocatable :: seedling_light_rec_b(:) !added by ahb 7/19/2021 - real(r8), allocatable :: seedling_mdd_crit(:) !added by ahb 7/19/2021 - real(r8), allocatable :: seedling_h2o_mort_a(:) !added by ahb 7/19/2021 - real(r8), allocatable :: seedling_h2o_mort_b(:) !added by ahb 7/19/2021 - real(r8), allocatable :: seedling_h2o_mort_c(:) !added by ahb 7/19/2021 - real(r8), allocatable :: seedling_root_depth(:) !added by ahb 7/27/2021 - real(r8), allocatable :: seedling_light_mort_a(:) !added by ahb on 7/27/2021 - real(r8), allocatable :: seedling_light_mort_b(:) !added by ahb on 7/27/2021 - real(r8), allocatable :: background_seedling_mort(:)!added by ahb on 7/27/2021 + real(r8), allocatable :: repro_frac_seed(:) ! fraciton of reproductive carbon that is seed + real(r8), allocatable :: a_emerg(:) ! mean fraction of seed bank emerging [day-1] + real(r8), allocatable :: b_emerg(:) ! seedling emergence sensitivity to soil moisture + real(r8), allocatable :: par_crit_germ(:) ! critical light level for germination [MJ m2-1 day-1] + real(r8), allocatable :: seedling_psi_emerg(:) ! critical soil moisture for seedling emergence [mm h2o suction] + real(r8), allocatable :: seedling_psi_crit(:) ! critical soil moisture initiating seedling stress + real(r8), allocatable :: seedling_light_rec_a(:) ! coefficient in light-based seedling to sapling transition rate + real(r8), allocatable :: seedling_light_rec_b(:) ! coefficient in light-based seedling to sapling transition rate + real(r8), allocatable :: seedling_mdd_crit(:) ! critical moisture deficit day accumulation for seedling moisture-based + ! seedling mortality to begin + real(r8), allocatable :: seedling_h2o_mort_a(:) ! coefficient in moisture-based seedling mortality + real(r8), allocatable :: seedling_h2o_mort_b(:) ! coefficient in moisture-based seedling mortality + real(r8), allocatable :: seedling_h2o_mort_c(:) ! coefficient in moisture-based seedling mortality + real(r8), allocatable :: seedling_root_depth(:) ! rooting depth of seedlings [m] + real(r8), allocatable :: seedling_light_mort_a(:) ! light-based seedling mortality coefficient + real(r8), allocatable :: seedling_light_mort_b(:) ! light-based seedling mortality coefficient + real(r8), allocatable :: background_seedling_mort(:)! background seedling mortality [yr-1] real(r8), allocatable :: trim_limit(:) ! Limit to reductions in leaf area w stress (m2/m2) real(r8), allocatable :: trim_inc(:) ! Incremental change in trimming function (m2/m2) diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index ff35efef52..a662050f68 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -51,15 +51,20 @@ module FatesConstantsMod !Flags specifying how tree regeneration works - integer, public, parameter :: TRS_no_seedling_dyn = 3 ! Constant defining the Tree Recruitment Scheme switch. This value - ! turns on size-based reproductive allocation and allocation to non-seed - ! reproductive biomass, but does not turn on seedling dynamics. - integer, public, parameter :: TRS = 2 !Constant defining the Tree Recruitment Scheme switch. This value turns on the full TRS. - integer, public, parameter :: default_regeneration = 1 !Constant defining FATES's default regeneration scheme switch. - real(fates_r8), public, parameter :: min_max_dbh_for_trees = 15._fates_r8 !cm; if pfts have a max dbh less - !than this value FATES - !will use the default regeneration scheme. This is to avoid - !the TRS being used for shrubs and grasses. + integer, public, parameter :: TRS_no_seedling_dyn = 3 ! Constant defining the Tree Recruitment + ! Scheme switch. This value turns on + ! size-based reproductive allocation + ! and allocation to non-seed + ! reproductive biomass, but does not turn + ! on seedling dynamics. + integer, public, parameter :: TRS = 2 ! Constant defining the Tree Recruitment + ! Scheme switch. Turns on full TRS. + integer, public, parameter :: default_regeneration = 1 ! Constant defining FATES's default + ! regeneration scheme switch. + real(fates_r8), public, parameter :: min_max_dbh_for_trees = 15._fates_r8 ! If pfts have a max dbh less + ! than this value FATES + ! will use the default regeneration scheme. + ! Avoids TRS for shrubs / grasses. integer, public, parameter :: trivial_np_comp_scaling = 2 ! This flag definition indicates that either ! nutrients are turned off in FATES, or, that the diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 7287916eca..2f6a8c47f6 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1969,16 +1969,11 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) real(r8) :: new_seedling_layer_par !seedling layer par in the current timestep real(r8) :: new_seedling_layer_smp(maxpft) !seedling layer smp in the current timestep real(r8) :: new_seedling_mdd(maxpft) !seedling layer moisture deficit days in the current timestep - - real(r8), parameter :: seedling_smp_crit = -175912.9_r8 !seedling soil moisture stress - !threshold at which point - !the seedling layer starts accumulating moisture - !deficit days; move to pft-specific param if works - integer :: ilayer_seedling_root(maxpft) !the soil layer at seedling rooting depth - integer :: n_leaf !number of leaf layers per canopy layer in patch + integer :: ilayer_seedling_root(maxpft) !the soil layer at seedling rooting depth + integer :: n_leaf !number of leaf layers per canopy layer in patch real(r8) :: lai_sun_frac real(r8) :: lai_shade_frac - integer,parameter :: ipar = 1 !solar radiation in the shortwave band (i.e. par) + integer,parameter :: ipar = 1 !solar radiation in the shortwave band (i.e. par) do s = 1,size(sites,dim=1) @@ -1991,37 +1986,41 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) call cpatch%tveg_lpa%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) call cpatch%tveg_longterm%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) - !updating seedling layer par, soil matric potential and - !moisture deficit days (mdd) in the seedling layer; ahb, August 2021 - !--------------------------------------------------------------------------------------- - - n_leaf = maxval(cpatch%ncan(cpatch%ncl_p,:)) !calculating the number of leaf layers - !in the lowest canopy layer + ! Update seedling layer running means of PAR, soil matric potential and + ! moisture deficit days (mdd). + n_leaf = maxval(cpatch%ncan(cpatch%ncl_p,:)) ! Calculate the number of leaf layers + ! in the lowest canopy layer - !calculating the fraction of total lai (summed across pfts) in sun vs. shade - !at the lowest leaf level of the lowest canopy level + ! Calculate the fraction of total lai (summed across pfts) in sun vs. shade + ! at the lowest leaf level of the lowest canopy level lai_sun_frac = sum(cpatch%ed_laisun_z(cpatch%ncl_p,:,n_leaf)) & / ( sum(cpatch%ed_laisun_z(cpatch%ncl_p,:,n_leaf)) + & !summed across pfts sum(cpatch%ed_laisha_z(cpatch%ncl_p,:,n_leaf)) ) !summed across pfts lai_shade_frac = 1.0_r8 - lai_sun_frac - !calculating seedling layer par for the current time step - !using the weighted average of direct and diffuse par profiles - + ! Calculate new_seedling_layer_par (total PAR at the lowest leaf layer of the lowest canopy layer) + ! using the weighted average of direct and diffuse par. + + ! Notes to code reviewers on calculating "new_seedling_layer_par" (4-11-2023): + ! 1. Charlie or Ryan, can you please verify that weighted-avg approach is indeed getting + ! *total* par at the lowest leaf layer of the lowest canopy layer? + ! 2. This variable currently might create a seedling layer par that is too dark because + ! it assumes that all seedlings are hiding under larger trees? Where the canopy is closed this is + ! OK, but in open forest it will overesimtae shade expected by seedlings I think? + ! What if the sun_frac weight above were multiplied by bc_in(s)%solad_parb(ifp,ipar) instead? new_seedling_layer_par = & (cpatch%parprof_dir_z(cpatch%ncl_p,n_leaf) * lai_sun_frac) + & (cpatch%parprof_dif_z(cpatch%ncl_p,n_leaf) * (1.0_r8 - lai_sun_frac)) - ! if there is no lai in the patch (i.e. no vegetation) then the lai_sun_frac - ! and lai_shade frac vars become nan, causing seedling layer par to be nan. - ! which messes up the running means. This say's that if there is no lai, the - ! par at the seedling layer is taken from the ctsm boundary conditions + ! If there is no lai on the patch then new seedling layer par becomes nan (because + ! lai_sun_frac is Inf). If this is the case then PAR at the seedling layer is + ! taken from the hlm boundary conditions (i.e. same as top of canopy). if (new_seedling_layer_par /= new_seedling_layer_par) then new_seedling_layer_par = bc_in(s)%solad_parb(ifp,ipar) + bc_in(s)%solai_parb(ifp,ipar) end if - ! update the par running means + ! Update the seedling layer par running means call cpatch%seedling_layer_par24%UpdateRMean(new_seedling_layer_par) call cpatch%sdlng_mort_par%UpdateRMean(new_seedling_layer_par) call cpatch%sdlng2sap_par%UpdateRMean(new_seedling_layer_par) @@ -2029,34 +2028,26 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) !write(fates_log(),*) 'new_seedling_layer_par', new_seedling_layer_par do pft = 1,numpft - !calculate the soil moisture at the seedling rooting depth for each pft + + ! Calculate the soil moisture at the seedling rooting depth for each pft ilayer_seedling_root(pft) = minloc(abs(bc_in(s)%z_sisl(:)-EDPftvarcon_inst%seedling_root_depth(pft)),dim=1) new_seedling_layer_smp(pft) = bc_in(s)%smp_sl(ilayer_seedling_root(pft)) - !calculate the new moisture deficit day (mdd) value for each pft + ! Calculate the new moisture deficit day (mdd) value for each pft new_seedling_mdd(pft) = (abs(EDPftvarcon_inst%seedling_psi_crit(pft)) - abs(new_seedling_layer_smp(pft))) & * (-1.0_r8) * sdlng_mdd_timescale - ! if mdds are negative then it means that soil is wetter than smp_crit and the moisture + ! If mdds are negative then it means that soil is wetter than smp_crit and the moisture ! deficit is 0 if (new_seedling_mdd(pft) < 0.0_r8) then new_seedling_mdd(pft) = 0.0_r8 endif - !update the smp and mdd running means + ! Update the seedling layer smp and mdd running means call cpatch%sdlng_emerg_smp(pft)%p%UpdateRMean(new_seedling_layer_smp(pft)) call cpatch%sdlng_mdd(pft)%p%UpdateRMean(new_seedling_mdd(pft)) - - - !write(fates_log(),*) 'new_seedling_layer_smp', new_seedling_layer_smp(pft) - !write(fates_log(),*) 'smpEmerg', cpatch%sdlng_emerg_smp(pft)%p%GetMean() - !write(fates_log(),*) 'new_sdling_mdd', new_seedling_mdd(pft) - !write(fates_log(),*) 'sdling_mdd', cpatch%sdlng_mdd(pft)%p%GetMean() - - enddo - !END ahb's changes - !--------------------------------------------------------------------------------------- + enddo ! !ccohort => cpatch%tallest !do while (associated(ccohort)) diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index cc9b0d9af5..14197a34d7 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -42,10 +42,10 @@ module PRTAllometricCarbonMod use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : i4 => fates_int use FatesConstantsMod , only : sec_per_day - use FatesConstantsMod , only : mm_per_cm !ahb - use FatesConstantsMod , only : TRS !ahb - use FatesConstantsMod , only : default_regeneration !ahb - use FatesConstantsMod , only : min_max_dbh_for_trees !ahb + use FatesConstantsMod , only : mm_per_cm + use FatesConstantsMod , only : TRS + use FatesConstantsMod , only : default_regeneration + use FatesConstantsMod , only : min_max_dbh_for_trees use FatesIntegratorsMod , only : RKF45 use FatesIntegratorsMod , only : Euler use FatesConstantsMod , only : calloc_abs_error @@ -77,7 +77,6 @@ module PRTAllometricCarbonMod integer, parameter :: repro_c_id = 5 ! Unique object index for reproductive carbon integer, parameter :: struct_c_id = 6 ! Unique object index for structural carbon integer, parameter :: num_vars = 6 ! THIS MUST MATCH THE LARGEST INDEX ABOVE - logical, parameter :: debug_trs = .true. ! local debug flag ! For this hypothesis, we integrate dbh along with the other 6. Since this @@ -976,56 +975,29 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) ct_dagwdd, ct_dbgwdd, ct_dsapdd, ct_ddeaddd) call bstore_allom(dbh,ipft,crowndamage, canopy_trim,ct_store,ct_dstoredd) - ! fraction of carbon going towards reproduction - !START ahb's changes + ! If the TRS is switched off then we use FATES's default reproductive allocation. if ( regeneration_model == default_regeneration .or. & prt_params%allom_dbh_maxheight(ipft) < min_max_dbh_for_trees ) then !The Tree Recruitment Scheme !is only for tree pfts - - !Default reproductive allocation + ! Calculate fraction of carbon going towards reproduction if (dbh <= prt_params%dbh_repro_threshold(ipft)) then ! cap on leaf biomass repro_fraction = prt_params%seed_alloc(ipft) else repro_fraction = prt_params%seed_alloc(ipft) + prt_params%seed_alloc_mature(ipft) - end if + end if ! End dbh check on if to add additional carbon to reproduction. + ! If the TRS is switched on (with or w/o seedling dynamics) then reproductive allocation is + ! a pft-specific function of dbh. This allows for the representation of different + ! reproductive schedules (Wenk and Falster, 2015) else if ( regeneration_model >= TRS .and. & prt_params%allom_dbh_maxheight(ipft) > min_max_dbh_for_trees ) then - !------------------------------------------------------------------------------------- - !Use Tree Recruitment Scheme's (TRS) approach to reproductive allocation. - !This reproductive allocation function calculates the fraction of available carbon - !allocated to reproductive tissue based on a cohort's dbh (mm). This function is based on - !empirical data and analysis at BCI (Visser et al., 2016). See Hanbury-Brown et al., 2022 - !for more details. - - !Visser MD, Bruijning M, Wright SJ, Muller-Landau HC, Jongejans E, Comita LS, - !de Kroon H. 2016. Functional traits as predictors of vital rates across the life cycle - !of tropical trees. Functional Ecology 30: 168–180. - !------------------------------------------------------------------------------------- - repro_fraction = prt_params%seed_alloc(ipft) * & (exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm) / & (1 + exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm))) - - !ahb diagnostic - !if (debug_trs) then - !if (hlm_day_of_year == 40 .OR. hlm_day_of_year == 270) then - - ! write(fates_log(),*) 'day_of_year:', hlm_day_of_year - ! write(fates_log(),*) 'pft:', ipft - ! write(fates_log(),*) 'dbh (cm):', dbh - ! write(fates_log(),*) 'repro_fraction:', repro_fraction - - !end if !day condition - !end if !debug condition - !end ahb diagnostic - - - end if !regeneration model switch - !END ahb's changes + end if ! TRS switch dCdx = 0.0_r8 From 765a6a7d595740c763f7b0be30977542f4b01540 Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Tue, 11 Apr 2023 17:27:51 -0600 Subject: [PATCH 630/852] fixed switch name error in comments --- biogeochem/EDPhysiologyMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index fdb112c439..42f16d2ce7 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1966,7 +1966,7 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) end if ! End use TRS - ! If the TRS is switched on with seedling dynamics (regeneration_model = 3) + ! If the TRS is switched on with seedling dynamics (regeneration_model = 2) ! then calculate seedling mortality. if ( regeneration_model == TRS .and. & prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees ) then From 9ce7eea28a05169862b52421c36654e2ad327242 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Wed, 12 Apr 2023 08:14:03 -0600 Subject: [PATCH 631/852] update for making --- unit_testing/CMakeLists.txt | 2 ++ unit_testing/cmake_tests.py | 55 ------------------------------- unit_testing/utils/CMakeLists.txt | 2 +- 3 files changed, 3 insertions(+), 56 deletions(-) delete mode 100755 unit_testing/cmake_tests.py diff --git a/unit_testing/CMakeLists.txt b/unit_testing/CMakeLists.txt index 506036d449..34f5abc758 100644 --- a/unit_testing/CMakeLists.txt +++ b/unit_testing/CMakeLists.txt @@ -10,3 +10,5 @@ include(CIME_utils) add_subdirectory(radiation) add_subdirectory(utils) + + diff --git a/unit_testing/cmake_tests.py b/unit_testing/cmake_tests.py deleted file mode 100755 index 4d7775ccb5..0000000000 --- a/unit_testing/cmake_tests.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys -from shutil import rmtree - -def main(): - cmake_stage("radiation test", - "/Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing", - "test_pfunit_path") - -def cmake_stage( - name, - test_spec_dir, - pfunit_path, - cmake_args=None, - clean=False, -): - """Run cmake in the current working directory. - - Arguments: - name - Name for output messages. - test_spec_dir - Test specification directory to run CMake on. - """ - if clean: - if os.path.isfile("CMakeCache.txt"): - os.remove("CMakeCache.txt") - if os.path.isdir("CMakeFiles"): - rmtree("CMakeFiles") - - if not os.path.isfile("CMakeCache.txt"): - - print("Running cmake for " + name + ".") - - cmake_command = [ - "cmake", - "-C Macros.cmake", - test_spec_dir, - # "-DCIMEROOT=" + _CIMEROOT, - # "-DSRC_ROOT=" + get_src_root(), - # "-DCIME_CMAKE_MODULE_DIRECTORY=" - # + os.path.abspath(os.path.join(_CIMEROOT, "CIME", "non_py", "src", "CMake")), - # "-DCMAKE_BUILD_TYPE=" + build_type, - # "-DPFUNIT_MPIRUN='" + mpirun_command + "'", - # "-DPFUNIT_PATH=" + pfunit_path, - ] - - if cmake_args is not None: - cmake_command.extend(cmake_args.split(" ")) - - #run_cmd_no_fail(" ".join(cmake_command), combine_output=True) - print(" ".join(cmake_command)) - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/unit_testing/utils/CMakeLists.txt b/unit_testing/utils/CMakeLists.txt index b5432bf9cd..8c80618658 100644 --- a/unit_testing/utils/CMakeLists.txt +++ b/unit_testing/utils/CMakeLists.txt @@ -2,4 +2,4 @@ list(APPEND utils_sources FatesUnitTestIOMod.F90 FatesUnitTestOrbitalMod.F90) # Export source list to parent -sourcelist_to_parent(circle_area_sources) \ No newline at end of file +sourcelist_to_parent(utils_sources) \ No newline at end of file From b9ec30f99612be0982b641e60c87850f2dd17604 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Wed, 12 Apr 2023 08:34:08 -0600 Subject: [PATCH 632/852] more updates for cmake --- unit_testing/CMakeLists.txt | 9 +++++++-- unit_testing/radiation/CMakeLists.txt | 10 ---------- unit_testing/test/CMakeLists.txt | 1 + unit_testing/test/radiation_test/CMakeLists.txt | 12 ++++++++++++ .../radiation_test}/FatesUnitTestRadiation.F90 | 0 unit_testing/utils/CMakeLists.txt | 4 +++- 6 files changed, 23 insertions(+), 13 deletions(-) delete mode 100644 unit_testing/radiation/CMakeLists.txt create mode 100644 unit_testing/test/CMakeLists.txt create mode 100644 unit_testing/test/radiation_test/CMakeLists.txt rename unit_testing/{radiation => test/radiation_test}/FatesUnitTestRadiation.F90 (100%) diff --git a/unit_testing/CMakeLists.txt b/unit_testing/CMakeLists.txt index 34f5abc758..f00baf40c4 100644 --- a/unit_testing/CMakeLists.txt +++ b/unit_testing/CMakeLists.txt @@ -7,8 +7,13 @@ project(radiation_tests Fortran C) include(CIME_utils) -add_subdirectory(radiation) +set(CLM_ROOT "..") -add_subdirectory(utils) +add_subdirectory(${CLM_ROOT}/src/fates/unit_testing/utils) +add_subdirectory(${CLM_ROOT}/src/fates/unit_testing/utils) +add_library(utils ${utils_sources}) +add_dependencies(utils) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) +link_directories(${CMAKE_CURRENT_BINARY_DIR}) \ No newline at end of file diff --git a/unit_testing/radiation/CMakeLists.txt b/unit_testing/radiation/CMakeLists.txt deleted file mode 100644 index 54408798ec..0000000000 --- a/unit_testing/radiation/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -# Local files -set(test_sources FatesUnitTestRadiation.F90) - -# Add sources we need from other directories -set(sources_needed - FatesUnitTestIOMod.F90 - FatesUnitTestOrbitalMod.F90) -extract_sources("${sources_needed}" "${utils_sources}" test_sources) - -add_executable(FATES_rad_test ${test_sources}) diff --git a/unit_testing/test/CMakeLists.txt b/unit_testing/test/CMakeLists.txt new file mode 100644 index 0000000000..6b1f8471cf --- /dev/null +++ b/unit_testing/test/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(radiation_test) \ No newline at end of file diff --git a/unit_testing/test/radiation_test/CMakeLists.txt b/unit_testing/test/radiation_test/CMakeLists.txt new file mode 100644 index 0000000000..a25360fb1c --- /dev/null +++ b/unit_testing/test/radiation_test/CMakeLists.txt @@ -0,0 +1,12 @@ +# Local files +set(test_sources FatesUnitTestRadiation.F90) + +# Add sources we need from other directories +#set(sources_needed +# FatesUnitTestIOMod.F90 +# FatesUnitTestOrbitalMod.F90) +#extract_sources("${sources_needed}" "${utils_sources}" test_sources) + +#add_executable(FATES_rad_test ${test_sources}) + +target_link_libraries(test_radiation_exe utils) diff --git a/unit_testing/radiation/FatesUnitTestRadiation.F90 b/unit_testing/test/radiation_test/FatesUnitTestRadiation.F90 similarity index 100% rename from unit_testing/radiation/FatesUnitTestRadiation.F90 rename to unit_testing/test/radiation_test/FatesUnitTestRadiation.F90 diff --git a/unit_testing/utils/CMakeLists.txt b/unit_testing/utils/CMakeLists.txt index 8c80618658..c78cf7f05d 100644 --- a/unit_testing/utils/CMakeLists.txt +++ b/unit_testing/utils/CMakeLists.txt @@ -1,5 +1,7 @@ # Append sources from this directory to the list. -list(APPEND utils_sources FatesUnitTestIOMod.F90 FatesUnitTestOrbitalMod.F90) +list(APPEND utils_sources + FatesUnitTestIOMod.F90 + FatesUnitTestOrbitalMod.F90) # Export source list to parent sourcelist_to_parent(utils_sources) \ No newline at end of file From 5a2fb0e706711a3e4cc8f00cc6b802178caf88bf Mon Sep 17 00:00:00 2001 From: adrifoster Date: Wed, 12 Apr 2023 10:46:44 -0600 Subject: [PATCH 633/852] move cmakelists --- CMakeLists.txt | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..78bb1bb231 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 2.8) + +#list(APPEND CMAKE_MODULE_PATH ${CIME_CMAKE_MODULE_DIRECTORY}) +#include(CIME_initial_setup) + +project(radiation_tests Fortran C) + +#include(CIME_utils) + +set(CLM_ROOT "../../") + +find_package (NetCDF COMPONENTS F90) +include_directories(${NETCDF_F90_INCLUDE_DIRS}) + +message(" inc = ${NETCDF_F90_INCLUDE_DIRS} ") + +#add_subdirectory(${CLM_ROOT}/src/fates/unit_testing/utils) +#add_subdirectory(${CLM_ROOT}/src/fates/main) +#add_subdirectory(${CLM_ROOT}/src/fates/unit_testing/test) + +#add_library(utils ${utils_sources}) + +#target_link_libraries(utils, ${NETCDF_F90_INCLUDE_DIRS}) +#include_directories(${CMAKE_CURRENT_BINARY_DIR}) +#link_directories(${CMAKE_CURRENT_BINARY_DIR}) \ No newline at end of file From 7ee366cce7a7543cee5fcf141831cfe7e9548b7c Mon Sep 17 00:00:00 2001 From: adrifoster Date: Wed, 12 Apr 2023 11:47:15 -0600 Subject: [PATCH 634/852] works except for netcdf --- CMakeLists.txt | 23 +- main/CMakeLists.txt | 5 +- unit_testing/CMakeLists.txt | 19 - .../test/radiation_test/CMakeLists.txt | 16 +- unit_testing/utils/FatesUnitTestIOMod.F90 | 330 +++++++++--------- 5 files changed, 187 insertions(+), 206 deletions(-) delete mode 100644 unit_testing/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 78bb1bb231..f7c8899d8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,25 +1,20 @@ cmake_minimum_required(VERSION 2.8) -#list(APPEND CMAKE_MODULE_PATH ${CIME_CMAKE_MODULE_DIRECTORY}) -#include(CIME_initial_setup) +list(APPEND CMAKE_MODULE_PATH ${CIME_CMAKE_MODULE_DIRECTORY}) +include(CIME_initial_setup) project(radiation_tests Fortran C) -#include(CIME_utils) +include(CIME_utils) set(CLM_ROOT "../../") -find_package (NetCDF COMPONENTS F90) -include_directories(${NETCDF_F90_INCLUDE_DIRS}) +add_subdirectory(${CLM_ROOT}/src/fates/main) +add_subdirectory(${CLM_ROOT}/src/fates/unit_testing/utils) +add_subdirectory(${CLM_ROOT}/src/fates/unit_testing/test) -message(" inc = ${NETCDF_F90_INCLUDE_DIRS} ") -#add_subdirectory(${CLM_ROOT}/src/fates/unit_testing/utils) -#add_subdirectory(${CLM_ROOT}/src/fates/main) -#add_subdirectory(${CLM_ROOT}/src/fates/unit_testing/test) +add_library(utils ${utils_sources}) -#add_library(utils ${utils_sources}) - -#target_link_libraries(utils, ${NETCDF_F90_INCLUDE_DIRS}) -#include_directories(${CMAKE_CURRENT_BINARY_DIR}) -#link_directories(${CMAKE_CURRENT_BINARY_DIR}) \ No newline at end of file +include_directories(${CMAKE_CURRENT_BINARY_DIR}) +link_directories(${CMAKE_CURRENT_BINARY_DIR}) \ No newline at end of file diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 4506d2c354..2d7863eb91 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -11,5 +11,8 @@ list(APPEND clm_sources FatesUtilsMod.F90 ) -sourcelist_to_parent(clm_sources) +list(APPEND utils_sources + FatesConstantsMod.F90) +sourcelist_to_parent(clm_sources) +sourcelist_to_parent(utils_sources) diff --git a/unit_testing/CMakeLists.txt b/unit_testing/CMakeLists.txt deleted file mode 100644 index f00baf40c4..0000000000 --- a/unit_testing/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8) - -list(APPEND CMAKE_MODULE_PATH ${CIME_CMAKE_MODULE_DIRECTORY}) -include(CIME_initial_setup) - -project(radiation_tests Fortran C) - -include(CIME_utils) - -set(CLM_ROOT "..") - -add_subdirectory(${CLM_ROOT}/src/fates/unit_testing/utils) -add_subdirectory(${CLM_ROOT}/src/fates/unit_testing/utils) - -add_library(utils ${utils_sources}) -add_dependencies(utils) - -include_directories(${CMAKE_CURRENT_BINARY_DIR}) -link_directories(${CMAKE_CURRENT_BINARY_DIR}) \ No newline at end of file diff --git a/unit_testing/test/radiation_test/CMakeLists.txt b/unit_testing/test/radiation_test/CMakeLists.txt index a25360fb1c..9263c1ee0d 100644 --- a/unit_testing/test/radiation_test/CMakeLists.txt +++ b/unit_testing/test/radiation_test/CMakeLists.txt @@ -1,12 +1,14 @@ # Local files set(test_sources FatesUnitTestRadiation.F90) -# Add sources we need from other directories -#set(sources_needed -# FatesUnitTestIOMod.F90 -# FatesUnitTestOrbitalMod.F90) -#extract_sources("${sources_needed}" "${utils_sources}" test_sources) +#Add sources we need from other directories +set(sources_needed + FatesUnitTestIOMod.F90 + FatesUnitTestOrbitalMod.F90 + FatesConstantsMod.F90) + +extract_sources("${sources_needed}" "${utils_sources}" test_sources) + +add_executable(FATES_rad_test ${test_sources}) -#add_executable(FATES_rad_test ${test_sources}) -target_link_libraries(test_radiation_exe utils) diff --git a/unit_testing/utils/FatesUnitTestIOMod.F90 b/unit_testing/utils/FatesUnitTestIOMod.F90 index 899942a282..02ec08a2ab 100644 --- a/unit_testing/utils/FatesUnitTestIOMod.F90 +++ b/unit_testing/utils/FatesUnitTestIOMod.F90 @@ -1,6 +1,6 @@ module FatesUnitTestIOMod - use FatesConstantsMod, only : fates_r8 => r8 - use netcdf + use FatesConstantsMod, only : r8 => fates_r8 + !use netcdf implicit none @@ -123,199 +123,199 @@ end function open_file !:.........................................................................: - subroutine write_radiation_data(file, kdir, declin) - ! - ! DESCRIPTION: - ! Opens the file filename if it can, returns a unit number for it. - ! The first time the function is called, it returns BASE_UNIT - ! + ! subroutine write_radiation_data(file, kdir, declin) + ! ! + ! ! DESCRIPTION: + ! ! Opens the file filename if it can, returns a unit number for it. + ! ! The first time the function is called, it returns BASE_UNIT + ! ! - ! ARGUMENTS: - character(len=MAX_PATH), intent(in) :: file ! output file name - real(r8), intent(in) :: kdir(num_pft,48) ! direct beam extinction coefficient - real(r8), intent(in) :: declin(48) + ! ! ARGUMENTS: + ! character(len=MAX_PATH), intent(in) :: file ! output file name + ! real(r8), intent(in) :: kdir(num_pft,48) ! direct beam extinction coefficient + ! real(r8), intent(in) :: declin(48) - ! LOCALS: - integer :: ncid - integer :: pft_dimid, time_dimid - integer :: kdir_id, declin_id - integer :: dimids(2) + ! ! LOCALS: + ! integer :: ncid + ! integer :: pft_dimid, time_dimid + ! integer :: kdir_id, declin_id + ! integer :: dimids(2) - ! Create the netCDF file. The nf90_clobber parameter tells netCDF to - ! overwrite this file, if it already exists. - call check(nf90_create(trim(file), NF90_CLOBBER, ncid)) + ! ! Create the netCDF file. The nf90_clobber parameter tells netCDF to + ! ! overwrite this file, if it already exists. + ! call check(nf90_create(trim(file), NF90_CLOBBER, ncid)) - ! define dimensions - call check(nf90_def_dim(ncid, "pft", num_pft, pft_dimid)) - call check(nf90_def_dim(ncid, "time", 48, time_dimid)) + ! ! define dimensions + ! call check(nf90_def_dim(ncid, "pft", num_pft, pft_dimid)) + ! call check(nf90_def_dim(ncid, "time", 48, time_dimid)) - ! define the variables - dimids = (/ pft_dimid, time_dimid/) - call check(nf90_def_var(ncid, "kdir", NF90_REAL8, dimids, kdir_id)) - call check(nf90_def_var(ncid, "declin", NF90_REAL8, time_dimid, declin_id)) + ! ! define the variables + ! dimids = (/ pft_dimid, time_dimid/) + ! call check(nf90_def_var(ncid, "kdir", NF90_REAL8, dimids, kdir_id)) + ! call check(nf90_def_var(ncid, "declin", NF90_REAL8, time_dimid, declin_id)) - ! end define mode - call check(nf90_enddef(ncid)) + ! ! end define mode + ! call check(nf90_enddef(ncid)) - ! write to file. - call check(nf90_put_var(ncid, kdir_id, kdir)) - call check(nf90_put_var(ncid, declin_id, declin)) + ! ! write to file. + ! call check(nf90_put_var(ncid, kdir_id, kdir)) + ! call check(nf90_put_var(ncid, declin_id, declin)) - ! close the file. - call check(nf90_close(ncid)) + ! ! close the file. + ! call check(nf90_close(ncid)) - end subroutine write_radiation_data + ! end subroutine write_radiation_data - !:.........................................................................: + ! !:.........................................................................: - subroutine check(status) - ! - ! DESCRIPTION: - ! Checks status of netcdf operations + ! subroutine check(status) + ! ! + ! ! DESCRIPTION: + ! ! Checks status of netcdf operations - ! ARGUMENTS: - integer, intent (in) :: status ! return status code from a netcdf procedure + ! ! ARGUMENTS: + ! integer, intent (in) :: status ! return status code from a netcdf procedure - if (status /= nf90_noerr) then - print *, trim(nf90_strerror(status)) - stop "Stopped" - end if + ! if (status /= nf90_noerr) then + ! print *, trim(nf90_strerror(status)) + ! stop "Stopped" + ! end if - end subroutine check + ! end subroutine check - !:.........................................................................: + ! !:.........................................................................: - subroutine read_patch_data(file, canopy_area, elai, esai, nrad) - ! - ! DESCRIPTION: - ! Reads and return patch data + ! subroutine read_patch_data(file, canopy_area, elai, esai, nrad) + ! ! + ! ! DESCRIPTION: + ! ! Reads and return patch data - ! ARGUMENTS: - character(len=MAX_PATH), intent(in) :: file ! patch file name - real(r8), intent(out) :: canopy_area(num_can,num_pft,nlevleaf) ! canopy area profile - real(r8), intent(out) :: elai(num_can,num_pft,nlevleaf) ! exposed lai profile - real(r8), intent(out) :: esai(num_can,num_pft,nlevleaf) ! exposed sai profile - real(r8), intent(out) :: nrad(num_can,num_pft) ! number of exposed leaf layers - - ! Data dictionary: declare variable types, definitions, and units - real(r8) :: nrad_r(num_can,num_pft) ! number of exposed leaf layers - integer :: fidA, varID - - ! open file - call check(nf90_open(trim(file), 0, fidA)) - - ! read patch data values - call check(nf90_inq_varid(fidA, "can_area", varID)) - call check(nf90_get_var(fidA, varID, canopy_area)) - - call check(nf90_inq_varid(fidA, "elai", varID)) - call check(nf90_get_var(fidA, varID, elai)) - - call check(nf90_inq_varid(fidA, "esai", varID)) - call check(nf90_get_var(fidA, varID, esai)) - - call check(nf90_inq_varid(fidA, "nrad", varID)) - call check(nf90_get_var(fidA, varID, nrad)) - - end subroutine read_patch_data - - !:.........................................................................: - - subroutine get_parameters(file, rhol, rhos, taul, taus, xl, ci) - ! - ! Purpose: - ! Returns parameter values - ! - ! Record of revisions: - ! Date Programmer Description of change - ! ======== ============= ===================== - ! 03/20/23 A. C. Foster Original code - ! - - ! Data dictionary: declare calling parameter types & definitions - character(len=100), intent(in) :: file ! parameter file name - real(r8), intent(out) :: rhol(num_pft,num_swb) ! leaf reflectance - real(r8), intent(out) :: rhos(num_pft,num_swb) ! stem reflectance - real(r8), intent(out) :: taul(num_pft,num_swb) ! leaf transmittance - real(r8), intent(out) :: taus(num_pft,num_swb) ! stem transmittance - real(r8), intent(out) :: xl(num_pft) ! leaf orientation index - real(r8), intent(out) :: ci(num_pft) ! clumping index - - ! read in all parameters - call read_param_netcdf(file, rhol(:,1), rhol(:,2), rhos(:,1), rhos(:,2), & - taul(:,1), taul(:,2), taus(:,1), taus(:,2), xl, ci) - - end subroutine get_parameters - - !:...........................................................................: - - subroutine read_param_netcdf(file, rholvis, rholnir, rhosvis, rhosnir, & - taulvis, taulnir, tausvis, tausnir, xl, ci) - ! - ! Purpose: - ! Reads a FATES netcdf parameter file - ! - ! Record of revisions: - ! Date Programmer Description of change - ! ======== ============= ===================== - ! 03/20/23 A. C. Foster Original code - ! - - ! Data dictionary: declare calling parameter types & definitions - character(len=100), intent(in) :: file ! parameter file name - real(r8), intent(out) :: rholvis(num_pft) ! vis leaf reflectance - real(r8), intent(out) :: rholnir(num_pft) ! nir leaf reflectance - real(r8), intent(out) :: rhosvis(num_pft) ! vis stem reflectance - real(r8), intent(out) :: rhosnir(num_pft) ! nir stem reflectance - real(r8), intent(out) :: taulvis(num_pft) ! vis leaf transmittance - real(r8), intent(out) :: taulnir(num_pft) ! nir leaf transmittance - real(r8), intent(out) :: tausvis(num_pft) ! vis stem transmittance - real(r8), intent(out) :: tausnir(num_pft) ! nir stem transmittance - real(r8), intent(out) :: xl(num_pft) ! leaf orientation index - real(r8), intent(out) :: ci(num_pft) ! clumping index - - ! Data dictionary: declare variable types, definitions, and units - integer :: fidA, paramID + ! ! ARGUMENTS: + ! character(len=MAX_PATH), intent(in) :: file ! patch file name + ! real(r8), intent(out) :: canopy_area(num_can,num_pft,nlevleaf) ! canopy area profile + ! real(r8), intent(out) :: elai(num_can,num_pft,nlevleaf) ! exposed lai profile + ! real(r8), intent(out) :: esai(num_can,num_pft,nlevleaf) ! exposed sai profile + ! real(r8), intent(out) :: nrad(num_can,num_pft) ! number of exposed leaf layers + + ! ! Data dictionary: declare variable types, definitions, and units + ! real(r8) :: nrad_r(num_can,num_pft) ! number of exposed leaf layers + ! integer :: fidA, varID + + ! ! open file + ! call check(nf90_open(trim(file), 0, fidA)) + + ! ! read patch data values + ! call check(nf90_inq_varid(fidA, "can_area", varID)) + ! call check(nf90_get_var(fidA, varID, canopy_area)) + + ! call check(nf90_inq_varid(fidA, "elai", varID)) + ! call check(nf90_get_var(fidA, varID, elai)) + + ! call check(nf90_inq_varid(fidA, "esai", varID)) + ! call check(nf90_get_var(fidA, varID, esai)) + + ! call check(nf90_inq_varid(fidA, "nrad", varID)) + ! call check(nf90_get_var(fidA, varID, nrad)) + + ! end subroutine read_patch_data + + ! !:.........................................................................: + + ! subroutine get_parameters(file, rhol, rhos, taul, taus, xl, ci) + ! ! + ! ! Purpose: + ! ! Returns parameter values + ! ! + ! ! Record of revisions: + ! ! Date Programmer Description of change + ! ! ======== ============= ===================== + ! ! 03/20/23 A. C. Foster Original code + ! ! + + ! ! Data dictionary: declare calling parameter types & definitions + ! character(len=100), intent(in) :: file ! parameter file name + ! real(r8), intent(out) :: rhol(num_pft,num_swb) ! leaf reflectance + ! real(r8), intent(out) :: rhos(num_pft,num_swb) ! stem reflectance + ! real(r8), intent(out) :: taul(num_pft,num_swb) ! leaf transmittance + ! real(r8), intent(out) :: taus(num_pft,num_swb) ! stem transmittance + ! real(r8), intent(out) :: xl(num_pft) ! leaf orientation index + ! real(r8), intent(out) :: ci(num_pft) ! clumping index + + ! ! read in all parameters + ! call read_param_netcdf(file, rhol(:,1), rhol(:,2), rhos(:,1), rhos(:,2), & + ! taul(:,1), taul(:,2), taus(:,1), taus(:,2), xl, ci) + + ! end subroutine get_parameters + + ! !:...........................................................................: + + ! subroutine read_param_netcdf(file, rholvis, rholnir, rhosvis, rhosnir, & + ! taulvis, taulnir, tausvis, tausnir, xl, ci) + ! ! + ! ! Purpose: + ! ! Reads a FATES netcdf parameter file + ! ! + ! ! Record of revisions: + ! ! Date Programmer Description of change + ! ! ======== ============= ===================== + ! ! 03/20/23 A. C. Foster Original code + ! ! + + ! ! Data dictionary: declare calling parameter types & definitions + ! character(len=100), intent(in) :: file ! parameter file name + ! real(r8), intent(out) :: rholvis(num_pft) ! vis leaf reflectance + ! real(r8), intent(out) :: rholnir(num_pft) ! nir leaf reflectance + ! real(r8), intent(out) :: rhosvis(num_pft) ! vis stem reflectance + ! real(r8), intent(out) :: rhosnir(num_pft) ! nir stem reflectance + ! real(r8), intent(out) :: taulvis(num_pft) ! vis leaf transmittance + ! real(r8), intent(out) :: taulnir(num_pft) ! nir leaf transmittance + ! real(r8), intent(out) :: tausvis(num_pft) ! vis stem transmittance + ! real(r8), intent(out) :: tausnir(num_pft) ! nir stem transmittance + ! real(r8), intent(out) :: xl(num_pft) ! leaf orientation index + ! real(r8), intent(out) :: ci(num_pft) ! clumping index + + ! ! Data dictionary: declare variable types, definitions, and units + ! integer :: fidA, paramID - ! open file - call check(nf90_open(trim(file), 0, fidA)) + ! ! open file + ! call check(nf90_open(trim(file), 0, fidA)) - ! read parameter values - call check(nf90_inq_varid(fidA, "fates_rad_leaf_rhovis", paramID)) - call check(nf90_get_var(fidA, paramID, rholvis)) + ! ! read parameter values + ! call check(nf90_inq_varid(fidA, "fates_rad_leaf_rhovis", paramID)) + ! call check(nf90_get_var(fidA, paramID, rholvis)) - call check(nf90_inq_varid(fidA, "fates_rad_leaf_rhonir", paramID)) - call check(nf90_get_var(fidA, paramID, rholnir)) + ! call check(nf90_inq_varid(fidA, "fates_rad_leaf_rhonir", paramID)) + ! call check(nf90_get_var(fidA, paramID, rholnir)) - call check(nf90_inq_varid(fidA, "fates_rad_stem_rhovis", paramID)) - call check(nf90_get_var(fidA, paramID, rhosvis)) + ! call check(nf90_inq_varid(fidA, "fates_rad_stem_rhovis", paramID)) + ! call check(nf90_get_var(fidA, paramID, rhosvis)) - call check(nf90_inq_varid(fidA, "fates_rad_stem_rhonir", paramID)) - call check(nf90_get_var(fidA, paramID, rhosnir)) + ! call check(nf90_inq_varid(fidA, "fates_rad_stem_rhonir", paramID)) + ! call check(nf90_get_var(fidA, paramID, rhosnir)) - call check(nf90_inq_varid(fidA, "fates_rad_leaf_tauvis", paramID)) - call check(nf90_get_var(fidA, paramID, taulvis)) + ! call check(nf90_inq_varid(fidA, "fates_rad_leaf_tauvis", paramID)) + ! call check(nf90_get_var(fidA, paramID, taulvis)) - call check(nf90_inq_varid(fidA, "fates_rad_leaf_taunir", paramID)) - call check(nf90_get_var(fidA, paramID, taulnir)) + ! call check(nf90_inq_varid(fidA, "fates_rad_leaf_taunir", paramID)) + ! call check(nf90_get_var(fidA, paramID, taulnir)) - call check(nf90_inq_varid(fidA, "fates_rad_stem_tauvis", paramID)) - call check(nf90_get_var(fidA, paramID, tausvis)) + ! call check(nf90_inq_varid(fidA, "fates_rad_stem_tauvis", paramID)) + ! call check(nf90_get_var(fidA, paramID, tausvis)) - call check(nf90_inq_varid(fidA, "fates_rad_stem_taunir", paramID)) - call check(nf90_get_var(fidA, paramID, tausnir)) + ! call check(nf90_inq_varid(fidA, "fates_rad_stem_taunir", paramID)) + ! call check(nf90_get_var(fidA, paramID, tausnir)) - call check(nf90_inq_varid(fidA, "fates_rad_leaf_xl", paramID)) - call check(nf90_get_var(fidA, paramID, xl)) + ! call check(nf90_inq_varid(fidA, "fates_rad_leaf_xl", paramID)) + ! call check(nf90_get_var(fidA, paramID, xl)) - call check(nf90_inq_varid(fidA, "fates_rad_leaf_clumping_index", paramID)) - call check(nf90_get_var(fidA, paramID, ci)) + ! call check(nf90_inq_varid(fidA, "fates_rad_leaf_clumping_index", paramID)) + ! call check(nf90_get_var(fidA, paramID, ci)) - ! close file - call check(nf90_close(fidA)) + ! ! close file + ! call check(nf90_close(fidA)) - end subroutine read_param_netcdf + ! end subroutine read_param_netcdf - !:...........................................................................: + ! !:...........................................................................: end module FatesUnitTestIOMod \ No newline at end of file From ec5d6b5ae0ff448d43764eb754a259057cc3a72f Mon Sep 17 00:00:00 2001 From: adrifoster Date: Wed, 12 Apr 2023 12:50:13 -0600 Subject: [PATCH 635/852] add testing functionality --- unit_testing/test/radiation_test/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/unit_testing/test/radiation_test/CMakeLists.txt b/unit_testing/test/radiation_test/CMakeLists.txt index 9263c1ee0d..895badcf9d 100644 --- a/unit_testing/test/radiation_test/CMakeLists.txt +++ b/unit_testing/test/radiation_test/CMakeLists.txt @@ -11,4 +11,7 @@ extract_sources("${sources_needed}" "${utils_sources}" test_sources) add_executable(FATES_rad_test ${test_sources}) +add_test(rad_test FATES_rad_test) +# Tell CTest how to figure out that "STOP 1" fails for the current +define_Fortran_stop_failure(rad_test) From 0480e5c049dbec0ece9408fd7eee78ae0b3da2f6 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 12 Apr 2023 16:55:06 -0400 Subject: [PATCH 636/852] Removed commented out code --- main/FatesInterfaceMod.F90 | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 6e83c2ac3a..f8bbf0da33 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -410,24 +410,8 @@ subroutine allocate_bcin(bc_in, nlevsoil_in, nlevdecomp_in, num_lu_harvest_cats, call endrun(msg=errMsg(sourcefile, __LINE__)) end if - !if( (nlevsoil_in*ndcmpy) > fates_maxElementsPerPatch .or. & - ! (nlevsoil_in*ncwd) > fates_maxElementsPerPatch) then - ! write(fates_log(), *) 'The restart files require that space is allocated' - ! write(fates_log(), *) 'to accomodate the multi-dimensional patch arrays' - ! write(fates_log(), *) 'that are nlevsoil*numpft and nlevsoil*ncwd' - ! write(fates_log(), *) 'fates_maxElementsPerPatch = ',fates_maxElementsPerPatch - ! write(fates_log(), *) 'nlevsoil = ',nlevsoil_in - ! write(fates_log(), *) 'dcmpy = ',ndcmpy - ! write(fates_log(), *) 'ncwd = ',ncwd - ! write(fates_log(), *) 'numpft*nlevsoil = ',nlevsoil_in*numpft - ! write(fates_log(), *) 'ncwd*nlevsoil = ',ncwd * nlevsoil_in - ! write(fates_log(), *) 'To increase max_elements, change numlevsoil_max' - ! call endrun(msg=errMsg(sourcefile, __LINE__)) - !end if - bc_in%nlevdecomp = nlevdecomp_in - if (hlm_use_vertsoilc == itrue) then if(bc_in%nlevdecomp .ne. bc_in%nlevsoil) then write(fates_log(), *) 'The host has signaled a vertically resolved' From 4e8936db685baf7e45be3e454ca26a75a422fe0b Mon Sep 17 00:00:00 2001 From: adrifoster Date: Thu, 13 Apr 2023 08:27:35 -0600 Subject: [PATCH 637/852] working for netcdf --- CMakeLists.txt | 32 ++++++++++++++++--- .../test/radiation_test/CMakeLists.txt | 23 +++++++++++++ unit_testing/utils/FatesUnitTestIOMod.F90 | 2 +- 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f7c8899d8b..213a44115a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,18 +1,40 @@ -cmake_minimum_required(VERSION 2.8) - -list(APPEND CMAKE_MODULE_PATH ${CIME_CMAKE_MODULE_DIRECTORY}) -include(CIME_initial_setup) +cmake_minimum_required(VERSION 3.4) project(radiation_tests Fortran C) +enable_language(Fortran) + +list(APPEND CMAKE_MODULE_PATH ${CIME_CMAKE_MODULE_DIRECTORY}) +include(CIME_initial_setup) include(CIME_utils) set(CLM_ROOT "../../") - add_subdirectory(${CLM_ROOT}/src/fates/main) add_subdirectory(${CLM_ROOT}/src/fates/unit_testing/utils) add_subdirectory(${CLM_ROOT}/src/fates/unit_testing/test) +set(NETCDF_C_DIR "/usr/local/Cellar/netcdf/4.9.2") +set(NETCDF_FORTRAN_DIR "/usr/local/Cellar/netcdf-fortran/4.6.0") +MESSAGE(">> CISM_NETCDF_C_DIR set to : ${NETCDF_C_DIR}") +MESSAGE(">> CISM_NETCDF_FORTRAN_DIR set to : ${NETCDF_FORTRAN_DIR}") + +FIND_PATH(NETCDFC_FOUND libnetcdf.a ${NETCDF_C_DIR}/lib) +FIND_PATH(NETCDFF_FOUND libnetcdff.a ${NETCDF_FORTRAN_DIR}/lib) +MESSAGE(" NETCDFC_FOUND = ${NETCDFC_FOUND}") +MESSAGE(" NETCDFF_FOUND = ${NETCDFF_FOUND}") + +IF (${NETCDFC_FOUND} STREQUAL ${NETCDF_C_DIR}/lib ) + SET(NETCDF_C_LIBS "netcdff;netcdf" CACHE STRING "Netcdf Library Names(s)") +ELSE() + SET(NETCDF_C_LIBS "netcdf" CACHE STRING "Netcdf Library Names(s)") +ENDIF() +MESSAGE(">> NETCDF_LIBS Library(s) set to : ${NETCDF_C_LIBS}") + + +include_directories(${NETCDF_C_DIR}/include + ${NETCDF_FORTRAN_DIR}/include) +link_directories(${NETCDF_C_DIR}/lib + ${NETCDF_FORTRAN_DIR}/lib) add_library(utils ${utils_sources}) diff --git a/unit_testing/test/radiation_test/CMakeLists.txt b/unit_testing/test/radiation_test/CMakeLists.txt index 895badcf9d..cd6f767d2b 100644 --- a/unit_testing/test/radiation_test/CMakeLists.txt +++ b/unit_testing/test/radiation_test/CMakeLists.txt @@ -9,6 +9,29 @@ set(sources_needed extract_sources("${sources_needed}" "${utils_sources}" test_sources) +set(NETCDF_C_DIR "/usr/local/Cellar/netcdf/4.9.2") +set(NETCDF_FORTRAN_DIR "/usr/local/Cellar/netcdf-fortran/4.6.0") +MESSAGE(">> CISM_NETCDF_C_DIR set to : ${NETCDF_C_DIR}") +MESSAGE(">> CISM_NETCDF_FORTRAN_DIR set to : ${NETCDF_FORTRAN_DIR}") + +FIND_PATH(NETCDFC_FOUND libnetcdf.a ${NETCDF_C_DIR}/lib) +FIND_PATH(NETCDFF_FOUND libnetcdff.a ${NETCDF_FORTRAN_DIR}/lib) +MESSAGE(" NETCDFC_FOUND = ${NETCDFC_FOUND}") +MESSAGE(" NETCDFF_FOUND = ${NETCDFF_FOUND}") + +IF (${NETCDFC_FOUND} STREQUAL ${NETCDF_C_DIR}/lib ) + SET(NETCDF_C_LIBS "netcdff;netcdf" CACHE STRING "Netcdf Library Names(s)") +ELSE() + SET(NETCDF_C_LIBS "netcdf" CACHE STRING "Netcdf Library Names(s)") +ENDIF() +MESSAGE(">> NETCDF_LIBS Library(s) set to : ${NETCDF_C_LIBS}") + + +include_directories(${NETCDF_C_DIR}/include + ${NETCDF_FORTRAN_DIR}/include) +link_directories(${NETCDF_C_DIR}/lib + ${NETCDF_FORTRAN_DIR}/lib) + add_executable(FATES_rad_test ${test_sources}) add_test(rad_test FATES_rad_test) diff --git a/unit_testing/utils/FatesUnitTestIOMod.F90 b/unit_testing/utils/FatesUnitTestIOMod.F90 index 02ec08a2ab..0cc004f7a4 100644 --- a/unit_testing/utils/FatesUnitTestIOMod.F90 +++ b/unit_testing/utils/FatesUnitTestIOMod.F90 @@ -1,6 +1,6 @@ module FatesUnitTestIOMod use FatesConstantsMod, only : r8 => fates_r8 - !use netcdf + use netcdf implicit none From ffeb8ee82c2a18e1e3b2bdbbf822d29e31062fa8 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Thu, 13 Apr 2023 09:19:27 -0600 Subject: [PATCH 638/852] adding a namelist --- build/.env_mach_specific.csh | 8 + build/.env_mach_specific.sh | 8 + build/Depends.gnu | 2 + build/Macros.cmake | 37 + .../__command_line_test__/CMakeCache.txt | 492 ++++++++ .../CMakeFiles/3.25.2/CMakeCCompiler.cmake | 72 ++ .../3.25.2/CMakeDetermineCompilerABI_C.bin | Bin 0 -> 16688 bytes .../CMakeDetermineCompilerABI_Fortran.bin | Bin 0 -> 33512 bytes .../3.25.2/CMakeFortranCompiler.cmake | 62 + .../CMakeFiles/3.25.2/CMakeSystem.cmake | 15 + .../3.25.2/CompilerIdC/CMakeCCompilerId.c | 868 +++++++++++++ .../CMakeFortranCompilerId.F | 1114 +++++++++++++++++ .../CMakeDirectoryInformation.cmake | 16 + .../CMakeFiles/Makefile.cmake | 141 +++ .../CMakeFiles/Makefile2 | 206 +++ .../CMakeFiles/Progress/1 | 1 + .../CMakeFiles/Progress/2 | 1 + .../CMakeFiles/Progress/3 | 1 + .../CMakeFiles/Progress/4 | 1 + .../CMakeFiles/Progress/6 | 1 + .../CMakeFiles/Progress/7 | 1 + .../CMakeFiles/Progress/8 | 1 + .../CMakeFiles/Progress/9 | 1 + .../CMakeFiles/Progress/count.txt | 1 + .../CMakeFiles/TargetDirectories.txt | 17 + .../CMakeFiles/cmake.check_cache | 1 + .../CMakeFiles/progress.marks | 1 + .../CMakeFiles/utils.dir/DependInfo.cmake | 37 + .../CMakeFiles/utils.dir/build.make | 140 +++ .../CMakeFiles/utils.dir/cmake_clean.cmake | 12 + .../utils.dir/cmake_clean_Fortran.cmake | 14 + .../utils.dir/cmake_clean_target.cmake | 3 + .../CMakeFiles/utils.dir/compiler_depend.make | 2 + .../CMakeFiles/utils.dir/compiler_depend.ts | 2 + .../CMakeFiles/utils.dir/depend.internal | 9 + .../CMakeFiles/utils.dir/depend.make | 25 + .../utils.dir/fatesconstantsmod.mod.stamp | Bin 0 -> 2256 bytes .../utils.dir/fatesunittestiomod.mod.stamp | Bin 0 -> 24087 bytes .../fatesunittestorbitalmod.mod.stamp | Bin 0 -> 25076 bytes .../CMakeFiles/utils.dir/flags.make | 10 + .../CMakeFiles/utils.dir/fortran.internal | 5 + .../CMakeFiles/utils.dir/link.txt | 2 + .../FatesConstantsMod.F90.o.provides.build | 0 .../CMakeFiles/utils.dir/progress.make | 5 + .../FatesUnitTestIOMod.F90.o.provides.build | 0 ...tesUnitTestOrbitalMod.F90.o.provides.build | 0 .../__command_line_test__/CTestTestfile.cmake | 9 + .../__command_line_test__/Macros.cmake | 1 + .../__command_line_test__/Makefile | 260 ++++ .../__command_line_test__/cmake_install.cmake | 57 + .../__command_line_test__/libutils.a | Bin 0 -> 40264 bytes .../CMakeDirectoryInformation.cmake | 16 + .../main/CMakeFiles/progress.marks | 1 + .../main/CTestTestfile.cmake | 6 + .../__command_line_test__/main/Makefile | 151 +++ .../main/cmake_install.cmake | 39 + .../CMakeDirectoryInformation.cmake | 16 + .../test/CMakeFiles/progress.marks | 1 + .../unit_testing/test/CTestTestfile.cmake | 7 + .../unit_testing/test/Makefile | 151 +++ .../unit_testing/test/cmake_install.cmake | 45 + .../CMakeDirectoryInformation.cmake | 16 + .../FATES_rad_test.dir/DependInfo.cmake | 37 + .../FatesConstantsMod.F90.o.provides.build | 0 .../FatesUnitTestIOMod.F90.o.provides.build | 0 ...tesUnitTestOrbitalMod.F90.o.provides.build | 0 .../CMakeFiles/FATES_rad_test.dir/build.make | 154 +++ .../FATES_rad_test.dir/cmake_clean.cmake | 13 + .../cmake_clean_Fortran.cmake | 14 + .../FATES_rad_test.dir/compiler_depend.make | 2 + .../FATES_rad_test.dir/compiler_depend.ts | 2 + .../FATES_rad_test.dir/depend.internal | 11 + .../CMakeFiles/FATES_rad_test.dir/depend.make | 27 + .../fatesconstantsmod.mod.stamp | Bin 0 -> 2256 bytes .../fatesunittestiomod.mod.stamp | Bin 0 -> 24087 bytes .../fatesunittestorbitalmod.mod.stamp | Bin 0 -> 25076 bytes .../CMakeFiles/FATES_rad_test.dir/flags.make | 10 + .../FATES_rad_test.dir/fortran.internal | 5 + .../CMakeFiles/FATES_rad_test.dir/link.txt | 1 + .../FATES_rad_test.dir/progress.make | 6 + .../radiation_test/CMakeFiles/progress.marks | 1 + .../test/radiation_test/CTestTestfile.cmake | 8 + .../unit_testing/test/radiation_test/Makefile | 274 ++++ .../test/radiation_test/cmake_install.cmake | 39 + .../CMakeDirectoryInformation.cmake | 16 + .../utils/CMakeFiles/progress.marks | 1 + .../unit_testing/utils/CTestTestfile.cmake | 6 + .../unit_testing/utils/Makefile | 151 +++ .../unit_testing/utils/cmake_install.cmake | 39 + build/cmake_macros/CMakeLists.txt | 4 + build/cmake_macros/CNL.cmake | 14 + build/cmake_macros/Darwin.cmake | 1 + build/cmake_macros/Macros.cmake | 37 + build/cmake_macros/arm.cmake | 0 build/cmake_macros/armgcc.cmake | 0 build/cmake_macros/athena.cmake | 0 build/cmake_macros/bluewaters.cmake | 0 build/cmake_macros/casper.cmake | 0 build/cmake_macros/centos7-linux.cmake | 1 + build/cmake_macros/cheyenne.cmake | 6 + build/cmake_macros/container.cmake | 7 + build/cmake_macros/cray.cmake | 37 + build/cmake_macros/cray_daint.cmake | 2 + build/cmake_macros/euler2.cmake | 5 + build/cmake_macros/euler3.cmake | 5 + build/cmake_macros/euler4.cmake | 5 + build/cmake_macros/frontera.cmake | 9 + build/cmake_macros/gnu.cmake | 43 + build/cmake_macros/gnu_cheyenne.cmake | 4 + build/cmake_macros/gnu_coeus.cmake | 2 + build/cmake_macros/gnu_fleabone.cmake | 27 + build/cmake_macros/gnu_hobart.cmake | 1 + build/cmake_macros/gnu_homebrew.cmake | 1 + build/cmake_macros/gnu_lobata.cmake | 15 + build/cmake_macros/gnu_melvin.cmake | 13 + build/cmake_macros/gnu_modex.cmake | 5 + build/cmake_macros/gust.cmake | 10 + build/cmake_macros/hobart.cmake | 9 + build/cmake_macros/ibm.cmake | 38 + build/cmake_macros/ibm_AIX.cmake | 18 + build/cmake_macros/ibm_BGQ.cmake | 11 + build/cmake_macros/intel.cmake | 61 + build/cmake_macros/intel_Darwin.cmake | 3 + build/cmake_macros/intel_aleph.cmake | 8 + build/cmake_macros/intel_athena.cmake | 20 + build/cmake_macros/intel_aws-hpc6a.cmake | 8 + build/cmake_macros/intel_bluewaters.cmake | 3 + build/cmake_macros/intel_casper.cmake | 9 + build/cmake_macros/intel_cheyenne.cmake | 12 + build/cmake_macros/intel_constance.cmake | 11 + build/cmake_macros/intel_cori-haswell.cmake | 9 + build/cmake_macros/intel_cori-knl.cmake | 9 + build/cmake_macros/intel_eastwind.cmake | 11 + build/cmake_macros/intel_edison.cmake | 11 + build/cmake_macros/intel_euler2.cmake | 7 + build/cmake_macros/intel_euler3.cmake | 7 + build/cmake_macros/intel_euler4.cmake | 7 + .../intel_greenplanet-sib29.cmake | 3 + .../intel_greenplanet-sky24.cmake | 3 + build/cmake_macros/intel_gust.cmake | 6 + build/cmake_macros/intel_hobart.cmake | 16 + build/cmake_macros/intel_izumi.cmake | 3 + build/cmake_macros/intel_laramie.cmake | 5 + build/cmake_macros/intel_lawrencium-lr3.cmake | 12 + build/cmake_macros/intel_sandiatoss3.cmake | 12 + build/cmake_macros/intel_stampede2-knl.cmake | 10 + build/cmake_macros/intel_stampede2-skx.cmake | 10 + build/cmake_macros/intel_theia.cmake | 4 + build/cmake_macros/intel_zeus.cmake | 18 + build/cmake_macros/izumi.cmake | 9 + build/cmake_macros/laramie.cmake | 6 + build/cmake_macros/lonestar5.cmake | 6 + build/cmake_macros/nag.cmake | 30 + build/cmake_macros/nvhpc-gpu.cmake | 46 + build/cmake_macros/nvhpc-gpu_casper.cmake | 15 + build/cmake_macros/nvhpc.cmake | 51 + build/cmake_macros/nvhpc_casper.cmake | 15 + build/cmake_macros/nvhpc_cheyenne.cmake | 4 + build/cmake_macros/nvhpc_gust.cmake | 3 + build/cmake_macros/oneapi.cmake | 61 + build/cmake_macros/pgi-gpu.cmake | 46 + build/cmake_macros/pgi-gpu_casper.cmake | 15 + build/cmake_macros/pgi.cmake | 46 + build/cmake_macros/pgi_bluewaters.cmake | 10 + build/cmake_macros/pgi_casper.cmake | 15 + build/cmake_macros/pgi_cheyenne.cmake | 4 + build/cmake_macros/pgi_constance.cmake | 11 + build/cmake_macros/pgi_daint.cmake | 3 + build/cmake_macros/pgi_eastwind.cmake | 20 + build/cmake_macros/pgi_euler2.cmake | 6 + build/cmake_macros/pgi_euler3.cmake | 6 + build/cmake_macros/pgi_euler4.cmake | 6 + build/cmake_macros/pgi_hobart.cmake | 10 + build/cmake_macros/pgi_izumi.cmake | 2 + build/cmake_macros/pgi_olympus.cmake | 11 + build/cmake_macros/pleiades-bro.cmake | 6 + build/cmake_macros/pleiades-has.cmake | 6 + build/cmake_macros/pleiades-ivy.cmake | 6 + build/cmake_macros/pleiades-san.cmake | 6 + build/cmake_macros/stampede2-knl.cmake | 4 + build/cmake_macros/stampede2-skx.cmake | 4 + build/cmake_macros/theta.cmake | 4 + build/cmake_macros/universal.cmake | 18 + build/cmake_macros/userdefined.cmake | 9 + build/cmake_macros/zeus.cmake | 8 + build/env_mach_specific.xml | 32 + test_list.xml | 7 + .../radiation_test/FatesUnitTestRadiation.F90 | 80 +- unit_testing/test/radiation_test/radiation_nl | 13 + 189 files changed, 6164 insertions(+), 52 deletions(-) create mode 100644 build/.env_mach_specific.csh create mode 100644 build/.env_mach_specific.sh create mode 100644 build/Depends.gnu create mode 100644 build/Macros.cmake create mode 100644 build/__command_line_test__/__command_line_test__/CMakeCache.txt create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CMakeCCompiler.cmake create mode 100755 build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CMakeDetermineCompilerABI_C.bin create mode 100755 build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CMakeDetermineCompilerABI_Fortran.bin create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CMakeFortranCompiler.cmake create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CMakeSystem.cmake create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CompilerIdC/CMakeCCompilerId.c create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CompilerIdFortran/CMakeFortranCompilerId.F create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/CMakeDirectoryInformation.cmake create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/Makefile.cmake create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/Makefile2 create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/1 create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/2 create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/3 create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/4 create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/6 create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/7 create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/8 create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/9 create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/count.txt create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/TargetDirectories.txt create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/cmake.check_cache create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/progress.marks create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/DependInfo.cmake create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/build.make create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/cmake_clean.cmake create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/cmake_clean_Fortran.cmake create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/cmake_clean_target.cmake create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/compiler_depend.make create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/compiler_depend.ts create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/depend.internal create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/depend.make create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fatesconstantsmod.mod.stamp create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fatesunittestiomod.mod.stamp create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fatesunittestorbitalmod.mod.stamp create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/flags.make create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fortran.internal create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/link.txt create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o.provides.build create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/progress.make create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o.provides.build create mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o.provides.build create mode 100644 build/__command_line_test__/__command_line_test__/CTestTestfile.cmake create mode 120000 build/__command_line_test__/__command_line_test__/Macros.cmake create mode 100644 build/__command_line_test__/__command_line_test__/Makefile create mode 100644 build/__command_line_test__/__command_line_test__/cmake_install.cmake create mode 100644 build/__command_line_test__/__command_line_test__/libutils.a create mode 100644 build/__command_line_test__/__command_line_test__/main/CMakeFiles/CMakeDirectoryInformation.cmake create mode 100644 build/__command_line_test__/__command_line_test__/main/CMakeFiles/progress.marks create mode 100644 build/__command_line_test__/__command_line_test__/main/CTestTestfile.cmake create mode 100644 build/__command_line_test__/__command_line_test__/main/Makefile create mode 100644 build/__command_line_test__/__command_line_test__/main/cmake_install.cmake create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/CMakeFiles/CMakeDirectoryInformation.cmake create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/CMakeFiles/progress.marks create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/CTestTestfile.cmake create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/Makefile create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/cmake_install.cmake create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/CMakeDirectoryInformation.cmake create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/DependInfo.cmake create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o.provides.build create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o.provides.build create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o.provides.build create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/cmake_clean.cmake create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/cmake_clean_Fortran.cmake create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/compiler_depend.make create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/compiler_depend.ts create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/depend.internal create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/depend.make create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesconstantsmod.mod.stamp create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestiomod.mod.stamp create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestorbitalmod.mod.stamp create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/flags.make create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fortran.internal create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/link.txt create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/progress.make create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/progress.marks create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CTestTestfile.cmake create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/Makefile create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/cmake_install.cmake create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/utils/CMakeFiles/CMakeDirectoryInformation.cmake create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/utils/CMakeFiles/progress.marks create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/utils/CTestTestfile.cmake create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/utils/Makefile create mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/utils/cmake_install.cmake create mode 100644 build/cmake_macros/CMakeLists.txt create mode 100644 build/cmake_macros/CNL.cmake create mode 100644 build/cmake_macros/Darwin.cmake create mode 100644 build/cmake_macros/Macros.cmake create mode 100644 build/cmake_macros/arm.cmake create mode 100644 build/cmake_macros/armgcc.cmake create mode 100644 build/cmake_macros/athena.cmake create mode 100644 build/cmake_macros/bluewaters.cmake create mode 100644 build/cmake_macros/casper.cmake create mode 100644 build/cmake_macros/centos7-linux.cmake create mode 100644 build/cmake_macros/cheyenne.cmake create mode 100644 build/cmake_macros/container.cmake create mode 100644 build/cmake_macros/cray.cmake create mode 100644 build/cmake_macros/cray_daint.cmake create mode 100644 build/cmake_macros/euler2.cmake create mode 100644 build/cmake_macros/euler3.cmake create mode 100644 build/cmake_macros/euler4.cmake create mode 100644 build/cmake_macros/frontera.cmake create mode 100644 build/cmake_macros/gnu.cmake create mode 100644 build/cmake_macros/gnu_cheyenne.cmake create mode 100644 build/cmake_macros/gnu_coeus.cmake create mode 100644 build/cmake_macros/gnu_fleabone.cmake create mode 100644 build/cmake_macros/gnu_hobart.cmake create mode 100644 build/cmake_macros/gnu_homebrew.cmake create mode 100644 build/cmake_macros/gnu_lobata.cmake create mode 100644 build/cmake_macros/gnu_melvin.cmake create mode 100644 build/cmake_macros/gnu_modex.cmake create mode 100644 build/cmake_macros/gust.cmake create mode 100644 build/cmake_macros/hobart.cmake create mode 100644 build/cmake_macros/ibm.cmake create mode 100644 build/cmake_macros/ibm_AIX.cmake create mode 100644 build/cmake_macros/ibm_BGQ.cmake create mode 100644 build/cmake_macros/intel.cmake create mode 100644 build/cmake_macros/intel_Darwin.cmake create mode 100644 build/cmake_macros/intel_aleph.cmake create mode 100644 build/cmake_macros/intel_athena.cmake create mode 100644 build/cmake_macros/intel_aws-hpc6a.cmake create mode 100644 build/cmake_macros/intel_bluewaters.cmake create mode 100644 build/cmake_macros/intel_casper.cmake create mode 100644 build/cmake_macros/intel_cheyenne.cmake create mode 100644 build/cmake_macros/intel_constance.cmake create mode 100644 build/cmake_macros/intel_cori-haswell.cmake create mode 100644 build/cmake_macros/intel_cori-knl.cmake create mode 100644 build/cmake_macros/intel_eastwind.cmake create mode 100644 build/cmake_macros/intel_edison.cmake create mode 100644 build/cmake_macros/intel_euler2.cmake create mode 100644 build/cmake_macros/intel_euler3.cmake create mode 100644 build/cmake_macros/intel_euler4.cmake create mode 100644 build/cmake_macros/intel_greenplanet-sib29.cmake create mode 100644 build/cmake_macros/intel_greenplanet-sky24.cmake create mode 100644 build/cmake_macros/intel_gust.cmake create mode 100644 build/cmake_macros/intel_hobart.cmake create mode 100644 build/cmake_macros/intel_izumi.cmake create mode 100644 build/cmake_macros/intel_laramie.cmake create mode 100644 build/cmake_macros/intel_lawrencium-lr3.cmake create mode 100644 build/cmake_macros/intel_sandiatoss3.cmake create mode 100644 build/cmake_macros/intel_stampede2-knl.cmake create mode 100644 build/cmake_macros/intel_stampede2-skx.cmake create mode 100644 build/cmake_macros/intel_theia.cmake create mode 100644 build/cmake_macros/intel_zeus.cmake create mode 100644 build/cmake_macros/izumi.cmake create mode 100644 build/cmake_macros/laramie.cmake create mode 100644 build/cmake_macros/lonestar5.cmake create mode 100644 build/cmake_macros/nag.cmake create mode 100644 build/cmake_macros/nvhpc-gpu.cmake create mode 100644 build/cmake_macros/nvhpc-gpu_casper.cmake create mode 100644 build/cmake_macros/nvhpc.cmake create mode 100644 build/cmake_macros/nvhpc_casper.cmake create mode 100644 build/cmake_macros/nvhpc_cheyenne.cmake create mode 100644 build/cmake_macros/nvhpc_gust.cmake create mode 100644 build/cmake_macros/oneapi.cmake create mode 100644 build/cmake_macros/pgi-gpu.cmake create mode 100644 build/cmake_macros/pgi-gpu_casper.cmake create mode 100644 build/cmake_macros/pgi.cmake create mode 100644 build/cmake_macros/pgi_bluewaters.cmake create mode 100644 build/cmake_macros/pgi_casper.cmake create mode 100644 build/cmake_macros/pgi_cheyenne.cmake create mode 100644 build/cmake_macros/pgi_constance.cmake create mode 100644 build/cmake_macros/pgi_daint.cmake create mode 100644 build/cmake_macros/pgi_eastwind.cmake create mode 100644 build/cmake_macros/pgi_euler2.cmake create mode 100644 build/cmake_macros/pgi_euler3.cmake create mode 100644 build/cmake_macros/pgi_euler4.cmake create mode 100644 build/cmake_macros/pgi_hobart.cmake create mode 100644 build/cmake_macros/pgi_izumi.cmake create mode 100644 build/cmake_macros/pgi_olympus.cmake create mode 100644 build/cmake_macros/pleiades-bro.cmake create mode 100644 build/cmake_macros/pleiades-has.cmake create mode 100644 build/cmake_macros/pleiades-ivy.cmake create mode 100644 build/cmake_macros/pleiades-san.cmake create mode 100644 build/cmake_macros/stampede2-knl.cmake create mode 100644 build/cmake_macros/stampede2-skx.cmake create mode 100644 build/cmake_macros/theta.cmake create mode 100644 build/cmake_macros/universal.cmake create mode 100644 build/cmake_macros/userdefined.cmake create mode 100644 build/cmake_macros/zeus.cmake create mode 100644 build/env_mach_specific.xml create mode 100644 test_list.xml create mode 100644 unit_testing/test/radiation_test/radiation_nl diff --git a/build/.env_mach_specific.csh b/build/.env_mach_specific.csh new file mode 100644 index 0000000000..35e5a959f4 --- /dev/null +++ b/build/.env_mach_specific.csh @@ -0,0 +1,8 @@ +# This file is for user convenience only and is not used by the model +# Changes to this file will be ignored and overwritten +# Changes to the environment should be made in env_mach_specific.xml +# Run ./case.setup --reset to regenerate this file +setenv COMPILER gnu +setenv MPILIB mpi-serial +setenv DEBUG TRUE +setenv OS Ventura diff --git a/build/.env_mach_specific.sh b/build/.env_mach_specific.sh new file mode 100644 index 0000000000..4adbda012f --- /dev/null +++ b/build/.env_mach_specific.sh @@ -0,0 +1,8 @@ +# This file is for user convenience only and is not used by the model +# Changes to this file will be ignored and overwritten +# Changes to the environment should be made in env_mach_specific.xml +# Run ./case.setup --reset to regenerate this file +export COMPILER=gnu +export MPILIB=mpi-serial +export DEBUG=TRUE +export OS=Ventura diff --git a/build/Depends.gnu b/build/Depends.gnu new file mode 100644 index 0000000000..2d53247217 --- /dev/null +++ b/build/Depends.gnu @@ -0,0 +1,2 @@ +geopk.o:geopk.F90 + $(FC) -c $(INCLDIR) $(INCS) $(FFLAGS) $(FREEFLAGS) -fcray-pointer $< diff --git a/build/Macros.cmake b/build/Macros.cmake new file mode 100644 index 0000000000..b089f58058 --- /dev/null +++ b/build/Macros.cmake @@ -0,0 +1,37 @@ +# +# Use this file to include the relevant macros based on +# machine/compiler settings. This file gets copied to CASEROOT +# and that's the one that gets included by the build system. Feel free +# to modify this file in the CASEROOT. +# +set(MACROS_DIR ${CASEROOT}/cmake_macros) + +set(UNIVERSAL_MACRO ${MACROS_DIR}/universal.cmake) +set(COMPILER_MACRO ${MACROS_DIR}/${COMPILER}.cmake) +set(OS_MACRO ${MACROS_DIR}/${OS}.cmake) +set(MACHINE_MACRO ${MACROS_DIR}/${MACH}.cmake) +set(COMPILER_OS_MACRO ${MACROS_DIR}/${COMPILER}_${OS}.cmake) +set(COMPILER_MACHINE_MACRO ${MACROS_DIR}/${COMPILER}_${MACH}.cmake) + +if (CONVERT_TO_MAKE) + get_cmake_property(VARS_BEFORE_BUILD_INTERNAL_IGNORE VARIABLES) +endif() + +# Include order defines precedence +foreach (MACRO_FILE ${UNIVERSAL_MACRO} ${COMPILER_MACRO} ${OS_MACRO} ${MACHINE_MACRO} ${COMPILER_OS_MACRO} ${COMPILER_MACHINE_MACRO}) + if (EXISTS ${MACRO_FILE}) + include(${MACRO_FILE}) + else() + message("No macro file found: ${MACRO_FILE}") + endif() +endforeach() + +if (CONVERT_TO_MAKE) + get_cmake_property(VARS_AFTER VARIABLES) + + foreach (VAR_AFTER IN LISTS VARS_AFTER) + if (NOT VAR_AFTER IN_LIST VARS_BEFORE_BUILD_INTERNAL_IGNORE) + message("CIME_SET_MAKEFILE_VAR ${VAR_AFTER} := ${${VAR_AFTER}}") + endif() + endforeach() +endif() diff --git a/build/__command_line_test__/__command_line_test__/CMakeCache.txt b/build/__command_line_test__/__command_line_test__/CMakeCache.txt new file mode 100644 index 0000000000..c99fedf020 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeCache.txt @@ -0,0 +1,492 @@ +# This is the CMakeCache file. +# For build in directory: /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ +# It was generated by CMake: /usr/local/Cellar/cmake/3.25.2/bin/cmake +# You can edit this file to change values found and used by cmake. +# If you do not want to change any of the values, simply exit the editor. +# If you do want to change a value, simply edit, save, and exit the editor. +# The syntax for the file is as follows: +# KEY:TYPE=VALUE +# KEY is the name of a variable in the cache. +# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. +# VALUE is the current value for the KEY. + +######################## +# EXTERNAL cache entries +######################## + +//No help, variable specified on the command line. +CASEROOT:UNINITIALIZED=/Users/afoster/Documents/ncar/CTSM/src/fates/build + +//No help, variable specified on the command line. +CIMEROOT:UNINITIALIZED=/Users/afoster/Documents/ncar/CTSM/cime/scripts/fortran_unit_testing/../.. + +//No help, variable specified on the command line. +CIME_CMAKE_MODULE_DIRECTORY:UNINITIALIZED=/Users/afoster/Documents/ncar/CTSM/cime/CIME/non_py/src/CMake + +//Path to a program. +CMAKE_ADDR2LINE:FILEPATH=CMAKE_ADDR2LINE-NOTFOUND + +//Path to a program. +CMAKE_AR:FILEPATH=/usr/bin/ar + +//Choose the type of build, options are: None Debug Release RelWithDebInfo +// MinSizeRel ... +CMAKE_BUILD_TYPE:STRING=CESM_DEBUG + +//Enable/Disable color output during build. +CMAKE_COLOR_MAKEFILE:BOOL=ON + +//C compiler +CMAKE_C_COMPILER:FILEPATH=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc + +//Flags used by the C compiler during all build types. +CMAKE_C_FLAGS:STRING= + +//Flags used by the C compiler during CESM_DEBUG builds. +CMAKE_C_FLAGS_CESM_DEBUG:STRING= + +//Flags used by the C compiler during DEBUG builds. +CMAKE_C_FLAGS_DEBUG:STRING=-g + +//Flags used by the C compiler during MINSIZEREL builds. +CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the C compiler during RELEASE builds. +CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG + +//Flags used by the C compiler during RELWITHDEBINFO builds. +CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//Path to a program. +CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND + +//Flags used by the linker during all build types. +CMAKE_EXE_LINKER_FLAGS:STRING=-L/usr/local/opt/lapack/lib + +//Flags used by the linker during CESM_DEBUG builds. +CMAKE_EXE_LINKER_FLAGS_CESM_DEBUG:STRING= + +//Flags used by the linker during DEBUG builds. +CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during MINSIZEREL builds. +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during RELEASE builds. +CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during RELWITHDEBINFO builds. +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Enable/Disable output of compile commands during generation. +CMAKE_EXPORT_COMPILE_COMMANDS:BOOL= + +//Value Computed by CMake. +CMAKE_FIND_PACKAGE_REDIRECTS_DIR:STATIC=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles/pkgRedirects + +//Fortran compiler +CMAKE_Fortran_COMPILER:FILEPATH=/usr/local/bin/gfortran + +//A wrapper around 'ar' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_Fortran_COMPILER_AR:FILEPATH=CMAKE_Fortran_COMPILER_AR-NOTFOUND + +//A wrapper around 'ranlib' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_Fortran_COMPILER_RANLIB:FILEPATH=CMAKE_Fortran_COMPILER_RANLIB-NOTFOUND + +//Flags used by the Fortran compiler during all build types. +CMAKE_Fortran_FLAGS:STRING= + +//Flags used by the Fortran compiler during CESM_DEBUG builds. +CMAKE_Fortran_FLAGS_CESM_DEBUG:STRING= + +//Flags used by the Fortran compiler during DEBUG builds. +CMAKE_Fortran_FLAGS_DEBUG:STRING=-g + +//Flags used by the Fortran compiler during MINSIZEREL builds. +CMAKE_Fortran_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG -Os + +//Flags used by the Fortran compiler during RELEASE builds. +CMAKE_Fortran_FLAGS_RELEASE:STRING=-O3 -DNDEBUG -O3 + +//Flags used by the Fortran compiler during RELWITHDEBINFO builds. +CMAKE_Fortran_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//Path to a program. +CMAKE_INSTALL_NAME_TOOL:FILEPATH=/usr/bin/install_name_tool + +//Install path prefix, prepended onto install directories. +CMAKE_INSTALL_PREFIX:PATH=/usr/local + +//Path to a program. +CMAKE_LINKER:FILEPATH=/usr/bin/ld + +//Path to a program. +CMAKE_MAKE_PROGRAM:FILEPATH=/usr/local/bin/gmake + +//Flags used by the linker during the creation of modules during +// all build types. +CMAKE_MODULE_LINKER_FLAGS:STRING=-L/usr/local/opt/lapack/lib + +//Flags used by the linker during the creation of modules during +// CESM_DEBUG builds. +CMAKE_MODULE_LINKER_FLAGS_CESM_DEBUG:STRING= + +//Flags used by the linker during the creation of modules during +// DEBUG builds. +CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of modules during +// MINSIZEREL builds. +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of modules during +// RELEASE builds. +CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of modules during +// RELWITHDEBINFO builds. +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_NM:FILEPATH=/usr/bin/nm + +//Path to a program. +CMAKE_OBJCOPY:FILEPATH=CMAKE_OBJCOPY-NOTFOUND + +//Path to a program. +CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump + +//Build architectures for OSX +CMAKE_OSX_ARCHITECTURES:STRING= + +//Minimum OS X version to target for deployment (at runtime); newer +// APIs weak linked. Set to empty string for default value. +CMAKE_OSX_DEPLOYMENT_TARGET:STRING= + +//The product will be built against the headers and libraries located +// inside the indicated SDK. +CMAKE_OSX_SYSROOT:PATH=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk + +//No help, variable specified on the command line. +CMAKE_PROGRAM_PATH:UNINITIALIZED=/Users/afoster/Documents/ncar/CTSM/cime/scripts/fortran_unit_testing/../../CIME/non_py/externals/genf90 + +//Value Computed by CMake +CMAKE_PROJECT_DESCRIPTION:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_HOMEPAGE_URL:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_NAME:STATIC=radiation_tests + +//Path to a program. +CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib + +//Path to a program. +CMAKE_READELF:FILEPATH=CMAKE_READELF-NOTFOUND + +//Flags used by the linker during the creation of shared libraries +// during all build types. +CMAKE_SHARED_LINKER_FLAGS:STRING=-L/usr/local/opt/lapack/lib + +//Flags used by the linker during the creation of shared libraries +// during CESM_DEBUG builds. +CMAKE_SHARED_LINKER_FLAGS_CESM_DEBUG:STRING= + +//Flags used by the linker during the creation of shared libraries +// during DEBUG builds. +CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of shared libraries +// during MINSIZEREL builds. +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELEASE builds. +CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELWITHDEBINFO builds. +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//If set, runtime paths are not added when installing shared libraries, +// but are added when building. +CMAKE_SKIP_INSTALL_RPATH:BOOL=NO + +//If set, runtime paths are not added when using shared libraries. +CMAKE_SKIP_RPATH:BOOL=NO + +//Flags used by the linker during the creation of static libraries +// during all build types. +CMAKE_STATIC_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of static libraries +// during CESM_DEBUG builds. +CMAKE_STATIC_LINKER_FLAGS_CESM_DEBUG:STRING= + +//Flags used by the linker during the creation of static libraries +// during DEBUG builds. +CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of static libraries +// during MINSIZEREL builds. +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELEASE builds. +CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELWITHDEBINFO builds. +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_STRIP:FILEPATH=/usr/bin/strip + +//If this value is on, makefiles will be generated without the +// .SILENT directive, and all commands will be echoed to the console +// during the make. This is useful for debugging only. With Visual +// Studio IDE projects all commands are done without /nologo. +CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE + +//No help, variable specified on the command line. +COMPILER:UNINITIALIZED=gnu + +//No help, variable specified on the command line. +DEBUG:UNINITIALIZED=TRUE + +//Use genf90.pl to regenerate out-of-date Fortran files from .in +// files. +ENABLE_GENF90:BOOL=ON + +//Path to a program. +GENF90:FILEPATH=/Users/afoster/Documents/ncar/CTSM/cime/CIME/non_py/externals/genf90/genf90.pl + +//No help, variable specified on the command line. +MACH:UNINITIALIZED=fleabone + +//No help, variable specified on the command line. +MPILIB:UNINITIALIZED=mpi-serial + +//Path to a file. +NETCDFC_FOUND:PATH=/usr/local/Cellar/netcdf/4.9.2/lib + +//Path to a file. +NETCDFF_FOUND:PATH=/usr/local/Cellar/netcdf-fortran/4.6.0/lib + +//Netcdf Library Names(s) +NETCDF_C_LIBS:STRING=netcdff;netcdf + +//No help, variable specified on the command line. +OS:UNINITIALIZED=Ventura + +//Path to a file. +PFUNIT_INCLUDE_DIR:PATH=/Users/afoster/pFUnit/include + +//Path to a library. +PFUNIT_LIBRARY:FILEPATH=/Users/afoster/pFUnit/lib/libpfunit.a + +//Path to a file. +PFUNIT_MODULE_DIR:PATH=/Users/afoster/pFUnit/mod + +//No help, variable specified on the command line. +PFUNIT_MPIRUN:UNINITIALIZED= + +//Path to a program. +PFUNIT_PARSER:FILEPATH=/Users/afoster/pFUnit/bin/pFUnitParser.py + +//No help, variable specified on the command line. +PFUNIT_PATH:UNINITIALIZED=/Users/afoster/pFUnit/ + +//No help, variable specified on the command line. +SRC_ROOT:UNINITIALIZED=/Users/afoster/Documents/ncar/CTSM + +//Allow color from the build output. +USE_COLOR:BOOL=ON + +//No help, variable specified on the command line. +USE_MPI_SERIAL:UNINITIALIZED=ON + +//No help, variable specified on the command line. +compile_threaded:UNINITIALIZED=FALSE + +//Value Computed by CMake +radiation_tests_BINARY_DIR:STATIC=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ + +//Value Computed by CMake +radiation_tests_IS_TOP_LEVEL:STATIC=ON + +//Value Computed by CMake +radiation_tests_SOURCE_DIR:STATIC=/Users/afoster/Documents/ncar/CTSM/src/fates + + +######################## +# INTERNAL cache entries +######################## + +//ADVANCED property for variable: CMAKE_ADDR2LINE +CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_AR +CMAKE_AR-ADVANCED:INTERNAL=1 +//This is the directory where this CMakeCache.txt was created +CMAKE_CACHEFILE_DIR:INTERNAL=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ +//Major version of cmake used to create the current loaded cache +CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 +//Minor version of cmake used to create the current loaded cache +CMAKE_CACHE_MINOR_VERSION:INTERNAL=25 +//Patch version of cmake used to create the current loaded cache +CMAKE_CACHE_PATCH_VERSION:INTERNAL=2 +//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE +CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1 +//Path to CMake executable. +CMAKE_COMMAND:INTERNAL=/usr/local/Cellar/cmake/3.25.2/bin/cmake +//Path to cpack program executable. +CMAKE_CPACK_COMMAND:INTERNAL=/usr/local/Cellar/cmake/3.25.2/bin/cpack +//Path to ctest program executable. +CMAKE_CTEST_COMMAND:INTERNAL=/usr/local/Cellar/cmake/3.25.2/bin/ctest +//ADVANCED property for variable: CMAKE_C_COMPILER +CMAKE_C_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS +CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_CESM_DEBUG +CMAKE_C_FLAGS_CESM_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG +CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL +CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE +CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO +CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_DLLTOOL +CMAKE_DLLTOOL-ADVANCED:INTERNAL=1 +//Path to cache edit program executable. +CMAKE_EDIT_COMMAND:INTERNAL=/usr/local/Cellar/cmake/3.25.2/bin/ccmake +//Executable file format +CMAKE_EXECUTABLE_FORMAT:INTERNAL=MACHO +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS +CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_CESM_DEBUG +CMAKE_EXE_LINKER_FLAGS_CESM_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG +CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE +CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS +CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1 +//Name of external makefile project generator. +CMAKE_EXTRA_GENERATOR:INTERNAL= +//ADVANCED property for variable: CMAKE_Fortran_COMPILER +CMAKE_Fortran_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_Fortran_COMPILER_AR +CMAKE_Fortran_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_Fortran_COMPILER_RANLIB +CMAKE_Fortran_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_Fortran_FLAGS +CMAKE_Fortran_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_Fortran_FLAGS_CESM_DEBUG +CMAKE_Fortran_FLAGS_CESM_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_Fortran_FLAGS_DEBUG +CMAKE_Fortran_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_Fortran_FLAGS_MINSIZEREL +CMAKE_Fortran_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_Fortran_FLAGS_RELEASE +CMAKE_Fortran_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_Fortran_FLAGS_RELWITHDEBINFO +CMAKE_Fortran_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//Name of generator. +CMAKE_GENERATOR:INTERNAL=Unix Makefiles +//Generator instance identifier. +CMAKE_GENERATOR_INSTANCE:INTERNAL= +//Name of generator platform. +CMAKE_GENERATOR_PLATFORM:INTERNAL= +//Name of generator toolset. +CMAKE_GENERATOR_TOOLSET:INTERNAL= +//Source directory with the top level CMakeLists.txt file for this +// project +CMAKE_HOME_DIRECTORY:INTERNAL=/Users/afoster/Documents/ncar/CTSM/src/fates +//ADVANCED property for variable: CMAKE_INSTALL_NAME_TOOL +CMAKE_INSTALL_NAME_TOOL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_LINKER +CMAKE_LINKER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MAKE_PROGRAM +CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS +CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_CESM_DEBUG +CMAKE_MODULE_LINKER_FLAGS_CESM_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG +CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE +CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_NM +CMAKE_NM-ADVANCED:INTERNAL=1 +//number of local generators +CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=5 +//ADVANCED property for variable: CMAKE_OBJCOPY +CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJDUMP +CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 +//Platform information initialized +CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RANLIB +CMAKE_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_READELF +CMAKE_READELF-ADVANCED:INTERNAL=1 +//Path to CMake installation. +CMAKE_ROOT:INTERNAL=/usr/local/Cellar/cmake/3.25.2/share/cmake +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS +CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_CESM_DEBUG +CMAKE_SHARED_LINKER_FLAGS_CESM_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG +CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE +CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH +CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_RPATH +CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS +CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_CESM_DEBUG +CMAKE_STATIC_LINKER_FLAGS_CESM_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG +CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE +CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STRIP +CMAKE_STRIP-ADVANCED:INTERNAL=1 +//uname command +CMAKE_UNAME:INTERNAL=/usr/bin/uname +//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE +CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 +//Details about finding pFUnit +FIND_PACKAGE_MESSAGE_DETAILS_pFUnit:INTERNAL=[/Users/afoster/pFUnit/lib/libpfunit.a][/Users/afoster/pFUnit/include][/Users/afoster/pFUnit/mod][/Users/afoster/pFUnit/bin/pFUnitParser.py][v()] +//ADVANCED property for variable: PFUNIT_INCLUDE_DIR +PFUNIT_INCLUDE_DIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: PFUNIT_LIBRARY +PFUNIT_LIBRARY-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: PFUNIT_MODULE_DIR +PFUNIT_MODULE_DIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: PFUNIT_PARSER +PFUNIT_PARSER-ADVANCED:INTERNAL=1 + diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CMakeCCompiler.cmake b/build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CMakeCCompiler.cmake new file mode 100644 index 0000000000..b02d92f9f2 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CMakeCCompiler.cmake @@ -0,0 +1,72 @@ +set(CMAKE_C_COMPILER "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc") +set(CMAKE_C_COMPILER_ARG1 "") +set(CMAKE_C_COMPILER_ID "AppleClang") +set(CMAKE_C_COMPILER_VERSION "14.0.0.14000029") +set(CMAKE_C_COMPILER_VERSION_INTERNAL "") +set(CMAKE_C_COMPILER_WRAPPER "") +set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "17") +set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "ON") +set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert;c_std_17;c_std_23") +set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") +set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") +set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") +set(CMAKE_C17_COMPILE_FEATURES "c_std_17") +set(CMAKE_C23_COMPILE_FEATURES "c_std_23") + +set(CMAKE_C_PLATFORM_ID "Darwin") +set(CMAKE_C_SIMULATE_ID "") +set(CMAKE_C_COMPILER_FRONTEND_VARIANT "") +set(CMAKE_C_SIMULATE_VERSION "") + + + + +set(CMAKE_AR "/usr/bin/ar") +set(CMAKE_C_COMPILER_AR "") +set(CMAKE_RANLIB "/usr/bin/ranlib") +set(CMAKE_C_COMPILER_RANLIB "") +set(CMAKE_LINKER "/usr/bin/ld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCC ) +set(CMAKE_C_COMPILER_LOADED 1) +set(CMAKE_C_COMPILER_WORKS TRUE) +set(CMAKE_C_ABI_COMPILED TRUE) + +set(CMAKE_C_COMPILER_ENV_VAR "CC") + +set(CMAKE_C_COMPILER_ID_RUN 1) +set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) +set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_C_LINKER_PREFERENCE 10) + +# Save compiler ABI information. +set(CMAKE_C_SIZEOF_DATA_PTR "8") +set(CMAKE_C_COMPILER_ABI "") +set(CMAKE_C_BYTE_ORDER "LITTLE_ENDIAN") +set(CMAKE_C_LIBRARY_ARCHITECTURE "") + +if(CMAKE_C_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_C_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") +endif() + +if(CMAKE_C_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + +set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/14.0.0/include;/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/usr/include;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include") +set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "") +set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/local/opt/lapack/lib;/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/usr/lib") +set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/System/Library/Frameworks") diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CMakeDetermineCompilerABI_C.bin b/build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CMakeDetermineCompilerABI_C.bin new file mode 100755 index 0000000000000000000000000000000000000000..4656549879429703477a75be0e856ae37b97684a GIT binary patch literal 16688 zcmeI3OKTHR6vuB&TkC_iE3qgTT!?nj)(03$(X@2h8EmJaMi4`}CY`ArNRyIGun{WV zh=d~eQHmRPZd`P!A40)Jgf5GS_&@U?8Ec^*;D6w79{1jJ&;8A8&zE06|D07Sl~zif zfet~l2;Qg+Jf%jVCRFSE%!2XESXq{AQc}tAzme3*Vx!gt<7pweB{-i;=2R5-BP}ZZ ziD>P++kWVWakAdw13U%`tI-yT`?}jD*zFCqUaM6b-Gcx2mwy=6dmbH+7<{dp z)t6q?(Oz}E7R1T^_M>{jR77Ioev)+gFIx5^W6p}%<-)#VPO+VgK8Bdc4N6~EYIpLa zOM3IU@Ow*7m!WyY1F-wByRa9ad8ml&5tVNv->COKgr^eu-!jmP(1~WFK2h^Hacyi6D1cU`LWMTBv%s2J)^Vw85zr-U!H1suiV3>$E_C^twLeZ(1tx{&Df|UGtO6o zN=YlT%QD-14_4I1T)Bw&G7~M+(IdfW$#xx;((0TXR%yMtq1|nFt%=Jw+!AhA{W8U_ zd!D22Z*aMlv6*V@@0E z;ag;V911ILAQ?>9AMZ1mwomk_gFa=DTsQn?S(h=Bj|YVtyL^#|1S~H%~${c literal 0 HcmV?d00001 diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CMakeDetermineCompilerABI_Fortran.bin b/build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CMakeDetermineCompilerABI_Fortran.bin new file mode 100755 index 0000000000000000000000000000000000000000..332e100ff099bddf2017b5dc5af95bddaa46c149 GIT binary patch literal 33512 zcmeI5U2GIp6vyw-Z7JH8Me*B&eXs^K?6&121q8OAOrtFgv`Lkio9XVf-MC-Q%!bl{ zEY=z~Si_5n&-!Tmi1C3C1rnl_7d1Q>9*vQt321mQhE!xd=gtf}JCzut4?g@4oVoYh zd(WA3fA?^(upP^7DS9{LOepMlS(<-vwz^lfrAIQwO+J( z^DixqbA<*b$#R|#de)UL^)_n zX*;D!`%Y6h-sgMWcu#mEeA{=J%}U#C9YYAXJyqoRL$Oku%+naJ-@y?@iB-?O=YPaB6?NON~+@p%{u*#U@3&fB+~P?&l$YP` zmBGBYNyjHzA6$FCi`rtO8mVY#C2di4 z&PgPDt9L&t)k(~a5mFZ18q%8xxmIIFnH@T6J7zB4 z8}xge<{hKV*gu&q7-`dzJTo$ta6kWj=6;udA!TF}{-o7%Os7(b+3p>3$F?m-v6wZt zqz&sxCg0VW=r1=%iS$mGXt~KfNJSuhI_BndfEI!nT=m_5qwXA8vf=z$7+$z(rHdgp;f)QqTW-i_40eh$vl1O zqM|*2Jz6<_ORtn}=%>bSoEo6&_cSD?JQ_dbqVm;wI-)L?@8ib{H19K15tlAj+xOB` zs_jYj>{ZWx^&C`Bot}X+k$q-1Ygma?&Uo2OY>jtqk9Q^P8N)KYrr|=mlr`-{-!Kgr zbPtX86>`N)*0g$hhvI`f>7?Y)$l!rpc4p2jOv!Z7u?}~?M18S-(=k&{rjYNa!;aPU zoS%EPl~Pc$$tyQ{r8aj^XtPl*+OoF!G!3HjynF^zyh=;RlJ^}WTxpBGu_nStV_Tad z8EPOWGFaGejPx_Y!jh!Al2v}Ysk!Fojq-|U*?nEKOgo<>T2|+9sf>6wpARM}t0x{H z00JNY0w4eaAOHd&00JNY0w4eaAOHd&00JNY0w4eaAOHd&00JNY0w4eaAOHd&00JNY z0w4eaAOHd&00JNY0w4eaAOHd&00JNY0w4eaAOHd&00JNY0w4ea|2cseMdWWk&ye!< z5&qQ!R8`*v=aPlLvF(ehM`?7@Z}ILspbG>v`gpfCL0TsLl=Md$LmzneKEy3;(~*WX zZHLe7QXGB+d5Su<5~OgUrnm$pS?&dB6NdxN;e_gk>MJ@<>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_C) +# define COMPILER_ID "SunPro" +# if __SUNPRO_C >= 0x5100 + /* __SUNPRO_C = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# endif + +#elif defined(__HP_cc) +# define COMPILER_ID "HP" + /* __HP_cc = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) + +#elif defined(__DECC) +# define COMPILER_ID "Compaq" + /* __DECC_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) + +#elif defined(__IBMC__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__open_xl__) && defined(__clang__) +# define COMPILER_ID "IBMClang" +# define COMPILER_VERSION_MAJOR DEC(__open_xl_version__) +# define COMPILER_VERSION_MINOR DEC(__open_xl_release__) +# define COMPILER_VERSION_PATCH DEC(__open_xl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__open_xl_ptf_fix_level__) + + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 +# define COMPILER_ID "XL" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TASKING__) +# define COMPILER_ID "Tasking" + # define COMPILER_VERSION_MAJOR DEC(__VERSION__/1000) + # define COMPILER_VERSION_MINOR DEC(__VERSION__ % 100) +# define COMPILER_VERSION_INTERNAL DEC(__VERSION__) + +#elif defined(__TINYC__) +# define COMPILER_ID "TinyCC" + +#elif defined(__BCC__) +# define COMPILER_ID "Bruce" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__LCC__) && (defined(__GNUC__) || defined(__GNUG__) || defined(__MCST__)) +# define COMPILER_ID "LCC" +# define COMPILER_VERSION_MAJOR DEC(1) +# if defined(__LCC__) +# define COMPILER_VERSION_MINOR DEC(__LCC__- 100) +# endif +# if defined(__LCC_MINOR__) +# define COMPILER_VERSION_PATCH DEC(__LCC_MINOR__) +# endif +# if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define SIMULATE_ID "GNU" +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif +# endif + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(_ADI_COMPILER) +# define COMPILER_ID "ADSP" +#if defined(__VERSIONNUM__) + /* __VERSIONNUM__ = 0xVVRRPPTT */ +# define COMPILER_VERSION_MAJOR DEC(__VERSIONNUM__ >> 24 & 0xFF) +# define COMPILER_VERSION_MINOR DEC(__VERSIONNUM__ >> 16 & 0xFF) +# define COMPILER_VERSION_PATCH DEC(__VERSIONNUM__ >> 8 & 0xFF) +# define COMPILER_VERSION_TWEAK DEC(__VERSIONNUM__ & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + +#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC) +# define COMPILER_ID "SDCC" +# if defined(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR) +# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH) +# else + /* SDCC = VRP */ +# define COMPILER_VERSION_MAJOR DEC(SDCC/100) +# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) +# define COMPILER_VERSION_PATCH DEC(SDCC % 10) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +# elif defined(_ADI_COMPILER) +# define PLATFORM_ID "ADSP" + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +# elif defined(__ADSPSHARC__) +# define ARCHITECTURE_ID "SHARC" + +# elif defined(__ADSPBLACKFIN__) +# define ARCHITECTURE_ID "Blackfin" + +#elif defined(__TASKING__) + +# if defined(__CTC__) || defined(__CPTC__) +# define ARCHITECTURE_ID "TriCore" + +# elif defined(__CMCS__) +# define ARCHITECTURE_ID "MCS" + +# elif defined(__CARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__CARC__) +# define ARCHITECTURE_ID "ARC" + +# elif defined(__C51__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__CPCP__) +# define ARCHITECTURE_ID "PCP" + +# else +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if !defined(__STDC__) && !defined(__clang__) +# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__) +# define C_VERSION "90" +# else +# define C_VERSION +# endif +#elif __STDC_VERSION__ > 201710L +# define C_VERSION "23" +#elif __STDC_VERSION__ >= 201710L +# define C_VERSION "17" +#elif __STDC_VERSION__ >= 201000L +# define C_VERSION "11" +#elif __STDC_VERSION__ >= 199901L +# define C_VERSION "99" +#else +# define C_VERSION "90" +#endif +const char* info_language_standard_default = + "INFO" ":" "standard_default[" C_VERSION "]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +#if (defined(__clang__) || defined(__GNUC__) || defined(__xlC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +#ifdef ID_VOID_MAIN +void main() {} +#else +# if defined(__CLASSIC_C__) +int main(argc, argv) int argc; char *argv[]; +# else +int main(int argc, char* argv[]) +# endif +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} +#endif diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CompilerIdFortran/CMakeFortranCompilerId.F b/build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CompilerIdFortran/CMakeFortranCompilerId.F new file mode 100644 index 0000000000..4e88c9ae60 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CompilerIdFortran/CMakeFortranCompilerId.F @@ -0,0 +1,1114 @@ + PROGRAM CMakeFortranCompilerId +#if 0 +! Identify the compiler +#endif +#if defined(_MSC_VER) + PRINT *, 'INFO:simulate[MSVC]' +# if _MSC_VER >= 1900 + PRINT *, 'INFO:simulate_version[019.00]' +# elif _MSC_VER >= 1800 + PRINT *, 'INFO:simulate_version[018.00]' +# elif _MSC_VER >= 1700 + PRINT *, 'INFO:simulate_version[017.00]' +# elif _MSC_VER >= 1600 + PRINT *, 'INFO:simulate_version[016.00]' +# elif _MSC_VER >= 1500 + PRINT *, 'INFO:simulate_version[015.00]' +# elif _MSC_VER >= 1400 + PRINT *, 'INFO:simulate_version[014.00]' +# elif _MSC_VER >= 1310 + PRINT *, 'INFO:simulate_version[013.01]' +# else + PRINT *, 'INFO:simulate_version[013.00]' +# endif +#endif +#if defined(__INTEL_LLVM_COMPILER) + PRINT *, 'INFO:compiler[IntelLLVM]' +! __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and +! later. Look for 6 digit vs. 8 digit version number to decide encoding. +! VVVV is no smaller than the current year when a version is released. +# if __INTEL_LLVM_COMPILER < 1000000 +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) +# else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) +# endif +#elif defined(__INTEL_COMPILER) && __INTEL_COMPILER == 201900 + PRINT *, 'INFO:compiler[IntelLLVM]' +! ifx 2021.1 forgot to define __INTEL_LLVM_COMPILER. +! Instead it defines __INTEL_COMPILER == 201900. +# define COMPILER_VERSION_MAJOR DEC(2021) +# define COMPILER_VERSION_MINOR DEC(1) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +#elif defined(__INTEL_COMPILER) || defined(__ICC) + PRINT *, 'INFO:compiler[Intel]' +! __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later. +# if __INTEL_COMPILER < 2021 +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) +! The third version component from --version is an update index, +! but no macro is provided for it. +# define COMPILER_VERSION_PATCH DEC(0) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +#elif defined(__SUNPRO_F95) + PRINT *, 'INFO:compiler[SunPro]' +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_F95>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_F95>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_F95 & 0xF) +#elif defined(__SUNPRO_F90) + PRINT *, 'INFO:compiler[SunPro]' +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_F90>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_F90>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_F90 & 0xF) +#elif defined(_CRAYFTN) + PRINT *, 'INFO:compiler[Cray]' +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) +# if defined(_RELEASE_PATCHLEVEL) +# define COMPILER_VERSION_PATCH DEC(_RELEASE_PATCHLEVEL) +# endif +#elif defined(__G95__) + PRINT *, 'INFO:compiler[G95]' +# define COMPILER_VERSION_MAJOR DEC(__G95__) +# define COMPILER_VERSION_MINOR DEC(__G95_MINOR__) +#elif defined(__PATHSCALE__) + PRINT *, 'INFO:compiler[PathScale]' +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif +#elif defined(__ABSOFT__) + PRINT *, 'INFO:compiler[Absoft]' +#elif defined(__LCC__) && (defined(__GNUC__) || defined(__GNUG__) || defined(__MCST__)) + PRINT *, 'INFO:compiler[LCC]' +# define COMPILER_VERSION_MAJOR DEC(1) +# define COMPILER_VERSION_MINOR DEC(__LCC__ - 100) +# if defined(__LCC_MINOR__) +# define COMPILER_VERSION_PATCH DEC(__LCC_MINOR__) +# endif +#elif defined(__GNUC__) + PRINT *, 'INFO:compiler[GNU]' +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif +#elif defined(__IBMC__) +# if defined(__COMPILER_VER__) + PRINT *, 'INFO:compiler[zOS]' +# elif __IBMC__ >= 800 + PRINT *, 'INFO:compiler[XL]' +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) +# else + PRINT *, 'INFO:compiler[VisualAge]' +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) +# endif +#elif defined(__NVCOMPILER) || defined(__NVCOMPILER_LLVM__) + PRINT *, 'INFO:compiler[NVHPC]' +# if defined(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# else +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# endif +# if defined(__NVCOMPILER_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# else +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# endif +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# elif defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif +#elif defined(__PGI) + PRINT *, 'INFO:compiler[PGI]' +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif +#elif defined(__FLANG) + PRINT *, 'INFO:compiler[Flang]' +# define COMPILER_VERSION_MAJOR DEC(__FLANG_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__FLANG_MINOR__) +# if defined(__FLANG_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__FLANG_PATCHLEVEL__) +# endif +#elif defined(__flang__) + PRINT *, 'INFO:compiler[LLVMFlang]' +# define COMPILER_VERSION_MAJOR DEC(__flang_major__) +# define COMPILER_VERSION_MINOR DEC(__flang_minor__) +# if defined(__flang_patchlevel__) +# define COMPILER_VERSION_PATCH DEC(__flang_patchlevel__) +# endif +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) + PRINT *, 'INFO:compiler[VisualAge]' +#elif defined(__hpux) || defined(__hpux__) + PRINT *, 'INFO:compiler[HP]' +#elif defined(NAGFOR) + PRINT *, 'INFO:compiler[NAG]' +#define COMPILER_VERSION_MAJOR DEC(__NAG_COMPILER_RELEASE/10) +#define COMPILER_VERSION_MINOR DEC(__NAG_COMPILER_RELEASE % 10) +#define COMPILER_VERSION_PATCH DEC(__NAG_COMPILER_BUILD) +#elif defined(__FUJITSU) + PRINT *, 'INFO:compiler[Fujitsu]' +# if defined(__FRT_major__) +# define COMPILER_VERSION_MAJOR DEC(__FRT_major__) +# define COMPILER_VERSION_MINOR DEC(__FRT_minor__) +# define COMPILER_VERSION_PATCH DEC(__FRT_patchlevel__) +# elif defined(__FRT_version__) + PRINT *, 'INFO:compiler_version['//__FRT_version__//']' +# endif +#else + PRINT *, 'INFO:compiler[]' +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + PRINT *, 'INFO:compiler_wrapper[CrayPrgEnv]' +#endif + +#if 0 +! Identify the platform +#endif +#if defined(__linux) || defined(__linux__) || defined(linux) + PRINT *, 'INFO:platform[Linux]' +#elif defined(__CYGWIN__) + PRINT *, 'INFO:platform[Cygwin]' +#elif defined(__MINGW32__) + PRINT *, 'INFO:platform[MinGW]' +#elif defined(__APPLE__) + PRINT *, 'INFO:platform[Darwin]' +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) + PRINT *, 'INFO:platform[Windows]' +#elif defined(__FreeBSD__) || defined(__FreeBSD) + PRINT *, 'INFO:platform[FreeBSD]' +#elif defined(__NetBSD__) || defined(__NetBSD) + PRINT *, 'INFO:platform[NetBSD]' +#elif defined(__OpenBSD__) || defined(__OPENBSD) + PRINT *, 'INFO:platform[OpenBSD]' +#elif defined(__sun) || defined(sun) + PRINT *, 'INFO:platform[SunOS]' +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) + PRINT *, 'INFO:platform[AIX]' +#elif defined(__hpux) || defined(__hpux__) + PRINT *, 'INFO:platform[HP-UX]' +#elif defined(__HAIKU__) + PRINT *, 'INFO:platform[Haiku]' +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) + PRINT *, 'INFO:platform[BeOS]' +#elif defined(__QNX__) || defined(__QNXNTO__) + PRINT *, 'INFO:platform[QNX]' +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) + PRINT *, 'INFO:platform[Tru64]' +#elif defined(__riscos) || defined(__riscos__) + PRINT *, 'INFO:platform[RISCos]' +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) + PRINT *, 'INFO:platform[SINIX]' +#elif defined(__UNIX_SV__) + PRINT *, 'INFO:platform[UNIX_SV]' +#elif defined(__bsdos__) + PRINT *, 'INFO:platform[BSDOS]' +#elif defined(_MPRAS) || defined(MPRAS) + PRINT *, 'INFO:platform[MP-RAS]' +#elif defined(__osf) || defined(__osf__) + PRINT *, 'INFO:platform[OSF1]' +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) + PRINT *, 'INFO:platform[SCO_SV]' +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) + PRINT *, 'INFO:platform[ULTRIX]' +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) + PRINT *, 'INFO:platform[Xenix]' +#else + PRINT *, 'INFO:platform[]' +#endif +#if defined(_WIN32) && (defined(__INTEL_COMPILER) || defined(__ICC)) +# if defined(_M_IA64) + PRINT *, 'INFO:arch[IA64]' +# elif defined(_M_X64) || defined(_M_AMD64) + PRINT *, 'INFO:arch[x64]' +# elif defined(_M_IX86) + PRINT *, 'INFO:arch[X86]' +# endif +#endif + +#if 0 +! Encode compiler version digits +#endif +#define DEC_8(n) (((n) / 10000000) % 10) +#define DEC_7(n) (((n) / 1000000) % 10) +#define DEC_6(n) (((n) / 100000) % 10) +#define DEC_5(n) (((n) / 10000) % 10) +#define DEC_4(n) (((n) / 1000) % 10) +#define DEC_3(n) (((n) / 100) % 10) +#define DEC_2(n) (((n) / 10) % 10) +#define DEC_1(n) (((n) ) % 10) +#define HEX_8(n) ((n)>>28 & 0xF) +#define HEX_7(n) ((n)>>24 & 0xF) +#define HEX_6(n) ((n)>>20 & 0xF) +#define HEX_5(n) ((n)>>16 & 0xF) +#define HEX_4(n) ((n)>>12 & 0xF) +#define HEX_3(n) ((n)>>8 & 0xF) +#define HEX_2(n) ((n)>>4 & 0xF) +#define HEX_1(n) ((n) & 0xF) + +#if defined(COMPILER_VERSION_MAJOR) +# undef DEC +# undef HEX +# define DEC(n) DEC_1(n) +# define HEX(n) HEX_1(n) +# if COMPILER_VERSION_MAJOR == 0 + PRINT *, 'INFO:compiler_version_MAJOR_digit_1[0]' +# elif COMPILER_VERSION_MAJOR == 1 + PRINT *, 'INFO:compiler_version_MAJOR_digit_1[1]' +# elif COMPILER_VERSION_MAJOR == 2 + PRINT *, 'INFO:compiler_version_MAJOR_digit_1[2]' +# elif COMPILER_VERSION_MAJOR == 3 + PRINT *, 'INFO:compiler_version_MAJOR_digit_1[3]' +# elif COMPILER_VERSION_MAJOR == 4 + PRINT *, 'INFO:compiler_version_MAJOR_digit_1[4]' +# elif COMPILER_VERSION_MAJOR == 5 + PRINT *, 'INFO:compiler_version_MAJOR_digit_1[5]' +# elif COMPILER_VERSION_MAJOR == 6 + PRINT *, 'INFO:compiler_version_MAJOR_digit_1[6]' +# elif COMPILER_VERSION_MAJOR == 7 + PRINT *, 'INFO:compiler_version_MAJOR_digit_1[7]' +# elif COMPILER_VERSION_MAJOR == 8 + PRINT *, 'INFO:compiler_version_MAJOR_digit_1[8]' +# elif COMPILER_VERSION_MAJOR == 9 + PRINT *, 'INFO:compiler_version_MAJOR_digit_1[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_2(n) +# define HEX(n) HEX_2(n) +# if COMPILER_VERSION_MAJOR == 0 + PRINT *, 'INFO:compiler_version_MAJOR_digit_2[0]' +# elif COMPILER_VERSION_MAJOR == 1 + PRINT *, 'INFO:compiler_version_MAJOR_digit_2[1]' +# elif COMPILER_VERSION_MAJOR == 2 + PRINT *, 'INFO:compiler_version_MAJOR_digit_2[2]' +# elif COMPILER_VERSION_MAJOR == 3 + PRINT *, 'INFO:compiler_version_MAJOR_digit_2[3]' +# elif COMPILER_VERSION_MAJOR == 4 + PRINT *, 'INFO:compiler_version_MAJOR_digit_2[4]' +# elif COMPILER_VERSION_MAJOR == 5 + PRINT *, 'INFO:compiler_version_MAJOR_digit_2[5]' +# elif COMPILER_VERSION_MAJOR == 6 + PRINT *, 'INFO:compiler_version_MAJOR_digit_2[6]' +# elif COMPILER_VERSION_MAJOR == 7 + PRINT *, 'INFO:compiler_version_MAJOR_digit_2[7]' +# elif COMPILER_VERSION_MAJOR == 8 + PRINT *, 'INFO:compiler_version_MAJOR_digit_2[8]' +# elif COMPILER_VERSION_MAJOR == 9 + PRINT *, 'INFO:compiler_version_MAJOR_digit_2[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_3(n) +# define HEX(n) HEX_3(n) +# if COMPILER_VERSION_MAJOR == 0 + PRINT *, 'INFO:compiler_version_MAJOR_digit_3[0]' +# elif COMPILER_VERSION_MAJOR == 1 + PRINT *, 'INFO:compiler_version_MAJOR_digit_3[1]' +# elif COMPILER_VERSION_MAJOR == 2 + PRINT *, 'INFO:compiler_version_MAJOR_digit_3[2]' +# elif COMPILER_VERSION_MAJOR == 3 + PRINT *, 'INFO:compiler_version_MAJOR_digit_3[3]' +# elif COMPILER_VERSION_MAJOR == 4 + PRINT *, 'INFO:compiler_version_MAJOR_digit_3[4]' +# elif COMPILER_VERSION_MAJOR == 5 + PRINT *, 'INFO:compiler_version_MAJOR_digit_3[5]' +# elif COMPILER_VERSION_MAJOR == 6 + PRINT *, 'INFO:compiler_version_MAJOR_digit_3[6]' +# elif COMPILER_VERSION_MAJOR == 7 + PRINT *, 'INFO:compiler_version_MAJOR_digit_3[7]' +# elif COMPILER_VERSION_MAJOR == 8 + PRINT *, 'INFO:compiler_version_MAJOR_digit_3[8]' +# elif COMPILER_VERSION_MAJOR == 9 + PRINT *, 'INFO:compiler_version_MAJOR_digit_3[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_4(n) +# define HEX(n) HEX_4(n) +# if COMPILER_VERSION_MAJOR == 0 + PRINT *, 'INFO:compiler_version_MAJOR_digit_4[0]' +# elif COMPILER_VERSION_MAJOR == 1 + PRINT *, 'INFO:compiler_version_MAJOR_digit_4[1]' +# elif COMPILER_VERSION_MAJOR == 2 + PRINT *, 'INFO:compiler_version_MAJOR_digit_4[2]' +# elif COMPILER_VERSION_MAJOR == 3 + PRINT *, 'INFO:compiler_version_MAJOR_digit_4[3]' +# elif COMPILER_VERSION_MAJOR == 4 + PRINT *, 'INFO:compiler_version_MAJOR_digit_4[4]' +# elif COMPILER_VERSION_MAJOR == 5 + PRINT *, 'INFO:compiler_version_MAJOR_digit_4[5]' +# elif COMPILER_VERSION_MAJOR == 6 + PRINT *, 'INFO:compiler_version_MAJOR_digit_4[6]' +# elif COMPILER_VERSION_MAJOR == 7 + PRINT *, 'INFO:compiler_version_MAJOR_digit_4[7]' +# elif COMPILER_VERSION_MAJOR == 8 + PRINT *, 'INFO:compiler_version_MAJOR_digit_4[8]' +# elif COMPILER_VERSION_MAJOR == 9 + PRINT *, 'INFO:compiler_version_MAJOR_digit_4[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_5(n) +# define HEX(n) HEX_5(n) +# if COMPILER_VERSION_MAJOR == 0 + PRINT *, 'INFO:compiler_version_MAJOR_digit_5[0]' +# elif COMPILER_VERSION_MAJOR == 1 + PRINT *, 'INFO:compiler_version_MAJOR_digit_5[1]' +# elif COMPILER_VERSION_MAJOR == 2 + PRINT *, 'INFO:compiler_version_MAJOR_digit_5[2]' +# elif COMPILER_VERSION_MAJOR == 3 + PRINT *, 'INFO:compiler_version_MAJOR_digit_5[3]' +# elif COMPILER_VERSION_MAJOR == 4 + PRINT *, 'INFO:compiler_version_MAJOR_digit_5[4]' +# elif COMPILER_VERSION_MAJOR == 5 + PRINT *, 'INFO:compiler_version_MAJOR_digit_5[5]' +# elif COMPILER_VERSION_MAJOR == 6 + PRINT *, 'INFO:compiler_version_MAJOR_digit_5[6]' +# elif COMPILER_VERSION_MAJOR == 7 + PRINT *, 'INFO:compiler_version_MAJOR_digit_5[7]' +# elif COMPILER_VERSION_MAJOR == 8 + PRINT *, 'INFO:compiler_version_MAJOR_digit_5[8]' +# elif COMPILER_VERSION_MAJOR == 9 + PRINT *, 'INFO:compiler_version_MAJOR_digit_5[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_6(n) +# define HEX(n) HEX_6(n) +# if COMPILER_VERSION_MAJOR == 0 + PRINT *, 'INFO:compiler_version_MAJOR_digit_6[0]' +# elif COMPILER_VERSION_MAJOR == 1 + PRINT *, 'INFO:compiler_version_MAJOR_digit_6[1]' +# elif COMPILER_VERSION_MAJOR == 2 + PRINT *, 'INFO:compiler_version_MAJOR_digit_6[2]' +# elif COMPILER_VERSION_MAJOR == 3 + PRINT *, 'INFO:compiler_version_MAJOR_digit_6[3]' +# elif COMPILER_VERSION_MAJOR == 4 + PRINT *, 'INFO:compiler_version_MAJOR_digit_6[4]' +# elif COMPILER_VERSION_MAJOR == 5 + PRINT *, 'INFO:compiler_version_MAJOR_digit_6[5]' +# elif COMPILER_VERSION_MAJOR == 6 + PRINT *, 'INFO:compiler_version_MAJOR_digit_6[6]' +# elif COMPILER_VERSION_MAJOR == 7 + PRINT *, 'INFO:compiler_version_MAJOR_digit_6[7]' +# elif COMPILER_VERSION_MAJOR == 8 + PRINT *, 'INFO:compiler_version_MAJOR_digit_6[8]' +# elif COMPILER_VERSION_MAJOR == 9 + PRINT *, 'INFO:compiler_version_MAJOR_digit_6[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_7(n) +# define HEX(n) HEX_7(n) +# if COMPILER_VERSION_MAJOR == 0 + PRINT *, 'INFO:compiler_version_MAJOR_digit_7[0]' +# elif COMPILER_VERSION_MAJOR == 1 + PRINT *, 'INFO:compiler_version_MAJOR_digit_7[1]' +# elif COMPILER_VERSION_MAJOR == 2 + PRINT *, 'INFO:compiler_version_MAJOR_digit_7[2]' +# elif COMPILER_VERSION_MAJOR == 3 + PRINT *, 'INFO:compiler_version_MAJOR_digit_7[3]' +# elif COMPILER_VERSION_MAJOR == 4 + PRINT *, 'INFO:compiler_version_MAJOR_digit_7[4]' +# elif COMPILER_VERSION_MAJOR == 5 + PRINT *, 'INFO:compiler_version_MAJOR_digit_7[5]' +# elif COMPILER_VERSION_MAJOR == 6 + PRINT *, 'INFO:compiler_version_MAJOR_digit_7[6]' +# elif COMPILER_VERSION_MAJOR == 7 + PRINT *, 'INFO:compiler_version_MAJOR_digit_7[7]' +# elif COMPILER_VERSION_MAJOR == 8 + PRINT *, 'INFO:compiler_version_MAJOR_digit_7[8]' +# elif COMPILER_VERSION_MAJOR == 9 + PRINT *, 'INFO:compiler_version_MAJOR_digit_7[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_8(n) +# define HEX(n) HEX_8(n) +# if COMPILER_VERSION_MAJOR == 0 + PRINT *, 'INFO:compiler_version_MAJOR_digit_8[0]' +# elif COMPILER_VERSION_MAJOR == 1 + PRINT *, 'INFO:compiler_version_MAJOR_digit_8[1]' +# elif COMPILER_VERSION_MAJOR == 2 + PRINT *, 'INFO:compiler_version_MAJOR_digit_8[2]' +# elif COMPILER_VERSION_MAJOR == 3 + PRINT *, 'INFO:compiler_version_MAJOR_digit_8[3]' +# elif COMPILER_VERSION_MAJOR == 4 + PRINT *, 'INFO:compiler_version_MAJOR_digit_8[4]' +# elif COMPILER_VERSION_MAJOR == 5 + PRINT *, 'INFO:compiler_version_MAJOR_digit_8[5]' +# elif COMPILER_VERSION_MAJOR == 6 + PRINT *, 'INFO:compiler_version_MAJOR_digit_8[6]' +# elif COMPILER_VERSION_MAJOR == 7 + PRINT *, 'INFO:compiler_version_MAJOR_digit_8[7]' +# elif COMPILER_VERSION_MAJOR == 8 + PRINT *, 'INFO:compiler_version_MAJOR_digit_8[8]' +# elif COMPILER_VERSION_MAJOR == 9 + PRINT *, 'INFO:compiler_version_MAJOR_digit_8[9]' +# endif + +#endif +#if defined(COMPILER_VERSION_MINOR) +# undef DEC +# undef HEX +# define DEC(n) DEC_1(n) +# define HEX(n) HEX_1(n) +# if COMPILER_VERSION_MINOR == 0 + PRINT *, 'INFO:compiler_version_MINOR_digit_1[0]' +# elif COMPILER_VERSION_MINOR == 1 + PRINT *, 'INFO:compiler_version_MINOR_digit_1[1]' +# elif COMPILER_VERSION_MINOR == 2 + PRINT *, 'INFO:compiler_version_MINOR_digit_1[2]' +# elif COMPILER_VERSION_MINOR == 3 + PRINT *, 'INFO:compiler_version_MINOR_digit_1[3]' +# elif COMPILER_VERSION_MINOR == 4 + PRINT *, 'INFO:compiler_version_MINOR_digit_1[4]' +# elif COMPILER_VERSION_MINOR == 5 + PRINT *, 'INFO:compiler_version_MINOR_digit_1[5]' +# elif COMPILER_VERSION_MINOR == 6 + PRINT *, 'INFO:compiler_version_MINOR_digit_1[6]' +# elif COMPILER_VERSION_MINOR == 7 + PRINT *, 'INFO:compiler_version_MINOR_digit_1[7]' +# elif COMPILER_VERSION_MINOR == 8 + PRINT *, 'INFO:compiler_version_MINOR_digit_1[8]' +# elif COMPILER_VERSION_MINOR == 9 + PRINT *, 'INFO:compiler_version_MINOR_digit_1[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_2(n) +# define HEX(n) HEX_2(n) +# if COMPILER_VERSION_MINOR == 0 + PRINT *, 'INFO:compiler_version_MINOR_digit_2[0]' +# elif COMPILER_VERSION_MINOR == 1 + PRINT *, 'INFO:compiler_version_MINOR_digit_2[1]' +# elif COMPILER_VERSION_MINOR == 2 + PRINT *, 'INFO:compiler_version_MINOR_digit_2[2]' +# elif COMPILER_VERSION_MINOR == 3 + PRINT *, 'INFO:compiler_version_MINOR_digit_2[3]' +# elif COMPILER_VERSION_MINOR == 4 + PRINT *, 'INFO:compiler_version_MINOR_digit_2[4]' +# elif COMPILER_VERSION_MINOR == 5 + PRINT *, 'INFO:compiler_version_MINOR_digit_2[5]' +# elif COMPILER_VERSION_MINOR == 6 + PRINT *, 'INFO:compiler_version_MINOR_digit_2[6]' +# elif COMPILER_VERSION_MINOR == 7 + PRINT *, 'INFO:compiler_version_MINOR_digit_2[7]' +# elif COMPILER_VERSION_MINOR == 8 + PRINT *, 'INFO:compiler_version_MINOR_digit_2[8]' +# elif COMPILER_VERSION_MINOR == 9 + PRINT *, 'INFO:compiler_version_MINOR_digit_2[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_3(n) +# define HEX(n) HEX_3(n) +# if COMPILER_VERSION_MINOR == 0 + PRINT *, 'INFO:compiler_version_MINOR_digit_3[0]' +# elif COMPILER_VERSION_MINOR == 1 + PRINT *, 'INFO:compiler_version_MINOR_digit_3[1]' +# elif COMPILER_VERSION_MINOR == 2 + PRINT *, 'INFO:compiler_version_MINOR_digit_3[2]' +# elif COMPILER_VERSION_MINOR == 3 + PRINT *, 'INFO:compiler_version_MINOR_digit_3[3]' +# elif COMPILER_VERSION_MINOR == 4 + PRINT *, 'INFO:compiler_version_MINOR_digit_3[4]' +# elif COMPILER_VERSION_MINOR == 5 + PRINT *, 'INFO:compiler_version_MINOR_digit_3[5]' +# elif COMPILER_VERSION_MINOR == 6 + PRINT *, 'INFO:compiler_version_MINOR_digit_3[6]' +# elif COMPILER_VERSION_MINOR == 7 + PRINT *, 'INFO:compiler_version_MINOR_digit_3[7]' +# elif COMPILER_VERSION_MINOR == 8 + PRINT *, 'INFO:compiler_version_MINOR_digit_3[8]' +# elif COMPILER_VERSION_MINOR == 9 + PRINT *, 'INFO:compiler_version_MINOR_digit_3[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_4(n) +# define HEX(n) HEX_4(n) +# if COMPILER_VERSION_MINOR == 0 + PRINT *, 'INFO:compiler_version_MINOR_digit_4[0]' +# elif COMPILER_VERSION_MINOR == 1 + PRINT *, 'INFO:compiler_version_MINOR_digit_4[1]' +# elif COMPILER_VERSION_MINOR == 2 + PRINT *, 'INFO:compiler_version_MINOR_digit_4[2]' +# elif COMPILER_VERSION_MINOR == 3 + PRINT *, 'INFO:compiler_version_MINOR_digit_4[3]' +# elif COMPILER_VERSION_MINOR == 4 + PRINT *, 'INFO:compiler_version_MINOR_digit_4[4]' +# elif COMPILER_VERSION_MINOR == 5 + PRINT *, 'INFO:compiler_version_MINOR_digit_4[5]' +# elif COMPILER_VERSION_MINOR == 6 + PRINT *, 'INFO:compiler_version_MINOR_digit_4[6]' +# elif COMPILER_VERSION_MINOR == 7 + PRINT *, 'INFO:compiler_version_MINOR_digit_4[7]' +# elif COMPILER_VERSION_MINOR == 8 + PRINT *, 'INFO:compiler_version_MINOR_digit_4[8]' +# elif COMPILER_VERSION_MINOR == 9 + PRINT *, 'INFO:compiler_version_MINOR_digit_4[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_5(n) +# define HEX(n) HEX_5(n) +# if COMPILER_VERSION_MINOR == 0 + PRINT *, 'INFO:compiler_version_MINOR_digit_5[0]' +# elif COMPILER_VERSION_MINOR == 1 + PRINT *, 'INFO:compiler_version_MINOR_digit_5[1]' +# elif COMPILER_VERSION_MINOR == 2 + PRINT *, 'INFO:compiler_version_MINOR_digit_5[2]' +# elif COMPILER_VERSION_MINOR == 3 + PRINT *, 'INFO:compiler_version_MINOR_digit_5[3]' +# elif COMPILER_VERSION_MINOR == 4 + PRINT *, 'INFO:compiler_version_MINOR_digit_5[4]' +# elif COMPILER_VERSION_MINOR == 5 + PRINT *, 'INFO:compiler_version_MINOR_digit_5[5]' +# elif COMPILER_VERSION_MINOR == 6 + PRINT *, 'INFO:compiler_version_MINOR_digit_5[6]' +# elif COMPILER_VERSION_MINOR == 7 + PRINT *, 'INFO:compiler_version_MINOR_digit_5[7]' +# elif COMPILER_VERSION_MINOR == 8 + PRINT *, 'INFO:compiler_version_MINOR_digit_5[8]' +# elif COMPILER_VERSION_MINOR == 9 + PRINT *, 'INFO:compiler_version_MINOR_digit_5[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_6(n) +# define HEX(n) HEX_6(n) +# if COMPILER_VERSION_MINOR == 0 + PRINT *, 'INFO:compiler_version_MINOR_digit_6[0]' +# elif COMPILER_VERSION_MINOR == 1 + PRINT *, 'INFO:compiler_version_MINOR_digit_6[1]' +# elif COMPILER_VERSION_MINOR == 2 + PRINT *, 'INFO:compiler_version_MINOR_digit_6[2]' +# elif COMPILER_VERSION_MINOR == 3 + PRINT *, 'INFO:compiler_version_MINOR_digit_6[3]' +# elif COMPILER_VERSION_MINOR == 4 + PRINT *, 'INFO:compiler_version_MINOR_digit_6[4]' +# elif COMPILER_VERSION_MINOR == 5 + PRINT *, 'INFO:compiler_version_MINOR_digit_6[5]' +# elif COMPILER_VERSION_MINOR == 6 + PRINT *, 'INFO:compiler_version_MINOR_digit_6[6]' +# elif COMPILER_VERSION_MINOR == 7 + PRINT *, 'INFO:compiler_version_MINOR_digit_6[7]' +# elif COMPILER_VERSION_MINOR == 8 + PRINT *, 'INFO:compiler_version_MINOR_digit_6[8]' +# elif COMPILER_VERSION_MINOR == 9 + PRINT *, 'INFO:compiler_version_MINOR_digit_6[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_7(n) +# define HEX(n) HEX_7(n) +# if COMPILER_VERSION_MINOR == 0 + PRINT *, 'INFO:compiler_version_MINOR_digit_7[0]' +# elif COMPILER_VERSION_MINOR == 1 + PRINT *, 'INFO:compiler_version_MINOR_digit_7[1]' +# elif COMPILER_VERSION_MINOR == 2 + PRINT *, 'INFO:compiler_version_MINOR_digit_7[2]' +# elif COMPILER_VERSION_MINOR == 3 + PRINT *, 'INFO:compiler_version_MINOR_digit_7[3]' +# elif COMPILER_VERSION_MINOR == 4 + PRINT *, 'INFO:compiler_version_MINOR_digit_7[4]' +# elif COMPILER_VERSION_MINOR == 5 + PRINT *, 'INFO:compiler_version_MINOR_digit_7[5]' +# elif COMPILER_VERSION_MINOR == 6 + PRINT *, 'INFO:compiler_version_MINOR_digit_7[6]' +# elif COMPILER_VERSION_MINOR == 7 + PRINT *, 'INFO:compiler_version_MINOR_digit_7[7]' +# elif COMPILER_VERSION_MINOR == 8 + PRINT *, 'INFO:compiler_version_MINOR_digit_7[8]' +# elif COMPILER_VERSION_MINOR == 9 + PRINT *, 'INFO:compiler_version_MINOR_digit_7[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_8(n) +# define HEX(n) HEX_8(n) +# if COMPILER_VERSION_MINOR == 0 + PRINT *, 'INFO:compiler_version_MINOR_digit_8[0]' +# elif COMPILER_VERSION_MINOR == 1 + PRINT *, 'INFO:compiler_version_MINOR_digit_8[1]' +# elif COMPILER_VERSION_MINOR == 2 + PRINT *, 'INFO:compiler_version_MINOR_digit_8[2]' +# elif COMPILER_VERSION_MINOR == 3 + PRINT *, 'INFO:compiler_version_MINOR_digit_8[3]' +# elif COMPILER_VERSION_MINOR == 4 + PRINT *, 'INFO:compiler_version_MINOR_digit_8[4]' +# elif COMPILER_VERSION_MINOR == 5 + PRINT *, 'INFO:compiler_version_MINOR_digit_8[5]' +# elif COMPILER_VERSION_MINOR == 6 + PRINT *, 'INFO:compiler_version_MINOR_digit_8[6]' +# elif COMPILER_VERSION_MINOR == 7 + PRINT *, 'INFO:compiler_version_MINOR_digit_8[7]' +# elif COMPILER_VERSION_MINOR == 8 + PRINT *, 'INFO:compiler_version_MINOR_digit_8[8]' +# elif COMPILER_VERSION_MINOR == 9 + PRINT *, 'INFO:compiler_version_MINOR_digit_8[9]' +# endif + +#endif +#if defined(COMPILER_VERSION_PATCH) +# undef DEC +# undef HEX +# define DEC(n) DEC_1(n) +# define HEX(n) HEX_1(n) +# if COMPILER_VERSION_PATCH == 0 + PRINT *, 'INFO:compiler_version_PATCH_digit_1[0]' +# elif COMPILER_VERSION_PATCH == 1 + PRINT *, 'INFO:compiler_version_PATCH_digit_1[1]' +# elif COMPILER_VERSION_PATCH == 2 + PRINT *, 'INFO:compiler_version_PATCH_digit_1[2]' +# elif COMPILER_VERSION_PATCH == 3 + PRINT *, 'INFO:compiler_version_PATCH_digit_1[3]' +# elif COMPILER_VERSION_PATCH == 4 + PRINT *, 'INFO:compiler_version_PATCH_digit_1[4]' +# elif COMPILER_VERSION_PATCH == 5 + PRINT *, 'INFO:compiler_version_PATCH_digit_1[5]' +# elif COMPILER_VERSION_PATCH == 6 + PRINT *, 'INFO:compiler_version_PATCH_digit_1[6]' +# elif COMPILER_VERSION_PATCH == 7 + PRINT *, 'INFO:compiler_version_PATCH_digit_1[7]' +# elif COMPILER_VERSION_PATCH == 8 + PRINT *, 'INFO:compiler_version_PATCH_digit_1[8]' +# elif COMPILER_VERSION_PATCH == 9 + PRINT *, 'INFO:compiler_version_PATCH_digit_1[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_2(n) +# define HEX(n) HEX_2(n) +# if COMPILER_VERSION_PATCH == 0 + PRINT *, 'INFO:compiler_version_PATCH_digit_2[0]' +# elif COMPILER_VERSION_PATCH == 1 + PRINT *, 'INFO:compiler_version_PATCH_digit_2[1]' +# elif COMPILER_VERSION_PATCH == 2 + PRINT *, 'INFO:compiler_version_PATCH_digit_2[2]' +# elif COMPILER_VERSION_PATCH == 3 + PRINT *, 'INFO:compiler_version_PATCH_digit_2[3]' +# elif COMPILER_VERSION_PATCH == 4 + PRINT *, 'INFO:compiler_version_PATCH_digit_2[4]' +# elif COMPILER_VERSION_PATCH == 5 + PRINT *, 'INFO:compiler_version_PATCH_digit_2[5]' +# elif COMPILER_VERSION_PATCH == 6 + PRINT *, 'INFO:compiler_version_PATCH_digit_2[6]' +# elif COMPILER_VERSION_PATCH == 7 + PRINT *, 'INFO:compiler_version_PATCH_digit_2[7]' +# elif COMPILER_VERSION_PATCH == 8 + PRINT *, 'INFO:compiler_version_PATCH_digit_2[8]' +# elif COMPILER_VERSION_PATCH == 9 + PRINT *, 'INFO:compiler_version_PATCH_digit_2[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_3(n) +# define HEX(n) HEX_3(n) +# if COMPILER_VERSION_PATCH == 0 + PRINT *, 'INFO:compiler_version_PATCH_digit_3[0]' +# elif COMPILER_VERSION_PATCH == 1 + PRINT *, 'INFO:compiler_version_PATCH_digit_3[1]' +# elif COMPILER_VERSION_PATCH == 2 + PRINT *, 'INFO:compiler_version_PATCH_digit_3[2]' +# elif COMPILER_VERSION_PATCH == 3 + PRINT *, 'INFO:compiler_version_PATCH_digit_3[3]' +# elif COMPILER_VERSION_PATCH == 4 + PRINT *, 'INFO:compiler_version_PATCH_digit_3[4]' +# elif COMPILER_VERSION_PATCH == 5 + PRINT *, 'INFO:compiler_version_PATCH_digit_3[5]' +# elif COMPILER_VERSION_PATCH == 6 + PRINT *, 'INFO:compiler_version_PATCH_digit_3[6]' +# elif COMPILER_VERSION_PATCH == 7 + PRINT *, 'INFO:compiler_version_PATCH_digit_3[7]' +# elif COMPILER_VERSION_PATCH == 8 + PRINT *, 'INFO:compiler_version_PATCH_digit_3[8]' +# elif COMPILER_VERSION_PATCH == 9 + PRINT *, 'INFO:compiler_version_PATCH_digit_3[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_4(n) +# define HEX(n) HEX_4(n) +# if COMPILER_VERSION_PATCH == 0 + PRINT *, 'INFO:compiler_version_PATCH_digit_4[0]' +# elif COMPILER_VERSION_PATCH == 1 + PRINT *, 'INFO:compiler_version_PATCH_digit_4[1]' +# elif COMPILER_VERSION_PATCH == 2 + PRINT *, 'INFO:compiler_version_PATCH_digit_4[2]' +# elif COMPILER_VERSION_PATCH == 3 + PRINT *, 'INFO:compiler_version_PATCH_digit_4[3]' +# elif COMPILER_VERSION_PATCH == 4 + PRINT *, 'INFO:compiler_version_PATCH_digit_4[4]' +# elif COMPILER_VERSION_PATCH == 5 + PRINT *, 'INFO:compiler_version_PATCH_digit_4[5]' +# elif COMPILER_VERSION_PATCH == 6 + PRINT *, 'INFO:compiler_version_PATCH_digit_4[6]' +# elif COMPILER_VERSION_PATCH == 7 + PRINT *, 'INFO:compiler_version_PATCH_digit_4[7]' +# elif COMPILER_VERSION_PATCH == 8 + PRINT *, 'INFO:compiler_version_PATCH_digit_4[8]' +# elif COMPILER_VERSION_PATCH == 9 + PRINT *, 'INFO:compiler_version_PATCH_digit_4[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_5(n) +# define HEX(n) HEX_5(n) +# if COMPILER_VERSION_PATCH == 0 + PRINT *, 'INFO:compiler_version_PATCH_digit_5[0]' +# elif COMPILER_VERSION_PATCH == 1 + PRINT *, 'INFO:compiler_version_PATCH_digit_5[1]' +# elif COMPILER_VERSION_PATCH == 2 + PRINT *, 'INFO:compiler_version_PATCH_digit_5[2]' +# elif COMPILER_VERSION_PATCH == 3 + PRINT *, 'INFO:compiler_version_PATCH_digit_5[3]' +# elif COMPILER_VERSION_PATCH == 4 + PRINT *, 'INFO:compiler_version_PATCH_digit_5[4]' +# elif COMPILER_VERSION_PATCH == 5 + PRINT *, 'INFO:compiler_version_PATCH_digit_5[5]' +# elif COMPILER_VERSION_PATCH == 6 + PRINT *, 'INFO:compiler_version_PATCH_digit_5[6]' +# elif COMPILER_VERSION_PATCH == 7 + PRINT *, 'INFO:compiler_version_PATCH_digit_5[7]' +# elif COMPILER_VERSION_PATCH == 8 + PRINT *, 'INFO:compiler_version_PATCH_digit_5[8]' +# elif COMPILER_VERSION_PATCH == 9 + PRINT *, 'INFO:compiler_version_PATCH_digit_5[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_6(n) +# define HEX(n) HEX_6(n) +# if COMPILER_VERSION_PATCH == 0 + PRINT *, 'INFO:compiler_version_PATCH_digit_6[0]' +# elif COMPILER_VERSION_PATCH == 1 + PRINT *, 'INFO:compiler_version_PATCH_digit_6[1]' +# elif COMPILER_VERSION_PATCH == 2 + PRINT *, 'INFO:compiler_version_PATCH_digit_6[2]' +# elif COMPILER_VERSION_PATCH == 3 + PRINT *, 'INFO:compiler_version_PATCH_digit_6[3]' +# elif COMPILER_VERSION_PATCH == 4 + PRINT *, 'INFO:compiler_version_PATCH_digit_6[4]' +# elif COMPILER_VERSION_PATCH == 5 + PRINT *, 'INFO:compiler_version_PATCH_digit_6[5]' +# elif COMPILER_VERSION_PATCH == 6 + PRINT *, 'INFO:compiler_version_PATCH_digit_6[6]' +# elif COMPILER_VERSION_PATCH == 7 + PRINT *, 'INFO:compiler_version_PATCH_digit_6[7]' +# elif COMPILER_VERSION_PATCH == 8 + PRINT *, 'INFO:compiler_version_PATCH_digit_6[8]' +# elif COMPILER_VERSION_PATCH == 9 + PRINT *, 'INFO:compiler_version_PATCH_digit_6[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_7(n) +# define HEX(n) HEX_7(n) +# if COMPILER_VERSION_PATCH == 0 + PRINT *, 'INFO:compiler_version_PATCH_digit_7[0]' +# elif COMPILER_VERSION_PATCH == 1 + PRINT *, 'INFO:compiler_version_PATCH_digit_7[1]' +# elif COMPILER_VERSION_PATCH == 2 + PRINT *, 'INFO:compiler_version_PATCH_digit_7[2]' +# elif COMPILER_VERSION_PATCH == 3 + PRINT *, 'INFO:compiler_version_PATCH_digit_7[3]' +# elif COMPILER_VERSION_PATCH == 4 + PRINT *, 'INFO:compiler_version_PATCH_digit_7[4]' +# elif COMPILER_VERSION_PATCH == 5 + PRINT *, 'INFO:compiler_version_PATCH_digit_7[5]' +# elif COMPILER_VERSION_PATCH == 6 + PRINT *, 'INFO:compiler_version_PATCH_digit_7[6]' +# elif COMPILER_VERSION_PATCH == 7 + PRINT *, 'INFO:compiler_version_PATCH_digit_7[7]' +# elif COMPILER_VERSION_PATCH == 8 + PRINT *, 'INFO:compiler_version_PATCH_digit_7[8]' +# elif COMPILER_VERSION_PATCH == 9 + PRINT *, 'INFO:compiler_version_PATCH_digit_7[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_8(n) +# define HEX(n) HEX_8(n) +# if COMPILER_VERSION_PATCH == 0 + PRINT *, 'INFO:compiler_version_PATCH_digit_8[0]' +# elif COMPILER_VERSION_PATCH == 1 + PRINT *, 'INFO:compiler_version_PATCH_digit_8[1]' +# elif COMPILER_VERSION_PATCH == 2 + PRINT *, 'INFO:compiler_version_PATCH_digit_8[2]' +# elif COMPILER_VERSION_PATCH == 3 + PRINT *, 'INFO:compiler_version_PATCH_digit_8[3]' +# elif COMPILER_VERSION_PATCH == 4 + PRINT *, 'INFO:compiler_version_PATCH_digit_8[4]' +# elif COMPILER_VERSION_PATCH == 5 + PRINT *, 'INFO:compiler_version_PATCH_digit_8[5]' +# elif COMPILER_VERSION_PATCH == 6 + PRINT *, 'INFO:compiler_version_PATCH_digit_8[6]' +# elif COMPILER_VERSION_PATCH == 7 + PRINT *, 'INFO:compiler_version_PATCH_digit_8[7]' +# elif COMPILER_VERSION_PATCH == 8 + PRINT *, 'INFO:compiler_version_PATCH_digit_8[8]' +# elif COMPILER_VERSION_PATCH == 9 + PRINT *, 'INFO:compiler_version_PATCH_digit_8[9]' +# endif + +#endif +#if defined(COMPILER_VERSION_TWEAK) +# undef DEC +# undef HEX +# define DEC(n) DEC_1(n) +# define HEX(n) HEX_1(n) +# if COMPILER_VERSION_TWEAK == 0 + PRINT *, 'INFO:compiler_version_TWEAK_digit_1[0]' +# elif COMPILER_VERSION_TWEAK == 1 + PRINT *, 'INFO:compiler_version_TWEAK_digit_1[1]' +# elif COMPILER_VERSION_TWEAK == 2 + PRINT *, 'INFO:compiler_version_TWEAK_digit_1[2]' +# elif COMPILER_VERSION_TWEAK == 3 + PRINT *, 'INFO:compiler_version_TWEAK_digit_1[3]' +# elif COMPILER_VERSION_TWEAK == 4 + PRINT *, 'INFO:compiler_version_TWEAK_digit_1[4]' +# elif COMPILER_VERSION_TWEAK == 5 + PRINT *, 'INFO:compiler_version_TWEAK_digit_1[5]' +# elif COMPILER_VERSION_TWEAK == 6 + PRINT *, 'INFO:compiler_version_TWEAK_digit_1[6]' +# elif COMPILER_VERSION_TWEAK == 7 + PRINT *, 'INFO:compiler_version_TWEAK_digit_1[7]' +# elif COMPILER_VERSION_TWEAK == 8 + PRINT *, 'INFO:compiler_version_TWEAK_digit_1[8]' +# elif COMPILER_VERSION_TWEAK == 9 + PRINT *, 'INFO:compiler_version_TWEAK_digit_1[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_2(n) +# define HEX(n) HEX_2(n) +# if COMPILER_VERSION_TWEAK == 0 + PRINT *, 'INFO:compiler_version_TWEAK_digit_2[0]' +# elif COMPILER_VERSION_TWEAK == 1 + PRINT *, 'INFO:compiler_version_TWEAK_digit_2[1]' +# elif COMPILER_VERSION_TWEAK == 2 + PRINT *, 'INFO:compiler_version_TWEAK_digit_2[2]' +# elif COMPILER_VERSION_TWEAK == 3 + PRINT *, 'INFO:compiler_version_TWEAK_digit_2[3]' +# elif COMPILER_VERSION_TWEAK == 4 + PRINT *, 'INFO:compiler_version_TWEAK_digit_2[4]' +# elif COMPILER_VERSION_TWEAK == 5 + PRINT *, 'INFO:compiler_version_TWEAK_digit_2[5]' +# elif COMPILER_VERSION_TWEAK == 6 + PRINT *, 'INFO:compiler_version_TWEAK_digit_2[6]' +# elif COMPILER_VERSION_TWEAK == 7 + PRINT *, 'INFO:compiler_version_TWEAK_digit_2[7]' +# elif COMPILER_VERSION_TWEAK == 8 + PRINT *, 'INFO:compiler_version_TWEAK_digit_2[8]' +# elif COMPILER_VERSION_TWEAK == 9 + PRINT *, 'INFO:compiler_version_TWEAK_digit_2[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_3(n) +# define HEX(n) HEX_3(n) +# if COMPILER_VERSION_TWEAK == 0 + PRINT *, 'INFO:compiler_version_TWEAK_digit_3[0]' +# elif COMPILER_VERSION_TWEAK == 1 + PRINT *, 'INFO:compiler_version_TWEAK_digit_3[1]' +# elif COMPILER_VERSION_TWEAK == 2 + PRINT *, 'INFO:compiler_version_TWEAK_digit_3[2]' +# elif COMPILER_VERSION_TWEAK == 3 + PRINT *, 'INFO:compiler_version_TWEAK_digit_3[3]' +# elif COMPILER_VERSION_TWEAK == 4 + PRINT *, 'INFO:compiler_version_TWEAK_digit_3[4]' +# elif COMPILER_VERSION_TWEAK == 5 + PRINT *, 'INFO:compiler_version_TWEAK_digit_3[5]' +# elif COMPILER_VERSION_TWEAK == 6 + PRINT *, 'INFO:compiler_version_TWEAK_digit_3[6]' +# elif COMPILER_VERSION_TWEAK == 7 + PRINT *, 'INFO:compiler_version_TWEAK_digit_3[7]' +# elif COMPILER_VERSION_TWEAK == 8 + PRINT *, 'INFO:compiler_version_TWEAK_digit_3[8]' +# elif COMPILER_VERSION_TWEAK == 9 + PRINT *, 'INFO:compiler_version_TWEAK_digit_3[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_4(n) +# define HEX(n) HEX_4(n) +# if COMPILER_VERSION_TWEAK == 0 + PRINT *, 'INFO:compiler_version_TWEAK_digit_4[0]' +# elif COMPILER_VERSION_TWEAK == 1 + PRINT *, 'INFO:compiler_version_TWEAK_digit_4[1]' +# elif COMPILER_VERSION_TWEAK == 2 + PRINT *, 'INFO:compiler_version_TWEAK_digit_4[2]' +# elif COMPILER_VERSION_TWEAK == 3 + PRINT *, 'INFO:compiler_version_TWEAK_digit_4[3]' +# elif COMPILER_VERSION_TWEAK == 4 + PRINT *, 'INFO:compiler_version_TWEAK_digit_4[4]' +# elif COMPILER_VERSION_TWEAK == 5 + PRINT *, 'INFO:compiler_version_TWEAK_digit_4[5]' +# elif COMPILER_VERSION_TWEAK == 6 + PRINT *, 'INFO:compiler_version_TWEAK_digit_4[6]' +# elif COMPILER_VERSION_TWEAK == 7 + PRINT *, 'INFO:compiler_version_TWEAK_digit_4[7]' +# elif COMPILER_VERSION_TWEAK == 8 + PRINT *, 'INFO:compiler_version_TWEAK_digit_4[8]' +# elif COMPILER_VERSION_TWEAK == 9 + PRINT *, 'INFO:compiler_version_TWEAK_digit_4[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_5(n) +# define HEX(n) HEX_5(n) +# if COMPILER_VERSION_TWEAK == 0 + PRINT *, 'INFO:compiler_version_TWEAK_digit_5[0]' +# elif COMPILER_VERSION_TWEAK == 1 + PRINT *, 'INFO:compiler_version_TWEAK_digit_5[1]' +# elif COMPILER_VERSION_TWEAK == 2 + PRINT *, 'INFO:compiler_version_TWEAK_digit_5[2]' +# elif COMPILER_VERSION_TWEAK == 3 + PRINT *, 'INFO:compiler_version_TWEAK_digit_5[3]' +# elif COMPILER_VERSION_TWEAK == 4 + PRINT *, 'INFO:compiler_version_TWEAK_digit_5[4]' +# elif COMPILER_VERSION_TWEAK == 5 + PRINT *, 'INFO:compiler_version_TWEAK_digit_5[5]' +# elif COMPILER_VERSION_TWEAK == 6 + PRINT *, 'INFO:compiler_version_TWEAK_digit_5[6]' +# elif COMPILER_VERSION_TWEAK == 7 + PRINT *, 'INFO:compiler_version_TWEAK_digit_5[7]' +# elif COMPILER_VERSION_TWEAK == 8 + PRINT *, 'INFO:compiler_version_TWEAK_digit_5[8]' +# elif COMPILER_VERSION_TWEAK == 9 + PRINT *, 'INFO:compiler_version_TWEAK_digit_5[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_6(n) +# define HEX(n) HEX_6(n) +# if COMPILER_VERSION_TWEAK == 0 + PRINT *, 'INFO:compiler_version_TWEAK_digit_6[0]' +# elif COMPILER_VERSION_TWEAK == 1 + PRINT *, 'INFO:compiler_version_TWEAK_digit_6[1]' +# elif COMPILER_VERSION_TWEAK == 2 + PRINT *, 'INFO:compiler_version_TWEAK_digit_6[2]' +# elif COMPILER_VERSION_TWEAK == 3 + PRINT *, 'INFO:compiler_version_TWEAK_digit_6[3]' +# elif COMPILER_VERSION_TWEAK == 4 + PRINT *, 'INFO:compiler_version_TWEAK_digit_6[4]' +# elif COMPILER_VERSION_TWEAK == 5 + PRINT *, 'INFO:compiler_version_TWEAK_digit_6[5]' +# elif COMPILER_VERSION_TWEAK == 6 + PRINT *, 'INFO:compiler_version_TWEAK_digit_6[6]' +# elif COMPILER_VERSION_TWEAK == 7 + PRINT *, 'INFO:compiler_version_TWEAK_digit_6[7]' +# elif COMPILER_VERSION_TWEAK == 8 + PRINT *, 'INFO:compiler_version_TWEAK_digit_6[8]' +# elif COMPILER_VERSION_TWEAK == 9 + PRINT *, 'INFO:compiler_version_TWEAK_digit_6[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_7(n) +# define HEX(n) HEX_7(n) +# if COMPILER_VERSION_TWEAK == 0 + PRINT *, 'INFO:compiler_version_TWEAK_digit_7[0]' +# elif COMPILER_VERSION_TWEAK == 1 + PRINT *, 'INFO:compiler_version_TWEAK_digit_7[1]' +# elif COMPILER_VERSION_TWEAK == 2 + PRINT *, 'INFO:compiler_version_TWEAK_digit_7[2]' +# elif COMPILER_VERSION_TWEAK == 3 + PRINT *, 'INFO:compiler_version_TWEAK_digit_7[3]' +# elif COMPILER_VERSION_TWEAK == 4 + PRINT *, 'INFO:compiler_version_TWEAK_digit_7[4]' +# elif COMPILER_VERSION_TWEAK == 5 + PRINT *, 'INFO:compiler_version_TWEAK_digit_7[5]' +# elif COMPILER_VERSION_TWEAK == 6 + PRINT *, 'INFO:compiler_version_TWEAK_digit_7[6]' +# elif COMPILER_VERSION_TWEAK == 7 + PRINT *, 'INFO:compiler_version_TWEAK_digit_7[7]' +# elif COMPILER_VERSION_TWEAK == 8 + PRINT *, 'INFO:compiler_version_TWEAK_digit_7[8]' +# elif COMPILER_VERSION_TWEAK == 9 + PRINT *, 'INFO:compiler_version_TWEAK_digit_7[9]' +# endif + +# undef DEC +# undef HEX +# define DEC(n) DEC_8(n) +# define HEX(n) HEX_8(n) +# if COMPILER_VERSION_TWEAK == 0 + PRINT *, 'INFO:compiler_version_TWEAK_digit_8[0]' +# elif COMPILER_VERSION_TWEAK == 1 + PRINT *, 'INFO:compiler_version_TWEAK_digit_8[1]' +# elif COMPILER_VERSION_TWEAK == 2 + PRINT *, 'INFO:compiler_version_TWEAK_digit_8[2]' +# elif COMPILER_VERSION_TWEAK == 3 + PRINT *, 'INFO:compiler_version_TWEAK_digit_8[3]' +# elif COMPILER_VERSION_TWEAK == 4 + PRINT *, 'INFO:compiler_version_TWEAK_digit_8[4]' +# elif COMPILER_VERSION_TWEAK == 5 + PRINT *, 'INFO:compiler_version_TWEAK_digit_8[5]' +# elif COMPILER_VERSION_TWEAK == 6 + PRINT *, 'INFO:compiler_version_TWEAK_digit_8[6]' +# elif COMPILER_VERSION_TWEAK == 7 + PRINT *, 'INFO:compiler_version_TWEAK_digit_8[7]' +# elif COMPILER_VERSION_TWEAK == 8 + PRINT *, 'INFO:compiler_version_TWEAK_digit_8[8]' +# elif COMPILER_VERSION_TWEAK == 9 + PRINT *, 'INFO:compiler_version_TWEAK_digit_8[9]' +# endif + +#endif + + END diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/CMakeDirectoryInformation.cmake b/build/__command_line_test__/__command_line_test__/CMakeFiles/CMakeDirectoryInformation.cmake new file mode 100644 index 0000000000..0626f191b1 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/CMakeDirectoryInformation.cmake @@ -0,0 +1,16 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.25 + +# Relative path conversion top directories. +set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/Users/afoster/Documents/ncar/CTSM/src/fates") +set(CMAKE_RELATIVE_PATH_TOP_BINARY "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__") + +# Force unix paths in dependencies. +set(CMAKE_FORCE_UNIX_PATHS 1) + + +# The C and CXX include file regular expressions for this directory. +set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") +set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") +set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) +set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/Makefile.cmake b/build/__command_line_test__/__command_line_test__/CMakeFiles/Makefile.cmake new file mode 100644 index 0000000000..ab222437f3 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/Makefile.cmake @@ -0,0 +1,141 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.25 + +# The generator used is: +set(CMAKE_DEPENDS_GENERATOR "Unix Makefiles") + +# The top level Makefile was generated from the following files: +set(CMAKE_MAKEFILE_DEPENDS + "CMakeCache.txt" + "/Users/afoster/Documents/ncar/CTSM/cime/CIME/non_py/src/CMake/CIME_initial_setup.cmake" + "/Users/afoster/Documents/ncar/CTSM/cime/CIME/non_py/src/CMake/CIME_utils.cmake" + "/Users/afoster/Documents/ncar/CTSM/cime/CIME/non_py/src/CMake/Compilers.cmake" + "/Users/afoster/Documents/ncar/CTSM/cime/CIME/non_py/src/CMake/FindpFUnit.cmake" + "/Users/afoster/Documents/ncar/CTSM/cime/CIME/non_py/src/CMake/Sourcelist_utils.cmake" + "/Users/afoster/Documents/ncar/CTSM/cime/CIME/non_py/src/CMake/genf90_utils.cmake" + "/Users/afoster/Documents/ncar/CTSM/cime/CIME/non_py/src/CMake/pFUnit_utils.cmake" + "/Users/afoster/Documents/ncar/CTSM/src/fates/CMakeLists.txt" + "CMakeFiles/3.25.2/CMakeCCompiler.cmake" + "CMakeFiles/3.25.2/CMakeFortranCompiler.cmake" + "CMakeFiles/3.25.2/CMakeSystem.cmake" + "Macros.cmake" + "/Users/afoster/Documents/ncar/CTSM/src/fates/build/cmake_macros/gnu.cmake" + "/Users/afoster/Documents/ncar/CTSM/src/fates/build/cmake_macros/gnu_fleabone.cmake" + "/Users/afoster/Documents/ncar/CTSM/src/fates/build/cmake_macros/universal.cmake" + "/Users/afoster/Documents/ncar/CTSM/src/fates/main/CMakeLists.txt" + "/Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/CMakeLists.txt" + "/Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/radiation_test/CMakeLists.txt" + "/Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/CMakeLists.txt" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeCCompiler.cmake.in" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeCCompilerABI.c" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeCInformation.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeCommonLanguageInclude.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeCompilerIdDetection.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeDetermineCCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeDetermineCompileFeatures.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeDetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeDetermineCompilerABI.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeDetermineCompilerId.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeDetermineFortranCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeDetermineSystem.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeFindBinUtils.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeFortranCompiler.cmake.in" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeFortranCompilerABI.F90" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeFortranInformation.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeGenericSystem.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeInitializeConfigs.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeLanguageInformation.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeParseArguments.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeParseImplicitIncludeInfo.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeParseImplicitLinkInfo.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeParseLibraryArchitecture.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeSystem.cmake.in" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeSystemSpecificInformation.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeSystemSpecificInitialize.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeTestCCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeTestCompilerCommon.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeTestFortranCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeUnixFindMake.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/ADSP-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/ARMCC-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/ARMClang-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/AppleClang-C.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/AppleClang-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/Borland-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/Bruce-C-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/Clang-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/Clang.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/Compaq-C-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/Cray-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/GHS-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/GNU-C-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/GNU-FindBinUtils.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/GNU-Fortran.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/GNU.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/HP-C-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/IAR-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/IBMClang-C-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/Intel-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/LCC-C-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/MSVC-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/NVHPC-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/PGI-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/PathScale-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/SCO-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/SDCC-C-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/SunPro-C-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/TI-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/Tasking-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/Watcom-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/XL-C-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/XLClang-C-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/zOS-C-DetermineCompiler.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/FindPackageHandleStandardArgs.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/FindPackageMessage.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Internal/FeatureTesting.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Platform/Apple-AppleClang-C.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Platform/Apple-Clang-C.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Platform/Apple-Clang.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Platform/Apple-GNU-Fortran.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Platform/Apple-GNU.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Platform/Darwin-Initialize.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Platform/Darwin.cmake" + "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Platform/UnixPaths.cmake" + ) + +# The corresponding makefile is: +set(CMAKE_MAKEFILE_OUTPUTS + "Makefile" + "CMakeFiles/cmake.check_cache" + ) + +# Byproducts of CMake generate step: +set(CMAKE_MAKEFILE_PRODUCTS + "CMakeFiles/3.25.2/CMakeSystem.cmake" + "CMakeFiles/3.25.2/CMakeFortranCompiler.cmake" + "CMakeFiles/3.25.2/CMakeCCompiler.cmake" + "CMakeFiles/3.25.2/CMakeFortranCompiler.cmake" + "CMakeFiles/3.25.2/CMakeCCompiler.cmake" + "CMakeFiles/CMakeDirectoryInformation.cmake" + "main/CMakeFiles/CMakeDirectoryInformation.cmake" + "unit_testing/utils/CMakeFiles/CMakeDirectoryInformation.cmake" + "unit_testing/test/CMakeFiles/CMakeDirectoryInformation.cmake" + "unit_testing/test/radiation_test/CMakeFiles/CMakeDirectoryInformation.cmake" + ) + +# Dependency information for all targets: +set(CMAKE_DEPEND_INFO_FILES + "CMakeFiles/utils.dir/DependInfo.cmake" + "unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/DependInfo.cmake" + ) diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/Makefile2 b/build/__command_line_test__/__command_line_test__/CMakeFiles/Makefile2 new file mode 100644 index 0000000000..966dd8971c --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/Makefile2 @@ -0,0 +1,206 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.25 + +# Default target executed when no arguments are given to make. +default_target: all +.PHONY : default_target + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Disable VCS-based implicit rules. +% : %,v + +# Disable VCS-based implicit rules. +% : RCS/% + +# Disable VCS-based implicit rules. +% : RCS/%,v + +# Disable VCS-based implicit rules. +% : SCCS/s.% + +# Disable VCS-based implicit rules. +% : s.% + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/local/Cellar/cmake/3.25.2/bin/cmake + +# The command to remove a file. +RM = /usr/local/Cellar/cmake/3.25.2/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ + +#============================================================================= +# Directory level rules for the build root directory + +# The main recursive "all" target. +all: CMakeFiles/utils.dir/all +all: main/all +all: unit_testing/utils/all +all: unit_testing/test/all +.PHONY : all + +# The main recursive "preinstall" target. +preinstall: main/preinstall +preinstall: unit_testing/utils/preinstall +preinstall: unit_testing/test/preinstall +.PHONY : preinstall + +# The main recursive "clean" target. +clean: CMakeFiles/utils.dir/clean +clean: main/clean +clean: unit_testing/utils/clean +clean: unit_testing/test/clean +.PHONY : clean + +#============================================================================= +# Directory level rules for directory main + +# Recursive "all" directory target. +main/all: +.PHONY : main/all + +# Recursive "preinstall" directory target. +main/preinstall: +.PHONY : main/preinstall + +# Recursive "clean" directory target. +main/clean: +.PHONY : main/clean + +#============================================================================= +# Directory level rules for directory unit_testing/test + +# Recursive "all" directory target. +unit_testing/test/all: unit_testing/test/radiation_test/all +.PHONY : unit_testing/test/all + +# Recursive "preinstall" directory target. +unit_testing/test/preinstall: unit_testing/test/radiation_test/preinstall +.PHONY : unit_testing/test/preinstall + +# Recursive "clean" directory target. +unit_testing/test/clean: unit_testing/test/radiation_test/clean +.PHONY : unit_testing/test/clean + +#============================================================================= +# Directory level rules for directory unit_testing/test/radiation_test + +# Recursive "all" directory target. +unit_testing/test/radiation_test/all: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/all +.PHONY : unit_testing/test/radiation_test/all + +# Recursive "preinstall" directory target. +unit_testing/test/radiation_test/preinstall: +.PHONY : unit_testing/test/radiation_test/preinstall + +# Recursive "clean" directory target. +unit_testing/test/radiation_test/clean: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/clean +.PHONY : unit_testing/test/radiation_test/clean + +#============================================================================= +# Directory level rules for directory unit_testing/utils + +# Recursive "all" directory target. +unit_testing/utils/all: +.PHONY : unit_testing/utils/all + +# Recursive "preinstall" directory target. +unit_testing/utils/preinstall: +.PHONY : unit_testing/utils/preinstall + +# Recursive "clean" directory target. +unit_testing/utils/clean: +.PHONY : unit_testing/utils/clean + +#============================================================================= +# Target rules for target CMakeFiles/utils.dir + +# All Build rule for target. +CMakeFiles/utils.dir/all: + $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/depend + $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/build + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles --progress-num=6,7,8,9 "Built target utils" +.PHONY : CMakeFiles/utils.dir/all + +# Build rule for subdir invocation for target. +CMakeFiles/utils.dir/rule: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles 4 + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 CMakeFiles/utils.dir/all + $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles 0 +.PHONY : CMakeFiles/utils.dir/rule + +# Convenience name for target. +utils: CMakeFiles/utils.dir/rule +.PHONY : utils + +# clean rule for target. +CMakeFiles/utils.dir/clean: + $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/clean +.PHONY : CMakeFiles/utils.dir/clean + +#============================================================================= +# Target rules for target unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir + +# All Build rule for target. +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/all: + $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/depend + $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles --progress-num=1,2,3,4,5 "Built target FATES_rad_test" +.PHONY : unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/all + +# Build rule for subdir invocation for target. +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/rule: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles 5 + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/all + $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles 0 +.PHONY : unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/rule + +# Convenience name for target. +FATES_rad_test: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/rule +.PHONY : FATES_rad_test + +# clean rule for target. +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/clean: + $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/clean +.PHONY : unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/clean + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/1 b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/1 new file mode 100644 index 0000000000..7b4d68d70f --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/1 @@ -0,0 +1 @@ +empty \ No newline at end of file diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/2 b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/2 new file mode 100644 index 0000000000..7b4d68d70f --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/2 @@ -0,0 +1 @@ +empty \ No newline at end of file diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/3 b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/3 new file mode 100644 index 0000000000..7b4d68d70f --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/3 @@ -0,0 +1 @@ +empty \ No newline at end of file diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/4 b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/4 new file mode 100644 index 0000000000..7b4d68d70f --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/4 @@ -0,0 +1 @@ +empty \ No newline at end of file diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/6 b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/6 new file mode 100644 index 0000000000..7b4d68d70f --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/6 @@ -0,0 +1 @@ +empty \ No newline at end of file diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/7 b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/7 new file mode 100644 index 0000000000..7b4d68d70f --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/7 @@ -0,0 +1 @@ +empty \ No newline at end of file diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/8 b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/8 new file mode 100644 index 0000000000..7b4d68d70f --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/8 @@ -0,0 +1 @@ +empty \ No newline at end of file diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/9 b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/9 new file mode 100644 index 0000000000..7b4d68d70f --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/9 @@ -0,0 +1 @@ +empty \ No newline at end of file diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/count.txt b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/count.txt new file mode 100644 index 0000000000..ec635144f6 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/count.txt @@ -0,0 +1 @@ +9 diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/TargetDirectories.txt b/build/__command_line_test__/__command_line_test__/CMakeFiles/TargetDirectories.txt new file mode 100644 index 0000000000..949f360985 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/TargetDirectories.txt @@ -0,0 +1,17 @@ +/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir +/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles/test.dir +/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles/edit_cache.dir +/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles/rebuild_cache.dir +/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/main/CMakeFiles/test.dir +/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/main/CMakeFiles/edit_cache.dir +/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/main/CMakeFiles/rebuild_cache.dir +/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/utils/CMakeFiles/test.dir +/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/utils/CMakeFiles/edit_cache.dir +/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/utils/CMakeFiles/rebuild_cache.dir +/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/CMakeFiles/test.dir +/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/CMakeFiles/edit_cache.dir +/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/CMakeFiles/rebuild_cache.dir +/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir +/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/test.dir +/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/edit_cache.dir +/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/rebuild_cache.dir diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/cmake.check_cache b/build/__command_line_test__/__command_line_test__/CMakeFiles/cmake.check_cache new file mode 100644 index 0000000000..3dccd73172 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/progress.marks b/build/__command_line_test__/__command_line_test__/CMakeFiles/progress.marks new file mode 100644 index 0000000000..ec635144f6 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/progress.marks @@ -0,0 +1 @@ +9 diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/DependInfo.cmake b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/DependInfo.cmake new file mode 100644 index 0000000000..1dab08913a --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/DependInfo.cmake @@ -0,0 +1,37 @@ + +# Consider dependencies only in project. +set(CMAKE_DEPENDS_IN_PROJECT_ONLY OFF) + +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "Fortran" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_Fortran + "/Users/afoster/Documents/ncar/CTSM/src/fates/main/FatesConstantsMod.F90" "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o" + "/Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestIOMod.F90" "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o" + "/Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestOrbitalMod.F90" "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o" + ) +set(CMAKE_Fortran_COMPILER_ID "GNU") +set(CMAKE_Fortran_SUBMODULE_SEP "@") +set(CMAKE_Fortran_SUBMODULE_EXT ".smod") + +# The include file search paths: +set(CMAKE_Fortran_TARGET_INCLUDE_PATH + "/Users/afoster/pFUnit/include" + "/Users/afoster/pFUnit/mod" + "/usr/local/Cellar/netcdf/4.9.2/include" + "/usr/local/Cellar/netcdf-fortran/4.6.0/include" + "." + ) + +# The set of dependency files which are needed: +set(CMAKE_DEPENDS_DEPENDENCY_FILES + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/build.make b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/build.make new file mode 100644 index 0000000000..e85a792b85 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/build.make @@ -0,0 +1,140 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.25 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Disable VCS-based implicit rules. +% : %,v + +# Disable VCS-based implicit rules. +% : RCS/% + +# Disable VCS-based implicit rules. +% : RCS/%,v + +# Disable VCS-based implicit rules. +% : SCCS/s.% + +# Disable VCS-based implicit rules. +% : s.% + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/local/Cellar/cmake/3.25.2/bin/cmake + +# The command to remove a file. +RM = /usr/local/Cellar/cmake/3.25.2/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ + +# Include any dependencies generated for this target. +include CMakeFiles/utils.dir/depend.make +# Include any dependencies generated by the compiler for this target. +include CMakeFiles/utils.dir/compiler_depend.make + +# Include the progress variables for this target. +include CMakeFiles/utils.dir/progress.make + +# Include the compile flags for this target's objects. +include CMakeFiles/utils.dir/flags.make + +CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o: CMakeFiles/utils.dir/flags.make +CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o: /Users/afoster/Documents/ncar/CTSM/src/fates/main/FatesConstantsMod.F90 + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building Fortran object CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o" + /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -c /Users/afoster/Documents/ncar/CTSM/src/fates/main/FatesConstantsMod.F90 -o CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o + +CMakeFiles/utils.dir/main/FatesConstantsMod.F90.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing Fortran source to CMakeFiles/utils.dir/main/FatesConstantsMod.F90.i" + /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -E /Users/afoster/Documents/ncar/CTSM/src/fates/main/FatesConstantsMod.F90 > CMakeFiles/utils.dir/main/FatesConstantsMod.F90.i + +CMakeFiles/utils.dir/main/FatesConstantsMod.F90.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling Fortran source to assembly CMakeFiles/utils.dir/main/FatesConstantsMod.F90.s" + /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -S /Users/afoster/Documents/ncar/CTSM/src/fates/main/FatesConstantsMod.F90 -o CMakeFiles/utils.dir/main/FatesConstantsMod.F90.s + +CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o: CMakeFiles/utils.dir/flags.make +CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o: /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestIOMod.F90 + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Building Fortran object CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o" + /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -c /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestIOMod.F90 -o CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o + +CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing Fortran source to CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.i" + /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -E /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestIOMod.F90 > CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.i + +CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling Fortran source to assembly CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.s" + /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -S /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestIOMod.F90 -o CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.s + +CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o: CMakeFiles/utils.dir/flags.make +CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o: /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestOrbitalMod.F90 + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles --progress-num=$(CMAKE_PROGRESS_3) "Building Fortran object CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o" + /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -c /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestOrbitalMod.F90 -o CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o + +CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing Fortran source to CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.i" + /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -E /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestOrbitalMod.F90 > CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.i + +CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling Fortran source to assembly CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.s" + /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -S /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestOrbitalMod.F90 -o CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.s + +# Object files for target utils +utils_OBJECTS = \ +"CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o" \ +"CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o" \ +"CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o" + +# External object files for target utils +utils_EXTERNAL_OBJECTS = + +libutils.a: CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o +libutils.a: CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o +libutils.a: CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o +libutils.a: CMakeFiles/utils.dir/build.make +libutils.a: CMakeFiles/utils.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles --progress-num=$(CMAKE_PROGRESS_4) "Linking Fortran static library libutils.a" + $(CMAKE_COMMAND) -P CMakeFiles/utils.dir/cmake_clean_target.cmake + $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/utils.dir/link.txt --verbose=$(VERBOSE) + +# Rule to build all files generated by this target. +CMakeFiles/utils.dir/build: libutils.a +.PHONY : CMakeFiles/utils.dir/build + +CMakeFiles/utils.dir/clean: + $(CMAKE_COMMAND) -P CMakeFiles/utils.dir/cmake_clean.cmake +.PHONY : CMakeFiles/utils.dir/clean + +CMakeFiles/utils.dir/depend: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /Users/afoster/Documents/ncar/CTSM/src/fates /Users/afoster/Documents/ncar/CTSM/src/fates /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : CMakeFiles/utils.dir/depend + diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/cmake_clean.cmake b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/cmake_clean.cmake new file mode 100644 index 0000000000..3c01a04cf5 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/cmake_clean.cmake @@ -0,0 +1,12 @@ +file(REMOVE_RECURSE + "CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o" + "CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o" + "CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o" + "libutils.a" + "libutils.pdb" +) + +# Per-language clean rules from dependency scanning. +foreach(lang Fortran) + include(CMakeFiles/utils.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/cmake_clean_Fortran.cmake b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/cmake_clean_Fortran.cmake new file mode 100644 index 0000000000..820ee03e9b --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/cmake_clean_Fortran.cmake @@ -0,0 +1,14 @@ +# Remove fortran modules provided by this target. +FILE(REMOVE + "fatesconstantsmod.mod" + "FATESCONSTANTSMOD.mod" + "CMakeFiles/utils.dir/fatesconstantsmod.mod.stamp" + + "fatesunittestiomod.mod" + "FATESUNITTESTIOMOD.mod" + "CMakeFiles/utils.dir/fatesunittestiomod.mod.stamp" + + "fatesunittestorbitalmod.mod" + "FATESUNITTESTORBITALMOD.mod" + "CMakeFiles/utils.dir/fatesunittestorbitalmod.mod.stamp" + ) diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/cmake_clean_target.cmake b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/cmake_clean_target.cmake new file mode 100644 index 0000000000..6da29f6b6f --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/cmake_clean_target.cmake @@ -0,0 +1,3 @@ +file(REMOVE_RECURSE + "libutils.a" +) diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/compiler_depend.make b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/compiler_depend.make new file mode 100644 index 0000000000..ab29ade490 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/compiler_depend.make @@ -0,0 +1,2 @@ +# Empty compiler generated dependencies file for utils. +# This may be replaced when dependencies are built. diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/compiler_depend.ts b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/compiler_depend.ts new file mode 100644 index 0000000000..92e446bc27 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/compiler_depend.ts @@ -0,0 +1,2 @@ +# CMAKE generated file: DO NOT EDIT! +# Timestamp file for compiler generated dependencies management for utils. diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/depend.internal b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/depend.internal new file mode 100644 index 0000000000..f7c3988daa --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/depend.internal @@ -0,0 +1,9 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.25 + +CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o + /Users/afoster/Documents/ncar/CTSM/src/fates/main/FatesConstantsMod.F90 +CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o + /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestIOMod.F90 +CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o + /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestOrbitalMod.F90 diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/depend.make b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/depend.make new file mode 100644 index 0000000000..304216def0 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/depend.make @@ -0,0 +1,25 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.25 + +# Note that incremental build could trigger a call to cmake_copy_f90_mod on each re-build +CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o.provides.build: CMakeFiles/utils.dir/fatesconstantsmod.mod.stamp +CMakeFiles/utils.dir/fatesconstantsmod.mod.stamp: CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o + $(CMAKE_COMMAND) -E cmake_copy_f90_mod fatesconstantsmod.mod CMakeFiles/utils.dir/fatesconstantsmod.mod.stamp GNU +CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o.provides.build: + $(CMAKE_COMMAND) -E touch CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o.provides.build +CMakeFiles/utils.dir/build: CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o.provides.build +CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o: CMakeFiles/utils.dir/fatesconstantsmod.mod.stamp +CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o: /usr/local/Cellar/netcdf-fortran/4.6.0/include/netcdf.mod +CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o.provides.build: CMakeFiles/utils.dir/fatesunittestiomod.mod.stamp +CMakeFiles/utils.dir/fatesunittestiomod.mod.stamp: CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o + $(CMAKE_COMMAND) -E cmake_copy_f90_mod fatesunittestiomod.mod CMakeFiles/utils.dir/fatesunittestiomod.mod.stamp GNU +CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o.provides.build: + $(CMAKE_COMMAND) -E touch CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o.provides.build +CMakeFiles/utils.dir/build: CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o.provides.build +CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o: CMakeFiles/utils.dir/fatesunittestiomod.mod.stamp +CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o.provides.build: CMakeFiles/utils.dir/fatesunittestorbitalmod.mod.stamp +CMakeFiles/utils.dir/fatesunittestorbitalmod.mod.stamp: CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o + $(CMAKE_COMMAND) -E cmake_copy_f90_mod fatesunittestorbitalmod.mod CMakeFiles/utils.dir/fatesunittestorbitalmod.mod.stamp GNU +CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o.provides.build: + $(CMAKE_COMMAND) -E touch CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o.provides.build +CMakeFiles/utils.dir/build: CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o.provides.build diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fatesconstantsmod.mod.stamp b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fatesconstantsmod.mod.stamp new file mode 100644 index 0000000000000000000000000000000000000000..2b4ac0b598d43fed2ea70fd8680dacf9fc821b43 GIT binary patch literal 2256 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 literal 0 HcmV?d00001 diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fatesunittestiomod.mod.stamp b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fatesunittestiomod.mod.stamp new file mode 100644 index 0000000000000000000000000000000000000000..bac5e8f68dbed86771ad6e160e953b2ced9f2e29 GIT binary patch literal 24087 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 P!!w~bQoeT*Pci-nwC<&` literal 0 HcmV?d00001 diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fatesunittestorbitalmod.mod.stamp b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fatesunittestorbitalmod.mod.stamp new file mode 100644 index 0000000000000000000000000000000000000000..cb85e3a79588da53be704d893829e4e21f8807ee GIT binary patch literal 25076 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%0Du&QhFE5>J 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 literal 0 HcmV?d00001 diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/flags.make b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/flags.make new file mode 100644 index 0000000000..97f3ac41ce --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/flags.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.25 + +# compile Fortran with /usr/local/bin/gfortran +Fortran_DEFINES = + +Fortran_INCLUDES = -I/Users/afoster/pFUnit/include -I/Users/afoster/pFUnit/mod -I/usr/local/Cellar/netcdf/4.9.2/include -I/usr/local/Cellar/netcdf-fortran/4.6.0/include -I/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ + +Fortran_FLAGS = -DCESMCOUPLED -DFORTRANUNDERSCORE -DNO_R16 -DCPRGNU -fconvert=big-endian -ffree-line-length-none -ffixed-line-length-none -g -Wall -Og -fbacktrace -ffpe-trap=zero,overflow -fcheck=bounds -fallow-argument-mismatch -fallow-invalid-boz -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk + diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fortran.internal b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fortran.internal new file mode 100644 index 0000000000..8030915fe2 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fortran.internal @@ -0,0 +1,5 @@ +# The fortran modules provided by this target. +provides + fatesconstantsmod.mod + fatesunittestiomod.mod + fatesunittestorbitalmod.mod diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/link.txt b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/link.txt new file mode 100644 index 0000000000..bac60900c6 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/link.txt @@ -0,0 +1,2 @@ +/usr/bin/ar qc libutils.a CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o +/usr/bin/ranlib libutils.a diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o.provides.build b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o.provides.build new file mode 100644 index 0000000000..e69de29bb2 diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/progress.make b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/progress.make new file mode 100644 index 0000000000..fdb0a7b084 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/progress.make @@ -0,0 +1,5 @@ +CMAKE_PROGRESS_1 = 6 +CMAKE_PROGRESS_2 = 7 +CMAKE_PROGRESS_3 = 8 +CMAKE_PROGRESS_4 = 9 + diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o.provides.build b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o.provides.build new file mode 100644 index 0000000000..e69de29bb2 diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o.provides.build b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o.provides.build new file mode 100644 index 0000000000..e69de29bb2 diff --git a/build/__command_line_test__/__command_line_test__/CTestTestfile.cmake b/build/__command_line_test__/__command_line_test__/CTestTestfile.cmake new file mode 100644 index 0000000000..2a25e968d2 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/CTestTestfile.cmake @@ -0,0 +1,9 @@ +# CMake generated Testfile for +# Source directory: /Users/afoster/Documents/ncar/CTSM/src/fates +# Build directory: /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ +# +# This file includes the relevant testing commands required for +# testing this directory and lists subdirectories to be tested as well. +subdirs("main") +subdirs("unit_testing/utils") +subdirs("unit_testing/test") diff --git a/build/__command_line_test__/__command_line_test__/Macros.cmake b/build/__command_line_test__/__command_line_test__/Macros.cmake new file mode 120000 index 0000000000..d2c6ddac24 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/Macros.cmake @@ -0,0 +1 @@ +/Users/afoster/Documents/ncar/CTSM/src/fates/build/Macros.cmake \ No newline at end of file diff --git a/build/__command_line_test__/__command_line_test__/Makefile b/build/__command_line_test__/__command_line_test__/Makefile new file mode 100644 index 0000000000..261969932c --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/Makefile @@ -0,0 +1,260 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.25 + +# Default target executed when no arguments are given to make. +default_target: all +.PHONY : default_target + +# Allow only one "make -f Makefile2" at a time, but pass parallelism. +.NOTPARALLEL: + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Disable VCS-based implicit rules. +% : %,v + +# Disable VCS-based implicit rules. +% : RCS/% + +# Disable VCS-based implicit rules. +% : RCS/%,v + +# Disable VCS-based implicit rules. +% : SCCS/s.% + +# Disable VCS-based implicit rules. +% : s.% + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/local/Cellar/cmake/3.25.2/bin/cmake + +# The command to remove a file. +RM = /usr/local/Cellar/cmake/3.25.2/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target test +test: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests..." + /usr/local/Cellar/cmake/3.25.2/bin/ctest --force-new-ctest-process $(ARGS) +.PHONY : test + +# Special rule for the target test +test/fast: test +.PHONY : test/fast + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." + /usr/local/Cellar/cmake/3.25.2/bin/ccmake -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache +.PHONY : edit_cache/fast + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." + /usr/local/Cellar/cmake/3.25.2/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache +.PHONY : rebuild_cache/fast + +# The main all target +all: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__//CMakeFiles/progress.marks + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 all + $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles 0 +.PHONY : all + +# The main clean target +clean: + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 clean +.PHONY : clean + +# The main clean target +clean/fast: clean +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 +.PHONY : depend + +#============================================================================= +# Target rules for targets named utils + +# Build rule for target. +utils: cmake_check_build_system + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 utils +.PHONY : utils + +# fast build rule for target. +utils/fast: + $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/build +.PHONY : utils/fast + +#============================================================================= +# Target rules for targets named FATES_rad_test + +# Build rule for target. +FATES_rad_test: cmake_check_build_system + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 FATES_rad_test +.PHONY : FATES_rad_test + +# fast build rule for target. +FATES_rad_test/fast: + $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build +.PHONY : FATES_rad_test/fast + +main/FatesConstantsMod.o: main/FatesConstantsMod.F90.o +.PHONY : main/FatesConstantsMod.o + +# target to build an object file +main/FatesConstantsMod.F90.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o +.PHONY : main/FatesConstantsMod.F90.o + +main/FatesConstantsMod.i: main/FatesConstantsMod.F90.i +.PHONY : main/FatesConstantsMod.i + +# target to preprocess a source file +main/FatesConstantsMod.F90.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/main/FatesConstantsMod.F90.i +.PHONY : main/FatesConstantsMod.F90.i + +main/FatesConstantsMod.s: main/FatesConstantsMod.F90.s +.PHONY : main/FatesConstantsMod.s + +# target to generate assembly for a file +main/FatesConstantsMod.F90.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/main/FatesConstantsMod.F90.s +.PHONY : main/FatesConstantsMod.F90.s + +unit_testing/utils/FatesUnitTestIOMod.o: unit_testing/utils/FatesUnitTestIOMod.F90.o +.PHONY : unit_testing/utils/FatesUnitTestIOMod.o + +# target to build an object file +unit_testing/utils/FatesUnitTestIOMod.F90.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o +.PHONY : unit_testing/utils/FatesUnitTestIOMod.F90.o + +unit_testing/utils/FatesUnitTestIOMod.i: unit_testing/utils/FatesUnitTestIOMod.F90.i +.PHONY : unit_testing/utils/FatesUnitTestIOMod.i + +# target to preprocess a source file +unit_testing/utils/FatesUnitTestIOMod.F90.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.i +.PHONY : unit_testing/utils/FatesUnitTestIOMod.F90.i + +unit_testing/utils/FatesUnitTestIOMod.s: unit_testing/utils/FatesUnitTestIOMod.F90.s +.PHONY : unit_testing/utils/FatesUnitTestIOMod.s + +# target to generate assembly for a file +unit_testing/utils/FatesUnitTestIOMod.F90.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.s +.PHONY : unit_testing/utils/FatesUnitTestIOMod.F90.s + +unit_testing/utils/FatesUnitTestOrbitalMod.o: unit_testing/utils/FatesUnitTestOrbitalMod.F90.o +.PHONY : unit_testing/utils/FatesUnitTestOrbitalMod.o + +# target to build an object file +unit_testing/utils/FatesUnitTestOrbitalMod.F90.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o +.PHONY : unit_testing/utils/FatesUnitTestOrbitalMod.F90.o + +unit_testing/utils/FatesUnitTestOrbitalMod.i: unit_testing/utils/FatesUnitTestOrbitalMod.F90.i +.PHONY : unit_testing/utils/FatesUnitTestOrbitalMod.i + +# target to preprocess a source file +unit_testing/utils/FatesUnitTestOrbitalMod.F90.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.i +.PHONY : unit_testing/utils/FatesUnitTestOrbitalMod.F90.i + +unit_testing/utils/FatesUnitTestOrbitalMod.s: unit_testing/utils/FatesUnitTestOrbitalMod.F90.s +.PHONY : unit_testing/utils/FatesUnitTestOrbitalMod.s + +# target to generate assembly for a file +unit_testing/utils/FatesUnitTestOrbitalMod.F90.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.s +.PHONY : unit_testing/utils/FatesUnitTestOrbitalMod.F90.s + +# Help Target +help: + @echo "The following are some of the valid targets for this Makefile:" + @echo "... all (the default if no target is provided)" + @echo "... clean" + @echo "... depend" + @echo "... edit_cache" + @echo "... rebuild_cache" + @echo "... test" + @echo "... FATES_rad_test" + @echo "... utils" + @echo "... main/FatesConstantsMod.o" + @echo "... main/FatesConstantsMod.i" + @echo "... main/FatesConstantsMod.s" + @echo "... unit_testing/utils/FatesUnitTestIOMod.o" + @echo "... unit_testing/utils/FatesUnitTestIOMod.i" + @echo "... unit_testing/utils/FatesUnitTestIOMod.s" + @echo "... unit_testing/utils/FatesUnitTestOrbitalMod.o" + @echo "... unit_testing/utils/FatesUnitTestOrbitalMod.i" + @echo "... unit_testing/utils/FatesUnitTestOrbitalMod.s" +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/build/__command_line_test__/__command_line_test__/cmake_install.cmake b/build/__command_line_test__/__command_line_test__/cmake_install.cmake new file mode 100644 index 0000000000..c8099b8c37 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/cmake_install.cmake @@ -0,0 +1,57 @@ +# Install script for directory: /Users/afoster/Documents/ncar/CTSM/src/fates + +# Set the install prefix +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "/usr/local") +endif() +string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + if(BUILD_TYPE) + string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + else() + set(CMAKE_INSTALL_CONFIG_NAME "CESM_DEBUG") + endif() + message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +endif() + +# Set the component getting installed. +if(NOT CMAKE_INSTALL_COMPONENT) + if(COMPONENT) + message(STATUS "Install component: \"${COMPONENT}\"") + set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + else() + set(CMAKE_INSTALL_COMPONENT) + endif() +endif() + +# Is this installation the result of a crosscompile? +if(NOT DEFINED CMAKE_CROSSCOMPILING) + set(CMAKE_CROSSCOMPILING "FALSE") +endif() + +# Set default install directory permissions. +if(NOT DEFINED CMAKE_OBJDUMP) + set(CMAKE_OBJDUMP "/usr/bin/objdump") +endif() + +if(NOT CMAKE_INSTALL_LOCAL_ONLY) + # Include the install script for each subdirectory. + include("/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/main/cmake_install.cmake") + include("/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/utils/cmake_install.cmake") + include("/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/cmake_install.cmake") + +endif() + +if(CMAKE_INSTALL_COMPONENT) + set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") +else() + set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") +endif() + +string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT + "${CMAKE_INSTALL_MANIFEST_FILES}") +file(WRITE "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/${CMAKE_INSTALL_MANIFEST}" + "${CMAKE_INSTALL_MANIFEST_CONTENT}") diff --git a/build/__command_line_test__/__command_line_test__/libutils.a b/build/__command_line_test__/__command_line_test__/libutils.a new file mode 100644 index 0000000000000000000000000000000000000000..801611e8e9d8fa8e4ac2679e58fcaf3a36e6b717 GIT binary patch literal 40264 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 UQt6UH7tf~(w7seEn0G4wA0CJvng9R* literal 0 HcmV?d00001 diff --git a/build/__command_line_test__/__command_line_test__/main/CMakeFiles/CMakeDirectoryInformation.cmake b/build/__command_line_test__/__command_line_test__/main/CMakeFiles/CMakeDirectoryInformation.cmake new file mode 100644 index 0000000000..0626f191b1 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/main/CMakeFiles/CMakeDirectoryInformation.cmake @@ -0,0 +1,16 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.25 + +# Relative path conversion top directories. +set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/Users/afoster/Documents/ncar/CTSM/src/fates") +set(CMAKE_RELATIVE_PATH_TOP_BINARY "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__") + +# Force unix paths in dependencies. +set(CMAKE_FORCE_UNIX_PATHS 1) + + +# The C and CXX include file regular expressions for this directory. +set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") +set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") +set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) +set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/build/__command_line_test__/__command_line_test__/main/CMakeFiles/progress.marks b/build/__command_line_test__/__command_line_test__/main/CMakeFiles/progress.marks new file mode 100644 index 0000000000..573541ac97 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/main/CMakeFiles/progress.marks @@ -0,0 +1 @@ +0 diff --git a/build/__command_line_test__/__command_line_test__/main/CTestTestfile.cmake b/build/__command_line_test__/__command_line_test__/main/CTestTestfile.cmake new file mode 100644 index 0000000000..09d92f9199 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/main/CTestTestfile.cmake @@ -0,0 +1,6 @@ +# CMake generated Testfile for +# Source directory: /Users/afoster/Documents/ncar/CTSM/src/fates/main +# Build directory: /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/main +# +# This file includes the relevant testing commands required for +# testing this directory and lists subdirectories to be tested as well. diff --git a/build/__command_line_test__/__command_line_test__/main/Makefile b/build/__command_line_test__/__command_line_test__/main/Makefile new file mode 100644 index 0000000000..c0af35d7b3 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/main/Makefile @@ -0,0 +1,151 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.25 + +# Default target executed when no arguments are given to make. +default_target: all +.PHONY : default_target + +# Allow only one "make -f Makefile2" at a time, but pass parallelism. +.NOTPARALLEL: + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Disable VCS-based implicit rules. +% : %,v + +# Disable VCS-based implicit rules. +% : RCS/% + +# Disable VCS-based implicit rules. +% : RCS/%,v + +# Disable VCS-based implicit rules. +% : SCCS/s.% + +# Disable VCS-based implicit rules. +% : s.% + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/local/Cellar/cmake/3.25.2/bin/cmake + +# The command to remove a file. +RM = /usr/local/Cellar/cmake/3.25.2/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target test +test: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests..." + /usr/local/Cellar/cmake/3.25.2/bin/ctest --force-new-ctest-process $(ARGS) +.PHONY : test + +# Special rule for the target test +test/fast: test +.PHONY : test/fast + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." + /usr/local/Cellar/cmake/3.25.2/bin/ccmake -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache +.PHONY : edit_cache/fast + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." + /usr/local/Cellar/cmake/3.25.2/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache +.PHONY : rebuild_cache/fast + +# The main all target +all: cmake_check_build_system + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/main//CMakeFiles/progress.marks + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 main/all + $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles 0 +.PHONY : all + +# The main clean target +clean: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 main/clean +.PHONY : clean + +# The main clean target +clean/fast: clean +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 main/preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 main/preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 +.PHONY : depend + +# Help Target +help: + @echo "The following are some of the valid targets for this Makefile:" + @echo "... all (the default if no target is provided)" + @echo "... clean" + @echo "... depend" + @echo "... edit_cache" + @echo "... rebuild_cache" + @echo "... test" +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/build/__command_line_test__/__command_line_test__/main/cmake_install.cmake b/build/__command_line_test__/__command_line_test__/main/cmake_install.cmake new file mode 100644 index 0000000000..930efcb765 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/main/cmake_install.cmake @@ -0,0 +1,39 @@ +# Install script for directory: /Users/afoster/Documents/ncar/CTSM/src/fates/main + +# Set the install prefix +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "/usr/local") +endif() +string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + if(BUILD_TYPE) + string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + else() + set(CMAKE_INSTALL_CONFIG_NAME "CESM_DEBUG") + endif() + message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +endif() + +# Set the component getting installed. +if(NOT CMAKE_INSTALL_COMPONENT) + if(COMPONENT) + message(STATUS "Install component: \"${COMPONENT}\"") + set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + else() + set(CMAKE_INSTALL_COMPONENT) + endif() +endif() + +# Is this installation the result of a crosscompile? +if(NOT DEFINED CMAKE_CROSSCOMPILING) + set(CMAKE_CROSSCOMPILING "FALSE") +endif() + +# Set default install directory permissions. +if(NOT DEFINED CMAKE_OBJDUMP) + set(CMAKE_OBJDUMP "/usr/bin/objdump") +endif() + diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/CMakeFiles/CMakeDirectoryInformation.cmake b/build/__command_line_test__/__command_line_test__/unit_testing/test/CMakeFiles/CMakeDirectoryInformation.cmake new file mode 100644 index 0000000000..0626f191b1 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/test/CMakeFiles/CMakeDirectoryInformation.cmake @@ -0,0 +1,16 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.25 + +# Relative path conversion top directories. +set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/Users/afoster/Documents/ncar/CTSM/src/fates") +set(CMAKE_RELATIVE_PATH_TOP_BINARY "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__") + +# Force unix paths in dependencies. +set(CMAKE_FORCE_UNIX_PATHS 1) + + +# The C and CXX include file regular expressions for this directory. +set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") +set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") +set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) +set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/CMakeFiles/progress.marks b/build/__command_line_test__/__command_line_test__/unit_testing/test/CMakeFiles/progress.marks new file mode 100644 index 0000000000..7ed6ff82de --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/test/CMakeFiles/progress.marks @@ -0,0 +1 @@ +5 diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/CTestTestfile.cmake b/build/__command_line_test__/__command_line_test__/unit_testing/test/CTestTestfile.cmake new file mode 100644 index 0000000000..9ed9c2cf62 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/test/CTestTestfile.cmake @@ -0,0 +1,7 @@ +# CMake generated Testfile for +# Source directory: /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test +# Build directory: /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test +# +# This file includes the relevant testing commands required for +# testing this directory and lists subdirectories to be tested as well. +subdirs("radiation_test") diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/Makefile b/build/__command_line_test__/__command_line_test__/unit_testing/test/Makefile new file mode 100644 index 0000000000..3b163f0e65 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/test/Makefile @@ -0,0 +1,151 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.25 + +# Default target executed when no arguments are given to make. +default_target: all +.PHONY : default_target + +# Allow only one "make -f Makefile2" at a time, but pass parallelism. +.NOTPARALLEL: + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Disable VCS-based implicit rules. +% : %,v + +# Disable VCS-based implicit rules. +% : RCS/% + +# Disable VCS-based implicit rules. +% : RCS/%,v + +# Disable VCS-based implicit rules. +% : SCCS/s.% + +# Disable VCS-based implicit rules. +% : s.% + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/local/Cellar/cmake/3.25.2/bin/cmake + +# The command to remove a file. +RM = /usr/local/Cellar/cmake/3.25.2/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target test +test: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests..." + /usr/local/Cellar/cmake/3.25.2/bin/ctest --force-new-ctest-process $(ARGS) +.PHONY : test + +# Special rule for the target test +test/fast: test +.PHONY : test/fast + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." + /usr/local/Cellar/cmake/3.25.2/bin/ccmake -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache +.PHONY : edit_cache/fast + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." + /usr/local/Cellar/cmake/3.25.2/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache +.PHONY : rebuild_cache/fast + +# The main all target +all: cmake_check_build_system + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test//CMakeFiles/progress.marks + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/test/all + $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles 0 +.PHONY : all + +# The main clean target +clean: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/test/clean +.PHONY : clean + +# The main clean target +clean/fast: clean +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/test/preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/test/preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 +.PHONY : depend + +# Help Target +help: + @echo "The following are some of the valid targets for this Makefile:" + @echo "... all (the default if no target is provided)" + @echo "... clean" + @echo "... depend" + @echo "... edit_cache" + @echo "... rebuild_cache" + @echo "... test" +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/cmake_install.cmake b/build/__command_line_test__/__command_line_test__/unit_testing/test/cmake_install.cmake new file mode 100644 index 0000000000..6b3c9fb0cc --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/test/cmake_install.cmake @@ -0,0 +1,45 @@ +# Install script for directory: /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test + +# Set the install prefix +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "/usr/local") +endif() +string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + if(BUILD_TYPE) + string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + else() + set(CMAKE_INSTALL_CONFIG_NAME "CESM_DEBUG") + endif() + message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +endif() + +# Set the component getting installed. +if(NOT CMAKE_INSTALL_COMPONENT) + if(COMPONENT) + message(STATUS "Install component: \"${COMPONENT}\"") + set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + else() + set(CMAKE_INSTALL_COMPONENT) + endif() +endif() + +# Is this installation the result of a crosscompile? +if(NOT DEFINED CMAKE_CROSSCOMPILING) + set(CMAKE_CROSSCOMPILING "FALSE") +endif() + +# Set default install directory permissions. +if(NOT DEFINED CMAKE_OBJDUMP) + set(CMAKE_OBJDUMP "/usr/bin/objdump") +endif() + +if(NOT CMAKE_INSTALL_LOCAL_ONLY) + # Include the install script for each subdirectory. + include("/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/cmake_install.cmake") + +endif() + diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/CMakeDirectoryInformation.cmake b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/CMakeDirectoryInformation.cmake new file mode 100644 index 0000000000..0626f191b1 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/CMakeDirectoryInformation.cmake @@ -0,0 +1,16 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.25 + +# Relative path conversion top directories. +set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/Users/afoster/Documents/ncar/CTSM/src/fates") +set(CMAKE_RELATIVE_PATH_TOP_BINARY "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__") + +# Force unix paths in dependencies. +set(CMAKE_FORCE_UNIX_PATHS 1) + + +# The C and CXX include file regular expressions for this directory. +set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") +set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") +set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) +set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/DependInfo.cmake b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/DependInfo.cmake new file mode 100644 index 0000000000..61a4a7133c --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/DependInfo.cmake @@ -0,0 +1,37 @@ + +# Consider dependencies only in project. +set(CMAKE_DEPENDS_IN_PROJECT_ONLY OFF) + +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "Fortran" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_Fortran + "/Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/radiation_test/FatesUnitTestRadiation.F90" "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o" + "/Users/afoster/Documents/ncar/CTSM/src/fates/main/FatesConstantsMod.F90" "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o" + "/Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestIOMod.F90" "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o" + "/Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestOrbitalMod.F90" "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o" + ) +set(CMAKE_Fortran_COMPILER_ID "GNU") +set(CMAKE_Fortran_SUBMODULE_SEP "@") +set(CMAKE_Fortran_SUBMODULE_EXT ".smod") + +# The include file search paths: +set(CMAKE_Fortran_TARGET_INCLUDE_PATH + "/Users/afoster/pFUnit/include" + "/Users/afoster/pFUnit/mod" + "/usr/local/Cellar/netcdf/4.9.2/include" + "/usr/local/Cellar/netcdf-fortran/4.6.0/include" + ) + +# The set of dependency files which are needed: +set(CMAKE_DEPENDS_DEPENDENCY_FILES + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o.provides.build b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o.provides.build new file mode 100644 index 0000000000..e69de29bb2 diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o.provides.build b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o.provides.build new file mode 100644 index 0000000000..e69de29bb2 diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o.provides.build b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o.provides.build new file mode 100644 index 0000000000..e69de29bb2 diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make new file mode 100644 index 0000000000..7149be51cf --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make @@ -0,0 +1,154 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.25 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Disable VCS-based implicit rules. +% : %,v + +# Disable VCS-based implicit rules. +% : RCS/% + +# Disable VCS-based implicit rules. +% : RCS/%,v + +# Disable VCS-based implicit rules. +% : SCCS/s.% + +# Disable VCS-based implicit rules. +% : s.% + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/local/Cellar/cmake/3.25.2/bin/cmake + +# The command to remove a file. +RM = /usr/local/Cellar/cmake/3.25.2/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ + +# Include any dependencies generated for this target. +include unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/depend.make +# Include any dependencies generated by the compiler for this target. +include unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/compiler_depend.make + +# Include the progress variables for this target. +include unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/progress.make + +# Include the compile flags for this target's objects. +include unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/flags.make + +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/flags.make +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o: /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/radiation_test/FatesUnitTestRadiation.F90 + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building Fortran object unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o" + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -c /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/radiation_test/FatesUnitTestRadiation.F90 -o CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o + +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing Fortran source to CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.i" + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -E /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/radiation_test/FatesUnitTestRadiation.F90 > CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.i + +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling Fortran source to assembly CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.s" + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -S /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/radiation_test/FatesUnitTestRadiation.F90 -o CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.s + +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/flags.make +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o: /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestIOMod.F90 + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Building Fortran object unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o" + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -c /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestIOMod.F90 -o CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o + +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing Fortran source to CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.i" + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -E /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestIOMod.F90 > CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.i + +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling Fortran source to assembly CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.s" + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -S /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestIOMod.F90 -o CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.s + +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/flags.make +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o: /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestOrbitalMod.F90 + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles --progress-num=$(CMAKE_PROGRESS_3) "Building Fortran object unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o" + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -c /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestOrbitalMod.F90 -o CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o + +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing Fortran source to CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.i" + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -E /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestOrbitalMod.F90 > CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.i + +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling Fortran source to assembly CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.s" + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -S /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestOrbitalMod.F90 -o CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.s + +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/flags.make +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o: /Users/afoster/Documents/ncar/CTSM/src/fates/main/FatesConstantsMod.F90 + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles --progress-num=$(CMAKE_PROGRESS_4) "Building Fortran object unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o" + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -c /Users/afoster/Documents/ncar/CTSM/src/fates/main/FatesConstantsMod.F90 -o CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o + +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing Fortran source to CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.i" + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -E /Users/afoster/Documents/ncar/CTSM/src/fates/main/FatesConstantsMod.F90 > CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.i + +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling Fortran source to assembly CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.s" + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -S /Users/afoster/Documents/ncar/CTSM/src/fates/main/FatesConstantsMod.F90 -o CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.s + +# Object files for target FATES_rad_test +FATES_rad_test_OBJECTS = \ +"CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o" \ +"CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o" \ +"CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o" \ +"CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o" + +# External object files for target FATES_rad_test +FATES_rad_test_EXTERNAL_OBJECTS = + +unit_testing/test/radiation_test/FATES_rad_test: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o +unit_testing/test/radiation_test/FATES_rad_test: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o +unit_testing/test/radiation_test/FATES_rad_test: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o +unit_testing/test/radiation_test/FATES_rad_test: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o +unit_testing/test/radiation_test/FATES_rad_test: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make +unit_testing/test/radiation_test/FATES_rad_test: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles --progress-num=$(CMAKE_PROGRESS_5) "Linking Fortran executable FATES_rad_test" + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/FATES_rad_test.dir/link.txt --verbose=$(VERBOSE) + +# Rule to build all files generated by this target. +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build: unit_testing/test/radiation_test/FATES_rad_test +.PHONY : unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build + +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/clean: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && $(CMAKE_COMMAND) -P CMakeFiles/FATES_rad_test.dir/cmake_clean.cmake +.PHONY : unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/clean + +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/depend: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /Users/afoster/Documents/ncar/CTSM/src/fates /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/radiation_test /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/depend + diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/cmake_clean.cmake b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/cmake_clean.cmake new file mode 100644 index 0000000000..6b7063ba42 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/cmake_clean.cmake @@ -0,0 +1,13 @@ +file(REMOVE_RECURSE + "CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o" + "CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o" + "CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o" + "CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o" + "FATES_rad_test" + "FATES_rad_test.pdb" +) + +# Per-language clean rules from dependency scanning. +foreach(lang Fortran) + include(CMakeFiles/FATES_rad_test.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/cmake_clean_Fortran.cmake b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/cmake_clean_Fortran.cmake new file mode 100644 index 0000000000..bd62e20bc8 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/cmake_clean_Fortran.cmake @@ -0,0 +1,14 @@ +# Remove fortran modules provided by this target. +FILE(REMOVE + "fatesconstantsmod.mod" + "FATESCONSTANTSMOD.mod" + "CMakeFiles/FATES_rad_test.dir/fatesconstantsmod.mod.stamp" + + "fatesunittestiomod.mod" + "FATESUNITTESTIOMOD.mod" + "CMakeFiles/FATES_rad_test.dir/fatesunittestiomod.mod.stamp" + + "fatesunittestorbitalmod.mod" + "FATESUNITTESTORBITALMOD.mod" + "CMakeFiles/FATES_rad_test.dir/fatesunittestorbitalmod.mod.stamp" + ) diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/compiler_depend.make b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/compiler_depend.make new file mode 100644 index 0000000000..80afc53fef --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/compiler_depend.make @@ -0,0 +1,2 @@ +# Empty compiler generated dependencies file for FATES_rad_test. +# This may be replaced when dependencies are built. diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/compiler_depend.ts b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/compiler_depend.ts new file mode 100644 index 0000000000..57ac27d1ed --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/compiler_depend.ts @@ -0,0 +1,2 @@ +# CMAKE generated file: DO NOT EDIT! +# Timestamp file for compiler generated dependencies management for FATES_rad_test. diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/depend.internal b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/depend.internal new file mode 100644 index 0000000000..46ca19ac45 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/depend.internal @@ -0,0 +1,11 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.25 + +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o + /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/radiation_test/FatesUnitTestRadiation.F90 +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o + /Users/afoster/Documents/ncar/CTSM/src/fates/main/FatesConstantsMod.F90 +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o + /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestIOMod.F90 +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o + /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestOrbitalMod.F90 diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/depend.make b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/depend.make new file mode 100644 index 0000000000..daa358a424 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/depend.make @@ -0,0 +1,27 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.25 + +# Note that incremental build could trigger a call to cmake_copy_f90_mod on each re-build +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestiomod.mod.stamp +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestorbitalmod.mod.stamp +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o.provides.build: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesconstantsmod.mod.stamp +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesconstantsmod.mod.stamp: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o + $(CMAKE_COMMAND) -E cmake_copy_f90_mod unit_testing/test/radiation_test/fatesconstantsmod.mod unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesconstantsmod.mod.stamp GNU +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o.provides.build: + $(CMAKE_COMMAND) -E touch unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o.provides.build +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o.provides.build +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesconstantsmod.mod.stamp +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o: /usr/local/Cellar/netcdf-fortran/4.6.0/include/netcdf.mod +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o.provides.build: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestiomod.mod.stamp +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestiomod.mod.stamp: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o + $(CMAKE_COMMAND) -E cmake_copy_f90_mod unit_testing/test/radiation_test/fatesunittestiomod.mod unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestiomod.mod.stamp GNU +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o.provides.build: + $(CMAKE_COMMAND) -E touch unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o.provides.build +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o.provides.build +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestiomod.mod.stamp +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o.provides.build: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestorbitalmod.mod.stamp +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestorbitalmod.mod.stamp: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o + $(CMAKE_COMMAND) -E cmake_copy_f90_mod unit_testing/test/radiation_test/fatesunittestorbitalmod.mod unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestorbitalmod.mod.stamp GNU +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o.provides.build: + $(CMAKE_COMMAND) -E touch unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o.provides.build +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o.provides.build diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesconstantsmod.mod.stamp b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesconstantsmod.mod.stamp new file mode 100644 index 0000000000000000000000000000000000000000..2b4ac0b598d43fed2ea70fd8680dacf9fc821b43 GIT binary patch literal 2256 zcmV;>2ru^^iwFP!000006WyF!bDKyO$KUxByvcshRA0C>Z}O&`Dc2-U%Hy4V>}sHq zh`49~dB*eU_aF%b5>3#qW4q%@QtE~%{L+{6?{neTk6#`hA8zi=G!M6lG@oQq#(8GW zust(_LW)X;W>n;<`4K*rAM&iML{^ob^YE9C9x|@3uFaSDWi%hI4fr_lo0zjeBuO4{ z;g?(%MPAIzSyVq%&^#0{K;O*7=GE2Ln}?gvw~x0E#=q}>yZ`c^`}y7dfGIkAkz+JPx`r*s{?~ga|mA(7S z&V4iVi)HzYL;`ufEo^HscV|X@?dtmQC5Mmb+Mqy~626fIPsubkv(IMyuWaTCn=y@z zxELLO7S_x>Lo;@0R*gpYXjBWd$Rbt;%~qn>fR=AJi41whx0_0=<&Ouf|H`lM71rU| zn|8f?&S&Sy-8C#3V1wxnY)*%5!-G8C@DdhboGpL+((666ar)2~BH{+oI9+t^5pnag z4IeXSp?EHL%dV7x7V9n`L|Qg-T*5qyE#_x?iqVXm*P(lsVxl#8V?6AH-5rxEw-pSx zhcYX9RLFA0llaeV9P+;aP!F?5CF_H#tRBV(94?-gJW9lpCo)@BE6uhTs@!5QX$XUr z4Ay)j3X#Hstn?U26huri#|d5JvISx4k)#dhYP)=eUGycaeD??7Y)84>V5^~vvxy`3 zZcN0GFx#65Y&TR%o-KJ<6=2-;T!7f~c9_P{)N~rmOLWX1HxG9=|N33OClm174A zWLbzO4#$D1Tgn@=dBO1~L<_8D1O2fQI(dg27W&K=fs0Y#TZ{SGxE*ICsE}2X@|7r_ zWLa@hNC5{Q5ma%WX=WMJt_I@tDFadX+Tp3~9s$h~2cmX@ZKfVl-;GTeT6cTZLRf=U zR(bIX_WYHcLj+_>9EqgV&EIuq*jgkCSL3SK>PDoVd=$jUx4o(Urp2B=*;G>yA?v*g z(L;n-n0eH-{J;@zRBL3VHKVjeOXX7Nfj52NK!+q!fCb}u6#YCa%|2pHw8`&=O1;Tb zkQ_-`z~jq=i)tNbTvj6C1Y!555gyd-Ko-wnsjI%aDa*u{R61aH%G6=Xn@PIFKgkVc@htBP_Cm z<_~8vKeKX2G}@r0dZ0~LT^8t)RQ$b(baO}IvzSwBzAX?XsZJt!vWm2vmP`{T1@!No>NYKCL&- zL+~Q%JC-eQAOge|NSTIU;~uC!DKnV#qHsh_SPPUqt5%vNKL!0TqdL}M*D__Z4|Z(y zIP+Yv5J9M995_}*&cnE@wuLXUK=J?}mw6G(a+KImAzw6Kjd4|Sfrc@Z9*7;SUDJmC ziu-Xk4)*?}nOd3I&JGJkk5|u|?~K^{0~@k}2Qaq=D@0hQXGoD=g7=?gGop=u?drp z3=T+^%_^_*@)^tm7eSE3Dc?IZ*V|NpSX*tgrEHzIo{HZXydV$sMEj4?Y5tr4~6fS}nFKvTs2#Z@pmjGW!$yR1w^ z2R^6fi(#92j&k7C&Vi<`Uji{xEJew`@ikxTa;7K96|U{uE|tQ!M#3i!>)`1^$85xq z6Gee!IAmkn3dotF%=`q-@n9KX1?o}3gt6y(9>XM*0^`N}EY-9XY%bhi%3!ByLZL^h zFt#z9q-k7ygiGUB2&un>$?JJ27DKA#07rIkc^1N^$pt7gIL*s)l_#$txL?54WXp-J zCYN?VwX_cEU@$9|_wi7S%+r{abqrF(yv?Gg4sZ+5?zX5pR-LkT5R< z+6Fl37%1qNy5vHOjQz`sE?f{YFl0|L9RKvL#8$gzTu?LHCIF+2Sfjot0@04*Q1#Qn zWOyCCR2#gh(KCj+c$&~ncF-`qrwe$M^Yu~>AxbF|g!;_281?01uC8rmAZO|*QmK^` z^(hM?&qoM8grm73_4{K6-X4QY(tqU&GHL%sCCIdlf!BK=(;j&<1~Q$2mrB4ya!=pK zfJ}Dw5(8vH$hNk?&~A%Zhw44+f4(gU-B(INPg^_LDK3OzI;lC_e?P%Sr;ZKUq+k67J+xOd z1syP)BZWqAgFRfM16Q10c?&%LvEb!U83JAGSX2QmudPRbnT5Kk{LqG{KPJFKo1A8i zLm%zuT0@W3OH+mp7!h@bFI;zqlVjnE+si9O-9*#%VKsRD97b3UsGs-;J-C}K2W?_> zQp})Dk9k?pvbq^f(6)PdK+xfIvS;8wd7n+wwJXraPBS&2&l^c^K&ROc&1y3D$pR;# zbm%7i05tSaYiH$DYzHW<@^3!c#nhrp(TE)OEW z--2m4?th1SNY`}@Z944m1+o)g@TRk6?%k+8HzRa9XC6A#ciSDtcjxOm^#(z=cj7{U zT^1RA#{+cXk>fgCCIg3D=!PLzoDbpR(BZK;Rl#NZcosqXlZi^c!_DrQ@`X-zrWetP eh}_@UD6gY7fj)d@(4muD8~+8>o>chnO#lFlSy+$& literal 0 HcmV?d00001 diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestiomod.mod.stamp b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestiomod.mod.stamp new file mode 100644 index 0000000000000000000000000000000000000000..bac5e8f68dbed86771ad6e160e953b2ced9f2e29 GIT binary patch literal 24087 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 P!!w~bQoeT*Pci-nwC<&` literal 0 HcmV?d00001 diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestorbitalmod.mod.stamp b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestorbitalmod.mod.stamp new file mode 100644 index 0000000000000000000000000000000000000000..cb85e3a79588da53be704d893829e4e21f8807ee GIT binary patch literal 25076 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%0Du&QhFE5>J z@qm#f^qT%-Xcx;+#dvXn!mXv@p8{v4{Cgx`%Z#5Z%gvwWB)W^G&&q2XJ2>uASUaBw z>=TRjOyLBnvG}8$4wNDGN(Zg+CEf-mCTA+psgMyBiScuVxhrmDjiEc%S;T2@tzq(% zzlSJv1{HigH^SgaN&b_r{zq+#)|;m^d|q1aKr&%S>`R%F)=u*fmKyr;Jm38>f#-d6 zOp(cQqOIpWHs&1fvZK3wi^&-2$Y7nv@e1Gl8NtinS^yu<^oQ!cW&+@nP+#C zXZs1|E_a3hHCBVFpWAms6r22?&8G1V%PPbi|8Um6@BN7ddJtUO1XmLDs3!{{(GjyY z3L9FB1XWO!EklJH$?Sl@6MIJ8k73X>w%Yc!ZjB1HkNQoe@^Ak)1YZ@^Gp4K|$f&Es z3rOHySsdc$?hTw3BGV7n7b^oZHa1I%;-gR-)RE-6p~K4q0r)Cgc_pS>nA1=ZD9k)! zkNd4|;mgKrm>-1Z^pM7H^$DF-MgG_-w_EE;ol(yoY^~Y#{28DxBTMjCBf+3lmjP7scLQufA5=fC55Qx zoxP?t1-x=|xzJ8d-l76%C10kGz5F+uxBg;p6%S>v&8DbjBB6D@y-l`^M5$PdoIgAg zEx!8WGg&LMOzKAWo{oYi1G@g=h zk)r6daKm96g%EEm`%FhdohoK*J9sE@B;JSF9qB>tEe_b+X*|JBpk7jj=dUXLy`zY}OqXasvzmY(}{MS)@)s zR;)i=;o10)ABgHbzT^m;JAb|U-m87)^KlaSYYCZoG5;SEM`@FIOIE=kn4)gs0w<6@ zCr1})2>AaRaYCc`WMlF4kZD1s?Xw;VL65^gW-5W(nV9)CXy+hcWXRlu6@PF@-h%ySL5zFE<8i3VB`GSI z`c+*sCqu@4c_CPf%8qo$D#>Xnta0sd?o0UaI=@!s_IG-c;%etR@*|wZc?m9M%PXx3 z7Q&n5r^eQ+qC2%kuoBMt=}aLn=&siwiytoM=I=XZgO@>@{J||gpQWV6nGR-0oTMw&IKTa|CI8Gs{AnLn;)~0uM1#$tbm%=fB_0(YX zUXE76!M=sZpe_4Z+QrfoW*F^`7eB$mkg>n1gzw*t+J0)qXZYS`+$Z^GC5g>?ZL71` zx*LYJ<%cqif(2TEkLC4X)>LI3y=SC@(9nLz*Kk^s;5HeJlXsiXm>LmH#j|}#FW#aU z$xvFKB7Vj)?E+3X?W_fN+fbfPz-#S`*RLg3jG z2@$fsRn1%`YI6r-QuHe>J>?wj6hA#P`mr8Ci)%c-?q4~Qa32%y-a1}Sl+tRmt3ep4 zbR44Leg>W@YQ616SyLb1kn`VK;v${AKWtgO-QV?neyKX{y6USDZ==Ow=snkw0%85r zZ3g!F1FTQ#t?(M|Tgtfldf^1cLBxugY#hz1*YV6 z)>om>Xz>iGqH|#om3VM`sNRnriWt!^e zkeAz>KA{TskPldkPhXfa?dyFEXc804#e)6Il1p)|;D}h{>GO|LMQ!*uR9|~z?uP(#j_5eC>bSG%3VitE+e%&wqM2uh!NpboYZz}TuWuBVdbjw$UR97<OBC6=o2|hZGhBlnW zXmZuKUdah}(B08M0m+b(68kD@%vVxYV1)X%zvPaC1O5 z7!M7381wte(4EaZTsa->IMg-up4pL|NrFSnA@Q6}WYeI?w9?GQFfvHA$+rYLrq%c0 z0yCm3EM4eIR&z6rS-QD{2_XZ$NcSW4QntzDXtkG}&bzmRX(l3TS|tPTRi*toj+o^$ z{alts$qB3Z-wjR}dduIt$@HU@vg|N6^r0f$U8A*{w#*gI;kWe<#pe=%;--&_M?z$D z{tEb-eqlZ`%$EL3zvo}}i<423lZRaT3sJ_1O*yQ;Q3=(n$j^`+MCS}Kj zEKJ^=4PU3D@g|Cs_8xF_Rer9T;iKnXpa>Yj^WnUnhj*V5q8$^miT9i8POeV%bc{_$ z=17cXZr6z>WLBD}OH$>aTeBa|0G=1x+QUhp5!=Yg*F=+RB-R^vWDk|o;+ zt;c-~&b0uz&m_6ic3yR6=O%pKtjDZ#$-Xr zn2RQW10a{8Ybv{a{zpd~a`iI386kM+F3BAs^9!Y!ue;dq<1lPYE+W#BhMKQKdxuRX zWBZ3qg42H(bcua9S?N$R_$ve>+n!jLm4mX-xo6@aHx*iDLJe29^E4`RGGk%1xbYg6B1Wah`#$l1o(-|po# z5>D7lw1AVX&x~8MDNV{Zzw5^eE^ zA?MO;rez{`kBAjjcH4%QG_(|*`<-Eh_f0gLOQ zK9HDESP}Cf!eWkJg74pMynjY<_M)=m3s_Z;wN^qPeEm0_0OXRK`YCKmaqC2GKnJDd z?;dkgYjJlX#TY{l30gAsICuSE@8y@$Fx5>-98EhKi5p2flBmNm%*EnDHPpC$NYJOS z_Td3~F}wsXx(c22pCBWV9_kI2^l`O~4)e7fQD~^Y>OSTe>b={O9PE|Z65OdoM|d3- z85r#KHG;oG`JhnmD&aNVex59_-owT zH6?y_wuqdK^ap$r0iU#^;EsdMy8%i0a(l|37NEhDgU6}-_L$5}?$z4; zz)-UwfjO5wHgJ7qeV?4S0CiTXw*d7ux}OnLO8O?e9u~j6PsHwBq)XLI_}RVM;Qe-2 zXc-BXhsLE6Z`iS+Ij9-8ydNJl*yQ~NI3ZBU8w7sWq4NKE9BZHB2^0Y8=Dc~$+b&P! zVR5NY89r}lmTTrNPs9fY{hGJ}FLL~1^a7i`TnF@Fs!J8PT=#E8eSQGh|DGL<#Ev?N zg&bQOv20RPd&0Lt$MkXtP}cQ>M~@-m^vu_wVaDfR@Dax6pa|sr@I0?>Pw=c(a3F&D z1rs|4%-LRpuaO>MJmfEd0#Cb*{`u>Jd}q8Z*n-_DuLe^9=5526EJx(Y)!eoPoys8* z4FAn@8sK9f=yqGF`?LT5Y9IKoJpl7f;%;-1crbc4&aXcTFxj1OAVbXprv#b9^aFEW zb|X{SeR!6kFnRdQlY~h`rFOW9pn`2%I|`!pLre z2Kt@=M|xh|h=KE51qWM)xHSy2Qu^yS-B&vnBU|oeGvR6PvR9yC1hw`Ip9kTeZBl9vjdTDkcr9m=SW{!RoT0k zB8!1!(RsueOMq$2wXByK~2jKRjoJRt(TD(&W6V)8<)VXvpclRSv9&2HrM2|zzEsT18)9N*0ek^K02Kf(R4lfM3o;eT0_O&5 zYKZ9Qzd$T8J{W*uvJZ1aEUlK-<&)F`p$`B+mG;At*pT*^c3-E7FSvVA!9k(zFa5`O zd){22i&npgRZO#b6D6w-N8%)^4uKG^$pk{UhV}NrnUu`BnHI>oHK*XFS``^A6v)`p zMf$;`rmk#xl3o8Cx-29VIg0dwoLi_bxg|Jjh92uaB2tj0jusY(t->)tJ>(uvnck*< zLA2ovm1=CIz=FqICOto2|rp8~a4K{Kut7-G@B;mO?4!Q%#81)Fr=#oBP9iIicNt`+9*WHP|Qmu`FKV_*0brG3hW*gl5oe*nqstgWj5 zxbt=!D)^)gXUmZ@^^^= z+ttUBhXA(I6l(T#_ekDlp8leymTI^&CWZ>Vc)~CPv+!JH42yeYpV|B>b^Sm;!w&`9 z{j{EKCngM^X(w_$aahZ@W@6PU%%K~RuL`zk2k?qMK!iC=o=X;?hfqthD{t>$p|pUD z&OH~$`(HqY{f=qZ?rzc14Cj<~sEx4mv;K>W7g~5)j}$Xig%VRylQz;-j=;fh1ux09 zfuKBeXJT1_n~No|qBL~3hgpvM(54yiOt1pzioz2x1aOvN%9ie5yr3@D(ACCP;}@88 z4*qq+u-;u1h_JGUd<&BQXU8(Td_diA3#HMO4n($3pOHP=dBPvX*bESFJ4w=Av?~b;baOU;fqddd1_= zSokjBtOQ~53=hUKeydzft{}(!C$}KhX=twTdziCQeqOzyfJ5s>JGU^IKGJZBCOLf% zycL<=P}4c95kOv6;y{+4LB8trc?_!!+V$s`W_d6?I%0uaIoViz?jGNO<;#N#An%`w z^)GFh3|)LU(2zpRwu9+r29f4mtgrBwo<~gbYQW+(gsKiC{ETv5V3o+3%G{t*(H2|m z*vmIM(SsO$l_cHdAm_Jn@m>m9r-YENIAdcN>$ECfwWbfDiCLcFQ&3sIg|yl_I1^qZCH#bzyw;)RZ3)!9yIfQp2Dq$KCC| zD6C~xG|hm1rC|pv>KnLuFk78N>2AQGk4lv|W8?YS#YC-xX%FZp?Pg%2Qzfzh{j@tS zQO@v3E3^oBt~GcbHLzbPf@+Hs0lz8~8x+PW?Ip{oSa*!3ObI}l+F;H^8#GzW1HU9w zf>E@E7^oQ$8L+|Zu>D1UDrm(qH3wbexJhpHULuHQ-ff$(Y?z6`XW(!BPkf~Tv$$mV z4TYA7N5h{65mv*0Lci)m#UpdOF5xhco+@jH9{@2Gik zPtAi($h!D+(5?XGy5|ZjT-Y423Ijk06E+u-r6|R`N!5lV_8I~;1Z-{xoB#%FCCqJ1 z@i{OF7NFbnpWYM6!)g<5OWPQ$?a4>E=cb0JGC_t8x6@#0M~tXt zuj526?hM6hV=CE!tO2%ckhW1GM%|i)oW1EDg`7fD_d)L2$7FZ&mAWE)3P1>+akJ2Q zYeiK$Ku<^EopA3STznVsl;%?y78&4G03z4z`<h^YTLXc*2ju=4s9PmKr=+$3Gdf{A`SWyp_$846PUG&!eVSv{=&Y{Fy z;=2j3C-aA@bJ)fipj*!)frZVfe;3uS5E{}&_C*xyvBZ{HWJK^SUA59|DAmUWmV7ts ze=JE01I_{Tal3nc{UPeC)4~8Uq(K4CstN!8ye+MjrHldnMar)^8t%-TqvfM|wE+|M zAO8!OnH<>1?MOpB5a3w<&C2wljL0FX$jaY$f9V=Wt@4iWKVx0(TIF6E=bq(W3itFd z9CJ~42pk(0q`aVz=7TFoD{;201j_V zc-L!nRiDOgGe@H`RaJ)09*+kz>4Kzho)Klvq!9>6(?%d5fzqC&X``Sh`%+W79T1R| zXLaaF7rkJdzFRY-RRVvw)+tc6%-n!s0B|n_z^0WMhj@fF6sC4;P!LyHd~h&(84*QC@a;gJpWrj^p}cfx7SDGQ|qtDMj9$-fBZy!00=9yItLIo zQjs1GC^zBf<*E&zK!)Q5jwN|bd2kPHmlU!#ijse@8e|82^2{%y)i4uDlHITdN| z)@D4|tt`Lf0Eq9B1DKe{o&#oI1O?gN$AmpkELeu;fBGxMCl8qAiAP|TDYk=?+g5TC zQ+)ujl;T6h{F^Q}_7Qt;SbSYFP($L1Ec!;lLkGhb$am`ZK)%zE$iw(QEnH<-98HiW z!QI^w>4pLqJf5D;q%YQ2*?LQ;B_6+gN zDNrARtCD6ym*+ZGO)qm{;`2BFTg_9{BX-c>=7sGXgRxLV47Y$bm zG;jwn@kHI)6p|Mz%J6YX!BMBq2|o95awQKZD^_)r(m!X&N!X)p()uPIE>1-P16dhIyE?}n2VtDOnipUvM$?%_LextBDqwMM{VQC+q9WhV^*`S~Bq z%TBnu!O0Z;W#>P2d)cRxUZaY7m67P)4p4!cslazlFS6LabMHZuwwcVnbBn&%fpZI) zxL){KO#iul$l!0w%T~Bw@VFr;DF3)|9C+|?aQXAE$ARwkmwx+;s~2au`PT5j5qoWV zhsRZ9GGAIc2drljfykL!_!o28jlJ zLOIt|TQPJio1hD^9vGOq)t(MdI%8YS_;vvHEJ|S|zOp92A>+IJIu~a)sxo(Ob#+daZ)na%QtFy6R_?0*_PEl2h)ByM6;_!mYx8r%_GiZa+t<_G<4ZKi{v~1{ zi4y(E`k*4!PPPrn>cRm&#+`!&l9nXzRoj9>N$%V!*z!Wj8jq6%hom3;c};+D`*}wh zY}StA*$V^p5AF5G$qetwP7?A7v$}r*+VIPQ6lbiyu~D(<%l>Fn8SCIvoR9p`-{>9F z_p>k~SL4h23xMP4tGAFK368rc=xuZ8`L+Lafq=gcHteS*PdiMQ$3JZKA(K)<;^x+? zT0?U&ZNzaJTiYdU?Kvhic=aX!Gso)sI)RLpjO6*+4MjY@sz?fpu}R1Qwkq+@AjGKu zPUck)la1T_OdXLSCD-bL?PV+4wZyvITzy2j6bMgWD?nQtR_e-rM+8^|=-LWAE$-N6 zAjKMW%{ST#>P}4|tM}XTFIMyB#aB=S`ZUs44!P-1ubeJz)EWvLVJuGijD6ie-91zp zm)d*a;ZqaQkS)ZecykX#ayTXMjDgrwFHc0(p%SIW(3r-UWgV{+kF_o%IzuPce{`)M z)!RK~vT!F6HpaCKb)_#HXo`joUe+B=!3EVK=SojD=rvomfGkmODo=<_X%z`Me8d4}{Kw;~1zN~NMh_PPj5w>PX5%5X#pO2bL?eyk7k)Nrj%E;F4~0gCY*$Q23HVwujd+8=w5L7fhkbfX^Ev59*H!fw;;gzi*BQvs|ET zb1`Ty-G&+;DfFsg29*{H3KB)kU*8} z?>g*WYEu(zTvBAzp!?Xrm8>7p+ufZs_>K%>5n-oJ7rdcQrGuZqj8ATQsaPSswPCDi zh8O)~1}qaHO-{T-Oq$iJ(^|&qz(%DUjupghmr%DN);wOMZ&S`vprD!5Jj|y+MWvhw zzvPrqXO%$XB&%toXjPEthGme`{3S9t`0&sFx@fC;i4`ANNNJ2Q#@rHOb1`|L3eHYk znY?KIT?*6xcg-RO4Z<4{Q5}R0WpH*XN`VMQ?f}A_K^bCLL-m>wz>?lxou07L1VKR% z3ptW0h=rTI7o55F>KQ<4-U*vRM`+k9yKRYLo^RFz^X%VCsrvDQqa zQuKlqzu~izW(}W}+CMTp*MT#Q$JedaOcT6`ak=;+P-XacjKRMH&Z)<%fh%ZQ8qXjy z<0=;Bf2lvw*WG=!@{SB~Uq34A_>H9W|FOw{XN~R8dq;zys#G8O|KEpXY9|6 za{OpUk%v4A-e>^rl#I4i&{}xLBC{P9e_O~*PG(vIPN)`to0*uNpk~Tv%6DClYPfC*RmS zgno0wJmeAK(C6maD}ZACrI&>hHw|xF1EK8i-?lpiLoY82B!%7G-__vnU4N4BZ;*$M z0%dx-j{~pYObcin!d`e=o)u~o?Sh$l?}!jed--|%+X$9N(GnEx;P`&FJWO`0&)Dfm ziH?eUaSLaO+x|b6>d~JPgeJZif#$NK(X=e zdl>Le8>hV<&N0ua@x^1CW{6R zlhzh|=@c!j#M}p9W-=lalSK$%5C*1AM`#}y0!bzt+>fZO<-48&7DU=P($ZD%y}5EV zu}TR>R={4Zd6@fjyxJwB#WlSldm%CVSU_*d+oBbl3getxFF$#YLM_+f1Em_KN=62( z5&lp&{AgB8^v3P0?9A=I112r8rA6>Ey+br0Vrb}MdVvHHSy&iWST`BJ3Kz*UE5{ym za>a((^q^iyE;{l(m6S#$-R9>2umA62iWTkFSE>fGHGBe+qgdE!1thC1v|-}!*du3q zs5==;4i2Oa4A@gpqMw|?Yw_IuB4eesbF-&3_d#Y3u2W*e3>ETEkGZ?~7W-*PHa42&Q-c-=RZOlzPD=txfXli&c@#fB0J% zpK^0kfLth^<{H+60X*c~fOTsZzK6K>F(}4} zj)}!MWEe}*%JO}Y)qp{Z&@2k4MxSCrf=e>s!xvM5VNXAC>y`WE!99ASGSs9kmXy@M zO5U{7#dxO+lSQP#{M=FC7I&GZYqm4_DZ2$cF1+{qayviGQubGpO%}PZH=Vt5NTRXn zVuTw5Rh2HZaOP~6nIF$WmlwDKP|!=Ov$G4a0|uW~*fI+u^~QX4iZ)m3?+3jsyPC?yAnv0vL<2vp zyyGxR66`Li9;KRxrwT54Ss{05KLUbPqK159f~6X*>ILPo420m`zkv`L$(pzr&CE>w z#T5;yw){_7=Cz;u!#@}j=lp)0?vwc$OCIxkl7npRgMSn!HbK5W2=@Zkf);RFpun&ATX>xK+mB3b_MvlJU5KS4^AF+hs$fJ0;%6#<&6TQ1t5!7 zs9Q!Z5lVl>1%Q!dCkcZ)o96U9U`_dU4g!h-O;LFk#yy49f4S zvxrU!UJIT(Ibp=X0eJM_lwNTuO93C$QX)HBjlN@#mos4&Jeql?=`EQ{x#dI5ql$%E zQw!%b9^6uCVy6begi@HoD9xKp$x*{OKVqA1cbQb-c6Nkq0rb+$_1a>p`}7=02D)=2 zG`Dhcy0zYJHw@Fj(g!0WcvyHLL;ZvM)u7F*CUKE+RkLFsJ=ux+xmK_Nq&$&Z7MX_- z-m9YJx@Pz@|L_Pmy#aJ|wR!RMFu0=F_sL?Yg^c767`g=)BokHH_2*DRu*>gjyZbw` z5mZ8-C7bsIyp3O3vNDJ7$O=FHJ9v6X+U0oE*vr#lVeD1RvW^oFHR=k2TBno7xTp}# zAsHEDp-5~byjH_ZVe01uBn~+EL8Tlc)1F>$MFV`Xhho0G8hmXMLJW+)+!$wcTWe+L zY4boI1Jj_G{^D@b2}jslDY4ae;5$cJ<;nP2WhtoKWYq$VcbZgzqr+jrCQ{4~Z0Q*v z&7%5UX(Zbb;4pGSMzNzY)=&(NI<F;{<*L!=MZA6`-XAfli-rpym=^U%q3x}Y2Wm{9k z+lHOrwi5&=Nq=oDgLOa$=Dwt0#_(-y4Z6*$`gxQ}U~}^PKwTd6fvpXHy1o$8Hgn6Q zj?MW8NgWxA=>m}1f^4dpa{Egg=4d?@w|)y-GaAay9Yt(ET6R)G0sn$X1*}BaPPDPliR==_fp5M@cL+x@>1Um@v`hbGH&Xs z_dl7;MmG;>*aaW2BSrF?AM3~vVwctCZ|n9mQ9wSX3BIkV{Mniyk>i=es%9S{gV^KM zFicpVq5JaK%wCch?|GnHIMav^=k=%ADP#o|Bu+XInqk$9F9+B4^qqhpk|9>RN5C*Sm8)bR-OwU1L~)^_y2{#t&rGayv;|)ceN3cRJ^^fbL;rC{oV9HJ%3upC%J#U-g*m0vjL!I9AMAzH|yzRS%yUtFNpVa?hcr8b6 z{r(mfhJ_(-1^5xqQLTzyeddJ*so)k=#j}nFR{Y+z6MqESyXJ1LSE1xe|1);qF0TW< zc`He01oK-DIewN^`rh0D?Y`M=tOqBb(3XSii*kn@#KlChzu9PCu}LKmANjAup~U^? z&CM_siGec8XMNBIG=7Lh-%BwLn|5`3msdb0&^i<9RAFa{EOG9ON7lH+$z}dW$Z~sE z9!Z(1+40K~Sp@wXLOF^^4gxIID?J9X**bL5nvWHMh%hN#<)0%cyGKkRM3o>sN657U zQ%DjuQ*UyWfrF&HZXV|#8skHd8!sOn0gmp>claiDiF5`qNG_eB-rbvQ-}0!op1g&C z9}4lK3JoM`A0yTb(bJTuUe=Fy(&5OI_>7{6>Nb2?CzgSdOKxAF+%^02@p;6d;fbqz z3u)$4CbPuoyr-`CL^8E#6V9g|A!9DyJwmsTB1x{Yad`$RtI!UrH2(2-43H!@5~VM% zLNp?ya2N_;CQ_fd69kEhp!IVt8n4tXrqC~-y+7^RDu4@xipaa~!vdKlL5cx)WC*1G zAW=d-EMlPgbf91D5yuwzr&@x`W2nzbLqDacc9nmEk2Az2IV5SrcXWs-I-^nb>BV;++C{8ag^F3mpd#=n@%>+N}*BkeLzQ zr|VD6-IWbvO>2F|YnvaFm8*PuUq#9Sguw(-ZuageCzw=~v~18Y^SHH9ps?^2z2(iCayx zS0~&w6`)jgi91OdX=MC646Wdvhg8!pMC+0whgb&C!)jgu`zhA7Y z?>=&VNS0Dak=*jD8MtN^-J-vnu&zaYto7U|t6Bp!lC-7oA`m5q(in%L%Qo&(Tl!uG~F}Nwl8w zwCRCKWu4v&BIb}hvm#NIT1DQwvEf;o070ToK-ALAGwgv>d2}E<&;AtIbEa8`zZLg> zKboPk)BSePgh21hee^STSe!c>6p(sN{Ah zu^uz?PVC^pr>w7LkS06aRc{FJpCthT*XyoslF}aVUz0!Vv36khuirxFiv7qrdjO^U zW712DP}cA{e?6(Hb@goh2dG0!zvH+=vf0GQ<-aceed6-aO7V&13$qEx){{s!&xIya z{rR}VU!n<_Q!jkE!K{%b)nb~GC4qfQ>_t-pA72!XvAoNs2j<;grE`g@`h0MHX{SPf zX#S$4P8X$703t1O0H8?xbswnl@h3MVT!Agb*!4f9x>r1o=2qDg)N@C^j;5|Z*eVCIG0adiytKU^b|2ahuaj)%7H)1 zeAil;C211K&iUmx(?zc-@+>>+4n9u=295HS$wac|hBy@o$^T z(oWsXQ&SCl?kCD$U6uD9p*wT5t`_(wrQ#(;3U8wA@(=Gk=JvwMlki>}Mp?QQ99S8r z?g}vClgoEX&hp@X=(iZh;@NbqYg%;%OY@1bAd!hs;P+?5xq0(?#yIVC6AJ`1@Szgd zn_(D&?Xfs__Iw|vHUuH1_Xz)HLW`!e|Mm-8`nhc-+x-W-%w6gFEZ;McoHe$E^pi%C zO2pRzE=Eo$GuqdUY#Lk|xgolY@5r1Fx*Xy~6WWw+G+Dzq% z*Fpw-LE~$)=Ew#6xi`#=HrXbH7!~jRyh}Ff7-=gqSp>m@a<=^7(v$Nea}6(H+rdK0 zLX2_79oSrPkZX!>jaSJAOKXj%QDpZcqn9C;krf_u-??N=&&b{{M3@4$fS7?6@g(e4 zl25$81Y>yrJpWxbCuS>Y<%AN_4qD`klg{h>Y`kH1p~{WuSYv(s#2P?p2^uD1B-qig z5sAIjTHC_fU~xXa?K<7(kxAS&lrk|)o88DYOp^>ljWcu3iS2{AAa?C1Q|__KA<}9` zEwrjVGA~kaTY^p*Z~9y&fO7L>l2D?`XGcjEKgwd&%jViM>iiBod9j#<(!LCPqO zJA4+8-K_!`qO=uJM?DNrEu1QOENMH)?g8zi!gC+``{^!{!PU#!d{njjc@ND0xqLig zO*L&4&+fRhiGG=pFre+4eoy}nYg_=x!Eesao9JDRxvysOHpcX^+0T^cg1 z(<@-9hs>#-lvBFoY3%JMcyfD>7k$EI}2=_D5oLOGXxAvo}gG}<$&J+!$`63~hT0!hB-xK82<-J(4) zn@uh6&SBvqV(i(P^CGoPj}v$Hb@hs^)ZyP4b4ZmU;ds)g>bbg-A4nbNpt+ugI4)yG zXmiCMzf@ahSjfnd;Yjm!1EC$PdBh(T6shuW!sQraZHT*h0^`|#Om~LKVJtTi2cTM0 z`(Ap)eb>fiU9hGFq;FYbEXZR_kvyo=LXx{`G;eP;Ig#BFr literal 0 HcmV?d00001 diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/flags.make b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/flags.make new file mode 100644 index 0000000000..0dcb8e6e9a --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/flags.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.25 + +# compile Fortran with /usr/local/bin/gfortran +Fortran_DEFINES = + +Fortran_INCLUDES = -I/Users/afoster/pFUnit/include -I/Users/afoster/pFUnit/mod -I/usr/local/Cellar/netcdf/4.9.2/include -I/usr/local/Cellar/netcdf-fortran/4.6.0/include + +Fortran_FLAGS = -DCESMCOUPLED -DFORTRANUNDERSCORE -DNO_R16 -DCPRGNU -fconvert=big-endian -ffree-line-length-none -ffixed-line-length-none -g -Wall -Og -fbacktrace -ffpe-trap=zero,overflow -fcheck=bounds -fallow-argument-mismatch -fallow-invalid-boz -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk + diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fortran.internal b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fortran.internal new file mode 100644 index 0000000000..8030915fe2 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fortran.internal @@ -0,0 +1,5 @@ +# The fortran modules provided by this target. +provides + fatesconstantsmod.mod + fatesunittestiomod.mod + fatesunittestorbitalmod.mod diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/link.txt b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/link.txt new file mode 100644 index 0000000000..2d1f965f41 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/link.txt @@ -0,0 +1 @@ +/usr/local/bin/gfortran -framework Accelerate -DCESMCOUPLED -DFORTRANUNDERSCORE -DNO_R16 -DCPRGNU -fconvert=big-endian -ffree-line-length-none -ffixed-line-length-none -g -Wall -Og -fbacktrace -ffpe-trap=zero,overflow -fcheck=bounds -fallow-argument-mismatch -fallow-invalid-boz -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o -o FATES_rad_test -L/usr/local/Cellar/netcdf/4.9.2/lib -L/usr/local/Cellar/netcdf-fortran/4.6.0/lib diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/progress.make b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/progress.make new file mode 100644 index 0000000000..33e6bffba3 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/progress.make @@ -0,0 +1,6 @@ +CMAKE_PROGRESS_1 = 1 +CMAKE_PROGRESS_2 = 2 +CMAKE_PROGRESS_3 = 3 +CMAKE_PROGRESS_4 = 4 +CMAKE_PROGRESS_5 = 5 + diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/progress.marks b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/progress.marks new file mode 100644 index 0000000000..7ed6ff82de --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/progress.marks @@ -0,0 +1 @@ +5 diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CTestTestfile.cmake b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CTestTestfile.cmake new file mode 100644 index 0000000000..cb5f7e2cb4 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CTestTestfile.cmake @@ -0,0 +1,8 @@ +# CMake generated Testfile for +# Source directory: /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/radiation_test +# Build directory: /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test +# +# This file includes the relevant testing commands required for +# testing this directory and lists subdirectories to be tested as well. +add_test(rad_test "FATES_rad_test") +set_tests_properties(rad_test PROPERTIES _BACKTRACE_TRIPLES "/Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/radiation_test/CMakeLists.txt;37;add_test;/Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/radiation_test/CMakeLists.txt;0;") diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/Makefile b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/Makefile new file mode 100644 index 0000000000..f12b8509d6 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/Makefile @@ -0,0 +1,274 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.25 + +# Default target executed when no arguments are given to make. +default_target: all +.PHONY : default_target + +# Allow only one "make -f Makefile2" at a time, but pass parallelism. +.NOTPARALLEL: + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Disable VCS-based implicit rules. +% : %,v + +# Disable VCS-based implicit rules. +% : RCS/% + +# Disable VCS-based implicit rules. +% : RCS/%,v + +# Disable VCS-based implicit rules. +% : SCCS/s.% + +# Disable VCS-based implicit rules. +% : s.% + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/local/Cellar/cmake/3.25.2/bin/cmake + +# The command to remove a file. +RM = /usr/local/Cellar/cmake/3.25.2/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target test +test: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests..." + /usr/local/Cellar/cmake/3.25.2/bin/ctest --force-new-ctest-process $(ARGS) +.PHONY : test + +# Special rule for the target test +test/fast: test +.PHONY : test/fast + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." + /usr/local/Cellar/cmake/3.25.2/bin/ccmake -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache +.PHONY : edit_cache/fast + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." + /usr/local/Cellar/cmake/3.25.2/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache +.PHONY : rebuild_cache/fast + +# The main all target +all: cmake_check_build_system + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test//CMakeFiles/progress.marks + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/test/radiation_test/all + $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles 0 +.PHONY : all + +# The main clean target +clean: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/test/radiation_test/clean +.PHONY : clean + +# The main clean target +clean/fast: clean +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/test/radiation_test/preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/test/radiation_test/preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 +.PHONY : depend + +# Convenience name for target. +unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/rule: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/rule +.PHONY : unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/rule + +# Convenience name for target. +FATES_rad_test: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/rule +.PHONY : FATES_rad_test + +# fast build rule for target. +FATES_rad_test/fast: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build +.PHONY : FATES_rad_test/fast + +FatesUnitTestRadiation.o: FatesUnitTestRadiation.F90.o +.PHONY : FatesUnitTestRadiation.o + +# target to build an object file +FatesUnitTestRadiation.F90.o: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o +.PHONY : FatesUnitTestRadiation.F90.o + +FatesUnitTestRadiation.i: FatesUnitTestRadiation.F90.i +.PHONY : FatesUnitTestRadiation.i + +# target to preprocess a source file +FatesUnitTestRadiation.F90.i: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.i +.PHONY : FatesUnitTestRadiation.F90.i + +FatesUnitTestRadiation.s: FatesUnitTestRadiation.F90.s +.PHONY : FatesUnitTestRadiation.s + +# target to generate assembly for a file +FatesUnitTestRadiation.F90.s: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.s +.PHONY : FatesUnitTestRadiation.F90.s + +__/__/__/main/FatesConstantsMod.o: __/__/__/main/FatesConstantsMod.F90.o +.PHONY : __/__/__/main/FatesConstantsMod.o + +# target to build an object file +__/__/__/main/FatesConstantsMod.F90.o: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o +.PHONY : __/__/__/main/FatesConstantsMod.F90.o + +__/__/__/main/FatesConstantsMod.i: __/__/__/main/FatesConstantsMod.F90.i +.PHONY : __/__/__/main/FatesConstantsMod.i + +# target to preprocess a source file +__/__/__/main/FatesConstantsMod.F90.i: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.i +.PHONY : __/__/__/main/FatesConstantsMod.F90.i + +__/__/__/main/FatesConstantsMod.s: __/__/__/main/FatesConstantsMod.F90.s +.PHONY : __/__/__/main/FatesConstantsMod.s + +# target to generate assembly for a file +__/__/__/main/FatesConstantsMod.F90.s: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.s +.PHONY : __/__/__/main/FatesConstantsMod.F90.s + +__/__/utils/FatesUnitTestIOMod.o: __/__/utils/FatesUnitTestIOMod.F90.o +.PHONY : __/__/utils/FatesUnitTestIOMod.o + +# target to build an object file +__/__/utils/FatesUnitTestIOMod.F90.o: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o +.PHONY : __/__/utils/FatesUnitTestIOMod.F90.o + +__/__/utils/FatesUnitTestIOMod.i: __/__/utils/FatesUnitTestIOMod.F90.i +.PHONY : __/__/utils/FatesUnitTestIOMod.i + +# target to preprocess a source file +__/__/utils/FatesUnitTestIOMod.F90.i: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.i +.PHONY : __/__/utils/FatesUnitTestIOMod.F90.i + +__/__/utils/FatesUnitTestIOMod.s: __/__/utils/FatesUnitTestIOMod.F90.s +.PHONY : __/__/utils/FatesUnitTestIOMod.s + +# target to generate assembly for a file +__/__/utils/FatesUnitTestIOMod.F90.s: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.s +.PHONY : __/__/utils/FatesUnitTestIOMod.F90.s + +__/__/utils/FatesUnitTestOrbitalMod.o: __/__/utils/FatesUnitTestOrbitalMod.F90.o +.PHONY : __/__/utils/FatesUnitTestOrbitalMod.o + +# target to build an object file +__/__/utils/FatesUnitTestOrbitalMod.F90.o: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o +.PHONY : __/__/utils/FatesUnitTestOrbitalMod.F90.o + +__/__/utils/FatesUnitTestOrbitalMod.i: __/__/utils/FatesUnitTestOrbitalMod.F90.i +.PHONY : __/__/utils/FatesUnitTestOrbitalMod.i + +# target to preprocess a source file +__/__/utils/FatesUnitTestOrbitalMod.F90.i: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.i +.PHONY : __/__/utils/FatesUnitTestOrbitalMod.F90.i + +__/__/utils/FatesUnitTestOrbitalMod.s: __/__/utils/FatesUnitTestOrbitalMod.F90.s +.PHONY : __/__/utils/FatesUnitTestOrbitalMod.s + +# target to generate assembly for a file +__/__/utils/FatesUnitTestOrbitalMod.F90.s: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.s +.PHONY : __/__/utils/FatesUnitTestOrbitalMod.F90.s + +# Help Target +help: + @echo "The following are some of the valid targets for this Makefile:" + @echo "... all (the default if no target is provided)" + @echo "... clean" + @echo "... depend" + @echo "... edit_cache" + @echo "... rebuild_cache" + @echo "... test" + @echo "... FATES_rad_test" + @echo "... FatesUnitTestRadiation.o" + @echo "... FatesUnitTestRadiation.i" + @echo "... FatesUnitTestRadiation.s" + @echo "... __/__/__/main/FatesConstantsMod.o" + @echo "... __/__/__/main/FatesConstantsMod.i" + @echo "... __/__/__/main/FatesConstantsMod.s" + @echo "... __/__/utils/FatesUnitTestIOMod.o" + @echo "... __/__/utils/FatesUnitTestIOMod.i" + @echo "... __/__/utils/FatesUnitTestIOMod.s" + @echo "... __/__/utils/FatesUnitTestOrbitalMod.o" + @echo "... __/__/utils/FatesUnitTestOrbitalMod.i" + @echo "... __/__/utils/FatesUnitTestOrbitalMod.s" +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/cmake_install.cmake b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/cmake_install.cmake new file mode 100644 index 0000000000..7f8055d555 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/cmake_install.cmake @@ -0,0 +1,39 @@ +# Install script for directory: /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/radiation_test + +# Set the install prefix +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "/usr/local") +endif() +string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + if(BUILD_TYPE) + string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + else() + set(CMAKE_INSTALL_CONFIG_NAME "CESM_DEBUG") + endif() + message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +endif() + +# Set the component getting installed. +if(NOT CMAKE_INSTALL_COMPONENT) + if(COMPONENT) + message(STATUS "Install component: \"${COMPONENT}\"") + set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + else() + set(CMAKE_INSTALL_COMPONENT) + endif() +endif() + +# Is this installation the result of a crosscompile? +if(NOT DEFINED CMAKE_CROSSCOMPILING) + set(CMAKE_CROSSCOMPILING "FALSE") +endif() + +# Set default install directory permissions. +if(NOT DEFINED CMAKE_OBJDUMP) + set(CMAKE_OBJDUMP "/usr/bin/objdump") +endif() + diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/utils/CMakeFiles/CMakeDirectoryInformation.cmake b/build/__command_line_test__/__command_line_test__/unit_testing/utils/CMakeFiles/CMakeDirectoryInformation.cmake new file mode 100644 index 0000000000..0626f191b1 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/utils/CMakeFiles/CMakeDirectoryInformation.cmake @@ -0,0 +1,16 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.25 + +# Relative path conversion top directories. +set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/Users/afoster/Documents/ncar/CTSM/src/fates") +set(CMAKE_RELATIVE_PATH_TOP_BINARY "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__") + +# Force unix paths in dependencies. +set(CMAKE_FORCE_UNIX_PATHS 1) + + +# The C and CXX include file regular expressions for this directory. +set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") +set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") +set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) +set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/utils/CMakeFiles/progress.marks b/build/__command_line_test__/__command_line_test__/unit_testing/utils/CMakeFiles/progress.marks new file mode 100644 index 0000000000..573541ac97 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/utils/CMakeFiles/progress.marks @@ -0,0 +1 @@ +0 diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/utils/CTestTestfile.cmake b/build/__command_line_test__/__command_line_test__/unit_testing/utils/CTestTestfile.cmake new file mode 100644 index 0000000000..6e2fdc5a3d --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/utils/CTestTestfile.cmake @@ -0,0 +1,6 @@ +# CMake generated Testfile for +# Source directory: /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils +# Build directory: /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/utils +# +# This file includes the relevant testing commands required for +# testing this directory and lists subdirectories to be tested as well. diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/utils/Makefile b/build/__command_line_test__/__command_line_test__/unit_testing/utils/Makefile new file mode 100644 index 0000000000..b1f822e9bf --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/utils/Makefile @@ -0,0 +1,151 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.25 + +# Default target executed when no arguments are given to make. +default_target: all +.PHONY : default_target + +# Allow only one "make -f Makefile2" at a time, but pass parallelism. +.NOTPARALLEL: + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Disable VCS-based implicit rules. +% : %,v + +# Disable VCS-based implicit rules. +% : RCS/% + +# Disable VCS-based implicit rules. +% : RCS/%,v + +# Disable VCS-based implicit rules. +% : SCCS/s.% + +# Disable VCS-based implicit rules. +% : s.% + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/local/Cellar/cmake/3.25.2/bin/cmake + +# The command to remove a file. +RM = /usr/local/Cellar/cmake/3.25.2/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target test +test: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests..." + /usr/local/Cellar/cmake/3.25.2/bin/ctest --force-new-ctest-process $(ARGS) +.PHONY : test + +# Special rule for the target test +test/fast: test +.PHONY : test/fast + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." + /usr/local/Cellar/cmake/3.25.2/bin/ccmake -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache +.PHONY : edit_cache/fast + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." + /usr/local/Cellar/cmake/3.25.2/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache +.PHONY : rebuild_cache/fast + +# The main all target +all: cmake_check_build_system + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/utils//CMakeFiles/progress.marks + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/utils/all + $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles 0 +.PHONY : all + +# The main clean target +clean: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/utils/clean +.PHONY : clean + +# The main clean target +clean/fast: clean +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/utils/preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/utils/preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 +.PHONY : depend + +# Help Target +help: + @echo "The following are some of the valid targets for this Makefile:" + @echo "... all (the default if no target is provided)" + @echo "... clean" + @echo "... depend" + @echo "... edit_cache" + @echo "... rebuild_cache" + @echo "... test" +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/utils/cmake_install.cmake b/build/__command_line_test__/__command_line_test__/unit_testing/utils/cmake_install.cmake new file mode 100644 index 0000000000..42c88ffb10 --- /dev/null +++ b/build/__command_line_test__/__command_line_test__/unit_testing/utils/cmake_install.cmake @@ -0,0 +1,39 @@ +# Install script for directory: /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils + +# Set the install prefix +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "/usr/local") +endif() +string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + if(BUILD_TYPE) + string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + else() + set(CMAKE_INSTALL_CONFIG_NAME "CESM_DEBUG") + endif() + message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +endif() + +# Set the component getting installed. +if(NOT CMAKE_INSTALL_COMPONENT) + if(COMPONENT) + message(STATUS "Install component: \"${COMPONENT}\"") + set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + else() + set(CMAKE_INSTALL_COMPONENT) + endif() +endif() + +# Is this installation the result of a crosscompile? +if(NOT DEFINED CMAKE_CROSSCOMPILING) + set(CMAKE_CROSSCOMPILING "FALSE") +endif() + +# Set default install directory permissions. +if(NOT DEFINED CMAKE_OBJDUMP) + set(CMAKE_OBJDUMP "/usr/bin/objdump") +endif() + diff --git a/build/cmake_macros/CMakeLists.txt b/build/cmake_macros/CMakeLists.txt new file mode 100644 index 0000000000..c2ebcb51be --- /dev/null +++ b/build/cmake_macros/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_policy(SET CMP0057 NEW) +cmake_minimum_required(VERSION 3.5) +project(cime LANGUAGES C Fortran) +include(../Macros.cmake) diff --git a/build/cmake_macros/CNL.cmake b/build/cmake_macros/CNL.cmake new file mode 100644 index 0000000000..7202f78196 --- /dev/null +++ b/build/cmake_macros/CNL.cmake @@ -0,0 +1,14 @@ +set(CMAKE_OPTS "-DCMAKE_SYSTEM_NAME=Catamount") +string(APPEND CPPDEFS " -DLINUX") +if (COMP_NAME STREQUAL gptl) + string(APPEND CPPDEFS " -DHAVE_NANOTIME -DBIT64 -DHAVE_VPRINTF -DHAVE_BACKTRACE -DHAVE_SLASHPROC -DHAVE_COMM_F2C -DHAVE_TIMES -DHAVE_GETTIMEOFDAY") +endif() +set(MPICC "cc") +set(MPICXX "CC") +set(MPIFC "ftn") +set(NETCDF_PATH "$ENV{NETCDF_DIR}") +set(PIO_FILESYSTEM_HINTS "lustre") +set(PNETCDF_PATH "$ENV{PARALLEL_NETCDF_DIR}") +set(SCC "cc") +set(SCXX "CC") +set(SFC "ftn") diff --git a/build/cmake_macros/Darwin.cmake b/build/cmake_macros/Darwin.cmake new file mode 100644 index 0000000000..89fd4bdc07 --- /dev/null +++ b/build/cmake_macros/Darwin.cmake @@ -0,0 +1 @@ +string(APPEND CPPDEFS " -DSYSDARWIN") diff --git a/build/cmake_macros/Macros.cmake b/build/cmake_macros/Macros.cmake new file mode 100644 index 0000000000..b089f58058 --- /dev/null +++ b/build/cmake_macros/Macros.cmake @@ -0,0 +1,37 @@ +# +# Use this file to include the relevant macros based on +# machine/compiler settings. This file gets copied to CASEROOT +# and that's the one that gets included by the build system. Feel free +# to modify this file in the CASEROOT. +# +set(MACROS_DIR ${CASEROOT}/cmake_macros) + +set(UNIVERSAL_MACRO ${MACROS_DIR}/universal.cmake) +set(COMPILER_MACRO ${MACROS_DIR}/${COMPILER}.cmake) +set(OS_MACRO ${MACROS_DIR}/${OS}.cmake) +set(MACHINE_MACRO ${MACROS_DIR}/${MACH}.cmake) +set(COMPILER_OS_MACRO ${MACROS_DIR}/${COMPILER}_${OS}.cmake) +set(COMPILER_MACHINE_MACRO ${MACROS_DIR}/${COMPILER}_${MACH}.cmake) + +if (CONVERT_TO_MAKE) + get_cmake_property(VARS_BEFORE_BUILD_INTERNAL_IGNORE VARIABLES) +endif() + +# Include order defines precedence +foreach (MACRO_FILE ${UNIVERSAL_MACRO} ${COMPILER_MACRO} ${OS_MACRO} ${MACHINE_MACRO} ${COMPILER_OS_MACRO} ${COMPILER_MACHINE_MACRO}) + if (EXISTS ${MACRO_FILE}) + include(${MACRO_FILE}) + else() + message("No macro file found: ${MACRO_FILE}") + endif() +endforeach() + +if (CONVERT_TO_MAKE) + get_cmake_property(VARS_AFTER VARIABLES) + + foreach (VAR_AFTER IN LISTS VARS_AFTER) + if (NOT VAR_AFTER IN_LIST VARS_BEFORE_BUILD_INTERNAL_IGNORE) + message("CIME_SET_MAKEFILE_VAR ${VAR_AFTER} := ${${VAR_AFTER}}") + endif() + endforeach() +endif() diff --git a/build/cmake_macros/arm.cmake b/build/cmake_macros/arm.cmake new file mode 100644 index 0000000000..e69de29bb2 diff --git a/build/cmake_macros/armgcc.cmake b/build/cmake_macros/armgcc.cmake new file mode 100644 index 0000000000..e69de29bb2 diff --git a/build/cmake_macros/athena.cmake b/build/cmake_macros/athena.cmake new file mode 100644 index 0000000000..e69de29bb2 diff --git a/build/cmake_macros/bluewaters.cmake b/build/cmake_macros/bluewaters.cmake new file mode 100644 index 0000000000..e69de29bb2 diff --git a/build/cmake_macros/casper.cmake b/build/cmake_macros/casper.cmake new file mode 100644 index 0000000000..e69de29bb2 diff --git a/build/cmake_macros/centos7-linux.cmake b/build/cmake_macros/centos7-linux.cmake new file mode 100644 index 0000000000..4dc3995df5 --- /dev/null +++ b/build/cmake_macros/centos7-linux.cmake @@ -0,0 +1 @@ +string(APPEND SLIBS " -L$(NETCDF_PATH)/lib -Wl,-rpath,$(NETCDF_PATH)/lib -lnetcdff -lnetcdf") diff --git a/build/cmake_macros/cheyenne.cmake b/build/cmake_macros/cheyenne.cmake new file mode 100644 index 0000000000..35c2d3c33e --- /dev/null +++ b/build/cmake_macros/cheyenne.cmake @@ -0,0 +1,6 @@ +if (COMP_NAME STREQUAL gptl) + string(APPEND CPPDEFS " -DHAVE_NANOTIME -DBIT64 -DHAVE_VPRINTF -DHAVE_BACKTRACE -DHAVE_SLASHPROC -DHAVE_COMM_F2C -DHAVE_TIMES -DHAVE_GETTIMEOFDAY") +endif() +set(NETCDF_PATH "$ENV{NETCDF}") +set(PIO_FILESYSTEM_HINTS "gpfs") +set(PNETCDF_PATH "$ENV{PNETCDF}") diff --git a/build/cmake_macros/container.cmake b/build/cmake_macros/container.cmake new file mode 100644 index 0000000000..82b8a1428d --- /dev/null +++ b/build/cmake_macros/container.cmake @@ -0,0 +1,7 @@ +if (COMP_NAME STREQUAL gptl) + string(APPEND CPPDEFS " -DHAVE_NANOTIME -DBIT64 -DHAVE_VPRINTF -DHAVE_BACKTRACE -DHAVE_SLASHPROC -DHAVE_COMM_F2C -DHAVE_TIMES -DHAVE_GETTIMEOFDAY") +endif() +set(NETCDF_PATH "/usr/local") +set(PNETCDF_PATH "/usr/local") +set(LDFLAGS "") +string(APPEND SLIBS " -lnetcdf -lnetcdff -llapack -lblas") diff --git a/build/cmake_macros/cray.cmake b/build/cmake_macros/cray.cmake new file mode 100644 index 0000000000..89c27843d7 --- /dev/null +++ b/build/cmake_macros/cray.cmake @@ -0,0 +1,37 @@ +if (NOT compile_threaded) + string(APPEND CFLAGS " -h noomp") +endif() +if (compile_threaded) + string(APPEND CFLAGS " -fopenmp") +endif() +if (DEBUG) + string(APPEND CFLAGS " -g -O0") +endif() +if (NOT DEBUG) + string(APPEND CFLAGS " -O2") +endif() +string(APPEND CPPDEFS " -DFORTRANUNDERSCORE -DNO_R16 -DCPRCRAY") +if (COMP_NAME STREQUAL pop) + string(APPEND CPPDEFS " -DDIR=NOOP") +endif() +if (COMP_NAME STREQUAL moby) + string(APPEND CPPDEFS " -DDIR=NOOP") +endif() +set(FC_AUTO_R8 "-s real64") +string(APPEND FFLAGS " -f free -N 255 -h byteswapio -x dir -ef") +if (NOT compile_threaded) + string(APPEND FFLAGS " -h noomp") +endif() +if (compile_threaded) + string(APPEND FFLAGS " -h omp") +endif() +if (DEBUG) + string(APPEND FFLAGS " -g -O0 -K trap=fp -m1") +endif() +if (NOT DEBUG) + string(APPEND FFLAGS " -O2,ipa2 -em") +endif() +set(FFLAGS_NOOPT "-O1,fp2,ipa0,scalar0,vector0") +set(HAS_F2008_CONTIGUOUS "TRUE") +set(LDFLAGS "-Wl,--allow-multiple-definition -h byteswapio") +string(APPEND LDFLAGS " -h omp") diff --git a/build/cmake_macros/cray_daint.cmake b/build/cmake_macros/cray_daint.cmake new file mode 100644 index 0000000000..5929a1be65 --- /dev/null +++ b/build/cmake_macros/cray_daint.cmake @@ -0,0 +1,2 @@ +string(APPEND FFLAGS " -I/project/s824/edavin/OASIS3-MCT_2.0/build.cray/build/lib/mct -I/project/s824/edavin/OASIS3-MCT_2.0/build.cray/build/lib/psmile.MPI1") +string(APPEND SLIBS " -L/project/s824/edavin/OASIS3-MCT_2.0/build.cray/lib -lpsmile.MPI1 -lscrip -lmct_oasis -lmpeu_oasis") diff --git a/build/cmake_macros/euler2.cmake b/build/cmake_macros/euler2.cmake new file mode 100644 index 0000000000..63ca8a325f --- /dev/null +++ b/build/cmake_macros/euler2.cmake @@ -0,0 +1,5 @@ +string(APPEND CPPDEFS " -DLINUX") +set(NETCDF_PATH "$ENV{NETCDF}") +set(PIO_FILESYSTEM_HINTS "lustre") +set(PNETCDF_PATH "$ENV{PNETCDF}") +set(SLIBS "-L$ENV{NETCDF}/lib -lnetcdf -lnetcdff") diff --git a/build/cmake_macros/euler3.cmake b/build/cmake_macros/euler3.cmake new file mode 100644 index 0000000000..63ca8a325f --- /dev/null +++ b/build/cmake_macros/euler3.cmake @@ -0,0 +1,5 @@ +string(APPEND CPPDEFS " -DLINUX") +set(NETCDF_PATH "$ENV{NETCDF}") +set(PIO_FILESYSTEM_HINTS "lustre") +set(PNETCDF_PATH "$ENV{PNETCDF}") +set(SLIBS "-L$ENV{NETCDF}/lib -lnetcdf -lnetcdff") diff --git a/build/cmake_macros/euler4.cmake b/build/cmake_macros/euler4.cmake new file mode 100644 index 0000000000..63ca8a325f --- /dev/null +++ b/build/cmake_macros/euler4.cmake @@ -0,0 +1,5 @@ +string(APPEND CPPDEFS " -DLINUX") +set(NETCDF_PATH "$ENV{NETCDF}") +set(PIO_FILESYSTEM_HINTS "lustre") +set(PNETCDF_PATH "$ENV{PNETCDF}") +set(SLIBS "-L$ENV{NETCDF}/lib -lnetcdf -lnetcdff") diff --git a/build/cmake_macros/frontera.cmake b/build/cmake_macros/frontera.cmake new file mode 100644 index 0000000000..bbdb959a39 --- /dev/null +++ b/build/cmake_macros/frontera.cmake @@ -0,0 +1,9 @@ +set(HAS_F2008_CONTIGUOUS "TRUE") +if (COMP_NAME STREQUAL gptl) + string(APPEND CPPDEFS " -DHAVE_NANOTIME -DBIT64 -DHAVE_VPRINTF -DHAVE_BACKTRACE -DHAVE_SLASHPROC -DHAVE_COMM_F2C -DHAVE_TIMES -DHAVE_GETTIMEOFDAY") +endif() +set(NETCDF_PATH "$ENV{TACC_NETCDF_DIR}") +set(PIO_FILESYSTEM_HINTS "lustre") +set(PNETCDF_PATH "$ENV{TACC_PNETCDF_DIR}") +string(APPEND LDFLAGS " -Wl,-rpath,${NETCDF_PATH}/lib") +string(APPEND SLIBS " -L${NETCDF_PATH}/lib -lnetcdff -lnetcdf") diff --git a/build/cmake_macros/gnu.cmake b/build/cmake_macros/gnu.cmake new file mode 100644 index 0000000000..621740c595 --- /dev/null +++ b/build/cmake_macros/gnu.cmake @@ -0,0 +1,43 @@ +string(APPEND CFLAGS " -std=gnu99") +if (compile_threaded) + string(APPEND CFLAGS " -fopenmp") +endif() +if (DEBUG) + string(APPEND CFLAGS " -g -Wall -Og -fbacktrace -ffpe-trap=invalid,zero,overflow -fcheck=bounds") +endif() +if (NOT DEBUG) + string(APPEND CFLAGS " -O") +endif() +string(APPEND CPPDEFS " -DFORTRANUNDERSCORE -DNO_R16 -DCPRGNU") +set(CXX_LINKER "FORTRAN") +set(FC_AUTO_R8 "-fdefault-real-8 -fdefault-double-8") +string(APPEND FFLAGS " -fconvert=big-endian -ffree-line-length-none -ffixed-line-length-none") +if (compile_threaded) + string(APPEND FFLAGS " -fopenmp") +endif() +if (DEBUG) + string(APPEND FFLAGS " -g -Wall -Og -fbacktrace -ffpe-trap=zero,overflow -fcheck=bounds") +endif() +if (NOT DEBUG) + string(APPEND FFLAGS " -O") +endif() +set(FFLAGS_NOOPT "-O0") +set(FIXEDFLAGS "-ffixed-form") +set(FREEFLAGS "-ffree-form") +set(HAS_F2008_CONTIGUOUS "FALSE") +if (compile_threaded) + string(APPEND LDFLAGS " -fopenmp") +endif() +set(MPICC "mpicc") +set(MPICXX "mpicxx") +set(MPIFC "mpif90") +set(SCC "gcc") +set(SCXX "g++") +set(SFC "gfortran") +set(SUPPORTS_CXX "TRUE") + +message("C compiler version is ${CMAKE_C_COMPILER_VERSION}") +message("Fortran compiler version is ${CMAKE_Fortran_COMPILER_VERSION}") +if (CMAKE_Fortran_COMPILER_VERSION VERSION_GREATER_EQUAL 10) + string(APPEND FFLAGS " -fallow-argument-mismatch -fallow-invalid-boz ") +endif() diff --git a/build/cmake_macros/gnu_cheyenne.cmake b/build/cmake_macros/gnu_cheyenne.cmake new file mode 100644 index 0000000000..988fbb33be --- /dev/null +++ b/build/cmake_macros/gnu_cheyenne.cmake @@ -0,0 +1,4 @@ +if (COMP_NAME STREQUAL pio1) + string(APPEND CPPDEFS " -DNO_MPIMOD") +endif() +string(APPEND SLIBS " -ldl") diff --git a/build/cmake_macros/gnu_coeus.cmake b/build/cmake_macros/gnu_coeus.cmake new file mode 100644 index 0000000000..f2c24ef9e8 --- /dev/null +++ b/build/cmake_macros/gnu_coeus.cmake @@ -0,0 +1,2 @@ +set(NETCDF_PATH "/vol/apps/hpc/stow/netcdf/4.4.1.1/gcc-6.3.0") +set(SLIBS "-L${NETCDF_PATH}/lib -lnetcdf -lnetcdff -lpmi") diff --git a/build/cmake_macros/gnu_fleabone.cmake b/build/cmake_macros/gnu_fleabone.cmake new file mode 100644 index 0000000000..d2f1e44096 --- /dev/null +++ b/build/cmake_macros/gnu_fleabone.cmake @@ -0,0 +1,27 @@ +set(NETCDF_C_PATH "/usr/local/Cellar/netcdf/4.9.2") +set(NETCDF_FORTRAN_PATH "/usr/local/Cellar/netcdf-fortran/4.6.0") + +# These LDFLAGS provide lapack and blas support on a Mac. This may require installation of +# the Apple Developer Tools. +string(APPEND LDFLAGS " -framework Accelerate") + +#string(APPEND FFLAGS " -Wunused") + +# Trying to produce a backtrace leads to a hang, so don't even try +#string(APPEND CFLAGS " -fno-backtrace") +#string(APPEND FFLAGS " -fno-backtrace") + +# This is needed to run the Fortran unit tests; +# this isn't needed to build and run CESM. +#if (MPILIB STREQUAL mpi-serial AND NOT compile_threaded) +set(PFUNIT_PATH "/Users/afoster/pFUnit/") +#endif() + +# Most of the following paths aren't necessary on my machine because I have my PATH set so +# that the right compilers are picked up by default. But it doesn't hurt to be explicit. +set(SFC "/usr/local/bin/gfortran") +set(SCC "/usr/bin/gcc") +set(SCXX "/usr/bin/g++") +set(MPIFC "/usr/local/bin/mpif90") +set(MPICC "/usr/local/bin/mpicc") +set(MPICXX "/usr/local/bin/mpic++") diff --git a/build/cmake_macros/gnu_hobart.cmake b/build/cmake_macros/gnu_hobart.cmake new file mode 100644 index 0000000000..35929dcc37 --- /dev/null +++ b/build/cmake_macros/gnu_hobart.cmake @@ -0,0 +1 @@ +string(APPEND SLIBS " -lm -ldl") diff --git a/build/cmake_macros/gnu_homebrew.cmake b/build/cmake_macros/gnu_homebrew.cmake new file mode 100644 index 0000000000..9e468c1276 --- /dev/null +++ b/build/cmake_macros/gnu_homebrew.cmake @@ -0,0 +1 @@ +string(APPEND LDFLAGS " -framework Accelerate -Wl,-rpath $(NETCDF)/lib") diff --git a/build/cmake_macros/gnu_lobata.cmake b/build/cmake_macros/gnu_lobata.cmake new file mode 100644 index 0000000000..60aeb9c8a8 --- /dev/null +++ b/build/cmake_macros/gnu_lobata.cmake @@ -0,0 +1,15 @@ +set(SUPPORTS_CXX "TRUE") +if (COMP_NAME STREQUAL gptl) + string(APPEND CPPDEFS " -DHAVE_VPRINTF -DHAVE_TIMES -DHAVE_GETTIMEOFDAY -DHAVE_BACKTRACE") +endif() +string(APPEND SLIBS " -L$ENV{NETCDF_FORTRAN_PATH}/lib/ -lnetcdff -L$ENV{NETCDF_C_PATH}/lib/ -lnetcdf -lcurl -llapack -lblas") +if (DEBUG) + string(APPEND FFLAGS " -g -fbacktrace -fbounds-check -ffpe-trap=invalid,zero,overflow") +else() + string(APPEND FFLAGS " -fno-unsafe-math-optimizations") +endif() +if (MPILIB STREQUAL mpi-serial) + set(SCC "gcc") + set(SFC "gfortran") +endif() +string(APPEND CXX_LIBS " -lstdc++") diff --git a/build/cmake_macros/gnu_melvin.cmake b/build/cmake_macros/gnu_melvin.cmake new file mode 100644 index 0000000000..668d542c96 --- /dev/null +++ b/build/cmake_macros/gnu_melvin.cmake @@ -0,0 +1,13 @@ +set(ALBANY_PATH "/projects/install/rhel6-x86_64/ACME/AlbanyTrilinos/Albany/build/install") +if (NOT DEBUG) + string(APPEND CFLAGS " -O2") +endif() +set(CONFIG_ARGS "--host=cray") +set(CXX_LIBS "-lstdc++ -lmpi_cxx") +if (NOT DEBUG) + string(APPEND FFLAGS " -O2") +endif() +set(NETCDF_PATH "$ENV{NETCDFROOT}") +set(PNETCDF_PATH "$ENV{PNETCDFROOT}") +execute_process(COMMAND ${NETCDF_PATH}/bin/nf-config --flibs OUTPUT_VARIABLE SHELL_CMD_OUTPUT_BUILD_INTERNAL_IGNORE0 OUTPUT_STRIP_TRAILING_WHITESPACE) +string(APPEND SLIBS " ${SHELL_CMD_OUTPUT_BUILD_INTERNAL_IGNORE0} -lblas -llapack") diff --git a/build/cmake_macros/gnu_modex.cmake b/build/cmake_macros/gnu_modex.cmake new file mode 100644 index 0000000000..83a692512a --- /dev/null +++ b/build/cmake_macros/gnu_modex.cmake @@ -0,0 +1,5 @@ +string(APPEND SLIBS " -L$ENV{HDF5_HOME}/lib -lhdf5_fortran -lhdf5 -lhdf5_hl -lhdf5hl_fortran") +string(APPEND SLIBS " -L$ENV{NETCDF_PATH}/lib/ -lnetcdff -lnetcdf -lcurl -lblas -llapack") +if (COMP_NAME STREQUAL gptl) + string(APPEND CPPDEFS " -DHAVE_VPRINTF -DHAVE_GETTIMEOFDAY -DHAVE_BACKTRACE") +endif() diff --git a/build/cmake_macros/gust.cmake b/build/cmake_macros/gust.cmake new file mode 100644 index 0000000000..5332d19c9e --- /dev/null +++ b/build/cmake_macros/gust.cmake @@ -0,0 +1,10 @@ +if (COMP_NAME STREQUAL gptl) + string(APPEND CPPDEFS " -DHAVE_NANOTIME -DBIT64 -DHAVE_VPRINTF -DHAVE_BACKTRACE -DHAVE_SLASHPROC -DHAVE_COMM_F2C -DHAVE_TIMES -DHAVE_GETTIMEOFDAY") +endif() +set(NETCDF_PATH "$ENV{NETCDF}") +set(PIO_FILESYSTEM_HINTS "lustre") +set(PNETCDF_PATH "$ENV{PNETCDF}") +# If we want to use cray-libsci instead of mkl uncomment this line as well as the module in config_machines.xml +#string(REPLACE "-mkl=cluster" "" SLIBS "${SLIBS}") +string(REPLACE "-mkl=cluster" "-qmkl=cluster" SLIBS "${SLIBS}") +#string(APPEND CPPDEFS " -DNO_SHR_VMATH ") \ No newline at end of file diff --git a/build/cmake_macros/hobart.cmake b/build/cmake_macros/hobart.cmake new file mode 100644 index 0000000000..8894b6a383 --- /dev/null +++ b/build/cmake_macros/hobart.cmake @@ -0,0 +1,9 @@ +if (COMP_NAME STREQUAL gptl) + string(APPEND CPPDEFS " -DHAVE_NANOTIME -DBIT64 -DHAVE_VPRINTF -DHAVE_BACKTRACE -DHAVE_SLASHPROC -DHAVE_COMM_F2C -DHAVE_TIMES -DHAVE_GETTIMEOFDAY") +endif() +set(LAPACK_LIBDIR "/usr/lib64") +if (MPILIB STREQUAL mvapich2) + set(MPI_LIB_NAME "mpich") +endif() +set(NETCDF_PATH "$ENV{NETCDF_PATH}") +string(APPEND SLIBS " -L${NETCDF_PATH}/lib -lnetcdff -lnetcdf") diff --git a/build/cmake_macros/ibm.cmake b/build/cmake_macros/ibm.cmake new file mode 100644 index 0000000000..37daaf31e5 --- /dev/null +++ b/build/cmake_macros/ibm.cmake @@ -0,0 +1,38 @@ +string(APPEND CFLAGS " -g -qfullpath -qmaxmem=-1") +if (NOT DEBUG) + string(APPEND CFLAGS " -O3") +endif() +if (compile_threaded) + string(APPEND CFLAGS " -qsmp=omp") +endif() +if (DEBUG AND compile_threaded) + string(APPEND CFLAGS " -qsmp=omp:noopt") +endif() +string(APPEND CPPDEFS " -DFORTRAN_SAME -DCPRIBM") +set(CPRE "-WF,-D") +set(FC_AUTO_R8 "-qrealsize=8") +string(APPEND FFLAGS " -g -qfullpath -qmaxmem=-1") +if (NOT DEBUG) + string(APPEND FFLAGS " -O2 -qstrict -qinline=auto") +endif() +if (compile_threaded) + string(APPEND FFLAGS " -qsmp=omp") +endif() +if (DEBUG) + string(APPEND FFLAGS " -qinitauto=7FF7FFFF -qflttrap=ov:zero:inv:en") +endif() +if (DEBUG AND compile_threaded) + string(APPEND FFLAGS " -qsmp=omp:noopt") +endif() +if (DEBUG AND COMP_NAME STREQUAL pop) + string(APPEND FFLAGS " -C") +endif() +set(FIXEDFLAGS "-qsuffix=f=f -qfixed=132") +set(FREEFLAGS "-qsuffix=f=f90:cpp=F90") +set(HAS_F2008_CONTIGUOUS "TRUE") +if (compile_threaded) + string(APPEND LDFLAGS " -qsmp=omp") +endif() +if (DEBUG AND compile_threaded) + string(APPEND LDFLAGS " -qsmp=omp:noopt") +endif() diff --git a/build/cmake_macros/ibm_AIX.cmake b/build/cmake_macros/ibm_AIX.cmake new file mode 100644 index 0000000000..ec2293afb9 --- /dev/null +++ b/build/cmake_macros/ibm_AIX.cmake @@ -0,0 +1,18 @@ +string(APPEND CFLAGS " -qarch=auto -qtune=auto -qcache=auto") +set(CONFIG_SHELL "/usr/bin/bash") +string(APPEND FFLAGS " -qarch=auto -qtune=auto -qcache=auto -qsclk=micro") +if (COMP_NAME STREQUAL cam) + string(APPEND FFLAGS " -qspill=6000") +endif() +if (DEBUG) + string(APPEND LDFLAGS " -qsigtrap=xl__trcedump") +endif() +string(APPEND LDFLAGS " -bdatapsize:64K -bstackpsize:64K -btextpsize:32K") +set(MPICC "mpcc_r") +set(MPIFC "mpxlf2003_r") +set(SCC "cc_r") +set(SFC "xlf2003_r") +string(APPEND SLIBS " -lmassv -lessl") +if (NOT DEBUG) + string(APPEND SLIBS " -lmass") +endif() diff --git a/build/cmake_macros/ibm_BGQ.cmake b/build/cmake_macros/ibm_BGQ.cmake new file mode 100644 index 0000000000..0f113a90fe --- /dev/null +++ b/build/cmake_macros/ibm_BGQ.cmake @@ -0,0 +1,11 @@ +set(CONFIG_ARGS "--build=powerpc-bgp-linux --host=powerpc64-suse-linux") +string(APPEND CPPDEFS " -DLINUX") +string(APPEND FFLAGS " -g -qfullpath -qmaxmem=-1 -qspillsize=2500 -qextname=flush") +if (NOT DEBUG) + string(APPEND FFLAGS " -O3 -qstrict -qinline=auto") +endif() +if (NOT DEBUG AND compile_threaded) +endif() +if (DEBUG AND compile_threaded) +endif() +set(LDFLAGS "-Wl,--relax -Wl,--allow-multiple-definition") diff --git a/build/cmake_macros/intel.cmake b/build/cmake_macros/intel.cmake new file mode 100644 index 0000000000..7328c85e30 --- /dev/null +++ b/build/cmake_macros/intel.cmake @@ -0,0 +1,61 @@ +string(APPEND CFLAGS " -qno-opt-dynamic-align -fp-model precise -std=gnu99") +if (compile_threaded) + string(APPEND CFLAGS " -qopenmp") +endif() +if (NOT DEBUG) + string(APPEND CFLAGS " -O2 -debug minimal") +endif() +if (DEBUG) + string(APPEND CFLAGS " -O0 -g") +endif() +string(APPEND CPPDEFS " -DFORTRANUNDERSCORE -DCPRINTEL") +string(APPEND CXX_LDFLAGS " -cxxlib") +set(CXX_LINKER "FORTRAN") +set(FC_AUTO_R8 "-r8") +string(APPEND FFLAGS " -qno-opt-dynamic-align -convert big_endian -assume byterecl -ftz -traceback -assume realloc_lhs -fp-model source") +if (compile_threaded) + string(APPEND FFLAGS " -qopenmp") +endif() +if (DEBUG) + string(APPEND FFLAGS " -O0 -g -check uninit -check bounds -check pointers -fpe0 -check noarg_temp_created") +endif() +if (NOT DEBUG) + string(APPEND FFLAGS " -O2 -debug minimal") +endif() +set(FFLAGS_NOOPT "-O0") +set(FIXEDFLAGS "-fixed") +set(FREEFLAGS "-free") +if (compile_threaded) + string(APPEND LDFLAGS " -qopenmp") +endif() +set(MPICC "mpicc") +set(MPICXX "mpicxx") +set(MPIFC "mpif90") +set(SCC "icc") +set(SCXX "icpc") +set(SFC "ifort") +if (MPILIB STREQUAL mpich) + string(APPEND SLIBS " -mkl=cluster") +endif() +if (MPILIB STREQUAL mpich2) + string(APPEND SLIBS " -mkl=cluster") +endif() +if (MPILIB STREQUAL mvapich) + string(APPEND SLIBS " -mkl=cluster") +endif() +if (MPILIB STREQUAL mvapich2) + string(APPEND SLIBS " -mkl=cluster") +endif() +if (MPILIB STREQUAL mpt) + string(APPEND SLIBS " -mkl=cluster") +endif() +if (MPILIB STREQUAL openmpi) + string(APPEND SLIBS " -mkl=cluster") +endif() +if (MPILIB STREQUAL impi) + string(APPEND SLIBS " -mkl=cluster") +endif() +if (MPILIB STREQUAL mpi-serial) + string(APPEND SLIBS " -mkl") +endif() +set(SUPPORTS_CXX "TRUE") diff --git a/build/cmake_macros/intel_Darwin.cmake b/build/cmake_macros/intel_Darwin.cmake new file mode 100644 index 0000000000..7a2450e00f --- /dev/null +++ b/build/cmake_macros/intel_Darwin.cmake @@ -0,0 +1,3 @@ +if (NOT compile_threaded) + string(APPEND FFLAGS " -heap-arrays") +endif() diff --git a/build/cmake_macros/intel_aleph.cmake b/build/cmake_macros/intel_aleph.cmake new file mode 100644 index 0000000000..76985f0ede --- /dev/null +++ b/build/cmake_macros/intel_aleph.cmake @@ -0,0 +1,8 @@ +set(CONFIG_ARGS "--host=cray") +string(APPEND CFLAGS " -xCORE-AVX2") +string(APPEND FFLAGS " -xCORE-AVX2") +string(APPEND SLIBS " -L$(NETCDF_DIR) -lnetcdff -Wl,--as-needed,-L$(NETCDF_DIR)/lib -lnetcdff -lnetcdf") +if (COMP_NAME STREQUAL gptl) + string(APPEND CPPDEFS " -DHAVE_PAPI -DHAVE_SLASHPROC") +endif() +string(APPEND LDFLAGS " -mkl") diff --git a/build/cmake_macros/intel_athena.cmake b/build/cmake_macros/intel_athena.cmake new file mode 100644 index 0000000000..b558b0fd4d --- /dev/null +++ b/build/cmake_macros/intel_athena.cmake @@ -0,0 +1,20 @@ +string(APPEND CFLAGS " -xHost") +string(APPEND CPPDEFS " -DINTEL_MKL -DHAVE_SSE2") +string(APPEND FFLAGS " -xHost") +if (COMP_NAME STREQUAL nemo) + string(APPEND FFLAGS " $(FC_AUTO_R8) -O3 -assume norealloc_lhs") +endif() +execute_process(COMMAND ${NETCDF_PATH}/bin/nc-config --flibs OUTPUT_VARIABLE SHELL_CMD_OUTPUT_BUILD_INTERNAL_IGNORE0 OUTPUT_STRIP_TRAILING_WHITESPACE) +string(APPEND SLIBS " ${SHELL_CMD_OUTPUT_BUILD_INTERNAL_IGNORE0}") +if (MPILIB STREQUAL mpich2) + set(MPICXX "mpiicpc") +endif() +if (MPILIB STREQUAL mpich2) + set(MPICC "mpiicc") +endif() +if (MPILIB STREQUAL mpich2) + set(MPIFC "mpiifort") +endif() +if (MPILIB STREQUAL mpich2) + set(TRILINOS_PATH "$ENV{TRILINOS_PATH}") +endif() diff --git a/build/cmake_macros/intel_aws-hpc6a.cmake b/build/cmake_macros/intel_aws-hpc6a.cmake new file mode 100644 index 0000000000..0e4d281538 --- /dev/null +++ b/build/cmake_macros/intel_aws-hpc6a.cmake @@ -0,0 +1,8 @@ +string(APPEND CFLAGS " -qopt-report -march=core-avx2 -mtune=core-avx2 -no-fma") +string(APPEND FFLAGS " -qopt-report -march=core-avx2 -mtune=core-avx2 -no-fma") +if (DEBUG) + string(APPEND CMAKE_OPTS " -DPIO_ENABLE_LOGGING=ON") +endif() +set(SLIBS "-lnetcdf -lnetcdff -lpnetcdf -lblas -llapack -lpthread -lm -ldl") +string(APPEND CPPDEFS " -DNO_SHR_VMATH") + diff --git a/build/cmake_macros/intel_bluewaters.cmake b/build/cmake_macros/intel_bluewaters.cmake new file mode 100644 index 0000000000..29b1da06da --- /dev/null +++ b/build/cmake_macros/intel_bluewaters.cmake @@ -0,0 +1,3 @@ +set(HAS_F2008_CONTIGUOUS "FALSE") +string(APPEND FFLAGS " -dynamic -mkl=sequential -no-fma") +string(APPEND CFLAGS " -dynamic -mkl=sequential -no-fma") diff --git a/build/cmake_macros/intel_casper.cmake b/build/cmake_macros/intel_casper.cmake new file mode 100644 index 0000000000..7ee1c8b71d --- /dev/null +++ b/build/cmake_macros/intel_casper.cmake @@ -0,0 +1,9 @@ +string(APPEND CFLAGS " -qopt-report -xCORE_AVX2 -no-fma") +string(APPEND FFLAGS " -qopt-report -xCORE_AVX2 -no-fma") +if (DEBUG) + string(APPEND CMAKE_OPTS " -DPIO_ENABLE_LOGGING=ON") +endif() +if (MPILIB STREQUAL mpi-serial AND NOT compile_threaded) + set(PFUNIT_PATH "$ENV{CESMDATAROOT}/tools/pFUnit/pFUnit3.2.8_cheyenne_Intel17.0.1_noMPI_noOpenMP") +endif() +set(HAS_F2008_CONTIGUOUS "TRUE") diff --git a/build/cmake_macros/intel_cheyenne.cmake b/build/cmake_macros/intel_cheyenne.cmake new file mode 100644 index 0000000000..f83ba0ebd2 --- /dev/null +++ b/build/cmake_macros/intel_cheyenne.cmake @@ -0,0 +1,12 @@ +string(APPEND CFLAGS " -qopt-report -xCORE_AVX2 -no-fma") +string(APPEND FFLAGS " -qopt-report -xCORE_AVX2 -no-fma") +if (DEBUG) + string(APPEND CMAKE_OPTS " -DPIO_ENABLE_LOGGING=ON") +endif() +if (MPILIB STREQUAL mpi-serial AND NOT compile_threaded) + set(PFUNIT_PATH "$ENV{CESMDATAROOT}/tools/pFUnit/pFUnit3.2.8_cheyenne_Intel17.0.1_noMPI_noOpenMP") +endif() +if (MPILIB STREQUAL mpt AND compile_threaded) + set(PFUNIT_PATH "$ENV{CESMDATAROOT}/tools/pFUnit/pFUnit3.2.8_cheyenne_Intel17.0.1_MPI_openMP") +endif() +set(HAS_F2008_CONTIGUOUS "TRUE") diff --git a/build/cmake_macros/intel_constance.cmake b/build/cmake_macros/intel_constance.cmake new file mode 100644 index 0000000000..5733786855 --- /dev/null +++ b/build/cmake_macros/intel_constance.cmake @@ -0,0 +1,11 @@ +if (NOT DEBUG) + string(APPEND CFLAGS " -O2") +endif() +set(CONFIG_ARGS "--host=cray") +string(APPEND CPPDEFS " -DLINUX") +if (NOT DEBUG) + string(APPEND FFLAGS " -O2") +endif() +set(NETCDF_PATH "$ENV{NETCDF_HOME}") +set(PIO_FILESYSTEM_HINTS "lustre") +set(SLIBS "-L${NETCDF_PATH}/lib -lnetcdf -lnetcdff -lpmi -L$ENV{MKL_PATH} -lmkl_rt") diff --git a/build/cmake_macros/intel_cori-haswell.cmake b/build/cmake_macros/intel_cori-haswell.cmake new file mode 100644 index 0000000000..6fe65eb1d9 --- /dev/null +++ b/build/cmake_macros/intel_cori-haswell.cmake @@ -0,0 +1,9 @@ +set(CONFIG_ARGS "--host=cray") +string(APPEND CFLAGS " -xCORE-AVX2") +string(APPEND FFLAGS " -xCORE-AVX2") +string(APPEND SLIBS " -L$(NETCDF_DIR) -lnetcdff -Wl,--as-needed,-L$(NETCDF_DIR)/lib -lnetcdff -lnetcdf") +if (COMP_NAME STREQUAL gptl) + string(APPEND CPPDEFS " -DHAVE_SLASHPROC") +endif() +string(APPEND LDFLAGS " -mkl") +set(HAS_F2008_CONTIGUOUS "FALSE") diff --git a/build/cmake_macros/intel_cori-knl.cmake b/build/cmake_macros/intel_cori-knl.cmake new file mode 100644 index 0000000000..683c1a8068 --- /dev/null +++ b/build/cmake_macros/intel_cori-knl.cmake @@ -0,0 +1,9 @@ +set(CONFIG_ARGS "--host=cray") +string(APPEND CFLAGS " -xMIC-AVX512") +string(APPEND FFLAGS " -xMIC-AVX512") +string(APPEND SLIBS " -L$(NETCDF_DIR) -lnetcdff -Wl,--as-needed,-L$(NETCDF_DIR)/lib -lnetcdff -lnetcdf") +if (COMP_NAME STREQUAL gptl) + string(APPEND CPPDEFS " -DHAVE_SLASHPROC") +endif() +string(APPEND LDFLAGS " -mkl -lmemkind -zmuldefs") +set(HAS_F2008_CONTIGUOUS "FALSE") diff --git a/build/cmake_macros/intel_eastwind.cmake b/build/cmake_macros/intel_eastwind.cmake new file mode 100644 index 0000000000..1a1dcf69b3 --- /dev/null +++ b/build/cmake_macros/intel_eastwind.cmake @@ -0,0 +1,11 @@ +if (NOT DEBUG) + string(APPEND CFLAGS " -O2") +endif() +set(CONFIG_ARGS "--host=cray") +string(APPEND CPPDEFS " -DLINUX") +if (NOT DEBUG) + string(APPEND FFLAGS " -O2") +endif() +set(NETCDF_PATH "$ENV{NETCDF_HOME}") +set(PIO_FILESYSTEM_HINTS "lustre") +set(SLIBS "-L${NETCDF_PATH}/lib -lnetcdf -lnetcdff -lpmi") diff --git a/build/cmake_macros/intel_edison.cmake b/build/cmake_macros/intel_edison.cmake new file mode 100644 index 0000000000..3f41409deb --- /dev/null +++ b/build/cmake_macros/intel_edison.cmake @@ -0,0 +1,11 @@ +if (NOT DEBUG) + string(APPEND CFLAGS " -O2") +endif() +set(CONFIG_ARGS "--host=cray") +if (COMP_NAME STREQUAL gptl) + string(APPEND CPPDEFS " -DHAVE_PAPI") +endif() +if (NOT DEBUG) + string(APPEND FFLAGS " -O2") +endif() +string(APPEND SLIBS " -L$ENV{NETCDF_DIR} -lnetcdff -Wl,--as-needed,-L$ENV{NETCDF_DIR}/lib -lnetcdff -lnetcdf") diff --git a/build/cmake_macros/intel_euler2.cmake b/build/cmake_macros/intel_euler2.cmake new file mode 100644 index 0000000000..42580b2a64 --- /dev/null +++ b/build/cmake_macros/intel_euler2.cmake @@ -0,0 +1,7 @@ +if (NOT DEBUG) + string(APPEND CFLAGS " -xCORE-AVX2") +endif() +if (NOT DEBUG) + string(APPEND FFLAGS " -xCORE-AVX2") +endif() +string(APPEND LDFLAGS " -mkl") diff --git a/build/cmake_macros/intel_euler3.cmake b/build/cmake_macros/intel_euler3.cmake new file mode 100644 index 0000000000..42580b2a64 --- /dev/null +++ b/build/cmake_macros/intel_euler3.cmake @@ -0,0 +1,7 @@ +if (NOT DEBUG) + string(APPEND CFLAGS " -xCORE-AVX2") +endif() +if (NOT DEBUG) + string(APPEND FFLAGS " -xCORE-AVX2") +endif() +string(APPEND LDFLAGS " -mkl") diff --git a/build/cmake_macros/intel_euler4.cmake b/build/cmake_macros/intel_euler4.cmake new file mode 100644 index 0000000000..42580b2a64 --- /dev/null +++ b/build/cmake_macros/intel_euler4.cmake @@ -0,0 +1,7 @@ +if (NOT DEBUG) + string(APPEND CFLAGS " -xCORE-AVX2") +endif() +if (NOT DEBUG) + string(APPEND FFLAGS " -xCORE-AVX2") +endif() +string(APPEND LDFLAGS " -mkl") diff --git a/build/cmake_macros/intel_greenplanet-sib29.cmake b/build/cmake_macros/intel_greenplanet-sib29.cmake new file mode 100644 index 0000000000..e445abd253 --- /dev/null +++ b/build/cmake_macros/intel_greenplanet-sib29.cmake @@ -0,0 +1,3 @@ +set(NETCDF_PATH "$ENV{NCDIR}") +set(PNETCDF_PATH "$ENV{PNDIR}") +string(APPEND SLIBS " -L${NETCDF_PATH}/lib -lnetcdf -lnetcdff") diff --git a/build/cmake_macros/intel_greenplanet-sky24.cmake b/build/cmake_macros/intel_greenplanet-sky24.cmake new file mode 100644 index 0000000000..e445abd253 --- /dev/null +++ b/build/cmake_macros/intel_greenplanet-sky24.cmake @@ -0,0 +1,3 @@ +set(NETCDF_PATH "$ENV{NCDIR}") +set(PNETCDF_PATH "$ENV{PNDIR}") +string(APPEND SLIBS " -L${NETCDF_PATH}/lib -lnetcdf -lnetcdff") diff --git a/build/cmake_macros/intel_gust.cmake b/build/cmake_macros/intel_gust.cmake new file mode 100644 index 0000000000..f3943efe8e --- /dev/null +++ b/build/cmake_macros/intel_gust.cmake @@ -0,0 +1,6 @@ +set(CONFIG_ARGS "--host=cray") +string(APPEND CFLAGS " -march=core-avx2") +string(APPEND FFLAGS " -march=core-avx2") +if (COMP_NAME STREQUAL gptl) + string(APPEND CPPDEFS " -DHAVE_SLASHPROC") +endif() diff --git a/build/cmake_macros/intel_hobart.cmake b/build/cmake_macros/intel_hobart.cmake new file mode 100644 index 0000000000..e9ac234fd1 --- /dev/null +++ b/build/cmake_macros/intel_hobart.cmake @@ -0,0 +1,16 @@ +string(APPEND CFLAGS " -lifcore") +string(APPEND FFLAGS " -lifcore") +if (MPILIB STREQUAL mpi-serial) + string(APPEND FFLAGS " -mcmodel medium") +endif() +string(APPEND LDFLAGS " -lquadmath") +string(APPEND LDFLAGS " -Wl,-rpath,${NETCDF_PATH}/lib") +string(APPEND LDFLAGS " -Wl,-rpath,$ENV{COMPILER_PATH}/lib/intel64") +string(APPEND LDFLAGS " -Wl,-rpath,$ENV{COMPILER_PATH}/mkl/lib/intel64") +string(APPEND LDFLAGS " -Wl,-rpath,$ENV{MPI_PATH}/lib") +string(APPEND LDFLAGS " -lifcore") +if (MPILIB STREQUAL mvapich2) +endif() +if (MPILIB STREQUAL mpi-serial AND NOT compile_threaded) + set(PFUNIT_PATH "/fs/cgd/csm/tools/pFUnit/pFUnit3.2.8_hobart_Intel15.0.2_noMPI_noOpenMP") +endif() diff --git a/build/cmake_macros/intel_izumi.cmake b/build/cmake_macros/intel_izumi.cmake new file mode 100644 index 0000000000..13f2e3be28 --- /dev/null +++ b/build/cmake_macros/intel_izumi.cmake @@ -0,0 +1,3 @@ +if (MPILIB STREQUAL mpi-serial AND NOT compile_threaded) + set(PFUNIT_PATH "/fs/cgd/csm/tools/pFUnit/pFUnit3.3.3_izumi_Intel19.0.1_noMPI_noOpenMP") +endif() diff --git a/build/cmake_macros/intel_laramie.cmake b/build/cmake_macros/intel_laramie.cmake new file mode 100644 index 0000000000..ba6a09daa2 --- /dev/null +++ b/build/cmake_macros/intel_laramie.cmake @@ -0,0 +1,5 @@ +string(APPEND CFLAGS " -vec-report") +string(APPEND FFLAGS " -vec-report") +if (DEBUG) + string(APPEND CMAKE_OPTS " -DPIO_ENABLE_LOGGING=ON") +endif() diff --git a/build/cmake_macros/intel_lawrencium-lr3.cmake b/build/cmake_macros/intel_lawrencium-lr3.cmake new file mode 100644 index 0000000000..8830234902 --- /dev/null +++ b/build/cmake_macros/intel_lawrencium-lr3.cmake @@ -0,0 +1,12 @@ +if (COMP_NAME STREQUAL gptl) + string(APPEND CPPDEFS " -DHAVE_VPRINTF -DHAVE_TIMES -DHAVE_GETTIMEOFDAY") +endif() +string(APPEND SLIBS " -lnetcdff -lnetcdf -mkl") +if (DEBUG) + string(APPEND FFLAGS " -ftrapuv") +endif() +if (DEBUG) + string(APPEND CFLAGS " -ftrapuv") +endif() +set(NETCDF_PATH "$ENV{NETCDF_DIR}") +set(LAPACK_LIBDIR "/global/software/sl-6.x86_64/modules/intel/2016.1.150/lapack/3.6.0-intel/lib") diff --git a/build/cmake_macros/intel_sandiatoss3.cmake b/build/cmake_macros/intel_sandiatoss3.cmake new file mode 100644 index 0000000000..8356ac5e73 --- /dev/null +++ b/build/cmake_macros/intel_sandiatoss3.cmake @@ -0,0 +1,12 @@ +if (NOT DEBUG) + string(APPEND CFLAGS " -O2") +endif() +set(CONFIG_ARGS "--host=cray") +set(ESMF_LIBDIR "/projects/ccsm/esmf-6.3.0rp1/lib/libO/Linux.intel.64.openmpi.default") +if (NOT DEBUG) + string(APPEND FFLAGS " -O2") +endif() +set(NETCDF_PATH "$ENV{NETCDFROOT}") +set(PIO_FILESYSTEM_HINTS "lustre") +set(PNETCDF_PATH "$ENV{PNETCDFROOT}") +string(APPEND SLIBS " -L${NETCDF_PATH}/lib -lnetcdff -L/projects/ccsm/BLAS-intel -lblas_LINUX") diff --git a/build/cmake_macros/intel_stampede2-knl.cmake b/build/cmake_macros/intel_stampede2-knl.cmake new file mode 100644 index 0000000000..6cdd9fe9c1 --- /dev/null +++ b/build/cmake_macros/intel_stampede2-knl.cmake @@ -0,0 +1,10 @@ +string(APPEND CFLAGS " -xCOMMON-AVX512 -no-fma") +string(APPEND FFLAGS " -xCOMMON-AVX512 -no-fma") +if (MPILIB STREQUAL mpi-serial) + string(APPEND FFLAGS " -mcmodel medium") +endif() +string(APPEND LDFLAGS " -L$ENV{TACC_HDF5_LIB} -lhdf5 $(MKL) -zmuldefs -xCOMMON-AVX512") +execute_process(COMMAND ${NETCDF_PATH}/bin/nf-config --flibs OUTPUT_VARIABLE SHELL_CMD_OUTPUT_BUILD_INTERNAL_IGNORE0 OUTPUT_STRIP_TRAILING_WHITESPACE) +string(APPEND SLIBS " ${SHELL_CMD_OUTPUT_BUILD_INTERNAL_IGNORE0} -L$ENV{TACC_HDF5_LIB} -lhdf5") +set(TRILINOS_PATH "$ENV{TRILINOS_PATH}") +set(HAS_F2008_CONTIGUOUS "FALSE") diff --git a/build/cmake_macros/intel_stampede2-skx.cmake b/build/cmake_macros/intel_stampede2-skx.cmake new file mode 100644 index 0000000000..6cdd9fe9c1 --- /dev/null +++ b/build/cmake_macros/intel_stampede2-skx.cmake @@ -0,0 +1,10 @@ +string(APPEND CFLAGS " -xCOMMON-AVX512 -no-fma") +string(APPEND FFLAGS " -xCOMMON-AVX512 -no-fma") +if (MPILIB STREQUAL mpi-serial) + string(APPEND FFLAGS " -mcmodel medium") +endif() +string(APPEND LDFLAGS " -L$ENV{TACC_HDF5_LIB} -lhdf5 $(MKL) -zmuldefs -xCOMMON-AVX512") +execute_process(COMMAND ${NETCDF_PATH}/bin/nf-config --flibs OUTPUT_VARIABLE SHELL_CMD_OUTPUT_BUILD_INTERNAL_IGNORE0 OUTPUT_STRIP_TRAILING_WHITESPACE) +string(APPEND SLIBS " ${SHELL_CMD_OUTPUT_BUILD_INTERNAL_IGNORE0} -L$ENV{TACC_HDF5_LIB} -lhdf5") +set(TRILINOS_PATH "$ENV{TRILINOS_PATH}") +set(HAS_F2008_CONTIGUOUS "FALSE") diff --git a/build/cmake_macros/intel_theia.cmake b/build/cmake_macros/intel_theia.cmake new file mode 100644 index 0000000000..6a09fe8c2c --- /dev/null +++ b/build/cmake_macros/intel_theia.cmake @@ -0,0 +1,4 @@ +set(MPICC "mpiicc") +set(MPICXX "mpiicpc") +set(MPIFC "mpiifort") +set(NETCDF_PATH "/apps/netcdf/4.3.0-intel") diff --git a/build/cmake_macros/intel_zeus.cmake b/build/cmake_macros/intel_zeus.cmake new file mode 100644 index 0000000000..281ae04b18 --- /dev/null +++ b/build/cmake_macros/intel_zeus.cmake @@ -0,0 +1,18 @@ +set(AR "xiar") +set(ARFLAGS "cru") +if (MPILIB STREQUAL mpi-serial) + string(APPEND FFLAGS " -mcmodel medium") + string(APPEND FFLAGS " -mkl -xSKYLAKE-AVX512 -qopt-zmm-usage=high -no-fma") + string(APPEND CFLAGS " -mkl -xSKYLAKE-AVX512 -qopt-zmm-usage=high -no-fma") + string(APPEND LDFLAGS " -mkl -lstdc++") + string(APPEND SLIBS " -lstdc++") +endif() +if (MPILIB STREQUAL impi) + string(APPEND FFLAGS " -mkl=cluster -xSKYLAKE-AVX512 -qopt-zmm-usage=high -no-fma") + string(APPEND CFLAGS " -mkl=cluster -xSKYLAKE-AVX512 -qopt-zmm-usage=high -no-fma") + string(APPEND LDFLAGS " -mkl=cluster") + string(APPEND SLIBS " -lstdc++") +endif() +set(MPICC "mpiicc") +set(MPICXX "mpiicpc") +set(MPIFC "mpiifort") diff --git a/build/cmake_macros/izumi.cmake b/build/cmake_macros/izumi.cmake new file mode 100644 index 0000000000..8894b6a383 --- /dev/null +++ b/build/cmake_macros/izumi.cmake @@ -0,0 +1,9 @@ +if (COMP_NAME STREQUAL gptl) + string(APPEND CPPDEFS " -DHAVE_NANOTIME -DBIT64 -DHAVE_VPRINTF -DHAVE_BACKTRACE -DHAVE_SLASHPROC -DHAVE_COMM_F2C -DHAVE_TIMES -DHAVE_GETTIMEOFDAY") +endif() +set(LAPACK_LIBDIR "/usr/lib64") +if (MPILIB STREQUAL mvapich2) + set(MPI_LIB_NAME "mpich") +endif() +set(NETCDF_PATH "$ENV{NETCDF_PATH}") +string(APPEND SLIBS " -L${NETCDF_PATH}/lib -lnetcdff -lnetcdf") diff --git a/build/cmake_macros/laramie.cmake b/build/cmake_macros/laramie.cmake new file mode 100644 index 0000000000..35c2d3c33e --- /dev/null +++ b/build/cmake_macros/laramie.cmake @@ -0,0 +1,6 @@ +if (COMP_NAME STREQUAL gptl) + string(APPEND CPPDEFS " -DHAVE_NANOTIME -DBIT64 -DHAVE_VPRINTF -DHAVE_BACKTRACE -DHAVE_SLASHPROC -DHAVE_COMM_F2C -DHAVE_TIMES -DHAVE_GETTIMEOFDAY") +endif() +set(NETCDF_PATH "$ENV{NETCDF}") +set(PIO_FILESYSTEM_HINTS "gpfs") +set(PNETCDF_PATH "$ENV{PNETCDF}") diff --git a/build/cmake_macros/lonestar5.cmake b/build/cmake_macros/lonestar5.cmake new file mode 100644 index 0000000000..0c5eec8054 --- /dev/null +++ b/build/cmake_macros/lonestar5.cmake @@ -0,0 +1,6 @@ +string(APPEND CPPDEFS " -DHAVE_NANOTIME") +set(NETCDF_PATH "$ENV{TACC_NETCDF_DIR}") +set(PIO_FILESYSTEM_HINTS "lustre") +set(PNETCDF_PATH "$ENV{TACC_PNETCDF_DIR}") +string(APPEND LDFLAGS " -Wl,-rpath,${NETCDF_PATH}/lib") +string(APPEND SLIBS " -L${NETCDF_PATH}/lib -lnetcdff -lnetcdf") diff --git a/build/cmake_macros/nag.cmake b/build/cmake_macros/nag.cmake new file mode 100644 index 0000000000..6a2d97c87a --- /dev/null +++ b/build/cmake_macros/nag.cmake @@ -0,0 +1,30 @@ +string(APPEND CFLAGS " -std=gnu99") +if (DEBUG) + string(APPEND CFLAGS " -g") +endif() +string(APPEND CPPDEFS " -DFORTRANUNDERSCORE -DNO_CRAY_POINTERS -DNO_SHR_VMATH -DCPRNAG -DNO_R16") +set(FC_AUTO_R8 "-r8") +string(APPEND FFLAGS " -Wp,-macro=no_com -convert=BIG_ENDIAN ") +string(APPEND FFLAGS "-indirect ${SRCROOT}/ccs_config/machines/nag_mpi_argument.txt") +if (NOT DEBUG) + string(APPEND FFLAGS " -ieee=full -O2") +endif() +if (DEBUG) + string(APPEND FFLAGS " -C=all -g -time -f2003 -ieee=stop") +endif() +if (DEBUG AND NOT compile_threaded) + string(APPEND FFLAGS " -gline") +endif() +if (COMP_NAME STREQUAL cism) + string(APPEND FFLAGS " -mismatch_all") +endif() +set(FFLAGS_NOOPT "-O0") +set(FIXEDFLAGS "-fixed") +set(FREEFLAGS "-free") +set(HAS_F2008_CONTIGUOUS "FALSE") +set(MPICC "mpicc") +set(MPIFC "mpif90") +set(SCC "gcc") +set(SFC "nagfor") +string(APPEND LDFLAGS " -lpthread") +string(APPEND CONFIG_ARGS " FCLIBS='-Wl,--as-needed,--allow-shlib-undefined -L$(COMPILER_PATH)/lib/NAG_Fortran -lf62rts'") diff --git a/build/cmake_macros/nvhpc-gpu.cmake b/build/cmake_macros/nvhpc-gpu.cmake new file mode 100644 index 0000000000..679e81b2f4 --- /dev/null +++ b/build/cmake_macros/nvhpc-gpu.cmake @@ -0,0 +1,46 @@ +string(APPEND CFLAGS " -gopt -time") +if (compile_threaded) + string(APPEND CFLAGS " -mp") +endif() +string(APPEND CPPDEFS " -DFORTRANUNDERSCORE -DNO_SHR_VMATH -DNO_R16 -DCPRPGI") +set(CXX_LINKER "CXX") +set(FC_AUTO_R8 "-r8") +string(APPEND FFLAGS " -i4 -gopt -time -Mextend -byteswapio -Mflushz -Kieee") +if (compile_threaded) + string(APPEND FFLAGS " -mp") +endif() +if (DEBUG) + string(APPEND FFLAGS " -O0 -g -Ktrap=fp -Mbounds -Kieee") +endif() +if (COMP_NAME STREQUAL datm) + string(APPEND FFLAGS " -Mnovect") +endif() +if (COMP_NAME STREQUAL dlnd) + string(APPEND FFLAGS " -Mnovect") +endif() +if (COMP_NAME STREQUAL drof) + string(APPEND FFLAGS " -Mnovect") +endif() +if (COMP_NAME STREQUAL dwav) + string(APPEND FFLAGS " -Mnovect") +endif() +if (COMP_NAME STREQUAL dice) + string(APPEND FFLAGS " -Mnovect") +endif() +if (COMP_NAME STREQUAL docn) + string(APPEND FFLAGS " -Mnovect") +endif() +set(FFLAGS_NOOPT "-O0") +set(FIXEDFLAGS "-Mfixed") +set(FREEFLAGS "-Mfree") +set(HAS_F2008_CONTIGUOUS "FALSE") +set(LDFLAGS "-time -Wl,--allow-multiple-definition") +if (compile_threaded) + string(APPEND LDFLAGS " -mp") +endif() +set(MPICC "mpicc") +set(MPICXX "mpicxx") +set(MPIFC "mpif90") +set(SCC "nvc") +set(SCXX "nvc++") +set(SFC "nvfortran") diff --git a/build/cmake_macros/nvhpc-gpu_casper.cmake b/build/cmake_macros/nvhpc-gpu_casper.cmake new file mode 100644 index 0000000000..ed2adbc6c9 --- /dev/null +++ b/build/cmake_macros/nvhpc-gpu_casper.cmake @@ -0,0 +1,15 @@ +if (NOT DEBUG) + string(APPEND CFLAGS " -O -tp=skylake -Mnofma") +endif() +if (NOT DEBUG) + string(APPEND FFLAGS " -O -tp=skylake -Mnofma") +endif() +string(APPEND FFLAGS " -I$(EXEROOT)/ocn/obj/FMS") +if (NOT DEBUG) + string(APPEND LDFLAGS " -O -tp=skylake -Mnofma -acc -gpu=cc70,lineinfo,nofma -Minfo=accel") +endif() +string(APPEND SLIBS " -llapack -lblas") +if (MPILIB STREQUAL mpi-serial) + string(APPEND SLIBS " -ldl") +endif() +string(APPEND SLIBS " -L${NETCDF_PATH}/lib -lnetcdf -lnetcdff") diff --git a/build/cmake_macros/nvhpc.cmake b/build/cmake_macros/nvhpc.cmake new file mode 100644 index 0000000000..3e1b451624 --- /dev/null +++ b/build/cmake_macros/nvhpc.cmake @@ -0,0 +1,51 @@ +string(APPEND CFLAGS " -gopt -time") +if (compile_threaded) + string(APPEND CFLAGS " -mp") +endif() +if (NOT DEBUG) + string(APPEND CFLAGS " -O ") + string(APPEND FFLAGS " -O -Mnofma") +endif() + +string(APPEND CPPDEFS " -DFORTRANUNDERSCORE -DNO_SHR_VMATH -DNO_R16 -DCPRPGI") +set(CXX_LINKER "CXX") +set(FC_AUTO_R8 "-r8") +string(APPEND FFLAGS " -i4 -gopt -time -Mextend -byteswapio -Mflushz -Kieee") +if (compile_threaded) + string(APPEND FFLAGS " -mp") +endif() +if (DEBUG) + string(APPEND FFLAGS " -O0 -g -Ktrap=fp -Mbounds -Kieee") +endif() +if (COMP_NAME STREQUAL datm) + string(APPEND FFLAGS " -Mnovect") +endif() +if (COMP_NAME STREQUAL dlnd) + string(APPEND FFLAGS " -Mnovect") +endif() +if (COMP_NAME STREQUAL drof) + string(APPEND FFLAGS " -Mnovect") +endif() +if (COMP_NAME STREQUAL dwav) + string(APPEND FFLAGS " -Mnovect") +endif() +if (COMP_NAME STREQUAL dice) + string(APPEND FFLAGS " -Mnovect") +endif() +if (COMP_NAME STREQUAL docn) + string(APPEND FFLAGS " -Mnovect") +endif() +set(FFLAGS_NOOPT "-O0") +set(FIXEDFLAGS "-Mfixed") +set(FREEFLAGS "-Mfree") +set(HAS_F2008_CONTIGUOUS "FALSE") +set(LDFLAGS "-time -Wl,--allow-multiple-definition") +if (compile_threaded) + string(APPEND LDFLAGS " -mp") +endif() +set(MPICC "mpicc") +set(MPICXX "mpicxx") +set(MPIFC "mpif90") +set(SCC "nvc") +set(SCXX "nvc++") +set(SFC "nvfortran") diff --git a/build/cmake_macros/nvhpc_casper.cmake b/build/cmake_macros/nvhpc_casper.cmake new file mode 100644 index 0000000000..f3eb207d1e --- /dev/null +++ b/build/cmake_macros/nvhpc_casper.cmake @@ -0,0 +1,15 @@ +if (NOT DEBUG) + string(APPEND CFLAGS " -O -tp=skylake -Mnofma") +endif() +if (NOT DEBUG) + string(APPEND FFLAGS " -O -tp=skylake -Mnofma") +endif() +string(APPEND FFLAGS " -I$(EXEROOT)/ocn/obj/FMS") +if (NOT DEBUG) + string(APPEND LDFLAGS " -O -tp=skylake -Mnofma") +endif() +string(APPEND SLIBS " -llapack -lblas") +if (MPILIB STREQUAL mpi-serial) + string(APPEND SLIBS " -ldl") +endif() +string(APPEND SLIBS " -L${NETCDF_PATH}/lib -lnetcdf -lnetcdff") diff --git a/build/cmake_macros/nvhpc_cheyenne.cmake b/build/cmake_macros/nvhpc_cheyenne.cmake new file mode 100644 index 0000000000..e3769dd9d7 --- /dev/null +++ b/build/cmake_macros/nvhpc_cheyenne.cmake @@ -0,0 +1,4 @@ +string(APPEND SLIBS " -llapack -lblas") +if (MPILIB STREQUAL mpi-serial) + string(APPEND SLIBS " -ldl") +endif() diff --git a/build/cmake_macros/nvhpc_gust.cmake b/build/cmake_macros/nvhpc_gust.cmake new file mode 100644 index 0000000000..461137315d --- /dev/null +++ b/build/cmake_macros/nvhpc_gust.cmake @@ -0,0 +1,3 @@ +if (NOT DEBUG) + string(APPEND FFLAGS " -target=zen3") +endif() diff --git a/build/cmake_macros/oneapi.cmake b/build/cmake_macros/oneapi.cmake new file mode 100644 index 0000000000..7328c85e30 --- /dev/null +++ b/build/cmake_macros/oneapi.cmake @@ -0,0 +1,61 @@ +string(APPEND CFLAGS " -qno-opt-dynamic-align -fp-model precise -std=gnu99") +if (compile_threaded) + string(APPEND CFLAGS " -qopenmp") +endif() +if (NOT DEBUG) + string(APPEND CFLAGS " -O2 -debug minimal") +endif() +if (DEBUG) + string(APPEND CFLAGS " -O0 -g") +endif() +string(APPEND CPPDEFS " -DFORTRANUNDERSCORE -DCPRINTEL") +string(APPEND CXX_LDFLAGS " -cxxlib") +set(CXX_LINKER "FORTRAN") +set(FC_AUTO_R8 "-r8") +string(APPEND FFLAGS " -qno-opt-dynamic-align -convert big_endian -assume byterecl -ftz -traceback -assume realloc_lhs -fp-model source") +if (compile_threaded) + string(APPEND FFLAGS " -qopenmp") +endif() +if (DEBUG) + string(APPEND FFLAGS " -O0 -g -check uninit -check bounds -check pointers -fpe0 -check noarg_temp_created") +endif() +if (NOT DEBUG) + string(APPEND FFLAGS " -O2 -debug minimal") +endif() +set(FFLAGS_NOOPT "-O0") +set(FIXEDFLAGS "-fixed") +set(FREEFLAGS "-free") +if (compile_threaded) + string(APPEND LDFLAGS " -qopenmp") +endif() +set(MPICC "mpicc") +set(MPICXX "mpicxx") +set(MPIFC "mpif90") +set(SCC "icc") +set(SCXX "icpc") +set(SFC "ifort") +if (MPILIB STREQUAL mpich) + string(APPEND SLIBS " -mkl=cluster") +endif() +if (MPILIB STREQUAL mpich2) + string(APPEND SLIBS " -mkl=cluster") +endif() +if (MPILIB STREQUAL mvapich) + string(APPEND SLIBS " -mkl=cluster") +endif() +if (MPILIB STREQUAL mvapich2) + string(APPEND SLIBS " -mkl=cluster") +endif() +if (MPILIB STREQUAL mpt) + string(APPEND SLIBS " -mkl=cluster") +endif() +if (MPILIB STREQUAL openmpi) + string(APPEND SLIBS " -mkl=cluster") +endif() +if (MPILIB STREQUAL impi) + string(APPEND SLIBS " -mkl=cluster") +endif() +if (MPILIB STREQUAL mpi-serial) + string(APPEND SLIBS " -mkl") +endif() +set(SUPPORTS_CXX "TRUE") diff --git a/build/cmake_macros/pgi-gpu.cmake b/build/cmake_macros/pgi-gpu.cmake new file mode 100644 index 0000000000..856574795e --- /dev/null +++ b/build/cmake_macros/pgi-gpu.cmake @@ -0,0 +1,46 @@ +string(APPEND CFLAGS " -gopt -time") +if (compile_threaded) + string(APPEND CFLAGS " -mp") +endif() +string(APPEND CPPDEFS " -DFORTRANUNDERSCORE -DNO_SHR_VMATH -DNO_R16 -DCPRPGI") +set(CXX_LINKER "CXX") +set(FC_AUTO_R8 "-r8") +string(APPEND FFLAGS " -i4 -gopt -time -Mextend -byteswapio -Mflushz -Kieee") +if (compile_threaded) + string(APPEND FFLAGS " -mp") +endif() +if (DEBUG) + string(APPEND FFLAGS " -O0 -g -Ktrap=fp -Mbounds -Kieee") +endif() +if (COMP_NAME STREQUAL datm) + string(APPEND FFLAGS " -Mnovect") +endif() +if (COMP_NAME STREQUAL dlnd) + string(APPEND FFLAGS " -Mnovect") +endif() +if (COMP_NAME STREQUAL drof) + string(APPEND FFLAGS " -Mnovect") +endif() +if (COMP_NAME STREQUAL dwav) + string(APPEND FFLAGS " -Mnovect") +endif() +if (COMP_NAME STREQUAL dice) + string(APPEND FFLAGS " -Mnovect") +endif() +if (COMP_NAME STREQUAL docn) + string(APPEND FFLAGS " -Mnovect") +endif() +set(FFLAGS_NOOPT "-O0") +set(FIXEDFLAGS "-Mfixed") +set(FREEFLAGS "-Mfree") +set(HAS_F2008_CONTIGUOUS "FALSE") +set(LDFLAGS "-time -Wl,--allow-multiple-definition") +if (compile_threaded) + string(APPEND LDFLAGS " -mp") +endif() +set(MPICC "mpicc") +set(MPICXX "mpicxx") +set(MPIFC "mpif90") +set(SCC "pgcc") +set(SCXX "pgc++") +set(SFC "pgf95") diff --git a/build/cmake_macros/pgi-gpu_casper.cmake b/build/cmake_macros/pgi-gpu_casper.cmake new file mode 100644 index 0000000000..600521a1bb --- /dev/null +++ b/build/cmake_macros/pgi-gpu_casper.cmake @@ -0,0 +1,15 @@ +if (NOT DEBUG) + string(APPEND CFLAGS " -O -tp=skylake -Mnofma") +endif() +if (NOT DEBUG) + string(APPEND FFLAGS " -O -tp=skylake -Mnofma") +endif() +string(APPEND FFLAGS " -I$(EXEROOT)/ocn/obj/FMS") +if (NOT DEBUG) + string(APPEND LDFLAGS " -O -tp=skylake -Mnofma -acc -ta=tesla:cc70,lineinfo,nofma -Minfo=accel") +endif() +string(APPEND SLIBS " -llapack -lblas") +if (MPILIB STREQUAL mpi-serial) + string(APPEND SLIBS " -ldl") +endif() +string(APPEND SLIBS " -L${NETCDF_PATH}/lib -lnetcdf -lnetcdff") diff --git a/build/cmake_macros/pgi.cmake b/build/cmake_macros/pgi.cmake new file mode 100644 index 0000000000..856574795e --- /dev/null +++ b/build/cmake_macros/pgi.cmake @@ -0,0 +1,46 @@ +string(APPEND CFLAGS " -gopt -time") +if (compile_threaded) + string(APPEND CFLAGS " -mp") +endif() +string(APPEND CPPDEFS " -DFORTRANUNDERSCORE -DNO_SHR_VMATH -DNO_R16 -DCPRPGI") +set(CXX_LINKER "CXX") +set(FC_AUTO_R8 "-r8") +string(APPEND FFLAGS " -i4 -gopt -time -Mextend -byteswapio -Mflushz -Kieee") +if (compile_threaded) + string(APPEND FFLAGS " -mp") +endif() +if (DEBUG) + string(APPEND FFLAGS " -O0 -g -Ktrap=fp -Mbounds -Kieee") +endif() +if (COMP_NAME STREQUAL datm) + string(APPEND FFLAGS " -Mnovect") +endif() +if (COMP_NAME STREQUAL dlnd) + string(APPEND FFLAGS " -Mnovect") +endif() +if (COMP_NAME STREQUAL drof) + string(APPEND FFLAGS " -Mnovect") +endif() +if (COMP_NAME STREQUAL dwav) + string(APPEND FFLAGS " -Mnovect") +endif() +if (COMP_NAME STREQUAL dice) + string(APPEND FFLAGS " -Mnovect") +endif() +if (COMP_NAME STREQUAL docn) + string(APPEND FFLAGS " -Mnovect") +endif() +set(FFLAGS_NOOPT "-O0") +set(FIXEDFLAGS "-Mfixed") +set(FREEFLAGS "-Mfree") +set(HAS_F2008_CONTIGUOUS "FALSE") +set(LDFLAGS "-time -Wl,--allow-multiple-definition") +if (compile_threaded) + string(APPEND LDFLAGS " -mp") +endif() +set(MPICC "mpicc") +set(MPICXX "mpicxx") +set(MPIFC "mpif90") +set(SCC "pgcc") +set(SCXX "pgc++") +set(SFC "pgf95") diff --git a/build/cmake_macros/pgi_bluewaters.cmake b/build/cmake_macros/pgi_bluewaters.cmake new file mode 100644 index 0000000000..ff5f160388 --- /dev/null +++ b/build/cmake_macros/pgi_bluewaters.cmake @@ -0,0 +1,10 @@ +if (NOT DEBUG) + string(APPEND CFLAGS " -O2") +endif() +string(APPEND CFLAGS " -nofma") +set(CXX_LIBS "-lmpichf90_pgi $ENV{PGI_PATH}/linux86-64/$ENV{PGI_VERSION}/lib/f90main.o") +if (NOT DEBUG) + string(APPEND FFLAGS " -O2") +endif() +string(APPEND FFLAGS " -nofma") +set(SUPPORTS_CXX "TRUE") diff --git a/build/cmake_macros/pgi_casper.cmake b/build/cmake_macros/pgi_casper.cmake new file mode 100644 index 0000000000..f3eb207d1e --- /dev/null +++ b/build/cmake_macros/pgi_casper.cmake @@ -0,0 +1,15 @@ +if (NOT DEBUG) + string(APPEND CFLAGS " -O -tp=skylake -Mnofma") +endif() +if (NOT DEBUG) + string(APPEND FFLAGS " -O -tp=skylake -Mnofma") +endif() +string(APPEND FFLAGS " -I$(EXEROOT)/ocn/obj/FMS") +if (NOT DEBUG) + string(APPEND LDFLAGS " -O -tp=skylake -Mnofma") +endif() +string(APPEND SLIBS " -llapack -lblas") +if (MPILIB STREQUAL mpi-serial) + string(APPEND SLIBS " -ldl") +endif() +string(APPEND SLIBS " -L${NETCDF_PATH}/lib -lnetcdf -lnetcdff") diff --git a/build/cmake_macros/pgi_cheyenne.cmake b/build/cmake_macros/pgi_cheyenne.cmake new file mode 100644 index 0000000000..e3769dd9d7 --- /dev/null +++ b/build/cmake_macros/pgi_cheyenne.cmake @@ -0,0 +1,4 @@ +string(APPEND SLIBS " -llapack -lblas") +if (MPILIB STREQUAL mpi-serial) + string(APPEND SLIBS " -ldl") +endif() diff --git a/build/cmake_macros/pgi_constance.cmake b/build/cmake_macros/pgi_constance.cmake new file mode 100644 index 0000000000..1a1dcf69b3 --- /dev/null +++ b/build/cmake_macros/pgi_constance.cmake @@ -0,0 +1,11 @@ +if (NOT DEBUG) + string(APPEND CFLAGS " -O2") +endif() +set(CONFIG_ARGS "--host=cray") +string(APPEND CPPDEFS " -DLINUX") +if (NOT DEBUG) + string(APPEND FFLAGS " -O2") +endif() +set(NETCDF_PATH "$ENV{NETCDF_HOME}") +set(PIO_FILESYSTEM_HINTS "lustre") +set(SLIBS "-L${NETCDF_PATH}/lib -lnetcdf -lnetcdff -lpmi") diff --git a/build/cmake_macros/pgi_daint.cmake b/build/cmake_macros/pgi_daint.cmake new file mode 100644 index 0000000000..9c9661883e --- /dev/null +++ b/build/cmake_macros/pgi_daint.cmake @@ -0,0 +1,3 @@ +string(APPEND FFLAGS " -I/project/s824/edavin/OASIS3-MCT_2.0/build.pgi/build/lib/mct -I/project/s824/edavin/OASIS3-MCT_2.0/build.pgi/build/lib/psmile.MPI1") +string(APPEND SLIBS " -llapack -lblas") +string(APPEND SLIBS " -L/project/s824/edavin/OASIS3-MCT_2.0/build.pgi/lib -lpsmile.MPI1 -lscrip -lmct_oasis -lmpeu_oasis") diff --git a/build/cmake_macros/pgi_eastwind.cmake b/build/cmake_macros/pgi_eastwind.cmake new file mode 100644 index 0000000000..6384e42c21 --- /dev/null +++ b/build/cmake_macros/pgi_eastwind.cmake @@ -0,0 +1,20 @@ +if (NOT DEBUG) + string(APPEND CFLAGS " -O2") +endif() +if (NOT compile_threaded) + string(APPEND CFLAGS " -nomp") +endif() +set(CONFIG_ARGS "--host=cray") +string(APPEND CPPDEFS " -DLINUX") +if (NOT DEBUG) + string(APPEND FFLAGS " -O2") +endif() +if (NOT compile_threaded) + string(APPEND FFLAGS " -nomp") +endif() +if (NOT compile_threaded) + string(APPEND LDFLAGS " -nomp") +endif() +set(NETCDF_PATH "$ENV{NETCDF_HOME}") +set(PIO_FILESYSTEM_HINTS "lustre") +set(SLIBS "-L${NETCDF_PATH}/lib -lnetcdf -lnetcdff -lpmi") diff --git a/build/cmake_macros/pgi_euler2.cmake b/build/cmake_macros/pgi_euler2.cmake new file mode 100644 index 0000000000..be865e50f9 --- /dev/null +++ b/build/cmake_macros/pgi_euler2.cmake @@ -0,0 +1,6 @@ +if (NOT DEBUG) + string(APPEND CFLAGS " -O2") +endif() +if (NOT DEBUG) + string(APPEND FFLAGS " -O2") +endif() diff --git a/build/cmake_macros/pgi_euler3.cmake b/build/cmake_macros/pgi_euler3.cmake new file mode 100644 index 0000000000..be865e50f9 --- /dev/null +++ b/build/cmake_macros/pgi_euler3.cmake @@ -0,0 +1,6 @@ +if (NOT DEBUG) + string(APPEND CFLAGS " -O2") +endif() +if (NOT DEBUG) + string(APPEND FFLAGS " -O2") +endif() diff --git a/build/cmake_macros/pgi_euler4.cmake b/build/cmake_macros/pgi_euler4.cmake new file mode 100644 index 0000000000..be865e50f9 --- /dev/null +++ b/build/cmake_macros/pgi_euler4.cmake @@ -0,0 +1,6 @@ +if (NOT DEBUG) + string(APPEND CFLAGS " -O2") +endif() +if (NOT DEBUG) + string(APPEND FFLAGS " -O2") +endif() diff --git a/build/cmake_macros/pgi_hobart.cmake b/build/cmake_macros/pgi_hobart.cmake new file mode 100644 index 0000000000..d3daece90a --- /dev/null +++ b/build/cmake_macros/pgi_hobart.cmake @@ -0,0 +1,10 @@ +if (NOT DEBUG) + string(APPEND CFLAGS " -O0") +endif() +if (NOT DEBUG) + string(APPEND FFLAGS " -O0") +endif() +string(APPEND LDFLAGS " -lgomp") +string(APPEND LDFLAGS " -Wl,-R${NETCDF_PATH}/lib") +string(APPEND LDFLAGS " -Wl,-R$ENV{COMPILER_PATH}/lib") +string(APPEND LDFLAGS " -Wl,-R$ENV{COMPILER_PATH}/libso") diff --git a/build/cmake_macros/pgi_izumi.cmake b/build/cmake_macros/pgi_izumi.cmake new file mode 100644 index 0000000000..3cb6b34e86 --- /dev/null +++ b/build/cmake_macros/pgi_izumi.cmake @@ -0,0 +1,2 @@ +set(CXX_LINKER "FORTRAN") +set(SUPPORTS_CXX "TRUE") diff --git a/build/cmake_macros/pgi_olympus.cmake b/build/cmake_macros/pgi_olympus.cmake new file mode 100644 index 0000000000..1ee0816812 --- /dev/null +++ b/build/cmake_macros/pgi_olympus.cmake @@ -0,0 +1,11 @@ +if (NOT DEBUG) + string(APPEND CFLAGS " -O2") +endif() +set(CONFIG_ARGS "--host=cray") +string(APPEND CPPDEFS " -DLINUX") +if (NOT DEBUG) + string(APPEND FFLAGS " -O2") +endif() +set(NETCDF_PATH "$ENV{NETCDF_LIB}/..") +set(PIO_FILESYSTEM_HINTS "lustre") +set(SLIBS "-L${NETCDF_PATH}/lib -lnetcdf -lnetcdff -lpmi") diff --git a/build/cmake_macros/pleiades-bro.cmake b/build/cmake_macros/pleiades-bro.cmake new file mode 100644 index 0000000000..f3e3bf82dd --- /dev/null +++ b/build/cmake_macros/pleiades-bro.cmake @@ -0,0 +1,6 @@ +string(APPEND CFLAGS " -axCORE-AVX2 -xSSE4.2 -no-fma") +string(APPEND FFLAGS " -axCORE-AVX2 -xSSE4.2 -no-fma") +set(MPICC "icc") +set(MPI_PATH "$ENV{MPI_ROOT}") +set(NETCDF_PATH "$ENV{NETCDF}") +set(PNETCDF_PATH "/home6/fvitt/pnetcdf/pnetcdf-1.12.2") diff --git a/build/cmake_macros/pleiades-has.cmake b/build/cmake_macros/pleiades-has.cmake new file mode 100644 index 0000000000..f3e3bf82dd --- /dev/null +++ b/build/cmake_macros/pleiades-has.cmake @@ -0,0 +1,6 @@ +string(APPEND CFLAGS " -axCORE-AVX2 -xSSE4.2 -no-fma") +string(APPEND FFLAGS " -axCORE-AVX2 -xSSE4.2 -no-fma") +set(MPICC "icc") +set(MPI_PATH "$ENV{MPI_ROOT}") +set(NETCDF_PATH "$ENV{NETCDF}") +set(PNETCDF_PATH "/home6/fvitt/pnetcdf/pnetcdf-1.12.2") diff --git a/build/cmake_macros/pleiades-ivy.cmake b/build/cmake_macros/pleiades-ivy.cmake new file mode 100644 index 0000000000..f3e3bf82dd --- /dev/null +++ b/build/cmake_macros/pleiades-ivy.cmake @@ -0,0 +1,6 @@ +string(APPEND CFLAGS " -axCORE-AVX2 -xSSE4.2 -no-fma") +string(APPEND FFLAGS " -axCORE-AVX2 -xSSE4.2 -no-fma") +set(MPICC "icc") +set(MPI_PATH "$ENV{MPI_ROOT}") +set(NETCDF_PATH "$ENV{NETCDF}") +set(PNETCDF_PATH "/home6/fvitt/pnetcdf/pnetcdf-1.12.2") diff --git a/build/cmake_macros/pleiades-san.cmake b/build/cmake_macros/pleiades-san.cmake new file mode 100644 index 0000000000..f3e3bf82dd --- /dev/null +++ b/build/cmake_macros/pleiades-san.cmake @@ -0,0 +1,6 @@ +string(APPEND CFLAGS " -axCORE-AVX2 -xSSE4.2 -no-fma") +string(APPEND FFLAGS " -axCORE-AVX2 -xSSE4.2 -no-fma") +set(MPICC "icc") +set(MPI_PATH "$ENV{MPI_ROOT}") +set(NETCDF_PATH "$ENV{NETCDF}") +set(PNETCDF_PATH "/home6/fvitt/pnetcdf/pnetcdf-1.12.2") diff --git a/build/cmake_macros/stampede2-knl.cmake b/build/cmake_macros/stampede2-knl.cmake new file mode 100644 index 0000000000..ed1c0d299b --- /dev/null +++ b/build/cmake_macros/stampede2-knl.cmake @@ -0,0 +1,4 @@ +string(APPEND CPPDEFS " -DHAVE_NANOTIME") +set(NETCDF_PATH "$ENV{TACC_NETCDF_DIR}") +set(PIO_FILESYSTEM_HINTS "lustre") +set(PNETCDF_PATH "$ENV{TACC_PNETCDF_DIR}") diff --git a/build/cmake_macros/stampede2-skx.cmake b/build/cmake_macros/stampede2-skx.cmake new file mode 100644 index 0000000000..ed1c0d299b --- /dev/null +++ b/build/cmake_macros/stampede2-skx.cmake @@ -0,0 +1,4 @@ +string(APPEND CPPDEFS " -DHAVE_NANOTIME") +set(NETCDF_PATH "$ENV{TACC_NETCDF_DIR}") +set(PIO_FILESYSTEM_HINTS "lustre") +set(PNETCDF_PATH "$ENV{TACC_PNETCDF_DIR}") diff --git a/build/cmake_macros/theta.cmake b/build/cmake_macros/theta.cmake new file mode 100644 index 0000000000..81db81ed2c --- /dev/null +++ b/build/cmake_macros/theta.cmake @@ -0,0 +1,4 @@ +string(APPEND CFLAGS " -xMIC-AVX512") +string(APPEND FFLAGS " -xMIC-AVX512") +set(CONFIG_ARGS "--host=cray") +string(APPEND SLIBS " -L$(NETCDF_DIR)/lib -lnetcdff -L$(NETCDF_DIR)/lib -lnetcdf -Wl,-rpath -Wl,$(NETCDF_DIR)/lib") diff --git a/build/cmake_macros/universal.cmake b/build/cmake_macros/universal.cmake new file mode 100644 index 0000000000..a1acb1ac17 --- /dev/null +++ b/build/cmake_macros/universal.cmake @@ -0,0 +1,18 @@ +string(APPEND CPPDEFS " -DCESMCOUPLED") +if (COMP_NAME STREQUAL pop) + string(APPEND CPPDEFS " -D_USE_FLOW_CONTROL") +endif() +if (COMP_NAME STREQUAL ufsatm) + string(APPEND CPPDEFS " -DSPMD") +endif() +if (COMP_NAME STREQUAL ufsatm) + string(APPEND INCLDIR " -I$(EXEROOT)/atm/obj/FMS") +endif() +if (COMP_NAME STREQUAL ufsatm) + string(APPEND FFLAGS " $(FC_AUTO_R8)") +endif() +if (COMP_NAME STREQUAL mom) + string(APPEND FFLAGS " $(FC_AUTO_R8) ") + string(APPEND CPPDEFS " -Duse_LARGEFILE") +endif() +set(SUPPORTS_CXX "FALSE") diff --git a/build/cmake_macros/userdefined.cmake b/build/cmake_macros/userdefined.cmake new file mode 100644 index 0000000000..798dcc9714 --- /dev/null +++ b/build/cmake_macros/userdefined.cmake @@ -0,0 +1,9 @@ +set(CONFIG_ARGS "") +string(APPEND CPPDEFS " ") +set(ESMF_LIBDIR "") +set(MPI_LIB_NAME "") +set(MPI_PATH "") +set(NETCDF_PATH "USERDEFINED_MUST_EDIT_THIS") +set(PNETCDF_PATH "") +execute_process(COMMAND ${NETCDF_PATH}/bin/nc-config --flibs OUTPUT_VARIABLE SHELL_CMD_OUTPUT_BUILD_INTERNAL_IGNORE0 OUTPUT_STRIP_TRAILING_WHITESPACE) +string(APPEND SLIBS " # USERDEFINED ${SHELL_CMD_OUTPUT_BUILD_INTERNAL_IGNORE0}") diff --git a/build/cmake_macros/zeus.cmake b/build/cmake_macros/zeus.cmake new file mode 100644 index 0000000000..8c24e3dc9b --- /dev/null +++ b/build/cmake_macros/zeus.cmake @@ -0,0 +1,8 @@ +set(PIO_FILESYSTEM_HINTS "gpfs") +set(NETCDF_PATH "$ENV{NETCDF}") +set(PNETCDF_PATH "$ENV{PNETCDF}") +string(APPEND CPPDEFS " -DNO_R16 -DHAVE_NANOTIME") +if (COMP_NAME STREQUAL nemo) + string(APPEND FFLAGS " $(FC_AUTO_R8) -O3 -assume norealloc_lhs") +endif() +execute_process(COMMAND ${NETCDF_PATH}/bin/nc-config --flibs) diff --git a/build/env_mach_specific.xml b/build/env_mach_specific.xml new file mode 100644 index 0000000000..dc1c9f88e9 --- /dev/null +++ b/build/env_mach_specific.xml @@ -0,0 +1,32 @@ + + +
+ These variables control the machine dependent environment including + the paths to compilers and libraries external to cime such as netcdf, + environment variables for use in the running job should also be set here. +
+ + + char + executable name + + + char + redirect for job output + + + + + /Users/afoster/esmf/esmf-8.4.0/lib/libg/Darwin.gfortranclang.64.openmpi.default/esmf.mk + + + mpirun + + -np $TOTALPES + --tag-output + + + + + +
diff --git a/test_list.xml b/test_list.xml new file mode 100644 index 0000000000..41719be6c2 --- /dev/null +++ b/test_list.xml @@ -0,0 +1,7 @@ + + + + unit_testing/test/radiation_test + + + diff --git a/unit_testing/test/radiation_test/FatesUnitTestRadiation.F90 b/unit_testing/test/radiation_test/FatesUnitTestRadiation.F90 index 21ca8c57df..042f5e71e2 100644 --- a/unit_testing/test/radiation_test/FatesUnitTestRadiation.F90 +++ b/unit_testing/test/radiation_test/FatesUnitTestRadiation.F90 @@ -13,68 +13,41 @@ program FatesUnitTestRadiation implicit none ! LOCALS: - character(len=256) :: param_file, patch_file, out_file ! file names - integer :: numpft, numSWb - ! real(r8) :: rhol(num_pft,num_swb) ! leaf reflectance (0-1) - ! real(r8) :: rhos(num_pft,num_swb) ! stem reflectance (0-1) - ! real(r8) :: taul(num_pft,num_swb) ! leaf transmittance (0-1) - ! real(r8) :: taus(num_pft,num_swb) ! stem transmittance (0-1) - ! real(r8) :: xl(num_pft) ! leaf/stem orientation index (-1-1) - ! real(r8) :: clumping_index(num_pft) ! clumping index (0-1) - ! real(r8) :: fcansno ! fraction of canopy covered by snow - ! real(r8) :: canopy_area_profile(num_can,num_pft,nlevleaf) ! fraction of crown area per canopy area in each layer - ! real(r8) :: elai_profile(num_can,num_pft,nlevleaf) ! exposed leaf area in each canopy layer, pft, and leaf layer - ! real(r8) :: esai_profile(num_can,num_pft,nlevleaf) ! exposed stem area in each canopy layer, pft, and leaf layer - ! real(r8) :: nrad_r(num_can,num_pft) ! number of exposed leaf layers for each canopy layer and pft - ! integer :: nrad(num_can,num_pft) ! number of exposed leaf layers for each canopy layer and pft - ! real(r8) :: k_dir(num_pft,48) ! direct beam extinction coefficient - ! real(SHR_KIND_R8) :: eccen ! orbital eccentricity - ! real(SHR_KIND_R8) :: mvelp ! moving vernal equinox long - ! real(SHR_KIND_R8) :: obliqr ! Earths obliquity in rad - ! real(SHR_KIND_R8) :: lambm0 ! Mean long of perihelion at vernal equinox (radians) - ! real(SHR_KIND_R8) :: mvelpp ! moving vernal equinox long of perihelion plus pi (rad) - ! real(SHR_KIND_R8) :: eccf ! Earth-sun distance factor (ie. (1/r)**2) - ! real(SHR_KIND_R8) :: calday ! calendar day (including fraction) - ! real(SHR_KIND_R8) :: declin ! solar declination (radians) - ! real(SHR_KIND_R8) :: cosz(48) ! cosine of solar zenith angle (radians) - ! real(r8) :: lat, lon - ! integer :: jday ! julian day - ! integer :: year ! year - ! integer :: i ! looping index + character(len=MAX_PATH) :: param_file, patch_file, out_file ! file names + integer :: numSWb ! number of shortwave bands to simulate + integer :: year, jday ! year and day of year to simulate + real(r8) :: lat, lon ! latitude/longitude to simulate [degrees] + real(r8) :: fcansno ! fraction of canopy covered by snow [0-1] interface - subroutine read_radiation_namelist(numpft, numSWb, param_file, patch_file, & - out_file) + subroutine read_radiation_namelist(numSWb, year, jday, lat, lon, fcansno, & + param_file, patch_file, out_file) use FatesUnitTestIOMod, only : MAX_PATH, MAX_CHAR, open_file implicit none - character(len=MAX_PATH), intent(out) :: param_file, patch_file, out_file ! file names - integer, intent(out) :: numpft, numSWb + character(len=MAX_PATH), intent(out) :: param_file, patch_file, out_file + integer, intent(out) :: numSWb, year, jday + real(r8), intent(out) :: lat, lon + real(r8), intent(out) :: fcansno end subroutine read_radiation_namelist end interface - print *, 'Hello, unit test' - - ! file_names - ! logf = open_file("log.txt") - - ! ! set julian day, year, and lat/lon here - ! jday = 165 - ! year = 2000 - ! lat = 45.76_r8*pi_const/180.0_r8 - ! lon = 237.67_r8*pi_const/180.0_r8 - ! fcansno = 0.0_r8 - - ! ! get patch and parameter values, as well as orbital parameters - ! call get_parameters(file_in, rhol, rhos, taul, taus, xl, clumping_index) + call read_radiation_namelist(numSWB, year, jday, lat, lon, fcansno, & + param_file, patch_file, out_file) + + ! open log file + logf = open_file("log.txt") + + ! get patch and parameter values, as well as orbital parameters + !call get_parameters(param_file, rhol, rhos, taul, taus, xl, clumping_index) + ! call read_patch_data(patch_file, canopy_area_profile, elai_profile, & ! esai_profile, nrad_r) - ! nrad = int(nrad_r) ! call get_orbital_vals(year, logf, eccen, mvelp, obliqr, lambm0, mvelpp) ! cosz(:) = 0.0 @@ -100,8 +73,8 @@ end program FatesUnitTestRadiation !:.............................................................................: -subroutine read_radiation_namelist(numpft, numSWb, param_file, patch_file, & - out_file) +subroutine read_radiation_namelist(numSWb, year, jday, lat, lon, fcansno, & + param_file, patch_file, out_file) use FatesUnitTestIOMod, only : MAX_PATH, MAX_CHAR, open_file @@ -115,7 +88,10 @@ subroutine read_radiation_namelist(numpft, numSWb, param_file, patch_file, & ! ARGUMENTS: character(len=MAX_PATH), intent(out) :: param_file, patch_file, out_file ! file names - integer, intent(out) :: numpft, numSWb + integer, intent(out) :: numSWb ! number of shortwave bands + integer, intent(out) :: year, jday ! year and day of year + real(r8), intent(out) :: lat, lon ! latitude and longitude [degrees] + real(r8), intent(out) :: fcansno ! fraction of canopy covered by snow [0-1] ! LOCALS: character(len=MAX_PATH) :: rad_nl = 'radiation_nl' ! radiation namelist name @@ -126,8 +102,8 @@ subroutine read_radiation_namelist(numpft, numSWb, param_file, patch_file, & ! Namelist of radiation parameters - namelist /radiation/ numpft, numSWb, param_file, patch_file, out_file - + namelist /radiation/ numSWb, year, jday, lat, lon, fcansno, param_file, & + patch_file, out_file ! Now read parameters namelist rad_nl_file = open_file(trim(rad_nl), 'r') diff --git a/unit_testing/test/radiation_test/radiation_nl b/unit_testing/test/radiation_test/radiation_nl new file mode 100644 index 0000000000..9b33dbf6e3 --- /dev/null +++ b/unit_testing/test/radiation_test/radiation_nl @@ -0,0 +1,13 @@ +&radiation +! parameters for the radiation unit test +! see FatesUnitTestRadiation.F90 +numSWb = 2 +year = 2000 +jday = 165 +lat = 45.0 +lon = 238.0 +fcansno = 0.0 +param_file = '/Users/afoster/Documents/ncar/fates/albedo_calib/fates_params_default.nc' +patch_file = 'patch_data.nc' +out_file = 'radiation_out.nc' +/ From 41ee71fd8b7ead4ec90ca9f85f9539d151d044ed Mon Sep 17 00:00:00 2001 From: adrifoster Date: Thu, 13 Apr 2023 09:20:04 -0600 Subject: [PATCH 639/852] accidentally added build --- build/.env_mach_specific.csh | 8 - build/.env_mach_specific.sh | 8 - build/Depends.gnu | 2 - build/Macros.cmake | 37 - .../__command_line_test__/CMakeCache.txt | 492 -------- .../CMakeFiles/3.25.2/CMakeCCompiler.cmake | 72 -- .../3.25.2/CMakeDetermineCompilerABI_C.bin | Bin 16688 -> 0 bytes .../CMakeDetermineCompilerABI_Fortran.bin | Bin 33512 -> 0 bytes .../3.25.2/CMakeFortranCompiler.cmake | 62 - .../CMakeFiles/3.25.2/CMakeSystem.cmake | 15 - .../3.25.2/CompilerIdC/CMakeCCompilerId.c | 868 ------------- .../CMakeFortranCompilerId.F | 1114 ----------------- .../CMakeDirectoryInformation.cmake | 16 - .../CMakeFiles/Makefile.cmake | 141 --- .../CMakeFiles/Makefile2 | 206 --- .../CMakeFiles/Progress/1 | 1 - .../CMakeFiles/Progress/2 | 1 - .../CMakeFiles/Progress/3 | 1 - .../CMakeFiles/Progress/4 | 1 - .../CMakeFiles/Progress/6 | 1 - .../CMakeFiles/Progress/7 | 1 - .../CMakeFiles/Progress/8 | 1 - .../CMakeFiles/Progress/9 | 1 - .../CMakeFiles/Progress/count.txt | 1 - .../CMakeFiles/TargetDirectories.txt | 17 - .../CMakeFiles/cmake.check_cache | 1 - .../CMakeFiles/progress.marks | 1 - .../CMakeFiles/utils.dir/DependInfo.cmake | 37 - .../CMakeFiles/utils.dir/build.make | 140 --- .../CMakeFiles/utils.dir/cmake_clean.cmake | 12 - .../utils.dir/cmake_clean_Fortran.cmake | 14 - .../utils.dir/cmake_clean_target.cmake | 3 - .../CMakeFiles/utils.dir/compiler_depend.make | 2 - .../CMakeFiles/utils.dir/compiler_depend.ts | 2 - .../CMakeFiles/utils.dir/depend.internal | 9 - .../CMakeFiles/utils.dir/depend.make | 25 - .../utils.dir/fatesconstantsmod.mod.stamp | Bin 2256 -> 0 bytes .../utils.dir/fatesunittestiomod.mod.stamp | Bin 24087 -> 0 bytes .../fatesunittestorbitalmod.mod.stamp | Bin 25076 -> 0 bytes .../CMakeFiles/utils.dir/flags.make | 10 - .../CMakeFiles/utils.dir/fortran.internal | 5 - .../CMakeFiles/utils.dir/link.txt | 2 - .../FatesConstantsMod.F90.o.provides.build | 0 .../CMakeFiles/utils.dir/progress.make | 5 - .../FatesUnitTestIOMod.F90.o.provides.build | 0 ...tesUnitTestOrbitalMod.F90.o.provides.build | 0 .../__command_line_test__/CTestTestfile.cmake | 9 - .../__command_line_test__/Macros.cmake | 1 - .../__command_line_test__/Makefile | 260 ---- .../__command_line_test__/cmake_install.cmake | 57 - .../__command_line_test__/libutils.a | Bin 40264 -> 0 bytes .../CMakeDirectoryInformation.cmake | 16 - .../main/CMakeFiles/progress.marks | 1 - .../main/CTestTestfile.cmake | 6 - .../__command_line_test__/main/Makefile | 151 --- .../main/cmake_install.cmake | 39 - .../CMakeDirectoryInformation.cmake | 16 - .../test/CMakeFiles/progress.marks | 1 - .../unit_testing/test/CTestTestfile.cmake | 7 - .../unit_testing/test/Makefile | 151 --- .../unit_testing/test/cmake_install.cmake | 45 - .../CMakeDirectoryInformation.cmake | 16 - .../FATES_rad_test.dir/DependInfo.cmake | 37 - .../FatesConstantsMod.F90.o.provides.build | 0 .../FatesUnitTestIOMod.F90.o.provides.build | 0 ...tesUnitTestOrbitalMod.F90.o.provides.build | 0 .../CMakeFiles/FATES_rad_test.dir/build.make | 154 --- .../FATES_rad_test.dir/cmake_clean.cmake | 13 - .../cmake_clean_Fortran.cmake | 14 - .../FATES_rad_test.dir/compiler_depend.make | 2 - .../FATES_rad_test.dir/compiler_depend.ts | 2 - .../FATES_rad_test.dir/depend.internal | 11 - .../CMakeFiles/FATES_rad_test.dir/depend.make | 27 - .../fatesconstantsmod.mod.stamp | Bin 2256 -> 0 bytes .../fatesunittestiomod.mod.stamp | Bin 24087 -> 0 bytes .../fatesunittestorbitalmod.mod.stamp | Bin 25076 -> 0 bytes .../CMakeFiles/FATES_rad_test.dir/flags.make | 10 - .../FATES_rad_test.dir/fortran.internal | 5 - .../CMakeFiles/FATES_rad_test.dir/link.txt | 1 - .../FATES_rad_test.dir/progress.make | 6 - .../radiation_test/CMakeFiles/progress.marks | 1 - .../test/radiation_test/CTestTestfile.cmake | 8 - .../unit_testing/test/radiation_test/Makefile | 274 ---- .../test/radiation_test/cmake_install.cmake | 39 - .../CMakeDirectoryInformation.cmake | 16 - .../utils/CMakeFiles/progress.marks | 1 - .../unit_testing/utils/CTestTestfile.cmake | 6 - .../unit_testing/utils/Makefile | 151 --- .../unit_testing/utils/cmake_install.cmake | 39 - build/cmake_macros/CMakeLists.txt | 4 - build/cmake_macros/CNL.cmake | 14 - build/cmake_macros/Darwin.cmake | 1 - build/cmake_macros/Macros.cmake | 37 - build/cmake_macros/arm.cmake | 0 build/cmake_macros/armgcc.cmake | 0 build/cmake_macros/athena.cmake | 0 build/cmake_macros/bluewaters.cmake | 0 build/cmake_macros/casper.cmake | 0 build/cmake_macros/centos7-linux.cmake | 1 - build/cmake_macros/cheyenne.cmake | 6 - build/cmake_macros/container.cmake | 7 - build/cmake_macros/cray.cmake | 37 - build/cmake_macros/cray_daint.cmake | 2 - build/cmake_macros/euler2.cmake | 5 - build/cmake_macros/euler3.cmake | 5 - build/cmake_macros/euler4.cmake | 5 - build/cmake_macros/frontera.cmake | 9 - build/cmake_macros/gnu.cmake | 43 - build/cmake_macros/gnu_cheyenne.cmake | 4 - build/cmake_macros/gnu_coeus.cmake | 2 - build/cmake_macros/gnu_fleabone.cmake | 27 - build/cmake_macros/gnu_hobart.cmake | 1 - build/cmake_macros/gnu_homebrew.cmake | 1 - build/cmake_macros/gnu_lobata.cmake | 15 - build/cmake_macros/gnu_melvin.cmake | 13 - build/cmake_macros/gnu_modex.cmake | 5 - build/cmake_macros/gust.cmake | 10 - build/cmake_macros/hobart.cmake | 9 - build/cmake_macros/ibm.cmake | 38 - build/cmake_macros/ibm_AIX.cmake | 18 - build/cmake_macros/ibm_BGQ.cmake | 11 - build/cmake_macros/intel.cmake | 61 - build/cmake_macros/intel_Darwin.cmake | 3 - build/cmake_macros/intel_aleph.cmake | 8 - build/cmake_macros/intel_athena.cmake | 20 - build/cmake_macros/intel_aws-hpc6a.cmake | 8 - build/cmake_macros/intel_bluewaters.cmake | 3 - build/cmake_macros/intel_casper.cmake | 9 - build/cmake_macros/intel_cheyenne.cmake | 12 - build/cmake_macros/intel_constance.cmake | 11 - build/cmake_macros/intel_cori-haswell.cmake | 9 - build/cmake_macros/intel_cori-knl.cmake | 9 - build/cmake_macros/intel_eastwind.cmake | 11 - build/cmake_macros/intel_edison.cmake | 11 - build/cmake_macros/intel_euler2.cmake | 7 - build/cmake_macros/intel_euler3.cmake | 7 - build/cmake_macros/intel_euler4.cmake | 7 - .../intel_greenplanet-sib29.cmake | 3 - .../intel_greenplanet-sky24.cmake | 3 - build/cmake_macros/intel_gust.cmake | 6 - build/cmake_macros/intel_hobart.cmake | 16 - build/cmake_macros/intel_izumi.cmake | 3 - build/cmake_macros/intel_laramie.cmake | 5 - build/cmake_macros/intel_lawrencium-lr3.cmake | 12 - build/cmake_macros/intel_sandiatoss3.cmake | 12 - build/cmake_macros/intel_stampede2-knl.cmake | 10 - build/cmake_macros/intel_stampede2-skx.cmake | 10 - build/cmake_macros/intel_theia.cmake | 4 - build/cmake_macros/intel_zeus.cmake | 18 - build/cmake_macros/izumi.cmake | 9 - build/cmake_macros/laramie.cmake | 6 - build/cmake_macros/lonestar5.cmake | 6 - build/cmake_macros/nag.cmake | 30 - build/cmake_macros/nvhpc-gpu.cmake | 46 - build/cmake_macros/nvhpc-gpu_casper.cmake | 15 - build/cmake_macros/nvhpc.cmake | 51 - build/cmake_macros/nvhpc_casper.cmake | 15 - build/cmake_macros/nvhpc_cheyenne.cmake | 4 - build/cmake_macros/nvhpc_gust.cmake | 3 - build/cmake_macros/oneapi.cmake | 61 - build/cmake_macros/pgi-gpu.cmake | 46 - build/cmake_macros/pgi-gpu_casper.cmake | 15 - build/cmake_macros/pgi.cmake | 46 - build/cmake_macros/pgi_bluewaters.cmake | 10 - build/cmake_macros/pgi_casper.cmake | 15 - build/cmake_macros/pgi_cheyenne.cmake | 4 - build/cmake_macros/pgi_constance.cmake | 11 - build/cmake_macros/pgi_daint.cmake | 3 - build/cmake_macros/pgi_eastwind.cmake | 20 - build/cmake_macros/pgi_euler2.cmake | 6 - build/cmake_macros/pgi_euler3.cmake | 6 - build/cmake_macros/pgi_euler4.cmake | 6 - build/cmake_macros/pgi_hobart.cmake | 10 - build/cmake_macros/pgi_izumi.cmake | 2 - build/cmake_macros/pgi_olympus.cmake | 11 - build/cmake_macros/pleiades-bro.cmake | 6 - build/cmake_macros/pleiades-has.cmake | 6 - build/cmake_macros/pleiades-ivy.cmake | 6 - build/cmake_macros/pleiades-san.cmake | 6 - build/cmake_macros/stampede2-knl.cmake | 4 - build/cmake_macros/stampede2-skx.cmake | 4 - build/cmake_macros/theta.cmake | 4 - build/cmake_macros/universal.cmake | 18 - build/cmake_macros/userdefined.cmake | 9 - build/cmake_macros/zeus.cmake | 8 - build/env_mach_specific.xml | 32 - 186 files changed, 6116 deletions(-) delete mode 100644 build/.env_mach_specific.csh delete mode 100644 build/.env_mach_specific.sh delete mode 100644 build/Depends.gnu delete mode 100644 build/Macros.cmake delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeCache.txt delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CMakeCCompiler.cmake delete mode 100755 build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CMakeDetermineCompilerABI_C.bin delete mode 100755 build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CMakeDetermineCompilerABI_Fortran.bin delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CMakeFortranCompiler.cmake delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CMakeSystem.cmake delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CompilerIdC/CMakeCCompilerId.c delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CompilerIdFortran/CMakeFortranCompilerId.F delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/CMakeDirectoryInformation.cmake delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/Makefile.cmake delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/Makefile2 delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/1 delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/2 delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/3 delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/4 delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/6 delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/7 delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/8 delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/9 delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/count.txt delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/TargetDirectories.txt delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/cmake.check_cache delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/progress.marks delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/DependInfo.cmake delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/build.make delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/cmake_clean.cmake delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/cmake_clean_Fortran.cmake delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/cmake_clean_target.cmake delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/compiler_depend.make delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/compiler_depend.ts delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/depend.internal delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/depend.make delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fatesconstantsmod.mod.stamp delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fatesunittestiomod.mod.stamp delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fatesunittestorbitalmod.mod.stamp delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/flags.make delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fortran.internal delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/link.txt delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o.provides.build delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/progress.make delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o.provides.build delete mode 100644 build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o.provides.build delete mode 100644 build/__command_line_test__/__command_line_test__/CTestTestfile.cmake delete mode 120000 build/__command_line_test__/__command_line_test__/Macros.cmake delete mode 100644 build/__command_line_test__/__command_line_test__/Makefile delete mode 100644 build/__command_line_test__/__command_line_test__/cmake_install.cmake delete mode 100644 build/__command_line_test__/__command_line_test__/libutils.a delete mode 100644 build/__command_line_test__/__command_line_test__/main/CMakeFiles/CMakeDirectoryInformation.cmake delete mode 100644 build/__command_line_test__/__command_line_test__/main/CMakeFiles/progress.marks delete mode 100644 build/__command_line_test__/__command_line_test__/main/CTestTestfile.cmake delete mode 100644 build/__command_line_test__/__command_line_test__/main/Makefile delete mode 100644 build/__command_line_test__/__command_line_test__/main/cmake_install.cmake delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/CMakeFiles/CMakeDirectoryInformation.cmake delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/CMakeFiles/progress.marks delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/CTestTestfile.cmake delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/Makefile delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/cmake_install.cmake delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/CMakeDirectoryInformation.cmake delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/DependInfo.cmake delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o.provides.build delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o.provides.build delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o.provides.build delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/cmake_clean.cmake delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/cmake_clean_Fortran.cmake delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/compiler_depend.make delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/compiler_depend.ts delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/depend.internal delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/depend.make delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesconstantsmod.mod.stamp delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestiomod.mod.stamp delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestorbitalmod.mod.stamp delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/flags.make delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fortran.internal delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/link.txt delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/progress.make delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/progress.marks delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CTestTestfile.cmake delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/Makefile delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/cmake_install.cmake delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/utils/CMakeFiles/CMakeDirectoryInformation.cmake delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/utils/CMakeFiles/progress.marks delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/utils/CTestTestfile.cmake delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/utils/Makefile delete mode 100644 build/__command_line_test__/__command_line_test__/unit_testing/utils/cmake_install.cmake delete mode 100644 build/cmake_macros/CMakeLists.txt delete mode 100644 build/cmake_macros/CNL.cmake delete mode 100644 build/cmake_macros/Darwin.cmake delete mode 100644 build/cmake_macros/Macros.cmake delete mode 100644 build/cmake_macros/arm.cmake delete mode 100644 build/cmake_macros/armgcc.cmake delete mode 100644 build/cmake_macros/athena.cmake delete mode 100644 build/cmake_macros/bluewaters.cmake delete mode 100644 build/cmake_macros/casper.cmake delete mode 100644 build/cmake_macros/centos7-linux.cmake delete mode 100644 build/cmake_macros/cheyenne.cmake delete mode 100644 build/cmake_macros/container.cmake delete mode 100644 build/cmake_macros/cray.cmake delete mode 100644 build/cmake_macros/cray_daint.cmake delete mode 100644 build/cmake_macros/euler2.cmake delete mode 100644 build/cmake_macros/euler3.cmake delete mode 100644 build/cmake_macros/euler4.cmake delete mode 100644 build/cmake_macros/frontera.cmake delete mode 100644 build/cmake_macros/gnu.cmake delete mode 100644 build/cmake_macros/gnu_cheyenne.cmake delete mode 100644 build/cmake_macros/gnu_coeus.cmake delete mode 100644 build/cmake_macros/gnu_fleabone.cmake delete mode 100644 build/cmake_macros/gnu_hobart.cmake delete mode 100644 build/cmake_macros/gnu_homebrew.cmake delete mode 100644 build/cmake_macros/gnu_lobata.cmake delete mode 100644 build/cmake_macros/gnu_melvin.cmake delete mode 100644 build/cmake_macros/gnu_modex.cmake delete mode 100644 build/cmake_macros/gust.cmake delete mode 100644 build/cmake_macros/hobart.cmake delete mode 100644 build/cmake_macros/ibm.cmake delete mode 100644 build/cmake_macros/ibm_AIX.cmake delete mode 100644 build/cmake_macros/ibm_BGQ.cmake delete mode 100644 build/cmake_macros/intel.cmake delete mode 100644 build/cmake_macros/intel_Darwin.cmake delete mode 100644 build/cmake_macros/intel_aleph.cmake delete mode 100644 build/cmake_macros/intel_athena.cmake delete mode 100644 build/cmake_macros/intel_aws-hpc6a.cmake delete mode 100644 build/cmake_macros/intel_bluewaters.cmake delete mode 100644 build/cmake_macros/intel_casper.cmake delete mode 100644 build/cmake_macros/intel_cheyenne.cmake delete mode 100644 build/cmake_macros/intel_constance.cmake delete mode 100644 build/cmake_macros/intel_cori-haswell.cmake delete mode 100644 build/cmake_macros/intel_cori-knl.cmake delete mode 100644 build/cmake_macros/intel_eastwind.cmake delete mode 100644 build/cmake_macros/intel_edison.cmake delete mode 100644 build/cmake_macros/intel_euler2.cmake delete mode 100644 build/cmake_macros/intel_euler3.cmake delete mode 100644 build/cmake_macros/intel_euler4.cmake delete mode 100644 build/cmake_macros/intel_greenplanet-sib29.cmake delete mode 100644 build/cmake_macros/intel_greenplanet-sky24.cmake delete mode 100644 build/cmake_macros/intel_gust.cmake delete mode 100644 build/cmake_macros/intel_hobart.cmake delete mode 100644 build/cmake_macros/intel_izumi.cmake delete mode 100644 build/cmake_macros/intel_laramie.cmake delete mode 100644 build/cmake_macros/intel_lawrencium-lr3.cmake delete mode 100644 build/cmake_macros/intel_sandiatoss3.cmake delete mode 100644 build/cmake_macros/intel_stampede2-knl.cmake delete mode 100644 build/cmake_macros/intel_stampede2-skx.cmake delete mode 100644 build/cmake_macros/intel_theia.cmake delete mode 100644 build/cmake_macros/intel_zeus.cmake delete mode 100644 build/cmake_macros/izumi.cmake delete mode 100644 build/cmake_macros/laramie.cmake delete mode 100644 build/cmake_macros/lonestar5.cmake delete mode 100644 build/cmake_macros/nag.cmake delete mode 100644 build/cmake_macros/nvhpc-gpu.cmake delete mode 100644 build/cmake_macros/nvhpc-gpu_casper.cmake delete mode 100644 build/cmake_macros/nvhpc.cmake delete mode 100644 build/cmake_macros/nvhpc_casper.cmake delete mode 100644 build/cmake_macros/nvhpc_cheyenne.cmake delete mode 100644 build/cmake_macros/nvhpc_gust.cmake delete mode 100644 build/cmake_macros/oneapi.cmake delete mode 100644 build/cmake_macros/pgi-gpu.cmake delete mode 100644 build/cmake_macros/pgi-gpu_casper.cmake delete mode 100644 build/cmake_macros/pgi.cmake delete mode 100644 build/cmake_macros/pgi_bluewaters.cmake delete mode 100644 build/cmake_macros/pgi_casper.cmake delete mode 100644 build/cmake_macros/pgi_cheyenne.cmake delete mode 100644 build/cmake_macros/pgi_constance.cmake delete mode 100644 build/cmake_macros/pgi_daint.cmake delete mode 100644 build/cmake_macros/pgi_eastwind.cmake delete mode 100644 build/cmake_macros/pgi_euler2.cmake delete mode 100644 build/cmake_macros/pgi_euler3.cmake delete mode 100644 build/cmake_macros/pgi_euler4.cmake delete mode 100644 build/cmake_macros/pgi_hobart.cmake delete mode 100644 build/cmake_macros/pgi_izumi.cmake delete mode 100644 build/cmake_macros/pgi_olympus.cmake delete mode 100644 build/cmake_macros/pleiades-bro.cmake delete mode 100644 build/cmake_macros/pleiades-has.cmake delete mode 100644 build/cmake_macros/pleiades-ivy.cmake delete mode 100644 build/cmake_macros/pleiades-san.cmake delete mode 100644 build/cmake_macros/stampede2-knl.cmake delete mode 100644 build/cmake_macros/stampede2-skx.cmake delete mode 100644 build/cmake_macros/theta.cmake delete mode 100644 build/cmake_macros/universal.cmake delete mode 100644 build/cmake_macros/userdefined.cmake delete mode 100644 build/cmake_macros/zeus.cmake delete mode 100644 build/env_mach_specific.xml diff --git a/build/.env_mach_specific.csh b/build/.env_mach_specific.csh deleted file mode 100644 index 35e5a959f4..0000000000 --- a/build/.env_mach_specific.csh +++ /dev/null @@ -1,8 +0,0 @@ -# This file is for user convenience only and is not used by the model -# Changes to this file will be ignored and overwritten -# Changes to the environment should be made in env_mach_specific.xml -# Run ./case.setup --reset to regenerate this file -setenv COMPILER gnu -setenv MPILIB mpi-serial -setenv DEBUG TRUE -setenv OS Ventura diff --git a/build/.env_mach_specific.sh b/build/.env_mach_specific.sh deleted file mode 100644 index 4adbda012f..0000000000 --- a/build/.env_mach_specific.sh +++ /dev/null @@ -1,8 +0,0 @@ -# This file is for user convenience only and is not used by the model -# Changes to this file will be ignored and overwritten -# Changes to the environment should be made in env_mach_specific.xml -# Run ./case.setup --reset to regenerate this file -export COMPILER=gnu -export MPILIB=mpi-serial -export DEBUG=TRUE -export OS=Ventura diff --git a/build/Depends.gnu b/build/Depends.gnu deleted file mode 100644 index 2d53247217..0000000000 --- a/build/Depends.gnu +++ /dev/null @@ -1,2 +0,0 @@ -geopk.o:geopk.F90 - $(FC) -c $(INCLDIR) $(INCS) $(FFLAGS) $(FREEFLAGS) -fcray-pointer $< diff --git a/build/Macros.cmake b/build/Macros.cmake deleted file mode 100644 index b089f58058..0000000000 --- a/build/Macros.cmake +++ /dev/null @@ -1,37 +0,0 @@ -# -# Use this file to include the relevant macros based on -# machine/compiler settings. This file gets copied to CASEROOT -# and that's the one that gets included by the build system. Feel free -# to modify this file in the CASEROOT. -# -set(MACROS_DIR ${CASEROOT}/cmake_macros) - -set(UNIVERSAL_MACRO ${MACROS_DIR}/universal.cmake) -set(COMPILER_MACRO ${MACROS_DIR}/${COMPILER}.cmake) -set(OS_MACRO ${MACROS_DIR}/${OS}.cmake) -set(MACHINE_MACRO ${MACROS_DIR}/${MACH}.cmake) -set(COMPILER_OS_MACRO ${MACROS_DIR}/${COMPILER}_${OS}.cmake) -set(COMPILER_MACHINE_MACRO ${MACROS_DIR}/${COMPILER}_${MACH}.cmake) - -if (CONVERT_TO_MAKE) - get_cmake_property(VARS_BEFORE_BUILD_INTERNAL_IGNORE VARIABLES) -endif() - -# Include order defines precedence -foreach (MACRO_FILE ${UNIVERSAL_MACRO} ${COMPILER_MACRO} ${OS_MACRO} ${MACHINE_MACRO} ${COMPILER_OS_MACRO} ${COMPILER_MACHINE_MACRO}) - if (EXISTS ${MACRO_FILE}) - include(${MACRO_FILE}) - else() - message("No macro file found: ${MACRO_FILE}") - endif() -endforeach() - -if (CONVERT_TO_MAKE) - get_cmake_property(VARS_AFTER VARIABLES) - - foreach (VAR_AFTER IN LISTS VARS_AFTER) - if (NOT VAR_AFTER IN_LIST VARS_BEFORE_BUILD_INTERNAL_IGNORE) - message("CIME_SET_MAKEFILE_VAR ${VAR_AFTER} := ${${VAR_AFTER}}") - endif() - endforeach() -endif() diff --git a/build/__command_line_test__/__command_line_test__/CMakeCache.txt b/build/__command_line_test__/__command_line_test__/CMakeCache.txt deleted file mode 100644 index c99fedf020..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeCache.txt +++ /dev/null @@ -1,492 +0,0 @@ -# This is the CMakeCache file. -# For build in directory: /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ -# It was generated by CMake: /usr/local/Cellar/cmake/3.25.2/bin/cmake -# You can edit this file to change values found and used by cmake. -# If you do not want to change any of the values, simply exit the editor. -# If you do want to change a value, simply edit, save, and exit the editor. -# The syntax for the file is as follows: -# KEY:TYPE=VALUE -# KEY is the name of a variable in the cache. -# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. -# VALUE is the current value for the KEY. - -######################## -# EXTERNAL cache entries -######################## - -//No help, variable specified on the command line. -CASEROOT:UNINITIALIZED=/Users/afoster/Documents/ncar/CTSM/src/fates/build - -//No help, variable specified on the command line. -CIMEROOT:UNINITIALIZED=/Users/afoster/Documents/ncar/CTSM/cime/scripts/fortran_unit_testing/../.. - -//No help, variable specified on the command line. -CIME_CMAKE_MODULE_DIRECTORY:UNINITIALIZED=/Users/afoster/Documents/ncar/CTSM/cime/CIME/non_py/src/CMake - -//Path to a program. -CMAKE_ADDR2LINE:FILEPATH=CMAKE_ADDR2LINE-NOTFOUND - -//Path to a program. -CMAKE_AR:FILEPATH=/usr/bin/ar - -//Choose the type of build, options are: None Debug Release RelWithDebInfo -// MinSizeRel ... -CMAKE_BUILD_TYPE:STRING=CESM_DEBUG - -//Enable/Disable color output during build. -CMAKE_COLOR_MAKEFILE:BOOL=ON - -//C compiler -CMAKE_C_COMPILER:FILEPATH=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc - -//Flags used by the C compiler during all build types. -CMAKE_C_FLAGS:STRING= - -//Flags used by the C compiler during CESM_DEBUG builds. -CMAKE_C_FLAGS_CESM_DEBUG:STRING= - -//Flags used by the C compiler during DEBUG builds. -CMAKE_C_FLAGS_DEBUG:STRING=-g - -//Flags used by the C compiler during MINSIZEREL builds. -CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG - -//Flags used by the C compiler during RELEASE builds. -CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG - -//Flags used by the C compiler during RELWITHDEBINFO builds. -CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG - -//Path to a program. -CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND - -//Flags used by the linker during all build types. -CMAKE_EXE_LINKER_FLAGS:STRING=-L/usr/local/opt/lapack/lib - -//Flags used by the linker during CESM_DEBUG builds. -CMAKE_EXE_LINKER_FLAGS_CESM_DEBUG:STRING= - -//Flags used by the linker during DEBUG builds. -CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during MINSIZEREL builds. -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during RELEASE builds. -CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during RELWITHDEBINFO builds. -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Enable/Disable output of compile commands during generation. -CMAKE_EXPORT_COMPILE_COMMANDS:BOOL= - -//Value Computed by CMake. -CMAKE_FIND_PACKAGE_REDIRECTS_DIR:STATIC=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles/pkgRedirects - -//Fortran compiler -CMAKE_Fortran_COMPILER:FILEPATH=/usr/local/bin/gfortran - -//A wrapper around 'ar' adding the appropriate '--plugin' option -// for the GCC compiler -CMAKE_Fortran_COMPILER_AR:FILEPATH=CMAKE_Fortran_COMPILER_AR-NOTFOUND - -//A wrapper around 'ranlib' adding the appropriate '--plugin' option -// for the GCC compiler -CMAKE_Fortran_COMPILER_RANLIB:FILEPATH=CMAKE_Fortran_COMPILER_RANLIB-NOTFOUND - -//Flags used by the Fortran compiler during all build types. -CMAKE_Fortran_FLAGS:STRING= - -//Flags used by the Fortran compiler during CESM_DEBUG builds. -CMAKE_Fortran_FLAGS_CESM_DEBUG:STRING= - -//Flags used by the Fortran compiler during DEBUG builds. -CMAKE_Fortran_FLAGS_DEBUG:STRING=-g - -//Flags used by the Fortran compiler during MINSIZEREL builds. -CMAKE_Fortran_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG -Os - -//Flags used by the Fortran compiler during RELEASE builds. -CMAKE_Fortran_FLAGS_RELEASE:STRING=-O3 -DNDEBUG -O3 - -//Flags used by the Fortran compiler during RELWITHDEBINFO builds. -CMAKE_Fortran_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG - -//Path to a program. -CMAKE_INSTALL_NAME_TOOL:FILEPATH=/usr/bin/install_name_tool - -//Install path prefix, prepended onto install directories. -CMAKE_INSTALL_PREFIX:PATH=/usr/local - -//Path to a program. -CMAKE_LINKER:FILEPATH=/usr/bin/ld - -//Path to a program. -CMAKE_MAKE_PROGRAM:FILEPATH=/usr/local/bin/gmake - -//Flags used by the linker during the creation of modules during -// all build types. -CMAKE_MODULE_LINKER_FLAGS:STRING=-L/usr/local/opt/lapack/lib - -//Flags used by the linker during the creation of modules during -// CESM_DEBUG builds. -CMAKE_MODULE_LINKER_FLAGS_CESM_DEBUG:STRING= - -//Flags used by the linker during the creation of modules during -// DEBUG builds. -CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during the creation of modules during -// MINSIZEREL builds. -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during the creation of modules during -// RELEASE builds. -CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during the creation of modules during -// RELWITHDEBINFO builds. -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Path to a program. -CMAKE_NM:FILEPATH=/usr/bin/nm - -//Path to a program. -CMAKE_OBJCOPY:FILEPATH=CMAKE_OBJCOPY-NOTFOUND - -//Path to a program. -CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump - -//Build architectures for OSX -CMAKE_OSX_ARCHITECTURES:STRING= - -//Minimum OS X version to target for deployment (at runtime); newer -// APIs weak linked. Set to empty string for default value. -CMAKE_OSX_DEPLOYMENT_TARGET:STRING= - -//The product will be built against the headers and libraries located -// inside the indicated SDK. -CMAKE_OSX_SYSROOT:PATH=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk - -//No help, variable specified on the command line. -CMAKE_PROGRAM_PATH:UNINITIALIZED=/Users/afoster/Documents/ncar/CTSM/cime/scripts/fortran_unit_testing/../../CIME/non_py/externals/genf90 - -//Value Computed by CMake -CMAKE_PROJECT_DESCRIPTION:STATIC= - -//Value Computed by CMake -CMAKE_PROJECT_HOMEPAGE_URL:STATIC= - -//Value Computed by CMake -CMAKE_PROJECT_NAME:STATIC=radiation_tests - -//Path to a program. -CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib - -//Path to a program. -CMAKE_READELF:FILEPATH=CMAKE_READELF-NOTFOUND - -//Flags used by the linker during the creation of shared libraries -// during all build types. -CMAKE_SHARED_LINKER_FLAGS:STRING=-L/usr/local/opt/lapack/lib - -//Flags used by the linker during the creation of shared libraries -// during CESM_DEBUG builds. -CMAKE_SHARED_LINKER_FLAGS_CESM_DEBUG:STRING= - -//Flags used by the linker during the creation of shared libraries -// during DEBUG builds. -CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during the creation of shared libraries -// during MINSIZEREL builds. -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during the creation of shared libraries -// during RELEASE builds. -CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during the creation of shared libraries -// during RELWITHDEBINFO builds. -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//If set, runtime paths are not added when installing shared libraries, -// but are added when building. -CMAKE_SKIP_INSTALL_RPATH:BOOL=NO - -//If set, runtime paths are not added when using shared libraries. -CMAKE_SKIP_RPATH:BOOL=NO - -//Flags used by the linker during the creation of static libraries -// during all build types. -CMAKE_STATIC_LINKER_FLAGS:STRING= - -//Flags used by the linker during the creation of static libraries -// during CESM_DEBUG builds. -CMAKE_STATIC_LINKER_FLAGS_CESM_DEBUG:STRING= - -//Flags used by the linker during the creation of static libraries -// during DEBUG builds. -CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during the creation of static libraries -// during MINSIZEREL builds. -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during the creation of static libraries -// during RELEASE builds. -CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during the creation of static libraries -// during RELWITHDEBINFO builds. -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Path to a program. -CMAKE_STRIP:FILEPATH=/usr/bin/strip - -//If this value is on, makefiles will be generated without the -// .SILENT directive, and all commands will be echoed to the console -// during the make. This is useful for debugging only. With Visual -// Studio IDE projects all commands are done without /nologo. -CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE - -//No help, variable specified on the command line. -COMPILER:UNINITIALIZED=gnu - -//No help, variable specified on the command line. -DEBUG:UNINITIALIZED=TRUE - -//Use genf90.pl to regenerate out-of-date Fortran files from .in -// files. -ENABLE_GENF90:BOOL=ON - -//Path to a program. -GENF90:FILEPATH=/Users/afoster/Documents/ncar/CTSM/cime/CIME/non_py/externals/genf90/genf90.pl - -//No help, variable specified on the command line. -MACH:UNINITIALIZED=fleabone - -//No help, variable specified on the command line. -MPILIB:UNINITIALIZED=mpi-serial - -//Path to a file. -NETCDFC_FOUND:PATH=/usr/local/Cellar/netcdf/4.9.2/lib - -//Path to a file. -NETCDFF_FOUND:PATH=/usr/local/Cellar/netcdf-fortran/4.6.0/lib - -//Netcdf Library Names(s) -NETCDF_C_LIBS:STRING=netcdff;netcdf - -//No help, variable specified on the command line. -OS:UNINITIALIZED=Ventura - -//Path to a file. -PFUNIT_INCLUDE_DIR:PATH=/Users/afoster/pFUnit/include - -//Path to a library. -PFUNIT_LIBRARY:FILEPATH=/Users/afoster/pFUnit/lib/libpfunit.a - -//Path to a file. -PFUNIT_MODULE_DIR:PATH=/Users/afoster/pFUnit/mod - -//No help, variable specified on the command line. -PFUNIT_MPIRUN:UNINITIALIZED= - -//Path to a program. -PFUNIT_PARSER:FILEPATH=/Users/afoster/pFUnit/bin/pFUnitParser.py - -//No help, variable specified on the command line. -PFUNIT_PATH:UNINITIALIZED=/Users/afoster/pFUnit/ - -//No help, variable specified on the command line. -SRC_ROOT:UNINITIALIZED=/Users/afoster/Documents/ncar/CTSM - -//Allow color from the build output. -USE_COLOR:BOOL=ON - -//No help, variable specified on the command line. -USE_MPI_SERIAL:UNINITIALIZED=ON - -//No help, variable specified on the command line. -compile_threaded:UNINITIALIZED=FALSE - -//Value Computed by CMake -radiation_tests_BINARY_DIR:STATIC=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ - -//Value Computed by CMake -radiation_tests_IS_TOP_LEVEL:STATIC=ON - -//Value Computed by CMake -radiation_tests_SOURCE_DIR:STATIC=/Users/afoster/Documents/ncar/CTSM/src/fates - - -######################## -# INTERNAL cache entries -######################## - -//ADVANCED property for variable: CMAKE_ADDR2LINE -CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_AR -CMAKE_AR-ADVANCED:INTERNAL=1 -//This is the directory where this CMakeCache.txt was created -CMAKE_CACHEFILE_DIR:INTERNAL=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ -//Major version of cmake used to create the current loaded cache -CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 -//Minor version of cmake used to create the current loaded cache -CMAKE_CACHE_MINOR_VERSION:INTERNAL=25 -//Patch version of cmake used to create the current loaded cache -CMAKE_CACHE_PATCH_VERSION:INTERNAL=2 -//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE -CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1 -//Path to CMake executable. -CMAKE_COMMAND:INTERNAL=/usr/local/Cellar/cmake/3.25.2/bin/cmake -//Path to cpack program executable. -CMAKE_CPACK_COMMAND:INTERNAL=/usr/local/Cellar/cmake/3.25.2/bin/cpack -//Path to ctest program executable. -CMAKE_CTEST_COMMAND:INTERNAL=/usr/local/Cellar/cmake/3.25.2/bin/ctest -//ADVANCED property for variable: CMAKE_C_COMPILER -CMAKE_C_COMPILER-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS -CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_CESM_DEBUG -CMAKE_C_FLAGS_CESM_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG -CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL -CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE -CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO -CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_DLLTOOL -CMAKE_DLLTOOL-ADVANCED:INTERNAL=1 -//Path to cache edit program executable. -CMAKE_EDIT_COMMAND:INTERNAL=/usr/local/Cellar/cmake/3.25.2/bin/ccmake -//Executable file format -CMAKE_EXECUTABLE_FORMAT:INTERNAL=MACHO -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS -CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_CESM_DEBUG -CMAKE_EXE_LINKER_FLAGS_CESM_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG -CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE -CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS -CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1 -//Name of external makefile project generator. -CMAKE_EXTRA_GENERATOR:INTERNAL= -//ADVANCED property for variable: CMAKE_Fortran_COMPILER -CMAKE_Fortran_COMPILER-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_Fortran_COMPILER_AR -CMAKE_Fortran_COMPILER_AR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_Fortran_COMPILER_RANLIB -CMAKE_Fortran_COMPILER_RANLIB-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_Fortran_FLAGS -CMAKE_Fortran_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_Fortran_FLAGS_CESM_DEBUG -CMAKE_Fortran_FLAGS_CESM_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_Fortran_FLAGS_DEBUG -CMAKE_Fortran_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_Fortran_FLAGS_MINSIZEREL -CMAKE_Fortran_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_Fortran_FLAGS_RELEASE -CMAKE_Fortran_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_Fortran_FLAGS_RELWITHDEBINFO -CMAKE_Fortran_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//Name of generator. -CMAKE_GENERATOR:INTERNAL=Unix Makefiles -//Generator instance identifier. -CMAKE_GENERATOR_INSTANCE:INTERNAL= -//Name of generator platform. -CMAKE_GENERATOR_PLATFORM:INTERNAL= -//Name of generator toolset. -CMAKE_GENERATOR_TOOLSET:INTERNAL= -//Source directory with the top level CMakeLists.txt file for this -// project -CMAKE_HOME_DIRECTORY:INTERNAL=/Users/afoster/Documents/ncar/CTSM/src/fates -//ADVANCED property for variable: CMAKE_INSTALL_NAME_TOOL -CMAKE_INSTALL_NAME_TOOL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_LINKER -CMAKE_LINKER-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MAKE_PROGRAM -CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS -CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_CESM_DEBUG -CMAKE_MODULE_LINKER_FLAGS_CESM_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG -CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE -CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_NM -CMAKE_NM-ADVANCED:INTERNAL=1 -//number of local generators -CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=5 -//ADVANCED property for variable: CMAKE_OBJCOPY -CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_OBJDUMP -CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 -//Platform information initialized -CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_RANLIB -CMAKE_RANLIB-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_READELF -CMAKE_READELF-ADVANCED:INTERNAL=1 -//Path to CMake installation. -CMAKE_ROOT:INTERNAL=/usr/local/Cellar/cmake/3.25.2/share/cmake -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS -CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_CESM_DEBUG -CMAKE_SHARED_LINKER_FLAGS_CESM_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG -CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE -CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH -CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_RPATH -CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS -CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_CESM_DEBUG -CMAKE_STATIC_LINKER_FLAGS_CESM_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG -CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE -CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STRIP -CMAKE_STRIP-ADVANCED:INTERNAL=1 -//uname command -CMAKE_UNAME:INTERNAL=/usr/bin/uname -//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE -CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 -//Details about finding pFUnit -FIND_PACKAGE_MESSAGE_DETAILS_pFUnit:INTERNAL=[/Users/afoster/pFUnit/lib/libpfunit.a][/Users/afoster/pFUnit/include][/Users/afoster/pFUnit/mod][/Users/afoster/pFUnit/bin/pFUnitParser.py][v()] -//ADVANCED property for variable: PFUNIT_INCLUDE_DIR -PFUNIT_INCLUDE_DIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: PFUNIT_LIBRARY -PFUNIT_LIBRARY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: PFUNIT_MODULE_DIR -PFUNIT_MODULE_DIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: PFUNIT_PARSER -PFUNIT_PARSER-ADVANCED:INTERNAL=1 - diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CMakeCCompiler.cmake b/build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CMakeCCompiler.cmake deleted file mode 100644 index b02d92f9f2..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CMakeCCompiler.cmake +++ /dev/null @@ -1,72 +0,0 @@ -set(CMAKE_C_COMPILER "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc") -set(CMAKE_C_COMPILER_ARG1 "") -set(CMAKE_C_COMPILER_ID "AppleClang") -set(CMAKE_C_COMPILER_VERSION "14.0.0.14000029") -set(CMAKE_C_COMPILER_VERSION_INTERNAL "") -set(CMAKE_C_COMPILER_WRAPPER "") -set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "17") -set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "ON") -set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert;c_std_17;c_std_23") -set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") -set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") -set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") -set(CMAKE_C17_COMPILE_FEATURES "c_std_17") -set(CMAKE_C23_COMPILE_FEATURES "c_std_23") - -set(CMAKE_C_PLATFORM_ID "Darwin") -set(CMAKE_C_SIMULATE_ID "") -set(CMAKE_C_COMPILER_FRONTEND_VARIANT "") -set(CMAKE_C_SIMULATE_VERSION "") - - - - -set(CMAKE_AR "/usr/bin/ar") -set(CMAKE_C_COMPILER_AR "") -set(CMAKE_RANLIB "/usr/bin/ranlib") -set(CMAKE_C_COMPILER_RANLIB "") -set(CMAKE_LINKER "/usr/bin/ld") -set(CMAKE_MT "") -set(CMAKE_COMPILER_IS_GNUCC ) -set(CMAKE_C_COMPILER_LOADED 1) -set(CMAKE_C_COMPILER_WORKS TRUE) -set(CMAKE_C_ABI_COMPILED TRUE) - -set(CMAKE_C_COMPILER_ENV_VAR "CC") - -set(CMAKE_C_COMPILER_ID_RUN 1) -set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) -set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) -set(CMAKE_C_LINKER_PREFERENCE 10) - -# Save compiler ABI information. -set(CMAKE_C_SIZEOF_DATA_PTR "8") -set(CMAKE_C_COMPILER_ABI "") -set(CMAKE_C_BYTE_ORDER "LITTLE_ENDIAN") -set(CMAKE_C_LIBRARY_ARCHITECTURE "") - -if(CMAKE_C_SIZEOF_DATA_PTR) - set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") -endif() - -if(CMAKE_C_COMPILER_ABI) - set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") -endif() - -if(CMAKE_C_LIBRARY_ARCHITECTURE) - set(CMAKE_LIBRARY_ARCHITECTURE "") -endif() - -set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") -if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) - set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") -endif() - - - - - -set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/14.0.0/include;/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/usr/include;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include") -set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "") -set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/local/opt/lapack/lib;/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/usr/lib") -set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/System/Library/Frameworks") diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CMakeDetermineCompilerABI_C.bin b/build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CMakeDetermineCompilerABI_C.bin deleted file mode 100755 index 4656549879429703477a75be0e856ae37b97684a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16688 zcmeI3OKTHR6vuB&TkC_iE3qgTT!?nj)(03$(X@2h8EmJaMi4`}CY`ArNRyIGun{WV zh=d~eQHmRPZd`P!A40)Jgf5GS_&@U?8Ec^*;D6w79{1jJ&;8A8&zE06|D07Sl~zif zfet~l2;Qg+Jf%jVCRFSE%!2XESXq{AQc}tAzme3*Vx!gt<7pweB{-i;=2R5-BP}ZZ ziD>P++kWVWakAdw13U%`tI-yT`?}jD*zFCqUaM6b-Gcx2mwy=6dmbH+7<{dp z)t6q?(Oz}E7R1T^_M>{jR77Ioev)+gFIx5^W6p}%<-)#VPO+VgK8Bdc4N6~EYIpLa zOM3IU@Ow*7m!WyY1F-wByRa9ad8ml&5tVNv->COKgr^eu-!jmP(1~WFK2h^Hacyi6D1cU`LWMTBv%s2J)^Vw85zr-U!H1suiV3>$E_C^twLeZ(1tx{&Df|UGtO6o zN=YlT%QD-14_4I1T)Bw&G7~M+(IdfW$#xx;((0TXR%yMtq1|nFt%=Jw+!AhA{W8U_ zd!D22Z*aMlv6*V@@0E z;ag;V911ILAQ?>9AMZ1mwomk_gFa=DTsQn?S(h=Bj|YVtyL^#|1S~H%~${c diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CMakeDetermineCompilerABI_Fortran.bin b/build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CMakeDetermineCompilerABI_Fortran.bin deleted file mode 100755 index 332e100ff099bddf2017b5dc5af95bddaa46c149..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33512 zcmeI5U2GIp6vyw-Z7JH8Me*B&eXs^K?6&121q8OAOrtFgv`Lkio9XVf-MC-Q%!bl{ zEY=z~Si_5n&-!Tmi1C3C1rnl_7d1Q>9*vQt321mQhE!xd=gtf}JCzut4?g@4oVoYh zd(WA3fA?^(upP^7DS9{LOepMlS(<-vwz^lfrAIQwO+J( z^DixqbA<*b$#R|#de)UL^)_n zX*;D!`%Y6h-sgMWcu#mEeA{=J%}U#C9YYAXJyqoRL$Oku%+naJ-@y?@iB-?O=YPaB6?NON~+@p%{u*#U@3&fB+~P?&l$YP` zmBGBYNyjHzA6$FCi`rtO8mVY#C2di4 z&PgPDt9L&t)k(~a5mFZ18q%8xxmIIFnH@T6J7zB4 z8}xge<{hKV*gu&q7-`dzJTo$ta6kWj=6;udA!TF}{-o7%Os7(b+3p>3$F?m-v6wZt zqz&sxCg0VW=r1=%iS$mGXt~KfNJSuhI_BndfEI!nT=m_5qwXA8vf=z$7+$z(rHdgp;f)QqTW-i_40eh$vl1O zqM|*2Jz6<_ORtn}=%>bSoEo6&_cSD?JQ_dbqVm;wI-)L?@8ib{H19K15tlAj+xOB` zs_jYj>{ZWx^&C`Bot}X+k$q-1Ygma?&Uo2OY>jtqk9Q^P8N)KYrr|=mlr`-{-!Kgr zbPtX86>`N)*0g$hhvI`f>7?Y)$l!rpc4p2jOv!Z7u?}~?M18S-(=k&{rjYNa!;aPU zoS%EPl~Pc$$tyQ{r8aj^XtPl*+OoF!G!3HjynF^zyh=;RlJ^}WTxpBGu_nStV_Tad z8EPOWGFaGejPx_Y!jh!Al2v}Ysk!Fojq-|U*?nEKOgo<>T2|+9sf>6wpARM}t0x{H z00JNY0w4eaAOHd&00JNY0w4eaAOHd&00JNY0w4eaAOHd&00JNY0w4eaAOHd&00JNY z0w4eaAOHd&00JNY0w4eaAOHd&00JNY0w4eaAOHd&00JNY0w4ea|2cseMdWWk&ye!< z5&qQ!R8`*v=aPlLvF(ehM`?7@Z}ILspbG>v`gpfCL0TsLl=Md$LmzneKEy3;(~*WX zZHLe7QXGB+d5Su<5~OgUrnm$pS?&dB6NdxN;e_gk>MJ@<>24 & 0x00FF) -# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) -# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) - -#elif defined(__BORLANDC__) -# define COMPILER_ID "Borland" - /* __BORLANDC__ = 0xVRR */ -# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) -# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) - -#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 -# define COMPILER_ID "Watcom" - /* __WATCOMC__ = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) -# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) -# if (__WATCOMC__ % 10) > 0 -# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) -# endif - -#elif defined(__WATCOMC__) -# define COMPILER_ID "OpenWatcom" - /* __WATCOMC__ = VVRP + 1100 */ -# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) -# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) -# if (__WATCOMC__ % 10) > 0 -# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) -# endif - -#elif defined(__SUNPRO_C) -# define COMPILER_ID "SunPro" -# if __SUNPRO_C >= 0x5100 - /* __SUNPRO_C = 0xVRRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) -# else - /* __SUNPRO_CC = 0xVRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) -# endif - -#elif defined(__HP_cc) -# define COMPILER_ID "HP" - /* __HP_cc = VVRRPP */ -# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) -# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) -# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) - -#elif defined(__DECC) -# define COMPILER_ID "Compaq" - /* __DECC_VER = VVRRTPPPP */ -# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) -# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) -# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) - -#elif defined(__IBMC__) && defined(__COMPILER_VER__) -# define COMPILER_ID "zOS" - /* __IBMC__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) - -#elif defined(__open_xl__) && defined(__clang__) -# define COMPILER_ID "IBMClang" -# define COMPILER_VERSION_MAJOR DEC(__open_xl_version__) -# define COMPILER_VERSION_MINOR DEC(__open_xl_release__) -# define COMPILER_VERSION_PATCH DEC(__open_xl_modification__) -# define COMPILER_VERSION_TWEAK DEC(__open_xl_ptf_fix_level__) - - -#elif defined(__ibmxl__) && defined(__clang__) -# define COMPILER_ID "XLClang" -# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) -# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) -# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) -# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) - - -#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 -# define COMPILER_ID "XL" - /* __IBMC__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) - -#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 -# define COMPILER_ID "VisualAge" - /* __IBMC__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) - -#elif defined(__NVCOMPILER) -# define COMPILER_ID "NVHPC" -# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) -# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) -# if defined(__NVCOMPILER_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) -# endif - -#elif defined(__PGI) -# define COMPILER_ID "PGI" -# define COMPILER_VERSION_MAJOR DEC(__PGIC__) -# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) -# if defined(__PGIC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) -# endif - -#elif defined(_CRAYC) -# define COMPILER_ID "Cray" -# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) -# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) - -#elif defined(__TI_COMPILER_VERSION__) -# define COMPILER_ID "TI" - /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ -# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) -# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) -# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) - -#elif defined(__CLANG_FUJITSU) -# define COMPILER_ID "FujitsuClang" -# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) -# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) -# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) -# define COMPILER_VERSION_INTERNAL_STR __clang_version__ - - -#elif defined(__FUJITSU) -# define COMPILER_ID "Fujitsu" -# if defined(__FCC_version__) -# define COMPILER_VERSION __FCC_version__ -# elif defined(__FCC_major__) -# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) -# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) -# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) -# endif -# if defined(__fcc_version) -# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) -# elif defined(__FCC_VERSION) -# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) -# endif - - -#elif defined(__ghs__) -# define COMPILER_ID "GHS" -/* __GHS_VERSION_NUMBER = VVVVRP */ -# ifdef __GHS_VERSION_NUMBER -# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) -# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) -# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) -# endif - -#elif defined(__TASKING__) -# define COMPILER_ID "Tasking" - # define COMPILER_VERSION_MAJOR DEC(__VERSION__/1000) - # define COMPILER_VERSION_MINOR DEC(__VERSION__ % 100) -# define COMPILER_VERSION_INTERNAL DEC(__VERSION__) - -#elif defined(__TINYC__) -# define COMPILER_ID "TinyCC" - -#elif defined(__BCC__) -# define COMPILER_ID "Bruce" - -#elif defined(__SCO_VERSION__) -# define COMPILER_ID "SCO" - -#elif defined(__ARMCC_VERSION) && !defined(__clang__) -# define COMPILER_ID "ARMCC" -#if __ARMCC_VERSION >= 1000000 - /* __ARMCC_VERSION = VRRPPPP */ - # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) - # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) - # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) -#else - /* __ARMCC_VERSION = VRPPPP */ - # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) - # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) - # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) -#endif - - -#elif defined(__clang__) && defined(__apple_build_version__) -# define COMPILER_ID "AppleClang" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# define COMPILER_VERSION_MAJOR DEC(__clang_major__) -# define COMPILER_VERSION_MINOR DEC(__clang_minor__) -# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif -# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) - -#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) -# define COMPILER_ID "ARMClang" - # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) - # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) - # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) -# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) - -#elif defined(__clang__) -# define COMPILER_ID "Clang" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# define COMPILER_VERSION_MAJOR DEC(__clang_major__) -# define COMPILER_VERSION_MINOR DEC(__clang_minor__) -# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif - -#elif defined(__LCC__) && (defined(__GNUC__) || defined(__GNUG__) || defined(__MCST__)) -# define COMPILER_ID "LCC" -# define COMPILER_VERSION_MAJOR DEC(1) -# if defined(__LCC__) -# define COMPILER_VERSION_MINOR DEC(__LCC__- 100) -# endif -# if defined(__LCC_MINOR__) -# define COMPILER_VERSION_PATCH DEC(__LCC_MINOR__) -# endif -# if defined(__GNUC__) && defined(__GNUC_MINOR__) -# define SIMULATE_ID "GNU" -# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) -# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) -# if defined(__GNUC_PATCHLEVEL__) -# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -# endif -# endif - -#elif defined(__GNUC__) -# define COMPILER_ID "GNU" -# define COMPILER_VERSION_MAJOR DEC(__GNUC__) -# if defined(__GNUC_MINOR__) -# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) -# endif -# if defined(__GNUC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -# endif - -#elif defined(_MSC_VER) -# define COMPILER_ID "MSVC" - /* _MSC_VER = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) -# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) -# if defined(_MSC_FULL_VER) -# if _MSC_VER >= 1400 - /* _MSC_FULL_VER = VVRRPPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) -# else - /* _MSC_FULL_VER = VVRRPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) -# endif -# endif -# if defined(_MSC_BUILD) -# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) -# endif - -#elif defined(_ADI_COMPILER) -# define COMPILER_ID "ADSP" -#if defined(__VERSIONNUM__) - /* __VERSIONNUM__ = 0xVVRRPPTT */ -# define COMPILER_VERSION_MAJOR DEC(__VERSIONNUM__ >> 24 & 0xFF) -# define COMPILER_VERSION_MINOR DEC(__VERSIONNUM__ >> 16 & 0xFF) -# define COMPILER_VERSION_PATCH DEC(__VERSIONNUM__ >> 8 & 0xFF) -# define COMPILER_VERSION_TWEAK DEC(__VERSIONNUM__ & 0xFF) -#endif - -#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) -# define COMPILER_ID "IAR" -# if defined(__VER__) && defined(__ICCARM__) -# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) -# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) -# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) -# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) -# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) -# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) -# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) -# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) -# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) -# endif - -#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC) -# define COMPILER_ID "SDCC" -# if defined(__SDCC_VERSION_MAJOR) -# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR) -# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR) -# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH) -# else - /* SDCC = VRP */ -# define COMPILER_VERSION_MAJOR DEC(SDCC/100) -# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) -# define COMPILER_VERSION_PATCH DEC(SDCC % 10) -# endif - - -/* These compilers are either not known or too old to define an - identification macro. Try to identify the platform and guess that - it is the native compiler. */ -#elif defined(__hpux) || defined(__hpua) -# define COMPILER_ID "HP" - -#else /* unknown compiler */ -# define COMPILER_ID "" -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; -#ifdef SIMULATE_ID -char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; -#endif - -#ifdef __QNXNTO__ -char const* qnxnto = "INFO" ":" "qnxnto[]"; -#endif - -#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) -char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; -#endif - -#define STRINGIFY_HELPER(X) #X -#define STRINGIFY(X) STRINGIFY_HELPER(X) - -/* Identify known platforms by name. */ -#if defined(__linux) || defined(__linux__) || defined(linux) -# define PLATFORM_ID "Linux" - -#elif defined(__MSYS__) -# define PLATFORM_ID "MSYS" - -#elif defined(__CYGWIN__) -# define PLATFORM_ID "Cygwin" - -#elif defined(__MINGW32__) -# define PLATFORM_ID "MinGW" - -#elif defined(__APPLE__) -# define PLATFORM_ID "Darwin" - -#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) -# define PLATFORM_ID "Windows" - -#elif defined(__FreeBSD__) || defined(__FreeBSD) -# define PLATFORM_ID "FreeBSD" - -#elif defined(__NetBSD__) || defined(__NetBSD) -# define PLATFORM_ID "NetBSD" - -#elif defined(__OpenBSD__) || defined(__OPENBSD) -# define PLATFORM_ID "OpenBSD" - -#elif defined(__sun) || defined(sun) -# define PLATFORM_ID "SunOS" - -#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) -# define PLATFORM_ID "AIX" - -#elif defined(__hpux) || defined(__hpux__) -# define PLATFORM_ID "HP-UX" - -#elif defined(__HAIKU__) -# define PLATFORM_ID "Haiku" - -#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) -# define PLATFORM_ID "BeOS" - -#elif defined(__QNX__) || defined(__QNXNTO__) -# define PLATFORM_ID "QNX" - -#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) -# define PLATFORM_ID "Tru64" - -#elif defined(__riscos) || defined(__riscos__) -# define PLATFORM_ID "RISCos" - -#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) -# define PLATFORM_ID "SINIX" - -#elif defined(__UNIX_SV__) -# define PLATFORM_ID "UNIX_SV" - -#elif defined(__bsdos__) -# define PLATFORM_ID "BSDOS" - -#elif defined(_MPRAS) || defined(MPRAS) -# define PLATFORM_ID "MP-RAS" - -#elif defined(__osf) || defined(__osf__) -# define PLATFORM_ID "OSF1" - -#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) -# define PLATFORM_ID "SCO_SV" - -#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) -# define PLATFORM_ID "ULTRIX" - -#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) -# define PLATFORM_ID "Xenix" - -#elif defined(__WATCOMC__) -# if defined(__LINUX__) -# define PLATFORM_ID "Linux" - -# elif defined(__DOS__) -# define PLATFORM_ID "DOS" - -# elif defined(__OS2__) -# define PLATFORM_ID "OS2" - -# elif defined(__WINDOWS__) -# define PLATFORM_ID "Windows3x" - -# elif defined(__VXWORKS__) -# define PLATFORM_ID "VxWorks" - -# else /* unknown platform */ -# define PLATFORM_ID -# endif - -#elif defined(__INTEGRITY) -# if defined(INT_178B) -# define PLATFORM_ID "Integrity178" - -# else /* regular Integrity */ -# define PLATFORM_ID "Integrity" -# endif - -# elif defined(_ADI_COMPILER) -# define PLATFORM_ID "ADSP" - -#else /* unknown platform */ -# define PLATFORM_ID - -#endif - -/* For windows compilers MSVC and Intel we can determine - the architecture of the compiler being used. This is because - the compilers do not have flags that can change the architecture, - but rather depend on which compiler is being used -*/ -#if defined(_WIN32) && defined(_MSC_VER) -# if defined(_M_IA64) -# define ARCHITECTURE_ID "IA64" - -# elif defined(_M_ARM64EC) -# define ARCHITECTURE_ID "ARM64EC" - -# elif defined(_M_X64) || defined(_M_AMD64) -# define ARCHITECTURE_ID "x64" - -# elif defined(_M_IX86) -# define ARCHITECTURE_ID "X86" - -# elif defined(_M_ARM64) -# define ARCHITECTURE_ID "ARM64" - -# elif defined(_M_ARM) -# if _M_ARM == 4 -# define ARCHITECTURE_ID "ARMV4I" -# elif _M_ARM == 5 -# define ARCHITECTURE_ID "ARMV5I" -# else -# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) -# endif - -# elif defined(_M_MIPS) -# define ARCHITECTURE_ID "MIPS" - -# elif defined(_M_SH) -# define ARCHITECTURE_ID "SHx" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__WATCOMC__) -# if defined(_M_I86) -# define ARCHITECTURE_ID "I86" - -# elif defined(_M_IX86) -# define ARCHITECTURE_ID "X86" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) -# if defined(__ICCARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__ICCRX__) -# define ARCHITECTURE_ID "RX" - -# elif defined(__ICCRH850__) -# define ARCHITECTURE_ID "RH850" - -# elif defined(__ICCRL78__) -# define ARCHITECTURE_ID "RL78" - -# elif defined(__ICCRISCV__) -# define ARCHITECTURE_ID "RISCV" - -# elif defined(__ICCAVR__) -# define ARCHITECTURE_ID "AVR" - -# elif defined(__ICC430__) -# define ARCHITECTURE_ID "MSP430" - -# elif defined(__ICCV850__) -# define ARCHITECTURE_ID "V850" - -# elif defined(__ICC8051__) -# define ARCHITECTURE_ID "8051" - -# elif defined(__ICCSTM8__) -# define ARCHITECTURE_ID "STM8" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__ghs__) -# if defined(__PPC64__) -# define ARCHITECTURE_ID "PPC64" - -# elif defined(__ppc__) -# define ARCHITECTURE_ID "PPC" - -# elif defined(__ARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__x86_64__) -# define ARCHITECTURE_ID "x64" - -# elif defined(__i386__) -# define ARCHITECTURE_ID "X86" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__TI_COMPILER_VERSION__) -# if defined(__TI_ARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__MSP430__) -# define ARCHITECTURE_ID "MSP430" - -# elif defined(__TMS320C28XX__) -# define ARCHITECTURE_ID "TMS320C28x" - -# elif defined(__TMS320C6X__) || defined(_TMS320C6X) -# define ARCHITECTURE_ID "TMS320C6x" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -# elif defined(__ADSPSHARC__) -# define ARCHITECTURE_ID "SHARC" - -# elif defined(__ADSPBLACKFIN__) -# define ARCHITECTURE_ID "Blackfin" - -#elif defined(__TASKING__) - -# if defined(__CTC__) || defined(__CPTC__) -# define ARCHITECTURE_ID "TriCore" - -# elif defined(__CMCS__) -# define ARCHITECTURE_ID "MCS" - -# elif defined(__CARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__CARC__) -# define ARCHITECTURE_ID "ARC" - -# elif defined(__C51__) -# define ARCHITECTURE_ID "8051" - -# elif defined(__CPCP__) -# define ARCHITECTURE_ID "PCP" - -# else -# define ARCHITECTURE_ID "" -# endif - -#else -# define ARCHITECTURE_ID -#endif - -/* Convert integer to decimal digit literals. */ -#define DEC(n) \ - ('0' + (((n) / 10000000)%10)), \ - ('0' + (((n) / 1000000)%10)), \ - ('0' + (((n) / 100000)%10)), \ - ('0' + (((n) / 10000)%10)), \ - ('0' + (((n) / 1000)%10)), \ - ('0' + (((n) / 100)%10)), \ - ('0' + (((n) / 10)%10)), \ - ('0' + ((n) % 10)) - -/* Convert integer to hex digit literals. */ -#define HEX(n) \ - ('0' + ((n)>>28 & 0xF)), \ - ('0' + ((n)>>24 & 0xF)), \ - ('0' + ((n)>>20 & 0xF)), \ - ('0' + ((n)>>16 & 0xF)), \ - ('0' + ((n)>>12 & 0xF)), \ - ('0' + ((n)>>8 & 0xF)), \ - ('0' + ((n)>>4 & 0xF)), \ - ('0' + ((n) & 0xF)) - -/* Construct a string literal encoding the version number. */ -#ifdef COMPILER_VERSION -char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; - -/* Construct a string literal encoding the version number components. */ -#elif defined(COMPILER_VERSION_MAJOR) -char const info_version[] = { - 'I', 'N', 'F', 'O', ':', - 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', - COMPILER_VERSION_MAJOR, -# ifdef COMPILER_VERSION_MINOR - '.', COMPILER_VERSION_MINOR, -# ifdef COMPILER_VERSION_PATCH - '.', COMPILER_VERSION_PATCH, -# ifdef COMPILER_VERSION_TWEAK - '.', COMPILER_VERSION_TWEAK, -# endif -# endif -# endif - ']','\0'}; -#endif - -/* Construct a string literal encoding the internal version number. */ -#ifdef COMPILER_VERSION_INTERNAL -char const info_version_internal[] = { - 'I', 'N', 'F', 'O', ':', - 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', - 'i','n','t','e','r','n','a','l','[', - COMPILER_VERSION_INTERNAL,']','\0'}; -#elif defined(COMPILER_VERSION_INTERNAL_STR) -char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; -#endif - -/* Construct a string literal encoding the version number components. */ -#ifdef SIMULATE_VERSION_MAJOR -char const info_simulate_version[] = { - 'I', 'N', 'F', 'O', ':', - 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', - SIMULATE_VERSION_MAJOR, -# ifdef SIMULATE_VERSION_MINOR - '.', SIMULATE_VERSION_MINOR, -# ifdef SIMULATE_VERSION_PATCH - '.', SIMULATE_VERSION_PATCH, -# ifdef SIMULATE_VERSION_TWEAK - '.', SIMULATE_VERSION_TWEAK, -# endif -# endif -# endif - ']','\0'}; -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; -char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; - - - -#if !defined(__STDC__) && !defined(__clang__) -# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__) -# define C_VERSION "90" -# else -# define C_VERSION -# endif -#elif __STDC_VERSION__ > 201710L -# define C_VERSION "23" -#elif __STDC_VERSION__ >= 201710L -# define C_VERSION "17" -#elif __STDC_VERSION__ >= 201000L -# define C_VERSION "11" -#elif __STDC_VERSION__ >= 199901L -# define C_VERSION "99" -#else -# define C_VERSION "90" -#endif -const char* info_language_standard_default = - "INFO" ":" "standard_default[" C_VERSION "]"; - -const char* info_language_extensions_default = "INFO" ":" "extensions_default[" -#if (defined(__clang__) || defined(__GNUC__) || defined(__xlC__) || \ - defined(__TI_COMPILER_VERSION__)) && \ - !defined(__STRICT_ANSI__) - "ON" -#else - "OFF" -#endif -"]"; - -/*--------------------------------------------------------------------------*/ - -#ifdef ID_VOID_MAIN -void main() {} -#else -# if defined(__CLASSIC_C__) -int main(argc, argv) int argc; char *argv[]; -# else -int main(int argc, char* argv[]) -# endif -{ - int require = 0; - require += info_compiler[argc]; - require += info_platform[argc]; - require += info_arch[argc]; -#ifdef COMPILER_VERSION_MAJOR - require += info_version[argc]; -#endif -#ifdef COMPILER_VERSION_INTERNAL - require += info_version_internal[argc]; -#endif -#ifdef SIMULATE_ID - require += info_simulate[argc]; -#endif -#ifdef SIMULATE_VERSION_MAJOR - require += info_simulate_version[argc]; -#endif -#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) - require += info_cray[argc]; -#endif - require += info_language_standard_default[argc]; - require += info_language_extensions_default[argc]; - (void)argv; - return require; -} -#endif diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CompilerIdFortran/CMakeFortranCompilerId.F b/build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CompilerIdFortran/CMakeFortranCompilerId.F deleted file mode 100644 index 4e88c9ae60..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/3.25.2/CompilerIdFortran/CMakeFortranCompilerId.F +++ /dev/null @@ -1,1114 +0,0 @@ - PROGRAM CMakeFortranCompilerId -#if 0 -! Identify the compiler -#endif -#if defined(_MSC_VER) - PRINT *, 'INFO:simulate[MSVC]' -# if _MSC_VER >= 1900 - PRINT *, 'INFO:simulate_version[019.00]' -# elif _MSC_VER >= 1800 - PRINT *, 'INFO:simulate_version[018.00]' -# elif _MSC_VER >= 1700 - PRINT *, 'INFO:simulate_version[017.00]' -# elif _MSC_VER >= 1600 - PRINT *, 'INFO:simulate_version[016.00]' -# elif _MSC_VER >= 1500 - PRINT *, 'INFO:simulate_version[015.00]' -# elif _MSC_VER >= 1400 - PRINT *, 'INFO:simulate_version[014.00]' -# elif _MSC_VER >= 1310 - PRINT *, 'INFO:simulate_version[013.01]' -# else - PRINT *, 'INFO:simulate_version[013.00]' -# endif -#endif -#if defined(__INTEL_LLVM_COMPILER) - PRINT *, 'INFO:compiler[IntelLLVM]' -! __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and -! later. Look for 6 digit vs. 8 digit version number to decide encoding. -! VVVV is no smaller than the current year when a version is released. -# if __INTEL_LLVM_COMPILER < 1000000 -# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) -# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) -# else -# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) -# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) -# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) -# endif -#elif defined(__INTEL_COMPILER) && __INTEL_COMPILER == 201900 - PRINT *, 'INFO:compiler[IntelLLVM]' -! ifx 2021.1 forgot to define __INTEL_LLVM_COMPILER. -! Instead it defines __INTEL_COMPILER == 201900. -# define COMPILER_VERSION_MAJOR DEC(2021) -# define COMPILER_VERSION_MINOR DEC(1) -# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) -# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) -#elif defined(__INTEL_COMPILER) || defined(__ICC) - PRINT *, 'INFO:compiler[Intel]' -! __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later. -# if __INTEL_COMPILER < 2021 -# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) -# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) -# if defined(__INTEL_COMPILER_UPDATE) -# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) -# else -# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) -# endif -# else -# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) -# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) -! The third version component from --version is an update index, -! but no macro is provided for it. -# define COMPILER_VERSION_PATCH DEC(0) -# endif -# if defined(__INTEL_COMPILER_BUILD_DATE) -# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) -# endif -#elif defined(__SUNPRO_F95) - PRINT *, 'INFO:compiler[SunPro]' -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_F95>>8) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_F95>>4 & 0xF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_F95 & 0xF) -#elif defined(__SUNPRO_F90) - PRINT *, 'INFO:compiler[SunPro]' -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_F90>>8) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_F90>>4 & 0xF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_F90 & 0xF) -#elif defined(_CRAYFTN) - PRINT *, 'INFO:compiler[Cray]' -# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) -# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) -# if defined(_RELEASE_PATCHLEVEL) -# define COMPILER_VERSION_PATCH DEC(_RELEASE_PATCHLEVEL) -# endif -#elif defined(__G95__) - PRINT *, 'INFO:compiler[G95]' -# define COMPILER_VERSION_MAJOR DEC(__G95__) -# define COMPILER_VERSION_MINOR DEC(__G95_MINOR__) -#elif defined(__PATHSCALE__) - PRINT *, 'INFO:compiler[PathScale]' -# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) -# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) -# if defined(__PATHCC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) -# endif -#elif defined(__ABSOFT__) - PRINT *, 'INFO:compiler[Absoft]' -#elif defined(__LCC__) && (defined(__GNUC__) || defined(__GNUG__) || defined(__MCST__)) - PRINT *, 'INFO:compiler[LCC]' -# define COMPILER_VERSION_MAJOR DEC(1) -# define COMPILER_VERSION_MINOR DEC(__LCC__ - 100) -# if defined(__LCC_MINOR__) -# define COMPILER_VERSION_PATCH DEC(__LCC_MINOR__) -# endif -#elif defined(__GNUC__) - PRINT *, 'INFO:compiler[GNU]' -# define COMPILER_VERSION_MAJOR DEC(__GNUC__) -# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) -# if defined(__GNUC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -# endif -#elif defined(__IBMC__) -# if defined(__COMPILER_VER__) - PRINT *, 'INFO:compiler[zOS]' -# elif __IBMC__ >= 800 - PRINT *, 'INFO:compiler[XL]' -# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) -# else - PRINT *, 'INFO:compiler[VisualAge]' -# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) -# endif -#elif defined(__NVCOMPILER) || defined(__NVCOMPILER_LLVM__) - PRINT *, 'INFO:compiler[NVHPC]' -# if defined(__NVCOMPILER_MAJOR__) -# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) -# else -# define COMPILER_VERSION_MAJOR DEC(__PGIC__) -# endif -# if defined(__NVCOMPILER_MINOR__) -# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) -# else -# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) -# endif -# if defined(__NVCOMPILER_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) -# elif defined(__PGIC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) -# endif -#elif defined(__PGI) - PRINT *, 'INFO:compiler[PGI]' -# define COMPILER_VERSION_MAJOR DEC(__PGIC__) -# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) -# if defined(__PGIC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) -# endif -#elif defined(__FLANG) - PRINT *, 'INFO:compiler[Flang]' -# define COMPILER_VERSION_MAJOR DEC(__FLANG_MAJOR__) -# define COMPILER_VERSION_MINOR DEC(__FLANG_MINOR__) -# if defined(__FLANG_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__FLANG_PATCHLEVEL__) -# endif -#elif defined(__flang__) - PRINT *, 'INFO:compiler[LLVMFlang]' -# define COMPILER_VERSION_MAJOR DEC(__flang_major__) -# define COMPILER_VERSION_MINOR DEC(__flang_minor__) -# if defined(__flang_patchlevel__) -# define COMPILER_VERSION_PATCH DEC(__flang_patchlevel__) -# endif -#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) - PRINT *, 'INFO:compiler[VisualAge]' -#elif defined(__hpux) || defined(__hpux__) - PRINT *, 'INFO:compiler[HP]' -#elif defined(NAGFOR) - PRINT *, 'INFO:compiler[NAG]' -#define COMPILER_VERSION_MAJOR DEC(__NAG_COMPILER_RELEASE/10) -#define COMPILER_VERSION_MINOR DEC(__NAG_COMPILER_RELEASE % 10) -#define COMPILER_VERSION_PATCH DEC(__NAG_COMPILER_BUILD) -#elif defined(__FUJITSU) - PRINT *, 'INFO:compiler[Fujitsu]' -# if defined(__FRT_major__) -# define COMPILER_VERSION_MAJOR DEC(__FRT_major__) -# define COMPILER_VERSION_MINOR DEC(__FRT_minor__) -# define COMPILER_VERSION_PATCH DEC(__FRT_patchlevel__) -# elif defined(__FRT_version__) - PRINT *, 'INFO:compiler_version['//__FRT_version__//']' -# endif -#else - PRINT *, 'INFO:compiler[]' -#endif -#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) - PRINT *, 'INFO:compiler_wrapper[CrayPrgEnv]' -#endif - -#if 0 -! Identify the platform -#endif -#if defined(__linux) || defined(__linux__) || defined(linux) - PRINT *, 'INFO:platform[Linux]' -#elif defined(__CYGWIN__) - PRINT *, 'INFO:platform[Cygwin]' -#elif defined(__MINGW32__) - PRINT *, 'INFO:platform[MinGW]' -#elif defined(__APPLE__) - PRINT *, 'INFO:platform[Darwin]' -#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) - PRINT *, 'INFO:platform[Windows]' -#elif defined(__FreeBSD__) || defined(__FreeBSD) - PRINT *, 'INFO:platform[FreeBSD]' -#elif defined(__NetBSD__) || defined(__NetBSD) - PRINT *, 'INFO:platform[NetBSD]' -#elif defined(__OpenBSD__) || defined(__OPENBSD) - PRINT *, 'INFO:platform[OpenBSD]' -#elif defined(__sun) || defined(sun) - PRINT *, 'INFO:platform[SunOS]' -#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) - PRINT *, 'INFO:platform[AIX]' -#elif defined(__hpux) || defined(__hpux__) - PRINT *, 'INFO:platform[HP-UX]' -#elif defined(__HAIKU__) - PRINT *, 'INFO:platform[Haiku]' -#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) - PRINT *, 'INFO:platform[BeOS]' -#elif defined(__QNX__) || defined(__QNXNTO__) - PRINT *, 'INFO:platform[QNX]' -#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) - PRINT *, 'INFO:platform[Tru64]' -#elif defined(__riscos) || defined(__riscos__) - PRINT *, 'INFO:platform[RISCos]' -#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) - PRINT *, 'INFO:platform[SINIX]' -#elif defined(__UNIX_SV__) - PRINT *, 'INFO:platform[UNIX_SV]' -#elif defined(__bsdos__) - PRINT *, 'INFO:platform[BSDOS]' -#elif defined(_MPRAS) || defined(MPRAS) - PRINT *, 'INFO:platform[MP-RAS]' -#elif defined(__osf) || defined(__osf__) - PRINT *, 'INFO:platform[OSF1]' -#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) - PRINT *, 'INFO:platform[SCO_SV]' -#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) - PRINT *, 'INFO:platform[ULTRIX]' -#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) - PRINT *, 'INFO:platform[Xenix]' -#else - PRINT *, 'INFO:platform[]' -#endif -#if defined(_WIN32) && (defined(__INTEL_COMPILER) || defined(__ICC)) -# if defined(_M_IA64) - PRINT *, 'INFO:arch[IA64]' -# elif defined(_M_X64) || defined(_M_AMD64) - PRINT *, 'INFO:arch[x64]' -# elif defined(_M_IX86) - PRINT *, 'INFO:arch[X86]' -# endif -#endif - -#if 0 -! Encode compiler version digits -#endif -#define DEC_8(n) (((n) / 10000000) % 10) -#define DEC_7(n) (((n) / 1000000) % 10) -#define DEC_6(n) (((n) / 100000) % 10) -#define DEC_5(n) (((n) / 10000) % 10) -#define DEC_4(n) (((n) / 1000) % 10) -#define DEC_3(n) (((n) / 100) % 10) -#define DEC_2(n) (((n) / 10) % 10) -#define DEC_1(n) (((n) ) % 10) -#define HEX_8(n) ((n)>>28 & 0xF) -#define HEX_7(n) ((n)>>24 & 0xF) -#define HEX_6(n) ((n)>>20 & 0xF) -#define HEX_5(n) ((n)>>16 & 0xF) -#define HEX_4(n) ((n)>>12 & 0xF) -#define HEX_3(n) ((n)>>8 & 0xF) -#define HEX_2(n) ((n)>>4 & 0xF) -#define HEX_1(n) ((n) & 0xF) - -#if defined(COMPILER_VERSION_MAJOR) -# undef DEC -# undef HEX -# define DEC(n) DEC_1(n) -# define HEX(n) HEX_1(n) -# if COMPILER_VERSION_MAJOR == 0 - PRINT *, 'INFO:compiler_version_MAJOR_digit_1[0]' -# elif COMPILER_VERSION_MAJOR == 1 - PRINT *, 'INFO:compiler_version_MAJOR_digit_1[1]' -# elif COMPILER_VERSION_MAJOR == 2 - PRINT *, 'INFO:compiler_version_MAJOR_digit_1[2]' -# elif COMPILER_VERSION_MAJOR == 3 - PRINT *, 'INFO:compiler_version_MAJOR_digit_1[3]' -# elif COMPILER_VERSION_MAJOR == 4 - PRINT *, 'INFO:compiler_version_MAJOR_digit_1[4]' -# elif COMPILER_VERSION_MAJOR == 5 - PRINT *, 'INFO:compiler_version_MAJOR_digit_1[5]' -# elif COMPILER_VERSION_MAJOR == 6 - PRINT *, 'INFO:compiler_version_MAJOR_digit_1[6]' -# elif COMPILER_VERSION_MAJOR == 7 - PRINT *, 'INFO:compiler_version_MAJOR_digit_1[7]' -# elif COMPILER_VERSION_MAJOR == 8 - PRINT *, 'INFO:compiler_version_MAJOR_digit_1[8]' -# elif COMPILER_VERSION_MAJOR == 9 - PRINT *, 'INFO:compiler_version_MAJOR_digit_1[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_2(n) -# define HEX(n) HEX_2(n) -# if COMPILER_VERSION_MAJOR == 0 - PRINT *, 'INFO:compiler_version_MAJOR_digit_2[0]' -# elif COMPILER_VERSION_MAJOR == 1 - PRINT *, 'INFO:compiler_version_MAJOR_digit_2[1]' -# elif COMPILER_VERSION_MAJOR == 2 - PRINT *, 'INFO:compiler_version_MAJOR_digit_2[2]' -# elif COMPILER_VERSION_MAJOR == 3 - PRINT *, 'INFO:compiler_version_MAJOR_digit_2[3]' -# elif COMPILER_VERSION_MAJOR == 4 - PRINT *, 'INFO:compiler_version_MAJOR_digit_2[4]' -# elif COMPILER_VERSION_MAJOR == 5 - PRINT *, 'INFO:compiler_version_MAJOR_digit_2[5]' -# elif COMPILER_VERSION_MAJOR == 6 - PRINT *, 'INFO:compiler_version_MAJOR_digit_2[6]' -# elif COMPILER_VERSION_MAJOR == 7 - PRINT *, 'INFO:compiler_version_MAJOR_digit_2[7]' -# elif COMPILER_VERSION_MAJOR == 8 - PRINT *, 'INFO:compiler_version_MAJOR_digit_2[8]' -# elif COMPILER_VERSION_MAJOR == 9 - PRINT *, 'INFO:compiler_version_MAJOR_digit_2[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_3(n) -# define HEX(n) HEX_3(n) -# if COMPILER_VERSION_MAJOR == 0 - PRINT *, 'INFO:compiler_version_MAJOR_digit_3[0]' -# elif COMPILER_VERSION_MAJOR == 1 - PRINT *, 'INFO:compiler_version_MAJOR_digit_3[1]' -# elif COMPILER_VERSION_MAJOR == 2 - PRINT *, 'INFO:compiler_version_MAJOR_digit_3[2]' -# elif COMPILER_VERSION_MAJOR == 3 - PRINT *, 'INFO:compiler_version_MAJOR_digit_3[3]' -# elif COMPILER_VERSION_MAJOR == 4 - PRINT *, 'INFO:compiler_version_MAJOR_digit_3[4]' -# elif COMPILER_VERSION_MAJOR == 5 - PRINT *, 'INFO:compiler_version_MAJOR_digit_3[5]' -# elif COMPILER_VERSION_MAJOR == 6 - PRINT *, 'INFO:compiler_version_MAJOR_digit_3[6]' -# elif COMPILER_VERSION_MAJOR == 7 - PRINT *, 'INFO:compiler_version_MAJOR_digit_3[7]' -# elif COMPILER_VERSION_MAJOR == 8 - PRINT *, 'INFO:compiler_version_MAJOR_digit_3[8]' -# elif COMPILER_VERSION_MAJOR == 9 - PRINT *, 'INFO:compiler_version_MAJOR_digit_3[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_4(n) -# define HEX(n) HEX_4(n) -# if COMPILER_VERSION_MAJOR == 0 - PRINT *, 'INFO:compiler_version_MAJOR_digit_4[0]' -# elif COMPILER_VERSION_MAJOR == 1 - PRINT *, 'INFO:compiler_version_MAJOR_digit_4[1]' -# elif COMPILER_VERSION_MAJOR == 2 - PRINT *, 'INFO:compiler_version_MAJOR_digit_4[2]' -# elif COMPILER_VERSION_MAJOR == 3 - PRINT *, 'INFO:compiler_version_MAJOR_digit_4[3]' -# elif COMPILER_VERSION_MAJOR == 4 - PRINT *, 'INFO:compiler_version_MAJOR_digit_4[4]' -# elif COMPILER_VERSION_MAJOR == 5 - PRINT *, 'INFO:compiler_version_MAJOR_digit_4[5]' -# elif COMPILER_VERSION_MAJOR == 6 - PRINT *, 'INFO:compiler_version_MAJOR_digit_4[6]' -# elif COMPILER_VERSION_MAJOR == 7 - PRINT *, 'INFO:compiler_version_MAJOR_digit_4[7]' -# elif COMPILER_VERSION_MAJOR == 8 - PRINT *, 'INFO:compiler_version_MAJOR_digit_4[8]' -# elif COMPILER_VERSION_MAJOR == 9 - PRINT *, 'INFO:compiler_version_MAJOR_digit_4[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_5(n) -# define HEX(n) HEX_5(n) -# if COMPILER_VERSION_MAJOR == 0 - PRINT *, 'INFO:compiler_version_MAJOR_digit_5[0]' -# elif COMPILER_VERSION_MAJOR == 1 - PRINT *, 'INFO:compiler_version_MAJOR_digit_5[1]' -# elif COMPILER_VERSION_MAJOR == 2 - PRINT *, 'INFO:compiler_version_MAJOR_digit_5[2]' -# elif COMPILER_VERSION_MAJOR == 3 - PRINT *, 'INFO:compiler_version_MAJOR_digit_5[3]' -# elif COMPILER_VERSION_MAJOR == 4 - PRINT *, 'INFO:compiler_version_MAJOR_digit_5[4]' -# elif COMPILER_VERSION_MAJOR == 5 - PRINT *, 'INFO:compiler_version_MAJOR_digit_5[5]' -# elif COMPILER_VERSION_MAJOR == 6 - PRINT *, 'INFO:compiler_version_MAJOR_digit_5[6]' -# elif COMPILER_VERSION_MAJOR == 7 - PRINT *, 'INFO:compiler_version_MAJOR_digit_5[7]' -# elif COMPILER_VERSION_MAJOR == 8 - PRINT *, 'INFO:compiler_version_MAJOR_digit_5[8]' -# elif COMPILER_VERSION_MAJOR == 9 - PRINT *, 'INFO:compiler_version_MAJOR_digit_5[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_6(n) -# define HEX(n) HEX_6(n) -# if COMPILER_VERSION_MAJOR == 0 - PRINT *, 'INFO:compiler_version_MAJOR_digit_6[0]' -# elif COMPILER_VERSION_MAJOR == 1 - PRINT *, 'INFO:compiler_version_MAJOR_digit_6[1]' -# elif COMPILER_VERSION_MAJOR == 2 - PRINT *, 'INFO:compiler_version_MAJOR_digit_6[2]' -# elif COMPILER_VERSION_MAJOR == 3 - PRINT *, 'INFO:compiler_version_MAJOR_digit_6[3]' -# elif COMPILER_VERSION_MAJOR == 4 - PRINT *, 'INFO:compiler_version_MAJOR_digit_6[4]' -# elif COMPILER_VERSION_MAJOR == 5 - PRINT *, 'INFO:compiler_version_MAJOR_digit_6[5]' -# elif COMPILER_VERSION_MAJOR == 6 - PRINT *, 'INFO:compiler_version_MAJOR_digit_6[6]' -# elif COMPILER_VERSION_MAJOR == 7 - PRINT *, 'INFO:compiler_version_MAJOR_digit_6[7]' -# elif COMPILER_VERSION_MAJOR == 8 - PRINT *, 'INFO:compiler_version_MAJOR_digit_6[8]' -# elif COMPILER_VERSION_MAJOR == 9 - PRINT *, 'INFO:compiler_version_MAJOR_digit_6[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_7(n) -# define HEX(n) HEX_7(n) -# if COMPILER_VERSION_MAJOR == 0 - PRINT *, 'INFO:compiler_version_MAJOR_digit_7[0]' -# elif COMPILER_VERSION_MAJOR == 1 - PRINT *, 'INFO:compiler_version_MAJOR_digit_7[1]' -# elif COMPILER_VERSION_MAJOR == 2 - PRINT *, 'INFO:compiler_version_MAJOR_digit_7[2]' -# elif COMPILER_VERSION_MAJOR == 3 - PRINT *, 'INFO:compiler_version_MAJOR_digit_7[3]' -# elif COMPILER_VERSION_MAJOR == 4 - PRINT *, 'INFO:compiler_version_MAJOR_digit_7[4]' -# elif COMPILER_VERSION_MAJOR == 5 - PRINT *, 'INFO:compiler_version_MAJOR_digit_7[5]' -# elif COMPILER_VERSION_MAJOR == 6 - PRINT *, 'INFO:compiler_version_MAJOR_digit_7[6]' -# elif COMPILER_VERSION_MAJOR == 7 - PRINT *, 'INFO:compiler_version_MAJOR_digit_7[7]' -# elif COMPILER_VERSION_MAJOR == 8 - PRINT *, 'INFO:compiler_version_MAJOR_digit_7[8]' -# elif COMPILER_VERSION_MAJOR == 9 - PRINT *, 'INFO:compiler_version_MAJOR_digit_7[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_8(n) -# define HEX(n) HEX_8(n) -# if COMPILER_VERSION_MAJOR == 0 - PRINT *, 'INFO:compiler_version_MAJOR_digit_8[0]' -# elif COMPILER_VERSION_MAJOR == 1 - PRINT *, 'INFO:compiler_version_MAJOR_digit_8[1]' -# elif COMPILER_VERSION_MAJOR == 2 - PRINT *, 'INFO:compiler_version_MAJOR_digit_8[2]' -# elif COMPILER_VERSION_MAJOR == 3 - PRINT *, 'INFO:compiler_version_MAJOR_digit_8[3]' -# elif COMPILER_VERSION_MAJOR == 4 - PRINT *, 'INFO:compiler_version_MAJOR_digit_8[4]' -# elif COMPILER_VERSION_MAJOR == 5 - PRINT *, 'INFO:compiler_version_MAJOR_digit_8[5]' -# elif COMPILER_VERSION_MAJOR == 6 - PRINT *, 'INFO:compiler_version_MAJOR_digit_8[6]' -# elif COMPILER_VERSION_MAJOR == 7 - PRINT *, 'INFO:compiler_version_MAJOR_digit_8[7]' -# elif COMPILER_VERSION_MAJOR == 8 - PRINT *, 'INFO:compiler_version_MAJOR_digit_8[8]' -# elif COMPILER_VERSION_MAJOR == 9 - PRINT *, 'INFO:compiler_version_MAJOR_digit_8[9]' -# endif - -#endif -#if defined(COMPILER_VERSION_MINOR) -# undef DEC -# undef HEX -# define DEC(n) DEC_1(n) -# define HEX(n) HEX_1(n) -# if COMPILER_VERSION_MINOR == 0 - PRINT *, 'INFO:compiler_version_MINOR_digit_1[0]' -# elif COMPILER_VERSION_MINOR == 1 - PRINT *, 'INFO:compiler_version_MINOR_digit_1[1]' -# elif COMPILER_VERSION_MINOR == 2 - PRINT *, 'INFO:compiler_version_MINOR_digit_1[2]' -# elif COMPILER_VERSION_MINOR == 3 - PRINT *, 'INFO:compiler_version_MINOR_digit_1[3]' -# elif COMPILER_VERSION_MINOR == 4 - PRINT *, 'INFO:compiler_version_MINOR_digit_1[4]' -# elif COMPILER_VERSION_MINOR == 5 - PRINT *, 'INFO:compiler_version_MINOR_digit_1[5]' -# elif COMPILER_VERSION_MINOR == 6 - PRINT *, 'INFO:compiler_version_MINOR_digit_1[6]' -# elif COMPILER_VERSION_MINOR == 7 - PRINT *, 'INFO:compiler_version_MINOR_digit_1[7]' -# elif COMPILER_VERSION_MINOR == 8 - PRINT *, 'INFO:compiler_version_MINOR_digit_1[8]' -# elif COMPILER_VERSION_MINOR == 9 - PRINT *, 'INFO:compiler_version_MINOR_digit_1[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_2(n) -# define HEX(n) HEX_2(n) -# if COMPILER_VERSION_MINOR == 0 - PRINT *, 'INFO:compiler_version_MINOR_digit_2[0]' -# elif COMPILER_VERSION_MINOR == 1 - PRINT *, 'INFO:compiler_version_MINOR_digit_2[1]' -# elif COMPILER_VERSION_MINOR == 2 - PRINT *, 'INFO:compiler_version_MINOR_digit_2[2]' -# elif COMPILER_VERSION_MINOR == 3 - PRINT *, 'INFO:compiler_version_MINOR_digit_2[3]' -# elif COMPILER_VERSION_MINOR == 4 - PRINT *, 'INFO:compiler_version_MINOR_digit_2[4]' -# elif COMPILER_VERSION_MINOR == 5 - PRINT *, 'INFO:compiler_version_MINOR_digit_2[5]' -# elif COMPILER_VERSION_MINOR == 6 - PRINT *, 'INFO:compiler_version_MINOR_digit_2[6]' -# elif COMPILER_VERSION_MINOR == 7 - PRINT *, 'INFO:compiler_version_MINOR_digit_2[7]' -# elif COMPILER_VERSION_MINOR == 8 - PRINT *, 'INFO:compiler_version_MINOR_digit_2[8]' -# elif COMPILER_VERSION_MINOR == 9 - PRINT *, 'INFO:compiler_version_MINOR_digit_2[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_3(n) -# define HEX(n) HEX_3(n) -# if COMPILER_VERSION_MINOR == 0 - PRINT *, 'INFO:compiler_version_MINOR_digit_3[0]' -# elif COMPILER_VERSION_MINOR == 1 - PRINT *, 'INFO:compiler_version_MINOR_digit_3[1]' -# elif COMPILER_VERSION_MINOR == 2 - PRINT *, 'INFO:compiler_version_MINOR_digit_3[2]' -# elif COMPILER_VERSION_MINOR == 3 - PRINT *, 'INFO:compiler_version_MINOR_digit_3[3]' -# elif COMPILER_VERSION_MINOR == 4 - PRINT *, 'INFO:compiler_version_MINOR_digit_3[4]' -# elif COMPILER_VERSION_MINOR == 5 - PRINT *, 'INFO:compiler_version_MINOR_digit_3[5]' -# elif COMPILER_VERSION_MINOR == 6 - PRINT *, 'INFO:compiler_version_MINOR_digit_3[6]' -# elif COMPILER_VERSION_MINOR == 7 - PRINT *, 'INFO:compiler_version_MINOR_digit_3[7]' -# elif COMPILER_VERSION_MINOR == 8 - PRINT *, 'INFO:compiler_version_MINOR_digit_3[8]' -# elif COMPILER_VERSION_MINOR == 9 - PRINT *, 'INFO:compiler_version_MINOR_digit_3[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_4(n) -# define HEX(n) HEX_4(n) -# if COMPILER_VERSION_MINOR == 0 - PRINT *, 'INFO:compiler_version_MINOR_digit_4[0]' -# elif COMPILER_VERSION_MINOR == 1 - PRINT *, 'INFO:compiler_version_MINOR_digit_4[1]' -# elif COMPILER_VERSION_MINOR == 2 - PRINT *, 'INFO:compiler_version_MINOR_digit_4[2]' -# elif COMPILER_VERSION_MINOR == 3 - PRINT *, 'INFO:compiler_version_MINOR_digit_4[3]' -# elif COMPILER_VERSION_MINOR == 4 - PRINT *, 'INFO:compiler_version_MINOR_digit_4[4]' -# elif COMPILER_VERSION_MINOR == 5 - PRINT *, 'INFO:compiler_version_MINOR_digit_4[5]' -# elif COMPILER_VERSION_MINOR == 6 - PRINT *, 'INFO:compiler_version_MINOR_digit_4[6]' -# elif COMPILER_VERSION_MINOR == 7 - PRINT *, 'INFO:compiler_version_MINOR_digit_4[7]' -# elif COMPILER_VERSION_MINOR == 8 - PRINT *, 'INFO:compiler_version_MINOR_digit_4[8]' -# elif COMPILER_VERSION_MINOR == 9 - PRINT *, 'INFO:compiler_version_MINOR_digit_4[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_5(n) -# define HEX(n) HEX_5(n) -# if COMPILER_VERSION_MINOR == 0 - PRINT *, 'INFO:compiler_version_MINOR_digit_5[0]' -# elif COMPILER_VERSION_MINOR == 1 - PRINT *, 'INFO:compiler_version_MINOR_digit_5[1]' -# elif COMPILER_VERSION_MINOR == 2 - PRINT *, 'INFO:compiler_version_MINOR_digit_5[2]' -# elif COMPILER_VERSION_MINOR == 3 - PRINT *, 'INFO:compiler_version_MINOR_digit_5[3]' -# elif COMPILER_VERSION_MINOR == 4 - PRINT *, 'INFO:compiler_version_MINOR_digit_5[4]' -# elif COMPILER_VERSION_MINOR == 5 - PRINT *, 'INFO:compiler_version_MINOR_digit_5[5]' -# elif COMPILER_VERSION_MINOR == 6 - PRINT *, 'INFO:compiler_version_MINOR_digit_5[6]' -# elif COMPILER_VERSION_MINOR == 7 - PRINT *, 'INFO:compiler_version_MINOR_digit_5[7]' -# elif COMPILER_VERSION_MINOR == 8 - PRINT *, 'INFO:compiler_version_MINOR_digit_5[8]' -# elif COMPILER_VERSION_MINOR == 9 - PRINT *, 'INFO:compiler_version_MINOR_digit_5[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_6(n) -# define HEX(n) HEX_6(n) -# if COMPILER_VERSION_MINOR == 0 - PRINT *, 'INFO:compiler_version_MINOR_digit_6[0]' -# elif COMPILER_VERSION_MINOR == 1 - PRINT *, 'INFO:compiler_version_MINOR_digit_6[1]' -# elif COMPILER_VERSION_MINOR == 2 - PRINT *, 'INFO:compiler_version_MINOR_digit_6[2]' -# elif COMPILER_VERSION_MINOR == 3 - PRINT *, 'INFO:compiler_version_MINOR_digit_6[3]' -# elif COMPILER_VERSION_MINOR == 4 - PRINT *, 'INFO:compiler_version_MINOR_digit_6[4]' -# elif COMPILER_VERSION_MINOR == 5 - PRINT *, 'INFO:compiler_version_MINOR_digit_6[5]' -# elif COMPILER_VERSION_MINOR == 6 - PRINT *, 'INFO:compiler_version_MINOR_digit_6[6]' -# elif COMPILER_VERSION_MINOR == 7 - PRINT *, 'INFO:compiler_version_MINOR_digit_6[7]' -# elif COMPILER_VERSION_MINOR == 8 - PRINT *, 'INFO:compiler_version_MINOR_digit_6[8]' -# elif COMPILER_VERSION_MINOR == 9 - PRINT *, 'INFO:compiler_version_MINOR_digit_6[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_7(n) -# define HEX(n) HEX_7(n) -# if COMPILER_VERSION_MINOR == 0 - PRINT *, 'INFO:compiler_version_MINOR_digit_7[0]' -# elif COMPILER_VERSION_MINOR == 1 - PRINT *, 'INFO:compiler_version_MINOR_digit_7[1]' -# elif COMPILER_VERSION_MINOR == 2 - PRINT *, 'INFO:compiler_version_MINOR_digit_7[2]' -# elif COMPILER_VERSION_MINOR == 3 - PRINT *, 'INFO:compiler_version_MINOR_digit_7[3]' -# elif COMPILER_VERSION_MINOR == 4 - PRINT *, 'INFO:compiler_version_MINOR_digit_7[4]' -# elif COMPILER_VERSION_MINOR == 5 - PRINT *, 'INFO:compiler_version_MINOR_digit_7[5]' -# elif COMPILER_VERSION_MINOR == 6 - PRINT *, 'INFO:compiler_version_MINOR_digit_7[6]' -# elif COMPILER_VERSION_MINOR == 7 - PRINT *, 'INFO:compiler_version_MINOR_digit_7[7]' -# elif COMPILER_VERSION_MINOR == 8 - PRINT *, 'INFO:compiler_version_MINOR_digit_7[8]' -# elif COMPILER_VERSION_MINOR == 9 - PRINT *, 'INFO:compiler_version_MINOR_digit_7[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_8(n) -# define HEX(n) HEX_8(n) -# if COMPILER_VERSION_MINOR == 0 - PRINT *, 'INFO:compiler_version_MINOR_digit_8[0]' -# elif COMPILER_VERSION_MINOR == 1 - PRINT *, 'INFO:compiler_version_MINOR_digit_8[1]' -# elif COMPILER_VERSION_MINOR == 2 - PRINT *, 'INFO:compiler_version_MINOR_digit_8[2]' -# elif COMPILER_VERSION_MINOR == 3 - PRINT *, 'INFO:compiler_version_MINOR_digit_8[3]' -# elif COMPILER_VERSION_MINOR == 4 - PRINT *, 'INFO:compiler_version_MINOR_digit_8[4]' -# elif COMPILER_VERSION_MINOR == 5 - PRINT *, 'INFO:compiler_version_MINOR_digit_8[5]' -# elif COMPILER_VERSION_MINOR == 6 - PRINT *, 'INFO:compiler_version_MINOR_digit_8[6]' -# elif COMPILER_VERSION_MINOR == 7 - PRINT *, 'INFO:compiler_version_MINOR_digit_8[7]' -# elif COMPILER_VERSION_MINOR == 8 - PRINT *, 'INFO:compiler_version_MINOR_digit_8[8]' -# elif COMPILER_VERSION_MINOR == 9 - PRINT *, 'INFO:compiler_version_MINOR_digit_8[9]' -# endif - -#endif -#if defined(COMPILER_VERSION_PATCH) -# undef DEC -# undef HEX -# define DEC(n) DEC_1(n) -# define HEX(n) HEX_1(n) -# if COMPILER_VERSION_PATCH == 0 - PRINT *, 'INFO:compiler_version_PATCH_digit_1[0]' -# elif COMPILER_VERSION_PATCH == 1 - PRINT *, 'INFO:compiler_version_PATCH_digit_1[1]' -# elif COMPILER_VERSION_PATCH == 2 - PRINT *, 'INFO:compiler_version_PATCH_digit_1[2]' -# elif COMPILER_VERSION_PATCH == 3 - PRINT *, 'INFO:compiler_version_PATCH_digit_1[3]' -# elif COMPILER_VERSION_PATCH == 4 - PRINT *, 'INFO:compiler_version_PATCH_digit_1[4]' -# elif COMPILER_VERSION_PATCH == 5 - PRINT *, 'INFO:compiler_version_PATCH_digit_1[5]' -# elif COMPILER_VERSION_PATCH == 6 - PRINT *, 'INFO:compiler_version_PATCH_digit_1[6]' -# elif COMPILER_VERSION_PATCH == 7 - PRINT *, 'INFO:compiler_version_PATCH_digit_1[7]' -# elif COMPILER_VERSION_PATCH == 8 - PRINT *, 'INFO:compiler_version_PATCH_digit_1[8]' -# elif COMPILER_VERSION_PATCH == 9 - PRINT *, 'INFO:compiler_version_PATCH_digit_1[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_2(n) -# define HEX(n) HEX_2(n) -# if COMPILER_VERSION_PATCH == 0 - PRINT *, 'INFO:compiler_version_PATCH_digit_2[0]' -# elif COMPILER_VERSION_PATCH == 1 - PRINT *, 'INFO:compiler_version_PATCH_digit_2[1]' -# elif COMPILER_VERSION_PATCH == 2 - PRINT *, 'INFO:compiler_version_PATCH_digit_2[2]' -# elif COMPILER_VERSION_PATCH == 3 - PRINT *, 'INFO:compiler_version_PATCH_digit_2[3]' -# elif COMPILER_VERSION_PATCH == 4 - PRINT *, 'INFO:compiler_version_PATCH_digit_2[4]' -# elif COMPILER_VERSION_PATCH == 5 - PRINT *, 'INFO:compiler_version_PATCH_digit_2[5]' -# elif COMPILER_VERSION_PATCH == 6 - PRINT *, 'INFO:compiler_version_PATCH_digit_2[6]' -# elif COMPILER_VERSION_PATCH == 7 - PRINT *, 'INFO:compiler_version_PATCH_digit_2[7]' -# elif COMPILER_VERSION_PATCH == 8 - PRINT *, 'INFO:compiler_version_PATCH_digit_2[8]' -# elif COMPILER_VERSION_PATCH == 9 - PRINT *, 'INFO:compiler_version_PATCH_digit_2[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_3(n) -# define HEX(n) HEX_3(n) -# if COMPILER_VERSION_PATCH == 0 - PRINT *, 'INFO:compiler_version_PATCH_digit_3[0]' -# elif COMPILER_VERSION_PATCH == 1 - PRINT *, 'INFO:compiler_version_PATCH_digit_3[1]' -# elif COMPILER_VERSION_PATCH == 2 - PRINT *, 'INFO:compiler_version_PATCH_digit_3[2]' -# elif COMPILER_VERSION_PATCH == 3 - PRINT *, 'INFO:compiler_version_PATCH_digit_3[3]' -# elif COMPILER_VERSION_PATCH == 4 - PRINT *, 'INFO:compiler_version_PATCH_digit_3[4]' -# elif COMPILER_VERSION_PATCH == 5 - PRINT *, 'INFO:compiler_version_PATCH_digit_3[5]' -# elif COMPILER_VERSION_PATCH == 6 - PRINT *, 'INFO:compiler_version_PATCH_digit_3[6]' -# elif COMPILER_VERSION_PATCH == 7 - PRINT *, 'INFO:compiler_version_PATCH_digit_3[7]' -# elif COMPILER_VERSION_PATCH == 8 - PRINT *, 'INFO:compiler_version_PATCH_digit_3[8]' -# elif COMPILER_VERSION_PATCH == 9 - PRINT *, 'INFO:compiler_version_PATCH_digit_3[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_4(n) -# define HEX(n) HEX_4(n) -# if COMPILER_VERSION_PATCH == 0 - PRINT *, 'INFO:compiler_version_PATCH_digit_4[0]' -# elif COMPILER_VERSION_PATCH == 1 - PRINT *, 'INFO:compiler_version_PATCH_digit_4[1]' -# elif COMPILER_VERSION_PATCH == 2 - PRINT *, 'INFO:compiler_version_PATCH_digit_4[2]' -# elif COMPILER_VERSION_PATCH == 3 - PRINT *, 'INFO:compiler_version_PATCH_digit_4[3]' -# elif COMPILER_VERSION_PATCH == 4 - PRINT *, 'INFO:compiler_version_PATCH_digit_4[4]' -# elif COMPILER_VERSION_PATCH == 5 - PRINT *, 'INFO:compiler_version_PATCH_digit_4[5]' -# elif COMPILER_VERSION_PATCH == 6 - PRINT *, 'INFO:compiler_version_PATCH_digit_4[6]' -# elif COMPILER_VERSION_PATCH == 7 - PRINT *, 'INFO:compiler_version_PATCH_digit_4[7]' -# elif COMPILER_VERSION_PATCH == 8 - PRINT *, 'INFO:compiler_version_PATCH_digit_4[8]' -# elif COMPILER_VERSION_PATCH == 9 - PRINT *, 'INFO:compiler_version_PATCH_digit_4[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_5(n) -# define HEX(n) HEX_5(n) -# if COMPILER_VERSION_PATCH == 0 - PRINT *, 'INFO:compiler_version_PATCH_digit_5[0]' -# elif COMPILER_VERSION_PATCH == 1 - PRINT *, 'INFO:compiler_version_PATCH_digit_5[1]' -# elif COMPILER_VERSION_PATCH == 2 - PRINT *, 'INFO:compiler_version_PATCH_digit_5[2]' -# elif COMPILER_VERSION_PATCH == 3 - PRINT *, 'INFO:compiler_version_PATCH_digit_5[3]' -# elif COMPILER_VERSION_PATCH == 4 - PRINT *, 'INFO:compiler_version_PATCH_digit_5[4]' -# elif COMPILER_VERSION_PATCH == 5 - PRINT *, 'INFO:compiler_version_PATCH_digit_5[5]' -# elif COMPILER_VERSION_PATCH == 6 - PRINT *, 'INFO:compiler_version_PATCH_digit_5[6]' -# elif COMPILER_VERSION_PATCH == 7 - PRINT *, 'INFO:compiler_version_PATCH_digit_5[7]' -# elif COMPILER_VERSION_PATCH == 8 - PRINT *, 'INFO:compiler_version_PATCH_digit_5[8]' -# elif COMPILER_VERSION_PATCH == 9 - PRINT *, 'INFO:compiler_version_PATCH_digit_5[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_6(n) -# define HEX(n) HEX_6(n) -# if COMPILER_VERSION_PATCH == 0 - PRINT *, 'INFO:compiler_version_PATCH_digit_6[0]' -# elif COMPILER_VERSION_PATCH == 1 - PRINT *, 'INFO:compiler_version_PATCH_digit_6[1]' -# elif COMPILER_VERSION_PATCH == 2 - PRINT *, 'INFO:compiler_version_PATCH_digit_6[2]' -# elif COMPILER_VERSION_PATCH == 3 - PRINT *, 'INFO:compiler_version_PATCH_digit_6[3]' -# elif COMPILER_VERSION_PATCH == 4 - PRINT *, 'INFO:compiler_version_PATCH_digit_6[4]' -# elif COMPILER_VERSION_PATCH == 5 - PRINT *, 'INFO:compiler_version_PATCH_digit_6[5]' -# elif COMPILER_VERSION_PATCH == 6 - PRINT *, 'INFO:compiler_version_PATCH_digit_6[6]' -# elif COMPILER_VERSION_PATCH == 7 - PRINT *, 'INFO:compiler_version_PATCH_digit_6[7]' -# elif COMPILER_VERSION_PATCH == 8 - PRINT *, 'INFO:compiler_version_PATCH_digit_6[8]' -# elif COMPILER_VERSION_PATCH == 9 - PRINT *, 'INFO:compiler_version_PATCH_digit_6[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_7(n) -# define HEX(n) HEX_7(n) -# if COMPILER_VERSION_PATCH == 0 - PRINT *, 'INFO:compiler_version_PATCH_digit_7[0]' -# elif COMPILER_VERSION_PATCH == 1 - PRINT *, 'INFO:compiler_version_PATCH_digit_7[1]' -# elif COMPILER_VERSION_PATCH == 2 - PRINT *, 'INFO:compiler_version_PATCH_digit_7[2]' -# elif COMPILER_VERSION_PATCH == 3 - PRINT *, 'INFO:compiler_version_PATCH_digit_7[3]' -# elif COMPILER_VERSION_PATCH == 4 - PRINT *, 'INFO:compiler_version_PATCH_digit_7[4]' -# elif COMPILER_VERSION_PATCH == 5 - PRINT *, 'INFO:compiler_version_PATCH_digit_7[5]' -# elif COMPILER_VERSION_PATCH == 6 - PRINT *, 'INFO:compiler_version_PATCH_digit_7[6]' -# elif COMPILER_VERSION_PATCH == 7 - PRINT *, 'INFO:compiler_version_PATCH_digit_7[7]' -# elif COMPILER_VERSION_PATCH == 8 - PRINT *, 'INFO:compiler_version_PATCH_digit_7[8]' -# elif COMPILER_VERSION_PATCH == 9 - PRINT *, 'INFO:compiler_version_PATCH_digit_7[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_8(n) -# define HEX(n) HEX_8(n) -# if COMPILER_VERSION_PATCH == 0 - PRINT *, 'INFO:compiler_version_PATCH_digit_8[0]' -# elif COMPILER_VERSION_PATCH == 1 - PRINT *, 'INFO:compiler_version_PATCH_digit_8[1]' -# elif COMPILER_VERSION_PATCH == 2 - PRINT *, 'INFO:compiler_version_PATCH_digit_8[2]' -# elif COMPILER_VERSION_PATCH == 3 - PRINT *, 'INFO:compiler_version_PATCH_digit_8[3]' -# elif COMPILER_VERSION_PATCH == 4 - PRINT *, 'INFO:compiler_version_PATCH_digit_8[4]' -# elif COMPILER_VERSION_PATCH == 5 - PRINT *, 'INFO:compiler_version_PATCH_digit_8[5]' -# elif COMPILER_VERSION_PATCH == 6 - PRINT *, 'INFO:compiler_version_PATCH_digit_8[6]' -# elif COMPILER_VERSION_PATCH == 7 - PRINT *, 'INFO:compiler_version_PATCH_digit_8[7]' -# elif COMPILER_VERSION_PATCH == 8 - PRINT *, 'INFO:compiler_version_PATCH_digit_8[8]' -# elif COMPILER_VERSION_PATCH == 9 - PRINT *, 'INFO:compiler_version_PATCH_digit_8[9]' -# endif - -#endif -#if defined(COMPILER_VERSION_TWEAK) -# undef DEC -# undef HEX -# define DEC(n) DEC_1(n) -# define HEX(n) HEX_1(n) -# if COMPILER_VERSION_TWEAK == 0 - PRINT *, 'INFO:compiler_version_TWEAK_digit_1[0]' -# elif COMPILER_VERSION_TWEAK == 1 - PRINT *, 'INFO:compiler_version_TWEAK_digit_1[1]' -# elif COMPILER_VERSION_TWEAK == 2 - PRINT *, 'INFO:compiler_version_TWEAK_digit_1[2]' -# elif COMPILER_VERSION_TWEAK == 3 - PRINT *, 'INFO:compiler_version_TWEAK_digit_1[3]' -# elif COMPILER_VERSION_TWEAK == 4 - PRINT *, 'INFO:compiler_version_TWEAK_digit_1[4]' -# elif COMPILER_VERSION_TWEAK == 5 - PRINT *, 'INFO:compiler_version_TWEAK_digit_1[5]' -# elif COMPILER_VERSION_TWEAK == 6 - PRINT *, 'INFO:compiler_version_TWEAK_digit_1[6]' -# elif COMPILER_VERSION_TWEAK == 7 - PRINT *, 'INFO:compiler_version_TWEAK_digit_1[7]' -# elif COMPILER_VERSION_TWEAK == 8 - PRINT *, 'INFO:compiler_version_TWEAK_digit_1[8]' -# elif COMPILER_VERSION_TWEAK == 9 - PRINT *, 'INFO:compiler_version_TWEAK_digit_1[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_2(n) -# define HEX(n) HEX_2(n) -# if COMPILER_VERSION_TWEAK == 0 - PRINT *, 'INFO:compiler_version_TWEAK_digit_2[0]' -# elif COMPILER_VERSION_TWEAK == 1 - PRINT *, 'INFO:compiler_version_TWEAK_digit_2[1]' -# elif COMPILER_VERSION_TWEAK == 2 - PRINT *, 'INFO:compiler_version_TWEAK_digit_2[2]' -# elif COMPILER_VERSION_TWEAK == 3 - PRINT *, 'INFO:compiler_version_TWEAK_digit_2[3]' -# elif COMPILER_VERSION_TWEAK == 4 - PRINT *, 'INFO:compiler_version_TWEAK_digit_2[4]' -# elif COMPILER_VERSION_TWEAK == 5 - PRINT *, 'INFO:compiler_version_TWEAK_digit_2[5]' -# elif COMPILER_VERSION_TWEAK == 6 - PRINT *, 'INFO:compiler_version_TWEAK_digit_2[6]' -# elif COMPILER_VERSION_TWEAK == 7 - PRINT *, 'INFO:compiler_version_TWEAK_digit_2[7]' -# elif COMPILER_VERSION_TWEAK == 8 - PRINT *, 'INFO:compiler_version_TWEAK_digit_2[8]' -# elif COMPILER_VERSION_TWEAK == 9 - PRINT *, 'INFO:compiler_version_TWEAK_digit_2[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_3(n) -# define HEX(n) HEX_3(n) -# if COMPILER_VERSION_TWEAK == 0 - PRINT *, 'INFO:compiler_version_TWEAK_digit_3[0]' -# elif COMPILER_VERSION_TWEAK == 1 - PRINT *, 'INFO:compiler_version_TWEAK_digit_3[1]' -# elif COMPILER_VERSION_TWEAK == 2 - PRINT *, 'INFO:compiler_version_TWEAK_digit_3[2]' -# elif COMPILER_VERSION_TWEAK == 3 - PRINT *, 'INFO:compiler_version_TWEAK_digit_3[3]' -# elif COMPILER_VERSION_TWEAK == 4 - PRINT *, 'INFO:compiler_version_TWEAK_digit_3[4]' -# elif COMPILER_VERSION_TWEAK == 5 - PRINT *, 'INFO:compiler_version_TWEAK_digit_3[5]' -# elif COMPILER_VERSION_TWEAK == 6 - PRINT *, 'INFO:compiler_version_TWEAK_digit_3[6]' -# elif COMPILER_VERSION_TWEAK == 7 - PRINT *, 'INFO:compiler_version_TWEAK_digit_3[7]' -# elif COMPILER_VERSION_TWEAK == 8 - PRINT *, 'INFO:compiler_version_TWEAK_digit_3[8]' -# elif COMPILER_VERSION_TWEAK == 9 - PRINT *, 'INFO:compiler_version_TWEAK_digit_3[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_4(n) -# define HEX(n) HEX_4(n) -# if COMPILER_VERSION_TWEAK == 0 - PRINT *, 'INFO:compiler_version_TWEAK_digit_4[0]' -# elif COMPILER_VERSION_TWEAK == 1 - PRINT *, 'INFO:compiler_version_TWEAK_digit_4[1]' -# elif COMPILER_VERSION_TWEAK == 2 - PRINT *, 'INFO:compiler_version_TWEAK_digit_4[2]' -# elif COMPILER_VERSION_TWEAK == 3 - PRINT *, 'INFO:compiler_version_TWEAK_digit_4[3]' -# elif COMPILER_VERSION_TWEAK == 4 - PRINT *, 'INFO:compiler_version_TWEAK_digit_4[4]' -# elif COMPILER_VERSION_TWEAK == 5 - PRINT *, 'INFO:compiler_version_TWEAK_digit_4[5]' -# elif COMPILER_VERSION_TWEAK == 6 - PRINT *, 'INFO:compiler_version_TWEAK_digit_4[6]' -# elif COMPILER_VERSION_TWEAK == 7 - PRINT *, 'INFO:compiler_version_TWEAK_digit_4[7]' -# elif COMPILER_VERSION_TWEAK == 8 - PRINT *, 'INFO:compiler_version_TWEAK_digit_4[8]' -# elif COMPILER_VERSION_TWEAK == 9 - PRINT *, 'INFO:compiler_version_TWEAK_digit_4[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_5(n) -# define HEX(n) HEX_5(n) -# if COMPILER_VERSION_TWEAK == 0 - PRINT *, 'INFO:compiler_version_TWEAK_digit_5[0]' -# elif COMPILER_VERSION_TWEAK == 1 - PRINT *, 'INFO:compiler_version_TWEAK_digit_5[1]' -# elif COMPILER_VERSION_TWEAK == 2 - PRINT *, 'INFO:compiler_version_TWEAK_digit_5[2]' -# elif COMPILER_VERSION_TWEAK == 3 - PRINT *, 'INFO:compiler_version_TWEAK_digit_5[3]' -# elif COMPILER_VERSION_TWEAK == 4 - PRINT *, 'INFO:compiler_version_TWEAK_digit_5[4]' -# elif COMPILER_VERSION_TWEAK == 5 - PRINT *, 'INFO:compiler_version_TWEAK_digit_5[5]' -# elif COMPILER_VERSION_TWEAK == 6 - PRINT *, 'INFO:compiler_version_TWEAK_digit_5[6]' -# elif COMPILER_VERSION_TWEAK == 7 - PRINT *, 'INFO:compiler_version_TWEAK_digit_5[7]' -# elif COMPILER_VERSION_TWEAK == 8 - PRINT *, 'INFO:compiler_version_TWEAK_digit_5[8]' -# elif COMPILER_VERSION_TWEAK == 9 - PRINT *, 'INFO:compiler_version_TWEAK_digit_5[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_6(n) -# define HEX(n) HEX_6(n) -# if COMPILER_VERSION_TWEAK == 0 - PRINT *, 'INFO:compiler_version_TWEAK_digit_6[0]' -# elif COMPILER_VERSION_TWEAK == 1 - PRINT *, 'INFO:compiler_version_TWEAK_digit_6[1]' -# elif COMPILER_VERSION_TWEAK == 2 - PRINT *, 'INFO:compiler_version_TWEAK_digit_6[2]' -# elif COMPILER_VERSION_TWEAK == 3 - PRINT *, 'INFO:compiler_version_TWEAK_digit_6[3]' -# elif COMPILER_VERSION_TWEAK == 4 - PRINT *, 'INFO:compiler_version_TWEAK_digit_6[4]' -# elif COMPILER_VERSION_TWEAK == 5 - PRINT *, 'INFO:compiler_version_TWEAK_digit_6[5]' -# elif COMPILER_VERSION_TWEAK == 6 - PRINT *, 'INFO:compiler_version_TWEAK_digit_6[6]' -# elif COMPILER_VERSION_TWEAK == 7 - PRINT *, 'INFO:compiler_version_TWEAK_digit_6[7]' -# elif COMPILER_VERSION_TWEAK == 8 - PRINT *, 'INFO:compiler_version_TWEAK_digit_6[8]' -# elif COMPILER_VERSION_TWEAK == 9 - PRINT *, 'INFO:compiler_version_TWEAK_digit_6[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_7(n) -# define HEX(n) HEX_7(n) -# if COMPILER_VERSION_TWEAK == 0 - PRINT *, 'INFO:compiler_version_TWEAK_digit_7[0]' -# elif COMPILER_VERSION_TWEAK == 1 - PRINT *, 'INFO:compiler_version_TWEAK_digit_7[1]' -# elif COMPILER_VERSION_TWEAK == 2 - PRINT *, 'INFO:compiler_version_TWEAK_digit_7[2]' -# elif COMPILER_VERSION_TWEAK == 3 - PRINT *, 'INFO:compiler_version_TWEAK_digit_7[3]' -# elif COMPILER_VERSION_TWEAK == 4 - PRINT *, 'INFO:compiler_version_TWEAK_digit_7[4]' -# elif COMPILER_VERSION_TWEAK == 5 - PRINT *, 'INFO:compiler_version_TWEAK_digit_7[5]' -# elif COMPILER_VERSION_TWEAK == 6 - PRINT *, 'INFO:compiler_version_TWEAK_digit_7[6]' -# elif COMPILER_VERSION_TWEAK == 7 - PRINT *, 'INFO:compiler_version_TWEAK_digit_7[7]' -# elif COMPILER_VERSION_TWEAK == 8 - PRINT *, 'INFO:compiler_version_TWEAK_digit_7[8]' -# elif COMPILER_VERSION_TWEAK == 9 - PRINT *, 'INFO:compiler_version_TWEAK_digit_7[9]' -# endif - -# undef DEC -# undef HEX -# define DEC(n) DEC_8(n) -# define HEX(n) HEX_8(n) -# if COMPILER_VERSION_TWEAK == 0 - PRINT *, 'INFO:compiler_version_TWEAK_digit_8[0]' -# elif COMPILER_VERSION_TWEAK == 1 - PRINT *, 'INFO:compiler_version_TWEAK_digit_8[1]' -# elif COMPILER_VERSION_TWEAK == 2 - PRINT *, 'INFO:compiler_version_TWEAK_digit_8[2]' -# elif COMPILER_VERSION_TWEAK == 3 - PRINT *, 'INFO:compiler_version_TWEAK_digit_8[3]' -# elif COMPILER_VERSION_TWEAK == 4 - PRINT *, 'INFO:compiler_version_TWEAK_digit_8[4]' -# elif COMPILER_VERSION_TWEAK == 5 - PRINT *, 'INFO:compiler_version_TWEAK_digit_8[5]' -# elif COMPILER_VERSION_TWEAK == 6 - PRINT *, 'INFO:compiler_version_TWEAK_digit_8[6]' -# elif COMPILER_VERSION_TWEAK == 7 - PRINT *, 'INFO:compiler_version_TWEAK_digit_8[7]' -# elif COMPILER_VERSION_TWEAK == 8 - PRINT *, 'INFO:compiler_version_TWEAK_digit_8[8]' -# elif COMPILER_VERSION_TWEAK == 9 - PRINT *, 'INFO:compiler_version_TWEAK_digit_8[9]' -# endif - -#endif - - END diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/CMakeDirectoryInformation.cmake b/build/__command_line_test__/__command_line_test__/CMakeFiles/CMakeDirectoryInformation.cmake deleted file mode 100644 index 0626f191b1..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/CMakeDirectoryInformation.cmake +++ /dev/null @@ -1,16 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 3.25 - -# Relative path conversion top directories. -set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/Users/afoster/Documents/ncar/CTSM/src/fates") -set(CMAKE_RELATIVE_PATH_TOP_BINARY "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__") - -# Force unix paths in dependencies. -set(CMAKE_FORCE_UNIX_PATHS 1) - - -# The C and CXX include file regular expressions for this directory. -set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") -set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") -set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) -set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/Makefile.cmake b/build/__command_line_test__/__command_line_test__/CMakeFiles/Makefile.cmake deleted file mode 100644 index ab222437f3..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/Makefile.cmake +++ /dev/null @@ -1,141 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 3.25 - -# The generator used is: -set(CMAKE_DEPENDS_GENERATOR "Unix Makefiles") - -# The top level Makefile was generated from the following files: -set(CMAKE_MAKEFILE_DEPENDS - "CMakeCache.txt" - "/Users/afoster/Documents/ncar/CTSM/cime/CIME/non_py/src/CMake/CIME_initial_setup.cmake" - "/Users/afoster/Documents/ncar/CTSM/cime/CIME/non_py/src/CMake/CIME_utils.cmake" - "/Users/afoster/Documents/ncar/CTSM/cime/CIME/non_py/src/CMake/Compilers.cmake" - "/Users/afoster/Documents/ncar/CTSM/cime/CIME/non_py/src/CMake/FindpFUnit.cmake" - "/Users/afoster/Documents/ncar/CTSM/cime/CIME/non_py/src/CMake/Sourcelist_utils.cmake" - "/Users/afoster/Documents/ncar/CTSM/cime/CIME/non_py/src/CMake/genf90_utils.cmake" - "/Users/afoster/Documents/ncar/CTSM/cime/CIME/non_py/src/CMake/pFUnit_utils.cmake" - "/Users/afoster/Documents/ncar/CTSM/src/fates/CMakeLists.txt" - "CMakeFiles/3.25.2/CMakeCCompiler.cmake" - "CMakeFiles/3.25.2/CMakeFortranCompiler.cmake" - "CMakeFiles/3.25.2/CMakeSystem.cmake" - "Macros.cmake" - "/Users/afoster/Documents/ncar/CTSM/src/fates/build/cmake_macros/gnu.cmake" - "/Users/afoster/Documents/ncar/CTSM/src/fates/build/cmake_macros/gnu_fleabone.cmake" - "/Users/afoster/Documents/ncar/CTSM/src/fates/build/cmake_macros/universal.cmake" - "/Users/afoster/Documents/ncar/CTSM/src/fates/main/CMakeLists.txt" - "/Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/CMakeLists.txt" - "/Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/radiation_test/CMakeLists.txt" - "/Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/CMakeLists.txt" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeCCompiler.cmake.in" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeCCompilerABI.c" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeCInformation.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeCommonLanguageInclude.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeCompilerIdDetection.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeDetermineCCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeDetermineCompileFeatures.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeDetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeDetermineCompilerABI.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeDetermineCompilerId.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeDetermineFortranCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeDetermineSystem.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeFindBinUtils.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeFortranCompiler.cmake.in" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeFortranCompilerABI.F90" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeFortranInformation.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeGenericSystem.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeInitializeConfigs.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeLanguageInformation.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeParseArguments.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeParseImplicitIncludeInfo.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeParseImplicitLinkInfo.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeParseLibraryArchitecture.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeSystem.cmake.in" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeSystemSpecificInformation.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeSystemSpecificInitialize.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeTestCCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeTestCompilerCommon.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeTestFortranCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/CMakeUnixFindMake.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/ADSP-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/ARMCC-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/ARMClang-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/AppleClang-C.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/AppleClang-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/Borland-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/Bruce-C-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/CMakeCommonCompilerMacros.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/Clang-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/Clang.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/Compaq-C-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/Cray-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/GHS-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/GNU-C-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/GNU-FindBinUtils.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/GNU-Fortran.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/GNU.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/HP-C-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/IAR-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/IBMClang-C-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/Intel-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/LCC-C-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/MSVC-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/NVHPC-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/PGI-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/PathScale-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/SCO-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/SDCC-C-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/SunPro-C-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/TI-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/Tasking-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/Watcom-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/XL-C-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/XLClang-C-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Compiler/zOS-C-DetermineCompiler.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/FindPackageHandleStandardArgs.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/FindPackageMessage.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Internal/FeatureTesting.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Platform/Apple-AppleClang-C.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Platform/Apple-Clang-C.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Platform/Apple-Clang.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Platform/Apple-GNU-Fortran.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Platform/Apple-GNU.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Platform/Darwin-Initialize.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Platform/Darwin.cmake" - "/usr/local/Cellar/cmake/3.25.2/share/cmake/Modules/Platform/UnixPaths.cmake" - ) - -# The corresponding makefile is: -set(CMAKE_MAKEFILE_OUTPUTS - "Makefile" - "CMakeFiles/cmake.check_cache" - ) - -# Byproducts of CMake generate step: -set(CMAKE_MAKEFILE_PRODUCTS - "CMakeFiles/3.25.2/CMakeSystem.cmake" - "CMakeFiles/3.25.2/CMakeFortranCompiler.cmake" - "CMakeFiles/3.25.2/CMakeCCompiler.cmake" - "CMakeFiles/3.25.2/CMakeFortranCompiler.cmake" - "CMakeFiles/3.25.2/CMakeCCompiler.cmake" - "CMakeFiles/CMakeDirectoryInformation.cmake" - "main/CMakeFiles/CMakeDirectoryInformation.cmake" - "unit_testing/utils/CMakeFiles/CMakeDirectoryInformation.cmake" - "unit_testing/test/CMakeFiles/CMakeDirectoryInformation.cmake" - "unit_testing/test/radiation_test/CMakeFiles/CMakeDirectoryInformation.cmake" - ) - -# Dependency information for all targets: -set(CMAKE_DEPEND_INFO_FILES - "CMakeFiles/utils.dir/DependInfo.cmake" - "unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/DependInfo.cmake" - ) diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/Makefile2 b/build/__command_line_test__/__command_line_test__/CMakeFiles/Makefile2 deleted file mode 100644 index 966dd8971c..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/Makefile2 +++ /dev/null @@ -1,206 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 3.25 - -# Default target executed when no arguments are given to make. -default_target: all -.PHONY : default_target - -#============================================================================= -# Special targets provided by cmake. - -# Disable implicit rules so canonical targets will work. -.SUFFIXES: - -# Disable VCS-based implicit rules. -% : %,v - -# Disable VCS-based implicit rules. -% : RCS/% - -# Disable VCS-based implicit rules. -% : RCS/%,v - -# Disable VCS-based implicit rules. -% : SCCS/s.% - -# Disable VCS-based implicit rules. -% : s.% - -.SUFFIXES: .hpux_make_needs_suffix_list - -# Command-line flag to silence nested $(MAKE). -$(VERBOSE)MAKESILENT = -s - -#Suppress display of executed commands. -$(VERBOSE).SILENT: - -# A target that is always out of date. -cmake_force: -.PHONY : cmake_force - -#============================================================================= -# Set environment variables for the build. - -# The shell in which to execute make rules. -SHELL = /bin/sh - -# The CMake executable. -CMAKE_COMMAND = /usr/local/Cellar/cmake/3.25.2/bin/cmake - -# The command to remove a file. -RM = /usr/local/Cellar/cmake/3.25.2/bin/cmake -E rm -f - -# Escaping for special characters. -EQUALS = = - -# The top-level source directory on which CMake was run. -CMAKE_SOURCE_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates - -# The top-level build directory on which CMake was run. -CMAKE_BINARY_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ - -#============================================================================= -# Directory level rules for the build root directory - -# The main recursive "all" target. -all: CMakeFiles/utils.dir/all -all: main/all -all: unit_testing/utils/all -all: unit_testing/test/all -.PHONY : all - -# The main recursive "preinstall" target. -preinstall: main/preinstall -preinstall: unit_testing/utils/preinstall -preinstall: unit_testing/test/preinstall -.PHONY : preinstall - -# The main recursive "clean" target. -clean: CMakeFiles/utils.dir/clean -clean: main/clean -clean: unit_testing/utils/clean -clean: unit_testing/test/clean -.PHONY : clean - -#============================================================================= -# Directory level rules for directory main - -# Recursive "all" directory target. -main/all: -.PHONY : main/all - -# Recursive "preinstall" directory target. -main/preinstall: -.PHONY : main/preinstall - -# Recursive "clean" directory target. -main/clean: -.PHONY : main/clean - -#============================================================================= -# Directory level rules for directory unit_testing/test - -# Recursive "all" directory target. -unit_testing/test/all: unit_testing/test/radiation_test/all -.PHONY : unit_testing/test/all - -# Recursive "preinstall" directory target. -unit_testing/test/preinstall: unit_testing/test/radiation_test/preinstall -.PHONY : unit_testing/test/preinstall - -# Recursive "clean" directory target. -unit_testing/test/clean: unit_testing/test/radiation_test/clean -.PHONY : unit_testing/test/clean - -#============================================================================= -# Directory level rules for directory unit_testing/test/radiation_test - -# Recursive "all" directory target. -unit_testing/test/radiation_test/all: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/all -.PHONY : unit_testing/test/radiation_test/all - -# Recursive "preinstall" directory target. -unit_testing/test/radiation_test/preinstall: -.PHONY : unit_testing/test/radiation_test/preinstall - -# Recursive "clean" directory target. -unit_testing/test/radiation_test/clean: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/clean -.PHONY : unit_testing/test/radiation_test/clean - -#============================================================================= -# Directory level rules for directory unit_testing/utils - -# Recursive "all" directory target. -unit_testing/utils/all: -.PHONY : unit_testing/utils/all - -# Recursive "preinstall" directory target. -unit_testing/utils/preinstall: -.PHONY : unit_testing/utils/preinstall - -# Recursive "clean" directory target. -unit_testing/utils/clean: -.PHONY : unit_testing/utils/clean - -#============================================================================= -# Target rules for target CMakeFiles/utils.dir - -# All Build rule for target. -CMakeFiles/utils.dir/all: - $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/depend - $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/build - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles --progress-num=6,7,8,9 "Built target utils" -.PHONY : CMakeFiles/utils.dir/all - -# Build rule for subdir invocation for target. -CMakeFiles/utils.dir/rule: cmake_check_build_system - $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles 4 - $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 CMakeFiles/utils.dir/all - $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles 0 -.PHONY : CMakeFiles/utils.dir/rule - -# Convenience name for target. -utils: CMakeFiles/utils.dir/rule -.PHONY : utils - -# clean rule for target. -CMakeFiles/utils.dir/clean: - $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/clean -.PHONY : CMakeFiles/utils.dir/clean - -#============================================================================= -# Target rules for target unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir - -# All Build rule for target. -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/all: - $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/depend - $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles --progress-num=1,2,3,4,5 "Built target FATES_rad_test" -.PHONY : unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/all - -# Build rule for subdir invocation for target. -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/rule: cmake_check_build_system - $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles 5 - $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/all - $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles 0 -.PHONY : unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/rule - -# Convenience name for target. -FATES_rad_test: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/rule -.PHONY : FATES_rad_test - -# clean rule for target. -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/clean: - $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/clean -.PHONY : unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/clean - -#============================================================================= -# Special targets to cleanup operation of make. - -# Special rule to run CMake to check the build system integrity. -# No rule that depends on this can have commands that come from listfiles -# because they might be regenerated. -cmake_check_build_system: - $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 -.PHONY : cmake_check_build_system - diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/1 b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/1 deleted file mode 100644 index 7b4d68d70f..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/1 +++ /dev/null @@ -1 +0,0 @@ -empty \ No newline at end of file diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/2 b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/2 deleted file mode 100644 index 7b4d68d70f..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/2 +++ /dev/null @@ -1 +0,0 @@ -empty \ No newline at end of file diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/3 b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/3 deleted file mode 100644 index 7b4d68d70f..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/3 +++ /dev/null @@ -1 +0,0 @@ -empty \ No newline at end of file diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/4 b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/4 deleted file mode 100644 index 7b4d68d70f..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/4 +++ /dev/null @@ -1 +0,0 @@ -empty \ No newline at end of file diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/6 b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/6 deleted file mode 100644 index 7b4d68d70f..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/6 +++ /dev/null @@ -1 +0,0 @@ -empty \ No newline at end of file diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/7 b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/7 deleted file mode 100644 index 7b4d68d70f..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/7 +++ /dev/null @@ -1 +0,0 @@ -empty \ No newline at end of file diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/8 b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/8 deleted file mode 100644 index 7b4d68d70f..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/8 +++ /dev/null @@ -1 +0,0 @@ -empty \ No newline at end of file diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/9 b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/9 deleted file mode 100644 index 7b4d68d70f..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/9 +++ /dev/null @@ -1 +0,0 @@ -empty \ No newline at end of file diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/count.txt b/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/count.txt deleted file mode 100644 index ec635144f6..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/Progress/count.txt +++ /dev/null @@ -1 +0,0 @@ -9 diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/TargetDirectories.txt b/build/__command_line_test__/__command_line_test__/CMakeFiles/TargetDirectories.txt deleted file mode 100644 index 949f360985..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/TargetDirectories.txt +++ /dev/null @@ -1,17 +0,0 @@ -/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir -/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles/test.dir -/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles/edit_cache.dir -/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles/rebuild_cache.dir -/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/main/CMakeFiles/test.dir -/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/main/CMakeFiles/edit_cache.dir -/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/main/CMakeFiles/rebuild_cache.dir -/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/utils/CMakeFiles/test.dir -/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/utils/CMakeFiles/edit_cache.dir -/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/utils/CMakeFiles/rebuild_cache.dir -/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/CMakeFiles/test.dir -/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/CMakeFiles/edit_cache.dir -/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/CMakeFiles/rebuild_cache.dir -/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir -/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/test.dir -/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/edit_cache.dir -/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/rebuild_cache.dir diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/cmake.check_cache b/build/__command_line_test__/__command_line_test__/CMakeFiles/cmake.check_cache deleted file mode 100644 index 3dccd73172..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/cmake.check_cache +++ /dev/null @@ -1 +0,0 @@ -# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/progress.marks b/build/__command_line_test__/__command_line_test__/CMakeFiles/progress.marks deleted file mode 100644 index ec635144f6..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/progress.marks +++ /dev/null @@ -1 +0,0 @@ -9 diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/DependInfo.cmake b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/DependInfo.cmake deleted file mode 100644 index 1dab08913a..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/DependInfo.cmake +++ /dev/null @@ -1,37 +0,0 @@ - -# Consider dependencies only in project. -set(CMAKE_DEPENDS_IN_PROJECT_ONLY OFF) - -# The set of languages for which implicit dependencies are needed: -set(CMAKE_DEPENDS_LANGUAGES - "Fortran" - ) -# The set of files for implicit dependencies of each language: -set(CMAKE_DEPENDS_CHECK_Fortran - "/Users/afoster/Documents/ncar/CTSM/src/fates/main/FatesConstantsMod.F90" "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o" - "/Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestIOMod.F90" "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o" - "/Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestOrbitalMod.F90" "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o" - ) -set(CMAKE_Fortran_COMPILER_ID "GNU") -set(CMAKE_Fortran_SUBMODULE_SEP "@") -set(CMAKE_Fortran_SUBMODULE_EXT ".smod") - -# The include file search paths: -set(CMAKE_Fortran_TARGET_INCLUDE_PATH - "/Users/afoster/pFUnit/include" - "/Users/afoster/pFUnit/mod" - "/usr/local/Cellar/netcdf/4.9.2/include" - "/usr/local/Cellar/netcdf-fortran/4.6.0/include" - "." - ) - -# The set of dependency files which are needed: -set(CMAKE_DEPENDS_DEPENDENCY_FILES - ) - -# Targets to which this target links. -set(CMAKE_TARGET_LINKED_INFO_FILES - ) - -# Fortran module output directory. -set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/build.make b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/build.make deleted file mode 100644 index e85a792b85..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/build.make +++ /dev/null @@ -1,140 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 3.25 - -# Delete rule output on recipe failure. -.DELETE_ON_ERROR: - -#============================================================================= -# Special targets provided by cmake. - -# Disable implicit rules so canonical targets will work. -.SUFFIXES: - -# Disable VCS-based implicit rules. -% : %,v - -# Disable VCS-based implicit rules. -% : RCS/% - -# Disable VCS-based implicit rules. -% : RCS/%,v - -# Disable VCS-based implicit rules. -% : SCCS/s.% - -# Disable VCS-based implicit rules. -% : s.% - -.SUFFIXES: .hpux_make_needs_suffix_list - -# Command-line flag to silence nested $(MAKE). -$(VERBOSE)MAKESILENT = -s - -#Suppress display of executed commands. -$(VERBOSE).SILENT: - -# A target that is always out of date. -cmake_force: -.PHONY : cmake_force - -#============================================================================= -# Set environment variables for the build. - -# The shell in which to execute make rules. -SHELL = /bin/sh - -# The CMake executable. -CMAKE_COMMAND = /usr/local/Cellar/cmake/3.25.2/bin/cmake - -# The command to remove a file. -RM = /usr/local/Cellar/cmake/3.25.2/bin/cmake -E rm -f - -# Escaping for special characters. -EQUALS = = - -# The top-level source directory on which CMake was run. -CMAKE_SOURCE_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates - -# The top-level build directory on which CMake was run. -CMAKE_BINARY_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ - -# Include any dependencies generated for this target. -include CMakeFiles/utils.dir/depend.make -# Include any dependencies generated by the compiler for this target. -include CMakeFiles/utils.dir/compiler_depend.make - -# Include the progress variables for this target. -include CMakeFiles/utils.dir/progress.make - -# Include the compile flags for this target's objects. -include CMakeFiles/utils.dir/flags.make - -CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o: CMakeFiles/utils.dir/flags.make -CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o: /Users/afoster/Documents/ncar/CTSM/src/fates/main/FatesConstantsMod.F90 - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building Fortran object CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o" - /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -c /Users/afoster/Documents/ncar/CTSM/src/fates/main/FatesConstantsMod.F90 -o CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o - -CMakeFiles/utils.dir/main/FatesConstantsMod.F90.i: cmake_force - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing Fortran source to CMakeFiles/utils.dir/main/FatesConstantsMod.F90.i" - /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -E /Users/afoster/Documents/ncar/CTSM/src/fates/main/FatesConstantsMod.F90 > CMakeFiles/utils.dir/main/FatesConstantsMod.F90.i - -CMakeFiles/utils.dir/main/FatesConstantsMod.F90.s: cmake_force - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling Fortran source to assembly CMakeFiles/utils.dir/main/FatesConstantsMod.F90.s" - /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -S /Users/afoster/Documents/ncar/CTSM/src/fates/main/FatesConstantsMod.F90 -o CMakeFiles/utils.dir/main/FatesConstantsMod.F90.s - -CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o: CMakeFiles/utils.dir/flags.make -CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o: /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestIOMod.F90 - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Building Fortran object CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o" - /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -c /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestIOMod.F90 -o CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o - -CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.i: cmake_force - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing Fortran source to CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.i" - /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -E /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestIOMod.F90 > CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.i - -CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.s: cmake_force - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling Fortran source to assembly CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.s" - /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -S /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestIOMod.F90 -o CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.s - -CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o: CMakeFiles/utils.dir/flags.make -CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o: /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestOrbitalMod.F90 - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles --progress-num=$(CMAKE_PROGRESS_3) "Building Fortran object CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o" - /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -c /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestOrbitalMod.F90 -o CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o - -CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.i: cmake_force - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing Fortran source to CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.i" - /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -E /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestOrbitalMod.F90 > CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.i - -CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.s: cmake_force - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling Fortran source to assembly CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.s" - /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -S /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestOrbitalMod.F90 -o CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.s - -# Object files for target utils -utils_OBJECTS = \ -"CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o" \ -"CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o" \ -"CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o" - -# External object files for target utils -utils_EXTERNAL_OBJECTS = - -libutils.a: CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o -libutils.a: CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o -libutils.a: CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o -libutils.a: CMakeFiles/utils.dir/build.make -libutils.a: CMakeFiles/utils.dir/link.txt - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles --progress-num=$(CMAKE_PROGRESS_4) "Linking Fortran static library libutils.a" - $(CMAKE_COMMAND) -P CMakeFiles/utils.dir/cmake_clean_target.cmake - $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/utils.dir/link.txt --verbose=$(VERBOSE) - -# Rule to build all files generated by this target. -CMakeFiles/utils.dir/build: libutils.a -.PHONY : CMakeFiles/utils.dir/build - -CMakeFiles/utils.dir/clean: - $(CMAKE_COMMAND) -P CMakeFiles/utils.dir/cmake_clean.cmake -.PHONY : CMakeFiles/utils.dir/clean - -CMakeFiles/utils.dir/depend: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /Users/afoster/Documents/ncar/CTSM/src/fates /Users/afoster/Documents/ncar/CTSM/src/fates /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/DependInfo.cmake --color=$(COLOR) -.PHONY : CMakeFiles/utils.dir/depend - diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/cmake_clean.cmake b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/cmake_clean.cmake deleted file mode 100644 index 3c01a04cf5..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/cmake_clean.cmake +++ /dev/null @@ -1,12 +0,0 @@ -file(REMOVE_RECURSE - "CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o" - "CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o" - "CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o" - "libutils.a" - "libutils.pdb" -) - -# Per-language clean rules from dependency scanning. -foreach(lang Fortran) - include(CMakeFiles/utils.dir/cmake_clean_${lang}.cmake OPTIONAL) -endforeach() diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/cmake_clean_Fortran.cmake b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/cmake_clean_Fortran.cmake deleted file mode 100644 index 820ee03e9b..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/cmake_clean_Fortran.cmake +++ /dev/null @@ -1,14 +0,0 @@ -# Remove fortran modules provided by this target. -FILE(REMOVE - "fatesconstantsmod.mod" - "FATESCONSTANTSMOD.mod" - "CMakeFiles/utils.dir/fatesconstantsmod.mod.stamp" - - "fatesunittestiomod.mod" - "FATESUNITTESTIOMOD.mod" - "CMakeFiles/utils.dir/fatesunittestiomod.mod.stamp" - - "fatesunittestorbitalmod.mod" - "FATESUNITTESTORBITALMOD.mod" - "CMakeFiles/utils.dir/fatesunittestorbitalmod.mod.stamp" - ) diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/cmake_clean_target.cmake b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/cmake_clean_target.cmake deleted file mode 100644 index 6da29f6b6f..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/cmake_clean_target.cmake +++ /dev/null @@ -1,3 +0,0 @@ -file(REMOVE_RECURSE - "libutils.a" -) diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/compiler_depend.make b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/compiler_depend.make deleted file mode 100644 index ab29ade490..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/compiler_depend.make +++ /dev/null @@ -1,2 +0,0 @@ -# Empty compiler generated dependencies file for utils. -# This may be replaced when dependencies are built. diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/compiler_depend.ts b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/compiler_depend.ts deleted file mode 100644 index 92e446bc27..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/compiler_depend.ts +++ /dev/null @@ -1,2 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Timestamp file for compiler generated dependencies management for utils. diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/depend.internal b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/depend.internal deleted file mode 100644 index f7c3988daa..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/depend.internal +++ /dev/null @@ -1,9 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 3.25 - -CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o - /Users/afoster/Documents/ncar/CTSM/src/fates/main/FatesConstantsMod.F90 -CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o - /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestIOMod.F90 -CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o - /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestOrbitalMod.F90 diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/depend.make b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/depend.make deleted file mode 100644 index 304216def0..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/depend.make +++ /dev/null @@ -1,25 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 3.25 - -# Note that incremental build could trigger a call to cmake_copy_f90_mod on each re-build -CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o.provides.build: CMakeFiles/utils.dir/fatesconstantsmod.mod.stamp -CMakeFiles/utils.dir/fatesconstantsmod.mod.stamp: CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o - $(CMAKE_COMMAND) -E cmake_copy_f90_mod fatesconstantsmod.mod CMakeFiles/utils.dir/fatesconstantsmod.mod.stamp GNU -CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o.provides.build: - $(CMAKE_COMMAND) -E touch CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o.provides.build -CMakeFiles/utils.dir/build: CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o.provides.build -CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o: CMakeFiles/utils.dir/fatesconstantsmod.mod.stamp -CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o: /usr/local/Cellar/netcdf-fortran/4.6.0/include/netcdf.mod -CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o.provides.build: CMakeFiles/utils.dir/fatesunittestiomod.mod.stamp -CMakeFiles/utils.dir/fatesunittestiomod.mod.stamp: CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o - $(CMAKE_COMMAND) -E cmake_copy_f90_mod fatesunittestiomod.mod CMakeFiles/utils.dir/fatesunittestiomod.mod.stamp GNU -CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o.provides.build: - $(CMAKE_COMMAND) -E touch CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o.provides.build -CMakeFiles/utils.dir/build: CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o.provides.build -CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o: CMakeFiles/utils.dir/fatesunittestiomod.mod.stamp -CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o.provides.build: CMakeFiles/utils.dir/fatesunittestorbitalmod.mod.stamp -CMakeFiles/utils.dir/fatesunittestorbitalmod.mod.stamp: CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o - $(CMAKE_COMMAND) -E cmake_copy_f90_mod fatesunittestorbitalmod.mod CMakeFiles/utils.dir/fatesunittestorbitalmod.mod.stamp GNU -CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o.provides.build: - $(CMAKE_COMMAND) -E touch CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o.provides.build -CMakeFiles/utils.dir/build: CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o.provides.build diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fatesconstantsmod.mod.stamp b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fatesconstantsmod.mod.stamp deleted file mode 100644 index 2b4ac0b598d43fed2ea70fd8680dacf9fc821b43..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2256 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 diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fatesunittestiomod.mod.stamp b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fatesunittestiomod.mod.stamp deleted file mode 100644 index bac5e8f68dbed86771ad6e160e953b2ced9f2e29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24087 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 P!!w~bQoeT*Pci-nwC<&` diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fatesunittestorbitalmod.mod.stamp b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fatesunittestorbitalmod.mod.stamp deleted file mode 100644 index cb85e3a79588da53be704d893829e4e21f8807ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25076 zcmZU(18^tL7d;whW81cEXJgwoH_pa(HnwfscCx|7*=S>9WBg~ozlVDDQnyaJdiqX( zditK*r+bDd`U}W^e`psy_AdL9iHt8feL>sj&pT-4kCl#Re?1?$FJlCZ;~zJBoXN10 zA>3TTNzD^a8{W?pDSv-46RrQEL=UpqwDFCLSY}RDJ0(RsBjq{o^JXaC|MTYTDoyb< zJk7rIEtxPb>)qiwl-ZE}3hCq}S&*Ix>9y>@zuz!k=!&zfuWW1)DZFdOy664uW7q%v zs}!c8-*edk$A`c2$AKc;6W!bMZSK&o78A2uhhGf~6 zrR$2($67+JjSH;kWu){H{mv4@uo9`tIbSKos=p^oAAFdi^r3pNE$H4f(<-YaPO`gc zr1a*E$tE-hDwU&1V*M9=hNmU$vesz}3?+t>^=cC;ktJZ1HWl|O86}Of2dR@x>RP8} z1tTg`B~XRl6*DRuCGN5pX}t9EjqE1Ye-_G1=4DM&M;T*var@Yft&>VHWa-j07-|f( zb{x`{8EOpI>s==nB1@8F%Tg7XapQ>wIPz1tJESe6_;NaE4jO&6TF|(+22+^`Y9}3H?_0-WCn=U_dD{`-y&NfbGc$ z8^C;_2aTj4ZX9M12NRXud4=#HlED~>`X(_@Xr|mut&7emr5WHEDtm@i8+rkqSfSvTXn-)Jlv;ok zo=i3FBKg~81+Ed@> z)AOt2$Hx}ZHdEin)aUa{pTCap>*vP>)3)#3);5;m=hObmXV1&-QJ??o{^{KI$Hm4K z;QzS&=F$7@2Kw`;O^DI$fh^Jd*->jjc%VOt2~tkcSQwRA1aevlR8_4XAA?yMa$3dM zSe(9=i@`@SrcvdFpH(6K4w+rj*?QQvVfk}dqn z5HDK&&k!+!y+)+dCe-QjettV@isbXt`?>cm$1>L@J~t;Fb{>Z9;fg+S5k<3PVO~M) zFG`?;M+=~^A*y?+u^iovNL6F+Q=rlVl1)9FRcAB0d2opLnb-BVB9<`m>qLhXX^HRqo z*uIvHlC}}PEOQ(M_84l6skKbXNUM?7b6xGeGTUsdIm~DygsFB=1O0$jsu8^`b7~0# zN1AzzuHBf&R{D!eb4Mjuu%V8Uy3w`l8LUA}>QPYkph}D2(U(S-3DF>MvVrZ?9eAm0 zh+;NK!?~ET>&_m2o6((BVpHhM6)z+BX@O}SC&XgtLjw#>GozS_hzm7N;ySiTLf5)B zxRV<_XiR!fXjYKF#ITcc`+QMp_%oI)%|kw%Mht=XZpLrv|3j?N8B+i+d>Q$JBVDRCXgn{>HY#z%pNK1B)>_P!C! zR6EcyzduN=P{}ay%(k+3dfXS1g0-ilKTK&5TsWDSU|Rk)KQ2zGMy*147js?C9R)a+aKp-4>SG%rA%6!nhO#lODa(r@z;UGzj9JWf zH|Bq<(V=!iOdj#XR%#R8O8xpnZam7N(FWIM6}bE@|67h0^)({8Cp2s~_(4EBUAEUq ztCj=;4F|&3A3X(Z$_6+%$k{-!BjG@oe17D|P`0{soRZ^W4K(dhL6^gnaGrAlW~jp* zJnCx%HIT!CpSn?Wj5ZP#6|0jZD|(<7&LA_8wSizO!jLgmrczx?dYhSr2Kkv0hYQlB z9j>Iibv6Y996xt(t(*{C_jVKuI>;ZvPAal9qp-@8uqOf5^ajHb8uWR`-;INK_TjvWrHE&pdf{4Y!hM2qs)bWe31Q@d>y*X_h4W}%ju zUzwpeb|N)_IF$s`uFPT_=>_X4HnA5vQMq8_k*k#J2R1Xtm;~h<%;GJ=pE;~ZUKb;}#svZ;Qp`&C2NtnrIbkFy*%_q)m4mGba-!4yEZO zjY->duP2{# z4F(|JXh@vgV7F2uY^nVIb2)604u`Ty0Dc(<>M^#e5@83;;tK7xABU4sG*e=AV*xLP zf={R_i2~2({A+HZO3K|Vyfiq}O|E_6ABYez zy;-2!GXYl?J}C9eOO92n3N}2>MR_fPaN2lIn=vbJ`+?1K7apmGD&{CDZAl5KV^*h=+%2Lq|1dV=d_A=Ix8h=b6BsD1E=x$W1Lxh;+2l|>D zom!4XM9RB}$g*=-@2cqAM=&={;2atlHur>kVpLpXr*oYx!ZtQ>T4ApkszM=4jNvTP zLo?a)642(;I~45(s9JZ>bgv^Bo`x}fOyC3?7<^1p{Vc(a`4bkUv$}>c^-SOx8z9qG zgXruA1Y3;4b(0)FQcv(VNOqOcI5TjJ1`-;fu6~0%gHK{?O4$aqPt1Vix*i*{97$dT zX=UMoXgTx;fd)WA+c|$sBJywA;vJ0BWM-3ondi;_BHA3vFosx5|Hw0%{?%HakrUd) zg%|)jQ@`o>Z*^B6MFtUG{d2tZzM$X0%jSa?tp=={2|ckug;I-2D@xrQ?~}+B7x`B$ z1RDFn*+0)wTp#-8c9^*I9?kOMe9^)UGv;Rw?h_I&6s zWN1V^XjfwG2oGI$oIAwn^+-amuhA(5ao~ArE8;GW^;K73(+U{iHidomIzWqT=E<0sqr;JhZ>!d#Kyf>P>-A@bh2|E<9?o4)$qfTuECDyT9=mrgzfP z^RIp-dDdS?Lq8feiruicwa8uwe=Vf*!swzG}-J3~2*69_*y z2q8X*W1vTZ_~-%;2S-+^%FgJKw%PB2H@E!Se#q+`Fi$7YZt%Skb=TBl+wv8*jMpl` zzUWH=IbxHBzN65DFC*plk#u4DSVUrJw%Xw#B?{V=vnckPjA;ba|y@pc9fu0bQP zH0QN1%k0^3wv(Lw!=7hch>RAXeySLKzW%@)Tnb`c3d)oc044fX#cecyZ-&zUffN}c z^p7^G#WG5-6G}}cw7(!k6Q9pWoUb*JLIT_SzugGyfjB3;p3&#cD#^bs!{Rt|trN5Q z3w#0hZ;1x^EezsF9KeN4{xh|s&mo<#)P2OP5juDp|B=`jO19_A4g$nA6qqNt2rxf< zmtmQhfSJ~jBC8!XLPN4?PDuQ7=fUsC`?6C8onlKXW)CZ?xL*2gjgvYLEv%zTL^F^N zxu4(*ZWcd?bIuv9Z2UTX3k~HrQ^8|B^}qyl_Hx?#FmP@V(6>Mk3vue&aV;BVt;(!z zZ$rUbpV_)`h*jGlP<2RNn*Kis^(w)T>#b6!Cen6G0p4f!&*QH4wPhfF_4#G=oHT*v zaF@dM!d>G~jnh7bh?i*pgVt@U5L z;G%bodcBntjo!jZ2_h~y?gMUW{*I6;uJPkhd;ZAe>PId(7~H3P@7z+WV= zJeMF8%Y{a-4^~o&4iE^bk3@Dy8RQg|AVltJx2({kQr#u~6DdqOkx57aHuYh=QB-}U zy!=Fc=A-rpT$|Qdwr0OVtqDY?miRJ(t<@J*dz;GcErcKk)$Sx2-Ag2OeIivSR<+{| zDfyOA2BsbIdSn;P&MGvg64g#UWxV=Py>@`UiL_#f?*SD=n8L9)DL@m%(23Xds0KpU zkz(~b-N2!)wDZw`O8m;a?_-S{gURA7lW@O3#m`Yc6Btf(+4>@_AchgtbDC8290vR? zUxJp}(gZ_<5ZF+tTri)3iWuL8MAFc4<)%qxD&uoE;m{woe`YYX_ z*zH8p;BjT9fq6*&NIZ-FuZPvKgSA@PvVz$Yl-n8jbaM;ej6Jf;V*3kLqu?DRR_7Q8 z!rUVnsw`DuRD>K+)A#}uNkpPihcSI4XF6#yQHwuvm@piBy#7czW`RbFhGCjV^gyB6 zai+KHh2>UiGVx8sPV|AIhVJ0QB4!~`uKF_5nDFGzDl)CN$GTp0h&mu1gz0}li~mLk z3+ice!sji>d)qUJRd`3uYbTWMiB7;tELRV19K`SiEiaFU`?QYN=0IVGTbi6?f(QEE zq8`Z@_2&yr2hCNv#928K8_XFax`vN19U&eaC5f%9u2kX+U7UBhYWWqhcy12VC&nrf z>g#!-DXfLUY+`58?`G><6oU-3)lXJSiv%2ZxY5=@;(om=C702aDYw{->;Z)|9F9QI zsZ27!9oU3JTz zN(tqp^`;U`Udli1#guRr(#g2q@7iPb$`B9&TlYa$#+)()g|G=U=oyopKZ?fH7#oG{ z(}-ajBHQn^@cEA-!G=|%t1&vMbuJ-n{KJYR0?6R;zZAfM+Mp8?sv6D6KdF5A!GqA8 zC?%E`6Qe`I7Rx$x7g^2F^K+!INHTrJp6`)5)B?5u2R%~+0G)Z^rA2vSYSLzF&$B^v zFm`I;U;z5}ay9agtPI?EeD@Rc8OW`agD@!okf?xBtbn|Wf*7;s+Yk-FgtSryKx;S+ zoR7IkqFJ(9Pme@69L$v(fNIzoRnS)Kx&5>}x<5xseuxJE)czpiC<5o;EZZ4{HI!N? zA{USWAi8)>xMnurkj+?9q3K7-SM9xy=zbS0T8nXLMsQv}^qyGyBb|SQYxo`{&|Dy5FLf8w^`E%@c%JVyz(~rAp3fV!urzCQ_bXu|D(@*KXGK zCUS_08vh`JyUD0^tcY7AV3#f8k2;u_9Jj^O)+ARI zYNlw7*XJo)1O2yJ_`1)H&k0mEuDlW+tiq0C;EsY9i z^e8huGnsbTZiDY_f~8eyTTr2I?Sds=-}v5+n%9Ibh-QoXK5owX{NS)p!ZbeEO!ZMe zF6($Y>ik|_`g&*lHi+i6&Ax?PJs*Z&`M#zBY|8l#&xFzRV2PZ^2l2B-T-U8p(Hh7hWYu0cBemcjc^;J zWxMeCt zrCly~@#E$uy;ZxY$kbfCtX!tZ#kWmJ&&gY9n;z?(HXdy=n%4m&_2~C_V@j0S^TBmF zKbn>!7m<7ZPeb?5^dPBTR06b`NgBzf&kH-;*5yK>EE|8r?yWa_^Q7o<-Wo7O3sgIU zc`(SF1s0~5@SDXGvm#o~`fnOz_h~fMxr}J#GX4zM_I`>Rouct^sw=aq6y{jj2A8G% z<*FlVyhZoMus*z&`Z!{p&}@kOEf}lo)*H?<$69V#Tk26q@9zE{X$phv7s;yJcRZ~Z zH4QO2qze>Nn5K#58-raoXKRjaC-2sGCtznr+1~k+aP8Yd0(DnZ#tI(Rr?kqD&*z5j zNlJEw^5AMQl|7byeD;Ff=Z2IGIqnLbHg{`6pJC2>XW??Mt-4@Np)0{CMkg#P=-12w zJ1i#3d^DyYyqyL3mEwi3Vx10dcu zqx@CF{{NY0uvUuwFviqapa+FD{pHUB>7qzAOn#Qe3g-VTs<99U)I^#_n@Q`Y-U~PW zq9CfiM1>j)UY8ay^+VYPLB{La-)9V4J$k}N?X!J=KHPfwLcjHSdE?9I;0tNt3oBV8Dz%=SJk{!o+WZYZZ@&#_Tz?eK*AfS-3~Y?U zI+9iGaejl!iz=;r*V6Ew&>Nk(9E$jBWH5&QQI!Bf3lsA|quNS+a50rqkfXlSw-L>G z`Qo)Wk`U|HWnz^;*xa(uR_SLBP3??r)n=yvPU}fV~ zrU?g8NTq_6?XPf!n%~asqKtJ{`OKf{#vfIKRUNQ(hn0Ia4x_=7lMU+^y7~7k0y`DQ z5y#I#gr~^eNmVj)+6^1A*Kwym3=NidX5IuVe;vS;1U@=p{2o&GMACd#v0ideN$Z?f zEpdMHWux6#!NLXi#SRsW8EjU>P@9-wQ&2~BoH%*hx9<6_MI>nsiiu^1(a8k6g@qxr zAAfK*SR~ofXwOUet1Mc#8JA6kgI5oifKi`UuQD}GXIzTPGPJj6I?&J2MH=gOs-&ZA zQCmsU?FWTNT{Ab`HzgM`UgRaxmF-R|$pjJeV>%&gm$xxa0fjxY(LO)cqN=H0q}Q~r z3wD#di*U=(fJry7-dCD;Hy3_+QE|h_WuMV+e>HO~6Mm`k#xBLxiSKoCcSNB@owOZE zTY}byLB%&-zkPi$RfuTk$YdaHG6H5GckV5j($6xurmg z3KqrWnvlq$LWDS%Rq^9AIk_^SGemh<;E}F`*ImEDHpcy|%)0#BBF~*%?1Gs))m96i z^hPmz#>i3&pE|<%;_KhbdmCzpkY>~^iK!LqlD^ypYw^}T)Jm5P1UDVx>c}55ytiI% zzh-#J{>}|qu(H+5muXhhem7zDN;7P+&`8NjuC$AMO&fyDFkyjN3n3yk|kW}Vg7m1Ev7H@hqXa^h0bS!+7VmFM9zm!OBg9dN(fS4~!NPq3Ah z-CO&&3nzTlm)D0av`IrK7SwM{FFd`e-4Cx!`8Ip(*C!-5Y`c&nQ`ktt`D!gS(MnZ~ z?n?U#>f$CMAtx#->W;Iou6P!MhIyI;#K1+XOr1jB@>~*3KFnGNUnpCd;YwNLAIuZR z?N%Gp=;WV0IZ!2xH0rS}2@9@;^ZK}jHaW4$f;C8J2`X8nb=2xm!;5zoxOhoQ`c$>* zkfrEHn--4?-dnyQDyIv3za$b}Jw9K(X&J*#C$Y;XnM%6C-CvFAAKl%Qe@O5D#g3If zXXk8KM7$f-&nUH9`(>t&kug#CUVX`F@6jen)gJf#WBr7(jjkwcM4;)!_MHQpwzSlfg+)%4t)SS4lZYL;GEorgX1?eGHE=Y7d zISi5SBt3aCXU3hgjPGlyt9k28i?Q(um$yhg6)c_KLDdCe6hz&@59GO*;ek360z|pc(pF}F1uIGr(L~#3dnthL|_}e+X;>1a6(7JI{ zL7r4qd$;P;N}^-?7Nf`&!8p}Io0zIFIe7+Ku6}^3Qh&qgb(Rd{WP_nPQqf41yEw#N zx}{kY?(?g=$}arqVk%r-_cXTWFAghR#5ow3VAnlKO%nX!ueKrUMd1qu0knAOsRvXxV%95+b~VB2fZF>Rs|L~{ za`K5&vfQsI=AQDXuWDQsWZTv3XCs&2r` z!9IbbF+?<&wy)gE-E z`D;Z?sI{!Ks-$gA_C+jled75|a{1SR*5uOncC+6UP;T5&VG;C!Y5gGzf_(V=%trq_ zLv5{ypDGDGXT;4Q>U)1-k~Jir{cz6hipK3*>Ai~nDA*!KGO z`^6fL&B#iQ^to4K7o18ZsfI5=Ok%i5t`JNIzj}E5f{P zzkwH>(RQ0@Rz@TsZ0sGpbJ6>wl%-xtD(FBFR3{C%o@*|s*j)7(Z;2YjC3;^WoY7*2 zag?65mi*ToQ)ZvDoA$1->S*BD%B|Qns}grJ^w3*ev6C#ov69s({&i^aCAn=cHz zj{-=)geQsJv_db~#QanTbx9a6S1Tv4)~NgY5Ft5t6x$RtWX-%IRN>Awx4|Dhjre;VFT6RjXdlTm1;O-ab0)Hr+@mPt-g zdn$3V`~k9Wro&^7inpke)M|8q%q}C7nwU6k*-)vjQuilHA}N`cJXC&zfz!Ute9@h} zpZgaDWK@02z5+jEs879Z*GTP!M#`EP!53`{! z%O1y?4%-q*>hq&pd(HtP`ykO{pqTOC^n}o>Z`{OXA{jXH={1~n+}ZO_8KNzwEAF;V zqPS)@lQ7n^l|4?g)$-I;W%nlzY61f_45cLQ_HC;zTRPcc$8~E9hGL|{w`~ai3_^DJ z7z~C#2P2OY6QNyZs?j(Ii4b=@dhOb(w%*&(3zB#U?A9F`th?MwazVgik|?qzzn1;P zI5yO=TXFEEAstHzE+h3eAd)P__aPy=XQ*L%)SZ*qmrt5nJ?A$(Z$C!Xy^7!qyu<98-e{cS-z!TFawuT09X)S7W^rs7>qaP%9p9MR*vT>*wSx`a zq;Q344?)zO?GjI&PUkvKd@){kcX_0-uX(zQBRy3>@c+JY_a|C{?fp%0Du&QhFE5>J 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 diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/flags.make b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/flags.make deleted file mode 100644 index 97f3ac41ce..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/flags.make +++ /dev/null @@ -1,10 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 3.25 - -# compile Fortran with /usr/local/bin/gfortran -Fortran_DEFINES = - -Fortran_INCLUDES = -I/Users/afoster/pFUnit/include -I/Users/afoster/pFUnit/mod -I/usr/local/Cellar/netcdf/4.9.2/include -I/usr/local/Cellar/netcdf-fortran/4.6.0/include -I/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ - -Fortran_FLAGS = -DCESMCOUPLED -DFORTRANUNDERSCORE -DNO_R16 -DCPRGNU -fconvert=big-endian -ffree-line-length-none -ffixed-line-length-none -g -Wall -Og -fbacktrace -ffpe-trap=zero,overflow -fcheck=bounds -fallow-argument-mismatch -fallow-invalid-boz -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk - diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fortran.internal b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fortran.internal deleted file mode 100644 index 8030915fe2..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/fortran.internal +++ /dev/null @@ -1,5 +0,0 @@ -# The fortran modules provided by this target. -provides - fatesconstantsmod.mod - fatesunittestiomod.mod - fatesunittestorbitalmod.mod diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/link.txt b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/link.txt deleted file mode 100644 index bac60900c6..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/link.txt +++ /dev/null @@ -1,2 +0,0 @@ -/usr/bin/ar qc libutils.a CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o -/usr/bin/ranlib libutils.a diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o.provides.build b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o.provides.build deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/progress.make b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/progress.make deleted file mode 100644 index fdb0a7b084..0000000000 --- a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/progress.make +++ /dev/null @@ -1,5 +0,0 @@ -CMAKE_PROGRESS_1 = 6 -CMAKE_PROGRESS_2 = 7 -CMAKE_PROGRESS_3 = 8 -CMAKE_PROGRESS_4 = 9 - diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o.provides.build b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o.provides.build deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o.provides.build b/build/__command_line_test__/__command_line_test__/CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o.provides.build deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/build/__command_line_test__/__command_line_test__/CTestTestfile.cmake b/build/__command_line_test__/__command_line_test__/CTestTestfile.cmake deleted file mode 100644 index 2a25e968d2..0000000000 --- a/build/__command_line_test__/__command_line_test__/CTestTestfile.cmake +++ /dev/null @@ -1,9 +0,0 @@ -# CMake generated Testfile for -# Source directory: /Users/afoster/Documents/ncar/CTSM/src/fates -# Build directory: /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ -# -# This file includes the relevant testing commands required for -# testing this directory and lists subdirectories to be tested as well. -subdirs("main") -subdirs("unit_testing/utils") -subdirs("unit_testing/test") diff --git a/build/__command_line_test__/__command_line_test__/Macros.cmake b/build/__command_line_test__/__command_line_test__/Macros.cmake deleted file mode 120000 index d2c6ddac24..0000000000 --- a/build/__command_line_test__/__command_line_test__/Macros.cmake +++ /dev/null @@ -1 +0,0 @@ -/Users/afoster/Documents/ncar/CTSM/src/fates/build/Macros.cmake \ No newline at end of file diff --git a/build/__command_line_test__/__command_line_test__/Makefile b/build/__command_line_test__/__command_line_test__/Makefile deleted file mode 100644 index 261969932c..0000000000 --- a/build/__command_line_test__/__command_line_test__/Makefile +++ /dev/null @@ -1,260 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 3.25 - -# Default target executed when no arguments are given to make. -default_target: all -.PHONY : default_target - -# Allow only one "make -f Makefile2" at a time, but pass parallelism. -.NOTPARALLEL: - -#============================================================================= -# Special targets provided by cmake. - -# Disable implicit rules so canonical targets will work. -.SUFFIXES: - -# Disable VCS-based implicit rules. -% : %,v - -# Disable VCS-based implicit rules. -% : RCS/% - -# Disable VCS-based implicit rules. -% : RCS/%,v - -# Disable VCS-based implicit rules. -% : SCCS/s.% - -# Disable VCS-based implicit rules. -% : s.% - -.SUFFIXES: .hpux_make_needs_suffix_list - -# Command-line flag to silence nested $(MAKE). -$(VERBOSE)MAKESILENT = -s - -#Suppress display of executed commands. -$(VERBOSE).SILENT: - -# A target that is always out of date. -cmake_force: -.PHONY : cmake_force - -#============================================================================= -# Set environment variables for the build. - -# The shell in which to execute make rules. -SHELL = /bin/sh - -# The CMake executable. -CMAKE_COMMAND = /usr/local/Cellar/cmake/3.25.2/bin/cmake - -# The command to remove a file. -RM = /usr/local/Cellar/cmake/3.25.2/bin/cmake -E rm -f - -# Escaping for special characters. -EQUALS = = - -# The top-level source directory on which CMake was run. -CMAKE_SOURCE_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates - -# The top-level build directory on which CMake was run. -CMAKE_BINARY_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ - -#============================================================================= -# Targets provided globally by CMake. - -# Special rule for the target test -test: - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests..." - /usr/local/Cellar/cmake/3.25.2/bin/ctest --force-new-ctest-process $(ARGS) -.PHONY : test - -# Special rule for the target test -test/fast: test -.PHONY : test/fast - -# Special rule for the target edit_cache -edit_cache: - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." - /usr/local/Cellar/cmake/3.25.2/bin/ccmake -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) -.PHONY : edit_cache - -# Special rule for the target edit_cache -edit_cache/fast: edit_cache -.PHONY : edit_cache/fast - -# Special rule for the target rebuild_cache -rebuild_cache: - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." - /usr/local/Cellar/cmake/3.25.2/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) -.PHONY : rebuild_cache - -# Special rule for the target rebuild_cache -rebuild_cache/fast: rebuild_cache -.PHONY : rebuild_cache/fast - -# The main all target -all: cmake_check_build_system - $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__//CMakeFiles/progress.marks - $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 all - $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles 0 -.PHONY : all - -# The main clean target -clean: - $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 clean -.PHONY : clean - -# The main clean target -clean/fast: clean -.PHONY : clean/fast - -# Prepare targets for installation. -preinstall: all - $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall -.PHONY : preinstall - -# Prepare targets for installation. -preinstall/fast: - $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall -.PHONY : preinstall/fast - -# clear depends -depend: - $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 -.PHONY : depend - -#============================================================================= -# Target rules for targets named utils - -# Build rule for target. -utils: cmake_check_build_system - $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 utils -.PHONY : utils - -# fast build rule for target. -utils/fast: - $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/build -.PHONY : utils/fast - -#============================================================================= -# Target rules for targets named FATES_rad_test - -# Build rule for target. -FATES_rad_test: cmake_check_build_system - $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 FATES_rad_test -.PHONY : FATES_rad_test - -# fast build rule for target. -FATES_rad_test/fast: - $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build -.PHONY : FATES_rad_test/fast - -main/FatesConstantsMod.o: main/FatesConstantsMod.F90.o -.PHONY : main/FatesConstantsMod.o - -# target to build an object file -main/FatesConstantsMod.F90.o: - $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/main/FatesConstantsMod.F90.o -.PHONY : main/FatesConstantsMod.F90.o - -main/FatesConstantsMod.i: main/FatesConstantsMod.F90.i -.PHONY : main/FatesConstantsMod.i - -# target to preprocess a source file -main/FatesConstantsMod.F90.i: - $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/main/FatesConstantsMod.F90.i -.PHONY : main/FatesConstantsMod.F90.i - -main/FatesConstantsMod.s: main/FatesConstantsMod.F90.s -.PHONY : main/FatesConstantsMod.s - -# target to generate assembly for a file -main/FatesConstantsMod.F90.s: - $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/main/FatesConstantsMod.F90.s -.PHONY : main/FatesConstantsMod.F90.s - -unit_testing/utils/FatesUnitTestIOMod.o: unit_testing/utils/FatesUnitTestIOMod.F90.o -.PHONY : unit_testing/utils/FatesUnitTestIOMod.o - -# target to build an object file -unit_testing/utils/FatesUnitTestIOMod.F90.o: - $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.o -.PHONY : unit_testing/utils/FatesUnitTestIOMod.F90.o - -unit_testing/utils/FatesUnitTestIOMod.i: unit_testing/utils/FatesUnitTestIOMod.F90.i -.PHONY : unit_testing/utils/FatesUnitTestIOMod.i - -# target to preprocess a source file -unit_testing/utils/FatesUnitTestIOMod.F90.i: - $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.i -.PHONY : unit_testing/utils/FatesUnitTestIOMod.F90.i - -unit_testing/utils/FatesUnitTestIOMod.s: unit_testing/utils/FatesUnitTestIOMod.F90.s -.PHONY : unit_testing/utils/FatesUnitTestIOMod.s - -# target to generate assembly for a file -unit_testing/utils/FatesUnitTestIOMod.F90.s: - $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestIOMod.F90.s -.PHONY : unit_testing/utils/FatesUnitTestIOMod.F90.s - -unit_testing/utils/FatesUnitTestOrbitalMod.o: unit_testing/utils/FatesUnitTestOrbitalMod.F90.o -.PHONY : unit_testing/utils/FatesUnitTestOrbitalMod.o - -# target to build an object file -unit_testing/utils/FatesUnitTestOrbitalMod.F90.o: - $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.o -.PHONY : unit_testing/utils/FatesUnitTestOrbitalMod.F90.o - -unit_testing/utils/FatesUnitTestOrbitalMod.i: unit_testing/utils/FatesUnitTestOrbitalMod.F90.i -.PHONY : unit_testing/utils/FatesUnitTestOrbitalMod.i - -# target to preprocess a source file -unit_testing/utils/FatesUnitTestOrbitalMod.F90.i: - $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.i -.PHONY : unit_testing/utils/FatesUnitTestOrbitalMod.F90.i - -unit_testing/utils/FatesUnitTestOrbitalMod.s: unit_testing/utils/FatesUnitTestOrbitalMod.F90.s -.PHONY : unit_testing/utils/FatesUnitTestOrbitalMod.s - -# target to generate assembly for a file -unit_testing/utils/FatesUnitTestOrbitalMod.F90.s: - $(MAKE) $(MAKESILENT) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/unit_testing/utils/FatesUnitTestOrbitalMod.F90.s -.PHONY : unit_testing/utils/FatesUnitTestOrbitalMod.F90.s - -# Help Target -help: - @echo "The following are some of the valid targets for this Makefile:" - @echo "... all (the default if no target is provided)" - @echo "... clean" - @echo "... depend" - @echo "... edit_cache" - @echo "... rebuild_cache" - @echo "... test" - @echo "... FATES_rad_test" - @echo "... utils" - @echo "... main/FatesConstantsMod.o" - @echo "... main/FatesConstantsMod.i" - @echo "... main/FatesConstantsMod.s" - @echo "... unit_testing/utils/FatesUnitTestIOMod.o" - @echo "... unit_testing/utils/FatesUnitTestIOMod.i" - @echo "... unit_testing/utils/FatesUnitTestIOMod.s" - @echo "... unit_testing/utils/FatesUnitTestOrbitalMod.o" - @echo "... unit_testing/utils/FatesUnitTestOrbitalMod.i" - @echo "... unit_testing/utils/FatesUnitTestOrbitalMod.s" -.PHONY : help - - - -#============================================================================= -# Special targets to cleanup operation of make. - -# Special rule to run CMake to check the build system integrity. -# No rule that depends on this can have commands that come from listfiles -# because they might be regenerated. -cmake_check_build_system: - $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 -.PHONY : cmake_check_build_system - diff --git a/build/__command_line_test__/__command_line_test__/cmake_install.cmake b/build/__command_line_test__/__command_line_test__/cmake_install.cmake deleted file mode 100644 index c8099b8c37..0000000000 --- a/build/__command_line_test__/__command_line_test__/cmake_install.cmake +++ /dev/null @@ -1,57 +0,0 @@ -# Install script for directory: /Users/afoster/Documents/ncar/CTSM/src/fates - -# Set the install prefix -if(NOT DEFINED CMAKE_INSTALL_PREFIX) - set(CMAKE_INSTALL_PREFIX "/usr/local") -endif() -string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") - -# Set the install configuration name. -if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - if(BUILD_TYPE) - string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" - CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") - else() - set(CMAKE_INSTALL_CONFIG_NAME "CESM_DEBUG") - endif() - message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") -endif() - -# Set the component getting installed. -if(NOT CMAKE_INSTALL_COMPONENT) - if(COMPONENT) - message(STATUS "Install component: \"${COMPONENT}\"") - set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") - else() - set(CMAKE_INSTALL_COMPONENT) - endif() -endif() - -# Is this installation the result of a crosscompile? -if(NOT DEFINED CMAKE_CROSSCOMPILING) - set(CMAKE_CROSSCOMPILING "FALSE") -endif() - -# Set default install directory permissions. -if(NOT DEFINED CMAKE_OBJDUMP) - set(CMAKE_OBJDUMP "/usr/bin/objdump") -endif() - -if(NOT CMAKE_INSTALL_LOCAL_ONLY) - # Include the install script for each subdirectory. - include("/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/main/cmake_install.cmake") - include("/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/utils/cmake_install.cmake") - include("/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/cmake_install.cmake") - -endif() - -if(CMAKE_INSTALL_COMPONENT) - set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") -else() - set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") -endif() - -string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT - "${CMAKE_INSTALL_MANIFEST_FILES}") -file(WRITE "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/${CMAKE_INSTALL_MANIFEST}" - "${CMAKE_INSTALL_MANIFEST_CONTENT}") diff --git a/build/__command_line_test__/__command_line_test__/libutils.a b/build/__command_line_test__/__command_line_test__/libutils.a deleted file mode 100644 index 801611e8e9d8fa8e4ac2679e58fcaf3a36e6b717..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40264 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 UQt6UH7tf~(w7seEn0G4wA0CJvng9R* diff --git a/build/__command_line_test__/__command_line_test__/main/CMakeFiles/CMakeDirectoryInformation.cmake b/build/__command_line_test__/__command_line_test__/main/CMakeFiles/CMakeDirectoryInformation.cmake deleted file mode 100644 index 0626f191b1..0000000000 --- a/build/__command_line_test__/__command_line_test__/main/CMakeFiles/CMakeDirectoryInformation.cmake +++ /dev/null @@ -1,16 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 3.25 - -# Relative path conversion top directories. -set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/Users/afoster/Documents/ncar/CTSM/src/fates") -set(CMAKE_RELATIVE_PATH_TOP_BINARY "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__") - -# Force unix paths in dependencies. -set(CMAKE_FORCE_UNIX_PATHS 1) - - -# The C and CXX include file regular expressions for this directory. -set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") -set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") -set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) -set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/build/__command_line_test__/__command_line_test__/main/CMakeFiles/progress.marks b/build/__command_line_test__/__command_line_test__/main/CMakeFiles/progress.marks deleted file mode 100644 index 573541ac97..0000000000 --- a/build/__command_line_test__/__command_line_test__/main/CMakeFiles/progress.marks +++ /dev/null @@ -1 +0,0 @@ -0 diff --git a/build/__command_line_test__/__command_line_test__/main/CTestTestfile.cmake b/build/__command_line_test__/__command_line_test__/main/CTestTestfile.cmake deleted file mode 100644 index 09d92f9199..0000000000 --- a/build/__command_line_test__/__command_line_test__/main/CTestTestfile.cmake +++ /dev/null @@ -1,6 +0,0 @@ -# CMake generated Testfile for -# Source directory: /Users/afoster/Documents/ncar/CTSM/src/fates/main -# Build directory: /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/main -# -# This file includes the relevant testing commands required for -# testing this directory and lists subdirectories to be tested as well. diff --git a/build/__command_line_test__/__command_line_test__/main/Makefile b/build/__command_line_test__/__command_line_test__/main/Makefile deleted file mode 100644 index c0af35d7b3..0000000000 --- a/build/__command_line_test__/__command_line_test__/main/Makefile +++ /dev/null @@ -1,151 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 3.25 - -# Default target executed when no arguments are given to make. -default_target: all -.PHONY : default_target - -# Allow only one "make -f Makefile2" at a time, but pass parallelism. -.NOTPARALLEL: - -#============================================================================= -# Special targets provided by cmake. - -# Disable implicit rules so canonical targets will work. -.SUFFIXES: - -# Disable VCS-based implicit rules. -% : %,v - -# Disable VCS-based implicit rules. -% : RCS/% - -# Disable VCS-based implicit rules. -% : RCS/%,v - -# Disable VCS-based implicit rules. -% : SCCS/s.% - -# Disable VCS-based implicit rules. -% : s.% - -.SUFFIXES: .hpux_make_needs_suffix_list - -# Command-line flag to silence nested $(MAKE). -$(VERBOSE)MAKESILENT = -s - -#Suppress display of executed commands. -$(VERBOSE).SILENT: - -# A target that is always out of date. -cmake_force: -.PHONY : cmake_force - -#============================================================================= -# Set environment variables for the build. - -# The shell in which to execute make rules. -SHELL = /bin/sh - -# The CMake executable. -CMAKE_COMMAND = /usr/local/Cellar/cmake/3.25.2/bin/cmake - -# The command to remove a file. -RM = /usr/local/Cellar/cmake/3.25.2/bin/cmake -E rm -f - -# Escaping for special characters. -EQUALS = = - -# The top-level source directory on which CMake was run. -CMAKE_SOURCE_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates - -# The top-level build directory on which CMake was run. -CMAKE_BINARY_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ - -#============================================================================= -# Targets provided globally by CMake. - -# Special rule for the target test -test: - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests..." - /usr/local/Cellar/cmake/3.25.2/bin/ctest --force-new-ctest-process $(ARGS) -.PHONY : test - -# Special rule for the target test -test/fast: test -.PHONY : test/fast - -# Special rule for the target edit_cache -edit_cache: - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." - /usr/local/Cellar/cmake/3.25.2/bin/ccmake -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) -.PHONY : edit_cache - -# Special rule for the target edit_cache -edit_cache/fast: edit_cache -.PHONY : edit_cache/fast - -# Special rule for the target rebuild_cache -rebuild_cache: - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." - /usr/local/Cellar/cmake/3.25.2/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) -.PHONY : rebuild_cache - -# Special rule for the target rebuild_cache -rebuild_cache/fast: rebuild_cache -.PHONY : rebuild_cache/fast - -# The main all target -all: cmake_check_build_system - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/main//CMakeFiles/progress.marks - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 main/all - $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles 0 -.PHONY : all - -# The main clean target -clean: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 main/clean -.PHONY : clean - -# The main clean target -clean/fast: clean -.PHONY : clean/fast - -# Prepare targets for installation. -preinstall: all - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 main/preinstall -.PHONY : preinstall - -# Prepare targets for installation. -preinstall/fast: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 main/preinstall -.PHONY : preinstall/fast - -# clear depends -depend: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 -.PHONY : depend - -# Help Target -help: - @echo "The following are some of the valid targets for this Makefile:" - @echo "... all (the default if no target is provided)" - @echo "... clean" - @echo "... depend" - @echo "... edit_cache" - @echo "... rebuild_cache" - @echo "... test" -.PHONY : help - - - -#============================================================================= -# Special targets to cleanup operation of make. - -# Special rule to run CMake to check the build system integrity. -# No rule that depends on this can have commands that come from listfiles -# because they might be regenerated. -cmake_check_build_system: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 -.PHONY : cmake_check_build_system - diff --git a/build/__command_line_test__/__command_line_test__/main/cmake_install.cmake b/build/__command_line_test__/__command_line_test__/main/cmake_install.cmake deleted file mode 100644 index 930efcb765..0000000000 --- a/build/__command_line_test__/__command_line_test__/main/cmake_install.cmake +++ /dev/null @@ -1,39 +0,0 @@ -# Install script for directory: /Users/afoster/Documents/ncar/CTSM/src/fates/main - -# Set the install prefix -if(NOT DEFINED CMAKE_INSTALL_PREFIX) - set(CMAKE_INSTALL_PREFIX "/usr/local") -endif() -string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") - -# Set the install configuration name. -if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - if(BUILD_TYPE) - string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" - CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") - else() - set(CMAKE_INSTALL_CONFIG_NAME "CESM_DEBUG") - endif() - message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") -endif() - -# Set the component getting installed. -if(NOT CMAKE_INSTALL_COMPONENT) - if(COMPONENT) - message(STATUS "Install component: \"${COMPONENT}\"") - set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") - else() - set(CMAKE_INSTALL_COMPONENT) - endif() -endif() - -# Is this installation the result of a crosscompile? -if(NOT DEFINED CMAKE_CROSSCOMPILING) - set(CMAKE_CROSSCOMPILING "FALSE") -endif() - -# Set default install directory permissions. -if(NOT DEFINED CMAKE_OBJDUMP) - set(CMAKE_OBJDUMP "/usr/bin/objdump") -endif() - diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/CMakeFiles/CMakeDirectoryInformation.cmake b/build/__command_line_test__/__command_line_test__/unit_testing/test/CMakeFiles/CMakeDirectoryInformation.cmake deleted file mode 100644 index 0626f191b1..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/test/CMakeFiles/CMakeDirectoryInformation.cmake +++ /dev/null @@ -1,16 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 3.25 - -# Relative path conversion top directories. -set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/Users/afoster/Documents/ncar/CTSM/src/fates") -set(CMAKE_RELATIVE_PATH_TOP_BINARY "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__") - -# Force unix paths in dependencies. -set(CMAKE_FORCE_UNIX_PATHS 1) - - -# The C and CXX include file regular expressions for this directory. -set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") -set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") -set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) -set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/CMakeFiles/progress.marks b/build/__command_line_test__/__command_line_test__/unit_testing/test/CMakeFiles/progress.marks deleted file mode 100644 index 7ed6ff82de..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/test/CMakeFiles/progress.marks +++ /dev/null @@ -1 +0,0 @@ -5 diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/CTestTestfile.cmake b/build/__command_line_test__/__command_line_test__/unit_testing/test/CTestTestfile.cmake deleted file mode 100644 index 9ed9c2cf62..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/test/CTestTestfile.cmake +++ /dev/null @@ -1,7 +0,0 @@ -# CMake generated Testfile for -# Source directory: /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test -# Build directory: /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test -# -# This file includes the relevant testing commands required for -# testing this directory and lists subdirectories to be tested as well. -subdirs("radiation_test") diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/Makefile b/build/__command_line_test__/__command_line_test__/unit_testing/test/Makefile deleted file mode 100644 index 3b163f0e65..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/test/Makefile +++ /dev/null @@ -1,151 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 3.25 - -# Default target executed when no arguments are given to make. -default_target: all -.PHONY : default_target - -# Allow only one "make -f Makefile2" at a time, but pass parallelism. -.NOTPARALLEL: - -#============================================================================= -# Special targets provided by cmake. - -# Disable implicit rules so canonical targets will work. -.SUFFIXES: - -# Disable VCS-based implicit rules. -% : %,v - -# Disable VCS-based implicit rules. -% : RCS/% - -# Disable VCS-based implicit rules. -% : RCS/%,v - -# Disable VCS-based implicit rules. -% : SCCS/s.% - -# Disable VCS-based implicit rules. -% : s.% - -.SUFFIXES: .hpux_make_needs_suffix_list - -# Command-line flag to silence nested $(MAKE). -$(VERBOSE)MAKESILENT = -s - -#Suppress display of executed commands. -$(VERBOSE).SILENT: - -# A target that is always out of date. -cmake_force: -.PHONY : cmake_force - -#============================================================================= -# Set environment variables for the build. - -# The shell in which to execute make rules. -SHELL = /bin/sh - -# The CMake executable. -CMAKE_COMMAND = /usr/local/Cellar/cmake/3.25.2/bin/cmake - -# The command to remove a file. -RM = /usr/local/Cellar/cmake/3.25.2/bin/cmake -E rm -f - -# Escaping for special characters. -EQUALS = = - -# The top-level source directory on which CMake was run. -CMAKE_SOURCE_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates - -# The top-level build directory on which CMake was run. -CMAKE_BINARY_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ - -#============================================================================= -# Targets provided globally by CMake. - -# Special rule for the target test -test: - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests..." - /usr/local/Cellar/cmake/3.25.2/bin/ctest --force-new-ctest-process $(ARGS) -.PHONY : test - -# Special rule for the target test -test/fast: test -.PHONY : test/fast - -# Special rule for the target edit_cache -edit_cache: - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." - /usr/local/Cellar/cmake/3.25.2/bin/ccmake -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) -.PHONY : edit_cache - -# Special rule for the target edit_cache -edit_cache/fast: edit_cache -.PHONY : edit_cache/fast - -# Special rule for the target rebuild_cache -rebuild_cache: - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." - /usr/local/Cellar/cmake/3.25.2/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) -.PHONY : rebuild_cache - -# Special rule for the target rebuild_cache -rebuild_cache/fast: rebuild_cache -.PHONY : rebuild_cache/fast - -# The main all target -all: cmake_check_build_system - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test//CMakeFiles/progress.marks - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/test/all - $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles 0 -.PHONY : all - -# The main clean target -clean: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/test/clean -.PHONY : clean - -# The main clean target -clean/fast: clean -.PHONY : clean/fast - -# Prepare targets for installation. -preinstall: all - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/test/preinstall -.PHONY : preinstall - -# Prepare targets for installation. -preinstall/fast: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/test/preinstall -.PHONY : preinstall/fast - -# clear depends -depend: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 -.PHONY : depend - -# Help Target -help: - @echo "The following are some of the valid targets for this Makefile:" - @echo "... all (the default if no target is provided)" - @echo "... clean" - @echo "... depend" - @echo "... edit_cache" - @echo "... rebuild_cache" - @echo "... test" -.PHONY : help - - - -#============================================================================= -# Special targets to cleanup operation of make. - -# Special rule to run CMake to check the build system integrity. -# No rule that depends on this can have commands that come from listfiles -# because they might be regenerated. -cmake_check_build_system: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 -.PHONY : cmake_check_build_system - diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/cmake_install.cmake b/build/__command_line_test__/__command_line_test__/unit_testing/test/cmake_install.cmake deleted file mode 100644 index 6b3c9fb0cc..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/test/cmake_install.cmake +++ /dev/null @@ -1,45 +0,0 @@ -# Install script for directory: /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test - -# Set the install prefix -if(NOT DEFINED CMAKE_INSTALL_PREFIX) - set(CMAKE_INSTALL_PREFIX "/usr/local") -endif() -string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") - -# Set the install configuration name. -if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - if(BUILD_TYPE) - string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" - CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") - else() - set(CMAKE_INSTALL_CONFIG_NAME "CESM_DEBUG") - endif() - message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") -endif() - -# Set the component getting installed. -if(NOT CMAKE_INSTALL_COMPONENT) - if(COMPONENT) - message(STATUS "Install component: \"${COMPONENT}\"") - set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") - else() - set(CMAKE_INSTALL_COMPONENT) - endif() -endif() - -# Is this installation the result of a crosscompile? -if(NOT DEFINED CMAKE_CROSSCOMPILING) - set(CMAKE_CROSSCOMPILING "FALSE") -endif() - -# Set default install directory permissions. -if(NOT DEFINED CMAKE_OBJDUMP) - set(CMAKE_OBJDUMP "/usr/bin/objdump") -endif() - -if(NOT CMAKE_INSTALL_LOCAL_ONLY) - # Include the install script for each subdirectory. - include("/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/cmake_install.cmake") - -endif() - diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/CMakeDirectoryInformation.cmake b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/CMakeDirectoryInformation.cmake deleted file mode 100644 index 0626f191b1..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/CMakeDirectoryInformation.cmake +++ /dev/null @@ -1,16 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 3.25 - -# Relative path conversion top directories. -set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/Users/afoster/Documents/ncar/CTSM/src/fates") -set(CMAKE_RELATIVE_PATH_TOP_BINARY "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__") - -# Force unix paths in dependencies. -set(CMAKE_FORCE_UNIX_PATHS 1) - - -# The C and CXX include file regular expressions for this directory. -set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") -set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") -set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) -set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/DependInfo.cmake b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/DependInfo.cmake deleted file mode 100644 index 61a4a7133c..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/DependInfo.cmake +++ /dev/null @@ -1,37 +0,0 @@ - -# Consider dependencies only in project. -set(CMAKE_DEPENDS_IN_PROJECT_ONLY OFF) - -# The set of languages for which implicit dependencies are needed: -set(CMAKE_DEPENDS_LANGUAGES - "Fortran" - ) -# The set of files for implicit dependencies of each language: -set(CMAKE_DEPENDS_CHECK_Fortran - "/Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/radiation_test/FatesUnitTestRadiation.F90" "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o" - "/Users/afoster/Documents/ncar/CTSM/src/fates/main/FatesConstantsMod.F90" "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o" - "/Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestIOMod.F90" "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o" - "/Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestOrbitalMod.F90" "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o" - ) -set(CMAKE_Fortran_COMPILER_ID "GNU") -set(CMAKE_Fortran_SUBMODULE_SEP "@") -set(CMAKE_Fortran_SUBMODULE_EXT ".smod") - -# The include file search paths: -set(CMAKE_Fortran_TARGET_INCLUDE_PATH - "/Users/afoster/pFUnit/include" - "/Users/afoster/pFUnit/mod" - "/usr/local/Cellar/netcdf/4.9.2/include" - "/usr/local/Cellar/netcdf-fortran/4.6.0/include" - ) - -# The set of dependency files which are needed: -set(CMAKE_DEPENDS_DEPENDENCY_FILES - ) - -# Targets to which this target links. -set(CMAKE_TARGET_LINKED_INFO_FILES - ) - -# Fortran module output directory. -set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o.provides.build b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o.provides.build deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o.provides.build b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o.provides.build deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o.provides.build b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o.provides.build deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make deleted file mode 100644 index 7149be51cf..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make +++ /dev/null @@ -1,154 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 3.25 - -# Delete rule output on recipe failure. -.DELETE_ON_ERROR: - -#============================================================================= -# Special targets provided by cmake. - -# Disable implicit rules so canonical targets will work. -.SUFFIXES: - -# Disable VCS-based implicit rules. -% : %,v - -# Disable VCS-based implicit rules. -% : RCS/% - -# Disable VCS-based implicit rules. -% : RCS/%,v - -# Disable VCS-based implicit rules. -% : SCCS/s.% - -# Disable VCS-based implicit rules. -% : s.% - -.SUFFIXES: .hpux_make_needs_suffix_list - -# Command-line flag to silence nested $(MAKE). -$(VERBOSE)MAKESILENT = -s - -#Suppress display of executed commands. -$(VERBOSE).SILENT: - -# A target that is always out of date. -cmake_force: -.PHONY : cmake_force - -#============================================================================= -# Set environment variables for the build. - -# The shell in which to execute make rules. -SHELL = /bin/sh - -# The CMake executable. -CMAKE_COMMAND = /usr/local/Cellar/cmake/3.25.2/bin/cmake - -# The command to remove a file. -RM = /usr/local/Cellar/cmake/3.25.2/bin/cmake -E rm -f - -# Escaping for special characters. -EQUALS = = - -# The top-level source directory on which CMake was run. -CMAKE_SOURCE_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates - -# The top-level build directory on which CMake was run. -CMAKE_BINARY_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ - -# Include any dependencies generated for this target. -include unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/depend.make -# Include any dependencies generated by the compiler for this target. -include unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/compiler_depend.make - -# Include the progress variables for this target. -include unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/progress.make - -# Include the compile flags for this target's objects. -include unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/flags.make - -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/flags.make -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o: /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/radiation_test/FatesUnitTestRadiation.F90 - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building Fortran object unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o" - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -c /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/radiation_test/FatesUnitTestRadiation.F90 -o CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o - -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.i: cmake_force - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing Fortran source to CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.i" - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -E /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/radiation_test/FatesUnitTestRadiation.F90 > CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.i - -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.s: cmake_force - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling Fortran source to assembly CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.s" - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -S /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/radiation_test/FatesUnitTestRadiation.F90 -o CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.s - -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/flags.make -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o: /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestIOMod.F90 - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Building Fortran object unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o" - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -c /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestIOMod.F90 -o CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o - -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.i: cmake_force - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing Fortran source to CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.i" - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -E /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestIOMod.F90 > CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.i - -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.s: cmake_force - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling Fortran source to assembly CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.s" - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -S /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestIOMod.F90 -o CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.s - -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/flags.make -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o: /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestOrbitalMod.F90 - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles --progress-num=$(CMAKE_PROGRESS_3) "Building Fortran object unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o" - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -c /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestOrbitalMod.F90 -o CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o - -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.i: cmake_force - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing Fortran source to CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.i" - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -E /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestOrbitalMod.F90 > CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.i - -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.s: cmake_force - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling Fortran source to assembly CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.s" - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -S /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestOrbitalMod.F90 -o CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.s - -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/flags.make -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o: /Users/afoster/Documents/ncar/CTSM/src/fates/main/FatesConstantsMod.F90 - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles --progress-num=$(CMAKE_PROGRESS_4) "Building Fortran object unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o" - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -c /Users/afoster/Documents/ncar/CTSM/src/fates/main/FatesConstantsMod.F90 -o CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o - -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.i: cmake_force - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing Fortran source to CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.i" - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -E /Users/afoster/Documents/ncar/CTSM/src/fates/main/FatesConstantsMod.F90 > CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.i - -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.s: cmake_force - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling Fortran source to assembly CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.s" - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && /usr/local/bin/gfortran $(Fortran_DEFINES) $(Fortran_INCLUDES) $(Fortran_FLAGS) -S /Users/afoster/Documents/ncar/CTSM/src/fates/main/FatesConstantsMod.F90 -o CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.s - -# Object files for target FATES_rad_test -FATES_rad_test_OBJECTS = \ -"CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o" \ -"CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o" \ -"CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o" \ -"CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o" - -# External object files for target FATES_rad_test -FATES_rad_test_EXTERNAL_OBJECTS = - -unit_testing/test/radiation_test/FATES_rad_test: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o -unit_testing/test/radiation_test/FATES_rad_test: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o -unit_testing/test/radiation_test/FATES_rad_test: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o -unit_testing/test/radiation_test/FATES_rad_test: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o -unit_testing/test/radiation_test/FATES_rad_test: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make -unit_testing/test/radiation_test/FATES_rad_test: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/link.txt - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles --progress-num=$(CMAKE_PROGRESS_5) "Linking Fortran executable FATES_rad_test" - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/FATES_rad_test.dir/link.txt --verbose=$(VERBOSE) - -# Rule to build all files generated by this target. -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build: unit_testing/test/radiation_test/FATES_rad_test -.PHONY : unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build - -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/clean: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test && $(CMAKE_COMMAND) -P CMakeFiles/FATES_rad_test.dir/cmake_clean.cmake -.PHONY : unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/clean - -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/depend: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /Users/afoster/Documents/ncar/CTSM/src/fates /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/radiation_test /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/DependInfo.cmake --color=$(COLOR) -.PHONY : unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/depend - diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/cmake_clean.cmake b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/cmake_clean.cmake deleted file mode 100644 index 6b7063ba42..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/cmake_clean.cmake +++ /dev/null @@ -1,13 +0,0 @@ -file(REMOVE_RECURSE - "CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o" - "CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o" - "CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o" - "CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o" - "FATES_rad_test" - "FATES_rad_test.pdb" -) - -# Per-language clean rules from dependency scanning. -foreach(lang Fortran) - include(CMakeFiles/FATES_rad_test.dir/cmake_clean_${lang}.cmake OPTIONAL) -endforeach() diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/cmake_clean_Fortran.cmake b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/cmake_clean_Fortran.cmake deleted file mode 100644 index bd62e20bc8..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/cmake_clean_Fortran.cmake +++ /dev/null @@ -1,14 +0,0 @@ -# Remove fortran modules provided by this target. -FILE(REMOVE - "fatesconstantsmod.mod" - "FATESCONSTANTSMOD.mod" - "CMakeFiles/FATES_rad_test.dir/fatesconstantsmod.mod.stamp" - - "fatesunittestiomod.mod" - "FATESUNITTESTIOMOD.mod" - "CMakeFiles/FATES_rad_test.dir/fatesunittestiomod.mod.stamp" - - "fatesunittestorbitalmod.mod" - "FATESUNITTESTORBITALMOD.mod" - "CMakeFiles/FATES_rad_test.dir/fatesunittestorbitalmod.mod.stamp" - ) diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/compiler_depend.make b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/compiler_depend.make deleted file mode 100644 index 80afc53fef..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/compiler_depend.make +++ /dev/null @@ -1,2 +0,0 @@ -# Empty compiler generated dependencies file for FATES_rad_test. -# This may be replaced when dependencies are built. diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/compiler_depend.ts b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/compiler_depend.ts deleted file mode 100644 index 57ac27d1ed..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/compiler_depend.ts +++ /dev/null @@ -1,2 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Timestamp file for compiler generated dependencies management for FATES_rad_test. diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/depend.internal b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/depend.internal deleted file mode 100644 index 46ca19ac45..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/depend.internal +++ /dev/null @@ -1,11 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 3.25 - -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o - /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/radiation_test/FatesUnitTestRadiation.F90 -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o - /Users/afoster/Documents/ncar/CTSM/src/fates/main/FatesConstantsMod.F90 -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o - /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestIOMod.F90 -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o - /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils/FatesUnitTestOrbitalMod.F90 diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/depend.make b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/depend.make deleted file mode 100644 index daa358a424..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/depend.make +++ /dev/null @@ -1,27 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 3.25 - -# Note that incremental build could trigger a call to cmake_copy_f90_mod on each re-build -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestiomod.mod.stamp -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestorbitalmod.mod.stamp -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o.provides.build: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesconstantsmod.mod.stamp -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesconstantsmod.mod.stamp: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o - $(CMAKE_COMMAND) -E cmake_copy_f90_mod unit_testing/test/radiation_test/fatesconstantsmod.mod unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesconstantsmod.mod.stamp GNU -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o.provides.build: - $(CMAKE_COMMAND) -E touch unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o.provides.build -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o.provides.build -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesconstantsmod.mod.stamp -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o: /usr/local/Cellar/netcdf-fortran/4.6.0/include/netcdf.mod -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o.provides.build: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestiomod.mod.stamp -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestiomod.mod.stamp: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o - $(CMAKE_COMMAND) -E cmake_copy_f90_mod unit_testing/test/radiation_test/fatesunittestiomod.mod unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestiomod.mod.stamp GNU -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o.provides.build: - $(CMAKE_COMMAND) -E touch unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o.provides.build -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o.provides.build -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestiomod.mod.stamp -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o.provides.build: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestorbitalmod.mod.stamp -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestorbitalmod.mod.stamp: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o - $(CMAKE_COMMAND) -E cmake_copy_f90_mod unit_testing/test/radiation_test/fatesunittestorbitalmod.mod unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestorbitalmod.mod.stamp GNU -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o.provides.build: - $(CMAKE_COMMAND) -E touch unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o.provides.build -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o.provides.build diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesconstantsmod.mod.stamp b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesconstantsmod.mod.stamp deleted file mode 100644 index 2b4ac0b598d43fed2ea70fd8680dacf9fc821b43..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2256 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 diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestiomod.mod.stamp b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestiomod.mod.stamp deleted file mode 100644 index bac5e8f68dbed86771ad6e160e953b2ced9f2e29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24087 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 P!!w~bQoeT*Pci-nwC<&` diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestorbitalmod.mod.stamp b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fatesunittestorbitalmod.mod.stamp deleted file mode 100644 index cb85e3a79588da53be704d893829e4e21f8807ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25076 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%0Du&QhFE5>J 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 diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/flags.make b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/flags.make deleted file mode 100644 index 0dcb8e6e9a..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/flags.make +++ /dev/null @@ -1,10 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 3.25 - -# compile Fortran with /usr/local/bin/gfortran -Fortran_DEFINES = - -Fortran_INCLUDES = -I/Users/afoster/pFUnit/include -I/Users/afoster/pFUnit/mod -I/usr/local/Cellar/netcdf/4.9.2/include -I/usr/local/Cellar/netcdf-fortran/4.6.0/include - -Fortran_FLAGS = -DCESMCOUPLED -DFORTRANUNDERSCORE -DNO_R16 -DCPRGNU -fconvert=big-endian -ffree-line-length-none -ffixed-line-length-none -g -Wall -Og -fbacktrace -ffpe-trap=zero,overflow -fcheck=bounds -fallow-argument-mismatch -fallow-invalid-boz -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk - diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fortran.internal b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fortran.internal deleted file mode 100644 index 8030915fe2..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/fortran.internal +++ /dev/null @@ -1,5 +0,0 @@ -# The fortran modules provided by this target. -provides - fatesconstantsmod.mod - fatesunittestiomod.mod - fatesunittestorbitalmod.mod diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/link.txt b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/link.txt deleted file mode 100644 index 2d1f965f41..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/link.txt +++ /dev/null @@ -1 +0,0 @@ -/usr/local/bin/gfortran -framework Accelerate -DCESMCOUPLED -DFORTRANUNDERSCORE -DNO_R16 -DCPRGNU -fconvert=big-endian -ffree-line-length-none -ffixed-line-length-none -g -Wall -Og -fbacktrace -ffpe-trap=zero,overflow -fcheck=bounds -fallow-argument-mismatch -fallow-invalid-boz -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o -o FATES_rad_test -L/usr/local/Cellar/netcdf/4.9.2/lib -L/usr/local/Cellar/netcdf-fortran/4.6.0/lib diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/progress.make b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/progress.make deleted file mode 100644 index 33e6bffba3..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/progress.make +++ /dev/null @@ -1,6 +0,0 @@ -CMAKE_PROGRESS_1 = 1 -CMAKE_PROGRESS_2 = 2 -CMAKE_PROGRESS_3 = 3 -CMAKE_PROGRESS_4 = 4 -CMAKE_PROGRESS_5 = 5 - diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/progress.marks b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/progress.marks deleted file mode 100644 index 7ed6ff82de..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CMakeFiles/progress.marks +++ /dev/null @@ -1 +0,0 @@ -5 diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CTestTestfile.cmake b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CTestTestfile.cmake deleted file mode 100644 index cb5f7e2cb4..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/CTestTestfile.cmake +++ /dev/null @@ -1,8 +0,0 @@ -# CMake generated Testfile for -# Source directory: /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/radiation_test -# Build directory: /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test -# -# This file includes the relevant testing commands required for -# testing this directory and lists subdirectories to be tested as well. -add_test(rad_test "FATES_rad_test") -set_tests_properties(rad_test PROPERTIES _BACKTRACE_TRIPLES "/Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/radiation_test/CMakeLists.txt;37;add_test;/Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/radiation_test/CMakeLists.txt;0;") diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/Makefile b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/Makefile deleted file mode 100644 index f12b8509d6..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/Makefile +++ /dev/null @@ -1,274 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 3.25 - -# Default target executed when no arguments are given to make. -default_target: all -.PHONY : default_target - -# Allow only one "make -f Makefile2" at a time, but pass parallelism. -.NOTPARALLEL: - -#============================================================================= -# Special targets provided by cmake. - -# Disable implicit rules so canonical targets will work. -.SUFFIXES: - -# Disable VCS-based implicit rules. -% : %,v - -# Disable VCS-based implicit rules. -% : RCS/% - -# Disable VCS-based implicit rules. -% : RCS/%,v - -# Disable VCS-based implicit rules. -% : SCCS/s.% - -# Disable VCS-based implicit rules. -% : s.% - -.SUFFIXES: .hpux_make_needs_suffix_list - -# Command-line flag to silence nested $(MAKE). -$(VERBOSE)MAKESILENT = -s - -#Suppress display of executed commands. -$(VERBOSE).SILENT: - -# A target that is always out of date. -cmake_force: -.PHONY : cmake_force - -#============================================================================= -# Set environment variables for the build. - -# The shell in which to execute make rules. -SHELL = /bin/sh - -# The CMake executable. -CMAKE_COMMAND = /usr/local/Cellar/cmake/3.25.2/bin/cmake - -# The command to remove a file. -RM = /usr/local/Cellar/cmake/3.25.2/bin/cmake -E rm -f - -# Escaping for special characters. -EQUALS = = - -# The top-level source directory on which CMake was run. -CMAKE_SOURCE_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates - -# The top-level build directory on which CMake was run. -CMAKE_BINARY_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ - -#============================================================================= -# Targets provided globally by CMake. - -# Special rule for the target test -test: - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests..." - /usr/local/Cellar/cmake/3.25.2/bin/ctest --force-new-ctest-process $(ARGS) -.PHONY : test - -# Special rule for the target test -test/fast: test -.PHONY : test/fast - -# Special rule for the target edit_cache -edit_cache: - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." - /usr/local/Cellar/cmake/3.25.2/bin/ccmake -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) -.PHONY : edit_cache - -# Special rule for the target edit_cache -edit_cache/fast: edit_cache -.PHONY : edit_cache/fast - -# Special rule for the target rebuild_cache -rebuild_cache: - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." - /usr/local/Cellar/cmake/3.25.2/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) -.PHONY : rebuild_cache - -# Special rule for the target rebuild_cache -rebuild_cache/fast: rebuild_cache -.PHONY : rebuild_cache/fast - -# The main all target -all: cmake_check_build_system - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test//CMakeFiles/progress.marks - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/test/radiation_test/all - $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles 0 -.PHONY : all - -# The main clean target -clean: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/test/radiation_test/clean -.PHONY : clean - -# The main clean target -clean/fast: clean -.PHONY : clean/fast - -# Prepare targets for installation. -preinstall: all - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/test/radiation_test/preinstall -.PHONY : preinstall - -# Prepare targets for installation. -preinstall/fast: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/test/radiation_test/preinstall -.PHONY : preinstall/fast - -# clear depends -depend: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 -.PHONY : depend - -# Convenience name for target. -unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/rule: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/rule -.PHONY : unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/rule - -# Convenience name for target. -FATES_rad_test: unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/rule -.PHONY : FATES_rad_test - -# fast build rule for target. -FATES_rad_test/fast: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build -.PHONY : FATES_rad_test/fast - -FatesUnitTestRadiation.o: FatesUnitTestRadiation.F90.o -.PHONY : FatesUnitTestRadiation.o - -# target to build an object file -FatesUnitTestRadiation.F90.o: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.o -.PHONY : FatesUnitTestRadiation.F90.o - -FatesUnitTestRadiation.i: FatesUnitTestRadiation.F90.i -.PHONY : FatesUnitTestRadiation.i - -# target to preprocess a source file -FatesUnitTestRadiation.F90.i: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.i -.PHONY : FatesUnitTestRadiation.F90.i - -FatesUnitTestRadiation.s: FatesUnitTestRadiation.F90.s -.PHONY : FatesUnitTestRadiation.s - -# target to generate assembly for a file -FatesUnitTestRadiation.F90.s: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/FatesUnitTestRadiation.F90.s -.PHONY : FatesUnitTestRadiation.F90.s - -__/__/__/main/FatesConstantsMod.o: __/__/__/main/FatesConstantsMod.F90.o -.PHONY : __/__/__/main/FatesConstantsMod.o - -# target to build an object file -__/__/__/main/FatesConstantsMod.F90.o: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.o -.PHONY : __/__/__/main/FatesConstantsMod.F90.o - -__/__/__/main/FatesConstantsMod.i: __/__/__/main/FatesConstantsMod.F90.i -.PHONY : __/__/__/main/FatesConstantsMod.i - -# target to preprocess a source file -__/__/__/main/FatesConstantsMod.F90.i: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.i -.PHONY : __/__/__/main/FatesConstantsMod.F90.i - -__/__/__/main/FatesConstantsMod.s: __/__/__/main/FatesConstantsMod.F90.s -.PHONY : __/__/__/main/FatesConstantsMod.s - -# target to generate assembly for a file -__/__/__/main/FatesConstantsMod.F90.s: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/__/main/FatesConstantsMod.F90.s -.PHONY : __/__/__/main/FatesConstantsMod.F90.s - -__/__/utils/FatesUnitTestIOMod.o: __/__/utils/FatesUnitTestIOMod.F90.o -.PHONY : __/__/utils/FatesUnitTestIOMod.o - -# target to build an object file -__/__/utils/FatesUnitTestIOMod.F90.o: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.o -.PHONY : __/__/utils/FatesUnitTestIOMod.F90.o - -__/__/utils/FatesUnitTestIOMod.i: __/__/utils/FatesUnitTestIOMod.F90.i -.PHONY : __/__/utils/FatesUnitTestIOMod.i - -# target to preprocess a source file -__/__/utils/FatesUnitTestIOMod.F90.i: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.i -.PHONY : __/__/utils/FatesUnitTestIOMod.F90.i - -__/__/utils/FatesUnitTestIOMod.s: __/__/utils/FatesUnitTestIOMod.F90.s -.PHONY : __/__/utils/FatesUnitTestIOMod.s - -# target to generate assembly for a file -__/__/utils/FatesUnitTestIOMod.F90.s: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestIOMod.F90.s -.PHONY : __/__/utils/FatesUnitTestIOMod.F90.s - -__/__/utils/FatesUnitTestOrbitalMod.o: __/__/utils/FatesUnitTestOrbitalMod.F90.o -.PHONY : __/__/utils/FatesUnitTestOrbitalMod.o - -# target to build an object file -__/__/utils/FatesUnitTestOrbitalMod.F90.o: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.o -.PHONY : __/__/utils/FatesUnitTestOrbitalMod.F90.o - -__/__/utils/FatesUnitTestOrbitalMod.i: __/__/utils/FatesUnitTestOrbitalMod.F90.i -.PHONY : __/__/utils/FatesUnitTestOrbitalMod.i - -# target to preprocess a source file -__/__/utils/FatesUnitTestOrbitalMod.F90.i: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.i -.PHONY : __/__/utils/FatesUnitTestOrbitalMod.F90.i - -__/__/utils/FatesUnitTestOrbitalMod.s: __/__/utils/FatesUnitTestOrbitalMod.F90.s -.PHONY : __/__/utils/FatesUnitTestOrbitalMod.s - -# target to generate assembly for a file -__/__/utils/FatesUnitTestOrbitalMod.F90.s: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/build.make unit_testing/test/radiation_test/CMakeFiles/FATES_rad_test.dir/__/__/utils/FatesUnitTestOrbitalMod.F90.s -.PHONY : __/__/utils/FatesUnitTestOrbitalMod.F90.s - -# Help Target -help: - @echo "The following are some of the valid targets for this Makefile:" - @echo "... all (the default if no target is provided)" - @echo "... clean" - @echo "... depend" - @echo "... edit_cache" - @echo "... rebuild_cache" - @echo "... test" - @echo "... FATES_rad_test" - @echo "... FatesUnitTestRadiation.o" - @echo "... FatesUnitTestRadiation.i" - @echo "... FatesUnitTestRadiation.s" - @echo "... __/__/__/main/FatesConstantsMod.o" - @echo "... __/__/__/main/FatesConstantsMod.i" - @echo "... __/__/__/main/FatesConstantsMod.s" - @echo "... __/__/utils/FatesUnitTestIOMod.o" - @echo "... __/__/utils/FatesUnitTestIOMod.i" - @echo "... __/__/utils/FatesUnitTestIOMod.s" - @echo "... __/__/utils/FatesUnitTestOrbitalMod.o" - @echo "... __/__/utils/FatesUnitTestOrbitalMod.i" - @echo "... __/__/utils/FatesUnitTestOrbitalMod.s" -.PHONY : help - - - -#============================================================================= -# Special targets to cleanup operation of make. - -# Special rule to run CMake to check the build system integrity. -# No rule that depends on this can have commands that come from listfiles -# because they might be regenerated. -cmake_check_build_system: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 -.PHONY : cmake_check_build_system - diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/cmake_install.cmake b/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/cmake_install.cmake deleted file mode 100644 index 7f8055d555..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/cmake_install.cmake +++ /dev/null @@ -1,39 +0,0 @@ -# Install script for directory: /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/test/radiation_test - -# Set the install prefix -if(NOT DEFINED CMAKE_INSTALL_PREFIX) - set(CMAKE_INSTALL_PREFIX "/usr/local") -endif() -string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") - -# Set the install configuration name. -if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - if(BUILD_TYPE) - string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" - CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") - else() - set(CMAKE_INSTALL_CONFIG_NAME "CESM_DEBUG") - endif() - message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") -endif() - -# Set the component getting installed. -if(NOT CMAKE_INSTALL_COMPONENT) - if(COMPONENT) - message(STATUS "Install component: \"${COMPONENT}\"") - set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") - else() - set(CMAKE_INSTALL_COMPONENT) - endif() -endif() - -# Is this installation the result of a crosscompile? -if(NOT DEFINED CMAKE_CROSSCOMPILING) - set(CMAKE_CROSSCOMPILING "FALSE") -endif() - -# Set default install directory permissions. -if(NOT DEFINED CMAKE_OBJDUMP) - set(CMAKE_OBJDUMP "/usr/bin/objdump") -endif() - diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/utils/CMakeFiles/CMakeDirectoryInformation.cmake b/build/__command_line_test__/__command_line_test__/unit_testing/utils/CMakeFiles/CMakeDirectoryInformation.cmake deleted file mode 100644 index 0626f191b1..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/utils/CMakeFiles/CMakeDirectoryInformation.cmake +++ /dev/null @@ -1,16 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 3.25 - -# Relative path conversion top directories. -set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/Users/afoster/Documents/ncar/CTSM/src/fates") -set(CMAKE_RELATIVE_PATH_TOP_BINARY "/Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__") - -# Force unix paths in dependencies. -set(CMAKE_FORCE_UNIX_PATHS 1) - - -# The C and CXX include file regular expressions for this directory. -set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") -set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") -set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) -set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/utils/CMakeFiles/progress.marks b/build/__command_line_test__/__command_line_test__/unit_testing/utils/CMakeFiles/progress.marks deleted file mode 100644 index 573541ac97..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/utils/CMakeFiles/progress.marks +++ /dev/null @@ -1 +0,0 @@ -0 diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/utils/CTestTestfile.cmake b/build/__command_line_test__/__command_line_test__/unit_testing/utils/CTestTestfile.cmake deleted file mode 100644 index 6e2fdc5a3d..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/utils/CTestTestfile.cmake +++ /dev/null @@ -1,6 +0,0 @@ -# CMake generated Testfile for -# Source directory: /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils -# Build directory: /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/utils -# -# This file includes the relevant testing commands required for -# testing this directory and lists subdirectories to be tested as well. diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/utils/Makefile b/build/__command_line_test__/__command_line_test__/unit_testing/utils/Makefile deleted file mode 100644 index b1f822e9bf..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/utils/Makefile +++ /dev/null @@ -1,151 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 3.25 - -# Default target executed when no arguments are given to make. -default_target: all -.PHONY : default_target - -# Allow only one "make -f Makefile2" at a time, but pass parallelism. -.NOTPARALLEL: - -#============================================================================= -# Special targets provided by cmake. - -# Disable implicit rules so canonical targets will work. -.SUFFIXES: - -# Disable VCS-based implicit rules. -% : %,v - -# Disable VCS-based implicit rules. -% : RCS/% - -# Disable VCS-based implicit rules. -% : RCS/%,v - -# Disable VCS-based implicit rules. -% : SCCS/s.% - -# Disable VCS-based implicit rules. -% : s.% - -.SUFFIXES: .hpux_make_needs_suffix_list - -# Command-line flag to silence nested $(MAKE). -$(VERBOSE)MAKESILENT = -s - -#Suppress display of executed commands. -$(VERBOSE).SILENT: - -# A target that is always out of date. -cmake_force: -.PHONY : cmake_force - -#============================================================================= -# Set environment variables for the build. - -# The shell in which to execute make rules. -SHELL = /bin/sh - -# The CMake executable. -CMAKE_COMMAND = /usr/local/Cellar/cmake/3.25.2/bin/cmake - -# The command to remove a file. -RM = /usr/local/Cellar/cmake/3.25.2/bin/cmake -E rm -f - -# Escaping for special characters. -EQUALS = = - -# The top-level source directory on which CMake was run. -CMAKE_SOURCE_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates - -# The top-level build directory on which CMake was run. -CMAKE_BINARY_DIR = /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ - -#============================================================================= -# Targets provided globally by CMake. - -# Special rule for the target test -test: - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests..." - /usr/local/Cellar/cmake/3.25.2/bin/ctest --force-new-ctest-process $(ARGS) -.PHONY : test - -# Special rule for the target test -test/fast: test -.PHONY : test/fast - -# Special rule for the target edit_cache -edit_cache: - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." - /usr/local/Cellar/cmake/3.25.2/bin/ccmake -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) -.PHONY : edit_cache - -# Special rule for the target edit_cache -edit_cache/fast: edit_cache -.PHONY : edit_cache/fast - -# Special rule for the target rebuild_cache -rebuild_cache: - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." - /usr/local/Cellar/cmake/3.25.2/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) -.PHONY : rebuild_cache - -# Special rule for the target rebuild_cache -rebuild_cache/fast: rebuild_cache -.PHONY : rebuild_cache/fast - -# The main all target -all: cmake_check_build_system - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/unit_testing/utils//CMakeFiles/progress.marks - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/utils/all - $(CMAKE_COMMAND) -E cmake_progress_start /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__/CMakeFiles 0 -.PHONY : all - -# The main clean target -clean: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/utils/clean -.PHONY : clean - -# The main clean target -clean/fast: clean -.PHONY : clean/fast - -# Prepare targets for installation. -preinstall: all - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/utils/preinstall -.PHONY : preinstall - -# Prepare targets for installation. -preinstall/fast: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 unit_testing/utils/preinstall -.PHONY : preinstall/fast - -# clear depends -depend: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 -.PHONY : depend - -# Help Target -help: - @echo "The following are some of the valid targets for this Makefile:" - @echo "... all (the default if no target is provided)" - @echo "... clean" - @echo "... depend" - @echo "... edit_cache" - @echo "... rebuild_cache" - @echo "... test" -.PHONY : help - - - -#============================================================================= -# Special targets to cleanup operation of make. - -# Special rule to run CMake to check the build system integrity. -# No rule that depends on this can have commands that come from listfiles -# because they might be regenerated. -cmake_check_build_system: - cd /Users/afoster/Documents/ncar/CTSM/src/fates/build/__command_line_test__/__command_line_test__ && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 -.PHONY : cmake_check_build_system - diff --git a/build/__command_line_test__/__command_line_test__/unit_testing/utils/cmake_install.cmake b/build/__command_line_test__/__command_line_test__/unit_testing/utils/cmake_install.cmake deleted file mode 100644 index 42c88ffb10..0000000000 --- a/build/__command_line_test__/__command_line_test__/unit_testing/utils/cmake_install.cmake +++ /dev/null @@ -1,39 +0,0 @@ -# Install script for directory: /Users/afoster/Documents/ncar/CTSM/src/fates/unit_testing/utils - -# Set the install prefix -if(NOT DEFINED CMAKE_INSTALL_PREFIX) - set(CMAKE_INSTALL_PREFIX "/usr/local") -endif() -string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") - -# Set the install configuration name. -if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - if(BUILD_TYPE) - string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" - CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") - else() - set(CMAKE_INSTALL_CONFIG_NAME "CESM_DEBUG") - endif() - message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") -endif() - -# Set the component getting installed. -if(NOT CMAKE_INSTALL_COMPONENT) - if(COMPONENT) - message(STATUS "Install component: \"${COMPONENT}\"") - set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") - else() - set(CMAKE_INSTALL_COMPONENT) - endif() -endif() - -# Is this installation the result of a crosscompile? -if(NOT DEFINED CMAKE_CROSSCOMPILING) - set(CMAKE_CROSSCOMPILING "FALSE") -endif() - -# Set default install directory permissions. -if(NOT DEFINED CMAKE_OBJDUMP) - set(CMAKE_OBJDUMP "/usr/bin/objdump") -endif() - diff --git a/build/cmake_macros/CMakeLists.txt b/build/cmake_macros/CMakeLists.txt deleted file mode 100644 index c2ebcb51be..0000000000 --- a/build/cmake_macros/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -cmake_policy(SET CMP0057 NEW) -cmake_minimum_required(VERSION 3.5) -project(cime LANGUAGES C Fortran) -include(../Macros.cmake) diff --git a/build/cmake_macros/CNL.cmake b/build/cmake_macros/CNL.cmake deleted file mode 100644 index 7202f78196..0000000000 --- a/build/cmake_macros/CNL.cmake +++ /dev/null @@ -1,14 +0,0 @@ -set(CMAKE_OPTS "-DCMAKE_SYSTEM_NAME=Catamount") -string(APPEND CPPDEFS " -DLINUX") -if (COMP_NAME STREQUAL gptl) - string(APPEND CPPDEFS " -DHAVE_NANOTIME -DBIT64 -DHAVE_VPRINTF -DHAVE_BACKTRACE -DHAVE_SLASHPROC -DHAVE_COMM_F2C -DHAVE_TIMES -DHAVE_GETTIMEOFDAY") -endif() -set(MPICC "cc") -set(MPICXX "CC") -set(MPIFC "ftn") -set(NETCDF_PATH "$ENV{NETCDF_DIR}") -set(PIO_FILESYSTEM_HINTS "lustre") -set(PNETCDF_PATH "$ENV{PARALLEL_NETCDF_DIR}") -set(SCC "cc") -set(SCXX "CC") -set(SFC "ftn") diff --git a/build/cmake_macros/Darwin.cmake b/build/cmake_macros/Darwin.cmake deleted file mode 100644 index 89fd4bdc07..0000000000 --- a/build/cmake_macros/Darwin.cmake +++ /dev/null @@ -1 +0,0 @@ -string(APPEND CPPDEFS " -DSYSDARWIN") diff --git a/build/cmake_macros/Macros.cmake b/build/cmake_macros/Macros.cmake deleted file mode 100644 index b089f58058..0000000000 --- a/build/cmake_macros/Macros.cmake +++ /dev/null @@ -1,37 +0,0 @@ -# -# Use this file to include the relevant macros based on -# machine/compiler settings. This file gets copied to CASEROOT -# and that's the one that gets included by the build system. Feel free -# to modify this file in the CASEROOT. -# -set(MACROS_DIR ${CASEROOT}/cmake_macros) - -set(UNIVERSAL_MACRO ${MACROS_DIR}/universal.cmake) -set(COMPILER_MACRO ${MACROS_DIR}/${COMPILER}.cmake) -set(OS_MACRO ${MACROS_DIR}/${OS}.cmake) -set(MACHINE_MACRO ${MACROS_DIR}/${MACH}.cmake) -set(COMPILER_OS_MACRO ${MACROS_DIR}/${COMPILER}_${OS}.cmake) -set(COMPILER_MACHINE_MACRO ${MACROS_DIR}/${COMPILER}_${MACH}.cmake) - -if (CONVERT_TO_MAKE) - get_cmake_property(VARS_BEFORE_BUILD_INTERNAL_IGNORE VARIABLES) -endif() - -# Include order defines precedence -foreach (MACRO_FILE ${UNIVERSAL_MACRO} ${COMPILER_MACRO} ${OS_MACRO} ${MACHINE_MACRO} ${COMPILER_OS_MACRO} ${COMPILER_MACHINE_MACRO}) - if (EXISTS ${MACRO_FILE}) - include(${MACRO_FILE}) - else() - message("No macro file found: ${MACRO_FILE}") - endif() -endforeach() - -if (CONVERT_TO_MAKE) - get_cmake_property(VARS_AFTER VARIABLES) - - foreach (VAR_AFTER IN LISTS VARS_AFTER) - if (NOT VAR_AFTER IN_LIST VARS_BEFORE_BUILD_INTERNAL_IGNORE) - message("CIME_SET_MAKEFILE_VAR ${VAR_AFTER} := ${${VAR_AFTER}}") - endif() - endforeach() -endif() diff --git a/build/cmake_macros/arm.cmake b/build/cmake_macros/arm.cmake deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/build/cmake_macros/armgcc.cmake b/build/cmake_macros/armgcc.cmake deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/build/cmake_macros/athena.cmake b/build/cmake_macros/athena.cmake deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/build/cmake_macros/bluewaters.cmake b/build/cmake_macros/bluewaters.cmake deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/build/cmake_macros/casper.cmake b/build/cmake_macros/casper.cmake deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/build/cmake_macros/centos7-linux.cmake b/build/cmake_macros/centos7-linux.cmake deleted file mode 100644 index 4dc3995df5..0000000000 --- a/build/cmake_macros/centos7-linux.cmake +++ /dev/null @@ -1 +0,0 @@ -string(APPEND SLIBS " -L$(NETCDF_PATH)/lib -Wl,-rpath,$(NETCDF_PATH)/lib -lnetcdff -lnetcdf") diff --git a/build/cmake_macros/cheyenne.cmake b/build/cmake_macros/cheyenne.cmake deleted file mode 100644 index 35c2d3c33e..0000000000 --- a/build/cmake_macros/cheyenne.cmake +++ /dev/null @@ -1,6 +0,0 @@ -if (COMP_NAME STREQUAL gptl) - string(APPEND CPPDEFS " -DHAVE_NANOTIME -DBIT64 -DHAVE_VPRINTF -DHAVE_BACKTRACE -DHAVE_SLASHPROC -DHAVE_COMM_F2C -DHAVE_TIMES -DHAVE_GETTIMEOFDAY") -endif() -set(NETCDF_PATH "$ENV{NETCDF}") -set(PIO_FILESYSTEM_HINTS "gpfs") -set(PNETCDF_PATH "$ENV{PNETCDF}") diff --git a/build/cmake_macros/container.cmake b/build/cmake_macros/container.cmake deleted file mode 100644 index 82b8a1428d..0000000000 --- a/build/cmake_macros/container.cmake +++ /dev/null @@ -1,7 +0,0 @@ -if (COMP_NAME STREQUAL gptl) - string(APPEND CPPDEFS " -DHAVE_NANOTIME -DBIT64 -DHAVE_VPRINTF -DHAVE_BACKTRACE -DHAVE_SLASHPROC -DHAVE_COMM_F2C -DHAVE_TIMES -DHAVE_GETTIMEOFDAY") -endif() -set(NETCDF_PATH "/usr/local") -set(PNETCDF_PATH "/usr/local") -set(LDFLAGS "") -string(APPEND SLIBS " -lnetcdf -lnetcdff -llapack -lblas") diff --git a/build/cmake_macros/cray.cmake b/build/cmake_macros/cray.cmake deleted file mode 100644 index 89c27843d7..0000000000 --- a/build/cmake_macros/cray.cmake +++ /dev/null @@ -1,37 +0,0 @@ -if (NOT compile_threaded) - string(APPEND CFLAGS " -h noomp") -endif() -if (compile_threaded) - string(APPEND CFLAGS " -fopenmp") -endif() -if (DEBUG) - string(APPEND CFLAGS " -g -O0") -endif() -if (NOT DEBUG) - string(APPEND CFLAGS " -O2") -endif() -string(APPEND CPPDEFS " -DFORTRANUNDERSCORE -DNO_R16 -DCPRCRAY") -if (COMP_NAME STREQUAL pop) - string(APPEND CPPDEFS " -DDIR=NOOP") -endif() -if (COMP_NAME STREQUAL moby) - string(APPEND CPPDEFS " -DDIR=NOOP") -endif() -set(FC_AUTO_R8 "-s real64") -string(APPEND FFLAGS " -f free -N 255 -h byteswapio -x dir -ef") -if (NOT compile_threaded) - string(APPEND FFLAGS " -h noomp") -endif() -if (compile_threaded) - string(APPEND FFLAGS " -h omp") -endif() -if (DEBUG) - string(APPEND FFLAGS " -g -O0 -K trap=fp -m1") -endif() -if (NOT DEBUG) - string(APPEND FFLAGS " -O2,ipa2 -em") -endif() -set(FFLAGS_NOOPT "-O1,fp2,ipa0,scalar0,vector0") -set(HAS_F2008_CONTIGUOUS "TRUE") -set(LDFLAGS "-Wl,--allow-multiple-definition -h byteswapio") -string(APPEND LDFLAGS " -h omp") diff --git a/build/cmake_macros/cray_daint.cmake b/build/cmake_macros/cray_daint.cmake deleted file mode 100644 index 5929a1be65..0000000000 --- a/build/cmake_macros/cray_daint.cmake +++ /dev/null @@ -1,2 +0,0 @@ -string(APPEND FFLAGS " -I/project/s824/edavin/OASIS3-MCT_2.0/build.cray/build/lib/mct -I/project/s824/edavin/OASIS3-MCT_2.0/build.cray/build/lib/psmile.MPI1") -string(APPEND SLIBS " -L/project/s824/edavin/OASIS3-MCT_2.0/build.cray/lib -lpsmile.MPI1 -lscrip -lmct_oasis -lmpeu_oasis") diff --git a/build/cmake_macros/euler2.cmake b/build/cmake_macros/euler2.cmake deleted file mode 100644 index 63ca8a325f..0000000000 --- a/build/cmake_macros/euler2.cmake +++ /dev/null @@ -1,5 +0,0 @@ -string(APPEND CPPDEFS " -DLINUX") -set(NETCDF_PATH "$ENV{NETCDF}") -set(PIO_FILESYSTEM_HINTS "lustre") -set(PNETCDF_PATH "$ENV{PNETCDF}") -set(SLIBS "-L$ENV{NETCDF}/lib -lnetcdf -lnetcdff") diff --git a/build/cmake_macros/euler3.cmake b/build/cmake_macros/euler3.cmake deleted file mode 100644 index 63ca8a325f..0000000000 --- a/build/cmake_macros/euler3.cmake +++ /dev/null @@ -1,5 +0,0 @@ -string(APPEND CPPDEFS " -DLINUX") -set(NETCDF_PATH "$ENV{NETCDF}") -set(PIO_FILESYSTEM_HINTS "lustre") -set(PNETCDF_PATH "$ENV{PNETCDF}") -set(SLIBS "-L$ENV{NETCDF}/lib -lnetcdf -lnetcdff") diff --git a/build/cmake_macros/euler4.cmake b/build/cmake_macros/euler4.cmake deleted file mode 100644 index 63ca8a325f..0000000000 --- a/build/cmake_macros/euler4.cmake +++ /dev/null @@ -1,5 +0,0 @@ -string(APPEND CPPDEFS " -DLINUX") -set(NETCDF_PATH "$ENV{NETCDF}") -set(PIO_FILESYSTEM_HINTS "lustre") -set(PNETCDF_PATH "$ENV{PNETCDF}") -set(SLIBS "-L$ENV{NETCDF}/lib -lnetcdf -lnetcdff") diff --git a/build/cmake_macros/frontera.cmake b/build/cmake_macros/frontera.cmake deleted file mode 100644 index bbdb959a39..0000000000 --- a/build/cmake_macros/frontera.cmake +++ /dev/null @@ -1,9 +0,0 @@ -set(HAS_F2008_CONTIGUOUS "TRUE") -if (COMP_NAME STREQUAL gptl) - string(APPEND CPPDEFS " -DHAVE_NANOTIME -DBIT64 -DHAVE_VPRINTF -DHAVE_BACKTRACE -DHAVE_SLASHPROC -DHAVE_COMM_F2C -DHAVE_TIMES -DHAVE_GETTIMEOFDAY") -endif() -set(NETCDF_PATH "$ENV{TACC_NETCDF_DIR}") -set(PIO_FILESYSTEM_HINTS "lustre") -set(PNETCDF_PATH "$ENV{TACC_PNETCDF_DIR}") -string(APPEND LDFLAGS " -Wl,-rpath,${NETCDF_PATH}/lib") -string(APPEND SLIBS " -L${NETCDF_PATH}/lib -lnetcdff -lnetcdf") diff --git a/build/cmake_macros/gnu.cmake b/build/cmake_macros/gnu.cmake deleted file mode 100644 index 621740c595..0000000000 --- a/build/cmake_macros/gnu.cmake +++ /dev/null @@ -1,43 +0,0 @@ -string(APPEND CFLAGS " -std=gnu99") -if (compile_threaded) - string(APPEND CFLAGS " -fopenmp") -endif() -if (DEBUG) - string(APPEND CFLAGS " -g -Wall -Og -fbacktrace -ffpe-trap=invalid,zero,overflow -fcheck=bounds") -endif() -if (NOT DEBUG) - string(APPEND CFLAGS " -O") -endif() -string(APPEND CPPDEFS " -DFORTRANUNDERSCORE -DNO_R16 -DCPRGNU") -set(CXX_LINKER "FORTRAN") -set(FC_AUTO_R8 "-fdefault-real-8 -fdefault-double-8") -string(APPEND FFLAGS " -fconvert=big-endian -ffree-line-length-none -ffixed-line-length-none") -if (compile_threaded) - string(APPEND FFLAGS " -fopenmp") -endif() -if (DEBUG) - string(APPEND FFLAGS " -g -Wall -Og -fbacktrace -ffpe-trap=zero,overflow -fcheck=bounds") -endif() -if (NOT DEBUG) - string(APPEND FFLAGS " -O") -endif() -set(FFLAGS_NOOPT "-O0") -set(FIXEDFLAGS "-ffixed-form") -set(FREEFLAGS "-ffree-form") -set(HAS_F2008_CONTIGUOUS "FALSE") -if (compile_threaded) - string(APPEND LDFLAGS " -fopenmp") -endif() -set(MPICC "mpicc") -set(MPICXX "mpicxx") -set(MPIFC "mpif90") -set(SCC "gcc") -set(SCXX "g++") -set(SFC "gfortran") -set(SUPPORTS_CXX "TRUE") - -message("C compiler version is ${CMAKE_C_COMPILER_VERSION}") -message("Fortran compiler version is ${CMAKE_Fortran_COMPILER_VERSION}") -if (CMAKE_Fortran_COMPILER_VERSION VERSION_GREATER_EQUAL 10) - string(APPEND FFLAGS " -fallow-argument-mismatch -fallow-invalid-boz ") -endif() diff --git a/build/cmake_macros/gnu_cheyenne.cmake b/build/cmake_macros/gnu_cheyenne.cmake deleted file mode 100644 index 988fbb33be..0000000000 --- a/build/cmake_macros/gnu_cheyenne.cmake +++ /dev/null @@ -1,4 +0,0 @@ -if (COMP_NAME STREQUAL pio1) - string(APPEND CPPDEFS " -DNO_MPIMOD") -endif() -string(APPEND SLIBS " -ldl") diff --git a/build/cmake_macros/gnu_coeus.cmake b/build/cmake_macros/gnu_coeus.cmake deleted file mode 100644 index f2c24ef9e8..0000000000 --- a/build/cmake_macros/gnu_coeus.cmake +++ /dev/null @@ -1,2 +0,0 @@ -set(NETCDF_PATH "/vol/apps/hpc/stow/netcdf/4.4.1.1/gcc-6.3.0") -set(SLIBS "-L${NETCDF_PATH}/lib -lnetcdf -lnetcdff -lpmi") diff --git a/build/cmake_macros/gnu_fleabone.cmake b/build/cmake_macros/gnu_fleabone.cmake deleted file mode 100644 index d2f1e44096..0000000000 --- a/build/cmake_macros/gnu_fleabone.cmake +++ /dev/null @@ -1,27 +0,0 @@ -set(NETCDF_C_PATH "/usr/local/Cellar/netcdf/4.9.2") -set(NETCDF_FORTRAN_PATH "/usr/local/Cellar/netcdf-fortran/4.6.0") - -# These LDFLAGS provide lapack and blas support on a Mac. This may require installation of -# the Apple Developer Tools. -string(APPEND LDFLAGS " -framework Accelerate") - -#string(APPEND FFLAGS " -Wunused") - -# Trying to produce a backtrace leads to a hang, so don't even try -#string(APPEND CFLAGS " -fno-backtrace") -#string(APPEND FFLAGS " -fno-backtrace") - -# This is needed to run the Fortran unit tests; -# this isn't needed to build and run CESM. -#if (MPILIB STREQUAL mpi-serial AND NOT compile_threaded) -set(PFUNIT_PATH "/Users/afoster/pFUnit/") -#endif() - -# Most of the following paths aren't necessary on my machine because I have my PATH set so -# that the right compilers are picked up by default. But it doesn't hurt to be explicit. -set(SFC "/usr/local/bin/gfortran") -set(SCC "/usr/bin/gcc") -set(SCXX "/usr/bin/g++") -set(MPIFC "/usr/local/bin/mpif90") -set(MPICC "/usr/local/bin/mpicc") -set(MPICXX "/usr/local/bin/mpic++") diff --git a/build/cmake_macros/gnu_hobart.cmake b/build/cmake_macros/gnu_hobart.cmake deleted file mode 100644 index 35929dcc37..0000000000 --- a/build/cmake_macros/gnu_hobart.cmake +++ /dev/null @@ -1 +0,0 @@ -string(APPEND SLIBS " -lm -ldl") diff --git a/build/cmake_macros/gnu_homebrew.cmake b/build/cmake_macros/gnu_homebrew.cmake deleted file mode 100644 index 9e468c1276..0000000000 --- a/build/cmake_macros/gnu_homebrew.cmake +++ /dev/null @@ -1 +0,0 @@ -string(APPEND LDFLAGS " -framework Accelerate -Wl,-rpath $(NETCDF)/lib") diff --git a/build/cmake_macros/gnu_lobata.cmake b/build/cmake_macros/gnu_lobata.cmake deleted file mode 100644 index 60aeb9c8a8..0000000000 --- a/build/cmake_macros/gnu_lobata.cmake +++ /dev/null @@ -1,15 +0,0 @@ -set(SUPPORTS_CXX "TRUE") -if (COMP_NAME STREQUAL gptl) - string(APPEND CPPDEFS " -DHAVE_VPRINTF -DHAVE_TIMES -DHAVE_GETTIMEOFDAY -DHAVE_BACKTRACE") -endif() -string(APPEND SLIBS " -L$ENV{NETCDF_FORTRAN_PATH}/lib/ -lnetcdff -L$ENV{NETCDF_C_PATH}/lib/ -lnetcdf -lcurl -llapack -lblas") -if (DEBUG) - string(APPEND FFLAGS " -g -fbacktrace -fbounds-check -ffpe-trap=invalid,zero,overflow") -else() - string(APPEND FFLAGS " -fno-unsafe-math-optimizations") -endif() -if (MPILIB STREQUAL mpi-serial) - set(SCC "gcc") - set(SFC "gfortran") -endif() -string(APPEND CXX_LIBS " -lstdc++") diff --git a/build/cmake_macros/gnu_melvin.cmake b/build/cmake_macros/gnu_melvin.cmake deleted file mode 100644 index 668d542c96..0000000000 --- a/build/cmake_macros/gnu_melvin.cmake +++ /dev/null @@ -1,13 +0,0 @@ -set(ALBANY_PATH "/projects/install/rhel6-x86_64/ACME/AlbanyTrilinos/Albany/build/install") -if (NOT DEBUG) - string(APPEND CFLAGS " -O2") -endif() -set(CONFIG_ARGS "--host=cray") -set(CXX_LIBS "-lstdc++ -lmpi_cxx") -if (NOT DEBUG) - string(APPEND FFLAGS " -O2") -endif() -set(NETCDF_PATH "$ENV{NETCDFROOT}") -set(PNETCDF_PATH "$ENV{PNETCDFROOT}") -execute_process(COMMAND ${NETCDF_PATH}/bin/nf-config --flibs OUTPUT_VARIABLE SHELL_CMD_OUTPUT_BUILD_INTERNAL_IGNORE0 OUTPUT_STRIP_TRAILING_WHITESPACE) -string(APPEND SLIBS " ${SHELL_CMD_OUTPUT_BUILD_INTERNAL_IGNORE0} -lblas -llapack") diff --git a/build/cmake_macros/gnu_modex.cmake b/build/cmake_macros/gnu_modex.cmake deleted file mode 100644 index 83a692512a..0000000000 --- a/build/cmake_macros/gnu_modex.cmake +++ /dev/null @@ -1,5 +0,0 @@ -string(APPEND SLIBS " -L$ENV{HDF5_HOME}/lib -lhdf5_fortran -lhdf5 -lhdf5_hl -lhdf5hl_fortran") -string(APPEND SLIBS " -L$ENV{NETCDF_PATH}/lib/ -lnetcdff -lnetcdf -lcurl -lblas -llapack") -if (COMP_NAME STREQUAL gptl) - string(APPEND CPPDEFS " -DHAVE_VPRINTF -DHAVE_GETTIMEOFDAY -DHAVE_BACKTRACE") -endif() diff --git a/build/cmake_macros/gust.cmake b/build/cmake_macros/gust.cmake deleted file mode 100644 index 5332d19c9e..0000000000 --- a/build/cmake_macros/gust.cmake +++ /dev/null @@ -1,10 +0,0 @@ -if (COMP_NAME STREQUAL gptl) - string(APPEND CPPDEFS " -DHAVE_NANOTIME -DBIT64 -DHAVE_VPRINTF -DHAVE_BACKTRACE -DHAVE_SLASHPROC -DHAVE_COMM_F2C -DHAVE_TIMES -DHAVE_GETTIMEOFDAY") -endif() -set(NETCDF_PATH "$ENV{NETCDF}") -set(PIO_FILESYSTEM_HINTS "lustre") -set(PNETCDF_PATH "$ENV{PNETCDF}") -# If we want to use cray-libsci instead of mkl uncomment this line as well as the module in config_machines.xml -#string(REPLACE "-mkl=cluster" "" SLIBS "${SLIBS}") -string(REPLACE "-mkl=cluster" "-qmkl=cluster" SLIBS "${SLIBS}") -#string(APPEND CPPDEFS " -DNO_SHR_VMATH ") \ No newline at end of file diff --git a/build/cmake_macros/hobart.cmake b/build/cmake_macros/hobart.cmake deleted file mode 100644 index 8894b6a383..0000000000 --- a/build/cmake_macros/hobart.cmake +++ /dev/null @@ -1,9 +0,0 @@ -if (COMP_NAME STREQUAL gptl) - string(APPEND CPPDEFS " -DHAVE_NANOTIME -DBIT64 -DHAVE_VPRINTF -DHAVE_BACKTRACE -DHAVE_SLASHPROC -DHAVE_COMM_F2C -DHAVE_TIMES -DHAVE_GETTIMEOFDAY") -endif() -set(LAPACK_LIBDIR "/usr/lib64") -if (MPILIB STREQUAL mvapich2) - set(MPI_LIB_NAME "mpich") -endif() -set(NETCDF_PATH "$ENV{NETCDF_PATH}") -string(APPEND SLIBS " -L${NETCDF_PATH}/lib -lnetcdff -lnetcdf") diff --git a/build/cmake_macros/ibm.cmake b/build/cmake_macros/ibm.cmake deleted file mode 100644 index 37daaf31e5..0000000000 --- a/build/cmake_macros/ibm.cmake +++ /dev/null @@ -1,38 +0,0 @@ -string(APPEND CFLAGS " -g -qfullpath -qmaxmem=-1") -if (NOT DEBUG) - string(APPEND CFLAGS " -O3") -endif() -if (compile_threaded) - string(APPEND CFLAGS " -qsmp=omp") -endif() -if (DEBUG AND compile_threaded) - string(APPEND CFLAGS " -qsmp=omp:noopt") -endif() -string(APPEND CPPDEFS " -DFORTRAN_SAME -DCPRIBM") -set(CPRE "-WF,-D") -set(FC_AUTO_R8 "-qrealsize=8") -string(APPEND FFLAGS " -g -qfullpath -qmaxmem=-1") -if (NOT DEBUG) - string(APPEND FFLAGS " -O2 -qstrict -qinline=auto") -endif() -if (compile_threaded) - string(APPEND FFLAGS " -qsmp=omp") -endif() -if (DEBUG) - string(APPEND FFLAGS " -qinitauto=7FF7FFFF -qflttrap=ov:zero:inv:en") -endif() -if (DEBUG AND compile_threaded) - string(APPEND FFLAGS " -qsmp=omp:noopt") -endif() -if (DEBUG AND COMP_NAME STREQUAL pop) - string(APPEND FFLAGS " -C") -endif() -set(FIXEDFLAGS "-qsuffix=f=f -qfixed=132") -set(FREEFLAGS "-qsuffix=f=f90:cpp=F90") -set(HAS_F2008_CONTIGUOUS "TRUE") -if (compile_threaded) - string(APPEND LDFLAGS " -qsmp=omp") -endif() -if (DEBUG AND compile_threaded) - string(APPEND LDFLAGS " -qsmp=omp:noopt") -endif() diff --git a/build/cmake_macros/ibm_AIX.cmake b/build/cmake_macros/ibm_AIX.cmake deleted file mode 100644 index ec2293afb9..0000000000 --- a/build/cmake_macros/ibm_AIX.cmake +++ /dev/null @@ -1,18 +0,0 @@ -string(APPEND CFLAGS " -qarch=auto -qtune=auto -qcache=auto") -set(CONFIG_SHELL "/usr/bin/bash") -string(APPEND FFLAGS " -qarch=auto -qtune=auto -qcache=auto -qsclk=micro") -if (COMP_NAME STREQUAL cam) - string(APPEND FFLAGS " -qspill=6000") -endif() -if (DEBUG) - string(APPEND LDFLAGS " -qsigtrap=xl__trcedump") -endif() -string(APPEND LDFLAGS " -bdatapsize:64K -bstackpsize:64K -btextpsize:32K") -set(MPICC "mpcc_r") -set(MPIFC "mpxlf2003_r") -set(SCC "cc_r") -set(SFC "xlf2003_r") -string(APPEND SLIBS " -lmassv -lessl") -if (NOT DEBUG) - string(APPEND SLIBS " -lmass") -endif() diff --git a/build/cmake_macros/ibm_BGQ.cmake b/build/cmake_macros/ibm_BGQ.cmake deleted file mode 100644 index 0f113a90fe..0000000000 --- a/build/cmake_macros/ibm_BGQ.cmake +++ /dev/null @@ -1,11 +0,0 @@ -set(CONFIG_ARGS "--build=powerpc-bgp-linux --host=powerpc64-suse-linux") -string(APPEND CPPDEFS " -DLINUX") -string(APPEND FFLAGS " -g -qfullpath -qmaxmem=-1 -qspillsize=2500 -qextname=flush") -if (NOT DEBUG) - string(APPEND FFLAGS " -O3 -qstrict -qinline=auto") -endif() -if (NOT DEBUG AND compile_threaded) -endif() -if (DEBUG AND compile_threaded) -endif() -set(LDFLAGS "-Wl,--relax -Wl,--allow-multiple-definition") diff --git a/build/cmake_macros/intel.cmake b/build/cmake_macros/intel.cmake deleted file mode 100644 index 7328c85e30..0000000000 --- a/build/cmake_macros/intel.cmake +++ /dev/null @@ -1,61 +0,0 @@ -string(APPEND CFLAGS " -qno-opt-dynamic-align -fp-model precise -std=gnu99") -if (compile_threaded) - string(APPEND CFLAGS " -qopenmp") -endif() -if (NOT DEBUG) - string(APPEND CFLAGS " -O2 -debug minimal") -endif() -if (DEBUG) - string(APPEND CFLAGS " -O0 -g") -endif() -string(APPEND CPPDEFS " -DFORTRANUNDERSCORE -DCPRINTEL") -string(APPEND CXX_LDFLAGS " -cxxlib") -set(CXX_LINKER "FORTRAN") -set(FC_AUTO_R8 "-r8") -string(APPEND FFLAGS " -qno-opt-dynamic-align -convert big_endian -assume byterecl -ftz -traceback -assume realloc_lhs -fp-model source") -if (compile_threaded) - string(APPEND FFLAGS " -qopenmp") -endif() -if (DEBUG) - string(APPEND FFLAGS " -O0 -g -check uninit -check bounds -check pointers -fpe0 -check noarg_temp_created") -endif() -if (NOT DEBUG) - string(APPEND FFLAGS " -O2 -debug minimal") -endif() -set(FFLAGS_NOOPT "-O0") -set(FIXEDFLAGS "-fixed") -set(FREEFLAGS "-free") -if (compile_threaded) - string(APPEND LDFLAGS " -qopenmp") -endif() -set(MPICC "mpicc") -set(MPICXX "mpicxx") -set(MPIFC "mpif90") -set(SCC "icc") -set(SCXX "icpc") -set(SFC "ifort") -if (MPILIB STREQUAL mpich) - string(APPEND SLIBS " -mkl=cluster") -endif() -if (MPILIB STREQUAL mpich2) - string(APPEND SLIBS " -mkl=cluster") -endif() -if (MPILIB STREQUAL mvapich) - string(APPEND SLIBS " -mkl=cluster") -endif() -if (MPILIB STREQUAL mvapich2) - string(APPEND SLIBS " -mkl=cluster") -endif() -if (MPILIB STREQUAL mpt) - string(APPEND SLIBS " -mkl=cluster") -endif() -if (MPILIB STREQUAL openmpi) - string(APPEND SLIBS " -mkl=cluster") -endif() -if (MPILIB STREQUAL impi) - string(APPEND SLIBS " -mkl=cluster") -endif() -if (MPILIB STREQUAL mpi-serial) - string(APPEND SLIBS " -mkl") -endif() -set(SUPPORTS_CXX "TRUE") diff --git a/build/cmake_macros/intel_Darwin.cmake b/build/cmake_macros/intel_Darwin.cmake deleted file mode 100644 index 7a2450e00f..0000000000 --- a/build/cmake_macros/intel_Darwin.cmake +++ /dev/null @@ -1,3 +0,0 @@ -if (NOT compile_threaded) - string(APPEND FFLAGS " -heap-arrays") -endif() diff --git a/build/cmake_macros/intel_aleph.cmake b/build/cmake_macros/intel_aleph.cmake deleted file mode 100644 index 76985f0ede..0000000000 --- a/build/cmake_macros/intel_aleph.cmake +++ /dev/null @@ -1,8 +0,0 @@ -set(CONFIG_ARGS "--host=cray") -string(APPEND CFLAGS " -xCORE-AVX2") -string(APPEND FFLAGS " -xCORE-AVX2") -string(APPEND SLIBS " -L$(NETCDF_DIR) -lnetcdff -Wl,--as-needed,-L$(NETCDF_DIR)/lib -lnetcdff -lnetcdf") -if (COMP_NAME STREQUAL gptl) - string(APPEND CPPDEFS " -DHAVE_PAPI -DHAVE_SLASHPROC") -endif() -string(APPEND LDFLAGS " -mkl") diff --git a/build/cmake_macros/intel_athena.cmake b/build/cmake_macros/intel_athena.cmake deleted file mode 100644 index b558b0fd4d..0000000000 --- a/build/cmake_macros/intel_athena.cmake +++ /dev/null @@ -1,20 +0,0 @@ -string(APPEND CFLAGS " -xHost") -string(APPEND CPPDEFS " -DINTEL_MKL -DHAVE_SSE2") -string(APPEND FFLAGS " -xHost") -if (COMP_NAME STREQUAL nemo) - string(APPEND FFLAGS " $(FC_AUTO_R8) -O3 -assume norealloc_lhs") -endif() -execute_process(COMMAND ${NETCDF_PATH}/bin/nc-config --flibs OUTPUT_VARIABLE SHELL_CMD_OUTPUT_BUILD_INTERNAL_IGNORE0 OUTPUT_STRIP_TRAILING_WHITESPACE) -string(APPEND SLIBS " ${SHELL_CMD_OUTPUT_BUILD_INTERNAL_IGNORE0}") -if (MPILIB STREQUAL mpich2) - set(MPICXX "mpiicpc") -endif() -if (MPILIB STREQUAL mpich2) - set(MPICC "mpiicc") -endif() -if (MPILIB STREQUAL mpich2) - set(MPIFC "mpiifort") -endif() -if (MPILIB STREQUAL mpich2) - set(TRILINOS_PATH "$ENV{TRILINOS_PATH}") -endif() diff --git a/build/cmake_macros/intel_aws-hpc6a.cmake b/build/cmake_macros/intel_aws-hpc6a.cmake deleted file mode 100644 index 0e4d281538..0000000000 --- a/build/cmake_macros/intel_aws-hpc6a.cmake +++ /dev/null @@ -1,8 +0,0 @@ -string(APPEND CFLAGS " -qopt-report -march=core-avx2 -mtune=core-avx2 -no-fma") -string(APPEND FFLAGS " -qopt-report -march=core-avx2 -mtune=core-avx2 -no-fma") -if (DEBUG) - string(APPEND CMAKE_OPTS " -DPIO_ENABLE_LOGGING=ON") -endif() -set(SLIBS "-lnetcdf -lnetcdff -lpnetcdf -lblas -llapack -lpthread -lm -ldl") -string(APPEND CPPDEFS " -DNO_SHR_VMATH") - diff --git a/build/cmake_macros/intel_bluewaters.cmake b/build/cmake_macros/intel_bluewaters.cmake deleted file mode 100644 index 29b1da06da..0000000000 --- a/build/cmake_macros/intel_bluewaters.cmake +++ /dev/null @@ -1,3 +0,0 @@ -set(HAS_F2008_CONTIGUOUS "FALSE") -string(APPEND FFLAGS " -dynamic -mkl=sequential -no-fma") -string(APPEND CFLAGS " -dynamic -mkl=sequential -no-fma") diff --git a/build/cmake_macros/intel_casper.cmake b/build/cmake_macros/intel_casper.cmake deleted file mode 100644 index 7ee1c8b71d..0000000000 --- a/build/cmake_macros/intel_casper.cmake +++ /dev/null @@ -1,9 +0,0 @@ -string(APPEND CFLAGS " -qopt-report -xCORE_AVX2 -no-fma") -string(APPEND FFLAGS " -qopt-report -xCORE_AVX2 -no-fma") -if (DEBUG) - string(APPEND CMAKE_OPTS " -DPIO_ENABLE_LOGGING=ON") -endif() -if (MPILIB STREQUAL mpi-serial AND NOT compile_threaded) - set(PFUNIT_PATH "$ENV{CESMDATAROOT}/tools/pFUnit/pFUnit3.2.8_cheyenne_Intel17.0.1_noMPI_noOpenMP") -endif() -set(HAS_F2008_CONTIGUOUS "TRUE") diff --git a/build/cmake_macros/intel_cheyenne.cmake b/build/cmake_macros/intel_cheyenne.cmake deleted file mode 100644 index f83ba0ebd2..0000000000 --- a/build/cmake_macros/intel_cheyenne.cmake +++ /dev/null @@ -1,12 +0,0 @@ -string(APPEND CFLAGS " -qopt-report -xCORE_AVX2 -no-fma") -string(APPEND FFLAGS " -qopt-report -xCORE_AVX2 -no-fma") -if (DEBUG) - string(APPEND CMAKE_OPTS " -DPIO_ENABLE_LOGGING=ON") -endif() -if (MPILIB STREQUAL mpi-serial AND NOT compile_threaded) - set(PFUNIT_PATH "$ENV{CESMDATAROOT}/tools/pFUnit/pFUnit3.2.8_cheyenne_Intel17.0.1_noMPI_noOpenMP") -endif() -if (MPILIB STREQUAL mpt AND compile_threaded) - set(PFUNIT_PATH "$ENV{CESMDATAROOT}/tools/pFUnit/pFUnit3.2.8_cheyenne_Intel17.0.1_MPI_openMP") -endif() -set(HAS_F2008_CONTIGUOUS "TRUE") diff --git a/build/cmake_macros/intel_constance.cmake b/build/cmake_macros/intel_constance.cmake deleted file mode 100644 index 5733786855..0000000000 --- a/build/cmake_macros/intel_constance.cmake +++ /dev/null @@ -1,11 +0,0 @@ -if (NOT DEBUG) - string(APPEND CFLAGS " -O2") -endif() -set(CONFIG_ARGS "--host=cray") -string(APPEND CPPDEFS " -DLINUX") -if (NOT DEBUG) - string(APPEND FFLAGS " -O2") -endif() -set(NETCDF_PATH "$ENV{NETCDF_HOME}") -set(PIO_FILESYSTEM_HINTS "lustre") -set(SLIBS "-L${NETCDF_PATH}/lib -lnetcdf -lnetcdff -lpmi -L$ENV{MKL_PATH} -lmkl_rt") diff --git a/build/cmake_macros/intel_cori-haswell.cmake b/build/cmake_macros/intel_cori-haswell.cmake deleted file mode 100644 index 6fe65eb1d9..0000000000 --- a/build/cmake_macros/intel_cori-haswell.cmake +++ /dev/null @@ -1,9 +0,0 @@ -set(CONFIG_ARGS "--host=cray") -string(APPEND CFLAGS " -xCORE-AVX2") -string(APPEND FFLAGS " -xCORE-AVX2") -string(APPEND SLIBS " -L$(NETCDF_DIR) -lnetcdff -Wl,--as-needed,-L$(NETCDF_DIR)/lib -lnetcdff -lnetcdf") -if (COMP_NAME STREQUAL gptl) - string(APPEND CPPDEFS " -DHAVE_SLASHPROC") -endif() -string(APPEND LDFLAGS " -mkl") -set(HAS_F2008_CONTIGUOUS "FALSE") diff --git a/build/cmake_macros/intel_cori-knl.cmake b/build/cmake_macros/intel_cori-knl.cmake deleted file mode 100644 index 683c1a8068..0000000000 --- a/build/cmake_macros/intel_cori-knl.cmake +++ /dev/null @@ -1,9 +0,0 @@ -set(CONFIG_ARGS "--host=cray") -string(APPEND CFLAGS " -xMIC-AVX512") -string(APPEND FFLAGS " -xMIC-AVX512") -string(APPEND SLIBS " -L$(NETCDF_DIR) -lnetcdff -Wl,--as-needed,-L$(NETCDF_DIR)/lib -lnetcdff -lnetcdf") -if (COMP_NAME STREQUAL gptl) - string(APPEND CPPDEFS " -DHAVE_SLASHPROC") -endif() -string(APPEND LDFLAGS " -mkl -lmemkind -zmuldefs") -set(HAS_F2008_CONTIGUOUS "FALSE") diff --git a/build/cmake_macros/intel_eastwind.cmake b/build/cmake_macros/intel_eastwind.cmake deleted file mode 100644 index 1a1dcf69b3..0000000000 --- a/build/cmake_macros/intel_eastwind.cmake +++ /dev/null @@ -1,11 +0,0 @@ -if (NOT DEBUG) - string(APPEND CFLAGS " -O2") -endif() -set(CONFIG_ARGS "--host=cray") -string(APPEND CPPDEFS " -DLINUX") -if (NOT DEBUG) - string(APPEND FFLAGS " -O2") -endif() -set(NETCDF_PATH "$ENV{NETCDF_HOME}") -set(PIO_FILESYSTEM_HINTS "lustre") -set(SLIBS "-L${NETCDF_PATH}/lib -lnetcdf -lnetcdff -lpmi") diff --git a/build/cmake_macros/intel_edison.cmake b/build/cmake_macros/intel_edison.cmake deleted file mode 100644 index 3f41409deb..0000000000 --- a/build/cmake_macros/intel_edison.cmake +++ /dev/null @@ -1,11 +0,0 @@ -if (NOT DEBUG) - string(APPEND CFLAGS " -O2") -endif() -set(CONFIG_ARGS "--host=cray") -if (COMP_NAME STREQUAL gptl) - string(APPEND CPPDEFS " -DHAVE_PAPI") -endif() -if (NOT DEBUG) - string(APPEND FFLAGS " -O2") -endif() -string(APPEND SLIBS " -L$ENV{NETCDF_DIR} -lnetcdff -Wl,--as-needed,-L$ENV{NETCDF_DIR}/lib -lnetcdff -lnetcdf") diff --git a/build/cmake_macros/intel_euler2.cmake b/build/cmake_macros/intel_euler2.cmake deleted file mode 100644 index 42580b2a64..0000000000 --- a/build/cmake_macros/intel_euler2.cmake +++ /dev/null @@ -1,7 +0,0 @@ -if (NOT DEBUG) - string(APPEND CFLAGS " -xCORE-AVX2") -endif() -if (NOT DEBUG) - string(APPEND FFLAGS " -xCORE-AVX2") -endif() -string(APPEND LDFLAGS " -mkl") diff --git a/build/cmake_macros/intel_euler3.cmake b/build/cmake_macros/intel_euler3.cmake deleted file mode 100644 index 42580b2a64..0000000000 --- a/build/cmake_macros/intel_euler3.cmake +++ /dev/null @@ -1,7 +0,0 @@ -if (NOT DEBUG) - string(APPEND CFLAGS " -xCORE-AVX2") -endif() -if (NOT DEBUG) - string(APPEND FFLAGS " -xCORE-AVX2") -endif() -string(APPEND LDFLAGS " -mkl") diff --git a/build/cmake_macros/intel_euler4.cmake b/build/cmake_macros/intel_euler4.cmake deleted file mode 100644 index 42580b2a64..0000000000 --- a/build/cmake_macros/intel_euler4.cmake +++ /dev/null @@ -1,7 +0,0 @@ -if (NOT DEBUG) - string(APPEND CFLAGS " -xCORE-AVX2") -endif() -if (NOT DEBUG) - string(APPEND FFLAGS " -xCORE-AVX2") -endif() -string(APPEND LDFLAGS " -mkl") diff --git a/build/cmake_macros/intel_greenplanet-sib29.cmake b/build/cmake_macros/intel_greenplanet-sib29.cmake deleted file mode 100644 index e445abd253..0000000000 --- a/build/cmake_macros/intel_greenplanet-sib29.cmake +++ /dev/null @@ -1,3 +0,0 @@ -set(NETCDF_PATH "$ENV{NCDIR}") -set(PNETCDF_PATH "$ENV{PNDIR}") -string(APPEND SLIBS " -L${NETCDF_PATH}/lib -lnetcdf -lnetcdff") diff --git a/build/cmake_macros/intel_greenplanet-sky24.cmake b/build/cmake_macros/intel_greenplanet-sky24.cmake deleted file mode 100644 index e445abd253..0000000000 --- a/build/cmake_macros/intel_greenplanet-sky24.cmake +++ /dev/null @@ -1,3 +0,0 @@ -set(NETCDF_PATH "$ENV{NCDIR}") -set(PNETCDF_PATH "$ENV{PNDIR}") -string(APPEND SLIBS " -L${NETCDF_PATH}/lib -lnetcdf -lnetcdff") diff --git a/build/cmake_macros/intel_gust.cmake b/build/cmake_macros/intel_gust.cmake deleted file mode 100644 index f3943efe8e..0000000000 --- a/build/cmake_macros/intel_gust.cmake +++ /dev/null @@ -1,6 +0,0 @@ -set(CONFIG_ARGS "--host=cray") -string(APPEND CFLAGS " -march=core-avx2") -string(APPEND FFLAGS " -march=core-avx2") -if (COMP_NAME STREQUAL gptl) - string(APPEND CPPDEFS " -DHAVE_SLASHPROC") -endif() diff --git a/build/cmake_macros/intel_hobart.cmake b/build/cmake_macros/intel_hobart.cmake deleted file mode 100644 index e9ac234fd1..0000000000 --- a/build/cmake_macros/intel_hobart.cmake +++ /dev/null @@ -1,16 +0,0 @@ -string(APPEND CFLAGS " -lifcore") -string(APPEND FFLAGS " -lifcore") -if (MPILIB STREQUAL mpi-serial) - string(APPEND FFLAGS " -mcmodel medium") -endif() -string(APPEND LDFLAGS " -lquadmath") -string(APPEND LDFLAGS " -Wl,-rpath,${NETCDF_PATH}/lib") -string(APPEND LDFLAGS " -Wl,-rpath,$ENV{COMPILER_PATH}/lib/intel64") -string(APPEND LDFLAGS " -Wl,-rpath,$ENV{COMPILER_PATH}/mkl/lib/intel64") -string(APPEND LDFLAGS " -Wl,-rpath,$ENV{MPI_PATH}/lib") -string(APPEND LDFLAGS " -lifcore") -if (MPILIB STREQUAL mvapich2) -endif() -if (MPILIB STREQUAL mpi-serial AND NOT compile_threaded) - set(PFUNIT_PATH "/fs/cgd/csm/tools/pFUnit/pFUnit3.2.8_hobart_Intel15.0.2_noMPI_noOpenMP") -endif() diff --git a/build/cmake_macros/intel_izumi.cmake b/build/cmake_macros/intel_izumi.cmake deleted file mode 100644 index 13f2e3be28..0000000000 --- a/build/cmake_macros/intel_izumi.cmake +++ /dev/null @@ -1,3 +0,0 @@ -if (MPILIB STREQUAL mpi-serial AND NOT compile_threaded) - set(PFUNIT_PATH "/fs/cgd/csm/tools/pFUnit/pFUnit3.3.3_izumi_Intel19.0.1_noMPI_noOpenMP") -endif() diff --git a/build/cmake_macros/intel_laramie.cmake b/build/cmake_macros/intel_laramie.cmake deleted file mode 100644 index ba6a09daa2..0000000000 --- a/build/cmake_macros/intel_laramie.cmake +++ /dev/null @@ -1,5 +0,0 @@ -string(APPEND CFLAGS " -vec-report") -string(APPEND FFLAGS " -vec-report") -if (DEBUG) - string(APPEND CMAKE_OPTS " -DPIO_ENABLE_LOGGING=ON") -endif() diff --git a/build/cmake_macros/intel_lawrencium-lr3.cmake b/build/cmake_macros/intel_lawrencium-lr3.cmake deleted file mode 100644 index 8830234902..0000000000 --- a/build/cmake_macros/intel_lawrencium-lr3.cmake +++ /dev/null @@ -1,12 +0,0 @@ -if (COMP_NAME STREQUAL gptl) - string(APPEND CPPDEFS " -DHAVE_VPRINTF -DHAVE_TIMES -DHAVE_GETTIMEOFDAY") -endif() -string(APPEND SLIBS " -lnetcdff -lnetcdf -mkl") -if (DEBUG) - string(APPEND FFLAGS " -ftrapuv") -endif() -if (DEBUG) - string(APPEND CFLAGS " -ftrapuv") -endif() -set(NETCDF_PATH "$ENV{NETCDF_DIR}") -set(LAPACK_LIBDIR "/global/software/sl-6.x86_64/modules/intel/2016.1.150/lapack/3.6.0-intel/lib") diff --git a/build/cmake_macros/intel_sandiatoss3.cmake b/build/cmake_macros/intel_sandiatoss3.cmake deleted file mode 100644 index 8356ac5e73..0000000000 --- a/build/cmake_macros/intel_sandiatoss3.cmake +++ /dev/null @@ -1,12 +0,0 @@ -if (NOT DEBUG) - string(APPEND CFLAGS " -O2") -endif() -set(CONFIG_ARGS "--host=cray") -set(ESMF_LIBDIR "/projects/ccsm/esmf-6.3.0rp1/lib/libO/Linux.intel.64.openmpi.default") -if (NOT DEBUG) - string(APPEND FFLAGS " -O2") -endif() -set(NETCDF_PATH "$ENV{NETCDFROOT}") -set(PIO_FILESYSTEM_HINTS "lustre") -set(PNETCDF_PATH "$ENV{PNETCDFROOT}") -string(APPEND SLIBS " -L${NETCDF_PATH}/lib -lnetcdff -L/projects/ccsm/BLAS-intel -lblas_LINUX") diff --git a/build/cmake_macros/intel_stampede2-knl.cmake b/build/cmake_macros/intel_stampede2-knl.cmake deleted file mode 100644 index 6cdd9fe9c1..0000000000 --- a/build/cmake_macros/intel_stampede2-knl.cmake +++ /dev/null @@ -1,10 +0,0 @@ -string(APPEND CFLAGS " -xCOMMON-AVX512 -no-fma") -string(APPEND FFLAGS " -xCOMMON-AVX512 -no-fma") -if (MPILIB STREQUAL mpi-serial) - string(APPEND FFLAGS " -mcmodel medium") -endif() -string(APPEND LDFLAGS " -L$ENV{TACC_HDF5_LIB} -lhdf5 $(MKL) -zmuldefs -xCOMMON-AVX512") -execute_process(COMMAND ${NETCDF_PATH}/bin/nf-config --flibs OUTPUT_VARIABLE SHELL_CMD_OUTPUT_BUILD_INTERNAL_IGNORE0 OUTPUT_STRIP_TRAILING_WHITESPACE) -string(APPEND SLIBS " ${SHELL_CMD_OUTPUT_BUILD_INTERNAL_IGNORE0} -L$ENV{TACC_HDF5_LIB} -lhdf5") -set(TRILINOS_PATH "$ENV{TRILINOS_PATH}") -set(HAS_F2008_CONTIGUOUS "FALSE") diff --git a/build/cmake_macros/intel_stampede2-skx.cmake b/build/cmake_macros/intel_stampede2-skx.cmake deleted file mode 100644 index 6cdd9fe9c1..0000000000 --- a/build/cmake_macros/intel_stampede2-skx.cmake +++ /dev/null @@ -1,10 +0,0 @@ -string(APPEND CFLAGS " -xCOMMON-AVX512 -no-fma") -string(APPEND FFLAGS " -xCOMMON-AVX512 -no-fma") -if (MPILIB STREQUAL mpi-serial) - string(APPEND FFLAGS " -mcmodel medium") -endif() -string(APPEND LDFLAGS " -L$ENV{TACC_HDF5_LIB} -lhdf5 $(MKL) -zmuldefs -xCOMMON-AVX512") -execute_process(COMMAND ${NETCDF_PATH}/bin/nf-config --flibs OUTPUT_VARIABLE SHELL_CMD_OUTPUT_BUILD_INTERNAL_IGNORE0 OUTPUT_STRIP_TRAILING_WHITESPACE) -string(APPEND SLIBS " ${SHELL_CMD_OUTPUT_BUILD_INTERNAL_IGNORE0} -L$ENV{TACC_HDF5_LIB} -lhdf5") -set(TRILINOS_PATH "$ENV{TRILINOS_PATH}") -set(HAS_F2008_CONTIGUOUS "FALSE") diff --git a/build/cmake_macros/intel_theia.cmake b/build/cmake_macros/intel_theia.cmake deleted file mode 100644 index 6a09fe8c2c..0000000000 --- a/build/cmake_macros/intel_theia.cmake +++ /dev/null @@ -1,4 +0,0 @@ -set(MPICC "mpiicc") -set(MPICXX "mpiicpc") -set(MPIFC "mpiifort") -set(NETCDF_PATH "/apps/netcdf/4.3.0-intel") diff --git a/build/cmake_macros/intel_zeus.cmake b/build/cmake_macros/intel_zeus.cmake deleted file mode 100644 index 281ae04b18..0000000000 --- a/build/cmake_macros/intel_zeus.cmake +++ /dev/null @@ -1,18 +0,0 @@ -set(AR "xiar") -set(ARFLAGS "cru") -if (MPILIB STREQUAL mpi-serial) - string(APPEND FFLAGS " -mcmodel medium") - string(APPEND FFLAGS " -mkl -xSKYLAKE-AVX512 -qopt-zmm-usage=high -no-fma") - string(APPEND CFLAGS " -mkl -xSKYLAKE-AVX512 -qopt-zmm-usage=high -no-fma") - string(APPEND LDFLAGS " -mkl -lstdc++") - string(APPEND SLIBS " -lstdc++") -endif() -if (MPILIB STREQUAL impi) - string(APPEND FFLAGS " -mkl=cluster -xSKYLAKE-AVX512 -qopt-zmm-usage=high -no-fma") - string(APPEND CFLAGS " -mkl=cluster -xSKYLAKE-AVX512 -qopt-zmm-usage=high -no-fma") - string(APPEND LDFLAGS " -mkl=cluster") - string(APPEND SLIBS " -lstdc++") -endif() -set(MPICC "mpiicc") -set(MPICXX "mpiicpc") -set(MPIFC "mpiifort") diff --git a/build/cmake_macros/izumi.cmake b/build/cmake_macros/izumi.cmake deleted file mode 100644 index 8894b6a383..0000000000 --- a/build/cmake_macros/izumi.cmake +++ /dev/null @@ -1,9 +0,0 @@ -if (COMP_NAME STREQUAL gptl) - string(APPEND CPPDEFS " -DHAVE_NANOTIME -DBIT64 -DHAVE_VPRINTF -DHAVE_BACKTRACE -DHAVE_SLASHPROC -DHAVE_COMM_F2C -DHAVE_TIMES -DHAVE_GETTIMEOFDAY") -endif() -set(LAPACK_LIBDIR "/usr/lib64") -if (MPILIB STREQUAL mvapich2) - set(MPI_LIB_NAME "mpich") -endif() -set(NETCDF_PATH "$ENV{NETCDF_PATH}") -string(APPEND SLIBS " -L${NETCDF_PATH}/lib -lnetcdff -lnetcdf") diff --git a/build/cmake_macros/laramie.cmake b/build/cmake_macros/laramie.cmake deleted file mode 100644 index 35c2d3c33e..0000000000 --- a/build/cmake_macros/laramie.cmake +++ /dev/null @@ -1,6 +0,0 @@ -if (COMP_NAME STREQUAL gptl) - string(APPEND CPPDEFS " -DHAVE_NANOTIME -DBIT64 -DHAVE_VPRINTF -DHAVE_BACKTRACE -DHAVE_SLASHPROC -DHAVE_COMM_F2C -DHAVE_TIMES -DHAVE_GETTIMEOFDAY") -endif() -set(NETCDF_PATH "$ENV{NETCDF}") -set(PIO_FILESYSTEM_HINTS "gpfs") -set(PNETCDF_PATH "$ENV{PNETCDF}") diff --git a/build/cmake_macros/lonestar5.cmake b/build/cmake_macros/lonestar5.cmake deleted file mode 100644 index 0c5eec8054..0000000000 --- a/build/cmake_macros/lonestar5.cmake +++ /dev/null @@ -1,6 +0,0 @@ -string(APPEND CPPDEFS " -DHAVE_NANOTIME") -set(NETCDF_PATH "$ENV{TACC_NETCDF_DIR}") -set(PIO_FILESYSTEM_HINTS "lustre") -set(PNETCDF_PATH "$ENV{TACC_PNETCDF_DIR}") -string(APPEND LDFLAGS " -Wl,-rpath,${NETCDF_PATH}/lib") -string(APPEND SLIBS " -L${NETCDF_PATH}/lib -lnetcdff -lnetcdf") diff --git a/build/cmake_macros/nag.cmake b/build/cmake_macros/nag.cmake deleted file mode 100644 index 6a2d97c87a..0000000000 --- a/build/cmake_macros/nag.cmake +++ /dev/null @@ -1,30 +0,0 @@ -string(APPEND CFLAGS " -std=gnu99") -if (DEBUG) - string(APPEND CFLAGS " -g") -endif() -string(APPEND CPPDEFS " -DFORTRANUNDERSCORE -DNO_CRAY_POINTERS -DNO_SHR_VMATH -DCPRNAG -DNO_R16") -set(FC_AUTO_R8 "-r8") -string(APPEND FFLAGS " -Wp,-macro=no_com -convert=BIG_ENDIAN ") -string(APPEND FFLAGS "-indirect ${SRCROOT}/ccs_config/machines/nag_mpi_argument.txt") -if (NOT DEBUG) - string(APPEND FFLAGS " -ieee=full -O2") -endif() -if (DEBUG) - string(APPEND FFLAGS " -C=all -g -time -f2003 -ieee=stop") -endif() -if (DEBUG AND NOT compile_threaded) - string(APPEND FFLAGS " -gline") -endif() -if (COMP_NAME STREQUAL cism) - string(APPEND FFLAGS " -mismatch_all") -endif() -set(FFLAGS_NOOPT "-O0") -set(FIXEDFLAGS "-fixed") -set(FREEFLAGS "-free") -set(HAS_F2008_CONTIGUOUS "FALSE") -set(MPICC "mpicc") -set(MPIFC "mpif90") -set(SCC "gcc") -set(SFC "nagfor") -string(APPEND LDFLAGS " -lpthread") -string(APPEND CONFIG_ARGS " FCLIBS='-Wl,--as-needed,--allow-shlib-undefined -L$(COMPILER_PATH)/lib/NAG_Fortran -lf62rts'") diff --git a/build/cmake_macros/nvhpc-gpu.cmake b/build/cmake_macros/nvhpc-gpu.cmake deleted file mode 100644 index 679e81b2f4..0000000000 --- a/build/cmake_macros/nvhpc-gpu.cmake +++ /dev/null @@ -1,46 +0,0 @@ -string(APPEND CFLAGS " -gopt -time") -if (compile_threaded) - string(APPEND CFLAGS " -mp") -endif() -string(APPEND CPPDEFS " -DFORTRANUNDERSCORE -DNO_SHR_VMATH -DNO_R16 -DCPRPGI") -set(CXX_LINKER "CXX") -set(FC_AUTO_R8 "-r8") -string(APPEND FFLAGS " -i4 -gopt -time -Mextend -byteswapio -Mflushz -Kieee") -if (compile_threaded) - string(APPEND FFLAGS " -mp") -endif() -if (DEBUG) - string(APPEND FFLAGS " -O0 -g -Ktrap=fp -Mbounds -Kieee") -endif() -if (COMP_NAME STREQUAL datm) - string(APPEND FFLAGS " -Mnovect") -endif() -if (COMP_NAME STREQUAL dlnd) - string(APPEND FFLAGS " -Mnovect") -endif() -if (COMP_NAME STREQUAL drof) - string(APPEND FFLAGS " -Mnovect") -endif() -if (COMP_NAME STREQUAL dwav) - string(APPEND FFLAGS " -Mnovect") -endif() -if (COMP_NAME STREQUAL dice) - string(APPEND FFLAGS " -Mnovect") -endif() -if (COMP_NAME STREQUAL docn) - string(APPEND FFLAGS " -Mnovect") -endif() -set(FFLAGS_NOOPT "-O0") -set(FIXEDFLAGS "-Mfixed") -set(FREEFLAGS "-Mfree") -set(HAS_F2008_CONTIGUOUS "FALSE") -set(LDFLAGS "-time -Wl,--allow-multiple-definition") -if (compile_threaded) - string(APPEND LDFLAGS " -mp") -endif() -set(MPICC "mpicc") -set(MPICXX "mpicxx") -set(MPIFC "mpif90") -set(SCC "nvc") -set(SCXX "nvc++") -set(SFC "nvfortran") diff --git a/build/cmake_macros/nvhpc-gpu_casper.cmake b/build/cmake_macros/nvhpc-gpu_casper.cmake deleted file mode 100644 index ed2adbc6c9..0000000000 --- a/build/cmake_macros/nvhpc-gpu_casper.cmake +++ /dev/null @@ -1,15 +0,0 @@ -if (NOT DEBUG) - string(APPEND CFLAGS " -O -tp=skylake -Mnofma") -endif() -if (NOT DEBUG) - string(APPEND FFLAGS " -O -tp=skylake -Mnofma") -endif() -string(APPEND FFLAGS " -I$(EXEROOT)/ocn/obj/FMS") -if (NOT DEBUG) - string(APPEND LDFLAGS " -O -tp=skylake -Mnofma -acc -gpu=cc70,lineinfo,nofma -Minfo=accel") -endif() -string(APPEND SLIBS " -llapack -lblas") -if (MPILIB STREQUAL mpi-serial) - string(APPEND SLIBS " -ldl") -endif() -string(APPEND SLIBS " -L${NETCDF_PATH}/lib -lnetcdf -lnetcdff") diff --git a/build/cmake_macros/nvhpc.cmake b/build/cmake_macros/nvhpc.cmake deleted file mode 100644 index 3e1b451624..0000000000 --- a/build/cmake_macros/nvhpc.cmake +++ /dev/null @@ -1,51 +0,0 @@ -string(APPEND CFLAGS " -gopt -time") -if (compile_threaded) - string(APPEND CFLAGS " -mp") -endif() -if (NOT DEBUG) - string(APPEND CFLAGS " -O ") - string(APPEND FFLAGS " -O -Mnofma") -endif() - -string(APPEND CPPDEFS " -DFORTRANUNDERSCORE -DNO_SHR_VMATH -DNO_R16 -DCPRPGI") -set(CXX_LINKER "CXX") -set(FC_AUTO_R8 "-r8") -string(APPEND FFLAGS " -i4 -gopt -time -Mextend -byteswapio -Mflushz -Kieee") -if (compile_threaded) - string(APPEND FFLAGS " -mp") -endif() -if (DEBUG) - string(APPEND FFLAGS " -O0 -g -Ktrap=fp -Mbounds -Kieee") -endif() -if (COMP_NAME STREQUAL datm) - string(APPEND FFLAGS " -Mnovect") -endif() -if (COMP_NAME STREQUAL dlnd) - string(APPEND FFLAGS " -Mnovect") -endif() -if (COMP_NAME STREQUAL drof) - string(APPEND FFLAGS " -Mnovect") -endif() -if (COMP_NAME STREQUAL dwav) - string(APPEND FFLAGS " -Mnovect") -endif() -if (COMP_NAME STREQUAL dice) - string(APPEND FFLAGS " -Mnovect") -endif() -if (COMP_NAME STREQUAL docn) - string(APPEND FFLAGS " -Mnovect") -endif() -set(FFLAGS_NOOPT "-O0") -set(FIXEDFLAGS "-Mfixed") -set(FREEFLAGS "-Mfree") -set(HAS_F2008_CONTIGUOUS "FALSE") -set(LDFLAGS "-time -Wl,--allow-multiple-definition") -if (compile_threaded) - string(APPEND LDFLAGS " -mp") -endif() -set(MPICC "mpicc") -set(MPICXX "mpicxx") -set(MPIFC "mpif90") -set(SCC "nvc") -set(SCXX "nvc++") -set(SFC "nvfortran") diff --git a/build/cmake_macros/nvhpc_casper.cmake b/build/cmake_macros/nvhpc_casper.cmake deleted file mode 100644 index f3eb207d1e..0000000000 --- a/build/cmake_macros/nvhpc_casper.cmake +++ /dev/null @@ -1,15 +0,0 @@ -if (NOT DEBUG) - string(APPEND CFLAGS " -O -tp=skylake -Mnofma") -endif() -if (NOT DEBUG) - string(APPEND FFLAGS " -O -tp=skylake -Mnofma") -endif() -string(APPEND FFLAGS " -I$(EXEROOT)/ocn/obj/FMS") -if (NOT DEBUG) - string(APPEND LDFLAGS " -O -tp=skylake -Mnofma") -endif() -string(APPEND SLIBS " -llapack -lblas") -if (MPILIB STREQUAL mpi-serial) - string(APPEND SLIBS " -ldl") -endif() -string(APPEND SLIBS " -L${NETCDF_PATH}/lib -lnetcdf -lnetcdff") diff --git a/build/cmake_macros/nvhpc_cheyenne.cmake b/build/cmake_macros/nvhpc_cheyenne.cmake deleted file mode 100644 index e3769dd9d7..0000000000 --- a/build/cmake_macros/nvhpc_cheyenne.cmake +++ /dev/null @@ -1,4 +0,0 @@ -string(APPEND SLIBS " -llapack -lblas") -if (MPILIB STREQUAL mpi-serial) - string(APPEND SLIBS " -ldl") -endif() diff --git a/build/cmake_macros/nvhpc_gust.cmake b/build/cmake_macros/nvhpc_gust.cmake deleted file mode 100644 index 461137315d..0000000000 --- a/build/cmake_macros/nvhpc_gust.cmake +++ /dev/null @@ -1,3 +0,0 @@ -if (NOT DEBUG) - string(APPEND FFLAGS " -target=zen3") -endif() diff --git a/build/cmake_macros/oneapi.cmake b/build/cmake_macros/oneapi.cmake deleted file mode 100644 index 7328c85e30..0000000000 --- a/build/cmake_macros/oneapi.cmake +++ /dev/null @@ -1,61 +0,0 @@ -string(APPEND CFLAGS " -qno-opt-dynamic-align -fp-model precise -std=gnu99") -if (compile_threaded) - string(APPEND CFLAGS " -qopenmp") -endif() -if (NOT DEBUG) - string(APPEND CFLAGS " -O2 -debug minimal") -endif() -if (DEBUG) - string(APPEND CFLAGS " -O0 -g") -endif() -string(APPEND CPPDEFS " -DFORTRANUNDERSCORE -DCPRINTEL") -string(APPEND CXX_LDFLAGS " -cxxlib") -set(CXX_LINKER "FORTRAN") -set(FC_AUTO_R8 "-r8") -string(APPEND FFLAGS " -qno-opt-dynamic-align -convert big_endian -assume byterecl -ftz -traceback -assume realloc_lhs -fp-model source") -if (compile_threaded) - string(APPEND FFLAGS " -qopenmp") -endif() -if (DEBUG) - string(APPEND FFLAGS " -O0 -g -check uninit -check bounds -check pointers -fpe0 -check noarg_temp_created") -endif() -if (NOT DEBUG) - string(APPEND FFLAGS " -O2 -debug minimal") -endif() -set(FFLAGS_NOOPT "-O0") -set(FIXEDFLAGS "-fixed") -set(FREEFLAGS "-free") -if (compile_threaded) - string(APPEND LDFLAGS " -qopenmp") -endif() -set(MPICC "mpicc") -set(MPICXX "mpicxx") -set(MPIFC "mpif90") -set(SCC "icc") -set(SCXX "icpc") -set(SFC "ifort") -if (MPILIB STREQUAL mpich) - string(APPEND SLIBS " -mkl=cluster") -endif() -if (MPILIB STREQUAL mpich2) - string(APPEND SLIBS " -mkl=cluster") -endif() -if (MPILIB STREQUAL mvapich) - string(APPEND SLIBS " -mkl=cluster") -endif() -if (MPILIB STREQUAL mvapich2) - string(APPEND SLIBS " -mkl=cluster") -endif() -if (MPILIB STREQUAL mpt) - string(APPEND SLIBS " -mkl=cluster") -endif() -if (MPILIB STREQUAL openmpi) - string(APPEND SLIBS " -mkl=cluster") -endif() -if (MPILIB STREQUAL impi) - string(APPEND SLIBS " -mkl=cluster") -endif() -if (MPILIB STREQUAL mpi-serial) - string(APPEND SLIBS " -mkl") -endif() -set(SUPPORTS_CXX "TRUE") diff --git a/build/cmake_macros/pgi-gpu.cmake b/build/cmake_macros/pgi-gpu.cmake deleted file mode 100644 index 856574795e..0000000000 --- a/build/cmake_macros/pgi-gpu.cmake +++ /dev/null @@ -1,46 +0,0 @@ -string(APPEND CFLAGS " -gopt -time") -if (compile_threaded) - string(APPEND CFLAGS " -mp") -endif() -string(APPEND CPPDEFS " -DFORTRANUNDERSCORE -DNO_SHR_VMATH -DNO_R16 -DCPRPGI") -set(CXX_LINKER "CXX") -set(FC_AUTO_R8 "-r8") -string(APPEND FFLAGS " -i4 -gopt -time -Mextend -byteswapio -Mflushz -Kieee") -if (compile_threaded) - string(APPEND FFLAGS " -mp") -endif() -if (DEBUG) - string(APPEND FFLAGS " -O0 -g -Ktrap=fp -Mbounds -Kieee") -endif() -if (COMP_NAME STREQUAL datm) - string(APPEND FFLAGS " -Mnovect") -endif() -if (COMP_NAME STREQUAL dlnd) - string(APPEND FFLAGS " -Mnovect") -endif() -if (COMP_NAME STREQUAL drof) - string(APPEND FFLAGS " -Mnovect") -endif() -if (COMP_NAME STREQUAL dwav) - string(APPEND FFLAGS " -Mnovect") -endif() -if (COMP_NAME STREQUAL dice) - string(APPEND FFLAGS " -Mnovect") -endif() -if (COMP_NAME STREQUAL docn) - string(APPEND FFLAGS " -Mnovect") -endif() -set(FFLAGS_NOOPT "-O0") -set(FIXEDFLAGS "-Mfixed") -set(FREEFLAGS "-Mfree") -set(HAS_F2008_CONTIGUOUS "FALSE") -set(LDFLAGS "-time -Wl,--allow-multiple-definition") -if (compile_threaded) - string(APPEND LDFLAGS " -mp") -endif() -set(MPICC "mpicc") -set(MPICXX "mpicxx") -set(MPIFC "mpif90") -set(SCC "pgcc") -set(SCXX "pgc++") -set(SFC "pgf95") diff --git a/build/cmake_macros/pgi-gpu_casper.cmake b/build/cmake_macros/pgi-gpu_casper.cmake deleted file mode 100644 index 600521a1bb..0000000000 --- a/build/cmake_macros/pgi-gpu_casper.cmake +++ /dev/null @@ -1,15 +0,0 @@ -if (NOT DEBUG) - string(APPEND CFLAGS " -O -tp=skylake -Mnofma") -endif() -if (NOT DEBUG) - string(APPEND FFLAGS " -O -tp=skylake -Mnofma") -endif() -string(APPEND FFLAGS " -I$(EXEROOT)/ocn/obj/FMS") -if (NOT DEBUG) - string(APPEND LDFLAGS " -O -tp=skylake -Mnofma -acc -ta=tesla:cc70,lineinfo,nofma -Minfo=accel") -endif() -string(APPEND SLIBS " -llapack -lblas") -if (MPILIB STREQUAL mpi-serial) - string(APPEND SLIBS " -ldl") -endif() -string(APPEND SLIBS " -L${NETCDF_PATH}/lib -lnetcdf -lnetcdff") diff --git a/build/cmake_macros/pgi.cmake b/build/cmake_macros/pgi.cmake deleted file mode 100644 index 856574795e..0000000000 --- a/build/cmake_macros/pgi.cmake +++ /dev/null @@ -1,46 +0,0 @@ -string(APPEND CFLAGS " -gopt -time") -if (compile_threaded) - string(APPEND CFLAGS " -mp") -endif() -string(APPEND CPPDEFS " -DFORTRANUNDERSCORE -DNO_SHR_VMATH -DNO_R16 -DCPRPGI") -set(CXX_LINKER "CXX") -set(FC_AUTO_R8 "-r8") -string(APPEND FFLAGS " -i4 -gopt -time -Mextend -byteswapio -Mflushz -Kieee") -if (compile_threaded) - string(APPEND FFLAGS " -mp") -endif() -if (DEBUG) - string(APPEND FFLAGS " -O0 -g -Ktrap=fp -Mbounds -Kieee") -endif() -if (COMP_NAME STREQUAL datm) - string(APPEND FFLAGS " -Mnovect") -endif() -if (COMP_NAME STREQUAL dlnd) - string(APPEND FFLAGS " -Mnovect") -endif() -if (COMP_NAME STREQUAL drof) - string(APPEND FFLAGS " -Mnovect") -endif() -if (COMP_NAME STREQUAL dwav) - string(APPEND FFLAGS " -Mnovect") -endif() -if (COMP_NAME STREQUAL dice) - string(APPEND FFLAGS " -Mnovect") -endif() -if (COMP_NAME STREQUAL docn) - string(APPEND FFLAGS " -Mnovect") -endif() -set(FFLAGS_NOOPT "-O0") -set(FIXEDFLAGS "-Mfixed") -set(FREEFLAGS "-Mfree") -set(HAS_F2008_CONTIGUOUS "FALSE") -set(LDFLAGS "-time -Wl,--allow-multiple-definition") -if (compile_threaded) - string(APPEND LDFLAGS " -mp") -endif() -set(MPICC "mpicc") -set(MPICXX "mpicxx") -set(MPIFC "mpif90") -set(SCC "pgcc") -set(SCXX "pgc++") -set(SFC "pgf95") diff --git a/build/cmake_macros/pgi_bluewaters.cmake b/build/cmake_macros/pgi_bluewaters.cmake deleted file mode 100644 index ff5f160388..0000000000 --- a/build/cmake_macros/pgi_bluewaters.cmake +++ /dev/null @@ -1,10 +0,0 @@ -if (NOT DEBUG) - string(APPEND CFLAGS " -O2") -endif() -string(APPEND CFLAGS " -nofma") -set(CXX_LIBS "-lmpichf90_pgi $ENV{PGI_PATH}/linux86-64/$ENV{PGI_VERSION}/lib/f90main.o") -if (NOT DEBUG) - string(APPEND FFLAGS " -O2") -endif() -string(APPEND FFLAGS " -nofma") -set(SUPPORTS_CXX "TRUE") diff --git a/build/cmake_macros/pgi_casper.cmake b/build/cmake_macros/pgi_casper.cmake deleted file mode 100644 index f3eb207d1e..0000000000 --- a/build/cmake_macros/pgi_casper.cmake +++ /dev/null @@ -1,15 +0,0 @@ -if (NOT DEBUG) - string(APPEND CFLAGS " -O -tp=skylake -Mnofma") -endif() -if (NOT DEBUG) - string(APPEND FFLAGS " -O -tp=skylake -Mnofma") -endif() -string(APPEND FFLAGS " -I$(EXEROOT)/ocn/obj/FMS") -if (NOT DEBUG) - string(APPEND LDFLAGS " -O -tp=skylake -Mnofma") -endif() -string(APPEND SLIBS " -llapack -lblas") -if (MPILIB STREQUAL mpi-serial) - string(APPEND SLIBS " -ldl") -endif() -string(APPEND SLIBS " -L${NETCDF_PATH}/lib -lnetcdf -lnetcdff") diff --git a/build/cmake_macros/pgi_cheyenne.cmake b/build/cmake_macros/pgi_cheyenne.cmake deleted file mode 100644 index e3769dd9d7..0000000000 --- a/build/cmake_macros/pgi_cheyenne.cmake +++ /dev/null @@ -1,4 +0,0 @@ -string(APPEND SLIBS " -llapack -lblas") -if (MPILIB STREQUAL mpi-serial) - string(APPEND SLIBS " -ldl") -endif() diff --git a/build/cmake_macros/pgi_constance.cmake b/build/cmake_macros/pgi_constance.cmake deleted file mode 100644 index 1a1dcf69b3..0000000000 --- a/build/cmake_macros/pgi_constance.cmake +++ /dev/null @@ -1,11 +0,0 @@ -if (NOT DEBUG) - string(APPEND CFLAGS " -O2") -endif() -set(CONFIG_ARGS "--host=cray") -string(APPEND CPPDEFS " -DLINUX") -if (NOT DEBUG) - string(APPEND FFLAGS " -O2") -endif() -set(NETCDF_PATH "$ENV{NETCDF_HOME}") -set(PIO_FILESYSTEM_HINTS "lustre") -set(SLIBS "-L${NETCDF_PATH}/lib -lnetcdf -lnetcdff -lpmi") diff --git a/build/cmake_macros/pgi_daint.cmake b/build/cmake_macros/pgi_daint.cmake deleted file mode 100644 index 9c9661883e..0000000000 --- a/build/cmake_macros/pgi_daint.cmake +++ /dev/null @@ -1,3 +0,0 @@ -string(APPEND FFLAGS " -I/project/s824/edavin/OASIS3-MCT_2.0/build.pgi/build/lib/mct -I/project/s824/edavin/OASIS3-MCT_2.0/build.pgi/build/lib/psmile.MPI1") -string(APPEND SLIBS " -llapack -lblas") -string(APPEND SLIBS " -L/project/s824/edavin/OASIS3-MCT_2.0/build.pgi/lib -lpsmile.MPI1 -lscrip -lmct_oasis -lmpeu_oasis") diff --git a/build/cmake_macros/pgi_eastwind.cmake b/build/cmake_macros/pgi_eastwind.cmake deleted file mode 100644 index 6384e42c21..0000000000 --- a/build/cmake_macros/pgi_eastwind.cmake +++ /dev/null @@ -1,20 +0,0 @@ -if (NOT DEBUG) - string(APPEND CFLAGS " -O2") -endif() -if (NOT compile_threaded) - string(APPEND CFLAGS " -nomp") -endif() -set(CONFIG_ARGS "--host=cray") -string(APPEND CPPDEFS " -DLINUX") -if (NOT DEBUG) - string(APPEND FFLAGS " -O2") -endif() -if (NOT compile_threaded) - string(APPEND FFLAGS " -nomp") -endif() -if (NOT compile_threaded) - string(APPEND LDFLAGS " -nomp") -endif() -set(NETCDF_PATH "$ENV{NETCDF_HOME}") -set(PIO_FILESYSTEM_HINTS "lustre") -set(SLIBS "-L${NETCDF_PATH}/lib -lnetcdf -lnetcdff -lpmi") diff --git a/build/cmake_macros/pgi_euler2.cmake b/build/cmake_macros/pgi_euler2.cmake deleted file mode 100644 index be865e50f9..0000000000 --- a/build/cmake_macros/pgi_euler2.cmake +++ /dev/null @@ -1,6 +0,0 @@ -if (NOT DEBUG) - string(APPEND CFLAGS " -O2") -endif() -if (NOT DEBUG) - string(APPEND FFLAGS " -O2") -endif() diff --git a/build/cmake_macros/pgi_euler3.cmake b/build/cmake_macros/pgi_euler3.cmake deleted file mode 100644 index be865e50f9..0000000000 --- a/build/cmake_macros/pgi_euler3.cmake +++ /dev/null @@ -1,6 +0,0 @@ -if (NOT DEBUG) - string(APPEND CFLAGS " -O2") -endif() -if (NOT DEBUG) - string(APPEND FFLAGS " -O2") -endif() diff --git a/build/cmake_macros/pgi_euler4.cmake b/build/cmake_macros/pgi_euler4.cmake deleted file mode 100644 index be865e50f9..0000000000 --- a/build/cmake_macros/pgi_euler4.cmake +++ /dev/null @@ -1,6 +0,0 @@ -if (NOT DEBUG) - string(APPEND CFLAGS " -O2") -endif() -if (NOT DEBUG) - string(APPEND FFLAGS " -O2") -endif() diff --git a/build/cmake_macros/pgi_hobart.cmake b/build/cmake_macros/pgi_hobart.cmake deleted file mode 100644 index d3daece90a..0000000000 --- a/build/cmake_macros/pgi_hobart.cmake +++ /dev/null @@ -1,10 +0,0 @@ -if (NOT DEBUG) - string(APPEND CFLAGS " -O0") -endif() -if (NOT DEBUG) - string(APPEND FFLAGS " -O0") -endif() -string(APPEND LDFLAGS " -lgomp") -string(APPEND LDFLAGS " -Wl,-R${NETCDF_PATH}/lib") -string(APPEND LDFLAGS " -Wl,-R$ENV{COMPILER_PATH}/lib") -string(APPEND LDFLAGS " -Wl,-R$ENV{COMPILER_PATH}/libso") diff --git a/build/cmake_macros/pgi_izumi.cmake b/build/cmake_macros/pgi_izumi.cmake deleted file mode 100644 index 3cb6b34e86..0000000000 --- a/build/cmake_macros/pgi_izumi.cmake +++ /dev/null @@ -1,2 +0,0 @@ -set(CXX_LINKER "FORTRAN") -set(SUPPORTS_CXX "TRUE") diff --git a/build/cmake_macros/pgi_olympus.cmake b/build/cmake_macros/pgi_olympus.cmake deleted file mode 100644 index 1ee0816812..0000000000 --- a/build/cmake_macros/pgi_olympus.cmake +++ /dev/null @@ -1,11 +0,0 @@ -if (NOT DEBUG) - string(APPEND CFLAGS " -O2") -endif() -set(CONFIG_ARGS "--host=cray") -string(APPEND CPPDEFS " -DLINUX") -if (NOT DEBUG) - string(APPEND FFLAGS " -O2") -endif() -set(NETCDF_PATH "$ENV{NETCDF_LIB}/..") -set(PIO_FILESYSTEM_HINTS "lustre") -set(SLIBS "-L${NETCDF_PATH}/lib -lnetcdf -lnetcdff -lpmi") diff --git a/build/cmake_macros/pleiades-bro.cmake b/build/cmake_macros/pleiades-bro.cmake deleted file mode 100644 index f3e3bf82dd..0000000000 --- a/build/cmake_macros/pleiades-bro.cmake +++ /dev/null @@ -1,6 +0,0 @@ -string(APPEND CFLAGS " -axCORE-AVX2 -xSSE4.2 -no-fma") -string(APPEND FFLAGS " -axCORE-AVX2 -xSSE4.2 -no-fma") -set(MPICC "icc") -set(MPI_PATH "$ENV{MPI_ROOT}") -set(NETCDF_PATH "$ENV{NETCDF}") -set(PNETCDF_PATH "/home6/fvitt/pnetcdf/pnetcdf-1.12.2") diff --git a/build/cmake_macros/pleiades-has.cmake b/build/cmake_macros/pleiades-has.cmake deleted file mode 100644 index f3e3bf82dd..0000000000 --- a/build/cmake_macros/pleiades-has.cmake +++ /dev/null @@ -1,6 +0,0 @@ -string(APPEND CFLAGS " -axCORE-AVX2 -xSSE4.2 -no-fma") -string(APPEND FFLAGS " -axCORE-AVX2 -xSSE4.2 -no-fma") -set(MPICC "icc") -set(MPI_PATH "$ENV{MPI_ROOT}") -set(NETCDF_PATH "$ENV{NETCDF}") -set(PNETCDF_PATH "/home6/fvitt/pnetcdf/pnetcdf-1.12.2") diff --git a/build/cmake_macros/pleiades-ivy.cmake b/build/cmake_macros/pleiades-ivy.cmake deleted file mode 100644 index f3e3bf82dd..0000000000 --- a/build/cmake_macros/pleiades-ivy.cmake +++ /dev/null @@ -1,6 +0,0 @@ -string(APPEND CFLAGS " -axCORE-AVX2 -xSSE4.2 -no-fma") -string(APPEND FFLAGS " -axCORE-AVX2 -xSSE4.2 -no-fma") -set(MPICC "icc") -set(MPI_PATH "$ENV{MPI_ROOT}") -set(NETCDF_PATH "$ENV{NETCDF}") -set(PNETCDF_PATH "/home6/fvitt/pnetcdf/pnetcdf-1.12.2") diff --git a/build/cmake_macros/pleiades-san.cmake b/build/cmake_macros/pleiades-san.cmake deleted file mode 100644 index f3e3bf82dd..0000000000 --- a/build/cmake_macros/pleiades-san.cmake +++ /dev/null @@ -1,6 +0,0 @@ -string(APPEND CFLAGS " -axCORE-AVX2 -xSSE4.2 -no-fma") -string(APPEND FFLAGS " -axCORE-AVX2 -xSSE4.2 -no-fma") -set(MPICC "icc") -set(MPI_PATH "$ENV{MPI_ROOT}") -set(NETCDF_PATH "$ENV{NETCDF}") -set(PNETCDF_PATH "/home6/fvitt/pnetcdf/pnetcdf-1.12.2") diff --git a/build/cmake_macros/stampede2-knl.cmake b/build/cmake_macros/stampede2-knl.cmake deleted file mode 100644 index ed1c0d299b..0000000000 --- a/build/cmake_macros/stampede2-knl.cmake +++ /dev/null @@ -1,4 +0,0 @@ -string(APPEND CPPDEFS " -DHAVE_NANOTIME") -set(NETCDF_PATH "$ENV{TACC_NETCDF_DIR}") -set(PIO_FILESYSTEM_HINTS "lustre") -set(PNETCDF_PATH "$ENV{TACC_PNETCDF_DIR}") diff --git a/build/cmake_macros/stampede2-skx.cmake b/build/cmake_macros/stampede2-skx.cmake deleted file mode 100644 index ed1c0d299b..0000000000 --- a/build/cmake_macros/stampede2-skx.cmake +++ /dev/null @@ -1,4 +0,0 @@ -string(APPEND CPPDEFS " -DHAVE_NANOTIME") -set(NETCDF_PATH "$ENV{TACC_NETCDF_DIR}") -set(PIO_FILESYSTEM_HINTS "lustre") -set(PNETCDF_PATH "$ENV{TACC_PNETCDF_DIR}") diff --git a/build/cmake_macros/theta.cmake b/build/cmake_macros/theta.cmake deleted file mode 100644 index 81db81ed2c..0000000000 --- a/build/cmake_macros/theta.cmake +++ /dev/null @@ -1,4 +0,0 @@ -string(APPEND CFLAGS " -xMIC-AVX512") -string(APPEND FFLAGS " -xMIC-AVX512") -set(CONFIG_ARGS "--host=cray") -string(APPEND SLIBS " -L$(NETCDF_DIR)/lib -lnetcdff -L$(NETCDF_DIR)/lib -lnetcdf -Wl,-rpath -Wl,$(NETCDF_DIR)/lib") diff --git a/build/cmake_macros/universal.cmake b/build/cmake_macros/universal.cmake deleted file mode 100644 index a1acb1ac17..0000000000 --- a/build/cmake_macros/universal.cmake +++ /dev/null @@ -1,18 +0,0 @@ -string(APPEND CPPDEFS " -DCESMCOUPLED") -if (COMP_NAME STREQUAL pop) - string(APPEND CPPDEFS " -D_USE_FLOW_CONTROL") -endif() -if (COMP_NAME STREQUAL ufsatm) - string(APPEND CPPDEFS " -DSPMD") -endif() -if (COMP_NAME STREQUAL ufsatm) - string(APPEND INCLDIR " -I$(EXEROOT)/atm/obj/FMS") -endif() -if (COMP_NAME STREQUAL ufsatm) - string(APPEND FFLAGS " $(FC_AUTO_R8)") -endif() -if (COMP_NAME STREQUAL mom) - string(APPEND FFLAGS " $(FC_AUTO_R8) ") - string(APPEND CPPDEFS " -Duse_LARGEFILE") -endif() -set(SUPPORTS_CXX "FALSE") diff --git a/build/cmake_macros/userdefined.cmake b/build/cmake_macros/userdefined.cmake deleted file mode 100644 index 798dcc9714..0000000000 --- a/build/cmake_macros/userdefined.cmake +++ /dev/null @@ -1,9 +0,0 @@ -set(CONFIG_ARGS "") -string(APPEND CPPDEFS " ") -set(ESMF_LIBDIR "") -set(MPI_LIB_NAME "") -set(MPI_PATH "") -set(NETCDF_PATH "USERDEFINED_MUST_EDIT_THIS") -set(PNETCDF_PATH "") -execute_process(COMMAND ${NETCDF_PATH}/bin/nc-config --flibs OUTPUT_VARIABLE SHELL_CMD_OUTPUT_BUILD_INTERNAL_IGNORE0 OUTPUT_STRIP_TRAILING_WHITESPACE) -string(APPEND SLIBS " # USERDEFINED ${SHELL_CMD_OUTPUT_BUILD_INTERNAL_IGNORE0}") diff --git a/build/cmake_macros/zeus.cmake b/build/cmake_macros/zeus.cmake deleted file mode 100644 index 8c24e3dc9b..0000000000 --- a/build/cmake_macros/zeus.cmake +++ /dev/null @@ -1,8 +0,0 @@ -set(PIO_FILESYSTEM_HINTS "gpfs") -set(NETCDF_PATH "$ENV{NETCDF}") -set(PNETCDF_PATH "$ENV{PNETCDF}") -string(APPEND CPPDEFS " -DNO_R16 -DHAVE_NANOTIME") -if (COMP_NAME STREQUAL nemo) - string(APPEND FFLAGS " $(FC_AUTO_R8) -O3 -assume norealloc_lhs") -endif() -execute_process(COMMAND ${NETCDF_PATH}/bin/nc-config --flibs) diff --git a/build/env_mach_specific.xml b/build/env_mach_specific.xml deleted file mode 100644 index dc1c9f88e9..0000000000 --- a/build/env_mach_specific.xml +++ /dev/null @@ -1,32 +0,0 @@ - - -
- These variables control the machine dependent environment including - the paths to compilers and libraries external to cime such as netcdf, - environment variables for use in the running job should also be set here. -
- - - char - executable name - - - char - redirect for job output - - - - - /Users/afoster/esmf/esmf-8.4.0/lib/libg/Darwin.gfortranclang.64.openmpi.default/esmf.mk - - - mpirun - - -np $TOTALPES - --tag-output - - - - - -
From 5dd504fbeaaf59ffc51d3321f17d2758fd78c271 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Thu, 13 Apr 2023 22:40:45 -0600 Subject: [PATCH 640/852] updates to add more modules --- CMakeLists.txt | 49 ++- main/CMakeLists.txt | 12 +- main/EDPftvarcon.F90 | 1 - parteh/CMakeLists.txt | 6 + unit_testing/radiation_test/CMakeLists.txt | 29 ++ unit_testing/radiation_test/FATES_rad_test | Bin 0 -> 73392 bytes .../radiation_test/FatesUnitTestRadiation.F90 | 235 +++++++++++++ unit_testing/radiation_test/log.txt | 1 + .../{test => }/radiation_test/radiation_nl | 1 - unit_testing/run_FATES_tests.py | 35 ++ unit_testing/test/CMakeLists.txt | 1 - .../test/radiation_test/CMakeLists.txt | 40 --- .../radiation_test/FatesUnitTestRadiation.F90 | 122 ------- unit_testing/utils/FatesUnitTestIOMod.F90 | 321 +++++++----------- 14 files changed, 464 insertions(+), 389 deletions(-) create mode 100644 parteh/CMakeLists.txt create mode 100644 unit_testing/radiation_test/CMakeLists.txt create mode 100755 unit_testing/radiation_test/FATES_rad_test create mode 100644 unit_testing/radiation_test/FatesUnitTestRadiation.F90 create mode 100644 unit_testing/radiation_test/log.txt rename unit_testing/{test => }/radiation_test/radiation_nl (96%) create mode 100644 unit_testing/run_FATES_tests.py delete mode 100644 unit_testing/test/CMakeLists.txt delete mode 100644 unit_testing/test/radiation_test/CMakeLists.txt delete mode 100644 unit_testing/test/radiation_test/FatesUnitTestRadiation.F90 diff --git a/CMakeLists.txt b/CMakeLists.txt index 213a44115a..6a640e8bb7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,42 +1,39 @@ cmake_minimum_required(VERSION 3.4) -project(radiation_tests Fortran C) +list(APPEND CMAKE_MODULE_PATH ${CIME_CMAKE_MODULE_DIRECTORY}) +include(CIME_initial_setup) + +project(FATES_tests Fortran C) enable_language(Fortran) -list(APPEND CMAKE_MODULE_PATH ${CIME_CMAKE_MODULE_DIRECTORY}) -include(CIME_initial_setup) include(CIME_utils) set(CLM_ROOT "../../") -add_subdirectory(${CLM_ROOT}/src/fates/main) -add_subdirectory(${CLM_ROOT}/src/fates/unit_testing/utils) -add_subdirectory(${CLM_ROOT}/src/fates/unit_testing/test) -set(NETCDF_C_DIR "/usr/local/Cellar/netcdf/4.9.2") -set(NETCDF_FORTRAN_DIR "/usr/local/Cellar/netcdf-fortran/4.6.0") -MESSAGE(">> CISM_NETCDF_C_DIR set to : ${NETCDF_C_DIR}") -MESSAGE(">> CISM_NETCDF_FORTRAN_DIR set to : ${NETCDF_FORTRAN_DIR}") +# Add source directories from other share code (csm_share, etc.) +add_subdirectory(${CLM_ROOT}/share/src csm_share) -FIND_PATH(NETCDFC_FOUND libnetcdf.a ${NETCDF_C_DIR}/lib) -FIND_PATH(NETCDFF_FOUND libnetcdff.a ${NETCDF_FORTRAN_DIR}/lib) -MESSAGE(" NETCDFC_FOUND = ${NETCDFC_FOUND}") -MESSAGE(" NETCDFF_FOUND = ${NETCDFF_FOUND}") +# Add FATES source directories +add_subdirectory(${CLM_ROOT}/src/fates/main fates_main) +add_subdirectory(${CLM_ROOT}/src/fates/parteh fates_parteh) +add_subdirectory(${CLM_ROOT}/src/fates/unit_testing/utils fates_test_utils) -IF (${NETCDFC_FOUND} STREQUAL ${NETCDF_C_DIR}/lib ) - SET(NETCDF_C_LIBS "netcdff;netcdf" CACHE STRING "Netcdf Library Names(s)") -ELSE() - SET(NETCDF_C_LIBS "netcdf" CACHE STRING "Netcdf Library Names(s)") -ENDIF() -MESSAGE(">> NETCDF_LIBS Library(s) set to : ${NETCDF_C_LIBS}") +# Build libraries containing stuff needed for the unit tests. +# Eventually, these add_library calls should probably be distributed into the correct location, rather than being in this top-level CMakeLists.txt file. +add_library(csm_share ${share_sources}) +declare_generated_dependencies(csm_share "${share_genf90_sources}") +add_library(fates ${fates_sources}) +add_library(utils ${utils_sources}) +add_dependencies(fates csm_share) -include_directories(${NETCDF_C_DIR}/include - ${NETCDF_FORTRAN_DIR}/include) -link_directories(${NETCDF_C_DIR}/lib - ${NETCDF_FORTRAN_DIR}/lib) +add_subdirectory(${CLM_ROOT}/src/fates/unit_testing/radiation_test fates_testing) -add_library(utils ${utils_sources}) +# We need to look for header files here, in order to pick up shr_assert.h +include_directories(${CLM_ROOT}/share/include) include_directories(${CMAKE_CURRENT_BINARY_DIR}) -link_directories(${CMAKE_CURRENT_BINARY_DIR}) \ No newline at end of file +link_directories(${CMAKE_CURRENT_BINARY_DIR}) + +# Add the test directories diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 2d7863eb91..8c65b32513 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -11,8 +11,14 @@ list(APPEND clm_sources FatesUtilsMod.F90 ) -list(APPEND utils_sources - FatesConstantsMod.F90) +list(APPEND fates_sources + FatesConstantsMod.F90 + EDPftvarcon.F90 + EDParamsMod.F90 + FatesGlobals.F90 + FatesInterfaceTypesMod.F90 + FatesParametersInterface.F90 + ) sourcelist_to_parent(clm_sources) -sourcelist_to_parent(utils_sources) +sourcelist_to_parent(fates_sources) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index ad6c87c38c..2b7eda73e2 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -7,7 +7,6 @@ module EDPftvarcon ! ! !USES: use EDParamsMod , only : maxSWb, ivis, inir - use EDParamsMod , only : n_uptake_mode, p_uptake_mode use FatesConstantsMod, only : r8 => fates_r8 use FatesConstantsMod, only : nearzero use FatesConstantsMod, only : itrue, ifalse diff --git a/parteh/CMakeLists.txt b/parteh/CMakeLists.txt new file mode 100644 index 0000000000..218608e794 --- /dev/null +++ b/parteh/CMakeLists.txt @@ -0,0 +1,6 @@ +list(APPEND fates_sources + PRTGenericMod.F90 + PRTParametersMod.F90 + ) + + sourcelist_to_parent(fates_sources) \ No newline at end of file diff --git a/unit_testing/radiation_test/CMakeLists.txt b/unit_testing/radiation_test/CMakeLists.txt new file mode 100644 index 0000000000..2d72ae6b9b --- /dev/null +++ b/unit_testing/radiation_test/CMakeLists.txt @@ -0,0 +1,29 @@ +# Local files +set(rad_sources FatesUnitTestRadiation.F90) + +set(NETCDF_C_DIR "/usr/local/Cellar/netcdf/4.9.2") +set(NETCDF_FORTRAN_DIR "/usr/local/Cellar/netcdf-fortran/4.6.0") + +FIND_PATH(NETCDFC_FOUND libnetcdf.a ${NETCDF_C_DIR}/lib) +FIND_PATH(NETCDFF_FOUND libnetcdff.a ${NETCDF_FORTRAN_DIR}/lib) +MESSAGE(" NETCDFC_FOUND = ${NETCDFC_FOUND}") +MESSAGE(" NETCDFF_FOUND = ${NETCDFF_FOUND}") + +include_directories(${NETCDF_C_DIR}/include + ${NETCDF_FORTRAN_DIR}/include) +link_directories(${NETCDF_C_DIR}/lib + ${NETCDF_FORTRAN_DIR}/lib) + +add_executable(FATES_rad_test ${rad_sources}) + +target_link_libraries(FATES_rad_test + netcdff + netcdf + fates + utils + csm_share) + +add_test(rad_test FATES_rad_test) + +# Tell CTest how to figure out that "STOP 1" fails for the current +define_Fortran_stop_failure(rad_test) diff --git a/unit_testing/radiation_test/FATES_rad_test b/unit_testing/radiation_test/FATES_rad_test new file mode 100755 index 0000000000000000000000000000000000000000..bdc660e5b40c7d5c2c876a13bd76bc77e79a2bee GIT binary patch literal 73392 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 fates_r8 + use EDPftvarcon, only : EDPftvarcon_type + !use EDParamsMod, only : nlevleaf, nclmax + + implicit none + + ! LOCALS: + character(len=MAX_PATH) :: param_file ! parameter file name + character(len=MAX_PATH) :: patch_file ! patch data file name + character(len=MAX_PATH) :: out_file ! output file name + integer :: year, jday ! year and day of year to simulate + real(r8) :: lat, lon ! latitude/longitude to simulate [degrees] + real(r8) :: fcansno ! fraction of canopy covered by snow [0-1] + real(r8), allocatable :: rhol(:,:) ! leaf reflectance [0-1] + real(r8), allocatable :: rhos(:,:) ! stem reflectance [0-1] + real(r8), allocatable :: taul(:,:) ! leaf transmittance [0-1] + real(r8), allocatable :: taus(:,:) ! stem transmittance [0-1] + real(r8), allocatable :: xl(:) ! leaf orientation index + real(r8), allocatable :: ci(:) ! clumping index + + ! PARAMETERS + integer, parameter :: numSWb = 2 ! number of shortwave bands to simulate + + interface + + subroutine read_radiation_namelist(year, jday, lat, lon, fcansno, & + param_file, patch_file, out_file) + + use FatesUnitTestIOMod, only : MAX_PATH, MAX_CHAR, open_file + use FatesConstantsMod, only : r8 => fates_r8 + + implicit none + + character(len=MAX_PATH), intent(out) :: param_file, patch_file, out_file + integer, intent(out) :: year, jday + real(r8), intent(out) :: lat, lon + real(r8), intent(out) :: fcansno + + end subroutine read_radiation_namelist + + subroutine read_radiation_params(file, numSWb, rhol, rhos, taul, taus, xl, & + ci) + + use FatesUnitTestIOMod, only : MAX_PATH, check, read_in_parameter + use FatesConstantsMod, only : r8 => fates_r8 + use netcdf + + implicit none + + character(len=MAX_PATH), intent(in) :: file + integer, intent(in) :: numSWb + real(r8), allocatable, intent(out) :: rhol(:,:) + real(r8), allocatable, intent(out) :: rhos(:,:) + real(r8), allocatable, intent(out) :: taul(:,:) + real(r8), allocatable, intent(out) :: taus(:,:) + real(r8), allocatable, intent(out) :: xl(:) + real(r8), allocatable, intent(out) :: ci(:) + + end subroutine read_radiation_params + + end interface + + call read_radiation_namelist(year, jday, lat, lon, fcansno, & + param_file, patch_file, out_file) + + ! open log file + logf = open_file("log.txt") + + ! read in FATES parameter file + call read_radiation_params(param_file, numSWb, rhol, rhos, taul, taus, xl, ci) + + ! read in patch data + call read_patch_data(patch_file, canopy_area_profile, elai_profile, & + esai_profile, nrad_r) + + ! call get_orbital_vals(year, logf, eccen, mvelp, obliqr, lambm0, mvelpp) + + ! cosz(:) = 0.0 + ! k_dir(:,:) = 0.0 + + ! ! for each half-hourly time step in the day + ! do i = 0, 47 + ! calday = jday + i*0.02083333_SHR_KIND_R8 + ! call shr_orb_decl(calday, eccen, mvelpp, lambm0, obliqr, declin, eccf) + ! cosz(i) = shr_orb_cosz(calday, lat, lon, declin) + + ! if (cosz(i) > 0.0_r8) then + ! ! call norman radiation scheme + ! call PatchNormanRadiation(rhol, rhos, taul, taus, xl, clumping_index, & + ! canopy_area_profile, elai_profile, esai_profile, fcansno, & + ! cosz(i), nrad, 2, k_dir(:,i)) + ! end if + ! end do + + ! call write_radiation_data(out_file, k_dir, cosz) + + close(logf) + +end program FatesUnitTestRadiation + +!:.............................................................................: + +subroutine read_radiation_namelist(year, jday, lat, lon, fcansno, param_file, & + patch_file, out_file) + ! + ! DESCRIPTION: + ! read in the namelist associated with the radiation unit tests and + ! initialize values + ! + + use FatesUnitTestIOMod, only : MAX_PATH, MAX_CHAR, open_file + use FatesConstantsMod, only : r8 => fates_r8 + + implicit none + + ! ARGUMENTS: + character(len=MAX_PATH), intent(out) :: param_file ! parameter file name + character(len=MAX_PATH), intent(out) :: patch_file ! patch data file name + character(len=MAX_PATH), intent(out) :: out_file ! output file name + integer, intent(out) :: year, jday ! year and day of year + real(r8), intent(out) :: lat, lon ! latitude and longitude [degrees] + real(r8), intent(out) :: fcansno ! fraction of canopy covered by snow [0-1] + + ! LOCALS: + character(len=MAX_PATH) :: rad_nl = 'radiation_nl' ! radiation namelist name + character(len=MAX_CHAR) :: message ! Error message + character(len=MAX_CHAR) :: msg ! I/O Error message + integer :: rad_nl_file ! unit number for namelist + integer :: ios ! I/O status + + + ! Namelist of radiation parameters + namelist /radiation/ year, jday, lat, lon, fcansno, param_file, patch_file, & + out_file + + ! Now read parameters namelist + rad_nl_file = open_file(trim(rad_nl), 'r') + read(rad_nl_file, radiation, iostat=ios, iomsg=msg) + + if (ios /= 0) then + ! Problem reading file - tell user. + write(message, '(A, I6, A, A)') "Error reading radiation namelist file", & + ios, "IOMSG: ", msg + write(*,*) message + stop "Stopped" + end if + + close(rad_nl_file) + +end subroutine read_radiation_namelist + +!:.............................................................................: + +subroutine read_radiation_params(file, numSWb, rhol, rhos, taul, taus, xl, ci) + ! + ! DESCRIPTION: + ! read in the parameters we need for this test + ! + + use FatesUnitTestIOMod, only : MAX_PATH, check, read_in_parameter + use FatesConstantsMod, only : r8 => fates_r8 + use netcdf + + implicit none + + ! ARGUMENTS: + character(len=MAX_PATH), intent(in) :: file ! parameter file name + integer, intent(in) :: numSWb ! number of shortwave bands to simulate + real(r8), allocatable, intent(out) :: rhol(:,:) ! leaf reflectance [0-1] + real(r8), allocatable, intent(out) :: rhos(:,:) ! stem reflectance [0-1] + real(r8), allocatable, intent(out) :: taul(:,:) ! leaf transmittance [0-1] + real(r8), allocatable, intent(out) :: taus(:,:) ! stem transmittance [0-1] + real(r8), allocatable, intent(out) :: xl(:) ! leaf orientation index + real(r8), allocatable, intent(out) :: ci(:) ! clumping index + + ! LOCALS: + integer :: funit ! file unit number + real(r8), allocatable :: rholvis(:) ! leaf visible reflectance [0-1] + real(r8), allocatable :: rholnir(:) ! leaf NIR reflectance [0-1] + real(r8), allocatable :: rhosvis(:) ! stem visible reflectance [0-1] + real(r8), allocatable :: rhosnir(:) ! stem NIR reflectance [0-1] + real(r8), allocatable :: taulvis(:) ! leaf visible transmittance [0-1] + real(r8), allocatable :: taulnir(:) ! leaf NIR transmittance [0-1] + real(r8), allocatable :: tausvis(:) ! stem visible transmittance [0-1] + real(r8), allocatable :: tausnir(:) ! stem NIR transmittance [0-1] + + ! open file + call check(nf90_open(trim(file), 0, funit)) + + ! read in parameters + call read_in_parameter(funit, 'fates_rad_leaf_rhovis', 'fates_pft', rholvis) + call read_in_parameter(funit, 'fates_rad_leaf_rhonir', 'fates_pft', rholnir) + call read_in_parameter(funit, 'fates_rad_stem_rhovis', 'fates_pft', rhosvis) + call read_in_parameter(funit, 'fates_rad_stem_rhonir', 'fates_pft', rhosnir) + call read_in_parameter(funit, 'fates_rad_leaf_tauvis', 'fates_pft', taulvis) + call read_in_parameter(funit, 'fates_rad_leaf_taunir', 'fates_pft', taulnir) + call read_in_parameter(funit, 'fates_rad_stem_tauvis', 'fates_pft', tausvis) + call read_in_parameter(funit, 'fates_rad_stem_taunir', 'fates_pft', tausnir) + call read_in_parameter(funit, 'fates_rad_leaf_xl', 'fates_pft', xl) + call read_in_parameter(funit, 'fates_rad_leaf_clumping_index', 'fates_pft', & + ci) + + ! allocate the arrays correctly + allocate(rhol(size(rholvis, 1), numSWb)) + allocate(rhos(size(rhosvis, 1), numSWb)) + allocate(taul(size(taulvis, 1), numSWb)) + allocate(taus(size(tausvis, 1), numSWb)) + + ! put arrays together + rhol(:,1) = rholvis + rhol(:,2) = rholnir + rhos(:,1) = rhosvis + rhos(:,2) = rhosnir + taul(:,1) = taulvis + taul(:,2) = taulnir + taus(:,1) = tausvis + taus(:,2) = tausnir + + ! close file + call check(nf90_close(funit)) + +end subroutine read_radiation_params + + + diff --git a/unit_testing/radiation_test/log.txt b/unit_testing/radiation_test/log.txt new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/unit_testing/radiation_test/log.txt @@ -0,0 +1 @@ + diff --git a/unit_testing/test/radiation_test/radiation_nl b/unit_testing/radiation_test/radiation_nl similarity index 96% rename from unit_testing/test/radiation_test/radiation_nl rename to unit_testing/radiation_test/radiation_nl index 9b33dbf6e3..3d0d608175 100644 --- a/unit_testing/test/radiation_test/radiation_nl +++ b/unit_testing/radiation_test/radiation_nl @@ -1,7 +1,6 @@ &radiation ! parameters for the radiation unit test ! see FatesUnitTestRadiation.F90 -numSWb = 2 year = 2000 jday = 165 lat = 45.0 diff --git a/unit_testing/run_FATES_tests.py b/unit_testing/run_FATES_tests.py new file mode 100644 index 0000000000..cd3d1206d3 --- /dev/null +++ b/unit_testing/run_FATES_tests.py @@ -0,0 +1,35 @@ +import os +import sys + +# +_CTSM_PYTHON = os.path.abspath( + os.path.join(os.path.dirname(__file__), "..", "..", "..", "python") +) +sys.path.insert(1, _CTSM_PYTHON) + +from ctsm import add_cime_to_path +from CIME.utils import run_cmd_no_fail + +from shutil import rmtree, copy + +def main(): + os.chdir("..") + if os.path.isdir("build"): + rmtree("build") + + ## super hacky right now!! + run_command = ["../../cime/scripts/fortran_unit_testing/run_tests.py", + "--build-dir", "build"] + run_cmd_no_fail(" ".join(run_command), combine_output=True) + + copy("build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/FATES_rad_test", + "unit_testing/test/radiation_test/") + + os.chdir("unit_testing/test/radiation_test") + run_command = ["./FATES_rad_test"] + output = run_cmd_no_fail(" ".join(run_command), combine_output=True) + print(output) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/unit_testing/test/CMakeLists.txt b/unit_testing/test/CMakeLists.txt deleted file mode 100644 index 6b1f8471cf..0000000000 --- a/unit_testing/test/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(radiation_test) \ No newline at end of file diff --git a/unit_testing/test/radiation_test/CMakeLists.txt b/unit_testing/test/radiation_test/CMakeLists.txt deleted file mode 100644 index cd6f767d2b..0000000000 --- a/unit_testing/test/radiation_test/CMakeLists.txt +++ /dev/null @@ -1,40 +0,0 @@ -# Local files -set(test_sources FatesUnitTestRadiation.F90) - -#Add sources we need from other directories -set(sources_needed - FatesUnitTestIOMod.F90 - FatesUnitTestOrbitalMod.F90 - FatesConstantsMod.F90) - -extract_sources("${sources_needed}" "${utils_sources}" test_sources) - -set(NETCDF_C_DIR "/usr/local/Cellar/netcdf/4.9.2") -set(NETCDF_FORTRAN_DIR "/usr/local/Cellar/netcdf-fortran/4.6.0") -MESSAGE(">> CISM_NETCDF_C_DIR set to : ${NETCDF_C_DIR}") -MESSAGE(">> CISM_NETCDF_FORTRAN_DIR set to : ${NETCDF_FORTRAN_DIR}") - -FIND_PATH(NETCDFC_FOUND libnetcdf.a ${NETCDF_C_DIR}/lib) -FIND_PATH(NETCDFF_FOUND libnetcdff.a ${NETCDF_FORTRAN_DIR}/lib) -MESSAGE(" NETCDFC_FOUND = ${NETCDFC_FOUND}") -MESSAGE(" NETCDFF_FOUND = ${NETCDFF_FOUND}") - -IF (${NETCDFC_FOUND} STREQUAL ${NETCDF_C_DIR}/lib ) - SET(NETCDF_C_LIBS "netcdff;netcdf" CACHE STRING "Netcdf Library Names(s)") -ELSE() - SET(NETCDF_C_LIBS "netcdf" CACHE STRING "Netcdf Library Names(s)") -ENDIF() -MESSAGE(">> NETCDF_LIBS Library(s) set to : ${NETCDF_C_LIBS}") - - -include_directories(${NETCDF_C_DIR}/include - ${NETCDF_FORTRAN_DIR}/include) -link_directories(${NETCDF_C_DIR}/lib - ${NETCDF_FORTRAN_DIR}/lib) - -add_executable(FATES_rad_test ${test_sources}) - -add_test(rad_test FATES_rad_test) - -# Tell CTest how to figure out that "STOP 1" fails for the current -define_Fortran_stop_failure(rad_test) diff --git a/unit_testing/test/radiation_test/FatesUnitTestRadiation.F90 b/unit_testing/test/radiation_test/FatesUnitTestRadiation.F90 deleted file mode 100644 index 042f5e71e2..0000000000 --- a/unit_testing/test/radiation_test/FatesUnitTestRadiation.F90 +++ /dev/null @@ -1,122 +0,0 @@ -program FatesUnitTestRadiation - ! - ! DESCRIPTION: - ! Test the FATES radiation schemes - ! - - use FatesUnitTestIOMod, only : logf, MAX_PATH - use FatesUnitTestOrbitalMod, only : SHR_KIND_R8 - use FatesUnitTestOrbitalMod, only : get_orbital_vals, shr_orb_cosz - use FatesUnitTestOrbitalMod, only : shr_orb_decl - !use EDParamsMod, only : nlevleaf, nclmax - - implicit none - - ! LOCALS: - character(len=MAX_PATH) :: param_file, patch_file, out_file ! file names - integer :: numSWb ! number of shortwave bands to simulate - integer :: year, jday ! year and day of year to simulate - real(r8) :: lat, lon ! latitude/longitude to simulate [degrees] - real(r8) :: fcansno ! fraction of canopy covered by snow [0-1] - - interface - - subroutine read_radiation_namelist(numSWb, year, jday, lat, lon, fcansno, & - param_file, patch_file, out_file) - - use FatesUnitTestIOMod, only : MAX_PATH, MAX_CHAR, open_file - - implicit none - - character(len=MAX_PATH), intent(out) :: param_file, patch_file, out_file - integer, intent(out) :: numSWb, year, jday - real(r8), intent(out) :: lat, lon - real(r8), intent(out) :: fcansno - - end subroutine read_radiation_namelist - - end interface - - call read_radiation_namelist(numSWB, year, jday, lat, lon, fcansno, & - param_file, patch_file, out_file) - - ! open log file - logf = open_file("log.txt") - - ! get patch and parameter values, as well as orbital parameters - !call get_parameters(param_file, rhol, rhos, taul, taus, xl, clumping_index) - - ! call read_patch_data(patch_file, canopy_area_profile, elai_profile, & - ! esai_profile, nrad_r) - ! call get_orbital_vals(year, logf, eccen, mvelp, obliqr, lambm0, mvelpp) - - ! cosz(:) = 0.0 - ! k_dir(:,:) = 0.0 - - ! ! for each half-hourly time step in the day - ! do i = 0, 47 - ! calday = jday + i*0.02083333_SHR_KIND_R8 - ! call shr_orb_decl(calday, eccen, mvelpp, lambm0, obliqr, declin, eccf) - ! cosz(i) = shr_orb_cosz(calday, lat, lon, declin) - - ! if (cosz(i) > 0.0_r8) then - ! ! call norman radiation scheme - ! call PatchNormanRadiation(rhol, rhos, taul, taus, xl, clumping_index, & - ! canopy_area_profile, elai_profile, esai_profile, fcansno, & - ! cosz(i), nrad, 2, k_dir(:,i)) - ! end if - ! end do - - ! call write_radiation_data(out_file, k_dir, cosz) - -end program FatesUnitTestRadiation - -!:.............................................................................: - -subroutine read_radiation_namelist(numSWb, year, jday, lat, lon, fcansno, & - param_file, patch_file, out_file) - - use FatesUnitTestIOMod, only : MAX_PATH, MAX_CHAR, open_file - - implicit none - - ! - ! DESCRIPTION: - ! read in the namelist associated with the radiation unit tests and - ! initialize values - ! - - ! ARGUMENTS: - character(len=MAX_PATH), intent(out) :: param_file, patch_file, out_file ! file names - integer, intent(out) :: numSWb ! number of shortwave bands - integer, intent(out) :: year, jday ! year and day of year - real(r8), intent(out) :: lat, lon ! latitude and longitude [degrees] - real(r8), intent(out) :: fcansno ! fraction of canopy covered by snow [0-1] - - ! LOCALS: - character(len=MAX_PATH) :: rad_nl = 'radiation_nl' ! radiation namelist name - character(len=MAX_PATH) :: message ! Error message - character(len=MAX_PATH) :: msg ! I/O Error message - integer :: rad_nl_file ! unit number for namelist - integer :: ios ! I/O status - - - ! Namelist of radiation parameters - namelist /radiation/ numSWb, year, jday, lat, lon, fcansno, param_file, & - patch_file, out_file - - ! Now read parameters namelist - rad_nl_file = open_file(trim(rad_nl), 'r') - read(rad_nl_file, radiation, iostat=ios, iomsg=msg) - - if (ios /= 0) then - ! Problem reading file - tell user. - write(message, '(A, I6, A, A)') "Error reading radiation namelist file", & - ios, "IOMSG: ", msg - write(*,*) message - stop "Stopped" - end if - - close(rad_nl_file) - -end subroutine read_radiation_namelist \ No newline at end of file diff --git a/unit_testing/utils/FatesUnitTestIOMod.F90 b/unit_testing/utils/FatesUnitTestIOMod.F90 index 0cc004f7a4..a065f3e37a 100644 --- a/unit_testing/utils/FatesUnitTestIOMod.F90 +++ b/unit_testing/utils/FatesUnitTestIOMod.F90 @@ -24,12 +24,12 @@ integer function unit_number() save if (first) then - ! Set first to false and iunit to base unit on first call - iunit = BASE_UNIT - first = .false. + ! Set first to false and iunit to base unit on first call + iunit = BASE_UNIT + first = .false. else - ! Otherwise, increment - iunit = iunit + 1 + ! Otherwise, increment + iunit = iunit + 1 endif ! Set to output @@ -54,7 +54,6 @@ integer function open_file(filename, mode) character(len = 9) :: fmode ! File open mode logical :: file_exists ! Does the file exist? character(len = MAX_PATH) :: fname ! Local filename (trimmed) - character(len = MAX_CHAR) :: message ! Error message integer :: i ! Looping index integer :: ios ! I/O status integer :: iunit = BASE_UNIT ! File unit number @@ -63,33 +62,33 @@ integer function open_file(filename, mode) ! Get mode of open (read, write, or read/write) ! Defaults to read/write if (present(mode)) then - select case(mode) - case ('r', 'R') - fmode = 'read' - case ('w', 'W') - fmode = 'write' - case ('rw', 'RW', 'wr', 'WR') - fmode = 'readwrite' - case DEFAULT - fmode = 'readwrite' - end select - else + select case(mode) + case ('r', 'R') + fmode = 'read' + case ('w', 'W') + fmode = 'write' + case ('rw', 'RW', 'wr', 'WR') + fmode = 'readwrite' + case DEFAULT fmode = 'readwrite' + end select + else + fmode = 'readwrite' endif ! trim filename of whitespace fname = trim(adjustl(filename)) if (fmode == 'read' .or. fmode == 'readwrite') then - ! Check for valid name of file - farray = 0 - do i = 1, len_trim(fname) - farray(i) = ichar(fname(i:i)) - enddo - if (any(farray > 126)) then - write(*,*) "Invalid filename" - stop "Stopped" - endif + ! Check for valid name of file + farray = 0 + do i = 1, len_trim(fname) + farray(i) = ichar(fname(i:i)) + enddo + if (any(farray > 126)) then + write(logf,'(A)') "Invalid filename" + stop + endif endif ! Does the file exist? @@ -97,32 +96,116 @@ integer function open_file(filename, mode) ! Open file if conditions are correct if (file_exists .and. fmode == 'write') then - write(message, '(A,A,A)') "File ", fname(1:len_trim(fname)), & - " exists. Cannot open write only." - write(*,*) message - stop "Stopped" + write(logf,'(A,A,A)') "File ", fname(1:len_trim(fname)), & + " exists. Cannot open write only." + stop else if (.not. file_exists .and. fmode == 'read') then - write(message, '(A,A,A)') "File ", fname(1:len_trim(fname)), & - " does not exist. Can't read." - write(*,*) message - stop "Stopped" + write(logf, '(A,A,A)') "File ", fname(1:len_trim(fname)), & + " does not exist. Can't read." + stop else - iunit = unit_number() - open(iunit, file=fname, action=fmode, iostat=ios) - if (ios /= 0) then - write(message, '(A,A,A,I6)') "Problem opening", & - fname(1:len_trim(fname)), " ios: ", ios - write(*,*) message - stop "Stopped" - endif + iunit = unit_number() + open(iunit, file=fname, action=fmode, iostat=ios) + if (ios /= 0) then + write(logf,'(A,A,A,I6)') "Problem opening", & + fname(1:len_trim(fname)), " ios: ", ios + stop + endif endif open_file = iunit - end function open_file + end function open_file + + !:.........................................................................: + + subroutine check(status) + ! + ! DESCRIPTION: + ! Checks status of netcdf operations + + ! ARGUMENTS: + integer, intent (in) :: status ! return status code from a netcdf procedure + + if (status /= nf90_noerr) then + write(logf,*) trim(nf90_strerror(status)) + stop + end if + + end subroutine check + + !:.........................................................................: + + subroutine read_in_parameter(funit, param_name, bounds, out_array) + ! + ! DESCRIPTION: + ! Reads in parameters from the FATES parameter file + ! + + ! ARGUMENTS: + integer, intent(in) :: funit ! file unit number + character(len=*), intent(in) :: param_name ! parameter name + character(len=*), intent(in) :: bounds ! bounds name + real(r8), allocatable, intent(out) :: out_array(:) ! parameter values + + ! LOCALS: + integer :: paramID ! parameter ID + integer :: dimID_axis_nbounds ! dimension ID + integer :: nbounds ! parameter bounds + + ! get axis id + call check(nf90_inq_dimid(funit, trim(bounds), dimID_axis_nbounds)) + + ! get parameter bounds + call check(nf90_inquire_dimension(funit, dimID_axis_nbounds, len=nbounds)) + + ! read parameter values + call check(nf90_inq_varid(funit, trim(param_name), paramID)) + + ! allocate + allocate(out_array(nbounds)) + call check(nf90_get_var(funit, paramID, out_array)) + + end subroutine read_in_parameter + + ! subroutine read_patch_data(file, canopy_area, elai, esai, nrad) + ! ! + ! ! DESCRIPTION: + ! ! Reads and return patch data + + ! ! ARGUMENTS: + ! character(len=MAX_PATH), intent(in) :: file ! patch file name + ! real(r8), intent(out) :: canopy_area(num_can,num_pft,nlevleaf) ! canopy area profile + ! real(r8), intent(out) :: elai(num_can,num_pft,nlevleaf) ! exposed lai profile + ! real(r8), intent(out) :: esai(num_can,num_pft,nlevleaf) ! exposed sai profile + ! real(r8), intent(out) :: nrad(num_can,num_pft) ! number of exposed leaf layers + + ! ! LOCALS: + ! real(r8) :: nrad_r(num_can,num_pft) ! number of exposed leaf layers + ! integer :: fidA, varID + + ! ! open file + ! call check(nf90_open(trim(file), 0, fidA)) + + ! ! read patch data values + ! call check(nf90_inq_varid(fidA, "can_area", varID)) + ! call check(nf90_get_var(fidA, varID, canopy_area)) + + ! call check(nf90_inq_varid(fidA, "elai", varID)) + ! call check(nf90_get_var(fidA, varID, elai)) + + ! call check(nf90_inq_varid(fidA, "esai", varID)) + ! call check(nf90_get_var(fidA, varID, esai)) + + ! call check(nf90_inq_varid(fidA, "nrad", varID)) + ! call check(nf90_get_var(fidA, varID, nrad)) + + ! end subroutine read_patch_data !:.........................................................................: + + ! subroutine write_radiation_data(file, kdir, declin) ! ! ! ! DESCRIPTION: @@ -166,156 +249,4 @@ end function open_file ! end subroutine write_radiation_data - ! !:.........................................................................: - - ! subroutine check(status) - ! ! - ! ! DESCRIPTION: - ! ! Checks status of netcdf operations - - ! ! ARGUMENTS: - ! integer, intent (in) :: status ! return status code from a netcdf procedure - - ! if (status /= nf90_noerr) then - ! print *, trim(nf90_strerror(status)) - ! stop "Stopped" - ! end if - - ! end subroutine check - - ! !:.........................................................................: - - ! subroutine read_patch_data(file, canopy_area, elai, esai, nrad) - ! ! - ! ! DESCRIPTION: - ! ! Reads and return patch data - - ! ! ARGUMENTS: - ! character(len=MAX_PATH), intent(in) :: file ! patch file name - ! real(r8), intent(out) :: canopy_area(num_can,num_pft,nlevleaf) ! canopy area profile - ! real(r8), intent(out) :: elai(num_can,num_pft,nlevleaf) ! exposed lai profile - ! real(r8), intent(out) :: esai(num_can,num_pft,nlevleaf) ! exposed sai profile - ! real(r8), intent(out) :: nrad(num_can,num_pft) ! number of exposed leaf layers - - ! ! Data dictionary: declare variable types, definitions, and units - ! real(r8) :: nrad_r(num_can,num_pft) ! number of exposed leaf layers - ! integer :: fidA, varID - - ! ! open file - ! call check(nf90_open(trim(file), 0, fidA)) - - ! ! read patch data values - ! call check(nf90_inq_varid(fidA, "can_area", varID)) - ! call check(nf90_get_var(fidA, varID, canopy_area)) - - ! call check(nf90_inq_varid(fidA, "elai", varID)) - ! call check(nf90_get_var(fidA, varID, elai)) - - ! call check(nf90_inq_varid(fidA, "esai", varID)) - ! call check(nf90_get_var(fidA, varID, esai)) - - ! call check(nf90_inq_varid(fidA, "nrad", varID)) - ! call check(nf90_get_var(fidA, varID, nrad)) - - ! end subroutine read_patch_data - - ! !:.........................................................................: - - ! subroutine get_parameters(file, rhol, rhos, taul, taus, xl, ci) - ! ! - ! ! Purpose: - ! ! Returns parameter values - ! ! - ! ! Record of revisions: - ! ! Date Programmer Description of change - ! ! ======== ============= ===================== - ! ! 03/20/23 A. C. Foster Original code - ! ! - - ! ! Data dictionary: declare calling parameter types & definitions - ! character(len=100), intent(in) :: file ! parameter file name - ! real(r8), intent(out) :: rhol(num_pft,num_swb) ! leaf reflectance - ! real(r8), intent(out) :: rhos(num_pft,num_swb) ! stem reflectance - ! real(r8), intent(out) :: taul(num_pft,num_swb) ! leaf transmittance - ! real(r8), intent(out) :: taus(num_pft,num_swb) ! stem transmittance - ! real(r8), intent(out) :: xl(num_pft) ! leaf orientation index - ! real(r8), intent(out) :: ci(num_pft) ! clumping index - - ! ! read in all parameters - ! call read_param_netcdf(file, rhol(:,1), rhol(:,2), rhos(:,1), rhos(:,2), & - ! taul(:,1), taul(:,2), taus(:,1), taus(:,2), xl, ci) - - ! end subroutine get_parameters - - ! !:...........................................................................: - - ! subroutine read_param_netcdf(file, rholvis, rholnir, rhosvis, rhosnir, & - ! taulvis, taulnir, tausvis, tausnir, xl, ci) - ! ! - ! ! Purpose: - ! ! Reads a FATES netcdf parameter file - ! ! - ! ! Record of revisions: - ! ! Date Programmer Description of change - ! ! ======== ============= ===================== - ! ! 03/20/23 A. C. Foster Original code - ! ! - - ! ! Data dictionary: declare calling parameter types & definitions - ! character(len=100), intent(in) :: file ! parameter file name - ! real(r8), intent(out) :: rholvis(num_pft) ! vis leaf reflectance - ! real(r8), intent(out) :: rholnir(num_pft) ! nir leaf reflectance - ! real(r8), intent(out) :: rhosvis(num_pft) ! vis stem reflectance - ! real(r8), intent(out) :: rhosnir(num_pft) ! nir stem reflectance - ! real(r8), intent(out) :: taulvis(num_pft) ! vis leaf transmittance - ! real(r8), intent(out) :: taulnir(num_pft) ! nir leaf transmittance - ! real(r8), intent(out) :: tausvis(num_pft) ! vis stem transmittance - ! real(r8), intent(out) :: tausnir(num_pft) ! nir stem transmittance - ! real(r8), intent(out) :: xl(num_pft) ! leaf orientation index - ! real(r8), intent(out) :: ci(num_pft) ! clumping index - - ! ! Data dictionary: declare variable types, definitions, and units - ! integer :: fidA, paramID - - ! ! open file - ! call check(nf90_open(trim(file), 0, fidA)) - - ! ! read parameter values - ! call check(nf90_inq_varid(fidA, "fates_rad_leaf_rhovis", paramID)) - ! call check(nf90_get_var(fidA, paramID, rholvis)) - - ! call check(nf90_inq_varid(fidA, "fates_rad_leaf_rhonir", paramID)) - ! call check(nf90_get_var(fidA, paramID, rholnir)) - - ! call check(nf90_inq_varid(fidA, "fates_rad_stem_rhovis", paramID)) - ! call check(nf90_get_var(fidA, paramID, rhosvis)) - - ! call check(nf90_inq_varid(fidA, "fates_rad_stem_rhonir", paramID)) - ! call check(nf90_get_var(fidA, paramID, rhosnir)) - - ! call check(nf90_inq_varid(fidA, "fates_rad_leaf_tauvis", paramID)) - ! call check(nf90_get_var(fidA, paramID, taulvis)) - - ! call check(nf90_inq_varid(fidA, "fates_rad_leaf_taunir", paramID)) - ! call check(nf90_get_var(fidA, paramID, taulnir)) - - ! call check(nf90_inq_varid(fidA, "fates_rad_stem_tauvis", paramID)) - ! call check(nf90_get_var(fidA, paramID, tausvis)) - - ! call check(nf90_inq_varid(fidA, "fates_rad_stem_taunir", paramID)) - ! call check(nf90_get_var(fidA, paramID, tausnir)) - - ! call check(nf90_inq_varid(fidA, "fates_rad_leaf_xl", paramID)) - ! call check(nf90_get_var(fidA, paramID, xl)) - - ! call check(nf90_inq_varid(fidA, "fates_rad_leaf_clumping_index", paramID)) - ! call check(nf90_get_var(fidA, paramID, ci)) - - ! ! close file - ! call check(nf90_close(fidA)) - - ! end subroutine read_param_netcdf - - ! !:...........................................................................: - end module FatesUnitTestIOMod \ No newline at end of file From a9a28a4431895958286611077cd9df0ece25c2eb Mon Sep 17 00:00:00 2001 From: adrifoster Date: Thu, 13 Apr 2023 22:41:13 -0600 Subject: [PATCH 641/852] move test directories --- CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a640e8bb7..16bb777d48 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,8 +28,6 @@ add_library(fates ${fates_sources}) add_library(utils ${utils_sources}) add_dependencies(fates csm_share) -add_subdirectory(${CLM_ROOT}/src/fates/unit_testing/radiation_test fates_testing) - # We need to look for header files here, in order to pick up shr_assert.h include_directories(${CLM_ROOT}/share/include) @@ -37,3 +35,4 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) link_directories(${CMAKE_CURRENT_BINARY_DIR}) # Add the test directories +add_subdirectory(${CLM_ROOT}/src/fates/unit_testing/radiation_test fates_testing) From cbba0d34b92886feb5940e546ee23eb50b27275b Mon Sep 17 00:00:00 2001 From: adrifoster Date: Fri, 14 Apr 2023 08:07:24 -0600 Subject: [PATCH 642/852] trying to get share to work --- CMakeLists.txt | 10 +++++++--- unit_testing/radiation_test/CMakeLists.txt | 11 ++++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 16bb777d48..c7da878060 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,14 +14,20 @@ set(CLM_ROOT "../../") # Add source directories from other share code (csm_share, etc.) add_subdirectory(${CLM_ROOT}/share/src csm_share) +set (csm_share_sources_needed + shr_log_mod.F90 + ) +extract_sources("${csm_share_sources_needed}" "${share_sources}" share_sources_needed) + # Add FATES source directories add_subdirectory(${CLM_ROOT}/src/fates/main fates_main) add_subdirectory(${CLM_ROOT}/src/fates/parteh fates_parteh) add_subdirectory(${CLM_ROOT}/src/fates/unit_testing/utils fates_test_utils) +add_subdirectory(${CLM_ROOT}/src/fates/unit_testing/radiation_test fates_testing) # Build libraries containing stuff needed for the unit tests. # Eventually, these add_library calls should probably be distributed into the correct location, rather than being in this top-level CMakeLists.txt file. -add_library(csm_share ${share_sources}) +add_library(csm_share ${share_sources_needed}) declare_generated_dependencies(csm_share "${share_genf90_sources}") add_library(fates ${fates_sources}) @@ -34,5 +40,3 @@ include_directories(${CLM_ROOT}/share/include) include_directories(${CMAKE_CURRENT_BINARY_DIR}) link_directories(${CMAKE_CURRENT_BINARY_DIR}) -# Add the test directories -add_subdirectory(${CLM_ROOT}/src/fates/unit_testing/radiation_test fates_testing) diff --git a/unit_testing/radiation_test/CMakeLists.txt b/unit_testing/radiation_test/CMakeLists.txt index 2d72ae6b9b..aafadb5c1c 100644 --- a/unit_testing/radiation_test/CMakeLists.txt +++ b/unit_testing/radiation_test/CMakeLists.txt @@ -14,16 +14,21 @@ include_directories(${NETCDF_C_DIR}/include link_directories(${NETCDF_C_DIR}/lib ${NETCDF_FORTRAN_DIR}/lib) -add_executable(FATES_rad_test ${rad_sources}) +add_executable(FATES_rad_exe ${rad_sources}) -target_link_libraries(FATES_rad_test +target_link_libraries(FATES_rad_exe PUBLIC netcdff netcdf fates utils csm_share) -add_test(rad_test FATES_rad_test) +target_include_directories(FATES_rad_exe PUBLIC + "${PROJECT_BINARY_DIR}" + "${PROJECT_SOURCE_DIR}/fates_main" + ) + +add_test(rad_test FATES_rad_exe) # Tell CTest how to figure out that "STOP 1" fails for the current define_Fortran_stop_failure(rad_test) From 0ff67f3c660da581886d19a0fe9fcc7c7fb700b5 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Fri, 14 Apr 2023 08:56:08 -0600 Subject: [PATCH 643/852] rearranging structure --- CMakeLists.txt | 68 +++++++++++++++--- biogeophys/test/CMakeLists.txt | 2 + .../test/solar_rad_test}/CMakeLists.txt | 12 ++-- .../FatesUnitTestRadiation.F90 | 0 .../test/solar_rad_test}/log.txt | 0 .../test/solar_rad_test}/radiation_nl | 0 .../run_FATES_tests.py | 0 .../utils => unit_test_shr}/CMakeLists.txt | 4 +- .../FatesUnitTestIOMod.F90 | 0 .../FatesUnitTestOrbitalMod.F90 | 0 unit_testing/radiation_test/FATES_rad_test | Bin 73392 -> 0 bytes 11 files changed, 67 insertions(+), 19 deletions(-) create mode 100644 biogeophys/test/CMakeLists.txt rename {unit_testing/radiation_test => biogeophys/test/solar_rad_test}/CMakeLists.txt (79%) rename {unit_testing/radiation_test => biogeophys/test/solar_rad_test}/FatesUnitTestRadiation.F90 (100%) rename {unit_testing/radiation_test => biogeophys/test/solar_rad_test}/log.txt (100%) rename {unit_testing/radiation_test => biogeophys/test/solar_rad_test}/radiation_nl (100%) rename {unit_testing => functional_unit_testing}/run_FATES_tests.py (100%) rename {unit_testing/utils => unit_test_shr}/CMakeLists.txt (70%) rename {unit_testing/utils => unit_test_shr}/FatesUnitTestIOMod.F90 (100%) rename {unit_testing/utils => unit_test_shr}/FatesUnitTestOrbitalMod.F90 (100%) delete mode 100755 unit_testing/radiation_test/FATES_rad_test diff --git a/CMakeLists.txt b/CMakeLists.txt index c7da878060..55422d596e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ include(CIME_initial_setup) project(FATES_tests Fortran C) -enable_language(Fortran) +#enable_language(Fortran) include(CIME_utils) @@ -14,24 +14,66 @@ set(CLM_ROOT "../../") # Add source directories from other share code (csm_share, etc.) add_subdirectory(${CLM_ROOT}/share/src csm_share) -set (csm_share_sources_needed - shr_log_mod.F90 - ) -extract_sources("${csm_share_sources_needed}" "${share_sources}" share_sources_needed) +## shr sources we need +## shr_log_mod.F90 +## shr_infnan_mod.F90.in +## shr_kind_mod.F90 +## shr_strconvert_mod + +# Extract just the files we need from csm_share +set (shr_sources_needed_base + shr_log_mod.F90 + shr_infnan_mod.F90 + shr_kind_mod.F90 + shr_sys_mod.F90 + shr_abort_mod.F90 + shr_strconvert_mod.F90 + ) +extract_sources("${shr_sources_needed_base}" "${share_sources}" shr_sources_needed) # Add FATES source directories add_subdirectory(${CLM_ROOT}/src/fates/main fates_main) add_subdirectory(${CLM_ROOT}/src/fates/parteh fates_parteh) -add_subdirectory(${CLM_ROOT}/src/fates/unit_testing/utils fates_test_utils) -add_subdirectory(${CLM_ROOT}/src/fates/unit_testing/radiation_test fates_testing) + +# Add general unit test directories (stubbed out files, etc.) +add_subdirectory(${CLM_ROOT}/src/fates/unit_test_shr) + +# Remove shr_mpi_mod from share_sources. +# This is needed because we want to use the mock shr_mpi_mod in place of the real one +# +# TODO: this should be moved into a general-purpose function in Sourcelist_utils. +# Then this block of code could be replaced with a single call, like: +# remove_source_file(${share_sources} "shr_mpi_mod.F90") +foreach (sourcefile ${share_sources}) + string(REGEX MATCH "shr_mpi_mod.F90" match_found ${sourcefile}) + if(match_found) + list(REMOVE_ITEM share_sources ${sourcefile}) + endif() +endforeach() + +# Remove shr_cal_mod from share_sources. +# +# shr_cal_mod depends on ESMF (or the lightweight esmf wrf timemgr, at +# least). Since CTSM doesn't currently use shr_cal_mod, we're avoiding +# the extra overhead of including esmf_wrf_timemgr sources in this +# build. +# +# TODO: like above, this should be moved into a general-purpose function +# in Sourcelist_utils. Then this block of code could be replaced with a +# single call, like: remove_source_file(${share_sources} +# "shr_cal_mod.F90") +foreach (sourcefile ${share_sources}) + string(REGEX MATCH "shr_cal_mod.F90" match_found ${sourcefile}) + if(match_found) + list(REMOVE_ITEM share_sources ${sourcefile}) + endif() +endforeach() # Build libraries containing stuff needed for the unit tests. # Eventually, these add_library calls should probably be distributed into the correct location, rather than being in this top-level CMakeLists.txt file. -add_library(csm_share ${share_sources_needed}) +add_library(csm_share ${shr_sources_needed}) declare_generated_dependencies(csm_share "${share_genf90_sources}") - add_library(fates ${fates_sources}) -add_library(utils ${utils_sources}) add_dependencies(fates csm_share) # We need to look for header files here, in order to pick up shr_assert.h @@ -40,3 +82,9 @@ include_directories(${CLM_ROOT}/share/include) include_directories(${CMAKE_CURRENT_BINARY_DIR}) link_directories(${CMAKE_CURRENT_BINARY_DIR}) +# Add the test directories +# Note: it's possible that these could be added by each source directory that +# has tests in it. However, it appears that the order needs to be done +# carefully: for example, include_directories and link_directories needs to be +# done before adding the tests themselves. +add_subdirectory(${CLM_ROOT}/src/fates/biogeophys/test fates_biogeophys_test) diff --git a/biogeophys/test/CMakeLists.txt b/biogeophys/test/CMakeLists.txt new file mode 100644 index 0000000000..76e7f575a3 --- /dev/null +++ b/biogeophys/test/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(solar_rad_test) + diff --git a/unit_testing/radiation_test/CMakeLists.txt b/biogeophys/test/solar_rad_test/CMakeLists.txt similarity index 79% rename from unit_testing/radiation_test/CMakeLists.txt rename to biogeophys/test/solar_rad_test/CMakeLists.txt index aafadb5c1c..415894202c 100644 --- a/unit_testing/radiation_test/CMakeLists.txt +++ b/biogeophys/test/solar_rad_test/CMakeLists.txt @@ -1,4 +1,3 @@ -# Local files set(rad_sources FatesUnitTestRadiation.F90) set(NETCDF_C_DIR "/usr/local/Cellar/netcdf/4.9.2") @@ -16,17 +15,16 @@ link_directories(${NETCDF_C_DIR}/lib add_executable(FATES_rad_exe ${rad_sources}) -target_link_libraries(FATES_rad_exe PUBLIC +target_link_libraries(FATES_rad_exe netcdff netcdf fates - utils csm_share) -target_include_directories(FATES_rad_exe PUBLIC - "${PROJECT_BINARY_DIR}" - "${PROJECT_SOURCE_DIR}/fates_main" - ) +#target_include_directories(FATES_rad_exe PUBLIC +# "${PROJECT_BINARY_DIR}" +# "${PROJECT_SOURCE_DIR}/fates_main" +# ) add_test(rad_test FATES_rad_exe) diff --git a/unit_testing/radiation_test/FatesUnitTestRadiation.F90 b/biogeophys/test/solar_rad_test/FatesUnitTestRadiation.F90 similarity index 100% rename from unit_testing/radiation_test/FatesUnitTestRadiation.F90 rename to biogeophys/test/solar_rad_test/FatesUnitTestRadiation.F90 diff --git a/unit_testing/radiation_test/log.txt b/biogeophys/test/solar_rad_test/log.txt similarity index 100% rename from unit_testing/radiation_test/log.txt rename to biogeophys/test/solar_rad_test/log.txt diff --git a/unit_testing/radiation_test/radiation_nl b/biogeophys/test/solar_rad_test/radiation_nl similarity index 100% rename from unit_testing/radiation_test/radiation_nl rename to biogeophys/test/solar_rad_test/radiation_nl diff --git a/unit_testing/run_FATES_tests.py b/functional_unit_testing/run_FATES_tests.py similarity index 100% rename from unit_testing/run_FATES_tests.py rename to functional_unit_testing/run_FATES_tests.py diff --git a/unit_testing/utils/CMakeLists.txt b/unit_test_shr/CMakeLists.txt similarity index 70% rename from unit_testing/utils/CMakeLists.txt rename to unit_test_shr/CMakeLists.txt index c78cf7f05d..783299e740 100644 --- a/unit_testing/utils/CMakeLists.txt +++ b/unit_test_shr/CMakeLists.txt @@ -1,7 +1,7 @@ # Append sources from this directory to the list. -list(APPEND utils_sources +list(APPEND fates_sources FatesUnitTestIOMod.F90 FatesUnitTestOrbitalMod.F90) # Export source list to parent -sourcelist_to_parent(utils_sources) \ No newline at end of file +sourcelist_to_parent(fates_sources) \ No newline at end of file diff --git a/unit_testing/utils/FatesUnitTestIOMod.F90 b/unit_test_shr/FatesUnitTestIOMod.F90 similarity index 100% rename from unit_testing/utils/FatesUnitTestIOMod.F90 rename to unit_test_shr/FatesUnitTestIOMod.F90 diff --git a/unit_testing/utils/FatesUnitTestOrbitalMod.F90 b/unit_test_shr/FatesUnitTestOrbitalMod.F90 similarity index 100% rename from unit_testing/utils/FatesUnitTestOrbitalMod.F90 rename to unit_test_shr/FatesUnitTestOrbitalMod.F90 diff --git a/unit_testing/radiation_test/FATES_rad_test b/unit_testing/radiation_test/FATES_rad_test deleted file mode 100755 index bdc660e5b40c7d5c2c876a13bd76bc77e79a2bee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73392 zcmeHw349aPzW;QCBG8lzC@M>k0A=e&3oTN6DlMjvLfHfq4WUhGAZ<#L0#%kmTOpJH zDk|=HaY3$LQBevCr0j~a2qJ>AxL_)%z*Rt8`v3mUnMu=7czFN5=X;+!qi4?YTh4Dg z%bW?*J(s@wy|E+(g-DVVjMNtCVz?w#NLrL6=|&_ylF^u*c1Olt8N-KCYyB&zezn0G z@rgnQM&rngF(d1vaQf2vZIWCMLo=mDGT3Nznx{ME3bH_cL(viOTazSks9x_1RXB@Q z!O!S$n(WTvqRaV(3>W-TWF}OvcU{KM;Vhou@Sz0C$7FtIWDKRQ5QNM8>h#TVIPI3g zi84YUzt|B%zE@ic1geuSm5Y4pe;JKAwn9gp0R#CR&lCKZ%#Z41|0`WaqdDK0XEzm? z1x6r0?R|pZUYQBi{pAbfOYZU_8I9>_Bh!onh7K7aqNP;ukr;q@MTitXjwy>WAYWV@fv)nCwBt`x~eq=W>9~m--49-Z;6w!g!AU^Juc#y3qt!^*+BDwr!OF#rsoKR~vl<6(k zvqOWV=|Ci%+8`Yd3zC*0Umh7GMMg+cQAD$-=H%w}%Cp&> zc2gl25`v1>yy(8skk~@z;ChgMeEcMuNLn_`uRfpXxa9hLlIroH5!py$_9Bxrp9m+) z!bB(5QHlP?*Q29I4U%F;lsKH`f*6Bkg56{VM0(Q)|CXOxEMxVQZ2rWBiU3!qzctUqC3 ze<8UYFnpnp5-YHTP%Zj)e>$w=rLl6q0+;)8fZ1v_*=2XeBt$1i$CEAjx?f6q)y3iE z_&)b1ME8k~t)tV*bj)fq<(lnA@(`N%MRHI)1n^ay$0J~3PEO49q&~(z3B623MOJgK zT$6p8r7%7&CN3UkBsFMXQc7|9|HCIHI$Hb>K3$L^k#=HyQ>=EA>onfgOSOP%0o4Mk z1yl>D7EmpqT0pgcY5~;(ss&UFs1{Hya1{%rjZV8WZB*LGQ6uzoPLIKXnxXPt-4f*b z9p$<+^3ej7#bKLh4+oqsr9B+w?d7^=XbwW&9C--AR{PO={K`B1%G55?e}E#Wwph)yt$T|HPuBEJ}A5FMlSwdOS zA4RS|a-qK;y~nS-)2~eJGW`cAa{ZBmK3!LY0ylCg6>yPJ=Zm7RT_#?LX0AMPP8>^k z#DysZy;5MDCS7L;+Mce<3enGbSGOEKs|8%MXgSVP^{$JVuJd}={!G`0S+1=H*N1xd z8eI}_^zL_cjB;1?dQ#mxq%Sot)g=&vH5@icqW{v?QFm!obmv9AJF&xHAS1vi(7a3f zNRq2umrvZvwrcfdg0rMqJcvXCLD@NzE{P>_%qY3rKs zo?GLtcenoMAj%R~BlE71nVs=5tAZ57j9Tc@gBgc5%*-U1O($k|%FJSY%qGjss6}DM zp$#)@C73Z{)7pL&tW}p)`+n0zE*-Y@_YEqfZ z+ zus}5kUO3T0JdWOka^(zNk>GJ2uSV)di`#(qhIzaoc=RJ4Pk={eWh!xK=3N60nLFq` z!e#bofi{EdXN1v2LEVC=$8ibDb;~GrE0c&zD{mpmQ7Jd>AZC|wYe#LB3k99Kbt}Pg z4>E5PV!2~LBq!T3fR1>1JskP=0d0e~4`>%c+`SYZJ<4^*DKGN`t>=gu{bqg68NJJ? z)9NeE^D(E_WNz2HcIaK9I?XfHnz!Gpcu!N&3@;b-Rkh-pt$$p9p;lkv(JcBFuVFS4 zr?kpOu5?{wg(r0lAvU1L6Rh&=LEZvb&UaP729H{;*GB5nDuk5eWCtuVoTniZQ zJZQVVvXw4V^V&flY6pGtUd`N>eHdr-l?giig@Yt?RM`w&q{KAOY-gIc&!eFk2|EwC z73Vb-v#CdSvyZu^E`zR(zOp5Rt|+GVijOoEGpSIS4nT!x6O9(VCgY;_E4*^jyFy66 z^7{y5#{e3O98;@z4M;*m6mQrufUgMp9B8g5^#RS+SBC14Gh!TtLO9U1|OTxR{eI9SS+ z0Th_O3@9*Do%sPtLIXEHa$$b(hy;LJ9=WhQ3gN(zEe{M>8oc0ar63zWT}ReW*U7^K zP(Dm3uW$Zq7$!fF)9RUD43qt6uQUIb0a*U#-vHRv&HtJYqapJ@2`HKWVd}%*{51>E zf>o8;F_X}`jmhbHOrV$^Z{S%&V-sMZT_d`@_p1)XIyAi}vO^aVqA|uu` zMyZOorBjKw_4Bn2M~UWFZt$8?s<~4td|iAK%_UeXBzQ|maMB0fP2kFr7@O|IEW`w8 zO~|~f&@SYN`%RIfD@sC+JE+9vNb$9eLa9!UVyd}QeuGXzRilt&KJO#3myqKD)C72- zpB&o+u!iKg#V1G9?}{AlQ4(_8MkOvsg0Ibhl249IOmj3E%;XOm4F%jWfpgIq^pc4Y z&PRg+J0=j4^iCI4TRkRSpEZHC1Biwv?PS;44T)@ z_!xFDB%jgDeZq%v#(;$+^TH=s4QL9g1c1gs8S>2PlOZ*wD8T1UU`*lE$vvr|_4C}H ziOFaO`0u{h8%|(3_Vx*282LOJ?IQM4uo8+f&>JP;^AS`+Pf|^$ug!##SP}K|^mm+O zA%}ZW!1~D7olH%}?_MkQs?2;fgyuK%wE+YRkC^$8*ZCO$?q=l7;F^i$MofAJjPlh8 z3q$2n9SKOA0KWKRSbKT<&H745xW005Y$mqt-8`AfbZ4MlLFI@feYf}ZWt)S9{Fxg4 zK|}K9VvD|8HGq13*`=V_(+rgZva=A!ix!c*Ar4mKp@KW*X(%IXUE7@+TI+?aKO`mH zDFc1BJ_)eFbq=F^VlNK*2SDDfytNvwIzBE_?(q%Cw+Mu8^{##EDe8ga5je>{oCm4T zI{0z{ztIPu0{9?ztH^U{n#j<7dUvaEeb6~nT7>SWSjV1Z)^VEt&Tu;|)LoSAr{zo5 z8Xf(>&rsRYP~C9SDgXm3}{kO@F8jm4C!2n|wI)fa3@6BH+*Z z;1dZBPZx2O7wV?VDlg~x8r@2+@+eX}9DT*=U1!OGW!1h7^!uc;q1$E}Dn6C<$?q3; zq?oA8g33P!&+ZAVY#KAO2B5?;-OWava=?Wj(?aV`IqDPWU{|4(;zK7OK-l0zcnb)b zuDuF;q<}x|gFgbe&&Mc8`k?n4@bPLmhffXUB$^s{zDCEVrOLLtOgt#T$#}AA(90ur z4Z1m%yLqHe_}P$!tr>Up#LSQxScKr|nb+XyY@w6Or&Be4#lm^{x$=}i%Jm^V1tdTC zE&)&X!DkSh1~u0lgId;HE4w<1ySkMwt8$zUzQ#J+ptGTQL*5?1y=@@P;qI(VEFZ$( zxm4s1C-tXZ*)^w*As$AFc(~Um_4dxP>WahvB{2H?FrEj7UqI{^@U}j9Ip79zqyd5? z(MDiAJq70*Fp~9^#hAfpBsZ`ETzMp8F_TBKK^e*VkYf1v;^iaRZ(dbKvIN->)5$&& zPv}U*dL#KMfz#TDvjI4M?wujvKS5hDw>`~y;3=NeoK7LVTn_1#+~K6`JzQD6>w>=9 z4t?1U-x$6Gg_L*}Cr?=J_Ue-_6{qp(nrj<8dnn1sr)vucnBLug#D6_`>FE?8vAOUH z?YD)v-*>80S)Q(67C7g8D!mUJQdx$(1pFf(d=3g|Q$N-YX>wGTR0>DLc>#s|Gs=~scy*-A%)ci)pXF72MQd((_t>YYztB%8Qe z;j!GH3pdb%x`7`D;QW$>DCd{App@zQJ=66QooniS?R`FAQcIJ)e?d4??_7el}(^3sFE z!CkJ4CH`n+VayYEUTova-5{-(X01Ly*2 zs%07+z8v$u*Dy^(eYs^iEzvzlbYzRmrESEe<-Gzf{OoSMjyATCG>NE3G(hdIp&wln z+Vx^@MS)19Z5k#G?Cvg^Y>Z5HqJt!*yK;5u{74*pwxWUfZAOkT7ziUePU~I>y5?X{bSmZvzACtQ+ z6}b-K#*xB^tDxlLsijQ(FB}f@Al)dsOlglUyXTh9c27N6zV&_|Y%-E3fn`Q@c$63W`MkDsui(jO>oiv2{`k z`AT6tr%BgY>7`gf2))yYgxTobRvVtL(dl?TLub&Joes|@IqPnGf=A?JQy~e_k!=76 z8e9f6i~*%L_Gd(A+16P8HjD?>M&7wQr5_$=ysJTt;nHIP*8gA{7?OL{p3mr)BR z0hC-JR^XrLoeH2n=KxBE7SK;*sL%9(k{JbboeZTGx@eb?O`r(xGaQ7Czi7vffYj%^ zi87hW7miSs%L8MPjI?oyq|vX~iHt&V3F~0Ea?`8^TQW@~$4_LjFhSu7K7O;KK&nh@ z-(`0_A&pC_t zSeo*t#HNAs#~R@A^+})eo_;+|`?&Ci>3z-IF96~S1?>e#&7#jx*SmXuhz$PWFOK$8 zkJEPyctD%PS&ggRj%I}P_a=tUTCi}lJ3a1{GS3+dVPzv^jUVFO^lYti8 zz)fo)TN=D0>GZm6>lm>jZ=q2a>FtHiYwjd-p&I3FPt__^>C{iE`5XG9br_!4p-U{HkX=kRff$+X-ipHDYBqbXXKH_uw)@p@q+>GwZ8*X?>e`U_Nx#I zXQ7h!gX^Jxb=k%6X_L7=`u)dW9tp*Y*~c;f7wvmHVfw(#P5Wu> zsX~3#G`q!VZU{D9&=EX<&U~uRRbV$=8K$o|qJ+dR-lrkBo<`mmde>3BQ1yP*nzUM@ zi-poO8zfOqgX6F_jc_ZU5>1#3ILe$~YGDV>;%{*`xS!W)X`&E8kp+DIsG;w6IMdy~ z?M5wdyeYiLAH3}-#|%OpfW8`c+6j?m^zP=pv5}IuD&KD+OM8bwFxQs#!s>}P(1s54 z(3fbfIHFm)Mf3I%obWF7Xx{cT*`g`;a(0;2!EU{TwTCZ8UXQFDNx6xZIByv2llkY5P6C-sPGhrQ}=i9?tKI^iGa8Xf@eTb_Dhg6oZgZi z0IGK;_Q0;No90qC?e=t}UU7^?LR&$FRlY5ZN*8TRsH}I5q#1gttPIYmNSP#|%u*q! zYpHHIk$`*|a*7ZXW6>X7P*a;G1wrFbQqe#%y({|BR9pa3W!Qo_pq{gp#yL${Td=0~ z?nr&h1|17FXnQ3}v}KbB^hiUz>7T7thK&RV(ZiRtRj&OT>;M3$5=%JMF>e!eOt2b) z0p!0(9zh#ApaJ6RG?$Zy4XxKHjTK*~$4cvUx_}syx6r9p?sO?<{EBS7??uQvs4-_R zqMU~!4!^Pf^4+?bSZD={nyw_wG4C+KMjl5nfc)j|L@;+)Baryy&gbM|k8yH(xktvT zCwJGp~eQ~ewA2Y7fGrQlUY1Y*pRz~U;z2cJ(}u*7--^Myh2?$p`!1nx*2HKMmBa&J9|W1zs-QDcJw|BB#P&!3s_P>QvQ1ofhg z1|NmJ?$`tI z9i7V4#MC&Nrb)^($Kz>y4XR8*f6y5 ze}or5+blaBg&iW_8}0&8V_=3|NaU21@hkyoEH6B(7t3kO&_VB#%SJ0D?x2Jq8q_jvTWfmx_cq?vopp zt=?}VxXlDVFmByRu-Xjh9zuCOFC2v&eKGP zRrQvn`xVTX*+Ob3jQ zfU!?A?+#4lC^dI*jAUM;=pKuN(2hb0!wW`=rLGHj*HP8zW^4v^)&c`1GVB2~qcVm& zwwmGqdvP4L!hxVAp~H@Ft;gXk_nc;!hjT;_BAmf@Y+@EM(6n%3Twt7U@y=@osW2e6 zQuPRoa|FiQ;w_?PiZZ!*Y`a{r<)Bdn;^Q*1bz>pr7bImDG;ZY`!MbC%qtq)~H~`NI zX!!x%Z=*4AnhF3LxX#UQ=15~cLF@a}8wK+FBDlt+{8RKw1A;~(CJY)|V|YkwNnP-Wp{xyaY#3^BegwW?>w#zVh|{dR(vw!N^q)-0%1BGLo=GC z8#l!)tpgs`p>AM7Z7tA7`B^L}zHYiwH&@}$xq|3z5Uq#Vh@m7i^q`FxF85~`b&U+o z#IUbm_>ERDvdIjG`ZMfyjSO26LkujEaJS5`z0B};Y{h&kcfUr4TR^nFmtgp+%3F;1ei=PL`b`pm-VQT^ZH|(UN zer^&neZpBB^F~vfkm)4J(w%xm{ySE*dNTDVnZ8FWrk#$E$u~F#P^7pMKgS-{;9679 zcMVND>6KdX8U@FCj2?p*QBR$ORO7i+KX{j+jbPKMKV^PPr;e`DgJ27){=`uZ@;I5} zK$&9~e~uZ##rbrUf0eNFG5!*3*?Lk6fp&@${owr$ZM5~J*Q4B!B==X;h`b89PyT_T zxAz<9jhv#)&%WM@{d#*%?rk=;Va)}19C`fUB^=6!QahS`VeN)Hys2nap5i}jO>(A0 z;OL@?5WTy>W}Q6y<LZ+4$8B-_8u~%z1>B5j8e4e%qNPSZJ`i$=jJpK=5usj|lg-Inh|!!qnTo zoO)PMBvifN9BV%3kbhLO;qSiwxV{{W77CAV}+kreDc< zmVM=+{@b#nUF5*>28-9tUGombp|U3f|tGy z2+3*F+Dt15a|Pj*H?1Tx*B{o1*{qrOGz3IxujT=R*wVH>5k;(8;Kw&L$!PKs;Atdg z^R%A6I%hELHZVg#;BkWB565*DcW4M(~@*k*4J4jB`6tKd!;M}PtG;Q&tCM8>GD z!&oPHv>sR|(u-(Pf_H5zn9!Ya5t$fhdRTJZ5NL!cWw?lgBR(K)6CjX5mxK{O;lR&HTQV-?#Jo zPJVx%-#_5@-Tc0n-#_B_1N?rF-w*NoVSfLN-;eV9aen`T-@oGbll<=G_iy?AG{1k( z?`Qb^9KZj_@8|jbBEMha_h0$_cYc?mNuywX59Rkp{2q>bp2cd06{NHrXR*nu72jsm zTFr$Mo%vdeL+i-LC(_Jztux_Vq`BILJCHQV#7wrSdF`Q}1xj>(!+Yz33TiCigDfvp&_L%;%afz4i` zb=tHhs}-LNbDAZ4zRe0f@U^ufK~M(+61|jw`Z98^cB;v4F-?G$WC++*);~V(FVH{3 zZijWR_xjlOShuR~7?9o7cB>ackBTwqmEll4~Y3^YkKfjuVRxKGr$W z%$Jvbe0lNHC+RQIC+!dWqu%o9Cx7x^B7bJ#wfO^5|1p2W$NnYy{6T-vl-uz5i2n=L zYmD$~@`sT65BlS;Sy%tKKdvx7;{U33@EXPkEmVJaeEbFLSdj@|2{!UAzp~$oi~9@4 zDL$y1gRiX9qeq<_f5CXe2oh4@Th;$l&m<*glUubBY4a!;Dt5DbI+9y{Q(* z<&A|FdtD>_)qu+|mBxCQoF}$6m-9qpJxop>h^aKz!{j`tTkFK(4LR20f+Czx87=fQ zf+s5ZfG;Yor#7=sPc5=EoX^uGj`cGBP2p)=p~aGZr|I4k-Iq%Yy+D8Gm^CH{NjsI+dGg;PydOD<A%cA z-LmaA932*LYSPbQbM(^=A3l2Y=;3zzv}x1qQdHL{N50)?vroXECBSaZ(M{X6XM(Al zR&T-*fMZJso|G+lC0bz6T&?9;W}LG+`jMy^798T*wGOkhpVmTq5o20ZYvk5$t69qvxoF$t3 zX|aL@R!GOXP>EjxhZ_rj&M4<{G=U%#Zh(Q%n?eI8#yr5FA{o`uqgPxk zzlNLXgj#r&%&ARF??ihwj)lDnjDmA@0QzaKppPZF+t@%qO*1*PT15+?i~s%pR{y-? z#0(p&YF}|`n0pG#{otO#JDZGW_MbI1YpaXdxz*W|pBQXsrY-w>m|w_cyCQe2ubNTB z?tJziuO8YI&HD7;F#OTXES7QT%#VXC=`6PU%Psc~bTDJ%-8T-C3K_UowLdnQz2wzL z*S>HUGsTaJ?f%?2rhBY*$*d2G*iY*YFZk`gDeRYiMZ4#JG=MELv|c#q2_q}>y#HKA zvYkyjI%UD41P6nZ_qF;yo~;@`a(LIaQ`q^aaf>(qY+_Dg^y@_SaKE6ea+8szTWn`4 z9y2rNTdjZD^?`$JeLcEx#m^2Fu`%}X?nT2`^pfQl<4)eo;vVnb=8=TSZ0hl+TD)K$ z#i;kA59F|Jq~N>R>_Q{sGDBhld#d-}*Yq7@V{INe&?G-t&%Qp_;Un87E!%(ec+-cQ z#IYw&wtLAtDTlpNwk_r`OnVU0yZh@UyDXe&0*uG4sCyZtBEXWA~ac3#MZ++=66Q0p9YP6AnEA6>{b%= z(TVI4^ZcB9%JbOpuFGAkAJntvQ(mb&5}CsWe;b<6V$m4(>ZNf7+wL9177jwg>yuf@ zn3ahiHa4@tU~{ljE=wp~%jV7<%)(!3dsptHB2mB2!umb5Yqmbo!Zc0ada-1Zoz=c^ z|GCvajuHNTeG=1en%OQXBZob3*Zz0EyuN_tzxl1>txOYpVMFx|T^_Npu{W&UC%t$V zo9h_3^!yMTi=z&w5jg1%(@aNNrc_ z9Opj$N$SK;HnetqoWTw~+2)~#J219r=d^CckKe`){kVL2t6o8@@ql)BR)uwD1;73H zY~tt)_H58kc?S$VSlX;U_Rp98kh<=LkC#+!>cocUzWUsOM%~%cgxQA4`}d~4acD2e$sKqa3G#V2A}IZQtHG$Y2&=zyZlJ%;#FPd zuU~vFwPbY4`1W57W-oi*>r-?`H}=%gZNE&p|6J;kUq-gRY5um<4(A^IM~AyFrLI0H zRkz*NnT=W1bo%2{u4gHw8MA)N?#AA1eAk?gJ>m(QQ>A5VyXvje%m$V;Z}MC7zSgpYL6803`Q_TwEx8z}>pQYF z{Wah3KD;CK;+8$LHNSUczmoW^Z)R&w?l9iv9mwwPGRNIC95`5o@-4$P?TEiFZsw%mKJ(oEl zbKNn$&(DK?xY>Armw%-`Sv$I2^5243(cO1XzqkAL)WG;-^K*BG9ebB8{I0gwkn<~8 z=wrAS;dZ>E6g=!Pyeyn*su+`EGBKVwVf`P%{6}dPGX6P<)7Vf(>trj zdmin(@8Zz(dszN2&wZKD^DfqV?ZU5LIxw0I?Q!dyE#DZ$%G*4XHM3$A3yN&pzv_iy zto042dnC*n=6NwR;*F_;hI$5MANFkCHiWfL+Wgy*3kFX!^JDi8TV`M#S3UC2urh<^ zr!ndGYHuFw8F6^u_XD3F#6B#($?~#h5c{M_$&jt3dQa|8zb!b`Rqx?(^437l9V1s3 zMz_!Kyym_CjmCLtp1pnFd@1_YH1@)@Tbo_@mU%iyEPnIZj~T0)Xqe_^sUBOus_v;L zZu6v!%-#6m)c)*++@nL|<8SpWXl6PUe*LZNpf39D+R^@*c5v0tyh-En(J5_{v-)!mz|O=PVvY(4g*E77z4tNa>syLgry9Q@6}pJF{z z7mO;4?G@|EX_GfPvRw?T`e?gVcQKk3cCOgcwlJFQ+?D!lL2xhDebUDxvbXp2%vkaI zu(*uw?6q$qKOa-wjg2<<+td5!u58_&<1Z{Y-j%KT;AqaJiCtNHeOYP8gsyDto?27T z16@2R`THK-{k_hEpz3q-a~+#Jy~F8sB|6WKJzwq7G)Kn{J`ht?nWpnJ+W+z9eGxhq ze@c5@b&$>z7=OP%c|+HY&-7=Z(vD|RlJl8)O6`L+=?>PpH9ty#okyR8`bioVs?Y(hve9Z@yxxi->N6lbJ()y&ZcK4*x6$ps@`w8b{sRZn9oY8 zo$UGQf`aEBu(Rim48Cba(gZeb&O^bwS{AcL>(7V%7@Wgy%8K6ZdCSNie0uHcV@FM5 zKd)HX`$D7POp$X)M)!ri4n(rqn?HTkJfR)y^tXyfi;u*y83RtdS)3HdR!*_a+HxqC zwbZ-rIkKx2yZGh#U0rXDXVW{s=a|{IAA9@UL$&YOZe&3#c0IWzF_tY@vi|9r72)il zGi6`#BeCrL<54BWv*OvILEdQBmNx8}H=g)sSB!g4+WkMBwZ^d{H|%XXZDSiYC3wH( z^GWgS$$y+ozQy>pZyZ}*@0EA4`NOGw919+BtXh(~@WqI%gcS=mz4_pfeM4D!>ghJ4 z$F+TA@}`%DMa=7%IXTtPwnY1eK4(+!yYruZ>CBy}T6p2 zv(zGnOK0jXP-8&||@*dLbJ8Epq&{$ad`x2kcBwl96YD3tf1MXYA+ zYa!n>V~n;f+kP^MecJI@*6yy{TaUHQWyJ2tW4HSDtGxf0NBZLTO8X0CU!m+HlzqjO z_7BQ_A#hz+_5sSeudKVuI&tI9kDhR462 z@l}bZcXaiTJ~JGi<#YbNrTI_?>*h|;zBMe@6F1`dW+xln<8j`0;=!ly7|S9z+~4QK zscg@NVS694dXw1alNK)Ay0j0=sCsW@e0O{*@S!i}-!(MGbM6MqvL)|Dv!G7xQ?DD< zi&-9ev#H71)pPEl=OYUi>e#pu+kR#jZe)McM?arG=>|4-OUCy#=URI%*=#$r*S7X- zO|{nSd%hJ*uKsRQd3Gz7y=zkIF@qyLaWPY0@36Buo3`-8a!0SGtlz5CiPK(f_HRNT4)yeFy?$K8wh#}WX5I{8C(ll@y?8N*=_dU)fBh4Z=kNd67+STU zcGK&(9k3p_@%K$XT^K%n@50|U*#^Y5A9Ukysbe4P`OZ7teodXQ&6v6JwTqkfuR7bS z@go;fpFfy!^MhkAY}(N4?|r+xbv`wE#KXs%*PPq*W0P-RaO^pkI^^@gdt2XpZqu?~ zSFJVK&Zf5Ml|J&9j!lFgwDNe^J5}~eI2*;Uv+_K;SI&Qw^E0U*b?iNR#;1Q{g3r&X zUusMC{QS54J0!YF@ASwyd*X4r)(N^&ng8@>7{N=+qtlMP`^5A+6XH{opC11AfyW+9 zy~o9V(hTp*`Ynw8Vo^!PZG!)e?1wc2%%0a5rfxr48FRQ(Q%*0H=80VL$Z{P|6>@(p z*KxKZuG!R|-&LxV@vBCD1>HAX3Ys1n6xpnC_!1lhy@FQy_m7%q1%u`I;UK?4>C`A9 za&fRIv{@7)3R-ulC`2s`!{1m1PV57XL?NlHaVY)fFk(qq=m3yMEDIB;%jJBfoUaZG zr5~vgUQ-Abkt8z`S(Mz7$l8c3Qe@%uPc1$GZS5K%Z)g}QbjfJ{mb|MQh0?z_h^Uek z@iYpJ1Ivh=a(!>3P+G_$fX6lV!|NS@*XIg&Dc6X{>HYe}kF$Bd*~qW^BZlIVHkHaj z_bY_nFMln9J{-U=;i=N5p^HiL`AxYYBbLbdGC5z~G_(oOBUZ}!>ZYOiE`k&Ry6-9X zqvLp>!%zIB2+(E9cy#C(5w63%95HeC$HH%94}OJ)B8!L&rJq1YgiBY7)BXTcoc4J~ z(Ch>4Ks(h<;KkMMTNn$=%EBL>4X@i-1S6e}=S9e3GmdKTxfAk!-&rZI|II z$c%K!46m%;@rY3Rnf-MUT15mNqsoBcjZLp;SBejk?d%p|*H5WWy5xTU=y>AZ%ntQ{ z!yk!ODHjCKBi+7L$l)d>=#u5Q2LEJ-&LIC>)gjVCu%yo?P248>Novk}@%8gZ_2u&& z=C_TAr+;UBCZPMLAdluFArIC0C1Oq+dJAgMiQ6?+3`UChhOfv{VYbLp5#EudVz@_^ z5ZmF0qBTGeiMV6BM)Gl~NmeMGu`gL;NRL+~pxiD8`X@p!CuM{FnBjq~%b2*~_ zo1C|lb1|+XOYtLnT#=<>nTagLzh&a}HgZn03&H8%41=VUg*?>6(S^9f1I-=9!P)MI^hVShD7EmpqT0pgcY5~;(ss&UFs1{Hypjtq+fNBBN z0;&a63#b-QEudOJwSZ~?)dH#oR12sUP%WTZK(&Bs0o4Nk0T%Fm5!hI0#aCee<1YGl z_w>zzvxjPH{{!5us;F8(wSZ~?)dH#oR12sUP%WTZK(&Bs0o4Mk1yl>D7EmpqT0pgc zY5~;(ss&UFs1{Hypjtq+fNBBN0;&a63#b-QEudOJwSZ~?)dH#oR12sUP%WTZK(&Bs z0o4Mk1yl>D7EmpqT0pgcY5~;(ss&UFs1{Hypjtq+fNBBN0{@FGpoMJNNN13ukd(hg zkD{df-FGUtp__d1awPuRd#TbQ=z{PE>Vp!H79wq@HvBgT>AoN-$!kbX#3 zr00QJ3V zID*Vsj{(th`}rfnljN+xCS$IxFp!!gC@ip2Fa%Icvs;{j*u1R)HnyUMOv625w3-Wz zC>7LaPtLlmnSAWXGuw?h`6jz52O(*^ObQ>4rO;`fcvTDvXoZ2vVL_CcoF?3JY_N8o z-3;vtOjfHc2f4W*r=W=E1-7XKFc-iyl99;dE66Cl5*#YcpBo}c!SJsG%$$w_TP`1O zc_ydXVJs{H_X1cW$7H2&Y*bumaRT6!9uEqUo+-k#lap`GnJlGQZ4>jP@*wh_G0$Q( zOACU?ZE&&?@oXwELwjj)5YZb8iwh>8wlpYIT7up~q(#$k`+5p)C#FIei%pS28fddm zusBUtU&AI4?OB0|FPO%>428R`4ryJGBi~Lhg) zNafIb!2>~3sPveNSQ)vtQnP}5qj|bHr`TyW=0kYMxH1^iB-j|G1;GU-7;jfFSF7%8 zEYd+RD|;T3rSyXlyb7VK)#7j(rG3GoJEQb{aEP=gUf6w4{PJGq*Zrf>j-X#dd#z~x zX^=al>L$#?X_&wxAk4pLP6lcw)seLMqCQ%#v&o`vlIxxVQJ<{9;S{2GDsa1~&ywro z9il#8u1ii)e^9P3m+Mc;buBzX{9aJt(?tEBR1cRVHb>MqQoRWfJ)*u-saK2oKDiz$ z*AG)2A9QIZ*MmTsOE>xY67XE5g8WS^3I6rnsON z1lJ)gzaBSSR38!mC;A^^1nfDPUa2eep^%F%h29@d^osx9k?EDXLf-?!&7a;M9*tlN z87_Elk?EDXLZ2eYMgM;I?*YFHWK-hh6RP|9gXsP3djfEOd#->l{p;&dZ^*vwlZ1RT z!JF)>)D`)5_{$dnC;NOY(?2cKD|Ll_1|M*B_VtGoz3El~drziU>I!|Yfd2jAM88O; z|3Ri#>I(e|#1&msAL57K60zFFFWx&*9XzCJf!kBAEAgF3btEOeZ$nuNbmb!cSM$d` z!1wn@3F-~`Bkp$5e_B)F52a50Dc(PoJES`4;}0i$TsJ__7s&KVU7>eV0T*RN?++*X z$I=DtahYDJ6F&8y)EqZl3cWv^==Tg0upKhJQdj6P9r8<|SKt?bPw}qIhe6FmU6~J? z%5^5shpiO2JRi1~>&ko>CD)btFix&3^Wm*>U6~Iv6u3Mel6?OD90It%|AJu$|9TtL z$)9)1^VesnYlW&lef{~-u+Sjh!mEY7;;4>JmGK8NN*dTCQielq4p-uPsa#jalSi&A zI(zvczmfx?-6x*HkPFQ0rl?!>Y>0y|33V70rlj7Iv$Ve z;pYX^X9m=l1k_&&sJ|0X-xpB-DxiKLpsoq6FHg6CdP+e3&VYJBKz)8d{n>!}mVo-# z0d-nOVNa|=;<_%N9vM(?9Zs)>lcp{SBCRvjVpueoFlbfkU`6h=b z*>NZn9Y<}Zf}-en$!N~uz}{5izyvB0FcEwvaA035abOaa2$(DxClwbIIZYF+;1?GS zdK_rr!?MIY&ti8tsbHark9rY>SSe1L=%w6qFo^&W4+EEhaj;j2@W$*Q+`p%QV?M5a(!)n1N{{Ge&U#kP)JDE%ulz z3m$E|Y)bb{+*h9JmBiau$XqGMa|A4RgaETEb z)bqPf0rI)L^`e-kD7p5%)StBxs_W5j`xQ9JTzP7_vI2awS5NVw;z;=axclmB(SQ#F zwwC{6TSc*nS0X7uipw{+|2^x||E Date: Fri, 14 Apr 2023 11:23:52 -0600 Subject: [PATCH 644/852] working now --- CMakeLists.txt | 24 ++++++++++++++++--- biogeochem/CMakeLists.txt | 5 ++++ biogeophys/test/solar_rad_test/CMakeLists.txt | 5 ---- .../solar_rad_test/FatesUnitTestRadiation.F90 | 4 ++-- main/FatesParametersInterface.F90 | 20 ++++------------ 5 files changed, 33 insertions(+), 25 deletions(-) create mode 100644 biogeochem/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 55422d596e..78c6945656 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,12 +13,16 @@ set(CLM_ROOT "../../") # Add source directories from other share code (csm_share, etc.) add_subdirectory(${CLM_ROOT}/share/src csm_share) +add_subdirectory(${CLM_ROOT}/share/unit_test_stubs/util csm_share_stubs) +#add_subdirectory(${CLM_ROOT}/src/unit_test_shr clm_unit_shr) +#add_subdirectory(${CLM_ROOT}/src/unit_test_stubs clm_unit_stubs) ## shr sources we need ## shr_log_mod.F90 -## shr_infnan_mod.F90.in +## shr_infnan_mod.F90 ## shr_kind_mod.F90 -## shr_strconvert_mod +## shr_strconvert_mod.F90 +## shr_sys_mod.F90 # Extract just the files we need from csm_share set (shr_sources_needed_base @@ -26,13 +30,14 @@ set (shr_sources_needed_base shr_infnan_mod.F90 shr_kind_mod.F90 shr_sys_mod.F90 - shr_abort_mod.F90 shr_strconvert_mod.F90 + shr_abort_mod.abortthrows.F90 ) extract_sources("${shr_sources_needed_base}" "${share_sources}" shr_sources_needed) # Add FATES source directories add_subdirectory(${CLM_ROOT}/src/fates/main fates_main) +add_subdirectory(${CLM_ROOT}/src/fates/biogeochem fates_biogeochem) add_subdirectory(${CLM_ROOT}/src/fates/parteh fates_parteh) # Add general unit test directories (stubbed out files, etc.) @@ -79,6 +84,19 @@ add_dependencies(fates csm_share) # We need to look for header files here, in order to pick up shr_assert.h include_directories(${CLM_ROOT}/share/include) +set(NETCDF_C_DIR "/usr/local/Cellar/netcdf/4.9.2") +set(NETCDF_FORTRAN_DIR "/usr/local/Cellar/netcdf-fortran/4.6.0") + +FIND_PATH(NETCDFC_FOUND libnetcdf.a ${NETCDF_C_DIR}/lib) +FIND_PATH(NETCDFF_FOUND libnetcdff.a ${NETCDF_FORTRAN_DIR}/lib) +MESSAGE(" NETCDFC_FOUND = ${NETCDFC_FOUND}") +MESSAGE(" NETCDFF_FOUND = ${NETCDFF_FOUND}") + +include_directories(${NETCDF_C_DIR}/include + ${NETCDF_FORTRAN_DIR}/include) +link_directories(${NETCDF_C_DIR}/lib + ${NETCDF_FORTRAN_DIR}/lib) + include_directories(${CMAKE_CURRENT_BINARY_DIR}) link_directories(${CMAKE_CURRENT_BINARY_DIR}) diff --git a/biogeochem/CMakeLists.txt b/biogeochem/CMakeLists.txt new file mode 100644 index 0000000000..692e22d9dc --- /dev/null +++ b/biogeochem/CMakeLists.txt @@ -0,0 +1,5 @@ +list(APPEND fates_sources + FatesLitterMod.F90 + ) + +sourcelist_to_parent(fates_sources) \ No newline at end of file diff --git a/biogeophys/test/solar_rad_test/CMakeLists.txt b/biogeophys/test/solar_rad_test/CMakeLists.txt index 415894202c..896cfc024e 100644 --- a/biogeophys/test/solar_rad_test/CMakeLists.txt +++ b/biogeophys/test/solar_rad_test/CMakeLists.txt @@ -21,11 +21,6 @@ target_link_libraries(FATES_rad_exe fates csm_share) -#target_include_directories(FATES_rad_exe PUBLIC -# "${PROJECT_BINARY_DIR}" -# "${PROJECT_SOURCE_DIR}/fates_main" -# ) - add_test(rad_test FATES_rad_exe) # Tell CTest how to figure out that "STOP 1" fails for the current diff --git a/biogeophys/test/solar_rad_test/FatesUnitTestRadiation.F90 b/biogeophys/test/solar_rad_test/FatesUnitTestRadiation.F90 index ba869803b6..05210b52df 100644 --- a/biogeophys/test/solar_rad_test/FatesUnitTestRadiation.F90 +++ b/biogeophys/test/solar_rad_test/FatesUnitTestRadiation.F90 @@ -80,8 +80,8 @@ end subroutine read_radiation_params call read_radiation_params(param_file, numSWb, rhol, rhos, taul, taus, xl, ci) ! read in patch data - call read_patch_data(patch_file, canopy_area_profile, elai_profile, & - esai_profile, nrad_r) + !call read_patch_data(patch_file, canopy_area_profile, elai_profile, & + ! esai_profile, nrad_r) ! call get_orbital_vals(year, logf, eccen, mvelp, obliqr, lambm0, mvelpp) diff --git a/main/FatesParametersInterface.F90 b/main/FatesParametersInterface.F90 index aa13150c4a..b19817a091 100644 --- a/main/FatesParametersInterface.F90 +++ b/main/FatesParametersInterface.F90 @@ -4,7 +4,7 @@ module FatesParametersInterface ! depend on any host modules. use FatesConstantsMod, only : r8 => fates_r8 - use FatesGlobals, only : fates_log + use FatesGlobals, only : fates_log, fates_endrun implicit none private ! Modules are private by default @@ -172,8 +172,6 @@ end subroutine RetrieveParameterScalar !----------------------------------------------------------------------- subroutine RetrieveParameter1D(this, name, data) - use abortutils, only : endrun - implicit none class(fates_parameters_type), intent(inout) :: this @@ -192,7 +190,7 @@ subroutine RetrieveParameter1D(this, name, data) do d = 1, max_dimensions write(fates_log(), *) this%parameters(i)%dimension_names(d), ', ', this%parameters(i)%dimension_sizes(d) end do - call endrun(msg='size error retreiving 1d parameter.') + call fates_endrun(msg='size error retreiving 1d parameter.') end if data = this%parameters(i)%data(:, 1) @@ -201,8 +199,6 @@ end subroutine RetrieveParameter1D !----------------------------------------------------------------------- subroutine RetrieveParameter2D(this, name, data) - use abortutils, only : endrun - implicit none class(fates_parameters_type), intent(inout) :: this @@ -225,7 +221,7 @@ subroutine RetrieveParameter2D(this, name, data) do d = 1, max_dimensions write(fates_log(), *) this%parameters(i)%dimension_names(d), ', ', this%parameters(i)%dimension_sizes(d) end do - call endrun(msg='size error retreiving 2d parameter.') + call fates_endrun(msg='size error retreiving 2d parameter.') end if data = this%parameters(i)%data @@ -234,8 +230,6 @@ end subroutine RetrieveParameter2D !----------------------------------------------------------------------- subroutine RetrieveParameter1DAllocate(this, name, data) - use abortutils, only : endrun - implicit none class(fates_parameters_type), intent(inout) :: this @@ -255,8 +249,6 @@ end subroutine RetrieveParameter1DAllocate !----------------------------------------------------------------------- subroutine RetrieveParameter2DAllocate(this, name, data) - use abortutils, only : endrun - implicit none class(fates_parameters_type), intent(inout) :: this @@ -439,9 +431,7 @@ end subroutine SetDataScalar !----------------------------------------------------------------------- subroutine SetData1D(this, index, data) - - use abortutils, only : endrun - + implicit none class(fates_parameters_type), intent(inout) :: this @@ -460,7 +450,7 @@ subroutine SetData1D(this, index, data) do d = 1, max_dimensions write(fates_log(), *) this%parameters(index)%dimension_names(d), ', ', this%parameters(index)%dimension_sizes(d) end do - call endrun(msg='size error setting 1d parameter.') + call fates_endrun(msg='size error setting 1d parameter.') end if allocate(this%parameters(index)%data(size_dim_1, 1)) From b42a6ce214677a831d0b3f403b5174f406a99dda Mon Sep 17 00:00:00 2001 From: Marcos Longo Date: Fri, 14 Apr 2023 19:01:33 -0700 Subject: [PATCH 645/852] A few bug fixes in the code. 1. For canopy trimming, the code should not use the actual elongation factors 2. Still in canopy trimming, the code is now accounting for semideciduous PFTs 3. Added a test to prevent canopy damage recovery unless leaves are flushing. --- biogeochem/EDCohortDynamicsMod.F90 | 35 +++++- biogeochem/EDMortalityFunctionsMod.F90 | 2 + biogeochem/EDPhysiologyMod.F90 | 161 ++++++++++++------------- main/FatesConstantsMod.F90 | 3 + 4 files changed, 118 insertions(+), 83 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 2d9154dd64..ecb7d3cf77 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -41,8 +41,12 @@ Module EDCohortDynamicsMod use PRTGenericMod , only : max_nleafage use EDTypesMod , only : ican_upper use EDTypesMod , only : site_fluxdiags_type - use PRTGenericMod , only : num_elements + use PRTGenericMod , only : num_elements use EDTypesMod , only : leaves_on + use EDTypesMod , only : leaves_off + use EDTypesMod , only : leaves_shedding + use EDTypesMod , only : ihard_stress_decid + use EDTypesMod , only : isemi_stress_decid use EDParamsMod , only : ED_val_cohort_age_fusion_tol use FatesInterfaceTypesMod , only : hlm_use_planthydro use FatesInterfaceTypesMod , only : hlm_parteh_mode @@ -2275,6 +2279,9 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) real(r8) :: nplant_recover ! number of plants in cohort that will ! recover to the next class integer :: el ! element loop counter + + logical :: is_hydecid_dormant ! Flag to signal that the cohort is drought deciduous and dormant + logical :: is_sedecid_dormant ! Flag to signal this is a deciduous PFT associate(dbh => ccohort%dbh, & ipft => ccohort%pft, & @@ -2295,6 +2302,16 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) return end if + + !--- Set some logical flags to simplify "if" blocks + is_hydecid_dormant = & + any(prt_params%stress_decid(ipft) == [ihard_stress_decid,isemi_stress_decid] ) & + .and. any(ccohort%status_coh == [leaves_off,leaves_shedding] ) + is_sedecid_dormant = & + ( prt_params%season_decid(ipft) == itrue ) & + .and. any(ccohort%status_coh == [leaves_off,leaves_shedding] ) + + ! If we have not returned, then this cohort both has ! a damaged status, and the ability to recover from that damage @@ -2303,7 +2320,7 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) ! To determine recovery, the first priority is to determine how much ! resources (C,N,P) are required to recover the plant to the target ! pool sizes of the next (less) damage class - + ! Target sapwood biomass according to allometry, trimming and phenology [kgC] call bsap_allom(dbh,ipft, ccohort%crowndamage-1, canopy_trim, elongf_stem, & sapw_area,target_sapw_c) @@ -2322,6 +2339,20 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) ! Target leaf biomass according to allometry, trimming and phenology [kgC] call bleaf(dbh,ipft,ccohort%crowndamage-1, canopy_trim, elongf_leaf, target_leaf_c) + + ! If plants are drought deciduous and are losing or lost all leaves, halt all + ! the growth. + if (is_hydecid_dormant) then + ! Drought-deciduous. Do not recover any tissue until the growing season + target_leaf_c = 0._r8 + target_fnrt_c = 0._r8 + target_sapw_c = 0._r8 + target_struct_c = 0._r8 + elseif (is_sedecid_dormant) then + ! Cold-deciduous. Do not recover leaves until the growing season + target_leaf_c = 0._r8 + end if + ! We will be taking the number of recovering plants ! based on minimum of available resources for C/N/P (initialize high) nplant_recover = 1.e10_r8 diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index e3baea2935..f2a0a2a29c 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -169,6 +169,8 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmor ! We compare storage with leaf biomass if plant were fully flushed, otherwise ! mortality would be underestimated for plants that lost all leaves and have no ! storage to flush new ones. + ! MLO. Why isn't this comparing with storage allometry (i.e., accounting for + ! cushion)? call bleaf(cohort_in%dbh,cohort_in%pft,cohort_in%crowndamage,cohort_in%canopy_trim, & 1.0_r8, target_leaf_c) store_c = cohort_in%prt%GetState(store_organ,carbon12_element) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index c97b4d8992..ac176086a7 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -23,6 +23,8 @@ module EDPhysiologyMod use FatesInterfaceTypesMod, only : hlm_use_tree_damage use FatesConstantsMod, only : r8 => fates_r8 use FatesConstantsMod, only : nearzero + use FatesConstantsMod, only : g_per_kg + use FatesConstantsMod, only : ndays_per_year use EDPftvarcon , only : EDPftvarcon_inst use PRTParametersMod , only : prt_params use EDPftvarcon , only : GetDecompyFrac @@ -149,6 +151,27 @@ module EDPhysiologyMod integer, parameter :: dleafon_drycheck = 100 ! Drought deciduous leaves max days on check parameter + real(r8), parameter :: decid_leaf_long_max = 1.0_r8 ! Maximum leaf lifespan for + ! deciduous PFTs [years] + + integer, parameter :: min_daysoff_dforcedflush = 30 ! This is the number of days that must had elapsed + ! since leaves had dropped, in order to forcably + ! flush leaves again. This does not impact flushing + ! due to real moisture constraints, and will prevent + ! drought deciduous in perennially wet environments + ! that have been forced to drop their leaves, from + ! flushing them back immediately. + + integer, parameter :: dd_offon_toler = 30 ! When flushing or shedding leaves, we check that + ! the dates are near last year's dates. This controls + ! the tolerance for deviating from last year. + + real(r8), parameter :: elongf_min = 0.05_r8 ! Minimum elongation factor. If elongation factor + ! reaches or falls below elongf_min, we assume + ! complete abscission. This avoids carrying out + ! a residual amount of leaves, which may create + ! computational problems. The current threshold + ! is the same used in ED-2.2. ! ============================================================================ @@ -616,6 +639,8 @@ subroutine trim_canopy( currentSite ) real(r8) :: optimum_trim ! Optimum trim value real(r8) :: target_c_area + + real(r8) :: pft_leaf_lifespan ! Leaf lifespan of each PFT [years] !---------------------------------------------------------------------- ipatch = 1 ! Start counting patches @@ -638,7 +663,7 @@ subroutine trim_canopy( currentSite ) initial_trim = currentCohort%canopy_trim - ! Add debug diagnstic output to determine which cohort + ! Add debug diagnostic output to determine which cohort if (debug) then write(fates_log(),*) 'Current cohort:', icohort write(fates_log(),*) 'Starting canopy trim:', initial_trim @@ -655,7 +680,7 @@ subroutine trim_canopy( currentSite ) currentCohort%n, currentCohort%canopy_layer, & currentPatch%canopy_layer_tlai,currentCohort%vcmax25top ) - ! We don't need check on sp mode here since we don't trim_canopy with sp mode + ! We don't need to check on sp mode here since we don't trim_canopy with sp mode currentCohort%treesai = tree_sai(currentCohort%pft, & currentCohort%dbh, currentCohort%crowndamage, & currentCohort%canopy_trim, & @@ -673,14 +698,15 @@ subroutine trim_canopy( currentSite ) call endrun(msg=errMsg(sourcefile, __LINE__)) endif - + ! Find target leaf biomass. Here we assume that leaves would be fully flushed + ! (elongation factor = 1) call bleaf(currentcohort%dbh,ipft,& - currentCohort%crowndamage, currentcohort%canopy_trim,currentCohort%efleaf_coh, tar_bl) + currentCohort%crowndamage, currentcohort%canopy_trim,1.0_r8, tar_bl) if ( int(prt_params%allom_fmode(ipft)) .eq. 1 ) then ! only query fine root biomass if using a fine root allometric model that takes leaf trim into account - call bfineroot(currentcohort%dbh,ipft,currentcohort%canopy_trim,currentcohort%l2fr, & - currentCohort%effnrt_coh, tar_bfr) + call bfineroot(currentcohort%dbh,ipft,currentcohort%canopy_trim, & + currentcohort%l2fr,1.0_r8, tar_bfr) bfr_per_bleaf = tar_bfr/tar_bl endif @@ -694,7 +720,7 @@ subroutine trim_canopy( currentSite ) nnu_clai_a(:,:) = 0._r8 nnu_clai_b(:,:) = 0._r8 - !Leaf cost vs netuptake for each leaf layer. + !Leaf cost vs net uptake for each leaf layer. do z = 1, currentCohort%nv ! Calculate the cumulative total vegetation area index (no snow occlusion, stems and leaves) @@ -720,47 +746,39 @@ subroutine trim_canopy( currentSite ) ! Nscaler value at leaf level z nscaler_levleaf = exp(-kn * cumulative_lai) ! Sla value at leaf level z after nitrogen profile scaling (m2/gC) - sla_levleaf = prt_params%slatop(ipft)/nscaler_levleaf - - if(sla_levleaf > sla_max)then - sla_levleaf = sla_max - end if - - !Leaf Cost kgC/m2/year-1 - !decidous costs. - if (prt_params%season_decid(ipft) == itrue .or. & - prt_params%stress_decid(ipft) == itrue )then + sla_levleaf = min(sla_max,prt_params%slatop(ipft)/nscaler_levleaf) - ! Leaf cost at leaf level z accounting for sla profile (kgC/m2) - currentCohort%leaf_cost = 1._r8/(sla_levleaf*1000.0_r8) + ! Find the realised leaf lifespan, depending on the leaf phenology. + if (prt_params%season_decid(ipft) == itrue) then + ! Cold-deciduous costs. Assume time-span to be 1 year to be consistent + ! with FATES default + pft_leaf_lifespan = decid_leaf_long_max - if ( int(prt_params%allom_fmode(ipft)) .eq. 1 ) then - ! if using trimmed leaf for fine root biomass allometry, add the cost of the root increment - ! to the leaf increment; otherwise do not. - currentCohort%leaf_cost = currentCohort%leaf_cost + & - 1.0_r8/(sla_levleaf*1000.0_r8) * & - bfr_per_bleaf / prt_params%root_long(ipft) - endif + elseif (any(prt_params%stress_decid(ipft) == [ihard_stress_decid,isemi_stress_decid]) )then + ! Drought-decidous costs. Assume time-span to be the least between + ! 1 year and the life span provided by the parameter file. + pft_leaf_lifespan = & + min(decid_leaf_long_max,sum(prt_params%leaf_long(ipft,:))) - currentCohort%leaf_cost = currentCohort%leaf_cost * & - (prt_params%grperc(ipft) + 1._r8) else !evergreen costs + pft_leaf_lifespan = sum(prt_params%leaf_long(ipft,:)) + end if - ! Leaf cost at leaf level z accounting for sla profile - currentCohort%leaf_cost = 1.0_r8/(sla_levleaf* & - sum(prt_params%leaf_long(ipft,:))*1000.0_r8) !convert from sla in m2g-1 to m2kg-1 + ! Leaf cost at leaf level z (kgC m-2 year-1) accounting for sla profile + ! (Convert from SLA in m2g-1 to m2kg-1) + currentCohort%leaf_cost = & + 1.0_r8/(sla_levleaf*pft_leaf_lifespan*g_per_kg) - if ( int(prt_params%allom_fmode(ipft)) .eq. 1 ) then - ! if using trimmed leaf for fine root biomass allometry, add the cost of the root increment - ! to the leaf increment; otherwise do not. - currentCohort%leaf_cost = currentCohort%leaf_cost + & - 1.0_r8/(sla_levleaf*1000.0_r8) * & - bfr_per_bleaf / prt_params%root_long(ipft) - endif - currentCohort%leaf_cost = currentCohort%leaf_cost * & - (prt_params%grperc(ipft) + 1._r8) - endif + if ( int(prt_params%allom_fmode(ipft)) == 1 ) then + ! if using trimmed leaf for fine root biomass allometry, add the cost of the root increment + ! to the leaf increment; otherwise do not. + currentCohort%leaf_cost = currentCohort%leaf_cost + & + 1.0_r8/(sla_levleaf*g_per_kg) * & + bfr_per_bleaf / prt_params%root_long(ipft) + end if + currentCohort%leaf_cost = currentCohort%leaf_cost * & + (prt_params%grperc(ipft) + 1._r8) ! Construct the arrays for a least square fit of the net_net_uptake versus the cumulative lai ! if at least nll leaf layers are present in the current cohort and only for the bottom nll @@ -907,10 +925,11 @@ subroutine phenology( currentSite, bc_in ) real(r8) :: temp_in_C ! daily averaged temperature in celsius real(r8) :: elongf_prev ! Elongation factor from previous time real(r8) :: elongf_1st ! First guess for elongation factor - integer :: pft_leaf_lifespan ! PFT life span of drought deciduous. - ! This is the shortest between the PFT leaf lifespan - ! and the maximum lifespan of drought deciduous - ! (see canopy_leaf_lifespan below) + integer :: ndays_pft_leaf_lifespan ! PFT life span of drought deciduous [days]. + ! This is the shortest between the PFT leaf + ! lifespan and the maximum lifespan of drought + ! deciduous (see parameter decid_leaf_long_max + ! at the beginning of this file). real(r8) :: phen_drought_threshold ! For drought hard-deciduous, this is the threshold ! below which plants will abscise leaves, and ! above which plants will flush leaves. For semi- @@ -941,26 +960,6 @@ subroutine phenology( currentSite, bc_in ) logical :: prolonged_off_period ! Have leaves been abscissed for too long? logical :: last_flush_long_ago ! Has it been a very long time since last flushing? - integer, parameter :: canopy_leaf_lifespan = 365 ! Maximum lifespan of drought decid leaves - - integer, parameter :: min_daysoff_dforcedflush = 30 ! This is the number of days that must had elapsed - ! since leaves had dropped, in order to forcably - ! flush leaves again. This does not impact flushing - ! due to real moisture constraints, and will prevent - ! drought deciduous in perennially wet environments - ! that have been forced to drop their leaves, from - ! flushing them back immediately. - - integer, parameter :: dd_offon_toler = 30 ! When flushing or shedding leaves, we check that - ! the dates are near last year's dates. This controls - ! the tolerance for deviating from last year. - - real(r8), parameter :: elongf_min = 0.05_r8 ! Minimum elongation factor. If elongation factor - ! reaches or falls below elongf_min, we assume - ! complete abscission. This avoids carrying out - ! a residual amount of leaves, which may create - ! computational problems. The current threshold - ! is the same used in ED-2.2. ! This is the integer model day. The first day of the simulation is 1, and it ! continues monotonically, indefinitely @@ -1040,7 +1039,7 @@ subroutine phenology( currentSite, bc_in ) !this logic is to prevent GDD accumulating after the leaves have fallen and before the ! beginnning of the accumulation period, to prevend erroneous autumn leaf flushing. - if(model_day_int>365)then !only do this after the first year to prevent odd behaviour + if(model_day_int> ndays_per_year)then !only do this after the first year to prevent odd behaviour if(currentSite%lat .gt. 0.0_r8)then !Northern Hemisphere ! In the north, don't accumulate when we are past the leaf fall date. @@ -1063,13 +1062,13 @@ subroutine phenology( currentSite, bc_in ) ! not had occured yet, so set it to last year to get things rolling if (model_day_int < currentSite%cleafoffdate) then - currentSite%cndaysleafoff = model_day_int - (currentSite%cleafoffdate - 365) + currentSite%cndaysleafoff = model_day_int - (currentSite%cleafoffdate - ndays_per_year) else currentSite%cndaysleafoff = model_day_int - currentSite%cleafoffdate end if if (model_day_int < currentSite%cleafondate) then - currentSite%cndaysleafon = model_day_int - (currentSite%cleafondate-365) + currentSite%cndaysleafon = model_day_int - (currentSite%cleafondate - ndays_per_year) else currentSite%cndaysleafon = model_day_int - currentSite%cleafondate end if @@ -1208,12 +1207,12 @@ subroutine phenology( currentSite, bc_in ) ! for the first year of simulation, we have to assume leaf drop / leaf flush ! dates to start, so if that is in the future, set it to last year if (model_day_int < currentSite%dleafoffdate(ipft)) then - currentSite%dndaysleafoff(ipft) = model_day_int - (currentSite%dleafoffdate(ipft)-365) + currentSite%dndaysleafoff(ipft) = model_day_int - (currentSite%dleafoffdate(ipft)-ndays_per_year) else currentSite%dndaysleafoff(ipft) = model_day_int - currentSite%dleafoffdate(ipft) end if if (model_day_int < currentSite%dleafondate(ipft)) then - currentSite%dndaysleafon(ipft) = model_day_int - (currentSite%dleafondate(ipft)-365) + currentSite%dndaysleafon(ipft) = model_day_int - (currentSite%dleafondate(ipft)-ndays_per_year) else currentSite%dndaysleafon(ipft) = model_day_int - currentSite%dleafondate(ipft) end if @@ -1227,9 +1226,8 @@ subroutine phenology( currentSite, bc_in ) ! (defined as a PFT parameter) and the maximum canopy leaf life span allowed ! for drought deciduous (local parameter). The sum term accounts for the ! total leaf life span of this cohort. - pft_leaf_lifespan = min( canopy_leaf_lifespan, & - nint(365*sum(prt_params%leaf_long(ipft,:))) ) - + ndays_pft_leaf_lifespan = & + nint(ndays_per_year*min(decid_leaf_long_max,sum(prt_params%leaf_long(ipft,:)))) !---~--- @@ -1275,24 +1273,25 @@ subroutine phenology( currentSite, bc_in ) ! Leaves have been "on" for longer than the leaf lifetime. prolonged_on_period = & any( currentSite%dstatus(ipft) == [phen_dstat_timeon,phen_dstat_moiston] ) .and. & - ( currentSite%dndaysleafon(ipft) > pft_leaf_lifespan ) + ( currentSite%dndaysleafon(ipft) > ndays_pft_leaf_lifespan ) ! Leaves have been "off" for a sufficiently long time and the last flushing ! was about one year ago (+/- tolerance). prolonged_off_period = & any( currentSite%dstatus(ipft) == [phen_dstat_timeoff,phen_dstat_moistoff] ) .and. & ( currentSite%dndaysleafoff(ipft) > phen_doff_time ) .and. & - ( currentSite%dndaysleafon(ipft) >= 365-dd_offon_toler ) .and. & - ( currentSite%dndaysleafon(ipft) <= 365+dd_offon_toler ) + ( currentSite%dndaysleafon(ipft) >= ndays_per_year-dd_offon_toler ) .and. & + ( currentSite%dndaysleafon(ipft) <= ndays_per_year+dd_offon_toler ) ! Last flushing was a very long time ago. last_flush_long_ago = & - ( currentSite%dstatus(ipft) == phen_dstat_moistoff ) .and. & - ( currentSite%dndaysleafon(ipft) > 365+dd_offon_toler ) + ( currentSite%dstatus(ipft) == phen_dstat_moistoff ) .and. & + ( currentSite%dndaysleafon(ipft) > ndays_per_year+dd_offon_toler ) !---~--- !---~--- ! Revision of the conditions, added an if/elseif/else structure to ensure only - ! up to one change occurs at any given time (ML 20211120) + ! up to one change occurs at any given time. Also, prevent changes until the + ! soil moisture memory is populated (the outer if check). !---~--- past_spinup_ifelse: if (model_day_int > numWaterMem) then drought_smoist_ifelse: if ( prolonged_off_period .and. & @@ -1392,10 +1391,10 @@ subroutine phenology( currentSite, bc_in ) ( currentSite%dndaysleafoff(ipft) <= min_daysoff_dforcedflush ) ! Leaves have been flushing for longer than their time span. prolonged_on_period = all( [elongf_prev,elongf_1st] >= elongf_min ) .and. & - ( currentSite%dndaysleafon(ipft) > pft_leaf_lifespan ) + ( currentSite%dndaysleafon(ipft) > ndays_pft_leaf_lifespan ) ! It's been a long time since the plants had flushed their leaves. last_flush_long_ago = all( [elongf_prev,elongf_1st] < elongf_min ) .and. & - ( currentSite%dndaysleafon(ipft) > 365+dd_offon_toler ) + ( currentSite%dndaysleafon(ipft) > ndays_per_year+dd_offon_toler ) !---~--- diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index ee3bd6cfb3..4cdaf6406b 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -173,6 +173,9 @@ module FatesConstantsMod ! If we need to link to 365.25-day-calendared HLM, rewire to pass through interface real(fates_r8), parameter, public :: days_per_year = 365.00_fates_r8 + ! Integer version of days per year. + integer, parameter, public :: ndays_per_year = nint(days_per_year) + ! Conversion: years per day. assume HLM uses 365 day calendar. ! If we need to link to 365.25-day-calendared HLM, rewire to pass through interface real(fates_r8), parameter, public :: years_per_day = 1.0_fates_r8/365.00_fates_r8 From a78f44f79cc962f0dc3d6748b504ae9cc67b074c Mon Sep 17 00:00:00 2001 From: adrifoster Date: Fri, 21 Apr 2023 09:21:35 -0600 Subject: [PATCH 646/852] more cmake stuff --- CMakeLists.txt | 15 +++++---------- biogeochem/CMakeLists.txt | 3 +++ biogeophys/CMakeLists.txt | 8 ++++++++ fire/CMakeLists.txt | 8 ++++++++ main/CMakeLists.txt | 9 +++++++++ main/FatesInterfaceMod.F90 | 15 ++++++++++----- parteh/CMakeLists.txt | 3 +++ 7 files changed, 46 insertions(+), 15 deletions(-) create mode 100644 biogeophys/CMakeLists.txt create mode 100644 fire/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 78c6945656..8c772fdf05 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,15 +14,8 @@ set(CLM_ROOT "../../") # Add source directories from other share code (csm_share, etc.) add_subdirectory(${CLM_ROOT}/share/src csm_share) add_subdirectory(${CLM_ROOT}/share/unit_test_stubs/util csm_share_stubs) -#add_subdirectory(${CLM_ROOT}/src/unit_test_shr clm_unit_shr) -#add_subdirectory(${CLM_ROOT}/src/unit_test_stubs clm_unit_stubs) - -## shr sources we need -## shr_log_mod.F90 -## shr_infnan_mod.F90 -## shr_kind_mod.F90 -## shr_strconvert_mod.F90 -## shr_sys_mod.F90 +add_subdirectory(${CLM_ROOT}/src/utils clm_utils) +add_subdirectory(${CLM_ROOT}/src/main clm_main) # Extract just the files we need from csm_share set (shr_sources_needed_base @@ -38,9 +31,11 @@ extract_sources("${shr_sources_needed_base}" "${share_sources}" shr_sources_need # Add FATES source directories add_subdirectory(${CLM_ROOT}/src/fates/main fates_main) add_subdirectory(${CLM_ROOT}/src/fates/biogeochem fates_biogeochem) +add_subdirectory(${CLM_ROOT}/src/fates/biogeophys fates_biogephys) add_subdirectory(${CLM_ROOT}/src/fates/parteh fates_parteh) +add_subdirectory(${CLM_ROOT}/src/fates/fire fates_fire) -# Add general unit test directories (stubbed out files, etc.) +# Add general unit test directories add_subdirectory(${CLM_ROOT}/src/fates/unit_test_shr) # Remove shr_mpi_mod from share_sources. diff --git a/biogeochem/CMakeLists.txt b/biogeochem/CMakeLists.txt index 692e22d9dc..b9a6889443 100644 --- a/biogeochem/CMakeLists.txt +++ b/biogeochem/CMakeLists.txt @@ -1,5 +1,8 @@ list(APPEND fates_sources FatesLitterMod.F90 + FatesAllometryMod.F90 + DamageMainMod.F90 + FatesPatchMod.F90 ) sourcelist_to_parent(fates_sources) \ No newline at end of file diff --git a/biogeophys/CMakeLists.txt b/biogeophys/CMakeLists.txt new file mode 100644 index 0000000000..037dd49fa7 --- /dev/null +++ b/biogeophys/CMakeLists.txt @@ -0,0 +1,8 @@ +# Note that this is just used for unit testing; hence, we only need to add +# source files that are currently used in unit tests + +list(APPEND fates_sources + FatesHydroWTFMod.F90 + ) + +sourcelist_to_parent(fates_sources) diff --git a/fire/CMakeLists.txt b/fire/CMakeLists.txt new file mode 100644 index 0000000000..0cec31a6a6 --- /dev/null +++ b/fire/CMakeLists.txt @@ -0,0 +1,8 @@ +# Note that this is just used for unit testing; hence, we only need to add +# source files that are currently used in unit tests + +list(APPEND fates_sources + SFParamsMod.F90 + ) + +sourcelist_to_parent(fates_sources) diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 8c65b32513..6cbca40357 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -13,11 +13,20 @@ list(APPEND clm_sources list(APPEND fates_sources FatesConstantsMod.F90 + EDTypesMod.F90 EDPftvarcon.F90 EDParamsMod.F90 FatesGlobals.F90 FatesInterfaceTypesMod.F90 FatesParametersInterface.F90 + FatesParameterDerivedMod.F90 + FatesHydraulicsMemMod.F90 + FatesRunningMeanMod.F90 + FatesCohortMod.F90 + FatesSizeAgeTypeIndicesMod.F90 + FatesIntegratorsMod.F90 + FatesUtilsMod.F90 + FatesSynchronizedParamsMod.F90 ) sourcelist_to_parent(clm_sources) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 41ae7798d0..72950c5cdb 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -95,6 +95,7 @@ module FatesInterfaceMod ! CIME Globals use shr_log_mod , only : errMsg => shr_log_errMsg use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) + use shr_kind_mod , only : SHR_KIND_CL ! Just use everything from FatesInterfaceTypesMod, this is ! its sister code @@ -723,7 +724,8 @@ end subroutine set_bcs ! =================================================================================== - subroutine SetFatesGlobalElements1(use_fates,surf_numpft,surf_numcft) + subroutine SetFatesGlobalElements1(use_fates,surf_numpft,surf_numcft, & + masterproc, paramfile, fates_paramfile) ! -------------------------------------------------------------------------------- ! @@ -735,16 +737,19 @@ subroutine SetFatesGlobalElements1(use_fates,surf_numpft,surf_numcft) implicit none - logical,intent(in) :: use_fates ! Is fates turned on? - integer,intent(in) :: surf_numpft ! Number of PFTs in surface dataset - integer,intent(in) :: surf_numcft ! Number of CFTs in surface dataset + logical, intent(in) :: use_fates ! Is fates turned on? + logical, intent(in) :: masterproc ! proc 0 logical for printing msgs + integer, intent(in) :: surf_numpft ! Number of PFTs in surface dataset + integer, intent(in) :: surf_numcft ! Number of CFTs in surface dataset + character(len=SHR_KIND_CL), intent(in) :: paramfile ! ASCII data file (host model) + character(len=SHR_KIND_CL), intent(in) :: fates_paramfile ! ASCII data file with PFT physiological constants (FATES) integer :: fates_numpft ! Number of PFTs tracked in FATES if (use_fates) then ! Self explanatory, read the fates parameter file - call FatesReadParameters() + call FatesReadParameters(paramfile, fates_paramfile, masterproc) fates_numpft = size(prt_params%wood_density,dim=1) diff --git a/parteh/CMakeLists.txt b/parteh/CMakeLists.txt index 218608e794..f04d622092 100644 --- a/parteh/CMakeLists.txt +++ b/parteh/CMakeLists.txt @@ -1,6 +1,9 @@ list(APPEND fates_sources PRTGenericMod.F90 PRTParametersMod.F90 + PRTParamsFATESMod.F90 + PRTAllometricCarbonMod.F90 + PRTAllometricCNPMod.F90 ) sourcelist_to_parent(fates_sources) \ No newline at end of file From 2786dc36c4de36a46cfb00be15aecbe337f64b32 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Fri, 21 Apr 2023 09:58:01 -0600 Subject: [PATCH 647/852] add parameter check for fates_rad_leaf_xl --- biogeophys/EDSurfaceAlbedoMod.F90 | 4 +++- main/EDPftvarcon.F90 | 10 ++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/biogeophys/EDSurfaceAlbedoMod.F90 b/biogeophys/EDSurfaceAlbedoMod.F90 index 48b9d1e448..b6b368aabe 100644 --- a/biogeophys/EDSurfaceAlbedoMod.F90 +++ b/biogeophys/EDSurfaceAlbedoMod.F90 @@ -363,7 +363,9 @@ subroutine PatchNormanRadiation (currentPatch, & cosz = max(0.001_r8, currentPatch%solar_zenith_angle ) !copied from previous radiation code... do ft = 1,numpft sb = (90._r8 - (acos(cosz)*180._r8/pi_const)) * (pi_const / 180._r8) - chil = xl(ft) !min(max(xl(ft), -0.4_r8), 0.6_r8 ) + !chil should be between -0.6 and 0.4 + ! Bonan (2019) doi:10.1017/9781107339217 pg. 238 + chil = min(max(xl(ft), -0.4_r8), 0.6_r8 ) if ( abs(chil) <= 0.01_r8) then chil = 0.01_r8 end if diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index faf0e78bb7..f9dd7d9a27 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1641,8 +1641,6 @@ subroutine FatesCheckParams(is_master) call endrun(msg=errMsg(sourcefile, __LINE__)) end select - - ! logging parameters, make sure they make sense if ( (logging_mechanical_frac + logging_collateral_frac + logging_direct_frac) .gt. 1._r8) then write(fates_log(),*) 'the sum of logging_mechanical_frac + logging_collateral_frac + logging_direct_frac' @@ -1675,6 +1673,14 @@ subroutine FatesCheckParams(is_master) do ipft = 1,npft + ! xl must be between -0.6 and 0.4 according to Bonan (2019) doi:10.1017/9781107339217 pg. 238 + !----------------------------------------------------------------------------------- + if (EDPftvarcon_inst%xl(ipft) < -0.6 .or. EDPftvarcon_inst%xl(ipft) > 0.4) then + write(fates_log(),*) 'fates_rad_leaf_xl for pft ', ipft, ' is outside the allowed range of -0.6 to 0.4' + write(fates_log(),*) 'Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + ! Check that parameter ranges for age-dependent mortality make sense !----------------------------------------------------------------------------------- if ( ( EDPftvarcon_inst%mort_ip_age_senescence(ipft) < fates_check_param_set ) .and. & From 774b699fff075a8ec8ef13e969d76a400da275cf Mon Sep 17 00:00:00 2001 From: adrifoster Date: Fri, 21 Apr 2023 10:38:32 -0600 Subject: [PATCH 648/852] update indentation to match style --- main/EDPftvarcon.F90 | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index f9dd7d9a27..e7b2761538 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1672,14 +1672,13 @@ subroutine FatesCheckParams(is_master) do ipft = 1,npft - - ! xl must be between -0.6 and 0.4 according to Bonan (2019) doi:10.1017/9781107339217 pg. 238 - !----------------------------------------------------------------------------------- - if (EDPftvarcon_inst%xl(ipft) < -0.6 .or. EDPftvarcon_inst%xl(ipft) > 0.4) then - write(fates_log(),*) 'fates_rad_leaf_xl for pft ', ipft, ' is outside the allowed range of -0.6 to 0.4' - write(fates_log(),*) 'Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + ! xl must be between -0.6 and 0.4 according to Bonan (2019) doi:10.1017/9781107339217 pg. 238 + !----------------------------------------------------------------------------------- + if (EDPftvarcon_inst%xl(ipft) < -0.6 .or. EDPftvarcon_inst%xl(ipft) > 0.4) then + write(fates_log(),*) 'fates_rad_leaf_xl for pft ', ipft, ' is outside the allowed range of -0.6 to 0.4' + write(fates_log(),*) 'Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if ! Check that parameter ranges for age-dependent mortality make sense !----------------------------------------------------------------------------------- From 733c72b99b4ee207d6e578ecfe8b88d3b75b8ea3 Mon Sep 17 00:00:00 2001 From: jessica needham Date: Fri, 21 Apr 2023 16:06:48 -0700 Subject: [PATCH 649/852] Add termination mortality to the mortality_cflux history variable --- main/FatesHistoryInterfaceMod.F90 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 106acdeb34..4cec9c89bc 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -3849,7 +3849,9 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_mortality_carbonflux_si_pft(io_si,i_pft) = hio_mortality_carbonflux_si_pft(io_si,i_pft) + & (sites(s)%fmort_carbonflux_canopy(i_pft) + & sites(s)%fmort_carbonflux_ustory(i_pft) + & - sites(s)%imort_carbonflux(i_pft) ) / g_per_kg ! cdk + sites(s)%imort_carbonflux(i_pft) ) / g_per_kg + & ! cdk + sites(s)%term_carbonflux_ustory(i_pft) * days_per_sec * ha_per_m2 + & + sites(s)%term_carbonflux_canopy(i_pft) * days_per_sec * ha_per_m2 hio_firemortality_carbonflux_si_pft(io_si,i_pft) = sites(s)%fmort_carbonflux_canopy(i_pft) / g_per_kg end do @@ -6716,7 +6718,7 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_firemortality_carbonflux_si_pft) - call this%set_history_var(vname='FATES_MORTALITY_HYDRAULIC_CFLUX_PF', units='kg m-2 s-1', & + call this%set_history_var(vname='FATES_MORTALITY_HYDRO_CFLUX_PF', units='kg m-2 s-1', & long='PFT-level flux of biomass carbon from live to dead pool from hydraulic failure mortality', & use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & From 05f52dd9cc80f6e2e425a9a009135867f0da5a49 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 21 Apr 2023 16:50:25 -0700 Subject: [PATCH 650/852] continuing to add updates and debug --- tools/luh2mod.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tools/luh2mod.py b/tools/luh2mod.py index efb40ef752..c33ad6f0b7 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -34,7 +34,8 @@ def main(): regrid_luh2["LATIXY"] = ds_regridtarget["LATIXY"] # Write the files - outputfile = os.path.join() + outputfile = os.path.join(os.getcwd(),'LUH2_states_transitions_management.timeseries_4x5_hist_simyr1850-2015_c230415.nc') + regrid_luh2.to_netcdf(outputfile) # Example of file naming scheme @@ -179,14 +180,17 @@ def BoundsVariableFixLUH2(inputdataset): # The user will need to use a surface data set to regrid from, but the surface datasets # need to have their dimensions renamed to something recognizable by xESMF -def DimensionFixSurfData(surfdataset): +def DimensionFixSurfData(inputdataset): # Rename the surface dataset dimensions to something recognizable by xESMF. - inputdataset = surfdataset.rename_dims(dims_dict={'lsmlat':'latitude','lsmlon':'longitude'}) + # inputdataset = surfdataset.rename_dims(dims_dict={'lsmlat':'latitude','lsmlon':'longitude'}) + inputdataset = inputdataset.rename_dims(dims_dict={'lsmlat':'lat','lsmlon':'lon'}) # Populate the new surface dataset with the actual lat/lon values - inputdataset['longitude'] = outputdataset.LONGXY.isel(latitude=0) - inputdataset['latitude'] = outputdataset.LATIXY.isel(longitude=0) + # inputdataset['longitude'] = inputdataset.LONGXY.isel(latitude=0) + # inputdataset['latitude'] = inputdataset.LATIXY.isel(longitude=0) + inputdataset['lon'] = inputdataset.LONGXY.isel(lat=0) + inputdataset['lat'] = inputdataset.LATIXY.isel(lon=0) print("Surface dataset dimensions renamed for xESMF") From fcffb8155f62cca5bacfffe85baceb803231449b Mon Sep 17 00:00:00 2001 From: adrifoster Date: Mon, 24 Apr 2023 13:24:58 -0600 Subject: [PATCH 651/852] fix numbers --- biogeophys/EDSurfaceAlbedoMod.F90 | 9 +++++---- main/EDPftvarcon.F90 | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/biogeophys/EDSurfaceAlbedoMod.F90 b/biogeophys/EDSurfaceAlbedoMod.F90 index b6b368aabe..2b0f7e0930 100644 --- a/biogeophys/EDSurfaceAlbedoMod.F90 +++ b/biogeophys/EDSurfaceAlbedoMod.F90 @@ -363,12 +363,13 @@ subroutine PatchNormanRadiation (currentPatch, & cosz = max(0.001_r8, currentPatch%solar_zenith_angle ) !copied from previous radiation code... do ft = 1,numpft sb = (90._r8 - (acos(cosz)*180._r8/pi_const)) * (pi_const / 180._r8) - !chil should be between -0.6 and 0.4 + !chil should be between -0.4 and 0.6 ! Bonan (2019) doi:10.1017/9781107339217 pg. 238 chil = min(max(xl(ft), -0.4_r8), 0.6_r8 ) - if ( abs(chil) <= 0.01_r8) then - chil = 0.01_r8 - end if + ! chil being close to zero shouldn't affect things + !if ( abs(chil) <= 0.01_r8) then + ! chil = 0.01_r8 + !end if phi1b(ft) = 0.5_r8 - 0.633_r8*chil - 0.330_r8*chil*chil phi2b(ft) = 0.877_r8 * (1._r8 - 2._r8*phi1b(ft)) !0 = horiz leaves, 1 - vert leaves. gdir = phi1b(ft) + phi2b(ft) * sin(sb) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index e7b2761538..e21f7207fb 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1672,9 +1672,9 @@ subroutine FatesCheckParams(is_master) do ipft = 1,npft - ! xl must be between -0.6 and 0.4 according to Bonan (2019) doi:10.1017/9781107339217 pg. 238 + ! xl must be between -0.4 and 0.6 according to Bonan (2019) doi:10.1017/9781107339217 pg. 238 !----------------------------------------------------------------------------------- - if (EDPftvarcon_inst%xl(ipft) < -0.6 .or. EDPftvarcon_inst%xl(ipft) > 0.4) then + if (EDPftvarcon_inst%xl(ipft) < -0.4 .or. EDPftvarcon_inst%xl(ipft) > 0.6) then write(fates_log(),*) 'fates_rad_leaf_xl for pft ', ipft, ' is outside the allowed range of -0.6 to 0.4' write(fates_log(),*) 'Aborting' call endrun(msg=errMsg(sourcefile, __LINE__)) From 924ec76948ac86457f922386848b722bda0c1447 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Mon, 24 Apr 2023 13:50:45 -0600 Subject: [PATCH 652/852] put use statements back --- .../solar_rad_test/FatesUnitTestRadiation.F90 | 111 ++---------------- main/FatesInterfaceMod.F90 | 5 +- 2 files changed, 11 insertions(+), 105 deletions(-) diff --git a/biogeophys/test/solar_rad_test/FatesUnitTestRadiation.F90 b/biogeophys/test/solar_rad_test/FatesUnitTestRadiation.F90 index 05210b52df..7f7e87d4b5 100644 --- a/biogeophys/test/solar_rad_test/FatesUnitTestRadiation.F90 +++ b/biogeophys/test/solar_rad_test/FatesUnitTestRadiation.F90 @@ -21,12 +21,6 @@ program FatesUnitTestRadiation integer :: year, jday ! year and day of year to simulate real(r8) :: lat, lon ! latitude/longitude to simulate [degrees] real(r8) :: fcansno ! fraction of canopy covered by snow [0-1] - real(r8), allocatable :: rhol(:,:) ! leaf reflectance [0-1] - real(r8), allocatable :: rhos(:,:) ! stem reflectance [0-1] - real(r8), allocatable :: taul(:,:) ! leaf transmittance [0-1] - real(r8), allocatable :: taus(:,:) ! stem transmittance [0-1] - real(r8), allocatable :: xl(:) ! leaf orientation index - real(r8), allocatable :: ci(:) ! clumping index ! PARAMETERS integer, parameter :: numSWb = 2 ! number of shortwave bands to simulate @@ -48,36 +42,20 @@ subroutine read_radiation_namelist(year, jday, lat, lon, fcansno, & end subroutine read_radiation_namelist - subroutine read_radiation_params(file, numSWb, rhol, rhos, taul, taus, xl, & - ci) - - use FatesUnitTestIOMod, only : MAX_PATH, check, read_in_parameter - use FatesConstantsMod, only : r8 => fates_r8 - use netcdf - - implicit none - - character(len=MAX_PATH), intent(in) :: file - integer, intent(in) :: numSWb - real(r8), allocatable, intent(out) :: rhol(:,:) - real(r8), allocatable, intent(out) :: rhos(:,:) - real(r8), allocatable, intent(out) :: taul(:,:) - real(r8), allocatable, intent(out) :: taus(:,:) - real(r8), allocatable, intent(out) :: xl(:) - real(r8), allocatable, intent(out) :: ci(:) - - end subroutine read_radiation_params - end interface - call read_radiation_namelist(year, jday, lat, lon, fcansno, & - param_file, patch_file, out_file) + !:...........................................................................: ! open log file logf = open_file("log.txt") - ! read in FATES parameter file - call read_radiation_params(param_file, numSWb, rhol, rhos, taul, taus, xl, ci) + ! read in namelist to get some runtime parameters + call read_radiation_namelist(year, jday, lat, lon, fcansno, param_file, & + patch_file, out_file) + + ! read in parameter file and initialize EDPFTvarcon_inst + + ! read in patch data !call read_patch_data(patch_file, canopy_area_profile, elai_profile, & @@ -149,9 +127,8 @@ subroutine read_radiation_namelist(year, jday, lat, lon, fcansno, param_file, & if (ios /= 0) then ! Problem reading file - tell user. - write(message, '(A, I6, A, A)') "Error reading radiation namelist file", & + write(logf, '(A, I6, A, A)') "Error reading radiation namelist file", & ios, "IOMSG: ", msg - write(*,*) message stop "Stopped" end if @@ -161,75 +138,5 @@ end subroutine read_radiation_namelist !:.............................................................................: -subroutine read_radiation_params(file, numSWb, rhol, rhos, taul, taus, xl, ci) - ! - ! DESCRIPTION: - ! read in the parameters we need for this test - ! - - use FatesUnitTestIOMod, only : MAX_PATH, check, read_in_parameter - use FatesConstantsMod, only : r8 => fates_r8 - use netcdf - - implicit none - - ! ARGUMENTS: - character(len=MAX_PATH), intent(in) :: file ! parameter file name - integer, intent(in) :: numSWb ! number of shortwave bands to simulate - real(r8), allocatable, intent(out) :: rhol(:,:) ! leaf reflectance [0-1] - real(r8), allocatable, intent(out) :: rhos(:,:) ! stem reflectance [0-1] - real(r8), allocatable, intent(out) :: taul(:,:) ! leaf transmittance [0-1] - real(r8), allocatable, intent(out) :: taus(:,:) ! stem transmittance [0-1] - real(r8), allocatable, intent(out) :: xl(:) ! leaf orientation index - real(r8), allocatable, intent(out) :: ci(:) ! clumping index - - ! LOCALS: - integer :: funit ! file unit number - real(r8), allocatable :: rholvis(:) ! leaf visible reflectance [0-1] - real(r8), allocatable :: rholnir(:) ! leaf NIR reflectance [0-1] - real(r8), allocatable :: rhosvis(:) ! stem visible reflectance [0-1] - real(r8), allocatable :: rhosnir(:) ! stem NIR reflectance [0-1] - real(r8), allocatable :: taulvis(:) ! leaf visible transmittance [0-1] - real(r8), allocatable :: taulnir(:) ! leaf NIR transmittance [0-1] - real(r8), allocatable :: tausvis(:) ! stem visible transmittance [0-1] - real(r8), allocatable :: tausnir(:) ! stem NIR transmittance [0-1] - - ! open file - call check(nf90_open(trim(file), 0, funit)) - - ! read in parameters - call read_in_parameter(funit, 'fates_rad_leaf_rhovis', 'fates_pft', rholvis) - call read_in_parameter(funit, 'fates_rad_leaf_rhonir', 'fates_pft', rholnir) - call read_in_parameter(funit, 'fates_rad_stem_rhovis', 'fates_pft', rhosvis) - call read_in_parameter(funit, 'fates_rad_stem_rhonir', 'fates_pft', rhosnir) - call read_in_parameter(funit, 'fates_rad_leaf_tauvis', 'fates_pft', taulvis) - call read_in_parameter(funit, 'fates_rad_leaf_taunir', 'fates_pft', taulnir) - call read_in_parameter(funit, 'fates_rad_stem_tauvis', 'fates_pft', tausvis) - call read_in_parameter(funit, 'fates_rad_stem_taunir', 'fates_pft', tausnir) - call read_in_parameter(funit, 'fates_rad_leaf_xl', 'fates_pft', xl) - call read_in_parameter(funit, 'fates_rad_leaf_clumping_index', 'fates_pft', & - ci) - - ! allocate the arrays correctly - allocate(rhol(size(rholvis, 1), numSWb)) - allocate(rhos(size(rhosvis, 1), numSWb)) - allocate(taul(size(taulvis, 1), numSWb)) - allocate(taus(size(tausvis, 1), numSWb)) - - ! put arrays together - rhol(:,1) = rholvis - rhol(:,2) = rholnir - rhos(:,1) = rhosvis - rhos(:,2) = rhosnir - taul(:,1) = taulvis - taul(:,2) = taulnir - taus(:,1) = tausvis - taus(:,2) = tausnir - - ! close file - call check(nf90_close(funit)) - -end subroutine read_radiation_params - diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 72950c5cdb..164661c148 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -724,8 +724,7 @@ end subroutine set_bcs ! =================================================================================== - subroutine SetFatesGlobalElements1(use_fates,surf_numpft,surf_numcft, & - masterproc, paramfile, fates_paramfile) + subroutine SetFatesGlobalElements1(use_fates,surf_numpft,surf_numcft) ! -------------------------------------------------------------------------------- ! @@ -749,7 +748,7 @@ subroutine SetFatesGlobalElements1(use_fates,surf_numpft,surf_numcft, & if (use_fates) then ! Self explanatory, read the fates parameter file - call FatesReadParameters(paramfile, fates_paramfile, masterproc) + call FatesReadParameters() fates_numpft = size(prt_params%wood_density,dim=1) From c8b81d2986f7e30b74c9f53f37bc878ce729e2c8 Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Mon, 24 Apr 2023 15:15:27 -0600 Subject: [PATCH 653/852] updated comments in adjust_SF_CWD_frac subroutine in response to review from ZR --- biogeochem/FatesLitterMod.F90 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/biogeochem/FatesLitterMod.F90 b/biogeochem/FatesLitterMod.F90 index 21a459b61f..e0ef9c80aa 100644 --- a/biogeochem/FatesLitterMod.F90 +++ b/biogeochem/FatesLitterMod.F90 @@ -447,15 +447,15 @@ subroutine adjust_SF_CWD_frac(dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) !LOCAL VARIABLES !These diameter ranges are based on work by Fosberg et al., 1971 - real(r8), parameter :: lb_max_diam = 7.6 !max diameter [cm] for large branch - real(r8), parameter :: sb_max_diam = 2.5 !max diameter [cm] for small branch - real(r8), parameter :: twig_max_diam = 0.6 !max diameter [cm] for twig + real(r8), parameter :: lb_max_diam = 7.6 !max diameter [cm] for large branch (100 hr fuel) + real(r8), parameter :: sb_max_diam = 2.5 !max diameter [cm] for small branch (10 hr fuel) + real(r8), parameter :: twig_max_diam = 0.6 !max diameter [cm] for twig (1 hr fuel) !------------------------------------------------------------------------------------ SF_val_CWD_frac_adj = SF_val_CWD_frac - !If dbh is larger than max size of a large branch (1,000 hr fuel) then we don't change + !If dbh is > 7.6 cm diameter then the main stem is 1,000 hr fuel and we don't change !how biomass is partitioned among cwd classes. if (dbh > lb_max_diam) then return From 83a51408a97f2e7a2468e810899db857b3b689b0 Mon Sep 17 00:00:00 2001 From: jessica needham Date: Mon, 24 Apr 2023 16:34:04 -0700 Subject: [PATCH 654/852] Fix units on carbonflux variables in EDTypesMod --- main/EDTypesMod.F90 | 6 +++--- main/FatesHistoryInterfaceMod.F90 | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 834561deaa..fd697f89d1 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -843,10 +843,10 @@ module EDTypesMod ! were terminated this timestep, on size x pft real(r8), allocatable :: term_carbonflux_canopy(:) ! carbon flux from live to dead pools associated - ! with termination mortality, per canopy level + ! with termination mortality, per canopy level. [kg C/ha/day] real(r8), allocatable :: term_carbonflux_ustory(:) ! carbon flux from live to dead pools associated - ! with termination mortality, per canopy level - real(r8), allocatable :: imort_carbonflux(:) ! biomass of individuals killed due to impact mortality per year. [kgC/ha/day] + ! with termination mortality, per canopy level. [kg C/ha/day] + real(r8), allocatable :: imort_carbonflux(:) ! biomass of individuals killed due to impact mortality per year. [gC/m2/sec] real(r8), allocatable :: fmort_carbonflux_canopy(:) ! biomass of canopy indivs killed due to fire per year. [gC/m2/sec] real(r8), allocatable :: fmort_carbonflux_ustory(:) ! biomass of understory indivs killed due to fire per year [gC/m2/sec] diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 4cec9c89bc..d63af9f00d 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -3849,7 +3849,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_mortality_carbonflux_si_pft(io_si,i_pft) = hio_mortality_carbonflux_si_pft(io_si,i_pft) + & (sites(s)%fmort_carbonflux_canopy(i_pft) + & sites(s)%fmort_carbonflux_ustory(i_pft) + & - sites(s)%imort_carbonflux(i_pft) ) / g_per_kg + & ! cdk + sites(s)%imort_carbonflux(i_pft) ) / g_per_kg + & sites(s)%term_carbonflux_ustory(i_pft) * days_per_sec * ha_per_m2 + & sites(s)%term_carbonflux_canopy(i_pft) * days_per_sec * ha_per_m2 From e46721eb3644bd5196268c73578cd641b2b798ba Mon Sep 17 00:00:00 2001 From: jessica needham Date: Mon, 24 Apr 2023 17:05:25 -0700 Subject: [PATCH 655/852] Tidying units on imort_carbonflux. Add logging imort to imort_agb_flux --- biogeochem/EDPatchDynamicsMod.F90 | 14 ++++++++++---- main/EDTypesMod.F90 | 10 +++++----- main/FatesHistoryInterfaceMod.F90 | 10 +++++----- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 4c4efca18f..ae42cbc754 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -760,14 +760,13 @@ subroutine spawn_patches( currentSite, bc_in) currentSite%imort_carbonflux(currentCohort%pft) = & currentSite%imort_carbonflux(currentCohort%pft) + & (nc%n * ED_val_understorey_death / hlm_freq_day ) * & - total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 + total_c * days_per_sec * years_per_day * ha_per_m2 currentSite%imort_abg_flux(currentCohort%size_class, currentCohort%pft) = & currentSite%imort_abg_flux(currentCohort%size_class, currentCohort%pft) + & (nc%n * ED_val_understorey_death / hlm_freq_day ) * & ( (sapw_c + struct_c + store_c) * prt_params%allom_agb_frac(currentCohort%pft) + & - leaf_c ) * & - g_per_kg * days_per_sec * years_per_day * ha_per_m2 + leaf_c ) * days_per_sec * years_per_day * ha_per_m2 ! Step 2: Apply survivor ship function based on the understory death fraction @@ -1020,7 +1019,14 @@ subroutine spawn_patches( currentSite, bc_in) currentSite%imort_carbonflux(currentCohort%pft) + & (nc%n * currentPatch%fract_ldist_not_harvested * & logging_coll_under_frac/ hlm_freq_day ) * & - total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 + total_c * days_per_sec * years_per_day * ha_per_m2 + + currentSite%imort_abg_flux(currentCohort%size_class, currentCohort%pft) = & + currentSite%imort_abg_flux(currentCohort%size_class, currentCohort%pft) + & + (nc%n * currentPatch%fract_ldist_not_harvested * & + logging_coll_under_frac/ hlm_freq_day ) * & + ( ( sapw_c + struct_c + store_c) * prt_params%allom_agb_frac(currentCohort%pft) + & + leaf_c ) * days_per_sec * years_per_day * ha_per_m2 ! Step 2: Apply survivor ship function based on the understory death fraction diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index fd697f89d1..9bd01ef5e7 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -843,15 +843,15 @@ module EDTypesMod ! were terminated this timestep, on size x pft real(r8), allocatable :: term_carbonflux_canopy(:) ! carbon flux from live to dead pools associated - ! with termination mortality, per canopy level. [kg C/ha/day] + ! with termination mortality, per canopy level. [kgC/ha/day] real(r8), allocatable :: term_carbonflux_ustory(:) ! carbon flux from live to dead pools associated - ! with termination mortality, per canopy level. [kg C/ha/day] - real(r8), allocatable :: imort_carbonflux(:) ! biomass of individuals killed due to impact mortality per year. [gC/m2/sec] + ! with termination mortality, per canopy level. [kgC/ha/day] + real(r8), allocatable :: imort_carbonflux(:) ! biomass of individuals killed due to impact mortality per year. [kgC/m2/sec] real(r8), allocatable :: fmort_carbonflux_canopy(:) ! biomass of canopy indivs killed due to fire per year. [gC/m2/sec] real(r8), allocatable :: fmort_carbonflux_ustory(:) ! biomass of understory indivs killed due to fire per year [gC/m2/sec] real(r8), allocatable :: term_abg_flux(:,:) ! aboveground biomass lost due to termination mortality x size x pft - real(r8), allocatable :: imort_abg_flux(:,:) ! aboveground biomass lost due to impact mortality x size x pft + real(r8), allocatable :: imort_abg_flux(:,:) ! aboveground biomass lost due to impact mortality x size x pft [kgC/m2/sec] real(r8), allocatable :: fmort_abg_flux(:,:) ! aboveground biomass lost due to fire mortality x size x pft @@ -880,7 +880,7 @@ module EDTypesMod real(r8), allocatable :: fmort_rate_ustory_damage(:,:,:) ! number of individuals per damage class that die from fire - ustory real(r8), allocatable :: fmort_cflux_canopy_damage(:,:) ! cflux per damage class that die from fire - canopy real(r8), allocatable :: fmort_cflux_ustory_damage(:,:) ! cflux per damage class that die from fire - ustory - real(r8), allocatable :: imort_cflux_damage(:,:) ! carbon flux from impact mortality by damage class + real(r8), allocatable :: imort_cflux_damage(:,:) ! carbon flux from impact mortality by damage class [kgC/m2/sec] real(r8), allocatable :: term_cflux_canopy_damage(:,:) ! carbon flux from termination mortality by damage class real(r8), allocatable :: term_cflux_ustory_damage(:,:) ! carbon flux from termination mortality by damage class diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index d63af9f00d..d71087353b 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -3843,13 +3843,13 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) ! treat carbon flux from imort the same way hio_understory_mortality_carbonflux_si(io_si) = hio_understory_mortality_carbonflux_si(io_si) + & - sum(sites(s)%imort_carbonflux(:)) / g_per_kg + sum(sites(s)%imort_carbonflux(:)) do i_pft = 1, numpft hio_mortality_carbonflux_si_pft(io_si,i_pft) = hio_mortality_carbonflux_si_pft(io_si,i_pft) + & (sites(s)%fmort_carbonflux_canopy(i_pft) + & - sites(s)%fmort_carbonflux_ustory(i_pft) + & - sites(s)%imort_carbonflux(i_pft) ) / g_per_kg + & + sites(s)%fmort_carbonflux_ustory(i_pft) ) / g_per_kg + & + sites(s)%imort_carbonflux(i_pft) + & sites(s)%term_carbonflux_ustory(i_pft) * days_per_sec * ha_per_m2 + & sites(s)%term_carbonflux_canopy(i_pft) * days_per_sec * ha_per_m2 @@ -3862,8 +3862,8 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) i_scpf = (i_pft-1)*nlevsclass + i_scls hio_abg_mortality_cflux_si_scpf(io_si,i_scpf) = hio_abg_mortality_cflux_si_scpf(io_si,i_scpf) + & (sites(s)%fmort_abg_flux(i_scls,i_pft) / g_per_kg ) + & - (sites(s)%imort_abg_flux(i_scls,i_pft) / g_per_kg) + & - (sites(s)%term_abg_flux(i_scls,i_pft) * days_per_sec * ha_per_m2 ) ! jfn + sites(s)%imort_abg_flux(i_scls,i_pft) + & + (sites(s)%term_abg_flux(i_scls,i_pft) * days_per_sec * ha_per_m2 ) end do end do From 67e7899ef70523f588831a5b330d54ad366c5c5b Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 24 Apr 2023 17:15:04 -0700 Subject: [PATCH 656/852] Implement reviewer suggested improvements Its better to use unset instead of -999. Fixing history output long name typo. --- main/FatesHistoryInterfaceMod.F90 | 2 +- main/FatesInterfaceMod.F90 | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index bab0bda56e..480524bf32 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -5503,7 +5503,7 @@ subroutine define_history_vars(this, initialize_variables) call this%set_history_var(vname='FATES_SEEDS_OUT_GRIDCELL_PF', & units='kg', & - long='Site-level seed mass output from neighboring gridcells per pft', & + long='Site-level seed mass output to neighboring gridcells per pft', & use_default='inactive', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_seeds_out_gc_si_pft) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 302a3fa934..a5ae45e23a 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -2060,8 +2060,8 @@ subroutine DetermineGridCellNeighbors(neighbors) allocate(ncells_array(0:npes-1)) allocate(begg_array(0:npes-1)) - ncells_array = -999 - begg_array = -999 + ncells_array = fates_unset_r8 + begg_array = fates_unset_r8 call t_startf('fates-seed-init-allgather') From 23e5b9f918aabedd8110c403ce13edf9badc90e1 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Wed, 26 Apr 2023 20:27:34 -0600 Subject: [PATCH 657/852] trying to add parameters --- CMakeLists.txt | 26 ++-- .../solar_rad_test/FatesUnitTestRadiation.F90 | 3 +- unit_test_shr/FatesUnitTestIOMod.F90 | 134 +++++++++++++++--- 3 files changed, 129 insertions(+), 34 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c772fdf05..893c300823 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,19 +14,17 @@ set(CLM_ROOT "../../") # Add source directories from other share code (csm_share, etc.) add_subdirectory(${CLM_ROOT}/share/src csm_share) add_subdirectory(${CLM_ROOT}/share/unit_test_stubs/util csm_share_stubs) -add_subdirectory(${CLM_ROOT}/src/utils clm_utils) -add_subdirectory(${CLM_ROOT}/src/main clm_main) # Extract just the files we need from csm_share -set (shr_sources_needed_base - shr_log_mod.F90 - shr_infnan_mod.F90 - shr_kind_mod.F90 - shr_sys_mod.F90 - shr_strconvert_mod.F90 - shr_abort_mod.abortthrows.F90 - ) -extract_sources("${shr_sources_needed_base}" "${share_sources}" shr_sources_needed) +# set (shr_sources_needed_base +# shr_log_mod.F90 +# shr_infnan_mod.F90 +# shr_kind_mod.F90 +# shr_sys_mod.F90 +# shr_strconvert_mod.F90 +# shr_abort_mod.abortthrows.F90 +# ) +# extract_sources("${shr_sources_needed_base}" "${share_sources}" shr_sources_needed) # Add FATES source directories add_subdirectory(${CLM_ROOT}/src/fates/main fates_main) @@ -35,6 +33,10 @@ add_subdirectory(${CLM_ROOT}/src/fates/biogeophys fates_biogephys) add_subdirectory(${CLM_ROOT}/src/fates/parteh fates_parteh) add_subdirectory(${CLM_ROOT}/src/fates/fire fates_fire) +# Add general unit test directories (stubbed out files, etc.) +add_subdirectory(${CLM_ROOT}/src/unit_test_stubs clm_stubs) +add_subdirectory(${CLM_ROOT}/src/unit_test_shr clm_tests) + # Add general unit test directories add_subdirectory(${CLM_ROOT}/src/fates/unit_test_shr) @@ -71,7 +73,7 @@ endforeach() # Build libraries containing stuff needed for the unit tests. # Eventually, these add_library calls should probably be distributed into the correct location, rather than being in this top-level CMakeLists.txt file. -add_library(csm_share ${shr_sources_needed}) +add_library(csm_share ${share_sources}) declare_generated_dependencies(csm_share "${share_genf90_sources}") add_library(fates ${fates_sources}) add_dependencies(fates csm_share) diff --git a/biogeophys/test/solar_rad_test/FatesUnitTestRadiation.F90 b/biogeophys/test/solar_rad_test/FatesUnitTestRadiation.F90 index 7f7e87d4b5..83c5a68964 100644 --- a/biogeophys/test/solar_rad_test/FatesUnitTestRadiation.F90 +++ b/biogeophys/test/solar_rad_test/FatesUnitTestRadiation.F90 @@ -96,7 +96,7 @@ subroutine read_radiation_namelist(year, jday, lat, lon, fcansno, param_file, & ! initialize values ! - use FatesUnitTestIOMod, only : MAX_PATH, MAX_CHAR, open_file + use FatesUnitTestIOMod, only : MAX_PATH, MAX_CHAR, open_file, logf use FatesConstantsMod, only : r8 => fates_r8 implicit none @@ -111,7 +111,6 @@ subroutine read_radiation_namelist(year, jday, lat, lon, fcansno, param_file, & ! LOCALS: character(len=MAX_PATH) :: rad_nl = 'radiation_nl' ! radiation namelist name - character(len=MAX_CHAR) :: message ! Error message character(len=MAX_CHAR) :: msg ! I/O Error message integer :: rad_nl_file ! unit number for namelist integer :: ios ! I/O status diff --git a/unit_test_shr/FatesUnitTestIOMod.F90 b/unit_test_shr/FatesUnitTestIOMod.F90 index a065f3e37a..d7f1bb8726 100644 --- a/unit_test_shr/FatesUnitTestIOMod.F90 +++ b/unit_test_shr/FatesUnitTestIOMod.F90 @@ -1,5 +1,12 @@ module FatesUnitTestIOMod - use FatesConstantsMod, only : r8 => fates_r8 + use FatesConstantsMod, only : r8 => fates_r8 + use FatesParametersInterface, only : fates_parameters_type + use FatesParametersInterface, only : param_string_length, max_used_dimensions + use EDParamsMod, only : FatesRegisterParams, FatesReceiveParams + use SFParamsMod, only : SpitFireRegisterParams, SpitFireReceiveParams + use PRTInitParamsFATESMod, only : PRTRegisterParams, PRTReceiveParams + use shr_kind_mod, only : SHR_KIND_CL + use FatesSynchronizedParamsMod, only : FatesSynchronizedParamsInst use netcdf implicit none @@ -136,37 +143,124 @@ end subroutine check !:.........................................................................: - subroutine read_in_parameter(funit, param_name, bounds, out_array) + subroutine read_parameters(fates_paramfile) ! ! DESCRIPTION: ! Reads in parameters from the FATES parameter file ! ! ARGUMENTS: - integer, intent(in) :: funit ! file unit number - character(len=*), intent(in) :: param_name ! parameter name - character(len=*), intent(in) :: bounds ! bounds name - real(r8), allocatable, intent(out) :: out_array(:) ! parameter values + character(len=SHR_KIND_CL), intent(in) :: fates_paramfile ! parameter file name + + ! LOCALS: + class(fates_parameters_type), allocatable :: fates_params + + allocate(fates_params) + call fates_params%Init() + call FatesRegisterParams(fates_params) + call SpitFireRegisterParams(fates_params) + call PRTRegisterParams(fates_params) + call FatesSynchronizedParamsInst%RegisterParams(fates_params) + + end subroutine read_parameters + + !:.........................................................................: + + subroutine read_netcdf_params(filename, fates_params) + ! + ! DESCRIPTION: + ! Calls actual netcdf library methods for reading FATES parameters from netcdf + ! + + ! ARGUMENTS: + character(len=*), intent(in) :: filename ! full path of parameter file + class(fates_parameters_type), intent(inout) :: fates_params ! fates parameters type ! LOCALS: - integer :: paramID ! parameter ID - integer :: dimID_axis_nbounds ! dimension ID - integer :: nbounds ! parameter bounds + logical :: file_exists ! does the file exist? + integer :: ncid ! netcdf file unit number + integer :: max_dim_size ! + + ! check if file is on disk + inquire(file=trim(adjustl(filename)), exist=file_exists) + if (.not. file_exists) then + write(logf,'(a)') 'File ', filename, ' does not exist.' + stop "Stopping" + end if + + ! open the file + call check(nf90_open(trim(adjustl(filename)), 0, ncid)) + + ! get and set the correct dimensions for the parameters + call set_param_dimensions(ncid, fates_params) + + ! max_dim_size = fates_params%GetMaxDimensionSize() + ! num_params = fates_params%num_params() + ! do i = 1, num_params + ! call fates_params%GetMetaData(i, name, dimension_shape, dimension_sizes, dimension_names, is_host_param) + ! if (is_host_file .eqv. is_host_param) then + ! select case(dimension_shape) + ! case(dimension_shape_scalar) + ! size_dim_1 = 1 + ! size_dim_2 = 1 + ! case(dimension_shape_1d) + ! size_dim_1 = dimension_sizes(1) + ! size_dim_2 = 1 + ! case(dimension_shape_2d) + ! size_dim_1 = dimension_sizes(1) + ! size_dim_2 = dimension_sizes(2) + ! case default + ! write(fates_log(),*) 'dimension shape:',dimension_shape + ! call endrun(msg='unsupported number of dimensions reading parameters.') + + ! end select + ! if (masterproc) then + ! write(fates_log(), *) 'clmfates_interfaceMod.F90:: reading '//trim(name) + ! end if + ! call readNcdio(ncid, name, dimension_shape, dimension_names, subname, data(1:size_dim_1, 1:size_dim_2)) + ! call fates_params%SetData(i, data(1:size_dim_1, 1:size_dim_2)) + ! end if + ! end do + ! deallocate(data) + ! call ncd_pio_closefile(ncid) + + end subroutine read_netcdf_params + + !:.........................................................................: - ! get axis id - call check(nf90_inq_dimid(funit, trim(bounds), dimID_axis_nbounds)) + subroutine set_param_dimensions(ncid, fates_params) + ! + ! DESCRIPTION: + ! get the list of dimensions used by the FATES parameters + ! - ! get parameter bounds - call check(nf90_inquire_dimension(funit, dimID_axis_nbounds, len=nbounds)) - - ! read parameter values - call check(nf90_inq_varid(funit, trim(param_name), paramID)) + ! ARGUMENTS: + integer, intent(inout) :: ncid ! netcdf unit number + class(fates_parameters_type), intent(inout) :: fates_params ! fates parameters - ! allocate - allocate(out_array(nbounds)) - call check(nf90_get_var(funit, paramID, out_array)) + ! LOCALS: + integer :: num_dimensions + character(len=param_string_length) :: dimension_names(max_used_dimensions) + integer :: dimension_sizes(max_used_dimensions) + integer :: d + integer :: dim_id - end subroutine read_in_parameter + dimension_sizes(:) = 0 + + call fates_params%GetUsedDimensions(.false., num_dimensions, & + dimension_names) + + do d = 1, num_dimensions + call check(nf90_inq_dimid(ncid, dimension_names(d), dim_id)) + call check(nf90_inquire_dimension(ncid, dim_id, len=dimension_sizes(d))) + end do + + call fates_params%SetDimensionSizes(.false., num_dimensions, & + dimension_names, dimension_sizes) + + end subroutine set_param_dimensions + + !:.........................................................................: ! subroutine read_patch_data(file, canopy_area, elai, esai, nrad) ! ! From 8c76111d57da07233308a649fec52991db9f8351 Mon Sep 17 00:00:00 2001 From: Marcos Longo Date: Mon, 1 May 2023 09:46:56 -0700 Subject: [PATCH 658/852] Update to the crown damage recovery procedure for drought deciduous. Since these plants do not let any allocation to tissues during the abscission phase, we can skip most calculations in the recovery sub-routine. --- biogeochem/EDCohortDynamicsMod.F90 | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index e644b9b8af..bbadcb320d 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -2339,8 +2339,15 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) ( prt_params%season_decid(ipft) == itrue ) & .and. any(ccohort%status_coh == [leaves_off,leaves_shedding] ) + ! If plants are drought deciduous and are losing or lost all leaves, they cannot + ! allocate carbon to any growth or recovery. Return a null pointer and wait until + ! the growing season. + if (is_hydecid_dormant) then + newly_recovered = .false. + return + end if + - ! If we have not returned, then this cohort both has ! a damaged status, and the ability to recover from that damage ! ----------------------------------------------------------------- @@ -2368,16 +2375,10 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) call bleaf(dbh,ipft,ccohort%crowndamage-1, canopy_trim, elongf_leaf, target_leaf_c) - ! If plants are drought deciduous and are losing or lost all leaves, halt all - ! the growth. - if (is_hydecid_dormant) then - ! Drought-deciduous. Do not recover any tissue until the growing season - target_leaf_c = 0._r8 - target_fnrt_c = 0._r8 - target_sapw_c = 0._r8 - target_struct_c = 0._r8 - elseif (is_sedecid_dormant) then - ! Cold-deciduous. Do not recover leaves until the growing season + ! If plants are cold deciduous, we do not let them recover leaves, but we allow + ! them to recover other tissues. This is due to back-compatibility, but we may + ! want to revisit this later. + if (is_sedecid_dormant) then target_leaf_c = 0._r8 end if From bf079500ef5cc181fbd93b77c93c738b90a763e2 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 1 May 2023 15:02:06 -0700 Subject: [PATCH 659/852] add year variable as copy of time dimension This is necessary due to a ncd_io read requirement set in dynsubgrid. --- tools/luh2mod.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/luh2mod.py b/tools/luh2mod.py index c33ad6f0b7..27174a2b13 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -33,6 +33,9 @@ def main(): regrid_luh2["LONGXY"] = ds_regridtarget["LONGXY"] regrid_luh2["LATIXY"] = ds_regridtarget["LATIXY"] + # Add 'YEAR' as a variable. This is an old requirement of the HLM and should simply be a copy of the `time` dimension + regrid_luh2["YEAR"] = regrid_luh2.time + # Write the files outputfile = os.path.join(os.getcwd(),'LUH2_states_transitions_management.timeseries_4x5_hist_simyr1850-2015_c230415.nc') From 915a0e1d35d9095c5cb016893242b83bb1c0b621 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 2 May 2023 12:17:40 -0600 Subject: [PATCH 660/852] update unit test --- functional_unit_testing/run_FATES_tests.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/functional_unit_testing/run_FATES_tests.py b/functional_unit_testing/run_FATES_tests.py index cd3d1206d3..29b2df5667 100644 --- a/functional_unit_testing/run_FATES_tests.py +++ b/functional_unit_testing/run_FATES_tests.py @@ -12,24 +12,24 @@ from shutil import rmtree, copy -def main(): +def main(build_dir): os.chdir("..") - if os.path.isdir("build"): - rmtree("build") + if os.path.isdir(build_dir): + rmtree(build_dir) ## super hacky right now!! run_command = ["../../cime/scripts/fortran_unit_testing/run_tests.py", - "--build-dir", "build"] + "--build-dir", "build.temp"] run_cmd_no_fail(" ".join(run_command), combine_output=True) - copy("build/__command_line_test__/__command_line_test__/unit_testing/test/radiation_test/FATES_rad_test", - "unit_testing/test/radiation_test/") + copy(os.path.join(build_dir, "__command_line_test__/__command_line_test__/fates_biogeophys_test/solar_rad_test/FATES_rad_exe"), + "biogeophys/test/solar_rad_test/") - os.chdir("unit_testing/test/radiation_test") - run_command = ["./FATES_rad_test"] + os.chdir("biogeophys/test/solar_rad_test") + run_command = ["./FATES_rad_exe"] output = run_cmd_no_fail(" ".join(run_command), combine_output=True) print(output) if __name__ == "__main__": - main() \ No newline at end of file + main("build.temp") \ No newline at end of file From de31624cc6fa33938aa1d1445e5ab6e44e29b556 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 2 May 2023 13:29:56 -0600 Subject: [PATCH 661/852] update unit test --- CMakeLists.txt | 22 +- biogeochem/FatesPatchMod.F90 | 98 ++++-- biogeophys/test/solar_rad_test/FATES_rad_exe | Bin 0 -> 978808 bytes .../solar_rad_test/FatesUnitTestRadiation.F90 | 206 +++++++++-- biogeophys/test/solar_rad_test/log.txt | 1 - biogeophys/test/solar_rad_test/pft_nlfile | 14 + biogeophys/test/solar_rad_test/radiation_nl | 2 +- main/FatesGlobals.F90 | 5 +- main/FatesInterfaceMod.F90 | 5 +- unit_test_shr/FatesUnitTestIOMod.F90 | 330 +++++++++++------- 10 files changed, 484 insertions(+), 199 deletions(-) create mode 100755 biogeophys/test/solar_rad_test/FATES_rad_exe delete mode 100644 biogeophys/test/solar_rad_test/log.txt create mode 100644 biogeophys/test/solar_rad_test/pft_nlfile diff --git a/CMakeLists.txt b/CMakeLists.txt index 893c300823..750173fc34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,16 +15,16 @@ set(CLM_ROOT "../../") add_subdirectory(${CLM_ROOT}/share/src csm_share) add_subdirectory(${CLM_ROOT}/share/unit_test_stubs/util csm_share_stubs) -# Extract just the files we need from csm_share -# set (shr_sources_needed_base -# shr_log_mod.F90 -# shr_infnan_mod.F90 -# shr_kind_mod.F90 -# shr_sys_mod.F90 -# shr_strconvert_mod.F90 -# shr_abort_mod.abortthrows.F90 -# ) -# extract_sources("${shr_sources_needed_base}" "${share_sources}" shr_sources_needed) +#Extract just the files we need from csm_share +set (shr_sources_needed_base + shr_log_mod.F90 + shr_infnan_mod.F90 + shr_kind_mod.F90 + shr_sys_mod.F90 + shr_strconvert_mod.F90 + shr_abort_mod.abortthrows.F90 + ) +extract_sources("${shr_sources_needed_base}" "${share_sources}" shr_sources_needed) # Add FATES source directories add_subdirectory(${CLM_ROOT}/src/fates/main fates_main) @@ -73,7 +73,7 @@ endforeach() # Build libraries containing stuff needed for the unit tests. # Eventually, these add_library calls should probably be distributed into the correct location, rather than being in this top-level CMakeLists.txt file. -add_library(csm_share ${share_sources}) +add_library(csm_share ${shr_sources_needed}) declare_generated_dependencies(csm_share "${share_genf90_sources}") add_library(fates ${fates_sources}) add_dependencies(fates csm_share) diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 index 90dd592ad1..4447c0804f 100644 --- a/biogeochem/FatesPatchMod.F90 +++ b/biogeochem/FatesPatchMod.F90 @@ -203,12 +203,14 @@ module FatesPatchMod procedure :: create procedure :: dump procedure :: check_vars + procedure :: init_running_means + procedure :: init_litter end type fates_patch_type contains - subroutine init(this, numSWb, numpft, nlevsoil, current_tod) + subroutine init(this, numSWb, nlevsoil) ! ! DESCRIPTION: ! Initialize a new patch @@ -217,16 +219,11 @@ subroutine init(this, numSWb, numpft, nlevsoil, current_tod) ! ARGUMENTS: class(fates_patch_type), intent(inout) :: this ! patch object integer, intent(in) :: numSWb ! number of shortwave broad-bands to track - integer, intent(in) :: numpft ! number of pfts to simulate integer, intent(in) :: nlevsoil ! number of soil layers - integer, intent(in) :: current_tod ! time of day [seconds past 0Z] ! LOCAL VARIABLES: integer :: el ! element loop index - ! Until bc's are pointed to by sites give veg a default temp [K] - real(r8), parameter :: temp_init_veg = 15._r8 + t_water_freeze_k_1atm - ! allocate arrays allocate(this%tr_soil_dir(numSWb)) allocate(this%tr_soil_dif(numSWb)) @@ -237,10 +234,6 @@ subroutine init(this, numSWb, numpft, nlevsoil, current_tod) allocate(this%sabs_dir(numSWb)) allocate(this%sabs_dif(numSWb)) allocate(this%fragmentation_scaler(nlevsoil)) - allocate(this%tveg24) - allocate(this%tveg_lpa) - allocate(this%tveg_longterm) - allocate(this%litter(num_elements)) ! initialize values to nan call this%nan_values() @@ -248,23 +241,7 @@ subroutine init(this, numSWb, numpft, nlevsoil, current_tod) ! zero values that should be zeroed call this%zero_values() - ! set initial values for running means - call this%tveg24%InitRMean(fixed_24hr, init_value=temp_init_veg, & - init_offset=real(current_tod, r8)) - call this%tveg_lpa%InitRmean(ema_lpa, init_value=temp_init_veg) - call this%tveg_longterm%InitRmean(ema_longterm, init_value=temp_init_veg) - - ! set initial values for litter - do el = 1, num_elements - call this%litter(el)%InitAllocate(numpft, nlevsoil, element_list(el)) - call this%litter(el)%ZeroFlux() - call this%litter(el)%InitConditions(init_leaf_fines=fates_unset_r8, & - init_root_fines=fates_unset_r8, init_ag_cwd=fates_unset_r8, & - init_bg_cwd=fates_unset_r8, init_seed=fates_unset_r8, & - init_seed_germ=fates_unset_r8) - end do - - end subroutine init + end subroutine init !:.........................................................................: @@ -468,6 +445,63 @@ end subroutine zero_values !:.........................................................................: + subroutine init_running_means(this, current_tod) + ! + ! DESCRIPTION: + ! set initial values for patch running means + ! + + ! ARGUMENTS: + class(fates_patch_type), intent(inout) :: this ! patch object + integer, intent(in) :: current_tod ! time of day [seconds past 0Z] + + ! PARAMETERS: + ! Until bc's are pointed to by sites give veg a default temp [K] + real(r8), parameter :: temp_init_veg = 15._r8 + t_water_freeze_k_1atm + + allocate(this%tveg24) + allocate(this%tveg_lpa) + allocate(this%tveg_longterm) + + ! set initial values for running means + call this%tveg24%InitRMean(fixed_24hr, init_value=temp_init_veg, & + init_offset=real(current_tod, r8)) + call this%tveg_lpa%InitRmean(ema_lpa, init_value=temp_init_veg) + call this%tveg_longterm%InitRmean(ema_longterm, init_value=temp_init_veg) + + end subroutine init_running_means + + !:.........................................................................: + + subroutine init_litter(this, numpft, nlevsoil) + ! + ! DESCRIPTION: + ! set initial values for litter + ! + + ! ARGUMENTS: + class(fates_patch_type), intent(inout) :: this ! patch object + integer, intent(in) :: numpft ! number of pfts to simulate + integer, intent(in) :: nlevsoil ! number of soil layers + + ! LOCALS: + integer :: el ! looping index + + allocate(this%litter(num_elements)) + + do el = 1, num_elements + call this%litter(el)%InitAllocate(numpft, nlevsoil, element_list(el)) + call this%litter(el)%ZeroFlux() + call this%litter(el)%InitConditions(init_leaf_fines=fates_unset_r8, & + init_root_fines=fates_unset_r8, init_ag_cwd=fates_unset_r8, & + init_bg_cwd=fates_unset_r8, init_seed=fates_unset_r8, & + init_seed_germ=fates_unset_r8) + end do + + end subroutine init_litter + + !:.........................................................................: + subroutine create(this, age, areap, label, nocomp_pft, numSWb, numpft, & nlevsoil, current_tod) ! @@ -487,8 +521,14 @@ subroutine create(this, age, areap, label, nocomp_pft, numSWb, numpft, & integer, intent(in) :: current_tod ! time of day [seconds past 0Z] ! initialize patch - ! also sets all values to nan, then some values to zero - call this%init(numSWb, numpft, nlevsoil, current_tod) + ! sets all values to nan, then some values to zero + call this%init(numSWb, nlevsoil) + + ! initialize running means for patch + call this%init_running_means(current_tod) + + ! initialize litter + call this%init_litter(numpft, nlevsoil) ! assign known patch attributes this%age = age diff --git a/biogeophys/test/solar_rad_test/FATES_rad_exe b/biogeophys/test/solar_rad_test/FATES_rad_exe new file mode 100755 index 0000000000000000000000000000000000000000..bdff0705d16b6f977db37b78dead936d7c56de92 GIT binary patch literal 978808 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ⅈA-RA4P@XB)zM&71Vqaz-h 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

WzbwN^?+ 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 literal 0 HcmV?d00001 diff --git a/biogeophys/test/solar_rad_test/FatesUnitTestRadiation.F90 b/biogeophys/test/solar_rad_test/FatesUnitTestRadiation.F90 index 83c5a68964..3caac90a38 100644 --- a/biogeophys/test/solar_rad_test/FatesUnitTestRadiation.F90 +++ b/biogeophys/test/solar_rad_test/FatesUnitTestRadiation.F90 @@ -4,44 +4,82 @@ program FatesUnitTestRadiation ! Test the FATES radiation schemes ! - use FatesUnitTestIOMod, only : logf, MAX_PATH, open_file - use FatesUnitTestOrbitalMod, only : SHR_KIND_R8 - use FatesUnitTestOrbitalMod, only : get_orbital_vals, shr_orb_cosz - use FatesUnitTestOrbitalMod, only : shr_orb_decl - use FatesConstantsMod, only : r8 => fates_r8 - use EDPftvarcon, only : EDPftvarcon_type - !use EDParamsMod, only : nlevleaf, nclmax + use FatesUnitTestIOMod, only : logf, MAX_PATH, open_file, read_patch_data + use FatesUnitTestOrbitalMod, only : SHR_KIND_R8 + use FatesUnitTestOrbitalMod, only : get_orbital_vals, shr_orb_cosz + use FatesUnitTestOrbitalMod, only : shr_orb_decl + use FatesConstantsMod, only : r8 => fates_r8 + use EDPftvarcon, only : EDPftvarcon_inst + use FatesParametersInterface, only : fates_parameters_type + use FatesPatchMod, only : fates_patch_type + use PRTGenericMod, only : num_elements, element_list, element_pos + use PRTGenericMod, only : carbon12_element implicit none ! LOCALS: - character(len=MAX_PATH) :: param_file ! parameter file name - character(len=MAX_PATH) :: patch_file ! patch data file name - character(len=MAX_PATH) :: out_file ! output file name - integer :: year, jday ! year and day of year to simulate - real(r8) :: lat, lon ! latitude/longitude to simulate [degrees] - real(r8) :: fcansno ! fraction of canopy covered by snow [0-1] + type(fates_patch_type), pointer :: fates_patch ! patch object + character(len=MAX_PATH) :: patch_file ! patch data file name + character(len=MAX_PATH) :: out_file ! output file name + integer :: year, jday ! year and day of year to simulate + integer :: num_pft ! number of pfts + real(r8) :: lat, lon ! latitude/longitude to simulate [degrees] + real(r8) :: fcansno ! fraction of canopy covered by snow [0-1] + real(r8), allocatable :: canopy_area(:,:,:) ! canopy area profile + real(r8), allocatable :: elai(:,:,:) ! exposed lai profile + real(r8), allocatable :: esai(:,:,:) ! exposed sai profile + integer, allocatable :: nrad(:,:) ! number of exposed leaf layers ! PARAMETERS - integer, parameter :: numSWb = 2 ! number of shortwave bands to simulate + integer, parameter :: numSWB = 2 ! number of shortwave bands to simulate + integer, parameter :: nlevsoil = 5 ! this shouldn't really matter + integer, parameter :: current_tod = 0 ! current time [seconds past 0Z] interface - subroutine read_radiation_namelist(year, jday, lat, lon, fcansno, & - param_file, patch_file, out_file) + subroutine read_radiation_namelist(year, jday, lat, lon, num_pft, fcansno, & + patch_file, out_file) use FatesUnitTestIOMod, only : MAX_PATH, MAX_CHAR, open_file use FatesConstantsMod, only : r8 => fates_r8 implicit none - character(len=MAX_PATH), intent(out) :: param_file, patch_file, out_file - integer, intent(out) :: year, jday + character(len=MAX_PATH), intent(out) :: patch_file, out_file + integer, intent(out) :: year, jday + integer, intent(out) :: num_pft real(r8), intent(out) :: lat, lon real(r8), intent(out) :: fcansno end subroutine read_radiation_namelist + subroutine read_pft_namelist(num_pft, numSWB, clumping_index, xl, rhol) + + use FatesUnitTestIOMod, only : MAX_PATH, MAX_CHAR, open_file, logf + use FatesConstantsMod, only : r8 => fates_r8 + + implicit none + + integer, intent(in) :: num_pft + integer, intent(in) :: numSWB + real(r8), intent(out) :: clumping_index(num_pft) + real(r8), intent(out) :: xl(num_pft) + real(r8), intent(out) :: rhol(num_pft,numSWB) + + end subroutine read_pft_namelist + subroutine init_pft_data(num_pft, numSWB) + + use EDPftvarcon, only : EDPftvarcon_inst + use FatesParametersInterface, only : fates_parameters_type + use FatesConstantsMod, only : r8 => fates_r8 + + implicit none + + integer, intent(in) :: num_pft + integer, intent(in) :: numSWB + + end subroutine init_pft_data + end interface !:...........................................................................: @@ -50,16 +88,22 @@ end subroutine read_radiation_namelist logf = open_file("log.txt") ! read in namelist to get some runtime parameters - call read_radiation_namelist(year, jday, lat, lon, fcansno, param_file, & + call read_radiation_namelist(year, jday, lat, lon, num_pft, fcansno, & patch_file, out_file) - - ! read in parameter file and initialize EDPFTvarcon_inst - - + ! initialize pft data + call init_pft_data(num_pft, numSWB) + ! read in patch data - !call read_patch_data(patch_file, canopy_area_profile, elai_profile, & - ! esai_profile, nrad_r) + call read_patch_data(patch_file, num_pft, canopy_area, elai, esai, nrad) + + ! initialize a patch and set values + allocate(fates_patch) + call fates_patch%init(numSWB, nlevsoil) + fates_patch%canopy_area_profile = canopy_area + fates_patch%elai_profile = elai + fates_patch%esai_profile = esai + fates_patch%nrad = nrad ! call get_orbital_vals(year, logf, eccen, mvelp, obliqr, lambm0, mvelpp) @@ -88,7 +132,7 @@ end program FatesUnitTestRadiation !:.............................................................................: -subroutine read_radiation_namelist(year, jday, lat, lon, fcansno, param_file, & +subroutine read_radiation_namelist(year, jday, lat, lon, num_pft, fcansno, & patch_file, out_file) ! ! DESCRIPTION: @@ -102,10 +146,10 @@ subroutine read_radiation_namelist(year, jday, lat, lon, fcansno, param_file, & implicit none ! ARGUMENTS: - character(len=MAX_PATH), intent(out) :: param_file ! parameter file name character(len=MAX_PATH), intent(out) :: patch_file ! patch data file name character(len=MAX_PATH), intent(out) :: out_file ! output file name integer, intent(out) :: year, jday ! year and day of year + integer, intent(out) :: num_pft ! number of pfts real(r8), intent(out) :: lat, lon ! latitude and longitude [degrees] real(r8), intent(out) :: fcansno ! fraction of canopy covered by snow [0-1] @@ -115,9 +159,8 @@ subroutine read_radiation_namelist(year, jday, lat, lon, fcansno, param_file, & integer :: rad_nl_file ! unit number for namelist integer :: ios ! I/O status - ! Namelist of radiation parameters - namelist /radiation/ year, jday, lat, lon, fcansno, param_file, patch_file, & + namelist /radiation/ year, jday, lat, lon, num_pft, fcansno, patch_file, & out_file ! Now read parameters namelist @@ -127,7 +170,7 @@ subroutine read_radiation_namelist(year, jday, lat, lon, fcansno, param_file, & if (ios /= 0) then ! Problem reading file - tell user. write(logf, '(A, I6, A, A)') "Error reading radiation namelist file", & - ios, "IOMSG: ", msg + ios, " IOMSG: ", msg stop "Stopped" end if @@ -137,5 +180,108 @@ end subroutine read_radiation_namelist !:.............................................................................: +subroutine read_pft_namelist(num_pft, numSWB, clumping_index, xl, rhol) +! +! DESCRIPTION: +! read in the namelist associated with the pft-specific parameters +! + +use FatesUnitTestIOMod, only : MAX_PATH, MAX_CHAR, open_file, logf +use FatesConstantsMod, only : r8 => fates_r8 + +implicit none + +! ARGUMENTS: +integer, intent(in) :: num_pft ! number of pfts +integer, intent(in) :: numSWB ! number of shortwave bands to simulate +real(r8), intent(out) :: clumping_index(num_pft) ! clumping index +real(r8), intent(out) :: xl(num_pft) ! leaf-stem orientation index +real(r8), intent(out) :: rhol(num_pft,numSWB) ! leaf reflectance [0-1] + +! LOCALS: +character(len=MAX_PATH) :: pft_nl = 'pft_nlfile' ! pft namelist name +character(len=MAX_CHAR) :: msg ! I/O Error message +integer :: pft_nl_file ! unit number for namelist +integer :: ios ! I/O status +real(r8) :: leaf_rhonir(num_pft) ! leaf NIR reflectance [0-1] +real(r8) :: leaf_taunir(num_pft) ! leaf NIR transmittance [0-1] +real(r8) :: leaf_rhovis(num_pft) ! leaf visible reflectance [0-1] +real(r8) :: leaf_tauvis(num_pft) ! leaf visible transmittance [0-1] +real(r8) :: stem_rhonir(num_pft) ! stem NIR reflectance [0-1] +real(r8) :: stem_taunir(num_pft) ! stem NIR transmittance [0-1] +real(r8) :: stem_rhovis(num_pft) ! stem visible reflectance [0-1] +real(r8) :: stem_tauvis(num_pft) ! stem visible transmittance [0-1] + +! Namelist of pft-specific parameters +namelist /params/ clumping_index, xl, leaf_rhonir, leaf_taunir, leaf_rhovis, & + leaf_tauvis, stem_rhonir, stem_taunir, stem_rhovis, stem_tauvis + +! Now read parameters namelist +pft_nl_file = open_file(trim(pft_nl), 'r') +read(pft_nl_file, params, iostat=ios, iomsg=msg) + +if (ios /= 0) then + ! Problem reading file - tell user. + write(logf, '(A, I6, A, A)') "Error reading pft namelist file", & + ios, " IOMSG: ", msg + stop "Stopped" +end if + +! combine arrays +rhol(:,1) = leaf_rhovis +rhol(:,2) = leaf_rhonir + +close(pft_nl_file) + +end subroutine read_pft_namelist + +!:.............................................................................: + +subroutine init_pft_data(num_pft, numSWB) + ! + ! DESCRIPTION: + ! read in the namelist associated with the pft-specific parameters and + ! initialize data + ! + + use EDPftvarcon, only : EDPftvarcon_inst + use FatesParametersInterface, only : fates_parameters_type + use FatesConstantsMod, only : r8 => fates_r8 + + implicit none + + ! ARGUMENTS: + integer, intent(in) :: num_pft ! number of pfts + integer, intent(in) :: numSWB ! number of shortwave bands to simulate + + ! LOCALS: + class(fates_parameters_type), allocatable :: fates_params ! FATES input parameters + real(r8) :: clumping_index(num_pft) ! clumping index + real(r8) :: xl(num_pft) ! leaf-stem orientation index + real(r8) :: rhol(num_pft,numSWB) ! leaf reflectance [0-1] + real(r8) :: rhos(num_pft,numSWB) ! stem reflectance [0-1] + real(r8) :: taul(num_pft,numSWB) ! leaf transmittance [0-1] + real(r8) :: taus(num_pft,numSWB) ! stem transmittance [0-1] + + ! initialize EDPFTvarcon_inst and fates_params + call EDPftvarcon_inst%Init() + allocate(fates_params) + call fates_params%Init() + call EDPftvarcon_inst%Register(fates_params) + + ! read in parameter values + call read_pft_namelist(num_pft, numSWB, clumping_index, xl, rhol) + + ! set values + ! TODO: make this read in from a parameter file, this is hacky + EDPftvarcon_inst%clumping_index = clumping_index + EDPftvarcon_inst%xl = xl + EDPftvarcon_inst%rhol = rhol + EDPftvarcon_inst%rhos = rhos + EDPftvarcon_inst%taul = taul + EDPftvarcon_inst%taus = taus + +end subroutine init_pft_data + diff --git a/biogeophys/test/solar_rad_test/log.txt b/biogeophys/test/solar_rad_test/log.txt deleted file mode 100644 index 8b13789179..0000000000 --- a/biogeophys/test/solar_rad_test/log.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/biogeophys/test/solar_rad_test/pft_nlfile b/biogeophys/test/solar_rad_test/pft_nlfile new file mode 100644 index 0000000000..bce144acef --- /dev/null +++ b/biogeophys/test/solar_rad_test/pft_nlfile @@ -0,0 +1,14 @@ +¶ms +! parameters for the radiation unit test +! see FatesUnitTestRadiation.F90 +leaf_rhonir = 0.46 0.41 0.39 0.46 0.41 0.41 0.46 0.41 0.41 0.28 0.28 0.28 +leaf_taunir = 0.33 0.32 0.42 0.33 0.43 0.43 0.33 0.43 0.43 0.40 0.40 0.40 +leaf_rhovis = 0.11 0.09 0.08 0.11 0.08 0.08 0.11 0.08 0.08 0.05 0.05 0.05 +leaf_tauvis = 0.06 0.04 0.06 0.06 0.06 0.06 0.06 0.06 0.06 0.05 0.05 0.05 +stem_rhovis = 0.21 0.12 0.12 0.21 0.21 0.21 0.21 0.21 0.21 0.31 0.31 0.31 +stem_rhonir = 0.49 0.36 0.36 0.49 0.49 0.49 0.49 0.49 0.49 0.53 0.53 0.53 +stem_tauvis = 0.001 0.001 0.001 0.001 0.001 0.001 0.001 0.001 0.001 0.120 0.120 0.120 +stem_taunir = 0.001 0.001 0.001 0.001 0.001 0.001 0.001 0.001 0.001 0.250 0.250 0.250 +xl = 0.32 0.01 0.01 0.32 0.20 0.59 0.32 0.59 0.59 -0.23 -0.23 -0.23 +clumping_index = 0.85 0.85 0.80 0.85 0.85 0.90 0.85 0.90 0.90 0.75 0.75 0.75 +/ diff --git a/biogeophys/test/solar_rad_test/radiation_nl b/biogeophys/test/solar_rad_test/radiation_nl index 3d0d608175..5c5cdf4c1f 100644 --- a/biogeophys/test/solar_rad_test/radiation_nl +++ b/biogeophys/test/solar_rad_test/radiation_nl @@ -5,8 +5,8 @@ year = 2000 jday = 165 lat = 45.0 lon = 238.0 +num_pft = 12 fcansno = 0.0 -param_file = '/Users/afoster/Documents/ncar/fates/albedo_calib/fates_params_default.nc' patch_file = 'patch_data.nc' out_file = 'radiation_out.nc' / diff --git a/main/FatesGlobals.F90 b/main/FatesGlobals.F90 index ebc0f326ff..56d381377c 100644 --- a/main/FatesGlobals.F90 +++ b/main/FatesGlobals.F90 @@ -83,7 +83,7 @@ subroutine fates_endrun(msg) ! This subroutine was derived from CLM's ! endrun_vanilla() in abortutils.F90 ! - use shr_sys_mod , only: shr_sys_abort + !use shr_sys_mod , only: shr_sys_abort ! ! !ARGUMENTS: implicit none @@ -91,7 +91,8 @@ subroutine fates_endrun(msg) !----------------------------------------------------------------------- write(fates_log(),*)'ENDRUN:', msg - call shr_sys_abort() + !call shr_sys_abort() + stop end subroutine fates_endrun diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 164661c148..2d23ca3346 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -737,12 +737,9 @@ subroutine SetFatesGlobalElements1(use_fates,surf_numpft,surf_numcft) implicit none logical, intent(in) :: use_fates ! Is fates turned on? - logical, intent(in) :: masterproc ! proc 0 logical for printing msgs integer, intent(in) :: surf_numpft ! Number of PFTs in surface dataset integer, intent(in) :: surf_numcft ! Number of CFTs in surface dataset - character(len=SHR_KIND_CL), intent(in) :: paramfile ! ASCII data file (host model) - character(len=SHR_KIND_CL), intent(in) :: fates_paramfile ! ASCII data file with PFT physiological constants (FATES) - + integer :: fates_numpft ! Number of PFTs tracked in FATES if (use_fates) then diff --git a/unit_test_shr/FatesUnitTestIOMod.F90 b/unit_test_shr/FatesUnitTestIOMod.F90 index d7f1bb8726..47f88080b4 100644 --- a/unit_test_shr/FatesUnitTestIOMod.F90 +++ b/unit_test_shr/FatesUnitTestIOMod.F90 @@ -1,12 +1,6 @@ module FatesUnitTestIOMod - use FatesConstantsMod, only : r8 => fates_r8 - use FatesParametersInterface, only : fates_parameters_type - use FatesParametersInterface, only : param_string_length, max_used_dimensions - use EDParamsMod, only : FatesRegisterParams, FatesReceiveParams - use SFParamsMod, only : SpitFireRegisterParams, SpitFireReceiveParams - use PRTInitParamsFATESMod, only : PRTRegisterParams, PRTReceiveParams - use shr_kind_mod, only : SHR_KIND_CL - use FatesSynchronizedParamsMod, only : FatesSynchronizedParamsInst + use FatesConstantsMod, only : r8 => fates_r8 + use shr_kind_mod, only : SHR_KIND_CL use netcdf implicit none @@ -16,6 +10,15 @@ module FatesUnitTestIOMod integer, parameter :: MAX_PATH = 256 ! Maximum path length integer, parameter :: MAX_CHAR = 80 ! Maximum length for messages integer :: logf ! Unit number for output log file + + interface get_var + module procedure get_var1D_real + module procedure get_var2D_real + module procedure get_var3D_real + module procedure get_var1D_int + module procedure get_var2D_int + module procedure get_var3D_int + end interface contains @@ -142,163 +145,248 @@ subroutine check(status) end subroutine check !:.........................................................................: - - subroutine read_parameters(fates_paramfile) + + subroutine read_patch_data(file, num_pft, canopy_area, elai, esai, nrad) ! ! DESCRIPTION: - ! Reads in parameters from the FATES parameter file + ! Reads and return patch data ! ! ARGUMENTS: - character(len=SHR_KIND_CL), intent(in) :: fates_paramfile ! parameter file name - + character(len=MAX_PATH), intent(in) :: file ! patch file name + integer, intent(in) :: num_pft ! number of PFTs + real(r8), allocatable, intent(out) :: canopy_area(:,:,:) ! canopy area profile + real(r8), allocatable, intent(out) :: elai(:,:,:) ! exposed lai profile + real(r8), allocatable, intent(out) :: esai(:,:,:) ! exposed sai profile + integer, allocatable, intent(out) :: nrad(:,:) ! number of exposed leaf layers + ! LOCALS: - class(fates_parameters_type), allocatable :: fates_params + integer :: ncid ! netcdf file unit number + + ! open file + call check(nf90_open(trim(file), 0, ncid)) + + ! read in data + call get_var(ncid, 'can_area', canopy_area) + call get_var(ncid, 'elai', elai) + call get_var(ncid, 'esai', esai) + call get_var(ncid, 'nrad', nrad) - allocate(fates_params) - call fates_params%Init() - call FatesRegisterParams(fates_params) - call SpitFireRegisterParams(fates_params) - call PRTRegisterParams(fates_params) - call FatesSynchronizedParamsInst%RegisterParams(fates_params) + ! close file + call check(nf90_close(ncid)) - end subroutine read_parameters + end subroutine read_patch_data !:.........................................................................: - subroutine read_netcdf_params(filename, fates_params) + subroutine get_dims(ncid, varID, dim_lens) ! ! DESCRIPTION: - ! Calls actual netcdf library methods for reading FATES parameters from netcdf + ! Get dimensions for a netcdf variable + ! + + ! ARGUMENTS + integer, intent(in) :: ncid ! netcdf file unit ID + integer, intent(in) :: varID ! variable ID + integer, allocatable, intent(out) :: dim_lens(:) ! dimension lengths + + ! LOCALS: + integer :: numDims ! number of dimensions + integer, allocatable :: dimIDs(:) ! dimension IDs + integer :: i ! looping index + + ! find dimensions of data + call check(nf90_inquire_variable(ncid, varID, ndims=numDims)) + + ! allocate data to grab dimension information + allocate(dim_lens(numDims)) + allocate(dimIDs(numDims)) + + ! get dimIDs + call check(nf90_inquire_variable(ncid, varID, dimids=dimIDs)) + + ! grab these dimensions + do i = 1, numDims + call check(nf90_inquire_dimension(ncid, dimIDs(i), len=dim_lens(i))) + end do + + end subroutine get_dims + + !:.........................................................................: + + subroutine get_var1D_real(ncid, var_name, data) + ! + ! DESCRIPTION: + ! Read in variables for 1D real data ! ! ARGUMENTS: - character(len=*), intent(in) :: filename ! full path of parameter file - class(fates_parameters_type), intent(inout) :: fates_params ! fates parameters type - + integer, intent(in) :: ncid ! netcdf file unit ID + character(len=*), intent(in) :: var_name ! variable name + real(r8), allocatable, intent(out) :: data(:) ! data values + ! LOCALS: - logical :: file_exists ! does the file exist? - integer :: ncid ! netcdf file unit number - integer :: max_dim_size ! - - ! check if file is on disk - inquire(file=trim(adjustl(filename)), exist=file_exists) - if (.not. file_exists) then - write(logf,'(a)') 'File ', filename, ' does not exist.' - stop "Stopping" - end if - - ! open the file - call check(nf90_open(trim(adjustl(filename)), 0, ncid)) - - ! get and set the correct dimensions for the parameters - call set_param_dimensions(ncid, fates_params) - - ! max_dim_size = fates_params%GetMaxDimensionSize() - ! num_params = fates_params%num_params() - ! do i = 1, num_params - ! call fates_params%GetMetaData(i, name, dimension_shape, dimension_sizes, dimension_names, is_host_param) - ! if (is_host_file .eqv. is_host_param) then - ! select case(dimension_shape) - ! case(dimension_shape_scalar) - ! size_dim_1 = 1 - ! size_dim_2 = 1 - ! case(dimension_shape_1d) - ! size_dim_1 = dimension_sizes(1) - ! size_dim_2 = 1 - ! case(dimension_shape_2d) - ! size_dim_1 = dimension_sizes(1) - ! size_dim_2 = dimension_sizes(2) - ! case default - ! write(fates_log(),*) 'dimension shape:',dimension_shape - ! call endrun(msg='unsupported number of dimensions reading parameters.') - - ! end select - ! if (masterproc) then - ! write(fates_log(), *) 'clmfates_interfaceMod.F90:: reading '//trim(name) - ! end if - ! call readNcdio(ncid, name, dimension_shape, dimension_names, subname, data(1:size_dim_1, 1:size_dim_2)) - ! call fates_params%SetData(i, data(1:size_dim_1, 1:size_dim_2)) - ! end if - ! end do - ! deallocate(data) - ! call ncd_pio_closefile(ncid) - - end subroutine read_netcdf_params + integer :: varID ! variable ID + integer, allocatable :: dim_lens(:) ! dimension lengths + + ! find variable ID first + call check(nf90_inq_varid(ncid, var_name, varID)) + + ! get dimensions of data + call get_dims(ncid, varID, dim_lens) + + ! read data + allocate(data(dim_lens(1))) + call check(nf90_get_var(ncid, varID, data)) + + end subroutine get_var1D_real !:.........................................................................: - subroutine set_param_dimensions(ncid, fates_params) + subroutine get_var1D_int(ncid, var_name, data) ! ! DESCRIPTION: - ! get the list of dimensions used by the FATES parameters + ! Read in variables for 1D integer data ! ! ARGUMENTS: - integer, intent(inout) :: ncid ! netcdf unit number - class(fates_parameters_type), intent(inout) :: fates_params ! fates parameters + integer, intent(in) :: ncid ! netcdf file unit ID + character(len=*), intent(in) :: var_name ! variable name + integer, allocatable, intent(out) :: data(:) ! data values ! LOCALS: - integer :: num_dimensions - character(len=param_string_length) :: dimension_names(max_used_dimensions) - integer :: dimension_sizes(max_used_dimensions) - integer :: d - integer :: dim_id - - dimension_sizes(:) = 0 + integer :: varID ! variable ID + integer, allocatable :: dim_lens(:) ! dimension lengths - call fates_params%GetUsedDimensions(.false., num_dimensions, & - dimension_names) + ! find variable ID first + call check(nf90_inq_varid(ncid, var_name, varID)) - do d = 1, num_dimensions - call check(nf90_inq_dimid(ncid, dimension_names(d), dim_id)) - call check(nf90_inquire_dimension(ncid, dim_id, len=dimension_sizes(d))) - end do + ! get dimensions of data + call get_dims(ncid, varID, dim_lens) - call fates_params%SetDimensionSizes(.false., num_dimensions, & - dimension_names, dimension_sizes) + ! read data + allocate(data(dim_lens(1))) + call check(nf90_get_var(ncid, varID, data)) + + end subroutine get_var1D_int - end subroutine set_param_dimensions + !:.........................................................................: + + subroutine get_var2D_real(ncid, var_name, data) + ! + ! DESCRIPTION: + ! Read in variables for 2D real data + ! + + ! ARGUMENTS: + integer, intent(in) :: ncid ! netcdf file unit ID + character(len=*), intent(in) :: var_name ! variable name + real(r8), allocatable, intent(out) :: data(:,:) ! data values + + ! LOCALS: + integer :: varID ! variable ID + integer, allocatable :: dim_lens(:) ! dimension lengths + + ! find variable ID first + call check(nf90_inq_varid(ncid, var_name, varID)) + + ! get dimensions of data + call get_dims(ncid, varID, dim_lens) + + ! read data + allocate(data(dim_lens(1), dim_lens(2))) + call check(nf90_get_var(ncid, varID, data)) + + end subroutine get_var2D_real !:.........................................................................: - ! subroutine read_patch_data(file, canopy_area, elai, esai, nrad) - ! ! - ! ! DESCRIPTION: - ! ! Reads and return patch data - - ! ! ARGUMENTS: - ! character(len=MAX_PATH), intent(in) :: file ! patch file name - ! real(r8), intent(out) :: canopy_area(num_can,num_pft,nlevleaf) ! canopy area profile - ! real(r8), intent(out) :: elai(num_can,num_pft,nlevleaf) ! exposed lai profile - ! real(r8), intent(out) :: esai(num_can,num_pft,nlevleaf) ! exposed sai profile - ! real(r8), intent(out) :: nrad(num_can,num_pft) ! number of exposed leaf layers + subroutine get_var2D_int(ncid, var_name, data) + ! + ! DESCRIPTION: + ! Read in variables for 2D integer data + ! - ! ! LOCALS: - ! real(r8) :: nrad_r(num_can,num_pft) ! number of exposed leaf layers - ! integer :: fidA, varID + ! ARGUMENTS: + integer, intent(in) :: ncid ! netcdf file unit ID + character(len=*), intent(in) :: var_name ! variable name + integer, allocatable, intent(out) :: data(:,:) ! data values - ! ! open file - ! call check(nf90_open(trim(file), 0, fidA)) + ! LOCALS: + integer :: varID ! variable ID + integer, allocatable :: dim_lens(:) ! dimension lengths + + ! find variable ID first + call check(nf90_inq_varid(ncid, var_name, varID)) + + ! get dimensions of data + call get_dims(ncid, varID, dim_lens) + + ! read data + allocate(data(dim_lens(1), dim_lens(2))) + call check(nf90_get_var(ncid, varID, data)) + + end subroutine get_var2D_int + + !:.........................................................................: + + subroutine get_var3D_real(ncid, var_name, data) + ! + ! DESCRIPTION: + ! Read in variables for 3D real data + ! - ! ! read patch data values - ! call check(nf90_inq_varid(fidA, "can_area", varID)) - ! call check(nf90_get_var(fidA, varID, canopy_area)) + ! ARGUMENTS: + integer, intent(in) :: ncid ! netcdf file unit ID + character(len=*), intent(in) :: var_name ! variable name + real(r8), allocatable, intent(out) :: data(:,:,:) ! data values - ! call check(nf90_inq_varid(fidA, "elai", varID)) - ! call check(nf90_get_var(fidA, varID, elai)) + ! LOCALS: + integer :: varID ! variable ID + integer, allocatable :: dim_lens(:) ! dimension lengths - ! call check(nf90_inq_varid(fidA, "esai", varID)) - ! call check(nf90_get_var(fidA, varID, esai)) + ! find variable ID first + call check(nf90_inq_varid(ncid, var_name, varID)) - ! call check(nf90_inq_varid(fidA, "nrad", varID)) - ! call check(nf90_get_var(fidA, varID, nrad)) + ! get dimensions of data + call get_dims(ncid, varID, dim_lens) - ! end subroutine read_patch_data + ! read data + allocate(data(dim_lens(1), dim_lens(2), dim_lens(3))) + call check(nf90_get_var(ncid, varID, data)) + + end subroutine get_var3D_real !:.........................................................................: - + subroutine get_var3D_int(ncid, var_name, data) + ! + ! DESCRIPTION: + ! Read in variables for 3D integer data + ! + + ! ARGUMENTS: + integer, intent(in) :: ncid ! netcdf file unit ID + character(len=*), intent(in) :: var_name ! variable name + integer, allocatable, intent(out) :: data(:,:,:) ! data values + + ! LOCALS: + integer :: varID ! variable ID + integer, allocatable :: dim_lens(:) ! dimension lengths + + ! find variable ID first + call check(nf90_inq_varid(ncid, var_name, varID)) + + ! get dimensions of data + call get_dims(ncid, varID, dim_lens) + + ! read data + allocate(data(dim_lens(1), dim_lens(2), dim_lens(3))) + call check(nf90_get_var(ncid, varID, data)) + + end subroutine get_var3D_int + + !:.........................................................................: ! subroutine write_radiation_data(file, kdir, declin) ! ! From db98e2a46ec06a97944bc8f1b483ab4d702c441f Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 2 May 2023 13:30:54 -0600 Subject: [PATCH 662/852] just refactor stuff --- biogeophys/test/CMakeLists.txt | 2 - biogeophys/test/solar_rad_test/CMakeLists.txt | 27 - biogeophys/test/solar_rad_test/FATES_rad_exe | Bin 978808 -> 0 bytes .../solar_rad_test/FatesUnitTestRadiation.F90 | 287 --------- biogeophys/test/solar_rad_test/pft_nlfile | 14 - biogeophys/test/solar_rad_test/radiation_nl | 12 - test_list.xml | 7 - unit_test_shr/CMakeLists.txt | 7 - unit_test_shr/FatesUnitTestIOMod.F90 | 434 ------------- unit_test_shr/FatesUnitTestOrbitalMod.F90 | 581 ------------------ 10 files changed, 1371 deletions(-) delete mode 100644 biogeophys/test/CMakeLists.txt delete mode 100644 biogeophys/test/solar_rad_test/CMakeLists.txt delete mode 100755 biogeophys/test/solar_rad_test/FATES_rad_exe delete mode 100644 biogeophys/test/solar_rad_test/FatesUnitTestRadiation.F90 delete mode 100644 biogeophys/test/solar_rad_test/pft_nlfile delete mode 100644 biogeophys/test/solar_rad_test/radiation_nl delete mode 100644 test_list.xml delete mode 100644 unit_test_shr/CMakeLists.txt delete mode 100644 unit_test_shr/FatesUnitTestIOMod.F90 delete mode 100644 unit_test_shr/FatesUnitTestOrbitalMod.F90 diff --git a/biogeophys/test/CMakeLists.txt b/biogeophys/test/CMakeLists.txt deleted file mode 100644 index 76e7f575a3..0000000000 --- a/biogeophys/test/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_subdirectory(solar_rad_test) - diff --git a/biogeophys/test/solar_rad_test/CMakeLists.txt b/biogeophys/test/solar_rad_test/CMakeLists.txt deleted file mode 100644 index 896cfc024e..0000000000 --- a/biogeophys/test/solar_rad_test/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -set(rad_sources FatesUnitTestRadiation.F90) - -set(NETCDF_C_DIR "/usr/local/Cellar/netcdf/4.9.2") -set(NETCDF_FORTRAN_DIR "/usr/local/Cellar/netcdf-fortran/4.6.0") - -FIND_PATH(NETCDFC_FOUND libnetcdf.a ${NETCDF_C_DIR}/lib) -FIND_PATH(NETCDFF_FOUND libnetcdff.a ${NETCDF_FORTRAN_DIR}/lib) -MESSAGE(" NETCDFC_FOUND = ${NETCDFC_FOUND}") -MESSAGE(" NETCDFF_FOUND = ${NETCDFF_FOUND}") - -include_directories(${NETCDF_C_DIR}/include - ${NETCDF_FORTRAN_DIR}/include) -link_directories(${NETCDF_C_DIR}/lib - ${NETCDF_FORTRAN_DIR}/lib) - -add_executable(FATES_rad_exe ${rad_sources}) - -target_link_libraries(FATES_rad_exe - netcdff - netcdf - fates - csm_share) - -add_test(rad_test FATES_rad_exe) - -# Tell CTest how to figure out that "STOP 1" fails for the current -define_Fortran_stop_failure(rad_test) diff --git a/biogeophys/test/solar_rad_test/FATES_rad_exe b/biogeophys/test/solar_rad_test/FATES_rad_exe deleted file mode 100755 index bdff0705d16b6f977db37b78dead936d7c56de92..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 978808 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ⅈA-RA4P@XB)zM&71Vqaz-h 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

WzbwN^?+ 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 diff --git a/biogeophys/test/solar_rad_test/FatesUnitTestRadiation.F90 b/biogeophys/test/solar_rad_test/FatesUnitTestRadiation.F90 deleted file mode 100644 index 3caac90a38..0000000000 --- a/biogeophys/test/solar_rad_test/FatesUnitTestRadiation.F90 +++ /dev/null @@ -1,287 +0,0 @@ -program FatesUnitTestRadiation - ! - ! DESCRIPTION: - ! Test the FATES radiation schemes - ! - - use FatesUnitTestIOMod, only : logf, MAX_PATH, open_file, read_patch_data - use FatesUnitTestOrbitalMod, only : SHR_KIND_R8 - use FatesUnitTestOrbitalMod, only : get_orbital_vals, shr_orb_cosz - use FatesUnitTestOrbitalMod, only : shr_orb_decl - use FatesConstantsMod, only : r8 => fates_r8 - use EDPftvarcon, only : EDPftvarcon_inst - use FatesParametersInterface, only : fates_parameters_type - use FatesPatchMod, only : fates_patch_type - use PRTGenericMod, only : num_elements, element_list, element_pos - use PRTGenericMod, only : carbon12_element - - implicit none - - ! LOCALS: - type(fates_patch_type), pointer :: fates_patch ! patch object - character(len=MAX_PATH) :: patch_file ! patch data file name - character(len=MAX_PATH) :: out_file ! output file name - integer :: year, jday ! year and day of year to simulate - integer :: num_pft ! number of pfts - real(r8) :: lat, lon ! latitude/longitude to simulate [degrees] - real(r8) :: fcansno ! fraction of canopy covered by snow [0-1] - real(r8), allocatable :: canopy_area(:,:,:) ! canopy area profile - real(r8), allocatable :: elai(:,:,:) ! exposed lai profile - real(r8), allocatable :: esai(:,:,:) ! exposed sai profile - integer, allocatable :: nrad(:,:) ! number of exposed leaf layers - - ! PARAMETERS - integer, parameter :: numSWB = 2 ! number of shortwave bands to simulate - integer, parameter :: nlevsoil = 5 ! this shouldn't really matter - integer, parameter :: current_tod = 0 ! current time [seconds past 0Z] - - interface - - subroutine read_radiation_namelist(year, jday, lat, lon, num_pft, fcansno, & - patch_file, out_file) - - use FatesUnitTestIOMod, only : MAX_PATH, MAX_CHAR, open_file - use FatesConstantsMod, only : r8 => fates_r8 - - implicit none - - character(len=MAX_PATH), intent(out) :: patch_file, out_file - integer, intent(out) :: year, jday - integer, intent(out) :: num_pft - real(r8), intent(out) :: lat, lon - real(r8), intent(out) :: fcansno - - end subroutine read_radiation_namelist - - subroutine read_pft_namelist(num_pft, numSWB, clumping_index, xl, rhol) - - use FatesUnitTestIOMod, only : MAX_PATH, MAX_CHAR, open_file, logf - use FatesConstantsMod, only : r8 => fates_r8 - - implicit none - - integer, intent(in) :: num_pft - integer, intent(in) :: numSWB - real(r8), intent(out) :: clumping_index(num_pft) - real(r8), intent(out) :: xl(num_pft) - real(r8), intent(out) :: rhol(num_pft,numSWB) - - end subroutine read_pft_namelist - subroutine init_pft_data(num_pft, numSWB) - - use EDPftvarcon, only : EDPftvarcon_inst - use FatesParametersInterface, only : fates_parameters_type - use FatesConstantsMod, only : r8 => fates_r8 - - implicit none - - integer, intent(in) :: num_pft - integer, intent(in) :: numSWB - - end subroutine init_pft_data - - end interface - - !:...........................................................................: - - ! open log file - logf = open_file("log.txt") - - ! read in namelist to get some runtime parameters - call read_radiation_namelist(year, jday, lat, lon, num_pft, fcansno, & - patch_file, out_file) - - ! initialize pft data - call init_pft_data(num_pft, numSWB) - - ! read in patch data - call read_patch_data(patch_file, num_pft, canopy_area, elai, esai, nrad) - - ! initialize a patch and set values - allocate(fates_patch) - call fates_patch%init(numSWB, nlevsoil) - fates_patch%canopy_area_profile = canopy_area - fates_patch%elai_profile = elai - fates_patch%esai_profile = esai - fates_patch%nrad = nrad - - ! call get_orbital_vals(year, logf, eccen, mvelp, obliqr, lambm0, mvelpp) - - ! cosz(:) = 0.0 - ! k_dir(:,:) = 0.0 - - ! ! for each half-hourly time step in the day - ! do i = 0, 47 - ! calday = jday + i*0.02083333_SHR_KIND_R8 - ! call shr_orb_decl(calday, eccen, mvelpp, lambm0, obliqr, declin, eccf) - ! cosz(i) = shr_orb_cosz(calday, lat, lon, declin) - - ! if (cosz(i) > 0.0_r8) then - ! ! call norman radiation scheme - ! call PatchNormanRadiation(rhol, rhos, taul, taus, xl, clumping_index, & - ! canopy_area_profile, elai_profile, esai_profile, fcansno, & - ! cosz(i), nrad, 2, k_dir(:,i)) - ! end if - ! end do - - ! call write_radiation_data(out_file, k_dir, cosz) - - close(logf) - -end program FatesUnitTestRadiation - -!:.............................................................................: - -subroutine read_radiation_namelist(year, jday, lat, lon, num_pft, fcansno, & - patch_file, out_file) - ! - ! DESCRIPTION: - ! read in the namelist associated with the radiation unit tests and - ! initialize values - ! - - use FatesUnitTestIOMod, only : MAX_PATH, MAX_CHAR, open_file, logf - use FatesConstantsMod, only : r8 => fates_r8 - - implicit none - - ! ARGUMENTS: - character(len=MAX_PATH), intent(out) :: patch_file ! patch data file name - character(len=MAX_PATH), intent(out) :: out_file ! output file name - integer, intent(out) :: year, jday ! year and day of year - integer, intent(out) :: num_pft ! number of pfts - real(r8), intent(out) :: lat, lon ! latitude and longitude [degrees] - real(r8), intent(out) :: fcansno ! fraction of canopy covered by snow [0-1] - - ! LOCALS: - character(len=MAX_PATH) :: rad_nl = 'radiation_nl' ! radiation namelist name - character(len=MAX_CHAR) :: msg ! I/O Error message - integer :: rad_nl_file ! unit number for namelist - integer :: ios ! I/O status - - ! Namelist of radiation parameters - namelist /radiation/ year, jday, lat, lon, num_pft, fcansno, patch_file, & - out_file - - ! Now read parameters namelist - rad_nl_file = open_file(trim(rad_nl), 'r') - read(rad_nl_file, radiation, iostat=ios, iomsg=msg) - - if (ios /= 0) then - ! Problem reading file - tell user. - write(logf, '(A, I6, A, A)') "Error reading radiation namelist file", & - ios, " IOMSG: ", msg - stop "Stopped" - end if - - close(rad_nl_file) - -end subroutine read_radiation_namelist - -!:.............................................................................: - -subroutine read_pft_namelist(num_pft, numSWB, clumping_index, xl, rhol) -! -! DESCRIPTION: -! read in the namelist associated with the pft-specific parameters -! - -use FatesUnitTestIOMod, only : MAX_PATH, MAX_CHAR, open_file, logf -use FatesConstantsMod, only : r8 => fates_r8 - -implicit none - -! ARGUMENTS: -integer, intent(in) :: num_pft ! number of pfts -integer, intent(in) :: numSWB ! number of shortwave bands to simulate -real(r8), intent(out) :: clumping_index(num_pft) ! clumping index -real(r8), intent(out) :: xl(num_pft) ! leaf-stem orientation index -real(r8), intent(out) :: rhol(num_pft,numSWB) ! leaf reflectance [0-1] - -! LOCALS: -character(len=MAX_PATH) :: pft_nl = 'pft_nlfile' ! pft namelist name -character(len=MAX_CHAR) :: msg ! I/O Error message -integer :: pft_nl_file ! unit number for namelist -integer :: ios ! I/O status -real(r8) :: leaf_rhonir(num_pft) ! leaf NIR reflectance [0-1] -real(r8) :: leaf_taunir(num_pft) ! leaf NIR transmittance [0-1] -real(r8) :: leaf_rhovis(num_pft) ! leaf visible reflectance [0-1] -real(r8) :: leaf_tauvis(num_pft) ! leaf visible transmittance [0-1] -real(r8) :: stem_rhonir(num_pft) ! stem NIR reflectance [0-1] -real(r8) :: stem_taunir(num_pft) ! stem NIR transmittance [0-1] -real(r8) :: stem_rhovis(num_pft) ! stem visible reflectance [0-1] -real(r8) :: stem_tauvis(num_pft) ! stem visible transmittance [0-1] - -! Namelist of pft-specific parameters -namelist /params/ clumping_index, xl, leaf_rhonir, leaf_taunir, leaf_rhovis, & - leaf_tauvis, stem_rhonir, stem_taunir, stem_rhovis, stem_tauvis - -! Now read parameters namelist -pft_nl_file = open_file(trim(pft_nl), 'r') -read(pft_nl_file, params, iostat=ios, iomsg=msg) - -if (ios /= 0) then - ! Problem reading file - tell user. - write(logf, '(A, I6, A, A)') "Error reading pft namelist file", & - ios, " IOMSG: ", msg - stop "Stopped" -end if - -! combine arrays -rhol(:,1) = leaf_rhovis -rhol(:,2) = leaf_rhonir - -close(pft_nl_file) - -end subroutine read_pft_namelist - -!:.............................................................................: - -subroutine init_pft_data(num_pft, numSWB) - ! - ! DESCRIPTION: - ! read in the namelist associated with the pft-specific parameters and - ! initialize data - ! - - use EDPftvarcon, only : EDPftvarcon_inst - use FatesParametersInterface, only : fates_parameters_type - use FatesConstantsMod, only : r8 => fates_r8 - - implicit none - - ! ARGUMENTS: - integer, intent(in) :: num_pft ! number of pfts - integer, intent(in) :: numSWB ! number of shortwave bands to simulate - - ! LOCALS: - class(fates_parameters_type), allocatable :: fates_params ! FATES input parameters - real(r8) :: clumping_index(num_pft) ! clumping index - real(r8) :: xl(num_pft) ! leaf-stem orientation index - real(r8) :: rhol(num_pft,numSWB) ! leaf reflectance [0-1] - real(r8) :: rhos(num_pft,numSWB) ! stem reflectance [0-1] - real(r8) :: taul(num_pft,numSWB) ! leaf transmittance [0-1] - real(r8) :: taus(num_pft,numSWB) ! stem transmittance [0-1] - - ! initialize EDPFTvarcon_inst and fates_params - call EDPftvarcon_inst%Init() - allocate(fates_params) - call fates_params%Init() - call EDPftvarcon_inst%Register(fates_params) - - ! read in parameter values - call read_pft_namelist(num_pft, numSWB, clumping_index, xl, rhol) - - ! set values - ! TODO: make this read in from a parameter file, this is hacky - EDPftvarcon_inst%clumping_index = clumping_index - EDPftvarcon_inst%xl = xl - EDPftvarcon_inst%rhol = rhol - EDPftvarcon_inst%rhos = rhos - EDPftvarcon_inst%taul = taul - EDPftvarcon_inst%taus = taus - -end subroutine init_pft_data - - - diff --git a/biogeophys/test/solar_rad_test/pft_nlfile b/biogeophys/test/solar_rad_test/pft_nlfile deleted file mode 100644 index bce144acef..0000000000 --- a/biogeophys/test/solar_rad_test/pft_nlfile +++ /dev/null @@ -1,14 +0,0 @@ -¶ms -! parameters for the radiation unit test -! see FatesUnitTestRadiation.F90 -leaf_rhonir = 0.46 0.41 0.39 0.46 0.41 0.41 0.46 0.41 0.41 0.28 0.28 0.28 -leaf_taunir = 0.33 0.32 0.42 0.33 0.43 0.43 0.33 0.43 0.43 0.40 0.40 0.40 -leaf_rhovis = 0.11 0.09 0.08 0.11 0.08 0.08 0.11 0.08 0.08 0.05 0.05 0.05 -leaf_tauvis = 0.06 0.04 0.06 0.06 0.06 0.06 0.06 0.06 0.06 0.05 0.05 0.05 -stem_rhovis = 0.21 0.12 0.12 0.21 0.21 0.21 0.21 0.21 0.21 0.31 0.31 0.31 -stem_rhonir = 0.49 0.36 0.36 0.49 0.49 0.49 0.49 0.49 0.49 0.53 0.53 0.53 -stem_tauvis = 0.001 0.001 0.001 0.001 0.001 0.001 0.001 0.001 0.001 0.120 0.120 0.120 -stem_taunir = 0.001 0.001 0.001 0.001 0.001 0.001 0.001 0.001 0.001 0.250 0.250 0.250 -xl = 0.32 0.01 0.01 0.32 0.20 0.59 0.32 0.59 0.59 -0.23 -0.23 -0.23 -clumping_index = 0.85 0.85 0.80 0.85 0.85 0.90 0.85 0.90 0.90 0.75 0.75 0.75 -/ diff --git a/biogeophys/test/solar_rad_test/radiation_nl b/biogeophys/test/solar_rad_test/radiation_nl deleted file mode 100644 index 5c5cdf4c1f..0000000000 --- a/biogeophys/test/solar_rad_test/radiation_nl +++ /dev/null @@ -1,12 +0,0 @@ -&radiation -! parameters for the radiation unit test -! see FatesUnitTestRadiation.F90 -year = 2000 -jday = 165 -lat = 45.0 -lon = 238.0 -num_pft = 12 -fcansno = 0.0 -patch_file = 'patch_data.nc' -out_file = 'radiation_out.nc' -/ diff --git a/test_list.xml b/test_list.xml deleted file mode 100644 index 41719be6c2..0000000000 --- a/test_list.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - unit_testing/test/radiation_test - - - diff --git a/unit_test_shr/CMakeLists.txt b/unit_test_shr/CMakeLists.txt deleted file mode 100644 index 783299e740..0000000000 --- a/unit_test_shr/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -# Append sources from this directory to the list. -list(APPEND fates_sources - FatesUnitTestIOMod.F90 - FatesUnitTestOrbitalMod.F90) - -# Export source list to parent -sourcelist_to_parent(fates_sources) \ No newline at end of file diff --git a/unit_test_shr/FatesUnitTestIOMod.F90 b/unit_test_shr/FatesUnitTestIOMod.F90 deleted file mode 100644 index 47f88080b4..0000000000 --- a/unit_test_shr/FatesUnitTestIOMod.F90 +++ /dev/null @@ -1,434 +0,0 @@ -module FatesUnitTestIOMod - use FatesConstantsMod, only : r8 => fates_r8 - use shr_kind_mod, only : SHR_KIND_CL - use netcdf - - implicit none - - ! LOCALS - integer, parameter :: BASE_UNIT = 10 ! Base unit for files the first time unit_number is called - integer, parameter :: MAX_PATH = 256 ! Maximum path length - integer, parameter :: MAX_CHAR = 80 ! Maximum length for messages - integer :: logf ! Unit number for output log file - - interface get_var - module procedure get_var1D_real - module procedure get_var2D_real - module procedure get_var3D_real - module procedure get_var1D_int - module procedure get_var2D_int - module procedure get_var3D_int - end interface - - contains - - integer function unit_number() - ! - ! DESCRIPTION: - ! Generates a unit number to be used in opening files - ! The first time the function is called, it returns BASE_UNIT - ! - ! LOCALS: - integer :: iunit ! File unit (increments after first call) - logical :: first = .true. ! First time this has been called? - save - - if (first) then - ! Set first to false and iunit to base unit on first call - iunit = BASE_UNIT - first = .false. - else - ! Otherwise, increment - iunit = iunit + 1 - endif - - ! Set to output - unit_number = iunit - - end function unit_number - - !:.........................................................................: - - integer function open_file(filename, mode) - ! - ! DESCRIPTION: - ! Opens the file filename if it can, returns a unit number for it. - ! The first time the function is called, it returns BASE_UNIT - ! - - ! ARGUMENTS: - character(len = *), intent(in) :: filename ! Name of file to open - character(len = *), intent(in), optional :: mode ! Optional mode ('r', 'w', 'rw') - - ! LOCALS: - character(len = 9) :: fmode ! File open mode - logical :: file_exists ! Does the file exist? - character(len = MAX_PATH) :: fname ! Local filename (trimmed) - integer :: i ! Looping index - integer :: ios ! I/O status - integer :: iunit = BASE_UNIT ! File unit number - integer, dimension(MAX_PATH) :: farray ! Array of characters of file name - - ! Get mode of open (read, write, or read/write) - ! Defaults to read/write - if (present(mode)) then - select case(mode) - case ('r', 'R') - fmode = 'read' - case ('w', 'W') - fmode = 'write' - case ('rw', 'RW', 'wr', 'WR') - fmode = 'readwrite' - case DEFAULT - fmode = 'readwrite' - end select - else - fmode = 'readwrite' - endif - - ! trim filename of whitespace - fname = trim(adjustl(filename)) - - if (fmode == 'read' .or. fmode == 'readwrite') then - ! Check for valid name of file - farray = 0 - do i = 1, len_trim(fname) - farray(i) = ichar(fname(i:i)) - enddo - if (any(farray > 126)) then - write(logf,'(A)') "Invalid filename" - stop - endif - endif - - ! Does the file exist? - inquire(file = fname, exist = file_exists) - - ! Open file if conditions are correct - if (file_exists .and. fmode == 'write') then - write(logf,'(A,A,A)') "File ", fname(1:len_trim(fname)), & - " exists. Cannot open write only." - stop - else if (.not. file_exists .and. fmode == 'read') then - write(logf, '(A,A,A)') "File ", fname(1:len_trim(fname)), & - " does not exist. Can't read." - stop - else - iunit = unit_number() - open(iunit, file=fname, action=fmode, iostat=ios) - if (ios /= 0) then - write(logf,'(A,A,A,I6)') "Problem opening", & - fname(1:len_trim(fname)), " ios: ", ios - stop - endif - endif - - open_file = iunit - - end function open_file - - !:.........................................................................: - - subroutine check(status) - ! - ! DESCRIPTION: - ! Checks status of netcdf operations - - ! ARGUMENTS: - integer, intent (in) :: status ! return status code from a netcdf procedure - - if (status /= nf90_noerr) then - write(logf,*) trim(nf90_strerror(status)) - stop - end if - - end subroutine check - - !:.........................................................................: - - subroutine read_patch_data(file, num_pft, canopy_area, elai, esai, nrad) - ! - ! DESCRIPTION: - ! Reads and return patch data - ! - - ! ARGUMENTS: - character(len=MAX_PATH), intent(in) :: file ! patch file name - integer, intent(in) :: num_pft ! number of PFTs - real(r8), allocatable, intent(out) :: canopy_area(:,:,:) ! canopy area profile - real(r8), allocatable, intent(out) :: elai(:,:,:) ! exposed lai profile - real(r8), allocatable, intent(out) :: esai(:,:,:) ! exposed sai profile - integer, allocatable, intent(out) :: nrad(:,:) ! number of exposed leaf layers - - ! LOCALS: - integer :: ncid ! netcdf file unit number - - ! open file - call check(nf90_open(trim(file), 0, ncid)) - - ! read in data - call get_var(ncid, 'can_area', canopy_area) - call get_var(ncid, 'elai', elai) - call get_var(ncid, 'esai', esai) - call get_var(ncid, 'nrad', nrad) - - ! close file - call check(nf90_close(ncid)) - - end subroutine read_patch_data - - !:.........................................................................: - - subroutine get_dims(ncid, varID, dim_lens) - ! - ! DESCRIPTION: - ! Get dimensions for a netcdf variable - ! - - ! ARGUMENTS - integer, intent(in) :: ncid ! netcdf file unit ID - integer, intent(in) :: varID ! variable ID - integer, allocatable, intent(out) :: dim_lens(:) ! dimension lengths - - ! LOCALS: - integer :: numDims ! number of dimensions - integer, allocatable :: dimIDs(:) ! dimension IDs - integer :: i ! looping index - - ! find dimensions of data - call check(nf90_inquire_variable(ncid, varID, ndims=numDims)) - - ! allocate data to grab dimension information - allocate(dim_lens(numDims)) - allocate(dimIDs(numDims)) - - ! get dimIDs - call check(nf90_inquire_variable(ncid, varID, dimids=dimIDs)) - - ! grab these dimensions - do i = 1, numDims - call check(nf90_inquire_dimension(ncid, dimIDs(i), len=dim_lens(i))) - end do - - end subroutine get_dims - - !:.........................................................................: - - subroutine get_var1D_real(ncid, var_name, data) - ! - ! DESCRIPTION: - ! Read in variables for 1D real data - ! - - ! ARGUMENTS: - integer, intent(in) :: ncid ! netcdf file unit ID - character(len=*), intent(in) :: var_name ! variable name - real(r8), allocatable, intent(out) :: data(:) ! data values - - ! LOCALS: - integer :: varID ! variable ID - integer, allocatable :: dim_lens(:) ! dimension lengths - - ! find variable ID first - call check(nf90_inq_varid(ncid, var_name, varID)) - - ! get dimensions of data - call get_dims(ncid, varID, dim_lens) - - ! read data - allocate(data(dim_lens(1))) - call check(nf90_get_var(ncid, varID, data)) - - end subroutine get_var1D_real - - !:.........................................................................: - - subroutine get_var1D_int(ncid, var_name, data) - ! - ! DESCRIPTION: - ! Read in variables for 1D integer data - ! - - ! ARGUMENTS: - integer, intent(in) :: ncid ! netcdf file unit ID - character(len=*), intent(in) :: var_name ! variable name - integer, allocatable, intent(out) :: data(:) ! data values - - ! LOCALS: - integer :: varID ! variable ID - integer, allocatable :: dim_lens(:) ! dimension lengths - - ! find variable ID first - call check(nf90_inq_varid(ncid, var_name, varID)) - - ! get dimensions of data - call get_dims(ncid, varID, dim_lens) - - ! read data - allocate(data(dim_lens(1))) - call check(nf90_get_var(ncid, varID, data)) - - end subroutine get_var1D_int - - !:.........................................................................: - - subroutine get_var2D_real(ncid, var_name, data) - ! - ! DESCRIPTION: - ! Read in variables for 2D real data - ! - - ! ARGUMENTS: - integer, intent(in) :: ncid ! netcdf file unit ID - character(len=*), intent(in) :: var_name ! variable name - real(r8), allocatable, intent(out) :: data(:,:) ! data values - - ! LOCALS: - integer :: varID ! variable ID - integer, allocatable :: dim_lens(:) ! dimension lengths - - ! find variable ID first - call check(nf90_inq_varid(ncid, var_name, varID)) - - ! get dimensions of data - call get_dims(ncid, varID, dim_lens) - - ! read data - allocate(data(dim_lens(1), dim_lens(2))) - call check(nf90_get_var(ncid, varID, data)) - - end subroutine get_var2D_real - - !:.........................................................................: - - subroutine get_var2D_int(ncid, var_name, data) - ! - ! DESCRIPTION: - ! Read in variables for 2D integer data - ! - - ! ARGUMENTS: - integer, intent(in) :: ncid ! netcdf file unit ID - character(len=*), intent(in) :: var_name ! variable name - integer, allocatable, intent(out) :: data(:,:) ! data values - - ! LOCALS: - integer :: varID ! variable ID - integer, allocatable :: dim_lens(:) ! dimension lengths - - ! find variable ID first - call check(nf90_inq_varid(ncid, var_name, varID)) - - ! get dimensions of data - call get_dims(ncid, varID, dim_lens) - - ! read data - allocate(data(dim_lens(1), dim_lens(2))) - call check(nf90_get_var(ncid, varID, data)) - - end subroutine get_var2D_int - - !:.........................................................................: - - subroutine get_var3D_real(ncid, var_name, data) - ! - ! DESCRIPTION: - ! Read in variables for 3D real data - ! - - ! ARGUMENTS: - integer, intent(in) :: ncid ! netcdf file unit ID - character(len=*), intent(in) :: var_name ! variable name - real(r8), allocatable, intent(out) :: data(:,:,:) ! data values - - ! LOCALS: - integer :: varID ! variable ID - integer, allocatable :: dim_lens(:) ! dimension lengths - - ! find variable ID first - call check(nf90_inq_varid(ncid, var_name, varID)) - - ! get dimensions of data - call get_dims(ncid, varID, dim_lens) - - ! read data - allocate(data(dim_lens(1), dim_lens(2), dim_lens(3))) - call check(nf90_get_var(ncid, varID, data)) - - end subroutine get_var3D_real - - !:.........................................................................: - - subroutine get_var3D_int(ncid, var_name, data) - ! - ! DESCRIPTION: - ! Read in variables for 3D integer data - ! - - ! ARGUMENTS: - integer, intent(in) :: ncid ! netcdf file unit ID - character(len=*), intent(in) :: var_name ! variable name - integer, allocatable, intent(out) :: data(:,:,:) ! data values - - ! LOCALS: - integer :: varID ! variable ID - integer, allocatable :: dim_lens(:) ! dimension lengths - - ! find variable ID first - call check(nf90_inq_varid(ncid, var_name, varID)) - - ! get dimensions of data - call get_dims(ncid, varID, dim_lens) - - ! read data - allocate(data(dim_lens(1), dim_lens(2), dim_lens(3))) - call check(nf90_get_var(ncid, varID, data)) - - end subroutine get_var3D_int - - !:.........................................................................: - - ! subroutine write_radiation_data(file, kdir, declin) - ! ! - ! ! DESCRIPTION: - ! ! Opens the file filename if it can, returns a unit number for it. - ! ! The first time the function is called, it returns BASE_UNIT - ! ! - - ! ! ARGUMENTS: - ! character(len=MAX_PATH), intent(in) :: file ! output file name - ! real(r8), intent(in) :: kdir(num_pft,48) ! direct beam extinction coefficient - ! real(r8), intent(in) :: declin(48) - - ! ! LOCALS: - ! integer :: ncid - ! integer :: pft_dimid, time_dimid - ! integer :: kdir_id, declin_id - ! integer :: dimids(2) - - ! ! Create the netCDF file. The nf90_clobber parameter tells netCDF to - ! ! overwrite this file, if it already exists. - ! call check(nf90_create(trim(file), NF90_CLOBBER, ncid)) - - ! ! define dimensions - ! call check(nf90_def_dim(ncid, "pft", num_pft, pft_dimid)) - ! call check(nf90_def_dim(ncid, "time", 48, time_dimid)) - - ! ! define the variables - ! dimids = (/ pft_dimid, time_dimid/) - ! call check(nf90_def_var(ncid, "kdir", NF90_REAL8, dimids, kdir_id)) - ! call check(nf90_def_var(ncid, "declin", NF90_REAL8, time_dimid, declin_id)) - - ! ! end define mode - ! call check(nf90_enddef(ncid)) - - ! ! write to file. - ! call check(nf90_put_var(ncid, kdir_id, kdir)) - ! call check(nf90_put_var(ncid, declin_id, declin)) - - ! ! close the file. - ! call check(nf90_close(ncid)) - - ! end subroutine write_radiation_data - -end module FatesUnitTestIOMod \ No newline at end of file diff --git a/unit_test_shr/FatesUnitTestOrbitalMod.F90 b/unit_test_shr/FatesUnitTestOrbitalMod.F90 deleted file mode 100644 index 843bf1e217..0000000000 --- a/unit_test_shr/FatesUnitTestOrbitalMod.F90 +++ /dev/null @@ -1,581 +0,0 @@ -module FatesUnitTestOrbitalMod - ! - ! DESCRIPTION: - ! Helper procedures for getting orbital values - ! Copied from shr_orb_mod from https://github.com/ESCOMP/CESM_share - ! - ! - - use FatesUnitTestIOMod - - implicit none - - integer, parameter :: SHR_KIND_R8 = selected_real_kind(12) ! 8 byte real - integer, parameter :: SHR_KIND_IN = kind(1) ! native integer - real(SHR_KIND_R8), parameter :: pi = 3.14159265358979323846_SHR_KIND_R8 - real(SHR_KIND_R8), parameter :: SHR_ORB_ECCEN_MIN = 0.0_SHR_KIND_R8 ! min value for eccen - real(SHR_KIND_R8), parameter :: SHR_ORB_ECCEN_MAX = 0.1_SHR_KIND_R8 ! max value for eccen - real(SHR_KIND_R8), parameter :: SHR_ORB_OBLIQ_MIN = -90.0_SHR_KIND_R8 ! min value for obliq - real(SHR_KIND_R8), parameter :: SHR_ORB_OBLIQ_MAX = +90.0_SHR_KIND_R8 ! max value for obliq - real(SHR_KIND_R8), parameter :: SHR_ORB_MVELP_MIN = 0.0_SHR_KIND_R8 ! min value for mvelp - real(SHR_KIND_R8), parameter :: SHR_ORB_MVELP_MAX = 360.0_SHR_KIND_R8 ! max value for mvelp - integer(SHR_KIND_IN), parameter :: SHR_ORB_UNDEF_INT = 2000000000 ! undefined int - real(SHR_KIND_R8), parameter :: SHR_ORB_UNDEF_REAL = 1.e36_SHR_KIND_R8 ! undefined real - - contains - - subroutine get_orbital_vals(iyear_AD, s_logunit, eccen, mvelp, obliqr, & - lambm0, mvelpp) - ! - ! Gets orbital values for a specific day - ! - - ! Data dictionary: calling arguments - integer(SHR_KIND_IN), intent(in) :: iyear_AD ! Year to calculate orbit for - integer, intent(in) :: s_logunit ! log file unit number - real(SHR_KIND_R8), intent(out) :: eccen ! orbital eccentricity - real(SHR_KIND_R8), intent(out) :: mvelp ! moving vernal equinox long - real(SHR_KIND_R8), intent(out) :: obliqr ! Earths obliquity in rad - real(SHR_KIND_R8), intent(out) :: lambm0 ! Mean long of perihelion at vernal equinox (radians) - real(SHR_KIND_R8), intent(out) :: mvelpp ! moving vernal equinox long of perihelion plus pi (rad) - - real(SHR_KIND_R8) :: obliq ! obliquity in degrees - - obliq = SHR_ORB_UNDEF_REAL - eccen = SHR_ORB_UNDEF_REAL - mvelp = SHR_ORB_UNDEF_REAL - - call shr_orb_params(iyear_AD, eccen, obliq, mvelp, obliqr, lambm0, & - mvelpp, s_logunit) - - end subroutine get_orbital_vals - - !:.........................................................................: - - subroutine shr_orb_params(iyear_AD, eccen, obliq, mvelp, & - obliqr, lambm0, mvelpp, s_logunit) - - !--------------------------------------------------------------------------- - ! - ! Calculate earths orbital parameters using Dave Threshers formula which - ! came from Berger, Andre. 1978 "A Simple Algorithm to Compute Long-Term - ! Variations of Daily Insolation". Contribution 18, Institute of Astronomy - ! and Geophysics, Universite Catholique de Louvain, Louvain-la-Neuve, Belgium - ! - !------------------------------Code history--------------------------------- - ! - ! Original Author: Erik Kluzek - ! Date: Oct/97 - ! - !--------------------------------------------------------------------------- - - !----------------------------- Arguments ----------------------------------- - integer(SHR_KIND_IN), intent(in) :: iyear_AD ! Year to calculate orbit for - real(SHR_KIND_R8), intent(inout) :: eccen ! orbital eccentricity - real(SHR_KIND_R8), intent(inout) :: obliq ! obliquity in degrees - real(SHR_KIND_R8), intent(inout) :: mvelp ! moving vernal equinox long - real(SHR_KIND_R8), intent(out) :: obliqr ! Earths obliquity in rad - real(SHR_KIND_R8), intent(out) :: lambm0 ! Mean long of perihelion at vernal equinox (radians) - real(SHR_KIND_R8), intent(out) :: mvelpp ! moving vernal equinox long of perihelion plus pi (rad) - integer, intent(in) :: s_logunit ! log file unit number - - !------------------------------ Parameters ---------------------------------- - integer(SHR_KIND_IN), parameter :: poblen = 47 ! # of elements in series wrt obliquity - integer(SHR_KIND_IN), parameter :: pecclen = 19 ! # of elements in series wrt eccentricity - integer(SHR_KIND_IN), parameter :: pmvelen = 78 ! # of elements in series wrt vernal equinox - real(SHR_KIND_R8), parameter :: psecdeg = 1.0_SHR_KIND_R8/3600.0_SHR_KIND_R8 ! arc sec to deg conversion - - real(SHR_KIND_R8) :: degrad = pi/180._SHR_KIND_R8 ! degree to radian conversion factor - real(SHR_KIND_R8) :: yb4_1950AD ! number of years before 1950 AD - - ! Cosine series data for computation of obliquity: amplitude (arc seconds), - ! rate (arc seconds/year), phase (degrees). - - real (SHR_KIND_R8), parameter :: obamp(poblen) = & ! amplitudes for obliquity cos series - & (/ -2462.2214466_SHR_KIND_R8, -857.3232075_SHR_KIND_R8, -629.3231835_SHR_KIND_R8, & - & -414.2804924_SHR_KIND_R8, -311.7632587_SHR_KIND_R8, 308.9408604_SHR_KIND_R8, & - & -162.5533601_SHR_KIND_R8, -116.1077911_SHR_KIND_R8, 101.1189923_SHR_KIND_R8, & - & -67.6856209_SHR_KIND_R8, 24.9079067_SHR_KIND_R8, 22.5811241_SHR_KIND_R8, & - & -21.1648355_SHR_KIND_R8, -15.6549876_SHR_KIND_R8, 15.3936813_SHR_KIND_R8, & - & 14.6660938_SHR_KIND_R8, -11.7273029_SHR_KIND_R8, 10.2742696_SHR_KIND_R8, & - & 6.4914588_SHR_KIND_R8, 5.8539148_SHR_KIND_R8, -5.4872205_SHR_KIND_R8, & - & -5.4290191_SHR_KIND_R8, 5.1609570_SHR_KIND_R8, 5.0786314_SHR_KIND_R8, & - & -4.0735782_SHR_KIND_R8, 3.7227167_SHR_KIND_R8, 3.3971932_SHR_KIND_R8, & - & -2.8347004_SHR_KIND_R8, -2.6550721_SHR_KIND_R8, -2.5717867_SHR_KIND_R8, & - & -2.4712188_SHR_KIND_R8, 2.4625410_SHR_KIND_R8, 2.2464112_SHR_KIND_R8, & - & -2.0755511_SHR_KIND_R8, -1.9713669_SHR_KIND_R8, -1.8813061_SHR_KIND_R8, & - & -1.8468785_SHR_KIND_R8, 1.8186742_SHR_KIND_R8, 1.7601888_SHR_KIND_R8, & - & -1.5428851_SHR_KIND_R8, 1.4738838_SHR_KIND_R8, -1.4593669_SHR_KIND_R8, & - & 1.4192259_SHR_KIND_R8, -1.1818980_SHR_KIND_R8, 1.1756474_SHR_KIND_R8, & - & -1.1316126_SHR_KIND_R8, 1.0896928_SHR_KIND_R8/) - - real (SHR_KIND_R8), parameter :: obrate(poblen) = & ! rates for obliquity cosine series - & (/ 31.609974_SHR_KIND_R8, 32.620504_SHR_KIND_R8, 24.172203_SHR_KIND_R8, & - & 31.983787_SHR_KIND_R8, 44.828336_SHR_KIND_R8, 30.973257_SHR_KIND_R8, & - & 43.668246_SHR_KIND_R8, 32.246691_SHR_KIND_R8, 30.599444_SHR_KIND_R8, & - & 42.681324_SHR_KIND_R8, 43.836462_SHR_KIND_R8, 47.439436_SHR_KIND_R8, & - & 63.219948_SHR_KIND_R8, 64.230478_SHR_KIND_R8, 1.010530_SHR_KIND_R8, & - & 7.437771_SHR_KIND_R8, 55.782177_SHR_KIND_R8, 0.373813_SHR_KIND_R8, & - & 13.218362_SHR_KIND_R8, 62.583231_SHR_KIND_R8, 63.593761_SHR_KIND_R8, & - & 76.438310_SHR_KIND_R8, 45.815258_SHR_KIND_R8, 8.448301_SHR_KIND_R8, & - & 56.792707_SHR_KIND_R8, 49.747842_SHR_KIND_R8, 12.058272_SHR_KIND_R8, & - & 75.278220_SHR_KIND_R8, 65.241008_SHR_KIND_R8, 64.604291_SHR_KIND_R8, & - & 1.647247_SHR_KIND_R8, 7.811584_SHR_KIND_R8, 12.207832_SHR_KIND_R8, & - & 63.856665_SHR_KIND_R8, 56.155990_SHR_KIND_R8, 77.448840_SHR_KIND_R8, & - & 6.801054_SHR_KIND_R8, 62.209418_SHR_KIND_R8, 20.656133_SHR_KIND_R8, & - & 48.344406_SHR_KIND_R8, 55.145460_SHR_KIND_R8, 69.000539_SHR_KIND_R8, & - & 11.071350_SHR_KIND_R8, 74.291298_SHR_KIND_R8, 11.047742_SHR_KIND_R8, & - & 0.636717_SHR_KIND_R8, 12.844549_SHR_KIND_R8/) - - real (SHR_KIND_R8), parameter :: obphas(poblen) = & ! phases for obliquity cosine series - & (/ 251.9025_SHR_KIND_R8, 280.8325_SHR_KIND_R8, 128.3057_SHR_KIND_R8, & - & 292.7252_SHR_KIND_R8, 15.3747_SHR_KIND_R8, 263.7951_SHR_KIND_R8, & - & 308.4258_SHR_KIND_R8, 240.0099_SHR_KIND_R8, 222.9725_SHR_KIND_R8, & - & 268.7809_SHR_KIND_R8, 316.7998_SHR_KIND_R8, 319.6024_SHR_KIND_R8, & - & 143.8050_SHR_KIND_R8, 172.7351_SHR_KIND_R8, 28.9300_SHR_KIND_R8, & - & 123.5968_SHR_KIND_R8, 20.2082_SHR_KIND_R8, 40.8226_SHR_KIND_R8, & - & 123.4722_SHR_KIND_R8, 155.6977_SHR_KIND_R8, 184.6277_SHR_KIND_R8, & - & 267.2772_SHR_KIND_R8, 55.0196_SHR_KIND_R8, 152.5268_SHR_KIND_R8, & - & 49.1382_SHR_KIND_R8, 204.6609_SHR_KIND_R8, 56.5233_SHR_KIND_R8, & - & 200.3284_SHR_KIND_R8, 201.6651_SHR_KIND_R8, 213.5577_SHR_KIND_R8, & - & 17.0374_SHR_KIND_R8, 164.4194_SHR_KIND_R8, 94.5422_SHR_KIND_R8, & - & 131.9124_SHR_KIND_R8, 61.0309_SHR_KIND_R8, 296.2073_SHR_KIND_R8, & - & 135.4894_SHR_KIND_R8, 114.8750_SHR_KIND_R8, 247.0691_SHR_KIND_R8, & - & 256.6114_SHR_KIND_R8, 32.1008_SHR_KIND_R8, 143.6804_SHR_KIND_R8, & - & 16.8784_SHR_KIND_R8, 160.6835_SHR_KIND_R8, 27.5932_SHR_KIND_R8, & - & 348.1074_SHR_KIND_R8, 82.6496_SHR_KIND_R8/) - - ! Cosine/sine series data for computation of eccentricity and fixed vernal - ! equinox longitude of perihelion (fvelp): amplitude, - ! rate (arc seconds/year), phase (degrees). - - real (SHR_KIND_R8), parameter :: ecamp (pecclen) = & ! ampl for eccen/fvelp cos/sin series - & (/ 0.01860798_SHR_KIND_R8, 0.01627522_SHR_KIND_R8, -0.01300660_SHR_KIND_R8, & - & 0.00988829_SHR_KIND_R8, -0.00336700_SHR_KIND_R8, 0.00333077_SHR_KIND_R8, & - & -0.00235400_SHR_KIND_R8, 0.00140015_SHR_KIND_R8, 0.00100700_SHR_KIND_R8, & - & 0.00085700_SHR_KIND_R8, 0.00064990_SHR_KIND_R8, 0.00059900_SHR_KIND_R8, & - & 0.00037800_SHR_KIND_R8, -0.00033700_SHR_KIND_R8, 0.00027600_SHR_KIND_R8, & - & 0.00018200_SHR_KIND_R8, -0.00017400_SHR_KIND_R8, -0.00012400_SHR_KIND_R8, & - & 0.00001250_SHR_KIND_R8/) - - real (SHR_KIND_R8), parameter :: ecrate(pecclen) = & ! rates for eccen/fvelp cos/sin series - & (/ 4.2072050_SHR_KIND_R8, 7.3460910_SHR_KIND_R8, 17.8572630_SHR_KIND_R8, & - & 17.2205460_SHR_KIND_R8, 16.8467330_SHR_KIND_R8, 5.1990790_SHR_KIND_R8, & - & 18.2310760_SHR_KIND_R8, 26.2167580_SHR_KIND_R8, 6.3591690_SHR_KIND_R8, & - & 16.2100160_SHR_KIND_R8, 3.0651810_SHR_KIND_R8, 16.5838290_SHR_KIND_R8, & - & 18.4939800_SHR_KIND_R8, 6.1909530_SHR_KIND_R8, 18.8677930_SHR_KIND_R8, & - & 17.4255670_SHR_KIND_R8, 6.1860010_SHR_KIND_R8, 18.4174410_SHR_KIND_R8, & - & 0.6678630_SHR_KIND_R8/) - - real (SHR_KIND_R8), parameter :: ecphas(pecclen) = & ! phases for eccen/fvelp cos/sin series - & (/ 28.620089_SHR_KIND_R8, 193.788772_SHR_KIND_R8, 308.307024_SHR_KIND_R8, & - & 320.199637_SHR_KIND_R8, 279.376984_SHR_KIND_R8, 87.195000_SHR_KIND_R8, & - & 349.129677_SHR_KIND_R8, 128.443387_SHR_KIND_R8, 154.143880_SHR_KIND_R8, & - & 291.269597_SHR_KIND_R8, 114.860583_SHR_KIND_R8, 332.092251_SHR_KIND_R8, & - & 296.414411_SHR_KIND_R8, 145.769910_SHR_KIND_R8, 337.237063_SHR_KIND_R8, & - & 152.092288_SHR_KIND_R8, 126.839891_SHR_KIND_R8, 210.667199_SHR_KIND_R8, & - & 72.108838_SHR_KIND_R8/) - - ! Sine series data for computation of moving vernal equinox longitude of - ! perihelion: amplitude (arc seconds), rate (arc sec/year), phase (degrees). - - real (SHR_KIND_R8), parameter :: mvamp (pmvelen) = & ! amplitudes for mvelp sine series - & (/ 7391.0225890_SHR_KIND_R8, 2555.1526947_SHR_KIND_R8, 2022.7629188_SHR_KIND_R8, & - & -1973.6517951_SHR_KIND_R8, 1240.2321818_SHR_KIND_R8, 953.8679112_SHR_KIND_R8, & - & -931.7537108_SHR_KIND_R8, 872.3795383_SHR_KIND_R8, 606.3544732_SHR_KIND_R8, & - & -496.0274038_SHR_KIND_R8, 456.9608039_SHR_KIND_R8, 346.9462320_SHR_KIND_R8, & - & -305.8412902_SHR_KIND_R8, 249.6173246_SHR_KIND_R8, -199.1027200_SHR_KIND_R8, & - & 191.0560889_SHR_KIND_R8, -175.2936572_SHR_KIND_R8, 165.9068833_SHR_KIND_R8, & - & 161.1285917_SHR_KIND_R8, 139.7878093_SHR_KIND_R8, -133.5228399_SHR_KIND_R8, & - & 117.0673811_SHR_KIND_R8, 104.6907281_SHR_KIND_R8, 95.3227476_SHR_KIND_R8, & - & 86.7824524_SHR_KIND_R8, 86.0857729_SHR_KIND_R8, 70.5893698_SHR_KIND_R8, & - & -69.9719343_SHR_KIND_R8, -62.5817473_SHR_KIND_R8, 61.5450059_SHR_KIND_R8, & - & -57.9364011_SHR_KIND_R8, 57.1899832_SHR_KIND_R8, -57.0236109_SHR_KIND_R8, & - & -54.2119253_SHR_KIND_R8, 53.2834147_SHR_KIND_R8, 52.1223575_SHR_KIND_R8, & - & -49.0059908_SHR_KIND_R8, -48.3118757_SHR_KIND_R8, -45.4191685_SHR_KIND_R8, & - & -42.2357920_SHR_KIND_R8, -34.7971099_SHR_KIND_R8, 34.4623613_SHR_KIND_R8, & - & -33.8356643_SHR_KIND_R8, 33.6689362_SHR_KIND_R8, -31.2521586_SHR_KIND_R8, & - & -30.8798701_SHR_KIND_R8, 28.4640769_SHR_KIND_R8, -27.1960802_SHR_KIND_R8, & - & 27.0860736_SHR_KIND_R8, -26.3437456_SHR_KIND_R8, 24.7253740_SHR_KIND_R8, & - & 24.6732126_SHR_KIND_R8, 24.4272733_SHR_KIND_R8, 24.0127327_SHR_KIND_R8, & - & 21.7150294_SHR_KIND_R8, -21.5375347_SHR_KIND_R8, 18.1148363_SHR_KIND_R8, & - & -16.9603104_SHR_KIND_R8, -16.1765215_SHR_KIND_R8, 15.5567653_SHR_KIND_R8, & - & 15.4846529_SHR_KIND_R8, 15.2150632_SHR_KIND_R8, 14.5047426_SHR_KIND_R8, & - & -14.3873316_SHR_KIND_R8, 13.1351419_SHR_KIND_R8, 12.8776311_SHR_KIND_R8, & - & 11.9867234_SHR_KIND_R8, 11.9385578_SHR_KIND_R8, 11.7030822_SHR_KIND_R8, & - & 11.6018181_SHR_KIND_R8, -11.2617293_SHR_KIND_R8, -10.4664199_SHR_KIND_R8, & - & 10.4333970_SHR_KIND_R8, -10.2377466_SHR_KIND_R8, 10.1934446_SHR_KIND_R8, & - & -10.1280191_SHR_KIND_R8, 10.0289441_SHR_KIND_R8, -10.0034259_SHR_KIND_R8/) - - real (SHR_KIND_R8), parameter :: mvrate(pmvelen) = & ! rates for mvelp sine series - & (/ 31.609974_SHR_KIND_R8, 32.620504_SHR_KIND_R8, 24.172203_SHR_KIND_R8, & - & 0.636717_SHR_KIND_R8, 31.983787_SHR_KIND_R8, 3.138886_SHR_KIND_R8, & - & 30.973257_SHR_KIND_R8, 44.828336_SHR_KIND_R8, 0.991874_SHR_KIND_R8, & - & 0.373813_SHR_KIND_R8, 43.668246_SHR_KIND_R8, 32.246691_SHR_KIND_R8, & - & 30.599444_SHR_KIND_R8, 2.147012_SHR_KIND_R8, 10.511172_SHR_KIND_R8, & - & 42.681324_SHR_KIND_R8, 13.650058_SHR_KIND_R8, 0.986922_SHR_KIND_R8, & - & 9.874455_SHR_KIND_R8, 13.013341_SHR_KIND_R8, 0.262904_SHR_KIND_R8, & - & 0.004952_SHR_KIND_R8, 1.142024_SHR_KIND_R8, 63.219948_SHR_KIND_R8, & - & 0.205021_SHR_KIND_R8, 2.151964_SHR_KIND_R8, 64.230478_SHR_KIND_R8, & - & 43.836462_SHR_KIND_R8, 47.439436_SHR_KIND_R8, 1.384343_SHR_KIND_R8, & - & 7.437771_SHR_KIND_R8, 18.829299_SHR_KIND_R8, 9.500642_SHR_KIND_R8, & - & 0.431696_SHR_KIND_R8, 1.160090_SHR_KIND_R8, 55.782177_SHR_KIND_R8, & - & 12.639528_SHR_KIND_R8, 1.155138_SHR_KIND_R8, 0.168216_SHR_KIND_R8, & - & 1.647247_SHR_KIND_R8, 10.884985_SHR_KIND_R8, 5.610937_SHR_KIND_R8, & - & 12.658184_SHR_KIND_R8, 1.010530_SHR_KIND_R8, 1.983748_SHR_KIND_R8, & - & 14.023871_SHR_KIND_R8, 0.560178_SHR_KIND_R8, 1.273434_SHR_KIND_R8, & - & 12.021467_SHR_KIND_R8, 62.583231_SHR_KIND_R8, 63.593761_SHR_KIND_R8, & - & 76.438310_SHR_KIND_R8, 4.280910_SHR_KIND_R8, 13.218362_SHR_KIND_R8, & - & 17.818769_SHR_KIND_R8, 8.359495_SHR_KIND_R8, 56.792707_SHR_KIND_R8, & - & 8.448301_SHR_KIND_R8, 1.978796_SHR_KIND_R8, 8.863925_SHR_KIND_R8, & - & 0.186365_SHR_KIND_R8, 8.996212_SHR_KIND_R8, 6.771027_SHR_KIND_R8, & - & 45.815258_SHR_KIND_R8, 12.002811_SHR_KIND_R8, 75.278220_SHR_KIND_R8, & - & 65.241008_SHR_KIND_R8, 18.870667_SHR_KIND_R8, 22.009553_SHR_KIND_R8, & - & 64.604291_SHR_KIND_R8, 11.498094_SHR_KIND_R8, 0.578834_SHR_KIND_R8, & - & 9.237738_SHR_KIND_R8, 49.747842_SHR_KIND_R8, 2.147012_SHR_KIND_R8, & - & 1.196895_SHR_KIND_R8, 2.133898_SHR_KIND_R8, 0.173168_SHR_KIND_R8/) - - real (SHR_KIND_R8), parameter :: mvphas(pmvelen) = & ! phases for mvelp sine series - & (/ 251.9025_SHR_KIND_R8, 280.8325_SHR_KIND_R8, 128.3057_SHR_KIND_R8, & - & 348.1074_SHR_KIND_R8, 292.7252_SHR_KIND_R8, 165.1686_SHR_KIND_R8, & - & 263.7951_SHR_KIND_R8, 15.3747_SHR_KIND_R8, 58.5749_SHR_KIND_R8, & - & 40.8226_SHR_KIND_R8, 308.4258_SHR_KIND_R8, 240.0099_SHR_KIND_R8, & - & 222.9725_SHR_KIND_R8, 106.5937_SHR_KIND_R8, 114.5182_SHR_KIND_R8, & - & 268.7809_SHR_KIND_R8, 279.6869_SHR_KIND_R8, 39.6448_SHR_KIND_R8, & - & 126.4108_SHR_KIND_R8, 291.5795_SHR_KIND_R8, 307.2848_SHR_KIND_R8, & - & 18.9300_SHR_KIND_R8, 273.7596_SHR_KIND_R8, 143.8050_SHR_KIND_R8, & - & 191.8927_SHR_KIND_R8, 125.5237_SHR_KIND_R8, 172.7351_SHR_KIND_R8, & - & 316.7998_SHR_KIND_R8, 319.6024_SHR_KIND_R8, 69.7526_SHR_KIND_R8, & - & 123.5968_SHR_KIND_R8, 217.6432_SHR_KIND_R8, 85.5882_SHR_KIND_R8, & - & 156.2147_SHR_KIND_R8, 66.9489_SHR_KIND_R8, 20.2082_SHR_KIND_R8, & - & 250.7568_SHR_KIND_R8, 48.0188_SHR_KIND_R8, 8.3739_SHR_KIND_R8, & - & 17.0374_SHR_KIND_R8, 155.3409_SHR_KIND_R8, 94.1709_SHR_KIND_R8, & - & 221.1120_SHR_KIND_R8, 28.9300_SHR_KIND_R8, 117.1498_SHR_KIND_R8, & - & 320.5095_SHR_KIND_R8, 262.3602_SHR_KIND_R8, 336.2148_SHR_KIND_R8, & - & 233.0046_SHR_KIND_R8, 155.6977_SHR_KIND_R8, 184.6277_SHR_KIND_R8, & - & 267.2772_SHR_KIND_R8, 78.9281_SHR_KIND_R8, 123.4722_SHR_KIND_R8, & - & 188.7132_SHR_KIND_R8, 180.1364_SHR_KIND_R8, 49.1382_SHR_KIND_R8, & - & 152.5268_SHR_KIND_R8, 98.2198_SHR_KIND_R8, 97.4808_SHR_KIND_R8, & - & 221.5376_SHR_KIND_R8, 168.2438_SHR_KIND_R8, 161.1199_SHR_KIND_R8, & - & 55.0196_SHR_KIND_R8, 262.6495_SHR_KIND_R8, 200.3284_SHR_KIND_R8, & - & 201.6651_SHR_KIND_R8, 294.6547_SHR_KIND_R8, 99.8233_SHR_KIND_R8, & - & 213.5577_SHR_KIND_R8, 154.1631_SHR_KIND_R8, 232.7153_SHR_KIND_R8, & - & 138.3034_SHR_KIND_R8, 204.6609_SHR_KIND_R8, 106.5938_SHR_KIND_R8, & - & 250.4676_SHR_KIND_R8, 332.3345_SHR_KIND_R8, 27.3039_SHR_KIND_R8/) - - !---------------------------Local variables---------------------------------- - integer(SHR_KIND_IN) :: i ! Index for series summations - real (SHR_KIND_R8) :: obsum ! Obliquity series summation - real (SHR_KIND_R8) :: cossum ! Cos series summation for eccentricity/fvelp - real (SHR_KIND_R8) :: sinsum ! Sin series summation for eccentricity/fvelp - real (SHR_KIND_R8) :: fvelp ! Fixed vernal equinox long of perihelion - real (SHR_KIND_R8) :: mvsum ! mvelp series summation - real (SHR_KIND_R8) :: beta ! Intermediate argument for lambm0 - real (SHR_KIND_R8) :: years ! Years to time of interest ( pos <=> future) - real (SHR_KIND_R8) :: eccen2 ! eccentricity squared - real (SHR_KIND_R8) :: eccen3 ! eccentricity cubed - - !-------------------------- Formats ----------------------------------------- - character(len=*),parameter :: F00 = "('(shr_orb_params) ',4a)" - character(len=*),parameter :: F01 = "('(shr_orb_params) ',a,i9)" - character(len=*),parameter :: F02 = "('(shr_orb_params) ',a,f6.3)" - character(len=*),parameter :: F03 = "('(shr_orb_params) ',a,es14.6)" - - !---------------------------------------------------------------------------- - ! radinp and algorithms below will need a degree to radian conversion factor - - ! Check for flag to use input orbit parameters - - IF ( iyear_AD == SHR_ORB_UNDEF_INT ) THEN - - ! Check input obliq, eccen, and mvelp to ensure reasonable - - if( obliq == SHR_ORB_UNDEF_REAL )then - write(s_logunit,F00) ' Have to specify orbital parameters:' - write(s_logunit,F00) 'Either set: iyear_AD, OR [obliq, eccen, and mvelp]:' - write(s_logunit,F00) 'iyear_AD is the year to simulate orbit for (ie. 1950): ' - write(s_logunit,F00) 'obliq, eccen, mvelp specify the orbit directly:' - write(s_logunit,F00) 'The AMIP II settings (for a 1995 orbit) are: ' - write(s_logunit,F00) ' obliq = 23.4441' - write(s_logunit,F00) ' eccen = 0.016715' - write(s_logunit,F00) ' mvelp = 102.7' - stop "Stopped" - end if - if( (obliq < SHR_ORB_OBLIQ_MIN).or.(obliq > SHR_ORB_OBLIQ_MAX) ) then - write(s_logunit,F03) 'Input obliquity unreasonable: ', obliq - stop "Stopped" - end if - if( (eccen < SHR_ORB_ECCEN_MIN).or.(eccen > SHR_ORB_ECCEN_MAX) ) then - write(s_logunit,F03) 'Input eccentricity unreasonable: ', eccen - stop "Stopped" - end if - if( (mvelp < SHR_ORB_MVELP_MIN).or.(mvelp > SHR_ORB_MVELP_MAX) ) then - write(s_logunit,F03) 'Input mvelp unreasonable: ' , mvelp - stop "Stopped" - end if - eccen2 = eccen*eccen - eccen3 = eccen2*eccen - - ELSE ! Otherwise calculate based on years before present - - yb4_1950AD = 1950.0_SHR_KIND_R8 - real(iyear_AD,SHR_KIND_R8) - if ( abs(yb4_1950AD) .gt. 1000000.0_SHR_KIND_R8 )then - write(s_logunit,F00) 'orbit only valid for years+-1000000' - write(s_logunit,F00) 'Relative to 1950 AD' - write(s_logunit,F03) '# of years before 1950: ',yb4_1950AD - write(s_logunit,F01) 'Year to simulate was : ',iyear_AD - stop "Stopped" - end if - - ! The following calculates the earths obliquity, orbital eccentricity - ! (and various powers of it) and vernal equinox mean longitude of - ! perihelion for years in the past (future = negative of years past), - ! using constants (see parameter section) given in the program of: - ! - ! Berger, Andre. 1978 A Simple Algorithm to Compute Long-Term Variations - ! of Daily Insolation. Contribution 18, Institute of Astronomy and - ! Geophysics, Universite Catholique de Louvain, Louvain-la-Neuve, Belgium. - ! - ! and formulas given in the paper (where less precise constants are also - ! given): - ! - ! Berger, Andre. 1978. Long-Term Variations of Daily Insolation and - ! Quaternary Climatic Changes. J. of the Atmo. Sci. 35:2362-2367 - ! - ! The algorithm is valid only to 1,000,000 years past or hence. - ! For a solution valid to 5-10 million years past see the above author. - ! Algorithm below is better for years closer to present than is the - ! 5-10 million year solution. - ! - ! Years to time of interest must be negative of years before present - ! (1950) in formulas that follow. - - years = - yb4_1950AD - - ! In the summations below, cosine or sine arguments, which end up in - ! degrees, must be converted to radians via multiplication by degrad. - ! - ! Summation of cosine series for obliquity (epsilon in Berger 1978) in - ! degrees. Convert the amplitudes and rates, which are in arc secs, into - ! degrees via multiplication by psecdeg (arc seconds to degrees conversion - ! factor). For obliq, first term is Berger 1978 epsilon star; second - ! term is series summation in degrees. - - obsum = 0.0_SHR_KIND_R8 - do i = 1, poblen - obsum = obsum + obamp(i)*psecdeg*cos((obrate(i)*psecdeg*years + & - & obphas(i))*degrad) - end do - obliq = 23.320556_SHR_KIND_R8 + obsum - - ! Summation of cosine and sine series for computation of eccentricity - ! (eccen; e in Berger 1978) and fixed vernal equinox longitude of - ! perihelion (fvelp; pi in Berger 1978), which is used for computation - ! of moving vernal equinox longitude of perihelion. Convert the rates, - ! which are in arc seconds, into degrees via multiplication by psecdeg. - - cossum = 0.0_SHR_KIND_R8 - do i = 1, pecclen - cossum = cossum+ecamp(i)*cos((ecrate(i)*psecdeg*years+ecphas(i))*degrad) - end do - - sinsum = 0.0_SHR_KIND_R8 - do i = 1, pecclen - sinsum = sinsum+ecamp(i)*sin((ecrate(i)*psecdeg*years+ecphas(i))*degrad) - end do - - ! Use summations to calculate eccentricity - - eccen2 = cossum*cossum + sinsum*sinsum - eccen = sqrt(eccen2) - eccen3 = eccen2*eccen - - ! A series of cases for fvelp, which is in radians. - if (abs(cossum) .le. 1.0E-8_SHR_KIND_R8) then - if (sinsum .eq. 0.0_SHR_KIND_R8) then - fvelp = 0.0_SHR_KIND_R8 - else if (sinsum .lt. 0.0_SHR_KIND_R8) then - fvelp = 1.5_SHR_KIND_R8*pi - else if (sinsum .gt. 0.0_SHR_KIND_R8) then - fvelp = .5_SHR_KIND_R8*pi - endif - else if (cossum .lt. 0.0_SHR_KIND_R8) then - fvelp = atan(sinsum/cossum) + pi - else ! cossum > 1.0e-8 - if (sinsum .lt. 0.0_SHR_KIND_R8) then - fvelp = atan(sinsum/cossum) + 2.0_SHR_KIND_R8*pi - else - fvelp = atan(sinsum/cossum) - endif - endif - - ! Summation of sin series for computation of moving vernal equinox long - ! of perihelion (mvelp; omega bar in Berger 1978) in degrees. For mvelp, - ! first term is fvelp in degrees; second term is Berger 1978 psi bar - ! times years and in degrees; third term is Berger 1978 zeta; fourth - ! term is series summation in degrees. Convert the amplitudes and rates, - ! which are in arc seconds, into degrees via multiplication by psecdeg. - ! Series summation plus second and third terms constitute Berger 1978 - ! psi, which is the general precession. - - mvsum = 0.0_SHR_KIND_R8 - do i = 1, pmvelen - mvsum = mvsum + mvamp(i)*psecdeg*sin((mvrate(i)*psecdeg*years + & - & mvphas(i))*degrad) - end do - mvelp = fvelp/degrad + 50.439273_SHR_KIND_R8*psecdeg*years + 3.392506_SHR_KIND_R8 + mvsum - - ! Cases to make sure mvelp is between 0 and 360. - - do while (mvelp .lt. 0.0_SHR_KIND_R8) - mvelp = mvelp + 360.0_SHR_KIND_R8 - end do - do while (mvelp .ge. 360.0_SHR_KIND_R8) - mvelp = mvelp - 360.0_SHR_KIND_R8 - end do - - END IF ! end of test on whether to calculate or use input orbital params - - ! Orbit needs the obliquity in radians - - obliqr = obliq*degrad - - ! 180 degrees must be added to mvelp since observations are made from the - ! earth and the sun is considered (wrongly for the algorithm) to go around - ! the earth. For a more graphic explanation see Appendix B in: - ! - ! A. Berger, M. Loutre and C. Tricot. 1993. Insolation and Earth Orbital - ! Periods. J. of Geophysical Research 98:10,341-10,362. - ! - ! Additionally, orbit will need this value in radians. So mvelp becomes - ! mvelpp (mvelp plus pi) - - mvelpp = (mvelp + 180._SHR_KIND_R8)*degrad - - ! Set up an argument used several times in lambm0 calculation ahead. - - beta = sqrt(1._SHR_KIND_R8 - eccen2) - - ! The mean longitude at the vernal equinox (lambda m nought in Berger - ! 1978; in radians) is calculated from the following formula given in - ! Berger 1978. At the vernal equinox the true longitude (lambda in Berger - ! 1978) is 0. - - lambm0 = 2._SHR_KIND_R8*((.5_SHR_KIND_R8*eccen + .125_SHR_KIND_R8*eccen3)*(1._SHR_KIND_R8 + beta)*sin(mvelpp) & - & - .250_SHR_KIND_R8*eccen2*(.5_SHR_KIND_R8 + beta)*sin(2._SHR_KIND_R8*mvelpp) & - & + .125_SHR_KIND_R8*eccen3*(1._SHR_KIND_R8/3._SHR_KIND_R8 + beta)*sin(3._SHR_KIND_R8*mvelpp)) - - end subroutine shr_orb_params - - !:..........................................................................: - - subroutine shr_orb_decl(calday, eccen, mvelpp, lambm0, obliqr, delta, eccf) - - !------------------------------------------------------------------------- - ! - ! Compute earth/orbit parameters using formula suggested by - ! Duane Thresher. - ! - !---------------------------Code history---------------------------------- - ! - ! Original version: Erik Kluzek - ! Date: Oct/1997 - ! - !------------------------------------------------------------------------- - - !------------------------------Arguments-------------------------------- - real(SHR_KIND_R8), intent(in) :: calday ! Calendar day, including fraction - real(SHR_KIND_R8), intent(in) :: eccen ! Eccentricity - real(SHR_KIND_R8), intent(in) :: obliqr ! Earths obliquity in radians - real(SHR_KIND_R8), intent(in) :: lambm0 ! Mean long of perihelion at the vernal equinox (radians) - real(SHR_KIND_R8), intent(in) :: mvelpp ! moving vernal equinox longitude of perihelion plus pi (radians) - real(SHR_KIND_R8), intent(out) :: delta ! Solar declination angle in rad - real(SHR_KIND_R8), intent(out) :: eccf ! Earth-sun distance factor (ie. (1/r)**2) - - !---------------------------Local variables----------------------------- - real(SHR_KIND_R8), parameter :: dayspy = 365.0_SHR_KIND_R8 ! days per year - real(SHR_KIND_R8), parameter :: ve = 80.5_SHR_KIND_R8 ! Calday of vernal equinox assumes Jan 1 = calday 1 - - real(SHR_KIND_R8) :: lambm ! Lambda m, mean long of perihelion (rad) - real(SHR_KIND_R8) :: lmm ! Intermediate argument involving lambm - real(SHR_KIND_R8) :: lamb ! Lambda, the earths long of perihelion - real(SHR_KIND_R8) :: invrho ! Inverse normalized sun/earth distance - real(SHR_KIND_R8) :: sinl ! Sine of lmm - - ! Compute eccentricity factor and solar declination using - ! day value where a round day (such as 213.0) refers to 0z at - ! Greenwich longitude. - ! - ! Use formulas from Berger, Andre 1978: Long-Term Variations of Daily - ! Insolation and Quaternary Climatic Changes. J. of the Atmo. Sci. - ! 35:2362-2367. - ! - ! To get the earths true longitude (position in orbit; lambda in Berger - ! 1978) which is necessary to find the eccentricity factor and declination, - ! must first calculate the mean longitude (lambda m in Berger 1978) at - ! the present day. This is done by adding to lambm0 (the mean longitude - ! at the vernal equinox, set as March 21 at noon, when lambda=0; in radians) - ! an increment (delta lambda m in Berger 1978) that is the number of - ! days past or before (a negative increment) the vernal equinox divided by - ! the days in a model year times the 2*pi radians in a complete orbit. - - lambm = lambm0 + (calday - ve)*2._SHR_KIND_R8*pi/dayspy - lmm = lambm - mvelpp - - ! The earths true longitude, in radians, is then found from - ! the formula in Berger 1978: - - sinl = sin(lmm) - lamb = lambm + eccen*(2._SHR_KIND_R8*sinl + & - eccen*(1.25_SHR_KIND_R8*sin(2._SHR_KIND_R8*lmm) + & - eccen*((13.0_SHR_KIND_R8/12.0_SHR_KIND_R8)* & - sin(3._SHR_KIND_R8*lmm) - 0.25_SHR_KIND_R8*sinl))) - - ! Using the obliquity, eccentricity, moving vernal equinox longitude of - ! perihelion (plus), and earths true longitude, the declination (delta) - ! and the normalized earth/sun distance (rho in Berger 1978; actually inverse - ! rho will be used), and thus the eccentricity factor (eccf), can be - ! calculated from formulas given in Berger 1978. - - invrho = (1._SHR_KIND_R8 + eccen*cos(lamb - mvelpp))/ & - (1._SHR_KIND_R8 - eccen*eccen) - - ! Set solar declination and eccentricity factor - - delta = asin(sin(obliqr)*sin(lamb)) - eccf = invrho*invrho - - return - - end subroutine shr_orb_decl - - !:---------------------------------------------------------------------------- - - real(SHR_KIND_R8) pure function shr_orb_cosz(jday, lat, lon, declin) - - !------------------------------------------------------------------------- - ! - ! FUNCTION to return the cosine of the solar zenith angle. - ! Assumes 365.0 days/year. - ! - !--------------- Code History -------------------------------------------- - ! - ! Original Author: Brian Kauffman - ! Date: Jan/98 - ! History: adapted from statement FUNCTION in share/orb_cosz.h - ! - !------------------------------------------------------------------------- - - real(SHR_KIND_R8), intent(in) :: jday ! Julian cal day (1.xx to 365.xx) - real(SHR_KIND_R8), intent(in) :: lat ! Centered latitude (radians) - real(SHR_KIND_R8), intent(in) :: lon ! Centered longitude (radians) - real(SHR_KIND_R8), intent(in) :: declin ! Solar declination (radians) - - !------------------------------------------------------------------------- - - shr_orb_cosz = sin(lat)*sin(declin) - cos(lat)*cos(declin) * & - cos((jday-floor(jday))*2.0_SHR_KIND_R8*pi + lon) - - end function shr_orb_cosz - -end module FatesUnitTestOrbitalMod \ No newline at end of file From 74cb26b282bc90bed80f50de69857399859b19ab Mon Sep 17 00:00:00 2001 From: adrifoster Date: Thu, 4 May 2023 10:39:37 -0600 Subject: [PATCH 663/852] refactor copy and dealloc --- biogeochem/EDCanopyStructureMod.F90 | 10 +- biogeochem/EDCohortDynamicsMod.F90 | 176 +------------- biogeochem/EDPatchDynamicsMod.F90 | 84 +------ biogeochem/EDPhysiologyMod.F90 | 3 +- biogeochem/FatesPatchMod.F90 | 336 +++++++++++++++++++------- main/FatesCohortMod.F90 | 358 +++++++++++++++++++--------- 6 files changed, 510 insertions(+), 457 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 144dd14781..5c867b698a 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -15,7 +15,7 @@ module EDCanopyStructureMod use EDPftvarcon , only : EDPftvarcon_inst use PRTParametersMod , only : prt_params use FatesAllometryMod , only : carea_allom - use EDCohortDynamicsMod , only : copy_cohort, terminate_cohorts, terminate_cohort, fuse_cohorts + use EDCohortDynamicsMod , only : terminate_cohorts, terminate_cohort, fuse_cohorts use EDCohortDynamicsMod , only : InitPRTObject use FatesAllometryMod , only : tree_lai use FatesAllometryMod , only : tree_sai @@ -670,7 +670,7 @@ subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr,bc_in) !allocate(copyc%tveg_lpa) !!allocate(copyc%l2fr_ema) ! Note, no need to give a starter value here, - ! that will be taken care of in copy_cohort() + ! that will be taken care of in copy() !!call copyc%l2fr_ema%InitRMean(ema_60day) ! Initialize the PARTEH object and point to the @@ -682,7 +682,7 @@ subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr,bc_in) call InitHydrCohort(currentSite,copyc) endif - call copy_cohort(currentCohort, copyc) + call currentCohort%copy(copyc) call copyc%InitPRTBoundaryConditions() newarea = currentCohort%c_area - cc_loss @@ -1138,7 +1138,7 @@ subroutine PromoteIntoLayer(currentSite,currentPatch,i_lyr) !!allocate(copyc%l2fr_ema) ! Note, no need to give a starter value here, - ! that will be taken care of in copy_cohort() + ! that will be taken care of in copy() !!call copyc%l2fr_ema%InitRMean(ema_60day) ! Initialize the PARTEH object and point to the @@ -1157,7 +1157,7 @@ subroutine PromoteIntoLayer(currentSite,currentPatch,i_lyr) !call copyc%tveg_lpa%InitRMean(ema_lpa,& ! init_value=currentPatch%tveg_lpa%GetMean()) - call copy_cohort(currentCohort, copyc) !makes an identical copy... + call currentCohort%copy(copyc) !makes an identical copy... call copyc%InitPRTBoundaryConditions() newarea = currentCohort%c_area - cc_gain !new area of existing cohort diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 7ed68711f1..a910bee762 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -1,9 +1,10 @@ Module EDCohortDynamicsMod ! - ! !DESCRIPTION: - ! Cohort stuctures in ED. + ! DESCRIPTION: + ! Cohort stuctures in FATES ! - ! !USES: + + ! USES: use FatesGlobals , only : endrun => fates_endrun use FatesGlobals , only : fates_log use FatesInterfaceTypesMod , only : hlm_freq_day @@ -49,7 +50,6 @@ Module EDCohortDynamicsMod use FatesInterfaceTypesMod , only : hlm_use_planthydro use FatesInterfaceTypesMod , only : hlm_parteh_mode use FatesPlantHydraulicsMod, only : FuseCohortHydraulics - use FatesPlantHydraulicsMod, only : CopyCohortHydraulics use FatesPlantHydraulicsMod, only : UpdateSizeDepPlantHydProps use FatesPlantHydraulicsMod, only : InitPlantHydStates use FatesPlantHydraulicsMod, only : InitHydrCohort @@ -122,7 +122,6 @@ Module EDCohortDynamicsMod public :: fuse_cohorts public :: insert_cohort public :: sort_cohorts - public :: copy_cohort public :: count_cohorts public :: InitPRTObject public :: SendCohortToLitter @@ -1449,172 +1448,7 @@ subroutine insert_cohort(currentPatch, pcc, ptall, pshort, tnull, snull, storebi end subroutine insert_cohort !-------------------------------------------------------------------------------------! - subroutine copy_cohort( currentCohort,copyc ) - ! - ! !DESCRIPTION: - ! Copies all the variables in one cohort into another empty cohort - ! - ! !USES: - ! - ! !ARGUMENTS - type(fates_cohort_type), intent(inout) , target :: copyc ! New cohort argument. - type(fates_cohort_type), intent(in) , target :: currentCohort ! Old cohort argument. - ! - ! !LOCAL VARIABLES: - type(fates_cohort_type), pointer :: n,o ! New and old cohort pointers - !---------------------------------------------------------------------- - o => currentCohort - n => copyc - - n%indexnumber = fates_unset_int - - ! VEGETATION STRUCTURE - n%pft = o%pft - n%crowndamage = o%crowndamage - n%n = o%n - n%dbh = o%dbh - n%coage = o%coage - n%hite = o%hite - n%g_sb_laweight = o%g_sb_laweight - n%leaf_cost = o%leaf_cost - n%canopy_layer = o%canopy_layer - n%canopy_layer_yesterday = o%canopy_layer_yesterday - n%nv = o%nv - n%status_coh = o%status_coh - n%canopy_trim = o%canopy_trim - n%excl_weight = o%excl_weight - n%prom_weight = o%prom_weight - n%size_class = o%size_class - n%size_class_lasttimestep = o%size_class_lasttimestep - n%size_by_pft_class = o%size_by_pft_class - n%coage_class = o%coage_class - n%coage_by_pft_class = o%coage_by_pft_class - - ! This transfers the PRT objects over. - call n%prt%CopyPRTVartypes(o%prt) - n%l2fr = o%l2fr - - ! Leaf biophysical rates - n%vcmax25top = o%vcmax25top - n%jmax25top = o%jmax25top - n%tpu25top = o%tpu25top - n%kp25top = o%kp25top - - ! Copy over running means - if(hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) then - n%cx_int = o%cx_int - n%ema_dcxdt = o%ema_dcxdt - n%cx0 = o%cx0 - end if - - ! CARBON FLUXES - n%gpp_acc_hold = o%gpp_acc_hold - n%gpp_acc = o%gpp_acc - n%gpp_tstep = o%gpp_tstep - - n%npp_acc_hold = o%npp_acc_hold - n%npp_tstep = o%npp_tstep - n%npp_acc = o%npp_acc - - if ( debug .and. .not.o%isnew ) write(fates_log(),*) 'EDcohortDyn Ia ',o%npp_acc - if ( debug .and. .not.o%isnew ) write(fates_log(),*) 'EDcohortDyn Ib ',o%resp_acc - - n%resp_tstep = o%resp_tstep - n%resp_acc = o%resp_acc - n%resp_acc_hold = o%resp_acc_hold - n%year_net_uptake = o%year_net_uptake - n%ts_net_uptake = o%ts_net_uptake - - ! These do not need to be copied because they - ! are written to history before dynamics occurs - ! and cohorts are reformed - n%daily_nh4_uptake = o%daily_nh4_uptake - n%daily_no3_uptake = o%daily_no3_uptake - n%sym_nfix_daily = o%sym_nfix_daily - n%daily_n_gain = o%daily_n_gain - n%daily_p_gain = o%daily_p_gain - n%daily_c_efflux = o%daily_c_efflux - n%daily_n_efflux = o%daily_n_efflux - n%daily_p_efflux = o%daily_p_efflux - n%daily_n_demand = o%daily_n_demand - n%daily_p_demand = o%daily_p_demand - - ! C13 discrimination - n%c13disc_clm = o%c13disc_clm - n%c13disc_acc = o%c13disc_acc - - !RESPIRATION - n%rdark = o%rdark - n%resp_m = o%resp_m - n%resp_m_unreduced= o%resp_m_unreduced - n%resp_excess = o%resp_excess - n%resp_g_tstep = o%resp_g_tstep - n%livestem_mr = o%livestem_mr - n%livecroot_mr = o%livecroot_mr - n%froot_mr = o%froot_mr - - ! ALLOCATION - n%dmort = o%dmort - n%seed_prod = o%seed_prod - - n%treelai = o%treelai - n%treesai = o%treesai - n%c_area = o%c_area - - ! Mortality diagnostics - n%cmort = o%cmort - n%bmort = o%bmort - n%hmort = o%hmort - n%smort = o%smort - n%asmort = o%asmort - n%frmort = o%frmort - n%dgmort = o%dgmort - - ! logging mortalities, Yi Xu - n%lmort_direct =o%lmort_direct - n%lmort_collateral =o%lmort_collateral - n%lmort_infra =o%lmort_infra - n%l_degrad =o%l_degrad - - ! Flags - n%isnew = o%isnew - - ! VARIABLES NEEDED FOR INTEGRATION - n%dndt = o%dndt - n%dhdt = o%dhdt - n%ddbhdt = o%ddbhdt - - ! FIRE - n%fraction_crown_burned = o%fraction_crown_burned - n%fire_mort = o%fire_mort - n%crownfire_mort = o%crownfire_mort - n%cambial_mort = o%cambial_mort - - ! Plant Hydraulics - - if( hlm_use_planthydro.eq.itrue ) then - call CopyCohortHydraulics(n,o) - endif - - ! indices for binning - n%size_class = o%size_class - n%size_class_lasttimestep = o%size_class_lasttimestep - n%size_by_pft_class = o%size_by_pft_class - n%coage_class = o%coage_class - n%coage_by_pft_class = o%coage_by_pft_class - - !Pointers - n%taller => NULL() ! pointer to next tallest cohort - n%shorter => NULL() ! pointer to next shorter cohort - !n%patchptr => o%patchptr ! pointer to patch that cohort is in - - - - - end subroutine copy_cohort - - !-------------------------------------------------------------------------------------! subroutine count_cohorts( currentPatch ) ! ! !DESCRIPTION: @@ -1935,7 +1769,7 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) rcohort%prt => null() call InitPRTObject(rcohort%prt) call rcohort%InitPRTBoundaryConditions() - call copy_cohort(ccohort, rcohort) + call ccohort%copy(rcohort) rcohort%n = nplant_recover diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 5674857236..3aaba6fb31 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -406,7 +406,7 @@ subroutine spawn_patches( currentSite, bc_in) ! !USES: use EDParamsMod , only : ED_val_understorey_death, logging_coll_under_frac - use EDCohortDynamicsMod , only : copy_cohort, terminate_cohorts + use EDCohortDynamicsMod , only : terminate_cohorts use FatesConstantsMod , only : rsnbl_math_prec ! @@ -691,7 +691,7 @@ subroutine spawn_patches( currentSite, bc_in) ! nc is the new cohort that goes in the disturbed patch (new_patch)... currentCohort ! is the curent cohort that stays in the donor patch (currentPatch) - call copy_cohort(currentCohort, nc) + call currentCohort%copy(nc) !this is the case as the new patch probably doesn't have a closed canopy, and ! even if it does, that will be sorted out in canopy_structure. @@ -2529,7 +2529,7 @@ subroutine fuse_2_patches(csite, dp, rp) end if ! We have no need for the dp pointer anymore, we have passed on it's legacy - call dealloc_patch(dp) + call dp%free_memory() deallocate(dp, stat=istat, errmsg=smsg) if (istat/=0) then write(fates_log(),*) 'dealloc006: fail on deallocate(dp):'//trim(smsg) @@ -2764,84 +2764,6 @@ subroutine DistributeSeeds(currentSite,seed_mass,el,pft) return end subroutine DistributeSeeds - - ! ===================================================================================== - - subroutine dealloc_patch(cpatch) - - ! This Subroutine is intended to de-allocate the allocatable memory that is pointed - ! to via the patch structure. This subroutine DOES NOT deallocate the patch - ! structure itself. - - type(fates_patch_type) :: cpatch - - type(fates_cohort_type), pointer :: ccohort ! current - type(fates_cohort_type), pointer :: ncohort ! next - integer :: el ! loop counter for elements - - ! First Deallocate the cohort space - ! ----------------------------------------------------------------------------------- - ccohort => cpatch%shortest - do while(associated(ccohort)) - - ncohort => ccohort%taller - - call DeallocateCohort(ccohort) - deallocate(ccohort, stat=istat, errmsg=smsg) - if (istat/=0) then - write(fates_log(),*) 'dealloc007: fail on deallocate(cchort):'//trim(smsg) - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - - ccohort => ncohort - - end do - - ! Deallocate all litter objects - do el=1,num_elements - call cpatch%litter(el)%DeallocateLitt() - end do - deallocate(cpatch%litter, stat=istat, errmsg=smsg) - if (istat/=0) then - write(fates_log(),*) 'dealloc008: fail on deallocate(cpatch%litter):'//trim(smsg) - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - - ! Secondly, deallocate the allocatable vector spaces in the patch - deallocate(cpatch%tr_soil_dir, & - cpatch%tr_soil_dif, & - cpatch%tr_soil_dir_dif, & - cpatch%fab, & - cpatch%fabd, & - cpatch%fabi, & - cpatch%sabs_dir, & - cpatch%sabs_dif, & - cpatch%fragmentation_scaler, stat=istat, errmsg=smsg) - if (istat/=0) then - write(fates_log(),*) 'dealloc009: fail on deallocate patch vectors:'//trim(smsg) - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - - ! Deallocate any running means - deallocate(cpatch%tveg24, stat=istat, errmsg=smsg) - if (istat/=0) then - write(fates_log(),*) 'dealloc010: fail on deallocate(cpatch%tveg24):'//trim(smsg) - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - deallocate(cpatch%tveg_lpa, stat=istat, errmsg=smsg) - if (istat/=0) then - write(fates_log(),*) 'dealloc011: fail on deallocate(cpatch%tveg_lpa):'//trim(smsg) - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - deallocate(cpatch%tveg_longterm, stat=istat, errmsg=smsg) - if (istat/=0) then - write(fates_log(),*) 'dealloc012: fail on deallocate(cpatch%tveg_longterm):'//trim(smsg) - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - - return - end subroutine dealloc_patch - ! ============================================================================ subroutine patch_pft_size_profile(cp_pnt) ! diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index b1500736e8..9a49d540e5 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -31,7 +31,6 @@ module EDPhysiologyMod use FatesInterfaceTypesMod, only : bc_out_type use EDCohortDynamicsMod , only : create_cohort, sort_cohorts use EDCohortDynamicsMod , only : InitPRTObject - use EDCohortDynamicsMod , only : copy_cohort use FatesAllometryMod , only : tree_lai use FatesAllometryMod , only : tree_sai use FatesAllometryMod , only : leafc_from_treelai @@ -277,7 +276,7 @@ subroutine GenerateDamageAndLitterFluxes( csite, cpatch, bc_in ) call ndcohort%zero_values() ! nc_canopy_d is the new cohort that gets damaged - call copy_cohort(ccohort, ndcohort) + call ccohort%copy(ndcohort) ! new number densities - we just do damaged cohort here - ! undamaged at the end of the cohort loop once we know how many damaged to diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 index 4447c0804f..ae536a9cb5 100644 --- a/biogeochem/FatesPatchMod.F90 +++ b/biogeochem/FatesPatchMod.F90 @@ -24,6 +24,9 @@ module FatesPatchMod implicit none private + ! for error message writing + character(len=*), parameter :: sourcefile = __FILE__ + type, public :: fates_patch_type ! POINTERS @@ -67,82 +70,82 @@ module FatesPatchMod !:.........................................................................: ! LEAF ORGANIZATION - real(r8) :: pft_agb_profile(maxpft,n_dbh_bins) ! binned aboveground biomass, for patch fusion [kgC/m2] - real(r8) :: canopy_layer_tlai(nclmax) ! total leaf area index of each canopy layer [m2 veg/m2 canopy area] - ! (patch without bare ground) - ! used to determine attenuation of parameters during photosynthesis - real(r8) :: total_canopy_area ! area that is covered by vegetation [m2] - real(r8) :: total_tree_area ! area that is covered by woody vegetation [m2] - real(r8) :: zstar ! height of smallest canopy tree, only meaningful in "strict PPA" mode [m] - real(r8) :: elai_profile(nclmax,maxpft,nlevleaf) ! exposed leaf area in each canopy layer, pft, and leaf layer [m2 leaf/m2 contributing crown area] - real(r8) :: esai_profile(nclmax,maxpft,nlevleaf) ! exposed stem area in each canopy layer, pft, and leaf layer [m2 leaf/m2 contributing crown area] - real(r8) :: tlai_profile(nclmax,maxpft,nlevleaf) - real(r8) :: tsai_profile(nclmax,maxpft,nlevleaf) - real(r8) :: canopy_area_profile(nclmax,maxpft,nlevleaf) ! fraction of crown area per canopy area in each layer - ! they will sum to 1.0 in the fully closed canopy layers - ! but only in leaf-layers that contain contributions - ! from all cohorts that donate to canopy_area - integer :: canopy_mask(nclmax,maxpft) ! is there any of this pft in this canopy layer? - integer :: nrad(nclmax,maxpft) ! number of exposed leaf layers for each canopy layer and pft - integer :: ncan(nclmax,maxpft) ! number of total leaf layers for each canopy layer and pft - real(r8) :: c_stomata ! mean stomatal conductance of all leaves in the patch [umol/m2/s] - real(r8) :: c_lblayer ! mean boundary layer conductance of all leaves in the patch [umol/m2/s] + real(r8), allocatable :: pft_agb_profile(:,:) ! binned aboveground biomass, for patch fusion [kgC/m2] + real(r8) :: canopy_layer_tlai(nclmax) ! total leaf area index of each canopy layer [m2 veg/m2 canopy area] + ! (patch without bare ground) + ! used to determine attenuation of parameters during photosynthesis + real(r8) :: total_canopy_area ! area that is covered by vegetation [m2] + real(r8) :: total_tree_area ! area that is covered by woody vegetation [m2] + real(r8) :: zstar ! height of smallest canopy tree, only meaningful in "strict PPA" mode [m] + real(r8), allocatable :: elai_profile(:,:,:) ! exposed leaf area in each canopy layer, pft, and leaf layer [m2 leaf/m2 contributing crown area] + real(r8), allocatable :: esai_profile(:,:,:) ! exposed stem area in each canopy layer, pft, and leaf layer [m2 leaf/m2 contributing crown area] + real(r8), allocatable :: tlai_profile(:,:,:) + real(r8), allocatable :: tsai_profile(:,:,:) + real(r8), allocatable :: canopy_area_profile(:,:,:) ! fraction of crown area per canopy area in each layer + ! they will sum to 1.0 in the fully closed canopy layers + ! but only in leaf-layers that contain contributions + ! from all cohorts that donate to canopy_area + integer, allocatable :: canopy_mask(:,:) ! is there any of this pft in this canopy layer? + integer, allocatable :: nrad(:,:) ! number of exposed leaf layers for each canopy layer and pft + integer, allocatable :: ncan(:,:) ! number of total leaf layers for each canopy layer and pft + real(r8) :: c_stomata ! mean stomatal conductance of all leaves in the patch [umol/m2/s] + real(r8) :: c_lblayer ! mean boundary layer conductance of all leaves in the patch [umol/m2/s] !:.........................................................................: - real(r8) :: layer_height_profile(nclmax,maxpft,nlevleaf) - real(r8) :: psn_z(nclmax,maxpft,nlevleaf) - real(r8) :: nrmlzd_parprof_pft_dir_z(n_rad_stream_types,nclmax,maxpft,nlevleaf) - real(r8) :: nrmlzd_parprof_pft_dif_z(n_rad_stream_types,nclmax,maxpft,nlevleaf) - real(r8) :: nrmlzd_parprof_dir_z(n_rad_stream_types,nclmax,nlevleaf) - real(r8) :: nrmlzd_parprof_dif_z(n_rad_stream_types,nclmax,nlevleaf) + real(r8), allocatable :: layer_height_profile(:,:,:) + real(r8), allocatable :: psn_z(:,:,:) + real(r8), allocatable :: nrmlzd_parprof_pft_dir_z(:,:,:,:) + real(r8), allocatable :: nrmlzd_parprof_pft_dif_z(:,:,:,:) + real(r8), allocatable :: nrmlzd_parprof_dir_z(:,:,:) + real(r8), allocatable :: nrmlzd_parprof_dif_z(:,:,:) !:.........................................................................: ! RADIATION - real(r8) :: radiation_error ! radiation error [W/m2] - real(r8) :: fcansno ! fraction of canopy covered in snow [0-1] - logical :: solar_zenith_flag ! integer flag specifying daylight (based on zenith angle) - real(r8) :: solar_zenith_angle ! solar zenith angle [radians] - real(r8) :: gnd_alb_dif(maxSWb) ! ground albedo for diffuse rad, both bands [0-1] - real(r8) :: gnd_alb_dir(maxSWb) ! ground albedo for direct rad, both bands [0-1] + real(r8) :: radiation_error ! radiation error [W/m2] + real(r8) :: fcansno ! fraction of canopy covered in snow [0-1] + logical :: solar_zenith_flag ! integer flag specifying daylight (based on zenith angle) + real(r8) :: solar_zenith_angle ! solar zenith angle [radians] + real(r8), allocatable :: gnd_alb_dif(:) ! ground albedo for diffuse rad, both bands [0-1] + real(r8), allocatable :: gnd_alb_dir(:) ! ground albedo for direct rad, both bands [0-1] ! organized by canopy layer, pft, and leaf layer - real(r8) :: fabd_sun_z(nclmax,maxpft,nlevleaf) ! sun fraction of direct light absorbed [0-1] - real(r8) :: fabd_sha_z(nclmax,maxpft,nlevleaf) ! shade fraction of direct light absorbed [0-1] - real(r8) :: fabi_sun_z(nclmax,maxpft,nlevleaf) ! sun fraction of indirect light absorbed [0-1] - real(r8) :: fabi_sha_z(nclmax,maxpft,nlevleaf) ! shade fraction of indirect light absorbed [0-1] - real(r8) :: ed_parsun_z(nclmax,maxpft,nlevleaf) ! PAR absorbed in the sun [W/m2] - real(r8) :: ed_parsha_z(nclmax,maxpft,nlevleaf) ! PAR absorbed in the shade [W/m2] - real(r8) :: ed_laisun_z(nclmax,maxpft,nlevleaf) - real(r8) :: ed_laisha_z(nclmax,maxpft,nlevleaf) - real(r8) :: f_sun(nclmax,maxpft,nlevleaf) ! fraction of leaves in the sun [0-1] + real(r8), allocatable :: fabd_sun_z(:,:,:) ! sun fraction of direct light absorbed [0-1] + real(r8), allocatable :: fabd_sha_z(:,:,:) ! shade fraction of direct light absorbed [0-1] + real(r8), allocatable :: fabi_sun_z(:,:,:) ! sun fraction of indirect light absorbed [0-1] + real(r8), allocatable :: fabi_sha_z(:,:,:) ! shade fraction of indirect light absorbed [0-1] + real(r8), allocatable :: ed_parsun_z(:,:,:) ! PAR absorbed in the sun [W/m2] + real(r8), allocatable :: ed_parsha_z(:,:,:) ! PAR absorbed in the shade [W/m2] + real(r8), allocatable :: ed_laisun_z(:,:,:) + real(r8), allocatable :: ed_laisha_z(:,:,:) + real(r8), allocatable :: f_sun(:,:,:) ! fraction of leaves in the sun [0-1] ! radiation profiles for comparison against observations - real(r8) :: parprof_pft_dir_z(nclmax,maxpft,nlevleaf) ! direct-beam PAR profile through canopy, by canopy, PFT, leaf level [W/m2] - real(r8) :: parprof_pft_dif_z(nclmax,maxpft,nlevleaf) ! diffuse PAR profile through canopy, by canopy, PFT, leaf level [W/m2] - real(r8) :: parprof_dir_z(nclmax,nlevleaf) ! direct-beam PAR profile through canopy, by canopy, leaf level [W/m2] - real(r8) :: parprof_dif_z(nclmax,nlevleaf) ! diffuse PAR profile through canopy, by canopy, leaf level [W/m2] + real(r8), allocatable :: parprof_pft_dir_z(:,:,:) ! direct-beam PAR profile through canopy, by canopy, PFT, leaf level [W/m2] + real(r8), allocatable :: parprof_pft_dif_z(:,:,:) ! diffuse PAR profile through canopy, by canopy, PFT, leaf level [W/m2] + real(r8), allocatable :: parprof_dir_z(:,:) ! direct-beam PAR profile through canopy, by canopy, leaf level [W/m2] + real(r8), allocatable :: parprof_dif_z(:,:) ! diffuse PAR profile through canopy, by canopy, leaf level [W/m2] - real(r8), allocatable :: tr_soil_dir(:) ! fraction of incoming direct radiation transmitted to the soil as direct, by numSWB [0-1] - real(r8), allocatable :: tr_soil_dif(:) ! fraction of incoming diffuse radiation that is transmitted to the soil as diffuse [0-1] - real(r8), allocatable :: tr_soil_dir_dif(:) ! fraction of incoming direct radiation that is transmitted to the soil as diffuse [0-1] - real(r8), allocatable :: fab(:) ! fraction of incoming total radiation that is absorbed by the canopy - real(r8), allocatable :: fabd(:) ! fraction of incoming direct radiation that is absorbed by the canopy - real(r8), allocatable :: fabi(:) ! fraction of incoming diffuse radiation that is absorbed by the canopy - real(r8), allocatable :: sabs_dir(:) ! fraction of incoming direct radiation that is absorbed by the canopy - real(r8), allocatable :: sabs_dif(:) ! fraction of incoming diffuse radiation that is absorbed by the canopy + real(r8), allocatable :: tr_soil_dir(:) ! fraction of incoming direct radiation transmitted to the soil as direct, by numSWB [0-1] + real(r8), allocatable :: tr_soil_dif(:) ! fraction of incoming diffuse radiation that is transmitted to the soil as diffuse [0-1] + real(r8), allocatable :: tr_soil_dir_dif(:) ! fraction of incoming direct radiation that is transmitted to the soil as diffuse [0-1] + real(r8), allocatable :: fab(:) ! fraction of incoming total radiation that is absorbed by the canopy + real(r8), allocatable :: fabd(:) ! fraction of incoming direct radiation that is absorbed by the canopy + real(r8), allocatable :: fabi(:) ! fraction of incoming diffuse radiation that is absorbed by the canopy + real(r8), allocatable :: sabs_dir(:) ! fraction of incoming direct radiation that is absorbed by the canopy + real(r8), allocatable :: sabs_dif(:) ! fraction of incoming diffuse radiation that is absorbed by the canopy !:.........................................................................: ! ROOTS - real(r8) :: btran_ft(maxpft) ! btran calculated seperately for each PFT - real(r8) :: bstress_sal_ft(maxpft) ! bstress from salinity calculated seperately for each PFT + real(r8), allocatable :: btran_ft(:) ! btran calculated seperately for each PFT + real(r8), allocatable :: bstress_sal_ft(:) ! bstress from salinity calculated seperately for each PFT !:.........................................................................: ! EXTERNAL SEED RAIN - real(r8) :: nitr_repro_stoich(maxpft) ! The NC ratio of a new recruit in this patch - real(r8) :: phos_repro_stoich(maxpft) ! The PC ratio of a new recruit in this patch + real(r8), allocatable :: nitr_repro_stoich(:) ! The NC ratio of a new recruit in this patch + real(r8), allocatable :: phos_repro_stoich(:) ! The PC ratio of a new recruit in this patch !:.........................................................................: @@ -162,33 +165,33 @@ module FatesPatchMod ! FUELS AND FIRE ! fuel characteristics - real(r8) :: sum_fuel ! total ground fuel related to ROS (omits 1000 hr fuels) [kgC/m2] - real(r8) :: fuel_frac(nfsc) ! fraction of each litter class in the ros_fuel [0-1] - real(r8) :: livegrass ! total aboveground grass biomass in patch [kgC/m2] - real(r8) :: fuel_bulkd ! average fuel bulk density of the ground fuel. [kg/m3] - ! (incl. live grasses, omits 1000hr fuels) - real(r8) :: fuel_sav ! average surface area to volume ratio of the ground fuel [cm-1] - ! (incl. live grasses, omits 1000hr fuels) - real(r8) :: fuel_mef ! average moisture of extinction factor - ! of the ground fuel (incl. live grasses, omits 1000hr fuels) - real(r8) :: fuel_eff_moist ! effective avearage fuel moisture content of the ground fuel - ! (incl. live grasses. omits 1000hr fuels) - real(r8) :: litter_moisture(nfsc) ! moisture of litter [m3/m3] + real(r8) :: sum_fuel ! total ground fuel related to ROS (omits 1000 hr fuels) [kgC/m2] + real(r8) :: fuel_frac(nfsc) ! fraction of each litter class in the ros_fuel [0-1] + real(r8) :: livegrass ! total aboveground grass biomass in patch [kgC/m2] + real(r8) :: fuel_bulkd ! average fuel bulk density of the ground fuel. [kg/m3] + ! (incl. live grasses, omits 1000hr fuels) + real(r8) :: fuel_sav ! average surface area to volume ratio of the ground fuel [cm-1] + ! (incl. live grasses, omits 1000hr fuels) + real(r8) :: fuel_mef ! average moisture of extinction factor + ! of the ground fuel (incl. live grasses, omits 1000hr fuels) + real(r8) :: fuel_eff_moist ! effective avearage fuel moisture content of the ground fuel + ! (incl. live grasses. omits 1000hr fuels) + real(r8) :: litter_moisture(nfsc) ! moisture of litter [m3/m3] ! fire spread - real(r8) :: ros_front ! rate of forward spread of fire [m/min] - real(r8) :: ros_back ! rate of backward spread of fire [m/min] - real(r8) :: effect_wspeed ! windspeed modified by fraction of relative grass and tree cover [m/min] - real(r8) :: tau_l ! duration of lethal heating [min] - real(r8) :: fi ! average fire intensity of flaming front [kJ/m/s] or [kW/m] - integer :: fire ! is there a fire? [1=yes; 0=no] - real(r8) :: fd ! fire duration [min] + real(r8) :: ros_front ! rate of forward spread of fire [m/min] + real(r8) :: ros_back ! rate of backward spread of fire [m/min] + real(r8) :: effect_wspeed ! windspeed modified by fraction of relative grass and tree cover [m/min] + real(r8) :: tau_l ! duration of lethal heating [min] + real(r8) :: fi ! average fire intensity of flaming front [kJ/m/s] or [kW/m] + integer :: fire ! is there a fire? [1=yes; 0=no] + real(r8) :: fd ! fire duration [min] ! fire effects - real(r8) :: scorch_ht(maxpft) ! scorch height [m] - real(r8) :: frac_burnt ! fraction burnt [0-1/day] - real(r8) :: tfc_ros ! total intensity-relevant fuel consumed - no trunks [kgC/m2 of burned ground/day] - real(r8) :: burnt_frac_litter(nfsc) ! fraction of each litter pool burned, conditional on it being burned [0-1] + real(r8), allocatable :: scorch_ht(:) ! scorch height [m] + real(r8) :: frac_burnt ! fraction burnt [0-1/day] + real(r8) :: tfc_ros ! total intensity-relevant fuel consumed - no trunks [kgC/m2 of burned ground/day] + real(r8) :: burnt_frac_litter(nfsc) ! fraction of each litter pool burned, conditional on it being burned [0-1] !:.........................................................................: @@ -200,31 +203,66 @@ module FatesPatchMod procedure :: init procedure :: nan_values procedure :: zero_values + procedure :: init_running_means + procedure :: init_litter procedure :: create + procedure :: free_memory procedure :: dump procedure :: check_vars - procedure :: init_running_means - procedure :: init_litter end type fates_patch_type contains - subroutine init(this, numSWb, nlevsoil) + subroutine init(this, numpft, numSWb, nlevsoil) ! ! DESCRIPTION: - ! Initialize a new patch + ! Initialize a new patch - allocate arrays and set values to nan and/or + ! 0.0 ! ! ARGUMENTS: class(fates_patch_type), intent(inout) :: this ! patch object + integer, intent(in) :: numpft ! number of pfts integer, intent(in) :: numSWb ! number of shortwave broad-bands to track integer, intent(in) :: nlevsoil ! number of soil layers - ! LOCAL VARIABLES: - integer :: el ! element loop index - ! allocate arrays + allocate(this%pft_agb_profile(numpft, N_DBH_BINS)) + allocate(this%elai_profile(nclmax,numpft,nlevleaf)) + allocate(this%esai_profile(nclmax,numpft,nlevleaf)) + allocate(this%tlai_profile(nclmax,numpft,nlevleaf)) + allocate(this%tsai_profile(nclmax,numpft,nlevleaf)) + allocate(this%canopy_area_profile(nclmax,numpft,nlevleaf)) + + allocate(this%canopy_mask(nclmax,numpft)) + allocate(this%nrad(nclmax,numpft)) + allocate(this%ncan(nclmax,numpft)) + + allocate(this%layer_height_profile(nclmax,numpft,nlevleaf)) + allocate(this%psn_z(nclmax,numpft,nlevleaf)) + allocate(this%nrmlzd_parprof_pft_dir_z(n_rad_stream_types,nclmax,numpft,nlevleaf)) + allocate(this%nrmlzd_parprof_pft_dif_z(n_rad_stream_types,nclmax,numpft,nlevleaf)) + allocate(this%nrmlzd_parprof_dir_z(n_rad_stream_types,nclmax,nlevleaf)) + allocate(this%nrmlzd_parprof_dif_z(n_rad_stream_types,nclmax,nlevleaf)) + + allocate(this%gnd_alb_dif(numSWb)) + allocate(this%gnd_alb_dir(numSWb)) + allocate(this%fabd_sun_z(nclmax,numpft,nlevleaf)) + allocate(this%fabd_sha_z(nclmax,numpft,nlevleaf)) + allocate(this%fabi_sun_z(nclmax,numpft,nlevleaf)) + allocate(this%fabi_sha_z(nclmax,numpft,nlevleaf)) + allocate(this%ed_parsun_z(nclmax,numpft,nlevleaf)) + allocate(this%ed_parsha_z(nclmax,numpft,nlevleaf)) + allocate(this%ed_laisun_z(nclmax,numpft,nlevleaf)) + allocate(this%ed_laisha_z(nclmax,numpft,nlevleaf)) + allocate(this%f_sun(nclmax,numpft,nlevleaf)) + + allocate(this%parprof_pft_dir_z(nclmax,numpft,nlevleaf)) + allocate(this%parprof_pft_dif_z(nclmax,numpft,nlevleaf)) + allocate(this%parprof_dir_z(nclmax,nlevleaf)) + allocate(this%parprof_dif_z(nclmax,nlevleaf)) + allocate(this%tr_soil_dir(numSWb)) allocate(this%tr_soil_dif(numSWb)) allocate(this%tr_soil_dir_dif(numSWb)) @@ -233,9 +271,18 @@ subroutine init(this, numSWb, nlevsoil) allocate(this%fabi(numSWb)) allocate(this%sabs_dir(numSWb)) allocate(this%sabs_dif(numSWb)) + + allocate(this%btran_ft(numpft)) + allocate(this%bstress_sal_ft(numpft)) + + allocate(this%nitr_repro_stoich(numpft)) + allocate(this%phos_repro_stoich(numpft)) + allocate(this%fragmentation_scaler(nlevsoil)) - ! initialize values to nan + allocate(this%scorch_ht(numpft)) + + ! initialize all values to nan call this%nan_values() ! zero values that should be zeroed @@ -552,6 +599,119 @@ end subroutine create !:.........................................................................: + subroutine free_memory(this) + ! + ! DESCRIPTION: + ! deallocate the allocatable memory associated with this patch + ! this DOES NOT deallocate the patch structure itself + ! + + ! ARGUMENTS: + class(fates_patch_type), intent(inout) :: this + + ! LOCALS: + type(fates_cohort_type), pointer :: ccohort ! current cohort + type(fates_cohort_type), pointer :: ncohort ! next cohort + integer :: el ! loop counter for elements + integer :: istat ! return status code + character(len=255) :: smsg ! message string for deallocation errors + + ! first deallocate the cohorts + ccohort => this%shortest + do while(associated(ccohort)) + ncohort => ccohort%taller + call DeallocateCohort(ccohort) + deallocate(ccohort, stat=istat, errmsg=smsg) + if (istat /= 0) then + write(fates_log(),*) 'dealloc007: fail on deallocate(cchort):'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + ccohort => ncohort + end do + + ! deallocate all litter objects + do el=1,num_elements + call this%litter(el)%DeallocateLitt() + end do + deallocate(this%litter, stat=istat, errmsg=smsg) + if (istat/=0) then + write(fates_log(),*) 'dealloc008: fail on deallocate(this%litter):'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + + ! deallocate the allocatable arrays + deallocate(this%pft_agb_profile, & + this%elai_profile, & + this%esai_profile, & + this%tlai_profile, & + this%tsai_profile, & + this%canopy_area_profile, & + this%canopy_mask, & + this%nrad, & + this%ncan, & + this%layer_height_profile, & + this%psn_z, & + this%nrmlzd_parprof_pft_dir_z, & + this%nrmlzd_parprof_pft_dif_z, & + this%nrmlzd_parprof_dir_z, & + this%nrmlzd_parprof_dif_z, & + this%gnd_alb_dif, & + this%gnd_alb_dir, & + this%fabd_sun_z, & + this%fabd_sha_z, & + this%fabi_sun_z, & + this%fabi_sha_z, & + this%ed_parsun_z, & + this%ed_parsha_z, & + this%ed_laisun_z, & + this%ed_laisha_z, & + this%f_sun, & + this%parprof_pft_dir_z, & + this%parprof_pft_dif_z, & + this%parprof_dir_z, & + this%parprof_dif_z, & + this%tr_soil_dir, & + this%tr_soil_dif, & + this%tr_soil_dir_dif, & + this%fab, & + this%fabd, & + this%fabi, & + this%sabs_dir, & + this%sabs_dif, & + this%btran_ft, & + this%bstress_sal_ft, & + this%nitr_repro_stoich, & + this%phos_repro_stoich, & + this%fragmentation_scaler, & + this%scorch_ht, & + stat=istat, errmsg=smsg) + + if (istat/=0) then + write(fates_log(),*) 'dealloc009: fail on deallocate patch vectors:'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + + ! deallocate running means + deallocate(this%tveg24, stat=istat, errmsg=smsg) + if (istat/=0) then + write(fates_log(),*) 'dealloc010: fail on deallocate(this%tveg24):'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + deallocate(this%tveg_lpa, stat=istat, errmsg=smsg) + if (istat/=0) then + write(fates_log(),*) 'dealloc011: fail on deallocate(this%tveg_lpa):'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + deallocate(this%tveg_longterm, stat=istat, errmsg=smsg) + if (istat/=0) then + write(fates_log(),*) 'dealloc012: fail on deallocate(this%tveg_longterm):'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + + end subroutine free_memory + + !:.........................................................................: + subroutine dump(this) ! ! DESCRIPTION: diff --git a/main/FatesCohortMod.F90 b/main/FatesCohortMod.F90 index 8073d70527..c7d15da584 100644 --- a/main/FatesCohortMod.F90 +++ b/main/FatesCohortMod.F90 @@ -19,6 +19,7 @@ module FatesCohortMod use PRTParametersMod, only : prt_params use FatesParameterDerivedMod, only : param_derived use FatesHydraulicsMemMod, only : ed_cohort_hydr_type + use FatesPlantHydraulicsMod, only : CopyCohortHydraulics use FatesInterfaceTypesMod, only : hlm_parteh_mode use FatesInterfaceTypesMod, only : hlm_use_sp use FatesInterfaceTypesMod, only : nleafage @@ -268,6 +269,7 @@ module FatesCohortMod procedure :: nan_values procedure :: zero_values procedure :: create + procedure :: copy procedure :: CanUpperUnder procedure :: InitPRTBoundaryConditions procedure :: UpdateCohortBioPhysRates @@ -620,6 +622,146 @@ end subroutine create !:.........................................................................: + subroutine copy(this, copy_cohort) + ! + ! DESCRIPTION: + ! copies all the variables in one cohort into a new cohort + ! + + ! ARGUMENTS + class(fates_cohort_type), intent(in) :: this ! old cohort + class(fates_cohort_type), intent(inout) :: copy_cohort ! new cohort + + copy_cohort%indexnumber = fates_unset_int + + ! POINTERS + copy_cohort%taller => NULL() + copy_cohort%shorter => NULL() + + ! PRT + call copy_cohort%prt%CopyPRTVartypes(this%prt) + copy_cohort%l2fr = this%l2fr + + ! VEGETATION STRUCTURE + copy_cohort%pft = this%pft + copy_cohort%n = this%n + copy_cohort%dbh = this%dbh + copy_cohort%coage = this%coage + copy_cohort%hite = this%hite + copy_cohort%canopy_layer = this%canopy_layer + copy_cohort%canopy_layer_yesterday = this%canopy_layer_yesterday + copy_cohort%crowndamage = this%crowndamage + copy_cohort%g_sb_laweight = this%g_sb_laweight + copy_cohort%canopy_trim = this%canopy_trim + copy_cohort%leaf_cost = this%leaf_cost + copy_cohort%excl_weight = this%excl_weight + copy_cohort%prom_weight = this%prom_weight + copy_cohort%nv = this%nv + copy_cohort%status_coh = this%status_coh + copy_cohort%c_area = this%c_area + copy_cohort%treelai = this%treelai + copy_cohort%treesai = this%treesai + copy_cohort%isnew = this%isnew + copy_cohort%size_class = this%size_class + copy_cohort%coage_class = this%coage_class + copy_cohort%size_by_pft_class = this%size_by_pft_class + copy_cohort%coage_by_pft_class = this%coage_by_pft_class + copy_cohort%size_class_lasttimestep = this%size_class_lasttimestep + + ! CARBON AND NUTRIENT FLUXES + copy_cohort%gpp_tstep = this%gpp_tstep + copy_cohort%gpp_acc = this%gpp_acc + copy_cohort%gpp_acc_hold = this%gpp_acc_hold + copy_cohort%npp_tstep = this%npp_tstep + copy_cohort%npp_acc = this%npp_acc + copy_cohort%npp_acc_hold = this%npp_acc_hold + copy_cohort%resp_tstep = this%resp_tstep + copy_cohort%resp_acc = this%resp_acc + copy_cohort%resp_acc_hold = this%resp_acc_hold + copy_cohort%c13disc_clm = this%c13disc_clm + copy_cohort%c13disc_acc = this%c13disc_acc + copy_cohort%vcmax25top = this%vcmax25top + copy_cohort%jmax25top = this%jmax25top + copy_cohort%tpu25top = this%tpu25top + copy_cohort%kp25top = this%kp25top + copy_cohort%ts_net_uptake = this%ts_net_uptake + copy_cohort%year_net_uptake = this%year_net_uptake + copy_cohort%cnp_limiter = this%cnp_limiter + + if (debug .and. .not. this%isnew) then + write(fates_log(),*) 'EDcohortDyn Ia ', this%npp_acc + write(fates_log(),*) 'EDcohortDyn Ib ', this%resp_acc + end if + + if (hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) then + copy_cohort%cx_int = this%cx_int + copy_cohort%ema_dcxdt = this%ema_dcxdt + copy_cohort%cx0 = this%cx0 + end if + + copy_cohort%nc_repro = this%nc_repro + copy_cohort%daily_nh4_uptake = this%daily_nh4_uptake + copy_cohort%daily_no3_uptake = this%daily_no3_uptake + copy_cohort%sym_nfix_daily = this%sym_nfix_daily + copy_cohort%sym_nfix_tstep = this%sym_nfix_tstep + copy_cohort%daily_n_gain = this%daily_n_gain + copy_cohort%daily_p_gain = this%daily_p_gain + copy_cohort%daily_c_efflux = this%daily_c_efflux + copy_cohort%daily_n_efflux = this%daily_n_efflux + copy_cohort%daily_p_efflux = this%daily_p_efflux + copy_cohort%daily_n_demand = this%daily_n_demand + copy_cohort%daily_p_demand = this%daily_p_demand + copy_cohort%seed_prod = this%seed_prod + + ! RESPIRATION COMPONENTS + copy_cohort%rdark = this%rdark + copy_cohort%resp_g_tstep = this%resp_g_tstep + copy_cohort%resp_m = this%resp_m + copy_cohort%resp_m_unreduced = this%resp_m_unreduced + copy_cohort%resp_excess = this%resp_excess + copy_cohort%livestem_mr = this%livestem_mr + copy_cohort%livecroot_mr = this%livecroot_mr + copy_cohort%froot_mr = this%froot_mr + + ! DAMAGE + copy_cohort%branch_frac = this%branch_frac + + ! MORTALITY + copy_cohort%dmort = this%dmort + copy_cohort%bmort = this%bmort + copy_cohort%cmort = this%cmort + copy_cohort%hmort = this%hmort + copy_cohort%frmort = this%frmort + copy_cohort%smort = this%smort + copy_cohort%asmort = this%asmort + copy_cohort%dgmort = this%dgmort + copy_cohort%lmort_direct = this%lmort_direct + copy_cohort%lmort_collateral = this%lmort_collateral + copy_cohort%lmort_infra = this%lmort_infra + copy_cohort%l_degrad = this%l_degrad + + ! GROWTH DERIVATIVES + copy_cohort%dndt = this%dndt + copy_cohort%dhdt = this%dhdt + copy_cohort%ddbhdt = this%ddbhdt + copy_cohort%dbdeaddt = this%dbdeaddt + + ! FIRE + copy_cohort%fraction_crown_burned = this%fraction_crown_burned + copy_cohort%cambial_mort = this%cambial_mort + copy_cohort%crownfire_mort = this%crownfire_mort + copy_cohort%fire_mort = this%fire_mort + + ! HYDRAULICS + + if (hlm_use_planthydro .eq. itrue) then + call CopyCohortHydraulics(copy_cohort, this) + endif + + end subroutine copy + + !:.........................................................................: + subroutine InitPRTBoundaryConditions(this) ! ! DESCRIPTION: @@ -627,7 +769,7 @@ subroutine InitPRTBoundaryConditions(this) ! allocation hypotheses. Each of these calls to "RegsterBC" are simply ! setting pointers. ! For instance, if the hypothesis wants to know what - ! the DBH of the plant is, then we pass in the dbh as an argument (new_cohort%dbh), + ! the DBH of the plant is, then we pass in the dbh as an argument (copy_cohort%dbh), ! and also tell it which boundary condition we are talking about (which is ! defined by an integer index (ac_bc_inout_id_dbh) ! @@ -647,48 +789,48 @@ subroutine InitPRTBoundaryConditions(this) select case(hlm_parteh_mode) case (prt_carbon_allom_hyp) - ! Register boundary conditions for the Carbon Only Allometric Hypothesis - - call this%prt%RegisterBCInOut(ac_bc_inout_id_dbh, bc_rval=this%dbh) - call this%prt%RegisterBCInOut(ac_bc_inout_id_netdc, bc_rval=this%npp_acc) - call this%prt%RegisterBCIn(ac_bc_in_id_cdamage, bc_ival=this%crowndamage) - call this%prt%RegisterBCIn(ac_bc_in_id_pft, bc_ival=this%pft) - call this%prt%RegisterBCIn(ac_bc_in_id_ctrim, bc_rval=this%canopy_trim) - call this%prt%RegisterBCIn(ac_bc_in_id_lstat, bc_ival=this%status_coh) - + ! Register boundary conditions for the Carbon Only Allometric Hypothesis + + call this%prt%RegisterBCInOut(ac_bc_inout_id_dbh, bc_rval=this%dbh) + call this%prt%RegisterBCInOut(ac_bc_inout_id_netdc, bc_rval=this%npp_acc) + call this%prt%RegisterBCIn(ac_bc_in_id_cdamage, bc_ival=this%crowndamage) + call this%prt%RegisterBCIn(ac_bc_in_id_pft, bc_ival=this%pft) + call this%prt%RegisterBCIn(ac_bc_in_id_ctrim, bc_rval=this%canopy_trim) + call this%prt%RegisterBCIn(ac_bc_in_id_lstat, bc_ival=this%status_coh) + case (prt_cnp_flex_allom_hyp) - ! Register boundary conditions for the CNP Allometric Hypothesis - - call this%prt%RegisterBCIn(acnp_bc_in_id_pft, bc_ival=this%pft) - call this%prt%RegisterBCIn(acnp_bc_in_id_ctrim, bc_rval=this%canopy_trim) - call this%prt%RegisterBCIn(acnp_bc_in_id_lstat, bc_ival=this%status_coh) - call this%prt%RegisterBCIn(acnp_bc_in_id_netdc, bc_rval=this%npp_acc) - - call this%prt%RegisterBCIn(acnp_bc_in_id_nc_repro, bc_rval=this%nc_repro) - call this%prt%RegisterBCIn(acnp_bc_in_id_pc_repro, bc_rval=this%pc_repro) - call this%prt%RegisterBCIn(acnp_bc_in_id_cdamage, bc_ival=this%crowndamage) - - call this%prt%RegisterBCInOut(acnp_bc_inout_id_dbh, bc_rval=this%dbh) - call this%prt%RegisterBCInOut(acnp_bc_inout_id_resp_excess, bc_rval=this%resp_excess) - call this%prt%RegisterBCInOut(acnp_bc_inout_id_l2fr, bc_rval=this%l2fr) - call this%prt%RegisterBCInOut(acnp_bc_inout_id_cx_int, bc_rval=this%cx_int) - call this%prt%RegisterBCInOut(acnp_bc_inout_id_emadcxdt, bc_rval=this%ema_dcxdt) - call this%prt%RegisterBCInOut(acnp_bc_inout_id_cx0, bc_rval=this%cx0) - - call this%prt%RegisterBCInOut(acnp_bc_inout_id_netdn, bc_rval=this%daily_n_gain) - call this%prt%RegisterBCInOut(acnp_bc_inout_id_netdp, bc_rval=this%daily_p_gain) - - call this%prt%RegisterBCOut(acnp_bc_out_id_cefflux, bc_rval=this%daily_c_efflux) - call this%prt%RegisterBCOut(acnp_bc_out_id_nefflux, bc_rval=this%daily_n_efflux) - call this%prt%RegisterBCOut(acnp_bc_out_id_pefflux, bc_rval=this%daily_p_efflux) - call this%prt%RegisterBCOut(acnp_bc_out_id_limiter, bc_ival=this%cnp_limiter) - + ! Register boundary conditions for the CNP Allometric Hypothesis + + call this%prt%RegisterBCIn(acnp_bc_in_id_pft, bc_ival=this%pft) + call this%prt%RegisterBCIn(acnp_bc_in_id_ctrim, bc_rval=this%canopy_trim) + call this%prt%RegisterBCIn(acnp_bc_in_id_lstat, bc_ival=this%status_coh) + call this%prt%RegisterBCIn(acnp_bc_in_id_netdc, bc_rval=this%npp_acc) + + call this%prt%RegisterBCIn(acnp_bc_in_id_nc_repro, bc_rval=this%nc_repro) + call this%prt%RegisterBCIn(acnp_bc_in_id_pc_repro, bc_rval=this%pc_repro) + call this%prt%RegisterBCIn(acnp_bc_in_id_cdamage, bc_ival=this%crowndamage) + + call this%prt%RegisterBCInOut(acnp_bc_inout_id_dbh, bc_rval=this%dbh) + call this%prt%RegisterBCInOut(acnp_bc_inout_id_resp_excess, bc_rval=this%resp_excess) + call this%prt%RegisterBCInOut(acnp_bc_inout_id_l2fr, bc_rval=this%l2fr) + call this%prt%RegisterBCInOut(acnp_bc_inout_id_cx_int, bc_rval=this%cx_int) + call this%prt%RegisterBCInOut(acnp_bc_inout_id_emadcxdt, bc_rval=this%ema_dcxdt) + call this%prt%RegisterBCInOut(acnp_bc_inout_id_cx0, bc_rval=this%cx0) + + call this%prt%RegisterBCInOut(acnp_bc_inout_id_netdn, bc_rval=this%daily_n_gain) + call this%prt%RegisterBCInOut(acnp_bc_inout_id_netdp, bc_rval=this%daily_p_gain) + + call this%prt%RegisterBCOut(acnp_bc_out_id_cefflux, bc_rval=this%daily_c_efflux) + call this%prt%RegisterBCOut(acnp_bc_out_id_nefflux, bc_rval=this%daily_n_efflux) + call this%prt%RegisterBCOut(acnp_bc_out_id_pefflux, bc_rval=this%daily_p_efflux) + call this%prt%RegisterBCOut(acnp_bc_out_id_limiter, bc_ival=this%cnp_limiter) + case DEFAULT - write(fates_log(),*) 'You specified an unknown PRT module' - write(fates_log(),*) 'Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) 'You specified an unknown PRT module' + write(fates_log(),*) 'Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) end select @@ -746,15 +888,15 @@ subroutine UpdateCohortBioPhysRates(this) this%kp25top = sum(param_derived%kp25top(ipft, 1:nleafage)* & frac_leaf_aclass(1:nleafage)) - else if (hlm_use_sp .eq. itrue) then + else if (hlm_use_sp .eq. itrue) then - this%vcmax25top = EDPftvarcon_inst%vcmax25top(ipft, 1) - this%jmax25top = param_derived%jmax25top(ipft, 1) - this%tpu25top = param_derived%tpu25top(ipft, 1) - this%kp25top = param_derived%kp25top(ipft, 1) + this%vcmax25top = EDPftvarcon_inst%vcmax25top(ipft, 1) + this%jmax25top = param_derived%jmax25top(ipft, 1) + this%tpu25top = param_derived%tpu25top(ipft, 1) + this%kp25top = param_derived%kp25top(ipft, 1) else - + this%vcmax25top = 0._r8 this%jmax25top = 0._r8 this%tpu25top = 0._r8 @@ -762,8 +904,6 @@ subroutine UpdateCohortBioPhysRates(this) end if - return - end subroutine UpdateCohortBioPhysRates !:.........................................................................: @@ -805,80 +945,78 @@ subroutine dump(this) write(fates_log(),*) '----------------------------------------' write(fates_log(),*) ' Dumping Cohort Information ' write(fates_log(),*) '----------------------------------------' - write(fates_log(),*) 'co%pft = ', this%pft - write(fates_log(),*) 'co%n = ', this%n - write(fates_log(),*) 'co%dbh = ', this%dbh - write(fates_log(),*) 'co%hite = ', this%hite - write(fates_log(),*) 'co%crowndamage = ', this%crowndamage - write(fates_log(),*) 'co%coage = ', this%coage - write(fates_log(),*) 'co%l2fr = ', this%l2fr + write(fates_log(),*) 'cthis%pft = ', this%pft + write(fates_log(),*) 'cthis%n = ', this%n + write(fates_log(),*) 'cthis%dbh = ', this%dbh + write(fates_log(),*) 'cthis%hite = ', this%hite + write(fates_log(),*) 'cthis%crowndamage = ', this%crowndamage + write(fates_log(),*) 'cthis%coage = ', this%coage + write(fates_log(),*) 'cthis%l2fr = ', this%l2fr write(fates_log(),*) 'leaf carbon = ', this%prt%GetState(leaf_organ,carbon12_element) write(fates_log(),*) 'fineroot carbon = ', this%prt%GetState(fnrt_organ,carbon12_element) write(fates_log(),*) 'sapwood carbon = ', this%prt%GetState(sapw_organ,carbon12_element) write(fates_log(),*) 'structural (dead) carbon = ', this%prt%GetState(struct_organ,carbon12_element) write(fates_log(),*) 'storage carbon = ', this%prt%GetState(store_organ,carbon12_element) write(fates_log(),*) 'reproductive carbon = ', this%prt%GetState(repro_organ,carbon12_element) - write(fates_log(),*) 'co%g_sb_laweight = ', this%g_sb_laweight - write(fates_log(),*) 'co%leaf_cost = ', this%leaf_cost - write(fates_log(),*) 'co%canopy_layer = ', this%canopy_layer - write(fates_log(),*) 'co%canopy_layer_yesterday = ', this%canopy_layer_yesterday - write(fates_log(),*) 'co%nv = ', this%nv - write(fates_log(),*) 'co%status_coh = ', this%status_coh - write(fates_log(),*) 'co%canopy_trim = ', this%canopy_trim - write(fates_log(),*) 'co%excl_weight = ', this%excl_weight - write(fates_log(),*) 'co%prom_weight = ', this%prom_weight - write(fates_log(),*) 'co%size_class = ', this%size_class - write(fates_log(),*) 'co%size_by_pft_class = ', this%size_by_pft_class - write(fates_log(),*) 'co%coage_class = ', this%coage_class - write(fates_log(),*) 'co%coage_by_pft_class = ', this%coage_by_pft_class - write(fates_log(),*) 'co%gpp_acc_hold = ', this%gpp_acc_hold - write(fates_log(),*) 'co%gpp_acc = ', this%gpp_acc - write(fates_log(),*) 'co%gpp_tstep = ', this%gpp_tstep - write(fates_log(),*) 'co%npp_acc_hold = ', this%npp_acc_hold - write(fates_log(),*) 'co%npp_tstep = ', this%npp_tstep - write(fates_log(),*) 'co%npp_acc = ', this%npp_acc - write(fates_log(),*) 'co%resp_tstep = ', this%resp_tstep - write(fates_log(),*) 'co%resp_acc = ', this%resp_acc - write(fates_log(),*) 'co%resp_acc_hold = ', this%resp_acc_hold - write(fates_log(),*) 'co%rdark = ', this%rdark - write(fates_log(),*) 'co%resp_m = ', this%resp_m - write(fates_log(),*) 'co%resp_g_tstep = ', this%resp_g_tstep - write(fates_log(),*) 'co%livestem_mr = ', this%livestem_mr - write(fates_log(),*) 'co%livecroot_mr = ', this%livecroot_mr - write(fates_log(),*) 'co%froot_mr = ', this%froot_mr - write(fates_log(),*) 'co%dgmort = ', this%dgmort - write(fates_log(),*) 'co%treelai = ', this%treelai - write(fates_log(),*) 'co%treesai = ', this%treesai - write(fates_log(),*) 'co%c_area = ', this%c_area - write(fates_log(),*) 'co%cmort = ', this%cmort - write(fates_log(),*) 'co%bmort = ', this%bmort - write(fates_log(),*) 'co%smort = ', this%smort - write(fates_log(),*) 'co%asmort = ', this%asmort - write(fates_log(),*) 'co%dgmort = ', this%dgmort - write(fates_log(),*) 'co%hmort = ', this%hmort - write(fates_log(),*) 'co%frmort = ', this%frmort - write(fates_log(),*) 'co%asmort = ', this%asmort - write(fates_log(),*) 'co%lmort_direct = ', this%lmort_direct - write(fates_log(),*) 'co%lmort_collateral = ', this%lmort_collateral - write(fates_log(),*) 'co%lmort_infra = ', this%lmort_infra - write(fates_log(),*) 'co%isnew = ', this%isnew - write(fates_log(),*) 'co%dndt = ', this%dndt - write(fates_log(),*) 'co%dhdt = ', this%dhdt - write(fates_log(),*) 'co%ddbhdt = ', this%ddbhdt - write(fates_log(),*) 'co%dbdeaddt = ', this%dbdeaddt - write(fates_log(),*) 'co%fraction_crown_burned = ', this%fraction_crown_burned - write(fates_log(),*) 'co%fire_mort = ', this%fire_mort - write(fates_log(),*) 'co%crownfire_mort = ', this%crownfire_mort - write(fates_log(),*) 'co%cambial_mort = ', this%cambial_mort - write(fates_log(),*) 'co%size_class = ', this%size_class - write(fates_log(),*) 'co%size_by_pft_class = ', this%size_by_pft_class + write(fates_log(),*) 'cthis%g_sb_laweight = ', this%g_sb_laweight + write(fates_log(),*) 'cthis%leaf_cost = ', this%leaf_cost + write(fates_log(),*) 'cthis%canopy_layer = ', this%canopy_layer + write(fates_log(),*) 'cthis%canopy_layer_yesterday = ', this%canopy_layer_yesterday + write(fates_log(),*) 'cthis%nv = ', this%nv + write(fates_log(),*) 'cthis%status_coh = ', this%status_coh + write(fates_log(),*) 'cthis%canopy_trim = ', this%canopy_trim + write(fates_log(),*) 'cthis%excl_weight = ', this%excl_weight + write(fates_log(),*) 'cthis%prom_weight = ', this%prom_weight + write(fates_log(),*) 'cthis%size_class = ', this%size_class + write(fates_log(),*) 'cthis%size_by_pft_class = ', this%size_by_pft_class + write(fates_log(),*) 'cthis%coage_class = ', this%coage_class + write(fates_log(),*) 'cthis%coage_by_pft_class = ', this%coage_by_pft_class + write(fates_log(),*) 'cthis%gpp_acc_hold = ', this%gpp_acc_hold + write(fates_log(),*) 'cthis%gpp_acc = ', this%gpp_acc + write(fates_log(),*) 'cthis%gpp_tstep = ', this%gpp_tstep + write(fates_log(),*) 'cthis%npp_acc_hold = ', this%npp_acc_hold + write(fates_log(),*) 'cthis%npp_tstep = ', this%npp_tstep + write(fates_log(),*) 'cthis%npp_acc = ', this%npp_acc + write(fates_log(),*) 'cthis%resp_tstep = ', this%resp_tstep + write(fates_log(),*) 'cthis%resp_acc = ', this%resp_acc + write(fates_log(),*) 'cthis%resp_acc_hold = ', this%resp_acc_hold + write(fates_log(),*) 'cthis%rdark = ', this%rdark + write(fates_log(),*) 'cthis%resp_m = ', this%resp_m + write(fates_log(),*) 'cthis%resp_g_tstep = ', this%resp_g_tstep + write(fates_log(),*) 'cthis%livestem_mr = ', this%livestem_mr + write(fates_log(),*) 'cthis%livecroot_mr = ', this%livecroot_mr + write(fates_log(),*) 'cthis%froot_mr = ', this%froot_mr + write(fates_log(),*) 'cthis%dgmort = ', this%dgmort + write(fates_log(),*) 'cthis%treelai = ', this%treelai + write(fates_log(),*) 'cthis%treesai = ', this%treesai + write(fates_log(),*) 'cthis%c_area = ', this%c_area + write(fates_log(),*) 'cthis%cmort = ', this%cmort + write(fates_log(),*) 'cthis%bmort = ', this%bmort + write(fates_log(),*) 'cthis%smort = ', this%smort + write(fates_log(),*) 'cthis%asmort = ', this%asmort + write(fates_log(),*) 'cthis%dgmort = ', this%dgmort + write(fates_log(),*) 'cthis%hmort = ', this%hmort + write(fates_log(),*) 'cthis%frmort = ', this%frmort + write(fates_log(),*) 'cthis%asmort = ', this%asmort + write(fates_log(),*) 'cthis%lmort_direct = ', this%lmort_direct + write(fates_log(),*) 'cthis%lmort_collateral = ', this%lmort_collateral + write(fates_log(),*) 'cthis%lmort_infra = ', this%lmort_infra + write(fates_log(),*) 'cthis%isnew = ', this%isnew + write(fates_log(),*) 'cthis%dndt = ', this%dndt + write(fates_log(),*) 'cthis%dhdt = ', this%dhdt + write(fates_log(),*) 'cthis%ddbhdt = ', this%ddbhdt + write(fates_log(),*) 'cthis%dbdeaddt = ', this%dbdeaddt + write(fates_log(),*) 'cthis%fraction_crown_burned = ', this%fraction_crown_burned + write(fates_log(),*) 'cthis%fire_mort = ', this%fire_mort + write(fates_log(),*) 'cthis%crownfire_mort = ', this%crownfire_mort + write(fates_log(),*) 'cthis%cambial_mort = ', this%cambial_mort + write(fates_log(),*) 'cthis%size_class = ', this%size_class + write(fates_log(),*) 'cthis%size_by_pft_class = ', this%size_by_pft_class if (associated(this%co_hydr)) call this%co_hydr%dump() write(fates_log(),*) '----------------------------------------' - return - end subroutine dump !:.........................................................................: From ce12d059959ddb5266f4a4315fa2629f1c33888d Mon Sep 17 00:00:00 2001 From: adrifoster Date: Thu, 4 May 2023 11:40:33 -0600 Subject: [PATCH 664/852] update for refactor --- biogeochem/EDCohortDynamicsMod.F90 | 32 ++---------------------------- biogeochem/EDPatchDynamicsMod.F90 | 3 +-- biogeochem/FatesPatchMod.F90 | 2 +- main/FatesCohortMod.F90 | 31 +++++++++++++++++++++++++++++ 4 files changed, 35 insertions(+), 33 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index a910bee762..d1ce6efc35 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -125,7 +125,6 @@ Module EDCohortDynamicsMod public :: count_cohorts public :: InitPRTObject public :: SendCohortToLitter - public :: DeallocateCohort public :: EvaluateAndCorrectDBH public :: DamageRecovery @@ -546,7 +545,7 @@ subroutine terminate_cohort(currentSite, currentPatch, currentCohort, bc_in) shorterCohort%taller => tallerCohort endif - call DeallocateCohort(currentCohort) + call currentCohort%free_memory() end subroutine terminate_cohort @@ -681,34 +680,7 @@ end subroutine SendCohortToLitter !-------------------------------------------------------------------------------------- - subroutine DeallocateCohort(currentCohort) - ! ---------------------------------------------------------------------------------- - ! This subroutine deallocates all dynamic memory and objects - ! inside the cohort structure. This DOES NOT deallocate - ! the cohort structure itself. - ! ---------------------------------------------------------------------------------- - - type(fates_cohort_type),intent(inout) :: currentCohort - integer :: istat ! return status code - character(len=255) :: smsg - - ! At this point, nothing should be pointing to current Cohort - if (hlm_use_planthydro.eq.itrue) call DeallocateHydrCohort(currentCohort) - - ! Deallocate the cohort's PRT structures - call currentCohort%prt%DeallocatePRTVartypes() - - ! Deallocate the PRT object - - deallocate(currentCohort%prt, stat=istat, errmsg=smsg) - if (istat/=0) then - write(fates_log(),*) 'dealloc002: fail in deallocate(currentCohort%prt):'//trim(smsg) - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - - return - end subroutine DeallocateCohort subroutine fuse_cohorts(currentSite, currentPatch, bc_in) @@ -1186,7 +1158,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) call UpdateSizeDepPlantHydProps(currentSite,currentCohort, bc_in) endif - call DeallocateCohort(nextc) + call nextc%free_memory() deallocate(nextc, stat=istat, errmsg=smsg) if (istat/=0) then write(fates_log(),*) 'dealloc003: fail on deallocate(nextc):'//trim(smsg) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 3aaba6fb31..c5bfabd6ec 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -11,7 +11,6 @@ module EDPatchDynamicsMod use EDPftvarcon , only : GetDecompyFrac use PRTParametersMod , only : prt_params use EDCohortDynamicsMod , only : fuse_cohorts, sort_cohorts, insert_cohort - use EDCohortDynamicsMod , only : DeallocateCohort use EDTypesMod , only : area_site => area use ChecksBalancesMod , only : PatchMassStock use FatesLitterMod , only : ncwd @@ -1110,7 +1109,7 @@ subroutine spawn_patches( currentSite, bc_in) else ! Get rid of the new temporary cohort - call DeallocateCohort(nc) + call nc%free_memory() deallocate(nc, stat=istat, errmsg=smsg) if (istat/=0) then write(fates_log(),*) 'dealloc005: fail on deallocate(nc):'//trim(smsg) diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 index ae536a9cb5..26eb43583f 100644 --- a/biogeochem/FatesPatchMod.F90 +++ b/biogeochem/FatesPatchMod.F90 @@ -620,7 +620,7 @@ subroutine free_memory(this) ccohort => this%shortest do while(associated(ccohort)) ncohort => ccohort%taller - call DeallocateCohort(ccohort) + call ccohort%free_memory() deallocate(ccohort, stat=istat, errmsg=smsg) if (istat /= 0) then write(fates_log(),*) 'dealloc007: fail on deallocate(cchort):'//trim(smsg) diff --git a/main/FatesCohortMod.F90 b/main/FatesCohortMod.F90 index c7d15da584..9cf451a5e8 100644 --- a/main/FatesCohortMod.F90 +++ b/main/FatesCohortMod.F90 @@ -760,6 +760,37 @@ subroutine copy(this, copy_cohort) end subroutine copy + !:.........................................................................: + + subroutine free_memory(this) + ! + ! DESCRIPTION: + ! deallocates all dynamic memory and objects within the cohort structure + ! DOES NOT deallocate the cohort structure itself + ! + + ! ARGUMENTS + type(fates_cohort_type), intent(inout) :: this ! cohort object + + ! LOCALS: + integer :: istat ! return status code + character(len=255) :: smsg ! error message + + ! at this point, nothing should be pointing to current cohort + if (hlm_use_planthydro .eq. itrue) call DeallocateHydrCohort(this) + + ! deallocate the cohort's PRT structures + call this%prt%DeallocatePRTVartypes() + + ! Deallocate the PRT object + deallocate(this%prt, stat=istat, errmsg=smsg) + if (istat /= 0) then + write(fates_log(),*) 'dealloc002: fail in deallocate(currentCohort%prt):'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + + end subroutine free_memory + !:.........................................................................: subroutine InitPRTBoundaryConditions(this) From 34b0fa04aab1a691e354682e279b6b9ec41f87fc Mon Sep 17 00:00:00 2001 From: adrifoster Date: Thu, 4 May 2023 13:58:31 -0600 Subject: [PATCH 665/852] fix circular dependencies with hydraulics objects --- biogeochem/FatesPatchMod.F90 | 20 ++++---- biogeophys/FatesPlantHydraulicsMod.F90 | 69 -------------------------- main/FatesCohortMod.F90 | 20 ++++---- main/FatesHydraulicsMemMod.F90 | 64 +++++++++++++++++++++++- 4 files changed, 83 insertions(+), 90 deletions(-) diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 index 26eb43583f..22103fc6a7 100644 --- a/biogeochem/FatesPatchMod.F90 +++ b/biogeochem/FatesPatchMod.F90 @@ -5,6 +5,7 @@ module FatesPatchMod use FatesConstantsMod, only : fates_unset_int use FatesConstantsMod, only : primaryforest, secondaryforest use FatesGlobals, only : fates_log + use FatesGlobals, only : endrun => fates_endrun use FatesUtilsMod, only : check_hlm_list use FatesUtilsMod, only : check_var_real use FatesCohortMod, only : fates_cohort_type @@ -20,6 +21,7 @@ module FatesPatchMod use FatesRunningMeanMod, only : ema_24hr, fixed_24hr, ema_lpa, ema_longterm use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) + use shr_log_mod, only : errMsg => shr_log_errMsg implicit none private @@ -558,18 +560,18 @@ subroutine create(this, age, areap, label, nocomp_pft, numSWb, numpft, & ! ARGUMENTS: class(fates_patch_type), intent(inout) :: this ! patch object - real(r8), intent(in) :: age ! notional age of this patch in years - real(r8), intent(in) :: areap ! initial area of this patch in m2. - integer, intent(in) :: label ! anthropogenic disturbance label - integer, intent(in) :: nocomp_pft ! no-competition mode pft label - integer, intent(in) :: numSWb ! number of shortwave broad-bands to track - integer, intent(in) :: numpft ! number of pfts to simulate - integer, intent(in) :: nlevsoil ! number of soil layers - integer, intent(in) :: current_tod ! time of day [seconds past 0Z] + real(r8), intent(in) :: age ! notional age of this patch in years + real(r8), intent(in) :: areap ! initial area of this patch in m2. + integer, intent(in) :: label ! anthropogenic disturbance label + integer, intent(in) :: nocomp_pft ! no-competition mode pft label + integer, intent(in) :: numSWb ! number of shortwave broad-bands to track + integer, intent(in) :: numpft ! number of pfts to simulate + integer, intent(in) :: nlevsoil ! number of soil layers + integer, intent(in) :: current_tod ! time of day [seconds past 0Z] ! initialize patch ! sets all values to nan, then some values to zero - call this%init(numSWb, nlevsoil) + call this%init(numpft, numSWb, nlevsoil) ! initialize running means for patch call this%init_running_means(current_tod) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 4b52cea541..7a38028db1 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -252,7 +252,6 @@ module FatesPlantHydraulicsMod public :: InitHydrCohort public :: DeallocateHydrCohort public :: UpdateH2OVeg - public :: CopyCohortHydraulics public :: FuseCohortHydraulics public :: UpdateSizeDepPlantHydProps public :: UpdateSizeDepPlantHydStates @@ -1195,74 +1194,6 @@ end function constrain_water_contents ! ===================================================================================== -subroutine CopyCohortHydraulics(newCohort, oldCohort) - - ! Arguments - type(fates_cohort_type), intent(inout), target :: newCohort - type(fates_cohort_type), intent(inout), target :: oldCohort - - ! Locals - type(ed_cohort_hydr_type), pointer :: ncohort_hydr - type(ed_cohort_hydr_type), pointer :: ocohort_hydr - - - ncohort_hydr => newCohort%co_hydr - ocohort_hydr => oldCohort%co_hydr - - ! Node heights - ncohort_hydr%z_node_ag = ocohort_hydr%z_node_ag - ncohort_hydr%z_upper_ag = ocohort_hydr%z_upper_ag - ncohort_hydr%z_lower_ag = ocohort_hydr%z_lower_ag - ncohort_hydr%z_node_troot = ocohort_hydr%z_node_troot - - ! Compartment kmax's - ncohort_hydr%kmax_petiole_to_leaf = ocohort_hydr%kmax_petiole_to_leaf - ncohort_hydr%kmax_stem_lower = ocohort_hydr%kmax_stem_lower - ncohort_hydr%kmax_stem_upper = ocohort_hydr%kmax_stem_upper - ncohort_hydr%kmax_troot_upper = ocohort_hydr%kmax_troot_upper - ncohort_hydr%kmax_troot_lower = ocohort_hydr%kmax_troot_lower - ncohort_hydr%kmax_aroot_upper = ocohort_hydr%kmax_aroot_upper - ncohort_hydr%kmax_aroot_lower = ocohort_hydr%kmax_aroot_lower - ncohort_hydr%kmax_aroot_radial_in = ocohort_hydr%kmax_aroot_radial_in - ncohort_hydr%kmax_aroot_radial_out = ocohort_hydr%kmax_aroot_radial_out - - ! Compartment volumes - ncohort_hydr%v_ag_init = ocohort_hydr%v_ag_init - ncohort_hydr%v_ag = ocohort_hydr%v_ag - ncohort_hydr%v_troot_init = ocohort_hydr%v_troot_init - ncohort_hydr%v_troot = ocohort_hydr%v_troot - ncohort_hydr%v_aroot_layer_init = ocohort_hydr%v_aroot_layer_init - ncohort_hydr%v_aroot_layer = ocohort_hydr%v_aroot_layer - ncohort_hydr%l_aroot_layer = ocohort_hydr%l_aroot_layer - - ! State Variables - ncohort_hydr%th_ag = ocohort_hydr%th_ag - ncohort_hydr%th_troot = ocohort_hydr%th_troot - ncohort_hydr%th_aroot = ocohort_hydr%th_aroot - ncohort_hydr%psi_ag = ocohort_hydr%psi_ag - ncohort_hydr%psi_troot = ocohort_hydr%psi_troot - ncohort_hydr%psi_aroot = ocohort_hydr%psi_aroot - ncohort_hydr%ftc_ag = ocohort_hydr%ftc_ag - ncohort_hydr%ftc_troot = ocohort_hydr%ftc_troot - ncohort_hydr%ftc_aroot = ocohort_hydr%ftc_aroot - - ! Other - ncohort_hydr%btran = ocohort_hydr%btran - ncohort_hydr%supsub_flag = ocohort_hydr%supsub_flag - ncohort_hydr%iterh1 = ocohort_hydr%iterh1 - ncohort_hydr%iterh2 = ocohort_hydr%iterh2 - ncohort_hydr%iterlayer = ocohort_hydr%iterlayer - ncohort_hydr%errh2o = ocohort_hydr%errh2o - - - ! BC PLANT HYDRAULICS - flux terms - ncohort_hydr%qtop = ocohort_hydr%qtop - - ncohort_hydr%is_newly_recruited = ocohort_hydr%is_newly_recruited - -end subroutine CopyCohortHydraulics - -! ===================================================================================== subroutine FuseCohortHydraulics(currentSite,currentCohort, nextCohort, bc_in, newn) diff --git a/main/FatesCohortMod.F90 b/main/FatesCohortMod.F90 index 9cf451a5e8..7cacf59c83 100644 --- a/main/FatesCohortMod.F90 +++ b/main/FatesCohortMod.F90 @@ -19,9 +19,9 @@ module FatesCohortMod use PRTParametersMod, only : prt_params use FatesParameterDerivedMod, only : param_derived use FatesHydraulicsMemMod, only : ed_cohort_hydr_type - use FatesPlantHydraulicsMod, only : CopyCohortHydraulics use FatesInterfaceTypesMod, only : hlm_parteh_mode use FatesInterfaceTypesMod, only : hlm_use_sp + use FatesInterfaceTypesMod, only : hlm_use_planthydro use FatesInterfaceTypesMod, only : nleafage use EDPftvarcon, only : EDPftvarcon_inst use FatesSizeAgeTypeIndicesMod, only : sizetype_class_index @@ -270,6 +270,7 @@ module FatesCohortMod procedure :: zero_values procedure :: create procedure :: copy + procedure :: free_memory procedure :: CanUpperUnder procedure :: InitPRTBoundaryConditions procedure :: UpdateCohortBioPhysRates @@ -630,7 +631,7 @@ subroutine copy(this, copy_cohort) ! ARGUMENTS class(fates_cohort_type), intent(in) :: this ! old cohort - class(fates_cohort_type), intent(inout) :: copy_cohort ! new cohort + class(fates_cohort_type), intent(inout) :: copy_cohort ! new cohort copy_cohort%indexnumber = fates_unset_int @@ -688,11 +689,6 @@ subroutine copy(this, copy_cohort) copy_cohort%year_net_uptake = this%year_net_uptake copy_cohort%cnp_limiter = this%cnp_limiter - if (debug .and. .not. this%isnew) then - write(fates_log(),*) 'EDcohortDyn Ia ', this%npp_acc - write(fates_log(),*) 'EDcohortDyn Ib ', this%resp_acc - end if - if (hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) then copy_cohort%cx_int = this%cx_int copy_cohort%ema_dcxdt = this%ema_dcxdt @@ -753,9 +749,8 @@ subroutine copy(this, copy_cohort) copy_cohort%fire_mort = this%fire_mort ! HYDRAULICS - if (hlm_use_planthydro .eq. itrue) then - call CopyCohortHydraulics(copy_cohort, this) + call copy_cohort%co_hydr%CopyCohortHydraulics(this%co_hydr) endif end subroutine copy @@ -770,14 +765,17 @@ subroutine free_memory(this) ! ! ARGUMENTS - type(fates_cohort_type), intent(inout) :: this ! cohort object + class(fates_cohort_type), intent(inout) :: this ! cohort object ! LOCALS: integer :: istat ! return status code character(len=255) :: smsg ! error message ! at this point, nothing should be pointing to current cohort - if (hlm_use_planthydro .eq. itrue) call DeallocateHydrCohort(this) + if (hlm_use_planthydro .eq. itrue) then + call this%co_hydr%DeAllocateHydrCohortArrays() + deallocate(this%co_hydr) + end if ! deallocate the cohort's PRT structures call this%prt%DeallocatePRTVartypes() diff --git a/main/FatesHydraulicsMemMod.F90 b/main/FatesHydraulicsMemMod.F90 index 22ade5f9b6..856599f2e5 100644 --- a/main/FatesHydraulicsMemMod.F90 +++ b/main/FatesHydraulicsMemMod.F90 @@ -315,12 +315,74 @@ module FatesHydraulicsMemMod procedure :: AllocateHydrCohortArrays procedure :: DeallocateHydrCohortArrays + procedure :: CopyCohortHydraulics procedure :: dump end type ed_cohort_hydr_type contains - + + subroutine CopyCohortHydraulics(ncohort_hydr, ocohort_hydr) + + ! Arguments + class(ed_cohort_hydr_type), intent(inout) :: ncohort_hydr + class(ed_cohort_hydr_type), intent(inout) :: ocohort_hydr + + ! Node heights + ncohort_hydr%z_node_ag = ocohort_hydr%z_node_ag + ncohort_hydr%z_upper_ag = ocohort_hydr%z_upper_ag + ncohort_hydr%z_lower_ag = ocohort_hydr%z_lower_ag + ncohort_hydr%z_node_troot = ocohort_hydr%z_node_troot + + ! Compartment kmax's + ncohort_hydr%kmax_petiole_to_leaf = ocohort_hydr%kmax_petiole_to_leaf + ncohort_hydr%kmax_stem_lower = ocohort_hydr%kmax_stem_lower + ncohort_hydr%kmax_stem_upper = ocohort_hydr%kmax_stem_upper + ncohort_hydr%kmax_troot_upper = ocohort_hydr%kmax_troot_upper + ncohort_hydr%kmax_troot_lower = ocohort_hydr%kmax_troot_lower + ncohort_hydr%kmax_aroot_upper = ocohort_hydr%kmax_aroot_upper + ncohort_hydr%kmax_aroot_lower = ocohort_hydr%kmax_aroot_lower + ncohort_hydr%kmax_aroot_radial_in = ocohort_hydr%kmax_aroot_radial_in + ncohort_hydr%kmax_aroot_radial_out = ocohort_hydr%kmax_aroot_radial_out + + ! Compartment volumes + ncohort_hydr%v_ag_init = ocohort_hydr%v_ag_init + ncohort_hydr%v_ag = ocohort_hydr%v_ag + ncohort_hydr%v_troot_init = ocohort_hydr%v_troot_init + ncohort_hydr%v_troot = ocohort_hydr%v_troot + ncohort_hydr%v_aroot_layer_init = ocohort_hydr%v_aroot_layer_init + ncohort_hydr%v_aroot_layer = ocohort_hydr%v_aroot_layer + ncohort_hydr%l_aroot_layer = ocohort_hydr%l_aroot_layer + + ! State Variables + ncohort_hydr%th_ag = ocohort_hydr%th_ag + ncohort_hydr%th_troot = ocohort_hydr%th_troot + ncohort_hydr%th_aroot = ocohort_hydr%th_aroot + ncohort_hydr%psi_ag = ocohort_hydr%psi_ag + ncohort_hydr%psi_troot = ocohort_hydr%psi_troot + ncohort_hydr%psi_aroot = ocohort_hydr%psi_aroot + ncohort_hydr%ftc_ag = ocohort_hydr%ftc_ag + ncohort_hydr%ftc_troot = ocohort_hydr%ftc_troot + ncohort_hydr%ftc_aroot = ocohort_hydr%ftc_aroot + + ! Other + ncohort_hydr%btran = ocohort_hydr%btran + ncohort_hydr%supsub_flag = ocohort_hydr%supsub_flag + ncohort_hydr%iterh1 = ocohort_hydr%iterh1 + ncohort_hydr%iterh2 = ocohort_hydr%iterh2 + ncohort_hydr%iterlayer = ocohort_hydr%iterlayer + ncohort_hydr%errh2o = ocohort_hydr%errh2o + + + ! BC PLANT HYDRAULICS - flux terms + ncohort_hydr%qtop = ocohort_hydr%qtop + + ncohort_hydr%is_newly_recruited = ocohort_hydr%is_newly_recruited + + end subroutine CopyCohortHydraulics + + ! ========================================================================== + subroutine AllocateHydrCohortArrays(this,nlevrhiz) ! Arguments From d879aea4721ed30223d2c313e20d20df69cbd4a5 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 4 May 2023 15:26:04 -0700 Subject: [PATCH 666/852] converting variables to snake case --- tools/luh2mod.py | 127 ++++++++++++++++++++++++----------------------- 1 file changed, 64 insertions(+), 63 deletions(-) diff --git a/tools/luh2mod.py b/tools/luh2mod.py index 27174a2b13..33ab993d98 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -12,34 +12,34 @@ def main(): # Add argument parser - subfunction? Seperate common module? - # inputfiles and range should be the only arguments + # input_files and range should be the only arguments # Allow variable input files (state and/or transitions and/or management) args = CommandLineArgs() # Prep the LUH2 data - ds_luh2 = PrepDataSet(args.luh2file,args.begin,args.end) + ds_luh2 = PrepDataSet(args.luh2_file,args.begin,args.end) # Prep the regrid target (assuming surface dataset) - ds_regridtarget= PrepDataSet(args.regridtargetfile,args.begin,args.end) + ds_regrid_target= PrepDataSet(args.regrid_target_file,args.begin,args.end) # Build regridder - regridder = RegridConservative(ds_luh2, ds_regridtarget, save=True) + regridder = RegridConservative(ds_luh2, ds_regrid_target, save=True) # Regrid the dataset(s) regrid_luh2 = regridder(ds_states) # Rename the dimensions for the output regrid_luh2 = regrid_luh2.rename_dims(dims_dict={'latitude':'lsmlat','longitude':'lsmlon'}) - regrid_luh2["LONGXY"] = ds_regridtarget["LONGXY"] - regrid_luh2["LATIXY"] = ds_regridtarget["LATIXY"] + regrid_luh2["LONGXY"] = ds_regrid_target["LONGXY"] + regrid_luh2["LATIXY"] = ds_regrid_target["LATIXY"] # Add 'YEAR' as a variable. This is an old requirement of the HLM and should simply be a copy of the `time` dimension regrid_luh2["YEAR"] = regrid_luh2.time # Write the files - outputfile = os.path.join(os.getcwd(),'LUH2_states_transitions_management.timeseries_4x5_hist_simyr1850-2015_c230415.nc') + output_file = os.path.join(os.getcwd(),'LUH2_states_transitions_management.timeseries_4x5_hist_simyr1850-2015_c230415.nc') - regrid_luh2.to_netcdf(outputfile) + regrid_luh2.to_netcdf(output_file) # Example of file naming scheme # finb_luh2_all_regrid.to_netcdf('LUH2_historical_1850_2015_4x5_cdk_220302.nc') @@ -50,13 +50,13 @@ def CommandLineArgs(): # Required input luh2 datafile # TO DO: using the checking function to report back if invalid file input - parser.add_argument("-l","--luh2file", require=True) + parser.add_argument("-l","--luh2_file", require=True) # Provide mutually exlusive arguments for regridding input selection # Currently assuming that if a target is provided that a regridder file will be saved - regridtarget = parser.add_mutually_exclusive_group(required=True) - regridtarget.add_argument("-rf","--regridderfile") # use previously save regridder file - regridtarget.add_argument("-rt","--regriddertarget") # use a dataset to regrid to + regrid_target = parser.add_mutually_exclusive_group(required=True) + regrid_target.add_argument("-rf","--regridderfile") # use previously save regridder file + regrid_target.add_argument("-rt","--regriddertarget") # use a dataset to regrid to # Optional input to subset the time range of the data parser.add_argument("-b","--begin") @@ -66,52 +66,52 @@ def CommandLineArgs(): return(args) -# Prepare the inputfile to be used for regridding -def PrepDataSet(inputfile,start,stop): +# Prepare the input_file to be used for regridding +def PrepDataSet(input_file,start,stop): # Import the data - inputdataset = ImportData(inputfile) + input_dataset = ImportData(input_file) # Truncate the data to the user defined range # This might need some more error handling for when # the start/stop is out of range try: - inputdataset = inputdataset.sel(time=slice(start,stop)) + input_dataset = input_dataset.sel(time=slice(start,stop)) except TypeError as err: print("TypeError:", err) print("Input must be a string") # Correct the necessary variables for both datasets - PrepDataSet_ESMF(inputdataset) + PrepDataSet_ESMF(input_dataset) # Set dataset masks - SetMask(inputdataset) + SetMask(input_dataset) - return(inputdataset) + return(input_dataset) # Updating datasets to work with xESMF -def PrepDataSet_ESMF(inputdataset): +def PrepDataSet_ESMF(input_dataset): # Check the dataset type - dsflag, dstype = CheckDataSet(inputdataset) + dsflag, dstype = CheckDataSet(input_dataset) if (dsflag): if(dstype == "LUH2"): - BoundsVariableFixLUH2(inputdataset) + BoundsVariableFixLUH2(input_dataset) elif(dstype == "Surface"): - DimensionFixSurfData(inputdataset) + DimensionFixSurfData(input_dataset) print("data set updated for xESMF") - return(inputdataset) + return(input_dataset) # Import luh2 or surface data sets -def ImportData(inputfile): +def ImportData(input_file): # Open files # Check to see if a ValueError is raised which is likely due # to the LUH2 time units being undecodable by cftime module try: - datasetout = xr.open_dataset(inputfile) - print("Input file dataset opened: {}".format(inputfile)) + datasetout = xr.open_dataset(input_file) + print("Input file dataset opened: {}".format(input_file)) return(datasetout) except ValueError as err: print("ValueError:", err) @@ -126,19 +126,19 @@ def ImportData(inputfile): # This issue here is that the luh2 time units start prior to # year 1672, which cftime should be able to handle, but it # appears to need a specific unit name convention "common_years" -def AttribUpdateLUH2(inputfile,output_append="modified"): +def AttribUpdateLUH2(input_file,output_append="modified"): # Define the output filename - index = inputfile.find(".nc") - outputfile = inputfile[:index] + "_" + output_append + inputfile[index:] + index = input_file.find(".nc") + output_file = input_file[:index] + "_" + output_append + input_file[index:] nco = Nco() # Get the 'time:units' string from the input using ncks - timeunitstr = nco.ncks(input=inputfile,variable="time",options=["-m"]).decode() + time_unit_string = nco.ncks(input=input_file,variable="time",options=["-m"]).decode() # Grab the units string and replace "years" with "common_years" - substr = re.search('time:units.*".*"',timeunitstr) + substr = re.search('time:units.*".*"',time_unit_string) newstr = substr.group().replace("time:units = \"years","\"common_years") # Use ncatted to update the time units @@ -146,15 +146,15 @@ def AttribUpdateLUH2(inputfile,output_append="modified"): var = "time" att_type = "c" opts = [" -a {0},{1},o,{2},{3}".format(att, var, att_type, newstr)] - nco.ncatted(input=inputfile, output=outputfile, options=opts) + nco.ncatted(input=input_file, output=output_file, options=opts) - print("Generated modified output file: {}".format(outputfile)) + print("Generated modified output file: {}".format(output_file)) - return(outputfile) + return(output_file) # The following is fixed with PR #62 for pynco but isn't in that latest update yet # on conda - # nco.ncatted(input=inputfile,output=outputfile,options=[ + # nco.ncatted(input=input_file,output=output_file,options=[ # Atted(mode="overwrite", # att_name="units", # var_name="time", @@ -167,61 +167,61 @@ def AttribUpdateLUH2(inputfile,output_append="modified"): # Each lat/lon boundary array is a 2D array corresponding to the bounds of each # coordinate position (e.g. lat_boundary would be 90.0 and 89.75 for lat coordinate # of 89.875). -def BoundsVariableFixLUH2(inputdataset): +def BoundsVariableFixLUH2(input_dataset): # Drop the old boundary names to avoid confusion - # outputdataset = inputdataset.drop(labels=['lat_bounds','lon_bounds']) + # outputdataset = input_dataset.drop(labels=['lat_bounds','lon_bounds']) # Create lat and lon bounds as a single dimension array out of the LUH2 two dimensional_bounds array. # Future todo: is it possible to have xESMF recognize and use the original 2D array? - inputdataset["lat_b"] = np.insert(inputdataset.lat_bounds[:,1].data,0,inputdataset.lat_bounds[0,0].data) - inputdataset["lon_b"] = np.insert(inputdataset.lon_bounds[:,1].data,0,inputdataset.lon_bounds[0,0].data) + input_dataset["lat_b"] = np.insert(input_dataset.lat_bounds[:,1].data,0,input_dataset.lat_bounds[0,0].data) + input_dataset["lon_b"] = np.insert(input_dataset.lon_bounds[:,1].data,0,input_dataset.lon_bounds[0,0].data) print("LUH2 dataset lat/lon boundary variables formatted and added as new variable for xESMF") - return(inputdataset) + return(input_dataset) # The user will need to use a surface data set to regrid from, but the surface datasets # need to have their dimensions renamed to something recognizable by xESMF -def DimensionFixSurfData(inputdataset): +def DimensionFixSurfData(input_dataset): # Rename the surface dataset dimensions to something recognizable by xESMF. - # inputdataset = surfdataset.rename_dims(dims_dict={'lsmlat':'latitude','lsmlon':'longitude'}) - inputdataset = inputdataset.rename_dims(dims_dict={'lsmlat':'lat','lsmlon':'lon'}) + # input_dataset = surfdataset.rename_dims(dims_dict={'lsmlat':'latitude','lsmlon':'longitude'}) + input_dataset = input_dataset.rename_dims(dims_dict={'lsmlat':'lat','lsmlon':'lon'}) # Populate the new surface dataset with the actual lat/lon values - # inputdataset['longitude'] = inputdataset.LONGXY.isel(latitude=0) - # inputdataset['latitude'] = inputdataset.LATIXY.isel(longitude=0) - inputdataset['lon'] = inputdataset.LONGXY.isel(lat=0) - inputdataset['lat'] = inputdataset.LATIXY.isel(lon=0) + # input_dataset['longitude'] = input_dataset.LONGXY.isel(latitude=0) + # input_dataset['latitude'] = input_dataset.LATIXY.isel(longitude=0) + input_dataset['lon'] = input_dataset.LONGXY.isel(lat=0) + input_dataset['lat'] = input_dataset.LATIXY.isel(lon=0) print("Surface dataset dimensions renamed for xESMF") - return(inputdataset) + return(input_dataset) -def SetMask(inputdataset): +def SetMask(input_dataset): # check what sort of inputdata is being provided; surface dataset or luh2 # LUH2 data will need to be masked based on the variable input to mask - dsflag,dstype = CheckDataSet(inputdataset) + dsflag,dstype = CheckDataSet(input_dataset) if (dsflag): if(dstype == "LUH2"): - SetMaskLUH2(inputdataset,'primf') # temporary + SetMaskLUH2(input_dataset,'primf') # temporary elif(dstype == "Surface"): - SetMaskSurfData(inputdataset) + SetMaskSurfData(input_dataset) print("mask added") - return(inputdataset) + return(input_dataset) # Check which dataset we're working with -def CheckDataSet(inputdataset): +def CheckDataSet(input_dataset): dsflag = False - if('primf' in list(inputdataset.variables)): + if('primf' in list(input_dataset.variables)): dstype = 'LUH2' dsflag = True print("LUH2") - elif('natpft' in list(inputdataset.variables)): + elif('natpft' in list(input_dataset.variables)): dstype = 'Surface' dsflag = True print("Surface") @@ -232,18 +232,19 @@ def CheckDataSet(inputdataset): return(dsflag,dstype) # LUH2 specific masking sub-function -def SetMaskLUH2(inputdataset,label_to_mask): +def SetMaskLUH2(input_dataset,static_data_set): # Instead of passing the label_to_mask, loop through this for all labels? - inputdataset["mask"] = xr.where(~np.isnan(inputdataset[label_to_mask].isel(time=0)), 1, 0) + # input_dataset["mask"] = xr.where(~np.isnan(input_dataset[label_to_mask].isel(time=0)), 1, 0) + input_dataset["mask"] = xr.where(state_data_set.icwtr == 1) # return(outputdataset) - return(inputdataset) + return(input_dataset) # Surface dataset specific masking sub-function -def SetMaskSurfData(inputdataset): +def SetMaskSurfData(input_dataset): # Instead of passing the label_to_mask, loop through this for all labels? - inputdataset["mask"] = inputdataset["PCT_NATVEG"]> 0 + input_dataset["mask"] = input_dataset["PCT_NATVEG"]> 0 # return(outputdataset) - return(inputdataset) + return(input_dataset) def RegridConservative(ds_to_regrid,ds_regrid_target,save=False): # define the regridder transformation From 848bbea5f22bb58b2bcb8882dbe4ac13d52db38d Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 4 May 2023 16:16:06 -0700 Subject: [PATCH 667/852] adjust regridding methods --- tools/luh2mod.py | 92 ++++++++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 42 deletions(-) diff --git a/tools/luh2mod.py b/tools/luh2mod.py index 33ab993d98..3355007324 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -16,17 +16,34 @@ def main(): # Allow variable input files (state and/or transitions and/or management) args = CommandLineArgs() - # Prep the LUH2 data + # Prep the LUH2 datasets and regrid target ds_luh2 = PrepDataSet(args.luh2_file,args.begin,args.end) - - # Prep the regrid target (assuming surface dataset) ds_regrid_target= PrepDataSet(args.regrid_target_file,args.begin,args.end) - # Build regridder - regridder = RegridConservative(ds_luh2, ds_regrid_target, save=True) + # Import the LUH2 static data to use for masking + ds_luh2_static = ImportData(args.luh2_static_file) + + # Create new variable where the ice water fraction is inverted + ds_luh2_static["landfrac"] = 1 - ds_luh2_static.icwtr + + # Mask all LUH2 input data using the ice/water fraction for the LUH2 static data + ds_luh2 = SetMaskLUH2(ds_luh2, ds_luh2_static) + ds_luh2_static = SetMaskLUH2(ds_luh2_static, ds_luh2_static) + + # Mask the regrid target + ds_regrid_target = SetMaskSurfData(ds_regrid_target) + + # Regrid the luh2 data to the target grid + regridder_luh2 = RegridConservative(ds_luh2, ds_regrid_target, save=True) + regrid_luh2 = regridder_luh2(ds_luh2) + + # Regrid the inverted ice/water fraction data to the target grid + regridder_land_fraction = RegridConservative(ds_luh2_static, ds_regrid_target) + regrid_land_fraction = regridder_land_fraction(ds_luh2_static) + + # Adjust the luh2 data by the land fraction + regrid_luh2 = regrid_luh2 / regrid_land_fraction.landfrac - # Regrid the dataset(s) - regrid_luh2 = regridder(ds_states) # Rename the dimensions for the output regrid_luh2 = regrid_luh2.rename_dims(dims_dict={'latitude':'lsmlat','longitude':'lsmlon'}) @@ -85,7 +102,7 @@ def PrepDataSet(input_file,start,stop): PrepDataSet_ESMF(input_dataset) # Set dataset masks - SetMask(input_dataset) + # SetMask(input_dataset) return(input_dataset) @@ -199,18 +216,33 @@ def DimensionFixSurfData(input_dataset): return(input_dataset) -def SetMask(input_dataset): +# def SetMask(input_dataset, masking_dataset): - # check what sort of inputdata is being provided; surface dataset or luh2 - # LUH2 data will need to be masked based on the variable input to mask - dsflag,dstype = CheckDataSet(input_dataset) - if (dsflag): - if(dstype == "LUH2"): - SetMaskLUH2(input_dataset,'primf') # temporary - elif(dstype == "Surface"): - SetMaskSurfData(input_dataset) - print("mask added") +# # check what sort of inputdata is being provided; surface dataset or luh2 +# # LUH2 data will need to be masked based on the variable input to mask +# dsflag,dstype = CheckDataSet(input_dataset) +# if (dsflag): +# if(dstype == "LUH2"): +# SetMaskLUH2(input_dataset) # temporary +# elif(dstype == "Surface"): +# SetMaskSurfData(input_dataset) +# print("mask added") +# +# return(input_dataset) +# LUH2 specific masking sub-function +def SetMaskLUH2(input_dataset,static_data_set): + + # Mask the luh2 data where the ice/water fraction is unity (i.e. fully ice covered gridcell) + input_dataset["mask"] = input_dataset.where(static_data_set.icwtr != 1) + # return(outputdataset) + return(input_dataset) + +# Surface dataset specific masking sub-function +def SetMaskSurfData(input_dataset): + # Instead of passing the label_to_mask, loop through this for all labels? + input_dataset["mask"] = input_dataset["PCT_NATVEG"] > 0 + # return(outputdataset) return(input_dataset) # Check which dataset we're working with @@ -231,21 +263,6 @@ def CheckDataSet(input_dataset): return(dsflag,dstype) -# LUH2 specific masking sub-function -def SetMaskLUH2(input_dataset,static_data_set): - # Instead of passing the label_to_mask, loop through this for all labels? - # input_dataset["mask"] = xr.where(~np.isnan(input_dataset[label_to_mask].isel(time=0)), 1, 0) - input_dataset["mask"] = xr.where(state_data_set.icwtr == 1) - # return(outputdataset) - return(input_dataset) - -# Surface dataset specific masking sub-function -def SetMaskSurfData(input_dataset): - # Instead of passing the label_to_mask, loop through this for all labels? - input_dataset["mask"] = input_dataset["PCT_NATVEG"]> 0 - # return(outputdataset) - return(input_dataset) - def RegridConservative(ds_to_regrid,ds_regrid_target,save=False): # define the regridder transformation regridder = xe.Regridder(ds_to_regrid, ds_regrid_target, "conservative") @@ -258,15 +275,6 @@ def RegridConservative(ds_to_regrid,ds_regrid_target,save=False): return(regridder) - - # Apply regridder - # regrid_states = regridder(finb_states) - # regrid_management= regridder(finb_management) - # regrid_transitions= regridder(finb_management) - - ### memory crashes on the transition data - #fin_transitions_regrid = regridder(finb) - # General functionality needed # - collect data for specific user-defined time period # - collect subset of the data variables (e.g. pasture, rangeland, etc) From 9a6a9032addc15e6063924eabc423b98df8ce604 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Fri, 5 May 2023 07:35:29 -0600 Subject: [PATCH 668/852] get rid of CMakeLists, only for unit test branch --- CMakeLists.txt | 105 --------------------- biogeochem/CMakeLists.txt | 8 -- biogeophys/CMakeLists.txt | 8 -- fire/CMakeLists.txt | 8 -- functional_unit_testing/run_FATES_tests.py | 35 ------- main/CMakeLists.txt | 19 ---- parteh/CMakeLists.txt | 9 -- 7 files changed, 192 deletions(-) delete mode 100644 CMakeLists.txt delete mode 100644 biogeochem/CMakeLists.txt delete mode 100644 biogeophys/CMakeLists.txt delete mode 100644 fire/CMakeLists.txt delete mode 100644 functional_unit_testing/run_FATES_tests.py delete mode 100644 parteh/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 750173fc34..0000000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,105 +0,0 @@ -cmake_minimum_required(VERSION 3.4) - -list(APPEND CMAKE_MODULE_PATH ${CIME_CMAKE_MODULE_DIRECTORY}) -include(CIME_initial_setup) - -project(FATES_tests Fortran C) - -#enable_language(Fortran) - -include(CIME_utils) - -set(CLM_ROOT "../../") - -# Add source directories from other share code (csm_share, etc.) -add_subdirectory(${CLM_ROOT}/share/src csm_share) -add_subdirectory(${CLM_ROOT}/share/unit_test_stubs/util csm_share_stubs) - -#Extract just the files we need from csm_share -set (shr_sources_needed_base - shr_log_mod.F90 - shr_infnan_mod.F90 - shr_kind_mod.F90 - shr_sys_mod.F90 - shr_strconvert_mod.F90 - shr_abort_mod.abortthrows.F90 - ) -extract_sources("${shr_sources_needed_base}" "${share_sources}" shr_sources_needed) - -# Add FATES source directories -add_subdirectory(${CLM_ROOT}/src/fates/main fates_main) -add_subdirectory(${CLM_ROOT}/src/fates/biogeochem fates_biogeochem) -add_subdirectory(${CLM_ROOT}/src/fates/biogeophys fates_biogephys) -add_subdirectory(${CLM_ROOT}/src/fates/parteh fates_parteh) -add_subdirectory(${CLM_ROOT}/src/fates/fire fates_fire) - -# Add general unit test directories (stubbed out files, etc.) -add_subdirectory(${CLM_ROOT}/src/unit_test_stubs clm_stubs) -add_subdirectory(${CLM_ROOT}/src/unit_test_shr clm_tests) - -# Add general unit test directories -add_subdirectory(${CLM_ROOT}/src/fates/unit_test_shr) - -# Remove shr_mpi_mod from share_sources. -# This is needed because we want to use the mock shr_mpi_mod in place of the real one -# -# TODO: this should be moved into a general-purpose function in Sourcelist_utils. -# Then this block of code could be replaced with a single call, like: -# remove_source_file(${share_sources} "shr_mpi_mod.F90") -foreach (sourcefile ${share_sources}) - string(REGEX MATCH "shr_mpi_mod.F90" match_found ${sourcefile}) - if(match_found) - list(REMOVE_ITEM share_sources ${sourcefile}) - endif() -endforeach() - -# Remove shr_cal_mod from share_sources. -# -# shr_cal_mod depends on ESMF (or the lightweight esmf wrf timemgr, at -# least). Since CTSM doesn't currently use shr_cal_mod, we're avoiding -# the extra overhead of including esmf_wrf_timemgr sources in this -# build. -# -# TODO: like above, this should be moved into a general-purpose function -# in Sourcelist_utils. Then this block of code could be replaced with a -# single call, like: remove_source_file(${share_sources} -# "shr_cal_mod.F90") -foreach (sourcefile ${share_sources}) - string(REGEX MATCH "shr_cal_mod.F90" match_found ${sourcefile}) - if(match_found) - list(REMOVE_ITEM share_sources ${sourcefile}) - endif() -endforeach() - -# Build libraries containing stuff needed for the unit tests. -# Eventually, these add_library calls should probably be distributed into the correct location, rather than being in this top-level CMakeLists.txt file. -add_library(csm_share ${shr_sources_needed}) -declare_generated_dependencies(csm_share "${share_genf90_sources}") -add_library(fates ${fates_sources}) -add_dependencies(fates csm_share) - -# We need to look for header files here, in order to pick up shr_assert.h -include_directories(${CLM_ROOT}/share/include) - -set(NETCDF_C_DIR "/usr/local/Cellar/netcdf/4.9.2") -set(NETCDF_FORTRAN_DIR "/usr/local/Cellar/netcdf-fortran/4.6.0") - -FIND_PATH(NETCDFC_FOUND libnetcdf.a ${NETCDF_C_DIR}/lib) -FIND_PATH(NETCDFF_FOUND libnetcdff.a ${NETCDF_FORTRAN_DIR}/lib) -MESSAGE(" NETCDFC_FOUND = ${NETCDFC_FOUND}") -MESSAGE(" NETCDFF_FOUND = ${NETCDFF_FOUND}") - -include_directories(${NETCDF_C_DIR}/include - ${NETCDF_FORTRAN_DIR}/include) -link_directories(${NETCDF_C_DIR}/lib - ${NETCDF_FORTRAN_DIR}/lib) - -include_directories(${CMAKE_CURRENT_BINARY_DIR}) -link_directories(${CMAKE_CURRENT_BINARY_DIR}) - -# Add the test directories -# Note: it's possible that these could be added by each source directory that -# has tests in it. However, it appears that the order needs to be done -# carefully: for example, include_directories and link_directories needs to be -# done before adding the tests themselves. -add_subdirectory(${CLM_ROOT}/src/fates/biogeophys/test fates_biogeophys_test) diff --git a/biogeochem/CMakeLists.txt b/biogeochem/CMakeLists.txt deleted file mode 100644 index b9a6889443..0000000000 --- a/biogeochem/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -list(APPEND fates_sources - FatesLitterMod.F90 - FatesAllometryMod.F90 - DamageMainMod.F90 - FatesPatchMod.F90 - ) - -sourcelist_to_parent(fates_sources) \ No newline at end of file diff --git a/biogeophys/CMakeLists.txt b/biogeophys/CMakeLists.txt deleted file mode 100644 index 037dd49fa7..0000000000 --- a/biogeophys/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# Note that this is just used for unit testing; hence, we only need to add -# source files that are currently used in unit tests - -list(APPEND fates_sources - FatesHydroWTFMod.F90 - ) - -sourcelist_to_parent(fates_sources) diff --git a/fire/CMakeLists.txt b/fire/CMakeLists.txt deleted file mode 100644 index 0cec31a6a6..0000000000 --- a/fire/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# Note that this is just used for unit testing; hence, we only need to add -# source files that are currently used in unit tests - -list(APPEND fates_sources - SFParamsMod.F90 - ) - -sourcelist_to_parent(fates_sources) diff --git a/functional_unit_testing/run_FATES_tests.py b/functional_unit_testing/run_FATES_tests.py deleted file mode 100644 index 29b2df5667..0000000000 --- a/functional_unit_testing/run_FATES_tests.py +++ /dev/null @@ -1,35 +0,0 @@ -import os -import sys - -# -_CTSM_PYTHON = os.path.abspath( - os.path.join(os.path.dirname(__file__), "..", "..", "..", "python") -) -sys.path.insert(1, _CTSM_PYTHON) - -from ctsm import add_cime_to_path -from CIME.utils import run_cmd_no_fail - -from shutil import rmtree, copy - -def main(build_dir): - os.chdir("..") - if os.path.isdir(build_dir): - rmtree(build_dir) - - ## super hacky right now!! - run_command = ["../../cime/scripts/fortran_unit_testing/run_tests.py", - "--build-dir", "build.temp"] - run_cmd_no_fail(" ".join(run_command), combine_output=True) - - copy(os.path.join(build_dir, "__command_line_test__/__command_line_test__/fates_biogeophys_test/solar_rad_test/FATES_rad_exe"), - "biogeophys/test/solar_rad_test/") - - os.chdir("biogeophys/test/solar_rad_test") - run_command = ["./FATES_rad_exe"] - output = run_cmd_no_fail(" ".join(run_command), combine_output=True) - print(output) - - -if __name__ == "__main__": - main("build.temp") \ No newline at end of file diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 6cbca40357..dfd5eaba2a 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -11,23 +11,4 @@ list(APPEND clm_sources FatesUtilsMod.F90 ) -list(APPEND fates_sources - FatesConstantsMod.F90 - EDTypesMod.F90 - EDPftvarcon.F90 - EDParamsMod.F90 - FatesGlobals.F90 - FatesInterfaceTypesMod.F90 - FatesParametersInterface.F90 - FatesParameterDerivedMod.F90 - FatesHydraulicsMemMod.F90 - FatesRunningMeanMod.F90 - FatesCohortMod.F90 - FatesSizeAgeTypeIndicesMod.F90 - FatesIntegratorsMod.F90 - FatesUtilsMod.F90 - FatesSynchronizedParamsMod.F90 - ) - sourcelist_to_parent(clm_sources) -sourcelist_to_parent(fates_sources) diff --git a/parteh/CMakeLists.txt b/parteh/CMakeLists.txt deleted file mode 100644 index f04d622092..0000000000 --- a/parteh/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -list(APPEND fates_sources - PRTGenericMod.F90 - PRTParametersMod.F90 - PRTParamsFATESMod.F90 - PRTAllometricCarbonMod.F90 - PRTAllometricCNPMod.F90 - ) - - sourcelist_to_parent(fates_sources) \ No newline at end of file From c2e4e24cf502cf51c81150dbb31c32a5dac00978 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 5 May 2023 13:12:45 -0700 Subject: [PATCH 669/852] various fixes and improvements --- tools/luh2mod.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/tools/luh2mod.py b/tools/luh2mod.py index 3355007324..c6932e0a8b 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -76,6 +76,7 @@ def CommandLineArgs(): regrid_target.add_argument("-rt","--regriddertarget") # use a dataset to regrid to # Optional input to subset the time range of the data + # TO DO: howto parser.add_argument("-b","--begin") parser.add_argument("-e","--end") @@ -84,11 +85,18 @@ def CommandLineArgs(): return(args) # Prepare the input_file to be used for regridding -def PrepDataSet(input_file,start,stop): +def PrepDataSet(input_file,start=None,stop=None): # Import the data input_dataset = ImportData(input_file) + # Use the maximum span if start and stop are not present + if (start == None): + start = input_dataset.time[0] + + if (stop == None): + stop = input_dataset.time[-1] + # Truncate the data to the user defined range # This might need some more error handling for when # the start/stop is out of range @@ -99,7 +107,7 @@ def PrepDataSet(input_file,start,stop): print("Input must be a string") # Correct the necessary variables for both datasets - PrepDataSet_ESMF(input_dataset) + input_dataset = PrepDataSet_ESMF(input_dataset) # Set dataset masks # SetMask(input_dataset) @@ -113,9 +121,11 @@ def PrepDataSet_ESMF(input_dataset): dsflag, dstype = CheckDataSet(input_dataset) if (dsflag): if(dstype == "LUH2"): - BoundsVariableFixLUH2(input_dataset) + print("PrepDataSet: LUH2") + input_dataset = BoundsVariableFixLUH2(input_dataset) elif(dstype == "Surface"): - DimensionFixSurfData(input_dataset) + print("PrepDataSet: SurfData") + input_dataset = DimensionFixSurfData(input_dataset) print("data set updated for xESMF") return(input_dataset) @@ -210,7 +220,7 @@ def DimensionFixSurfData(input_dataset): # input_dataset['longitude'] = input_dataset.LONGXY.isel(latitude=0) # input_dataset['latitude'] = input_dataset.LATIXY.isel(longitude=0) input_dataset['lon'] = input_dataset.LONGXY.isel(lat=0) - input_dataset['lat'] = input_dataset.LATIXY.isel(lon=0) + input_dataset['lat'] = input_dataset.LATIXY.isel(lon=0) print("Surface dataset dimensions renamed for xESMF") @@ -234,7 +244,7 @@ def DimensionFixSurfData(input_dataset): def SetMaskLUH2(input_dataset,static_data_set): # Mask the luh2 data where the ice/water fraction is unity (i.e. fully ice covered gridcell) - input_dataset["mask"] = input_dataset.where(static_data_set.icwtr != 1) + input_dataset["mask"] = (static_data_set.icwtr != 1) # return(outputdataset) return(input_dataset) From 243137f415594b16d282784ac6a98eec170f2a42 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Fri, 5 May 2023 14:52:40 -0600 Subject: [PATCH 670/852] put cohort mod in biogeochem folder --- {main => biogeochem}/FatesCohortMod.F90 | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {main => biogeochem}/FatesCohortMod.F90 (100%) diff --git a/main/FatesCohortMod.F90 b/biogeochem/FatesCohortMod.F90 similarity index 100% rename from main/FatesCohortMod.F90 rename to biogeochem/FatesCohortMod.F90 From c77dff19e09f7c910f1050999ab0094a938e76ba Mon Sep 17 00:00:00 2001 From: adrifoster Date: Fri, 5 May 2023 15:04:57 -0600 Subject: [PATCH 671/852] remove chil check in EDSurfaceAlbedoMod --- biogeophys/EDSurfaceAlbedoMod.F90 | 3 --- 1 file changed, 3 deletions(-) diff --git a/biogeophys/EDSurfaceAlbedoMod.F90 b/biogeophys/EDSurfaceAlbedoMod.F90 index 2b0f7e0930..465cefff52 100644 --- a/biogeophys/EDSurfaceAlbedoMod.F90 +++ b/biogeophys/EDSurfaceAlbedoMod.F90 @@ -363,9 +363,6 @@ subroutine PatchNormanRadiation (currentPatch, & cosz = max(0.001_r8, currentPatch%solar_zenith_angle ) !copied from previous radiation code... do ft = 1,numpft sb = (90._r8 - (acos(cosz)*180._r8/pi_const)) * (pi_const / 180._r8) - !chil should be between -0.4 and 0.6 - ! Bonan (2019) doi:10.1017/9781107339217 pg. 238 - chil = min(max(xl(ft), -0.4_r8), 0.6_r8 ) ! chil being close to zero shouldn't affect things !if ( abs(chil) <= 0.01_r8) then ! chil = 0.01_r8 From 99eac94d8e2bc9c901ab4efa7656e74ae5733e12 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 5 May 2023 15:37:19 -0700 Subject: [PATCH 672/852] Separated luh2 module and luh2 call script --- tools/luh2.py | 132 +++++++++++++++++++++++++++++++++-------------- tools/luh2mod.py | 109 ++++++++++---------------------------- 2 files changed, 120 insertions(+), 121 deletions(-) diff --git a/tools/luh2.py b/tools/luh2.py index 44cd0d1e9a..0457d092a5 100644 --- a/tools/luh2.py +++ b/tools/luh2.py @@ -1,40 +1,96 @@ #!/usr/bin/env python3 -import luh2mod as luh2 - -# Location of luh2 data - move this to input -# file_states = "/home/glemieux/Data/luh2/orig/states.nc" -# file_management = "/home/glemieux/Data/luh2/orig/management.nc" -# file_transitions = "/home/glemieux/Data/luh2/orig/transitions.nc" - -# # Modify the files -# mod_file_states = luh2.attribupdate(file_states) -# mod_file_management = luh2.attribupdate(file_management) -# mod_file_transitions = luh2.attribupdate(file_transitions) -mod_file_states = "/home/glemieux/Data/luh2/states_modified.nc" -mod_file_management = "/home/glemieux/Data/luh2/management_modified.nc" -mod_file_transitions = "/home/glemieux/Data/luh2/transitions_modified.nc" - -# Open modified files -ds_states = luh2.ImportData(mod_file_states) -# ds_management = luh2.importdata(mod_file_management) -# ds_transitions = luh2.importdata(mod_file_transitions) - -# Fix the bounds of the LUH2 variable for xESMF -ds_states = luh2.BoundsVariableFixLUH2(ds_states) -# ds_management= luh2.BoundsFixLUH2(ds_management) -# ds_transitions = luh2.BoundsFixLUH2(ds_transitions) - -# Grab surface data set to use as regrid "target" -# Import the surface dataset -file_surfdata = "/home/glemieux/Data/luh2/surfdata_4x5_16pfts_Irrig_CMIP6_simyr2000_c170824.nc" -ds_surfdata = luh2.ImportData(file_surfdata) -# modify the surface data set to enable xesmf regridder to find necessary data - = luh2.DimensionFixSurfData(file_surfdata) - -print("done") - - -# def main(): -# if __name__ == "__main__": -# main() +import argparse, os +from luh2mod import PrepDataSet, ImportData, SetMaskLUH2, SetMaskSurfData +from luh2mod import RegridConservative + +# Add version checking here in case environment.yml not used +def main(): + + # Add argument parser - subfunction? Seperate common module? + # input_files and range should be the only arguments + # Allow variable input files (state and/or transitions and/or management) + args = CommandLineArgs() + + # Prep the LUH2 datasets and regrid target + # To Do: need logic to handle taking in a saved regrid file + ds_luh2 = PrepDataSet(args.luh2_file,args.begin,args.end) + ds_regrid_target= PrepDataSet(args.regridder_target_file,args.begin,args.end) + + # Import the LUH2 static data to use for masking + ds_luh2_static = ImportData(args.luh2_static_file) + + # Create new variable where the ice water fraction is inverted + ds_luh2_static["landfrac"] = 1 - ds_luh2_static.icwtr + + # Mask all LUH2 input data using the ice/water fraction for the LUH2 static data + ds_luh2 = SetMaskLUH2(ds_luh2, ds_luh2_static) + ds_luh2_static = SetMaskLUH2(ds_luh2_static, ds_luh2_static) + + # Mask the regrid target + ds_regrid_target = SetMaskSurfData(ds_regrid_target) + + # Regrid the luh2 data to the target grid + regridder_luh2 = RegridConservative(ds_luh2, ds_regrid_target, save=True) + regrid_luh2 = regridder_luh2(ds_luh2) + + # # Regrid the inverted ice/water fraction data to the target grid + # # regridder_land_fraction = RegridConservative(ds_luh2_static, ds_regrid_target) + # # regrid_land_fraction = regridder_land_fraction(ds_luh2_static) + # regrid_land_fraction = regridder_luh2(ds_luh2_static) + + # # Adjust the luh2 data by the land fraction + # # To Do: check if we need to do this for transition and management data as well + # regrid_luh2 = regrid_luh2 / regrid_land_fraction.landfrac + + # # Rename the dimensions for the output + # regrid_luh2 = regrid_luh2.rename_dims(dims_dict={'latitude':'lsmlat','longitude':'lsmlon'}) + # regrid_luh2["LONGXY"] = ds_regrid_target["LONGXY"] + # regrid_luh2["LATIXY"] = ds_regrid_target["LATIXY"] + + # # Add 'YEAR' as a variable. This is an old requirement of the HLM and should simply be a copy of the `time` dimension + # regrid_luh2["YEAR"] = regrid_luh2.time + + # # Write the files + # # TO DO: add check to handle if the user enters the full path + # output_filename = args.output + # if (args.output == None): + # output_filename = 'LUH2_timeseries.nc' + + # output_file = os.path.join(os.getcwd(),output_filename) + # regrid_luh2.to_netcdf(output_file) + + # Example of file naming scheme + # finb_luh2_all_regrid.to_netcdf('LUH2_historical_1850_2015_4x5_cdk_220302.nc') + +def CommandLineArgs(): + + parser = argparse.ArgumentParser(description="placeholder desc") + + # Required input luh2 datafile + # TO DO: using the checking function to report back if invalid file input + parser.add_argument("-l","--luh2_file", required=True) + + # Required static luh2 data to get the ice/water fraction + parser.add_argument("-s", "--luh2_static_file", required=True) + + # Provide mutually exlusive arguments for regridding input selection + # Currently assuming that if a target is provided that a regridder file will be saved + regrid_target = parser.add_mutually_exclusive_group(required=True) + regrid_target.add_argument("-rf","--regridder_file") # use previously save regridder file + regrid_target.add_argument("-rt","--regridder_target_file") # use a dataset to regrid to + + # Optional input to subset the time range of the data + parser.add_argument("-b","--begin") + parser.add_argument("-e","--end") + + # Optional output argument + parser.add_argument("-o","--output") + + args = parser.parse_args() + + return(args) + + +if __name__ == "__main__": + main() diff --git a/tools/luh2mod.py b/tools/luh2mod.py index c6932e0a8b..f106d784c0 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -1,89 +1,12 @@ #!/usr/bin/env python3 -import argparse, os, re +import re import numpy as np import xarray as xr import xesmf as xe from nco import Nco from nco.custom import Atted -# Add version checking here in case environment.yml not used - -def main(): - - # Add argument parser - subfunction? Seperate common module? - # input_files and range should be the only arguments - # Allow variable input files (state and/or transitions and/or management) - args = CommandLineArgs() - - # Prep the LUH2 datasets and regrid target - ds_luh2 = PrepDataSet(args.luh2_file,args.begin,args.end) - ds_regrid_target= PrepDataSet(args.regrid_target_file,args.begin,args.end) - - # Import the LUH2 static data to use for masking - ds_luh2_static = ImportData(args.luh2_static_file) - - # Create new variable where the ice water fraction is inverted - ds_luh2_static["landfrac"] = 1 - ds_luh2_static.icwtr - - # Mask all LUH2 input data using the ice/water fraction for the LUH2 static data - ds_luh2 = SetMaskLUH2(ds_luh2, ds_luh2_static) - ds_luh2_static = SetMaskLUH2(ds_luh2_static, ds_luh2_static) - - # Mask the regrid target - ds_regrid_target = SetMaskSurfData(ds_regrid_target) - - # Regrid the luh2 data to the target grid - regridder_luh2 = RegridConservative(ds_luh2, ds_regrid_target, save=True) - regrid_luh2 = regridder_luh2(ds_luh2) - - # Regrid the inverted ice/water fraction data to the target grid - regridder_land_fraction = RegridConservative(ds_luh2_static, ds_regrid_target) - regrid_land_fraction = regridder_land_fraction(ds_luh2_static) - - # Adjust the luh2 data by the land fraction - regrid_luh2 = regrid_luh2 / regrid_land_fraction.landfrac - - - # Rename the dimensions for the output - regrid_luh2 = regrid_luh2.rename_dims(dims_dict={'latitude':'lsmlat','longitude':'lsmlon'}) - regrid_luh2["LONGXY"] = ds_regrid_target["LONGXY"] - regrid_luh2["LATIXY"] = ds_regrid_target["LATIXY"] - - # Add 'YEAR' as a variable. This is an old requirement of the HLM and should simply be a copy of the `time` dimension - regrid_luh2["YEAR"] = regrid_luh2.time - - # Write the files - output_file = os.path.join(os.getcwd(),'LUH2_states_transitions_management.timeseries_4x5_hist_simyr1850-2015_c230415.nc') - - regrid_luh2.to_netcdf(output_file) - - # Example of file naming scheme - # finb_luh2_all_regrid.to_netcdf('LUH2_historical_1850_2015_4x5_cdk_220302.nc') - -def CommandLineArgs(): - - parser = argparse.ArgumentParser(description="placeholder desc") - - # Required input luh2 datafile - # TO DO: using the checking function to report back if invalid file input - parser.add_argument("-l","--luh2_file", require=True) - - # Provide mutually exlusive arguments for regridding input selection - # Currently assuming that if a target is provided that a regridder file will be saved - regrid_target = parser.add_mutually_exclusive_group(required=True) - regrid_target.add_argument("-rf","--regridderfile") # use previously save regridder file - regrid_target.add_argument("-rt","--regriddertarget") # use a dataset to regrid to - - # Optional input to subset the time range of the data - # TO DO: howto - parser.add_argument("-b","--begin") - parser.add_argument("-e","--end") - - args = parser.parse_args() - - return(args) - # Prepare the input_file to be used for regridding def PrepDataSet(input_file,start=None,stop=None): @@ -104,7 +27,7 @@ def PrepDataSet(input_file,start=None,stop=None): input_dataset = input_dataset.sel(time=slice(start,stop)) except TypeError as err: print("TypeError:", err) - print("Input must be a string") + print("Input must be a string\n") # Correct the necessary variables for both datasets input_dataset = PrepDataSet_ESMF(input_dataset) @@ -126,7 +49,7 @@ def PrepDataSet_ESMF(input_dataset): elif(dstype == "Surface"): print("PrepDataSet: SurfData") input_dataset = DimensionFixSurfData(input_dataset) - print("data set updated for xESMF") + print("data set updated for xESMF\n") return(input_dataset) @@ -144,7 +67,7 @@ def ImportData(input_file): print("ValueError:", err) errmsg = "User direction: If error is due to units being 'years since ...' " \ "update the input data file to change to 'common_years since...'. " \ - "This can be done using the luh2.attribupdate function." + "This can be done using the luh2.attribupdate function\n." print() print(errmsg) @@ -175,7 +98,7 @@ def AttribUpdateLUH2(input_file,output_append="modified"): opts = [" -a {0},{1},o,{2},{3}".format(att, var, att_type, newstr)] nco.ncatted(input=input_file, output=output_file, options=opts) - print("Generated modified output file: {}".format(output_file)) + print("Generated modified output file: {}\n".format(output_file)) return(output_file) @@ -274,6 +197,10 @@ def CheckDataSet(input_dataset): return(dsflag,dstype) def RegridConservative(ds_to_regrid,ds_regrid_target,save=False): + + + print("\nDefining regridder") + # define the regridder transformation regridder = xe.Regridder(ds_to_regrid, ds_regrid_target, "conservative") @@ -283,7 +210,23 @@ def RegridConservative(ds_to_regrid,ds_regrid_target,save=False): filename = regridder.to_netcdf("regridder.nc") print("regridder saved to file: ", filename) - return(regridder) + ds_regrid = ds_to_regrid.copy() + print("regridding") + + # Loop through the variables one at a time to conserve memory + # To Do: implement dask + # To Do: can we skip time, lat, and lon variables? + ds_varnames = list(ds_to_regrid.variables.keys()) + varlen = len(ds_to_regrid.variables) + for i in range(varlen-1): + if (not(ds_varnames[i] == 'time' or ds_varnames[i] == 'lon' or + ds_varnames[i] == 'lat')): + print("regridding variable {}/{}: {}".format(i+1, varlen, ds_varnames[i])) + ds_regrid[ds_varnames[i]] = regridder(ds_to_regrid[ds_varnames[i]]) + else: + print("skipping variable {}/{}: {}".format(i+1, varlen, ds_varnames[i])) + + return(ds_regrid) # General functionality needed # - collect data for specific user-defined time period From 1e0e02fa414080c438a6b684b7d9557d0c65987b Mon Sep 17 00:00:00 2001 From: adrifoster Date: Mon, 8 May 2023 10:42:20 -0600 Subject: [PATCH 673/852] put endrun back --- main/FatesGlobals.F90 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/main/FatesGlobals.F90 b/main/FatesGlobals.F90 index 56d381377c..71e4120df0 100644 --- a/main/FatesGlobals.F90 +++ b/main/FatesGlobals.F90 @@ -91,8 +91,7 @@ subroutine fates_endrun(msg) !----------------------------------------------------------------------- write(fates_log(),*)'ENDRUN:', msg - !call shr_sys_abort() - stop + call shr_sys_abort() end subroutine fates_endrun From e5e3f49c5d12bde61a3ea5dae9ff092a79ef5ab8 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Mon, 8 May 2023 10:59:34 -0600 Subject: [PATCH 674/852] remove allocatable arrays --- biogeochem/FatesPatchMod.F90 | 199 +++++++++++------------------------ 1 file changed, 59 insertions(+), 140 deletions(-) diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 index 22103fc6a7..8356a1f64c 100644 --- a/biogeochem/FatesPatchMod.F90 +++ b/biogeochem/FatesPatchMod.F90 @@ -72,82 +72,82 @@ module FatesPatchMod !:.........................................................................: ! LEAF ORGANIZATION - real(r8), allocatable :: pft_agb_profile(:,:) ! binned aboveground biomass, for patch fusion [kgC/m2] - real(r8) :: canopy_layer_tlai(nclmax) ! total leaf area index of each canopy layer [m2 veg/m2 canopy area] - ! (patch without bare ground) - ! used to determine attenuation of parameters during photosynthesis - real(r8) :: total_canopy_area ! area that is covered by vegetation [m2] - real(r8) :: total_tree_area ! area that is covered by woody vegetation [m2] - real(r8) :: zstar ! height of smallest canopy tree, only meaningful in "strict PPA" mode [m] - real(r8), allocatable :: elai_profile(:,:,:) ! exposed leaf area in each canopy layer, pft, and leaf layer [m2 leaf/m2 contributing crown area] - real(r8), allocatable :: esai_profile(:,:,:) ! exposed stem area in each canopy layer, pft, and leaf layer [m2 leaf/m2 contributing crown area] - real(r8), allocatable :: tlai_profile(:,:,:) - real(r8), allocatable :: tsai_profile(:,:,:) - real(r8), allocatable :: canopy_area_profile(:,:,:) ! fraction of crown area per canopy area in each layer - ! they will sum to 1.0 in the fully closed canopy layers - ! but only in leaf-layers that contain contributions - ! from all cohorts that donate to canopy_area - integer, allocatable :: canopy_mask(:,:) ! is there any of this pft in this canopy layer? - integer, allocatable :: nrad(:,:) ! number of exposed leaf layers for each canopy layer and pft - integer, allocatable :: ncan(:,:) ! number of total leaf layers for each canopy layer and pft - real(r8) :: c_stomata ! mean stomatal conductance of all leaves in the patch [umol/m2/s] - real(r8) :: c_lblayer ! mean boundary layer conductance of all leaves in the patch [umol/m2/s] + real(r8) :: pft_agb_profile(maxpft,n_dbh_bins) ! binned aboveground biomass, for patch fusion [kgC/m2] + real(r8) :: canopy_layer_tlai(nclmax) ! total leaf area index of each canopy layer [m2 veg/m2 canopy area] + ! (patch without bare ground) + ! used to determine attenuation of parameters during photosynthesis + real(r8) :: total_canopy_area ! area that is covered by vegetation [m2] + real(r8) :: total_tree_area ! area that is covered by woody vegetation [m2] + real(r8) :: zstar ! height of smallest canopy tree, only meaningful in "strict PPA" mode [m] + real(r8) :: elai_profile(nclmax,maxpft,nlevleaf) ! exposed leaf area in each canopy layer, pft, and leaf layer [m2 leaf/m2 contributing crown area] + real(r8) :: esai_profile(nclmax,maxpft,nlevleaf) ! exposed stem area in each canopy layer, pft, and leaf layer [m2 leaf/m2 contributing crown area] + real(r8) :: tlai_profile(nclmax,maxpft,nlevleaf) + real(r8) :: tsai_profile(nclmax,maxpft,nlevleaf) + real(r8) :: canopy_area_profile(nclmax,maxpft,nlevleaf) ! fraction of crown area per canopy area in each layer + ! they will sum to 1.0 in the fully closed canopy layers + ! but only in leaf-layers that contain contributions + ! from all cohorts that donate to canopy_area + integer :: canopy_mask(nclmax,maxpft) ! is there any of this pft in this canopy layer? + integer :: nrad(nclmax,maxpft) ! number of exposed leaf layers for each canopy layer and pft + integer :: ncan(nclmax,maxpft) ! number of total leaf layers for each canopy layer and pft + real(r8) :: c_stomata ! mean stomatal conductance of all leaves in the patch [umol/m2/s] + real(r8) :: c_lblayer ! mean boundary layer conductance of all leaves in the patch [umol/m2/s] !:.........................................................................: - real(r8), allocatable :: layer_height_profile(:,:,:) - real(r8), allocatable :: psn_z(:,:,:) - real(r8), allocatable :: nrmlzd_parprof_pft_dir_z(:,:,:,:) - real(r8), allocatable :: nrmlzd_parprof_pft_dif_z(:,:,:,:) - real(r8), allocatable :: nrmlzd_parprof_dir_z(:,:,:) - real(r8), allocatable :: nrmlzd_parprof_dif_z(:,:,:) + real(r8) :: layer_height_profile(nclmax,maxpft,nlevleaf) + real(r8) :: psn_z(nclmax,maxpft,nlevleaf) + real(r8) :: nrmlzd_parprof_pft_dir_z(n_rad_stream_types,nclmax,maxpft,nlevleaf) + real(r8) :: nrmlzd_parprof_pft_dif_z(n_rad_stream_types,nclmax,maxpft,nlevleaf) + real(r8) :: nrmlzd_parprof_dir_z(n_rad_stream_types,nclmax,nlevleaf) + real(r8) :: nrmlzd_parprof_dif_z(n_rad_stream_types,nclmax,nlevleaf) !:.........................................................................: ! RADIATION - real(r8) :: radiation_error ! radiation error [W/m2] - real(r8) :: fcansno ! fraction of canopy covered in snow [0-1] - logical :: solar_zenith_flag ! integer flag specifying daylight (based on zenith angle) - real(r8) :: solar_zenith_angle ! solar zenith angle [radians] - real(r8), allocatable :: gnd_alb_dif(:) ! ground albedo for diffuse rad, both bands [0-1] - real(r8), allocatable :: gnd_alb_dir(:) ! ground albedo for direct rad, both bands [0-1] + real(r8) :: radiation_error ! radiation error [W/m2] + real(r8) :: fcansno ! fraction of canopy covered in snow [0-1] + logical :: solar_zenith_flag ! integer flag specifying daylight (based on zenith angle) + real(r8) :: solar_zenith_angle ! solar zenith angle [radians] + real(r8) :: gnd_alb_dif(maxSWb) ! ground albedo for diffuse rad, both bands [0-1] + real(r8) :: gnd_alb_dir(maxSWb) ! ground albedo for direct rad, both bands [0-1] ! organized by canopy layer, pft, and leaf layer - real(r8), allocatable :: fabd_sun_z(:,:,:) ! sun fraction of direct light absorbed [0-1] - real(r8), allocatable :: fabd_sha_z(:,:,:) ! shade fraction of direct light absorbed [0-1] - real(r8), allocatable :: fabi_sun_z(:,:,:) ! sun fraction of indirect light absorbed [0-1] - real(r8), allocatable :: fabi_sha_z(:,:,:) ! shade fraction of indirect light absorbed [0-1] - real(r8), allocatable :: ed_parsun_z(:,:,:) ! PAR absorbed in the sun [W/m2] - real(r8), allocatable :: ed_parsha_z(:,:,:) ! PAR absorbed in the shade [W/m2] - real(r8), allocatable :: ed_laisun_z(:,:,:) - real(r8), allocatable :: ed_laisha_z(:,:,:) - real(r8), allocatable :: f_sun(:,:,:) ! fraction of leaves in the sun [0-1] + real(r8) :: fabd_sun_z(nclmax,maxpft,nlevleaf) ! sun fraction of direct light absorbed [0-1] + real(r8) :: fabd_sha_z(nclmax,maxpft,nlevleaf) ! shade fraction of direct light absorbed [0-1] + real(r8) :: fabi_sun_z(nclmax,maxpft,nlevleaf) ! sun fraction of indirect light absorbed [0-1] + real(r8) :: fabi_sha_z(nclmax,maxpft,nlevleaf) ! shade fraction of indirect light absorbed [0-1] + real(r8) :: ed_parsun_z(nclmax,maxpft,nlevleaf) ! PAR absorbed in the sun [W/m2] + real(r8) :: ed_parsha_z(nclmax,maxpft,nlevleaf) ! PAR absorbed in the shade [W/m2] + real(r8) :: ed_laisun_z(nclmax,maxpft,nlevleaf) + real(r8) :: ed_laisha_z(nclmax,maxpft,nlevleaf) + real(r8) :: f_sun(nclmax,maxpft,nlevleaf) ! fraction of leaves in the sun [0-1] ! radiation profiles for comparison against observations - real(r8), allocatable :: parprof_pft_dir_z(:,:,:) ! direct-beam PAR profile through canopy, by canopy, PFT, leaf level [W/m2] - real(r8), allocatable :: parprof_pft_dif_z(:,:,:) ! diffuse PAR profile through canopy, by canopy, PFT, leaf level [W/m2] - real(r8), allocatable :: parprof_dir_z(:,:) ! direct-beam PAR profile through canopy, by canopy, leaf level [W/m2] - real(r8), allocatable :: parprof_dif_z(:,:) ! diffuse PAR profile through canopy, by canopy, leaf level [W/m2] + real(r8) :: parprof_pft_dir_z(nclmax,maxpft,nlevleaf) ! direct-beam PAR profile through canopy, by canopy, PFT, leaf level [W/m2] + real(r8) :: parprof_pft_dif_z(nclmax,maxpft,nlevleaf) ! diffuse PAR profile through canopy, by canopy, PFT, leaf level [W/m2] + real(r8) :: parprof_dir_z(nclmax,nlevleaf) ! direct-beam PAR profile through canopy, by canopy, leaf level [W/m2] + real(r8) :: parprof_dif_z(nclmax,nlevleaf) ! diffuse PAR profile through canopy, by canopy, leaf level [W/m2] - real(r8), allocatable :: tr_soil_dir(:) ! fraction of incoming direct radiation transmitted to the soil as direct, by numSWB [0-1] - real(r8), allocatable :: tr_soil_dif(:) ! fraction of incoming diffuse radiation that is transmitted to the soil as diffuse [0-1] - real(r8), allocatable :: tr_soil_dir_dif(:) ! fraction of incoming direct radiation that is transmitted to the soil as diffuse [0-1] - real(r8), allocatable :: fab(:) ! fraction of incoming total radiation that is absorbed by the canopy - real(r8), allocatable :: fabd(:) ! fraction of incoming direct radiation that is absorbed by the canopy - real(r8), allocatable :: fabi(:) ! fraction of incoming diffuse radiation that is absorbed by the canopy - real(r8), allocatable :: sabs_dir(:) ! fraction of incoming direct radiation that is absorbed by the canopy - real(r8), allocatable :: sabs_dif(:) ! fraction of incoming diffuse radiation that is absorbed by the canopy + real(r8), allocatable :: tr_soil_dir(:) ! fraction of incoming direct radiation transmitted to the soil as direct, by numSWB [0-1] + real(r8), allocatable :: tr_soil_dif(:) ! fraction of incoming diffuse radiation that is transmitted to the soil as diffuse [0-1] + real(r8), allocatable :: tr_soil_dir_dif(:) ! fraction of incoming direct radiation that is transmitted to the soil as diffuse [0-1] + real(r8), allocatable :: fab(:) ! fraction of incoming total radiation that is absorbed by the canopy + real(r8), allocatable :: fabd(:) ! fraction of incoming direct radiation that is absorbed by the canopy + real(r8), allocatable :: fabi(:) ! fraction of incoming diffuse radiation that is absorbed by the canopy + real(r8), allocatable :: sabs_dir(:) ! fraction of incoming direct radiation that is absorbed by the canopy + real(r8), allocatable :: sabs_dif(:) ! fraction of incoming diffuse radiation that is absorbed by the canopy !:.........................................................................: ! ROOTS - real(r8), allocatable :: btran_ft(:) ! btran calculated seperately for each PFT - real(r8), allocatable :: bstress_sal_ft(:) ! bstress from salinity calculated seperately for each PFT + real(r8) :: btran_ft(maxpft) ! btran calculated seperately for each PFT + real(r8) :: bstress_sal_ft(maxpft) ! bstress from salinity calculated seperately for each PFT !:.........................................................................: ! EXTERNAL SEED RAIN - real(r8), allocatable :: nitr_repro_stoich(:) ! The NC ratio of a new recruit in this patch - real(r8), allocatable :: phos_repro_stoich(:) ! The PC ratio of a new recruit in this patch + real(r8) :: nitr_repro_stoich(maxpft) ! The NC ratio of a new recruit in this patch + real(r8) :: phos_repro_stoich(maxpft) ! The PC ratio of a new recruit in this patch !:.........................................................................: @@ -190,7 +190,7 @@ module FatesPatchMod real(r8) :: fd ! fire duration [min] ! fire effects - real(r8), allocatable :: scorch_ht(:) ! scorch height [m] + real(r8) :: scorch_ht(maxpft) ! scorch height [m] real(r8) :: frac_burnt ! fraction burnt [0-1/day] real(r8) :: tfc_ros ! total intensity-relevant fuel consumed - no trunks [kgC/m2 of burned ground/day] real(r8) :: burnt_frac_litter(nfsc) ! fraction of each litter pool burned, conditional on it being burned [0-1] @@ -230,41 +230,6 @@ subroutine init(this, numpft, numSWb, nlevsoil) integer, intent(in) :: nlevsoil ! number of soil layers ! allocate arrays - allocate(this%pft_agb_profile(numpft, N_DBH_BINS)) - allocate(this%elai_profile(nclmax,numpft,nlevleaf)) - allocate(this%esai_profile(nclmax,numpft,nlevleaf)) - allocate(this%tlai_profile(nclmax,numpft,nlevleaf)) - allocate(this%tsai_profile(nclmax,numpft,nlevleaf)) - allocate(this%canopy_area_profile(nclmax,numpft,nlevleaf)) - - allocate(this%canopy_mask(nclmax,numpft)) - allocate(this%nrad(nclmax,numpft)) - allocate(this%ncan(nclmax,numpft)) - - allocate(this%layer_height_profile(nclmax,numpft,nlevleaf)) - allocate(this%psn_z(nclmax,numpft,nlevleaf)) - allocate(this%nrmlzd_parprof_pft_dir_z(n_rad_stream_types,nclmax,numpft,nlevleaf)) - allocate(this%nrmlzd_parprof_pft_dif_z(n_rad_stream_types,nclmax,numpft,nlevleaf)) - allocate(this%nrmlzd_parprof_dir_z(n_rad_stream_types,nclmax,nlevleaf)) - allocate(this%nrmlzd_parprof_dif_z(n_rad_stream_types,nclmax,nlevleaf)) - - allocate(this%gnd_alb_dif(numSWb)) - allocate(this%gnd_alb_dir(numSWb)) - allocate(this%fabd_sun_z(nclmax,numpft,nlevleaf)) - allocate(this%fabd_sha_z(nclmax,numpft,nlevleaf)) - allocate(this%fabi_sun_z(nclmax,numpft,nlevleaf)) - allocate(this%fabi_sha_z(nclmax,numpft,nlevleaf)) - allocate(this%ed_parsun_z(nclmax,numpft,nlevleaf)) - allocate(this%ed_parsha_z(nclmax,numpft,nlevleaf)) - allocate(this%ed_laisun_z(nclmax,numpft,nlevleaf)) - allocate(this%ed_laisha_z(nclmax,numpft,nlevleaf)) - allocate(this%f_sun(nclmax,numpft,nlevleaf)) - - allocate(this%parprof_pft_dir_z(nclmax,numpft,nlevleaf)) - allocate(this%parprof_pft_dif_z(nclmax,numpft,nlevleaf)) - allocate(this%parprof_dir_z(nclmax,nlevleaf)) - allocate(this%parprof_dif_z(nclmax,nlevleaf)) - allocate(this%tr_soil_dir(numSWb)) allocate(this%tr_soil_dif(numSWb)) allocate(this%tr_soil_dir_dif(numSWb)) @@ -274,16 +239,6 @@ subroutine init(this, numpft, numSWb, nlevsoil) allocate(this%sabs_dir(numSWb)) allocate(this%sabs_dif(numSWb)) - allocate(this%btran_ft(numpft)) - allocate(this%bstress_sal_ft(numpft)) - - allocate(this%nitr_repro_stoich(numpft)) - allocate(this%phos_repro_stoich(numpft)) - - allocate(this%fragmentation_scaler(nlevsoil)) - - allocate(this%scorch_ht(numpft)) - ! initialize all values to nan call this%nan_values() @@ -642,37 +597,7 @@ subroutine free_memory(this) endif ! deallocate the allocatable arrays - deallocate(this%pft_agb_profile, & - this%elai_profile, & - this%esai_profile, & - this%tlai_profile, & - this%tsai_profile, & - this%canopy_area_profile, & - this%canopy_mask, & - this%nrad, & - this%ncan, & - this%layer_height_profile, & - this%psn_z, & - this%nrmlzd_parprof_pft_dir_z, & - this%nrmlzd_parprof_pft_dif_z, & - this%nrmlzd_parprof_dir_z, & - this%nrmlzd_parprof_dif_z, & - this%gnd_alb_dif, & - this%gnd_alb_dir, & - this%fabd_sun_z, & - this%fabd_sha_z, & - this%fabi_sun_z, & - this%fabi_sha_z, & - this%ed_parsun_z, & - this%ed_parsha_z, & - this%ed_laisun_z, & - this%ed_laisha_z, & - this%f_sun, & - this%parprof_pft_dir_z, & - this%parprof_pft_dif_z, & - this%parprof_dir_z, & - this%parprof_dif_z, & - this%tr_soil_dir, & + deallocate(this%tr_soil_dir, & this%tr_soil_dif, & this%tr_soil_dir_dif, & this%fab, & @@ -680,12 +605,6 @@ subroutine free_memory(this) this%fabi, & this%sabs_dir, & this%sabs_dif, & - this%btran_ft, & - this%bstress_sal_ft, & - this%nitr_repro_stoich, & - this%phos_repro_stoich, & - this%fragmentation_scaler, & - this%scorch_ht, & stat=istat, errmsg=smsg) if (istat/=0) then From b04fd2e2f5ef58d17bcdae150e5251ae7c824b4e Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 8 May 2023 11:47:24 -0700 Subject: [PATCH 675/852] More updates --- tools/luh2.py | 28 ++++++++++++++-------------- tools/luh2mod.py | 18 ++++++++++-------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/tools/luh2.py b/tools/luh2.py index 0457d092a5..5634534d66 100644 --- a/tools/luh2.py +++ b/tools/luh2.py @@ -31,34 +31,34 @@ def main(): ds_regrid_target = SetMaskSurfData(ds_regrid_target) # Regrid the luh2 data to the target grid - regridder_luh2 = RegridConservative(ds_luh2, ds_regrid_target, save=True) - regrid_luh2 = regridder_luh2(ds_luh2) + regridder_luh2,regrid_luh2 = RegridConservative(ds_luh2, ds_regrid_target, save=True) # # Regrid the inverted ice/water fraction data to the target grid - # # regridder_land_fraction = RegridConservative(ds_luh2_static, ds_regrid_target) - # # regrid_land_fraction = regridder_land_fraction(ds_luh2_static) - # regrid_land_fraction = regridder_luh2(ds_luh2_static) + #regridder_land_fraction = RegridConservative(ds_luh2_static, ds_regrid_target) + #regrid_land_fraction = regridder_land_fraction(ds_luh2_static) + regrid_land_fraction = regridder_luh2(ds_luh2_static) # # Adjust the luh2 data by the land fraction # # To Do: check if we need to do this for transition and management data as well - # regrid_luh2 = regrid_luh2 / regrid_land_fraction.landfrac + regrid_luh2 = regrid_luh2 / regrid_land_fraction.landfrac # # Rename the dimensions for the output + # TO DO: double check if this is necessary # regrid_luh2 = regrid_luh2.rename_dims(dims_dict={'latitude':'lsmlat','longitude':'lsmlon'}) - # regrid_luh2["LONGXY"] = ds_regrid_target["LONGXY"] - # regrid_luh2["LATIXY"] = ds_regrid_target["LATIXY"] + regrid_luh2["LONGXY"] = ds_regrid_target["LONGXY"] + regrid_luh2["LATIXY"] = ds_regrid_target["LATIXY"] # # Add 'YEAR' as a variable. This is an old requirement of the HLM and should simply be a copy of the `time` dimension - # regrid_luh2["YEAR"] = regrid_luh2.time + regrid_luh2["YEAR"] = regrid_luh2.time # # Write the files # # TO DO: add check to handle if the user enters the full path - # output_filename = args.output - # if (args.output == None): - # output_filename = 'LUH2_timeseries.nc' + output_filename = args.output + if (args.output == None): + output_filename = 'LUH2_timeseries.nc' - # output_file = os.path.join(os.getcwd(),output_filename) - # regrid_luh2.to_netcdf(output_file) + output_file = os.path.join(os.getcwd(),output_filename) + regrid_luh2.to_netcdf(output_file) # Example of file naming scheme # finb_luh2_all_regrid.to_netcdf('LUH2_historical_1850_2015_4x5_cdk_220302.nc') diff --git a/tools/luh2mod.py b/tools/luh2mod.py index f106d784c0..d8749b08dc 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -219,14 +219,16 @@ def RegridConservative(ds_to_regrid,ds_regrid_target,save=False): ds_varnames = list(ds_to_regrid.variables.keys()) varlen = len(ds_to_regrid.variables) for i in range(varlen-1): - if (not(ds_varnames[i] == 'time' or ds_varnames[i] == 'lon' or - ds_varnames[i] == 'lat')): - print("regridding variable {}/{}: {}".format(i+1, varlen, ds_varnames[i])) - ds_regrid[ds_varnames[i]] = regridder(ds_to_regrid[ds_varnames[i]]) - else: - print("skipping variable {}/{}: {}".format(i+1, varlen, ds_varnames[i])) - - return(ds_regrid) + # Skip time variable + if (ds_varnames[i] != "time"): + # Only regrid variables that match the lat/lon shape + if (ds_regrid[ds_varnames[i]][0].shape == (ds_regrid.lat.shape[0], ds_regrid.lon.shape[0])): + print("regridding variable {}/{}: {}".format(i+1, varlen, ds_varnames[i])) + ds_regrid[ds_varnames[i]] = regridder(ds_to_regrid[ds_varnames[i]]) + else: + print("skipping variable {}/{}: {}".format(i+1, varlen, ds_varnames[i])) + + return(regridder,ds_regrid) # General functionality needed # - collect data for specific user-defined time period From 9692da0aa0d42f2d6ddaee859dd21216c5d02e7e Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 8 May 2023 11:53:24 -0700 Subject: [PATCH 676/852] Update phi1b calculation to use xl directly --- biogeophys/EDSurfaceAlbedoMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeophys/EDSurfaceAlbedoMod.F90 b/biogeophys/EDSurfaceAlbedoMod.F90 index 465cefff52..2f1696a1db 100644 --- a/biogeophys/EDSurfaceAlbedoMod.F90 +++ b/biogeophys/EDSurfaceAlbedoMod.F90 @@ -367,7 +367,7 @@ subroutine PatchNormanRadiation (currentPatch, & !if ( abs(chil) <= 0.01_r8) then ! chil = 0.01_r8 !end if - phi1b(ft) = 0.5_r8 - 0.633_r8*chil - 0.330_r8*chil*chil + phi1b(ft) = 0.5_r8 - 0.633_r8*xl(ft) - 0.330_r8*xl(ft)*xl(ft) phi2b(ft) = 0.877_r8 * (1._r8 - 2._r8*phi1b(ft)) !0 = horiz leaves, 1 - vert leaves. gdir = phi1b(ft) + phi2b(ft) * sin(sb) !how much direct light penetrates a singleunit of lai? From 3d5709b161294014073383fdb4ef9a2a0c940936 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Mon, 8 May 2023 13:29:32 -0600 Subject: [PATCH 677/852] add abort back --- main/FatesGlobals.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/FatesGlobals.F90 b/main/FatesGlobals.F90 index 71e4120df0..ebc0f326ff 100644 --- a/main/FatesGlobals.F90 +++ b/main/FatesGlobals.F90 @@ -83,7 +83,7 @@ subroutine fates_endrun(msg) ! This subroutine was derived from CLM's ! endrun_vanilla() in abortutils.F90 ! - !use shr_sys_mod , only: shr_sys_abort + use shr_sys_mod , only: shr_sys_abort ! ! !ARGUMENTS: implicit none From 447b2f4257b4e6edcd702e3875dfe61e759a5f5e Mon Sep 17 00:00:00 2001 From: adrifoster Date: Mon, 8 May 2023 14:00:11 -0600 Subject: [PATCH 678/852] add fragmentation scalar --- biogeochem/FatesPatchMod.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 index 8356a1f64c..96ce038b70 100644 --- a/biogeochem/FatesPatchMod.F90 +++ b/biogeochem/FatesPatchMod.F90 @@ -605,6 +605,7 @@ subroutine free_memory(this) this%fabi, & this%sabs_dir, & this%sabs_dif, & + this%fragmentation_scaler, & stat=istat, errmsg=smsg) if (istat/=0) then From 20f9cb122ec9bc161df0039a66ccce865274847e Mon Sep 17 00:00:00 2001 From: adrifoster Date: Mon, 8 May 2023 14:18:58 -0600 Subject: [PATCH 679/852] add shr_sys_abort use --- main/FatesGlobals.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/FatesGlobals.F90 b/main/FatesGlobals.F90 index 71e4120df0..ebc0f326ff 100644 --- a/main/FatesGlobals.F90 +++ b/main/FatesGlobals.F90 @@ -83,7 +83,7 @@ subroutine fates_endrun(msg) ! This subroutine was derived from CLM's ! endrun_vanilla() in abortutils.F90 ! - !use shr_sys_mod , only: shr_sys_abort + use shr_sys_mod , only: shr_sys_abort ! ! !ARGUMENTS: implicit none From ecae3ab879d5b55a7bf42d49098d4a94759e040e Mon Sep 17 00:00:00 2001 From: adrifoster Date: Mon, 8 May 2023 14:21:25 -0600 Subject: [PATCH 680/852] fragmentation scalar --- biogeochem/FatesPatchMod.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 index 96ce038b70..dad402ac49 100644 --- a/biogeochem/FatesPatchMod.F90 +++ b/biogeochem/FatesPatchMod.F90 @@ -238,6 +238,7 @@ subroutine init(this, numpft, numSWb, nlevsoil) allocate(this%fabi(numSWb)) allocate(this%sabs_dir(numSWb)) allocate(this%sabs_dif(numSWb)) + allocate(this%fragmentation_scaler(nlevsoil)) ! initialize all values to nan call this%nan_values() From 472eaa616c300dabab38b2103b0ed646c3c33a8c Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 8 May 2023 14:54:54 -0700 Subject: [PATCH 681/852] start working on allowing read in of regridder file --- tools/luh2.py | 36 ++++++++++++++++++++++-------------- tools/luh2mod.py | 2 ++ 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/tools/luh2.py b/tools/luh2.py index 5634534d66..559a72610e 100644 --- a/tools/luh2.py +++ b/tools/luh2.py @@ -13,25 +13,31 @@ def main(): args = CommandLineArgs() # Prep the LUH2 datasets and regrid target - # To Do: need logic to handle taking in a saved regrid file ds_luh2 = PrepDataSet(args.luh2_file,args.begin,args.end) - ds_regrid_target= PrepDataSet(args.regridder_target_file,args.begin,args.end) - # Import the LUH2 static data to use for masking - ds_luh2_static = ImportData(args.luh2_static_file) + if (args.regridder_file == None): + ds_regrid_target = PrepDataSet(args.regridder_target_file,args.begin,args.end) - # Create new variable where the ice water fraction is inverted - ds_luh2_static["landfrac"] = 1 - ds_luh2_static.icwtr + # Import the LUH2 static data to use for masking + ds_luh2_static = ImportData(args.luh2_static_file) - # Mask all LUH2 input data using the ice/water fraction for the LUH2 static data - ds_luh2 = SetMaskLUH2(ds_luh2, ds_luh2_static) - ds_luh2_static = SetMaskLUH2(ds_luh2_static, ds_luh2_static) + # Create new variable where the ice water fraction is inverted + ds_luh2_static["landfrac"] = 1 - ds_luh2_static.icwtr - # Mask the regrid target - ds_regrid_target = SetMaskSurfData(ds_regrid_target) + # Mask all LUH2 input data using the ice/water fraction for the LUH2 static data + ds_luh2 = SetMaskLUH2(ds_luh2, ds_luh2_static) + ds_luh2_static = SetMaskLUH2(ds_luh2_static, ds_luh2_static) - # Regrid the luh2 data to the target grid - regridder_luh2,regrid_luh2 = RegridConservative(ds_luh2, ds_regrid_target, save=True) + # Mask the regrid target + ds_regrid_target = SetMaskSurfData(ds_regrid_target) + + # Regrid the luh2 data to the target grid + regridder_luh2,regrid_luh2 = RegridConservative(ds_luh2, ds_regrid_target, save=True) + + elif (args.regridder_target_file == None): + regridder_luhs = ImportData(args.regridder_file) + # TO DO: check that the time bounds match the argument bounds + # TO DO: create bypass option to regridder function # # Regrid the inverted ice/water fraction data to the target grid #regridder_land_fraction = RegridConservative(ds_luh2_static, ds_regrid_target) @@ -53,11 +59,13 @@ def main(): # # Write the files # # TO DO: add check to handle if the user enters the full path - output_filename = args.output if (args.output == None): output_filename = 'LUH2_timeseries.nc' + else: + output_filename = args.output output_file = os.path.join(os.getcwd(),output_filename) + print("generating output: {}".format(output_file)) regrid_luh2.to_netcdf(output_file) # Example of file naming scheme diff --git a/tools/luh2mod.py b/tools/luh2mod.py index d8749b08dc..5e3e051e6a 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -227,6 +227,8 @@ def RegridConservative(ds_to_regrid,ds_regrid_target,save=False): ds_regrid[ds_varnames[i]] = regridder(ds_to_regrid[ds_varnames[i]]) else: print("skipping variable {}/{}: {}".format(i+1, varlen, ds_varnames[i])) + else: + print("skipping variable {}/{}: {}".format(i+1, varlen, ds_varnames[i])) return(regridder,ds_regrid) From 2e1c73623f2c98eca7b13ad7afe0f5b6dbf34f2a Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 8 May 2023 17:03:47 -0700 Subject: [PATCH 682/852] Fix regridding loop --- tools/luh2.py | 16 +++++++++++--- tools/luh2mod.py | 55 ++++++++++++++++++++++++++++++++++-------------- 2 files changed, 52 insertions(+), 19 deletions(-) diff --git a/tools/luh2.py b/tools/luh2.py index 559a72610e..0a5ea6229e 100644 --- a/tools/luh2.py +++ b/tools/luh2.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import argparse, os +import xarray as xr from luh2mod import PrepDataSet, ImportData, SetMaskLUH2, SetMaskSurfData from luh2mod import RegridConservative @@ -32,10 +33,10 @@ def main(): ds_regrid_target = SetMaskSurfData(ds_regrid_target) # Regrid the luh2 data to the target grid - regridder_luh2,regrid_luh2 = RegridConservative(ds_luh2, ds_regrid_target, save=True) + regrid_luh2,regridder_luh2 = RegridConservative(ds_luh2, ds_regrid_target, save=True) elif (args.regridder_target_file == None): - regridder_luhs = ImportData(args.regridder_file) + regridder_luh2 = ImportData(args.regridder_file) # TO DO: check that the time bounds match the argument bounds # TO DO: create bypass option to regridder function @@ -50,13 +51,19 @@ def main(): # # Rename the dimensions for the output # TO DO: double check if this is necessary - # regrid_luh2 = regrid_luh2.rename_dims(dims_dict={'latitude':'lsmlat','longitude':'lsmlon'}) + regrid_luh2 = regrid_luh2.rename_dims(dims_dict={'lat':'lsmlat','lon':'lsmlon'}) regrid_luh2["LONGXY"] = ds_regrid_target["LONGXY"] regrid_luh2["LATIXY"] = ds_regrid_target["LATIXY"] # # Add 'YEAR' as a variable. This is an old requirement of the HLM and should simply be a copy of the `time` dimension regrid_luh2["YEAR"] = regrid_luh2.time + # Merge existing regrided luh2 file with merge input target + # TO DO: check that the grid resolution and time bounds match + if (args.luh2_merge_file != None): + ds_luh2_merge = ImportData(args.luh2_merge_file) + regrid_luh2 = regrid_luhs.merge(ds_luh2_merge) + # # Write the files # # TO DO: add check to handle if the user enters the full path if (args.output == None): @@ -95,6 +102,9 @@ def CommandLineArgs(): # Optional output argument parser.add_argument("-o","--output") + # Optional merge argument to enable merging of other files + parser.add_argument("-m", "--luh2_merge_file") + args = parser.parse_args() return(args) diff --git a/tools/luh2mod.py b/tools/luh2mod.py index 5e3e051e6a..63b52f1331 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -198,39 +198,62 @@ def CheckDataSet(input_dataset): def RegridConservative(ds_to_regrid,ds_regrid_target,save=False): + # define the regridder transformation + regridder = GenerateRegridder(ds_to_regrid, ds_regrid_target, save) - print("\nDefining regridder") + # Loop through the variables to regrid + ds_regrid = RegridLoop(ds_to_regrid, regridder) - # define the regridder transformation - regridder = xe.Regridder(ds_to_regrid, ds_regrid_target, "conservative") + return (ds_regrid, regridder) - # If save flag is set, write regridder to a file - # TO DO: define a more useful name based on inputs - if(save): - filename = regridder.to_netcdf("regridder.nc") - print("regridder saved to file: ", filename) +def RegridLoop(ds_to_regrid, regridder): - ds_regrid = ds_to_regrid.copy() - print("regridding") + # To Do: implement this with dask + print("\nRegridding") # Loop through the variables one at a time to conserve memory - # To Do: implement dask - # To Do: can we skip time, lat, and lon variables? ds_varnames = list(ds_to_regrid.variables.keys()) varlen = len(ds_to_regrid.variables) + first_var = False for i in range(varlen-1): + # Skip time variable if (ds_varnames[i] != "time"): - # Only regrid variables that match the lat/lon shape - if (ds_regrid[ds_varnames[i]][0].shape == (ds_regrid.lat.shape[0], ds_regrid.lon.shape[0])): + + # Only regrid variables that match the lat/lon shape. + if (ds_to_regrid[ds_varnames[i]][0].shape == (ds_to_regrid.lat.shape[0], ds_to_regrid.lon.shape[0])): print("regridding variable {}/{}: {}".format(i+1, varlen, ds_varnames[i])) - ds_regrid[ds_varnames[i]] = regridder(ds_to_regrid[ds_varnames[i]]) + + # For the first non-coordinate variable, copy and regrid the dataset as a whole. + # This makes sure to correctly include the lat/lon in the regridding. + if (not(first_var)): + ds_regrid = ds_to_regrid[ds_varnames[i]].to_dataset() # convert data array to dataset + ds_regrid = regridder(ds_regrid) + first_var = True + + # Once the first variable has been included, then we can regrid by variable + else: + ds_regrid[ds_varnames[i]] = regridder(ds_to_regrid[ds_varnames[i]]) else: print("skipping variable {}/{}: {}".format(i+1, varlen, ds_varnames[i])) else: print("skipping variable {}/{}: {}".format(i+1, varlen, ds_varnames[i])) - return(regridder,ds_regrid) + return(ds_regrid) + +def GenerateRegridder(ds_to_regrid, ds_regrid_target,save=False): + + print("\nDefining regridder") + regridder = xe.Regridder(ds_to_regrid, ds_regrid_target, "conservative") + + # If save flag is set, write regridder to a file + # TO DO: define a more useful name based on inputs + if(save): + filename = regridder.to_netcdf("regridder.nc") + print("regridder saved to file: ", filename) + + return(regridder) + # General functionality needed # - collect data for specific user-defined time period From 21c7c9600423a3c6767c0ccae7317f71096ee0db Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 9 May 2023 07:23:31 -0600 Subject: [PATCH 683/852] begin to update for style --- biogeochem/FatesPatchMod.F90 | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 index dad402ac49..a5f0f7bed5 100644 --- a/biogeochem/FatesPatchMod.F90 +++ b/biogeochem/FatesPatchMod.F90 @@ -216,7 +216,7 @@ module FatesPatchMod contains - subroutine init(this, numpft, numSWb, nlevsoil) + subroutine init(this, numSWb, nlevsoil) ! ! DESCRIPTION: ! Initialize a new patch - allocate arrays and set values to nan and/or @@ -225,7 +225,6 @@ subroutine init(this, numpft, numSWb, nlevsoil) ! ARGUMENTS: class(fates_patch_type), intent(inout) :: this ! patch object - integer, intent(in) :: numpft ! number of pfts integer, intent(in) :: numSWb ! number of shortwave broad-bands to track integer, intent(in) :: nlevsoil ! number of soil layers @@ -250,7 +249,7 @@ end subroutine init !:.........................................................................: - subroutine nan_values(this) + subroutine nanValues(this) ! ! DESCRIPTION: ! Sets all values in patch to nan From e8c2ea8fcaed26a01626cae03b6d3c6552a8223e Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 9 May 2023 11:06:11 -0600 Subject: [PATCH 684/852] update style on patchmod --- biogeochem/EDPatchDynamicsMod.F90 | 4 +- biogeochem/FatesPatchMod.F90 | 155 +++++++++++++++--------------- main/EDInitMod.F90 | 2 +- main/FatesInventoryInitMod.F90 | 2 +- main/FatesRestartInterfaceMod.F90 | 2 +- 5 files changed, 83 insertions(+), 82 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index c5bfabd6ec..8780294ee9 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -537,7 +537,7 @@ subroutine spawn_patches( currentSite, bc_in) ! first create patch to receive primary forest area if ( site_areadis_primary .gt. nearzero ) then allocate(new_patch_primary) - call new_patch_primary%create(age, site_areadis_primary, & + call new_patch_primary%Create(age, site_areadis_primary, & primaryforest, i_nocomp_pft, hlm_numSWb, numpft, & currentSite%nlevsoil, hlm_current_tod) @@ -560,7 +560,7 @@ subroutine spawn_patches( currentSite, bc_in) ! next create patch to receive secondary forest area if (site_areadis_secondary .gt. nearzero) then allocate(new_patch_secondary) - call new_patch_secondary%create(age, site_areadis_secondary, & + call new_patch_secondary%Create(age, site_areadis_secondary, & secondaryforest, i_nocomp_pft, hlm_numSWb, numpft, & currentSite%nlevsoil, hlm_current_tod) diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 index a5f0f7bed5..ddeee61f65 100644 --- a/biogeochem/FatesPatchMod.F90 +++ b/biogeochem/FatesPatchMod.F90 @@ -37,7 +37,7 @@ module FatesPatchMod type (fates_patch_type), pointer :: older => null() ! pointer to next older patch type (fates_patch_type), pointer :: younger => null() ! pointer to next younger patch - !:.........................................................................: + !--------------------------------------------------------------------------- ! INDICES integer :: patchno ! unique number given to each new patch created for tracking @@ -48,7 +48,7 @@ module FatesPatchMod ! is set to unset. This is set in patch%create as an argument ! to that procedure. - !:.........................................................................: + !--------------------------------------------------------------------------- ! PATCH INFO real(r8) :: age ! average patch age [years] @@ -59,7 +59,7 @@ module FatesPatchMod integer :: anthro_disturbance_label ! patch label for anthropogenic disturbance classification real(r8) :: age_since_anthro_disturbance ! average age for secondary forest since last anthropogenic disturbance [years] - !:.........................................................................: + !--------------------------------------------------------------------------- ! RUNNING MEANS !class(rmean_type), pointer :: t2m ! place-holder for 2m air temperature (variable window-size) @@ -69,7 +69,7 @@ module FatesPatchMod class(rmean_type), pointer :: tveg_longterm ! long-term running mean of vegetation temperature at the ! leaf photosynthesis acclimation timescale [K] (i.e T_home) - !:.........................................................................: + !--------------------------------------------------------------------------- ! LEAF ORGANIZATION real(r8) :: pft_agb_profile(maxpft,n_dbh_bins) ! binned aboveground biomass, for patch fusion [kgC/m2] @@ -92,8 +92,8 @@ module FatesPatchMod integer :: ncan(nclmax,maxpft) ! number of total leaf layers for each canopy layer and pft real(r8) :: c_stomata ! mean stomatal conductance of all leaves in the patch [umol/m2/s] real(r8) :: c_lblayer ! mean boundary layer conductance of all leaves in the patch [umol/m2/s] - !:.........................................................................: - + + !TODO - can we delete these? real(r8) :: layer_height_profile(nclmax,maxpft,nlevleaf) real(r8) :: psn_z(nclmax,maxpft,nlevleaf) real(r8) :: nrmlzd_parprof_pft_dir_z(n_rad_stream_types,nclmax,maxpft,nlevleaf) @@ -101,7 +101,7 @@ module FatesPatchMod real(r8) :: nrmlzd_parprof_dir_z(n_rad_stream_types,nclmax,nlevleaf) real(r8) :: nrmlzd_parprof_dif_z(n_rad_stream_types,nclmax,nlevleaf) - !:.........................................................................: + !--------------------------------------------------------------------------- ! RADIATION real(r8) :: radiation_error ! radiation error [W/m2] @@ -137,19 +137,19 @@ module FatesPatchMod real(r8), allocatable :: sabs_dir(:) ! fraction of incoming direct radiation that is absorbed by the canopy real(r8), allocatable :: sabs_dif(:) ! fraction of incoming diffuse radiation that is absorbed by the canopy - !:.........................................................................: + !--------------------------------------------------------------------------- ! ROOTS real(r8) :: btran_ft(maxpft) ! btran calculated seperately for each PFT real(r8) :: bstress_sal_ft(maxpft) ! bstress from salinity calculated seperately for each PFT - !:.........................................................................: + !--------------------------------------------------------------------------- ! EXTERNAL SEED RAIN real(r8) :: nitr_repro_stoich(maxpft) ! The NC ratio of a new recruit in this patch real(r8) :: phos_repro_stoich(maxpft) ! The PC ratio of a new recruit in this patch - !:.........................................................................: + !--------------------------------------------------------------------------- ! DISTURBANCE real(r8) :: disturbance_rates(n_dist_types) ! disturbance rate [0-1/day] from 1) mortality @@ -157,13 +157,13 @@ module FatesPatchMod ! 3) logging mortatliy real(r8) :: fract_ldist_not_harvested ! fraction of logged area that is canopy trees that weren't harvested [0-1] - !:.........................................................................: + !--------------------------------------------------------------------------- ! LITTER AND COARSE WOODY DEBRIS type(litter_type), pointer :: litter(:) ! litter (leaf,fnrt,CWD and seeds) for different elements real(r8), allocatable :: fragmentation_scaler(:) ! scale rate of litter fragmentation based on soil layer [0-1] - !:.........................................................................: + !--------------------------------------------------------------------------- ! FUELS AND FIRE ! fuel characteristics @@ -195,61 +195,62 @@ module FatesPatchMod real(r8) :: tfc_ros ! total intensity-relevant fuel consumed - no trunks [kgC/m2 of burned ground/day] real(r8) :: burnt_frac_litter(nfsc) ! fraction of each litter pool burned, conditional on it being burned [0-1] - !:.........................................................................: + !--------------------------------------------------------------------------- ! PLANT HYDRAULICS (not currently used in hydraulics RGK 03-2018) ! type(ed_patch_hydr_type), pointer :: pa_hydr ! All patch hydraulics data, see FatesHydraulicsMemMod.F90 contains - procedure :: init - procedure :: nan_values - procedure :: zero_values - procedure :: init_running_means - procedure :: init_litter - procedure :: create - procedure :: free_memory - procedure :: dump - procedure :: check_vars + procedure :: Init + procedure :: NanValues + procedure :: ZeroValues + procedure :: InitRunningMeans + procedure :: InitLitter + procedure :: Create + procedure :: FreeMemory + procedure :: Dump + procedure :: CheckVars end type fates_patch_type contains - subroutine init(this, numSWb, nlevsoil) + !=========================================================================== + + subroutine Init(this, num_swb, num_levsoil) ! ! DESCRIPTION: - ! Initialize a new patch - allocate arrays and set values to nan and/or - ! 0.0 + ! Initialize a new patch - allocate arrays and set values to nan and/or 0.0 ! ! ARGUMENTS: class(fates_patch_type), intent(inout) :: this ! patch object - integer, intent(in) :: numSWb ! number of shortwave broad-bands to track - integer, intent(in) :: nlevsoil ! number of soil layers + integer, intent(in) :: num_swb ! number of shortwave broad-bands to track + integer, intent(in) :: num_levsoil ! number of soil layers ! allocate arrays - allocate(this%tr_soil_dir(numSWb)) - allocate(this%tr_soil_dif(numSWb)) - allocate(this%tr_soil_dir_dif(numSWb)) - allocate(this%fab(numSWb)) - allocate(this%fabd(numSWb)) - allocate(this%fabi(numSWb)) - allocate(this%sabs_dir(numSWb)) - allocate(this%sabs_dif(numSWb)) - allocate(this%fragmentation_scaler(nlevsoil)) + allocate(this%tr_soil_dir(num_swb)) + allocate(this%tr_soil_dif(num_swb)) + allocate(this%tr_soil_dir_dif(num_swb)) + allocate(this%fab(num_swb)) + allocate(this%fabd(num_swb)) + allocate(this%fabi(num_swb)) + allocate(this%sabs_dir(num_swb)) + allocate(this%sabs_dif(num_swb)) + allocate(this%fragmentation_scaler(num_levsoil)) ! initialize all values to nan - call this%nan_values() + call this%NanValues() ! zero values that should be zeroed - call this%zero_values() + call this%ZeroValues() - end subroutine init + end subroutine Init - !:.........................................................................: + !=========================================================================== - subroutine nanValues(this) + subroutine NanValues(this) ! ! DESCRIPTION: ! Sets all values in patch to nan @@ -370,11 +371,11 @@ subroutine nanValues(this) this%tfc_ros = nan this%burnt_frac_litter(:) = nan - end subroutine nan_values + end subroutine NanValues - !:.........................................................................: + !=========================================================================== - subroutine zero_values(this) + subroutine ZeroValues(this) ! ! DESCRIPTION: ! sets specific variables in patch to zero @@ -445,11 +446,11 @@ subroutine zero_values(this) this%tfc_ros = 0.0_r8 this%burnt_frac_litter(:) = 0.0_r8 - end subroutine zero_values + end subroutine ZeroValues - !:.........................................................................: + !=========================================================================== - subroutine init_running_means(this, current_tod) + subroutine InitRunningMeans(this, current_tod) ! ! DESCRIPTION: ! set initial values for patch running means @@ -473,20 +474,20 @@ subroutine init_running_means(this, current_tod) call this%tveg_lpa%InitRmean(ema_lpa, init_value=temp_init_veg) call this%tveg_longterm%InitRmean(ema_longterm, init_value=temp_init_veg) - end subroutine init_running_means + end subroutine InitRunningMeans - !:.........................................................................: + !=========================================================================== - subroutine init_litter(this, numpft, nlevsoil) + subroutine InitLitter(this, num_pft, num_levsoil) ! ! DESCRIPTION: ! set initial values for litter ! ! ARGUMENTS: - class(fates_patch_type), intent(inout) :: this ! patch object - integer, intent(in) :: numpft ! number of pfts to simulate - integer, intent(in) :: nlevsoil ! number of soil layers + class(fates_patch_type), intent(inout) :: this ! patch object + integer, intent(in) :: num_pft ! number of pfts to simulate + integer, intent(in) :: num_levsoil ! number of soil layers ! LOCALS: integer :: el ! looping index @@ -494,7 +495,7 @@ subroutine init_litter(this, numpft, nlevsoil) allocate(this%litter(num_elements)) do el = 1, num_elements - call this%litter(el)%InitAllocate(numpft, nlevsoil, element_list(el)) + call this%litter(el)%InitAllocate(num_pft, num_levsoil, element_list(el)) call this%litter(el)%ZeroFlux() call this%litter(el)%InitConditions(init_leaf_fines=fates_unset_r8, & init_root_fines=fates_unset_r8, init_ag_cwd=fates_unset_r8, & @@ -502,12 +503,12 @@ subroutine init_litter(this, numpft, nlevsoil) init_seed_germ=fates_unset_r8) end do - end subroutine init_litter + end subroutine InitLitter - !:.........................................................................: + !=========================================================================== - subroutine create(this, age, areap, label, nocomp_pft, numSWb, numpft, & - nlevsoil, current_tod) + subroutine Create(this, age, area, label, nocomp_pft, num_swb, num_pft, & + num_levsoil, current_tod) ! ! DESCRIPTION: ! create a new patch with input and default values @@ -516,28 +517,28 @@ subroutine create(this, age, areap, label, nocomp_pft, numSWb, numpft, & ! ARGUMENTS: class(fates_patch_type), intent(inout) :: this ! patch object real(r8), intent(in) :: age ! notional age of this patch in years - real(r8), intent(in) :: areap ! initial area of this patch in m2. + real(r8), intent(in) :: area ! initial area of this patch in m2. integer, intent(in) :: label ! anthropogenic disturbance label integer, intent(in) :: nocomp_pft ! no-competition mode pft label - integer, intent(in) :: numSWb ! number of shortwave broad-bands to track - integer, intent(in) :: numpft ! number of pfts to simulate - integer, intent(in) :: nlevsoil ! number of soil layers + integer, intent(in) :: num_swb ! number of shortwave broad-bands to track + integer, intent(in) :: num_pft ! number of pfts to simulate + integer, intent(in) :: num_levsoil ! number of soil layers integer, intent(in) :: current_tod ! time of day [seconds past 0Z] ! initialize patch ! sets all values to nan, then some values to zero - call this%init(numpft, numSWb, nlevsoil) + call this%Init(num_swb, num_levsoil) ! initialize running means for patch - call this%init_running_means(current_tod) + call this%InitRunningMeans(current_tod) ! initialize litter - call this%init_litter(numpft, nlevsoil) + call this%InitLitter(num_pft, num_levsoil) ! assign known patch attributes this%age = age this%age_class = 1 - this%area = areap + this%area = area ! assign anthropgenic disturbance category and label this%anthro_disturbance_label = label @@ -552,11 +553,11 @@ subroutine create(this, age, areap, label, nocomp_pft, numSWb, numpft, & this%tr_soil_dif(:) = 1.0_r8 this%NCL_p = 1 - end subroutine create + end subroutine Create - !:.........................................................................: + !=========================================================================== - subroutine free_memory(this) + subroutine FreeMemory(this) ! ! DESCRIPTION: ! deallocate the allocatable memory associated with this patch @@ -630,11 +631,11 @@ subroutine free_memory(this) call endrun(msg=errMsg(sourcefile, __LINE__)) endif - end subroutine free_memory + end subroutine FreeMemory - !:.........................................................................: + !=========================================================================== - subroutine dump(this) + subroutine Dump(this) ! ! DESCRIPTION: ! print attributes of a patch @@ -679,11 +680,11 @@ subroutine dump(this) write(fates_log(),*) 'bg_cwd(c,sl): ',sum(this%litter(el)%bg_cwd) end do - end subroutine dump + end subroutine Dump - !:.........................................................................: + !=========================================================================== - subroutine check_vars(this, var_aliases, return_code) + subroutine CheckVars(this, var_aliases, return_code) ! ! DESCRIPTION: ! perform numerical checks on patch variables of interest @@ -736,8 +737,8 @@ subroutine check_vars(this, var_aliases, return_code) end if end if -end subroutine check_vars + end subroutine CheckVars -!:.........................................................................: + !=========================================================================== end module FatesPatchMod \ No newline at end of file diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 8dd15a9a8d..3419596026 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -611,7 +611,7 @@ subroutine init_patches( nsites, sites, bc_in) if(newparea.gt.0._r8)then ! Stop patches being initilialized when PFT not present in nocomop mode allocate(newp) - call newp%create(age, newparea, primaryforest, nocomp_pft, & + call newp%Create(age, newparea, primaryforest, nocomp_pft, & hlm_numSWb, numpft, sites(s)%nlevsoil, hlm_current_tod) if(is_first_patch.eq.itrue)then !is this the first patch? diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index 1c9b0f9449..254dc100ff 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -276,7 +276,7 @@ subroutine initialize_sites_by_inventory(nsites,sites,bc_in) age_init = 0.0_r8 area_init = 0.0_r8 allocate(newpatch) - call newpatch%create(age_init, area_init, primaryforest, & + call newpatch%Create(age_init, area_init, primaryforest, & fates_unset_int, hlm_numSWb, numpft, sites(s)%nlevsoil, & hlm_current_tod) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index dcd99da82e..f76fdd2680 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -2590,7 +2590,7 @@ subroutine create_patchcohort_structure(this, nc, nsites, sites, bc_in, bc_out) nocomp_pft = fates_unset_int ! the nocomp_pft label is set after patch creation has occured in 'get_restart_vectors' ! make new patch - call newp%create(fates_unset_r8, fates_unset_r8, primaryforest, & + call newp%Create(fates_unset_r8, fates_unset_r8, primaryforest, & nocomp_pft, hlm_numSWb, numpft, sites(s)%nlevsoil, & hlm_current_tod) From 4b9e9d5b6aa7277edd1f97e1fee1aca4010a98dd Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 9 May 2023 11:24:21 -0600 Subject: [PATCH 685/852] update style to match style guide --- biogeochem/EDCanopyStructureMod.F90 | 4 +- biogeochem/EDCohortDynamicsMod.F90 | 8 +-- biogeochem/EDPatchDynamicsMod.F90 | 10 +-- biogeochem/EDPhysiologyMod.F90 | 6 +- biogeochem/FatesCohortMod.F90 | 96 ++++++++++++++--------------- biogeochem/FatesPatchMod.F90 | 14 ++--- main/FatesHydraulicsMemMod.F90 | 10 +-- main/FatesRestartInterfaceMod.F90 | 4 +- 8 files changed, 76 insertions(+), 76 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 5c867b698a..174855ea5d 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -682,7 +682,7 @@ subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr,bc_in) call InitHydrCohort(currentSite,copyc) endif - call currentCohort%copy(copyc) + call currentCohort%Copy(copyc) call copyc%InitPRTBoundaryConditions() newarea = currentCohort%c_area - cc_loss @@ -1157,7 +1157,7 @@ subroutine PromoteIntoLayer(currentSite,currentPatch,i_lyr) !call copyc%tveg_lpa%InitRMean(ema_lpa,& ! init_value=currentPatch%tveg_lpa%GetMean()) - call currentCohort%copy(copyc) !makes an identical copy... + call currentCohort%Copy(copyc) !makes an identical copy... call copyc%InitPRTBoundaryConditions() newarea = currentCohort%c_area - cc_gain !new area of existing cohort diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index d1ce6efc35..cad2a5ee26 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -202,7 +202,7 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & ! create new cohort allocate(new_cohort) -call new_cohort%create(prt, pft, nn, hite, coage, dbh, status, ctrim, carea, & +call new_cohort%Create(prt, pft, nn, hite, coage, dbh, status, ctrim, carea, & clayer, crowndamage, spread, patchptr%canopy_layer_tlai) ! Put cohort at the right place in the linked list @@ -545,7 +545,7 @@ subroutine terminate_cohort(currentSite, currentPatch, currentCohort, bc_in) shorterCohort%taller => tallerCohort endif - call currentCohort%free_memory() + call currentCohort%FreeMemory() end subroutine terminate_cohort @@ -1158,7 +1158,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) call UpdateSizeDepPlantHydProps(currentSite,currentCohort, bc_in) endif - call nextc%free_memory() + call nextc%FreeMemory() deallocate(nextc, stat=istat, errmsg=smsg) if (istat/=0) then write(fates_log(),*) 'dealloc003: fail on deallocate(nextc):'//trim(smsg) @@ -1741,7 +1741,7 @@ subroutine DamageRecovery(csite,cpatch,ccohort,newly_recovered) rcohort%prt => null() call InitPRTObject(rcohort%prt) call rcohort%InitPRTBoundaryConditions() - call ccohort%copy(rcohort) + call ccohort%Copy(rcohort) rcohort%n = nplant_recover diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 8780294ee9..753aa4ff4f 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -485,7 +485,7 @@ subroutine spawn_patches( currentSite, bc_in) if(disturbance_rate > (1.0_r8 + rsnbl_math_prec)) then write(fates_log(),*) 'patch disturbance rate > 1 ?',disturbance_rate - call currentPatch%dump() + call currentPatch%Dump() call endrun(msg=errMsg(sourcefile, __LINE__)) end if @@ -686,11 +686,11 @@ subroutine spawn_patches( currentSite, bc_in) !allocate(nc%tveg_lpa) !call nc%tveg_lpa%InitRMean(ema_lpa,init_value=new_patch%tveg_lpa%GetMean()) - call nc%zero_values() + call nc%ZeroValues() ! nc is the new cohort that goes in the disturbed patch (new_patch)... currentCohort ! is the curent cohort that stays in the donor patch (currentPatch) - call currentCohort%copy(nc) + call currentCohort%Copy(nc) !this is the case as the new patch probably doesn't have a closed canopy, and ! even if it does, that will be sorted out in canopy_structure. @@ -1109,7 +1109,7 @@ subroutine spawn_patches( currentSite, bc_in) else ! Get rid of the new temporary cohort - call nc%free_memory() + call nc%FreeMemory() deallocate(nc, stat=istat, errmsg=smsg) if (istat/=0) then write(fates_log(),*) 'dealloc005: fail on deallocate(nc):'//trim(smsg) @@ -2528,7 +2528,7 @@ subroutine fuse_2_patches(csite, dp, rp) end if ! We have no need for the dp pointer anymore, we have passed on it's legacy - call dp%free_memory() + call dp%FreeMemory() deallocate(dp, stat=istat, errmsg=smsg) if (istat/=0) then write(fates_log(),*) 'dealloc006: fail on deallocate(dp):'//trim(smsg) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 9a49d540e5..b0961d2e81 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -273,10 +273,10 @@ subroutine GenerateDamageAndLitterFluxes( csite, cpatch, bc_in ) call InitPRTObject(ndcohort%prt) call ndcohort%InitPRTBoundaryConditions() - call ndcohort%zero_values() + call ndcohort%ZeroValues() ! nc_canopy_d is the new cohort that gets damaged - call ccohort%copy(ndcohort) + call ccohort%Copy(ndcohort) ! new number densities - we just do damaged cohort here - ! undamaged at the end of the cohort loop once we know how many damaged to @@ -2027,7 +2027,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) !---------------------------------------------------------------------- allocate(temp_cohort) ! create temporary cohort - call temp_cohort%zero_values() + call temp_cohort%ZeroValues() do ft = 1,numpft diff --git a/biogeochem/FatesCohortMod.F90 b/biogeochem/FatesCohortMod.F90 index 7cacf59c83..a589c160ba 100644 --- a/biogeochem/FatesCohortMod.F90 +++ b/biogeochem/FatesCohortMod.F90 @@ -57,7 +57,7 @@ module FatesCohortMod type (fates_cohort_type), pointer :: taller => null() ! pointer to next tallest cohort type (fates_cohort_type), pointer :: shorter => null() ! pointer to next shorter cohort - !:.........................................................................: + !--------------------------------------------------------------------------- ! Multi-species, multi-organ Plant Reactive Transport (PRT) ! Contains carbon and nutrient state variables for various plant organs @@ -70,7 +70,7 @@ module FatesCohortMod ! parameters, with a tendency driven by ! nutrient storage) [kg root / kg leaf] - !:.........................................................................: + !--------------------------------------------------------------------------- ! VEGETATION STRUCTURE @@ -110,7 +110,7 @@ module FatesCohortMod integer :: coage_by_pft_class ! index that indicates the cohorts position of the join cohort age class x PFT integer :: size_class_lasttimestep ! size class of the cohort at the last time step - !:.........................................................................: + !--------------------------------------------------------------------------- ! CARBON AND NUTRIENT FLUXES @@ -188,7 +188,7 @@ module FatesCohortMod real(r8) :: seed_prod ! diagnostic seed production rate [kgC/plant/day] - !:.........................................................................: + !--------------------------------------------------------------------------- ! RESPIRATION COMPONENTS real(r8) :: rdark ! dark respiration [kgC/indiv/s] @@ -200,12 +200,12 @@ module FatesCohortMod real(r8) :: livecroot_mr ! belowground live stem maintenance respiration [kgC/indiv/s] real(r8) :: froot_mr ! live fine root maintenance respiration [kgC/indiv/s] - !:.........................................................................: + !--------------------------------------------------------------------------- ! DAMAGE real(r8) :: branch_frac ! fraction of aboveground woody biomass in branches [0-1] - !:.........................................................................: + !--------------------------------------------------------------------------- ! MORTALITY real(r8) :: dmort ! proportional mortality rate [/year] @@ -228,7 +228,7 @@ module FatesCohortMod ! (i.e. they are moved to newly-anthro-disturbed secondary ! forest patch) [fraction/logging activity] - !:.........................................................................: + !--------------------------------------------------------------------------- ! NITROGEN POOLS ! -------------------------------------------------------------------------- @@ -237,7 +237,7 @@ module FatesCohortMod ! Local values are used in that routine. ! -------------------------------------------------------------------------- - !:.........................................................................: + !--------------------------------------------------------------------------- ! GROWTH DERIVIATIVES real(r8) :: dndt ! time derivative of cohort size [n/year] @@ -245,7 +245,7 @@ module FatesCohortMod real(r8) :: ddbhdt ! time derivative of dbh [cm/year] real(r8) :: dbdeaddt ! time derivative of dead biomass [kgC/year] - !:.........................................................................: + !--------------------------------------------------------------------------- ! FIRE real(r8) :: fraction_crown_burned ! proportion of crown affected by fire [0-1] @@ -255,31 +255,31 @@ module FatesCohortMod ! (conditional on the tree being subjected to the fire) real(r8) :: fire_mort ! post-fire mortality from cambial and crown damage assuming two are independent [0-1] - !:.........................................................................: + !--------------------------------------------------------------------------- ! HYDRAULICS type(ed_cohort_hydr_type), pointer :: co_hydr ! all cohort hydraulics data, see FatesHydraulicsMemMod.F90 - !:.........................................................................: - contains - procedure :: init - procedure :: dump - procedure :: nan_values - procedure :: zero_values - procedure :: create - procedure :: copy - procedure :: free_memory + procedure :: Init + procedure :: NanValues + procedure :: ZeroValues + procedure :: Create + procedure :: Copy + procedure :: FreeMemory procedure :: CanUpperUnder procedure :: InitPRTBoundaryConditions procedure :: UpdateCohortBioPhysRates + procedure :: Dump end type fates_cohort_type contains - subroutine init(this, prt) + !=========================================================================== + + subroutine Init(this, prt) ! ! DESCRIPTION: ! Create new cohort and set default values for all variables @@ -289,8 +289,8 @@ subroutine init(this, prt) class(fates_cohort_type), intent(inout), target :: this class(prt_vartypes), intent(inout), pointer :: prt ! allocated PARTEH object - call this%nan_values() ! make everything in the cohort not-a-number - call this%zero_values() ! zero things that need to be zeroed + call this%NanValues() ! make everything in the cohort not-a-number + call this%ZeroValues() ! zero things that need to be zeroed ! point to the PARTEH object this%prt => prt @@ -307,11 +307,11 @@ subroutine init(this, prt) ! growth, disturbance and mortality. this%isnew = .true. - end subroutine init + end subroutine Init - !:.........................................................................: + !=========================================================================== - subroutine nan_values(this) + subroutine NanValues(this) ! ! DESCRIPTION: ! make all the cohort variables NaN or unset so they aren't used before defined @@ -433,11 +433,11 @@ subroutine nan_values(this) this%crownfire_mort = nan this%fire_mort = nan - end subroutine nan_values + end subroutine NanValues - !:.........................................................................: + !=========================================================================== - subroutine zero_values(this) + subroutine ZeroValues(this) ! ! DESCRIPTION: ! Zero variables that need to be accounted for if this cohort is altered @@ -513,11 +513,11 @@ subroutine zero_values(this) this%crownfire_mort = 0._r8 this%fire_mort = 0._r8 - end subroutine zero_values + end subroutine ZeroValues - !:.........................................................................: + !=========================================================================== - subroutine create(this, prt, pft, nn, hite, coage, dbh, status, & + subroutine Create(this, prt, pft, nn, hite, coage, dbh, status, & ctrim, carea, clayer, crowndamage, spread, can_tlai) ! ! DESCRIPTION: @@ -544,7 +544,7 @@ subroutine create(this, prt, pft, nn, hite, coage, dbh, status, & real(r8) :: leaf_c ! total leaf carbon [kgC] ! initialize cohort - call this%init(prt) + call this%Init(prt) ! set values this%pft = pft @@ -563,7 +563,7 @@ subroutine create(this, prt, pft, nn, hite, coage, dbh, status, & ! In these cases, testing if things like biomass are reasonable is premature ! However, in this part of the code, we will pass in nominal values for size, number and type if (this%dbh <= 0._r8 .or. this%n == 0._r8 .or. this%pft == 0) then - write(fates_log(),*) 'FATES: something is zero in cohort%create', & + write(fates_log(),*) 'FATES: something is zero in cohort%Create', & this%dbh, this%n, this%pft call endrun(msg=errMsg(sourcefile, __LINE__)) endif @@ -619,11 +619,11 @@ subroutine create(this, prt, pft, nn, hite, coage, dbh, status, & this%treelai,this%vcmax25top, 2) end if - end subroutine create + end subroutine Create - !:.........................................................................: + !=========================================================================== - subroutine copy(this, copy_cohort) + subroutine Copy(this, copy_cohort) ! ! DESCRIPTION: ! copies all the variables in one cohort into a new cohort @@ -753,11 +753,11 @@ subroutine copy(this, copy_cohort) call copy_cohort%co_hydr%CopyCohortHydraulics(this%co_hydr) endif - end subroutine copy + end subroutine Copy - !:.........................................................................: + !=========================================================================== - subroutine free_memory(this) + subroutine FreeMemory(this) ! ! DESCRIPTION: ! deallocates all dynamic memory and objects within the cohort structure @@ -787,9 +787,9 @@ subroutine free_memory(this) call endrun(msg=errMsg(sourcefile, __LINE__)) endif - end subroutine free_memory + end subroutine FreeMemory - !:.........................................................................: + !=========================================================================== subroutine InitPRTBoundaryConditions(this) ! @@ -865,7 +865,7 @@ subroutine InitPRTBoundaryConditions(this) end subroutine InitPRTBoundaryConditions - !:.........................................................................: + !=========================================================================== subroutine UpdateCohortBioPhysRates(this) ! @@ -935,7 +935,7 @@ subroutine UpdateCohortBioPhysRates(this) end subroutine UpdateCohortBioPhysRates - !:.........................................................................: + !=========================================================================== function CanUpperUnder(this) result(can_position) ! @@ -960,9 +960,9 @@ function CanUpperUnder(this) result(can_position) end function CanUpperUnder - !:.........................................................................: + !=========================================================================== - subroutine dump(this) + subroutine Dump(this) ! ! DESCRIPTION: ! Print out attributes of a cohort @@ -1042,12 +1042,12 @@ subroutine dump(this) write(fates_log(),*) 'cthis%size_class = ', this%size_class write(fates_log(),*) 'cthis%size_by_pft_class = ', this%size_by_pft_class - if (associated(this%co_hydr)) call this%co_hydr%dump() + if (associated(this%co_hydr)) call this%co_hydr%Dump() write(fates_log(),*) '----------------------------------------' - end subroutine dump + end subroutine Dump - !:.........................................................................: + !=========================================================================== end module FatesCohortMod \ No newline at end of file diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 index ddeee61f65..9ec2e38969 100644 --- a/biogeochem/FatesPatchMod.F90 +++ b/biogeochem/FatesPatchMod.F90 @@ -45,7 +45,7 @@ module FatesPatchMod ! each patch ID corresponds to a pft number since each ! patch has only one pft. Bareground patches are given ! a zero integer as a label. If nocomp is not active this - ! is set to unset. This is set in patch%create as an argument + ! is set to unset. This is set in patch%Create as an argument ! to that procedure. !--------------------------------------------------------------------------- @@ -578,7 +578,7 @@ subroutine FreeMemory(this) ccohort => this%shortest do while(associated(ccohort)) ncohort => ccohort%taller - call ccohort%free_memory() + call ccohort%FreeMemory() deallocate(ccohort, stat=istat, errmsg=smsg) if (istat /= 0) then write(fates_log(),*) 'dealloc007: fail on deallocate(cchort):'//trim(smsg) @@ -708,8 +708,8 @@ subroutine CheckVars(this, var_aliases, return_code) do while(associated(currentCohort)) call check_var_real(currentCohort%n, 'cohort%n', return_code) if (.not.(return_code .eq. 0)) then - call this%dump() - call currentCohort%dump() + call this%Dump() + call currentCohort%Dump() return end if currentCohort => currentCohort%taller @@ -721,8 +721,8 @@ subroutine CheckVars(this, var_aliases, return_code) do while(associated(currentCohort)) call check_var_real(currentCohort%dbh, 'cohort%dbh', return_code) if (.not. (return_code .eq. 0)) then - call this%dump() - call currentCohort%dump() + call this%Dump() + call currentCohort%Dump() return end if currentCohort => currentCohort%taller @@ -732,7 +732,7 @@ subroutine CheckVars(this, var_aliases, return_code) if (check_hlm_list(trim(var_aliases), 'pa_area')) then call check_var_real(this%area, 'patch%area', return_code) if (.not. (return_code .eq. 0)) then - call this%dump() + call this%Dump() return end if end if diff --git a/main/FatesHydraulicsMemMod.F90 b/main/FatesHydraulicsMemMod.F90 index 856599f2e5..61e97173c7 100644 --- a/main/FatesHydraulicsMemMod.F90 +++ b/main/FatesHydraulicsMemMod.F90 @@ -316,7 +316,7 @@ module FatesHydraulicsMemMod procedure :: AllocateHydrCohortArrays procedure :: DeallocateHydrCohortArrays procedure :: CopyCohortHydraulics - procedure :: dump + procedure :: Dump end type ed_cohort_hydr_type @@ -425,9 +425,9 @@ subroutine DeallocateHydrCohortArrays(this) return end subroutine DeallocateHydrCohortArrays - ! =================================================================================== + ! ========================================================================== - subroutine dump(this) + subroutine Dump(this) class(ed_cohort_hydr_type), intent(in) :: this @@ -440,9 +440,9 @@ subroutine dump(this) return - end subroutine dump + end subroutine Dump - !:..........................................................................: + ! ========================================================================== subroutine InitHydrSite(this,numpft,numlevsclass,hydr_solver_type,nlevsoil) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index f76fdd2680..4f72dd69d0 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -2622,8 +2622,8 @@ subroutine create_patchcohort_structure(this, nc, nsites, sites, bc_in, bc_out) do fto = 1, rio_ncohort_pa( io_idx_co_1st ) allocate(new_cohort) - call new_cohort%nan_values() - call new_cohort%zero_values() + call new_cohort%NanValues() + call new_cohort%ZeroValues() ! If this is the first in the list, it is tallest if (.not.associated(newp%tallest)) then From 92a57d0a890ada1175dabb02a2f8202ce5cf3213 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 9 May 2023 13:45:06 -0700 Subject: [PATCH 686/852] Remove unnecessary xarray import call --- tools/luh2.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/luh2.py b/tools/luh2.py index 0a5ea6229e..22e8d8bab7 100644 --- a/tools/luh2.py +++ b/tools/luh2.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 import argparse, os -import xarray as xr from luh2mod import PrepDataSet, ImportData, SetMaskLUH2, SetMaskSurfData from luh2mod import RegridConservative From 009e4574b04002efedb613792ef88275fcca0052 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 9 May 2023 15:31:32 -0700 Subject: [PATCH 687/852] remove old chil local variable and commented out code --- biogeophys/EDSurfaceAlbedoMod.F90 | 5 ----- 1 file changed, 5 deletions(-) diff --git a/biogeophys/EDSurfaceAlbedoMod.F90 b/biogeophys/EDSurfaceAlbedoMod.F90 index 2f1696a1db..18d29c0109 100644 --- a/biogeophys/EDSurfaceAlbedoMod.F90 +++ b/biogeophys/EDSurfaceAlbedoMod.F90 @@ -265,7 +265,6 @@ subroutine PatchNormanRadiation (currentPatch, & integer :: fp,iv,s ! array indices integer :: ib ! waveband number real(r8) :: cosz ! 0.001 <= coszen <= 1.000 - real(r8) :: chil real(r8) :: gdir @@ -363,10 +362,6 @@ subroutine PatchNormanRadiation (currentPatch, & cosz = max(0.001_r8, currentPatch%solar_zenith_angle ) !copied from previous radiation code... do ft = 1,numpft sb = (90._r8 - (acos(cosz)*180._r8/pi_const)) * (pi_const / 180._r8) - ! chil being close to zero shouldn't affect things - !if ( abs(chil) <= 0.01_r8) then - ! chil = 0.01_r8 - !end if phi1b(ft) = 0.5_r8 - 0.633_r8*xl(ft) - 0.330_r8*xl(ft)*xl(ft) phi2b(ft) = 0.877_r8 * (1._r8 - 2._r8*phi1b(ft)) !0 = horiz leaves, 1 - vert leaves. gdir = phi1b(ft) + phi2b(ft) * sin(sb) From a265ef3c9663e51999d3e63da9979d7b6fd6b1d7 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Wed, 10 May 2023 12:00:47 -0600 Subject: [PATCH 688/852] update for style --- biogeochem/FatesCohortMod.F90 | 328 +++++++++++++++++----------------- 1 file changed, 164 insertions(+), 164 deletions(-) diff --git a/biogeochem/FatesCohortMod.F90 b/biogeochem/FatesCohortMod.F90 index a589c160ba..01d652464a 100644 --- a/biogeochem/FatesCohortMod.F90 +++ b/biogeochem/FatesCohortMod.F90 @@ -623,134 +623,134 @@ end subroutine Create !=========================================================================== - subroutine Copy(this, copy_cohort) + subroutine Copy(this, copyCohort) ! ! DESCRIPTION: ! copies all the variables in one cohort into a new cohort ! ! ARGUMENTS - class(fates_cohort_type), intent(in) :: this ! old cohort - class(fates_cohort_type), intent(inout) :: copy_cohort ! new cohort + class(fates_cohort_type), intent(in) :: this ! old cohort + class(fates_cohort_type), intent(inout) :: copyCohort ! new cohort - copy_cohort%indexnumber = fates_unset_int + copyCohort%indexnumber = fates_unset_int ! POINTERS - copy_cohort%taller => NULL() - copy_cohort%shorter => NULL() + copyCohort%taller => NULL() + copyCohort%shorter => NULL() ! PRT - call copy_cohort%prt%CopyPRTVartypes(this%prt) - copy_cohort%l2fr = this%l2fr + call copyCohort%prt%CopyPRTVartypes(this%prt) + copyCohort%l2fr = this%l2fr ! VEGETATION STRUCTURE - copy_cohort%pft = this%pft - copy_cohort%n = this%n - copy_cohort%dbh = this%dbh - copy_cohort%coage = this%coage - copy_cohort%hite = this%hite - copy_cohort%canopy_layer = this%canopy_layer - copy_cohort%canopy_layer_yesterday = this%canopy_layer_yesterday - copy_cohort%crowndamage = this%crowndamage - copy_cohort%g_sb_laweight = this%g_sb_laweight - copy_cohort%canopy_trim = this%canopy_trim - copy_cohort%leaf_cost = this%leaf_cost - copy_cohort%excl_weight = this%excl_weight - copy_cohort%prom_weight = this%prom_weight - copy_cohort%nv = this%nv - copy_cohort%status_coh = this%status_coh - copy_cohort%c_area = this%c_area - copy_cohort%treelai = this%treelai - copy_cohort%treesai = this%treesai - copy_cohort%isnew = this%isnew - copy_cohort%size_class = this%size_class - copy_cohort%coage_class = this%coage_class - copy_cohort%size_by_pft_class = this%size_by_pft_class - copy_cohort%coage_by_pft_class = this%coage_by_pft_class - copy_cohort%size_class_lasttimestep = this%size_class_lasttimestep + copyCohort%pft = this%pft + copyCohort%n = this%n + copyCohort%dbh = this%dbh + copyCohort%coage = this%coage + copyCohort%hite = this%hite + copyCohort%canopy_layer = this%canopy_layer + copyCohort%canopy_layer_yesterday = this%canopy_layer_yesterday + copyCohort%crowndamage = this%crowndamage + copyCohort%g_sb_laweight = this%g_sb_laweight + copyCohort%canopy_trim = this%canopy_trim + copyCohort%leaf_cost = this%leaf_cost + copyCohort%excl_weight = this%excl_weight + copyCohort%prom_weight = this%prom_weight + copyCohort%nv = this%nv + copyCohort%status_coh = this%status_coh + copyCohort%c_area = this%c_area + copyCohort%treelai = this%treelai + copyCohort%treesai = this%treesai + copyCohort%isnew = this%isnew + copyCohort%size_class = this%size_class + copyCohort%coage_class = this%coage_class + copyCohort%size_by_pft_class = this%size_by_pft_class + copyCohort%coage_by_pft_class = this%coage_by_pft_class + copyCohort%size_class_lasttimestep = this%size_class_lasttimestep ! CARBON AND NUTRIENT FLUXES - copy_cohort%gpp_tstep = this%gpp_tstep - copy_cohort%gpp_acc = this%gpp_acc - copy_cohort%gpp_acc_hold = this%gpp_acc_hold - copy_cohort%npp_tstep = this%npp_tstep - copy_cohort%npp_acc = this%npp_acc - copy_cohort%npp_acc_hold = this%npp_acc_hold - copy_cohort%resp_tstep = this%resp_tstep - copy_cohort%resp_acc = this%resp_acc - copy_cohort%resp_acc_hold = this%resp_acc_hold - copy_cohort%c13disc_clm = this%c13disc_clm - copy_cohort%c13disc_acc = this%c13disc_acc - copy_cohort%vcmax25top = this%vcmax25top - copy_cohort%jmax25top = this%jmax25top - copy_cohort%tpu25top = this%tpu25top - copy_cohort%kp25top = this%kp25top - copy_cohort%ts_net_uptake = this%ts_net_uptake - copy_cohort%year_net_uptake = this%year_net_uptake - copy_cohort%cnp_limiter = this%cnp_limiter + copyCohort%gpp_tstep = this%gpp_tstep + copyCohort%gpp_acc = this%gpp_acc + copyCohort%gpp_acc_hold = this%gpp_acc_hold + copyCohort%npp_tstep = this%npp_tstep + copyCohort%npp_acc = this%npp_acc + copyCohort%npp_acc_hold = this%npp_acc_hold + copyCohort%resp_tstep = this%resp_tstep + copyCohort%resp_acc = this%resp_acc + copyCohort%resp_acc_hold = this%resp_acc_hold + copyCohort%c13disc_clm = this%c13disc_clm + copyCohort%c13disc_acc = this%c13disc_acc + copyCohort%vcmax25top = this%vcmax25top + copyCohort%jmax25top = this%jmax25top + copyCohort%tpu25top = this%tpu25top + copyCohort%kp25top = this%kp25top + copyCohort%ts_net_uptake = this%ts_net_uptake + copyCohort%year_net_uptake = this%year_net_uptake + copyCohort%cnp_limiter = this%cnp_limiter if (hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) then - copy_cohort%cx_int = this%cx_int - copy_cohort%ema_dcxdt = this%ema_dcxdt - copy_cohort%cx0 = this%cx0 + copyCohort%cx_int = this%cx_int + copyCohort%ema_dcxdt = this%ema_dcxdt + copyCohort%cx0 = this%cx0 end if - copy_cohort%nc_repro = this%nc_repro - copy_cohort%daily_nh4_uptake = this%daily_nh4_uptake - copy_cohort%daily_no3_uptake = this%daily_no3_uptake - copy_cohort%sym_nfix_daily = this%sym_nfix_daily - copy_cohort%sym_nfix_tstep = this%sym_nfix_tstep - copy_cohort%daily_n_gain = this%daily_n_gain - copy_cohort%daily_p_gain = this%daily_p_gain - copy_cohort%daily_c_efflux = this%daily_c_efflux - copy_cohort%daily_n_efflux = this%daily_n_efflux - copy_cohort%daily_p_efflux = this%daily_p_efflux - copy_cohort%daily_n_demand = this%daily_n_demand - copy_cohort%daily_p_demand = this%daily_p_demand - copy_cohort%seed_prod = this%seed_prod + copyCohort%nc_repro = this%nc_repro + copyCohort%daily_nh4_uptake = this%daily_nh4_uptake + copyCohort%daily_no3_uptake = this%daily_no3_uptake + copyCohort%sym_nfix_daily = this%sym_nfix_daily + copyCohort%sym_nfix_tstep = this%sym_nfix_tstep + copyCohort%daily_n_gain = this%daily_n_gain + copyCohort%daily_p_gain = this%daily_p_gain + copyCohort%daily_c_efflux = this%daily_c_efflux + copyCohort%daily_n_efflux = this%daily_n_efflux + copyCohort%daily_p_efflux = this%daily_p_efflux + copyCohort%daily_n_demand = this%daily_n_demand + copyCohort%daily_p_demand = this%daily_p_demand + copyCohort%seed_prod = this%seed_prod ! RESPIRATION COMPONENTS - copy_cohort%rdark = this%rdark - copy_cohort%resp_g_tstep = this%resp_g_tstep - copy_cohort%resp_m = this%resp_m - copy_cohort%resp_m_unreduced = this%resp_m_unreduced - copy_cohort%resp_excess = this%resp_excess - copy_cohort%livestem_mr = this%livestem_mr - copy_cohort%livecroot_mr = this%livecroot_mr - copy_cohort%froot_mr = this%froot_mr + copyCohort%rdark = this%rdark + copyCohort%resp_g_tstep = this%resp_g_tstep + copyCohort%resp_m = this%resp_m + copyCohort%resp_m_unreduced = this%resp_m_unreduced + copyCohort%resp_excess = this%resp_excess + copyCohort%livestem_mr = this%livestem_mr + copyCohort%livecroot_mr = this%livecroot_mr + copyCohort%froot_mr = this%froot_mr ! DAMAGE - copy_cohort%branch_frac = this%branch_frac + copyCohort%branch_frac = this%branch_frac ! MORTALITY - copy_cohort%dmort = this%dmort - copy_cohort%bmort = this%bmort - copy_cohort%cmort = this%cmort - copy_cohort%hmort = this%hmort - copy_cohort%frmort = this%frmort - copy_cohort%smort = this%smort - copy_cohort%asmort = this%asmort - copy_cohort%dgmort = this%dgmort - copy_cohort%lmort_direct = this%lmort_direct - copy_cohort%lmort_collateral = this%lmort_collateral - copy_cohort%lmort_infra = this%lmort_infra - copy_cohort%l_degrad = this%l_degrad + copyCohort%dmort = this%dmort + copyCohort%bmort = this%bmort + copyCohort%cmort = this%cmort + copyCohort%hmort = this%hmort + copyCohort%frmort = this%frmort + copyCohort%smort = this%smort + copyCohort%asmort = this%asmort + copyCohort%dgmort = this%dgmort + copyCohort%lmort_direct = this%lmort_direct + copyCohort%lmort_collateral = this%lmort_collateral + copyCohort%lmort_infra = this%lmort_infra + copyCohort%l_degrad = this%l_degrad ! GROWTH DERIVATIVES - copy_cohort%dndt = this%dndt - copy_cohort%dhdt = this%dhdt - copy_cohort%ddbhdt = this%ddbhdt - copy_cohort%dbdeaddt = this%dbdeaddt + copyCohort%dndt = this%dndt + copyCohort%dhdt = this%dhdt + copyCohort%ddbhdt = this%ddbhdt + copyCohort%dbdeaddt = this%dbdeaddt ! FIRE - copy_cohort%fraction_crown_burned = this%fraction_crown_burned - copy_cohort%cambial_mort = this%cambial_mort - copy_cohort%crownfire_mort = this%crownfire_mort - copy_cohort%fire_mort = this%fire_mort + copyCohort%fraction_crown_burned = this%fraction_crown_burned + copyCohort%cambial_mort = this%cambial_mort + copyCohort%crownfire_mort = this%crownfire_mort + copyCohort%fire_mort = this%fire_mort ! HYDRAULICS if (hlm_use_planthydro .eq. itrue) then - call copy_cohort%co_hydr%CopyCohortHydraulics(this%co_hydr) + call copyCohort%co_hydr%CopyCohortHydraulics(this%co_hydr) endif end subroutine Copy @@ -798,7 +798,7 @@ subroutine InitPRTBoundaryConditions(this) ! allocation hypotheses. Each of these calls to "RegsterBC" are simply ! setting pointers. ! For instance, if the hypothesis wants to know what - ! the DBH of the plant is, then we pass in the dbh as an argument (copy_cohort%dbh), + ! the DBH of the plant is, then we pass in the dbh as an argument (copyCohort%dbh), ! and also tell it which boundary condition we are talking about (which is ! defined by an integer index (ac_bc_inout_id_dbh) ! @@ -974,73 +974,73 @@ subroutine Dump(this) write(fates_log(),*) '----------------------------------------' write(fates_log(),*) ' Dumping Cohort Information ' write(fates_log(),*) '----------------------------------------' - write(fates_log(),*) 'cthis%pft = ', this%pft - write(fates_log(),*) 'cthis%n = ', this%n - write(fates_log(),*) 'cthis%dbh = ', this%dbh - write(fates_log(),*) 'cthis%hite = ', this%hite - write(fates_log(),*) 'cthis%crowndamage = ', this%crowndamage - write(fates_log(),*) 'cthis%coage = ', this%coage - write(fates_log(),*) 'cthis%l2fr = ', this%l2fr - write(fates_log(),*) 'leaf carbon = ', this%prt%GetState(leaf_organ,carbon12_element) - write(fates_log(),*) 'fineroot carbon = ', this%prt%GetState(fnrt_organ,carbon12_element) - write(fates_log(),*) 'sapwood carbon = ', this%prt%GetState(sapw_organ,carbon12_element) - write(fates_log(),*) 'structural (dead) carbon = ', this%prt%GetState(struct_organ,carbon12_element) - write(fates_log(),*) 'storage carbon = ', this%prt%GetState(store_organ,carbon12_element) - write(fates_log(),*) 'reproductive carbon = ', this%prt%GetState(repro_organ,carbon12_element) - write(fates_log(),*) 'cthis%g_sb_laweight = ', this%g_sb_laweight - write(fates_log(),*) 'cthis%leaf_cost = ', this%leaf_cost - write(fates_log(),*) 'cthis%canopy_layer = ', this%canopy_layer - write(fates_log(),*) 'cthis%canopy_layer_yesterday = ', this%canopy_layer_yesterday - write(fates_log(),*) 'cthis%nv = ', this%nv - write(fates_log(),*) 'cthis%status_coh = ', this%status_coh - write(fates_log(),*) 'cthis%canopy_trim = ', this%canopy_trim - write(fates_log(),*) 'cthis%excl_weight = ', this%excl_weight - write(fates_log(),*) 'cthis%prom_weight = ', this%prom_weight - write(fates_log(),*) 'cthis%size_class = ', this%size_class - write(fates_log(),*) 'cthis%size_by_pft_class = ', this%size_by_pft_class - write(fates_log(),*) 'cthis%coage_class = ', this%coage_class - write(fates_log(),*) 'cthis%coage_by_pft_class = ', this%coage_by_pft_class - write(fates_log(),*) 'cthis%gpp_acc_hold = ', this%gpp_acc_hold - write(fates_log(),*) 'cthis%gpp_acc = ', this%gpp_acc - write(fates_log(),*) 'cthis%gpp_tstep = ', this%gpp_tstep - write(fates_log(),*) 'cthis%npp_acc_hold = ', this%npp_acc_hold - write(fates_log(),*) 'cthis%npp_tstep = ', this%npp_tstep - write(fates_log(),*) 'cthis%npp_acc = ', this%npp_acc - write(fates_log(),*) 'cthis%resp_tstep = ', this%resp_tstep - write(fates_log(),*) 'cthis%resp_acc = ', this%resp_acc - write(fates_log(),*) 'cthis%resp_acc_hold = ', this%resp_acc_hold - write(fates_log(),*) 'cthis%rdark = ', this%rdark - write(fates_log(),*) 'cthis%resp_m = ', this%resp_m - write(fates_log(),*) 'cthis%resp_g_tstep = ', this%resp_g_tstep - write(fates_log(),*) 'cthis%livestem_mr = ', this%livestem_mr - write(fates_log(),*) 'cthis%livecroot_mr = ', this%livecroot_mr - write(fates_log(),*) 'cthis%froot_mr = ', this%froot_mr - write(fates_log(),*) 'cthis%dgmort = ', this%dgmort - write(fates_log(),*) 'cthis%treelai = ', this%treelai - write(fates_log(),*) 'cthis%treesai = ', this%treesai - write(fates_log(),*) 'cthis%c_area = ', this%c_area - write(fates_log(),*) 'cthis%cmort = ', this%cmort - write(fates_log(),*) 'cthis%bmort = ', this%bmort - write(fates_log(),*) 'cthis%smort = ', this%smort - write(fates_log(),*) 'cthis%asmort = ', this%asmort - write(fates_log(),*) 'cthis%dgmort = ', this%dgmort - write(fates_log(),*) 'cthis%hmort = ', this%hmort - write(fates_log(),*) 'cthis%frmort = ', this%frmort - write(fates_log(),*) 'cthis%asmort = ', this%asmort - write(fates_log(),*) 'cthis%lmort_direct = ', this%lmort_direct - write(fates_log(),*) 'cthis%lmort_collateral = ', this%lmort_collateral - write(fates_log(),*) 'cthis%lmort_infra = ', this%lmort_infra - write(fates_log(),*) 'cthis%isnew = ', this%isnew - write(fates_log(),*) 'cthis%dndt = ', this%dndt - write(fates_log(),*) 'cthis%dhdt = ', this%dhdt - write(fates_log(),*) 'cthis%ddbhdt = ', this%ddbhdt - write(fates_log(),*) 'cthis%dbdeaddt = ', this%dbdeaddt - write(fates_log(),*) 'cthis%fraction_crown_burned = ', this%fraction_crown_burned - write(fates_log(),*) 'cthis%fire_mort = ', this%fire_mort - write(fates_log(),*) 'cthis%crownfire_mort = ', this%crownfire_mort - write(fates_log(),*) 'cthis%cambial_mort = ', this%cambial_mort - write(fates_log(),*) 'cthis%size_class = ', this%size_class - write(fates_log(),*) 'cthis%size_by_pft_class = ', this%size_by_pft_class + write(fates_log(),*) 'cohort%pft = ', this%pft + write(fates_log(),*) 'cohort%n = ', this%n + write(fates_log(),*) 'cohort%dbh = ', this%dbh + write(fates_log(),*) 'cohort%hite = ', this%hite + write(fates_log(),*) 'cohort%crowndamage = ', this%crowndamage + write(fates_log(),*) 'cohort%coage = ', this%coage + write(fates_log(),*) 'cohort%l2fr = ', this%l2fr + write(fates_log(),*) 'leaf carbon = ', this%prt%GetState(leaf_organ,carbon12_element) + write(fates_log(),*) 'fineroot carbon = ', this%prt%GetState(fnrt_organ,carbon12_element) + write(fates_log(),*) 'sapwood carbon = ', this%prt%GetState(sapw_organ,carbon12_element) + write(fates_log(),*) 'structural (dead) carbon = ', this%prt%GetState(struct_organ,carbon12_element) + write(fates_log(),*) 'storage carbon = ', this%prt%GetState(store_organ,carbon12_element) + write(fates_log(),*) 'reproductive carbon = ', this%prt%GetState(repro_organ,carbon12_element) + write(fates_log(),*) 'cohort%g_sb_laweight = ', this%g_sb_laweight + write(fates_log(),*) 'cohort%leaf_cost = ', this%leaf_cost + write(fates_log(),*) 'cohort%canopy_layer = ', this%canopy_layer + write(fates_log(),*) 'cohort%canopy_layer_yesterday = ', this%canopy_layer_yesterday + write(fates_log(),*) 'cohort%nv = ', this%nv + write(fates_log(),*) 'cohort%status_coh = ', this%status_coh + write(fates_log(),*) 'cohort%canopy_trim = ', this%canopy_trim + write(fates_log(),*) 'cohort%excl_weight = ', this%excl_weight + write(fates_log(),*) 'cohort%prom_weight = ', this%prom_weight + write(fates_log(),*) 'cohort%size_class = ', this%size_class + write(fates_log(),*) 'cohort%size_by_pft_class = ', this%size_by_pft_class + write(fates_log(),*) 'cohort%coage_class = ', this%coage_class + write(fates_log(),*) 'cohort%coage_by_pft_class = ', this%coage_by_pft_class + write(fates_log(),*) 'cohort%gpp_acc_hold = ', this%gpp_acc_hold + write(fates_log(),*) 'cohort%gpp_acc = ', this%gpp_acc + write(fates_log(),*) 'cohort%gpp_tstep = ', this%gpp_tstep + write(fates_log(),*) 'cohort%npp_acc_hold = ', this%npp_acc_hold + write(fates_log(),*) 'cohort%npp_tstep = ', this%npp_tstep + write(fates_log(),*) 'cohort%npp_acc = ', this%npp_acc + write(fates_log(),*) 'cohort%resp_tstep = ', this%resp_tstep + write(fates_log(),*) 'cohort%resp_acc = ', this%resp_acc + write(fates_log(),*) 'cohort%resp_acc_hold = ', this%resp_acc_hold + write(fates_log(),*) 'cohort%rdark = ', this%rdark + write(fates_log(),*) 'cohort%resp_m = ', this%resp_m + write(fates_log(),*) 'cohort%resp_g_tstep = ', this%resp_g_tstep + write(fates_log(),*) 'cohort%livestem_mr = ', this%livestem_mr + write(fates_log(),*) 'cohort%livecroot_mr = ', this%livecroot_mr + write(fates_log(),*) 'cohort%froot_mr = ', this%froot_mr + write(fates_log(),*) 'cohort%dgmort = ', this%dgmort + write(fates_log(),*) 'cohort%treelai = ', this%treelai + write(fates_log(),*) 'cohort%treesai = ', this%treesai + write(fates_log(),*) 'cohort%c_area = ', this%c_area + write(fates_log(),*) 'cohort%cmort = ', this%cmort + write(fates_log(),*) 'cohort%bmort = ', this%bmort + write(fates_log(),*) 'cohort%smort = ', this%smort + write(fates_log(),*) 'cohort%asmort = ', this%asmort + write(fates_log(),*) 'cohort%dgmort = ', this%dgmort + write(fates_log(),*) 'cohort%hmort = ', this%hmort + write(fates_log(),*) 'cohort%frmort = ', this%frmort + write(fates_log(),*) 'cohort%asmort = ', this%asmort + write(fates_log(),*) 'cohort%lmort_direct = ', this%lmort_direct + write(fates_log(),*) 'cohort%lmort_collateral = ', this%lmort_collateral + write(fates_log(),*) 'cohort%lmort_infra = ', this%lmort_infra + write(fates_log(),*) 'cohort%isnew = ', this%isnew + write(fates_log(),*) 'cohort%dndt = ', this%dndt + write(fates_log(),*) 'cohort%dhdt = ', this%dhdt + write(fates_log(),*) 'cohort%ddbhdt = ', this%ddbhdt + write(fates_log(),*) 'cohort%dbdeaddt = ', this%dbdeaddt + write(fates_log(),*) 'cohort%fraction_crown_burned = ', this%fraction_crown_burned + write(fates_log(),*) 'cohort%fire_mort = ', this%fire_mort + write(fates_log(),*) 'cohort%crownfire_mort = ', this%crownfire_mort + write(fates_log(),*) 'cohort%cambial_mort = ', this%cambial_mort + write(fates_log(),*) 'cohort%size_class = ', this%size_class + write(fates_log(),*) 'cohort%size_by_pft_class = ', this%size_by_pft_class if (associated(this%co_hydr)) call this%co_hydr%Dump() From 548467d66040db0a36fd053419d62d8dc2fb79d8 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Wed, 10 May 2023 14:34:27 -0600 Subject: [PATCH 689/852] add target --- biogeochem/FatesCohortMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/FatesCohortMod.F90 b/biogeochem/FatesCohortMod.F90 index 01d652464a..46775fb6a9 100644 --- a/biogeochem/FatesCohortMod.F90 +++ b/biogeochem/FatesCohortMod.F90 @@ -813,7 +813,7 @@ subroutine InitPRTBoundaryConditions(this) ! value boundary condition. ! ARGUMENTS: - class(fates_cohort_type), intent(inout) :: this + class(fates_cohort_type), intent(inout), target :: this select case(hlm_parteh_mode) case (prt_carbon_allom_hyp) From c7662c18396b4947e75f821784b453ed3f5e96b9 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 10 May 2023 14:31:31 -0700 Subject: [PATCH 690/852] Add clarifying language per reviewer suggestions --- biogeochem/EDPhysiologyMod.F90 | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 1ae6fe9abf..d2d1de19e5 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1770,7 +1770,8 @@ subroutine SeedUpdate( currentSite, bc_in, bc_out) integer :: pft real(r8) :: store_m_to_repro ! mass sent from storage to reproduction upon death [kg/plant] real(r8) :: site_seed_rain(numpft) ! This is the sum of seed-rain for the site [kg/site/day] - real(r8) :: site_disp_frac(numpft) ! Fraction of seeds to disperse out to other sites + real(r8) :: site_disp_frac(numpft) ! Fraction of seeds from prodeced in current grid cell to + ! disperse out to other gridcells real(r8) :: seed_in_external ! Mass of externally generated seeds [kg/m2/day] real(r8) :: seed_stoich ! Mass ratio of nutrient per C12 in seeds [kg/kg] real(r8) :: seed_prod ! Seed produced in this dynamics step [kg/day] @@ -1854,12 +1855,14 @@ subroutine SeedUpdate( currentSite, bc_in, bc_out) do pft = 1,numpft if(currentSite%use_this_pft(pft).eq.itrue)then - ! Seed input from local sources (within site) + + ! Seed input from local sources (within site). Note that a fraction of the + ! internal seed rain is sent out to neighboring gridcells. litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)*(1-site_disp_frac(pft))/area ![kg/m2/day] + ! If there is forced external seed rain, we calculate the input mass flux ! from the different elements, using the mean stoichiometry of new ! recruits for the current patch and lowest canopy position - select case(element_id) case(carbon12_element) seed_stoich = 1._r8 @@ -1971,7 +1974,7 @@ subroutine SeedGermination( litt, cold_stat, drought_stat ) !set the germination only under the growing season...c.xu if ((prt_params%season_decid(pft) == itrue ) .and. & - (any(cold_stat == [phen_cstat_nevercold,phen_cstat_iscold]))) then + (any(cold_stat == [phen_cstat_nevercold,phen_cstat_iscold]))) then ! no germination for all PFTs when cold litt%seed_germ_in(pft) = 0.0_r8 endif From 0c2d335e653a893d97b701faf05c7f1158ccc289 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 10 May 2023 16:09:03 -0700 Subject: [PATCH 691/852] Add parameter patch file --- .../api25.4.0_041023_fates_params_default.cdl | 1559 +++++++++++++++++ .../archive/api25.4.0_041023_pr958.xml | 52 + 2 files changed, 1611 insertions(+) create mode 100644 parameter_files/archive/api25.4.0_041023_fates_params_default.cdl create mode 100644 parameter_files/archive/api25.4.0_041023_pr958.xml diff --git a/parameter_files/archive/api25.4.0_041023_fates_params_default.cdl b/parameter_files/archive/api25.4.0_041023_fates_params_default.cdl new file mode 100644 index 0000000000..d461cb6fbb --- /dev/null +++ b/parameter_files/archive/api25.4.0_041023_fates_params_default.cdl @@ -0,0 +1,1559 @@ +netcdf fates_params_default { +dimensions: + fates_NCWD = 4 ; + fates_history_age_bins = 7 ; + fates_history_coage_bins = 2 ; + fates_history_damage_bins = 2 ; + fates_history_height_bins = 6 ; + fates_history_size_bins = 13 ; + fates_hlm_pftno = 14 ; + fates_hydr_organs = 4 ; + fates_leafage_class = 1 ; + fates_litterclass = 6 ; + fates_pft = 12 ; + fates_plant_organs = 4 ; + fates_string_length = 60 ; +variables: + double fates_history_ageclass_bin_edges(fates_history_age_bins) ; + fates_history_ageclass_bin_edges:units = "yr" ; + fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; + double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; + fates_history_coageclass_bin_edges:units = "years" ; + fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; + double fates_history_height_bin_edges(fates_history_height_bins) ; + fates_history_height_bin_edges:units = "m" ; + fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; + double fates_history_damage_bin_edges(fates_history_damage_bins) ; + fates_history_damage_bin_edges:units = "% crown loss" ; + fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; + double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; + fates_history_sizeclass_bin_edges:units = "cm" ; + fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; + double fates_alloc_organ_id(fates_plant_organs) ; + fates_alloc_organ_id:units = "unitless" ; + fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; + double fates_hydro_htftype_node(fates_hydr_organs) ; + fates_hydro_htftype_node:units = "unitless" ; + fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; + char fates_pftname(fates_pft, fates_string_length) ; + fates_pftname:units = "unitless - string" ; + fates_pftname:long_name = "Description of plant type" ; + char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; + fates_hydro_organ_name:units = "unitless - string" ; + fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; + char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; + fates_alloc_organ_name:units = "unitless - string" ; + fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; + 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" ; + 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" ; + double fates_alloc_storage_cushion(fates_pft) ; + fates_alloc_storage_cushion:units = "fraction" ; + fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; + double fates_alloc_store_priority_frac(fates_pft) ; + fates_alloc_store_priority_frac:units = "unitless" ; + fates_alloc_store_priority_frac:long_name = "for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage" ; + double fates_allom_agb1(fates_pft) ; + fates_allom_agb1:units = "variable" ; + fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; + double fates_allom_agb2(fates_pft) ; + fates_allom_agb2:units = "variable" ; + fates_allom_agb2:long_name = "Parameter 2 for agb allometry" ; + double fates_allom_agb3(fates_pft) ; + fates_allom_agb3:units = "variable" ; + fates_allom_agb3:long_name = "Parameter 3 for agb allometry" ; + double fates_allom_agb4(fates_pft) ; + fates_allom_agb4:units = "variable" ; + fates_allom_agb4:long_name = "Parameter 4 for agb allometry" ; + double fates_allom_agb_frac(fates_pft) ; + fates_allom_agb_frac:units = "fraction" ; + fates_allom_agb_frac:long_name = "Fraction of woody biomass that is above ground" ; + double fates_allom_amode(fates_pft) ; + fates_allom_amode:units = "index" ; + fates_allom_amode:long_name = "AGB allometry function index." ; + double fates_allom_blca_expnt_diff(fates_pft) ; + fates_allom_blca_expnt_diff:units = "unitless" ; + fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; + double fates_allom_cmode(fates_pft) ; + fates_allom_cmode:units = "index" ; + fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; + double fates_allom_crown_depth_frac(fates_pft) ; + fates_allom_crown_depth_frac:units = "fraction" ; + fates_allom_crown_depth_frac:long_name = "the depth of a cohort crown as a fraction of its height" ; + double fates_allom_d2bl1(fates_pft) ; + fates_allom_d2bl1:units = "variable" ; + fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; + double fates_allom_d2bl2(fates_pft) ; + fates_allom_d2bl2:units = "variable" ; + fates_allom_d2bl2:long_name = "Parameter 2 for d2bl allometry" ; + double fates_allom_d2bl3(fates_pft) ; + fates_allom_d2bl3:units = "unitless" ; + fates_allom_d2bl3:long_name = "Parameter 3 for d2bl allometry" ; + double fates_allom_d2ca_coefficient_max(fates_pft) ; + fates_allom_d2ca_coefficient_max:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_max:long_name = "max (savanna) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2ca_coefficient_min(fates_pft) ; + fates_allom_d2ca_coefficient_min:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_min:long_name = "min (forest) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2h1(fates_pft) ; + fates_allom_d2h1:units = "variable" ; + fates_allom_d2h1:long_name = "Parameter 1 for d2h allometry (intercept, or c)" ; + double fates_allom_d2h2(fates_pft) ; + fates_allom_d2h2:units = "variable" ; + fates_allom_d2h2:long_name = "Parameter 2 for d2h allometry (slope, or m)" ; + double fates_allom_d2h3(fates_pft) ; + fates_allom_d2h3:units = "variable" ; + fates_allom_d2h3:long_name = "Parameter 3 for d2h allometry (optional)" ; + double fates_allom_dbh_maxheight(fates_pft) ; + fates_allom_dbh_maxheight:units = "cm" ; + fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; + double fates_allom_fmode(fates_pft) ; + fates_allom_fmode:units = "index" ; + fates_allom_fmode:long_name = "fine root biomass allometry function index." ; + double fates_allom_fnrt_prof_a(fates_pft) ; + fates_allom_fnrt_prof_a:units = "unitless" ; + fates_allom_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; + double fates_allom_fnrt_prof_b(fates_pft) ; + fates_allom_fnrt_prof_b:units = "unitless" ; + fates_allom_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; + double fates_allom_fnrt_prof_mode(fates_pft) ; + fates_allom_fnrt_prof_mode:units = "index" ; + fates_allom_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; + double fates_allom_frbstor_repro(fates_pft) ; + fates_allom_frbstor_repro:units = "fraction" ; + fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; + double fates_allom_hmode(fates_pft) ; + fates_allom_hmode:units = "index" ; + fates_allom_hmode:long_name = "height allometry function index." ; + double fates_allom_l2fr(fates_pft) ; + fates_allom_l2fr:units = "gC/gC" ; + fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; + double fates_allom_la_per_sa_int(fates_pft) ; + fates_allom_la_per_sa_int:units = "m2/cm2" ; + fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; + double fates_allom_la_per_sa_slp(fates_pft) ; + fates_allom_la_per_sa_slp:units = "m2/cm2/m" ; + fates_allom_la_per_sa_slp:long_name = "Leaf area per sapwood area rate of change with height, slope (optional)" ; + double fates_allom_lmode(fates_pft) ; + fates_allom_lmode:units = "index" ; + fates_allom_lmode:long_name = "leaf biomass allometry function index." ; + double fates_allom_sai_scaler(fates_pft) ; + fates_allom_sai_scaler:units = "m2/m2" ; + fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; + double fates_allom_smode(fates_pft) ; + fates_allom_smode:units = "index" ; + fates_allom_smode:long_name = "sapwood allometry function index." ; + double fates_allom_stmode(fates_pft) ; + fates_allom_stmode:units = "index" ; + fates_allom_stmode:long_name = "storage allometry function index: 1) Storage proportional to leaf biomass (with trimming), 2) Storage proportional to maximum leaf biomass (not trimmed)" ; + double fates_allom_zroot_k(fates_pft) ; + fates_allom_zroot_k:units = "unitless" ; + fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; + double fates_allom_zroot_max_dbh(fates_pft) ; + fates_allom_zroot_max_dbh:units = "cm" ; + fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; + double fates_allom_zroot_max_z(fates_pft) ; + fates_allom_zroot_max_z:units = "m" ; + fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_allom_zroot_min_dbh(fates_pft) ; + fates_allom_zroot_min_dbh:units = "cm" ; + fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; + double fates_allom_zroot_min_z(fates_pft) ; + fates_allom_zroot_min_z:units = "m" ; + fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_c2b(fates_pft) ; + fates_c2b:units = "ratio" ; + fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; + double fates_cnp_eca_alpha_ptase(fates_pft) ; + fates_cnp_eca_alpha_ptase:units = "g/m3" ; + fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; + double fates_cnp_eca_decompmicc(fates_pft) ; + fates_cnp_eca_decompmicc:units = "gC/m3" ; + fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; + double fates_cnp_eca_km_nh4(fates_pft) ; + fates_cnp_eca_km_nh4:units = "gN/m3" ; + fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; + double fates_cnp_eca_km_no3(fates_pft) ; + fates_cnp_eca_km_no3:units = "gN/m3" ; + fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; + double fates_cnp_eca_km_p(fates_pft) ; + fates_cnp_eca_km_p:units = "gP/m3" ; + fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; + double fates_cnp_eca_km_ptase(fates_pft) ; + fates_cnp_eca_km_ptase:units = "gP/m3" ; + fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; + double fates_cnp_eca_lambda_ptase(fates_pft) ; + fates_cnp_eca_lambda_ptase:units = "g/m3" ; + fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; + double fates_cnp_eca_vmax_ptase(fates_pft) ; + fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; + fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; + double fates_cnp_nfix1(fates_pft) ; + fates_cnp_nfix1:units = "fraction" ; + fates_cnp_nfix1:long_name = "fractional surcharge added to maintenance respiration that drives symbiotic fixation" ; + double fates_cnp_nitr_store_ratio(fates_pft) ; + fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; + fates_cnp_nitr_store_ratio:long_name = "storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code)" ; + double fates_cnp_phos_store_ratio(fates_pft) ; + fates_cnp_phos_store_ratio:units = "(gP/gP)" ; + fates_cnp_phos_store_ratio:long_name = "storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code)" ; + double fates_cnp_pid_kd(fates_pft) ; + fates_cnp_pid_kd:units = "unknown" ; + fates_cnp_pid_kd:long_name = "derivative constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_pid_ki(fates_pft) ; + fates_cnp_pid_ki:units = "unknown" ; + fates_cnp_pid_ki:long_name = "integral constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_pid_kp(fates_pft) ; + fates_cnp_pid_kp:units = "unknown" ; + fates_cnp_pid_kp:long_name = "proportional constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_prescribed_nuptake(fates_pft) ; + fates_cnp_prescribed_nuptake:units = "fraction" ; + fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; + double fates_cnp_prescribed_puptake(fates_pft) ; + fates_cnp_prescribed_puptake:units = "fraction" ; + fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; + double fates_cnp_store_ovrflw_frac(fates_pft) ; + fates_cnp_store_ovrflw_frac:units = "fraction" ; + fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; + double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_nitr_retrans:units = "fraction" ; + fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; + double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_phos_retrans:units = "fraction" ; + fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; + double fates_cnp_vmax_nh4(fates_pft) ; + fates_cnp_vmax_nh4:units = "gN/gC/s" ; + fates_cnp_vmax_nh4:long_name = "maximum (potential) uptake rate of NH4 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_nh4 for usage)" ; + double fates_cnp_vmax_no3(fates_pft) ; + fates_cnp_vmax_no3:units = "gN/gC/s" ; + fates_cnp_vmax_no3:long_name = "maximum (potential) uptake rate of NO3 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_no3 for usage)" ; + double fates_cnp_vmax_p(fates_pft) ; + fates_cnp_vmax_p:units = "gP/gC/s" ; + fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; + double fates_damage_frac(fates_pft) ; + fates_damage_frac:units = "fraction" ; + fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; + double fates_damage_mort_p1(fates_pft) ; + fates_damage_mort_p1:units = "fraction" ; + fates_damage_mort_p1:long_name = "inflection point of damage mortality function, a value of 0.8 means 50% mortality with 80% loss of crown, turn off with a large number" ; + double fates_damage_mort_p2(fates_pft) ; + fates_damage_mort_p2:units = "unitless" ; + fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; + 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_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" ; + double fates_fire_alpha_SH(fates_pft) ; + fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; + fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; + double fates_fire_bark_scaler(fates_pft) ; + fates_fire_bark_scaler:units = "fraction" ; + fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; + double fates_fire_crown_kill(fates_pft) ; + fates_fire_crown_kill:units = "NA" ; + fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; + double fates_frag_fnrt_fcel(fates_pft) ; + fates_frag_fnrt_fcel:units = "fraction" ; + fates_frag_fnrt_fcel:long_name = "Fine root litter cellulose fraction" ; + double fates_frag_fnrt_flab(fates_pft) ; + fates_frag_fnrt_flab:units = "fraction" ; + fates_frag_fnrt_flab:long_name = "Fine root litter labile fraction" ; + double fates_frag_fnrt_flig(fates_pft) ; + fates_frag_fnrt_flig:units = "fraction" ; + fates_frag_fnrt_flig:long_name = "Fine root litter lignin fraction" ; + double fates_frag_leaf_fcel(fates_pft) ; + fates_frag_leaf_fcel:units = "fraction" ; + fates_frag_leaf_fcel:long_name = "Leaf litter cellulose fraction" ; + double fates_frag_leaf_flab(fates_pft) ; + fates_frag_leaf_flab:units = "fraction" ; + fates_frag_leaf_flab:long_name = "Leaf litter labile fraction" ; + double fates_frag_leaf_flig(fates_pft) ; + fates_frag_leaf_flig:units = "fraction" ; + fates_frag_leaf_flig:long_name = "Leaf litter lignin fraction" ; + double fates_frag_seed_decay_rate(fates_pft) ; + fates_frag_seed_decay_rate:units = "yr-1" ; + fates_frag_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; + double fates_grperc(fates_pft) ; + fates_grperc:units = "unitless" ; + fates_grperc:long_name = "Growth respiration factor" ; + double fates_hydro_avuln_gs(fates_pft) ; + fates_hydro_avuln_gs:units = "unitless" ; + fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; + double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; + fates_hydro_avuln_node:units = "unitless" ; + fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; + double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; + fates_hydro_epsil_node:units = "MPa" ; + fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; + double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; + fates_hydro_fcap_node:units = "unitless" ; + fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; + double fates_hydro_k_lwp(fates_pft) ; + fates_hydro_k_lwp:units = "unitless" ; + fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; + double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; + fates_hydro_kmax_node:units = "kg/MPa/m/s" ; + fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; + double fates_hydro_p50_gs(fates_pft) ; + fates_hydro_p50_gs:units = "MPa" ; + fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; + double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; + fates_hydro_p50_node:units = "MPa" ; + fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; + double fates_hydro_p_taper(fates_pft) ; + fates_hydro_p_taper:units = "unitless" ; + fates_hydro_p_taper:long_name = "xylem taper exponent" ; + double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pinot_node:units = "MPa" ; + fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; + double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pitlp_node:units = "MPa" ; + fates_hydro_pitlp_node:long_name = "turgor loss point" ; + double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; + fates_hydro_resid_node:units = "cm3/cm3" ; + fates_hydro_resid_node:long_name = "residual water conent" ; + double fates_hydro_rfrac_stem(fates_pft) ; + fates_hydro_rfrac_stem:units = "fraction" ; + fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; + double fates_hydro_rs2(fates_pft) ; + fates_hydro_rs2:units = "m" ; + fates_hydro_rs2:long_name = "absorbing root radius" ; + double fates_hydro_srl(fates_pft) ; + fates_hydro_srl:units = "m g-1" ; + fates_hydro_srl:long_name = "specific root length" ; + double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; + fates_hydro_thetas_node:units = "cm3/cm3" ; + fates_hydro_thetas_node:long_name = "saturated water content" ; + double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_alpha_node:units = "MPa-1" ; + fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; + double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_m_node:units = "unitless" ; + fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; + 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_leaf_c3psn(fates_pft) ; + fates_leaf_c3psn:units = "flag" ; + fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; + double fates_leaf_jmaxha(fates_pft) ; + fates_leaf_jmaxha:units = "J/mol" ; + fates_leaf_jmaxha:long_name = "activation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_jmaxhd(fates_pft) ; + fates_leaf_jmaxhd:units = "J/mol" ; + fates_leaf_jmaxhd:long_name = "deactivation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_jmaxse(fates_pft) ; + fates_leaf_jmaxse:units = "J/mol/K" ; + fates_leaf_jmaxse:long_name = "entropy term for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_slamax(fates_pft) ; + fates_leaf_slamax:units = "m^2/gC" ; + fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; + double fates_leaf_slatop(fates_pft) ; + fates_leaf_slatop:units = "m^2/gC" ; + fates_leaf_slatop:long_name = "Specific Leaf Area (SLA) at top of canopy, projected area basis" ; + double fates_leaf_stomatal_intercept(fates_pft) ; + fates_leaf_stomatal_intercept:units = "umol H2O/m**2/s" ; + fates_leaf_stomatal_intercept:long_name = "Minimum unstressed stomatal conductance for Ball-Berry model and Medlyn model" ; + double fates_leaf_stomatal_slope_ballberry(fates_pft) ; + fates_leaf_stomatal_slope_ballberry:units = "unitless" ; + fates_leaf_stomatal_slope_ballberry:long_name = "stomatal slope parameter, as per Ball-Berry" ; + double fates_leaf_stomatal_slope_medlyn(fates_pft) ; + fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; + fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; + double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; + fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; + fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; + double fates_leaf_vcmaxha(fates_pft) ; + fates_leaf_vcmaxha:units = "J/mol" ; + fates_leaf_vcmaxha:long_name = "activation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_vcmaxhd(fates_pft) ; + fates_leaf_vcmaxhd:units = "J/mol" ; + fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_vcmaxse(fates_pft) ; + fates_leaf_vcmaxse:units = "J/mol/K" ; + fates_leaf_vcmaxse:long_name = "entropy term for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_maintresp_leaf_atkin2017_baserate(fates_pft) ; + fates_maintresp_leaf_atkin2017_baserate:units = "umol CO2/m^2/s" ; + fates_maintresp_leaf_atkin2017_baserate:long_name = "Leaf maintenance respiration base rate parameter (r0) per Atkin et al 2017" ; + double fates_maintresp_leaf_ryan1991_baserate(fates_pft) ; + fates_maintresp_leaf_ryan1991_baserate:units = "gC/gN/s" ; + fates_maintresp_leaf_ryan1991_baserate:long_name = "Leaf maintenance respiration base rate per Ryan et al 1991" ; + double fates_maintresp_reduction_curvature(fates_pft) ; + fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; + fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; + double fates_maintresp_reduction_intercept(fates_pft) ; + fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; + fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; + double fates_mort_bmort(fates_pft) ; + fates_mort_bmort:units = "1/yr" ; + fates_mort_bmort:long_name = "background mortality rate" ; + double fates_mort_freezetol(fates_pft) ; + fates_mort_freezetol:units = "degrees C" ; + fates_mort_freezetol:long_name = "minimum temperature tolerance" ; + double fates_mort_hf_flc_threshold(fates_pft) ; + fates_mort_hf_flc_threshold:units = "fraction" ; + fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; + double fates_mort_hf_sm_threshold(fates_pft) ; + fates_mort_hf_sm_threshold:units = "unitless" ; + fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; + double fates_mort_ip_age_senescence(fates_pft) ; + fates_mort_ip_age_senescence:units = "years" ; + fates_mort_ip_age_senescence:long_name = "Mortality cohort age senescence inflection point. If _ this mortality term is off. Setting this value turns on age dependent mortality. " ; + double fates_mort_ip_size_senescence(fates_pft) ; + fates_mort_ip_size_senescence:units = "dbh cm" ; + fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; + double fates_mort_prescribed_canopy(fates_pft) ; + fates_mort_prescribed_canopy:units = "1/yr" ; + fates_mort_prescribed_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; + double fates_mort_prescribed_understory(fates_pft) ; + fates_mort_prescribed_understory:units = "1/yr" ; + fates_mort_prescribed_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; + double fates_mort_r_age_senescence(fates_pft) ; + fates_mort_r_age_senescence:units = "mortality rate year^-1" ; + fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; + double fates_mort_r_size_senescence(fates_pft) ; + fates_mort_r_size_senescence:units = "mortality rate dbh^-1" ; + fates_mort_r_size_senescence:long_name = "Mortality dbh senescence rate of change. Sensible range is around 0.03-0.06. Larger values give steeper mortality curves." ; + double fates_mort_scalar_coldstress(fates_pft) ; + fates_mort_scalar_coldstress:units = "1/yr" ; + fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; + double fates_mort_scalar_cstarvation(fates_pft) ; + fates_mort_scalar_cstarvation:units = "1/yr" ; + fates_mort_scalar_cstarvation:long_name = "maximum mortality rate from carbon starvation" ; + double fates_mort_scalar_hydrfailure(fates_pft) ; + fates_mort_scalar_hydrfailure:units = "1/yr" ; + fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; + double fates_nonhydro_smpsc(fates_pft) ; + fates_nonhydro_smpsc:units = "mm" ; + fates_nonhydro_smpsc:long_name = "Soil water potential at full stomatal closure" ; + double fates_nonhydro_smpso(fates_pft) ; + fates_nonhydro_smpso:units = "mm" ; + fates_nonhydro_smpso:long_name = "Soil water potential at full stomatal opening" ; + double fates_phen_cold_size_threshold(fates_pft) ; + fates_phen_cold_size_threshold:units = "cm" ; + fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; + double fates_phen_evergreen(fates_pft) ; + fates_phen_evergreen:units = "logical flag" ; + fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; + double fates_phen_flush_fraction(fates_pft) ; + fates_phen_flush_fraction:units = "fraction" ; + fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; + double fates_phen_fnrt_drop_frac(fates_pft) ; + fates_phen_fnrt_drop_frac:units = "fraction" ; + fates_phen_fnrt_drop_frac:long_name = "fraction of fine roots to drop during drought or cold" ; + double fates_phen_season_decid(fates_pft) ; + fates_phen_season_decid:units = "logical flag" ; + fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; + double fates_phen_stem_drop_fraction(fates_pft) ; + fates_phen_stem_drop_fraction:units = "fraction" ; + fates_phen_stem_drop_fraction:long_name = "fraction of stems to drop for non-woody species during drought/cold" ; + double fates_phen_stress_decid(fates_pft) ; + fates_phen_stress_decid:units = "logical flag" ; + fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; + double fates_prescribed_npp_canopy(fates_pft) ; + fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; + double fates_prescribed_npp_understory(fates_pft) ; + fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; + double fates_rad_leaf_clumping_index(fates_pft) ; + fates_rad_leaf_clumping_index:units = "fraction (0-1)" ; + fates_rad_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; + double fates_rad_leaf_rhonir(fates_pft) ; + fates_rad_leaf_rhonir:units = "fraction" ; + fates_rad_leaf_rhonir:long_name = "Leaf reflectance: near-IR" ; + double fates_rad_leaf_rhovis(fates_pft) ; + fates_rad_leaf_rhovis:units = "fraction" ; + fates_rad_leaf_rhovis:long_name = "Leaf reflectance: visible" ; + double fates_rad_leaf_taunir(fates_pft) ; + fates_rad_leaf_taunir:units = "fraction" ; + fates_rad_leaf_taunir:long_name = "Leaf transmittance: near-IR" ; + double fates_rad_leaf_tauvis(fates_pft) ; + fates_rad_leaf_tauvis:units = "fraction" ; + fates_rad_leaf_tauvis:long_name = "Leaf transmittance: visible" ; + double fates_rad_leaf_xl(fates_pft) ; + fates_rad_leaf_xl:units = "unitless" ; + fates_rad_leaf_xl:long_name = "Leaf/stem orientation index" ; + double fates_rad_stem_rhonir(fates_pft) ; + fates_rad_stem_rhonir:units = "fraction" ; + fates_rad_stem_rhonir:long_name = "Stem reflectance: near-IR" ; + double fates_rad_stem_rhovis(fates_pft) ; + fates_rad_stem_rhovis:units = "fraction" ; + fates_rad_stem_rhovis:long_name = "Stem reflectance: visible" ; + double fates_rad_stem_taunir(fates_pft) ; + fates_rad_stem_taunir:units = "fraction" ; + fates_rad_stem_taunir:long_name = "Stem transmittance: near-IR" ; + double fates_rad_stem_tauvis(fates_pft) ; + fates_rad_stem_tauvis:units = "fraction" ; + fates_rad_stem_tauvis:long_name = "Stem transmittance: visible" ; + double fates_recruit_height_min(fates_pft) ; + fates_recruit_height_min:units = "m" ; + fates_recruit_height_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; + double fates_recruit_init_density(fates_pft) ; + fates_recruit_init_density:units = "stems/m2" ; + fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation. If negative sets initial tree dbh - only to be used in nocomp mode" ; + double fates_recruit_prescribed_rate(fates_pft) ; + fates_recruit_prescribed_rate:units = "n/yr" ; + fates_recruit_prescribed_rate:long_name = "recruitment rate for prescribed physiology mode" ; + double fates_recruit_seed_alloc(fates_pft) ; + fates_recruit_seed_alloc:units = "fraction" ; + fates_recruit_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; + double fates_recruit_seed_alloc_mature(fates_pft) ; + fates_recruit_seed_alloc_mature:units = "fraction" ; + fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; + double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; + fates_recruit_seed_dbh_repro_threshold:units = "cm" ; + fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter where the plant will increase allocation to the seed pool by fraction: fates_recruit_seed_alloc_mature" ; + double fates_recruit_seed_germination_rate(fates_pft) ; + fates_recruit_seed_germination_rate:units = "yr-1" ; + fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; + double fates_recruit_seed_supplement(fates_pft) ; + fates_recruit_seed_supplement:units = "KgC/m2/yr" ; + fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; + double fates_stoich_nitr(fates_plant_organs, fates_pft) ; + fates_stoich_nitr:units = "gN/gC" ; + fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; + double fates_stoich_phos(fates_plant_organs, fates_pft) ; + fates_stoich_phos:units = "gP/gC" ; + fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; + double fates_trim_inc(fates_pft) ; + fates_trim_inc:units = "m2/m2" ; + fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; + double fates_trim_limit(fates_pft) ; + fates_trim_limit:units = "m2/m2" ; + fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; + double fates_turb_displar(fates_pft) ; + fates_turb_displar:units = "unitless" ; + fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; + double fates_turb_leaf_diameter(fates_pft) ; + fates_turb_leaf_diameter:units = "m" ; + fates_turb_leaf_diameter:long_name = "Characteristic leaf dimension" ; + double fates_turb_z0mr(fates_pft) ; + fates_turb_z0mr:units = "unitless" ; + fates_turb_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; + double fates_turnover_branch(fates_pft) ; + fates_turnover_branch:units = "yr" ; + fates_turnover_branch:long_name = "turnover time of branches" ; + double fates_turnover_fnrt(fates_pft) ; + fates_turnover_fnrt:units = "yr" ; + fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; + double fates_turnover_leaf(fates_leafage_class, fates_pft) ; + fates_turnover_leaf:units = "yr" ; + fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; + double fates_turnover_senleaf_fdrought(fates_pft) ; + fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; + fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; + double fates_wood_density(fates_pft) ; + fates_wood_density:units = "g/cm3" ; + fates_wood_density:long_name = "mean density of woody tissue in plant" ; + double fates_woody(fates_pft) ; + fates_woody:units = "logical flag" ; + fates_woody:long_name = "Binary woody lifeform flag" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_fire_FBD(fates_litterclass) ; + fates_fire_FBD:units = "kg Biomass/m3" ; + fates_fire_FBD:long_name = "fuel bulk density" ; + double fates_fire_low_moisture_Coeff(fates_litterclass) ; + fates_fire_low_moisture_Coeff:units = "NA" ; + fates_fire_low_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_low_moisture_Slope(fates_litterclass) ; + fates_fire_low_moisture_Slope:units = "NA" ; + fates_fire_low_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture(fates_litterclass) ; + fates_fire_mid_moisture:units = "NA" ; + fates_fire_mid_moisture:long_name = "spitfire litter moisture threshold to be considered medium dry" ; + double fates_fire_mid_moisture_Coeff(fates_litterclass) ; + fates_fire_mid_moisture_Coeff:units = "NA" ; + fates_fire_mid_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture_Slope(fates_litterclass) ; + fates_fire_mid_moisture_Slope:units = "NA" ; + fates_fire_mid_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_min_moisture(fates_litterclass) ; + fates_fire_min_moisture:units = "NA" ; + fates_fire_min_moisture:long_name = "spitfire litter moisture threshold to be considered very dry" ; + double fates_fire_SAV(fates_litterclass) ; + fates_fire_SAV:units = "cm-1" ; + fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; + double fates_frag_maxdecomp(fates_litterclass) ; + fates_frag_maxdecomp:units = "yr-1" ; + fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; + 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_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" ; + double fates_cnp_eca_plant_escalar ; + fates_cnp_eca_plant_escalar:units = "" ; + fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; + double fates_cohort_age_fusion_tol ; + fates_cohort_age_fusion_tol:units = "unitless" ; + fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; + double fates_cohort_size_fusion_tol ; + fates_cohort_size_fusion_tol:units = "unitless" ; + fates_cohort_size_fusion_tol:long_name = "minimum fraction in difference in dbh between cohorts" ; + double fates_comp_excln ; + fates_comp_excln:units = "none" ; + fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; + double fates_damage_canopy_layer_code ; + fates_damage_canopy_layer_code:units = "unitless" ; + fates_damage_canopy_layer_code:long_name = "Integer code that decides whether damage affects canopy trees (1), understory trees (2)" ; + double fates_damage_event_code ; + fates_damage_event_code:units = "unitless" ; + fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; + double fates_dev_arbitrary ; + fates_dev_arbitrary:units = "unknown" ; + fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; + double fates_fire_active_crown_fire ; + fates_fire_active_crown_fire:units = "0 or 1" ; + fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; + double fates_fire_cg_strikes ; + fates_fire_cg_strikes:units = "fraction (0-1)" ; + fates_fire_cg_strikes:long_name = "fraction of cloud to ground lightning strikes" ; + double fates_fire_drying_ratio ; + fates_fire_drying_ratio:units = "NA" ; + fates_fire_drying_ratio:long_name = "spitfire parameter, fire drying ratio for fuel moisture, alpha_FMC EQ 6 Thonicke et al 2010" ; + double fates_fire_durat_slope ; + fates_fire_durat_slope:units = "NA" ; + fates_fire_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; + double fates_fire_fdi_a ; + fates_fire_fdi_a:units = "NA" ; + fates_fire_fdi_a:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010" ; + double fates_fire_fdi_alpha ; + fates_fire_fdi_alpha:units = "NA" ; + fates_fire_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; + double fates_fire_fdi_b ; + fates_fire_fdi_b:units = "NA" ; + fates_fire_fdi_b:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010 " ; + double fates_fire_fuel_energy ; + fates_fire_fuel_energy:units = "kJ/kg" ; + fates_fire_fuel_energy:long_name = "spitfire parameter, heat content of fuel" ; + double fates_fire_max_durat ; + fates_fire_max_durat:units = "minutes" ; + fates_fire_max_durat:long_name = "spitfire parameter, fire maximum duration, Equation 14 Thonicke et al 2010" ; + double fates_fire_miner_damp ; + fates_fire_miner_damp:units = "NA" ; + fates_fire_miner_damp:long_name = "spitfire parameter, mineral-dampening coefficient EQ A1 Thonicke et al 2010 " ; + double fates_fire_miner_total ; + fates_fire_miner_total:units = "fraction" ; + fates_fire_miner_total:long_name = "spitfire parameter, total mineral content, Table A1 Thonicke et al 2010" ; + double fates_fire_nignitions ; + fates_fire_nignitions:units = "ignitions per year per km2" ; + fates_fire_nignitions:long_name = "number of annual ignitions per square km" ; + double fates_fire_part_dens ; + fates_fire_part_dens:units = "kg/m2" ; + fates_fire_part_dens:long_name = "spitfire parameter, oven dry particle density, Table A1 Thonicke et al 2010" ; + double fates_fire_threshold ; + fates_fire_threshold:units = "kW/m" ; + fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; + double fates_frag_cwd_fcel ; + fates_frag_cwd_fcel:units = "unitless" ; + fates_frag_cwd_fcel:long_name = "Cellulose fraction for CWD" ; + double fates_frag_cwd_flig ; + fates_frag_cwd_flig:units = "unitless" ; + fates_frag_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; + double fates_hydro_kmax_rsurf1 ; + fates_hydro_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; + double fates_hydro_kmax_rsurf2 ; + fates_hydro_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; + double fates_hydro_psi0 ; + fates_hydro_psi0:units = "MPa" ; + fates_hydro_psi0:long_name = "sapwood water potential at saturation" ; + double fates_hydro_psicap ; + fates_hydro_psicap:units = "MPa" ; + fates_hydro_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; + 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_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" ; + double fates_landuse_logging_collateral_frac ; + fates_landuse_logging_collateral_frac:units = "fraction" ; + fates_landuse_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; + double fates_landuse_logging_dbhmax ; + fates_landuse_logging_dbhmax:units = "cm" ; + fates_landuse_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; + double fates_landuse_logging_dbhmax_infra ; + fates_landuse_logging_dbhmax_infra:units = "cm" ; + fates_landuse_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; + double fates_landuse_logging_dbhmin ; + fates_landuse_logging_dbhmin:units = "cm" ; + fates_landuse_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; + double fates_landuse_logging_direct_frac ; + fates_landuse_logging_direct_frac:units = "fraction" ; + fates_landuse_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; + double fates_landuse_logging_event_code ; + fates_landuse_logging_event_code:units = "unitless" ; + fates_landuse_logging_event_code:long_name = "Integer code that options how logging events are structured" ; + double fates_landuse_logging_export_frac ; + fates_landuse_logging_export_frac:units = "fraction" ; + fates_landuse_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; + double fates_landuse_logging_mechanical_frac ; + fates_landuse_logging_mechanical_frac:units = "fraction" ; + fates_landuse_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; + double fates_landuse_pprodharv10_forest_mean ; + fates_landuse_pprodharv10_forest_mean:units = "fraction" ; + fates_landuse_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; + double fates_leaf_photo_temp_acclim_thome_time ; + fates_leaf_photo_temp_acclim_thome_time:units = "years" ; + fates_leaf_photo_temp_acclim_thome_time:long_name = "Length of the window for the long-term (i.e. T_home in Kumarathunge et al 2019) exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_leaf_photo_tempsens_model = 2)" ; + double fates_leaf_photo_temp_acclim_timescale ; + fates_leaf_photo_temp_acclim_timescale:units = "days" ; + fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_maintresp_leaf_model=2 or fates_leaf_photo_tempsens_model = 2)" ; + double fates_leaf_photo_tempsens_model ; + fates_leaf_photo_tempsens_model:units = "unitless" ; + fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating; 2=Kumarathunge et al 2019" ; + double fates_leaf_stomatal_assim_model ; + fates_leaf_stomatal_assim_model:units = "unitless" ; + fates_leaf_stomatal_assim_model:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; + double fates_leaf_stomatal_model ; + fates_leaf_stomatal_model:units = "unitless" ; + fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; + double fates_leaf_theta_cj_c3 ; + fates_leaf_theta_cj_c3:units = "unitless" ; + fates_leaf_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; + double fates_leaf_theta_cj_c4 ; + fates_leaf_theta_cj_c4:units = "unitless" ; + fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; + double fates_maintresp_leaf_model ; + fates_maintresp_leaf_model:units = "unitless" ; + fates_maintresp_leaf_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991), 2=Atkin et al., (2017)" ; + double fates_maintresp_nonleaf_baserate ; + fates_maintresp_nonleaf_baserate:units = "gC/gN/s" ; + fates_maintresp_nonleaf_baserate:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; + double fates_maxcohort ; + fates_maxcohort:units = "count" ; + fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; + double fates_maxpatch_primary ; + fates_maxpatch_primary:units = "count" ; + fates_maxpatch_primary:long_name = "maximum number of primary vegetation patches per site" ; + double fates_maxpatch_secondary ; + fates_maxpatch_secondary:units = "count" ; + fates_maxpatch_secondary:long_name = "maximum number of secondary vegetation patches per site" ; + double fates_mort_disturb_frac ; + fates_mort_disturb_frac:units = "fraction" ; + fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; + double fates_mort_understorey_death ; + fates_mort_understorey_death:units = "fraction" ; + fates_mort_understorey_death:long_name = "fraction of plants in understorey cohort impacted by overstorey tree-fall" ; + double fates_patch_fusion_tol ; + fates_patch_fusion_tol:units = "unitless" ; + fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; + double fates_phen_chilltemp ; + fates_phen_chilltemp:units = "degrees C" ; + fates_phen_chilltemp:long_name = "chilling day counting threshold for vegetation" ; + double fates_phen_coldtemp ; + fates_phen_coldtemp:units = "degrees C" ; + fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; + double fates_phen_drought_model ; + fates_phen_drought_model:units = "unitless" ; + fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; + double fates_phen_drought_threshold ; + fates_phen_drought_threshold:units = "m3/m3 or mm" ; + fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_gddthresh_a ; + fates_phen_gddthresh_a:units = "none" ; + fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_b ; + fates_phen_gddthresh_b:units = "none" ; + fates_phen_gddthresh_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_c ; + fates_phen_gddthresh_c:units = "none" ; + fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_mindaysoff ; + fates_phen_mindaysoff:units = "days" ; + fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves became off-allometry" ; + double fates_phen_mindayson ; + fates_phen_mindayson:units = "days" ; + fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; + double fates_phen_moist_threshold ; + fates_phen_moist_threshold:units = "m3/m3 or mm" ; + fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_ncolddayslim ; + fates_phen_ncolddayslim:units = "days" ; + fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; + double fates_q10_froz ; + fates_q10_froz:units = "unitless" ; + fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; + double fates_q10_mr ; + fates_q10_mr:units = "unitless" ; + fates_q10_mr:long_name = "Q10 for maintenance respiration" ; + double fates_soil_salinity ; + fates_soil_salinity:units = "ppt" ; + fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; + double fates_vai_top_bin_width ; + fates_vai_top_bin_width:units = "m2/m2" ; + fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; + double fates_vai_width_increase_factor ; + fates_vai_width_increase_factor:units = "unitless" ; + fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; + +// global attributes: + :history = "This file was generated by BatchPatchParams.py:\nCDL Base File = archive/api24.1.0_101722_fates_params_default.cdl\nXML patch file = archive/api24.1.0_101722_patch_params.xml" ; +data: + + fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; + + fates_history_coageclass_bin_edges = 0, 5 ; + + fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; + + fates_history_damage_bin_edges = 0, 80 ; + + fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, + 80, 90, 100 ; + + fates_alloc_organ_id = 1, 2, 3, 6 ; + + fates_hydro_htftype_node = 1, 1, 1, 1 ; + + fates_pftname = + "broadleaf_evergreen_tropical_tree ", + "needleleaf_evergreen_extratrop_tree ", + "needleleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_tree ", + "broadleaf_hydrodecid_tropical_tree ", + "broadleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_shrub ", + "broadleaf_hydrodecid_extratrop_shrub ", + "broadleaf_colddecid_extratrop_shrub ", + "arctic_c3_grass ", + "cool_c3_grass ", + "c4_grass " ; + + fates_hydro_organ_name = + "leaf ", + "stem ", + "transporting root ", + "absorbing root " ; + + fates_alloc_organ_name = + "leaf", + "fine root", + "sapwood", + "structure" ; + + fates_litterclass_name = + "twig ", + "small branch ", + "large branch ", + "trunk ", + "dead leaves ", + "live grass " ; + + 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, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; + + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + 1.2, 1.2, 1.2 ; + + fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8, 0.8 ; + + fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, + 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; + + fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, + 0.572, 0.572, 0.572, 0.572 ; + + fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, + 1.94, 1.94, 1.94 ; + + fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, + 0.931, 0.931, 0.931, 0.931 ; + + fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6 ; + + fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, + 0.95, 1, 1, 1 ; + + fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07 ; + + fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, + 1.3 ; + + fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, + 0.55, 0.55, 0.55 ; + + fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464 ; + + fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119 ; + + fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, + 0.64, 0.64, 0.64 ; + + fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, + 0.37, 0.37, 0.37 ; + + fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, + -999.9, -999.9, -999.9, -999.9, -999.9 ; + + fates_allom_dbh_maxheight = 90, 80, 80, 80, 90, 80, 3, 3, 2, 0.35, 0.35, 0.35 ; + + fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; + + fates_allom_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; + + fates_allom_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8 ; + + fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_zroot_k = 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 ; + + fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; + + fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + + fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 280, 280 ; + + fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, + 0.14, 0.14, 0.14 ; + + fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, + 0.27, 0.27, 0.27 ; + + fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_nfix1 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_pid_kd = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; + + fates_cnp_pid_ki = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_pid_kp = 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005 ; + + fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_turnover_nitr_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_turnover_phos_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_vmax_nh4 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, + 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; + + fates_cnp_vmax_no3 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, + 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; + + fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, + 5e-10, 5e-10, 5e-10, 5e-10 ; + + fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01 ; + + fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; + + fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, + 5.5, 5.5 ; + + fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2 ; + + fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07, 0.07 ; + + fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, + 0.775, 0.775, 0.775, 0.775, 0.775 ; + + fates_frag_fnrt_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_fnrt_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_fnrt_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_leaf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, + 0.51, 0.51, 0.51, 0.51 ; + + fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, + 0.11, 0.11 ; + + fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + 2.5, 2.5 ; + + fates_hydro_avuln_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_hydro_epsil_node = + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_hydro_fcap_node = + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_kmax_node = + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; + + fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + -1.5, -1.5, -1.5 ; + + fates_hydro_p50_node = + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25 ; + + fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, + 0.333, 0.333, 0.333, 0.333, 0.333 ; + + fates_hydro_pinot_node = + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; + + fates_hydro_pitlp_node = + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + -1.67, -1.67, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; + + fates_hydro_resid_node = + 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; + + fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + 0.625, 0.625, 0.625, 0.625, 0.625 ; + + fates_hydro_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, + 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; + + fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; + + fates_hydro_thetas_node = + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; + + fates_hydro_vg_alpha_node = + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005 ; + + fates_hydro_vg_m_node = + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_hydro_vg_n_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_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, + 43540, 43540, 43540, 43540 ; + + fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, + 152040, 152040, 152040, 152040, 152040 ; + + fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, + 495 ; + + fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, + 0.03, 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_slatop = 0.012, 0.005, 0.024, 0.009, 0.03, 0.03, 0.012, 0.03, + 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, + 10000, 10000, 10000, 10000, 10000, 40000 ; + + fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, + 4.7, 2.2, 5.3, 1.6 ; + + fates_leaf_vcmax25top = + 50, 62, 39, 61, 41, 58, 62, 54, 54, 78, 78, 78 ; + + fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, + 65330, 65330, 65330, 65330 ; + + fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, + 149250, 149250, 149250, 149250, 149250 ; + + fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, + 485 ; + + fates_maintresp_leaf_atkin2017_baserate = 1.756, 1.4995, 1.4995, 1.756, + 1.756, 1.756, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956, 2.1956 ; + + fates_maintresp_leaf_ryan1991_baserate = 2.525e-06, 2.525e-06, 2.525e-06, + 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, + 2.525e-06, 2.525e-06, 2.525e-06 ; + + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; + + fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, + 0.014, 0.014, 0.014, 0.014 ; + + fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -80, -60, -10, -80, -80, + -20, 2.5 ; + + fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, + 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; + + fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_prescribed_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, + 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; + + fates_mort_prescribed_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, + 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; + + fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_nonhydro_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, + -255000, -255000, -255000, -255000, -255000, -255000 ; + + fates_nonhydro_smpso = -66000, -66000, -66000, -66000, -66000, -66000, + -66000, -66000, -66000, -66000, -66000, -66000 ; + + fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; + + fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, + 0.5 ; + + fates_phen_fnrt_drop_frac = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; + + fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; + + fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, + 0.4, 0.4, 0.4 ; + + fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, + 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; + + fates_rad_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, + 0.9, 0.75, 0.75, 0.75 ; + + fates_rad_leaf_rhonir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, + 0.41, 0.28, 0.28, 0.28 ; + + fates_rad_leaf_rhovis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, + 0.08, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_taunir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, + 0.43, 0.4, 0.4, 0.4 ; + + fates_rad_leaf_tauvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, + 0.06, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, + -0.23, -0.23, -0.23 ; + + fates_rad_stem_rhonir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, + 0.49, 0.53, 0.53, 0.53 ; + + fates_rad_stem_rhovis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.31, 0.31, 0.31 ; + + fates_rad_stem_taunir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.25, 0.25, 0.25 ; + + fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.12, 0.12, 0.12 ; + + fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.2, 0.2, 0.2, + 0.125, 0.125, 0.125 ; + + fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2, 0.2, 0.2 ; + + fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, + 0.02, 0.02, 0.02, 0.02, 0.02 ; + + fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, + 0.9 ; + + fates_recruit_seed_dbh_repro_threshold = 90, 80, 80, 80, 90, 80, 3, 3, 2, + 0.35, 0.35, 0.35 ; + + fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_stoich_nitr = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; + + fates_stoich_phos = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; + + fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, + 0.03, 0.03 ; + + fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; + + fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, + 0.67, 0.67, 0.67 ; + + fates_turb_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.04, 0.04, 0.04, 0.04 ; + + fates_turb_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, + 0.055, 0.055, 0.055, 0.055 ; + + fates_turnover_branch = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; + + fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_leaf = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_wood_density = 0.7, 0.4, 0.7, 0.53, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, + 0.7 ; + + fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; + + fates_hlm_pft_map = + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + + fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; + + fates_fire_low_moisture_Coeff = 1.12, 1.09, 0.98, 0.8, 1.15, 1.15 ; + + fates_fire_low_moisture_Slope = 0.62, 0.72, 0.85, 0.8, 0.62, 0.62 ; + + fates_fire_mid_moisture = 0.72, 0.51, 0.38, 1, 0.8, 0.8 ; + + fates_fire_mid_moisture_Coeff = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_mid_moisture_Slope = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_min_moisture = 0.18, 0.12, 0, 0, 0.24, 0.24 ; + + fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; + + fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; + + fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; + + fates_canopy_closure_thresh = 0.8 ; + + fates_cnp_eca_plant_escalar = 1.25e-05 ; + + fates_cohort_age_fusion_tol = 0.08 ; + + fates_cohort_size_fusion_tol = 0.08 ; + + fates_comp_excln = 3 ; + + fates_damage_canopy_layer_code = 1 ; + + fates_damage_event_code = 1 ; + + fates_dev_arbitrary = _ ; + + fates_fire_active_crown_fire = 0 ; + + fates_fire_cg_strikes = 0.2 ; + + fates_fire_drying_ratio = 66000 ; + + fates_fire_durat_slope = -11.06 ; + + fates_fire_fdi_a = 17.62 ; + + fates_fire_fdi_alpha = 0.00037 ; + + fates_fire_fdi_b = 243.12 ; + + fates_fire_fuel_energy = 18000 ; + + fates_fire_max_durat = 240 ; + + fates_fire_miner_damp = 0.41739 ; + + fates_fire_miner_total = 0.055 ; + + fates_fire_nignitions = 15 ; + + fates_fire_part_dens = 513 ; + + fates_fire_threshold = 50 ; + + fates_frag_cwd_fcel = 0.76 ; + + fates_frag_cwd_flig = 0.24 ; + + fates_hydro_kmax_rsurf1 = 20 ; + + fates_hydro_kmax_rsurf2 = 0.0001 ; + + fates_hydro_psi0 = 0 ; + + fates_hydro_psicap = -0.6 ; + + fates_hydro_solver = 1 ; + + fates_landuse_logging_coll_under_frac = 0.55983 ; + + fates_landuse_logging_collateral_frac = 0.05 ; + + fates_landuse_logging_dbhmax = _ ; + + fates_landuse_logging_dbhmax_infra = 35 ; + + fates_landuse_logging_dbhmin = 50 ; + + fates_landuse_logging_direct_frac = 0.15 ; + + fates_landuse_logging_event_code = -30 ; + + fates_landuse_logging_export_frac = 0.8 ; + + fates_landuse_logging_mechanical_frac = 0.05 ; + + fates_landuse_pprodharv10_forest_mean = 0.8125 ; + + fates_leaf_photo_temp_acclim_thome_time = 30 ; + + fates_leaf_photo_temp_acclim_timescale = 30 ; + + fates_leaf_photo_tempsens_model = 1 ; + + fates_leaf_stomatal_assim_model = 1 ; + + fates_leaf_stomatal_model = 1 ; + + fates_leaf_theta_cj_c3 = 0.999 ; + + fates_leaf_theta_cj_c4 = 0.999 ; + + fates_maintresp_leaf_model = 1 ; + + fates_maintresp_nonleaf_baserate = 2.525e-06 ; + + fates_maxcohort = 100 ; + + fates_maxpatch_primary = 10 ; + + fates_maxpatch_secondary = 4 ; + + fates_mort_disturb_frac = 1 ; + + fates_mort_understorey_death = 0.55983 ; + + fates_patch_fusion_tol = 0.05 ; + + fates_phen_chilltemp = 5 ; + + fates_phen_coldtemp = 7.5 ; + + fates_phen_drought_model = 0 ; + + fates_phen_drought_threshold = 0.15 ; + + fates_phen_gddthresh_a = -68 ; + + fates_phen_gddthresh_b = 638 ; + + fates_phen_gddthresh_c = -0.01 ; + + fates_phen_mindaysoff = 100 ; + + fates_phen_mindayson = 90 ; + + fates_phen_moist_threshold = 0.18 ; + + fates_phen_ncolddayslim = 5 ; + + fates_q10_froz = 1.5 ; + + fates_q10_mr = 1.5 ; + + fates_soil_salinity = 0.4 ; + + fates_vai_top_bin_width = 1 ; + + fates_vai_width_increase_factor = 1 ; +} diff --git a/parameter_files/archive/api25.4.0_041023_pr958.xml b/parameter_files/archive/api25.4.0_041023_pr958.xml new file mode 100644 index 0000000000..295bb2c1fd --- /dev/null +++ b/parameter_files/archive/api25.4.0_041023_pr958.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + archive/api25.4.0_041023_fates_params_default.cdl + fates_params_default_test.cdl + 1,2,3,4,5,6,7,8,9,10,11,12 + + + fates_phen_fnrt_drop_fraction + fraction of fine roots to drop during drought/cold + + + Leaf longevity (ie turnover timescale). For drought-deciduous PFTs, this also indicates the maximum length of the growing (i.e., leaves on) season. + + + fates_pft + -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4 + + + fates_pft + -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9 + + + fates_pft + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 + + + fates_phen_drought_model + + + From 5c72c2fad15cc247bda5cd034da6404f7beb10e5 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 12 May 2023 16:06:54 -0700 Subject: [PATCH 692/852] Adding state correction function --- tools/luh2.py | 38 +++++++++++++++++++++++++------------- tools/luh2mod.py | 37 ++++++++++++++++++++++++++++--------- 2 files changed, 53 insertions(+), 22 deletions(-) diff --git a/tools/luh2.py b/tools/luh2.py index 22e8d8bab7..67a728dcd5 100644 --- a/tools/luh2.py +++ b/tools/luh2.py @@ -1,8 +1,11 @@ #!/usr/bin/env python3 +# LUH2 python script +# Usage: python luh2.py -l -s + import argparse, os from luh2mod import PrepDataSet, ImportData, SetMaskLUH2, SetMaskSurfData -from luh2mod import RegridConservative +from luh2mod import RegridConservative, CorrectStateSum # Add version checking here in case environment.yml not used def main(): @@ -15,13 +18,14 @@ def main(): # Prep the LUH2 datasets and regrid target ds_luh2 = PrepDataSet(args.luh2_file,args.begin,args.end) + if (args.regridder_file == None): ds_regrid_target = PrepDataSet(args.regridder_target_file,args.begin,args.end) # Import the LUH2 static data to use for masking ds_luh2_static = ImportData(args.luh2_static_file) - # Create new variable where the ice water fraction is inverted + # Create new variable where the ice water fraction is inverted w ds_luh2_static["landfrac"] = 1 - ds_luh2_static.icwtr # Mask all LUH2 input data using the ice/water fraction for the LUH2 static data @@ -32,6 +36,7 @@ def main(): ds_regrid_target = SetMaskSurfData(ds_regrid_target) # Regrid the luh2 data to the target grid + # TO DO: provide a check for the save argument based on the input arguments regrid_luh2,regridder_luh2 = RegridConservative(ds_luh2, ds_regrid_target, save=True) elif (args.regridder_target_file == None): @@ -44,18 +49,21 @@ def main(): #regrid_land_fraction = regridder_land_fraction(ds_luh2_static) regrid_land_fraction = regridder_luh2(ds_luh2_static) - # # Adjust the luh2 data by the land fraction - # # To Do: check if we need to do this for transition and management data as well + # Adjust the luh2 data by the land fraction regrid_luh2 = regrid_luh2 / regrid_land_fraction.landfrac - # # Rename the dimensions for the output - # TO DO: double check if this is necessary - regrid_luh2 = regrid_luh2.rename_dims(dims_dict={'lat':'lsmlat','lon':'lsmlon'}) - regrid_luh2["LONGXY"] = ds_regrid_target["LONGXY"] - regrid_luh2["LATIXY"] = ds_regrid_target["LATIXY"] + regrid_luh2 = CorrectStateSum(regrid_luh2) - # # Add 'YEAR' as a variable. This is an old requirement of the HLM and should simply be a copy of the `time` dimension + # Add additional required variables for the host land model + # Add 'YEAR' as a variable. + # This is an old requirement of the HLM and should simply be a copy of the `time` dimension regrid_luh2["YEAR"] = regrid_luh2.time + regrid_luh2["LONGXY"] = ds_regrid_target["LONGXY"] # TO DO: double check if this is strictly necessary + regrid_luh2["LATIXY"] = ds_regrid_target["LATIXY"] # TO DO: double check if this is strictly necessary + + + # Rename the dimensions for the output + regrid_luh2 = regrid_luh2.rename_dims({'lat':'lsmlat','lon':'lsmlon'}) # Merge existing regrided luh2 file with merge input target # TO DO: check that the grid resolution and time bounds match @@ -85,15 +93,19 @@ def CommandLineArgs(): # TO DO: using the checking function to report back if invalid file input parser.add_argument("-l","--luh2_file", required=True) - # Required static luh2 data to get the ice/water fraction - parser.add_argument("-s", "--luh2_static_file", required=True) - # Provide mutually exlusive arguments for regridding input selection # Currently assuming that if a target is provided that a regridder file will be saved regrid_target = parser.add_mutually_exclusive_group(required=True) regrid_target.add_argument("-rf","--regridder_file") # use previously save regridder file regrid_target.add_argument("-rt","--regridder_target_file") # use a dataset to regrid to + # TO DO: static file is required if regridder file argument is not used + # Required static luh2 data to get the ice/water fraction + parser.add_argument("-s", "--luh2_static_file") + + # Optional argument for defining the regridder file name + parser.add_argument("-rs", "--regridder_save_name") + # Optional input to subset the time range of the data parser.add_argument("-b","--begin") parser.add_argument("-e","--end") diff --git a/tools/luh2mod.py b/tools/luh2mod.py index 63b52f1331..61304bba8e 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -32,9 +32,6 @@ def PrepDataSet(input_file,start=None,stop=None): # Correct the necessary variables for both datasets input_dataset = PrepDataSet_ESMF(input_dataset) - # Set dataset masks - # SetMask(input_dataset) - return(input_dataset) # Updating datasets to work with xESMF @@ -61,8 +58,6 @@ def ImportData(input_file): # to the LUH2 time units being undecodable by cftime module try: datasetout = xr.open_dataset(input_file) - print("Input file dataset opened: {}".format(input_file)) - return(datasetout) except ValueError as err: print("ValueError:", err) errmsg = "User direction: If error is due to units being 'years since ...' " \ @@ -70,7 +65,9 @@ def ImportData(input_file): "This can be done using the luh2.attribupdate function\n." print() print(errmsg) - + else: + print("Input file dataset opened: {}".format(input_file)) + return(datasetout) # Modify the luh2 metadata to enable xarray to read in data # This issue here is that the luh2 time units start prior to @@ -119,14 +116,14 @@ def AttribUpdateLUH2(input_file,output_append="modified"): # of 89.875). def BoundsVariableFixLUH2(input_dataset): - # Drop the old boundary names to avoid confusion - # outputdataset = input_dataset.drop(labels=['lat_bounds','lon_bounds']) - # Create lat and lon bounds as a single dimension array out of the LUH2 two dimensional_bounds array. # Future todo: is it possible to have xESMF recognize and use the original 2D array? input_dataset["lat_b"] = np.insert(input_dataset.lat_bounds[:,1].data,0,input_dataset.lat_bounds[0,0].data) input_dataset["lon_b"] = np.insert(input_dataset.lon_bounds[:,1].data,0,input_dataset.lon_bounds[0,0].data) + # Drop the old boundary names to avoid confusion + input_dataset = input_dataset.drop(labels=['lat_bounds','lon_bounds']) + print("LUH2 dataset lat/lon boundary variables formatted and added as new variable for xESMF") return(input_dataset) @@ -254,6 +251,28 @@ def GenerateRegridder(ds_to_regrid, ds_regrid_target,save=False): return(regridder) +# Temporary: Add minor correction factor to assure states sum to one +def CorrectStateSum(input_dataset): + + # Do this only for the state data set + if (not(any('irrig' in var for var in input_dataset) or + any('_to_' in var for var in input_dataset))): + + # Drop the secma and secmb variables temporarily + temp_dataset = input_dataset.drop({'secma','secmb'}) + + # Sum the remaining state variables and normalize + state_sum = temp_dataset.to_array().sum(dim='variable') + state_sum = state_sum.where(state_sum != 0) + temp_dataset = temp_dataset / state_sum + + # Update dataset with new scaled values + input_dataset.update(temp_dataset) + + # Save the correction value + input_dataset["stscf"] = 1.0 / state_sum + + return(input_dataset) # General functionality needed # - collect data for specific user-defined time period From 0b86cd217bb508f5bdb17df6d4e18e12e3a903eb Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 12 May 2023 21:24:37 -0700 Subject: [PATCH 693/852] Add handling of regridder argument option --- tools/luh2.py | 17 ++++++++++++++--- tools/luh2mod.py | 15 ++++++++------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/tools/luh2.py b/tools/luh2.py index 67a728dcd5..c2ba10fc03 100644 --- a/tools/luh2.py +++ b/tools/luh2.py @@ -15,6 +15,7 @@ def main(): # Allow variable input files (state and/or transitions and/or management) args = CommandLineArgs() + # Prep the LUH2 datasets and regrid target ds_luh2 = PrepDataSet(args.luh2_file,args.begin,args.end) @@ -35,9 +36,18 @@ def main(): # Mask the regrid target ds_regrid_target = SetMaskSurfData(ds_regrid_target) + # Handle regridder file save name + # TO DO: add check to handle if the user enters the full path + # TO DO: check if its possible to enter nothing with the argument + if (args.regridder_save_name == None): + regridder_save_file = None + print("Warning: Regridder will not be saved to file") + else: + output_filename = regridder_save_name + # Regrid the luh2 data to the target grid # TO DO: provide a check for the save argument based on the input arguments - regrid_luh2,regridder_luh2 = RegridConservative(ds_luh2, ds_regrid_target, save=True) + regrid_luh2,regridder_luh2 = RegridConservative(ds_luh2, ds_regrid_target, regridder_save_file) elif (args.regridder_target_file == None): regridder_luh2 = ImportData(args.regridder_file) @@ -52,6 +62,7 @@ def main(): # Adjust the luh2 data by the land fraction regrid_luh2 = regrid_luh2 / regrid_land_fraction.landfrac + # Correct the state sum (will be returned as if in not state values) regrid_luh2 = CorrectStateSum(regrid_luh2) # Add additional required variables for the host land model @@ -71,8 +82,8 @@ def main(): ds_luh2_merge = ImportData(args.luh2_merge_file) regrid_luh2 = regrid_luhs.merge(ds_luh2_merge) - # # Write the files - # # TO DO: add check to handle if the user enters the full path + # Write the files + # TO DO: add check to handle if the user enters the full path if (args.output == None): output_filename = 'LUH2_timeseries.nc' else: diff --git a/tools/luh2mod.py b/tools/luh2mod.py index 61304bba8e..bbd47b0f39 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -193,10 +193,10 @@ def CheckDataSet(input_dataset): return(dsflag,dstype) -def RegridConservative(ds_to_regrid,ds_regrid_target,save=False): +def RegridConservative(ds_to_regrid,ds_regrid_target,regridder_save_file): # define the regridder transformation - regridder = GenerateRegridder(ds_to_regrid, ds_regrid_target, save) + regridder = GenerateRegridder(ds_to_regrid, ds_regrid_target, regridder_save_file) # Loop through the variables to regrid ds_regrid = RegridLoop(ds_to_regrid, regridder) @@ -238,15 +238,16 @@ def RegridLoop(ds_to_regrid, regridder): return(ds_regrid) -def GenerateRegridder(ds_to_regrid, ds_regrid_target,save=False): +def GenerateRegridder(ds_to_regrid, ds_regrid_target,regridder_save_file): - print("\nDefining regridder") - regridder = xe.Regridder(ds_to_regrid, ds_regrid_target, "conservative") + regrid_method = "conservative" + print("\nDefining regridder, method: ", regrid_method) + regridder = xe.Regridder(ds_to_regrid, ds_regrid_target, regrid_method) # If save flag is set, write regridder to a file # TO DO: define a more useful name based on inputs - if(save): - filename = regridder.to_netcdf("regridder.nc") + if(not(isinstance(regridder_save_file,type(None)))): + filename = regridder.to_netcdf(regridder_save_file) print("regridder saved to file: ", filename) return(regridder) From 430bd037b50d315881b07fb203aa003cb2f89b08 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 12 May 2023 21:35:25 -0700 Subject: [PATCH 694/852] switch the importdata and prepdataset functions --- tools/luh2.py | 5 ++--- tools/luh2mod.py | 58 +++++++++++++++++++++++++----------------------- 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/tools/luh2.py b/tools/luh2.py index c2ba10fc03..b3a183514e 100644 --- a/tools/luh2.py +++ b/tools/luh2.py @@ -17,11 +17,11 @@ def main(): # Prep the LUH2 datasets and regrid target - ds_luh2 = PrepDataSet(args.luh2_file,args.begin,args.end) + ds_luh2 = ImportData(args.luh2_file,args.begin,args.end) if (args.regridder_file == None): - ds_regrid_target = PrepDataSet(args.regridder_target_file,args.begin,args.end) + ds_regrid_target = ImportData(args.regridder_target_file,args.begin,args.end) # Import the LUH2 static data to use for masking ds_luh2_static = ImportData(args.luh2_static_file) @@ -52,7 +52,6 @@ def main(): elif (args.regridder_target_file == None): regridder_luh2 = ImportData(args.regridder_file) # TO DO: check that the time bounds match the argument bounds - # TO DO: create bypass option to regridder function # # Regrid the inverted ice/water fraction data to the target grid #regridder_land_fraction = RegridConservative(ds_luh2_static, ds_regrid_target) diff --git a/tools/luh2mod.py b/tools/luh2mod.py index bbd47b0f39..8d9b210ae8 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -7,17 +7,37 @@ from nco import Nco from nco.custom import Atted -# Prepare the input_file to be used for regridding -def PrepDataSet(input_file,start=None,stop=None): +# Import luh2 or surface data sets +def ImportData(input_file,start=None,stop=None): + + # Open files + # Check to see if a ValueError is raised which is likely due + # to the LUH2 time units being undecodable by cftime module + try: + datasetout = xr.open_dataset(input_file) + except ValueError as err: + print("ValueError:", err) + errmsg = "User direction: If error is due to units being 'years since ...' " \ + "update the input data file to change to 'common_years since...'. " \ + "This can be done using the luh2.attribupdate function\n." + print() + print(errmsg) + else: + print("Input file dataset opened: {}".format(input_file)) + + datasetout = PrepDataset(datasetout,start,stop) + + return(datasetout) - # Import the data - input_dataset = ImportData(input_file) + +# Prepare the input_file to be used for regridding +def PrepDataset(input_dataset,start=None,stop=None): # Use the maximum span if start and stop are not present - if (start == None): + if (isinstance(start,type(None))): start = input_dataset.time[0] - if (stop == None): + if (isinstance(stop,type(None))): stop = input_dataset.time[-1] # Truncate the data to the user defined range @@ -30,44 +50,26 @@ def PrepDataSet(input_file,start=None,stop=None): print("Input must be a string\n") # Correct the necessary variables for both datasets - input_dataset = PrepDataSet_ESMF(input_dataset) + input_dataset = PrepDataset_ESMF(input_dataset) return(input_dataset) # Updating datasets to work with xESMF -def PrepDataSet_ESMF(input_dataset): +def PrepDataset_ESMF(input_dataset): # Check the dataset type dsflag, dstype = CheckDataSet(input_dataset) if (dsflag): if(dstype == "LUH2"): - print("PrepDataSet: LUH2") + print("PrepDataset: LUH2") input_dataset = BoundsVariableFixLUH2(input_dataset) elif(dstype == "Surface"): - print("PrepDataSet: SurfData") + print("PrepDataset: SurfData") input_dataset = DimensionFixSurfData(input_dataset) print("data set updated for xESMF\n") return(input_dataset) -# Import luh2 or surface data sets -def ImportData(input_file): - - # Open files - # Check to see if a ValueError is raised which is likely due - # to the LUH2 time units being undecodable by cftime module - try: - datasetout = xr.open_dataset(input_file) - except ValueError as err: - print("ValueError:", err) - errmsg = "User direction: If error is due to units being 'years since ...' " \ - "update the input data file to change to 'common_years since...'. " \ - "This can be done using the luh2.attribupdate function\n." - print() - print(errmsg) - else: - print("Input file dataset opened: {}".format(input_file)) - return(datasetout) # Modify the luh2 metadata to enable xarray to read in data # This issue here is that the luh2 time units start prior to From 3a31c2a1aef8d2c0c73a45789b5705295bf551a6 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 12 May 2023 21:57:55 -0700 Subject: [PATCH 695/852] Correct some issues --- tools/luh2.py | 7 +++---- tools/luh2mod.py | 7 +++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tools/luh2.py b/tools/luh2.py index b3a183514e..9037caabed 100644 --- a/tools/luh2.py +++ b/tools/luh2.py @@ -4,7 +4,7 @@ # Usage: python luh2.py -l -s import argparse, os -from luh2mod import PrepDataSet, ImportData, SetMaskLUH2, SetMaskSurfData +from luh2mod import ImportData, SetMaskLUH2, SetMaskSurfData from luh2mod import RegridConservative, CorrectStateSum # Add version checking here in case environment.yml not used @@ -71,15 +71,14 @@ def main(): regrid_luh2["LONGXY"] = ds_regrid_target["LONGXY"] # TO DO: double check if this is strictly necessary regrid_luh2["LATIXY"] = ds_regrid_target["LATIXY"] # TO DO: double check if this is strictly necessary - # Rename the dimensions for the output regrid_luh2 = regrid_luh2.rename_dims({'lat':'lsmlat','lon':'lsmlon'}) # Merge existing regrided luh2 file with merge input target # TO DO: check that the grid resolution and time bounds match - if (args.luh2_merge_file != None): + if (not(isinstance(args.luh2_merge_file,type(None)))): ds_luh2_merge = ImportData(args.luh2_merge_file) - regrid_luh2 = regrid_luhs.merge(ds_luh2_merge) + regrid_luh2 = regrid_luh2.merge(ds_luh2_merge) # Write the files # TO DO: add check to handle if the user enters the full path diff --git a/tools/luh2mod.py b/tools/luh2mod.py index 8d9b210ae8..98b44d17fe 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -257,7 +257,7 @@ def GenerateRegridder(ds_to_regrid, ds_regrid_target,regridder_save_file): # Temporary: Add minor correction factor to assure states sum to one def CorrectStateSum(input_dataset): - # Do this only for the state data set + # Only calculate the state sum to unity correction for the appropiate dataset if (not(any('irrig' in var for var in input_dataset) or any('_to_' in var for var in input_dataset))): @@ -275,7 +275,10 @@ def CorrectStateSum(input_dataset): # Save the correction value input_dataset["stscf"] = 1.0 / state_sum - return(input_dataset) + # If this is the transitions data apply the state correction to the transitions + # elif (any('_to_' in var for var in input_dataset)): + + return(input_dataset) # General functionality needed # - collect data for specific user-defined time period From 9af66f0d965adf53c1bb069d7c0646bad83493cc Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 12 May 2023 22:09:16 -0700 Subject: [PATCH 696/852] adding type checks --- tools/luh2mod.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/luh2mod.py b/tools/luh2mod.py index 98b44d17fe..a19734fb77 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -45,9 +45,11 @@ def PrepDataset(input_dataset,start=None,stop=None): # the start/stop is out of range try: input_dataset = input_dataset.sel(time=slice(start,stop)) - except TypeError as err: - print("TypeError:", err) + except TypeError as type_err: print("Input must be a string\n") + raise TypeError(type_err) + except AttributeError: + pass # likely due to input_dataset not having time for surface dataset # Correct the necessary variables for both datasets input_dataset = PrepDataset_ESMF(input_dataset) From 23dabb778bc830caee35cded8f559477a3fcf6ff Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 12 May 2023 22:22:16 -0700 Subject: [PATCH 697/852] adding check against the time variable for the input dataset --- tools/luh2mod.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/tools/luh2mod.py b/tools/luh2mod.py index a19734fb77..f5abe77ef8 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -34,11 +34,13 @@ def ImportData(input_file,start=None,stop=None): def PrepDataset(input_dataset,start=None,stop=None): # Use the maximum span if start and stop are not present - if (isinstance(start,type(None))): - start = input_dataset.time[0] + dsflag, dstype = CheckDataset(input_dataset) + if(dstype != "static"): + if (isinstance(start,type(None))): + start = input_dataset.time[0] - if (isinstance(stop,type(None))): - stop = input_dataset.time[-1] + if (isinstance(stop,type(None))): + stop = input_dataset.time[-1] # Truncate the data to the user defined range # This might need some more error handling for when @@ -48,8 +50,6 @@ def PrepDataset(input_dataset,start=None,stop=None): except TypeError as type_err: print("Input must be a string\n") raise TypeError(type_err) - except AttributeError: - pass # likely due to input_dataset not having time for surface dataset # Correct the necessary variables for both datasets input_dataset = PrepDataset_ESMF(input_dataset) @@ -60,7 +60,7 @@ def PrepDataset(input_dataset,start=None,stop=None): def PrepDataset_ESMF(input_dataset): # Check the dataset type - dsflag, dstype = CheckDataSet(input_dataset) + dsflag, dstype = CheckDataset(input_dataset) if (dsflag): if(dstype == "LUH2"): print("PrepDataset: LUH2") @@ -154,7 +154,7 @@ def DimensionFixSurfData(input_dataset): # # check what sort of inputdata is being provided; surface dataset or luh2 # # LUH2 data will need to be masked based on the variable input to mask -# dsflag,dstype = CheckDataSet(input_dataset) +# dsflag,dstype = CheckDataset(input_dataset) # if (dsflag): # if(dstype == "LUH2"): # SetMaskLUH2(input_dataset) # temporary @@ -180,17 +180,21 @@ def SetMaskSurfData(input_dataset): return(input_dataset) # Check which dataset we're working with -def CheckDataSet(input_dataset): +def CheckDataset(input_dataset): dsflag = False - if('primf' in list(input_dataset.variables)): + dsvars = list(input_dataset.variables) + if('primf' in dsvars): dstype = 'LUH2' dsflag = True print("LUH2") - elif('natpft' in list(input_dataset.variables)): + elif('natpft' in dsvars): dstype = 'Surface' dsflag = True print("Surface") + elif('icwtr' in dsvars): + dstype = 'static' + dsflag = True else: dstype = 'Unknown' print("Unrecognize data set") From 61306a09396ccdd6c2f73af56e5dd4310da42d27 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 12 May 2023 22:25:44 -0700 Subject: [PATCH 698/852] fix import function --- tools/luh2mod.py | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/tools/luh2mod.py b/tools/luh2mod.py index f5abe77ef8..780a28a496 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -42,25 +42,23 @@ def PrepDataset(input_dataset,start=None,stop=None): if (isinstance(stop,type(None))): stop = input_dataset.time[-1] - # Truncate the data to the user defined range - # This might need some more error handling for when - # the start/stop is out of range - try: - input_dataset = input_dataset.sel(time=slice(start,stop)) - except TypeError as type_err: - print("Input must be a string\n") - raise TypeError(type_err) - - # Correct the necessary variables for both datasets - input_dataset = PrepDataset_ESMF(input_dataset) + # Truncate the data to the user defined range + # This might need some more error handling for when + # the start/stop is out of range + try: + input_dataset = input_dataset.sel(time=slice(start,stop)) + except TypeError as type_err: + print("Input must be a string\n") + raise TypeError(type_err) + + # Correct the necessary variables for both datasets + input_dataset = PrepDataset_ESMF(input_dataset,dsflag,dstype) return(input_dataset) # Updating datasets to work with xESMF -def PrepDataset_ESMF(input_dataset): +def PrepDataset_ESMF(input_dataset,dsflag,dstype): - # Check the dataset type - dsflag, dstype = CheckDataset(input_dataset) if (dsflag): if(dstype == "LUH2"): print("PrepDataset: LUH2") From 4e830a85d0f8fca20e990a90f1b9c25509f00a6f Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 12 May 2023 22:29:36 -0700 Subject: [PATCH 699/852] fix argument call --- tools/luh2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/luh2.py b/tools/luh2.py index 9037caabed..4565870ea1 100644 --- a/tools/luh2.py +++ b/tools/luh2.py @@ -43,7 +43,7 @@ def main(): regridder_save_file = None print("Warning: Regridder will not be saved to file") else: - output_filename = regridder_save_name + output_filename = args.regridder_save_name # Regrid the luh2 data to the target grid # TO DO: provide a check for the save argument based on the input arguments From e4b43ac1922a53f4a777894969af67e4b7b36db0 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 12 May 2023 22:58:44 -0700 Subject: [PATCH 700/852] update check function outputs --- tools/luh2.py | 5 +++-- tools/luh2mod.py | 9 +++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/tools/luh2.py b/tools/luh2.py index 4565870ea1..53c65bf875 100644 --- a/tools/luh2.py +++ b/tools/luh2.py @@ -5,7 +5,7 @@ import argparse, os from luh2mod import ImportData, SetMaskLUH2, SetMaskSurfData -from luh2mod import RegridConservative, CorrectStateSum +from luh2mod import RegridConservative, RegridLoop, CorrectStateSum # Add version checking here in case environment.yml not used def main(): @@ -43,7 +43,7 @@ def main(): regridder_save_file = None print("Warning: Regridder will not be saved to file") else: - output_filename = args.regridder_save_name + regridder_save_file = args.regridder_save_name # Regrid the luh2 data to the target grid # TO DO: provide a check for the save argument based on the input arguments @@ -51,6 +51,7 @@ def main(): elif (args.regridder_target_file == None): regridder_luh2 = ImportData(args.regridder_file) + regrid_luh2 = RegridLoop(ds_luh2,regridder_luh2) # TO DO: check that the time bounds match the argument bounds # # Regrid the inverted ice/water fraction data to the target grid diff --git a/tools/luh2mod.py b/tools/luh2mod.py index 780a28a496..aab8aba228 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -35,7 +35,8 @@ def PrepDataset(input_dataset,start=None,stop=None): # Use the maximum span if start and stop are not present dsflag, dstype = CheckDataset(input_dataset) - if(dstype != "static"): + + if(not(dstype in ('static','regrid'))): if (isinstance(start,type(None))): start = input_dataset.time[0] @@ -182,7 +183,7 @@ def CheckDataset(input_dataset): dsflag = False dsvars = list(input_dataset.variables) - if('primf' in dsvars): + if('primf' in dsvars or 'primf_to_secdn' in dsvars or 'irrig' in dsvars): dstype = 'LUH2' dsflag = True print("LUH2") @@ -193,6 +194,9 @@ def CheckDataset(input_dataset): elif('icwtr' in dsvars): dstype = 'static' dsflag = True + elif('col' in dsvars): + dstype = 'regrid' + dsflag = True else: dstype = 'Unknown' print("Unrecognize data set") @@ -262,6 +266,7 @@ def GenerateRegridder(ds_to_regrid, ds_regrid_target,regridder_save_file): def CorrectStateSum(input_dataset): # Only calculate the state sum to unity correction for the appropiate dataset + # TO DO: Update this to use the check function if (not(any('irrig' in var for var in input_dataset) or any('_to_' in var for var in input_dataset))): From 5916d15bbc25e610a0ba7a1253cb5a1cc2179e14 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Mon, 15 May 2023 10:30:04 -0600 Subject: [PATCH 701/852] get rid of temporary cohort allocation --- biogeochem/EDCohortDynamicsMod.F90 | 36 +- biogeochem/EDPhysiologyMod.F90 | 560 +++++++++++++---------------- biogeochem/FatesCohortMod.F90 | 5 +- main/EDInitMod.F90 | 426 ++++++++++------------ 4 files changed, 474 insertions(+), 553 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index cad2a5ee26..069b0147c9 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -191,7 +191,7 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & ! !LOCAL VARIABLES: -type(fates_cohort_type), pointer :: new_cohort ! Pointer to New Cohort structure. +type(fates_cohort_type), pointer :: newCohort ! Pointer to New Cohort structure. type(fates_cohort_type), pointer :: storesmallcohort type(fates_cohort_type), pointer :: storebigcohort real(r8) :: rmean_temp ! running mean temperature @@ -201,8 +201,8 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & !---------------------------------------------------------------------- ! create new cohort -allocate(new_cohort) -call new_cohort%Create(prt, pft, nn, hite, coage, dbh, status, ctrim, carea, & +allocate(newCohort) +call newCohort%Create(prt, pft, nn, hite, coage, dbh, status, ctrim, carea, & clayer, crowndamage, spread, patchptr%canopy_layer_tlai) ! Put cohort at the right place in the linked list @@ -213,53 +213,53 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & tnull = 0 else tnull = 1 - patchptr%tallest => new_cohort + patchptr%tallest => newCohort endif if (associated(patchptr%shortest)) then snull = 0 else snull = 1 - patchptr%shortest => new_cohort + patchptr%shortest => newCohort endif ! Allocate running mean functions ! (Keeping as an example) -!! allocate(new_cohort%tveg_lpa) -!! call new_cohort%tveg_lpa%InitRMean(ema_lpa,init_value=patchptr%tveg_lpa%GetMean()) +!! allocate(newCohort%tveg_lpa) +!! call newCohort%tveg_lpa%InitRMean(ema_lpa,init_value=patchptr%tveg_lpa%GetMean()) if( hlm_use_planthydro.eq.itrue ) then nlevrhiz = currentSite%si_hydr%nlevrhiz ! This allocates array spaces - call InitHydrCohort(currentSite,new_cohort) + call InitHydrCohort(currentSite, newCohort) ! zero out the water balance error - new_cohort%co_hydr%errh2o = 0._r8 + newCohort%co_hydr%errh2o = 0._r8 ! This calculates node heights - call UpdatePlantHydrNodes(new_cohort,new_cohort%pft, & - new_cohort%hite,currentSite%si_hydr) + call UpdatePlantHydrNodes(newCohort, newCohort%pft, & + newCohort%hite,currentSite%si_hydr) ! This calculates volumes and lengths - call UpdatePlantHydrLenVol(new_cohort,currentSite%si_hydr) + call UpdatePlantHydrLenVol(newCohort,currentSite%si_hydr) ! This updates the Kmax's of the plant's compartments - call UpdatePlantKmax(new_cohort%co_hydr,new_cohort,currentSite%si_hydr) + call UpdatePlantKmax(newCohort%co_hydr,newCohort,currentSite%si_hydr) ! Since this is a newly initialized plant, we set the previous compartment-size ! equal to the ones we just calculated. - call SavePreviousCompartmentVolumes(new_cohort%co_hydr) + call SavePreviousCompartmentVolumes(newCohort%co_hydr) ! This comes up with starter suctions and then water contents ! based on the soil values - call InitPlantHydStates(currentSite,new_cohort) + call InitPlantHydStates(currentSite,newCohort) if(recruitstatus==1)then - new_cohort%co_hydr%is_newly_recruited = .true. + newCohort%co_hydr%is_newly_recruited = .true. ! If plant hydraulics is active, we must constrain the ! number density of the new recruits based on the moisture @@ -267,14 +267,14 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & ! So we go through the process of pre-initializing the hydraulic ! states in the temporary cohort, to calculate this new number density rmean_temp = patchptr%tveg24%GetMean() - call ConstrainRecruitNumber(currentSite, new_cohort, patchptr, & + call ConstrainRecruitNumber(currentSite, newCohort, patchptr, & bc_in, rmean_temp) endif endif -call insert_cohort(patchptr, new_cohort, patchptr%tallest, patchptr%shortest, tnull, snull, & +call insert_cohort(patchptr, newCohort, patchptr%tallest, patchptr%shortest, tnull, snull, & storebigcohort, storesmallcohort) patchptr%tallest => storebigcohort diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index b0961d2e81..25d6a35ae9 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -21,6 +21,7 @@ module EDPhysiologyMod use FatesInterfaceTypesMod, only : hlm_nitrogen_spec use FatesInterfaceTypesMod, only : hlm_phosphorus_spec use FatesInterfaceTypesMod, only : hlm_use_tree_damage + use FatesInterfaceTypesMod, only : hlm_use_ed_prescribed_phys use FatesConstantsMod, only : r8 => fates_r8 use FatesConstantsMod, only : nearzero use FatesConstantsMod, only : nocomp_bareground @@ -1970,334 +1971,283 @@ end subroutine SeedGermination ! ===================================================================================== - - - - ! ===================================================================================== - subroutine recruitment( currentSite, currentPatch, bc_in ) ! ! !DESCRIPTION: ! spawn new cohorts of juveniles of each PFT ! - ! !USES: - use FatesInterfaceTypesMod, only : hlm_use_ed_prescribed_phys - use FatesLitterMod , only : ncwd - ! ! !ARGUMENTS - type(ed_site_type), intent(inout) :: currentSite - type(fates_patch_type), intent(inout),pointer :: currentPatch - type(bc_in_type), intent(in) :: bc_in - ! + type(ed_site_type), intent(inout) :: currentSite + type(fates_patch_type), intent(inout), pointer :: currentPatch + type(bc_in_type), intent(in) :: bc_in + ! !LOCAL VARIABLES: - class(prt_vartypes), pointer :: prt - integer :: ft - integer :: c - type (fates_cohort_type) , pointer :: temp_cohort - type (litter_type), pointer :: litt ! The litter object (carbon right now) - type(site_massbal_type), pointer :: site_mass ! For accounting total in-out mass fluxes - integer :: cohortstatus - integer :: el ! loop counter for element - integer :: element_id ! element index consistent with definitions in PRTGenericMod - integer :: iage ! age loop counter for leaf age bins - integer :: crowndamage - integer,parameter :: recruitstatus = 1 !weather it the new created cohorts is recruited or initialized - real(r8) :: c_leaf ! target leaf biomass [kgC] - real(r8) :: c_fnrt ! target fine root biomass [kgC] - real(r8) :: c_sapw ! target sapwood biomass [kgC] - real(r8) :: a_sapw ! target sapwood cross section are [m2] (dummy) - real(r8) :: c_agw ! target Above ground biomass [kgC] - real(r8) :: c_bgw ! target Below ground biomass [kgC] - real(r8) :: c_struct ! target Structural biomass [kgc] - real(r8) :: c_store ! target Storage biomass [kgC] - real(r8) :: m_leaf ! leaf mass (element agnostic) [kg] - real(r8) :: m_fnrt ! fine-root mass (element agnostic) [kg] - real(r8) :: m_sapw ! sapwood mass (element agnostic) [kg] - real(r8) :: m_agw ! AG wood mass (element agnostic) [kg] - real(r8) :: m_bgw ! BG wood mass (element agnostic) [kg] - real(r8) :: m_struct ! structural mass (element agnostic) [kg] - real(r8) :: m_store ! storage mass (element agnostic) [kg] - real(r8) :: m_repro ! reproductive mass (element agnostic) [kg] - real(r8) :: mass_avail ! The mass of each nutrient/carbon available in the seed_germination pool [kg] - real(r8) :: mass_demand ! Total mass demanded by the plant to achieve the stoichiometric targets - ! of all the organs in the recruits. Used for both [kg per plant] and [kg per cohort] - real(r8) :: stem_drop_fraction - - !---------------------------------------------------------------------- - - allocate(temp_cohort) ! create temporary cohort - call temp_cohort%ZeroValues() - - - do ft = 1,numpft - - ! The following if block is for the prescribed biogeography and/or nocomp modes. - ! Since currentSite%use_this_pft is a site-level quantity and thus only limits whether a given PFT - ! is permitted on a given gridcell or not, it applies to the prescribed biogeography case only. - ! If nocomp is enabled, then we must determine whether a given PFT is allowed on a given patch or not. - - if(currentSite%use_this_pft(ft).eq.itrue & - .and. ((hlm_use_nocomp .eq. ifalse) .or. (ft .eq. currentPatch%nocomp_pft_label)))then - - temp_cohort%canopy_trim = init_recruit_trim - temp_cohort%pft = ft - temp_cohort%hite = EDPftvarcon_inst%hgt_min(ft) - temp_cohort%coage = 0.0_r8 - stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(ft) - temp_cohort%l2fr = currentSite%rec_l2fr(ft,currentPatch%NCL_p) - temp_cohort%crowndamage = 1 ! new recruits are undamaged - - call h2d_allom(temp_cohort%hite,ft,temp_cohort%dbh) - - - ! Initialize live pools - call bleaf(temp_cohort%dbh,ft,temp_cohort%crowndamage,& - temp_cohort%canopy_trim,c_leaf) - call bfineroot(temp_cohort%dbh,ft,temp_cohort%canopy_trim,temp_cohort%l2fr,c_fnrt) - call bsap_allom(temp_cohort%dbh,ft,temp_cohort%crowndamage, & - temp_cohort%canopy_trim,a_sapw, c_sapw) - call bagw_allom(temp_cohort%dbh,ft,temp_cohort%crowndamage, c_agw) - call bbgw_allom(temp_cohort%dbh,ft,c_bgw) - call bdead_allom(c_agw,c_bgw,c_sapw,ft,c_struct) - call bstore_allom(temp_cohort%dbh,ft, temp_cohort%crowndamage, & - temp_cohort%canopy_trim,c_store) - - ! Default assumption is that leaves are on - cohortstatus = leaves_on - - ! But if the plant is seasonally (cold) deciduous, and the site status is flagged - ! as "cold", then set the cohort's status to leaves_off, and remember the leaf biomass - if ((prt_params%season_decid(ft) == itrue) .and. & - (any(currentSite%cstatus == [phen_cstat_nevercold,phen_cstat_iscold]))) then - c_leaf = 0.0_r8 - - ! If plant is not woody then set sapwood and structural biomass as well - if (prt_params%woody(ft).ne.itrue) then - c_sapw = (1.0_r8 - stem_drop_fraction) * c_sapw - c_struct = (1.0_r8 - stem_drop_fraction) * c_struct - endif - cohortstatus = leaves_off + class(prt_vartypes), pointer :: prt ! PARTEH object + type(litter_type), pointer :: litt ! litter object (carbon right now) + type(site_massbal_type), pointer :: site_mass ! for accounting total in-out mass fluxes + integer :: ft ! loop counter for PFTs + integer :: leaf_status ! cohort phenology status [leaves on/off] + integer :: el ! loop counter for element + integer :: element_id ! element index consistent with definitions in PRTGenericMod + integer :: iage ! age loop counter for leaf age bins + integer :: crowndamage ! crown damage class of the cohort [1 = undamaged, >1 = damaged] + real(r8) :: hite ! new cohort height [m] + real(r8) :: dbh ! new cohort DBH [cm] + real(r8) :: cohort_n ! new cohort density + real(r8) :: l2fr ! leaf to fineroot biomass ratio [0-1] + real(r8) :: c_leaf ! target leaf biomass [kgC] + real(r8) :: c_fnrt ! target fine root biomass [kgC] + real(r8) :: c_sapw ! target sapwood biomass [kgC] + real(r8) :: a_sapw ! target sapwood cross section are [m2] (dummy) + real(r8) :: c_agw ! target Above ground biomass [kgC] + real(r8) :: c_bgw ! target Below ground biomass [kgC] + real(r8) :: c_struct ! target Structural biomass [kgc] + real(r8) :: c_store ! target Storage biomass [kgC] + real(r8) :: m_leaf ! leaf mass (element agnostic) [kg] + real(r8) :: m_fnrt ! fine-root mass (element agnostic) [kg] + real(r8) :: m_sapw ! sapwood mass (element agnostic) [kg] + real(r8) :: m_agw ! AG wood mass (element agnostic) [kg] + real(r8) :: m_bgw ! BG wood mass (element agnostic) [kg] + real(r8) :: m_struct ! structural mass (element agnostic) [kg] + real(r8) :: m_store ! storage mass (element agnostic) [kg] + real(r8) :: m_repro ! reproductive mass (element agnostic) [kg] + real(r8) :: mass_avail ! mass of each nutrient/carbon available in the seed_germination pool [kg] + real(r8) :: mass_demand ! total mass demanded by the plant to achieve the stoichiometric targets + real(r8) :: stem_drop_fraction ! of all the organs in the recruits. Used for both [kg per plant] and [kg per cohort] + integer, parameter :: recruitstatus = 1 ! whether the newly created cohorts are recruited or initialized + + !--------------------------------------------------------------------------- + + do ft = 1, numpft + + ! The following if block is for the prescribed biogeography and/or nocomp modes. + ! Since currentSite%use_this_pft is a site-level quantity and thus only limits whether a given PFT + ! is permitted on a given gridcell or not, it applies to the prescribed biogeography case only. + ! If nocomp is enabled, then we must determine whether a given PFT is allowed on a given patch or not. + + if (currentSite%use_this_pft(ft) .eq. itrue .and. & + ((hlm_use_nocomp .eq. ifalse) .or. (ft .eq. currentPatch%nocomp_pft_label))) then + + hite = EDPftvarcon_inst%hgt_min(ft) + stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(ft) + l2fr = currentSite%rec_l2fr(ft, currentPatch%NCL_p) + crowndamage = 1 ! new recruits are undamaged + + ! calculate DBH from initial height + call h2d_allom(hite, ft, dbh) + + ! calculate live pools + call bleaf(dbh, ft, crowndamage, init_recruit_trim, c_leaf) + call bfineroot(dbh, ft, init_recruit_trim, l2fr, c_fnrt) + call bsap_allom(dbh, ft, crowndamage, init_recruit_trim, a_sapw, c_sapw) + call bagw_allom(dbh, ft, crowndamage, c_agw) + call bbgw_allom(dbh, ft, c_bgw) + call bdead_allom(c_agw, c_bgw, c_sapw, ft, c_struct) + call bstore_allom(dbh, ft, crowndamage, init_recruit_trim, c_store) + + ! default assumption is that leaves are on + leaf_status = leaves_on + + ! if the plant is seasonally (cold) deciduous, and the site status is flagged + ! as "cold", then set the cohort's status to leaves_off, and remember the leaf biomass + if ((prt_params%season_decid(ft) == itrue) .and. & + (any(currentSite%cstatus == [phen_cstat_nevercold, phen_cstat_iscold]))) then + leaf_status = leaves_off + c_leaf = 0.0_r8 + + ! if plant is not woody then set sapwood and structural biomass to 0.0 as well + if (prt_params%woody(ft) .ne. itrue) then + c_sapw = (1.0_r8 - stem_drop_fraction)*c_sapw + c_struct = (1.0_r8 - stem_drop_fraction)*c_struct endif - - ! Or.. if the plant is drought deciduous, and the site status is flagged as - ! "in a drought", then likewise, set the cohort's status to leaves_off, and remember leaf - ! biomass - if ((prt_params%stress_decid(ft) == itrue) .and. & - (any(currentSite%dstatus == [phen_dstat_timeoff,phen_dstat_moistoff]))) then - c_leaf = 0.0_r8 - - ! If plant is not woody then set sapwood and structural biomass as well - if(prt_params%woody(ft).ne.itrue)then - c_sapw = (1.0_r8 - stem_drop_fraction) * c_sapw - c_struct = (1.0_r8 - stem_drop_fraction) * c_struct - endif - cohortstatus = leaves_off - endif - - - ! Cycle through available carbon and nutrients, find the limiting element - ! to dictate the total number of plants that can be generated - - if ( (hlm_use_ed_prescribed_phys .eq. ifalse) .or. & - (EDPftvarcon_inst%prescribed_recruitment(ft) .lt. 0._r8) ) then - - temp_cohort%n = 1.e20_r8 - - do el = 1,num_elements - - element_id = element_list(el) - select case(element_id) - case(carbon12_element) - - mass_demand = c_struct+c_leaf+c_fnrt+c_sapw+c_store - - case(nitrogen_element) - - mass_demand = & - c_struct*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(struct_organ)) + & - c_leaf*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)) + & - c_fnrt*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)) + & - c_sapw*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) + & - StorageNutrientTarget(ft, element_id, & - c_leaf*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)), & - c_fnrt*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)), & - c_sapw*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)), & - c_struct*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(struct_organ))) - - case(phosphorus_element) - - mass_demand = & - c_struct*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(struct_organ)) + & - c_leaf*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)) + & - c_fnrt*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)) + & - c_sapw*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) + & - StorageNutrientTarget(ft, element_id, & - c_leaf*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)), & - c_fnrt*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)), & - c_sapw*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)), & - c_struct*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(struct_organ))) - - case default - write(fates_log(),*) 'Undefined element type in recruitment' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end select - - mass_avail = currentPatch%area * currentPatch%litter(el)%seed_germ(ft) - - ! ------------------------------------------------------------------------ - ! Update number density if this is the limiting mass - ! ------------------------------------------------------------------------ - - temp_cohort%n = min(temp_cohort%n, mass_avail/mass_demand) - - end do - - - else - ! prescribed recruitment rates. number per sq. meter per year - temp_cohort%n = currentPatch%area * & - EDPftvarcon_inst%prescribed_recruitment(ft) * & - hlm_freq_day + endif + + ! if the plant is drought deciduous, and the site status is flagged as + ! "in a drought", then likewise, set the cohort's status to leaves_off, and remember leaf + ! biomass + if ((prt_params%stress_decid(ft) == itrue) .and. & + (any(currentSite%dstatus == [phen_dstat_timeoff, phen_dstat_moistoff]))) then + leaf_status = leaves_off + c_leaf = 0.0_r8 + + ! ff plant is not woody then set sapwood and structural biomass as well + if(prt_params%woody(ft) .ne. itrue)then + c_sapw = (1.0_r8 - stem_drop_fraction)*c_sapw + c_struct = (1.0_r8 - stem_drop_fraction)*c_struct endif + endif + + ! cycle through available carbon and nutrients, find the limiting element + ! to dictate the total number of plants that can be generated + if ((hlm_use_ed_prescribed_phys .eq. ifalse) .or. & + (EDPftvarcon_inst%prescribed_recruitment(ft) .lt. 0._r8) ) then + + cohort_n = 1.e20_r8 + + do el = 1, num_elements + element_id = element_list(el) + select case(element_id) + case(carbon12_element) + + mass_demand = c_struct + c_leaf + c_fnrt + c_sapw + c_store + + case(nitrogen_element) + + mass_demand = & + c_struct*prt_params%nitr_stoich_p1(ft, prt_params%organ_param_id(struct_organ)) + & + c_leaf*prt_params%nitr_stoich_p1(ft, prt_params%organ_param_id(leaf_organ)) + & + c_fnrt*prt_params%nitr_stoich_p1(ft, prt_params%organ_param_id(fnrt_organ)) + & + c_sapw*prt_params%nitr_stoich_p1(ft, prt_params%organ_param_id(sapw_organ)) + & + StorageNutrientTarget(ft, element_id, & + c_leaf*prt_params%nitr_stoich_p1(ft, prt_params%organ_param_id(leaf_organ)), & + c_fnrt*prt_params%nitr_stoich_p1(ft, prt_params%organ_param_id(fnrt_organ)), & + c_sapw*prt_params%nitr_stoich_p1(ft, prt_params%organ_param_id(sapw_organ)), & + c_struct*prt_params%nitr_stoich_p1(ft, prt_params%organ_param_id(struct_organ))) + + case(phosphorus_element) + + mass_demand = & + c_struct*prt_params%phos_stoich_p1(ft, prt_params%organ_param_id(struct_organ)) + & + c_leaf*prt_params%phos_stoich_p1(ft, prt_params%organ_param_id(leaf_organ)) + & + c_fnrt*prt_params%phos_stoich_p1(ft, prt_params%organ_param_id(fnrt_organ)) + & + c_sapw*prt_params%phos_stoich_p1(ft, prt_params%organ_param_id(sapw_organ)) + & + StorageNutrientTarget(ft, element_id, & + c_leaf*prt_params%phos_stoich_p1(ft, prt_params%organ_param_id(leaf_organ)), & + c_fnrt*prt_params%phos_stoich_p1(ft, prt_params%organ_param_id(fnrt_organ)), & + c_sapw*prt_params%phos_stoich_p1(ft, prt_params%organ_param_id(sapw_organ)), & + c_struct*prt_params%phos_stoich_p1(ft, prt_params%organ_param_id(struct_organ))) + + case default + write(fates_log(),*) 'Undefined element type in recruitment' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select + + mass_avail = currentPatch%area*currentPatch%litter(el)%seed_germ(ft) + + ! update number density if this is the limiting mass + cohort_n = min(cohort_n, mass_avail/mass_demand) - ! Only bother allocating a new cohort if there is a reasonable amount of it - any_recruits: if (temp_cohort%n > min_n_safemath )then - - ! ----------------------------------------------------------------------------- - ! PART II. - ! Initialize the PARTEH object, and determine the initial masses of all - ! organs and elements. - ! ----------------------------------------------------------------------------- - prt => null() - call InitPRTObject(prt) - - do el = 1,num_elements - - element_id = element_list(el) - - ! If this is carbon12, then the initialization is straight forward - ! otherwise, we use stoichiometric ratios - select case(element_id) - case(carbon12_element) - - m_struct = c_struct - m_leaf = c_leaf - m_fnrt = c_fnrt - m_sapw = c_sapw - m_store = c_store - m_repro = 0._r8 - - case(nitrogen_element) - - m_struct = c_struct*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(struct_organ)) - m_leaf = c_leaf*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)) - m_fnrt = c_fnrt*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)) - m_sapw = c_sapw*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) - m_store = StorageNutrientTarget(ft, element_id, m_leaf, m_fnrt, m_sapw, m_struct ) - m_repro = 0._r8 - - case(phosphorus_element) - - m_struct = c_struct*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(struct_organ)) - m_leaf = c_leaf*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)) - m_fnrt = c_fnrt*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)) - m_sapw = c_sapw*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) - m_store = StorageNutrientTarget(ft, element_id, m_leaf, m_fnrt, m_sapw, m_struct ) - m_repro = 0._r8 - - end select - - select case(hlm_parteh_mode) - case (prt_carbon_allom_hyp,prt_cnp_flex_allom_hyp ) - - ! Put all of the leaf mass into the first bin - call SetState(prt,leaf_organ, element_id,m_leaf,1) - do iage = 2,nleafage - call SetState(prt,leaf_organ, element_id,0._r8,iage) - end do - - call SetState(prt,fnrt_organ, element_id, m_fnrt) - call SetState(prt,sapw_organ, element_id, m_sapw) - call SetState(prt,store_organ, element_id, m_store) - call SetState(prt,struct_organ, element_id, m_struct) - call SetState(prt,repro_organ, element_id, m_repro) - - case default - write(fates_log(),*) 'Unspecified PARTEH module during create_cohort' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end select - - site_mass => currentSite%mass_balance(el) - - ! Remove mass from the germination pool. However, if we are use prescribed physiology, - ! AND the forced recruitment model, then we are not realling using the prognostic - ! seed_germination model, so we have to short circuit things. We send all of the - ! seed germination mass to an outflux pool, and use an arbitrary generic input flux - ! to balance out the new recruits. - - if ( (hlm_use_ed_prescribed_phys .eq. itrue ) .and. & - (EDPftvarcon_inst%prescribed_recruitment(ft) .ge. 0._r8 )) then - - site_mass%flux_generic_in = site_mass%flux_generic_in + & - temp_cohort%n*(m_struct + m_leaf + m_fnrt + m_sapw + m_store + m_repro) - - site_mass%flux_generic_out = site_mass%flux_generic_out + & - currentPatch%area * currentPatch%litter(el)%seed_germ(ft) - - currentPatch%litter(el)%seed_germ(ft) = 0._r8 - - - else - - currentPatch%litter(el)%seed_germ(ft) = currentPatch%litter(el)%seed_germ(ft) - & - temp_cohort%n / currentPatch%area * & - (m_struct + m_leaf + m_fnrt + m_sapw + m_store + m_repro) - - end if - - - - end do + end do - ! This call cycles through the initial conditions, and makes sure that they - ! are all initialized. - ! ----------------------------------------------------------------------------------- + else + ! prescribed recruitment rates. number per sq. meter per year + cohort_n = currentPatch%area * EDPftvarcon_inst%prescribed_recruitment(ft) * & + hlm_freq_day + endif - call prt%CheckInitialConditions() + ! Only bother allocating a new cohort if there is a reasonable amount of it + any_recruits: if (cohort_n > min_n_safemath) then - ! This initializes the cohort + ! -------------------------------------------------------------------------------- + ! PART II. + ! Initialize the PARTEH object, and determine the initial masses of all + ! organs and elements. + ! -------------------------------------------------------------------------------- + + prt => null() + call InitPRTObject(prt) + + do el = 1,num_elements + + element_id = element_list(el) + + ! If this is carbon12, then the initialization is straight forward + ! otherwise, we use stoichiometric ratios + select case(element_id) + case(carbon12_element) + + m_struct = c_struct + m_leaf = c_leaf + m_fnrt = c_fnrt + m_sapw = c_sapw + m_store = c_store + m_repro = 0._r8 + + case(nitrogen_element) + + m_struct = c_struct*prt_params%nitr_stoich_p1(ft, prt_params%organ_param_id(struct_organ)) + m_leaf = c_leaf*prt_params%nitr_stoich_p1(ft, prt_params%organ_param_id(leaf_organ)) + m_fnrt = c_fnrt*prt_params%nitr_stoich_p1(ft, prt_params%organ_param_id(fnrt_organ)) + m_sapw = c_sapw*prt_params%nitr_stoich_p1(ft, prt_params%organ_param_id(sapw_organ)) + m_store = StorageNutrientTarget(ft, element_id, m_leaf, m_fnrt, m_sapw, m_struct) + m_repro = 0._r8 + + case(phosphorus_element) + + m_struct = c_struct*prt_params%phos_stoich_p1(ft, prt_params%organ_param_id(struct_organ)) + m_leaf = c_leaf*prt_params%phos_stoich_p1(ft, prt_params%organ_param_id(leaf_organ)) + m_fnrt = c_fnrt*prt_params%phos_stoich_p1(ft, prt_params%organ_param_id(fnrt_organ)) + m_sapw = c_sapw*prt_params%phos_stoich_p1(ft, prt_params%organ_param_id(sapw_organ)) + m_store = StorageNutrientTarget(ft, element_id, m_leaf, m_fnrt, m_sapw, m_struct) + m_repro = 0._r8 + + end select + + select case(hlm_parteh_mode) + case (prt_carbon_allom_hyp, prt_cnp_flex_allom_hyp) + + ! put all of the leaf mass into the first bin + call SetState(prt, leaf_organ, element_id, m_leaf, 1) + do iage = 2, nleafage + call SetState(prt,leaf_organ, element_id, 0._r8, iage) + end do + + call SetState(prt, fnrt_organ, element_id, m_fnrt) + call SetState(prt, sapw_organ, element_id, m_sapw) + call SetState(prt, store_organ, element_id, m_store) + call SetState(prt, struct_organ, element_id, m_struct) + call SetState(prt, repro_organ, element_id, m_repro) + + case default + write(fates_log(),*) 'Unspecified PARTEH module during create_cohort' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select + + site_mass => currentSite%mass_balance(el) + + ! Remove mass from the germination pool. However, if we are use prescribed physiology, + ! AND the forced recruitment model, then we are not realling using the prognostic + ! seed_germination model, so we have to short circuit things. We send all of the + ! seed germination mass to an outflux pool, and use an arbitrary generic input flux + ! to balance out the new recruits. + if ((hlm_use_ed_prescribed_phys .eq. itrue) .and. & + (EDPftvarcon_inst%prescribed_recruitment(ft) .ge. 0._r8)) then + + site_mass%flux_generic_in = site_mass%flux_generic_in + & + cohort_n*(m_struct + m_leaf + m_fnrt + m_sapw + m_store + m_repro) + + site_mass%flux_generic_out = site_mass%flux_generic_out + & + currentPatch%area * currentPatch%litter(el)%seed_germ(ft) + + currentPatch%litter(el)%seed_germ(ft) = 0._r8 + else + currentPatch%litter(el)%seed_germ(ft) = & + currentPatch%litter(el)%seed_germ(ft) - cohort_n / currentPatch%area * & + (m_struct + m_leaf + m_fnrt + m_sapw + m_store + m_repro) + end if + end do - call create_cohort(currentSite,currentPatch, temp_cohort%pft, temp_cohort%n, & - temp_cohort%hite, temp_cohort%coage, temp_cohort%dbh, prt, & - cohortstatus, recruitstatus, & - temp_cohort%canopy_trim,temp_cohort%c_area, & - currentPatch%NCL_p, & - temp_cohort%crowndamage, & - currentSite%spread, bc_in) + ! cycle through the initial conditions, and makes sure that they are all initialized + call prt%CheckInitialConditions() - ! Note that if hydraulics is on, the number of cohorts may had - ! changed due to hydraulic constraints. - ! This constaint is applied during "create_cohort" subroutine. + call create_cohort(currentSite, currentPatch, ft, cohort_n, hite, 0.0_r8, dbh, & + prt, leaf_status, recruitstatus, init_recruit_trim, 0.0_r8, & + currentPatch%NCL_p, crowndamage, currentSite%spread, bc_in) - ! keep track of how many individuals were recruited for passing to history - currentSite%recruitment_rate(ft) = currentSite%recruitment_rate(ft) + temp_cohort%n + ! Note that if hydraulics is on, the number of cohorts may have + ! changed due to hydraulic constraints. + ! This constaint is applied during "create_cohort" subroutine. + ! keep track of how many individuals were recruited for passing to history + currentSite%recruitment_rate(ft) = currentSite%recruitment_rate(ft) + cohort_n endif any_recruits - endif !use_this_pft + endif !use_this_pft enddo !pft loop - - deallocate(temp_cohort, stat=istat, errmsg=smsg) - if (istat/=0) then - write(fates_log(),*) 'dealloc013: fail on deallocate(temp_cohort):'//trim(smsg) - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - - end subroutine recruitment - ! ============================================================================ + ! ====================================================================================== subroutine CWDInput( currentSite, currentPatch, litt, bc_in) diff --git a/biogeochem/FatesCohortMod.F90 b/biogeochem/FatesCohortMod.F90 index 46775fb6a9..6ca89921ba 100644 --- a/biogeochem/FatesCohortMod.F90 +++ b/biogeochem/FatesCohortMod.F90 @@ -286,7 +286,7 @@ subroutine Init(this, prt) ! ! ARGUMENTS: - class(fates_cohort_type), intent(inout), target :: this + class(fates_cohort_type), intent(inout) :: this class(prt_vartypes), intent(inout), pointer :: prt ! allocated PARTEH object call this%NanValues() ! make everything in the cohort not-a-number @@ -298,7 +298,6 @@ subroutine Init(this, prt) ! The PARTEH cohort object should be allocated and already ! initialized in this routine. call this%prt%CheckInitialConditions() - call this%InitPRTBoundaryConditions() ! new cohorts do not have mortality rates, nor have they moved any ! carbon when they are created. They will bias our statistics @@ -619,6 +618,8 @@ subroutine Create(this, prt, pft, nn, hite, coage, dbh, status, & this%treelai,this%vcmax25top, 2) end if + call this%InitPRTBoundaryConditions() + end subroutine Create !=========================================================================== diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 3419596026..13d17c88fe 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -735,281 +735,252 @@ subroutine init_patches( nsites, sites, bc_in) end subroutine init_patches ! ============================================================================ - subroutine init_cohorts( site_in, patch_in, bc_in) + + subroutine init_cohorts(site_in, patch_in, bc_in) ! - ! !DESCRIPTION: + ! DESCRIPTION: ! initialize new cohorts on bare ground ! - ! !USES: - - ! - ! !ARGUMENTS - type(ed_site_type), intent(inout), pointer :: site_in - type(fates_patch_type), intent(inout), pointer :: patch_in - type(bc_in_type), intent(in) :: bc_in - ! - ! !LOCAL VARIABLES: - type(fates_cohort_type),pointer :: temp_cohort - class(prt_vartypes),pointer :: prt_obj - integer :: cstatus - integer :: pft - integer :: crowndamage ! which crown damage class - integer :: iage ! index for leaf age loop - integer :: el ! index for element loop - integer :: element_id ! element index consistent with defs in PRTGeneric - integer :: use_pft_local(numpft) ! determine whether this PFT is used for this patch and site. - real(r8) :: c_agw ! biomass above ground (non-leaf) [kgC] - real(r8) :: c_bgw ! biomass below ground (non-fineroot) [kgC] - real(r8) :: c_leaf ! biomass in leaves [kgC] - real(r8) :: c_fnrt ! biomass in fine roots [kgC] - real(r8) :: c_sapw ! biomass in sapwood [kgC] - real(r8) :: c_struct ! biomass in structure (dead) [kgC] - real(r8) :: c_store ! biomass in storage [kgC] - real(r8) :: a_sapw ! area in sapwood (dummy) [m2] - real(r8) :: m_struct ! Generic (any element) mass for structure [kg] - real(r8) :: m_leaf ! Generic mass for leaf [kg] - real(r8) :: m_fnrt ! Generic mass for fine-root [kg] - real(r8) :: m_sapw ! Generic mass for sapwood [kg] - real(r8) :: m_store ! Generic mass for storage [kg] - real(r8) :: m_repro ! Generic mass for reproductive tissues [kg] - real(r8) :: stem_drop_fraction - - integer, parameter :: rstatus = 0 - integer init - - real(r8) :: dummy_n ! set cohort n to a dummy value of 1 + + ! ARGUMENTS + type(ed_site_type), intent(inout), pointer :: site_in + type(fates_patch_type), intent(inout), pointer :: patch_in + type(bc_in_type), intent(in) :: bc_in + + ! LOCAL VARIABLES: + class(prt_vartypes), pointer :: prt ! PARTEH object + integer :: leaf_status ! cohort phenology status [leaves on/off] + integer :: pft ! index for PFT + integer :: crowndamage ! crown damage class + integer :: iage ! index for leaf age loop + integer :: el ! index for element loop + integer :: element_id ! element index consistent with defs in PRTGeneric + integer :: use_pft_local(numpft) ! determine whether this PFT is used for this patch and site + integer :: crown_damage ! crown damage class of the cohort [1 = undamaged, >1 = damaged] + real(r8) :: l2fr ! leaf to fineroot biomass ratio [0-1] + real(r8) :: canopy_trim ! fraction of the maximum leaf biomass that we are targeting [0-1] + real(r8) :: cohort_n ! cohort density + real(r8) :: dbh ! cohort dbh [cm] + real(r8) :: c_area ! cohort crown area [m2] + real(r8) :: c_agw ! above ground (non-leaf) biomass [kgC] + real(r8) :: c_bgw ! below ground (non-fineroot) biomss [kgC] + real(r8) :: c_leaf ! leaf biomass [kgC] + real(r8) :: c_fnrt ! fine root biomss [kgC] + real(r8) :: c_sapw ! sapwood biomass [kgC] + real(r8) :: c_struct ! structural (dead) biomass [kgC] + real(r8) :: c_store ! storage biomass [kgC] + real(r8) :: a_sapw ! sapwood area [m2] + real(r8) :: m_struct ! generic (any element) mass for structure [kg] + real(r8) :: m_leaf ! generic mass for leaf [kg] + real(r8) :: m_fnrt ! generic mass for fine-root [kg] + real(r8) :: m_sapw ! generic mass for sapwood [kg] + real(r8) :: m_store ! generic mass for storage [kg] + real(r8) :: m_repro ! generic mass for reproductive tissues [kg] + real(r8) :: stem_drop_fraction ! of all the organs in the recruits. Used for both [kg per plant] and [kg per cohort] + integer, parameter :: recruitstatus = 0 ! whether the newly created cohorts are recruited or initialized - !---------------------------------------------------------------------- + !------------------------------------------------------------------------------------- patch_in%tallest => null() patch_in%shortest => null() - ! Manage interactions of fixed biogeog (site level filter) and - ! nocomp (patch level filter) + ! Manage interactions of fixed biogeog (site level filter) and nocomp (patch level filter) ! Need to cover all potential biogeog x nocomp combinations ! 1. biogeog = false. nocomp = false: all PFTs on (DEFAULT) ! 2. biogeog = true. nocomp = false: site level filter ! 3. biogeog = false. nocomp = true : patch level filter ! 4. biogeog = true. nocomp = true : patch and site level filter ! in principle this could be a patch level variable. - do pft = 1,numpft - ! Turn every PFT ON, unless we are in a special case. - use_pft_local(pft) = itrue ! Case 1 - if(hlm_use_fixed_biogeog.eq.itrue)then !filter geographically - use_pft_local(pft) = site_in%use_this_pft(pft) ! Case 2 - if(hlm_use_nocomp.eq.itrue.and.pft.ne.patch_in%nocomp_pft_label)then - ! Having set the biogeog filter as on or off, turn off all PFTs - ! whose identiy does not correspond to this patch label. - use_pft_local(pft) = ifalse ! Case 3 - endif - else - if(hlm_use_nocomp.eq.itrue.and.pft.ne.patch_in%nocomp_pft_label)then - ! This case has all PFTs on their own patch everywhere. - use_pft_local(pft) = ifalse ! Case 4 - endif - endif + do pft = 1, numpft + ! first turn every PFT ON, unless we are in a special case + use_pft_local(pft) = itrue ! Case 1 + if (hlm_use_fixed_biogeog .eq. itrue) then !filter geographically + use_pft_local(pft) = site_in%use_this_pft(pft) ! Case 2 + if (hlm_use_nocomp .eq. itrue .and. pft .ne. patch_in%nocomp_pft_label) then + ! having set the biogeog filter as on or off, turn off all PFTs + ! whose identity does not correspond to this patch label + use_pft_local(pft) = ifalse ! Case 3 + endif + else + if (hlm_use_nocomp .eq. itrue .and pft .ne. patch_in%nocomp_pft_label) then + ! This case has all PFTs on their own patch everywhere + use_pft_local(pft) = ifalse ! Case 4 + endif + endif end do - - do pft = 1,numpft - - if(use_pft_local(pft).eq.itrue)then + do pft = 1, numpft + if (use_pft_local(pft) .eq. itrue) then - allocate(temp_cohort) ! temporary cohort - temp_cohort%pft = pft - temp_cohort%l2fr = prt_params%allom_l2fr(pft) - temp_cohort%canopy_trim = 1.0_r8 - temp_cohort%crowndamage = 1 ! Assume no damage to begin with + l2fr = prt_params%allom_l2fr(pft) + canopy_trim = 1.0_r8 + crown_damage = 1 ! Assume no damage to begin with - ! If positive EDPftvarcon_inst%initd is interpreted as initial recruit density. - ! If negative EDPftvarcon_inst%initd is interpreted as initial dbh. - ! Dbh-initialization can only be used in nocomp mode. - ! In the dbh-initialization case, we calculate crown area for a single tree and then calculate - ! the density of plants needed for a full canopy. - - if(EDPftvarcon_inst%initd(pft)>nearzero) then ! interpret as initial density and calculate diameter - - temp_cohort%n = EDPftvarcon_inst%initd(pft) * patch_in%area - if(hlm_use_nocomp.eq.itrue)then !in nocomp mode we only have one PFT per patch - ! as opposed to numpft's. So we should up the initial density - ! to compensate (otherwise runs are very hard to compare) - ! this multiplies it by the number of PFTs there would have been in - ! the single shared patch in competition mode. - ! n.b. that this is the same as currentcohort%n = %initd(pft) &AREA - temp_cohort%n = temp_cohort%n * sum(site_in%use_this_pft) - endif + ! If positive EDPftvarcon_inst%initd is interpreted as initial recruit density. + ! If negative EDPftvarcon_inst%initd is interpreted as initial dbh. + ! Dbh-initialization can only be used in nocomp mode. + ! In the dbh-initialization case, we calculate crown area for a single tree and then calculate + ! the density of plants needed for a full canopy. + if (EDPftvarcon_inst%initd(pft) > nearzero) then ! interpret as initial density and calculate diameter + + cohort_n = EDPftvarcon_inst%initd(pft)*patch_in%area + if (hlm_use_nocomp .eq. itrue) then !in nocomp mode we only have one PFT per patch + ! as opposed to numpft's. So we should up the initial density + ! to compensate (otherwise runs are very hard to compare) + ! this multiplies it by the number of PFTs there would have been in + ! the single shared patch in competition mode. + ! n.b. that this is the same as currentcohort%n = %initd(pft) &AREA + cohort_n = cohort_n*sum(site_in%use_this_pft) + endif - ! h,dbh,leafc,n from SP values or from small initial size. - if(hlm_use_sp.eq.itrue)then - init = itrue - ! At this point, we do not know the bc_in values of tlai tsai and htop, - ! so this is initializing to an arbitrary value for the very first timestep. - ! Not sure if there's a way around this or not. - call assign_cohort_SP_properties(temp_cohort, 0.5_r8,0.2_r8, 0.1_r8,patch_in%area,init,c_leaf) - - else - temp_cohort%hite = EDPftvarcon_inst%hgt_min(pft) - ! Calculate the plant diameter from height - call h2d_allom(temp_cohort%hite,pft,temp_cohort%dbh) - - ! Calculate the leaf biomass from allometry - ! (calculates a maximum first, then applies canopy trim) - call bleaf(temp_cohort%dbh,pft,temp_cohort%crowndamage, & - temp_cohort%canopy_trim,c_leaf) - - endif ! sp mode - - else ! interpret as initial diameter and calculate density - if(hlm_use_nocomp .eq. itrue)then - temp_cohort%dbh = abs(EDPftvarcon_inst%initd(pft)) - - ! calculate crown area of a single plant - dummy_n = 1.0_r8 ! make n=1 to get area of one tree - - call carea_allom(temp_cohort%dbh, dummy_n, init_spread_inventory, temp_cohort%pft, & - temp_cohort%crowndamage, temp_cohort%c_area) - - ! calculate initial density required to close canopy - temp_cohort%n = patch_in%area / temp_cohort%c_area - - ! Calculate the leaf biomass from allometry - ! (calculates a maximum first, then applies canopy trim) - call bleaf(temp_cohort%dbh,pft,temp_cohort%crowndamage, & - temp_cohort%canopy_trim,c_leaf) - - else - write(fates_log(),*) 'Negative fates_recruit_init_density can only be used in no comp mode' - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif + ! h, dbh, leafc, n from SP values or from small initial size + if (hlm_use_sp .eq. itrue) then + ! At this point, we do not know the bc_in values of tlai tsai and htop, + ! so this is initializing to an arbitrary value for the very first timestep. + ! Not sure if there's a way around this or not. + call assign_cohort_SP_properties(temp_cohort, 0.5_r8, 0.2_r8, 0.1_r8, & + patch_in%area, itrue, c_leaf) + else + ! calculate the plant diameter from height + call h2d_allom(EDPftvarcon_inst%hgt_min(pft), pft, dbh) + + ! Calculate the leaf biomass from allometry + ! (calculates a maximum first, then applies canopy trim) + call bleaf(dbh, pft, crowndamage, canopy_trim, c_leaf) + endif ! sp mode + + else ! interpret as initial diameter and calculate density + if (hlm_use_nocomp .eq. itrue) then + dbh = abs(EDPftvarcon_inst%initd(pft)) + ! calculate crown area of a single plant + call carea_allom(dbh, 1.0_r8, init_spread_inventory, pft, crowndamage, & + c_area) + + ! calculate initial density required to close canopy + cohort_n = patch_in%area/c_area + + ! Calculate the leaf biomass from allometry + ! (calculates a maximum first, then applies canopy trim) + call bleaf(dbh, pft, crowndamage, canopy_trim, c_leaf) + + else + write(fates_log(),*) 'Negative fates_recruit_init_density can only be used in no comp mode' + call endrun(msg=errMsg(sourcefile, __LINE__)) endif + endif + ! calculate total above-ground biomass from allometry + call bagw_allom(dbh, pft, crowndamage, c_agw) - ! Calculate total above-ground biomass from allometry - call bagw_allom(temp_cohort%dbh,pft,temp_cohort%crowndamage,c_agw) - - ! Calculate coarse root biomass from allometry - call bbgw_allom(temp_cohort%dbh,pft,c_bgw) - - ! Calculate fine root biomass from allometry - ! (calculates a maximum and then trimming value) - call bfineroot(temp_cohort%dbh,pft,temp_cohort%canopy_trim,temp_cohort%l2fr,c_fnrt) + ! calculate coarse root biomass from allometry + call bbgw_allom(dbh pft, c_bgw) - ! Calculate sapwood biomass - call bsap_allom(temp_cohort%dbh,pft,temp_cohort%crowndamage, & - temp_cohort%canopy_trim,a_sapw,c_sapw) + ! Calculate fine root biomass from allometry + ! (calculates a maximum and then trimming value) + call bfineroot(dbh, pft, canopy_trim, l2fr, c_fnrt) - call bdead_allom( c_agw, c_bgw, c_sapw, pft, c_struct ) + ! Calculate sapwood biomass + call bsap_allom(dbh, pft, crowndamage, canopy_trim, a_sapw, c_sapw) - call bstore_allom(temp_cohort%dbh, pft, temp_cohort%crowndamage, & - temp_cohort%canopy_trim, c_store) + call bdead_allom(c_agw, c_bgw, c_sapw, pft, c_struct) + call bstore_allom(dbh, pft, crowndamage, canopy_trim, c_store) - cstatus = leaves_on + leaf_status = leaves_on - stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(temp_cohort%pft) + stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(pft) - if(hlm_use_sp.eq.ifalse)then ! do not override SP vales with phenology + if (hlm_use_sp .eq. ifalse) then ! do not override SP vales with phenology - if( prt_params%season_decid(pft) == itrue .and. & - any(site_in%cstatus == [phen_cstat_nevercold,phen_cstat_iscold])) then - c_leaf = 0._r8 - c_sapw = (1.0_r8-stem_drop_fraction) * c_sapw - c_struct = (1.0_r8-stem_drop_fraction) * c_struct - cstatus = leaves_off - endif - - if ( prt_params%stress_decid(pft) == itrue .and. & - any(site_in%dstatus == [phen_dstat_timeoff,phen_dstat_moistoff])) then - c_leaf = 0._r8 - c_sapw = (1.0_r8-stem_drop_fraction) * c_sapw - c_struct = (1.0_r8-stem_drop_fraction) * c_struct - cstatus = leaves_off - endif - - end if ! SP mode + if (prt_params%season_decid(pft) == itrue .and. & + any(site_in%cstatus == [phen_cstat_nevercold, phen_cstat_iscold])) then + c_leaf = 0._r8 + c_sapw = (1.0_r8 - stem_drop_fraction)*c_sapw + c_struct = (1.0_r8 - stem_drop_fraction)*c_struct + cstatus = leaves_off + endif - if ( debug ) write(fates_log(),*) 'EDInitMod.F90 call create_cohort ' + if (prt_params%stress_decid(pft) == itrue .and. & + any(site_in%dstatus == [phen_dstat_timeoff, phen_dstat_moistoff])) then + c_leaf = 0._r8 + c_sapw = (1.0_r8 - stem_drop_fraction)*c_sapw + c_struct = (1.0_r8-stem_drop_fraction)*c_struct + cstatus = leaves_off + endif + end if ! SP mode - temp_cohort%coage = 0.0_r8 + if (debug) write(fates_log(),*) 'EDInitMod.F90 call create_cohort ' + ! -------------------------------------------------------------------------------- + ! Initialize the mass of every element in every organ of the organ + ! -------------------------------------------------------------------------------- - ! -------------------------------------------------------------------------------- - ! Initialize the mass of every element in every organ of the organ - ! -------------------------------------------------------------------------------- + prt => null() + call InitPRTObject(prt) - prt_obj => null() - call InitPRTObject(prt_obj) + do el = 1, num_elements - do el = 1,num_elements + element_id = element_list(el) + ! If this is carbon12, then the initialization is straight forward + ! otherwise, we use stoichiometric ratios + select case(element_id) + case(carbon12_element) - element_id = element_list(el) + m_struct = c_struct + m_leaf = c_leaf + m_fnrt = c_fnrt + m_sapw = c_sapw + m_store = c_store + m_repro = 0._r8 - ! If this is carbon12, then the initialization is straight forward - ! otherwise, we use stoichiometric ratios - select case(element_id) - case(carbon12_element) + case(nitrogen_element) - m_struct = c_struct - m_leaf = c_leaf - m_fnrt = c_fnrt - m_sapw = c_sapw - m_store = c_store - m_repro = 0._r8 + m_struct = c_struct*prt_params%nitr_stoich_p1(pft, prt_params%organ_param_id(struct_organ)) + m_leaf = c_leaf*prt_params%nitr_stoich_p1(pft, prt_params%organ_param_id(leaf_organ)) + m_fnrt = c_fnrt*prt_params%nitr_stoich_p1(pft, prt_params%organ_param_id(fnrt_organ)) + m_sapw = c_sapw*prt_params%nitr_stoich_p1(pft, prt_params%organ_param_id(sapw_organ)) + m_repro = 0._r8 + m_store = StorageNutrientTarget(pft, element_id, m_leaf, m_fnrt, m_sapw, m_struct) - case(nitrogen_element) + case(phosphorus_element) - m_struct = c_struct*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(struct_organ)) - m_leaf = c_leaf*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(leaf_organ)) - m_fnrt = c_fnrt*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(fnrt_organ)) - m_sapw = c_sapw*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(sapw_organ)) - m_repro = 0._r8 - m_store = StorageNutrientTarget(pft,element_id,m_leaf,m_fnrt,m_sapw,m_struct) + m_struct = c_struct*prt_params%phos_stoich_p1(pft, prt_params%organ_param_id(struct_organ)) + m_leaf = c_leaf*prt_params%phos_stoich_p1(pft, prt_params%organ_param_id(leaf_organ)) + m_fnrt = c_fnrt*prt_params%phos_stoich_p1(pft, prt_params%organ_param_id(fnrt_organ)) + m_sapw = c_sapw*prt_params%phos_stoich_p1(pft, prt_params%organ_param_id(sapw_organ)) + m_repro = 0._r8 + m_store = StorageNutrientTarget(pft, element_id, m_leaf, m_fnrt, m_sapw, m_struct) - case(phosphorus_element) + end select - m_struct = c_struct*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(struct_organ)) - m_leaf = c_leaf*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(leaf_organ)) - m_fnrt = c_fnrt*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(fnrt_organ)) - m_sapw = c_sapw*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(sapw_organ)) - m_repro = 0._r8 - m_store = StorageNutrientTarget(pft,element_id,m_leaf,m_fnrt,m_sapw,m_struct) + select case(hlm_parteh_mode) + case (prt_carbon_allom_hyp, prt_cnp_flex_allom_hyp ) - end select + ! Put all of the leaf mass into the first bin + call SetState(prt_obj, leaf_organ, element_id, m_leaf, 1) + do iage = 2,nleafage + call SetState(prt_obj, leaf_organ, element_id, 0._r8, iage) + end do - select case(hlm_parteh_mode) - case (prt_carbon_allom_hyp,prt_cnp_flex_allom_hyp ) + call SetState(prt_obj, fnrt_organ, element_id, m_fnrt) + call SetState(prt_obj, sapw_organ, element_id, m_sapw) + call SetState(prt_obj, store_organ, element_id, m_store) + call SetState(prt_obj, struct_organ, element_id, m_struct) + call SetState(prt_obj, repro_organ, element_id, m_repro) - ! Put all of the leaf mass into the first bin - call SetState(prt_obj,leaf_organ, element_id,m_leaf,1) - do iage = 2,nleafage - call SetState(prt_obj,leaf_organ, element_id,0._r8,iage) - end do + case default + write(fates_log(),*) 'Unspecified PARTEH module during create_cohort' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select - call SetState(prt_obj,fnrt_organ, element_id, m_fnrt) - call SetState(prt_obj,sapw_organ, element_id, m_sapw) - call SetState(prt_obj,store_organ, element_id, m_store) - call SetState(prt_obj,struct_organ, element_id, m_struct) - call SetState(prt_obj,repro_organ, element_id, m_repro) + end do - case default - write(fates_log(),*) 'Unspecified PARTEH module during create_cohort' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end select + call prt_obj%CheckInitialConditions() - end do + call create_cohort(site_in, patch_in, pft, cohort_n, & + EDPftvarcon_inst%hgt_min(pft), 0.0_r8, dbh, prt, leaf_status, recruitstatus, & + canopy_trim, c_area, 1, crowndamage, site_in%spread, bc_in) - call prt_obj%CheckInitialConditions() - - call create_cohort(site_in, patch_in, pft, temp_cohort%n, temp_cohort%hite, & - temp_cohort%coage, temp_cohort%dbh, prt_obj, cstatus, rstatus, & - temp_cohort%canopy_trim, temp_cohort%c_area,1,temp_cohort%crowndamage, site_in%spread, bc_in) - - deallocate(temp_cohort, stat=istat, errmsg=smsg) - if (istat/=0) then - write(fates_log(),*) 'dealloc014: fail on deallocate(temp_cohort):'//trim(smsg) - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - - endif !use_this_pft + endif !use_this_pft enddo !numpft ! (Keeping as an example) @@ -1023,10 +994,9 @@ subroutine init_cohorts( site_in, patch_in, bc_in) call fuse_cohorts(site_in, patch_in,bc_in) call sort_cohorts(patch_in) - end subroutine init_cohorts - ! =============================================================================================== + ! ====================================================================================== end module EDInitMod From 6a8f12bbbb0b39c870fedff83bc146f923e0d643 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Mon, 15 May 2023 10:31:46 -0600 Subject: [PATCH 702/852] do_inventory_out off --- main/FatesInventoryInitMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index 254dc100ff..8a1d83542c 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -97,7 +97,7 @@ module FatesInventoryInitMod ! defined in model memory and a physical ! site listed in the file - logical, parameter :: do_inventory_out = .true. + logical, parameter :: do_inventory_out = .false. public :: initialize_sites_by_inventory From 8bd42ea98dcdd28c8e4ba314322240a77c44baa9 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 16 May 2023 09:01:30 -0600 Subject: [PATCH 703/852] remove temp cohort --- biogeochem/EDPhysiologyMod.F90 | 212 ++++++++++++++++++--------------- main/EDInitMod.F90 | 34 +++--- 2 files changed, 135 insertions(+), 111 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 25d6a35ae9..7aae864201 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -130,6 +130,7 @@ module EDPhysiologyMod public :: phenology public :: satellite_phenology public :: assign_cohort_SP_properties + public :: calculate_SP_properties public :: recruitment public :: ZeroLitterFluxes @@ -1621,121 +1622,144 @@ subroutine satellite_phenology(currentSite, bc_in) end subroutine satellite_phenology - ! ===================================================================================== - - subroutine assign_cohort_SP_properties(currentCohort,htop,tlai,tsai,parea,init,leaf_c) - - ! -----------------------------------------------------------------------------------! - ! Takes the daily inputs of leaf area index, stem area index and canopy height and - ! translates them into a FATES structure with one patch and one cohort per PFT - ! The leaf area of the cohort is modified each day to match that asserted by the HLM - ! -----------------------------------------------------------------------------------! - - - type(fates_cohort_type), intent(inout), target :: currentCohort - - real(r8), intent(in) :: tlai ! target leaf area index from SP inputs - real(r8), intent(in) :: tsai ! target stem area index from SP inputs - real(r8), intent(in) :: htop ! target tree height from SP inputs - real(r8), intent(in) :: parea ! patch area for this PFT - integer, intent(in) :: init ! are we in the initialization routine? if so do not set leaf_c - real(r8), intent(out) :: leaf_c ! leaf carbon estimated to generate target tlai - - real(r8) :: dummy_n ! set cohort n to a dummy value of 1.0 - integer :: fates_pft ! fates pft numer for weighting loop - real(r8) :: spread ! dummy value of canopy spread to estimate c_area - real(r8) :: check_treelai - real(r8) :: canopylai(1:nclmax) - real(r8) :: fracerr - real(r8) :: oldcarea - - ! Do some checks - if(associated(currentCohort%shorter))then - write(fates_log(),*) 'SP mode has >1 cohort' - write(fates_log(),*) "SP mode >1 cohort: PFT",currentCohort%pft, currentCohort%shorter%pft - write(fates_log(),*) "SP mode >1 cohort: CL",currentCohort%canopy_layer, currentCohort%shorter%canopy_layer - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - !------------------------------------------ - ! Calculate dbh from input height, and c_area from dbh - !------------------------------------------ - currentCohort%hite = htop - - fates_pft = currentCohort%pft - call h2d_allom(currentCohort%hite,fates_pft,currentCohort%dbh) - - dummy_n = 1.0_r8 ! make n=1 to get area of one tree. - spread = 1.0_r8 ! fix this to 0 to remove dynamics of canopy closure, assuming a closed canopy. - ! n.b. the value of this will only affect 'n', which isn't/shouldn't be a diagnostic in - ! SP mode. - call carea_allom(currentCohort%dbh,dummy_n,spread,currentCohort%pft,& - currentCohort%crowndamage,currentCohort%c_area) - - !------------------------------------------ - ! Calculate canopy N assuming patch area is full - !------------------------------------------ - currentCohort%n = parea / currentCohort%c_area + ! ====================================================================================== - ! correct c_area for the new nplant - call carea_allom(currentCohort%dbh,currentCohort%n,spread,currentCohort%pft,& - currentCohort%crowndamage,currentCohort%c_area) + subroutine calculate_SP_properties(htop, tlai, tsai, parea, pft, crown_damage, & + canopy_layer, vcmax25top, leaf_c, dbh, cohort_n, c_area) + ! + ! DESCRIPTION: + ! Takes the daily inputs of leaf area index, stem area index and canopy height and + ! translates them into a FATES structure with one patch and one cohort per PFT. + ! The leaf area of the cohort is modified each day to match that asserted by the HLM + ! - ! ------------------------------------------ - ! Calculate leaf carbon from target treelai - ! ------------------------------------------ - currentCohort%treelai = tlai + ! ARGUMENTS: + real(r8), intent(in) :: tlai ! target leaf area index from SP inputs [m2 m-2] + real(r8), intent(in) :: tsai ! target stem area index from SP inputs [m2 m-2] + real(r8), intent(in) :: htop ! target tree height from SP inputs [m] + real(r8), intent(in) :: parea ! patch area for this PFT [m2] + real(r8), intent(in) :: vcmax25top ! maximum carboxylation at canopy top and 25degC [umol CO2/m2/s] + integer, intent(in) :: pft ! cohort PFT index + integer, intent(in) :: crown_damage ! cohort crown damage status + integer, intent(in) :: canopy_layer ! canopy status of cohort [1 = canopy, 2 = understorey, etc.] + real(r8), intent(out) :: leaf_c ! leaf carbon estimated to generate target tlai [kgC] + real(r8), intent(out) :: dbh ! cohort diameter at breast height [cm] + real(r8), intent(out) :: cohort_n ! cohort density [/m2] + real(r8), intent(out) :: c_area + + ! LOCAL VARIABLES: + real(r8) :: check_treelai ! check tree LAI against input tlai [m2/m2] + real(r8) :: canopylai(1:nclmax) ! canopy LAI [m2/m2] + real(r8) :: oldcarea ! save value of crown area [m2] + + ! calculate DBH from input height + call h2d_allom(htop, pft, dbh) + + ! calculate canopy area, assuming n = 1.0 and spread = 1.0_r8 + call carea_allom(dbh, 1.0_r8, 1.0_r8, pft, crown_damage, c_area) + + ! calculate canopy N assuming patch area is full + cohort_n = parea/c_area + + ! correct c_area for the new nplant, assuming spread = 1.0 + call carea_allom(dbh, cohort_n, 1.0_r8, pft, crown_damage, c_area) + + ! calculate leaf carbon from target treelai canopylai(:) = 0._r8 - if(init.eq.itrue)then - ! If we are initializing, the canopy layer has not been set yet, so just set to 1 - currentCohort%canopy_layer = 1 - ! We need to get the vcmax25top - currentCohort%vcmax25top = EDPftvarcon_inst%vcmax25top(currentCohort%pft,1) - endif - leaf_c = leafc_from_treelai( currentCohort%treelai, currentCohort%pft, currentCohort%c_area,& - currentCohort%n, currentCohort%canopy_layer, currentCohort%vcmax25top) + leaf_c = leafc_from_treelai(tlai, pft, c_area, cohort_n, canopy_layer, vcmax25top) - !check that the inverse calculation of leafc from treelai is the same as the + ! check that the inverse calculation of leafc from treelai is the same as the ! standard calculation of treelai from leafc. Maybe can delete eventually? + check_treelai = tree_lai(leaf_c, pft, c_area, cohort_n, canopy_layer, & + canopylai, vcmax25top) - check_treelai = tree_lai(leaf_c, currentCohort%pft, currentCohort%c_area, & - currentCohort%n, currentCohort%canopy_layer, & - canopylai,currentCohort%vcmax25top ) - - if( abs(currentCohort%treelai-check_treelai).gt.1.0e-12)then !this is not as precise as nearzero - write(fates_log(),*) 'error in validate treelai',currentCohort%treelai,check_treelai,currentCohort%treelai-check_treelai - write(fates_log(),*) 'tree_lai inputs: ', currentCohort%pft, currentCohort%c_area, currentCohort%n, & - currentCohort%canopy_layer, currentCohort%vcmax25top + if (abs(tlai - check_treelai) .gt. 1.0e-12) then !this is not as precise as nearzero + write(fates_log(),*) 'error in validate treelai', tlai, check_treelai, tlai - check_treelai + write(fates_log(),*) 'tree_lai inputs: ', pft, c_area, cohort_n, & + canopy_layer, vcmax25top call endrun(msg=errMsg(sourcefile, __LINE__)) end if ! the carea_allom routine sometimes generates precision-tolerance level errors in the canopy area ! these mean that the canopy area does not exactly add up to the patch area, which causes chaos in ! the radiation routines. Correct both the area and the 'n' to remove error, and don't use - !! carea_allom in SP mode after this point. - - if(abs(currentCohort%c_area-parea).gt.nearzero)then ! there is an error - if(abs(currentCohort%c_area-parea).lt.10.e-9)then !correct this if it's a very small error - oldcarea = currentCohort%c_area - !generate new cohort area - currentCohort%c_area = currentCohort%c_area - (currentCohort%c_area- parea) - currentCohort%n = currentCohort%n * (currentCohort%c_area/oldcarea) - if(abs(currentCohort%c_area-parea).gt.nearzero)then - write(fates_log(),*) 'SPassign, c_area still broken',currentCohort%c_area-parea,currentCohort%c_area-oldcarea - call endrun(msg=errMsg(sourcefile, __LINE__)) + ! carea_allom in SP mode after this point. + + if (abs(c_area - parea) .gt. nearzero) then ! there is an error + if (abs(c_area - parea) .lt. 10.e-9) then ! correct this if it's a very small error + oldcarea = c_area + ! generate new cohort area + c_area = c_area - (c_area - parea) + cohort_n = cohort_n*(c_area/oldcarea) + if (abs(c_area-parea) .gt. nearzero) then + write(fates_log(),*) 'SPassign, c_area still broken', c_area - parea, c_area - oldcarea + call endrun(msg=errMsg(sourcefile, __LINE__)) end if else - write(fates_log(),*) 'SPassign, big error in c_area',currentCohort%c_area-parea,currentCohort%pft + write(fates_log(),*) 'SPassign, big error in c_area', c_area - parea, pft end if ! still broken end if !small error - if(init.eq.ifalse)then - call SetState(currentCohort%prt, leaf_organ, carbon12_element, leaf_c, 1) + end subroutine calculate_SP_properties + + ! ====================================================================================== + + subroutine assign_cohort_SP_properties(currentCohort, htop, tlai, tsai, parea, init, & + leaf_c) + ! + ! DESCRIPTION: + ! Takes the daily inputs of leaf area index, stem area index and canopy height and + ! translates them into a FATES structure with one patch and one cohort per PFT. + ! The leaf area of the cohort is modified each day to match that asserted by the HLM + + + ! ARGUMENTS + type(fates_cohort_type), intent(inout), target :: currentCohort ! cohort object + real(r8), intent(in) :: tlai ! target leaf area index from SP inputs [m2/m2] + real(r8), intent(in) :: tsai ! target stem area index from SP inputs [m2/m2] + real(r8), intent(in) :: htop ! target tree height from SP inputs [m] + real(r8), intent(in) :: parea ! patch area for this PFT [m2] + integer, intent(in) :: init ! are we in the initialization routine? if so do not set leaf_c + real(r8), intent(out) :: leaf_c ! leaf carbon estimated to generate target tlai [kgC] + + ! LOCAL VARIABLES + real(r8) :: dbh ! cohort dbh [cm] + real(r8) :: cohort_n ! cohort density [/m2] + real(r8) :: c_area ! cohort canopy area [m2] + + if (associated(currentCohort%shorter)) then + write(fates_log(),*) 'SP mode has >1 cohort' + write(fates_log(),*) "SP mode >1 cohort: PFT", currentCohort%pft, currentCohort%shorter%pft + write(fates_log(),*) "SP mode >1 cohort: CL", currentCohort%canopy_layer, currentCohort%shorter%canopy_layer + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + if (init .eq. itrue) then + ! If we are initializing, the canopy layer has not been set yet, so just set to 1 + currentCohort%canopy_layer = 1 + ! We need to get the vcmax25top + currentCohort%vcmax25top = EDPftvarcon_inst%vcmax25top(currentCohort%pft, 1) endif - ! assert sai + call calculate_SP_properties(htop, tlai, tsai, parea, currentCohort%pft, & + currentCohort%crowndamage, currentCohort%canopy_layer, currentCohort%vcmax25top, & + leaf_c, dbh, cohort_n, c_area) + + ! set allometric characteristics + currentCohort%hite = htop + currentCohort%dbh = dbh + currentCohort%n = cohort_n + currentCohort%c_area = c_area + currentCohort%treelai = tlai currentCohort%treesai = tsai + leaf_c = leafc_from_treelai(tlai, currentCohort%pft, currentCohort%c_area, & + currentCohort%n, currentCohort%canopy_layer, currentCohort%vcmax25top) + + if (init .eq. ifalse) then + call SetState(currentCohort%prt, leaf_organ, carbon12_element, leaf_c, 1) + endif + end subroutine assign_cohort_SP_properties ! ===================================================================================== diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 13d17c88fe..8a72e542ae 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -21,7 +21,7 @@ module EDInitMod use EDCohortDynamicsMod , only : create_cohort, fuse_cohorts, sort_cohorts use EDCohortDynamicsMod , only : InitPRTObject use EDPatchDynamicsMod , only : set_patchno - use EDPhysiologyMod , only : assign_cohort_sp_properties + use EDPhysiologyMod , only : calculate_sp_properties use ChecksBalancesMod , only : SiteMassStock use FatesInterfaceTypesMod , only : hlm_day_of_year use EDTypesMod , only : ed_site_type @@ -802,7 +802,7 @@ subroutine init_cohorts(site_in, patch_in, bc_in) use_pft_local(pft) = ifalse ! Case 3 endif else - if (hlm_use_nocomp .eq. itrue .and pft .ne. patch_in%nocomp_pft_label) then + if (hlm_use_nocomp .eq. itrue .and. pft .ne. patch_in%nocomp_pft_label) then ! This case has all PFTs on their own patch everywhere use_pft_local(pft) = ifalse ! Case 4 endif @@ -838,8 +838,9 @@ subroutine init_cohorts(site_in, patch_in, bc_in) ! At this point, we do not know the bc_in values of tlai tsai and htop, ! so this is initializing to an arbitrary value for the very first timestep. ! Not sure if there's a way around this or not. - call assign_cohort_SP_properties(temp_cohort, 0.5_r8, 0.2_r8, 0.1_r8, & - patch_in%area, itrue, c_leaf) + call calculate_SP_properties(0.5_r8, 0.2_r8, 0.1_r8, patch_in%area, pft, & + crown_damage, 1, EDPftvarcon_inst%vcmax25top(pft, 1), c_leaf, dbh, & + cohort_n, c_area) else ! calculate the plant diameter from height call h2d_allom(EDPftvarcon_inst%hgt_min(pft), pft, dbh) @@ -873,7 +874,7 @@ subroutine init_cohorts(site_in, patch_in, bc_in) call bagw_allom(dbh, pft, crowndamage, c_agw) ! calculate coarse root biomass from allometry - call bbgw_allom(dbh pft, c_bgw) + call bbgw_allom(dbh, pft, c_bgw) ! Calculate fine root biomass from allometry ! (calculates a maximum and then trimming value) @@ -896,7 +897,7 @@ subroutine init_cohorts(site_in, patch_in, bc_in) c_leaf = 0._r8 c_sapw = (1.0_r8 - stem_drop_fraction)*c_sapw c_struct = (1.0_r8 - stem_drop_fraction)*c_struct - cstatus = leaves_off + leaf_status = leaves_off endif if (prt_params%stress_decid(pft) == itrue .and. & @@ -904,7 +905,7 @@ subroutine init_cohorts(site_in, patch_in, bc_in) c_leaf = 0._r8 c_sapw = (1.0_r8 - stem_drop_fraction)*c_sapw c_struct = (1.0_r8-stem_drop_fraction)*c_struct - cstatus = leaves_off + leaf_status = leaves_off endif end if ! SP mode @@ -955,17 +956,17 @@ subroutine init_cohorts(site_in, patch_in, bc_in) select case(hlm_parteh_mode) case (prt_carbon_allom_hyp, prt_cnp_flex_allom_hyp ) - ! Put all of the leaf mass into the first bin - call SetState(prt_obj, leaf_organ, element_id, m_leaf, 1) + ! Put all of the leaf mass into the first bin + call SetState(prt, leaf_organ, element_id, m_leaf, 1) do iage = 2,nleafage - call SetState(prt_obj, leaf_organ, element_id, 0._r8, iage) + call SetState(prt, leaf_organ, element_id, 0._r8, iage) end do - call SetState(prt_obj, fnrt_organ, element_id, m_fnrt) - call SetState(prt_obj, sapw_organ, element_id, m_sapw) - call SetState(prt_obj, store_organ, element_id, m_store) - call SetState(prt_obj, struct_organ, element_id, m_struct) - call SetState(prt_obj, repro_organ, element_id, m_repro) + call SetState(prt, fnrt_organ, element_id, m_fnrt) + call SetState(prt, sapw_organ, element_id, m_sapw) + call SetState(prt, store_organ, element_id, m_store) + call SetState(prt, struct_organ, element_id, m_struct) + call SetState(prt, repro_organ, element_id, m_repro) case default write(fates_log(),*) 'Unspecified PARTEH module during create_cohort' @@ -974,7 +975,7 @@ subroutine init_cohorts(site_in, patch_in, bc_in) end do - call prt_obj%CheckInitialConditions() + call prt%CheckInitialConditions() call create_cohort(site_in, patch_in, pft, cohort_n, & EDPftvarcon_inst%hgt_min(pft), 0.0_r8, dbh, prt, leaf_status, recruitstatus, & @@ -998,5 +999,4 @@ end subroutine init_cohorts ! ====================================================================================== - end module EDInitMod From 3879006cd57682848318fc0ab255d2c3667df0ab Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 16 May 2023 09:47:06 -0600 Subject: [PATCH 704/852] update l2fr definition --- biogeochem/FatesCohortMod.F90 | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/biogeochem/FatesCohortMod.F90 b/biogeochem/FatesCohortMod.F90 index 6ca89921ba..e72a76fa26 100644 --- a/biogeochem/FatesCohortMod.F90 +++ b/biogeochem/FatesCohortMod.F90 @@ -62,13 +62,12 @@ module FatesCohortMod ! Multi-species, multi-organ Plant Reactive Transport (PRT) ! Contains carbon and nutrient state variables for various plant organs class(prt_vartypes), pointer :: prt - real(r8) :: l2fr ! leaf to fineroot biomass ratio (this is constant - ! in carbon only simulationss, and is set by the - ! allom_l2fr_min parameter. In nutrient - ! enabled simulations, this is dynamic, will - ! vary between allom_l2fr_min and allom_l2fr_max - ! parameters, with a tendency driven by - ! nutrient storage) [kg root / kg leaf] + real(r8) :: l2fr ! leaf to fineroot biomass ratio [kg root / kg leaf] + ! (this is constant in carbon only simulationss, and + ! is set by the allom_l2fr parameter). + ! For nutrient enabled simulations, this is dynamic. + ! In cold-start simulations, the allom_l2fr + ! parameter sets the starter value. !--------------------------------------------------------------------------- From 614e4a4badc8a945831e92e3978141200e96549b Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 16 May 2023 10:20:02 -0600 Subject: [PATCH 705/852] dangling pointer --- biogeochem/FatesCohortMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/FatesCohortMod.F90 b/biogeochem/FatesCohortMod.F90 index e72a76fa26..df04360d18 100644 --- a/biogeochem/FatesCohortMod.F90 +++ b/biogeochem/FatesCohortMod.F90 @@ -522,7 +522,7 @@ subroutine Create(this, prt, pft, nn, hite, coage, dbh, status, & ! set up values for a newly created cohort ! ARGUMENTS - class(fates_cohort_type), intent(inout) :: this ! cohort object + class(fates_cohort_type), intent(inout), :: this ! cohort object class(prt_vartypes), intent(inout), pointer :: prt ! The allocated PARTEH object integer, intent(in) :: pft ! cohort Plant Functional Type integer, intent(in) :: crowndamage ! cohort damage class From 474551652857d9bbc1a09c4dad4995888e2585f2 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 16 May 2023 11:03:35 -0600 Subject: [PATCH 706/852] update to target --- biogeochem/FatesCohortMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/FatesCohortMod.F90 b/biogeochem/FatesCohortMod.F90 index df04360d18..5b3155dcab 100644 --- a/biogeochem/FatesCohortMod.F90 +++ b/biogeochem/FatesCohortMod.F90 @@ -522,7 +522,7 @@ subroutine Create(this, prt, pft, nn, hite, coage, dbh, status, & ! set up values for a newly created cohort ! ARGUMENTS - class(fates_cohort_type), intent(inout), :: this ! cohort object + class(fates_cohort_type), intent(inout), target :: this ! cohort object class(prt_vartypes), intent(inout), pointer :: prt ! The allocated PARTEH object integer, intent(in) :: pft ! cohort Plant Functional Type integer, intent(in) :: crowndamage ! cohort damage class From f22540da7a3a84ee0fe98074b7685673d0b2ad6f Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 16 May 2023 11:42:13 -0700 Subject: [PATCH 707/852] Add bash script --- tools/luh2.sh | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tools/luh2.sh diff --git a/tools/luh2.sh b/tools/luh2.sh new file mode 100644 index 0000000000..08a673741b --- /dev/null +++ b/tools/luh2.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# Note that this script must be run with the luh2 conda environment + +# Regrid the luh2 data against a target surface data set +python luh2.py -l ~/Data/luh2/states.nc -s ~/Data/luh2/staticData_quarterdeg.nc \ + -rt ~/Data/luh2/surfdata_4x5_16pfts_Irrig_CMIP6_simyr2000_c170824.nc \ + -rs regridder.nc \ + -o LUH2_historical_0850_2015_4x5.nc + +# Regrid the luh2 transitions data using the saved regridder file and merge into previous regrid output +python luh2.py -l ~/Data/luh2/transitions.nc \ + -rf regridder.nc \ + -m LUH2_historical_0850_2015_4x5.nc \ + -o LUH2_historical_0850_2015_4x5.nc + +# Regrid the luh2 management data using the saved regridder file and merge into previous regrid output +python luh2.py -l ~/Data/luh2/management.nc \ + -rf regridder.nc \ + -m LUH2_historical_0850_2015_4x5.nc \ + -o LUH2_historical_0850_2015_4x5.nc From f93741bd32927b41eb1ee6cf6268aa6eb68a70c8 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 16 May 2023 12:52:58 -0600 Subject: [PATCH 708/852] fix crown_damage --- main/EDInitMod.F90 | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 8a72e542ae..15fe7113d6 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -751,13 +751,12 @@ subroutine init_cohorts(site_in, patch_in, bc_in) class(prt_vartypes), pointer :: prt ! PARTEH object integer :: leaf_status ! cohort phenology status [leaves on/off] integer :: pft ! index for PFT - integer :: crowndamage ! crown damage class integer :: iage ! index for leaf age loop integer :: el ! index for element loop integer :: element_id ! element index consistent with defs in PRTGeneric integer :: use_pft_local(numpft) ! determine whether this PFT is used for this patch and site integer :: crown_damage ! crown damage class of the cohort [1 = undamaged, >1 = damaged] - real(r8) :: l2fr ! leaf to fineroot biomass ratio [0-1] + real(r8) :: l2fr ! leaf to fineroot biomass ratio [kg kg-1] real(r8) :: canopy_trim ! fraction of the maximum leaf biomass that we are targeting [0-1] real(r8) :: cohort_n ! cohort density real(r8) :: dbh ! cohort dbh [cm] @@ -847,14 +846,14 @@ subroutine init_cohorts(site_in, patch_in, bc_in) ! Calculate the leaf biomass from allometry ! (calculates a maximum first, then applies canopy trim) - call bleaf(dbh, pft, crowndamage, canopy_trim, c_leaf) + call bleaf(dbh, pft, crown_damage, canopy_trim, c_leaf) endif ! sp mode else ! interpret as initial diameter and calculate density if (hlm_use_nocomp .eq. itrue) then dbh = abs(EDPftvarcon_inst%initd(pft)) ! calculate crown area of a single plant - call carea_allom(dbh, 1.0_r8, init_spread_inventory, pft, crowndamage, & + call carea_allom(dbh, 1.0_r8, init_spread_inventory, pft, crown_damage, & c_area) ! calculate initial density required to close canopy @@ -862,7 +861,7 @@ subroutine init_cohorts(site_in, patch_in, bc_in) ! Calculate the leaf biomass from allometry ! (calculates a maximum first, then applies canopy trim) - call bleaf(dbh, pft, crowndamage, canopy_trim, c_leaf) + call bleaf(dbh, pft, crown_damage, canopy_trim, c_leaf) else write(fates_log(),*) 'Negative fates_recruit_init_density can only be used in no comp mode' @@ -871,7 +870,7 @@ subroutine init_cohorts(site_in, patch_in, bc_in) endif ! calculate total above-ground biomass from allometry - call bagw_allom(dbh, pft, crowndamage, c_agw) + call bagw_allom(dbh, pft, crown_damage, c_agw) ! calculate coarse root biomass from allometry call bbgw_allom(dbh, pft, c_bgw) @@ -881,10 +880,10 @@ subroutine init_cohorts(site_in, patch_in, bc_in) call bfineroot(dbh, pft, canopy_trim, l2fr, c_fnrt) ! Calculate sapwood biomass - call bsap_allom(dbh, pft, crowndamage, canopy_trim, a_sapw, c_sapw) + call bsap_allom(dbh, pft, crown_damage, canopy_trim, a_sapw, c_sapw) call bdead_allom(c_agw, c_bgw, c_sapw, pft, c_struct) - call bstore_allom(dbh, pft, crowndamage, canopy_trim, c_store) + call bstore_allom(dbh, pft, crown_damage, canopy_trim, c_store) leaf_status = leaves_on @@ -979,7 +978,7 @@ subroutine init_cohorts(site_in, patch_in, bc_in) call create_cohort(site_in, patch_in, pft, cohort_n, & EDPftvarcon_inst%hgt_min(pft), 0.0_r8, dbh, prt, leaf_status, recruitstatus, & - canopy_trim, c_area, 1, crowndamage, site_in%spread, bc_in) + canopy_trim, c_area, 1, crown_damage, site_in%spread, bc_in) endif !use_this_pft enddo !numpft From 9ec55457128a60cbcc76996f202ab1ace761589d Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 16 May 2023 16:00:28 -0700 Subject: [PATCH 709/852] update UpdateParamAPI tool This allows for dimensionality updates using the variable_change flag --- .../archive/api25.4.0_041023_pr958.xml | 7 +- tools/UpdateParamAPI.py | 74 +++++++++++++++---- 2 files changed, 65 insertions(+), 16 deletions(-) diff --git a/parameter_files/archive/api25.4.0_041023_pr958.xml b/parameter_files/archive/api25.4.0_041023_pr958.xml index 295bb2c1fd..15a9885a8e 100644 --- a/parameter_files/archive/api25.4.0_041023_pr958.xml +++ b/parameter_files/archive/api25.4.0_041023_pr958.xml @@ -1,12 +1,12 @@ - + - + @@ -36,14 +36,17 @@ fates_pft -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4 + threshold for drought phenology (or lower threshold for semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm) fates_pft -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9 + upper threshold for drought phenology (only for drought semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm) fates_pft 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 + day threshold compared against days since leaves abscised (shed) fates_phen_drought_model diff --git a/tools/UpdateParamAPI.py b/tools/UpdateParamAPI.py index 0d8f47abf0..129bfeed45 100755 --- a/tools/UpdateParamAPI.py +++ b/tools/UpdateParamAPI.py @@ -346,7 +346,7 @@ def main(): sel_values = selectvalues(ncfile,list(dimnames),ipft_list,values,dcode) - [ncfile,ncvar] = createvar(ncfile,paramname,dimnames,units,longname,dcode,sel_values) + [ncfile,ncvar] = reatevar(ncfile,paramname,dimnames,units,longname,dcode,sel_values) ncfile.flush() ncfile.close() @@ -373,25 +373,71 @@ def main(): ncfile = netcdf.netcdf_file(base_nc,"a",mmap=False) ncvar_o = ncfile.variables[paramname_o] - dims_o = ncvar_o.dimensions + # dims_o = ncvar_o.dimensions dtype_o = ncvar_o.typecode() units_o = ncvar_o.units.decode("utf-8") longname_o = ncvar_o.long_name.decode("utf-8") - + + # Check for a parameter name change try: - paramname = mod.find('na').text.strip() + newparamname = mod.find('na').text.strip() + except: + newparamname = None + + # Check for a dimensionality change + try: + dimnames = tuple(mod.find('di').text.replace(" ","").split(',')) except: - paramname = None + dimnames = None - # Change the parameter's name - if(not isinstance(paramname,type(None))): - if not dims_o: - [ncfile,ncvar] = createvar(ncfile,paramname,dims_o,units_o,longname_o,dtype_o,float(ncvar_o.data)) + # Change the parameter's name and/or the dimensionality + if(not isinstance(newparamname,type(None)) or not isinstance(dimnames,type(None))): + + # Initialize the parameter name to pass to the create variable function + # If this is None, a dimension update is happening and this will be updated + # below + paramname = newparamname + + # If no dimension change, use the previous dimensions + if not dimnames: + dims_o = ncvar_o.dimensions + else: + # If dimension to change to is scalar, set dims_o to an empty list + if(dimnames[0]=='scalar' or dimnames[0]=='none' or dimnames[0]==''): + dims_o = () + else: + dims_o = dimnames + + # If there is no dimension change grab the original data + if (isinstance(dimnames,type(None))): + if not dims_o: + ncvardata = float(ncvar_o.data) + # [ncfile,ncvar] = createvar(ncfile,paramname,dims_o,units_o,longname_o,dtype_o,float(ncvar_o.data)) + else: + ncvardata = ncvar_o[:].copy() + # [ncfile,ncvar] = createvar(ncfile,paramname,dims_o,units_o,longname_o,dtype_o,ncvar_o[:].copy()) + # If there is a dimension change create zero filled data else: - [ncfile,ncvar] = createvar(ncfile,paramname,dims_o,units_o,longname_o,dtype_o,ncvar_o[:].copy()) + # If there isn't a parameter name change, grab the old name + if (isinstance(paramname,type(None))): + paramname = paramname_o + + # If changing to scalar + if not dims_o: + ncvardata = 0. + # read the dimensions and create a + else: + dimsize = [] + for idim,name in enumerate(dimnames): + dimsize.append(ncfile.dimensions[name]) + ncvardata = np.zeros(dimsize) + + # Create the new variable + [ncfile,ncvar] = createvar(ncfile,paramname,dims_o,units_o,longname_o,dtype_o,ncvardata) + else: ncvar = ncvar_o - + # Change the metadata: try: units = mod.find('un').text.strip() @@ -426,9 +472,9 @@ def main(): ncfile.close() # Finally, if we did perform a re-name, and - # created a new variable. We need to delete the - # old one - if(not isinstance(paramname,type(None))): + # created a new variable. We need to delete the old one + # This is not necessary for a dimension only change + if(not isinstance(newparamname,type(None))): removevar(base_nc,paramname_o) paramname = paramname_o From ea5d83a241cd05ac0c30388137e53407d382e9ca Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 16 May 2023 16:06:09 -0700 Subject: [PATCH 710/852] update parameter file This parameter file update uses the UpdateParamApi tool, which results in slightly different formatting due to line length limits. This also corrects the discrepency in the mindaysoff naming --- .../archive/api25.4.0_041023_pr958.xml | 2 +- parameter_files/fates_params_default.cdl | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/parameter_files/archive/api25.4.0_041023_pr958.xml b/parameter_files/archive/api25.4.0_041023_pr958.xml index 15a9885a8e..a2f22209d1 100644 --- a/parameter_files/archive/api25.4.0_041023_pr958.xml +++ b/parameter_files/archive/api25.4.0_041023_pr958.xml @@ -23,7 +23,7 @@ archive/api25.4.0_041023_fates_params_default.cdl - fates_params_default_test.cdl + fates_params_default.cdl 1,2,3,4,5,6,7,8,9,10,11,12 diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 7761e46e47..25b36a57f1 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -449,7 +449,7 @@ variables: double fates_phen_fnrt_drop_fraction(fates_pft) ; fates_phen_fnrt_drop_fraction:units = "fraction" ; fates_phen_fnrt_drop_fraction:long_name = "fraction of fine roots to drop during drought/cold" ; - double fates_phen_doff_time(fates_pft) ; + double fates_phen_mindaysoff(fates_pft) ; fates_phen_mindaysoff:units = "days" ; fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves abscised (shed)" ; double fates_phen_moist_threshold(fates_pft) ; @@ -1259,8 +1259,9 @@ data: fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_phen_drought_threshold = -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, - -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4 ; + fates_phen_drought_threshold = -152957.4, -152957.4, -152957.4, -152957.4, + -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, + -152957.4, -152957.4 ; fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; @@ -1269,10 +1270,12 @@ data: fates_phen_fnrt_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_phen_mindaysoff = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 ; + fates_phen_mindaysoff = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; - fates_phen_moist_threshold = -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, - -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9 ; + fates_phen_moist_threshold = -122365.9, -122365.9, -122365.9, -122365.9, + -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, + -122365.9, -122365.9 ; fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; From 34f804b3ff359c55862b320a973ce8557448c61a Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Wed, 17 May 2023 10:27:14 -0700 Subject: [PATCH 711/852] Update biogeochem/EDPatchDynamicsMod.F90 fixed spelling of comments Co-authored-by: Marcos Longo <5891904+mpaiao@users.noreply.github.com> --- biogeochem/EDPatchDynamicsMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 8b39565909..32b0535a48 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -2100,7 +2100,7 @@ subroutine create_patch(currentSite, new_patch, age, areap, label,nocomp_pft) ! Until bc's are pointed to by sites give veg a default temp [K] real(r8), parameter :: temp_init_veg = 15._r8+t_water_freeze_k_1atm - real(r8), parameter :: init_seedling_par = 5.0_r8 !arbtrary initialization for + real(r8), parameter :: init_seedling_par = 5.0_r8 !arbitrary initialization for !seedling layer PAR [MJ m-2 d-1] real(r8), parameter :: init_seedling_smp = -26652.0_r8 !arbitrary initialization of smp [mm] From fe98bd0e5a0df9515a7c9f83c36fb9027bb57e12 Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Wed, 17 May 2023 10:30:00 -0700 Subject: [PATCH 712/852] Update biogeochem/EDPhysiologyMod.F90 update regeneration_model flag Co-authored-by: Marcos Longo <5891904+mpaiao@users.noreply.github.com> --- biogeochem/EDPhysiologyMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 42f16d2ce7..1012c92480 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1858,7 +1858,7 @@ subroutine SeedIn( currentSite, bc_in ) litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)/area ! If we are using the Tree Recruitment Scheme (TRS) with or w/o seedling dynamics - if ( regeneration_model >= TRS .and. & + if ( any(regeneration_model == [TRS, TRS_no_seedling_dyn]) .and. & prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees) then ! Send a fraction of reproductive carbon to litter to account for From f3dfcb1fc332568f6871938017264f4676dcafbb Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Wed, 17 May 2023 10:30:21 -0700 Subject: [PATCH 713/852] Update biogeochem/EDPhysiologyMod.F90 update regeneration model flag Co-authored-by: Marcos Longo <5891904+mpaiao@users.noreply.github.com> --- biogeochem/EDPhysiologyMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 1012c92480..c1f7f8fbe0 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1956,7 +1956,7 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) ! If the TRS is switched on and the pft is a tree then add non-seed reproductive biomass ! to the seed decay flux. This was added to litt%seed_decay in the previously called SeedIn ! subroutine - if ( regeneration_model >= TRS .and. & + if ( any(regeneration_model == [TRS, TRS_no_seedling_dyn]) .and. & prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees ) then litt%seed_decay(pft) = litt%seed_decay(pft) + &! From non-seed reproductive biomass (added in From e3e60df0daf61c1365574e8c7ec27d9c4d5d158b Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Wed, 17 May 2023 10:43:38 -0700 Subject: [PATCH 714/852] Update biogeochem/EDPhysiologyMod.F90 avoid calculating seedling mort rate when it is not needed Co-authored-by: Marcos Longo <5891904+mpaiao@users.noreply.github.com> --- biogeochem/EDPhysiologyMod.F90 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index c1f7f8fbe0..1fbeb13293 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1993,13 +1993,13 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) seedling_mdds = currentPatch%sdlng_mdd(pft)%p%GetMean() ! Calculate seedling mortality as a function of moisture deficit days (mdd) - seedling_h2o_mort_rate = EDPftvarcon_inst%seedling_h2o_mort_a(pft) * seedling_mdds**2 + & - EDPftvarcon_inst%seedling_h2o_mort_b(pft) * seedling_mdds + & - EDPftvarcon_inst%seedling_h2o_mort_c(pft) - ! If the seedling mmd value is below a critical threshold then moisture-based mortality is zero if (seedling_mdds < EDPftvarcon_inst%seedling_mdd_crit(pft)) then seedling_h2o_mort_rate = 0.0_r8 + else + seedling_h2o_mort_rate = EDPftvarcon_inst%seedling_h2o_mort_a(pft) * seedling_mdds**2 + & + EDPftvarcon_inst%seedling_h2o_mort_b(pft) * seedling_mdds + & + EDPftvarcon_inst%seedling_h2o_mort_c(pft) end if ! mdd threshold check ! Step 3. Sum modes of mortality (including background mortality) and send dead seedlings From 89b7cb0238f40416c55e02aef88331e28bb7f793 Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Wed, 17 May 2023 12:10:53 -0700 Subject: [PATCH 715/852] Update parteh/PRTAllometricCarbonMod.F90 update the regeneration_model flag Co-authored-by: Marcos Longo <5891904+mpaiao@users.noreply.github.com> --- parteh/PRTAllometricCarbonMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 14197a34d7..d02a9f8e7f 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -990,7 +990,7 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) ! If the TRS is switched on (with or w/o seedling dynamics) then reproductive allocation is ! a pft-specific function of dbh. This allows for the representation of different ! reproductive schedules (Wenk and Falster, 2015) - else if ( regeneration_model >= TRS .and. & + else if ( any(regeneration_model == [TRS, TRS_no_seedling_dyn]) .and. & prt_params%allom_dbh_maxheight(ipft) > min_max_dbh_for_trees ) then repro_fraction = prt_params%seed_alloc(ipft) * & From 384255d2695d8ed6d17ba673ad6c98fffc88c631 Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Wed, 17 May 2023 13:13:11 -0600 Subject: [PATCH 716/852] small updates made to comments, indents, and the regeneration model switch in response to code review --- main/FatesConstantsMod.F90 | 8 ++++-- main/FatesInterfaceMod.F90 | 46 ++++++++++++++----------------- main/FatesRestartInterfaceMod.F90 | 4 +-- 3 files changed, 27 insertions(+), 31 deletions(-) diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index a662050f68..a3c0047bb3 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -197,9 +197,7 @@ module FatesConstantsMod ! Conversion: megajoules per joule real(fates_r8), parameter, public :: megajoules_per_joule = 1.0E-6_fates_r8 - ! Conversion: megapascals per mm H2O suction - real(fates_r8), parameter, public :: mpa_per_mm_suction = 1.0E-5_fates_r8 - + ! Conversion: days per second real(fates_r8), parameter, public :: days_per_sec = 1.0_fates_r8/86400.0_fates_r8 @@ -249,6 +247,10 @@ module FatesConstantsMod ! Pascals to megapascals real(fates_r8), parameter, public :: mpa_per_pa = 1.e-6_fates_r8 + ! Conversion: megapascals per mm H2O suction + real(fates_r8), parameter, public :: mpa_per_mm_suction = dens_fresh_liquid_water * & + grav_earth * 1.0E-9_fates_r8 + ! For numerical inquiry real(fates_r8), parameter, public :: fates_huge = huge(g_per_kg) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 02ab768fcd..39e54bfe0c 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1990,13 +1990,6 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) ! Calculate new_seedling_layer_par (total PAR at the lowest leaf layer of the lowest canopy layer) ! using the weighted average of direct and diffuse par. - ! Notes to code reviewers on calculating "new_seedling_layer_par" (4-11-2023): - ! 1. Charlie or Ryan, can you please verify that weighted-avg approach is indeed getting - ! *total* par at the lowest leaf layer of the lowest canopy layer? - ! 2. This variable currently might create a seedling layer par that is too dark because - ! it assumes that all seedlings are hiding under larger trees? Where the canopy is closed this is - ! OK, but in open forest it will overesimtae shade expected by seedlings I think? - ! What if the sun_frac weight above were multiplied by bc_in(s)%solad_parb(ifp,ipar) instead? new_seedling_layer_par = & (cpatch%parprof_dir_z(cpatch%ncl_p,n_leaf) * lai_sun_frac) + & (cpatch%parprof_dif_z(cpatch%ncl_p,n_leaf) * (1.0_r8 - lai_sun_frac)) @@ -2016,26 +2009,27 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) !write(fates_log(),*) 'new_seedling_layer_par', new_seedling_layer_par do pft = 1,numpft + + ! Calculate the soil moisture at the seedling rooting depth for each pft + + ilayer_seedling_root(pft) = minloc(abs(bc_in(s)%z_sisl(:)-EDPftvarcon_inst%seedling_root_depth(pft)),dim=1) + new_seedling_layer_smp(pft) = bc_in(s)%smp_sl(ilayer_seedling_root(pft)) + + ! Calculate the new moisture deficit day (mdd) value for each pft + new_seedling_mdd(pft) = (abs(EDPftvarcon_inst%seedling_psi_crit(pft)) - abs(new_seedling_layer_smp(pft))) & + * (-1.0_r8) * sdlng_mdd_timescale + + ! If mdds are negative then it means that soil is wetter than smp_crit and the moisture + ! deficit is 0 + if (new_seedling_mdd(pft) < 0.0_r8) then + new_seedling_mdd(pft) = 0.0_r8 + endif + + ! Update the seedling layer smp and mdd running means + call cpatch%sdlng_emerg_smp(pft)%p%UpdateRMean(new_seedling_layer_smp(pft)) + call cpatch%sdlng_mdd(pft)%p%UpdateRMean(new_seedling_mdd(pft)) - ! Calculate the soil moisture at the seedling rooting depth for each pft - - ilayer_seedling_root(pft) = minloc(abs(bc_in(s)%z_sisl(:)-EDPftvarcon_inst%seedling_root_depth(pft)),dim=1) - new_seedling_layer_smp(pft) = bc_in(s)%smp_sl(ilayer_seedling_root(pft)) - - ! Calculate the new moisture deficit day (mdd) value for each pft - new_seedling_mdd(pft) = (abs(EDPftvarcon_inst%seedling_psi_crit(pft)) - abs(new_seedling_layer_smp(pft))) & - * (-1.0_r8) * sdlng_mdd_timescale - - ! If mdds are negative then it means that soil is wetter than smp_crit and the moisture - ! deficit is 0 - if (new_seedling_mdd(pft) < 0.0_r8) then - new_seedling_mdd(pft) = 0.0_r8 - endif - - ! Update the seedling layer smp and mdd running means - call cpatch%sdlng_emerg_smp(pft)%p%UpdateRMean(new_seedling_layer_smp(pft)) - call cpatch%sdlng_mdd(pft)%p%UpdateRMean(new_seedling_mdd(pft)) - enddo ! + enddo !end pft loop !ccohort => cpatch%tallest !do while (associated(ccohort)) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 7b36de7a21..6109bd8a6b 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -3179,8 +3179,8 @@ subroutine get_restart_vectors(this, nc, nsites, sites) call this%GetRMeanRestartVar(cpatch%sdlng2sap_par, ir_sdlng2sap_par_pa,io_idx_co_1st) do pft = 1, maxpft - call this%GetRMeanRestartVar(cpatch%sdlng_mdd(pft)%p, ir_sdlng_mdd_pa,io_idx_co_1st) - call this%GetRMeanRestartVar(cpatch%sdlng_emerg_smp(pft)%p, ir_sdlng_emerg_smp_pa,io_idx_co_1st) + call this%GetRMeanRestartVar(cpatch%sdlng_mdd(pft)%p, ir_sdlng_mdd_pa,io_idx_co_1st) + call this%GetRMeanRestartVar(cpatch%sdlng_emerg_smp(pft)%p, ir_sdlng_emerg_smp_pa,io_idx_co_1st) enddo ! set cohorts per patch for IO From eb79dd83d6d38de17e6f9b2eed5073c9dbd5f95b Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 17 May 2023 16:41:58 -0700 Subject: [PATCH 717/852] refactoring luh2 module This refactor is to account for a misunderstanding in the way that the reuse of a saved regridder weights file is to be applied. --- tools/luh2.py | 103 +++++++++++++++++++++-------------------------- tools/luh2.sh | 34 +++++++++------- tools/luh2mod.py | 35 ++++++++-------- 3 files changed, 86 insertions(+), 86 deletions(-) mode change 100644 => 100755 tools/luh2.sh diff --git a/tools/luh2.py b/tools/luh2.py index 53c65bf875..720780ad43 100644 --- a/tools/luh2.py +++ b/tools/luh2.py @@ -15,72 +15,67 @@ def main(): # Allow variable input files (state and/or transitions and/or management) args = CommandLineArgs() - - # Prep the LUH2 datasets and regrid target + # Import and prep the LUH2 datasets and regrid target ds_luh2 = ImportData(args.luh2_file,args.begin,args.end) + ds_regrid_target = ImportData(args.regridder_target_file,args.begin,args.end) - if (args.regridder_file == None): - ds_regrid_target = ImportData(args.regridder_target_file,args.begin,args.end) - - # Import the LUH2 static data to use for masking - ds_luh2_static = ImportData(args.luh2_static_file) - - # Create new variable where the ice water fraction is inverted w - ds_luh2_static["landfrac"] = 1 - ds_luh2_static.icwtr - - # Mask all LUH2 input data using the ice/water fraction for the LUH2 static data - ds_luh2 = SetMaskLUH2(ds_luh2, ds_luh2_static) - ds_luh2_static = SetMaskLUH2(ds_luh2_static, ds_luh2_static) + # Import the LUH2 static data to use for masking + ds_luh2_static = ImportData(args.luh2_static_file) - # Mask the regrid target - ds_regrid_target = SetMaskSurfData(ds_regrid_target) + # Create new variable where the ice water fraction is inverted w + ds_luh2_static["landfrac"] = 1 - ds_luh2_static.icwtr - # Handle regridder file save name - # TO DO: add check to handle if the user enters the full path - # TO DO: check if its possible to enter nothing with the argument - if (args.regridder_save_name == None): - regridder_save_file = None - print("Warning: Regridder will not be saved to file") - else: - regridder_save_file = args.regridder_save_name + # Mask all LUH2 input data using the ice/water fraction for the LUH2 static data + ds_luh2 = SetMaskLUH2(ds_luh2, ds_luh2_static) + ds_luh2_static = SetMaskLUH2(ds_luh2_static, ds_luh2_static) - # Regrid the luh2 data to the target grid - # TO DO: provide a check for the save argument based on the input arguments - regrid_luh2,regridder_luh2 = RegridConservative(ds_luh2, ds_regrid_target, regridder_save_file) + # Mask the regrid target + ds_regrid_target = SetMaskSurfData(ds_regrid_target) - elif (args.regridder_target_file == None): - regridder_luh2 = ImportData(args.regridder_file) - regrid_luh2 = RegridLoop(ds_luh2,regridder_luh2) - # TO DO: check that the time bounds match the argument bounds - - # # Regrid the inverted ice/water fraction data to the target grid - #regridder_land_fraction = RegridConservative(ds_luh2_static, ds_regrid_target) - #regrid_land_fraction = regridder_land_fraction(ds_luh2_static) + # Determine if we are saving a new regridder or using an old one + # TO DO: add check to handle if the user enters the full path + # TO DO: check if its possible to enter nothing with the argument + regrid_reuse = False + # If we are merging files together, we assume that the weights file + # being supplied exists on file + if (not isinstance(args.luh2_merge_file,type(None))): + regrid_reuse = True + + # Regrid the luh2 data to the target grid + # TO DO: provide a check for the save argument based on the input arguments + regrid_luh2,regridder_luh2 = RegridConservative(ds_luh2, ds_regrid_target, + args.regridder_weights, regrid_reuse) + + # Regrid the inverted ice/water fraction data to the target grid regrid_land_fraction = regridder_luh2(ds_luh2_static) # Adjust the luh2 data by the land fraction + # TO DO: determine if this is necessary for the transitions and management data regrid_luh2 = regrid_luh2 / regrid_land_fraction.landfrac - # Correct the state sum (will be returned as if in not state values) + # Correct the state sum (checks if argument passed is state file in the function) regrid_luh2 = CorrectStateSum(regrid_luh2) - # Add additional required variables for the host land model - # Add 'YEAR' as a variable. - # This is an old requirement of the HLM and should simply be a copy of the `time` dimension - regrid_luh2["YEAR"] = regrid_luh2.time - regrid_luh2["LONGXY"] = ds_regrid_target["LONGXY"] # TO DO: double check if this is strictly necessary - regrid_luh2["LATIXY"] = ds_regrid_target["LATIXY"] # TO DO: double check if this is strictly necessary - - # Rename the dimensions for the output - regrid_luh2 = regrid_luh2.rename_dims({'lat':'lsmlat','lon':'lsmlon'}) - # Merge existing regrided luh2 file with merge input target # TO DO: check that the grid resolution and time bounds match if (not(isinstance(args.luh2_merge_file,type(None)))): ds_luh2_merge = ImportData(args.luh2_merge_file) regrid_luh2 = regrid_luh2.merge(ds_luh2_merge) + # Add additional required variables for the host land model + # Add 'YEAR' as a variable. + # This is an old requirement of the HLM and should simply be a copy of the `time` dimension + # If we are merging, we might not need to do this, so check to see if its there already + if (not "YEAR" in list(regrid_luh2.variables)): + regrid_luh2["YEAR"] = regrid_luh2.time + regrid_luh2["LONGXY"] = ds_regrid_target["LONGXY"] # TO DO: double check if this is strictly necessary + regrid_luh2["LATIXY"] = ds_regrid_target["LATIXY"] # TO DO: double check if this is strictly necessary + + # Rename the dimensions for the output. This needs to happen after the "LONGXY/LATIXY" assignment + if ('lat' in list(regrid_luh2.dims)): + regrid_luh2 = regrid_luh2.rename_dims({'lat':'lsmlat','lon':'lsmlon'}) + # Write the files # TO DO: add check to handle if the user enters the full path if (args.output == None): @@ -103,18 +98,14 @@ def CommandLineArgs(): # TO DO: using the checking function to report back if invalid file input parser.add_argument("-l","--luh2_file", required=True) - # Provide mutually exlusive arguments for regridding input selection - # Currently assuming that if a target is provided that a regridder file will be saved - regrid_target = parser.add_mutually_exclusive_group(required=True) - regrid_target.add_argument("-rf","--regridder_file") # use previously save regridder file - regrid_target.add_argument("-rt","--regridder_target_file") # use a dataset to regrid to + # Required static luh2 data to get the ice/water fraction for masking + parser.add_argument("-s", "--luh2_static_file", required=True) - # TO DO: static file is required if regridder file argument is not used - # Required static luh2 data to get the ice/water fraction - parser.add_argument("-s", "--luh2_static_file") + # File to use as regridder target (e.g. a surface dataset) + parser.add_argument("-r","--regridder_target_file", required=True) - # Optional argument for defining the regridder file name - parser.add_argument("-rs", "--regridder_save_name") + # Filename to use or save for the regridder weights + parser.add_argument("-w", "--regridder_weights", required=True) # Optional input to subset the time range of the data parser.add_argument("-b","--begin") diff --git a/tools/luh2.sh b/tools/luh2.sh old mode 100644 new mode 100755 index 08a673741b..3b179f206c --- a/tools/luh2.sh +++ b/tools/luh2.sh @@ -1,21 +1,27 @@ #!/bin/bash - # Note that this script must be run with the luh2 conda environment +# LUH2 data names +export DATA_LOC=~/Data/luh2 +export STATES_FILE=states_modified.nc +export STATIC_FILE=staticData_quarterdeg.nc +export REGRID_TARGET_FILE=surfdata_4x5_16pfts_Irrig_CMIP6_simyr2000_c170824.nc + +# Save files +export REGRID_SAVE=regridder.nc +export OUTPUT=LUH2_historical_0850_2015_4x5.nc + +# Combine strings +export STATES=${DATA_LOC}/${STATES_FILE} +export STATIC=${DATA_LOC}/${STATIC_FILE} +export REGRID_TARGET=${DATA_LOC}/${REGRID_TARGET_FILE} + + # Regrid the luh2 data against a target surface data set -python luh2.py -l ~/Data/luh2/states.nc -s ~/Data/luh2/staticData_quarterdeg.nc \ - -rt ~/Data/luh2/surfdata_4x5_16pfts_Irrig_CMIP6_simyr2000_c170824.nc \ - -rs regridder.nc \ - -o LUH2_historical_0850_2015_4x5.nc +python luh2.py -l ${STATES} -s ${STATIC} -r ${REGRID_TARGET} -w ${REGRID_SAVE} -o ${OUTPUT} -# Regrid the luh2 transitions data using the saved regridder file and merge into previous regrid output -python luh2.py -l ~/Data/luh2/transitions.nc \ - -rf regridder.nc \ - -m LUH2_historical_0850_2015_4x5.nc \ - -o LUH2_historical_0850_2015_4x5.nc +# Regrid the luh2 transitions data using the saved regridder weights file and merge into previous regrid output +# python luh2.py -l ${STATES} -s ${STATIC} -rt ${REGRID_TARGET} -rf ${REGRID_SAVE} -m ${OUTPUT} -o ${OUTPUT} # Regrid the luh2 management data using the saved regridder file and merge into previous regrid output -python luh2.py -l ~/Data/luh2/management.nc \ - -rf regridder.nc \ - -m LUH2_historical_0850_2015_4x5.nc \ - -o LUH2_historical_0850_2015_4x5.nc +# python luh2.py -l ${STATES} -s ${STATIC} -rt ${REGRID_TARGET} -rf ${REGRID_SAVE} -m ${OUTPUT} -o ${OUTPUT} diff --git a/tools/luh2mod.py b/tools/luh2mod.py index aab8aba228..c92e57eab3 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -203,16 +203,33 @@ def CheckDataset(input_dataset): return(dsflag,dstype) -def RegridConservative(ds_to_regrid,ds_regrid_target,regridder_save_file): +def RegridConservative(ds_to_regrid, ds_regrid_target, regridder_weights, regrid_reuse): # define the regridder transformation - regridder = GenerateRegridder(ds_to_regrid, ds_regrid_target, regridder_save_file) + regridder = GenerateRegridder(ds_to_regrid, ds_regrid_target, regridder_weights, regrid_reuse) # Loop through the variables to regrid ds_regrid = RegridLoop(ds_to_regrid, regridder) return (ds_regrid, regridder) +def GenerateRegridder(ds_to_regrid, ds_regrid_target, regridder_weights_file, regrid_reuse): + + regrid_method = "conservative" + print("\nDefining regridder, method: ", regrid_method) + + if (regrid_reuse): + regridder = xe.Regridder(ds_to_regrid, ds_regrid_target, + regrid_method, weights=regridder_weights_file) + else: + regridder = xe.Regridder(ds_to_regrid, ds_regrid_target, regrid_method) + + # If we are not reusing the regridder weights file, then save the regridder + filename = regridder.to_netcdf(regridder_weights_file) + print("regridder saved to file: ", filename) + + return(regridder) + def RegridLoop(ds_to_regrid, regridder): # To Do: implement this with dask @@ -248,20 +265,6 @@ def RegridLoop(ds_to_regrid, regridder): return(ds_regrid) -def GenerateRegridder(ds_to_regrid, ds_regrid_target,regridder_save_file): - - regrid_method = "conservative" - print("\nDefining regridder, method: ", regrid_method) - regridder = xe.Regridder(ds_to_regrid, ds_regrid_target, regrid_method) - - # If save flag is set, write regridder to a file - # TO DO: define a more useful name based on inputs - if(not(isinstance(regridder_save_file,type(None)))): - filename = regridder.to_netcdf(regridder_save_file) - print("regridder saved to file: ", filename) - - return(regridder) - # Temporary: Add minor correction factor to assure states sum to one def CorrectStateSum(input_dataset): From 1941e66cccb5778f51f879481340023dca6d9aee Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 17 May 2023 17:11:24 -0700 Subject: [PATCH 718/852] Add merge flag to import data This avoids prepping the data if its already been prepped --- tools/luh2.py | 3 +-- tools/luh2mod.py | 14 +++++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/tools/luh2.py b/tools/luh2.py index 720780ad43..7b18b0655c 100644 --- a/tools/luh2.py +++ b/tools/luh2.py @@ -19,7 +19,6 @@ def main(): ds_luh2 = ImportData(args.luh2_file,args.begin,args.end) ds_regrid_target = ImportData(args.regridder_target_file,args.begin,args.end) - # Import the LUH2 static data to use for masking ds_luh2_static = ImportData(args.luh2_static_file) @@ -60,7 +59,7 @@ def main(): # Merge existing regrided luh2 file with merge input target # TO DO: check that the grid resolution and time bounds match if (not(isinstance(args.luh2_merge_file,type(None)))): - ds_luh2_merge = ImportData(args.luh2_merge_file) + ds_luh2_merge = ImportData(args.luh2_merge_file,True) regrid_luh2 = regrid_luh2.merge(ds_luh2_merge) # Add additional required variables for the host land model diff --git a/tools/luh2mod.py b/tools/luh2mod.py index c92e57eab3..a815773203 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -8,7 +8,7 @@ from nco.custom import Atted # Import luh2 or surface data sets -def ImportData(input_file,start=None,stop=None): +def ImportData(input_file,start=None,stop=None,merge_flag=False): # Open files # Check to see if a ValueError is raised which is likely due @@ -25,13 +25,13 @@ def ImportData(input_file,start=None,stop=None): else: print("Input file dataset opened: {}".format(input_file)) - datasetout = PrepDataset(datasetout,start,stop) + datasetout = PrepDataset(datasetout,start,stop,merge_flag) return(datasetout) # Prepare the input_file to be used for regridding -def PrepDataset(input_dataset,start=None,stop=None): +def PrepDataset(input_dataset,start=None,stop=None,merge_flag=False): # Use the maximum span if start and stop are not present dsflag, dstype = CheckDataset(input_dataset) @@ -53,7 +53,9 @@ def PrepDataset(input_dataset,start=None,stop=None): raise TypeError(type_err) # Correct the necessary variables for both datasets - input_dataset = PrepDataset_ESMF(input_dataset,dsflag,dstype) + # We don't need to Prep the incoming dataset if it's being opened to merge + if(not merge_flag): + input_dataset = PrepDataset_ESMF(input_dataset,dsflag,dstype) return(input_dataset) @@ -183,7 +185,9 @@ def CheckDataset(input_dataset): dsflag = False dsvars = list(input_dataset.variables) - if('primf' in dsvars or 'primf_to_secdn' in dsvars or 'irrig' in dsvars): + if('primf' in dsvars or + 'primf_to_secdn' in dsvars or + any('irrig' in subname for subname in dsvars)): dstype = 'LUH2' dsflag = True print("LUH2") From 1cee03040442cab51ce04d44c0d1484a8734f62f Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 17 May 2023 23:56:21 -0700 Subject: [PATCH 719/852] fix order of operations --- tools/luh2.py | 21 +++++++++++---------- tools/luh2.sh | 10 +++++++--- tools/luh2mod.py | 1 + 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/tools/luh2.py b/tools/luh2.py index 7b18b0655c..71e8b777c4 100644 --- a/tools/luh2.py +++ b/tools/luh2.py @@ -56,12 +56,6 @@ def main(): # Correct the state sum (checks if argument passed is state file in the function) regrid_luh2 = CorrectStateSum(regrid_luh2) - # Merge existing regrided luh2 file with merge input target - # TO DO: check that the grid resolution and time bounds match - if (not(isinstance(args.luh2_merge_file,type(None)))): - ds_luh2_merge = ImportData(args.luh2_merge_file,True) - regrid_luh2 = regrid_luh2.merge(ds_luh2_merge) - # Add additional required variables for the host land model # Add 'YEAR' as a variable. # This is an old requirement of the HLM and should simply be a copy of the `time` dimension @@ -72,23 +66,30 @@ def main(): regrid_luh2["LATIXY"] = ds_regrid_target["LATIXY"] # TO DO: double check if this is strictly necessary # Rename the dimensions for the output. This needs to happen after the "LONGXY/LATIXY" assignment - if ('lat' in list(regrid_luh2.dims)): + if (not 'lsmlat' in list(regrid_luh2.dims)): regrid_luh2 = regrid_luh2.rename_dims({'lat':'lsmlat','lon':'lsmlon'}) + # Merge existing regrided luh2 file with merge input target + # TO DO: check that the grid resolution + # We could do this with an append during the write phase instead of the merge + if (not(isinstance(args.luh2_merge_file,type(None)))): + ds_luh2_merge = ImportData(args.luh2_merge_file,args.begin,args.end,merge_flag=True) + #ds_luh2_merge = ds_luh2_merge.merge(regrid_luh2) + regrid_luh2 = regrid_luh2.merge(ds_luh2_merge) + # Write the files # TO DO: add check to handle if the user enters the full path + # TO DO: add check if user sets the output the same as the input if (args.output == None): output_filename = 'LUH2_timeseries.nc' else: output_filename = args.output + output_file = os.path.join(os.getcwd(),output_filename) print("generating output: {}".format(output_file)) regrid_luh2.to_netcdf(output_file) - # Example of file naming scheme - # finb_luh2_all_regrid.to_netcdf('LUH2_historical_1850_2015_4x5_cdk_220302.nc') - def CommandLineArgs(): parser = argparse.ArgumentParser(description="placeholder desc") diff --git a/tools/luh2.sh b/tools/luh2.sh index 3b179f206c..710c771811 100755 --- a/tools/luh2.sh +++ b/tools/luh2.sh @@ -4,6 +4,8 @@ # LUH2 data names export DATA_LOC=~/Data/luh2 export STATES_FILE=states_modified.nc +export TRANSITIONS_FILE=transitions_modified.nc +export MANAGE_FILE=management_modified.nc export STATIC_FILE=staticData_quarterdeg.nc export REGRID_TARGET_FILE=surfdata_4x5_16pfts_Irrig_CMIP6_simyr2000_c170824.nc @@ -13,15 +15,17 @@ export OUTPUT=LUH2_historical_0850_2015_4x5.nc # Combine strings export STATES=${DATA_LOC}/${STATES_FILE} +export TRANSITIONS=${DATA_LOC}/${TRANSITIONS_FILE} +export MANAGE=${DATA_LOC}/${MANAGE_FILE} export STATIC=${DATA_LOC}/${STATIC_FILE} export REGRID_TARGET=${DATA_LOC}/${REGRID_TARGET_FILE} # Regrid the luh2 data against a target surface data set -python luh2.py -l ${STATES} -s ${STATIC} -r ${REGRID_TARGET} -w ${REGRID_SAVE} -o ${OUTPUT} +python luh2.py -l ${STATES} -s ${STATIC} -r ${REGRID_TARGET} -w ${REGRID_SAVE} -o states_regrid.nc # Regrid the luh2 transitions data using the saved regridder weights file and merge into previous regrid output -# python luh2.py -l ${STATES} -s ${STATIC} -rt ${REGRID_TARGET} -rf ${REGRID_SAVE} -m ${OUTPUT} -o ${OUTPUT} +python luh2.py -l ${TRANSITIONS} -s ${STATIC} -r ${REGRID_TARGET} -w ${REGRID_SAVE} -m states_regrid.nc -o states_trans_regrid.nc # Regrid the luh2 management data using the saved regridder file and merge into previous regrid output -# python luh2.py -l ${STATES} -s ${STATIC} -rt ${REGRID_TARGET} -rf ${REGRID_SAVE} -m ${OUTPUT} -o ${OUTPUT} +python luh2.py -l ${MANAGE} -s ${STATIC} -r ${REGRID_TARGET} -w ${REGRID_SAVE} -m states_trans_regrid.nc -o ${OUTPUT} diff --git a/tools/luh2mod.py b/tools/luh2mod.py index a815773203..815cf8f22c 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -267,6 +267,7 @@ def RegridLoop(ds_to_regrid, regridder): else: print("skipping variable {}/{}: {}".format(i+1, varlen, ds_varnames[i])) + print("\n") return(ds_regrid) # Temporary: Add minor correction factor to assure states sum to one From 4eadfb7081f6b843b3854a324c0c894f447691f8 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 18 May 2023 12:58:50 -0700 Subject: [PATCH 720/852] add commands to remove intermediate file copies This helps mitigate loss of storage space --- tools/luh2.sh | 51 ++++++++++++++++++++++++++++++++++++++++-------- tools/luh2mod.py | 18 ++++++++--------- 2 files changed, 51 insertions(+), 18 deletions(-) diff --git a/tools/luh2.sh b/tools/luh2.sh index 710c771811..c68057a245 100755 --- a/tools/luh2.sh +++ b/tools/luh2.sh @@ -1,11 +1,16 @@ #!/bin/bash +# WARNING: This script generates intermediate copies of the LUH2 +# data which at its peak takes up approximately 42G of space. +# # Note that this script must be run with the luh2 conda environment +# It requires a single argument that points to the full path location +# of the luh2 data and the dataset to regrid against # LUH2 data names -export DATA_LOC=~/Data/luh2 -export STATES_FILE=states_modified.nc -export TRANSITIONS_FILE=transitions_modified.nc -export MANAGE_FILE=management_modified.nc +export DATA_LOC=$1 +export STATES_FILE=states.nc +export TRANSITIONS_FILE=transitions.nc +export MANAGE_FILE=management.nc export STATIC_FILE=staticData_quarterdeg.nc export REGRID_TARGET_FILE=surfdata_4x5_16pfts_Irrig_CMIP6_simyr2000_c170824.nc @@ -19,13 +24,43 @@ export TRANSITIONS=${DATA_LOC}/${TRANSITIONS_FILE} export MANAGE=${DATA_LOC}/${MANAGE_FILE} export STATIC=${DATA_LOC}/${STATIC_FILE} export REGRID_TARGET=${DATA_LOC}/${REGRID_TARGET_FILE} +export REGRIDDER=${DATA_LOC}/${REGRID_SAVE} +# Create copies of the luh2 data that have the time data modified +# Comment this out if the user already has the modified datasets available -# Regrid the luh2 data against a target surface data set -python luh2.py -l ${STATES} -s ${STATIC} -r ${REGRID_TARGET} -w ${REGRID_SAVE} -o states_regrid.nc +# Update that filename to point to + +# Regrid the luh2 data against a target surface data set and then remove the states_modified file +echo "starting storage" +du -h ${DATA_LOC} +echo "Correcting LUH2 time data for ${STATES}" +python -c "from luh2mod import AttributeUpdateLUH2; AttributeUpdateLUH2('${STATES}')" +export STATES=${DATA_LOC}/states_modified.nc +python luh2.py -l ${STATES} -s ${STATIC} -r ${REGRID_TARGET} -w ${REGRIDDER} -o ${DATA_LOC}/states_regrid.nc +echo -e"storage status:\n" +du -h ${DATA_LOC} +rm ${STATES} # Regrid the luh2 transitions data using the saved regridder weights file and merge into previous regrid output -python luh2.py -l ${TRANSITIONS} -s ${STATIC} -r ${REGRID_TARGET} -w ${REGRID_SAVE} -m states_regrid.nc -o states_trans_regrid.nc +echo "Correcting LUH2 time data for ${TRANSITIONS}" +python -c "from luh2mod import AttributeUpdateLUH2; AttributeUpdateLUH2('${TRANSITIONS}')" +export TRANSITIONS=${DATA_LOC}/transitions_modified.nc +python luh2.py -l ${TRANSITIONS} -s ${STATIC} -r ${REGRID_TARGET} -w ${REGRIDDER} \ + -m ${DATA_LOC}/states_regrid.nc -o ${DATA_LOC}/states_trans_regrid.nc +echo -e"storage status:\n" +du -h ${DATA_LOC} +rm ${TRANSITIONS} +rm ${DATA_LOC}/states_regrid.nc # Regrid the luh2 management data using the saved regridder file and merge into previous regrid output -python luh2.py -l ${MANAGE} -s ${STATIC} -r ${REGRID_TARGET} -w ${REGRID_SAVE} -m states_trans_regrid.nc -o ${OUTPUT} +echo "Correcting LUH2 time data for ${MANAGE}" +python -c "from luh2mod import AttributeUpdateLUH2; AttributeUpdateLUH2('${MANAGE}')" +export MANAGE=${DATA_LOC}/management_modified.nc +python luh2.py -l ${MANAGE} -s ${STATIC} -r ${REGRID_TARGET} -w ${REGRIDDER} \ + -m ${DATA_LOC}/states_trans_regrid.nc -o ${OUTPUT} +echo -e"storage status:\n" +du -h ${DATA_LOC} +rm ${MANAGE} +rm ${DATA_LOC}/states_trans_regrid.nc +rm ${REGRIDDER} diff --git a/tools/luh2mod.py b/tools/luh2mod.py index 815cf8f22c..62c4312187 100644 --- a/tools/luh2mod.py +++ b/tools/luh2mod.py @@ -73,13 +73,13 @@ def PrepDataset_ESMF(input_dataset,dsflag,dstype): return(input_dataset) - # Modify the luh2 metadata to enable xarray to read in data # This issue here is that the luh2 time units start prior to # year 1672, which cftime should be able to handle, but it # appears to need a specific unit name convention "common_years" -def AttribUpdateLUH2(input_file,output_append="modified"): +def AttributeUpdateLUH2(input_file,output_append="modified"): + # TO DO: Make this so that it can handle more than just absolute file location # Define the output filename index = input_file.find(".nc") output_file = input_file[:index] + "_" + output_append + input_file[index:] @@ -100,21 +100,22 @@ def AttribUpdateLUH2(input_file,output_append="modified"): opts = [" -a {0},{1},o,{2},{3}".format(att, var, att_type, newstr)] nco.ncatted(input=input_file, output=output_file, options=opts) - print("Generated modified output file: {}\n".format(output_file)) - - return(output_file) - # The following is fixed with PR #62 for pynco but isn't in that latest update yet # on conda # nco.ncatted(input=input_file,output=output_file,options=[ # Atted(mode="overwrite", # att_name="units", # var_name="time", - # value=newstr + # value=newstr, # stype="c" # ), # ]) + print("Generated modified output file: {}\n".format(output_file)) + + return(output_file) + + # Create the necessary variable "lat_b" and "lon_b" for xESMF conservative regridding # Each lat/lon boundary array is a 2D array corresponding to the bounds of each # coordinate position (e.g. lat_boundary would be 90.0 and 89.75 for lat coordinate @@ -292,9 +293,6 @@ def CorrectStateSum(input_dataset): # Save the correction value input_dataset["stscf"] = 1.0 / state_sum - # If this is the transitions data apply the state correction to the transitions - # elif (any('_to_' in var for var in input_dataset)): - return(input_dataset) # General functionality needed From e6278f637ba4f87d45ac58dea9953340d80abe6a Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 18 May 2023 13:07:14 -0700 Subject: [PATCH 721/852] move all luh2 code into named folder --- tools/{ => luh2}/conda-luh2.yml | 0 tools/{ => luh2}/luh2.py | 0 tools/{ => luh2}/luh2.sh | 0 tools/{ => luh2}/luh2mod.py | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename tools/{ => luh2}/conda-luh2.yml (100%) rename tools/{ => luh2}/luh2.py (100%) rename tools/{ => luh2}/luh2.sh (100%) rename tools/{ => luh2}/luh2mod.py (100%) diff --git a/tools/conda-luh2.yml b/tools/luh2/conda-luh2.yml similarity index 100% rename from tools/conda-luh2.yml rename to tools/luh2/conda-luh2.yml diff --git a/tools/luh2.py b/tools/luh2/luh2.py similarity index 100% rename from tools/luh2.py rename to tools/luh2/luh2.py diff --git a/tools/luh2.sh b/tools/luh2/luh2.sh similarity index 100% rename from tools/luh2.sh rename to tools/luh2/luh2.sh diff --git a/tools/luh2mod.py b/tools/luh2/luh2mod.py similarity index 100% rename from tools/luh2mod.py rename to tools/luh2/luh2mod.py From 21c573b03dac6c2dd763aaa4c09a32533f27d411 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 19 May 2023 12:03:18 -0700 Subject: [PATCH 722/852] correct indexing for elongation factor --- parteh/PRTAllometricCNPMod.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 4072e907b6..71032f467c 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -2283,9 +2283,9 @@ function AllomCNPGrowthDeriv(l_state_array,l_state_mask,cbalance,intgr_params) r ipft = int(intgr_params(intgr_parm_pft)) l2fr = intgr_params(intgr_parm_l2fr) crown_damage = int(intgr_params(intgr_parm_cdamage)) - elongf_leaf = intgr_params(acnp_bc_in_id_efleaf) - elongf_fnrt = intgr_params(acnp_bc_in_id_effnrt) - elongf_stem = intgr_params(acnp_bc_in_id_efstem) + elongf_leaf = intgr_params(intgr_parm_efleaf) + elongf_fnrt = intgr_params(intgr_parm_effnrt) + elongf_stem = intgr_params(intgr_parm_efstem) call bleaf(dbh,ipft,crown_damage,canopy_trim, elongf_leaf, leaf_c_target,leaf_dcdd_target) call bfineroot(dbh,ipft,canopy_trim,l2fr, elongf_fnrt, fnrt_c_target,fnrt_dcdd_target) From 28bcafc8219bb2373d9c4492856cb46a64654b5a Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 23 May 2023 15:41:28 -0700 Subject: [PATCH 723/852] convert YEAR from cftime object to number --- tools/luh2/luh2.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/luh2/luh2.py b/tools/luh2/luh2.py index 71e8b777c4..1e5c5ef857 100644 --- a/tools/luh2/luh2.py +++ b/tools/luh2/luh2.py @@ -4,6 +4,7 @@ # Usage: python luh2.py -l -s import argparse, os +from cftime import date2num from luh2mod import ImportData, SetMaskLUH2, SetMaskSurfData from luh2mod import RegridConservative, RegridLoop, CorrectStateSum @@ -61,7 +62,7 @@ def main(): # This is an old requirement of the HLM and should simply be a copy of the `time` dimension # If we are merging, we might not need to do this, so check to see if its there already if (not "YEAR" in list(regrid_luh2.variables)): - regrid_luh2["YEAR"] = regrid_luh2.time + regrid_luh2["YEAR"] = date2num(regrid_luh2.time,'common_years since 0-00-00 00:00:00') regrid_luh2["LONGXY"] = ds_regrid_target["LONGXY"] # TO DO: double check if this is strictly necessary regrid_luh2["LATIXY"] = ds_regrid_target["LATIXY"] # TO DO: double check if this is strictly necessary From 934ad20c221d58264575d4bea067ec37fb1dcfde Mon Sep 17 00:00:00 2001 From: Marcos Longo Date: Wed, 24 May 2023 13:34:51 -0700 Subject: [PATCH 724/852] Changed defaults for drought deciduous. --- parameter_files/archive/api25.4.0_041023_pr958.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/parameter_files/archive/api25.4.0_041023_pr958.xml b/parameter_files/archive/api25.4.0_041023_pr958.xml index a2f22209d1..311a6a00b8 100644 --- a/parameter_files/archive/api25.4.0_041023_pr958.xml +++ b/parameter_files/archive/api25.4.0_041023_pr958.xml @@ -33,6 +33,10 @@ Leaf longevity (ie turnover timescale). For drought-deciduous PFTs, this also indicates the maximum length of the growing (i.e., leaves on) season. + + fates_pft + 1.2, 1.2, 1.2, 1.2, 2.4, 1.2, 1.2, 2.4, 1.2, 1.2, 1.2, 1.2 + fates_pft -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4 @@ -48,6 +52,10 @@ 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 day threshold compared against days since leaves abscised (shed) + + fates_pft + 50, 62, 39, 61, 58, 58, 62, 54, 54, 78, 78, 78 + fates_phen_drought_model From a178f9da840d75a75e54c7594fcff2037cdeeff1 Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Tue, 30 May 2023 19:03:01 -0700 Subject: [PATCH 725/852] bugfixes to reduce memory usage and interpret cftime reference point --- tools/luh2/luh2.py | 2 +- tools/luh2/luh2mod.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/luh2/luh2.py b/tools/luh2/luh2.py index 1e5c5ef857..78385b6284 100644 --- a/tools/luh2/luh2.py +++ b/tools/luh2/luh2.py @@ -62,7 +62,7 @@ def main(): # This is an old requirement of the HLM and should simply be a copy of the `time` dimension # If we are merging, we might not need to do this, so check to see if its there already if (not "YEAR" in list(regrid_luh2.variables)): - regrid_luh2["YEAR"] = date2num(regrid_luh2.time,'common_years since 0-00-00 00:00:00') + regrid_luh2["YEAR"] = date2num(regrid_luh2.time,'common_years since 0-01-01 00:00:00') regrid_luh2["LONGXY"] = ds_regrid_target["LONGXY"] # TO DO: double check if this is strictly necessary regrid_luh2["LATIXY"] = ds_regrid_target["LATIXY"] # TO DO: double check if this is strictly necessary diff --git a/tools/luh2/luh2mod.py b/tools/luh2/luh2mod.py index 62c4312187..a26ae68727 100644 --- a/tools/luh2/luh2mod.py +++ b/tools/luh2/luh2mod.py @@ -14,7 +14,7 @@ def ImportData(input_file,start=None,stop=None,merge_flag=False): # Check to see if a ValueError is raised which is likely due # to the LUH2 time units being undecodable by cftime module try: - datasetout = xr.open_dataset(input_file) + datasetout = xr.open_dataset(input_file, cache=False) except ValueError as err: print("ValueError:", err) errmsg = "User direction: If error is due to units being 'years since ...' " \ From befe7ddbd5593365feeaf851262dba67015a502c Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 5 Jun 2023 21:20:32 -0400 Subject: [PATCH 726/852] Adding the fates_rad_model to the parameter file --- main/EDParamsMod.F90 | 11 +++++++++++ main/EDPftvarcon.F90 | 12 +++++++++++- parameter_files/archive/api25.4.0_041023_pr958.xml | 9 ++++++++- parameter_files/fates_params_default.cdl | 14 +++++++++----- tools/UpdateParamAPI.py | 2 +- 5 files changed, 40 insertions(+), 8 deletions(-) diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 3db869715c..3ee56df5f2 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -36,6 +36,8 @@ module EDParamsMod integer,protected, public :: photo_tempsens_model ! switch for choosing the model that defines the temperature ! sensitivity of photosynthetic parameters (vcmax, jmax). ! 1=non-acclimating, 2=Kumarathunge et al., 2019 + + integer,protected, public :: radiation_model ! Switch betrween Norman (1) and Two-stream (2) radiation models real(r8),protected, public :: fates_mortality_disturbance_fraction ! the fraction of canopy mortality that results in disturbance real(r8),protected, public :: ED_val_comp_excln ! weighting factor for canopy layer exclusion and promotion @@ -94,6 +96,7 @@ module EDParamsMod character(len=param_string_length),parameter,public :: ED_name_photo_temp_acclim_thome_time = "fates_leaf_photo_temp_acclim_thome_time" character(len=param_string_length),parameter,public :: name_photo_tempsens_model = "fates_leaf_photo_tempsens_model" character(len=param_string_length),parameter,public :: name_maintresp_model = "fates_maintresp_leaf_model" + character(len=param_string_length),parameter,public :: name_radiation_model = "fates_rad_model" character(len=param_string_length),parameter,public :: ED_name_hydr_htftype_node = "fates_hydro_htftype_node" character(len=param_string_length),parameter,public :: ED_name_mort_disturb_frac = "fates_mort_disturb_frac" character(len=param_string_length),parameter,public :: ED_name_comp_excln = "fates_comp_excln" @@ -263,6 +266,7 @@ subroutine FatesParamsInit() photo_temp_acclim_thome_time = nan photo_tempsens_model = -9 maintresp_leaf_model = -9 + radiation_model = -9 fates_mortality_disturbance_fraction = nan ED_val_comp_excln = nan ED_val_vai_top_bin_width = nan @@ -349,6 +353,9 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=name_photo_tempsens_model,dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=name_radiation_model,dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=name_maintresp_model,dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -550,6 +557,10 @@ subroutine FatesReceiveParams(fates_params) data=tmpreal) photo_tempsens_model = nint(tmpreal) + call fates_params%RetrieveParameter(name=name_radiation_model, & + data=tmpreal) + radiation_model = nint(tmpreal) + call fates_params%RetrieveParameter(name=name_maintresp_model, & data=tmpreal) maintresp_leaf_model = nint(tmpreal) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index caf061d9c8..aff0303b9b 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -25,7 +25,7 @@ module EDPftvarcon use FatesConstantsMod , only : prescribed_n_uptake use FatesConstantsMod , only : coupled_p_uptake use FatesConstantsMod , only : coupled_n_uptake - + ! CIME Globals use shr_log_mod , only : errMsg => shr_log_errMsg @@ -1533,6 +1533,7 @@ subroutine FatesCheckParams(is_master) use FatesConstantsMod , only : itrue, ifalse use EDParamsMod , only : logging_mechanical_frac, logging_collateral_frac use EDParamsMod , only : logging_direct_frac,logging_export_frac + use EDParamsMod , only : radiation_model use FatesInterfaceTypesMod, only : hlm_use_fixed_biogeog,hlm_use_sp, hlm_name use FatesInterfaceTypesMod, only : hlm_use_inventory_init @@ -1555,6 +1556,15 @@ subroutine FatesCheckParams(is_master) if(.not.is_master) return + if(radiation_model.ne.1) then + write(fates_log(),*) 'The only available canopoy radiation model' + write(fates_log(),*) 'is the Norman scheme: fates_rad_model = 1' + write(fates_log(),*) 'The two-stream scheme is not available yet' + write(fates_log(),*) 'You specified fates_rad_model = ',radiation_model + write(fates_log(),*) 'Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + select case (hlm_parteh_mode) case (prt_cnp_flex_allom_hyp) diff --git a/parameter_files/archive/api25.4.0_041023_pr958.xml b/parameter_files/archive/api25.4.0_041023_pr958.xml index 311a6a00b8..2aa90e35ff 100644 --- a/parameter_files/archive/api25.4.0_041023_pr958.xml +++ b/parameter_files/archive/api25.4.0_041023_pr958.xml @@ -6,7 +6,7 @@ - + @@ -59,5 +59,12 @@ fates_phen_drought_model + + fates_rad_model + scalar + unitless + switch designating the model for canopy radiation, 1 = Norman, 2 = Two-stream (experimental) + 1 + diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 25b36a57f1..bed78d180c 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1,4 +1,4 @@ -netcdf fates_params_default { +netcdf tmp { dimensions: fates_NCWD = 4 ; fates_history_age_bins = 7 ; @@ -365,7 +365,7 @@ variables: double fates_leaf_stomatal_slope_medlyn(fates_pft) ; fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; - double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; + double fates_leaf_vcmax25top(fates_pft) ; fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; double fates_leaf_vcmaxha(fates_pft) ; @@ -785,6 +785,9 @@ variables: double fates_q10_mr ; fates_q10_mr:units = "unitless" ; fates_q10_mr:long_name = "Q10 for maintenance respiration" ; + double fates_rad_model ; + fates_rad_model:units = "unitless" ; + fates_rad_model:long_name = "switch designating the model for canopy radiation, 1 = Norman, 2 = Two-stream (experimental)" ; double fates_soil_salinity ; fates_soil_salinity:units = "ppt" ; fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; @@ -854,7 +857,7 @@ data: 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; - fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 2.4, 1.2, 1.2, 2.4, 1.2, 1.2, 1.2, 1.2 ; fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, @@ -1193,8 +1196,7 @@ data: fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, 4.7, 2.2, 5.3, 1.6 ; - fates_leaf_vcmax25top = - 50, 62, 39, 61, 41, 58, 62, 54, 54, 78, 78, 78 ; + fates_leaf_vcmax25top = 50, 62, 39, 61, 58, 58, 62, 54, 54, 78, 78, 78 ; fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330 ; @@ -1551,6 +1553,8 @@ data: fates_q10_mr = 1.5 ; + fates_rad_model = 1 ; + fates_soil_salinity = 0.4 ; fates_vai_top_bin_width = 1 ; diff --git a/tools/UpdateParamAPI.py b/tools/UpdateParamAPI.py index 129bfeed45..f23ef5d24c 100755 --- a/tools/UpdateParamAPI.py +++ b/tools/UpdateParamAPI.py @@ -346,7 +346,7 @@ def main(): sel_values = selectvalues(ncfile,list(dimnames),ipft_list,values,dcode) - [ncfile,ncvar] = reatevar(ncfile,paramname,dimnames,units,longname,dcode,sel_values) + [ncfile,ncvar] = createvar(ncfile,paramname,dimnames,units,longname,dcode,sel_values) ncfile.flush() ncfile.close() From afb8194ca9a1f90850c34a2639bba56877f26e1d Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 6 Jun 2023 13:26:58 -0400 Subject: [PATCH 727/852] Added TRS recruitment parameters --- .../archive/api25.4.0_041023_pr958.xml | 161 ++++++++++++++++++ parameter_files/fates_params_default.cdl | 141 +++++++++++++++ 2 files changed, 302 insertions(+) diff --git a/parameter_files/archive/api25.4.0_041023_pr958.xml b/parameter_files/archive/api25.4.0_041023_pr958.xml index 2aa90e35ff..38672ab4de 100644 --- a/parameter_files/archive/api25.4.0_041023_pr958.xml +++ b/parameter_files/archive/api25.4.0_041023_pr958.xml @@ -66,5 +66,166 @@ switch designating the model for canopy radiation, 1 = Norman, 2 = Two-stream (experimental) 1 + + fates_trs_repro_alloc_a + fates_pft + fraction + shape parameter for sigmoidal function relating dbh to reproductive allocation + 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049 + + + fates_trs_repro_alloc_b + fates_pft + fraction + intercept parameter for sigmoidal function relating dbh to reproductive allocation + -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171 + + + fates_trs_repro_frac_seed + fates_pft + fraction + fraction of reproductive mass that is seed + 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24 + + + fates_trs_seedling_a_emerg + fates_pft + day -1 + mean fraction of seed bank emerging + 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003 + + + fates_trs_seedling_b_emerg + fates_pft + day -1 + seedling emergence sensitivity to soil moisture + 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 + + + fates_trs_seedling_par_crit_germ + fates_pft + MJ m-2 day-1 + critical light level for germination + 0.656, 0.656, 0.656, 0.656, 0.656, 0.656, 0.656, 0.656, 0.656, 0.656, 0.656, 0.656 + + + fates_trs_seedling_root_depth + fates_pft + m + rooting depth of seedlings + 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06 + + + fates_trs_seedling_psi_emerg + fates_pft + mm h20 suction + critical soil moisture for seedling emergence + -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65 + + + fates_trs_seedling_psi_crit + fates_pft + mm H2O + critical soil moisture (suction) for seedling stress + -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7 + + + fates_trs_seedling_mdd_crit + fates_pft + mm H2O day + critical moisture deficit (suction) day accumulation for seedling moisture-based seedling mortality to begin + 1400000.0, 1400000.0, 1400000.0, 1400000.0, 1400000.0, 1400000.0, 1400000.0, 1400000.0, 1400000.0, 1400000.0, 1400000.0, 1400000.0 + + + fates_trs_seedling_h2o_mort_a + fates_pft + - + coefficient in moisture-based seedling mortality + 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17 + + + fates_trs_seedling_h2o_mort_b + fates_pft + - + coefficient in moisture-based seedling mortality + -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11 + + + fates_trs_seedling_h2o_mort_c + fates_pft + - + coefficient in moisture-based seedling mortality + 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05 + + + fates_trs_seedling_light_mort_a + fates_pft + - + light-based seedling mortality coefficient + -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694 + + + fates_trs_seedling_light_mort_b + fates_pft + - + light-based seedling mortality coefficient + -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063 + + + fates_trs_seedling_background_mort + fates_pft + yr-1 + background seedling mortality rate + 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371 + + + fates_trs_seedling_light_rec_a + fates_pft + - + coefficient in light-based seedling to sapling transition + 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, 0.007 + + + fates_trs_seedling_light_rec_b + fates_pft + - + coefficient in light-based seedling to sapling transition + 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615 + + + fates_regeneration_model + scalar + - + switch for choosing between FATES's default regeneration scheme (1), the full Tree Recruitment Scheme (2; Hanbury-Brown et al., 2022), or (3) the Tree Recruitment Scheme without seedling dynamics + 1 + + + fates_trs_seedling_emerg_h2o_timescale + scalar + days + Length of the window for the exponential moving average of smp used to calculate seedling emergence + 7 + + + fates_trs_seedling_mort_par_timescale + scalar + days + Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling mortality + 32 + + + fates_trs_seedling_mdd_timescale + scalar + days + Length of the window for the exponential moving average of moisture deficit days used to calculate seedling mortality + 126 + + + fates_trs_seedling2sap_par_timescale + scalar + days + Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling to sapling transition rates + 32 + diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index bed78d180c..350f6ee97c 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -536,6 +536,60 @@ variables: double fates_trim_limit(fates_pft) ; fates_trim_limit:units = "m2/m2" ; fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; + double fates_trs_repro_alloc_a(fates_pft) ; + fates_trs_repro_alloc_a:units = "fraction" ; + fates_trs_repro_alloc_a:long_name = "shape parameter for sigmoidal function relating dbh to reproductive allocation" ; + double fates_trs_repro_alloc_b(fates_pft) ; + fates_trs_repro_alloc_b:units = "fraction" ; + fates_trs_repro_alloc_b:long_name = "intercept parameter for sigmoidal function relating dbh to reproductive allocation" ; + double fates_trs_repro_frac_seed(fates_pft) ; + fates_trs_repro_frac_seed:units = "fraction" ; + fates_trs_repro_frac_seed:long_name = "fraction of reproductive mass that is seed" ; + double fates_trs_seedling_a_emerg(fates_pft) ; + fates_trs_seedling_a_emerg:units = "day -1" ; + fates_trs_seedling_a_emerg:long_name = "mean fraction of seed bank emerging" ; + double fates_trs_seedling_b_emerg(fates_pft) ; + fates_trs_seedling_b_emerg:units = "day -1" ; + fates_trs_seedling_b_emerg:long_name = "seedling emergence sensitivity to soil moisture" ; + double fates_trs_seedling_background_mort(fates_pft) ; + fates_trs_seedling_background_mort:units = "yr-1" ; + fates_trs_seedling_background_mort:long_name = "background seedling mortality rate" ; + double fates_trs_seedling_h2o_mort_a(fates_pft) ; + fates_trs_seedling_h2o_mort_a:units = "-" ; + fates_trs_seedling_h2o_mort_a:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_trs_seedling_h2o_mort_b(fates_pft) ; + fates_trs_seedling_h2o_mort_b:units = "-" ; + fates_trs_seedling_h2o_mort_b:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_trs_seedling_h2o_mort_c(fates_pft) ; + fates_trs_seedling_h2o_mort_c:units = "-" ; + fates_trs_seedling_h2o_mort_c:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_trs_seedling_light_mort_a(fates_pft) ; + fates_trs_seedling_light_mort_a:units = "-" ; + fates_trs_seedling_light_mort_a:long_name = "light-based seedling mortality coefficient" ; + double fates_trs_seedling_light_mort_b(fates_pft) ; + fates_trs_seedling_light_mort_b:units = "-" ; + fates_trs_seedling_light_mort_b:long_name = "light-based seedling mortality coefficient" ; + double fates_trs_seedling_light_rec_a(fates_pft) ; + fates_trs_seedling_light_rec_a:units = "-" ; + fates_trs_seedling_light_rec_a:long_name = "coefficient in light-based seedling to sapling transition" ; + double fates_trs_seedling_light_rec_b(fates_pft) ; + fates_trs_seedling_light_rec_b:units = "-" ; + fates_trs_seedling_light_rec_b:long_name = "coefficient in light-based seedling to sapling transition" ; + double fates_trs_seedling_mdd_crit(fates_pft) ; + fates_trs_seedling_mdd_crit:units = "mm H2O day" ; + fates_trs_seedling_mdd_crit:long_name = "critical moisture deficit (suction) day accumulation for seedling moisture-based seedling mortality to begin" ; + double fates_trs_seedling_par_crit_germ(fates_pft) ; + fates_trs_seedling_par_crit_germ:units = "MJ m-2 day-1" ; + fates_trs_seedling_par_crit_germ:long_name = "critical light level for germination" ; + double fates_trs_seedling_psi_crit(fates_pft) ; + fates_trs_seedling_psi_crit:units = "mm H2O" ; + fates_trs_seedling_psi_crit:long_name = "critical soil moisture (suction) for seedling stress" ; + double fates_trs_seedling_psi_emerg(fates_pft) ; + fates_trs_seedling_psi_emerg:units = "mm h20 suction" ; + fates_trs_seedling_psi_emerg:long_name = "critical soil moisture for seedling emergence" ; + double fates_trs_seedling_root_depth(fates_pft) ; + fates_trs_seedling_root_depth:units = "m" ; + fates_trs_seedling_root_depth:long_name = "rooting depth of seedlings" ; double fates_turb_displar(fates_pft) ; fates_turb_displar:units = "unitless" ; fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; @@ -788,9 +842,24 @@ variables: double fates_rad_model ; fates_rad_model:units = "unitless" ; fates_rad_model:long_name = "switch designating the model for canopy radiation, 1 = Norman, 2 = Two-stream (experimental)" ; + double fates_regeneration_model ; + fates_regeneration_model:units = "-" ; + fates_regeneration_model:long_name = "switch for choosing between FATES\'s default regeneration scheme (1), the full Tree Recruitment Scheme (2; Hanbury-Brown et al., 2022), or (3) the Tree Recruitment Scheme without seedling dynamics" ; double fates_soil_salinity ; fates_soil_salinity:units = "ppt" ; fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; + double fates_trs_seedling2sap_par_timescale ; + fates_trs_seedling2sap_par_timescale:units = "days" ; + fates_trs_seedling2sap_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling to sapling transition rates" ; + double fates_trs_seedling_emerg_h2o_timescale ; + fates_trs_seedling_emerg_h2o_timescale:units = "days" ; + fates_trs_seedling_emerg_h2o_timescale:long_name = "Length of the window for the exponential moving average of smp used to calculate seedling emergence" ; + double fates_trs_seedling_mdd_timescale ; + fates_trs_seedling_mdd_timescale:units = "days" ; + fates_trs_seedling_mdd_timescale:long_name = "Length of the window for the exponential moving average of moisture deficit days used to calculate seedling mortality" ; + double fates_trs_seedling_mort_par_timescale ; + fates_trs_seedling_mort_par_timescale:units = "days" ; + fates_trs_seedling_mort_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling mortality" ; double fates_vai_top_bin_width ; fates_vai_top_bin_width:units = "m2/m2" ; fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; @@ -1368,6 +1437,68 @@ data: fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; + fates_trs_repro_alloc_a = 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, + 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049 ; + + fates_trs_repro_alloc_b = -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, + -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171 ; + + fates_trs_repro_frac_seed = 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, + 0.24, 0.24, 0.24, 0.24 ; + + fates_trs_seedling_a_emerg = 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, + 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003 ; + + fates_trs_seedling_b_emerg = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + 1.2, 1.2, 1.2 ; + + fates_trs_seedling_background_mort = 0.1085371, 0.1085371, 0.1085371, + 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, + 0.1085371, 0.1085371, 0.1085371 ; + + fates_trs_seedling_h2o_mort_a = 4.070565e-17, 4.070565e-17, 4.070565e-17, + 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, + 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17 ; + + fates_trs_seedling_h2o_mort_b = -6.390757e-11, -6.390757e-11, -6.390757e-11, + -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, + -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11 ; + + fates_trs_seedling_h2o_mort_c = 1.268992e-05, 1.268992e-05, 1.268992e-05, + 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, + 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05 ; + + fates_trs_seedling_light_mort_a = -0.009897694, -0.009897694, -0.009897694, + -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, + -0.009897694, -0.009897694, -0.009897694, -0.009897694 ; + + fates_trs_seedling_light_mort_b = -7.154063, -7.154063, -7.154063, + -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, + -7.154063, -7.154063, -7.154063 ; + + fates_trs_seedling_light_rec_a = 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, + 0.007, 0.007, 0.007, 0.007, 0.007, 0.007 ; + + fates_trs_seedling_light_rec_b = 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, + 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615 ; + + fates_trs_seedling_mdd_crit = 1400000, 1400000, 1400000, 1400000, 1400000, + 1400000, 1400000, 1400000, 1400000, 1400000, 1400000, 1400000 ; + + fates_trs_seedling_par_crit_germ = 0.656, 0.656, 0.656, 0.656, 0.656, 0.656, + 0.656, 0.656, 0.656, 0.656, 0.656, 0.656 ; + + fates_trs_seedling_psi_crit = -251995.7, -251995.7, -251995.7, -251995.7, + -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, + -251995.7, -251995.7 ; + + fates_trs_seedling_psi_emerg = -15744.65, -15744.65, -15744.65, -15744.65, + -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, + -15744.65, -15744.65 ; + + fates_trs_seedling_root_depth = 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, + 0.06, 0.06, 0.06, 0.06, 0.06 ; + fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67 ; @@ -1555,8 +1686,18 @@ data: fates_rad_model = 1 ; + fates_regeneration_model = 1 ; + fates_soil_salinity = 0.4 ; + fates_trs_seedling2sap_par_timescale = 32 ; + + fates_trs_seedling_emerg_h2o_timescale = 7 ; + + fates_trs_seedling_mdd_timescale = 126 ; + + fates_trs_seedling_mort_par_timescale = 32 ; + fates_vai_top_bin_width = 1 ; fates_vai_width_increase_factor = 1 ; From 894206bbbbbbf3c81147ef24cae860b057d837cf Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 6 Jun 2023 14:20:00 -0400 Subject: [PATCH 728/852] Small syntax updates to trs parameter long-names --- parameter_files/archive/api25.4.0_041023_pr958.xml | 2 +- parameter_files/fates_params_default.cdl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/parameter_files/archive/api25.4.0_041023_pr958.xml b/parameter_files/archive/api25.4.0_041023_pr958.xml index 38672ab4de..16b3af5890 100644 --- a/parameter_files/archive/api25.4.0_041023_pr958.xml +++ b/parameter_files/archive/api25.4.0_041023_pr958.xml @@ -196,7 +196,7 @@ fates_regeneration_model scalar - - switch for choosing between FATES's default regeneration scheme (1), the full Tree Recruitment Scheme (2; Hanbury-Brown et al., 2022), or (3) the Tree Recruitment Scheme without seedling dynamics + switch for choosing between FATES's: 1) default regeneration scheme , 2) the Tree Recruitment Scheme (Hanbury-Brown et al., 2022), or (3) the Tree Recruitment Scheme without seedling dynamics 1 diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 350f6ee97c..a3a210d658 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -844,7 +844,7 @@ variables: fates_rad_model:long_name = "switch designating the model for canopy radiation, 1 = Norman, 2 = Two-stream (experimental)" ; double fates_regeneration_model ; fates_regeneration_model:units = "-" ; - fates_regeneration_model:long_name = "switch for choosing between FATES\'s default regeneration scheme (1), the full Tree Recruitment Scheme (2; Hanbury-Brown et al., 2022), or (3) the Tree Recruitment Scheme without seedling dynamics" ; + fates_regeneration_model:long_name = "switch for choosing between FATES\'s: 1) default regeneration scheme , 2) the Tree Recruitment Scheme (Hanbury-Brown et al., 2022), or (3) the Tree Recruitment Scheme without seedling dynamics" ; double fates_soil_salinity ; fates_soil_salinity:units = "ppt" ; fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; From 4a14057ebaf07b2f1b215c92882da72305827b26 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 6 Jun 2023 14:33:27 -0400 Subject: [PATCH 729/852] Merged in Adam HBs definitions for pft parameters --- main/EDPftvarcon.F90 | 160 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index aff0303b9b..3547ec3e49 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -105,6 +105,24 @@ module EDPftvarcon real(r8), allocatable :: germination_rate(:) ! Fraction of seed mass germinating per year (yr-1) real(r8), allocatable :: seed_decay_rate(:) ! Fraction of seed mass (both germinated and ! ungerminated), decaying per year (yr-1) + + real(r8), allocatable :: repro_frac_seed(:) ! fraciton of reproductive carbon that is seed + real(r8), allocatable :: a_emerg(:) ! mean fraction of seed bank emerging [day-1] + real(r8), allocatable :: b_emerg(:) ! seedling emergence sensitivity to soil moisture + real(r8), allocatable :: par_crit_germ(:) ! critical light level for germination [MJ m2-1 day-1] + real(r8), allocatable :: seedling_psi_emerg(:) ! critical soil moisture for seedling emergence [mm h2o suction] + real(r8), allocatable :: seedling_psi_crit(:) ! critical soil moisture initiating seedling stress + real(r8), allocatable :: seedling_light_rec_a(:) ! coefficient in light-based seedling to sapling transition rate + real(r8), allocatable :: seedling_light_rec_b(:) ! coefficient in light-based seedling to sapling transition rate + real(r8), allocatable :: seedling_mdd_crit(:) ! critical moisture deficit day accumulation for seedling moisture-based + ! seedling mortality to begin + real(r8), allocatable :: seedling_h2o_mort_a(:) ! coefficient in moisture-based seedling mortality + real(r8), allocatable :: seedling_h2o_mort_b(:) ! coefficient in moisture-based seedling mortality + real(r8), allocatable :: seedling_h2o_mort_c(:) ! coefficient in moisture-based seedling mortality + real(r8), allocatable :: seedling_root_depth(:) ! rooting depth of seedlings [m] + real(r8), allocatable :: seedling_light_mort_a(:) ! light-based seedling mortality coefficient + real(r8), allocatable :: seedling_light_mort_b(:) ! light-based seedling mortality coefficient + real(r8), allocatable :: background_seedling_mort(:)! background seedling mortality [yr-1] real(r8), allocatable :: trim_limit(:) ! Limit to reductions in leaf area w stress (m2/m2) real(r8), allocatable :: trim_inc(:) ! Incremental change in trimming function (m2/m2) @@ -578,6 +596,70 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_trs_repro_frac_seed' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_trs_seedling_a_emerg' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_trs_seedling_b_emerg' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_trs_seedling_par_crit_germ' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_trs_seedling_psi_emerg' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_trs_seedling_psi_crit' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_trs_seedling_light_rec_a' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_trs_seedling_light_rec_b' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_trs_seedling_mdd_crit' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_trs_seedling_h2o_mort_a' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_trs_seedling_h2o_mort_b' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_trs_seedling_h2o_mort_c' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_trs_seedling_root_depth' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_trs_seedling_light_mort_a' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_trs_seedling_light_mort_b' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_trs_seedling_background_mort' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_frag_seed_decay_rate' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -941,6 +1023,70 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetrieveParameterAllocate(name=name, & data=this%germination_rate) + name = 'fates_trs_repro_frac_seed' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%repro_frac_seed) + + name = 'fates_trs_seedling_a_emerg' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%a_emerg) + + name = 'fates_trs_seedling_b_emerg' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%b_emerg) + + name = 'fates_trs_seedling_par_crit_germ' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%par_crit_germ) + + name = 'fates_trs_seedling_psi_emerg' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%seedling_psi_emerg) + + name = 'fates_trs_seedling_psi_crit' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%seedling_psi_crit) + + name = 'fates_trs_seedling_light_rec_a' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%seedling_light_rec_a) + + name = 'fates_trs_seedling_light_rec_b' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%seedling_light_rec_b) + + name = 'fates_trs_seedling_mdd_crit' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%seedling_mdd_crit) + + name = 'fates_trs_seedling_h2o_mort_a' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%seedling_h2o_mort_a) + + name = 'fates_trs_seedling_h2o_mort_b' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%seedling_h2o_mort_b) + + name = 'fates_trs_seedling_h2o_mort_c' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%seedling_h2o_mort_c) + + name = 'fates_trs_seedling_root_depth' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%seedling_root_depth) + + name = 'fates_trs_seedling_light_mort_a' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%seedling_light_mort_a) + + name = 'fates_trs_seedling_light_mort_b' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%seedling_light_mort_b) + + name = 'fates_trs_seedling_background_mort' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%background_seedling_mort) + name = 'fates_frag_seed_decay_rate' call fates_params%RetrieveParameterAllocate(name=name, & data=this%seed_decay_rate) @@ -1479,6 +1625,20 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'jmaxse = ',EDPftvarcon_inst%jmaxse write(fates_log(),fmt0) 'germination_timescale = ',EDPftvarcon_inst%germination_rate write(fates_log(),fmt0) 'seed_decay_turnover = ',EDPftvarcon_inst%seed_decay_rate + write(fates_log(),fmt0) 'repro_frac_seed = ',EDPftvarcon_inst%repro_frac_seed + write(fates_log(),fmt0) 'a_emerg = ',EDPftvarcon_inst%a_emerg + write(fates_log(),fmt0) 'b_emerg = ',EDPftvarcon_inst%b_emerg + write(fates_log(),fmt0) 'par_crit_germ = ',EDPftvarcon_inst%par_crit_germ + write(fates_log(),fmt0) 'seedling_psi_emerg = ',EDPftvarcon_inst%seedling_psi_emerg + write(fates_log(),fmt0) 'seedling_psi_crit = ',EDPftvarcon_inst%seedling_psi_crit + write(fates_log(),fmt0) 'seedling_mdd_crit = ',EDPftvarcon_inst%seedling_mdd_crit + write(fates_log(),fmt0) 'seedling_light_rec_a = ',EDPftvarcon_inst%seedling_light_rec_a + write(fates_log(),fmt0) 'seedling_light_rec_b = ',EDPftvarcon_inst%seedling_light_rec_b + write(fates_log(),fmt0) 'background_seedling_mort = ',EDPftvarcon_inst%background_seedling_mort + write(fates_log(),fmt0) 'seedling_root_depth = ',EDPftvarcon_inst%seedling_root_depth + write(fates_log(),fmt0) 'seedling_h2o_mort_a = ',EDPftvarcon_inst%seedling_h2o_mort_a + write(fates_log(),fmt0) 'seedling_h2o_mort_b = ',EDPftvarcon_inst%seedling_h2o_mort_b + write(fates_log(),fmt0) 'seedling_h2o_mort_c = ',EDPftvarcon_inst%seedling_h2o_mort_c write(fates_log(),fmt0) 'trim_limit = ',EDPftvarcon_inst%trim_limit write(fates_log(),fmt0) 'trim_inc = ',EDPftvarcon_inst%trim_inc write(fates_log(),fmt0) 'rhol = ',EDPftvarcon_inst%rhol From fea2085bd0937cbcc8085e46ba228a16e573ced9 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 6 Jun 2023 14:38:47 -0400 Subject: [PATCH 730/852] Merged in more regeneration parameter definitions and the model switch from Adams regeneration branch --- main/EDParamsMod.F90 | 65 +++++++++++++++++++++++++++++++++++++++++++- main/EDPftvarcon.F90 | 12 +++++++- 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 3ee56df5f2..f62903e7de 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -33,6 +33,16 @@ module EDParamsMod ! T_home term in Kumarathunge parameterization [years] integer,protected, public :: maintresp_leaf_model ! switch for choosing between leaf maintenance ! respiration model. 1=Ryan (1991), 2=Atkin et al (2017) + real(r8),protected, public :: sdlng_emerg_h2o_timescale !Length of the window for the exponential moving + !average of smp used to calculate seedling emergence + real(r8),protected, public :: sdlng_mort_par_timescale !Length of the window for the exponential moving average + !of par at the seedling layer used to calculate + !seedling mortality + real(r8),protected, public :: sdlng_mdd_timescale !Length of the window for the exponential moving average + ! of moisture deficit days used to calculate seedling mortality + real(r8),protected, public :: sdlng2sap_par_timescale !Length of the window for the exponential + !moving average of par at the seedling layer used to + !calculate seedling to sapling transition rates integer,protected, public :: photo_tempsens_model ! switch for choosing the model that defines the temperature ! sensitivity of photosynthetic parameters (vcmax, jmax). ! 1=non-acclimating, 2=Kumarathunge et al., 2019 @@ -60,6 +70,11 @@ 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 :: regeneration_model ! Switch for choosing between regeneration models: + ! (1) for Fates default + ! (2) for the Tree Recruitment Scheme (Hanbury-Brown et al., 2022) + ! (3) for the Tree Recruitment Scheme without seedling dynamics + logical,protected, public :: active_crown_fire ! flag, 1=active crown fire 0=no active crown fire character(len=param_string_length),parameter :: fates_name_active_crown_fire = "fates_fire_active_crown_fire" @@ -90,6 +105,11 @@ module EDParamsMod ! Switch that defines the current pressure-volume and pressure-conductivity model ! to be used at each node (compartment/organ) ! 1 = Christofferson et al. 2016 (TFS), 2 = Van Genuchten 1980 + + character(len=param_string_length),parameter,public :: ED_name_sdlng_emerg_h2o_timescale = "fates_trs_seedling_emerg_h2o_timescale" + character(len=param_string_length),parameter,public :: ED_name_sdlng_mort_par_timescale = "fates_trs_seedling_mort_par_timescale" + character(len=param_string_length),parameter,public :: ED_name_sdlng_mdd_timescale = "fates_trs_seedling_mdd_timescale" + character(len=param_string_length),parameter,public :: ED_name_sdlng2sap_par_timescale = "fates_trs_seedling2sap_par_timescale" integer, protected,allocatable,public :: hydr_htftype_node(:) character(len=param_string_length),parameter,public :: ED_name_photo_temp_acclim_timescale = "fates_leaf_photo_temp_acclim_timescale" @@ -119,6 +139,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_regeneration_model= "fates_regeneration_model" character(len=param_string_length),parameter,public :: name_theta_cj_c3 = "fates_leaf_theta_cj_c3" character(len=param_string_length),parameter,public :: name_theta_cj_c4 = "fates_leaf_theta_cj_c4" @@ -263,6 +284,10 @@ subroutine FatesParamsInit() vai_top_bin_width = nan vai_width_increase_factor = nan photo_temp_acclim_timescale = nan + sdlng_emerg_h2o_timescale = nan + sdlng_mort_par_timescale = nan + sdlng_mdd_timescale = nan + sdlng2sap_par_timescale = nan photo_temp_acclim_thome_time = nan photo_tempsens_model = -9 maintresp_leaf_model = -9 @@ -288,6 +313,7 @@ subroutine FatesParamsInit() ED_val_patch_fusion_tol = nan ED_val_canopy_closure_thresh = nan stomatal_model = -9 + regeneration_model = -9 stomatal_assim_model = -9 maxpatch_primary = -9 maxpatch_secondary = -9 @@ -347,6 +373,18 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=ED_name_photo_temp_acclim_timescale, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=ED_name_sdlng_emerg_h2o_timescale, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + + call fates_params%RegisterParameter(name=ED_name_sdlng_mort_par_timescale, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + + call fates_params%RegisterParameter(name=ED_name_sdlng_mdd_timescale, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + + call fates_params%RegisterParameter(name=ED_name_sdlng2sap_par_timescale, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=ED_name_photo_temp_acclim_thome_time, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -427,7 +465,10 @@ 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_regeneration_model, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=stomatal_assim_name, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -550,6 +591,18 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetrieveParameter(name=ED_name_photo_temp_acclim_timescale, & data=photo_temp_acclim_timescale) + call fates_params%RetrieveParameter(name=ED_name_sdlng_emerg_h2o_timescale, & + data=sdlng_emerg_h2o_timescale) + + call fates_params%RetrieveParameter(name=ED_name_sdlng_mort_par_timescale, & + data=sdlng_mort_par_timescale) + + call fates_params%RetrieveParameter(name=ED_name_sdlng_mdd_timescale, & + data=sdlng_mdd_timescale) + + call fates_params%RetrieveParameter(name=ED_name_sdlng2sap_par_timescale, & + data=sdlng2sap_par_timescale) + call fates_params%RetrieveParameter(name=ED_name_photo_temp_acclim_thome_time, & data=photo_temp_acclim_thome_time) @@ -629,6 +682,10 @@ subroutine FatesReceiveParams(fates_params) data=tmpreal) stomatal_model = nint(tmpreal) + call fates_params%RetrieveParameter(name=ED_name_regeneration_model, & + data=tmpreal) + regeneration_model = nint(tmpreal) + call fates_params%RetrieveParameter(name=stomatal_assim_name, & data=tmpreal) stomatal_assim_model = nint(tmpreal) @@ -768,6 +825,11 @@ subroutine FatesReportParams(is_master) write(fates_log(),*) '----------- FATES Scalar Parameters -----------------' write(fates_log(),fmt0) 'vai_top_bin_width = ',vai_top_bin_width write(fates_log(),fmt0) 'vai_width_increase_factor = ',vai_width_increase_factor + write(fates_log(),fmt0) 'photo_temp_acclim_timescale = ',photo_temp_acclim_timescale + write(fates_log(),fmt0) 'sdlng_emerg_h2o_timescale = ', sdlng_emerg_h2o_timescale + write(fates_log(),fmt0) 'sdlng_mort_par_timescale = ', sdlng_mort_par_timescale + write(fates_log(),fmt0) 'sdlng_mdd_timescale = ', sdlng_mdd_timescale + write(fates_log(),fmt0) 'sdlng2sap_par_timescale = ', sdlng2sap_par_timescale write(fates_log(),fmt0) 'photo_temp_acclim_timescale (days) = ',photo_temp_acclim_timescale write(fates_log(),fmt0) 'photo_temp_acclim_thome_time (years) = ',photo_temp_acclim_thome_time write(fates_log(),fmti) 'hydr_htftype_node = ',hydr_htftype_node @@ -791,6 +853,7 @@ 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) '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/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 3547ec3e49..f84cf96b9a 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1694,6 +1694,7 @@ subroutine FatesCheckParams(is_master) 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 : regeneration_model use FatesInterfaceTypesMod, only : hlm_use_fixed_biogeog,hlm_use_sp, hlm_name use FatesInterfaceTypesMod, only : hlm_use_inventory_init @@ -1717,13 +1718,22 @@ subroutine FatesCheckParams(is_master) if(.not.is_master) return if(radiation_model.ne.1) then - write(fates_log(),*) 'The only available canopoy radiation model' + write(fates_log(),*) 'The only available canopy radiation model' write(fates_log(),*) 'is the Norman scheme: fates_rad_model = 1' write(fates_log(),*) 'The two-stream scheme is not available yet' write(fates_log(),*) 'You specified fates_rad_model = ',radiation_model write(fates_log(),*) 'Aborting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if + + if(regeneration_model.ne.1) then + write(fates_log(),*) 'The only available regeneration model' + write(fates_log(),*) 'is the default, ie 1' + write(fates_log(),*) 'The Hanbury-Brown models are not available yet' + write(fates_log(),*) 'You specified fates_regeneration_model = ',regeneration_model + write(fates_log(),*) 'Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if select case (hlm_parteh_mode) From 074c043576607023c806c1f8dd654a6d2f10b12e Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 7 Jun 2023 11:53:39 -0400 Subject: [PATCH 731/852] Added AHB parameters to parteh --- parteh/PRTParametersMod.F90 | 5 +++-- parteh/PRTParamsFATESMod.F90 | 20 +++++++++++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/parteh/PRTParametersMod.F90 b/parteh/PRTParametersMod.F90 index 3dac9443c0..71cd48070c 100644 --- a/parteh/PRTParametersMod.F90 +++ b/parteh/PRTParametersMod.F90 @@ -96,8 +96,9 @@ module PRTParametersMod real(r8), allocatable :: seed_alloc_mature(:) ! fraction of carbon balance allocated to ! clonal reproduction. real(r8), allocatable :: seed_alloc(:) ! fraction of carbon balance allocated to seeds. - - + real(r8), allocatable :: repro_alloc_a(:) ! ahb added this; sigmoidal shape param relating dbh to seed allocation fraction + real(r8), allocatable :: repro_alloc_b(:) ! ahb added this; intercept param relating dbh to seed allocation fraction + ! Derived parameters integer, allocatable :: organ_param_id(:) ! This is the sparse reverse lookup index map. This is dimensioned diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index 0acb2d4c91..4a9423c151 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -249,6 +249,14 @@ subroutine PRTRegisterPFT(fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_trs_repro_alloc_a' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_trs_repro_alloc_b' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_c2b' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -531,11 +539,19 @@ subroutine PRTReceivePFT(fates_params) name = 'fates_recruit_seed_alloc_mature' call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%seed_alloc_mature) - + name = 'fates_recruit_seed_alloc' call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%seed_alloc) + name = 'fates_trs_repro_alloc_a' + call fates_params%RetrieveParameterAllocate(name=name, & + data=prt_params%repro_alloc_a) + + name = 'fates_trs_repro_alloc_b' + call fates_params%RetrieveParameterAllocate(name=name, & + data=prt_params%repro_alloc_b) + name = 'fates_c2b' call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%c2b) @@ -927,6 +943,8 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'senleaf_long_fdrought = ',prt_params%senleaf_long_fdrought write(fates_log(),fmt0) 'seed_alloc_mature = ',prt_params%seed_alloc_mature write(fates_log(),fmt0) 'seed_alloc = ',prt_params%seed_alloc + write(fates_log(),fmt0) 'repro_alloc_a = ',prt_params%repro_alloc_a + write(fates_log(),fmt0) 'repro_alloc_b = ',prt_params%repro_alloc_b write(fates_log(),fmt0) 'slamax = ',prt_params%slamax write(fates_log(),fmt0) 'slatop = ',prt_params%slatop write(fates_log(),fmt0) 'allom_sai_scaler = ',prt_params%allom_sai_scaler From 091627e30fcc2c0deb35892ad846514a45b1ce34 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 7 Jun 2023 12:38:30 -0400 Subject: [PATCH 732/852] Updated memory needed for phenoology restart --- main/FatesInterfaceMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index f8bbf0da33..82b4357ea7 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -832,7 +832,7 @@ subroutine SetFatesGlobalElements2(use_fates) end if fates_maxElementsPerSite = max(fates_maxPatchesPerSite * fates_maxElementsPerPatch, & - numWatermem, num_vegtemp_mem, num_elements, nlevsclass*numpft) + numWatermem*numpft, num_vegtemp_mem, num_elements, nlevsclass*numpft) if(hlm_use_planthydro==itrue)then fates_maxElementsPerSite = max(fates_maxElementsPerSite, nshell*nlevsoi_hyd_max ) From 66d37975b6c053b711884af6c05776003a97875a Mon Sep 17 00:00:00 2001 From: Adam Hanbury-Brown Date: Thu, 8 Jun 2023 18:14:37 -0600 Subject: [PATCH 733/852] changes in response to Ryan's comments --- biogeochem/EDPhysiologyMod.F90 | 12 ++-- main/FatesConstantsMod.F90 | 2 +- parteh/PRTAllometricCNPMod.F90 | 102 ++++++++++++++++++++++++------ parteh/PRTAllometricCarbonMod.F90 | 5 +- 4 files changed, 91 insertions(+), 30 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 1fbeb13293..9b5fe78682 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -25,7 +25,7 @@ module EDPhysiologyMod use FatesConstantsMod, only : nearzero use FatesConstantsMod, only : sec_per_day use FatesConstantsMod, only : default_regeneration - use FatesConstantsMod, only : TRS + use FatesConstantsMod, only : TRS_regeneration use FatesConstantsMod, only : TRS_no_seedling_dyn use FatesConstantsMod, only : min_max_dbh_for_trees use FatesConstantsMod, only : megajoules_per_joule @@ -1858,7 +1858,7 @@ subroutine SeedIn( currentSite, bc_in ) litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)/area ! If we are using the Tree Recruitment Scheme (TRS) with or w/o seedling dynamics - if ( any(regeneration_model == [TRS, TRS_no_seedling_dyn]) .and. & + if ( any(regeneration_model == [TRS_regeneration, TRS_no_seedling_dyn]) .and. & prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees) then ! Send a fraction of reproductive carbon to litter to account for @@ -1956,7 +1956,7 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) ! If the TRS is switched on and the pft is a tree then add non-seed reproductive biomass ! to the seed decay flux. This was added to litt%seed_decay in the previously called SeedIn ! subroutine - if ( any(regeneration_model == [TRS, TRS_no_seedling_dyn]) .and. & + if ( any(regeneration_model == [TRS_regeneration, TRS_no_seedling_dyn]) .and. & prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees ) then litt%seed_decay(pft) = litt%seed_decay(pft) + &! From non-seed reproductive biomass (added in @@ -1968,7 +1968,7 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) ! If the TRS is switched on with seedling dynamics (regeneration_model = 2) ! then calculate seedling mortality. - if ( regeneration_model == TRS .and. & + if ( regeneration_model == TRS_regeneration .and. & prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees ) then !---------------------------------------------------------------------- @@ -2076,7 +2076,7 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) ! If TRS seedling dynamics is switched on we calculate seedling emergence (i.e. germination) ! as a pft-specific function of understory light and soil moisture. - else if ( regeneration_model == TRS .and. & + else if ( regeneration_model == TRS_regeneration .and. & prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees ) then ! Step 1. Calculate how germination rate is modified by understory light @@ -2322,7 +2322,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) ! If TRS seedling dynamics is on then calculate the available mass to make new recruits ! as a pft-specific function of light and soil moisture in the seedling layer. - else if ( regeneration_model == TRS .and. & + else if ( regeneration_model == TRS_regeneration .and. & prt_params%allom_dbh_maxheight(ft) > min_max_dbh_for_trees ) then sdlng2sap_par = currentPatch%sdlng2sap_par%GetMean() * sec_per_day * megajoules_per_joule diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index a3c0047bb3..e189e67a64 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -57,7 +57,7 @@ module FatesConstantsMod ! and allocation to non-seed ! reproductive biomass, but does not turn ! on seedling dynamics. - integer, public, parameter :: TRS = 2 ! Constant defining the Tree Recruitment + integer, public, parameter :: TRS_regeneration = 2 ! Constant defining the Tree Recruitment ! Scheme switch. Turns on full TRS. integer, public, parameter :: default_regeneration = 1 ! Constant defining FATES's default ! regeneration scheme switch. diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 0f4b29b4b6..a4ecccddd3 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -47,6 +47,7 @@ module PRTAllometricCNPMod use FatesConstantsMod , only : calloc_abs_error use FatesConstantsMod , only : rsnbl_math_prec use FatesConstantsMod , only : years_per_day + use FatesConstantsMod , only : mm_per_cm use FatesIntegratorsMod , only : RKF45 use FatesIntegratorsMod , only : Euler use FatesConstantsMod , only : calloc_abs_error @@ -55,6 +56,10 @@ module PRTAllometricCNPMod use FatesConstantsMod , only : fates_unset_r8 use FatesConstantsMod , only : fates_unset_int use FatesConstantsMod , only : sec_per_day + use FatesConstantsMod , only : TRS_regeneration + use FatesConstantsMod , only : default_regeneration + use FatesConstantsMod , only : TRS_no_seedling_dyn + use FatesConstantsMod , only : min_max_dbh_for_trees use PRTParametersMod , only : prt_params use EDTypesMod , only : leaves_on,leaves_off use EDTypesMod , only : p_uptake_mode @@ -62,6 +67,9 @@ module PRTAllometricCNPMod use FatesConstantsMod , only : prescribed_p_uptake use FatesConstantsMod , only : prescribed_n_uptake use EDPftvarcon, only : EDPftvarcon_inst + use EDParamsMod , only : regeneration_model + + implicit none private @@ -1452,13 +1460,30 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & ! just different from the other pools. It is not based on proportionality, ! so its mask is set differently. We (inefficiently) just included ! reproduction in the previous loop, but oh well, we over-write now. + + ! If the TRS is switched off then we use FATES's default reproductive allocation. + if ( regeneration_model == default_regeneration .or. & + prt_params%allom_dbh_maxheight(ipft) < min_max_dbh_for_trees ) then ! The Tree Recruitment Scheme + ! is only for trees + if (dbh <= prt_params%dbh_repro_threshold(ipft)) then + repro_c_frac = prt_params%seed_alloc(ipft) + else + repro_c_frac = prt_params%seed_alloc(ipft) + prt_params%seed_alloc_mature(ipft) + end if - if (dbh <= prt_params%dbh_repro_threshold(ipft)) then - repro_c_frac = prt_params%seed_alloc(ipft) - else - repro_c_frac = prt_params%seed_alloc(ipft) + prt_params%seed_alloc_mature(ipft) - end if - + ! If the TRS is switched on (with or w/o seedling dynamics) then reproductive allocation is + ! a pft-specific function of dbh. This allows for the representation of different + ! reproductive schedules (Wenk and Falster, 2015) + else if ( any(regeneration_model == [TRS_regeneration, TRS_no_seedling_dyn]) .and. & + prt_params%allom_dbh_maxheight(ipft) > min_max_dbh_for_trees ) then + + repro_c_frac = prt_params%seed_alloc(ipft) * & + (exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm) / & + (1 + exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm))) + + end if ! regeneration switch + + if(repro_c_frac>nearzero)then state_mask(repro_id) = .true. n_mask_organs = n_mask_organs + 1 @@ -2253,15 +2278,32 @@ function AllomCNPGrowthDeriv(l_state_array,l_state_mask,cbalance,intgr_params) r call bstore_allom(dbh,ipft,crown_damage,canopy_trim,store_c_target,store_dcdd_target) if (mask_repro) then - ! fraction of carbon going towards reproduction - if (dbh <= prt_params%dbh_repro_threshold(ipft)) then - repro_fraction = prt_params%seed_alloc(ipft) - else - repro_fraction = prt_params%seed_alloc(ipft) + prt_params%seed_alloc_mature(ipft) - end if - else + + ! If the TRS is switched off then we use FATES's default reproductive allocation. + if ( regeneration_model == default_regeneration .or. & + prt_params%allom_dbh_maxheight(ipft) < min_max_dbh_for_trees ) then ! The Tree Recruitment Scheme + ! is only for trees + if (dbh <= prt_params%dbh_repro_threshold(ipft)) then + repro_fraction = prt_params%seed_alloc(ipft) + else + repro_fraction = prt_params%seed_alloc(ipft) + prt_params%seed_alloc_mature(ipft) + end if + + ! If the TRS is switched on (with or w/o seedling dynamics) then reproductive allocation is + ! a pft-specific function of dbh. This allows for the representation of different + ! reproductive schedules (Wenk and Falster, 2015) + else if ( any(regeneration_model == [TRS_regeneration, TRS_no_seedling_dyn]) .and. & + prt_params%allom_dbh_maxheight(ipft) > min_max_dbh_for_trees ) then + + repro_fraction = prt_params%seed_alloc(ipft) * & + (exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm) / & + (1 + exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm))) + + end if ! regeneration switch + + else ! mask repro repro_fraction = 0._r8 - end if + end if !mask repro total_dcostdd = 0._r8 if (mask_struct) then @@ -2369,14 +2411,32 @@ subroutine EstimateGrowthNC(this,target_c,target_dcdd,state_mask,avg_nc,avg_pc) pc_repro => this%bc_in(acnp_bc_in_id_pc_repro)%rval) if(state_mask(repro_id)) then - if (dbh <= prt_params%dbh_repro_threshold(ipft)) then - repro_c_frac = prt_params%seed_alloc(ipft) - else - repro_c_frac = prt_params%seed_alloc(ipft) + prt_params%seed_alloc_mature(ipft) - end if - else + + ! If the TRS is switched off then we use FATES's default reproductive allocation. + if ( regeneration_model == default_regeneration .or. & + prt_params%allom_dbh_maxheight(ipft) < min_max_dbh_for_trees ) then ! The Tree Recruitment Scheme + ! is only for trees + if (dbh <= prt_params%dbh_repro_threshold(ipft)) then + repro_c_frac = prt_params%seed_alloc(ipft) + else + repro_c_frac = prt_params%seed_alloc(ipft) + prt_params%seed_alloc_mature(ipft) + end if + + ! If the TRS is switched on (with or w/o seedling dynamics) then reproductive allocation is + ! a pft-specific function of dbh. This allows for the representation of different + ! reproductive schedules (Wenk and Falster, 2015) + else if ( any(regeneration_model == [TRS_regeneration, TRS_no_seedling_dyn]) .and. & + prt_params%allom_dbh_maxheight(ipft) > min_max_dbh_for_trees ) then + + repro_c_frac = prt_params%seed_alloc(ipft) * & + (exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm) / & + (1 + exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm))) + + end if ! regeneration switch + + else ! state mask repro_c_frac = 0._r8 - end if + end if ! state mask ! Estimate the total weight total_w = 0._r8 diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index d02a9f8e7f..92a7c606c1 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -43,8 +43,9 @@ module PRTAllometricCarbonMod use FatesConstantsMod , only : i4 => fates_int use FatesConstantsMod , only : sec_per_day use FatesConstantsMod , only : mm_per_cm - use FatesConstantsMod , only : TRS + use FatesConstantsMod , only : TRS_regeneration use FatesConstantsMod , only : default_regeneration + use FatesConstantsMod , only : TRS_no_seedling_dyn use FatesConstantsMod , only : min_max_dbh_for_trees use FatesIntegratorsMod , only : RKF45 use FatesIntegratorsMod , only : Euler @@ -990,7 +991,7 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) ! If the TRS is switched on (with or w/o seedling dynamics) then reproductive allocation is ! a pft-specific function of dbh. This allows for the representation of different ! reproductive schedules (Wenk and Falster, 2015) - else if ( any(regeneration_model == [TRS, TRS_no_seedling_dyn]) .and. & + else if ( any(regeneration_model == [TRS_regeneration, TRS_no_seedling_dyn]) .and. & prt_params%allom_dbh_maxheight(ipft) > min_max_dbh_for_trees ) then repro_fraction = prt_params%seed_alloc(ipft) * & From e0eb4ad40b8e38de8173cd1c125c614198cfbecb Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 12 Jun 2023 11:46:37 -0400 Subject: [PATCH 734/852] Initializing EMA NPP used for nitrogen fixation correctly, also adding restart term --- main/EDInitMod.F90 | 4 ++++ main/FatesInterfaceMod.F90 | 3 +-- main/FatesRestartInterfaceMod.F90 | 22 ++++++++++++++++------ 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 45b3ac7551..670d997ab9 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -265,6 +265,10 @@ subroutine zero_site( site_in ) call site_in%flux_diags(el)%ZeroFluxDiags() end do + ! This will be initialized in FatesSoilBGCFluxMod:PrepCH4BCs() + ! It checks to see if the value is below -9000. If it is, + ! it will assume the first value of the smoother is set + site_in%ema_npp = -9999.9_r8 ! termination and recruitment info site_in%term_nindivs_canopy(:,:) = 0._r8 diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index f8bbf0da33..899df87e62 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -620,8 +620,7 @@ subroutine allocate_bcout(bc_out, nlevsoil_in, nlevdecomp_in) bc_out%rootfr_pa(0,1:nlevsoil_in)=1._r8/real(nlevsoil_in,r8) end if - bc_out%ema_npp = nan - + bc_out%ema_npp = -9999.9_r8 ! Fates -> BGC fragmentation mass fluxes select case(hlm_parteh_mode) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 35ae60ca50..f441b1950f 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -255,7 +255,8 @@ module FatesRestartInterfaceMod integer :: ir_fmortcflux_usto_sicdsc integer :: ir_crownarea_cano_si integer :: ir_crownarea_usto_si - + integer :: ir_emanpp_si + ! Hydraulic indices integer :: ir_hydro_th_ag_covec @@ -1404,6 +1405,11 @@ subroutine define_restart_vars(this, initialize_variables) units='m2/ha/year', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_crownarea_usto_si) + call this%set_restart_var(vname='fates_emanpp', vtype=site_r8, & + long_name='smoothed NPP (exp. moving avg) at the site level (for fixation)', & + units='kg/m2/yr', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_emanpp_si) + call this%DefineRMeanRestartVar(vname='fates_tveg24patch',vtype=cohort_r8, & long_name='24-hour patch veg temp', & units='K', initialize=initialize_variables,ivar=ivar, index = ir_tveg24_pa) @@ -1997,7 +2003,8 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_fmortcflux_cano_sicdsc => this%rvars(ir_fmortcflux_cano_sicdsc)%r81d, & rio_fmortcflux_usto_sicdsc => this%rvars(ir_fmortcflux_usto_sicdsc)%r81d, & rio_crownarea_cano_damage_si=> this%rvars(ir_crownarea_cano_si)%r81d, & - rio_crownarea_usto_damage_si=> this%rvars(ir_crownarea_usto_si)%r81d) + rio_crownarea_usto_damage_si=> this%rvars(ir_crownarea_usto_si)%r81d, & + rio_emanpp_si => this%rvars(ir_emanpp_si)%r81d) totalCohorts = 0 @@ -2380,13 +2387,14 @@ subroutine set_restart_vectors(this,nc,nsites,sites) end do rio_demorate_sisc(io_idx_si_sc) = sites(s)%demotion_rate(i_scls) - rio_promrate_sisc(io_idx_si_sc) = sites(s)%promotion_rate(i_scls) + rio_promrate_sisc(io_idx_si_sc) = sites(s)%promotion_rate(i_scls) io_idx_si_sc = io_idx_si_sc + 1 end do + rio_termcarea_cano_si(io_idx_si) = sites(s)%term_crownarea_canopy rio_termcarea_usto_si(io_idx_si) = sites(s)%term_crownarea_ustory - + rio_emanpp_si(io_idx_si) = sites(s)%ema_npp ! this only copies live portions of transitions - but that's ok because the mortality ! bit only needs to be added for history outputs @@ -2892,6 +2900,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_fmortcflux_usto_sicdsc => this%rvars(ir_fmortcflux_usto_sicdsc)%r81d, & rio_crownarea_cano_damage_si=> this%rvars(ir_crownarea_cano_si)%r81d, & rio_crownarea_usto_damage_si=> this%rvars(ir_crownarea_usto_si)%r81d, & + rio_emanpp_si => this%rvars(ir_emanpp_si)%r81d, & rio_imortcflux_sipft => this%rvars(ir_imortcflux_sipft)%r81d, & rio_fmortcflux_cano_sipft => this%rvars(ir_fmortcflux_cano_sipft)%r81d, & rio_fmortcflux_usto_sipft => this%rvars(ir_fmortcflux_usto_sipft)%r81d, & @@ -3349,12 +3358,13 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%crownarea_canopy_damage = rio_crownarea_cano_damage_si(io_idx_si) sites(s)%crownarea_ustory_damage = rio_crownarea_usto_damage_si(io_idx_si) - + + end if + sites(s)%ema_npp = rio_emanpp_si(io_idx_si) sites(s)%term_crownarea_canopy = rio_termcarea_cano_si(io_idx_si) sites(s)%term_crownarea_ustory = rio_termcarea_usto_si(io_idx_si) - sites(s)%imort_crownarea = rio_imortcarea_si(io_idx_si) sites(s)%fmort_crownarea_canopy = rio_fmortcarea_cano_si(io_idx_si) sites(s)%fmort_crownarea_ustory = rio_fmortcarea_usto_si(io_idx_si) From 635fccea53ee061c3b06d30adaa2326409e362e7 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 13 Jun 2023 12:08:19 -0400 Subject: [PATCH 735/852] Made special routine to calculate forest floor light levels for seedlings --- main/EDTypesMod.F90 | 96 ++++++++++++++++++++++++++++++++++++++ main/FatesInterfaceMod.F90 | 38 ++++++--------- 2 files changed, 109 insertions(+), 25 deletions(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index c015ea86d4..466ad12147 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -1235,4 +1235,100 @@ subroutine dump_cohort_hydr(ccohort) return end subroutine dump_cohort_hydr + ! ======================================================================================== + + subroutine SeedlingParPatch(cpatch, & + atm_par, & + seedling_par_high, par_high_frac, & + seedling_par_low, par_low_frac) + + ! Calculate the intensity of PAR for seedlings in the current patch. + ! To do this, we need to get a weighted average of light penetrating + ! though (parprof) the lowest leaf layers. We will need to identify + ! how closed (area) the lowest canopy layer is, because we will use + ! an area weighted average of the light coming from the canopy above + ! and an area weighted average of the light penetrating through the + ! existing portino of the lowest layer. + ! + ! This routine will generate two intensities, light levels on the exposed + ! ground in the lowest layer, and light levels under the existing + ! vegetation in the lowest layer, along with the area fraction + ! of those two (which should sum to unity). + + ! Arguments + type(ed_patch_type) :: cpatch + real(r8), intent(in) :: atm_par ! direct+diffuse PAR at canopy top [W/m2] + real(r8), intent(out) :: seedling_par_high ! High intensity PAR for seedlings [W/m2] + real(r8), intent(out) :: par_high_frac ! Area fraction with high intensity + real(r8), intent(out) :: seedling_par_low ! Low intensity PAR for seedlings [W/m2] + real(r8), intent(out) :: par_low_frac ! Area fraction with low intensity + + ! Locals + real(r8) :: upper_par ! The PAR intensity coming from the canopy layer above [w/m2] + real(r8) :: upper_area ! The area fraction of the upper canopy + real(r8) :: lower_par ! The PAR intensity under the lower-most canopy [W/m2] + real(r8) :: lower_area ! The area fractino of the lower canopy + integer :: cl ! current canopy layer + integer :: ipft ! current PFT index + integer :: iv ! lower-most leaf layer index for the cl & pft combo + + ! Radiation intensity exiting the layer above the bottom-most + upper_par = 0._r8 + upper_area = 0._r8 + cl = max(1,cpatch%NCL_p-1) + do ipft = 1,numpft + iv = cpatch%ncan(cl,ft) + upper_par = upper_par + cpatch%canopy_area_profile(cl,ifpt,1)*& + (cpatch%parprof_pft_dir_z(cl,ipft,iv)+cpatch%parprof_pft_dif_z(cl,ipft,iv)) + upper_area = upper_area + cpatch%canopy_area_profile(cl,ifpt,1) + end do + if(upper_area>nearzero)then + upper_par = upper_par/upper_area + else + upper_par = 0._r8 + end if + + ! If we do have more than one layer, then we need to figure out + ! the average of light on the exposed ground under the veg + + if(cpatch%NCL_p>1) then + + ! Factor in atmospheric downwelling radiation if the upper + ! layer happens to be the top-most + if(cl==1)then + upper_par = cpatch%total_canopy_area*upper_par + & + (1._r8-cpatch%total_canopy_area)*(bc_in(s)%solad_parb(ifp,ipar)+bc_in(s)%solai_parb(ifp,ipar)) + end if + + cl = cpatch%NCL_p + lower_area = 0._r8 + lower_par = 0._r8 + do ipft = 1,numpft + iv = cpatch%ncan(cl,ft) + lower_area = lower_area+cpatch%canopy_area_profile(cl,ifpt,1) + par_bottom = cpatch%parprof_pft_dir_z(cl,ipft,iv) + & + cpatch%parprof_pft_dif_z(cl,ipft,iv) + lower_par = lower_par + cpatch%canopy_area_profile(cl,ifpt,1)*par_bottom + end do + if(lower_area>nearzero)then + lower_par = lower_par / lower_area + else + lower_par = 0._r8 + end if + + seedling_par_high = upper_par + par_high_frac = (1._r8-lower_area) + seedling_par_low = lower_par/lower_ara + par_low_frac = lower_area + + else + + seedling_par_high = bc_in(s)%solad_parb(ifp,ipar)+bc_in(s)%solai_parb(ifp,ipar) + par_high_frac = 1._r8-cpatch%total_canopy_area + seedling_par_low = upper_par + par_low_frac = cpatch%total_canopy_area + + end if + + return end module EDTypesMod diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 39e54bfe0c..734392147b 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1973,33 +1973,21 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) call cpatch%tveg24%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) call cpatch%tveg_lpa%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) call cpatch%tveg_longterm%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) + + ! Return the par intensity at the ground. This routine + ! breaks it up into high and low light levels. The high + ! levels are the light on the exposed ground at the surface + ! and the low levels are the intensity under the bottom-most + ! vegetation. - ! Update seedling layer running means of PAR, soil matric potential and - ! moisture deficit days (mdd). - n_leaf = maxval(cpatch%ncan(cpatch%ncl_p,:)) ! Calculate the number of leaf layers - ! in the lowest canopy layer - - ! Calculate the fraction of total lai (summed across pfts) in sun vs. shade - ! at the lowest leaf level of the lowest canopy level - lai_sun_frac = sum(cpatch%ed_laisun_z(cpatch%ncl_p,:,n_leaf)) & - / ( sum(cpatch%ed_laisun_z(cpatch%ncl_p,:,n_leaf)) + & !summed across pfts - sum(cpatch%ed_laisha_z(cpatch%ncl_p,:,n_leaf)) ) !summed across pfts - - lai_shade_frac = 1.0_r8 - lai_sun_frac - - ! Calculate new_seedling_layer_par (total PAR at the lowest leaf layer of the lowest canopy layer) - ! using the weighted average of direct and diffuse par. - - new_seedling_layer_par = & - (cpatch%parprof_dir_z(cpatch%ncl_p,n_leaf) * lai_sun_frac) + & - (cpatch%parprof_dif_z(cpatch%ncl_p,n_leaf) * (1.0_r8 - lai_sun_frac)) + call SeedlingParPatch(cpatch, & + bc_in(s)%solad_parb(ifp,ipar) + bc_in(s)%solai_parb(ifp,ipar), & + seedling_par_high, & + par_high_frac, & + seedling_par_low, & + par_low_frac) - ! If there is no lai on the patch then new seedling layer par becomes nan (because - ! lai_sun_frac is Inf). If this is the case then PAR at the seedling layer is - ! taken from the hlm boundary conditions (i.e. same as top of canopy). - if (new_seedling_layer_par /= new_seedling_layer_par) then - new_seedling_layer_par = bc_in(s)%solad_parb(ifp,ipar) + bc_in(s)%solai_parb(ifp,ipar) - end if + new_seedling_layer_par = seedling_par_high*par_high_frac + seedling_par_low*par_low_frac ! Update the seedling layer par running means call cpatch%seedling_layer_par24%UpdateRMean(new_seedling_layer_par) From e57df0d19f6803145e9c99cd02417a3b6943f2ea Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 13 Jun 2023 17:53:53 -0400 Subject: [PATCH 736/852] Added seedling light intensity subroutine --- main/EDTypesMod.F90 | 97 +--------------------------- main/FatesInterfaceMod.F90 | 128 ++++++++++++++++++++++++++++++++----- 2 files changed, 112 insertions(+), 113 deletions(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 466ad12147..ce9dd74617 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -1235,100 +1235,5 @@ subroutine dump_cohort_hydr(ccohort) return end subroutine dump_cohort_hydr - ! ======================================================================================== - - subroutine SeedlingParPatch(cpatch, & - atm_par, & - seedling_par_high, par_high_frac, & - seedling_par_low, par_low_frac) - - ! Calculate the intensity of PAR for seedlings in the current patch. - ! To do this, we need to get a weighted average of light penetrating - ! though (parprof) the lowest leaf layers. We will need to identify - ! how closed (area) the lowest canopy layer is, because we will use - ! an area weighted average of the light coming from the canopy above - ! and an area weighted average of the light penetrating through the - ! existing portino of the lowest layer. - ! - ! This routine will generate two intensities, light levels on the exposed - ! ground in the lowest layer, and light levels under the existing - ! vegetation in the lowest layer, along with the area fraction - ! of those two (which should sum to unity). - - ! Arguments - type(ed_patch_type) :: cpatch - real(r8), intent(in) :: atm_par ! direct+diffuse PAR at canopy top [W/m2] - real(r8), intent(out) :: seedling_par_high ! High intensity PAR for seedlings [W/m2] - real(r8), intent(out) :: par_high_frac ! Area fraction with high intensity - real(r8), intent(out) :: seedling_par_low ! Low intensity PAR for seedlings [W/m2] - real(r8), intent(out) :: par_low_frac ! Area fraction with low intensity - - ! Locals - real(r8) :: upper_par ! The PAR intensity coming from the canopy layer above [w/m2] - real(r8) :: upper_area ! The area fraction of the upper canopy - real(r8) :: lower_par ! The PAR intensity under the lower-most canopy [W/m2] - real(r8) :: lower_area ! The area fractino of the lower canopy - integer :: cl ! current canopy layer - integer :: ipft ! current PFT index - integer :: iv ! lower-most leaf layer index for the cl & pft combo - - ! Radiation intensity exiting the layer above the bottom-most - upper_par = 0._r8 - upper_area = 0._r8 - cl = max(1,cpatch%NCL_p-1) - do ipft = 1,numpft - iv = cpatch%ncan(cl,ft) - upper_par = upper_par + cpatch%canopy_area_profile(cl,ifpt,1)*& - (cpatch%parprof_pft_dir_z(cl,ipft,iv)+cpatch%parprof_pft_dif_z(cl,ipft,iv)) - upper_area = upper_area + cpatch%canopy_area_profile(cl,ifpt,1) - end do - if(upper_area>nearzero)then - upper_par = upper_par/upper_area - else - upper_par = 0._r8 - end if - - ! If we do have more than one layer, then we need to figure out - ! the average of light on the exposed ground under the veg - - if(cpatch%NCL_p>1) then - - ! Factor in atmospheric downwelling radiation if the upper - ! layer happens to be the top-most - if(cl==1)then - upper_par = cpatch%total_canopy_area*upper_par + & - (1._r8-cpatch%total_canopy_area)*(bc_in(s)%solad_parb(ifp,ipar)+bc_in(s)%solai_parb(ifp,ipar)) - end if - - cl = cpatch%NCL_p - lower_area = 0._r8 - lower_par = 0._r8 - do ipft = 1,numpft - iv = cpatch%ncan(cl,ft) - lower_area = lower_area+cpatch%canopy_area_profile(cl,ifpt,1) - par_bottom = cpatch%parprof_pft_dir_z(cl,ipft,iv) + & - cpatch%parprof_pft_dif_z(cl,ipft,iv) - lower_par = lower_par + cpatch%canopy_area_profile(cl,ifpt,1)*par_bottom - end do - if(lower_area>nearzero)then - lower_par = lower_par / lower_area - else - lower_par = 0._r8 - end if - - seedling_par_high = upper_par - par_high_frac = (1._r8-lower_area) - seedling_par_low = lower_par/lower_ara - par_low_frac = lower_area - - else - - seedling_par_high = bc_in(s)%solad_parb(ifp,ipar)+bc_in(s)%solai_parb(ifp,ipar) - par_high_frac = 1._r8-cpatch%total_canopy_area - seedling_par_low = upper_par - par_low_frac = cpatch%total_canopy_area - - end if - - return + end module EDTypesMod diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 734392147b..78ea664d0e 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1954,14 +1954,16 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) type(ed_patch_type), pointer :: cpatch type(ed_cohort_type), pointer :: ccohort integer :: s, ifp, io_si, pft - real(r8) :: new_seedling_layer_par !seedling layer par in the current timestep - real(r8) :: new_seedling_layer_smp(maxpft) !seedling layer smp in the current timestep - real(r8) :: new_seedling_mdd(maxpft) !seedling layer moisture deficit days in the current timestep - integer :: ilayer_seedling_root(maxpft) !the soil layer at seedling rooting depth - integer :: n_leaf !number of leaf layers per canopy layer in patch - real(r8) :: lai_sun_frac - real(r8) :: lai_shade_frac - integer,parameter :: ipar = 1 !solar radiation in the shortwave band (i.e. par) + real(r8) :: new_seedling_layer_par ! seedling layer par in the current timestep + real(r8) :: new_seedling_layer_smp(maxpft) ! seedling layer smp in the current timestep + real(r8) :: new_seedling_mdd(maxpft) ! seedling layer moisture deficit days in the current timestep + integer :: ilayer_seedling_root(maxpft) ! the soil layer at seedling rooting depth + integer :: n_leaf ! number of leaf layers per canopy layer in patch + real(r8) :: seedling_par_high ! higher intensity par for seedlings (par at exposed ground) [W/m2] + real(r8) :: par_high_frac ! fraction of ground where PAR is high + real(r8) :: seedling_par_low ! lower intensity par for seedlings (par under the undergrowth) [W/m2] + real(r8) :: par_low_frac ! fraction of ground where PAR is low + integer,parameter :: ipar = 1 ! solar radiation in the shortwave band (i.e. par) do s = 1,size(sites,dim=1) @@ -2010,7 +2012,7 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) ! If mdds are negative then it means that soil is wetter than smp_crit and the moisture ! deficit is 0 if (new_seedling_mdd(pft) < 0.0_r8) then - new_seedling_mdd(pft) = 0.0_r8 + new_seedling_mdd(pft) = 0.0_r8 endif ! Update the seedling layer smp and mdd running means @@ -2024,13 +2026,105 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) ! call ccohort%tveg_lpa%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) ! ccohort => ccohort%shorter !end do - end if - - cpatch => cpatch%younger - enddo + end if + + cpatch => cpatch%younger + enddo + end do + + return +end subroutine UpdateFatesRMeansTStep + +! ======================================================================================== + +subroutine SeedlingParPatch(cpatch, & + atm_par, & + seedling_par_high, par_high_frac, & + seedling_par_low, par_low_frac) + + ! Calculate the intensity of PAR for seedlings in the current patch. + ! To do this, we need to get a weighted average of light penetrating + ! though (parprof) the lowest leaf layers. We will need to identify + ! how closed (area) the lowest canopy layer is, because we will use + ! an area weighted average of the light coming from the canopy above + ! and an area weighted average of the light penetrating through the + ! existing portino of the lowest layer. + ! + ! This routine will generate two intensities, light levels on the exposed + ! ground in the lowest layer, and light levels under the existing + ! vegetation in the lowest layer, along with the area fraction + ! of those two (which should sum to unity). + + ! Arguments + type(ed_patch_type) :: cpatch ! the current patch + real(r8), intent(in) :: atm_par ! direct+diffuse PAR at canopy top [W/m2] + real(r8), intent(out) :: seedling_par_high ! High intensity PAR for seedlings [W/m2] + real(r8), intent(out) :: par_high_frac ! Area fraction with high intensity + real(r8), intent(out) :: seedling_par_low ! Low intensity PAR for seedlings [W/m2] + real(r8), intent(out) :: par_low_frac ! Area fraction with low intensity + + ! Locals + real(r8) :: upper_par ! The PAR intensity coming from the canopy layer above [w/m2] + real(r8) :: upper_area ! The area fraction of the upper canopy + real(r8) :: lower_par ! The PAR intensity under the lower-most canopy [W/m2] + real(r8) :: lower_area ! The area fractino of the lower canopy + integer :: cl ! current canopy layer + integer :: ipft ! current PFT index + integer :: iv ! lower-most leaf layer index for the cl & pft combo + + ! Radiation intensity exiting the layer above the bottom-most + upper_par = 0._r8 + upper_area = 0._r8 + cl = max(1,cpatch%NCL_p-1) + do ipft = 1,numpft + iv = cpatch%ncan(cl,ipft) + upper_par = upper_par + cpatch%canopy_area_profile(cl,ipft,1)* & + (cpatch%parprof_pft_dir_z(cl,ipft,iv)+cpatch%parprof_pft_dif_z(cl,ipft,iv)) + upper_area = upper_area + cpatch%canopy_area_profile(cl,ipft,1) + end do + if(upper_area>nearzero)then + upper_par = upper_par/upper_area + else + upper_par = 0._r8 + end if + + ! If we do have more than one layer, then we need to figure out + ! the average of light on the exposed ground under the veg + + if(cpatch%NCL_p>1) then + + cl = cpatch%NCL_p + lower_area = 0._r8 + lower_par = 0._r8 + do ipft = 1,numpft + iv = cpatch%ncan(cl,ipft) + lower_area = lower_area+cpatch%canopy_area_profile(cl,ipft,1) + lower_par = lower_par + & + cpatch%canopy_area_profile(cl,ipft,1)*& + (cpatch%parprof_pft_dir_z(cl,ipft,iv) + cpatch%parprof_pft_dif_z(cl,ipft,iv)) end do + if(lower_area>nearzero)then + lower_par = lower_par / lower_area + else + lower_par = 0._r8 + end if - return - end subroutine UpdateFatesRMeansTStep - - end module FatesInterfaceMod + seedling_par_high = upper_par + par_high_frac = (1._r8-lower_area) + seedling_par_low = lower_par/lower_area + par_low_frac = lower_area + + else + + seedling_par_high = atm_par + par_high_frac = 1._r8-cpatch%total_canopy_area + seedling_par_low = upper_par + par_low_frac = cpatch%total_canopy_area + + end if + + return +end subroutine SeedlingParPatch + + +end module FatesInterfaceMod From c276459897303884948c3de213da57fb3a862356 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 13 Jun 2023 17:56:25 -0400 Subject: [PATCH 737/852] removed unused variable --- main/FatesInterfaceMod.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 78ea664d0e..3593f5b143 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1958,7 +1958,6 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) real(r8) :: new_seedling_layer_smp(maxpft) ! seedling layer smp in the current timestep real(r8) :: new_seedling_mdd(maxpft) ! seedling layer moisture deficit days in the current timestep integer :: ilayer_seedling_root(maxpft) ! the soil layer at seedling rooting depth - integer :: n_leaf ! number of leaf layers per canopy layer in patch real(r8) :: seedling_par_high ! higher intensity par for seedlings (par at exposed ground) [W/m2] real(r8) :: par_high_frac ! fraction of ground where PAR is high real(r8) :: seedling_par_low ! lower intensity par for seedlings (par under the undergrowth) [W/m2] From 8365c3393e8e381fa3dd1dc1ad6b50711eff7ad7 Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Wed, 21 Jun 2023 09:33:26 -0700 Subject: [PATCH 738/852] fixed typo that was preventing a clear error message to be written when pft-indices argument not specified in command line --- tools/FatesPFTIndexSwapper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/FatesPFTIndexSwapper.py b/tools/FatesPFTIndexSwapper.py index 5e8772b5a9..99e258bdc6 100755 --- a/tools/FatesPFTIndexSwapper.py +++ b/tools/FatesPFTIndexSwapper.py @@ -85,7 +85,7 @@ def interp_args(argv): input_fname = "none" output_fname = "none" donor_pft_indices = -9 - donot_pft_indices_str = '' + donor_pft_indices_str = '' histflag = True try: opts, args = getopt.getopt(argv, 'h',["fin=","fout=","pft-indices=","nohist"]) From efde58c2873a1e7a3224da55fb283e6e55965981 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 23 Jun 2023 11:58:23 -0600 Subject: [PATCH 739/852] Fix to the restart order issue --- main/FatesRestartInterfaceMod.F90 | 130 +++++++++++++++--------------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 6efceb3191..3e20b7528b 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -2087,6 +2087,8 @@ subroutine set_restart_vectors(this,nc,nsites,sites) io_idx_si_cacls= io_idx_co_1st io_idx_si_cdsc = io_idx_co_1st io_idx_si_cdpf = io_idx_co_1st + io_idx_si_scpf = io_idx_co_1st + io_idx_si_pft = io_idx_co_1st ! recruitment rate do i_pft = 1,numpft @@ -2101,6 +2103,32 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_area_pft_sift(io_idx_co_1st+i_pft-1) = sites(s)%area_pft(i_pft) end do + do i_scls = 1, nlevsclass + do i_pft = 1, numpft + rio_fmortrate_cano_siscpf(io_idx_si_scpf) = sites(s)%fmort_rate_canopy(i_scls, i_pft) + rio_fmortrate_usto_siscpf(io_idx_si_scpf) = sites(s)%fmort_rate_ustory(i_scls, i_pft) + rio_imortrate_siscpf(io_idx_si_scpf) = sites(s)%imort_rate(i_scls, i_pft) + rio_fmortrate_crown_siscpf(io_idx_si_scpf) = sites(s)%fmort_rate_crown(i_scls, i_pft) + rio_fmortrate_cambi_siscpf(io_idx_si_scpf) = sites(s)%fmort_rate_cambial(i_scls, i_pft) + rio_termnindiv_cano_siscpf(io_idx_si_scpf) = sites(s)%term_nindivs_canopy(i_scls,i_pft) + rio_termnindiv_usto_siscpf(io_idx_si_scpf) = sites(s)%term_nindivs_ustory(i_scls,i_pft) + rio_growflx_fusion_siscpf(io_idx_si_scpf) = sites(s)%growthflux_fusion(i_scls, i_pft) + rio_abg_term_flux_siscpf(io_idx_si_scpf) = sites(s)%term_abg_flux(i_scls, i_pft) + rio_abg_imort_flux_siscpf(io_idx_si_scpf) = sites(s)%imort_abg_flux(i_scls, i_pft) + rio_abg_fmort_flux_siscpf(io_idx_si_scpf) = sites(s)%fmort_abg_flux(i_scls, i_pft) + io_idx_si_scpf = io_idx_si_scpf + 1 + end do + end do + + do i_pft = 1, numpft + rio_termcflux_cano_sipft(io_idx_si_pft) = sites(s)%term_carbonflux_canopy(i_pft) + rio_termcflux_usto_sipft(io_idx_si_pft) = sites(s)%term_carbonflux_ustory(i_pft) + rio_fmortcflux_cano_sipft(io_idx_si_pft) = sites(s)%fmort_carbonflux_canopy(i_pft) + rio_fmortcflux_usto_sipft(io_idx_si_pft) = sites(s)%fmort_carbonflux_ustory(i_pft) + rio_imortcflux_sipft(io_idx_si_pft) = sites(s)%imort_carbonflux(i_pft) + io_idx_si_pft = io_idx_si_pft + 1 + end do + if(hlm_use_sp.eq.ifalse)then do el = 1, num_elements @@ -2128,6 +2156,8 @@ subroutine set_restart_vectors(this,nc,nsites,sites) end do end if + + ! canopy spread term rio_spread_si(io_idx_si) = sites(s)%spread @@ -2136,7 +2166,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) ! new column, reset num patches patchespersite = 0 - do while(associated(cpatch)) + do_patch: do while(associated(cpatch)) ! found patch, increment patchespersite = patchespersite + 1 @@ -2414,31 +2444,12 @@ subroutine set_restart_vectors(this,nc,nsites,sites) cpatch => cpatch%younger - enddo ! cpatch do while - - io_idx_si_scpf = io_idx_co_1st + enddo do_patch ! cpatch do while ! Fill the site level diagnostics arrays do i_scls = 1, nlevsclass - do i_pft = 1, numpft - - rio_fmortrate_cano_siscpf(io_idx_si_scpf) = sites(s)%fmort_rate_canopy(i_scls, i_pft) - rio_fmortrate_usto_siscpf(io_idx_si_scpf) = sites(s)%fmort_rate_ustory(i_scls, i_pft) - rio_imortrate_siscpf(io_idx_si_scpf) = sites(s)%imort_rate(i_scls, i_pft) - rio_fmortrate_crown_siscpf(io_idx_si_scpf) = sites(s)%fmort_rate_crown(i_scls, i_pft) - rio_fmortrate_cambi_siscpf(io_idx_si_scpf) = sites(s)%fmort_rate_cambial(i_scls, i_pft) - rio_termnindiv_cano_siscpf(io_idx_si_scpf) = sites(s)%term_nindivs_canopy(i_scls,i_pft) - rio_termnindiv_usto_siscpf(io_idx_si_scpf) = sites(s)%term_nindivs_ustory(i_scls,i_pft) - rio_growflx_fusion_siscpf(io_idx_si_scpf) = sites(s)%growthflux_fusion(i_scls, i_pft) - - rio_abg_term_flux_siscpf(io_idx_si_scpf) = sites(s)%term_abg_flux(i_scls, i_pft) - rio_abg_imort_flux_siscpf(io_idx_si_scpf) = sites(s)%imort_abg_flux(i_scls, i_pft) - rio_abg_fmort_flux_siscpf(io_idx_si_scpf) = sites(s)%fmort_abg_flux(i_scls, i_pft) - io_idx_si_scpf = io_idx_si_scpf + 1 - end do - - rio_demorate_sisc(io_idx_si_sc) = sites(s)%demotion_rate(i_scls) + rio_demorate_sisc(io_idx_si_sc) = sites(s)%demotion_rate(i_scls) rio_promrate_sisc(io_idx_si_sc) = sites(s)%promotion_rate(i_scls) io_idx_si_sc = io_idx_si_sc + 1 @@ -2479,16 +2490,6 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_democflux_si(io_idx_si) = sites(s)%demotion_carbonflux rio_promcflux_si(io_idx_si) = sites(s)%promotion_carbonflux - io_idx_si_pft = io_idx_co_1st - do i_pft = 1, numpft - rio_termcflux_cano_sipft(io_idx_si_pft) = sites(s)%term_carbonflux_canopy(i_pft) - rio_termcflux_usto_sipft(io_idx_si_pft) = sites(s)%term_carbonflux_ustory(i_pft) - rio_fmortcflux_cano_sipft(io_idx_si_pft) = sites(s)%fmort_carbonflux_canopy(i_pft) - rio_fmortcflux_usto_sipft(io_idx_si_pft) = sites(s)%fmort_carbonflux_ustory(i_pft) - rio_imortcflux_sipft(io_idx_si_pft) = sites(s)%imort_carbonflux(i_pft) - io_idx_si_pft = io_idx_si_pft + 1 - end do - rio_imortcarea_si(io_idx_si) = sites(s)%imort_crownarea rio_fmortcarea_cano_si(io_idx_si) = sites(s)%fmort_crownarea_canopy rio_fmortcarea_usto_si(io_idx_si) = sites(s)%fmort_crownarea_ustory @@ -3008,6 +3009,8 @@ subroutine get_restart_vectors(this, nc, nsites, sites) io_idx_si_cacls= io_idx_co_1st io_idx_si_cdsc = io_idx_co_1st io_idx_si_cdpf = io_idx_co_1st + io_idx_si_scpf = io_idx_co_1st + io_idx_si_pft = io_idx_co_1st ! read seed_bank info(site-level, but PFT-resolved) do i_pft = 1,numpft @@ -3029,6 +3032,33 @@ subroutine get_restart_vectors(this, nc, nsites, sites) endif endif + do i_scls = 1,nlevsclass + do i_pft = 1, numpft + sites(s)%fmort_rate_canopy(i_scls, i_pft) = rio_fmortrate_cano_siscpf(io_idx_si_scpf) + sites(s)%fmort_rate_ustory(i_scls, i_pft) = rio_fmortrate_usto_siscpf(io_idx_si_scpf) + sites(s)%imort_rate(i_scls, i_pft) = rio_imortrate_siscpf(io_idx_si_scpf) + sites(s)%fmort_rate_crown(i_scls, i_pft) = rio_fmortrate_crown_siscpf(io_idx_si_scpf) + sites(s)%fmort_rate_cambial(i_scls, i_pft) = rio_fmortrate_cambi_siscpf(io_idx_si_scpf) + sites(s)%term_nindivs_canopy(i_scls,i_pft) = rio_termnindiv_cano_siscpf(io_idx_si_scpf) + sites(s)%term_nindivs_ustory(i_scls,i_pft) = rio_termnindiv_usto_siscpf(io_idx_si_scpf) + sites(s)%growthflux_fusion(i_scls, i_pft) = rio_growflx_fusion_siscpf(io_idx_si_scpf) + sites(s)%term_abg_flux(i_scls,i_pft) = rio_abg_term_flux_siscpf(io_idx_si_scpf) + sites(s)%imort_abg_flux(i_scls,i_pft) = rio_abg_imort_flux_siscpf(io_idx_si_scpf) + sites(s)%fmort_abg_flux(i_scls,i_pft) = rio_abg_fmort_flux_siscpf(io_idx_si_scpf) + io_idx_si_scpf = io_idx_si_scpf + 1 + end do + end do + + do i_pft = 1, numpft + sites(s)%term_carbonflux_canopy(i_pft) = rio_termcflux_cano_sipft(io_idx_si_pft) + sites(s)%term_carbonflux_ustory(i_pft) = rio_termcflux_usto_sipft(io_idx_si_pft) + sites(s)%fmort_carbonflux_canopy(i_pft) = rio_fmortcflux_cano_sipft(io_idx_si_pft) + sites(s)%fmort_carbonflux_ustory(i_pft) = rio_fmortcflux_usto_sipft(io_idx_si_pft) + sites(s)%imort_carbonflux(i_pft) = rio_imortcflux_sipft(io_idx_si_pft) + io_idx_si_pft = io_idx_si_pft + 1 + end do + + ! Mass balance and diagnostics across elements at the site level if(hlm_use_sp.eq.ifalse)then do el = 1, num_elements @@ -3061,7 +3091,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) patchespersite = 0 cpatch => sites(s)%oldest_patch - do while(associated(cpatch)) + do_patch: do while(associated(cpatch)) patchespersite = patchespersite + 1 @@ -3333,8 +3363,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) end if cpatch => cpatch%younger - - enddo ! patch do while + enddo do_patch if(patchespersite .ne. rio_npatch_si(io_idx_si)) then write(fates_log(),*) 'Number of patches per site during retrieval does not match allocation' @@ -3391,30 +3420,11 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ! Fill the site level diagnostics arrays ! ----------------------------------------------------------------------------- - - io_idx_si_scpf = io_idx_co_1st - do i_scls = 1,nlevsclass - do i_pft = 1, numpft - sites(s)%fmort_rate_canopy(i_scls, i_pft) = rio_fmortrate_cano_siscpf(io_idx_si_scpf) - sites(s)%fmort_rate_ustory(i_scls, i_pft) = rio_fmortrate_usto_siscpf(io_idx_si_scpf) - sites(s)%imort_rate(i_scls, i_pft) = rio_imortrate_siscpf(io_idx_si_scpf) - sites(s)%fmort_rate_crown(i_scls, i_pft) = rio_fmortrate_crown_siscpf(io_idx_si_scpf) - sites(s)%fmort_rate_cambial(i_scls, i_pft) = rio_fmortrate_cambi_siscpf(io_idx_si_scpf) - sites(s)%term_nindivs_canopy(i_scls,i_pft) = rio_termnindiv_cano_siscpf(io_idx_si_scpf) - sites(s)%term_nindivs_ustory(i_scls,i_pft) = rio_termnindiv_usto_siscpf(io_idx_si_scpf) - sites(s)%growthflux_fusion(i_scls, i_pft) = rio_growflx_fusion_siscpf(io_idx_si_scpf) - - sites(s)%term_abg_flux(i_scls,i_pft) = rio_abg_term_flux_siscpf(io_idx_si_scpf) - sites(s)%imort_abg_flux(i_scls,i_pft) = rio_abg_imort_flux_siscpf(io_idx_si_scpf) - sites(s)%fmort_abg_flux(i_scls,i_pft) = rio_abg_fmort_flux_siscpf(io_idx_si_scpf) - - io_idx_si_scpf = io_idx_si_scpf + 1 - end do sites(s)%demotion_rate(i_scls) = rio_demorate_sisc(io_idx_si_sc) sites(s)%promotion_rate(i_scls) = rio_promrate_sisc(io_idx_si_sc) - + io_idx_si_sc = io_idx_si_sc + 1 end do @@ -3452,16 +3462,6 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%demotion_carbonflux = rio_democflux_si(io_idx_si) sites(s)%promotion_carbonflux = rio_promcflux_si(io_idx_si) - io_idx_si_pft = io_idx_co_1st - do i_pft = 1, numpft - sites(s)%term_carbonflux_canopy(i_pft) = rio_termcflux_cano_sipft(io_idx_si_pft) - sites(s)%term_carbonflux_ustory(i_pft) = rio_termcflux_usto_sipft(io_idx_si_pft) - sites(s)%fmort_carbonflux_canopy(i_pft) = rio_fmortcflux_cano_sipft(io_idx_si_pft) - sites(s)%fmort_carbonflux_ustory(i_pft) = rio_fmortcflux_usto_sipft(io_idx_si_pft) - sites(s)%imort_carbonflux(i_pft) = rio_imortcflux_sipft(io_idx_si_pft) - io_idx_si_pft = io_idx_si_pft + 1 - end do - ! Site level phenology status flags sites(s)%cstatus = rio_cd_status_si(io_idx_si) From 49f82ab05ae0c088fc0e4bac976fc43bf4e56f54 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 23 Jun 2023 12:48:24 -0600 Subject: [PATCH 740/852] moved nlevsclass calculation earlier in subroutine --- main/FatesInterfaceMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 82b4357ea7..47fb444d38 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -822,6 +822,7 @@ subroutine SetFatesGlobalElements2(use_fates) nleafage = size(prt_params%leaf_long,dim=2) end if + nlevsclass = size(ED_val_history_sizeclass_bin_edges,dim=1) ! These values are used to define the restart file allocations and general structure ! of memory for the cohort arrays @@ -885,7 +886,6 @@ subroutine SetFatesGlobalElements2(use_fates) ! Identify number of size and age class bins for history output ! assume these arrays are 1-indexed - nlevsclass = size(ED_val_history_sizeclass_bin_edges,dim=1) nlevage = size(ED_val_history_ageclass_bin_edges,dim=1) nlevheight = size(ED_val_history_height_bin_edges,dim=1) nlevcoage = size(ED_val_history_coageclass_bin_edges,dim=1) From 180ba13a58c357a41b7ffc455eef8e2d1b6b92f2 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 26 Jun 2023 11:58:25 -0400 Subject: [PATCH 741/852] Moved restart calls for new phen variables to different location --- main/FatesRestartInterfaceMod.F90 | 39 +++++++++++-------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 3e20b7528b..ec0e4ffc1f 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -2126,10 +2126,15 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_fmortcflux_cano_sipft(io_idx_si_pft) = sites(s)%fmort_carbonflux_canopy(i_pft) rio_fmortcflux_usto_sipft(io_idx_si_pft) = sites(s)%fmort_carbonflux_ustory(i_pft) rio_imortcflux_sipft(io_idx_si_pft) = sites(s)%imort_carbonflux(i_pft) + rio_dd_status_sift(io_idx_si_pft) = sites(s)%dstatus(i_pft) + rio_dleafondate_sift(io_idx_si_pft) = sites(s)%dleafondate(i_pft) + rio_dleafoffdate_sift(io_idx_si_pft) = sites(s)%dleafoffdate(i_pft) + rio_dndaysleafon_sift(io_idx_si_pft) = sites(s)%dndaysleafon(i_pft) + rio_dndaysleafoff_sift(io_idx_si_pft) = sites(s)%dndaysleafoff(i_pft) + rio_elong_factor_sift(io_idx_si_pft) = sites(s)%elong_factor(i_pft) io_idx_si_pft = io_idx_si_pft + 1 end do - if(hlm_use_sp.eq.ifalse)then do el = 1, num_elements @@ -2504,18 +2509,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_gdd_si(io_idx_si) = sites(s)%grow_deg_days rio_phenmodeldate_si(io_idx_si) = sites(s)%phen_model_date - ! Drought-deciduous phenology are now PFT dependent - io_idx_si_pft = io_idx_co_1st - do i_pft = 1,numpft - rio_dd_status_sift(io_idx_si_pft) = sites(s)%dstatus(i_pft) - rio_dleafondate_sift(io_idx_si_pft) = sites(s)%dleafondate(i_pft) - rio_dleafoffdate_sift(io_idx_si_pft) = sites(s)%dleafoffdate(i_pft) - rio_dndaysleafon_sift(io_idx_si_pft) = sites(s)%dndaysleafon(i_pft) - rio_dndaysleafoff_sift(io_idx_si_pft) = sites(s)%dndaysleafoff(i_pft) - rio_elong_factor_sift(io_idx_si_pft) = sites(s)%elong_factor(i_pft) - - io_idx_si_pft = io_idx_si_pft + 1 - end do + rio_acc_ni_si(io_idx_si) = sites(s)%acc_NI @@ -3055,10 +3049,15 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%fmort_carbonflux_canopy(i_pft) = rio_fmortcflux_cano_sipft(io_idx_si_pft) sites(s)%fmort_carbonflux_ustory(i_pft) = rio_fmortcflux_usto_sipft(io_idx_si_pft) sites(s)%imort_carbonflux(i_pft) = rio_imortcflux_sipft(io_idx_si_pft) + sites(s)%dstatus(i_pft) = rio_dd_status_sift(io_idx_si_pft) + sites(s)%dleafondate(i_pft) = rio_dleafondate_sift(io_idx_si_pft) + sites(s)%dleafoffdate(i_pft) = rio_dleafoffdate_sift(io_idx_si_pft) + sites(s)%dndaysleafon(i_pft) = rio_dndaysleafon_sift(io_idx_si_pft) + sites(s)%dndaysleafoff(i_pft) = rio_dndaysleafoff_sift(io_idx_si_pft) + sites(s)%elong_factor(i_pft) = rio_elong_factor_sift(io_idx_si_pft) io_idx_si_pft = io_idx_si_pft + 1 end do - ! Mass balance and diagnostics across elements at the site level if(hlm_use_sp.eq.ifalse)then do el = 1, num_elements @@ -3474,17 +3473,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%grow_deg_days = rio_gdd_si(io_idx_si) sites(s)%phen_model_date= rio_phenmodeldate_si(io_idx_si) - ! Fill drought-deciduous variables, which are now PFT variables. - io_idx_si_pft = io_idx_co_1st - do i_pft = 1,numpft - sites(s)%dstatus(i_pft) = rio_dd_status_sift(io_idx_si_pft) - sites(s)%dleafondate(i_pft) = rio_dleafondate_sift(io_idx_si_pft) - sites(s)%dleafoffdate(i_pft) = rio_dleafoffdate_sift(io_idx_si_pft) - sites(s)%dndaysleafon(i_pft) = rio_dndaysleafon_sift(io_idx_si_pft) - sites(s)%dndaysleafoff(i_pft) = rio_dndaysleafoff_sift(io_idx_si_pft) - sites(s)%elong_factor(i_pft) = rio_elong_factor_sift(io_idx_si_pft) - io_idx_si_pft = io_idx_si_pft + 1 - end do + sites(s)%acc_NI = rio_acc_ni_si(io_idx_si) sites(s)%snow_depth = rio_snow_depth_si(io_idx_si) From fa431f59cea75634a37c61b802eccf241f1f718c Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 26 Jun 2023 11:34:16 -0600 Subject: [PATCH 742/852] removed change of vcmax parameter --- parameter_files/archive/api25.4.0_041023_pr958.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/parameter_files/archive/api25.4.0_041023_pr958.xml b/parameter_files/archive/api25.4.0_041023_pr958.xml index 16b3af5890..4c1e7d673a 100644 --- a/parameter_files/archive/api25.4.0_041023_pr958.xml +++ b/parameter_files/archive/api25.4.0_041023_pr958.xml @@ -53,7 +53,6 @@ day threshold compared against days since leaves abscised (shed) - fates_pft 50, 62, 39, 61, 58, 58, 62, 54, 54, 78, 78, 78 From bd82b5fe27cf26269a3d6618177e1375117e9f55 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 26 Jun 2023 14:56:15 -0400 Subject: [PATCH 743/852] updating the default parameter file per fixes in the api update xml to vcmax --- parameter_files/fates_params_default.cdl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index a3a210d658..46f3cea4f5 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -365,7 +365,7 @@ variables: double fates_leaf_stomatal_slope_medlyn(fates_pft) ; fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; - double fates_leaf_vcmax25top(fates_pft) ; + double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; double fates_leaf_vcmaxha(fates_pft) ; @@ -1265,7 +1265,8 @@ data: fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, 4.7, 2.2, 5.3, 1.6 ; - fates_leaf_vcmax25top = 50, 62, 39, 61, 58, 58, 62, 54, 54, 78, 78, 78 ; + fates_leaf_vcmax25top = + 50, 62, 39, 61, 58, 58, 62, 54, 54, 78, 78, 78 ; fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330 ; From facbf556b848e089ba98e1a003b8b2deaf736a30 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 26 Jun 2023 18:49:01 -0600 Subject: [PATCH 744/852] fix to the parameter file --- parameter_files/fates_params_default.cdl | 205 ++++------------------- 1 file changed, 30 insertions(+), 175 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index a3a210d658..d461cb6fbb 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1,4 +1,4 @@ -netcdf tmp { +netcdf fates_params_default { dimensions: fates_NCWD = 4 ; fates_history_age_bins = 7 ; @@ -365,7 +365,7 @@ variables: double fates_leaf_stomatal_slope_medlyn(fates_pft) ; fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; - double fates_leaf_vcmax25top(fates_pft) ; + double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; double fates_leaf_vcmaxha(fates_pft) ; @@ -437,24 +437,15 @@ variables: double fates_phen_cold_size_threshold(fates_pft) ; fates_phen_cold_size_threshold:units = "cm" ; fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; - double fates_phen_drought_threshold(fates_pft) ; - fates_phen_drought_threshold:units = "m3/m3 or mm" ; - fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold for semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; double fates_phen_evergreen(fates_pft) ; fates_phen_evergreen:units = "logical flag" ; fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; double fates_phen_flush_fraction(fates_pft) ; fates_phen_flush_fraction:units = "fraction" ; fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; - double fates_phen_fnrt_drop_fraction(fates_pft) ; - fates_phen_fnrt_drop_fraction:units = "fraction" ; - fates_phen_fnrt_drop_fraction:long_name = "fraction of fine roots to drop during drought/cold" ; - double fates_phen_mindaysoff(fates_pft) ; - fates_phen_mindaysoff:units = "days" ; - fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves abscised (shed)" ; - double fates_phen_moist_threshold(fates_pft) ; - fates_phen_moist_threshold:units = "m3/m3 or mm" ; - fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for drought semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_fnrt_drop_frac(fates_pft) ; + fates_phen_fnrt_drop_frac:units = "fraction" ; + fates_phen_fnrt_drop_frac:long_name = "fraction of fine roots to drop during drought or cold" ; double fates_phen_season_decid(fates_pft) ; fates_phen_season_decid:units = "logical flag" ; fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; @@ -536,60 +527,6 @@ variables: double fates_trim_limit(fates_pft) ; fates_trim_limit:units = "m2/m2" ; fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; - double fates_trs_repro_alloc_a(fates_pft) ; - fates_trs_repro_alloc_a:units = "fraction" ; - fates_trs_repro_alloc_a:long_name = "shape parameter for sigmoidal function relating dbh to reproductive allocation" ; - double fates_trs_repro_alloc_b(fates_pft) ; - fates_trs_repro_alloc_b:units = "fraction" ; - fates_trs_repro_alloc_b:long_name = "intercept parameter for sigmoidal function relating dbh to reproductive allocation" ; - double fates_trs_repro_frac_seed(fates_pft) ; - fates_trs_repro_frac_seed:units = "fraction" ; - fates_trs_repro_frac_seed:long_name = "fraction of reproductive mass that is seed" ; - double fates_trs_seedling_a_emerg(fates_pft) ; - fates_trs_seedling_a_emerg:units = "day -1" ; - fates_trs_seedling_a_emerg:long_name = "mean fraction of seed bank emerging" ; - double fates_trs_seedling_b_emerg(fates_pft) ; - fates_trs_seedling_b_emerg:units = "day -1" ; - fates_trs_seedling_b_emerg:long_name = "seedling emergence sensitivity to soil moisture" ; - double fates_trs_seedling_background_mort(fates_pft) ; - fates_trs_seedling_background_mort:units = "yr-1" ; - fates_trs_seedling_background_mort:long_name = "background seedling mortality rate" ; - double fates_trs_seedling_h2o_mort_a(fates_pft) ; - fates_trs_seedling_h2o_mort_a:units = "-" ; - fates_trs_seedling_h2o_mort_a:long_name = "coefficient in moisture-based seedling mortality" ; - double fates_trs_seedling_h2o_mort_b(fates_pft) ; - fates_trs_seedling_h2o_mort_b:units = "-" ; - fates_trs_seedling_h2o_mort_b:long_name = "coefficient in moisture-based seedling mortality" ; - double fates_trs_seedling_h2o_mort_c(fates_pft) ; - fates_trs_seedling_h2o_mort_c:units = "-" ; - fates_trs_seedling_h2o_mort_c:long_name = "coefficient in moisture-based seedling mortality" ; - double fates_trs_seedling_light_mort_a(fates_pft) ; - fates_trs_seedling_light_mort_a:units = "-" ; - fates_trs_seedling_light_mort_a:long_name = "light-based seedling mortality coefficient" ; - double fates_trs_seedling_light_mort_b(fates_pft) ; - fates_trs_seedling_light_mort_b:units = "-" ; - fates_trs_seedling_light_mort_b:long_name = "light-based seedling mortality coefficient" ; - double fates_trs_seedling_light_rec_a(fates_pft) ; - fates_trs_seedling_light_rec_a:units = "-" ; - fates_trs_seedling_light_rec_a:long_name = "coefficient in light-based seedling to sapling transition" ; - double fates_trs_seedling_light_rec_b(fates_pft) ; - fates_trs_seedling_light_rec_b:units = "-" ; - fates_trs_seedling_light_rec_b:long_name = "coefficient in light-based seedling to sapling transition" ; - double fates_trs_seedling_mdd_crit(fates_pft) ; - fates_trs_seedling_mdd_crit:units = "mm H2O day" ; - fates_trs_seedling_mdd_crit:long_name = "critical moisture deficit (suction) day accumulation for seedling moisture-based seedling mortality to begin" ; - double fates_trs_seedling_par_crit_germ(fates_pft) ; - fates_trs_seedling_par_crit_germ:units = "MJ m-2 day-1" ; - fates_trs_seedling_par_crit_germ:long_name = "critical light level for germination" ; - double fates_trs_seedling_psi_crit(fates_pft) ; - fates_trs_seedling_psi_crit:units = "mm H2O" ; - fates_trs_seedling_psi_crit:long_name = "critical soil moisture (suction) for seedling stress" ; - double fates_trs_seedling_psi_emerg(fates_pft) ; - fates_trs_seedling_psi_emerg:units = "mm h20 suction" ; - fates_trs_seedling_psi_emerg:long_name = "critical soil moisture for seedling emergence" ; - double fates_trs_seedling_root_depth(fates_pft) ; - fates_trs_seedling_root_depth:units = "m" ; - fates_trs_seedling_root_depth:long_name = "rooting depth of seedlings" ; double fates_turb_displar(fates_pft) ; fates_turb_displar:units = "unitless" ; fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; @@ -607,7 +544,7 @@ variables: fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; double fates_turnover_leaf(fates_leafage_class, fates_pft) ; fates_turnover_leaf:units = "yr" ; - fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale). For drought-deciduous PFTs, this also indicates the maximum length of the growing (i.e., leaves on) season." ; + fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; double fates_turnover_senleaf_fdrought(fates_pft) ; fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; @@ -818,6 +755,12 @@ variables: double fates_phen_coldtemp ; fates_phen_coldtemp:units = "degrees C" ; fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; + double fates_phen_drought_model ; + fates_phen_drought_model:units = "unitless" ; + fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; + double fates_phen_drought_threshold ; + fates_phen_drought_threshold:units = "m3/m3 or mm" ; + fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; double fates_phen_gddthresh_a ; fates_phen_gddthresh_a:units = "none" ; fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; @@ -827,9 +770,15 @@ variables: double fates_phen_gddthresh_c ; fates_phen_gddthresh_c:units = "none" ; fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_mindaysoff ; + fates_phen_mindaysoff:units = "days" ; + fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves became off-allometry" ; double fates_phen_mindayson ; fates_phen_mindayson:units = "days" ; fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; + double fates_phen_moist_threshold ; + fates_phen_moist_threshold:units = "m3/m3 or mm" ; + fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; double fates_phen_ncolddayslim ; fates_phen_ncolddayslim:units = "days" ; fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; @@ -839,27 +788,9 @@ variables: double fates_q10_mr ; fates_q10_mr:units = "unitless" ; fates_q10_mr:long_name = "Q10 for maintenance respiration" ; - double fates_rad_model ; - fates_rad_model:units = "unitless" ; - fates_rad_model:long_name = "switch designating the model for canopy radiation, 1 = Norman, 2 = Two-stream (experimental)" ; - double fates_regeneration_model ; - fates_regeneration_model:units = "-" ; - fates_regeneration_model:long_name = "switch for choosing between FATES\'s: 1) default regeneration scheme , 2) the Tree Recruitment Scheme (Hanbury-Brown et al., 2022), or (3) the Tree Recruitment Scheme without seedling dynamics" ; double fates_soil_salinity ; fates_soil_salinity:units = "ppt" ; fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; - double fates_trs_seedling2sap_par_timescale ; - fates_trs_seedling2sap_par_timescale:units = "days" ; - fates_trs_seedling2sap_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling to sapling transition rates" ; - double fates_trs_seedling_emerg_h2o_timescale ; - fates_trs_seedling_emerg_h2o_timescale:units = "days" ; - fates_trs_seedling_emerg_h2o_timescale:long_name = "Length of the window for the exponential moving average of smp used to calculate seedling emergence" ; - double fates_trs_seedling_mdd_timescale ; - fates_trs_seedling_mdd_timescale:units = "days" ; - fates_trs_seedling_mdd_timescale:long_name = "Length of the window for the exponential moving average of moisture deficit days used to calculate seedling mortality" ; - double fates_trs_seedling_mort_par_timescale ; - fates_trs_seedling_mort_par_timescale:units = "days" ; - fates_trs_seedling_mort_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling mortality" ; double fates_vai_top_bin_width ; fates_vai_top_bin_width:units = "m2/m2" ; fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; @@ -926,7 +857,7 @@ data: 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; - fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 2.4, 1.2, 1.2, 2.4, 1.2, + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 ; fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, @@ -1265,7 +1196,8 @@ data: fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, 4.7, 2.2, 5.3, 1.6 ; - fates_leaf_vcmax25top = 50, 62, 39, 61, 58, 58, 62, 54, 54, 78, 78, 78 ; + fates_leaf_vcmax25top = + 50, 62, 39, 61, 41, 58, 62, 54, 54, 78, 78, 78 ; fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330 ; @@ -1330,23 +1262,12 @@ data: fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_phen_drought_threshold = -152957.4, -152957.4, -152957.4, -152957.4, - -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, - -152957.4, -152957.4 ; - fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_phen_fnrt_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_phen_mindaysoff = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100 ; - - fates_phen_moist_threshold = -122365.9, -122365.9, -122365.9, -122365.9, - -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, - -122365.9, -122365.9 ; + fates_phen_fnrt_drop_frac = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; @@ -1437,68 +1358,6 @@ data: fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; - fates_trs_repro_alloc_a = 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, - 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049 ; - - fates_trs_repro_alloc_b = -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, - -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171 ; - - fates_trs_repro_frac_seed = 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, - 0.24, 0.24, 0.24, 0.24 ; - - fates_trs_seedling_a_emerg = 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, - 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003 ; - - fates_trs_seedling_b_emerg = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, - 1.2, 1.2, 1.2 ; - - fates_trs_seedling_background_mort = 0.1085371, 0.1085371, 0.1085371, - 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, - 0.1085371, 0.1085371, 0.1085371 ; - - fates_trs_seedling_h2o_mort_a = 4.070565e-17, 4.070565e-17, 4.070565e-17, - 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, - 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17 ; - - fates_trs_seedling_h2o_mort_b = -6.390757e-11, -6.390757e-11, -6.390757e-11, - -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, - -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11 ; - - fates_trs_seedling_h2o_mort_c = 1.268992e-05, 1.268992e-05, 1.268992e-05, - 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, - 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05 ; - - fates_trs_seedling_light_mort_a = -0.009897694, -0.009897694, -0.009897694, - -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, - -0.009897694, -0.009897694, -0.009897694, -0.009897694 ; - - fates_trs_seedling_light_mort_b = -7.154063, -7.154063, -7.154063, - -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, - -7.154063, -7.154063, -7.154063 ; - - fates_trs_seedling_light_rec_a = 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, - 0.007, 0.007, 0.007, 0.007, 0.007, 0.007 ; - - fates_trs_seedling_light_rec_b = 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, - 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615 ; - - fates_trs_seedling_mdd_crit = 1400000, 1400000, 1400000, 1400000, 1400000, - 1400000, 1400000, 1400000, 1400000, 1400000, 1400000, 1400000 ; - - fates_trs_seedling_par_crit_germ = 0.656, 0.656, 0.656, 0.656, 0.656, 0.656, - 0.656, 0.656, 0.656, 0.656, 0.656, 0.656 ; - - fates_trs_seedling_psi_crit = -251995.7, -251995.7, -251995.7, -251995.7, - -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, - -251995.7, -251995.7 ; - - fates_trs_seedling_psi_emerg = -15744.65, -15744.65, -15744.65, -15744.65, - -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, - -15744.65, -15744.65 ; - - fates_trs_seedling_root_depth = 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, - 0.06, 0.06, 0.06, 0.06, 0.06 ; - fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67 ; @@ -1670,34 +1529,30 @@ data: fates_phen_coldtemp = 7.5 ; + fates_phen_drought_model = 0 ; + + fates_phen_drought_threshold = 0.15 ; + fates_phen_gddthresh_a = -68 ; fates_phen_gddthresh_b = 638 ; fates_phen_gddthresh_c = -0.01 ; + fates_phen_mindaysoff = 100 ; + fates_phen_mindayson = 90 ; + fates_phen_moist_threshold = 0.18 ; + fates_phen_ncolddayslim = 5 ; fates_q10_froz = 1.5 ; fates_q10_mr = 1.5 ; - fates_rad_model = 1 ; - - fates_regeneration_model = 1 ; - fates_soil_salinity = 0.4 ; - fates_trs_seedling2sap_par_timescale = 32 ; - - fates_trs_seedling_emerg_h2o_timescale = 7 ; - - fates_trs_seedling_mdd_timescale = 126 ; - - fates_trs_seedling_mort_par_timescale = 32 ; - fates_vai_top_bin_width = 1 ; fates_vai_width_increase_factor = 1 ; From 0a3c66c2c31516b9b4108dbb431d95eb8b443df3 Mon Sep 17 00:00:00 2001 From: Marcos Longo Date: Mon, 26 Jun 2023 21:10:45 -0700 Subject: [PATCH 745/852] Added future parameters for addressing issue 1014 in an upcoming pull request. --- main/EDPftvarcon.F90 | 24 ++++++++++++++++++++++++ parameter_files/fates_params_default.cdl | 10 ++++++++++ 2 files changed, 34 insertions(+) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index f84cf96b9a..148df49e78 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -80,6 +80,8 @@ module EDPftvarcon ! 1=linear, 0=very curved real(r8), allocatable :: maintresp_reduction_intercept(:) ! intercept of MR reduction as f(carbon storage), ! 0=no throttling, 1=max throttling + real(r8), allocatable :: maintresp_reduction_upthresh (:) ! Upper threshold for storage biomass (relative + ! to leaf biomass) above which MR is not reduced real(r8), allocatable :: maintresp_leaf_atkin2017_baserate(:) ! leaf maintenance respiration base rate (r0) ! per Atkin et al 2017 @@ -94,6 +96,7 @@ module EDPftvarcon real(r8), allocatable :: mort_scalar_coldstress(:) ! maximum mortality rate from cold stress real(r8), allocatable :: mort_scalar_cstarvation(:) ! maximum mortality rate from carbon starvation real(r8), allocatable :: mort_scalar_hydrfailure(:) ! maximum mortality rate from hydraulic failure + real(r8), allocatable :: mort_upthresh_cstarvation(:) ! threshold for storage biomass (relative to target leaf biomass) above which carbon starvation is zero real(r8), allocatable :: hf_sm_threshold(:) ! soil moisture (btran units) at which drought mortality begins for non-hydraulic model real(r8), allocatable :: hf_flc_threshold(:) ! plant fractional loss of conductivity at which drought mortality begins for hydraulic model real(r8), allocatable :: vcmaxha(:) ! activation energy for vcmax @@ -448,6 +451,10 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_maintresp_reduction_upthresh' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_maintresp_leaf_atkin2017_baserate' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -560,6 +567,10 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_mort_upthresh_cstarvation' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_mort_hf_sm_threshold' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -865,6 +876,10 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetrieveParameterAllocate(name=name, & data=this%maintresp_reduction_intercept) + name = 'fates_maintresp_reduction_upthresh' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%maintresp_reduction_upthresh) + name = 'fates_maintresp_leaf_atkin2017_baserate' call fates_params%RetrieveParameterAllocate(name=name, & data=this%maintresp_leaf_atkin2017_baserate) @@ -961,6 +976,10 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetrieveParameterAllocate(name=name, & data=this%mort_scalar_hydrfailure) + name = 'fates_mort_upthresh_cstarvation' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%mort_upthresh_cstarvation) + name = 'fates_mort_ip_size_senescence' call fates_params%RetrieveParameterAllocate(name=name, & @@ -986,6 +1005,10 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetrieveParameterAllocate(name=name, & data=this%mort_scalar_cstarvation) + name = 'fates_mort_upthresh_cstarvation' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%mort_upthresh_cstarvation) + name = 'fates_mort_hf_sm_threshold' call fates_params%RetrieveParameterAllocate(name=name, & @@ -1615,6 +1638,7 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'mort_scalar_coldstress = ',EDPftvarcon_inst%mort_scalar_coldstress write(fates_log(),fmt0) 'mort_scalar_cstarvation = ',EDPftvarcon_inst%mort_scalar_cstarvation write(fates_log(),fmt0) 'mort_scalar_hydrfailure = ',EDPftvarcon_inst%mort_scalar_hydrfailure + write(fates_log(),fmt0) 'mort_upthresh_cstarvation = ',EDPftvarcon_inst%mort_upthresh_cstarvation write(fates_log(),fmt0) 'hf_sm_threshold = ',EDPftvarcon_inst%hf_sm_threshold write(fates_log(),fmt0) 'hf_flc_threshold = ',EDPftvarcon_inst%hf_flc_threshold write(fates_log(),fmt0) 'vcmaxha = ',EDPftvarcon_inst%vcmaxha diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index a3a210d658..d1b219a36a 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -389,6 +389,9 @@ variables: double fates_maintresp_reduction_intercept(fates_pft) ; fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; + double fates_maintresp_reduction_upthresh(fates_pft) ; + fates_maintresp_reduction_upthresh:units = "unitless (0-1)" ; + fates_maintresp_reduction_upthresh:long_name = "upper threshold for storage biomass (relative to leaf biomass) above which MR is not reduced" ; double fates_mort_bmort(fates_pft) ; fates_mort_bmort:units = "1/yr" ; fates_mort_bmort:long_name = "background mortality rate" ; @@ -428,6 +431,9 @@ variables: double fates_mort_scalar_hydrfailure(fates_pft) ; fates_mort_scalar_hydrfailure:units = "1/yr" ; fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; + double fates_mort_upthresh_cstarvation(fates_pft) ; + fates_mort_upthresh_cstarvation:units = "unitless" ; + fates_mort_upthresh_cstarvation:long_name = "threshold for storage biomass (relative to target leaf biomass) above which carbon starvation is zero" ; double fates_nonhydro_smpsc(fates_pft) ; fates_nonhydro_smpsc:units = "mm" ; fates_nonhydro_smpsc:long_name = "Soil water potential at full stomatal closure" ; @@ -1288,6 +1294,8 @@ data: fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_maintresp_reduction_upthresh = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014 ; @@ -1322,6 +1330,8 @@ data: fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6 ; + fates_mort_upthresh_cstarvation = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_nonhydro_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, -255000, -255000, -255000, -255000, -255000, -255000 ; From 59f56ee08e8e177db9e05737664b8e719b4e9626 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 27 Jun 2023 11:39:26 -0400 Subject: [PATCH 746/852] reapplied parameter update from xml, something got lost in a merge --- parameter_files/fates_params_default.cdl | 198 ++++++++++++++++++++--- 1 file changed, 172 insertions(+), 26 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 2ca43a0672..f1521d70d6 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -437,15 +437,24 @@ variables: double fates_phen_cold_size_threshold(fates_pft) ; fates_phen_cold_size_threshold:units = "cm" ; fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; + double fates_phen_drought_threshold(fates_pft) ; + fates_phen_drought_threshold:units = "m3/m3 or mm" ; + fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold for semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; double fates_phen_evergreen(fates_pft) ; fates_phen_evergreen:units = "logical flag" ; fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; double fates_phen_flush_fraction(fates_pft) ; fates_phen_flush_fraction:units = "fraction" ; fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; - double fates_phen_fnrt_drop_frac(fates_pft) ; - fates_phen_fnrt_drop_frac:units = "fraction" ; - fates_phen_fnrt_drop_frac:long_name = "fraction of fine roots to drop during drought or cold" ; + double fates_phen_fnrt_drop_fraction(fates_pft) ; + fates_phen_fnrt_drop_fraction:units = "fraction" ; + fates_phen_fnrt_drop_fraction:long_name = "fraction of fine roots to drop during drought/cold" ; + double fates_phen_mindaysoff(fates_pft) ; + fates_phen_mindaysoff:units = "days" ; + fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves abscised (shed)" ; + double fates_phen_moist_threshold(fates_pft) ; + fates_phen_moist_threshold:units = "m3/m3 or mm" ; + fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for drought semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; double fates_phen_season_decid(fates_pft) ; fates_phen_season_decid:units = "logical flag" ; fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; @@ -527,6 +536,60 @@ variables: double fates_trim_limit(fates_pft) ; fates_trim_limit:units = "m2/m2" ; fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; + double fates_trs_repro_alloc_a(fates_pft) ; + fates_trs_repro_alloc_a:units = "fraction" ; + fates_trs_repro_alloc_a:long_name = "shape parameter for sigmoidal function relating dbh to reproductive allocation" ; + double fates_trs_repro_alloc_b(fates_pft) ; + fates_trs_repro_alloc_b:units = "fraction" ; + fates_trs_repro_alloc_b:long_name = "intercept parameter for sigmoidal function relating dbh to reproductive allocation" ; + double fates_trs_repro_frac_seed(fates_pft) ; + fates_trs_repro_frac_seed:units = "fraction" ; + fates_trs_repro_frac_seed:long_name = "fraction of reproductive mass that is seed" ; + double fates_trs_seedling_a_emerg(fates_pft) ; + fates_trs_seedling_a_emerg:units = "day -1" ; + fates_trs_seedling_a_emerg:long_name = "mean fraction of seed bank emerging" ; + double fates_trs_seedling_b_emerg(fates_pft) ; + fates_trs_seedling_b_emerg:units = "day -1" ; + fates_trs_seedling_b_emerg:long_name = "seedling emergence sensitivity to soil moisture" ; + double fates_trs_seedling_background_mort(fates_pft) ; + fates_trs_seedling_background_mort:units = "yr-1" ; + fates_trs_seedling_background_mort:long_name = "background seedling mortality rate" ; + double fates_trs_seedling_h2o_mort_a(fates_pft) ; + fates_trs_seedling_h2o_mort_a:units = "-" ; + fates_trs_seedling_h2o_mort_a:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_trs_seedling_h2o_mort_b(fates_pft) ; + fates_trs_seedling_h2o_mort_b:units = "-" ; + fates_trs_seedling_h2o_mort_b:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_trs_seedling_h2o_mort_c(fates_pft) ; + fates_trs_seedling_h2o_mort_c:units = "-" ; + fates_trs_seedling_h2o_mort_c:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_trs_seedling_light_mort_a(fates_pft) ; + fates_trs_seedling_light_mort_a:units = "-" ; + fates_trs_seedling_light_mort_a:long_name = "light-based seedling mortality coefficient" ; + double fates_trs_seedling_light_mort_b(fates_pft) ; + fates_trs_seedling_light_mort_b:units = "-" ; + fates_trs_seedling_light_mort_b:long_name = "light-based seedling mortality coefficient" ; + double fates_trs_seedling_light_rec_a(fates_pft) ; + fates_trs_seedling_light_rec_a:units = "-" ; + fates_trs_seedling_light_rec_a:long_name = "coefficient in light-based seedling to sapling transition" ; + double fates_trs_seedling_light_rec_b(fates_pft) ; + fates_trs_seedling_light_rec_b:units = "-" ; + fates_trs_seedling_light_rec_b:long_name = "coefficient in light-based seedling to sapling transition" ; + double fates_trs_seedling_mdd_crit(fates_pft) ; + fates_trs_seedling_mdd_crit:units = "mm H2O day" ; + fates_trs_seedling_mdd_crit:long_name = "critical moisture deficit (suction) day accumulation for seedling moisture-based seedling mortality to begin" ; + double fates_trs_seedling_par_crit_germ(fates_pft) ; + fates_trs_seedling_par_crit_germ:units = "MJ m-2 day-1" ; + fates_trs_seedling_par_crit_germ:long_name = "critical light level for germination" ; + double fates_trs_seedling_psi_crit(fates_pft) ; + fates_trs_seedling_psi_crit:units = "mm H2O" ; + fates_trs_seedling_psi_crit:long_name = "critical soil moisture (suction) for seedling stress" ; + double fates_trs_seedling_psi_emerg(fates_pft) ; + fates_trs_seedling_psi_emerg:units = "mm h20 suction" ; + fates_trs_seedling_psi_emerg:long_name = "critical soil moisture for seedling emergence" ; + double fates_trs_seedling_root_depth(fates_pft) ; + fates_trs_seedling_root_depth:units = "m" ; + fates_trs_seedling_root_depth:long_name = "rooting depth of seedlings" ; double fates_turb_displar(fates_pft) ; fates_turb_displar:units = "unitless" ; fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; @@ -544,7 +607,7 @@ variables: fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; double fates_turnover_leaf(fates_leafage_class, fates_pft) ; fates_turnover_leaf:units = "yr" ; - fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; + fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale). For drought-deciduous PFTs, this also indicates the maximum length of the growing (i.e., leaves on) season." ; double fates_turnover_senleaf_fdrought(fates_pft) ; fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; @@ -755,12 +818,6 @@ variables: double fates_phen_coldtemp ; fates_phen_coldtemp:units = "degrees C" ; fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; - double fates_phen_drought_model ; - fates_phen_drought_model:units = "unitless" ; - fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; - double fates_phen_drought_threshold ; - fates_phen_drought_threshold:units = "m3/m3 or mm" ; - fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; double fates_phen_gddthresh_a ; fates_phen_gddthresh_a:units = "none" ; fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; @@ -770,15 +827,9 @@ variables: double fates_phen_gddthresh_c ; fates_phen_gddthresh_c:units = "none" ; fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_mindaysoff ; - fates_phen_mindaysoff:units = "days" ; - fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves became off-allometry" ; double fates_phen_mindayson ; fates_phen_mindayson:units = "days" ; fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; - double fates_phen_moist_threshold ; - fates_phen_moist_threshold:units = "m3/m3 or mm" ; - fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; double fates_phen_ncolddayslim ; fates_phen_ncolddayslim:units = "days" ; fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; @@ -788,9 +839,27 @@ variables: double fates_q10_mr ; fates_q10_mr:units = "unitless" ; fates_q10_mr:long_name = "Q10 for maintenance respiration" ; + double fates_rad_model ; + fates_rad_model:units = "unitless" ; + fates_rad_model:long_name = "switch designating the model for canopy radiation, 1 = Norman, 2 = Two-stream (experimental)" ; + double fates_regeneration_model ; + fates_regeneration_model:units = "-" ; + fates_regeneration_model:long_name = "switch for choosing between FATES\'s: 1) default regeneration scheme , 2) the Tree Recruitment Scheme (Hanbury-Brown et al., 2022), or (3) the Tree Recruitment Scheme without seedling dynamics" ; double fates_soil_salinity ; fates_soil_salinity:units = "ppt" ; fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; + double fates_trs_seedling2sap_par_timescale ; + fates_trs_seedling2sap_par_timescale:units = "days" ; + fates_trs_seedling2sap_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling to sapling transition rates" ; + double fates_trs_seedling_emerg_h2o_timescale ; + fates_trs_seedling_emerg_h2o_timescale:units = "days" ; + fates_trs_seedling_emerg_h2o_timescale:long_name = "Length of the window for the exponential moving average of smp used to calculate seedling emergence" ; + double fates_trs_seedling_mdd_timescale ; + fates_trs_seedling_mdd_timescale:units = "days" ; + fates_trs_seedling_mdd_timescale:long_name = "Length of the window for the exponential moving average of moisture deficit days used to calculate seedling mortality" ; + double fates_trs_seedling_mort_par_timescale ; + fates_trs_seedling_mort_par_timescale:units = "days" ; + fates_trs_seedling_mort_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling mortality" ; double fates_vai_top_bin_width ; fates_vai_top_bin_width:units = "m2/m2" ; fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; @@ -857,7 +926,7 @@ data: 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; - fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 2.4, 1.2, 1.2, 2.4, 1.2, 1.2, 1.2, 1.2 ; fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, @@ -1262,12 +1331,23 @@ data: fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_phen_drought_threshold = -152957.4, -152957.4, -152957.4, -152957.4, + -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, + -152957.4, -152957.4 ; + fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, 0.5 ; - fates_phen_fnrt_drop_frac = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_phen_fnrt_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_mindaysoff = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_phen_moist_threshold = -122365.9, -122365.9, -122365.9, -122365.9, + -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, + -122365.9, -122365.9 ; fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; @@ -1358,6 +1438,68 @@ data: fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; + fates_trs_repro_alloc_a = 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, + 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049 ; + + fates_trs_repro_alloc_b = -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, + -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171 ; + + fates_trs_repro_frac_seed = 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, + 0.24, 0.24, 0.24, 0.24 ; + + fates_trs_seedling_a_emerg = 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, + 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003 ; + + fates_trs_seedling_b_emerg = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + 1.2, 1.2, 1.2 ; + + fates_trs_seedling_background_mort = 0.1085371, 0.1085371, 0.1085371, + 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, + 0.1085371, 0.1085371, 0.1085371 ; + + fates_trs_seedling_h2o_mort_a = 4.070565e-17, 4.070565e-17, 4.070565e-17, + 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, + 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17 ; + + fates_trs_seedling_h2o_mort_b = -6.390757e-11, -6.390757e-11, -6.390757e-11, + -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, + -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11 ; + + fates_trs_seedling_h2o_mort_c = 1.268992e-05, 1.268992e-05, 1.268992e-05, + 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, + 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05 ; + + fates_trs_seedling_light_mort_a = -0.009897694, -0.009897694, -0.009897694, + -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, + -0.009897694, -0.009897694, -0.009897694, -0.009897694 ; + + fates_trs_seedling_light_mort_b = -7.154063, -7.154063, -7.154063, + -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, + -7.154063, -7.154063, -7.154063 ; + + fates_trs_seedling_light_rec_a = 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, + 0.007, 0.007, 0.007, 0.007, 0.007, 0.007 ; + + fates_trs_seedling_light_rec_b = 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, + 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615 ; + + fates_trs_seedling_mdd_crit = 1400000, 1400000, 1400000, 1400000, 1400000, + 1400000, 1400000, 1400000, 1400000, 1400000, 1400000, 1400000 ; + + fates_trs_seedling_par_crit_germ = 0.656, 0.656, 0.656, 0.656, 0.656, 0.656, + 0.656, 0.656, 0.656, 0.656, 0.656, 0.656 ; + + fates_trs_seedling_psi_crit = -251995.7, -251995.7, -251995.7, -251995.7, + -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, + -251995.7, -251995.7 ; + + fates_trs_seedling_psi_emerg = -15744.65, -15744.65, -15744.65, -15744.65, + -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, + -15744.65, -15744.65 ; + + fates_trs_seedling_root_depth = 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, + 0.06, 0.06, 0.06, 0.06, 0.06 ; + fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67 ; @@ -1529,30 +1671,34 @@ data: fates_phen_coldtemp = 7.5 ; - fates_phen_drought_model = 0 ; - - fates_phen_drought_threshold = 0.15 ; - fates_phen_gddthresh_a = -68 ; fates_phen_gddthresh_b = 638 ; fates_phen_gddthresh_c = -0.01 ; - fates_phen_mindaysoff = 100 ; - fates_phen_mindayson = 90 ; - fates_phen_moist_threshold = 0.18 ; - fates_phen_ncolddayslim = 5 ; fates_q10_froz = 1.5 ; fates_q10_mr = 1.5 ; + fates_rad_model = 1 ; + + fates_regeneration_model = 1 ; + fates_soil_salinity = 0.4 ; + fates_trs_seedling2sap_par_timescale = 32 ; + + fates_trs_seedling_emerg_h2o_timescale = 7 ; + + fates_trs_seedling_mdd_timescale = 126 ; + + fates_trs_seedling_mort_par_timescale = 32 ; + fates_vai_top_bin_width = 1 ; fates_vai_width_increase_factor = 1 ; From cbf0d69d61f71c04e69e0f30aefba0f82abc3ecb Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 27 Jun 2023 17:00:45 -0700 Subject: [PATCH 747/852] add seed dispersal parameters for PR 1005 This also updates the comment header identifying which changes are associated with which pull request --- .../archive/api25.4.0_041023_pr958.xml | 48 +++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/parameter_files/archive/api25.4.0_041023_pr958.xml b/parameter_files/archive/api25.4.0_041023_pr958.xml index 16b3af5890..420b77bbb3 100644 --- a/parameter_files/archive/api25.4.0_041023_pr958.xml +++ b/parameter_files/archive/api25.4.0_041023_pr958.xml @@ -1,11 +1,25 @@ - + + + + + - + + + + + + + + + + + @@ -220,12 +234,40 @@ Length of the window for the exponential moving average of moisture deficit days used to calculate seedling mortality 126 - + fates_trs_seedling2sap_par_timescale scalar days Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling to sapling transition rates 32 + + fates_seed_dispersal_max_dist + fates_pft + m + maximum seed dispersal distance for a given pft + + + + fates_seed_dispersal_fraction + fates_pft + fraction + fraction of seed rain to be dispersed to other grid cells + + + + fates_seed_dispersal_pdf_scale + fates_pft + unitless + seed dispersal probability density function scale parameter, A, Table 1 Bullock et al 2016 + + + + fates_seed_dispersal_pdf_shape + fates_pft + unitless + seed dispersal probability density function shape parameter, B, Table 1 Bullock et al 2016 + + From a6008b907a3c35038a3b02706203757f45a1b7c6 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 27 Jun 2023 17:24:35 -0700 Subject: [PATCH 748/852] adds two new parameters to address issue 1014 these will be utilitized in a future pull request --- .../archive/api25.4.0_041023_pr958.xml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/parameter_files/archive/api25.4.0_041023_pr958.xml b/parameter_files/archive/api25.4.0_041023_pr958.xml index 420b77bbb3..c5acaa8853 100644 --- a/parameter_files/archive/api25.4.0_041023_pr958.xml +++ b/parameter_files/archive/api25.4.0_041023_pr958.xml @@ -3,7 +3,7 @@ - + @@ -19,6 +19,9 @@ + + + @@ -267,6 +270,20 @@ fates_pft unitless seed dispersal probability density function shape parameter, B, Table 1 Bullock et al 2016 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + + + fates_maintresp_reduction_upthresh + fates_pft + unitless (0-1) + upper threshold for storage biomass (relative to leaf biomass) above which MR is not reduced + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + + + fates_mort_upthresh_cstarvation + fates_pft + unitless + threshold for storage biomass (relative to target leaf biomass) above which carbon starvation is zero From e4cf214b99f4ed7ad5bc5c47be84d4a3ad120498 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 27 Jun 2023 19:20:22 -0600 Subject: [PATCH 749/852] provisions for frozen/arid conditions on drought deciduous suction triggers --- biogeochem/EDPhysiologyMod.F90 | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index b92c330d2b..d0d66b219b 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -898,7 +898,7 @@ subroutine phenology( currentSite, bc_in ) use EDParamsMod, only : ED_val_phen_mindayson use EDParamsMod, only : ED_val_phen_ncolddayslim use EDParamsMod, only : ED_val_phen_coldtemp - + use EDBtranMod, only : check_layer_water ! ! !ARGUMENTS: type(ed_site_type), intent(inout), target :: currentSite @@ -913,6 +913,7 @@ subroutine phenology( currentSite, bc_in ) integer :: i_wmem ! Loop counter for water mem days integer :: i_tmem ! Loop counter for veg temp mem days integer :: ipft ! plant functional type index + integer :: j ! Soil layer index real(r8) :: mean_10day_liqvol ! mean soil liquid volume over last 10 days [m3/m3] real(r8) :: mean_10day_smp ! mean soil matric potential over last 10 days [mm] real(r8) :: leaf_c ! leaf carbon [kg] @@ -1183,12 +1184,25 @@ subroutine phenology( currentSite, bc_in ) ! Set the memory to be the weighted average of the soil properties, using the ! root fraction of each layer (except the topmost one) as the weighting factor. + currentSite%liqvol_memory(1,ipft) = sum( bc_in%h2o_liqvol_sl (2:nlevroot) * & currentSite%rootfrac_scr(2:nlevroot) ) / & - rootfrac_notop - currentSite%smp_memory (1,ipft) = sum( bc_in%smp_sl (2:nlevroot) * & - currentSite%rootfrac_scr(2:nlevroot) ) / & - rootfrac_notop + rootfrac_notop + currentSite%smp_memory (1,ipft) = 0._r8 + do j = 2,nlevroot + if(check_layer_water(bc_in%h2o_liqvol_sl(j),bc_in%tempk_sl(j)) ) then + currentSite%smp_memory (1,ipft) = currentSite%smp_memory (1,ipft) + & + bc_in%smp_sl (j) * & + currentSite%rootfrac_scr(j) / & + rootfrac_notop + else + ! Nominal extreme suction for frozen or unreasonably dry soil + currentSite%smp_memory (1,ipft) = currentSite%smp_memory (1,ipft) + & + -10000._r8* & + currentSite%rootfrac_scr(j) / & + rootfrac_notop + end if + end do ! Calculate the mean soil moisture ( liquid volume (m3/m3) and matric potential (mm)) ! over the last 10 days From 8d2d76585f97e6a38994afbf3bde47f5540a29a6 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 27 Jun 2023 21:28:37 -0400 Subject: [PATCH 750/852] Updating parameter file --- parameter_files/archive/api25.4.0_041023_pr958.xml | 14 ++++++++++++++ parameter_files/fates_params_default.cdl | 12 ++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/parameter_files/archive/api25.4.0_041023_pr958.xml b/parameter_files/archive/api25.4.0_041023_pr958.xml index 4c1e7d673a..5ad6134ffe 100644 --- a/parameter_files/archive/api25.4.0_041023_pr958.xml +++ b/parameter_files/archive/api25.4.0_041023_pr958.xml @@ -26,6 +26,20 @@ fates_params_default.cdl 1,2,3,4,5,6,7,8,9,10,11,12 + + maintresp_reduction_upthresh + fates_pft + unitless (0-1) + upper threshold for storage biomass (relative to leaf biomass) above which MR is not reduced + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + + + fates_mort_upthresh_cstarvation + fates_pft + unitless + threshold for storage biomass (relative to target leaf biomass) above which carbon starvation is zero + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + fates_phen_fnrt_drop_fraction fraction of fine roots to drop during drought/cold diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 95fdaecb86..aeb33a74b8 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1,4 +1,4 @@ -netcdf fates_params_default { +netcdf tmp { dimensions: fates_NCWD = 4 ; fates_history_age_bins = 7 ; @@ -389,9 +389,6 @@ variables: double fates_maintresp_reduction_intercept(fates_pft) ; fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; - double fates_maintresp_reduction_upthresh(fates_pft) ; - fates_maintresp_reduction_upthresh:units = "unitless (0-1)" ; - fates_maintresp_reduction_upthresh:long_name = "upper threshold for storage biomass (relative to leaf biomass) above which MR is not reduced" ; double fates_mort_bmort(fates_pft) ; fates_mort_bmort:units = "1/yr" ; fates_mort_bmort:long_name = "background mortality rate" ; @@ -623,6 +620,9 @@ variables: double fates_woody(fates_pft) ; fates_woody:units = "logical flag" ; fates_woody:long_name = "Binary woody lifeform flag" ; + double maintresp_reduction_upthresh(fates_pft) ; + maintresp_reduction_upthresh:units = "unitless (0-1)" ; + maintresp_reduction_upthresh:long_name = "upper threshold for storage biomass (relative to leaf biomass) above which MR is not reduced" ; double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; fates_hlm_pft_map:units = "area fraction" ; fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; @@ -1295,8 +1295,6 @@ data: fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_maintresp_reduction_upthresh = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014 ; @@ -1533,6 +1531,8 @@ data: fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; + maintresp_reduction_upthresh = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_hlm_pft_map = 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, From f87ea87757c01e96a979ac588f513f15c9ae1566 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 27 Jun 2023 22:57:27 -0400 Subject: [PATCH 751/852] fixed parameter name --- parameter_files/archive/api25.4.0_041023_pr958.xml | 2 +- parameter_files/fates_params_default.cdl | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/parameter_files/archive/api25.4.0_041023_pr958.xml b/parameter_files/archive/api25.4.0_041023_pr958.xml index 5ad6134ffe..fb424d93e0 100644 --- a/parameter_files/archive/api25.4.0_041023_pr958.xml +++ b/parameter_files/archive/api25.4.0_041023_pr958.xml @@ -27,7 +27,7 @@ 1,2,3,4,5,6,7,8,9,10,11,12 - maintresp_reduction_upthresh + fates_maintresp_reduction_upthresh fates_pft unitless (0-1) upper threshold for storage biomass (relative to leaf biomass) above which MR is not reduced diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index aeb33a74b8..6a48bdaa41 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -389,6 +389,9 @@ variables: double fates_maintresp_reduction_intercept(fates_pft) ; fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; + double fates_maintresp_reduction_upthresh(fates_pft) ; + fates_maintresp_reduction_upthresh:units = "unitless (0-1)" ; + fates_maintresp_reduction_upthresh:long_name = "upper threshold for storage biomass (relative to leaf biomass) above which MR is not reduced" ; double fates_mort_bmort(fates_pft) ; fates_mort_bmort:units = "1/yr" ; fates_mort_bmort:long_name = "background mortality rate" ; @@ -620,9 +623,6 @@ variables: double fates_woody(fates_pft) ; fates_woody:units = "logical flag" ; fates_woody:long_name = "Binary woody lifeform flag" ; - double maintresp_reduction_upthresh(fates_pft) ; - maintresp_reduction_upthresh:units = "unitless (0-1)" ; - maintresp_reduction_upthresh:long_name = "upper threshold for storage biomass (relative to leaf biomass) above which MR is not reduced" ; double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; fates_hlm_pft_map:units = "area fraction" ; fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; @@ -1295,6 +1295,8 @@ data: fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_maintresp_reduction_upthresh = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014 ; @@ -1531,8 +1533,6 @@ data: fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; - maintresp_reduction_upthresh = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_hlm_pft_map = 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, From 5830b351853faf8459cbaf848746aed776847c2f Mon Sep 17 00:00:00 2001 From: Marcos Longo <5891904+mpaiao@users.noreply.github.com> Date: Wed, 28 Jun 2023 09:07:26 -0700 Subject: [PATCH 752/852] Update EDPhysiologyMod.F90 Revised the lower threshold for soil potential (and turned into a local constant). --- biogeochem/EDPhysiologyMod.F90 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index b5d7f1d4a9..9040343100 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -178,6 +178,9 @@ module EDPhysiologyMod ! computational problems. The current threshold ! is the same used in ED-2.2. + real(r8), parameter :: smp_lwr_bound = -1000000._r8 ! Imposed soil matric potential lower bound for + ! frozen or excessively dry soils, used when + ! computing water stress. ! ============================================================================ contains @@ -1202,7 +1205,7 @@ subroutine phenology( currentSite, bc_in ) else ! Nominal extreme suction for frozen or unreasonably dry soil currentSite%smp_memory (1,ipft) = currentSite%smp_memory (1,ipft) + & - -10000._r8* & + smp_lwr_bound * & currentSite%rootfrac_scr(j) / & rootfrac_notop end if From 6da2d8509ebf8116d61f7349617b3e6722b43d91 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 28 Jun 2023 15:35:24 -0700 Subject: [PATCH 753/852] correct values assignment error for param patch This also updates the output default parameter file --- .../archive/api25.4.0_041023_pr958.xml | 4 ++-- parameter_files/fates_params_default.cdl | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/parameter_files/archive/api25.4.0_041023_pr958.xml b/parameter_files/archive/api25.4.0_041023_pr958.xml index c5acaa8853..74f8f88def 100644 --- a/parameter_files/archive/api25.4.0_041023_pr958.xml +++ b/parameter_files/archive/api25.4.0_041023_pr958.xml @@ -270,7 +270,7 @@ fates_pft unitless seed dispersal probability density function shape parameter, B, Table 1 Bullock et al 2016 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + fates_maintresp_reduction_upthresh @@ -284,7 +284,7 @@ fates_pft unitless threshold for storage biomass (relative to target leaf biomass) above which carbon starvation is zero - + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index d1b219a36a..e7b96c5bed 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -530,6 +530,18 @@ variables: double fates_recruit_seed_supplement(fates_pft) ; fates_recruit_seed_supplement:units = "KgC/m2/yr" ; fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; + double fates_seed_dispersal_fraction(fates_pft) ; + fates_seed_dispersal_fraction:units = "fraction" ; + fates_seed_dispersal_fraction:long_name = "fraction of seed rain to be dispersed to other grid cells" ; + double fates_seed_dispersal_max_dist(fates_pft) ; + fates_seed_dispersal_max_dist:units = "m" ; + fates_seed_dispersal_max_dist:long_name = "maximum seed dispersal distance for a given pft" ; + double fates_seed_dispersal_pdf_scale(fates_pft) ; + fates_seed_dispersal_pdf_scale:units = "unitless" ; + fates_seed_dispersal_pdf_scale:long_name = "seed dispersal probability density function scale parameter, A, Table 1 Bullock et al 2016" ; + double fates_seed_dispersal_pdf_shape(fates_pft) ; + fates_seed_dispersal_pdf_shape:units = "unitless" ; + fates_seed_dispersal_pdf_shape:long_name = "seed dispersal probability density function shape parameter, B, Table 1 Bullock et al 2016" ; double fates_stoich_nitr(fates_plant_organs, fates_pft) ; fates_stoich_nitr:units = "gN/gC" ; fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; @@ -1423,6 +1435,14 @@ data: fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_seed_dispersal_fraction = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_seed_dispersal_max_dist = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_seed_dispersal_pdf_scale = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_seed_dispersal_pdf_shape = _, _, _, _, _, _, _, _, _, _, _, _ ; + fates_stoich_nitr = 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, From 516c7e8c7a5e4ec63b3d0640a5a70b7a0c565f03 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 28 Jun 2023 15:41:25 -0700 Subject: [PATCH 754/852] fix default param name in file --- 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 4f90e4f6fb..f170fe2275 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1,4 +1,4 @@ -netcdf tmp { +netcdf fates_params_default { dimensions: fates_NCWD = 4 ; fates_history_age_bins = 7 ; From 3fb867309b2a81a7e0eac9ce05a8439f1586e364 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 30 Jun 2023 15:10:21 -0700 Subject: [PATCH 755/852] remove regeneration model setting check This came in with a previous pull request that included multiple pull request updates to the default parameter file. This protection is no longer needed for this specific pull request. --- main/EDPftvarcon.F90 | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index da5a064ca7..31c9a08ad5 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1718,7 +1718,6 @@ subroutine FatesCheckParams(is_master) 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 : regeneration_model use FatesInterfaceTypesMod, only : hlm_use_fixed_biogeog,hlm_use_sp, hlm_name use FatesInterfaceTypesMod, only : hlm_use_inventory_init @@ -1750,16 +1749,6 @@ subroutine FatesCheckParams(is_master) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if(regeneration_model.ne.1) then - write(fates_log(),*) 'The only available regeneration model' - write(fates_log(),*) 'is the default, ie 1' - write(fates_log(),*) 'The Hanbury-Brown models are not available yet' - write(fates_log(),*) 'You specified fates_regeneration_model = ',regeneration_model - write(fates_log(),*) 'Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - select case (hlm_parteh_mode) case (prt_cnp_flex_allom_hyp) From 7395273ce1e6b52989d376c84ae36a2d2a9c3948 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 6 Jul 2023 11:45:43 -0700 Subject: [PATCH 756/852] update seedlingparpatch to handle newly spawned patches Newly spawned patches that have treefall disturbance in the first canopy will not have cohorts until the recruitment step after this update. As such, avoid indexing via ncan which will be zero. --- main/FatesInterfaceMod.F90 | 45 +++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index fac69a1716..01a5c49f55 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1983,10 +1983,8 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) call SeedlingParPatch(cpatch, & bc_in(s)%solad_parb(ifp,ipar) + bc_in(s)%solai_parb(ifp,ipar), & - seedling_par_high, & - par_high_frac, & - seedling_par_low, & - par_low_frac) + seedling_par_high, par_high_frac, seedling_par_low,& + & par_low_frac) new_seedling_layer_par = seedling_par_high*par_high_frac + seedling_par_low*par_low_frac @@ -2071,25 +2069,34 @@ subroutine SeedlingParPatch(cpatch, & integer :: ipft ! current PFT index integer :: iv ! lower-most leaf layer index for the cl & pft combo - ! Radiation intensity exiting the layer above the bottom-most - upper_par = 0._r8 - upper_area = 0._r8 - cl = max(1,cpatch%NCL_p-1) - do ipft = 1,numpft - iv = cpatch%ncan(cl,ipft) - upper_par = upper_par + cpatch%canopy_area_profile(cl,ipft,1)* & - (cpatch%parprof_pft_dir_z(cl,ipft,iv)+cpatch%parprof_pft_dif_z(cl,ipft,iv)) - upper_area = upper_area + cpatch%canopy_area_profile(cl,ipft,1) - end do - if(upper_area>nearzero)then - upper_par = upper_par/upper_area - else + + ! Check that there are cohorts on the current patch as this calculation is + ! not relevant in that case (and will result in an index error due to ncan being zero) + if (cpatch%countcohorts .gt. 0) then + + ! Radiation intensity exiting the layer above the bottom-most upper_par = 0._r8 + upper_area = 0._r8 + cl = max(1,cpatch%NCL_p-1) + do ipft = 1,numpft + iv = cpatch%ncan(cl,ipft) + upper_par = upper_par + cpatch%canopy_area_profile(cl,ipft,1)* & + (cpatch%parprof_pft_dir_z(cl,ipft,iv)+cpatch%parprof_pft_dif_z(cl,ipft,iv)) + upper_area = upper_area + cpatch%canopy_area_profile(cl,ipft,1) + end do + if(upper_area>nearzero)then + upper_par = upper_par/upper_area + else + upper_par = 0._r8 + end if + else + upper_par = fates_unset_r8 end if ! If we do have more than one layer, then we need to figure out ! the average of light on the exposed ground under the veg - + ! Note that newly spawned patches without cohorts have a default + ! NCL_p of one. if(cpatch%NCL_p>1) then cl = cpatch%NCL_p @@ -2115,6 +2122,8 @@ subroutine SeedlingParPatch(cpatch, & else + ! In the case where the patch is newly spawned and has no cohorts, + ! total_canopy_area should be zero seedling_par_high = atm_par par_high_frac = 1._r8-cpatch%total_canopy_area seedling_par_low = upper_par From 537301019b998e6130f347072143c00f2801dfde Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 6 Jul 2023 17:08:11 -0700 Subject: [PATCH 757/852] initial refactor of seedlingparpatch This refactor attempts to reduce repeated lines of code --- main/FatesInterfaceMod.F90 | 70 ++++++++++++-------------------------- 1 file changed, 22 insertions(+), 48 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 01a5c49f55..82d6e39f70 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -2069,68 +2069,42 @@ subroutine SeedlingParPatch(cpatch, & integer :: ipft ! current PFT index integer :: iv ! lower-most leaf layer index for the cl & pft combo + ! Assuming there is a single canopy layer + seedling_par_high = atm_par + par_high_frac = 1._r8-cpatch%total_canopy_area + par_low_frac = cpatch%total_canopy_area - ! Check that there are cohorts on the current patch as this calculation is - ! not relevant in that case (and will result in an index error due to ncan being zero) - if (cpatch%countcohorts .gt. 0) then - - ! Radiation intensity exiting the layer above the bottom-most + do cl = cpatch%NCL_p,max(1,cpatch%NCL_p-1),-1 upper_par = 0._r8 upper_area = 0._r8 - cl = max(1,cpatch%NCL_p-1) do ipft = 1,numpft iv = cpatch%ncan(cl,ipft) - upper_par = upper_par + cpatch%canopy_area_profile(cl,ipft,1)* & - (cpatch%parprof_pft_dir_z(cl,ipft,iv)+cpatch%parprof_pft_dif_z(cl,ipft,iv)) - upper_area = upper_area + cpatch%canopy_area_profile(cl,ipft,1) + ! Avoid calculating when there are no leaf layers for the given pft + if (iv .ne. 0) then + upper_par = upper_par + cpatch%canopy_area_profile(cl,ipft,1)* & + (cpatch%parprof_pft_dir_z(cl,ipft,iv)+cpatch%parprof_pft_dif_z(cl,ipft,iv)) + upper_area = upper_area + cpatch%canopy_area_profile(cl,ipft,1) + end if end do if(upper_area>nearzero)then upper_par = upper_par/upper_area else upper_par = 0._r8 end if - else - upper_par = fates_unset_r8 - end if - - ! If we do have more than one layer, then we need to figure out - ! the average of light on the exposed ground under the veg - ! Note that newly spawned patches without cohorts have a default - ! NCL_p of one. - if(cpatch%NCL_p>1) then - - cl = cpatch%NCL_p - lower_area = 0._r8 - lower_par = 0._r8 - do ipft = 1,numpft - iv = cpatch%ncan(cl,ipft) - lower_area = lower_area+cpatch%canopy_area_profile(cl,ipft,1) - lower_par = lower_par + & - cpatch%canopy_area_profile(cl,ipft,1)*& - (cpatch%parprof_pft_dir_z(cl,ipft,iv) + cpatch%parprof_pft_dif_z(cl,ipft,iv)) - end do - if(lower_area>nearzero)then - lower_par = lower_par / lower_area + + ! If we do have more than one layer, then we need to figure out + ! the average of light on the exposed ground under the veg + ! Note that newly spawned patches without cohorts have a default + ! NCL_p of one. + if(cl .lt. cpatch%NCL_p) then + seedling_par_high = seedling_par_low + par_high_frac = (1._r8-upper_area) + seedling_par_low = upper_par/upper_area + par_low_frac = upper_area else - lower_par = 0._r8 + seedling_par_low = upper_par end if - seedling_par_high = upper_par - par_high_frac = (1._r8-lower_area) - seedling_par_low = lower_par/lower_area - par_low_frac = lower_area - - else - - ! In the case where the patch is newly spawned and has no cohorts, - ! total_canopy_area should be zero - seedling_par_high = atm_par - par_high_frac = 1._r8-cpatch%total_canopy_area - seedling_par_low = upper_par - par_low_frac = cpatch%total_canopy_area - - end if - return end subroutine SeedlingParPatch From 06b92a97eba85d0ca918c5593acb907e0df7b0a5 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 6 Jul 2023 23:19:19 -0600 Subject: [PATCH 758/852] add missing end do --- main/FatesInterfaceMod.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 82d6e39f70..1fca2e0269 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -2104,6 +2104,7 @@ subroutine SeedlingParPatch(cpatch, & else seedling_par_low = upper_par end if + end do return end subroutine SeedlingParPatch From 53cd4a13e1d11a313174eb34682f450146dd5073 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 6 Jul 2023 23:32:13 -0700 Subject: [PATCH 759/852] update SeedlingParPatch to avoid zero ncan per pft --- main/FatesInterfaceMod.F90 | 40 ++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 01a5c49f55..5d7e96a6a8 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -2069,28 +2069,23 @@ subroutine SeedlingParPatch(cpatch, & integer :: ipft ! current PFT index integer :: iv ! lower-most leaf layer index for the cl & pft combo - - ! Check that there are cohorts on the current patch as this calculation is - ! not relevant in that case (and will result in an index error due to ncan being zero) - if (cpatch%countcohorts .gt. 0) then - - ! Radiation intensity exiting the layer above the bottom-most - upper_par = 0._r8 - upper_area = 0._r8 - cl = max(1,cpatch%NCL_p-1) - do ipft = 1,numpft - iv = cpatch%ncan(cl,ipft) + ! Radiation intensity exiting the layer above the bottom-most + upper_par = 0._r8 + upper_area = 0._r8 + cl = max(1,cpatch%NCL_p-1) + do ipft = 1,numpft + iv = cpatch%ncan(cl,ipft) + ! Avoid cases where ncan is zero for a given pft + if (iv .ne. 0) then upper_par = upper_par + cpatch%canopy_area_profile(cl,ipft,1)* & (cpatch%parprof_pft_dir_z(cl,ipft,iv)+cpatch%parprof_pft_dif_z(cl,ipft,iv)) upper_area = upper_area + cpatch%canopy_area_profile(cl,ipft,1) - end do - if(upper_area>nearzero)then - upper_par = upper_par/upper_area - else - upper_par = 0._r8 end if + end do + if(upper_area>nearzero)then + upper_par = upper_par/upper_area else - upper_par = fates_unset_r8 + upper_par = 0._r8 end if ! If we do have more than one layer, then we need to figure out @@ -2104,10 +2099,13 @@ subroutine SeedlingParPatch(cpatch, & lower_par = 0._r8 do ipft = 1,numpft iv = cpatch%ncan(cl,ipft) - lower_area = lower_area+cpatch%canopy_area_profile(cl,ipft,1) - lower_par = lower_par + & - cpatch%canopy_area_profile(cl,ipft,1)*& - (cpatch%parprof_pft_dir_z(cl,ipft,iv) + cpatch%parprof_pft_dif_z(cl,ipft,iv)) + ! Avoid cases where ncan is zero for a given pft + if (iv .ne. 0) then + lower_area = lower_area+cpatch%canopy_area_profile(cl,ipft,1) + lower_par = lower_par + & + cpatch%canopy_area_profile(cl,ipft,1)*& + (cpatch%parprof_pft_dir_z(cl,ipft,iv) + cpatch%parprof_pft_dif_z(cl,ipft,iv)) + end if end do if(lower_area>nearzero)then lower_par = lower_par / lower_area From 7eb363d79b8c79dcb0ea0c3d5631f10e9fc8fcf5 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 7 Jul 2023 00:37:24 -0600 Subject: [PATCH 760/852] update names and remove old code --- main/FatesInterfaceMod.F90 | 42 +++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 1fca2e0269..3dd713f5fb 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -2061,49 +2061,53 @@ subroutine SeedlingParPatch(cpatch, & real(r8), intent(out) :: par_low_frac ! Area fraction with low intensity ! Locals - real(r8) :: upper_par ! The PAR intensity coming from the canopy layer above [w/m2] - real(r8) :: upper_area ! The area fraction of the upper canopy - real(r8) :: lower_par ! The PAR intensity under the lower-most canopy [W/m2] - real(r8) :: lower_area ! The area fractino of the lower canopy + real(r8) :: cl_par ! The PAR intensity coming from the canopy layer [w/m2] + real(r8) :: cl_area ! The area fraction of the given canopy layer integer :: cl ! current canopy layer integer :: ipft ! current PFT index integer :: iv ! lower-most leaf layer index for the cl & pft combo - ! Assuming there is a single canopy layer + ! Start with the assumption that there is a single canopy layer seedling_par_high = atm_par par_high_frac = 1._r8-cpatch%total_canopy_area par_low_frac = cpatch%total_canopy_area + ! Work up through the canopy layers from the bottom layer do cl = cpatch%NCL_p,max(1,cpatch%NCL_p-1),-1 - upper_par = 0._r8 - upper_area = 0._r8 + cl_par = 0._r8 + cl_area = 0._r8 do ipft = 1,numpft iv = cpatch%ncan(cl,ipft) - ! Avoid calculating when there are no leaf layers for the given pft + ! Avoid calculating when there are no leaf layers for the given pft in the current canopy layer if (iv .ne. 0) then - upper_par = upper_par + cpatch%canopy_area_profile(cl,ipft,1)* & + cl_par = cl_par + cpatch%canopy_area_profile(cl,ipft,1)* & (cpatch%parprof_pft_dir_z(cl,ipft,iv)+cpatch%parprof_pft_dif_z(cl,ipft,iv)) - upper_area = upper_area + cpatch%canopy_area_profile(cl,ipft,1) + cl_area = cl_area + cpatch%canopy_area_profile(cl,ipft,1) end if end do - if(upper_area>nearzero)then - upper_par = upper_par/upper_area + + ! Set the cl_par to zero if the area is near zero. Otherwise scale the par by the area + if(cl_area>nearzero)then + cl_par = cl_par/cl_area else - upper_par = 0._r8 + cl_par = 0._r8 end if ! If we do have more than one layer, then we need to figure out ! the average of light on the exposed ground under the veg - ! Note that newly spawned patches without cohorts have a default - ! NCL_p of one. + ! Since we are working up through the canopy layers from the ground, + ! set the par_high to the previous par_low value and update + ! the par_low to the new cl_par value if(cl .lt. cpatch%NCL_p) then seedling_par_high = seedling_par_low - par_high_frac = (1._r8-upper_area) - seedling_par_low = upper_par/upper_area - par_low_frac = upper_area + par_high_frac = (1._r8-cl_area) + seedling_par_low = cl_par + par_low_frac = cl_area + ! If we only have one layer, only set the seedling_par_low else - seedling_par_low = upper_par + seedling_par_low = cl_par end if + end do return From 7c8a53cf6b65c2bef7c96f729a82575152425b8d Mon Sep 17 00:00:00 2001 From: Marcos Longo <5891904+mpaiao@users.noreply.github.com> Date: Fri, 7 Jul 2023 08:57:27 -0700 Subject: [PATCH 761/852] Fix EDInitMod.F90 initialisation of drought deciduous variables Two local variables were not initialised before the first time being used (thanks @adrifoster for spotting it!). This PR fixes it. --- main/EDInitMod.F90 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index de0a5be0e5..c5fd5afea1 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -847,6 +847,10 @@ subroutine init_cohorts( site_in, patch_in, bc_in) temp_cohort%canopy_trim = 1.0_r8 temp_cohort%crowndamage = 1 ! Assume no damage to begin with + ! Retrieve drop fraction of non-leaf tissues for phenology initialisation + fnrt_drop_fraction = prt_params%phen_fnrt_drop_fraction(pft) + stem_drop_fraction = prt_params%phen_stem_drop_fraction(pft) + ! Initialise phenology variables. spmode_case: select case (hlm_use_sp) From f7776b2d2e4b7d72352b54a71ace19f9bc6f4fcd Mon Sep 17 00:00:00 2001 From: Marcos Longo <5891904+mpaiao@users.noreply.github.com> Date: Fri, 7 Jul 2023 09:16:33 -0700 Subject: [PATCH 762/852] Remove duplicated init of the drought deciduous local variables I forgot to delete the assignment of the local variables when I moved it to the beginning of the `do` loop (thanks @glemieux). --- main/EDInitMod.F90 | 5 ----- 1 file changed, 5 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index c5fd5afea1..50d2bcf56c 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -917,11 +917,6 @@ subroutine init_cohorts( site_in, patch_in, bc_in) temp_cohort%n = temp_cohort%n * sum(site_in%use_this_pft) endif - ! Retrieve drop fraction of non-leaf tissues for phenology initialisation - fnrt_drop_fraction = prt_params%phen_fnrt_drop_fraction(temp_cohort%pft) - stem_drop_fraction = prt_params%phen_stem_drop_fraction(temp_cohort%pft) - - ! h,dbh,leafc,n from SP values or from small initial size. if(hlm_use_sp.eq.itrue)then From 64c50364569a762d4a9ec893344887d4556b0519 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Thu, 13 Jul 2023 09:12:22 -0600 Subject: [PATCH 763/852] merge conflicts fix --- biogeochem/EDCohortDynamicsMod.F90 | 12 +++++++----- biogeochem/EDPhysiologyMod.F90 | 12 ++++++------ main/EDInitMod.F90 | 6 +++--- main/EDTypesMod.F90 | 20 +------------------- main/FatesConstantsMod.F90 | 19 +++++++++++++++++++ main/FatesInventoryInitMod.F90 | 4 ++-- parteh/PRTAllometricCNPMod.F90 | 10 +++++----- parteh/PRTAllometricCarbonMod.F90 | 6 +++--- parteh/PRTParamsFATESMod.F90 | 2 +- 9 files changed, 47 insertions(+), 44 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 2285c9b731..cb4cdb0a1b 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -48,9 +48,9 @@ Module EDCohortDynamicsMod use PRTGenericMod , only : num_elements use FatesConstantsMod , only : leaves_on use FatesConstantsMod , only : leaves_off - use EDTypesMod , only : leaves_shedding - use EDTypesMod , only : ihard_stress_decid - use EDTypesMod , only : isemi_stress_decid + use FatesConstantsMod , only : leaves_shedding + use FatesConstantsMod , only : ihard_stress_decid + use FatesConstantsMod , only : isemi_stress_decid use EDParamsMod , only : ED_val_cohort_age_fusion_tol use FatesInterfaceTypesMod , only : hlm_use_planthydro use FatesInterfaceTypesMod , only : hlm_parteh_mode @@ -206,8 +206,10 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & ! create new cohort allocate(newCohort) -call newCohort%Create(prt, pft, nn, hite, coage, dbh, status, ctrim, carea, & - clayer, crowndamage, spread, patchptr%canopy_layer_tlai) +call newCohort%Create(prt, pft, nn, hite, coage, dbh, status, ctrim, carea, & + clayer, crowndamage, spread, patchptr%canopy_layer_tlai, elongf_leaf, elongf_fnrt, & + elongf_stem) + ! Put cohort at the right place in the linked list storebigcohort => patchptr%tallest diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 942e9fdd5c..f031c3739e 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -56,9 +56,9 @@ module EDPhysiologyMod use FatesLitterMod , only : adjust_SF_CWD_frac use EDParamsMod , only : nclmax use EDTypesMod , only : AREA,AREA_INV - use EDTypesMod , only : leaves_shedding - use EDTypesMod , only : ihard_stress_decid - use EDTypesMod , only : isemi_stress_decid + use FatesConstantsMod , only : leaves_shedding + use FatesConstantsMod , only : ihard_stress_decid + use FatesConstantsMod , only : isemi_stress_decid use EDParamsMod , only : nlevleaf use EDTypesMod , only : num_vegtemp_mem use FatesConstantsMod , only : maxpft @@ -2318,8 +2318,8 @@ subroutine recruitment(currentSite, currentPatch, bc_in) (ft .eq. currentPatch%nocomp_pft_label))) then hite = EDPftvarcon_inst%hgt_min(ft) - stem_drop_fraction = EDPftvarcon_inst%phen_stem_drop_fraction(ft) - fnrt_drop_fraction = EDPftvarcon_inst%phen_fnrt_drop_fraction(ft) + stem_drop_fraction = prt_params%phen_stem_drop_fraction(ft) + fnrt_drop_fraction = prt_params%phen_fnrt_drop_fraction(ft) l2fr = currentSite%rec_l2fr(ft, currentPatch%NCL_p) crowndamage = 1 ! new recruits are undamaged @@ -2373,7 +2373,7 @@ subroutine recruitment(currentSite, currentPatch, bc_in) call bsap_allom(dbh, ft, crowndamage, init_recruit_trim, & efstem_coh, a_sapw, c_sapw) call bagw_allom(dbh, ft, crowndamage, efstem_coh, c_agw) - call bbgw_allom(dbh, ft, c_bgw) + call bbgw_allom(dbh, ft, efstem_coh, c_bgw) call bdead_allom(c_agw, c_bgw, c_sapw, ft, c_struct) call bstore_allom(dbh, ft, crowndamage, init_recruit_trim, c_store) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index f3d7b4673e..1b57ccfaeb 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -34,8 +34,8 @@ module EDInitMod use EDTypesMod , only : init_spread_inventory use FatesConstantsMod , only : leaves_on use FatesConstantsMod , only : leaves_off - use EDTypesMod , only : ihard_stress_decid - use EDTypesMod , only : isemi_stress_decid + use FatesConstantsMod , only : ihard_stress_decid + use FatesConstantsMod , only : isemi_stress_decid use PRTGenericMod , only : num_elements use PRTGenericMod , only : element_list use EDTypesMod , only : phen_cstat_nevercold @@ -925,7 +925,7 @@ subroutine init_cohorts(site_in, patch_in, bc_in) ! Calculate the leaf biomass from allometry ! (calculates a maximum first, then applies canopy trim) - call bleaf(dbh, pft, crown_damage, canopy_trim, c_leaf) + call bleaf(dbh, pft, crown_damage, canopy_trim, efleaf_coh, c_leaf) endif ! sp mode else ! interpret as initial diameter and calculate density diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index c3063341c1..7e4991e04b 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -82,25 +82,7 @@ module EDTypesMod integer, parameter, public :: numlevsoil_max = 30 ! This is scratch space used for static arrays ! The actual number of soil layers should not exceed this - integer, parameter, public :: leaves_shedding = 3 ! Flag specifying that a deciduous plant has leaves - ! but is shedding them (partial shedding). This plant - ! should not allocate carbon towards growth or - ! reproduction. - integer, parameter, public :: ihard_stress_decid = 1 ! If the PFT is stress (drought) deciduous, - ! this flag is used to tell that the PFT - ! is a "hard" deciduous (i.e., the plant - ! has only two statuses, the plant either - ! sheds all leaves when it's time, or seeks - ! to flush the leaves back to allometry - ! when conditions improve. -integer, parameter, public :: isemi_stress_decid = 2 ! If the PFT is stress (drought) deciduous, - ! this flag is used to tell that the PFT - ! is a semi-deciduous (i.e., the plant - ! can downregulate the amount of leaves - ! relative to the allometry based on - ! soil moisture conditions. It can still - ! shed all leaves if conditions are very - ! dry. + ! BIOLOGY/BIOGEOCHEMISTRY diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index 9608df48f8..deff05a1bb 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -53,6 +53,25 @@ module FatesConstantsMod integer, parameter, public :: leaves_off = 1 ! Flag specifying that a deciduous plant has dropped ! its leaves and should not be trying to allocate ! towards any growth. + integer, parameter, public :: leaves_shedding = 3 ! Flag specifying that a deciduous plant has leaves + ! but is shedding them (partial shedding). This plant + ! should not allocate carbon towards growth or + ! reproduction. +integer, parameter, public :: ihard_stress_decid = 1 ! If the PFT is stress (drought) deciduous, + ! this flag is used to tell that the PFT + ! is a "hard" deciduous (i.e., the plant + ! has only two statuses, the plant either + ! sheds all leaves when it's time, or seeks + ! to flush the leaves back to allometry + ! when conditions improve. +integer, parameter, public :: isemi_stress_decid = 2 ! If the PFT is stress (drought) deciduous, + ! this flag is used to tell that the PFT + ! is a semi-deciduous (i.e., the plant + ! can downregulate the amount of leaves + ! relative to the allometry based on + ! soil moisture conditions. It can still + ! shed all leaves if conditions are very + ! dry. integer, parameter, public :: ican_upper = 1 ! nominal index for the upper canopy integer, parameter, public :: ican_ustory = 2 ! nominal index for diagnostics that refer to understory layers diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index 8c51aafdd0..21346873f0 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -41,8 +41,8 @@ module FatesInventoryInitMod use EDTypesMod , only : area use FatesConstantsMod, only : leaves_on use FatesConstantsMod, only : leaves_off - use EDTypesMod , only : ihard_stress_decid - use EDTypesMod , only : isemi_stress_decid + use FatesConstantsMod, only : ihard_stress_decid + use FatesConstantsMod, only : isemi_stress_decid use PRTGenericMod , only : num_elements use PRTGenericMod , only : element_list use EDTypesMod , only : phen_cstat_nevercold diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 1e3b25b3bf..108de586e8 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -57,11 +57,11 @@ module PRTAllometricCNPMod use FatesConstantsMod , only : sec_per_day use PRTParametersMod , only : prt_params use FatesConstantsMod , only : leaves_on,leaves_off - use EDTypesMod , only : leaves_shedding - use EDTypesMod , only : p_uptake_mode - use EDTypesMod , only : n_uptake_mode - use FatesConstantsMod , only : prescribed_p_uptake - use FatesConstantsMod , only : prescribed_n_uptake + use FatesConstantsMod , only : leaves_shedding + use EDParamsMod , only : p_uptake_mode + use EDParamsMod , only : n_uptake_mode + use FatesConstantsMod , only : prescribed_p_uptake + use FatesConstantsMod , only : prescribed_n_uptake use EDPftvarcon, only : EDPftvarcon_inst implicit none diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 0ca8546bcc..d211520a0f 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -51,9 +51,9 @@ module PRTAllometricCarbonMod use FatesConstantsMod , only : leaves_on use FatesConstantsMod , only : leaves_off - use EDTypesMod , only : leaves_shedding - use EDTypesMod , only : ihard_stress_decid - use EDTypesMod , only : isemi_stress_decid + use FatesConstantsMod , only : leaves_shedding + use FatesConstantsMod , only : ihard_stress_decid + use FatesConstantsMod , only : isemi_stress_decid implicit none private diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index 4a9423c151..d30ac1681c 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -32,7 +32,7 @@ module PRTInitParamsFatesMod use FatesAllometryMod, only : set_root_fraction use PRTGenericMod, only : StorageNutrientTarget use EDTypesMod, only : init_recruit_trim - use EDTypesMod, only : ihard_stress_decid, isemi_stress_decid + use FatesConstantsMod, only : ihard_stress_decid, isemi_stress_decid ! ! !PUBLIC TYPES: From 36e6c5021fa1dc3607a526674e24fe6f62fbe40b Mon Sep 17 00:00:00 2001 From: adrifoster Date: Thu, 13 Jul 2023 11:17:45 -0600 Subject: [PATCH 764/852] adding some consistency checks --- biogeochem/EDCanopyStructureMod.F90 | 8 ++++---- biogeochem/EDPhysiologyMod.F90 | 28 +++++++++++++++------------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 31d36c5e60..1b13fc6e78 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -8,7 +8,7 @@ module EDCanopyStructureMod use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : itrue, ifalse use FatesConstantsMod , only : tinyr8 - use FatesConstantsMod , only : nearzero + use FatesConstantsMod , only : nearzero, calloc_abs_error use FatesConstantsMod , only : rsnbl_math_prec use FatesConstantsMod , only : nocomp_bareground use FatesGlobals , only : fates_log @@ -1389,9 +1389,9 @@ subroutine canopy_summarization( nsites, sites, bc_in ) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if(currentPatch%total_canopy_area-currentPatch%area.gt.1.0e-16)then - write(fates_log(),*) 'too much canopy in summary',s, & - currentPatch%nocomp_pft_label, currentPatch%total_canopy_area-currentPatch%area + if (currentPatch%total_canopy_area - currentPatch%area > calloc_abs_error) then + write(fates_log(),*) 'too much canopy in summary', s, & + currentPatch%nocomp_pft_label, currentPatch%total_canopy_area - currentPatch%area call endrun(msg=errMsg(sourcefile, __LINE__)) end if end if !sp mode diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 9040343100..860a3c4b43 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -26,6 +26,7 @@ module EDPhysiologyMod use FatesConstantsMod, only : g_per_kg use FatesConstantsMod, only : ndays_per_year use FatesConstantsMod, only : nocomp_bareground + use FatesConstantsMod, only : calloc_abs_error use EDPftvarcon , only : EDPftvarcon_inst use PRTParametersMod , only : prt_params use EDPftvarcon , only : GetDecompyFrac @@ -1962,19 +1963,20 @@ subroutine assign_cohort_SP_properties(currentCohort,htop,tlai,tsai,parea,init,l ! the radiation routines. Correct both the area and the 'n' to remove error, and don't use !! carea_allom in SP mode after this point. - if(abs(currentCohort%c_area-parea).gt.nearzero)then ! there is an error - if(abs(currentCohort%c_area-parea).lt.10.e-9)then !correct this if it's a very small error - oldcarea = currentCohort%c_area - !generate new cohort area - currentCohort%c_area = currentCohort%c_area - (currentCohort%c_area- parea) - currentCohort%n = currentCohort%n * (currentCohort%c_area/oldcarea) - if(abs(currentCohort%c_area-parea).gt.nearzero)then - write(fates_log(),*) 'SPassign, c_area still broken',currentCohort%c_area-parea,currentCohort%c_area-oldcarea - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - else - write(fates_log(),*) 'SPassign, big error in c_area',currentCohort%c_area-parea,currentCohort%pft - end if ! still broken + if (abs(currentCohort%c_area - parea) > nearzero) then ! there is an error + if (abs(currentCohort%c_area - parea) < calloc_abs_error) then !correct this if it's a very small error + oldcarea = currentCohort%c_area + ! generate new cohort area + currentCohort%c_area = currentCohort%c_area - (currentCohort%c_area - parea) + currentCohort%n = currentCohort%n*(currentCohort%c_area/oldcarea) + if (abs(currentCohort%c_area - parea) > nearzero) then + write(fates_log(),*) 'SPassign, c_area still broken', currentCohort%c_area - parea, currentCohort%c_area - oldcarea + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + else + write(fates_log(),*) 'SPassign, big error in c_area', currentCohort%c_area - parea, currentCohort%pft + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if ! still broken end if !small error if(init.eq.ifalse)then From 0da02a930785c61029a7cda8937afdd4584b3547 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Thu, 13 Jul 2023 11:18:23 -0600 Subject: [PATCH 765/852] don't fuse/sort cohorts if in SP --- main/EDInitMod.F90 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 5e5693cf21..a922745fd3 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -1083,8 +1083,10 @@ subroutine init_cohorts( site_in, patch_in, bc_in) !temp_cohort => temp_cohort%shorter !end do - call fuse_cohorts(site_in, patch_in,bc_in) - call sort_cohorts(patch_in) + if (hlm_use_sp == ifalse) then + call fuse_cohorts(site_in, patch_in,bc_in) + call sort_cohorts(patch_in) + end if end subroutine init_cohorts From 7d18eaaeb391a3dc15ddfef84dbf7532c211e608 Mon Sep 17 00:00:00 2001 From: jessica needham Date: Mon, 17 Jul 2023 11:14:45 -0700 Subject: [PATCH 766/852] Fix c3/c4 if else in Ryan 1991 LMR model. Tidy places in code where we distinguish c3 c4 plants. --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index f9c8b68f73..8991e0e60a 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -2101,7 +2101,8 @@ subroutine LeafLayerMaintenanceRespiration_Ryan_1991(lnc_top, & ! Locals real(r8) :: lmr25 ! leaf layer: leaf maintenance respiration rate at 25C (umol CO2/m**2/s) real(r8) :: lmr25top ! canopy top leaf maint resp rate at 25C for this pft (umol CO2/m**2/s) - + integer :: c3c4_path_index ! Index for which photosynthetic pathway + ! Parameter real(r8), parameter :: lmrha = 46390._r8 ! activation energy for lmr (J/mol) real(r8), parameter :: lmrhd = 150650._r8 ! deactivation energy for lmr (J/mol) @@ -2117,7 +2118,10 @@ subroutine LeafLayerMaintenanceRespiration_Ryan_1991(lnc_top, & ! ---------------------------------------------------------------------------------- lmr25 = lmr25top * nscaler - if (nint(EDPftvarcon_inst%c3psn(ft)) /= 1) then + ! photosynthetic pathway: 0. = c4, 1. = c3 + c3c4_path_index = nint(EDPftvarcon_inst%c3psn(ft)) + + if (c3c4_path_index == c3_path_index) then ! temperature sensitivity of C3 plants lmr = lmr25 * ft1_f(veg_tempk, lmrha) * & fth_f(veg_tempk, lmrhd, lmrse, lmrc) @@ -2249,7 +2253,7 @@ subroutine LeafLayerBiophysicalRates( parsun_lsl, & ! (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 ! Parameters ! --------------------------------------------------------------------------------- @@ -2312,14 +2316,18 @@ subroutine LeafLayerBiophysicalRates( parsun_lsl, & co2_rcurve_islope25 = co2_rcurve_islope25top_ft * nscaler ! Adjust for temperature - vcmax = vcmax25 * ft1_f(veg_tempk, vcmaxha) * fth_f(veg_tempk, vcmaxhd, vcmaxse, vcmaxc) - jmax = jmax25 * ft1_f(veg_tempk, jmaxha) * fth_f(veg_tempk, jmaxhd, jmaxse, jmaxc) + ! photosynthetic pathway: 0. = c4, 1. = c3 + c3c4_path_index = nint(EDPftvarcon_inst%c3psn(ft)) - if (nint(EDPftvarcon_inst%c3psn(ft)) /= 1) then + if (c3c4_path_index == c3_path_index) then + vcmax = vcmax25 * ft1_f(veg_tempk, vcmaxha) * fth_f(veg_tempk, vcmaxhd, vcmaxse, vcmaxc) + jmax = jmax25 * ft1_f(veg_tempk, jmaxha) * fth_f(veg_tempk, jmaxhd, jmaxse, jmaxc) + else vcmax = vcmax25 * 2._r8**((veg_tempk-(tfrz+25._r8))/10._r8) vcmax = vcmax / (1._r8 + exp( 0.2_r8*((tfrz+15._r8)-veg_tempk ) )) vcmax = vcmax / (1._r8 + exp( 0.3_r8*(veg_tempk-(tfrz+40._r8)) )) end if + !q10 response of product limited psn. co2_rcurve_islope = co2_rcurve_islope25 * 2._r8**((veg_tempk-(tfrz+25._r8))/10._r8) end if From 66e5b2ee99c19c340cbdd5f52b10509c5cef620e Mon Sep 17 00:00:00 2001 From: jessica needham Date: Mon, 17 Jul 2023 11:53:51 -0700 Subject: [PATCH 767/852] Moving jmax out of c3/c4 if else --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 8991e0e60a..bae50e8221 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -2321,13 +2321,14 @@ subroutine LeafLayerBiophysicalRates( parsun_lsl, & if (c3c4_path_index == c3_path_index) then vcmax = vcmax25 * ft1_f(veg_tempk, vcmaxha) * fth_f(veg_tempk, vcmaxhd, vcmaxse, vcmaxc) - jmax = jmax25 * ft1_f(veg_tempk, jmaxha) * fth_f(veg_tempk, jmaxhd, jmaxse, jmaxc) else vcmax = vcmax25 * 2._r8**((veg_tempk-(tfrz+25._r8))/10._r8) vcmax = vcmax / (1._r8 + exp( 0.2_r8*((tfrz+15._r8)-veg_tempk ) )) vcmax = vcmax / (1._r8 + exp( 0.3_r8*(veg_tempk-(tfrz+40._r8)) )) end if + jmax = jmax25 * ft1_f(veg_tempk, jmaxha) * fth_f(veg_tempk, jmaxhd, jmaxse, jmaxc) + !q10 response of product limited psn. co2_rcurve_islope = co2_rcurve_islope25 * 2._r8**((veg_tempk-(tfrz+25._r8))/10._r8) end if From c295e3eb55b10c5d46de93c1a35fffcb8d736097 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 18 Jul 2023 15:16:20 -0400 Subject: [PATCH 768/852] Added allocation restrictions on TRS running means, reduced memory usage, fixed restarts for TRS --- biogeochem/EDPatchDynamicsMod.F90 | 97 +++++++++++++------------ biogeochem/EDPhysiologyMod.F90 | 86 +++++++++++----------- main/FatesInterfaceMod.F90 | 100 +++++++++++++------------- main/FatesRestartInterfaceMod.F90 | 116 +++++++++++++++++------------- parteh/PRTAllometricCNPMod.F90 | 28 ++++++-- parteh/PRTAllometricCarbonMod.F90 | 44 +++++++----- 6 files changed, 261 insertions(+), 210 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index c4282f524c..81caad2b28 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -54,6 +54,7 @@ module EDPatchDynamicsMod use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : itrue, ifalse use FatesConstantsMod , only : t_water_freeze_k_1atm + use FatesConstantsMod , only : TRS_regeneration use FatesPlantHydraulicsMod, only : InitHydrCohort use FatesPlantHydraulicsMod, only : AccumulateMortalityWaterStorage use FatesPlantHydraulicsMod, only : DeallocateHydrCohort @@ -64,6 +65,7 @@ module EDPatchDynamicsMod use EDLoggingMortalityMod, only : get_harvestable_carbon use EDLoggingMortalityMod, only : get_harvest_debt use EDParamsMod , only : fates_mortality_disturbance_fraction + use EDParamsMod , only : regeneration_model use FatesAllometryMod , only : carea_allom use FatesAllometryMod , only : set_root_fraction use FatesConstantsMod , only : g_per_kg @@ -661,17 +663,19 @@ subroutine spawn_patches( currentSite, bc_in) ! -------------------------------------------------------------------------- call new_patch%tveg24%CopyFromDonor(currentPatch%tveg24) call new_patch%tveg_lpa%CopyFromDonor(currentPatch%tveg_lpa) - call new_patch%seedling_layer_par24%CopyFromDonor(currentPatch%seedling_layer_par24) - call new_patch%sdlng_mort_par%CopyFromDonor(currentPatch%sdlng_mort_par) - call new_patch%sdlng2sap_par%CopyFromDonor(currentPatch%sdlng2sap_par) - do pft = 1,maxpft - call new_patch%sdlng_emerg_smp(pft)%p%CopyFromDonor(currentPatch%sdlng_emerg_smp(pft)%p) - call new_patch%sdlng_mdd(pft)%p%CopyFromDonor(currentPatch%sdlng_mdd(pft)%p) - enddo + if ( regeneration_model == TRS_regeneration ) then + call new_patch%seedling_layer_par24%CopyFromDonor(currentPatch%seedling_layer_par24) + call new_patch%sdlng_mort_par%CopyFromDonor(currentPatch%sdlng_mort_par) + call new_patch%sdlng2sap_par%CopyFromDonor(currentPatch%sdlng2sap_par) + do pft = 1,numpft + call new_patch%sdlng_emerg_smp(pft)%p%CopyFromDonor(currentPatch%sdlng_emerg_smp(pft)%p) + call new_patch%sdlng_mdd(pft)%p%CopyFromDonor(currentPatch%sdlng_mdd(pft)%p) + enddo + end if call new_patch%tveg_longterm%CopyFromDonor(currentPatch%tveg_longterm) - + ! -------------------------------------------------------------------------- ! The newly formed patch from disturbance (new_patch), has now been given ! some litter from dead plants and pre-existing litter from the donor patches. @@ -2139,22 +2143,25 @@ subroutine create_patch(currentSite, new_patch, age, areap, label,nocomp_pft) call new_patch%tveg24%InitRMean(fixed_24hr,init_value=temp_init_veg,init_offset=real(hlm_current_tod,r8) ) allocate(new_patch%tveg_lpa) call new_patch%tveg_lpa%InitRmean(ema_lpa,init_value=temp_init_veg) - allocate(new_patch%seedling_layer_par24) - call new_patch%seedling_layer_par24%InitRMean(fixed_24hr,init_value=init_seedling_par, init_offset=real(hlm_current_tod,r8)) - allocate(new_patch%sdlng_mort_par) - call new_patch%sdlng_mort_par%InitRMean(ema_sdlng_mort_par,init_value=temp_init_veg) - allocate(new_patch%sdlng2sap_par) - call new_patch%sdlng2sap_par%InitRMean(ema_sdlng2sap_par,init_value=init_seedling_par) + - allocate(new_patch%sdlng_mdd(maxpft)) - allocate(new_patch%sdlng_emerg_smp(maxpft)) - - do pft = 1,maxpft - allocate(new_patch%sdlng_mdd(pft)%p) - call new_patch%sdlng_mdd(pft)%p%InitRMean(ema_sdlng_mdd, init_value=0.0_r8) - allocate(new_patch%sdlng_emerg_smp(pft)%p) - call new_patch%sdlng_emerg_smp(pft)%p%InitRMean(ema_sdlng_emerg_h2o,init_value=init_seedling_smp) - enddo + if ( regeneration_model == TRS_regeneration ) then + allocate(new_patch%seedling_layer_par24) + call new_patch%seedling_layer_par24%InitRMean(fixed_24hr,init_value=init_seedling_par, init_offset=real(hlm_current_tod,r8)) + allocate(new_patch%sdlng_mort_par) + call new_patch%sdlng_mort_par%InitRMean(ema_sdlng_mort_par,init_value=temp_init_veg) + allocate(new_patch%sdlng2sap_par) + call new_patch%sdlng2sap_par%InitRMean(ema_sdlng2sap_par,init_value=init_seedling_par) + allocate(new_patch%sdlng_mdd(numpft)) + allocate(new_patch%sdlng_emerg_smp(numpft)) + do pft = 1,numpft + allocate(new_patch%sdlng_mdd(pft)%p) + call new_patch%sdlng_mdd(pft)%p%InitRMean(ema_sdlng_mdd, init_value=0.0_r8) + allocate(new_patch%sdlng_emerg_smp(pft)%p) + call new_patch%sdlng_emerg_smp(pft)%p%InitRMean(ema_sdlng_emerg_h2o,init_value=init_seedling_smp) + enddo + end if + allocate(new_patch%tveg_longterm) call new_patch%tveg_longterm%InitRmean(ema_longterm,init_value=temp_init_veg) @@ -2730,16 +2737,18 @@ subroutine fuse_2_patches(csite, dp, rp) ! Weighted mean of the running means call rp%tveg24%FuseRMean(dp%tveg24,rp%area*inv_sum_area) call rp%tveg_lpa%FuseRMean(dp%tveg_lpa,rp%area*inv_sum_area) - call rp%seedling_layer_par24%FuseRMean(dp%seedling_layer_par24,rp%area*inv_sum_area) !ahb - call rp%tveg_longterm%FuseRMean(dp%tveg_longterm,rp%area*inv_sum_area) - - do pft = 1,maxpft - call rp%sdlng_emerg_smp(pft)%p%FuseRMean(dp%sdlng_emerg_smp(pft)%p,rp%area*inv_sum_area) !ahb - call rp%sdlng_mdd(pft)%p%FuseRMean(dp%sdlng_mdd(pft)%p,rp%area*inv_sum_area) !ahb - enddo - call rp%sdlng_mort_par%FuseRMean(dp%sdlng_mort_par,rp%area*inv_sum_area) !ahb - call rp%sdlng2sap_par%FuseRMean(dp%sdlng2sap_par,rp%area*inv_sum_area) !ahb + if ( regeneration_model == TRS_regeneration ) then + call rp%seedling_layer_par24%FuseRMean(dp%seedling_layer_par24,rp%area*inv_sum_area) + call rp%sdlng_mort_par%FuseRMean(dp%sdlng_mort_par,rp%area*inv_sum_area) + call rp%sdlng2sap_par%FuseRMean(dp%sdlng2sap_par,rp%area*inv_sum_area) + do pft = 1,numpft + call rp%sdlng_emerg_smp(pft)%p%FuseRMean(dp%sdlng_emerg_smp(pft)%p,rp%area*inv_sum_area) + call rp%sdlng_mdd(pft)%p%FuseRMean(dp%sdlng_mdd(pft)%p,rp%area*inv_sum_area) + enddo + end if + + call rp%tveg_longterm%FuseRMean(dp%tveg_longterm,rp%area*inv_sum_area) rp%fuel_eff_moist = (dp%fuel_eff_moist*dp%area + rp%fuel_eff_moist*rp%area) * inv_sum_area rp%livegrass = (dp%livegrass*dp%area + rp%livegrass*rp%area) * inv_sum_area @@ -3122,19 +3131,17 @@ subroutine dealloc_patch(cpatch) endif ! Deallocate any running means - deallocate(cpatch%seedling_layer_par24) - deallocate(cpatch%sdlng_mort_par) - deallocate(cpatch%sdlng2sap_par) - - do pft = 1, maxpft - deallocate(cpatch%sdlng_mdd(pft)%p) - deallocate(cpatch%sdlng_emerg_smp(pft)%p) - enddo - - - deallocate(cpatch%sdlng_mdd) - deallocate(cpatch%sdlng_emerg_smp) - + if ( regeneration_model == TRS_regeneration ) then + deallocate(cpatch%seedling_layer_par24) + deallocate(cpatch%sdlng_mort_par) + deallocate(cpatch%sdlng2sap_par) + do pft = 1, numpft + deallocate(cpatch%sdlng_mdd(pft)%p) + deallocate(cpatch%sdlng_emerg_smp(pft)%p) + enddo + deallocate(cpatch%sdlng_mdd) + deallocate(cpatch%sdlng_emerg_smp) + end if deallocate(cpatch%tveg24, stat=istat, errmsg=smsg) if (istat/=0) then diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 3f70ff2f1d..cff1632775 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2312,61 +2312,61 @@ subroutine SeedGermination( litt, cold_stat, drought_stat, bc_in, currentPatch ) ! that times the ratio of (hypothetical) seed mass to recruit biomass !============================================================================================== - do pft = 1,numpft - + do pft = 1,numpft + ! If the TRS's seedling dynamics is switched off, then we use FATES's default approach ! to germination - if ( regeneration_model == default_regeneration .or. & + if_tfs_or_def: if ( regeneration_model == default_regeneration .or. & regeneration_model == TRS_no_seedling_dyn .or. & prt_params%allom_dbh_maxheight(pft) < min_max_dbh_for_trees ) then - litt%seed_germ_in(pft) = min(litt%seed(pft) * EDPftvarcon_inst%germination_rate(pft), & - max_germination)*years_per_day - - ! If TRS seedling dynamics is switched on we calculate seedling emergence (i.e. germination) - ! as a pft-specific function of understory light and soil moisture. + litt%seed_germ_in(pft) = min(litt%seed(pft) * EDPftvarcon_inst%germination_rate(pft), & + max_germination)*years_per_day + + ! If TRS seedling dynamics is switched on we calculate seedling emergence (i.e. germination) + ! as a pft-specific function of understory light and soil moisture. else if ( regeneration_model == TRS_regeneration .and. & - prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees ) then - - ! Step 1. Calculate how germination rate is modified by understory light - ! This applies to photoblastic germinators (e.g. many tropical pioneers) + prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees ) then - ! Calculate mean PAR at the seedling layer (MJ m-2 day-1) over the prior 24 hours - seedling_layer_par = currentPatch%seedling_layer_par24%GetMean() * sec_per_day * megajoules_per_joule + ! Step 1. Calculate how germination rate is modified by understory light + ! This applies to photoblastic germinators (e.g. many tropical pioneers) - ! Calculate the photoblastic germination rate modifier (Eq. 3 Hanbury-Brown et al., 2022) - photoblastic_germ_modifier = seedling_layer_par / & - (seedling_layer_par + EDPftvarcon_inst%par_crit_germ(pft)) + ! Calculate mean PAR at the seedling layer (MJ m-2 day-1) over the prior 24 hours + seedling_layer_par = currentPatch%seedling_layer_par24%GetMean() * sec_per_day * megajoules_per_joule - ! Step 2. Calculate how germination rate is modified by soil moisture in the rooting zone of - ! the seedlings. This is a pft-specific running mean based on pft-specific seedling rooting - ! depth. + ! Calculate the photoblastic germination rate modifier (Eq. 3 Hanbury-Brown et al., 2022) + photoblastic_germ_modifier = seedling_layer_par / & + (seedling_layer_par + EDPftvarcon_inst%par_crit_germ(pft)) - ! Get running mean of soil matric potential (mm of H2O suction) at the seedling rooting depth - ! This running mean based on pft-specific seedling rooting depth. - seedling_layer_smp = currentPatch%sdlng_emerg_smp(pft)%p%GetMean() + ! Step 2. Calculate how germination rate is modified by soil moisture in the rooting zone of + ! the seedlings. This is a pft-specific running mean based on pft-specific seedling rooting + ! depth. - ! Calculate a soil wetness index (1 / -soil matric pontential (MPa) ) used by the TRS - ! to calculate seedling mortality from moisture stress. - wetness_index = 1.0_r8 / (seedling_layer_smp * (-1.0_r8) * mpa_per_mm_suction) + ! Get running mean of soil matric potential (mm of H2O suction) at the seedling rooting depth + ! This running mean based on pft-specific seedling rooting depth. + seedling_layer_smp = currentPatch%sdlng_emerg_smp(pft)%p%GetMean() - ! Step 3. Calculate the seedling emergence rate based on soil moisture and germination - ! rate modifier (Step 1). See Eq. 4 of Hanbury-Brown et al., 2022 - - ! If SMP is below a pft-specific value, then no germination occurs - if ( seedling_layer_smp .GE. EDPftvarcon_inst%seedling_psi_emerg(pft) ) then - seedling_emerg_rate = photoblastic_germ_modifier * EDPftvarcon_inst%a_emerg(pft) * & - wetness_index**EDPftvarcon_inst%b_emerg(pft) - else - - seedling_emerg_rate = 0.0_r8 - - end if ! End soil-moisture based seedling emergence rate - - ! Step 4. Calculate the amount of carbon germinating out of the seed bank - litt%seed_germ_in(pft) = litt%seed(pft) * seedling_emerg_rate - - end if !End use TRS with seedling dynamics + ! Calculate a soil wetness index (1 / -soil matric pontential (MPa) ) used by the TRS + ! to calculate seedling mortality from moisture stress. + wetness_index = 1.0_r8 / (seedling_layer_smp * (-1.0_r8) * mpa_per_mm_suction) + + ! Step 3. Calculate the seedling emergence rate based on soil moisture and germination + ! rate modifier (Step 1). See Eq. 4 of Hanbury-Brown et al., 2022 + + ! If SMP is below a pft-specific value, then no germination occurs + if ( seedling_layer_smp .GE. EDPftvarcon_inst%seedling_psi_emerg(pft) ) then + seedling_emerg_rate = photoblastic_germ_modifier * EDPftvarcon_inst%a_emerg(pft) * & + wetness_index**EDPftvarcon_inst%b_emerg(pft) + else + + seedling_emerg_rate = 0.0_r8 + + end if ! End soil-moisture based seedling emergence rate + + ! Step 4. Calculate the amount of carbon germinating out of the seed bank + litt%seed_germ_in(pft) = litt%seed(pft) * seedling_emerg_rate + + end if if_tfs_or_def !set the germination only under the growing season...c.xu diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 3dd713f5fb..0544fba060 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1954,15 +1954,15 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) type(ed_patch_type), pointer :: cpatch type(ed_cohort_type), pointer :: ccohort integer :: s, ifp, io_si, pft - real(r8) :: new_seedling_layer_par ! seedling layer par in the current timestep - real(r8) :: new_seedling_layer_smp(maxpft) ! seedling layer smp in the current timestep - real(r8) :: new_seedling_mdd(maxpft) ! seedling layer moisture deficit days in the current timestep - integer :: ilayer_seedling_root(maxpft) ! the soil layer at seedling rooting depth - real(r8) :: seedling_par_high ! higher intensity par for seedlings (par at exposed ground) [W/m2] - real(r8) :: par_high_frac ! fraction of ground where PAR is high - real(r8) :: seedling_par_low ! lower intensity par for seedlings (par under the undergrowth) [W/m2] - real(r8) :: par_low_frac ! fraction of ground where PAR is low - integer,parameter :: ipar = 1 ! solar radiation in the shortwave band (i.e. par) + real(r8) :: new_seedling_layer_par ! seedling layer par in the current timestep + real(r8) :: new_seedling_layer_smp ! seedling layer smp in the current timestep + real(r8) :: new_seedling_mdd ! seedling layer moisture deficit days in the current timestep + integer :: ilayer_seedling_root ! the soil layer at seedling rooting depth + real(r8) :: seedling_par_high ! higher intensity par for seedlings (par at exposed ground) [W/m2] + real(r8) :: par_high_frac ! fraction of ground where PAR is high + real(r8) :: seedling_par_low ! lower intensity par for seedlings (par under the undergrowth) [W/m2] + real(r8) :: par_low_frac ! fraction of ground where PAR is low + integer,parameter :: ipar = 1 ! solar radiation in the shortwave band (i.e. par) do s = 1,size(sites,dim=1) @@ -1975,49 +1975,53 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) call cpatch%tveg_lpa%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) call cpatch%tveg_longterm%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) - ! Return the par intensity at the ground. This routine - ! breaks it up into high and low light levels. The high - ! levels are the light on the exposed ground at the surface - ! and the low levels are the intensity under the bottom-most - ! vegetation. - - call SeedlingParPatch(cpatch, & - bc_in(s)%solad_parb(ifp,ipar) + bc_in(s)%solai_parb(ifp,ipar), & - seedling_par_high, par_high_frac, seedling_par_low,& - & par_low_frac) - - new_seedling_layer_par = seedling_par_high*par_high_frac + seedling_par_low*par_low_frac + ! Update the seedling layer par running means - call cpatch%seedling_layer_par24%UpdateRMean(new_seedling_layer_par) - call cpatch%sdlng_mort_par%UpdateRMean(new_seedling_layer_par) - call cpatch%sdlng2sap_par%UpdateRMean(new_seedling_layer_par) + if ( regeneration_model == TRS_regeneration ) then - !write(fates_log(),*) 'new_seedling_layer_par', new_seedling_layer_par + ! Return the par intensity at the ground. This routine + ! breaks it up into high and low light levels. The high + ! levels are the light on the exposed ground at the surface + ! and the low levels are the intensity under the bottom-most + ! vegetation. + + call SeedlingParPatch(cpatch, & + bc_in(s)%solad_parb(ifp,ipar) + bc_in(s)%solai_parb(ifp,ipar), & + seedling_par_high, par_high_frac, seedling_par_low,& + & par_low_frac) + + new_seedling_layer_par = seedling_par_high*par_high_frac + seedling_par_low*par_low_frac + + call cpatch%seedling_layer_par24%UpdateRMean(new_seedling_layer_par) + call cpatch%sdlng_mort_par%UpdateRMean(new_seedling_layer_par) + call cpatch%sdlng2sap_par%UpdateRMean(new_seedling_layer_par) + + do pft = 1,numpft + + ! Calculate the soil moisture at the seedling rooting depth for each pft + + ilayer_seedling_root = minloc(abs(bc_in(s)%z_sisl(:)-EDPftvarcon_inst%seedling_root_depth(pft)),dim=1) + new_seedling_layer_smp = bc_in(s)%smp_sl(ilayer_seedling_root) + + ! Calculate the new moisture deficit day (mdd) value for each pft + new_seedling_mdd = (abs(EDPftvarcon_inst%seedling_psi_crit(pft)) - abs(new_seedling_layer_smp)) & + * (-1.0_r8) * sdlng_mdd_timescale + + ! If mdds are negative then it means that soil is wetter than smp_crit and the moisture + ! deficit is 0 + if (new_seedling_mdd < 0.0_r8) then + new_seedling_mdd = 0.0_r8 + endif + + ! Update the seedling layer smp and mdd running means + call cpatch%sdlng_emerg_smp(pft)%p%UpdateRMean(new_seedling_layer_smp) + call cpatch%sdlng_mdd(pft)%p%UpdateRMean(new_seedling_mdd) + + enddo !end pft loop + + end if - do pft = 1,numpft - - ! Calculate the soil moisture at the seedling rooting depth for each pft - - ilayer_seedling_root(pft) = minloc(abs(bc_in(s)%z_sisl(:)-EDPftvarcon_inst%seedling_root_depth(pft)),dim=1) - new_seedling_layer_smp(pft) = bc_in(s)%smp_sl(ilayer_seedling_root(pft)) - - ! Calculate the new moisture deficit day (mdd) value for each pft - new_seedling_mdd(pft) = (abs(EDPftvarcon_inst%seedling_psi_crit(pft)) - abs(new_seedling_layer_smp(pft))) & - * (-1.0_r8) * sdlng_mdd_timescale - - ! If mdds are negative then it means that soil is wetter than smp_crit and the moisture - ! deficit is 0 - if (new_seedling_mdd(pft) < 0.0_r8) then - new_seedling_mdd(pft) = 0.0_r8 - endif - - ! Update the seedling layer smp and mdd running means - call cpatch%sdlng_emerg_smp(pft)%p%UpdateRMean(new_seedling_layer_smp(pft)) - call cpatch%sdlng_mdd(pft)%p%UpdateRMean(new_seedling_mdd(pft)) - - enddo !end pft loop - !ccohort => cpatch%tallest !do while (associated(ccohort)) ! call ccohort%tveg_lpa%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 29395c56d5..ed77ae1d6f 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -1,15 +1,17 @@ module FatesRestartInterfaceMod - use FatesConstantsMod, only : r8 => fates_r8 - use FatesConstantsMod, only : fates_avg_flag_length - use FatesConstantsMod, only : fates_short_string_length - use FatesConstantsMod, only : fates_long_string_length - use FatesConstantsMod, only : itrue - use FatesConstantsMod, only : ifalse - use FatesConstantsMod, only : fates_unset_r8, fates_unset_int - use FatesConstantsMod, only : primaryforest - use FatesConstantsMod, only : nearzero + use FatesConstantsMod, only : r8 => fates_r8 + use FatesConstantsMod, only : fates_avg_flag_length + use FatesConstantsMod, only : fates_short_string_length + use FatesConstantsMod, only : fates_long_string_length + use FatesConstantsMod, only : itrue + use FatesConstantsMod, only : ifalse + use FatesConstantsMod, only : fates_unset_r8, fates_unset_int + use FatesConstantsMod, only : primaryforest + use FatesConstantsMod, only : nearzero + use FatesConstantsMod, only : default_regeneration + use FatesConstantsMod, only : TRS_regeneration use FatesGlobals, only : fates_log use FatesGlobals, only : endrun => fates_endrun use FatesIODimensionsMod, only : fates_io_dimension_type @@ -47,7 +49,8 @@ module FatesRestartInterfaceMod use PRTGenericMod, only : num_elements use FatesRunningMeanMod, only : rmean_type use FatesRunningMeanMod, only : ema_lpa - + use EDParamsMod, only : regeneration_model + ! CIME GLOBALS use shr_log_mod , only : errMsg => shr_log_errMsg @@ -157,12 +160,13 @@ module FatesRestartInterfaceMod ! Running Means integer :: ir_tveg24_pa integer :: ir_tveglpa_pa - integer :: ir_seedling_layer_par24_pa !ahb - integer :: ir_sdlng_emerg_smp_pa !ahb - integer :: ir_sdlng_mort_par_pa ! ahb - integer :: ir_sdlng2sap_par_pa ! ahb - integer :: ir_sdlng_mdd_pa ! ahb + integer :: ir_seedling_layer_par24_pa + integer :: ir_sdlng_emerg_smp_pa + integer :: ir_sdlng_mort_par_pa + integer :: ir_sdlng2sap_par_pa + integer :: ir_sdlng_mdd_pa integer :: ir_tveglongterm_pa + ! (Keeping as an example) !!integer :: ir_tveglpa_co @@ -1461,26 +1465,30 @@ subroutine define_restart_vars(this, initialize_variables) long_name='24-hour patch veg temp', & units='K', initialize=initialize_variables,ivar=ivar, index = ir_tveg24_pa) - call this%DefineRMeanRestartVar(vname='fates_seedling_layer_par24',vtype=cohort_r8, & - long_name='24-hour seedling layer PAR', & - units='W m2-1', initialize=initialize_variables,ivar=ivar, index = ir_seedling_layer_par24_pa) - - call this%DefineRMeanRestartVar(vname='fates_sdlng_emerg_smp',vtype=cohort_r8, & - long_name='seedling layer PAR on the seedling emergence timescale', & - units='mm suction', initialize=initialize_variables,ivar=ivar, index = ir_sdlng_emerg_smp_pa) - - call this%DefineRMeanRestartVar(vname='fates_sdlng_mort_par',vtype=cohort_r8, & - long_name='seedling layer PAR on the seedling mortality timescale', & - units='W m2-1', initialize=initialize_variables,ivar=ivar, index = ir_sdlng_mort_par_pa) - - call this%DefineRMeanRestartVar(vname='fates_sdlng2sap_par',vtype=cohort_r8, & - long_name='seedling layer PAR on the seedling to sapling transition timescale', & - units='W m2-1', initialize=initialize_variables,ivar=ivar, index = ir_sdlng2sap_par_pa) - - call this%DefineRMeanRestartVar(vname='fates_sdlng_mdd',vtype=cohort_r8, & - long_name='seedling moisture deficit days', & - units='mm days', initialize=initialize_variables,ivar=ivar, index = ir_sdlng_mdd_pa) + if ( regeneration_model == TRS_regeneration ) then + + call this%DefineRMeanRestartVar(vname='fates_seedling_layer_par24',vtype=cohort_r8, & + long_name='24-hour seedling layer PAR', & + units='W m2-1', initialize=initialize_variables,ivar=ivar, index = ir_seedling_layer_par24_pa) + + call this%DefineRMeanRestartVar(vname='fates_sdlng_emerg_smp',vtype=cohort_r8, & + long_name='seedling layer PAR on the seedling emergence timescale', & + units='mm suction', initialize=initialize_variables,ivar=ivar, index = ir_sdlng_emerg_smp_pa) + + call this%DefineRMeanRestartVar(vname='fates_sdlng_mort_par',vtype=cohort_r8, & + long_name='seedling layer PAR on the seedling mortality timescale', & + units='W m2-1', initialize=initialize_variables,ivar=ivar, index = ir_sdlng_mort_par_pa) + + call this%DefineRMeanRestartVar(vname='fates_sdlng2sap_par',vtype=cohort_r8, & + long_name='seedling layer PAR on the seedling to sapling transition timescale', & + units='W m2-1', initialize=initialize_variables,ivar=ivar, index = ir_sdlng2sap_par_pa) + + call this%DefineRMeanRestartVar(vname='fates_sdlng_mdd',vtype=cohort_r8, & + long_name='seedling moisture deficit days', & + units='mm days', initialize=initialize_variables,ivar=ivar, index = ir_sdlng_mdd_pa) + end if + call this%DefineRMeanRestartVar(vname='fates_tveglpapatch',vtype=cohort_r8, & long_name='running average (EMA) of patch veg temp for photo acclim', & units='K', initialize=initialize_variables,ivar=ivar, index = ir_tveglpa_pa) @@ -2360,14 +2368,18 @@ subroutine set_restart_vectors(this,nc,nsites,sites) call this%SetRMeanRestartVar(cpatch%tveg24, ir_tveg24_pa, io_idx_co_1st) call this%SetRMeanRestartVar(cpatch%tveg_lpa, ir_tveglpa_pa, io_idx_co_1st) call this%SetRMeanRestartVar(cpatch%tveg_longterm, ir_tveglongterm_pa, io_idx_co_1st) - call this%SetRMeanRestartVar(cpatch%seedling_layer_par24, ir_seedling_layer_par24_pa, io_idx_co_1st) - call this%SetRMeanRestartVar(cpatch%sdlng_mort_par, ir_sdlng_mort_par_pa,io_idx_co_1st) - call this%SetRMeanRestartVar(cpatch%sdlng2sap_par, ir_sdlng2sap_par_pa,io_idx_co_1st) - - do i_pft = 1, maxpft - call this%SetRMeanRestartVar(cpatch%sdlng_mdd(i_pft)%p, ir_sdlng_mdd_pa,io_idx_co_1st) - call this%SetRMeanRestartVar(cpatch%sdlng_emerg_smp(i_pft)%p, ir_sdlng_emerg_smp_pa,io_idx_co_1st) - enddo + + if ( regeneration_model == TRS_regeneration ) then + call this%SetRMeanRestartVar(cpatch%seedling_layer_par24, ir_seedling_layer_par24_pa, io_idx_co_1st) + call this%SetRMeanRestartVar(cpatch%sdlng_mort_par, ir_sdlng_mort_par_pa,io_idx_co_1st) + call this%SetRMeanRestartVar(cpatch%sdlng2sap_par, ir_sdlng2sap_par_pa,io_idx_co_1st) + io_idx_pa_pft = io_idx_co_1st + do i_pft = 1, numpft + call this%SetRMeanRestartVar(cpatch%sdlng_mdd(i_pft)%p, ir_sdlng_mdd_pa,io_idx_pa_pft) + call this%SetRMeanRestartVar(cpatch%sdlng_emerg_smp(i_pft)%p, ir_sdlng_emerg_smp_pa,io_idx_pa_pft) + io_idx_pa_pft = io_idx_pa_pft + 1 + enddo + end if ! set cohorts per patch for IO rio_ncohort_pa( io_idx_co_1st ) = cohortsperpatch @@ -3291,14 +3303,18 @@ subroutine get_restart_vectors(this, nc, nsites, sites) call this%GetRMeanRestartVar(cpatch%tveg24, ir_tveg24_pa, io_idx_co_1st) call this%GetRMeanRestartVar(cpatch%tveg_lpa, ir_tveglpa_pa, io_idx_co_1st) call this%GetRMeanRestartVar(cpatch%tveg_longterm, ir_tveglongterm_pa, io_idx_co_1st) - call this%GetRMeanRestartVar(cpatch%seedling_layer_par24, ir_seedling_layer_par24_pa, io_idx_co_1st) - call this%GetRMeanRestartVar(cpatch%sdlng_mort_par, ir_sdlng_mort_par_pa,io_idx_co_1st) - call this%GetRMeanRestartVar(cpatch%sdlng2sap_par, ir_sdlng2sap_par_pa,io_idx_co_1st) - - do pft = 1, maxpft - call this%GetRMeanRestartVar(cpatch%sdlng_mdd(pft)%p, ir_sdlng_mdd_pa,io_idx_co_1st) - call this%GetRMeanRestartVar(cpatch%sdlng_emerg_smp(pft)%p, ir_sdlng_emerg_smp_pa,io_idx_co_1st) - enddo + + if ( regeneration_model == TRS_regeneration ) then + call this%GetRMeanRestartVar(cpatch%seedling_layer_par24, ir_seedling_layer_par24_pa, io_idx_co_1st) + call this%GetRMeanRestartVar(cpatch%sdlng_mort_par, ir_sdlng_mort_par_pa,io_idx_co_1st) + call this%GetRMeanRestartVar(cpatch%sdlng2sap_par, ir_sdlng2sap_par_pa,io_idx_co_1st) + io_idx_pa_pft = io_idx_co_1st + do pft = 1, numpft + call this%GetRMeanRestartVar(cpatch%sdlng_mdd(pft)%p, ir_sdlng_mdd_pa,io_idx_pa_pft) + call this%GetRMeanRestartVar(cpatch%sdlng_emerg_smp(pft)%p, ir_sdlng_emerg_smp_pa,io_idx_pa_pft) + io_idx_pa_pft = io_idx_pa_pft + 1 + enddo + end if ! set cohorts per patch for IO diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 113d9b95a2..b97bfe68cd 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -1487,11 +1487,15 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & ! just different from the other pools. It is not based on proportionality, ! so its mask is set differently. We (inefficiently) just included ! reproduction in the previous loop, but oh well, we over-write now. - - ! If the TRS is switched off then we use FATES's default reproductive allocation. + + ! If the TRS is switched off, or if the plant is a shrub or grass + ! then we use FATES's default reproductive allocation. + ! We designate a plant a shrub or grass if its dbh at maximum height + ! is less than 15 cm + if ( regeneration_model == default_regeneration .or. & - prt_params%allom_dbh_maxheight(ipft) < min_max_dbh_for_trees ) then ! The Tree Recruitment Scheme - ! is only for trees + prt_params%allom_dbh_maxheight(ipft) < min_max_dbh_for_trees ) then + if (dbh <= prt_params%dbh_repro_threshold(ipft)) then repro_c_frac = prt_params%seed_alloc(ipft) else @@ -1508,6 +1512,12 @@ subroutine CNPStatureGrowth(this,c_gain, n_gain, p_gain, & (exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm) / & (1 + exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm))) + else + + write(fates_log(),*) 'unknown seed allocation and regeneration model, exiting' + write(fates_log(),*) 'regeneration_model: ',regeneration_model + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if ! regeneration switch @@ -2342,7 +2352,10 @@ function AllomCNPGrowthDeriv(l_state_array,l_state_mask,cbalance,intgr_params) r repro_fraction = prt_params%seed_alloc(ipft) * & (exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm) / & (1 + exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm))) - + else + write(fates_log(),*) 'unknown seed allocation and regeneration model, exiting' + write(fates_log(),*) 'regeneration_model: ',regeneration_model + call endrun(msg=errMsg(sourcefile, __LINE__)) end if ! regeneration switch else ! mask repro @@ -2475,7 +2488,10 @@ subroutine EstimateGrowthNC(this,target_c,target_dcdd,state_mask,avg_nc,avg_pc) repro_c_frac = prt_params%seed_alloc(ipft) * & (exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm) / & (1 + exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm))) - + else + write(fates_log(),*) 'unknown seed allocation and regeneration model, exiting' + write(fates_log(),*) 'regeneration_model: ',regeneration_model + call endrun(msg=errMsg(sourcefile, __LINE__)) end if ! regeneration switch else ! state mask diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 6a1c7ab7a1..a9b3ea2ab8 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -1061,27 +1061,35 @@ function AllomCGrowthDeriv(c_pools,c_mask,cbalance,intgr_params) result(dCdx) ct_dagwdd, ct_dbgwdd, ct_dsapdd, ct_ddeaddd) call bstore_allom(dbh,ipft,crowndamage, canopy_trim,ct_store,ct_dstoredd) - ! If the TRS is switched off then we use FATES's default reproductive allocation. - if ( regeneration_model == default_regeneration .or. & - prt_params%allom_dbh_maxheight(ipft) < min_max_dbh_for_trees ) then !The Tree Recruitment Scheme - !is only for tree pfts - ! Calculate fraction of carbon going towards reproduction - if (dbh <= prt_params%dbh_repro_threshold(ipft)) then ! cap on leaf biomass - repro_fraction = prt_params%seed_alloc(ipft) - else - repro_fraction = prt_params%seed_alloc(ipft) + prt_params%seed_alloc_mature(ipft) - end if ! End dbh check on if to add additional carbon to reproduction. + ! If the TRS is switched off, or if the plant is a shrub or grass + ! then we use FATES's default reproductive allocation. + ! We designate a plant a shrub or grass if its dbh at maximum height + ! is less than 15 cm - ! If the TRS is switched on (with or w/o seedling dynamics) then reproductive allocation is - ! a pft-specific function of dbh. This allows for the representation of different - ! reproductive schedules (Wenk and Falster, 2015) - else if ( any(regeneration_model == [TRS_regeneration, TRS_no_seedling_dyn]) .and. & - prt_params%allom_dbh_maxheight(ipft) > min_max_dbh_for_trees ) then + if ( regeneration_model == default_regeneration .or. & + prt_params%allom_dbh_maxheight(ipft) < min_max_dbh_for_trees ) then - repro_fraction = prt_params%seed_alloc(ipft) * & - (exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm) / & - (1 + exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm))) + ! TRS is only for tree pfts + ! Calculate fraction of carbon going towards reproduction + if (dbh <= prt_params%dbh_repro_threshold(ipft)) then ! cap on leaf biomass + repro_fraction = prt_params%seed_alloc(ipft) + else + repro_fraction = prt_params%seed_alloc(ipft) + prt_params%seed_alloc_mature(ipft) + end if ! End dbh check on if to add additional carbon to reproduction. + + ! If the TRS is switched on (with or w/o seedling dynamics) then reproductive allocation is + ! a pft-specific function of dbh. This allows for the representation of different + ! reproductive schedules (Wenk and Falster, 2015) + else if ( any(regeneration_model == [TRS_regeneration, TRS_no_seedling_dyn]) .and. & + prt_params%allom_dbh_maxheight(ipft) > min_max_dbh_for_trees ) then + repro_fraction = prt_params%seed_alloc(ipft) * & + (exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm) / & + (1 + exp(prt_params%repro_alloc_b(ipft) + prt_params%repro_alloc_a(ipft)*dbh*mm_per_cm))) + else + write(fates_log(),*) 'unknown seed allocation and regeneration model, exiting' + write(fates_log(),*) 'regeneration_model: ',regeneration_model + call endrun(msg=errMsg(sourcefile, __LINE__)) end if ! TRS switch dCdx = 0.0_r8 From 931726128a65e4a4d303268bd547f3e88f8a0896 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 18 Jul 2023 15:31:23 -0700 Subject: [PATCH 769/852] fix type of unset used --- main/FatesInterfaceMod.F90 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index ca49cb198a..b297029ca9 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -2005,6 +2005,7 @@ subroutine DetermineGridCellNeighbors(neighbors) use perf_mod , only : t_startf, t_stopf use FatesDispersalMod , only : neighborhood_type, neighbor_type, ProbabilityDensity use FatesUtilsMod , only : GetNeighborDistance + use FatesConstantsMod , only : fates_unset_int use EDPftvarcon , only : EDPftvarcon_inst ! Arguments @@ -2048,8 +2049,8 @@ subroutine DetermineGridCellNeighbors(neighbors) allocate(ncells_array(0:npes-1)) allocate(begg_array(0:npes-1)) - ncells_array = fates_unset_r8 - begg_array = fates_unset_r8 + ncells_array(:) = fates_unset_int + begg_array(:) = fates_unset_int call t_startf('fates-seed-init-allgather') From 3a0c3522ce68911c2cd6847f48381ff741f3a05f Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 18 Jul 2023 17:32:31 -0600 Subject: [PATCH 770/852] replace use of ldecomp --- main/FatesInterfaceMod.F90 | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index b297029ca9..7616dc6ba0 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1999,7 +1999,7 @@ subroutine DetermineGridCellNeighbors(neighbors) ! neighbor for later use. This should be called after decompInit_lnd and surf_get_grid ! as it relies on ldecomp and ldomain information. - use decompMod , only : ldecomp, procinfo, get_proc_global + use decompMod , only : procinfo, get_proc_global use domainMod , only : ldomain use spmdMod , only : MPI_REAL8, MPI_INTEGER, mpicom, npes, masterproc, iam use perf_mod , only : t_startf, t_stopf @@ -2015,12 +2015,12 @@ subroutine DetermineGridCellNeighbors(neighbors) type (neighbor_type), pointer :: current_neighbor type (neighbor_type), pointer :: another_neighbor - integer :: i, gi,gj ! indices - integer :: numg ! number of land gridcells - integer :: ngcheck ! number of land gridcells, globally - integer :: numproc ! number of processors, globally - integer :: ier,mpierr ! error code - integer :: ipft ! pft index + integer :: i, gi,gj ! indices + integer :: numg ! number of land gridcells + integer :: ngcheck ! number of land gridcells, globally + integer :: numproc ! number of processors, globally + integer :: ier,mpierr ! error code + integer :: ipft ! pft index integer :: ldsize ! ldomain size integer, allocatable :: ncells_array(:), begg_array(:) @@ -2037,8 +2037,7 @@ subroutine DetermineGridCellNeighbors(neighbors) ! Allocate array neighbor type - numg = size(ldecomp%gdc2glo) - + call get_proc_global(ng=numg) allocate(neighbors(numg), stat=ier) neighbors(:)%neighbor_count = 0 From 3f6b2be28483bc51127ef6f6b743f200be35e78b Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 18 Jul 2023 18:57:55 -0600 Subject: [PATCH 771/852] added use statement --- main/FatesInterfaceMod.F90 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 0544fba060..91308e9cf0 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -19,6 +19,7 @@ module FatesInterfaceMod use EDParamsMod , only : maxpatch_primary use EDParamsMod , only : maxpatch_secondary use EDParamsMod , only : max_cohort_per_patch + use EDParamsMod , only : regeneration_model use EDTypesMod , only : maxSWb use EDTypesMod , only : ivis use EDTypesMod , only : inir @@ -38,6 +39,7 @@ module FatesInterfaceMod use FatesConstantsMod , only : nearzero use FatesConstantsMod , only : sec_per_day use FatesConstantsMod , only : days_per_year + use FatesConstantsMod , only : TRS_regeneration use FatesGlobals , only : fates_global_verbose use FatesGlobals , only : fates_log use FatesGlobals , only : endrun => fates_endrun From ef3e76fa86cde85d8746eed6d984d29808a0ec10 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 19 Jul 2023 15:21:18 -0700 Subject: [PATCH 772/852] add loop names to seedupdate --- biogeochem/EDPhysiologyMod.F90 | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 221b8d9264..02e38a1bb0 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1781,7 +1781,7 @@ subroutine SeedUpdate( currentSite, bc_in, bc_out) integer :: el ! loop counter for litter element types integer :: element_id ! element id consistent with parteh/PRTGenericMod.F90 - do el = 1, num_elements + el_loop: do el = 1, num_elements site_seed_rain(:) = 0._r8 site_disp_frac(:) = 0._r8 @@ -1797,7 +1797,7 @@ subroutine SeedUpdate( currentSite, bc_in, bc_out) ! Loop over all patches and sum up the seed input for each PFT currentPatch => currentSite%oldest_patch - do while (associated(currentPatch)) + seed_rain_loop: do while (associated(currentPatch)) currentCohort => currentPatch%tallest do while (associated(currentCohort)) @@ -1834,7 +1834,7 @@ subroutine SeedUpdate( currentSite, bc_in, bc_out) enddo !cohort loop currentPatch => currentPatch%younger - enddo + enddo seed_rain_loop ! We can choose to homogenize seeds. This is simple, we just ! add up all the seed from each pft at the site level, and then @@ -1843,15 +1843,11 @@ subroutine SeedUpdate( currentSite, bc_in, bc_out) site_seed_rain(1:numpft) = sum(site_seed_rain(:))/real(numpft,r8) end if - ! Loop over all patches again and disperse the mixed seeds into the input flux ! arrays - ! Loop over all patches and sum up the seed input for each PFT currentPatch => currentSite%oldest_patch - - - do while (associated(currentPatch)) + seed_in_loop: do while (associated(currentPatch)) litt => currentPatch%litter(el) do pft = 1,numpft @@ -1889,13 +1885,13 @@ subroutine SeedUpdate( currentSite, bc_in, bc_out) enddo currentPatch => currentPatch%younger - enddo + enddo seed_in_loop - do pft = 1,numpft - site_mass%seed_out = site_mass%seed_out + site_seed_rain(pft)*site_disp_frac(pft) ![kg/site/day] - end do + do pft = 1,numpft + site_mass%seed_out = site_mass%seed_out + site_seed_rain(pft)*site_disp_frac(pft) ![kg/site/day] + end do - end do + end do el_loop do pft = 1,numpft bc_out%seed_out(pft) = bc_out%seed_out(pft) + site_seed_rain(pft)*site_disp_frac(pft) ![kg/site/day] From e229d6f9bb0836424a214327bbd824993016f23b Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 19 Jul 2023 15:30:10 -0700 Subject: [PATCH 773/852] move dispersal fraction outside of element loop This fraction is pft specific and doesn't vary with element type, so can be moved out --- biogeochem/EDPhysiologyMod.F90 | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 02e38a1bb0..d75871ec8d 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1781,16 +1781,15 @@ subroutine SeedUpdate( currentSite, bc_in, bc_out) integer :: el ! loop counter for litter element types integer :: element_id ! element id consistent with parteh/PRTGenericMod.F90 + ! If the dispersal kernel is not turned on, keep the dispersal fraction at zero + site_disp_frac(:) = 0._r8 + if (fates_dispersal_kernel_mode .ne. fates_dispersal_kernel_none) then + site_disp_frac(:) = EDPftvarcon_inst%seed_dispersal_fraction(:) + end if + el_loop: do el = 1, num_elements site_seed_rain(:) = 0._r8 - site_disp_frac(:) = 0._r8 - - ! If the dispersal kernel is not turned on, keep the dispersal fraction at zero - if (fates_dispersal_kernel_mode .ne. fates_dispersal_kernel_none) then - site_disp_frac(:) = EDPftvarcon_inst%seed_dispersal_fraction(:) - end if - element_id = element_list(el) site_mass => currentSite%mass_balance(el) From 145d77d818c84ff65ea743900dd96e60fa1ee77a Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 19 Jul 2023 16:00:45 -0700 Subject: [PATCH 774/852] Refactor seed disperal out of bc types Since the seed_in/out variables are not being used directly by the hlm, these don't have to be help in the bc types. Moving these helps avoid breaking API changes with history updates. --- biogeochem/EDPhysiologyMod.F90 | 9 ++++----- main/EDInitMod.F90 | 10 ++++++++-- main/EDMainMod.F90 | 2 +- main/EDTypesMod.F90 | 4 ++++ main/FatesHistoryInterfaceMod.F90 | 4 ++-- main/FatesInterfaceMod.F90 | 9 --------- main/FatesInterfaceTypesMod.F90 | 5 +---- 7 files changed, 20 insertions(+), 23 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index d75871ec8d..ed10a89cc9 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1739,7 +1739,7 @@ end subroutine assign_cohort_SP_properties ! ===================================================================================== - subroutine SeedUpdate( currentSite, bc_in, bc_out) + subroutine SeedUpdate( currentSite ) ! ----------------------------------------------------------------------------------- ! Flux from plants into the seed pool. @@ -1761,8 +1761,6 @@ subroutine SeedUpdate( currentSite, bc_in, bc_out) ! ! !ARGUMENTS type(ed_site_type), intent(inout), target :: currentSite - type(bc_in_type), intent(in) :: bc_in - type(bc_out_type), intent(inout) :: bc_out type(ed_patch_type), pointer :: currentPatch type(litter_type), pointer :: litt @@ -1875,7 +1873,7 @@ subroutine SeedUpdate( currentSite, bc_in, bc_out) ! Seed input from external sources (user param seed rain, or dispersal model) ! Include both prescribed seed_suppl and seed_in dispersed from neighbouring gridcells - seed_in_external = bc_in%seed_in(pft)/area + seed_stoich*EDPftvarcon_inst%seed_suppl(pft)*years_per_day ![kg/m2/day] + seed_in_external = currentSite%seed_in(pft)/area + seed_stoich*EDPftvarcon_inst%seed_suppl(pft)*years_per_day ![kg/m2/day] litt%seed_in_extern(pft) = litt%seed_in_extern(pft) + seed_in_external ! Seeds entering externally [kg/site/day] @@ -1886,6 +1884,7 @@ subroutine SeedUpdate( currentSite, bc_in, bc_out) currentPatch => currentPatch%younger enddo seed_in_loop + ! Determine the total site-level seed output for the current element do pft = 1,numpft site_mass%seed_out = site_mass%seed_out + site_seed_rain(pft)*site_disp_frac(pft) ![kg/site/day] end do @@ -1893,7 +1892,7 @@ subroutine SeedUpdate( currentSite, bc_in, bc_out) end do el_loop do pft = 1,numpft - bc_out%seed_out(pft) = bc_out%seed_out(pft) + site_seed_rain(pft)*site_disp_frac(pft) ![kg/site/day] + currentSite%seed_out(pft) = currentSite%seed_out(pft) + site_seed_rain(pft)*site_disp_frac(pft) ![kg/site/day] end do return diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 45b3ac7551..e1a5807006 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -201,12 +201,14 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) ! Initialize the static soil ! arrays from the boundary (initial) condition - site_in%zi_soil(:) = bc_in%zi_sisl(:) site_in%dz_soil(:) = bc_in%dz_sisl(:) site_in%z_soil(:) = bc_in%z_sisl(:) - ! + ! Seed dispersal + allocate(site_in%seed_in(1:numpft)) + allocate(site_in%seed_out(1:numpft)) + end subroutine init_site_vars ! ============================================================================ @@ -321,6 +323,10 @@ subroutine zero_site( site_in ) ! canopy spread site_in%spread = 0._r8 + ! Seed dispersal + site_in%seed_in(:) = 0.0_r8 + site_in%seed_out(:) = 0.0_r8 + site_in%area_pft(:) = 0._r8 site_in%use_this_pft(:) = fates_unset_int site_in%area_by_age(:) = 0._r8 diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 07d44d8915..5d623eee46 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -726,7 +726,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! fluxes. However, because this is potentially a cross-patch mixing model ! we will calculate this as a group - call SeedUpdate(currentSite,bc_in,bc_out) + call SeedUpdate(currentSite) ! Calculate all other litter fluxes ! ----------------------------------------------------------------------------------- diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 9bd01ef5e7..28ac01c215 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -894,6 +894,10 @@ module EDTypesMod ! Canopy Spread real(r8) :: spread ! dynamic canopy allometric term [unitless] + ! Seed dispersal + real(r8), allocatable :: seed_out(:) ! amount of seed leaving the site [kg/site/day] + real(r8), allocatable :: seed_in(:) ! amount of seed dispersed into the site from neighbouring cells [kg/site/day] + ! site-level variables to keep track of the disturbance rates, both actual and "potential" real(r8) :: disturbance_rates_primary_to_primary(N_DIST_TYPES) ! actual disturbance rates from primary patches to primary patches [m2/m2/day] real(r8) :: disturbance_rates_primary_to_secondary(N_DIST_TYPES) ! actual disturbance rates from primary patches to secondary patches [m2/m2/day] diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 91f5f46a7e..fec198ea47 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -3941,8 +3941,8 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in,bc_out) hio_recruitment_si_pft(io_si,i_pft) = sites(s)%recruitment_rate(i_pft) * days_per_year / m2_per_ha ! Gridcell output and inputs - hio_seeds_out_gc_si_pft(io_si,i_pft) = bc_out(s)%seed_out(i_pft) - hio_seeds_in_gc_si_pft(io_si,i_pft) = bc_in(s)%seed_in(i_pft) + hio_seeds_out_gc_si_pft(io_si,i_pft) = sites(s)%seed_out(i_pft) + hio_seeds_in_gc_si_pft(io_si,i_pft) = sites(s)%seed_in(i_pft) end do sites(s)%recruitment_rate(:) = 0._r8 diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index ca49cb198a..1132d70b52 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -373,9 +373,6 @@ subroutine zero_bcs(fates,s) end if fates%bc_out(s)%plant_stored_h2o_si = 0.0_r8 - fates%bc_in(s)%seed_in(:) = 0.0_r8 - fates%bc_out(s)%seed_out(:) = 0.0_r8 - ! Land Use realated fates%bc_out(s)%gpp_site = 0.0_r8 fates%bc_out(s)%ar_site = 0.0_r8 @@ -520,9 +517,6 @@ subroutine allocate_bcin(bc_in, nlevsoil_in, nlevdecomp_in, num_lu_harvest_cats, allocate(bc_in%h2o_liq_sisl(nlevsoil_in)); bc_in%h2o_liq_sisl = nan end if - ! Seed dispersal - allocate(bc_in%seed_in(1:numpft)) - ! Land use ! harvest flag denote data from hlm, @@ -681,9 +675,6 @@ subroutine allocate_bcout(bc_out, nlevsoil_in, nlevdecomp_in) allocate(bc_out%qflx_ro_sisl(nlevsoil_in)) end if - ! Seed dispersal - allocate(bc_out%seed_out(1:numpft)) - return end subroutine allocate_bcout diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 3dbbdea8fd..3d405421c5 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -539,8 +539,7 @@ module FatesInterfaceTypesMod real(r8),allocatable :: hksat_sisl(:) ! hydraulic conductivity at saturation (mm H2O /s) real(r8),allocatable :: h2o_liq_sisl(:) ! Liquid water mass in each layer (kg/m2) real(r8) :: smpmin_si ! restriction for min of soil potential (mm) - real(r8), allocatable :: seed_in(:) ! amount of seed dispersed into the site from neighbouring cells [kg/site/day] - + ! Land use ! --------------------------------------------------------------------------------- real(r8),allocatable :: hlm_harvest_rates(:) ! annual harvest rate per cat from hlm for a site @@ -743,8 +742,6 @@ module FatesInterfaceTypesMod ! small fluxes for various reasons ! [mm H2O/s] - real(r8),allocatable :: seed_out(:) ! amount of seed leaving the site [kg/site/day] - ! FATES LULCC real(r8) :: hrv_deadstemc_to_prod10c ! Harvested C flux to 10-yr wood product pool [Site-Level, gC m-2 s-1] real(r8) :: hrv_deadstemc_to_prod100c ! Harvested C flux to 100-yr wood product pool [Site-Level, gC m-2 s-1] From 69691b5c011bf887223dedb20748e59be069e30f Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 19 Jul 2023 18:02:28 -0600 Subject: [PATCH 775/852] remove bc_out argument due to refactor --- main/FatesHistoryInterfaceMod.F90 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index fec198ea47..71548df0f5 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2098,7 +2098,7 @@ end subroutine update_history_nutrflux ! ==================================================================================== - subroutine update_history_dyn(this,nc,nsites,sites,bc_in,bc_out) + subroutine update_history_dyn(this,nc,nsites,sites,bc_in) ! --------------------------------------------------------------------------------- ! This is the call to update the history IO arrays that are expected to only change @@ -2130,7 +2130,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in,bc_out) integer , intent(in) :: nc ! clump index integer , intent(in) :: nsites type(ed_site_type) , intent(inout), target :: sites(nsites) - type(bc_out_type) , intent(in) :: bc_out(nsites) type(bc_in_type) , intent(in) :: bc_in(nsites) ! Locals type(litter_type), pointer :: litt_c ! Pointer to the carbon12 litter pool From 8d7764fe8fe0ad902daaf221128cec4647d93ab4 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 19 Jul 2023 20:57:02 -0600 Subject: [PATCH 776/852] fix on germinated seed mortality, a switch check and history field names and units for seed_bank stuff --- biogeochem/EDPhysiologyMod.F90 | 234 +++++++++++++++--------------- main/EDPftvarcon.F90 | 16 +- main/FatesHistoryInterfaceMod.F90 | 32 ++-- 3 files changed, 152 insertions(+), 130 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index cff1632775..a62a3c1f62 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2103,47 +2103,46 @@ subroutine SeedIn( currentSite, bc_in ) if(currentSite%use_this_pft(pft).eq.itrue)then - ! Seed input from local sources (within site) - litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)/area - - ! If we are using the Tree Recruitment Scheme (TRS) with or w/o seedling dynamics - if ( any(regeneration_model == [TRS_regeneration, TRS_no_seedling_dyn]) .and. & - prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees) then - - ! Send a fraction of reproductive carbon to litter to account for - ! non-seed reproductive carbon (e.g. flowers, fruit, etc.) - litt%seed_decay(pft) = litt%seed_in_local(pft) * (1.0_r8 - EDPftvarcon_inst%repro_frac_seed(pft)) - - ! Note: The default regeneration scheme sends all reproductive carbon to seed - end if !Use TRS - - - ! If there is forced external seed rain, we calculate the input mass flux - ! from the different elements, using the mean stoichiometry of new - ! recruits for the current patch and lowest canopy position - - select case(element_id) - case(carbon12_element) - seed_stoich = 1._r8 - case(nitrogen_element) - seed_stoich = currentPatch%nitr_repro_stoich(pft) - case(phosphorus_element) - seed_stoich = currentPatch%phos_repro_stoich(pft) - case default - write(fates_log(), *) 'undefined element specified' - write(fates_log(), *) 'while defining forced external seed mass flux' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end select - - ! Seed input from external sources (user param seed rain, or dispersal model) - seed_in_external = seed_stoich*EDPftvarcon_inst%seed_suppl(pft)*years_per_day - litt%seed_in_extern(pft) = litt%seed_in_extern(pft) + seed_in_external - - ! Seeds entering externally [kg/site/day] - site_mass%seed_in = site_mass%seed_in + seed_in_external*currentPatch%area - end if !use this pft + ! Seed input from local sources (within site) + litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)/area + + ! If we are using the Tree Recruitment Scheme (TRS) with or w/o seedling dynamics + if ( any(regeneration_model == [TRS_regeneration, TRS_no_seedling_dyn]) .and. & + prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees) then + + ! Send a fraction of reproductive carbon to litter to account for + ! non-seed reproductive carbon (e.g. flowers, fruit, etc.) + litt%seed_decay(pft) = litt%seed_in_local(pft) * (1.0_r8 - EDPftvarcon_inst%repro_frac_seed(pft)) + + ! Note: The default regeneration scheme sends all reproductive carbon to seed + end if !Use TRS + + ! If there is forced external seed rain, we calculate the input mass flux + ! from the different elements, using the mean stoichiometry of new + ! recruits for the current patch and lowest canopy position + + select case(element_id) + case(carbon12_element) + seed_stoich = 1._r8 + case(nitrogen_element) + seed_stoich = currentPatch%nitr_repro_stoich(pft) + case(phosphorus_element) + seed_stoich = currentPatch%phos_repro_stoich(pft) + case default + write(fates_log(), *) 'undefined element specified' + write(fates_log(), *) 'while defining forced external seed mass flux' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select + + ! Seed input from external sources (user param seed rain, or dispersal model) + seed_in_external = seed_stoich*EDPftvarcon_inst%seed_suppl(pft)*years_per_day + litt%seed_in_extern(pft) = litt%seed_in_extern(pft) + seed_in_external + + ! Seeds entering externally [kg/site/day] + site_mass%seed_in = site_mass%seed_in + seed_in_external*currentPatch%area + end if !use this pft enddo - + currentPatch => currentPatch%younger enddo @@ -2196,71 +2195,78 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) if ( regeneration_model == default_regeneration .or. & prt_params%allom_dbh_maxheight(pft) < min_max_dbh_for_trees ) then - ! Default seed decay (TRS is off) - litt%seed_decay(pft) = litt%seed(pft) * & - EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day + ! Default seed decay (TRS is off) + litt%seed_decay(pft) = litt%seed(pft) * & + EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day - end if ! End default regeneration model + end if ! If the TRS is switched on and the pft is a tree then add non-seed reproductive biomass ! to the seed decay flux. This was added to litt%seed_decay in the previously called SeedIn ! subroutine if ( any(regeneration_model == [TRS_regeneration, TRS_no_seedling_dyn]) .and. & - prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees ) then - - litt%seed_decay(pft) = litt%seed_decay(pft) + &! From non-seed reproductive biomass (added in - ! in the SeedIn subroutine. - litt%seed(pft) * EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day - - end if ! End use TRS + prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees ) then + + litt%seed_decay(pft) = litt%seed_decay(pft) + &! From non-seed reproductive biomass (added in + ! in the SeedIn subroutine. + litt%seed(pft) * EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day + + end if ! If the TRS is switched on with seedling dynamics (regeneration_model = 2) ! then calculate seedling mortality. - if ( regeneration_model == TRS_regeneration .and. & - prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees ) then - - !---------------------------------------------------------------------- - ! Seedling mortality (flux from seedling pool to litter) - ! Note: The TRS uses the litt%seed_germ data struture to track seedlings - - ! Step 1. Calculate the daily seedling mortality rate from light stress - - ! Calculate the cumulative light at the seedling layer over a prior number of - ! days determined by the "fates_tres_seedling_mort_par_timescale" parameter. - seedling_layer_par = currentPatch%sdlng_mort_par%GetMean() * megajoules_per_joule * & - sec_per_day * sdlng_mort_par_timescale + if_trs_germ_decay: if ( regeneration_model == TRS_regeneration .and. & + prt_params%allom_dbh_maxheight(pft) > min_max_dbh_for_trees ) then + + !---------------------------------------------------------------------- + ! Seedling mortality (flux from seedling pool to litter) + ! Note: The TRS uses the litt%seed_germ data struture to track seedlings + ! + ! Step 1. Calculate the daily seedling mortality rate from light stress + ! + ! Calculate the cumulative light at the seedling layer over a prior number of + ! days determined by the "fates_tres_seedling_mort_par_timescale" parameter. - ! Calculate daily seedling mortality rate from light - seedling_light_mort_rate = exp( EDPftvarcon_inst%seedling_light_mort_a(pft) * & - seedling_layer_par + EDPftvarcon_inst%seedling_light_mort_b(pft) ) + seedling_layer_par = currentPatch%sdlng_mort_par%GetMean() * megajoules_per_joule * & + sec_per_day * sdlng_mort_par_timescale + + ! Calculate daily seedling mortality rate from light + seedling_light_mort_rate = exp( EDPftvarcon_inst%seedling_light_mort_a(pft) * & + seedling_layer_par + EDPftvarcon_inst%seedling_light_mort_b(pft) ) - ! Step 2. Calculate the daily seedling mortality rate from moisture stress + ! Step 2. Calculate the daily seedling mortality rate from moisture stress + + ! Get the current seedling moisture deficit days (tracked as a pft-specific exponential + ! average) + seedling_mdds = currentPatch%sdlng_mdd(pft)%p%GetMean() + + ! Calculate seedling mortality as a function of moisture deficit days (mdd) + ! If the seedling mmd value is below a critical threshold then moisture-based mortality is zero + if (seedling_mdds < EDPftvarcon_inst%seedling_mdd_crit(pft)) then + seedling_h2o_mort_rate = 0.0_r8 + else + seedling_h2o_mort_rate = EDPftvarcon_inst%seedling_h2o_mort_a(pft) * seedling_mdds**2 + & + EDPftvarcon_inst%seedling_h2o_mort_b(pft) * seedling_mdds + & + EDPftvarcon_inst%seedling_h2o_mort_c(pft) + end if ! mdd threshold check + + ! Step 3. Sum modes of mortality (including background mortality) and send dead seedlings + ! to litter + litt%seed_germ_decay(pft) = (litt%seed_germ(pft) * seedling_light_mort_rate) + & + (litt%seed_germ(pft) * seedling_h2o_mort_rate) + & + (litt%seed_germ(pft) * EDPftvarcon_inst%background_seedling_mort(pft) & + * years_per_day) - ! Get the current seedling moisture deficit days (tracked as a pft-specific exponential - ! average) - seedling_mdds = currentPatch%sdlng_mdd(pft)%p%GetMean() - - ! Calculate seedling mortality as a function of moisture deficit days (mdd) - ! If the seedling mmd value is below a critical threshold then moisture-based mortality is zero - if (seedling_mdds < EDPftvarcon_inst%seedling_mdd_crit(pft)) then - seedling_h2o_mort_rate = 0.0_r8 - else - seedling_h2o_mort_rate = EDPftvarcon_inst%seedling_h2o_mort_a(pft) * seedling_mdds**2 + & - EDPftvarcon_inst%seedling_h2o_mort_b(pft) * seedling_mdds + & - EDPftvarcon_inst%seedling_h2o_mort_c(pft) - end if ! mdd threshold check - - ! Step 3. Sum modes of mortality (including background mortality) and send dead seedlings - ! to litter - litt%seed_germ_decay(pft) = (litt%seed_germ(pft) * seedling_light_mort_rate) + & - (litt%seed_germ(pft) * seedling_h2o_mort_rate) + & - (litt%seed_germ(pft) * EDPftvarcon_inst%background_seedling_mort(pft) & - * years_per_day) - end if ! End use TRS with seedling dynamics + else + + litt%seed_germ_decay(pft) = litt%seed_germ(pft) * & + EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day + end if if_trs_germ_decay + enddo - + return end subroutine SeedDecay @@ -2530,12 +2536,12 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) ! Cycle through available carbon and nutrients, find the limiting element ! to dictate the total number of plants that can be generated - if ( (hlm_use_ed_prescribed_phys .eq. ifalse) .or. & + if_not_presribed: if ( (hlm_use_ed_prescribed_phys .eq. ifalse) .or. & (EDPftvarcon_inst%prescribed_recruitment(ft) .lt. 0._r8) ) then - temp_cohort%n = 1.e20_r8 + temp_cohort%n = 1.e20_r8 - do el = 1,num_elements + do_elem: do el = 1,num_elements element_id = element_list(el) select case(element_id) @@ -2580,32 +2586,32 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) regeneration_model == TRS_no_seedling_dyn .or. & prt_params%allom_dbh_maxheight(ft) < min_max_dbh_for_trees ) then - mass_avail = currentPatch%area * currentPatch%litter(el)%seed_germ(ft) + mass_avail = currentPatch%area * currentPatch%litter(el)%seed_germ(ft) ! If TRS seedling dynamics is on then calculate the available mass to make new recruits ! as a pft-specific function of light and soil moisture in the seedling layer. else if ( regeneration_model == TRS_regeneration .and. & prt_params%allom_dbh_maxheight(ft) > min_max_dbh_for_trees ) then - sdlng2sap_par = currentPatch%sdlng2sap_par%GetMean() * sec_per_day * megajoules_per_joule - - mass_avail = currentPatch%area * currentPatch%litter(el)%seed_germ(ft) * & - EDPftvarcon_inst%seedling_light_rec_a(ft) * & - sdlng2sap_par**EDPftvarcon_inst%seedling_light_rec_b(ft) + sdlng2sap_par = currentPatch%sdlng2sap_par%GetMean() * sec_per_day * megajoules_per_joule + + mass_avail = currentPatch%area * currentPatch%litter(el)%seed_germ(ft) * & + EDPftvarcon_inst%seedling_light_rec_a(ft) * & + sdlng2sap_par**EDPftvarcon_inst%seedling_light_rec_b(ft) - ! If soil moisture is below pft-specific seedling moisture stress threshold the - ! recruitment does not occur. - ilayer_seedling_root = minloc(abs(bc_in%z_sisl(:)-EDPftvarcon_inst%seedling_root_depth(ft)),dim=1) - - seedling_layer_smp = bc_in%smp_sl(ilayer_seedling_root) - - if ( seedling_layer_smp < EDPftvarcon_inst%seedling_psi_crit(ft) ) then - - mass_avail = 0.0_r8 - - end if ! End check if soil moisture is sufficient for recruitment - + ! If soil moisture is below pft-specific seedling moisture stress threshold the + ! recruitment does not occur. + ilayer_seedling_root = minloc(abs(bc_in%z_sisl(:)-EDPftvarcon_inst%seedling_root_depth(ft)),dim=1) + + seedling_layer_smp = bc_in%smp_sl(ilayer_seedling_root) + + if ( seedling_layer_smp < EDPftvarcon_inst%seedling_psi_crit(ft) ) then + + mass_avail = 0.0_r8 + + end if ! End check if soil moisture is sufficient for recruitment + end if ! End use TRS with seedling dynamics ! ------------------------------------------------------------------------ @@ -2614,15 +2620,17 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) temp_cohort%n = min(temp_cohort%n, mass_avail/mass_demand) - end do + end do do_elem else + ! prescribed recruitment rates. number per sq. meter per year temp_cohort%n = currentPatch%area * & EDPftvarcon_inst%prescribed_recruitment(ft) * & hlm_freq_day - endif + + endif if_not_presribed ! Only bother allocating a new cohort if there is a reasonable amount of it any_recruits: if (temp_cohort%n > min_n_safemath )then diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 31c9a08ad5..22add34b3a 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -25,7 +25,10 @@ module EDPftvarcon use FatesConstantsMod , only : prescribed_n_uptake use FatesConstantsMod , only : coupled_p_uptake use FatesConstantsMod , only : coupled_n_uptake - + use FatesConstantsMod , only : default_regeneration + use FatesConstantsMod , only : TRS_regeneration + use FatesConstantsMod , only : TRS_no_seedling_dyn + use EDParamsMod , only : regeneration_model ! CIME Globals use shr_log_mod , only : errMsg => shr_log_errMsg @@ -1749,6 +1752,17 @@ subroutine FatesCheckParams(is_master) call endrun(msg=errMsg(sourcefile, __LINE__)) end if + if(.not.any(regeneration_model == [default_regeneration, & + TRS_regeneration, & + TRS_no_seedling_dyn] )) then + write(fates_log(),*) 'The regeneration model must be set to a known model type' + write(fates_log(),*) 'the default is 1, and the Hanbury-Brown models are 2 and 3' + write(fates_log(),*) 'You specified fates_regeneration_model = ',regeneration_model + write(fates_log(),*) 'Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + select case (hlm_parteh_mode) case (prt_cnp_flex_allom_hyp) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 45ed876bf6..0594c77506 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -251,8 +251,8 @@ module FatesHistoryInterfaceMod integer :: ih_seed_bank_si ! carbon only integer :: ih_seeds_in_si ! carbon only integer :: ih_seeds_in_local_si ! carbon only - integer :: ih_seed_bank_trs_si ! carbon only - integer :: ih_seedling_pool_trs_si ! carbon only + integer :: ih_ungerm_seed_bank_si ! carbon only + integer :: ih_seedling_pool_si ! carbon only integer :: ih_ba_weighted_height_si integer :: ih_ca_weighted_height_si integer :: ih_seeds_in_local_elem @@ -2265,10 +2265,10 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_litter_in_si => this%hvars(ih_litter_in_si)%r81d, & hio_litter_out_si => this%hvars(ih_litter_out_si)%r81d, & hio_seed_bank_si => this%hvars(ih_seed_bank_si)%r81d, & - hio_seed_bank_trs_si => this%hvars(ih_seed_bank_trs_si)%r81d, & - hio_seedling_pool_trs_si => this%hvars(ih_seedling_pool_trs_si)%r81d, & + hio_ungerm_seed_bank_si => this%hvars(ih_ungerm_seed_bank_si)%r81d, & + hio_seedling_pool_si => this%hvars(ih_seedling_pool_si)%r81d, & hio_seeds_in_si => this%hvars(ih_seeds_in_si)%r81d, & - hio_seeds_in_local_si => this%hvars(ih_seeds_in_local_si)%r81d, & + hio_seeds_in_local_si => this%hvars(ih_seeds_in_local_si)%r81d, & hio_litter_in_elem => this%hvars(ih_litter_in_elem)%r82d, & hio_litter_out_elem => this%hvars(ih_litter_out_elem)%r82d, & hio_seed_bank_elem => this%hvars(ih_seed_bank_elem)%r82d, & @@ -4000,8 +4000,8 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_litter_out_si(io_si) = 0._r8 hio_seed_bank_si(io_si) = 0._r8 - hio_seed_bank_trs_si(io_si) = 0._r8 - hio_seedling_pool_trs_si(io_si) = 0._r8 + hio_ungerm_seed_bank_si(io_si) = 0._r8 + hio_seedling_pool_si(io_si) = 0._r8 hio_seeds_in_si(io_si) = 0._r8 hio_seeds_in_local_si(io_si) = 0._r8 @@ -4025,14 +4025,14 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) ! Sum up total seed bank (germinated and ungerminated) hio_seed_bank_si(io_si) = hio_seed_bank_si(io_si) + & (sum(litt%seed(:))+sum(litt%seed_germ(:))) * & - area_frac * days_per_sec + area_frac ! Sum up total seed bank (just ungerminated) - hio_seed_bank_trs_si(io_si) = hio_seed_bank_trs_si(io_si) + & + hio_ungerm_seed_bank_si(io_si) = hio_ungerm_seed_bank_si(io_si) + & sum(litt%seed(:)) * area_frac ! Sum up total seedling pool - hio_seedling_pool_trs_si(io_si) = hio_seedling_pool_trs_si(io_si) + & + hio_seedling_pool_si(io_si) = hio_seedling_pool_si(io_si) + & sum(litt%seed_germ(:)) * area_frac ! Sum up the input flux into the seed bank (local and external) @@ -5831,17 +5831,17 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_seed_bank_si) - call this%set_history_var(vname='FATES_SEED_BANK_TRS', units='kg m-2', & - long='total seed mass of all PFTs in kg carbon per m2 land area', & + call this%set_history_var(vname='FATES_UNGERM_SEED_BANK', units='kg m-2', & + long='ungerminated seed mass of all PFTs in kg carbon per m2 land area', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_seed_bank_trs_si) + index = ih_ungerm_seed_bank_si) - call this%set_history_var(vname='FATES_SEEDLING_POOL_TRS', units='kg m-2', & - long='total seedling mass of all PFTs in kg carbon per m2 land area', & + call this%set_history_var(vname='FATES_SEEDLING_POOL', units='kg m-2', & + long='total seedling (ie germinated seeds) mass of all PFTs in kg carbon per m2 land area', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_seedling_pool_trs_si) + index = ih_seedling_pool_si) call this%set_history_var(vname='FATES_SEEDS_IN', units='kg m-2 s-1', & long='seed production rate in kg carbon per m2 second', & From 40281baa65d4c21952c6447dd7ce99a84f7ba36d Mon Sep 17 00:00:00 2001 From: adrifoster Date: Thu, 20 Jul 2023 10:13:18 -0600 Subject: [PATCH 777/852] fix errors --- biogeochem/EDCanopyStructureMod.F90 | 4 ++-- biogeochem/EDPhysiologyMod.F90 | 4 ++-- main/EDInitMod.F90 | 32 +++++++++++++++-------------- main/FatesConstantsMod.F90 | 1 + 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 1b13fc6e78..464f964972 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -8,7 +8,7 @@ module EDCanopyStructureMod use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : itrue, ifalse use FatesConstantsMod , only : tinyr8 - use FatesConstantsMod , only : nearzero, calloc_abs_error + use FatesConstantsMod , only : nearzero, canopy_sum_error use FatesConstantsMod , only : rsnbl_math_prec use FatesConstantsMod , only : nocomp_bareground use FatesGlobals , only : fates_log @@ -1389,7 +1389,7 @@ subroutine canopy_summarization( nsites, sites, bc_in ) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if (currentPatch%total_canopy_area - currentPatch%area > calloc_abs_error) then + if (currentPatch%total_canopy_area - currentPatch%area > canopy_sum_error) then write(fates_log(),*) 'too much canopy in summary', s, & currentPatch%nocomp_pft_label, currentPatch%total_canopy_area - currentPatch%area call endrun(msg=errMsg(sourcefile, __LINE__)) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 860a3c4b43..f4c5e8407b 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -26,7 +26,7 @@ module EDPhysiologyMod use FatesConstantsMod, only : g_per_kg use FatesConstantsMod, only : ndays_per_year use FatesConstantsMod, only : nocomp_bareground - use FatesConstantsMod, only : calloc_abs_error + use FatesConstantsMod, only : canopy_sum_error use EDPftvarcon , only : EDPftvarcon_inst use PRTParametersMod , only : prt_params use EDPftvarcon , only : GetDecompyFrac @@ -1951,7 +1951,7 @@ subroutine assign_cohort_SP_properties(currentCohort,htop,tlai,tsai,parea,init,l currentCohort%n, currentCohort%canopy_layer, & canopylai,currentCohort%vcmax25top ) - if( abs(currentCohort%treelai-check_treelai).gt.1.0e-12)then !this is not as precise as nearzero + if (abs(currentCohort%treelai - check_treelai) > canopy_sum_error) then !this is not as precise as nearzero write(fates_log(),*) 'error in validate treelai',currentCohort%treelai,check_treelai,currentCohort%treelai-check_treelai write(fates_log(),*) 'tree_lai inputs: ', currentCohort%pft, currentCohort%c_area, currentCohort%n, & currentCohort%canopy_layer, currentCohort%vcmax25top diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index a922745fd3..96a3f3bd5a 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -552,7 +552,8 @@ subroutine init_patches( nsites, sites, bc_in) integer :: num_new_patches integer :: nocomp_pft real(r8) :: newparea - real(r8) :: tota !check on area + real(r8) :: total !check on area + real(r8) :: area_diff integer :: is_first_patch type(ed_site_type), pointer :: sitep @@ -686,28 +687,29 @@ subroutine init_patches( nsites, sites, bc_in) end do !no new patches !check if the total area adds to the same as site area - tota = 0.0_r8 + total = 0.0_r8 newp => sites(s)%oldest_patch do while (associated(newp)) - tota=tota+newp%area - newp=>newp%younger + total = total + newp%area + newp => newp%younger end do - - if(abs(tota-area).gt.nearzero*area)then - if(abs(tota-area).lt.1.0e-10_r8)then ! this is a precision error - if(sites(s)%oldest_patch%area.gt.(tota-area+nearzero))then + + area_diff = total - area + if (abs(area_diff) > nearzero) then + if (abs(area_diff) < canopy_sum_error) then ! this is a precision error + if (sites(s)%oldest_patch%area > area_diff + nearzero) then ! remove or add extra area ! if the oldest patch has enough area, use that - sites(s)%oldest_patch%area = sites(s)%oldest_patch%area - (tota-area) - if(debug) write(fates_log(),*) 'fixing patch precision - oldest',s, tota-area + sites(s)%oldest_patch%area = sites(s)%oldest_patch%area - area_diff + if (debug) write(fates_log(),*) 'fixing patch precision - oldest', s, area_diff else ! or otherwise take the area from the youngest patch. - sites(s)%youngest_patch%area = sites(s)%oldest_patch%area - (tota-area) - if(debug) write(fates_log(),*) 'fixing patch precision -youngest ',s, tota-area - endif + sites(s)%youngest_patch%area = sites(s)%youngest_patch%area - area_diff + if (debug) write(fates_log(),*) 'fixing patch precision -youngest ', s, area_diff + end if else !this is a big error not just a precision error. - write(fates_log(),*) 'issue with patch area in EDinit',tota-area,tota + write(fates_log(),*) 'issue with patch area in EDinit', area_diff, total call endrun(msg=errMsg(sourcefile, __LINE__)) - endif ! big error + end if ! big error end if ! too much patch area ! For carbon balance checks, we need to initialize the diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index cbf19198a7..bf514d5910 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -83,6 +83,7 @@ module FatesConstantsMod ! of carbon conservation in units of kgC/plant. This gives an effective ! error tolerance of 1 microgram. real(fates_r8), parameter, public :: calloc_abs_error = 1.0e-9_fates_r8 + real(fates_r8), parameter, public :: canopy_sum_error = 1.0e-9_fates_r8 ! Rounding errors seem to hover around 1e-15 for the gnu compiler ! when not applying compiler directives for safe math. An example From 6635ca06272a0ea1df5c32a935f93124cf20a648 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Thu, 20 Jul 2023 10:40:06 -0600 Subject: [PATCH 778/852] change name of error tol --- biogeochem/EDCanopyStructureMod.F90 | 4 ++-- biogeochem/EDPhysiologyMod.F90 | 4 ++-- main/EDInitMod.F90 | 3 ++- main/FatesConstantsMod.F90 | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 464f964972..2232b74580 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -8,7 +8,7 @@ module EDCanopyStructureMod use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : itrue, ifalse use FatesConstantsMod , only : tinyr8 - use FatesConstantsMod , only : nearzero, canopy_sum_error + use FatesConstantsMod , only : nearzero, area_error use FatesConstantsMod , only : rsnbl_math_prec use FatesConstantsMod , only : nocomp_bareground use FatesGlobals , only : fates_log @@ -1389,7 +1389,7 @@ subroutine canopy_summarization( nsites, sites, bc_in ) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if (currentPatch%total_canopy_area - currentPatch%area > canopy_sum_error) then + if (currentPatch%total_canopy_area - currentPatch%area > area_error) then write(fates_log(),*) 'too much canopy in summary', s, & currentPatch%nocomp_pft_label, currentPatch%total_canopy_area - currentPatch%area call endrun(msg=errMsg(sourcefile, __LINE__)) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index f4c5e8407b..1a9f6b2cdb 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -26,7 +26,7 @@ module EDPhysiologyMod use FatesConstantsMod, only : g_per_kg use FatesConstantsMod, only : ndays_per_year use FatesConstantsMod, only : nocomp_bareground - use FatesConstantsMod, only : canopy_sum_error + use FatesConstantsMod, only : area_error use EDPftvarcon , only : EDPftvarcon_inst use PRTParametersMod , only : prt_params use EDPftvarcon , only : GetDecompyFrac @@ -1951,7 +1951,7 @@ subroutine assign_cohort_SP_properties(currentCohort,htop,tlai,tsai,parea,init,l currentCohort%n, currentCohort%canopy_layer, & canopylai,currentCohort%vcmax25top ) - if (abs(currentCohort%treelai - check_treelai) > canopy_sum_error) then !this is not as precise as nearzero + if (abs(currentCohort%treelai - check_treelai) > area_error) then !this is not as precise as nearzero write(fates_log(),*) 'error in validate treelai',currentCohort%treelai,check_treelai,currentCohort%treelai-check_treelai write(fates_log(),*) 'tree_lai inputs: ', currentCohort%pft, currentCohort%c_area, currentCohort%n, & currentCohort%canopy_layer, currentCohort%vcmax25top diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 96a3f3bd5a..915f41be36 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -9,6 +9,7 @@ module EDInitMod use FatesConstantsMod , only : itrue use FatesConstantsMod , only : fates_unset_int use FatesConstantsMod , only : primaryforest + use FatesConstantsMod , only : area_error use FatesConstantsMod , only : nearzero use FatesGlobals , only : endrun => fates_endrun use EDTypesMod , only : nclmax @@ -696,7 +697,7 @@ subroutine init_patches( nsites, sites, bc_in) area_diff = total - area if (abs(area_diff) > nearzero) then - if (abs(area_diff) < canopy_sum_error) then ! this is a precision error + if (abs(area_diff) < area_error) then ! this is a precision error if (sites(s)%oldest_patch%area > area_diff + nearzero) then ! remove or add extra area ! if the oldest patch has enough area, use that diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index bf514d5910..bcc51b3ac8 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -83,7 +83,7 @@ module FatesConstantsMod ! of carbon conservation in units of kgC/plant. This gives an effective ! error tolerance of 1 microgram. real(fates_r8), parameter, public :: calloc_abs_error = 1.0e-9_fates_r8 - real(fates_r8), parameter, public :: canopy_sum_error = 1.0e-9_fates_r8 + real(fates_r8), parameter, public :: area_error = 1.0e-9_fates_r8 ! error tolerance for area checks (canopy, patch) ! Rounding errors seem to hover around 1e-15 for the gnu compiler ! when not applying compiler directives for safe math. An example From a3a8c5d988fa5e5f246203eb6dc44a54a782e3b3 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 20 Jul 2023 14:00:51 -0600 Subject: [PATCH 779/852] changed litter initialization to invalid for cold-start SP runs --- main/EDInitMod.F90 | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 5e5693cf21..caf0c5843b 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -8,6 +8,7 @@ module EDInitMod use FatesConstantsMod , only : ifalse use FatesConstantsMod , only : itrue use FatesConstantsMod , only : fates_unset_int + use FatesConstantsMod , only : fates_unset_r8 use FatesConstantsMod , only : primaryforest use FatesConstantsMod , only : nearzero use FatesGlobals , only : endrun => fates_endrun @@ -553,6 +554,7 @@ subroutine init_patches( nsites, sites, bc_in) integer :: nocomp_pft real(r8) :: newparea real(r8) :: tota !check on area + real(r8) :: litt_init !invalid for satphen, 0 otherwise integer :: is_first_patch type(ed_site_type), pointer :: sitep @@ -665,13 +667,18 @@ subroutine init_patches( nsites, sites, bc_in) ! Initialize the litter pools to zero, these ! pools will be populated by looping over the existing patches ! and transfering in mass + if(hlm_use_sp.eq.itrue)then + litt_init = fates_unset_r8 + else + litt_init = 0._r8 + end if do el=1,num_elements - call newp%litter(el)%InitConditions(init_leaf_fines=0._r8, & - init_root_fines=0._r8, & - init_ag_cwd=0._r8, & - init_bg_cwd=0._r8, & - init_seed=0._r8, & - init_seed_germ=0._r8) + call newp%litter(el)%InitConditions(init_leaf_fines=litt_init, & + init_root_fines=litt_init, & + init_ag_cwd=litt_init, & + init_bg_cwd=litt_init, & + init_seed=litt_init, & + init_seed_germ=litt_init) end do sitep => sites(s) From e3fc66d7ecd9370709493d875569ad99b8b61640 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 20 Jul 2023 14:25:33 -0600 Subject: [PATCH 780/852] the changes to default parameter file had already been implemented in a prior PR, reverting duplicate additions for TRS variables --- parameter_files/fates_params_default.cdl | 136 +---------------------- 1 file changed, 4 insertions(+), 132 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index f13f05d329..f170fe2275 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -151,16 +151,16 @@ variables: fates_allom_stmode:long_name = "storage allometry function index: 1) Storage proportional to leaf biomass (with trimming), 2) Storage proportional to maximum leaf biomass (not trimmed)" ; double fates_allom_zroot_k(fates_pft) ; fates_allom_zroot_k:units = "unitless" ; - fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model (NOT USED)" ; + fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; double fates_allom_zroot_max_dbh(fates_pft) ; fates_allom_zroot_max_dbh:units = "cm" ; - fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth (NOT USED)" ; + fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; double fates_allom_zroot_max_z(fates_pft) ; fates_allom_zroot_max_z:units = "m" ; - fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh (NOT USED). note: max_z=min_z=large, sets rooting depth to soil depth" ; + fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; double fates_allom_zroot_min_dbh(fates_pft) ; fates_allom_zroot_min_dbh:units = "cm" ; - fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined (NOT USED)" ; + fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; double fates_allom_zroot_min_z(fates_pft) ; fates_allom_zroot_min_z:units = "m" ; fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; @@ -476,60 +476,6 @@ variables: double fates_prescribed_npp_understory(fates_pft) ; fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; - double fates_trs_repro_alloc_a(fates_pft) ; - fates_trs_repro_alloc_a:units = "fraction" ; - fates_trs_repro_alloc_a:long_name = "shape parameter for sigmoidal function relating dbh to reproductive allocation" ; - double fates_trs_repro_alloc_b(fates_pft) ; - fates_trs_repro_alloc_b:units = "fraction" ; - fates_trs_repro_alloc_b:long_name = "intercept parameter for sigmoidal function relating dbh to reproductive allocation" ; - double fates_trs_repro_frac_seed(fates_pft) ; - fates_trs_repro_frac_seed:units = "fraction" ; - fates_trs_repro_frac_seed:long_name = "fraction of reproductive mass that is seed" ; - double fates_trs_seedling_a_emerg(fates_pft) ; - fates_trs_seedling_a_emerg:units = "day -1" ; - fates_trs_seedling_a_emerg:long_name = "mean fraction of seed bank emerging" ; - double fates_trs_seedling_b_emerg(fates_pft) ; - fates_trs_seedling_b_emerg:units = "day -1" ; - fates_trs_seedling_b_emerg:long_name = "seedling emergence sensitivity to soil moisture" ; - double fates_trs_seedling_par_crit_germ(fates_pft) ; - fates_trs_seedling_par_crit_germ:units = "Megajoules m2-1 day-1 " ; - fates_trs_seedling_par_crit_germ:long_name = "critical light level for germination" ; - double fates_trs_seedling_root_depth(fates_pft) ; - fates_trs_seedling_root_depth:units = "m" ; - fates_trs_seedling_root_depth:long_name = "rooting depth of seedlings" ; - double fates_trs_seedling_psi_emerg(fates_pft) ; - fates_trs_seedling_psi_emerg:units = "mm h20 suction" ; - fates_trs_seedling_psi_emerg:long_name = "critical soil moisture for seedling emergence" ; - double fates_trs_seedling_psi_crit(fates_pft) ; - fates_trs_seedling_psi_crit:units = "mm h20 suction" ; - fates_trs_seedling_psi_crit:long_name = "critical soil moisture for seedling stress" ; - double fates_trs_seedling_mdd_crit(fates_pft) ; - fates_trs_seedling_mdd_crit:units = "moisture deficit days (mm h2o suction * days)" ; - fates_trs_seedling_mdd_crit:long_name = "critical moisture deficit day accumulation for seedling moisture-based seedling mortality to begin" ; - double fates_trs_seedling_h2o_mort_a(fates_pft) ; - fates_trs_seedling_h2o_mort_a:units = "-" ; - fates_trs_seedling_h2o_mort_a:long_name = "coefficient in moisture-based seedling mortality" ; - double fates_trs_seedling_h2o_mort_b(fates_pft) ; - fates_trs_seedling_h2o_mort_b:units = "-" ; - fates_trs_seedling_h2o_mort_b:long_name = "coefficient in moisture-based seedling mortality" ; - double fates_trs_seedling_h2o_mort_c(fates_pft) ; - fates_trs_seedling_h2o_mort_c:units = "-" ; - fates_trs_seedling_h2o_mort_c:long_name = "coefficient in moisture-based seedling mortality" ; - double fates_trs_seedling_light_mort_a(fates_pft) ; - fates_trs_seedling_light_mort_a:units = "-" ; - fates_trs_seedling_light_mort_a:long_name = "light-based seedling mortality coefficient" ; - double fates_trs_seedling_light_mort_b(fates_pft) ; - fates_trs_seedling_light_mort_b:units = "-" ; - fates_trs_seedling_light_mort_b:long_name = "light-based seedling mortality coefficient" ; - double fates_trs_seedling_background_mort(fates_pft) ; - fates_trs_seedling_background_mort:units = "yr-1" ; - fates_trs_seedling_background_mort:long_name = "background seedling mortality rate" ; - double fates_trs_seedling_light_rec_a(fates_pft) ; - fates_trs_seedling_light_rec_a:units = "-" ; - fates_trs_seedling_light_rec_a:long_name = "coefficient in light-based seedling to sapling transition" ; - double fates_trs_seedling_light_rec_b(fates_pft) ; - fates_trs_seedling_light_rec_b:units = "-" ; - fates_trs_seedling_light_rec_b:long_name = "coefficient in light-based seedling to sapling transition" ; double fates_rad_leaf_clumping_index(fates_pft) ; fates_rad_leaf_clumping_index:units = "fraction (0-1)" ; fates_rad_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; @@ -854,9 +800,6 @@ variables: double fates_leaf_stomatal_model ; fates_leaf_stomatal_model:units = "unitless" ; fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; - double fates_regeneration_model ; - fates_regeneration_model:units = "unitless" ; - fates_regeneration_model:long_name = "switch for choosing between FATES's default regeneration scheme (1), the full Tree Recruitment Scheme (2; Hanbury-Brown et al., 2022), or (3) the Tree Recruitment Scheme without seedling dynamics" ; double fates_leaf_theta_cj_c3 ; fates_leaf_theta_cj_c3:units = "unitless" ; fates_leaf_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; @@ -908,18 +851,6 @@ variables: double fates_phen_ncolddayslim ; fates_phen_ncolddayslim:units = "days" ; fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; - double fates_trs_seedling_emerg_h2o_timescale ; - fates_trs_seedling_emerg_h2o_timescale:units = "days" ; - fates_trs_seedling_emerg_h2o_timescale:long_name = "Length of the window for the exponential moving average of smp used to calculate seedling emergence" ; - double fates_trs_seedling_mort_par_timescale ; - fates_trs_seedling_mort_par_timescale:units = "days" ; - fates_trs_seedling_mort_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling mortality" ; - double fates_trs_seedling_mdd_timescale ; - fates_trs_seedling_mdd_timescale:units = "days" ; - fates_trs_seedling_mdd_timescale:long_name = "Length of the window for the exponential moving average of moisture deficit days used to calculate seedling mortality" ; - double fates_trs_seedling2sap_par_timescale ; - fates_trs_seedling2sap_par_timescale:units = "days" ; - fates_trs_seedling2sap_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling to sapling transition rates" ; double fates_q10_froz ; fates_q10_froz:units = "unitless" ; fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; @@ -1491,63 +1422,6 @@ data: fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02 ; - fates_trs_repro_alloc_a = 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, - 0.0049, 0.0049, 0.0049, 0.0049, 0.0049 ; - - fates_trs_repro_alloc_b = -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, - -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171 ; - - fates_trs_repro_frac_seed = 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, - 0.24, 0.24, 0.24 ; - - fates_trs_seedling_a_emerg = 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, - 0.0003, 0.0003, 0.0003, 0.0003 ; - - fates_trs_seedling_b_emerg = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 ; - - fates_trs_seedling_par_crit_germ = 0.656, 0.656, 0.656, 0.656, 0.656, 0.656, - 0.656, 0.656, 0.656, 0.656, 0.656, 0.656 ; - - fates_trs_seedling_psi_emerg = -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, - -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65 ; - - fates_trs_seedling_psi_crit = -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, - -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7 ; - - fates_trs_seedling_mdd_crit = 1400000.0, 1400000.0, 1400000.0, 1400000.0, 1400000.0, - 1400000.0, 1400000.0, 1400000.0, 1400000.0, 1400000.0, 1400000.0, 1400000.0 ; - - fates_trs_seedling_h2o_mort_a = 4.070565e-17, 4.070565e-17, 4.070565e-17, - 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, - 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17 ; - - fates_trs_seedling_h2o_mort_b = -6.390757e-11, -6.390757e-11, -6.390757e-11, - -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, - -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11 ; - - fates_trs_seedling_h2o_mort_c = 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, - 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, - 1.268992e-05, 1.268992e-05 ; - - fates_trs_seedling_light_mort_a = -0.009897694, -0.009897694, -0.009897694, -0.009897694, - -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, - -0.009897694, -0.009897694 ; - - fates_trs_seedling_light_mort_b = -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, - -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063 ; - - fates_trs_seedling_background_mort = 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, - 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371 ; - - fates_trs_seedling_root_depth = 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, - 0.06, 0.06, 0.06, 0.06, 0.06, 0.06 ; - - fates_trs_seedling_light_rec_a = 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, - 0.007, 0.007, 0.007 ; - - fates_trs_seedling_light_rec_b = 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, - 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615 ; - fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; @@ -1775,8 +1649,6 @@ data: fates_landuse_logging_coll_under_frac = 0.55983 ; - fates_regeneration_model = 1 ; - fates_landuse_logging_collateral_frac = 0.05 ; fates_landuse_logging_dbhmax = _ ; From d09b149ea550690e25d5877c550c1ac5f51123a1 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 20 Jul 2023 19:02:32 -0600 Subject: [PATCH 781/852] removed xml patch file --- .../patch_TRS_bciopt_1_12_2022.xml | 52 ------------------- 1 file changed, 52 deletions(-) delete mode 100644 parameter_files/patch_TRS_bciopt_1_12_2022.xml diff --git a/parameter_files/patch_TRS_bciopt_1_12_2022.xml b/parameter_files/patch_TRS_bciopt_1_12_2022.xml deleted file mode 100644 index 4e135f9d5b..0000000000 --- a/parameter_files/patch_TRS_bciopt_1_12_2022.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - This parameter dataset was created by Ryan Knox rgknox@lbl.gov. Please contact if using in published work. The calibration uses the following datasets: [1] Ely et al. 2019. Leaf mass area, Panama. NGEE-Tropics data collection.http://dx.doi.org/10.15486/ngt/1411973 and [2] Condit et al. 2019. Complete data from the Barro Colorado 50-ha plot. https://doi.org/10.15146/5xcp-0d46. [3] Koven et al. 2019. Benchmarking and parameter sensitivity of physiological and vegetation dynamics using the functionally assembled terrestrial ecosystem simulator. Biogeosciences. The ECA nutrient aquisition parmeters are unconstrained, the file output naming convention vmn6phi is shorthand for vmax for nitrogen uptake is order e-6 and for phosphorus is excessively high. These parameters were calibrated with the special fates modification in main/EDTypesMod.F90: nclmax = 3 - fates_params_default.cdl - fates_params_TRS_bci_opt224_vmn6phi_011222.cdl - 1 - - 0 - 0 - 1,1,3,4 - 0.03347526,0.024,1e-08,0.0047 - 0.03347526,0.024,1e-08,0.0047 - 0.025,0,0,0 - 0.45,0.25,0,0 - 0.8012471 - 30.94711 - 0.0673 - 0.976 - -9 - -9 - 3 - 0.1266844 - 1.281329 - -9 - 0.768654 - 0.768654 - 57.6 - 0.74 - 21.6 - 200 - 2 - 5 - 0.4863088 - 3 - 3e-06 - 3e-06 - 3e-07 - 3e-08 - 0.03991654 - 0.01995827 - 0.01303514 - 0.02955703 - 3 - 3 - 0.04680188 - 0.001 - 0.8374751 - -1 - 0.5 - 1 - - From d652c21c5e904385bc4ee9c6927ef949206c602a Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 24 Jul 2023 11:58:05 -0600 Subject: [PATCH 782/852] implement decode_times=False --- tools/luh2/luh2.py | 13 ++++---- tools/luh2/luh2mod.py | 74 +++++++------------------------------------ 2 files changed, 19 insertions(+), 68 deletions(-) diff --git a/tools/luh2/luh2.py b/tools/luh2/luh2.py index 78385b6284..5c4bf68858 100644 --- a/tools/luh2/luh2.py +++ b/tools/luh2/luh2.py @@ -3,8 +3,7 @@ # LUH2 python script # Usage: python luh2.py -l -s -import argparse, os -from cftime import date2num +import argparse, os, sys from luh2mod import ImportData, SetMaskLUH2, SetMaskSurfData from luh2mod import RegridConservative, RegridLoop, CorrectStateSum @@ -62,7 +61,7 @@ def main(): # This is an old requirement of the HLM and should simply be a copy of the `time` dimension # If we are merging, we might not need to do this, so check to see if its there already if (not "YEAR" in list(regrid_luh2.variables)): - regrid_luh2["YEAR"] = date2num(regrid_luh2.time,'common_years since 0-01-01 00:00:00') + regrid_luh2["YEAR"] = regrid_luh2.time regrid_luh2["LONGXY"] = ds_regrid_target["LONGXY"] # TO DO: double check if this is strictly necessary regrid_luh2["LATIXY"] = ds_regrid_target["LATIXY"] # TO DO: double check if this is strictly necessary @@ -109,8 +108,11 @@ def CommandLineArgs(): parser.add_argument("-w", "--regridder_weights", required=True) # Optional input to subset the time range of the data - parser.add_argument("-b","--begin") - parser.add_argument("-e","--end") + # TODO: add support for parsing the input and checking against the allowable date range + parser.add_argument("-b","--begin", type=int, choices=range(850,2015), + help="beginning of date range to slice (allowable range is 0850-2015)") + parser.add_argument("-e","--end", type=int, choices=range(850,2015), + help="ending of date range to slice (allowable range is 0850-2015)") # Optional output argument parser.add_argument("-o","--output") @@ -122,6 +124,5 @@ def CommandLineArgs(): return(args) - if __name__ == "__main__": main() diff --git a/tools/luh2/luh2mod.py b/tools/luh2/luh2mod.py index a26ae68727..83ff10e40f 100644 --- a/tools/luh2/luh2mod.py +++ b/tools/luh2/luh2mod.py @@ -4,31 +4,20 @@ import numpy as np import xarray as xr import xesmf as xe -from nco import Nco -from nco.custom import Atted # Import luh2 or surface data sets def ImportData(input_file,start=None,stop=None,merge_flag=False): # Open files - # Check to see if a ValueError is raised which is likely due - # to the LUH2 time units being undecodable by cftime module - try: - datasetout = xr.open_dataset(input_file, cache=False) - except ValueError as err: - print("ValueError:", err) - errmsg = "User direction: If error is due to units being 'years since ...' " \ - "update the input data file to change to 'common_years since...'. " \ - "This can be done using the luh2.attribupdate function\n." - print() - print(errmsg) - else: - print("Input file dataset opened: {}".format(input_file)) - - datasetout = PrepDataset(datasetout,start,stop,merge_flag) + # Set decode_times to false as the luh2 raw data is outside the range + # of the standard NetCDF datetime format. + datasetout = xr.open_dataset(input_file, cache=False, decode_times=False) + print("Input file dataset opened: {}".format(input_file)) - return(datasetout) + # Prep the input data for use + datasetout = PrepDataset(datasetout,start,stop,merge_flag) + return(datasetout) # Prepare the input_file to be used for regridding def PrepDataset(input_dataset,start=None,stop=None,merge_flag=False): @@ -43,11 +32,15 @@ def PrepDataset(input_dataset,start=None,stop=None,merge_flag=False): if (isinstance(stop,type(None))): stop = input_dataset.time[-1] + # Convert the date to years since 0850 + years_since_start = start - 850 + years_since_stop = stop - 850 + # Truncate the data to the user defined range # This might need some more error handling for when # the start/stop is out of range try: - input_dataset = input_dataset.sel(time=slice(start,stop)) + input_dataset = input_dataset.sel(time=slice(years_since_start,years_since_stop)) except TypeError as type_err: print("Input must be a string\n") raise TypeError(type_err) @@ -73,49 +66,6 @@ def PrepDataset_ESMF(input_dataset,dsflag,dstype): return(input_dataset) -# Modify the luh2 metadata to enable xarray to read in data -# This issue here is that the luh2 time units start prior to -# year 1672, which cftime should be able to handle, but it -# appears to need a specific unit name convention "common_years" -def AttributeUpdateLUH2(input_file,output_append="modified"): - - # TO DO: Make this so that it can handle more than just absolute file location - # Define the output filename - index = input_file.find(".nc") - output_file = input_file[:index] + "_" + output_append + input_file[index:] - - nco = Nco() - - # Get the 'time:units' string from the input using ncks - time_unit_string = nco.ncks(input=input_file,variable="time",options=["-m"]).decode() - - # Grab the units string and replace "years" with "common_years" - substr = re.search('time:units.*".*"',time_unit_string) - newstr = substr.group().replace("time:units = \"years","\"common_years") - - # Use ncatted to update the time units - att = "units" - var = "time" - att_type = "c" - opts = [" -a {0},{1},o,{2},{3}".format(att, var, att_type, newstr)] - nco.ncatted(input=input_file, output=output_file, options=opts) - - # The following is fixed with PR #62 for pynco but isn't in that latest update yet - # on conda - # nco.ncatted(input=input_file,output=output_file,options=[ - # Atted(mode="overwrite", - # att_name="units", - # var_name="time", - # value=newstr, - # stype="c" - # ), - # ]) - - print("Generated modified output file: {}\n".format(output_file)) - - return(output_file) - - # Create the necessary variable "lat_b" and "lon_b" for xESMF conservative regridding # Each lat/lon boundary array is a 2D array corresponding to the bounds of each # coordinate position (e.g. lat_boundary would be 90.0 and 89.75 for lat coordinate From 14153c5c55625b2ba3f1680f3f924be2bbe59d60 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 24 Jul 2023 15:00:22 -0600 Subject: [PATCH 783/852] remove call to attribute update in shell script --- tools/luh2/luh2.sh | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tools/luh2/luh2.sh b/tools/luh2/luh2.sh index c68057a245..06ae70ecfd 100755 --- a/tools/luh2/luh2.sh +++ b/tools/luh2/luh2.sh @@ -34,8 +34,6 @@ export REGRIDDER=${DATA_LOC}/${REGRID_SAVE} # Regrid the luh2 data against a target surface data set and then remove the states_modified file echo "starting storage" du -h ${DATA_LOC} -echo "Correcting LUH2 time data for ${STATES}" -python -c "from luh2mod import AttributeUpdateLUH2; AttributeUpdateLUH2('${STATES}')" export STATES=${DATA_LOC}/states_modified.nc python luh2.py -l ${STATES} -s ${STATIC} -r ${REGRID_TARGET} -w ${REGRIDDER} -o ${DATA_LOC}/states_regrid.nc echo -e"storage status:\n" @@ -43,8 +41,6 @@ du -h ${DATA_LOC} rm ${STATES} # Regrid the luh2 transitions data using the saved regridder weights file and merge into previous regrid output -echo "Correcting LUH2 time data for ${TRANSITIONS}" -python -c "from luh2mod import AttributeUpdateLUH2; AttributeUpdateLUH2('${TRANSITIONS}')" export TRANSITIONS=${DATA_LOC}/transitions_modified.nc python luh2.py -l ${TRANSITIONS} -s ${STATIC} -r ${REGRID_TARGET} -w ${REGRIDDER} \ -m ${DATA_LOC}/states_regrid.nc -o ${DATA_LOC}/states_trans_regrid.nc @@ -54,8 +50,6 @@ rm ${TRANSITIONS} rm ${DATA_LOC}/states_regrid.nc # Regrid the luh2 management data using the saved regridder file and merge into previous regrid output -echo "Correcting LUH2 time data for ${MANAGE}" -python -c "from luh2mod import AttributeUpdateLUH2; AttributeUpdateLUH2('${MANAGE}')" export MANAGE=${DATA_LOC}/management_modified.nc python luh2.py -l ${MANAGE} -s ${STATIC} -r ${REGRID_TARGET} -w ${REGRIDDER} \ -m ${DATA_LOC}/states_trans_regrid.nc -o ${OUTPUT} From 35dee92f297767b5ecc6753cac609942320dd2d1 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 24 Jul 2023 15:22:32 -0600 Subject: [PATCH 784/852] reworking luh2 shell script call --- tools/luh2/luh2.sh | 55 ++++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 31 deletions(-) diff --git a/tools/luh2/luh2.sh b/tools/luh2/luh2.sh index 06ae70ecfd..1e43dec9ef 100755 --- a/tools/luh2/luh2.sh +++ b/tools/luh2/luh2.sh @@ -7,54 +7,47 @@ # of the luh2 data and the dataset to regrid against # LUH2 data names -export DATA_LOC=$1 -export STATES_FILE=states.nc -export TRANSITIONS_FILE=transitions.nc -export MANAGE_FILE=management.nc -export STATIC_FILE=staticData_quarterdeg.nc -export REGRID_TARGET_FILE=surfdata_4x5_16pfts_Irrig_CMIP6_simyr2000_c170824.nc +DATA_LOC=$1 +TARGET_LOC=$2 +OUTPUT_LOC=$3 +STATES_FILE=states.nc +TRANSITIONS_FILE=transitions.nc +MANAGE_FILE=management.nc +STATIC_FILE=staticData_quarterdeg.nc +REGRID_TARGET_FILE=surfdata_4x5_16pfts_Irrig_CMIP6_simyr2000_c170824.nc # Save files -export REGRID_SAVE=regridder.nc -export OUTPUT=LUH2_historical_0850_2015_4x5.nc +REGRID_SAVE=regridder.nc +OUTPUT_FILE=LUH2_historical_0850_2015_4x5.nc # Combine strings -export STATES=${DATA_LOC}/${STATES_FILE} -export TRANSITIONS=${DATA_LOC}/${TRANSITIONS_FILE} -export MANAGE=${DATA_LOC}/${MANAGE_FILE} -export STATIC=${DATA_LOC}/${STATIC_FILE} -export REGRID_TARGET=${DATA_LOC}/${REGRID_TARGET_FILE} -export REGRIDDER=${DATA_LOC}/${REGRID_SAVE} +STATES=${DATA_LOC}/${STATES_FILE} +TRANSITIONS=${DATA_LOC}/${TRANSITIONS_FILE} +MANAGE=${DATA_LOC}/${MANAGE_FILE} +STATIC=${DATA_LOC}/${STATIC_FILE} +REGRID_TARGET=${TARGET_LOC}/${REGRID_TARGET_FILE} +REGRIDDER=${OUTPUT_LOC}/${REGRID_SAVE} -# Create copies of the luh2 data that have the time data modified # Comment this out if the user already has the modified datasets available -# Update that filename to point to - # Regrid the luh2 data against a target surface data set and then remove the states_modified file echo "starting storage" -du -h ${DATA_LOC} -export STATES=${DATA_LOC}/states_modified.nc -python luh2.py -l ${STATES} -s ${STATIC} -r ${REGRID_TARGET} -w ${REGRIDDER} -o ${DATA_LOC}/states_regrid.nc +du -h ${OUTPUT_LOC} +python luh2.py -l ${STATES} -s ${STATIC} -r ${REGRID_TARGET} -w ${REGRIDDER} -o ${OUTPUT_LOC}/states_regrid.nc echo -e"storage status:\n" -du -h ${DATA_LOC} -rm ${STATES} +du -h ${OUTPUT_LOC} # Regrid the luh2 transitions data using the saved regridder weights file and merge into previous regrid output -export TRANSITIONS=${DATA_LOC}/transitions_modified.nc python luh2.py -l ${TRANSITIONS} -s ${STATIC} -r ${REGRID_TARGET} -w ${REGRIDDER} \ - -m ${DATA_LOC}/states_regrid.nc -o ${DATA_LOC}/states_trans_regrid.nc + -m ${OUTPUT_LOC}/states_regrid.nc -o ${OUTPUT_LOC}/states_trans_regrid.nc echo -e"storage status:\n" -du -h ${DATA_LOC} -rm ${TRANSITIONS} +du -h ${OUTPUT_LOC} rm ${DATA_LOC}/states_regrid.nc # Regrid the luh2 management data using the saved regridder file and merge into previous regrid output -export MANAGE=${DATA_LOC}/management_modified.nc python luh2.py -l ${MANAGE} -s ${STATIC} -r ${REGRID_TARGET} -w ${REGRIDDER} \ - -m ${DATA_LOC}/states_trans_regrid.nc -o ${OUTPUT} + -m ${OUTPUT_LOC}/states_trans_regrid.nc -o ${OUTPUT_LOC}/${OUTPUT_FILE} echo -e"storage status:\n" -du -h ${DATA_LOC} -rm ${MANAGE} -rm ${DATA_LOC}/states_trans_regrid.nc +du -h ${OUTPUT_LOC} +rm ${OUTPUT_LOC}/states_trans_regrid.nc rm ${REGRIDDER} From 822699a2b306ca97ba91002433549664bbd7a112 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 24 Jul 2023 14:26:00 -0700 Subject: [PATCH 785/852] Correct seed_in_external and seed_out calculations --- biogeochem/EDPhysiologyMod.F90 | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index ed10a89cc9..0e3a148f1f 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1873,7 +1873,7 @@ subroutine SeedUpdate( currentSite ) ! Seed input from external sources (user param seed rain, or dispersal model) ! Include both prescribed seed_suppl and seed_in dispersed from neighbouring gridcells - seed_in_external = currentSite%seed_in(pft)/area + seed_stoich*EDPftvarcon_inst%seed_suppl(pft)*years_per_day ![kg/m2/day] + seed_in_external = seed_stoich*(currentSite%seed_in(pft)/area + EDPftvarcon_inst%seed_suppl(pft)*years_per_day) ![kg/m2/day] litt%seed_in_extern(pft) = litt%seed_in_extern(pft) + seed_in_external ! Seeds entering externally [kg/site/day] @@ -1884,17 +1884,15 @@ subroutine SeedUpdate( currentSite ) currentPatch => currentPatch%younger enddo seed_in_loop - ! Determine the total site-level seed output for the current element + ! Determine the total site-level seed output for the current element and update the seed_out mass + ! for each element loop since the site_seed_rain is resent and updated for each element loop iteration do pft = 1,numpft site_mass%seed_out = site_mass%seed_out + site_seed_rain(pft)*site_disp_frac(pft) ![kg/site/day] + currentSite%seed_out(pft) = currentSite%seed_out(pft) + site_seed_rain(pft)*site_disp_frac(pft) ![kg/site/day] end do end do el_loop - do pft = 1,numpft - currentSite%seed_out(pft) = currentSite%seed_out(pft) + site_seed_rain(pft)*site_disp_frac(pft) ![kg/site/day] - end do - return end subroutine SeedUpdate From 2e4cc834d15f8b37fdd4139808d037f5186429a5 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 24 Jul 2023 16:02:26 -0700 Subject: [PATCH 786/852] update parameter patch file for api25.5 --- .../api25.4.0_032323_fates_params_default.cdl | 1559 ----------------- ...pr1005.xml => api25.5.0_072423_pr1005.xml} | 4 +- 2 files changed, 2 insertions(+), 1561 deletions(-) delete mode 100644 parameter_files/archive/api25.4.0_032323_fates_params_default.cdl rename parameter_files/archive/{api25.4.0_032323_pr1005.xml => api25.5.0_072423_pr1005.xml} (96%) diff --git a/parameter_files/archive/api25.4.0_032323_fates_params_default.cdl b/parameter_files/archive/api25.4.0_032323_fates_params_default.cdl deleted file mode 100644 index d461cb6fbb..0000000000 --- a/parameter_files/archive/api25.4.0_032323_fates_params_default.cdl +++ /dev/null @@ -1,1559 +0,0 @@ -netcdf fates_params_default { -dimensions: - fates_NCWD = 4 ; - fates_history_age_bins = 7 ; - fates_history_coage_bins = 2 ; - fates_history_damage_bins = 2 ; - fates_history_height_bins = 6 ; - fates_history_size_bins = 13 ; - fates_hlm_pftno = 14 ; - fates_hydr_organs = 4 ; - fates_leafage_class = 1 ; - fates_litterclass = 6 ; - fates_pft = 12 ; - fates_plant_organs = 4 ; - fates_string_length = 60 ; -variables: - double fates_history_ageclass_bin_edges(fates_history_age_bins) ; - fates_history_ageclass_bin_edges:units = "yr" ; - fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; - double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; - fates_history_coageclass_bin_edges:units = "years" ; - fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; - double fates_history_height_bin_edges(fates_history_height_bins) ; - fates_history_height_bin_edges:units = "m" ; - fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; - double fates_history_damage_bin_edges(fates_history_damage_bins) ; - fates_history_damage_bin_edges:units = "% crown loss" ; - fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; - double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; - fates_history_sizeclass_bin_edges:units = "cm" ; - fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; - double fates_alloc_organ_id(fates_plant_organs) ; - fates_alloc_organ_id:units = "unitless" ; - fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; - double fates_hydro_htftype_node(fates_hydr_organs) ; - fates_hydro_htftype_node:units = "unitless" ; - fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; - char fates_pftname(fates_pft, fates_string_length) ; - fates_pftname:units = "unitless - string" ; - fates_pftname:long_name = "Description of plant type" ; - char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; - fates_hydro_organ_name:units = "unitless - string" ; - fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; - char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; - fates_alloc_organ_name:units = "unitless - string" ; - fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; - 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" ; - 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" ; - double fates_alloc_storage_cushion(fates_pft) ; - fates_alloc_storage_cushion:units = "fraction" ; - fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; - double fates_alloc_store_priority_frac(fates_pft) ; - fates_alloc_store_priority_frac:units = "unitless" ; - fates_alloc_store_priority_frac:long_name = "for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage" ; - double fates_allom_agb1(fates_pft) ; - fates_allom_agb1:units = "variable" ; - fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; - double fates_allom_agb2(fates_pft) ; - fates_allom_agb2:units = "variable" ; - fates_allom_agb2:long_name = "Parameter 2 for agb allometry" ; - double fates_allom_agb3(fates_pft) ; - fates_allom_agb3:units = "variable" ; - fates_allom_agb3:long_name = "Parameter 3 for agb allometry" ; - double fates_allom_agb4(fates_pft) ; - fates_allom_agb4:units = "variable" ; - fates_allom_agb4:long_name = "Parameter 4 for agb allometry" ; - double fates_allom_agb_frac(fates_pft) ; - fates_allom_agb_frac:units = "fraction" ; - fates_allom_agb_frac:long_name = "Fraction of woody biomass that is above ground" ; - double fates_allom_amode(fates_pft) ; - fates_allom_amode:units = "index" ; - fates_allom_amode:long_name = "AGB allometry function index." ; - double fates_allom_blca_expnt_diff(fates_pft) ; - fates_allom_blca_expnt_diff:units = "unitless" ; - fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; - double fates_allom_cmode(fates_pft) ; - fates_allom_cmode:units = "index" ; - fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; - double fates_allom_crown_depth_frac(fates_pft) ; - fates_allom_crown_depth_frac:units = "fraction" ; - fates_allom_crown_depth_frac:long_name = "the depth of a cohort crown as a fraction of its height" ; - double fates_allom_d2bl1(fates_pft) ; - fates_allom_d2bl1:units = "variable" ; - fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; - double fates_allom_d2bl2(fates_pft) ; - fates_allom_d2bl2:units = "variable" ; - fates_allom_d2bl2:long_name = "Parameter 2 for d2bl allometry" ; - double fates_allom_d2bl3(fates_pft) ; - fates_allom_d2bl3:units = "unitless" ; - fates_allom_d2bl3:long_name = "Parameter 3 for d2bl allometry" ; - double fates_allom_d2ca_coefficient_max(fates_pft) ; - fates_allom_d2ca_coefficient_max:units = "m2 cm^(-1/beta)" ; - fates_allom_d2ca_coefficient_max:long_name = "max (savanna) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; - double fates_allom_d2ca_coefficient_min(fates_pft) ; - fates_allom_d2ca_coefficient_min:units = "m2 cm^(-1/beta)" ; - fates_allom_d2ca_coefficient_min:long_name = "min (forest) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; - double fates_allom_d2h1(fates_pft) ; - fates_allom_d2h1:units = "variable" ; - fates_allom_d2h1:long_name = "Parameter 1 for d2h allometry (intercept, or c)" ; - double fates_allom_d2h2(fates_pft) ; - fates_allom_d2h2:units = "variable" ; - fates_allom_d2h2:long_name = "Parameter 2 for d2h allometry (slope, or m)" ; - double fates_allom_d2h3(fates_pft) ; - fates_allom_d2h3:units = "variable" ; - fates_allom_d2h3:long_name = "Parameter 3 for d2h allometry (optional)" ; - double fates_allom_dbh_maxheight(fates_pft) ; - fates_allom_dbh_maxheight:units = "cm" ; - fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; - double fates_allom_fmode(fates_pft) ; - fates_allom_fmode:units = "index" ; - fates_allom_fmode:long_name = "fine root biomass allometry function index." ; - double fates_allom_fnrt_prof_a(fates_pft) ; - fates_allom_fnrt_prof_a:units = "unitless" ; - fates_allom_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; - double fates_allom_fnrt_prof_b(fates_pft) ; - fates_allom_fnrt_prof_b:units = "unitless" ; - fates_allom_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; - double fates_allom_fnrt_prof_mode(fates_pft) ; - fates_allom_fnrt_prof_mode:units = "index" ; - fates_allom_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; - double fates_allom_frbstor_repro(fates_pft) ; - fates_allom_frbstor_repro:units = "fraction" ; - fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; - double fates_allom_hmode(fates_pft) ; - fates_allom_hmode:units = "index" ; - fates_allom_hmode:long_name = "height allometry function index." ; - double fates_allom_l2fr(fates_pft) ; - fates_allom_l2fr:units = "gC/gC" ; - fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; - double fates_allom_la_per_sa_int(fates_pft) ; - fates_allom_la_per_sa_int:units = "m2/cm2" ; - fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; - double fates_allom_la_per_sa_slp(fates_pft) ; - fates_allom_la_per_sa_slp:units = "m2/cm2/m" ; - fates_allom_la_per_sa_slp:long_name = "Leaf area per sapwood area rate of change with height, slope (optional)" ; - double fates_allom_lmode(fates_pft) ; - fates_allom_lmode:units = "index" ; - fates_allom_lmode:long_name = "leaf biomass allometry function index." ; - double fates_allom_sai_scaler(fates_pft) ; - fates_allom_sai_scaler:units = "m2/m2" ; - fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; - double fates_allom_smode(fates_pft) ; - fates_allom_smode:units = "index" ; - fates_allom_smode:long_name = "sapwood allometry function index." ; - double fates_allom_stmode(fates_pft) ; - fates_allom_stmode:units = "index" ; - fates_allom_stmode:long_name = "storage allometry function index: 1) Storage proportional to leaf biomass (with trimming), 2) Storage proportional to maximum leaf biomass (not trimmed)" ; - double fates_allom_zroot_k(fates_pft) ; - fates_allom_zroot_k:units = "unitless" ; - fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; - double fates_allom_zroot_max_dbh(fates_pft) ; - fates_allom_zroot_max_dbh:units = "cm" ; - fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; - double fates_allom_zroot_max_z(fates_pft) ; - fates_allom_zroot_max_z:units = "m" ; - fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; - double fates_allom_zroot_min_dbh(fates_pft) ; - fates_allom_zroot_min_dbh:units = "cm" ; - fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; - double fates_allom_zroot_min_z(fates_pft) ; - fates_allom_zroot_min_z:units = "m" ; - fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; - double fates_c2b(fates_pft) ; - fates_c2b:units = "ratio" ; - fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; - double fates_cnp_eca_alpha_ptase(fates_pft) ; - fates_cnp_eca_alpha_ptase:units = "g/m3" ; - fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; - double fates_cnp_eca_decompmicc(fates_pft) ; - fates_cnp_eca_decompmicc:units = "gC/m3" ; - fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; - double fates_cnp_eca_km_nh4(fates_pft) ; - fates_cnp_eca_km_nh4:units = "gN/m3" ; - fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; - double fates_cnp_eca_km_no3(fates_pft) ; - fates_cnp_eca_km_no3:units = "gN/m3" ; - fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; - double fates_cnp_eca_km_p(fates_pft) ; - fates_cnp_eca_km_p:units = "gP/m3" ; - fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; - double fates_cnp_eca_km_ptase(fates_pft) ; - fates_cnp_eca_km_ptase:units = "gP/m3" ; - fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; - double fates_cnp_eca_lambda_ptase(fates_pft) ; - fates_cnp_eca_lambda_ptase:units = "g/m3" ; - fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; - double fates_cnp_eca_vmax_ptase(fates_pft) ; - fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; - fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; - double fates_cnp_nfix1(fates_pft) ; - fates_cnp_nfix1:units = "fraction" ; - fates_cnp_nfix1:long_name = "fractional surcharge added to maintenance respiration that drives symbiotic fixation" ; - double fates_cnp_nitr_store_ratio(fates_pft) ; - fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; - fates_cnp_nitr_store_ratio:long_name = "storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code)" ; - double fates_cnp_phos_store_ratio(fates_pft) ; - fates_cnp_phos_store_ratio:units = "(gP/gP)" ; - fates_cnp_phos_store_ratio:long_name = "storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code)" ; - double fates_cnp_pid_kd(fates_pft) ; - fates_cnp_pid_kd:units = "unknown" ; - fates_cnp_pid_kd:long_name = "derivative constant of the PID controller on adaptive fine-root biomass" ; - double fates_cnp_pid_ki(fates_pft) ; - fates_cnp_pid_ki:units = "unknown" ; - fates_cnp_pid_ki:long_name = "integral constant of the PID controller on adaptive fine-root biomass" ; - double fates_cnp_pid_kp(fates_pft) ; - fates_cnp_pid_kp:units = "unknown" ; - fates_cnp_pid_kp:long_name = "proportional constant of the PID controller on adaptive fine-root biomass" ; - double fates_cnp_prescribed_nuptake(fates_pft) ; - fates_cnp_prescribed_nuptake:units = "fraction" ; - fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; - double fates_cnp_prescribed_puptake(fates_pft) ; - fates_cnp_prescribed_puptake:units = "fraction" ; - fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; - double fates_cnp_store_ovrflw_frac(fates_pft) ; - fates_cnp_store_ovrflw_frac:units = "fraction" ; - fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; - double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; - fates_cnp_turnover_nitr_retrans:units = "fraction" ; - fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; - double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; - fates_cnp_turnover_phos_retrans:units = "fraction" ; - fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; - double fates_cnp_vmax_nh4(fates_pft) ; - fates_cnp_vmax_nh4:units = "gN/gC/s" ; - fates_cnp_vmax_nh4:long_name = "maximum (potential) uptake rate of NH4 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_nh4 for usage)" ; - double fates_cnp_vmax_no3(fates_pft) ; - fates_cnp_vmax_no3:units = "gN/gC/s" ; - fates_cnp_vmax_no3:long_name = "maximum (potential) uptake rate of NO3 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_no3 for usage)" ; - double fates_cnp_vmax_p(fates_pft) ; - fates_cnp_vmax_p:units = "gP/gC/s" ; - fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; - double fates_damage_frac(fates_pft) ; - fates_damage_frac:units = "fraction" ; - fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; - double fates_damage_mort_p1(fates_pft) ; - fates_damage_mort_p1:units = "fraction" ; - fates_damage_mort_p1:long_name = "inflection point of damage mortality function, a value of 0.8 means 50% mortality with 80% loss of crown, turn off with a large number" ; - double fates_damage_mort_p2(fates_pft) ; - fates_damage_mort_p2:units = "unitless" ; - fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; - 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_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" ; - double fates_fire_alpha_SH(fates_pft) ; - fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; - fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; - double fates_fire_bark_scaler(fates_pft) ; - fates_fire_bark_scaler:units = "fraction" ; - fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; - double fates_fire_crown_kill(fates_pft) ; - fates_fire_crown_kill:units = "NA" ; - fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; - double fates_frag_fnrt_fcel(fates_pft) ; - fates_frag_fnrt_fcel:units = "fraction" ; - fates_frag_fnrt_fcel:long_name = "Fine root litter cellulose fraction" ; - double fates_frag_fnrt_flab(fates_pft) ; - fates_frag_fnrt_flab:units = "fraction" ; - fates_frag_fnrt_flab:long_name = "Fine root litter labile fraction" ; - double fates_frag_fnrt_flig(fates_pft) ; - fates_frag_fnrt_flig:units = "fraction" ; - fates_frag_fnrt_flig:long_name = "Fine root litter lignin fraction" ; - double fates_frag_leaf_fcel(fates_pft) ; - fates_frag_leaf_fcel:units = "fraction" ; - fates_frag_leaf_fcel:long_name = "Leaf litter cellulose fraction" ; - double fates_frag_leaf_flab(fates_pft) ; - fates_frag_leaf_flab:units = "fraction" ; - fates_frag_leaf_flab:long_name = "Leaf litter labile fraction" ; - double fates_frag_leaf_flig(fates_pft) ; - fates_frag_leaf_flig:units = "fraction" ; - fates_frag_leaf_flig:long_name = "Leaf litter lignin fraction" ; - double fates_frag_seed_decay_rate(fates_pft) ; - fates_frag_seed_decay_rate:units = "yr-1" ; - fates_frag_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; - double fates_grperc(fates_pft) ; - fates_grperc:units = "unitless" ; - fates_grperc:long_name = "Growth respiration factor" ; - double fates_hydro_avuln_gs(fates_pft) ; - fates_hydro_avuln_gs:units = "unitless" ; - fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; - double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; - fates_hydro_avuln_node:units = "unitless" ; - fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; - double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; - fates_hydro_epsil_node:units = "MPa" ; - fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; - double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; - fates_hydro_fcap_node:units = "unitless" ; - fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; - double fates_hydro_k_lwp(fates_pft) ; - fates_hydro_k_lwp:units = "unitless" ; - fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; - double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; - fates_hydro_kmax_node:units = "kg/MPa/m/s" ; - fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; - double fates_hydro_p50_gs(fates_pft) ; - fates_hydro_p50_gs:units = "MPa" ; - fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; - double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; - fates_hydro_p50_node:units = "MPa" ; - fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; - double fates_hydro_p_taper(fates_pft) ; - fates_hydro_p_taper:units = "unitless" ; - fates_hydro_p_taper:long_name = "xylem taper exponent" ; - double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; - fates_hydro_pinot_node:units = "MPa" ; - fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; - double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; - fates_hydro_pitlp_node:units = "MPa" ; - fates_hydro_pitlp_node:long_name = "turgor loss point" ; - double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; - fates_hydro_resid_node:units = "cm3/cm3" ; - fates_hydro_resid_node:long_name = "residual water conent" ; - double fates_hydro_rfrac_stem(fates_pft) ; - fates_hydro_rfrac_stem:units = "fraction" ; - fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; - double fates_hydro_rs2(fates_pft) ; - fates_hydro_rs2:units = "m" ; - fates_hydro_rs2:long_name = "absorbing root radius" ; - double fates_hydro_srl(fates_pft) ; - fates_hydro_srl:units = "m g-1" ; - fates_hydro_srl:long_name = "specific root length" ; - double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; - fates_hydro_thetas_node:units = "cm3/cm3" ; - fates_hydro_thetas_node:long_name = "saturated water content" ; - double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; - fates_hydro_vg_alpha_node:units = "MPa-1" ; - fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; - double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; - fates_hydro_vg_m_node:units = "unitless" ; - fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; - 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_leaf_c3psn(fates_pft) ; - fates_leaf_c3psn:units = "flag" ; - fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; - double fates_leaf_jmaxha(fates_pft) ; - fates_leaf_jmaxha:units = "J/mol" ; - fates_leaf_jmaxha:long_name = "activation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; - double fates_leaf_jmaxhd(fates_pft) ; - fates_leaf_jmaxhd:units = "J/mol" ; - fates_leaf_jmaxhd:long_name = "deactivation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; - double fates_leaf_jmaxse(fates_pft) ; - fates_leaf_jmaxse:units = "J/mol/K" ; - fates_leaf_jmaxse:long_name = "entropy term for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; - double fates_leaf_slamax(fates_pft) ; - fates_leaf_slamax:units = "m^2/gC" ; - fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; - double fates_leaf_slatop(fates_pft) ; - fates_leaf_slatop:units = "m^2/gC" ; - fates_leaf_slatop:long_name = "Specific Leaf Area (SLA) at top of canopy, projected area basis" ; - double fates_leaf_stomatal_intercept(fates_pft) ; - fates_leaf_stomatal_intercept:units = "umol H2O/m**2/s" ; - fates_leaf_stomatal_intercept:long_name = "Minimum unstressed stomatal conductance for Ball-Berry model and Medlyn model" ; - double fates_leaf_stomatal_slope_ballberry(fates_pft) ; - fates_leaf_stomatal_slope_ballberry:units = "unitless" ; - fates_leaf_stomatal_slope_ballberry:long_name = "stomatal slope parameter, as per Ball-Berry" ; - double fates_leaf_stomatal_slope_medlyn(fates_pft) ; - fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; - fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; - double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; - fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; - fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; - double fates_leaf_vcmaxha(fates_pft) ; - fates_leaf_vcmaxha:units = "J/mol" ; - fates_leaf_vcmaxha:long_name = "activation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; - double fates_leaf_vcmaxhd(fates_pft) ; - fates_leaf_vcmaxhd:units = "J/mol" ; - fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; - double fates_leaf_vcmaxse(fates_pft) ; - fates_leaf_vcmaxse:units = "J/mol/K" ; - fates_leaf_vcmaxse:long_name = "entropy term for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; - double fates_maintresp_leaf_atkin2017_baserate(fates_pft) ; - fates_maintresp_leaf_atkin2017_baserate:units = "umol CO2/m^2/s" ; - fates_maintresp_leaf_atkin2017_baserate:long_name = "Leaf maintenance respiration base rate parameter (r0) per Atkin et al 2017" ; - double fates_maintresp_leaf_ryan1991_baserate(fates_pft) ; - fates_maintresp_leaf_ryan1991_baserate:units = "gC/gN/s" ; - fates_maintresp_leaf_ryan1991_baserate:long_name = "Leaf maintenance respiration base rate per Ryan et al 1991" ; - double fates_maintresp_reduction_curvature(fates_pft) ; - fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; - fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; - double fates_maintresp_reduction_intercept(fates_pft) ; - fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; - fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; - double fates_mort_bmort(fates_pft) ; - fates_mort_bmort:units = "1/yr" ; - fates_mort_bmort:long_name = "background mortality rate" ; - double fates_mort_freezetol(fates_pft) ; - fates_mort_freezetol:units = "degrees C" ; - fates_mort_freezetol:long_name = "minimum temperature tolerance" ; - double fates_mort_hf_flc_threshold(fates_pft) ; - fates_mort_hf_flc_threshold:units = "fraction" ; - fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; - double fates_mort_hf_sm_threshold(fates_pft) ; - fates_mort_hf_sm_threshold:units = "unitless" ; - fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; - double fates_mort_ip_age_senescence(fates_pft) ; - fates_mort_ip_age_senescence:units = "years" ; - fates_mort_ip_age_senescence:long_name = "Mortality cohort age senescence inflection point. If _ this mortality term is off. Setting this value turns on age dependent mortality. " ; - double fates_mort_ip_size_senescence(fates_pft) ; - fates_mort_ip_size_senescence:units = "dbh cm" ; - fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; - double fates_mort_prescribed_canopy(fates_pft) ; - fates_mort_prescribed_canopy:units = "1/yr" ; - fates_mort_prescribed_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; - double fates_mort_prescribed_understory(fates_pft) ; - fates_mort_prescribed_understory:units = "1/yr" ; - fates_mort_prescribed_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; - double fates_mort_r_age_senescence(fates_pft) ; - fates_mort_r_age_senescence:units = "mortality rate year^-1" ; - fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; - double fates_mort_r_size_senescence(fates_pft) ; - fates_mort_r_size_senescence:units = "mortality rate dbh^-1" ; - fates_mort_r_size_senescence:long_name = "Mortality dbh senescence rate of change. Sensible range is around 0.03-0.06. Larger values give steeper mortality curves." ; - double fates_mort_scalar_coldstress(fates_pft) ; - fates_mort_scalar_coldstress:units = "1/yr" ; - fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; - double fates_mort_scalar_cstarvation(fates_pft) ; - fates_mort_scalar_cstarvation:units = "1/yr" ; - fates_mort_scalar_cstarvation:long_name = "maximum mortality rate from carbon starvation" ; - double fates_mort_scalar_hydrfailure(fates_pft) ; - fates_mort_scalar_hydrfailure:units = "1/yr" ; - fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; - double fates_nonhydro_smpsc(fates_pft) ; - fates_nonhydro_smpsc:units = "mm" ; - fates_nonhydro_smpsc:long_name = "Soil water potential at full stomatal closure" ; - double fates_nonhydro_smpso(fates_pft) ; - fates_nonhydro_smpso:units = "mm" ; - fates_nonhydro_smpso:long_name = "Soil water potential at full stomatal opening" ; - double fates_phen_cold_size_threshold(fates_pft) ; - fates_phen_cold_size_threshold:units = "cm" ; - fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; - double fates_phen_evergreen(fates_pft) ; - fates_phen_evergreen:units = "logical flag" ; - fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; - double fates_phen_flush_fraction(fates_pft) ; - fates_phen_flush_fraction:units = "fraction" ; - fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; - double fates_phen_fnrt_drop_frac(fates_pft) ; - fates_phen_fnrt_drop_frac:units = "fraction" ; - fates_phen_fnrt_drop_frac:long_name = "fraction of fine roots to drop during drought or cold" ; - double fates_phen_season_decid(fates_pft) ; - fates_phen_season_decid:units = "logical flag" ; - fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; - double fates_phen_stem_drop_fraction(fates_pft) ; - fates_phen_stem_drop_fraction:units = "fraction" ; - fates_phen_stem_drop_fraction:long_name = "fraction of stems to drop for non-woody species during drought/cold" ; - double fates_phen_stress_decid(fates_pft) ; - fates_phen_stress_decid:units = "logical flag" ; - fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; - double fates_prescribed_npp_canopy(fates_pft) ; - fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; - fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; - double fates_prescribed_npp_understory(fates_pft) ; - fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; - fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; - double fates_rad_leaf_clumping_index(fates_pft) ; - fates_rad_leaf_clumping_index:units = "fraction (0-1)" ; - fates_rad_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; - double fates_rad_leaf_rhonir(fates_pft) ; - fates_rad_leaf_rhonir:units = "fraction" ; - fates_rad_leaf_rhonir:long_name = "Leaf reflectance: near-IR" ; - double fates_rad_leaf_rhovis(fates_pft) ; - fates_rad_leaf_rhovis:units = "fraction" ; - fates_rad_leaf_rhovis:long_name = "Leaf reflectance: visible" ; - double fates_rad_leaf_taunir(fates_pft) ; - fates_rad_leaf_taunir:units = "fraction" ; - fates_rad_leaf_taunir:long_name = "Leaf transmittance: near-IR" ; - double fates_rad_leaf_tauvis(fates_pft) ; - fates_rad_leaf_tauvis:units = "fraction" ; - fates_rad_leaf_tauvis:long_name = "Leaf transmittance: visible" ; - double fates_rad_leaf_xl(fates_pft) ; - fates_rad_leaf_xl:units = "unitless" ; - fates_rad_leaf_xl:long_name = "Leaf/stem orientation index" ; - double fates_rad_stem_rhonir(fates_pft) ; - fates_rad_stem_rhonir:units = "fraction" ; - fates_rad_stem_rhonir:long_name = "Stem reflectance: near-IR" ; - double fates_rad_stem_rhovis(fates_pft) ; - fates_rad_stem_rhovis:units = "fraction" ; - fates_rad_stem_rhovis:long_name = "Stem reflectance: visible" ; - double fates_rad_stem_taunir(fates_pft) ; - fates_rad_stem_taunir:units = "fraction" ; - fates_rad_stem_taunir:long_name = "Stem transmittance: near-IR" ; - double fates_rad_stem_tauvis(fates_pft) ; - fates_rad_stem_tauvis:units = "fraction" ; - fates_rad_stem_tauvis:long_name = "Stem transmittance: visible" ; - double fates_recruit_height_min(fates_pft) ; - fates_recruit_height_min:units = "m" ; - fates_recruit_height_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; - double fates_recruit_init_density(fates_pft) ; - fates_recruit_init_density:units = "stems/m2" ; - fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation. If negative sets initial tree dbh - only to be used in nocomp mode" ; - double fates_recruit_prescribed_rate(fates_pft) ; - fates_recruit_prescribed_rate:units = "n/yr" ; - fates_recruit_prescribed_rate:long_name = "recruitment rate for prescribed physiology mode" ; - double fates_recruit_seed_alloc(fates_pft) ; - fates_recruit_seed_alloc:units = "fraction" ; - fates_recruit_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; - double fates_recruit_seed_alloc_mature(fates_pft) ; - fates_recruit_seed_alloc_mature:units = "fraction" ; - fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; - double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; - fates_recruit_seed_dbh_repro_threshold:units = "cm" ; - fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter where the plant will increase allocation to the seed pool by fraction: fates_recruit_seed_alloc_mature" ; - double fates_recruit_seed_germination_rate(fates_pft) ; - fates_recruit_seed_germination_rate:units = "yr-1" ; - fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; - double fates_recruit_seed_supplement(fates_pft) ; - fates_recruit_seed_supplement:units = "KgC/m2/yr" ; - fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; - double fates_stoich_nitr(fates_plant_organs, fates_pft) ; - fates_stoich_nitr:units = "gN/gC" ; - fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; - double fates_stoich_phos(fates_plant_organs, fates_pft) ; - fates_stoich_phos:units = "gP/gC" ; - fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; - double fates_trim_inc(fates_pft) ; - fates_trim_inc:units = "m2/m2" ; - fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; - double fates_trim_limit(fates_pft) ; - fates_trim_limit:units = "m2/m2" ; - fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; - double fates_turb_displar(fates_pft) ; - fates_turb_displar:units = "unitless" ; - fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; - double fates_turb_leaf_diameter(fates_pft) ; - fates_turb_leaf_diameter:units = "m" ; - fates_turb_leaf_diameter:long_name = "Characteristic leaf dimension" ; - double fates_turb_z0mr(fates_pft) ; - fates_turb_z0mr:units = "unitless" ; - fates_turb_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; - double fates_turnover_branch(fates_pft) ; - fates_turnover_branch:units = "yr" ; - fates_turnover_branch:long_name = "turnover time of branches" ; - double fates_turnover_fnrt(fates_pft) ; - fates_turnover_fnrt:units = "yr" ; - fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; - double fates_turnover_leaf(fates_leafage_class, fates_pft) ; - fates_turnover_leaf:units = "yr" ; - fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale)" ; - double fates_turnover_senleaf_fdrought(fates_pft) ; - fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; - fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; - double fates_wood_density(fates_pft) ; - fates_wood_density:units = "g/cm3" ; - fates_wood_density:long_name = "mean density of woody tissue in plant" ; - double fates_woody(fates_pft) ; - fates_woody:units = "logical flag" ; - fates_woody:long_name = "Binary woody lifeform flag" ; - double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; - fates_hlm_pft_map:units = "area fraction" ; - fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; - double fates_fire_FBD(fates_litterclass) ; - fates_fire_FBD:units = "kg Biomass/m3" ; - fates_fire_FBD:long_name = "fuel bulk density" ; - double fates_fire_low_moisture_Coeff(fates_litterclass) ; - fates_fire_low_moisture_Coeff:units = "NA" ; - fates_fire_low_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_low_moisture_Slope(fates_litterclass) ; - fates_fire_low_moisture_Slope:units = "NA" ; - fates_fire_low_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_mid_moisture(fates_litterclass) ; - fates_fire_mid_moisture:units = "NA" ; - fates_fire_mid_moisture:long_name = "spitfire litter moisture threshold to be considered medium dry" ; - double fates_fire_mid_moisture_Coeff(fates_litterclass) ; - fates_fire_mid_moisture_Coeff:units = "NA" ; - fates_fire_mid_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_mid_moisture_Slope(fates_litterclass) ; - fates_fire_mid_moisture_Slope:units = "NA" ; - fates_fire_mid_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_min_moisture(fates_litterclass) ; - fates_fire_min_moisture:units = "NA" ; - fates_fire_min_moisture:long_name = "spitfire litter moisture threshold to be considered very dry" ; - double fates_fire_SAV(fates_litterclass) ; - fates_fire_SAV:units = "cm-1" ; - fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; - double fates_frag_maxdecomp(fates_litterclass) ; - fates_frag_maxdecomp:units = "yr-1" ; - fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; - 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_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" ; - double fates_cnp_eca_plant_escalar ; - fates_cnp_eca_plant_escalar:units = "" ; - fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; - double fates_cohort_age_fusion_tol ; - fates_cohort_age_fusion_tol:units = "unitless" ; - fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; - double fates_cohort_size_fusion_tol ; - fates_cohort_size_fusion_tol:units = "unitless" ; - fates_cohort_size_fusion_tol:long_name = "minimum fraction in difference in dbh between cohorts" ; - double fates_comp_excln ; - fates_comp_excln:units = "none" ; - fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; - double fates_damage_canopy_layer_code ; - fates_damage_canopy_layer_code:units = "unitless" ; - fates_damage_canopy_layer_code:long_name = "Integer code that decides whether damage affects canopy trees (1), understory trees (2)" ; - double fates_damage_event_code ; - fates_damage_event_code:units = "unitless" ; - fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; - double fates_dev_arbitrary ; - fates_dev_arbitrary:units = "unknown" ; - fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; - double fates_fire_active_crown_fire ; - fates_fire_active_crown_fire:units = "0 or 1" ; - fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; - double fates_fire_cg_strikes ; - fates_fire_cg_strikes:units = "fraction (0-1)" ; - fates_fire_cg_strikes:long_name = "fraction of cloud to ground lightning strikes" ; - double fates_fire_drying_ratio ; - fates_fire_drying_ratio:units = "NA" ; - fates_fire_drying_ratio:long_name = "spitfire parameter, fire drying ratio for fuel moisture, alpha_FMC EQ 6 Thonicke et al 2010" ; - double fates_fire_durat_slope ; - fates_fire_durat_slope:units = "NA" ; - fates_fire_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; - double fates_fire_fdi_a ; - fates_fire_fdi_a:units = "NA" ; - fates_fire_fdi_a:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010" ; - double fates_fire_fdi_alpha ; - fates_fire_fdi_alpha:units = "NA" ; - fates_fire_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; - double fates_fire_fdi_b ; - fates_fire_fdi_b:units = "NA" ; - fates_fire_fdi_b:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010 " ; - double fates_fire_fuel_energy ; - fates_fire_fuel_energy:units = "kJ/kg" ; - fates_fire_fuel_energy:long_name = "spitfire parameter, heat content of fuel" ; - double fates_fire_max_durat ; - fates_fire_max_durat:units = "minutes" ; - fates_fire_max_durat:long_name = "spitfire parameter, fire maximum duration, Equation 14 Thonicke et al 2010" ; - double fates_fire_miner_damp ; - fates_fire_miner_damp:units = "NA" ; - fates_fire_miner_damp:long_name = "spitfire parameter, mineral-dampening coefficient EQ A1 Thonicke et al 2010 " ; - double fates_fire_miner_total ; - fates_fire_miner_total:units = "fraction" ; - fates_fire_miner_total:long_name = "spitfire parameter, total mineral content, Table A1 Thonicke et al 2010" ; - double fates_fire_nignitions ; - fates_fire_nignitions:units = "ignitions per year per km2" ; - fates_fire_nignitions:long_name = "number of annual ignitions per square km" ; - double fates_fire_part_dens ; - fates_fire_part_dens:units = "kg/m2" ; - fates_fire_part_dens:long_name = "spitfire parameter, oven dry particle density, Table A1 Thonicke et al 2010" ; - double fates_fire_threshold ; - fates_fire_threshold:units = "kW/m" ; - fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; - double fates_frag_cwd_fcel ; - fates_frag_cwd_fcel:units = "unitless" ; - fates_frag_cwd_fcel:long_name = "Cellulose fraction for CWD" ; - double fates_frag_cwd_flig ; - fates_frag_cwd_flig:units = "unitless" ; - fates_frag_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; - double fates_hydro_kmax_rsurf1 ; - fates_hydro_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; - fates_hydro_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; - double fates_hydro_kmax_rsurf2 ; - fates_hydro_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; - fates_hydro_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; - double fates_hydro_psi0 ; - fates_hydro_psi0:units = "MPa" ; - fates_hydro_psi0:long_name = "sapwood water potential at saturation" ; - double fates_hydro_psicap ; - fates_hydro_psicap:units = "MPa" ; - fates_hydro_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; - 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_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" ; - double fates_landuse_logging_collateral_frac ; - fates_landuse_logging_collateral_frac:units = "fraction" ; - fates_landuse_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; - double fates_landuse_logging_dbhmax ; - fates_landuse_logging_dbhmax:units = "cm" ; - fates_landuse_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; - double fates_landuse_logging_dbhmax_infra ; - fates_landuse_logging_dbhmax_infra:units = "cm" ; - fates_landuse_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; - double fates_landuse_logging_dbhmin ; - fates_landuse_logging_dbhmin:units = "cm" ; - fates_landuse_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; - double fates_landuse_logging_direct_frac ; - fates_landuse_logging_direct_frac:units = "fraction" ; - fates_landuse_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; - double fates_landuse_logging_event_code ; - fates_landuse_logging_event_code:units = "unitless" ; - fates_landuse_logging_event_code:long_name = "Integer code that options how logging events are structured" ; - double fates_landuse_logging_export_frac ; - fates_landuse_logging_export_frac:units = "fraction" ; - fates_landuse_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; - double fates_landuse_logging_mechanical_frac ; - fates_landuse_logging_mechanical_frac:units = "fraction" ; - fates_landuse_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; - double fates_landuse_pprodharv10_forest_mean ; - fates_landuse_pprodharv10_forest_mean:units = "fraction" ; - fates_landuse_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; - double fates_leaf_photo_temp_acclim_thome_time ; - fates_leaf_photo_temp_acclim_thome_time:units = "years" ; - fates_leaf_photo_temp_acclim_thome_time:long_name = "Length of the window for the long-term (i.e. T_home in Kumarathunge et al 2019) exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_leaf_photo_tempsens_model = 2)" ; - double fates_leaf_photo_temp_acclim_timescale ; - fates_leaf_photo_temp_acclim_timescale:units = "days" ; - fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_maintresp_leaf_model=2 or fates_leaf_photo_tempsens_model = 2)" ; - double fates_leaf_photo_tempsens_model ; - fates_leaf_photo_tempsens_model:units = "unitless" ; - fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating; 2=Kumarathunge et al 2019" ; - double fates_leaf_stomatal_assim_model ; - fates_leaf_stomatal_assim_model:units = "unitless" ; - fates_leaf_stomatal_assim_model:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; - double fates_leaf_stomatal_model ; - fates_leaf_stomatal_model:units = "unitless" ; - fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; - double fates_leaf_theta_cj_c3 ; - fates_leaf_theta_cj_c3:units = "unitless" ; - fates_leaf_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; - double fates_leaf_theta_cj_c4 ; - fates_leaf_theta_cj_c4:units = "unitless" ; - fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; - double fates_maintresp_leaf_model ; - fates_maintresp_leaf_model:units = "unitless" ; - fates_maintresp_leaf_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991), 2=Atkin et al., (2017)" ; - double fates_maintresp_nonleaf_baserate ; - fates_maintresp_nonleaf_baserate:units = "gC/gN/s" ; - fates_maintresp_nonleaf_baserate:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; - double fates_maxcohort ; - fates_maxcohort:units = "count" ; - fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; - double fates_maxpatch_primary ; - fates_maxpatch_primary:units = "count" ; - fates_maxpatch_primary:long_name = "maximum number of primary vegetation patches per site" ; - double fates_maxpatch_secondary ; - fates_maxpatch_secondary:units = "count" ; - fates_maxpatch_secondary:long_name = "maximum number of secondary vegetation patches per site" ; - double fates_mort_disturb_frac ; - fates_mort_disturb_frac:units = "fraction" ; - fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; - double fates_mort_understorey_death ; - fates_mort_understorey_death:units = "fraction" ; - fates_mort_understorey_death:long_name = "fraction of plants in understorey cohort impacted by overstorey tree-fall" ; - double fates_patch_fusion_tol ; - fates_patch_fusion_tol:units = "unitless" ; - fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; - double fates_phen_chilltemp ; - fates_phen_chilltemp:units = "degrees C" ; - fates_phen_chilltemp:long_name = "chilling day counting threshold for vegetation" ; - double fates_phen_coldtemp ; - fates_phen_coldtemp:units = "degrees C" ; - fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; - double fates_phen_drought_model ; - fates_phen_drought_model:units = "unitless" ; - fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; - double fates_phen_drought_threshold ; - fates_phen_drought_threshold:units = "m3/m3 or mm" ; - fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; - double fates_phen_gddthresh_a ; - fates_phen_gddthresh_a:units = "none" ; - fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_gddthresh_b ; - fates_phen_gddthresh_b:units = "none" ; - fates_phen_gddthresh_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_gddthresh_c ; - fates_phen_gddthresh_c:units = "none" ; - fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_mindaysoff ; - fates_phen_mindaysoff:units = "days" ; - fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves became off-allometry" ; - double fates_phen_mindayson ; - fates_phen_mindayson:units = "days" ; - fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; - double fates_phen_moist_threshold ; - fates_phen_moist_threshold:units = "m3/m3 or mm" ; - fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; - double fates_phen_ncolddayslim ; - fates_phen_ncolddayslim:units = "days" ; - fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; - double fates_q10_froz ; - fates_q10_froz:units = "unitless" ; - fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; - double fates_q10_mr ; - fates_q10_mr:units = "unitless" ; - fates_q10_mr:long_name = "Q10 for maintenance respiration" ; - double fates_soil_salinity ; - fates_soil_salinity:units = "ppt" ; - fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; - double fates_vai_top_bin_width ; - fates_vai_top_bin_width:units = "m2/m2" ; - fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; - double fates_vai_width_increase_factor ; - fates_vai_width_increase_factor:units = "unitless" ; - fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; - -// global attributes: - :history = "This file was generated by BatchPatchParams.py:\nCDL Base File = archive/api24.1.0_101722_fates_params_default.cdl\nXML patch file = archive/api24.1.0_101722_patch_params.xml" ; -data: - - fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; - - fates_history_coageclass_bin_edges = 0, 5 ; - - fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; - - fates_history_damage_bin_edges = 0, 80 ; - - fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, - 80, 90, 100 ; - - fates_alloc_organ_id = 1, 2, 3, 6 ; - - fates_hydro_htftype_node = 1, 1, 1, 1 ; - - fates_pftname = - "broadleaf_evergreen_tropical_tree ", - "needleleaf_evergreen_extratrop_tree ", - "needleleaf_colddecid_extratrop_tree ", - "broadleaf_evergreen_extratrop_tree ", - "broadleaf_hydrodecid_tropical_tree ", - "broadleaf_colddecid_extratrop_tree ", - "broadleaf_evergreen_extratrop_shrub ", - "broadleaf_hydrodecid_extratrop_shrub ", - "broadleaf_colddecid_extratrop_shrub ", - "arctic_c3_grass ", - "cool_c3_grass ", - "c4_grass " ; - - fates_hydro_organ_name = - "leaf ", - "stem ", - "transporting root ", - "absorbing root " ; - - fates_alloc_organ_name = - "leaf", - "fine root", - "sapwood", - "structure" ; - - fates_litterclass_name = - "twig ", - "small branch ", - "large branch ", - "trunk ", - "dead leaves ", - "live grass " ; - - 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, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; - - fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, - 1.2, 1.2, 1.2 ; - - fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, - 0.8, 0.8, 0.8, 0.8 ; - - fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, - 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; - - fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, - 0.572, 0.572, 0.572, 0.572 ; - - fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, - 1.94, 1.94, 1.94 ; - - fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, - 0.931, 0.931, 0.931, 0.931 ; - - fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6 ; - - fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, - 0.95, 1, 1, 1 ; - - fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, - 0.07, 0.07, 0.07 ; - - fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, - 1.3 ; - - fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, - 0.55, 0.55, 0.55 ; - - fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464 ; - - fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119 ; - - fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, - 0.64, 0.64, 0.64 ; - - fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, - 0.37, 0.37, 0.37 ; - - fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, - -999.9, -999.9, -999.9, -999.9, -999.9 ; - - fates_allom_dbh_maxheight = 90, 80, 80, 80, 90, 80, 3, 3, 2, 0.35, 0.35, 0.35 ; - - fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; - - fates_allom_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; - - fates_allom_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - - fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, - 0.8, 0.8, 0.8 ; - - fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1, 0.1 ; - - fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_zroot_k = 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 ; - - fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; - - fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100 ; - - fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1 ; - - fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100 ; - - fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; - - fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5 ; - - fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, - 280, 280 ; - - fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, - 0.14, 0.14, 0.14 ; - - fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, - 0.27, 0.27, 0.27 ; - - fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1 ; - - fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, - 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - - fates_cnp_nfix1 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5, 1.5 ; - - fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5, 1.5 ; - - fates_cnp_pid_kd = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; - - fates_cnp_pid_ki = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_pid_kp = 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005 ; - - fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_turnover_nitr_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_turnover_phos_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_vmax_nh4 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, - 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; - - fates_cnp_vmax_no3 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, - 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; - - fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, - 5e-10, 5e-10, 5e-10, 5e-10 ; - - fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, - 0.01, 0.01, 0.01 ; - - fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; - - fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, - 5.5, 5.5 ; - - fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, - 0.2 ; - - fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, - 0.07, 0.07, 0.07, 0.07 ; - - fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, - 0.775, 0.775, 0.775, 0.775, 0.775 ; - - fates_frag_fnrt_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5 ; - - fates_frag_fnrt_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; - - fates_frag_fnrt_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; - - fates_frag_leaf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5 ; - - fates_frag_leaf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; - - fates_frag_leaf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; - - fates_frag_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, - 0.51, 0.51, 0.51, 0.51 ; - - fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, - 0.11, 0.11 ; - - fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, - 2.5, 2.5 ; - - fates_hydro_avuln_node = - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 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_hydro_epsil_node = - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - - fates_hydro_fcap_node = - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, - 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_hydro_kmax_node = - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; - - fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, - -1.5, -1.5, -1.5 ; - - fates_hydro_p50_node = - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25 ; - - fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, - 0.333, 0.333, 0.333, 0.333, 0.333 ; - - fates_hydro_pinot_node = - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; - - fates_hydro_pitlp_node = - -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, - -1.67, -1.67, - -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, - -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, - -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; - - fates_hydro_resid_node = - 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, - 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - - fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, - 0.625, 0.625, 0.625, 0.625, 0.625 ; - - fates_hydro_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, - 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; - - fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; - - fates_hydro_thetas_node = - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; - - fates_hydro_vg_alpha_node = - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005 ; - - fates_hydro_vg_m_node = - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_hydro_vg_n_node = - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 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_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, - 43540, 43540, 43540, 43540 ; - - fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, - 152040, 152040, 152040, 152040, 152040 ; - - fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, - 495 ; - - fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, - 0.03, 0.03, 0.03, 0.03, 0.03 ; - - fates_leaf_slatop = 0.012, 0.005, 0.024, 0.009, 0.03, 0.03, 0.012, 0.03, - 0.03, 0.03, 0.03, 0.03 ; - - fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, - 10000, 10000, 10000, 10000, 10000, 40000 ; - - fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - - fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, - 4.7, 2.2, 5.3, 1.6 ; - - fates_leaf_vcmax25top = - 50, 62, 39, 61, 41, 58, 62, 54, 54, 78, 78, 78 ; - - fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, - 65330, 65330, 65330, 65330 ; - - fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, - 149250, 149250, 149250, 149250, 149250 ; - - fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, - 485 ; - - fates_maintresp_leaf_atkin2017_baserate = 1.756, 1.4995, 1.4995, 1.756, - 1.756, 1.756, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956, 2.1956 ; - - fates_maintresp_leaf_ryan1991_baserate = 2.525e-06, 2.525e-06, 2.525e-06, - 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, - 2.525e-06, 2.525e-06, 2.525e-06 ; - - fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, - 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; - - fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, - 0.014, 0.014, 0.014, 0.014 ; - - fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -80, -60, -10, -80, -80, - -20, 2.5 ; - - fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5 ; - - fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, - 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; - - fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_prescribed_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, - 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; - - fates_mort_prescribed_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, - 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; - - fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - - fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6, 0.6 ; - - fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6, 0.6 ; - - fates_nonhydro_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, - -255000, -255000, -255000, -255000, -255000, -255000 ; - - fates_nonhydro_smpso = -66000, -66000, -66000, -66000, -66000, -66000, - -66000, -66000, -66000, -66000, -66000, -66000 ; - - fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; - - fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, - 0.5 ; - - fates_phen_fnrt_drop_frac = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; - - fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; - - fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, - 0.4, 0.4, 0.4 ; - - fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, - 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; - - fates_rad_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, - 0.9, 0.75, 0.75, 0.75 ; - - fates_rad_leaf_rhonir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, - 0.41, 0.28, 0.28, 0.28 ; - - fates_rad_leaf_rhovis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, - 0.08, 0.05, 0.05, 0.05 ; - - fates_rad_leaf_taunir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, - 0.43, 0.4, 0.4, 0.4 ; - - fates_rad_leaf_tauvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, - 0.06, 0.05, 0.05, 0.05 ; - - fates_rad_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, - -0.23, -0.23, -0.23 ; - - fates_rad_stem_rhonir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, - 0.49, 0.53, 0.53, 0.53 ; - - fates_rad_stem_rhovis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.21, 0.31, 0.31, 0.31 ; - - fates_rad_stem_taunir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, - 0.001, 0.001, 0.25, 0.25, 0.25 ; - - fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, - 0.001, 0.001, 0.12, 0.12, 0.12 ; - - fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.2, 0.2, 0.2, - 0.125, 0.125, 0.125 ; - - fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, - 0.2, 0.2, 0.2 ; - - fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, - 0.02, 0.02, 0.02, 0.02, 0.02 ; - - fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1, 0.1 ; - - fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, - 0.9 ; - - fates_recruit_seed_dbh_repro_threshold = 90, 80, 80, 80, 90, 80, 3, 3, 2, - 0.35, 0.35, 0.35 ; - - fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_stoich_nitr = - 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, - 0.0047, 0.0047, 0.0047 ; - - fates_stoich_phos = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, - 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, - 0.00047, 0.00047, 0.00047, 0.00047 ; - - fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, - 0.03, 0.03 ; - - fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; - - fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, - 0.67, 0.67, 0.67 ; - - fates_turb_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.04, 0.04, 0.04, 0.04 ; - - fates_turb_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, - 0.055, 0.055, 0.055, 0.055 ; - - fates_turnover_branch = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; - - fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - - fates_turnover_leaf = - 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - - fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_wood_density = 0.7, 0.4, 0.7, 0.53, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, - 0.7 ; - - fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; - - fates_hlm_pft_map = - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; - - fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; - - fates_fire_low_moisture_Coeff = 1.12, 1.09, 0.98, 0.8, 1.15, 1.15 ; - - fates_fire_low_moisture_Slope = 0.62, 0.72, 0.85, 0.8, 0.62, 0.62 ; - - fates_fire_mid_moisture = 0.72, 0.51, 0.38, 1, 0.8, 0.8 ; - - fates_fire_mid_moisture_Coeff = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; - - fates_fire_mid_moisture_Slope = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; - - fates_fire_min_moisture = 0.18, 0.12, 0, 0, 0.24, 0.24 ; - - fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; - - fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; - - fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; - - fates_canopy_closure_thresh = 0.8 ; - - fates_cnp_eca_plant_escalar = 1.25e-05 ; - - fates_cohort_age_fusion_tol = 0.08 ; - - fates_cohort_size_fusion_tol = 0.08 ; - - fates_comp_excln = 3 ; - - fates_damage_canopy_layer_code = 1 ; - - fates_damage_event_code = 1 ; - - fates_dev_arbitrary = _ ; - - fates_fire_active_crown_fire = 0 ; - - fates_fire_cg_strikes = 0.2 ; - - fates_fire_drying_ratio = 66000 ; - - fates_fire_durat_slope = -11.06 ; - - fates_fire_fdi_a = 17.62 ; - - fates_fire_fdi_alpha = 0.00037 ; - - fates_fire_fdi_b = 243.12 ; - - fates_fire_fuel_energy = 18000 ; - - fates_fire_max_durat = 240 ; - - fates_fire_miner_damp = 0.41739 ; - - fates_fire_miner_total = 0.055 ; - - fates_fire_nignitions = 15 ; - - fates_fire_part_dens = 513 ; - - fates_fire_threshold = 50 ; - - fates_frag_cwd_fcel = 0.76 ; - - fates_frag_cwd_flig = 0.24 ; - - fates_hydro_kmax_rsurf1 = 20 ; - - fates_hydro_kmax_rsurf2 = 0.0001 ; - - fates_hydro_psi0 = 0 ; - - fates_hydro_psicap = -0.6 ; - - fates_hydro_solver = 1 ; - - fates_landuse_logging_coll_under_frac = 0.55983 ; - - fates_landuse_logging_collateral_frac = 0.05 ; - - fates_landuse_logging_dbhmax = _ ; - - fates_landuse_logging_dbhmax_infra = 35 ; - - fates_landuse_logging_dbhmin = 50 ; - - fates_landuse_logging_direct_frac = 0.15 ; - - fates_landuse_logging_event_code = -30 ; - - fates_landuse_logging_export_frac = 0.8 ; - - fates_landuse_logging_mechanical_frac = 0.05 ; - - fates_landuse_pprodharv10_forest_mean = 0.8125 ; - - fates_leaf_photo_temp_acclim_thome_time = 30 ; - - fates_leaf_photo_temp_acclim_timescale = 30 ; - - fates_leaf_photo_tempsens_model = 1 ; - - fates_leaf_stomatal_assim_model = 1 ; - - fates_leaf_stomatal_model = 1 ; - - fates_leaf_theta_cj_c3 = 0.999 ; - - fates_leaf_theta_cj_c4 = 0.999 ; - - fates_maintresp_leaf_model = 1 ; - - fates_maintresp_nonleaf_baserate = 2.525e-06 ; - - fates_maxcohort = 100 ; - - fates_maxpatch_primary = 10 ; - - fates_maxpatch_secondary = 4 ; - - fates_mort_disturb_frac = 1 ; - - fates_mort_understorey_death = 0.55983 ; - - fates_patch_fusion_tol = 0.05 ; - - fates_phen_chilltemp = 5 ; - - fates_phen_coldtemp = 7.5 ; - - fates_phen_drought_model = 0 ; - - fates_phen_drought_threshold = 0.15 ; - - fates_phen_gddthresh_a = -68 ; - - fates_phen_gddthresh_b = 638 ; - - fates_phen_gddthresh_c = -0.01 ; - - fates_phen_mindaysoff = 100 ; - - fates_phen_mindayson = 90 ; - - fates_phen_moist_threshold = 0.18 ; - - fates_phen_ncolddayslim = 5 ; - - fates_q10_froz = 1.5 ; - - fates_q10_mr = 1.5 ; - - fates_soil_salinity = 0.4 ; - - fates_vai_top_bin_width = 1 ; - - fates_vai_width_increase_factor = 1 ; -} diff --git a/parameter_files/archive/api25.4.0_032323_pr1005.xml b/parameter_files/archive/api25.5.0_072423_pr1005.xml similarity index 96% rename from parameter_files/archive/api25.4.0_032323_pr1005.xml rename to parameter_files/archive/api25.5.0_072423_pr1005.xml index 46c3c778c7..57a436e580 100644 --- a/parameter_files/archive/api25.4.0_032323_pr1005.xml +++ b/parameter_files/archive/api25.5.0_072423_pr1005.xml @@ -12,7 +12,7 @@ - + @@ -27,7 +27,7 @@ the variables --> - archive/api25.4.0_032323_fates_params_default.cdl + archive/api25.4.0_041023_fates_params_default.cdl fates_params_default.cdl 1,2,3,4,5,6,7,8,9,10,11,12 From f08b81f14deb6b4db71abd408f6a3a7596ee7ce7 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 24 Jul 2023 16:06:34 -0700 Subject: [PATCH 787/852] add api25.5 param file to archive --- .../api25.5.0_072423_fates_params_default.cdl | 1735 +++++++++++++++++ 1 file changed, 1735 insertions(+) create mode 100644 parameter_files/archive/api25.5.0_072423_fates_params_default.cdl diff --git a/parameter_files/archive/api25.5.0_072423_fates_params_default.cdl b/parameter_files/archive/api25.5.0_072423_fates_params_default.cdl new file mode 100644 index 0000000000..f170fe2275 --- /dev/null +++ b/parameter_files/archive/api25.5.0_072423_fates_params_default.cdl @@ -0,0 +1,1735 @@ +netcdf fates_params_default { +dimensions: + fates_NCWD = 4 ; + fates_history_age_bins = 7 ; + fates_history_coage_bins = 2 ; + fates_history_damage_bins = 2 ; + fates_history_height_bins = 6 ; + fates_history_size_bins = 13 ; + fates_hlm_pftno = 14 ; + fates_hydr_organs = 4 ; + fates_leafage_class = 1 ; + fates_litterclass = 6 ; + fates_pft = 12 ; + fates_plant_organs = 4 ; + fates_string_length = 60 ; +variables: + double fates_history_ageclass_bin_edges(fates_history_age_bins) ; + fates_history_ageclass_bin_edges:units = "yr" ; + fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; + double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; + fates_history_coageclass_bin_edges:units = "years" ; + fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; + double fates_history_height_bin_edges(fates_history_height_bins) ; + fates_history_height_bin_edges:units = "m" ; + fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; + double fates_history_damage_bin_edges(fates_history_damage_bins) ; + fates_history_damage_bin_edges:units = "% crown loss" ; + fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; + double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; + fates_history_sizeclass_bin_edges:units = "cm" ; + fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; + double fates_alloc_organ_id(fates_plant_organs) ; + fates_alloc_organ_id:units = "unitless" ; + fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; + double fates_hydro_htftype_node(fates_hydr_organs) ; + fates_hydro_htftype_node:units = "unitless" ; + fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; + char fates_pftname(fates_pft, fates_string_length) ; + fates_pftname:units = "unitless - string" ; + fates_pftname:long_name = "Description of plant type" ; + char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; + fates_hydro_organ_name:units = "unitless - string" ; + fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; + char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; + fates_alloc_organ_name:units = "unitless - string" ; + fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; + 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" ; + 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" ; + double fates_alloc_storage_cushion(fates_pft) ; + fates_alloc_storage_cushion:units = "fraction" ; + fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; + double fates_alloc_store_priority_frac(fates_pft) ; + fates_alloc_store_priority_frac:units = "unitless" ; + fates_alloc_store_priority_frac:long_name = "for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage" ; + double fates_allom_agb1(fates_pft) ; + fates_allom_agb1:units = "variable" ; + fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; + double fates_allom_agb2(fates_pft) ; + fates_allom_agb2:units = "variable" ; + fates_allom_agb2:long_name = "Parameter 2 for agb allometry" ; + double fates_allom_agb3(fates_pft) ; + fates_allom_agb3:units = "variable" ; + fates_allom_agb3:long_name = "Parameter 3 for agb allometry" ; + double fates_allom_agb4(fates_pft) ; + fates_allom_agb4:units = "variable" ; + fates_allom_agb4:long_name = "Parameter 4 for agb allometry" ; + double fates_allom_agb_frac(fates_pft) ; + fates_allom_agb_frac:units = "fraction" ; + fates_allom_agb_frac:long_name = "Fraction of woody biomass that is above ground" ; + double fates_allom_amode(fates_pft) ; + fates_allom_amode:units = "index" ; + fates_allom_amode:long_name = "AGB allometry function index." ; + double fates_allom_blca_expnt_diff(fates_pft) ; + fates_allom_blca_expnt_diff:units = "unitless" ; + fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; + double fates_allom_cmode(fates_pft) ; + fates_allom_cmode:units = "index" ; + fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; + double fates_allom_crown_depth_frac(fates_pft) ; + fates_allom_crown_depth_frac:units = "fraction" ; + fates_allom_crown_depth_frac:long_name = "the depth of a cohort crown as a fraction of its height" ; + double fates_allom_d2bl1(fates_pft) ; + fates_allom_d2bl1:units = "variable" ; + fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; + double fates_allom_d2bl2(fates_pft) ; + fates_allom_d2bl2:units = "variable" ; + fates_allom_d2bl2:long_name = "Parameter 2 for d2bl allometry" ; + double fates_allom_d2bl3(fates_pft) ; + fates_allom_d2bl3:units = "unitless" ; + fates_allom_d2bl3:long_name = "Parameter 3 for d2bl allometry" ; + double fates_allom_d2ca_coefficient_max(fates_pft) ; + fates_allom_d2ca_coefficient_max:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_max:long_name = "max (savanna) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2ca_coefficient_min(fates_pft) ; + fates_allom_d2ca_coefficient_min:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_min:long_name = "min (forest) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2h1(fates_pft) ; + fates_allom_d2h1:units = "variable" ; + fates_allom_d2h1:long_name = "Parameter 1 for d2h allometry (intercept, or c)" ; + double fates_allom_d2h2(fates_pft) ; + fates_allom_d2h2:units = "variable" ; + fates_allom_d2h2:long_name = "Parameter 2 for d2h allometry (slope, or m)" ; + double fates_allom_d2h3(fates_pft) ; + fates_allom_d2h3:units = "variable" ; + fates_allom_d2h3:long_name = "Parameter 3 for d2h allometry (optional)" ; + double fates_allom_dbh_maxheight(fates_pft) ; + fates_allom_dbh_maxheight:units = "cm" ; + fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; + double fates_allom_fmode(fates_pft) ; + fates_allom_fmode:units = "index" ; + fates_allom_fmode:long_name = "fine root biomass allometry function index." ; + double fates_allom_fnrt_prof_a(fates_pft) ; + fates_allom_fnrt_prof_a:units = "unitless" ; + fates_allom_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; + double fates_allom_fnrt_prof_b(fates_pft) ; + fates_allom_fnrt_prof_b:units = "unitless" ; + fates_allom_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; + double fates_allom_fnrt_prof_mode(fates_pft) ; + fates_allom_fnrt_prof_mode:units = "index" ; + fates_allom_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; + double fates_allom_frbstor_repro(fates_pft) ; + fates_allom_frbstor_repro:units = "fraction" ; + fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; + double fates_allom_hmode(fates_pft) ; + fates_allom_hmode:units = "index" ; + fates_allom_hmode:long_name = "height allometry function index." ; + double fates_allom_l2fr(fates_pft) ; + fates_allom_l2fr:units = "gC/gC" ; + fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; + double fates_allom_la_per_sa_int(fates_pft) ; + fates_allom_la_per_sa_int:units = "m2/cm2" ; + fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; + double fates_allom_la_per_sa_slp(fates_pft) ; + fates_allom_la_per_sa_slp:units = "m2/cm2/m" ; + fates_allom_la_per_sa_slp:long_name = "Leaf area per sapwood area rate of change with height, slope (optional)" ; + double fates_allom_lmode(fates_pft) ; + fates_allom_lmode:units = "index" ; + fates_allom_lmode:long_name = "leaf biomass allometry function index." ; + double fates_allom_sai_scaler(fates_pft) ; + fates_allom_sai_scaler:units = "m2/m2" ; + fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; + double fates_allom_smode(fates_pft) ; + fates_allom_smode:units = "index" ; + fates_allom_smode:long_name = "sapwood allometry function index." ; + double fates_allom_stmode(fates_pft) ; + fates_allom_stmode:units = "index" ; + fates_allom_stmode:long_name = "storage allometry function index: 1) Storage proportional to leaf biomass (with trimming), 2) Storage proportional to maximum leaf biomass (not trimmed)" ; + double fates_allom_zroot_k(fates_pft) ; + fates_allom_zroot_k:units = "unitless" ; + fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; + double fates_allom_zroot_max_dbh(fates_pft) ; + fates_allom_zroot_max_dbh:units = "cm" ; + fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; + double fates_allom_zroot_max_z(fates_pft) ; + fates_allom_zroot_max_z:units = "m" ; + fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_allom_zroot_min_dbh(fates_pft) ; + fates_allom_zroot_min_dbh:units = "cm" ; + fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; + double fates_allom_zroot_min_z(fates_pft) ; + fates_allom_zroot_min_z:units = "m" ; + fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_c2b(fates_pft) ; + fates_c2b:units = "ratio" ; + fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; + double fates_cnp_eca_alpha_ptase(fates_pft) ; + fates_cnp_eca_alpha_ptase:units = "g/m3" ; + fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; + double fates_cnp_eca_decompmicc(fates_pft) ; + fates_cnp_eca_decompmicc:units = "gC/m3" ; + fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; + double fates_cnp_eca_km_nh4(fates_pft) ; + fates_cnp_eca_km_nh4:units = "gN/m3" ; + fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; + double fates_cnp_eca_km_no3(fates_pft) ; + fates_cnp_eca_km_no3:units = "gN/m3" ; + fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; + double fates_cnp_eca_km_p(fates_pft) ; + fates_cnp_eca_km_p:units = "gP/m3" ; + fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; + double fates_cnp_eca_km_ptase(fates_pft) ; + fates_cnp_eca_km_ptase:units = "gP/m3" ; + fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; + double fates_cnp_eca_lambda_ptase(fates_pft) ; + fates_cnp_eca_lambda_ptase:units = "g/m3" ; + fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; + double fates_cnp_eca_vmax_ptase(fates_pft) ; + fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; + fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; + double fates_cnp_nfix1(fates_pft) ; + fates_cnp_nfix1:units = "fraction" ; + fates_cnp_nfix1:long_name = "fractional surcharge added to maintenance respiration that drives symbiotic fixation" ; + double fates_cnp_nitr_store_ratio(fates_pft) ; + fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; + fates_cnp_nitr_store_ratio:long_name = "storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code)" ; + double fates_cnp_phos_store_ratio(fates_pft) ; + fates_cnp_phos_store_ratio:units = "(gP/gP)" ; + fates_cnp_phos_store_ratio:long_name = "storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code)" ; + double fates_cnp_pid_kd(fates_pft) ; + fates_cnp_pid_kd:units = "unknown" ; + fates_cnp_pid_kd:long_name = "derivative constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_pid_ki(fates_pft) ; + fates_cnp_pid_ki:units = "unknown" ; + fates_cnp_pid_ki:long_name = "integral constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_pid_kp(fates_pft) ; + fates_cnp_pid_kp:units = "unknown" ; + fates_cnp_pid_kp:long_name = "proportional constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_prescribed_nuptake(fates_pft) ; + fates_cnp_prescribed_nuptake:units = "fraction" ; + fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; + double fates_cnp_prescribed_puptake(fates_pft) ; + fates_cnp_prescribed_puptake:units = "fraction" ; + fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; + double fates_cnp_store_ovrflw_frac(fates_pft) ; + fates_cnp_store_ovrflw_frac:units = "fraction" ; + fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; + double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_nitr_retrans:units = "fraction" ; + fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; + double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_phos_retrans:units = "fraction" ; + fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; + double fates_cnp_vmax_nh4(fates_pft) ; + fates_cnp_vmax_nh4:units = "gN/gC/s" ; + fates_cnp_vmax_nh4:long_name = "maximum (potential) uptake rate of NH4 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_nh4 for usage)" ; + double fates_cnp_vmax_no3(fates_pft) ; + fates_cnp_vmax_no3:units = "gN/gC/s" ; + fates_cnp_vmax_no3:long_name = "maximum (potential) uptake rate of NO3 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_no3 for usage)" ; + double fates_cnp_vmax_p(fates_pft) ; + fates_cnp_vmax_p:units = "gP/gC/s" ; + fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; + double fates_damage_frac(fates_pft) ; + fates_damage_frac:units = "fraction" ; + fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; + double fates_damage_mort_p1(fates_pft) ; + fates_damage_mort_p1:units = "fraction" ; + fates_damage_mort_p1:long_name = "inflection point of damage mortality function, a value of 0.8 means 50% mortality with 80% loss of crown, turn off with a large number" ; + double fates_damage_mort_p2(fates_pft) ; + fates_damage_mort_p2:units = "unitless" ; + fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; + 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_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" ; + double fates_fire_alpha_SH(fates_pft) ; + fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; + fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; + double fates_fire_bark_scaler(fates_pft) ; + fates_fire_bark_scaler:units = "fraction" ; + fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; + double fates_fire_crown_kill(fates_pft) ; + fates_fire_crown_kill:units = "NA" ; + fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; + double fates_frag_fnrt_fcel(fates_pft) ; + fates_frag_fnrt_fcel:units = "fraction" ; + fates_frag_fnrt_fcel:long_name = "Fine root litter cellulose fraction" ; + double fates_frag_fnrt_flab(fates_pft) ; + fates_frag_fnrt_flab:units = "fraction" ; + fates_frag_fnrt_flab:long_name = "Fine root litter labile fraction" ; + double fates_frag_fnrt_flig(fates_pft) ; + fates_frag_fnrt_flig:units = "fraction" ; + fates_frag_fnrt_flig:long_name = "Fine root litter lignin fraction" ; + double fates_frag_leaf_fcel(fates_pft) ; + fates_frag_leaf_fcel:units = "fraction" ; + fates_frag_leaf_fcel:long_name = "Leaf litter cellulose fraction" ; + double fates_frag_leaf_flab(fates_pft) ; + fates_frag_leaf_flab:units = "fraction" ; + fates_frag_leaf_flab:long_name = "Leaf litter labile fraction" ; + double fates_frag_leaf_flig(fates_pft) ; + fates_frag_leaf_flig:units = "fraction" ; + fates_frag_leaf_flig:long_name = "Leaf litter lignin fraction" ; + double fates_frag_seed_decay_rate(fates_pft) ; + fates_frag_seed_decay_rate:units = "yr-1" ; + fates_frag_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; + double fates_grperc(fates_pft) ; + fates_grperc:units = "unitless" ; + fates_grperc:long_name = "Growth respiration factor" ; + double fates_hydro_avuln_gs(fates_pft) ; + fates_hydro_avuln_gs:units = "unitless" ; + fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; + double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; + fates_hydro_avuln_node:units = "unitless" ; + fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; + double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; + fates_hydro_epsil_node:units = "MPa" ; + fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; + double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; + fates_hydro_fcap_node:units = "unitless" ; + fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; + double fates_hydro_k_lwp(fates_pft) ; + fates_hydro_k_lwp:units = "unitless" ; + fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; + double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; + fates_hydro_kmax_node:units = "kg/MPa/m/s" ; + fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; + double fates_hydro_p50_gs(fates_pft) ; + fates_hydro_p50_gs:units = "MPa" ; + fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; + double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; + fates_hydro_p50_node:units = "MPa" ; + fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; + double fates_hydro_p_taper(fates_pft) ; + fates_hydro_p_taper:units = "unitless" ; + fates_hydro_p_taper:long_name = "xylem taper exponent" ; + double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pinot_node:units = "MPa" ; + fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; + double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pitlp_node:units = "MPa" ; + fates_hydro_pitlp_node:long_name = "turgor loss point" ; + double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; + fates_hydro_resid_node:units = "cm3/cm3" ; + fates_hydro_resid_node:long_name = "residual water conent" ; + double fates_hydro_rfrac_stem(fates_pft) ; + fates_hydro_rfrac_stem:units = "fraction" ; + fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; + double fates_hydro_rs2(fates_pft) ; + fates_hydro_rs2:units = "m" ; + fates_hydro_rs2:long_name = "absorbing root radius" ; + double fates_hydro_srl(fates_pft) ; + fates_hydro_srl:units = "m g-1" ; + fates_hydro_srl:long_name = "specific root length" ; + double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; + fates_hydro_thetas_node:units = "cm3/cm3" ; + fates_hydro_thetas_node:long_name = "saturated water content" ; + double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_alpha_node:units = "MPa-1" ; + fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; + double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_m_node:units = "unitless" ; + fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; + 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_leaf_c3psn(fates_pft) ; + fates_leaf_c3psn:units = "flag" ; + fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; + double fates_leaf_jmaxha(fates_pft) ; + fates_leaf_jmaxha:units = "J/mol" ; + fates_leaf_jmaxha:long_name = "activation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_jmaxhd(fates_pft) ; + fates_leaf_jmaxhd:units = "J/mol" ; + fates_leaf_jmaxhd:long_name = "deactivation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_jmaxse(fates_pft) ; + fates_leaf_jmaxse:units = "J/mol/K" ; + fates_leaf_jmaxse:long_name = "entropy term for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_slamax(fates_pft) ; + fates_leaf_slamax:units = "m^2/gC" ; + fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; + double fates_leaf_slatop(fates_pft) ; + fates_leaf_slatop:units = "m^2/gC" ; + fates_leaf_slatop:long_name = "Specific Leaf Area (SLA) at top of canopy, projected area basis" ; + double fates_leaf_stomatal_intercept(fates_pft) ; + fates_leaf_stomatal_intercept:units = "umol H2O/m**2/s" ; + fates_leaf_stomatal_intercept:long_name = "Minimum unstressed stomatal conductance for Ball-Berry model and Medlyn model" ; + double fates_leaf_stomatal_slope_ballberry(fates_pft) ; + fates_leaf_stomatal_slope_ballberry:units = "unitless" ; + fates_leaf_stomatal_slope_ballberry:long_name = "stomatal slope parameter, as per Ball-Berry" ; + double fates_leaf_stomatal_slope_medlyn(fates_pft) ; + fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; + fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; + double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; + fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; + fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; + double fates_leaf_vcmaxha(fates_pft) ; + fates_leaf_vcmaxha:units = "J/mol" ; + fates_leaf_vcmaxha:long_name = "activation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_vcmaxhd(fates_pft) ; + fates_leaf_vcmaxhd:units = "J/mol" ; + fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_vcmaxse(fates_pft) ; + fates_leaf_vcmaxse:units = "J/mol/K" ; + fates_leaf_vcmaxse:long_name = "entropy term for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_maintresp_leaf_atkin2017_baserate(fates_pft) ; + fates_maintresp_leaf_atkin2017_baserate:units = "umol CO2/m^2/s" ; + fates_maintresp_leaf_atkin2017_baserate:long_name = "Leaf maintenance respiration base rate parameter (r0) per Atkin et al 2017" ; + double fates_maintresp_leaf_ryan1991_baserate(fates_pft) ; + fates_maintresp_leaf_ryan1991_baserate:units = "gC/gN/s" ; + fates_maintresp_leaf_ryan1991_baserate:long_name = "Leaf maintenance respiration base rate per Ryan et al 1991" ; + double fates_maintresp_reduction_curvature(fates_pft) ; + fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; + fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; + double fates_maintresp_reduction_intercept(fates_pft) ; + fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; + fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; + double fates_maintresp_reduction_upthresh(fates_pft) ; + fates_maintresp_reduction_upthresh:units = "unitless (0-1)" ; + fates_maintresp_reduction_upthresh:long_name = "upper threshold for storage biomass (relative to leaf biomass) above which MR is not reduced" ; + double fates_mort_bmort(fates_pft) ; + fates_mort_bmort:units = "1/yr" ; + fates_mort_bmort:long_name = "background mortality rate" ; + double fates_mort_freezetol(fates_pft) ; + fates_mort_freezetol:units = "degrees C" ; + fates_mort_freezetol:long_name = "minimum temperature tolerance" ; + double fates_mort_hf_flc_threshold(fates_pft) ; + fates_mort_hf_flc_threshold:units = "fraction" ; + fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; + double fates_mort_hf_sm_threshold(fates_pft) ; + fates_mort_hf_sm_threshold:units = "unitless" ; + fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; + double fates_mort_ip_age_senescence(fates_pft) ; + fates_mort_ip_age_senescence:units = "years" ; + fates_mort_ip_age_senescence:long_name = "Mortality cohort age senescence inflection point. If _ this mortality term is off. Setting this value turns on age dependent mortality. " ; + double fates_mort_ip_size_senescence(fates_pft) ; + fates_mort_ip_size_senescence:units = "dbh cm" ; + fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; + double fates_mort_prescribed_canopy(fates_pft) ; + fates_mort_prescribed_canopy:units = "1/yr" ; + fates_mort_prescribed_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; + double fates_mort_prescribed_understory(fates_pft) ; + fates_mort_prescribed_understory:units = "1/yr" ; + fates_mort_prescribed_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; + double fates_mort_r_age_senescence(fates_pft) ; + fates_mort_r_age_senescence:units = "mortality rate year^-1" ; + fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; + double fates_mort_r_size_senescence(fates_pft) ; + fates_mort_r_size_senescence:units = "mortality rate dbh^-1" ; + fates_mort_r_size_senescence:long_name = "Mortality dbh senescence rate of change. Sensible range is around 0.03-0.06. Larger values give steeper mortality curves." ; + double fates_mort_scalar_coldstress(fates_pft) ; + fates_mort_scalar_coldstress:units = "1/yr" ; + fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; + double fates_mort_scalar_cstarvation(fates_pft) ; + fates_mort_scalar_cstarvation:units = "1/yr" ; + fates_mort_scalar_cstarvation:long_name = "maximum mortality rate from carbon starvation" ; + double fates_mort_scalar_hydrfailure(fates_pft) ; + fates_mort_scalar_hydrfailure:units = "1/yr" ; + fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; + double fates_mort_upthresh_cstarvation(fates_pft) ; + fates_mort_upthresh_cstarvation:units = "unitless" ; + fates_mort_upthresh_cstarvation:long_name = "threshold for storage biomass (relative to target leaf biomass) above which carbon starvation is zero" ; + double fates_nonhydro_smpsc(fates_pft) ; + fates_nonhydro_smpsc:units = "mm" ; + fates_nonhydro_smpsc:long_name = "Soil water potential at full stomatal closure" ; + double fates_nonhydro_smpso(fates_pft) ; + fates_nonhydro_smpso:units = "mm" ; + fates_nonhydro_smpso:long_name = "Soil water potential at full stomatal opening" ; + double fates_phen_cold_size_threshold(fates_pft) ; + fates_phen_cold_size_threshold:units = "cm" ; + fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; + double fates_phen_drought_threshold(fates_pft) ; + fates_phen_drought_threshold:units = "m3/m3 or mm" ; + fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold for semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_evergreen(fates_pft) ; + fates_phen_evergreen:units = "logical flag" ; + fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; + double fates_phen_flush_fraction(fates_pft) ; + fates_phen_flush_fraction:units = "fraction" ; + fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; + double fates_phen_fnrt_drop_fraction(fates_pft) ; + fates_phen_fnrt_drop_fraction:units = "fraction" ; + fates_phen_fnrt_drop_fraction:long_name = "fraction of fine roots to drop during drought/cold" ; + double fates_phen_mindaysoff(fates_pft) ; + fates_phen_mindaysoff:units = "days" ; + fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves abscised (shed)" ; + double fates_phen_moist_threshold(fates_pft) ; + fates_phen_moist_threshold:units = "m3/m3 or mm" ; + fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for drought semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_season_decid(fates_pft) ; + fates_phen_season_decid:units = "logical flag" ; + fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; + double fates_phen_stem_drop_fraction(fates_pft) ; + fates_phen_stem_drop_fraction:units = "fraction" ; + fates_phen_stem_drop_fraction:long_name = "fraction of stems to drop for non-woody species during drought/cold" ; + double fates_phen_stress_decid(fates_pft) ; + fates_phen_stress_decid:units = "logical flag" ; + fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; + double fates_prescribed_npp_canopy(fates_pft) ; + fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; + double fates_prescribed_npp_understory(fates_pft) ; + fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; + double fates_rad_leaf_clumping_index(fates_pft) ; + fates_rad_leaf_clumping_index:units = "fraction (0-1)" ; + fates_rad_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; + double fates_rad_leaf_rhonir(fates_pft) ; + fates_rad_leaf_rhonir:units = "fraction" ; + fates_rad_leaf_rhonir:long_name = "Leaf reflectance: near-IR" ; + double fates_rad_leaf_rhovis(fates_pft) ; + fates_rad_leaf_rhovis:units = "fraction" ; + fates_rad_leaf_rhovis:long_name = "Leaf reflectance: visible" ; + double fates_rad_leaf_taunir(fates_pft) ; + fates_rad_leaf_taunir:units = "fraction" ; + fates_rad_leaf_taunir:long_name = "Leaf transmittance: near-IR" ; + double fates_rad_leaf_tauvis(fates_pft) ; + fates_rad_leaf_tauvis:units = "fraction" ; + fates_rad_leaf_tauvis:long_name = "Leaf transmittance: visible" ; + double fates_rad_leaf_xl(fates_pft) ; + fates_rad_leaf_xl:units = "unitless" ; + fates_rad_leaf_xl:long_name = "Leaf/stem orientation index" ; + double fates_rad_stem_rhonir(fates_pft) ; + fates_rad_stem_rhonir:units = "fraction" ; + fates_rad_stem_rhonir:long_name = "Stem reflectance: near-IR" ; + double fates_rad_stem_rhovis(fates_pft) ; + fates_rad_stem_rhovis:units = "fraction" ; + fates_rad_stem_rhovis:long_name = "Stem reflectance: visible" ; + double fates_rad_stem_taunir(fates_pft) ; + fates_rad_stem_taunir:units = "fraction" ; + fates_rad_stem_taunir:long_name = "Stem transmittance: near-IR" ; + double fates_rad_stem_tauvis(fates_pft) ; + fates_rad_stem_tauvis:units = "fraction" ; + fates_rad_stem_tauvis:long_name = "Stem transmittance: visible" ; + double fates_recruit_height_min(fates_pft) ; + fates_recruit_height_min:units = "m" ; + fates_recruit_height_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; + double fates_recruit_init_density(fates_pft) ; + fates_recruit_init_density:units = "stems/m2" ; + fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation. If negative sets initial tree dbh - only to be used in nocomp mode" ; + double fates_recruit_prescribed_rate(fates_pft) ; + fates_recruit_prescribed_rate:units = "n/yr" ; + fates_recruit_prescribed_rate:long_name = "recruitment rate for prescribed physiology mode" ; + double fates_recruit_seed_alloc(fates_pft) ; + fates_recruit_seed_alloc:units = "fraction" ; + fates_recruit_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; + double fates_recruit_seed_alloc_mature(fates_pft) ; + fates_recruit_seed_alloc_mature:units = "fraction" ; + fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; + double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; + fates_recruit_seed_dbh_repro_threshold:units = "cm" ; + fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter where the plant will increase allocation to the seed pool by fraction: fates_recruit_seed_alloc_mature" ; + double fates_recruit_seed_germination_rate(fates_pft) ; + fates_recruit_seed_germination_rate:units = "yr-1" ; + fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; + double fates_recruit_seed_supplement(fates_pft) ; + fates_recruit_seed_supplement:units = "KgC/m2/yr" ; + fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; + double fates_seed_dispersal_fraction(fates_pft) ; + fates_seed_dispersal_fraction:units = "fraction" ; + fates_seed_dispersal_fraction:long_name = "fraction of seed rain to be dispersed to other grid cells" ; + double fates_seed_dispersal_max_dist(fates_pft) ; + fates_seed_dispersal_max_dist:units = "m" ; + fates_seed_dispersal_max_dist:long_name = "maximum seed dispersal distance for a given pft" ; + double fates_seed_dispersal_pdf_scale(fates_pft) ; + fates_seed_dispersal_pdf_scale:units = "unitless" ; + fates_seed_dispersal_pdf_scale:long_name = "seed dispersal probability density function scale parameter, A, Table 1 Bullock et al 2016" ; + double fates_seed_dispersal_pdf_shape(fates_pft) ; + fates_seed_dispersal_pdf_shape:units = "unitless" ; + fates_seed_dispersal_pdf_shape:long_name = "seed dispersal probability density function shape parameter, B, Table 1 Bullock et al 2016" ; + double fates_stoich_nitr(fates_plant_organs, fates_pft) ; + fates_stoich_nitr:units = "gN/gC" ; + fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; + double fates_stoich_phos(fates_plant_organs, fates_pft) ; + fates_stoich_phos:units = "gP/gC" ; + fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; + double fates_trim_inc(fates_pft) ; + fates_trim_inc:units = "m2/m2" ; + fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; + double fates_trim_limit(fates_pft) ; + fates_trim_limit:units = "m2/m2" ; + fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; + double fates_trs_repro_alloc_a(fates_pft) ; + fates_trs_repro_alloc_a:units = "fraction" ; + fates_trs_repro_alloc_a:long_name = "shape parameter for sigmoidal function relating dbh to reproductive allocation" ; + double fates_trs_repro_alloc_b(fates_pft) ; + fates_trs_repro_alloc_b:units = "fraction" ; + fates_trs_repro_alloc_b:long_name = "intercept parameter for sigmoidal function relating dbh to reproductive allocation" ; + double fates_trs_repro_frac_seed(fates_pft) ; + fates_trs_repro_frac_seed:units = "fraction" ; + fates_trs_repro_frac_seed:long_name = "fraction of reproductive mass that is seed" ; + double fates_trs_seedling_a_emerg(fates_pft) ; + fates_trs_seedling_a_emerg:units = "day -1" ; + fates_trs_seedling_a_emerg:long_name = "mean fraction of seed bank emerging" ; + double fates_trs_seedling_b_emerg(fates_pft) ; + fates_trs_seedling_b_emerg:units = "day -1" ; + fates_trs_seedling_b_emerg:long_name = "seedling emergence sensitivity to soil moisture" ; + double fates_trs_seedling_background_mort(fates_pft) ; + fates_trs_seedling_background_mort:units = "yr-1" ; + fates_trs_seedling_background_mort:long_name = "background seedling mortality rate" ; + double fates_trs_seedling_h2o_mort_a(fates_pft) ; + fates_trs_seedling_h2o_mort_a:units = "-" ; + fates_trs_seedling_h2o_mort_a:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_trs_seedling_h2o_mort_b(fates_pft) ; + fates_trs_seedling_h2o_mort_b:units = "-" ; + fates_trs_seedling_h2o_mort_b:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_trs_seedling_h2o_mort_c(fates_pft) ; + fates_trs_seedling_h2o_mort_c:units = "-" ; + fates_trs_seedling_h2o_mort_c:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_trs_seedling_light_mort_a(fates_pft) ; + fates_trs_seedling_light_mort_a:units = "-" ; + fates_trs_seedling_light_mort_a:long_name = "light-based seedling mortality coefficient" ; + double fates_trs_seedling_light_mort_b(fates_pft) ; + fates_trs_seedling_light_mort_b:units = "-" ; + fates_trs_seedling_light_mort_b:long_name = "light-based seedling mortality coefficient" ; + double fates_trs_seedling_light_rec_a(fates_pft) ; + fates_trs_seedling_light_rec_a:units = "-" ; + fates_trs_seedling_light_rec_a:long_name = "coefficient in light-based seedling to sapling transition" ; + double fates_trs_seedling_light_rec_b(fates_pft) ; + fates_trs_seedling_light_rec_b:units = "-" ; + fates_trs_seedling_light_rec_b:long_name = "coefficient in light-based seedling to sapling transition" ; + double fates_trs_seedling_mdd_crit(fates_pft) ; + fates_trs_seedling_mdd_crit:units = "mm H2O day" ; + fates_trs_seedling_mdd_crit:long_name = "critical moisture deficit (suction) day accumulation for seedling moisture-based seedling mortality to begin" ; + double fates_trs_seedling_par_crit_germ(fates_pft) ; + fates_trs_seedling_par_crit_germ:units = "MJ m-2 day-1" ; + fates_trs_seedling_par_crit_germ:long_name = "critical light level for germination" ; + double fates_trs_seedling_psi_crit(fates_pft) ; + fates_trs_seedling_psi_crit:units = "mm H2O" ; + fates_trs_seedling_psi_crit:long_name = "critical soil moisture (suction) for seedling stress" ; + double fates_trs_seedling_psi_emerg(fates_pft) ; + fates_trs_seedling_psi_emerg:units = "mm h20 suction" ; + fates_trs_seedling_psi_emerg:long_name = "critical soil moisture for seedling emergence" ; + double fates_trs_seedling_root_depth(fates_pft) ; + fates_trs_seedling_root_depth:units = "m" ; + fates_trs_seedling_root_depth:long_name = "rooting depth of seedlings" ; + double fates_turb_displar(fates_pft) ; + fates_turb_displar:units = "unitless" ; + fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; + double fates_turb_leaf_diameter(fates_pft) ; + fates_turb_leaf_diameter:units = "m" ; + fates_turb_leaf_diameter:long_name = "Characteristic leaf dimension" ; + double fates_turb_z0mr(fates_pft) ; + fates_turb_z0mr:units = "unitless" ; + fates_turb_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; + double fates_turnover_branch(fates_pft) ; + fates_turnover_branch:units = "yr" ; + fates_turnover_branch:long_name = "turnover time of branches" ; + double fates_turnover_fnrt(fates_pft) ; + fates_turnover_fnrt:units = "yr" ; + fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; + double fates_turnover_leaf(fates_leafage_class, fates_pft) ; + fates_turnover_leaf:units = "yr" ; + fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale). For drought-deciduous PFTs, this also indicates the maximum length of the growing (i.e., leaves on) season." ; + double fates_turnover_senleaf_fdrought(fates_pft) ; + fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; + fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; + double fates_wood_density(fates_pft) ; + fates_wood_density:units = "g/cm3" ; + fates_wood_density:long_name = "mean density of woody tissue in plant" ; + double fates_woody(fates_pft) ; + fates_woody:units = "logical flag" ; + fates_woody:long_name = "Binary woody lifeform flag" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_fire_FBD(fates_litterclass) ; + fates_fire_FBD:units = "kg Biomass/m3" ; + fates_fire_FBD:long_name = "fuel bulk density" ; + double fates_fire_low_moisture_Coeff(fates_litterclass) ; + fates_fire_low_moisture_Coeff:units = "NA" ; + fates_fire_low_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_low_moisture_Slope(fates_litterclass) ; + fates_fire_low_moisture_Slope:units = "NA" ; + fates_fire_low_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture(fates_litterclass) ; + fates_fire_mid_moisture:units = "NA" ; + fates_fire_mid_moisture:long_name = "spitfire litter moisture threshold to be considered medium dry" ; + double fates_fire_mid_moisture_Coeff(fates_litterclass) ; + fates_fire_mid_moisture_Coeff:units = "NA" ; + fates_fire_mid_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture_Slope(fates_litterclass) ; + fates_fire_mid_moisture_Slope:units = "NA" ; + fates_fire_mid_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_min_moisture(fates_litterclass) ; + fates_fire_min_moisture:units = "NA" ; + fates_fire_min_moisture:long_name = "spitfire litter moisture threshold to be considered very dry" ; + double fates_fire_SAV(fates_litterclass) ; + fates_fire_SAV:units = "cm-1" ; + fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; + double fates_frag_maxdecomp(fates_litterclass) ; + fates_frag_maxdecomp:units = "yr-1" ; + fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; + 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_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" ; + double fates_cnp_eca_plant_escalar ; + fates_cnp_eca_plant_escalar:units = "" ; + fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; + double fates_cohort_age_fusion_tol ; + fates_cohort_age_fusion_tol:units = "unitless" ; + fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; + double fates_cohort_size_fusion_tol ; + fates_cohort_size_fusion_tol:units = "unitless" ; + fates_cohort_size_fusion_tol:long_name = "minimum fraction in difference in dbh between cohorts" ; + double fates_comp_excln ; + fates_comp_excln:units = "none" ; + fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; + double fates_damage_canopy_layer_code ; + fates_damage_canopy_layer_code:units = "unitless" ; + fates_damage_canopy_layer_code:long_name = "Integer code that decides whether damage affects canopy trees (1), understory trees (2)" ; + double fates_damage_event_code ; + fates_damage_event_code:units = "unitless" ; + fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; + double fates_dev_arbitrary ; + fates_dev_arbitrary:units = "unknown" ; + fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; + double fates_fire_active_crown_fire ; + fates_fire_active_crown_fire:units = "0 or 1" ; + fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; + double fates_fire_cg_strikes ; + fates_fire_cg_strikes:units = "fraction (0-1)" ; + fates_fire_cg_strikes:long_name = "fraction of cloud to ground lightning strikes" ; + double fates_fire_drying_ratio ; + fates_fire_drying_ratio:units = "NA" ; + fates_fire_drying_ratio:long_name = "spitfire parameter, fire drying ratio for fuel moisture, alpha_FMC EQ 6 Thonicke et al 2010" ; + double fates_fire_durat_slope ; + fates_fire_durat_slope:units = "NA" ; + fates_fire_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; + double fates_fire_fdi_a ; + fates_fire_fdi_a:units = "NA" ; + fates_fire_fdi_a:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010" ; + double fates_fire_fdi_alpha ; + fates_fire_fdi_alpha:units = "NA" ; + fates_fire_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; + double fates_fire_fdi_b ; + fates_fire_fdi_b:units = "NA" ; + fates_fire_fdi_b:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010 " ; + double fates_fire_fuel_energy ; + fates_fire_fuel_energy:units = "kJ/kg" ; + fates_fire_fuel_energy:long_name = "spitfire parameter, heat content of fuel" ; + double fates_fire_max_durat ; + fates_fire_max_durat:units = "minutes" ; + fates_fire_max_durat:long_name = "spitfire parameter, fire maximum duration, Equation 14 Thonicke et al 2010" ; + double fates_fire_miner_damp ; + fates_fire_miner_damp:units = "NA" ; + fates_fire_miner_damp:long_name = "spitfire parameter, mineral-dampening coefficient EQ A1 Thonicke et al 2010 " ; + double fates_fire_miner_total ; + fates_fire_miner_total:units = "fraction" ; + fates_fire_miner_total:long_name = "spitfire parameter, total mineral content, Table A1 Thonicke et al 2010" ; + double fates_fire_nignitions ; + fates_fire_nignitions:units = "ignitions per year per km2" ; + fates_fire_nignitions:long_name = "number of annual ignitions per square km" ; + double fates_fire_part_dens ; + fates_fire_part_dens:units = "kg/m2" ; + fates_fire_part_dens:long_name = "spitfire parameter, oven dry particle density, Table A1 Thonicke et al 2010" ; + double fates_fire_threshold ; + fates_fire_threshold:units = "kW/m" ; + fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; + double fates_frag_cwd_fcel ; + fates_frag_cwd_fcel:units = "unitless" ; + fates_frag_cwd_fcel:long_name = "Cellulose fraction for CWD" ; + double fates_frag_cwd_flig ; + fates_frag_cwd_flig:units = "unitless" ; + fates_frag_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; + double fates_hydro_kmax_rsurf1 ; + fates_hydro_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; + double fates_hydro_kmax_rsurf2 ; + fates_hydro_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; + double fates_hydro_psi0 ; + fates_hydro_psi0:units = "MPa" ; + fates_hydro_psi0:long_name = "sapwood water potential at saturation" ; + double fates_hydro_psicap ; + fates_hydro_psicap:units = "MPa" ; + fates_hydro_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; + 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_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" ; + double fates_landuse_logging_collateral_frac ; + fates_landuse_logging_collateral_frac:units = "fraction" ; + fates_landuse_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; + double fates_landuse_logging_dbhmax ; + fates_landuse_logging_dbhmax:units = "cm" ; + fates_landuse_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; + double fates_landuse_logging_dbhmax_infra ; + fates_landuse_logging_dbhmax_infra:units = "cm" ; + fates_landuse_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; + double fates_landuse_logging_dbhmin ; + fates_landuse_logging_dbhmin:units = "cm" ; + fates_landuse_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; + double fates_landuse_logging_direct_frac ; + fates_landuse_logging_direct_frac:units = "fraction" ; + fates_landuse_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; + double fates_landuse_logging_event_code ; + fates_landuse_logging_event_code:units = "unitless" ; + fates_landuse_logging_event_code:long_name = "Integer code that options how logging events are structured" ; + double fates_landuse_logging_export_frac ; + fates_landuse_logging_export_frac:units = "fraction" ; + fates_landuse_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; + double fates_landuse_logging_mechanical_frac ; + fates_landuse_logging_mechanical_frac:units = "fraction" ; + fates_landuse_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; + double fates_landuse_pprodharv10_forest_mean ; + fates_landuse_pprodharv10_forest_mean:units = "fraction" ; + fates_landuse_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; + double fates_leaf_photo_temp_acclim_thome_time ; + fates_leaf_photo_temp_acclim_thome_time:units = "years" ; + fates_leaf_photo_temp_acclim_thome_time:long_name = "Length of the window for the long-term (i.e. T_home in Kumarathunge et al 2019) exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_leaf_photo_tempsens_model = 2)" ; + double fates_leaf_photo_temp_acclim_timescale ; + fates_leaf_photo_temp_acclim_timescale:units = "days" ; + fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_maintresp_leaf_model=2 or fates_leaf_photo_tempsens_model = 2)" ; + double fates_leaf_photo_tempsens_model ; + fates_leaf_photo_tempsens_model:units = "unitless" ; + fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating; 2=Kumarathunge et al 2019" ; + double fates_leaf_stomatal_assim_model ; + fates_leaf_stomatal_assim_model:units = "unitless" ; + fates_leaf_stomatal_assim_model:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; + double fates_leaf_stomatal_model ; + fates_leaf_stomatal_model:units = "unitless" ; + fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; + double fates_leaf_theta_cj_c3 ; + fates_leaf_theta_cj_c3:units = "unitless" ; + fates_leaf_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; + double fates_leaf_theta_cj_c4 ; + fates_leaf_theta_cj_c4:units = "unitless" ; + fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; + double fates_maintresp_leaf_model ; + fates_maintresp_leaf_model:units = "unitless" ; + fates_maintresp_leaf_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991), 2=Atkin et al., (2017)" ; + double fates_maintresp_nonleaf_baserate ; + fates_maintresp_nonleaf_baserate:units = "gC/gN/s" ; + fates_maintresp_nonleaf_baserate:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; + double fates_maxcohort ; + fates_maxcohort:units = "count" ; + fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; + double fates_maxpatch_primary ; + fates_maxpatch_primary:units = "count" ; + fates_maxpatch_primary:long_name = "maximum number of primary vegetation patches per site" ; + double fates_maxpatch_secondary ; + fates_maxpatch_secondary:units = "count" ; + fates_maxpatch_secondary:long_name = "maximum number of secondary vegetation patches per site" ; + double fates_mort_disturb_frac ; + fates_mort_disturb_frac:units = "fraction" ; + fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; + double fates_mort_understorey_death ; + fates_mort_understorey_death:units = "fraction" ; + fates_mort_understorey_death:long_name = "fraction of plants in understorey cohort impacted by overstorey tree-fall" ; + double fates_patch_fusion_tol ; + fates_patch_fusion_tol:units = "unitless" ; + fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; + double fates_phen_chilltemp ; + fates_phen_chilltemp:units = "degrees C" ; + fates_phen_chilltemp:long_name = "chilling day counting threshold for vegetation" ; + double fates_phen_coldtemp ; + fates_phen_coldtemp:units = "degrees C" ; + fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; + double fates_phen_gddthresh_a ; + fates_phen_gddthresh_a:units = "none" ; + fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_b ; + fates_phen_gddthresh_b:units = "none" ; + fates_phen_gddthresh_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_c ; + fates_phen_gddthresh_c:units = "none" ; + fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_mindayson ; + fates_phen_mindayson:units = "days" ; + fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; + double fates_phen_ncolddayslim ; + fates_phen_ncolddayslim:units = "days" ; + fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; + double fates_q10_froz ; + fates_q10_froz:units = "unitless" ; + fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; + double fates_q10_mr ; + fates_q10_mr:units = "unitless" ; + fates_q10_mr:long_name = "Q10 for maintenance respiration" ; + double fates_rad_model ; + fates_rad_model:units = "unitless" ; + fates_rad_model:long_name = "switch designating the model for canopy radiation, 1 = Norman, 2 = Two-stream (experimental)" ; + double fates_regeneration_model ; + fates_regeneration_model:units = "-" ; + fates_regeneration_model:long_name = "switch for choosing between FATES\'s: 1) default regeneration scheme , 2) the Tree Recruitment Scheme (Hanbury-Brown et al., 2022), or (3) the Tree Recruitment Scheme without seedling dynamics" ; + double fates_soil_salinity ; + fates_soil_salinity:units = "ppt" ; + fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; + double fates_trs_seedling2sap_par_timescale ; + fates_trs_seedling2sap_par_timescale:units = "days" ; + fates_trs_seedling2sap_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling to sapling transition rates" ; + double fates_trs_seedling_emerg_h2o_timescale ; + fates_trs_seedling_emerg_h2o_timescale:units = "days" ; + fates_trs_seedling_emerg_h2o_timescale:long_name = "Length of the window for the exponential moving average of smp used to calculate seedling emergence" ; + double fates_trs_seedling_mdd_timescale ; + fates_trs_seedling_mdd_timescale:units = "days" ; + fates_trs_seedling_mdd_timescale:long_name = "Length of the window for the exponential moving average of moisture deficit days used to calculate seedling mortality" ; + double fates_trs_seedling_mort_par_timescale ; + fates_trs_seedling_mort_par_timescale:units = "days" ; + fates_trs_seedling_mort_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling mortality" ; + double fates_vai_top_bin_width ; + fates_vai_top_bin_width:units = "m2/m2" ; + fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; + double fates_vai_width_increase_factor ; + fates_vai_width_increase_factor:units = "unitless" ; + fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; + +// global attributes: + :history = "This file was generated by BatchPatchParams.py:\nCDL Base File = archive/api24.1.0_101722_fates_params_default.cdl\nXML patch file = archive/api24.1.0_101722_patch_params.xml" ; +data: + + fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; + + fates_history_coageclass_bin_edges = 0, 5 ; + + fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; + + fates_history_damage_bin_edges = 0, 80 ; + + fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, + 80, 90, 100 ; + + fates_alloc_organ_id = 1, 2, 3, 6 ; + + fates_hydro_htftype_node = 1, 1, 1, 1 ; + + fates_pftname = + "broadleaf_evergreen_tropical_tree ", + "needleleaf_evergreen_extratrop_tree ", + "needleleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_tree ", + "broadleaf_hydrodecid_tropical_tree ", + "broadleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_shrub ", + "broadleaf_hydrodecid_extratrop_shrub ", + "broadleaf_colddecid_extratrop_shrub ", + "arctic_c3_grass ", + "cool_c3_grass ", + "c4_grass " ; + + fates_hydro_organ_name = + "leaf ", + "stem ", + "transporting root ", + "absorbing root " ; + + fates_alloc_organ_name = + "leaf", + "fine root", + "sapwood", + "structure" ; + + fates_litterclass_name = + "twig ", + "small branch ", + "large branch ", + "trunk ", + "dead leaves ", + "live grass " ; + + 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, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; + + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 2.4, 1.2, 1.2, 2.4, 1.2, + 1.2, 1.2, 1.2 ; + + fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8, 0.8 ; + + fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, + 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; + + fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, + 0.572, 0.572, 0.572, 0.572 ; + + fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, + 1.94, 1.94, 1.94 ; + + fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, + 0.931, 0.931, 0.931, 0.931 ; + + fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6 ; + + fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, + 0.95, 1, 1, 1 ; + + fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07 ; + + fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, + 1.3 ; + + fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, + 0.55, 0.55, 0.55 ; + + fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464 ; + + fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119 ; + + fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, + 0.64, 0.64, 0.64 ; + + fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, + 0.37, 0.37, 0.37 ; + + fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, + -999.9, -999.9, -999.9, -999.9, -999.9 ; + + fates_allom_dbh_maxheight = 90, 80, 80, 80, 90, 80, 3, 3, 2, 0.35, 0.35, 0.35 ; + + fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; + + fates_allom_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; + + fates_allom_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8 ; + + fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_zroot_k = 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 ; + + fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; + + fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + + fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 280, 280 ; + + fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, + 0.14, 0.14, 0.14 ; + + fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, + 0.27, 0.27, 0.27 ; + + fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_nfix1 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_pid_kd = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; + + fates_cnp_pid_ki = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_pid_kp = 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005 ; + + fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_turnover_nitr_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_turnover_phos_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_vmax_nh4 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, + 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; + + fates_cnp_vmax_no3 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, + 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; + + fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, + 5e-10, 5e-10, 5e-10, 5e-10 ; + + fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01 ; + + fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; + + fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, + 5.5, 5.5 ; + + fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2 ; + + fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07, 0.07 ; + + fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, + 0.775, 0.775, 0.775, 0.775, 0.775 ; + + fates_frag_fnrt_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_fnrt_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_fnrt_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_leaf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, + 0.51, 0.51, 0.51, 0.51 ; + + fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, + 0.11, 0.11 ; + + fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + 2.5, 2.5 ; + + fates_hydro_avuln_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_hydro_epsil_node = + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_hydro_fcap_node = + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_kmax_node = + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; + + fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + -1.5, -1.5, -1.5 ; + + fates_hydro_p50_node = + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25 ; + + fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, + 0.333, 0.333, 0.333, 0.333, 0.333 ; + + fates_hydro_pinot_node = + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; + + fates_hydro_pitlp_node = + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + -1.67, -1.67, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; + + fates_hydro_resid_node = + 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; + + fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + 0.625, 0.625, 0.625, 0.625, 0.625 ; + + fates_hydro_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, + 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; + + fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; + + fates_hydro_thetas_node = + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; + + fates_hydro_vg_alpha_node = + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005 ; + + fates_hydro_vg_m_node = + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_hydro_vg_n_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 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_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, + 43540, 43540, 43540, 43540 ; + + fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, + 152040, 152040, 152040, 152040, 152040 ; + + fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, + 495 ; + + fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, + 0.03, 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_slatop = 0.012, 0.005, 0.024, 0.009, 0.03, 0.03, 0.012, 0.03, + 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, + 10000, 10000, 10000, 10000, 10000, 40000 ; + + fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, + 4.7, 2.2, 5.3, 1.6 ; + + fates_leaf_vcmax25top = + 50, 62, 39, 61, 58, 58, 62, 54, 54, 78, 78, 78 ; + + fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, + 65330, 65330, 65330, 65330 ; + + fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, + 149250, 149250, 149250, 149250, 149250 ; + + fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, + 485 ; + + fates_maintresp_leaf_atkin2017_baserate = 1.756, 1.4995, 1.4995, 1.756, + 1.756, 1.756, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956, 2.1956 ; + + fates_maintresp_leaf_ryan1991_baserate = 2.525e-06, 2.525e-06, 2.525e-06, + 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, + 2.525e-06, 2.525e-06, 2.525e-06 ; + + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; + + fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_maintresp_reduction_upthresh = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, + 0.014, 0.014, 0.014, 0.014 ; + + fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -80, -60, -10, -80, -80, + -20, 2.5 ; + + fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, + 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; + + fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_prescribed_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, + 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; + + fates_mort_prescribed_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, + 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; + + fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_mort_upthresh_cstarvation = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_nonhydro_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, + -255000, -255000, -255000, -255000, -255000, -255000 ; + + fates_nonhydro_smpso = -66000, -66000, -66000, -66000, -66000, -66000, + -66000, -66000, -66000, -66000, -66000, -66000 ; + + fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_drought_threshold = -152957.4, -152957.4, -152957.4, -152957.4, + -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, + -152957.4, -152957.4 ; + + fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; + + fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, + 0.5 ; + + fates_phen_fnrt_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_mindaysoff = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_phen_moist_threshold = -122365.9, -122365.9, -122365.9, -122365.9, + -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, + -122365.9, -122365.9 ; + + fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; + + fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; + + fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, + 0.4, 0.4, 0.4 ; + + fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, + 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; + + fates_rad_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, + 0.9, 0.75, 0.75, 0.75 ; + + fates_rad_leaf_rhonir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, + 0.41, 0.28, 0.28, 0.28 ; + + fates_rad_leaf_rhovis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, + 0.08, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_taunir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, + 0.43, 0.4, 0.4, 0.4 ; + + fates_rad_leaf_tauvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, + 0.06, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, + -0.23, -0.23, -0.23 ; + + fates_rad_stem_rhonir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, + 0.49, 0.53, 0.53, 0.53 ; + + fates_rad_stem_rhovis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.31, 0.31, 0.31 ; + + fates_rad_stem_taunir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.25, 0.25, 0.25 ; + + fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.12, 0.12, 0.12 ; + + fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.2, 0.2, 0.2, + 0.125, 0.125, 0.125 ; + + fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2, 0.2, 0.2 ; + + fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, + 0.02, 0.02, 0.02, 0.02, 0.02 ; + + fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, + 0.9 ; + + fates_recruit_seed_dbh_repro_threshold = 90, 80, 80, 80, 90, 80, 3, 3, 2, + 0.35, 0.35, 0.35 ; + + fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_seed_dispersal_fraction = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_seed_dispersal_max_dist = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_seed_dispersal_pdf_scale = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_seed_dispersal_pdf_shape = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_stoich_nitr = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; + + fates_stoich_phos = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; + + fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, + 0.03, 0.03 ; + + fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; + + fates_trs_repro_alloc_a = 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, + 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049 ; + + fates_trs_repro_alloc_b = -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, + -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171 ; + + fates_trs_repro_frac_seed = 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, + 0.24, 0.24, 0.24, 0.24 ; + + fates_trs_seedling_a_emerg = 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, + 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003 ; + + fates_trs_seedling_b_emerg = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + 1.2, 1.2, 1.2 ; + + fates_trs_seedling_background_mort = 0.1085371, 0.1085371, 0.1085371, + 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, + 0.1085371, 0.1085371, 0.1085371 ; + + fates_trs_seedling_h2o_mort_a = 4.070565e-17, 4.070565e-17, 4.070565e-17, + 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, + 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17 ; + + fates_trs_seedling_h2o_mort_b = -6.390757e-11, -6.390757e-11, -6.390757e-11, + -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, + -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11 ; + + fates_trs_seedling_h2o_mort_c = 1.268992e-05, 1.268992e-05, 1.268992e-05, + 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, + 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05 ; + + fates_trs_seedling_light_mort_a = -0.009897694, -0.009897694, -0.009897694, + -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, + -0.009897694, -0.009897694, -0.009897694, -0.009897694 ; + + fates_trs_seedling_light_mort_b = -7.154063, -7.154063, -7.154063, + -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, + -7.154063, -7.154063, -7.154063 ; + + fates_trs_seedling_light_rec_a = 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, + 0.007, 0.007, 0.007, 0.007, 0.007, 0.007 ; + + fates_trs_seedling_light_rec_b = 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, + 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615 ; + + fates_trs_seedling_mdd_crit = 1400000, 1400000, 1400000, 1400000, 1400000, + 1400000, 1400000, 1400000, 1400000, 1400000, 1400000, 1400000 ; + + fates_trs_seedling_par_crit_germ = 0.656, 0.656, 0.656, 0.656, 0.656, 0.656, + 0.656, 0.656, 0.656, 0.656, 0.656, 0.656 ; + + fates_trs_seedling_psi_crit = -251995.7, -251995.7, -251995.7, -251995.7, + -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, + -251995.7, -251995.7 ; + + fates_trs_seedling_psi_emerg = -15744.65, -15744.65, -15744.65, -15744.65, + -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, + -15744.65, -15744.65 ; + + fates_trs_seedling_root_depth = 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, + 0.06, 0.06, 0.06, 0.06, 0.06 ; + + fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, + 0.67, 0.67, 0.67 ; + + fates_turb_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.04, 0.04, 0.04, 0.04 ; + + fates_turb_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, + 0.055, 0.055, 0.055, 0.055 ; + + fates_turnover_branch = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; + + fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_leaf = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_wood_density = 0.7, 0.4, 0.7, 0.53, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, + 0.7 ; + + fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; + + fates_hlm_pft_map = + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + + fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; + + fates_fire_low_moisture_Coeff = 1.12, 1.09, 0.98, 0.8, 1.15, 1.15 ; + + fates_fire_low_moisture_Slope = 0.62, 0.72, 0.85, 0.8, 0.62, 0.62 ; + + fates_fire_mid_moisture = 0.72, 0.51, 0.38, 1, 0.8, 0.8 ; + + fates_fire_mid_moisture_Coeff = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_mid_moisture_Slope = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_min_moisture = 0.18, 0.12, 0, 0, 0.24, 0.24 ; + + fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; + + fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; + + fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; + + fates_canopy_closure_thresh = 0.8 ; + + fates_cnp_eca_plant_escalar = 1.25e-05 ; + + fates_cohort_age_fusion_tol = 0.08 ; + + fates_cohort_size_fusion_tol = 0.08 ; + + fates_comp_excln = 3 ; + + fates_damage_canopy_layer_code = 1 ; + + fates_damage_event_code = 1 ; + + fates_dev_arbitrary = _ ; + + fates_fire_active_crown_fire = 0 ; + + fates_fire_cg_strikes = 0.2 ; + + fates_fire_drying_ratio = 66000 ; + + fates_fire_durat_slope = -11.06 ; + + fates_fire_fdi_a = 17.62 ; + + fates_fire_fdi_alpha = 0.00037 ; + + fates_fire_fdi_b = 243.12 ; + + fates_fire_fuel_energy = 18000 ; + + fates_fire_max_durat = 240 ; + + fates_fire_miner_damp = 0.41739 ; + + fates_fire_miner_total = 0.055 ; + + fates_fire_nignitions = 15 ; + + fates_fire_part_dens = 513 ; + + fates_fire_threshold = 50 ; + + fates_frag_cwd_fcel = 0.76 ; + + fates_frag_cwd_flig = 0.24 ; + + fates_hydro_kmax_rsurf1 = 20 ; + + fates_hydro_kmax_rsurf2 = 0.0001 ; + + fates_hydro_psi0 = 0 ; + + fates_hydro_psicap = -0.6 ; + + fates_hydro_solver = 1 ; + + fates_landuse_logging_coll_under_frac = 0.55983 ; + + fates_landuse_logging_collateral_frac = 0.05 ; + + fates_landuse_logging_dbhmax = _ ; + + fates_landuse_logging_dbhmax_infra = 35 ; + + fates_landuse_logging_dbhmin = 50 ; + + fates_landuse_logging_direct_frac = 0.15 ; + + fates_landuse_logging_event_code = -30 ; + + fates_landuse_logging_export_frac = 0.8 ; + + fates_landuse_logging_mechanical_frac = 0.05 ; + + fates_landuse_pprodharv10_forest_mean = 0.8125 ; + + fates_leaf_photo_temp_acclim_thome_time = 30 ; + + fates_leaf_photo_temp_acclim_timescale = 30 ; + + fates_leaf_photo_tempsens_model = 1 ; + + fates_leaf_stomatal_assim_model = 1 ; + + fates_leaf_stomatal_model = 1 ; + + fates_leaf_theta_cj_c3 = 0.999 ; + + fates_leaf_theta_cj_c4 = 0.999 ; + + fates_maintresp_leaf_model = 1 ; + + fates_maintresp_nonleaf_baserate = 2.525e-06 ; + + fates_maxcohort = 100 ; + + fates_maxpatch_primary = 10 ; + + fates_maxpatch_secondary = 4 ; + + fates_mort_disturb_frac = 1 ; + + fates_mort_understorey_death = 0.55983 ; + + fates_patch_fusion_tol = 0.05 ; + + fates_phen_chilltemp = 5 ; + + fates_phen_coldtemp = 7.5 ; + + fates_phen_gddthresh_a = -68 ; + + fates_phen_gddthresh_b = 638 ; + + fates_phen_gddthresh_c = -0.01 ; + + fates_phen_mindayson = 90 ; + + fates_phen_ncolddayslim = 5 ; + + fates_q10_froz = 1.5 ; + + fates_q10_mr = 1.5 ; + + fates_rad_model = 1 ; + + fates_regeneration_model = 1 ; + + fates_soil_salinity = 0.4 ; + + fates_trs_seedling2sap_par_timescale = 32 ; + + fates_trs_seedling_emerg_h2o_timescale = 7 ; + + fates_trs_seedling_mdd_timescale = 126 ; + + fates_trs_seedling_mort_par_timescale = 32 ; + + fates_vai_top_bin_width = 1 ; + + fates_vai_width_increase_factor = 1 ; +} From 4a6aca7ad434416448d1079fcd047402d5e491b3 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 24 Jul 2023 16:15:32 -0700 Subject: [PATCH 788/852] correct call to previously archived default (api25.5) --- parameter_files/archive/api25.5.0_072423_pr1005.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parameter_files/archive/api25.5.0_072423_pr1005.xml b/parameter_files/archive/api25.5.0_072423_pr1005.xml index 57a436e580..7dbc06d9ce 100644 --- a/parameter_files/archive/api25.5.0_072423_pr1005.xml +++ b/parameter_files/archive/api25.5.0_072423_pr1005.xml @@ -27,7 +27,7 @@ the variables --> - archive/api25.4.0_041023_fates_params_default.cdl + archive/api25.5.0_072423_fates_params_default.cdl fates_params_default.cdl 1,2,3,4,5,6,7,8,9,10,11,12 From c62e4011221b14a9f32192066b81b3c9b1d4c683 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 24 Jul 2023 16:19:00 -0700 Subject: [PATCH 789/852] remove archive and api update the default param file was updated with the seed dispersal parameters in api25.5 --- .../api25.5.0_072423_fates_params_default.cdl | 1735 ----------------- .../archive/api25.5.0_072423_pr1005.xml | 63 - 2 files changed, 1798 deletions(-) delete mode 100644 parameter_files/archive/api25.5.0_072423_fates_params_default.cdl delete mode 100644 parameter_files/archive/api25.5.0_072423_pr1005.xml diff --git a/parameter_files/archive/api25.5.0_072423_fates_params_default.cdl b/parameter_files/archive/api25.5.0_072423_fates_params_default.cdl deleted file mode 100644 index f170fe2275..0000000000 --- a/parameter_files/archive/api25.5.0_072423_fates_params_default.cdl +++ /dev/null @@ -1,1735 +0,0 @@ -netcdf fates_params_default { -dimensions: - fates_NCWD = 4 ; - fates_history_age_bins = 7 ; - fates_history_coage_bins = 2 ; - fates_history_damage_bins = 2 ; - fates_history_height_bins = 6 ; - fates_history_size_bins = 13 ; - fates_hlm_pftno = 14 ; - fates_hydr_organs = 4 ; - fates_leafage_class = 1 ; - fates_litterclass = 6 ; - fates_pft = 12 ; - fates_plant_organs = 4 ; - fates_string_length = 60 ; -variables: - double fates_history_ageclass_bin_edges(fates_history_age_bins) ; - fates_history_ageclass_bin_edges:units = "yr" ; - fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; - double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; - fates_history_coageclass_bin_edges:units = "years" ; - fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; - double fates_history_height_bin_edges(fates_history_height_bins) ; - fates_history_height_bin_edges:units = "m" ; - fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; - double fates_history_damage_bin_edges(fates_history_damage_bins) ; - fates_history_damage_bin_edges:units = "% crown loss" ; - fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; - double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; - fates_history_sizeclass_bin_edges:units = "cm" ; - fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; - double fates_alloc_organ_id(fates_plant_organs) ; - fates_alloc_organ_id:units = "unitless" ; - fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; - double fates_hydro_htftype_node(fates_hydr_organs) ; - fates_hydro_htftype_node:units = "unitless" ; - fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; - char fates_pftname(fates_pft, fates_string_length) ; - fates_pftname:units = "unitless - string" ; - fates_pftname:long_name = "Description of plant type" ; - char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; - fates_hydro_organ_name:units = "unitless - string" ; - fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; - char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; - fates_alloc_organ_name:units = "unitless - string" ; - fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; - 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" ; - 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" ; - double fates_alloc_storage_cushion(fates_pft) ; - fates_alloc_storage_cushion:units = "fraction" ; - fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; - double fates_alloc_store_priority_frac(fates_pft) ; - fates_alloc_store_priority_frac:units = "unitless" ; - fates_alloc_store_priority_frac:long_name = "for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage" ; - double fates_allom_agb1(fates_pft) ; - fates_allom_agb1:units = "variable" ; - fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; - double fates_allom_agb2(fates_pft) ; - fates_allom_agb2:units = "variable" ; - fates_allom_agb2:long_name = "Parameter 2 for agb allometry" ; - double fates_allom_agb3(fates_pft) ; - fates_allom_agb3:units = "variable" ; - fates_allom_agb3:long_name = "Parameter 3 for agb allometry" ; - double fates_allom_agb4(fates_pft) ; - fates_allom_agb4:units = "variable" ; - fates_allom_agb4:long_name = "Parameter 4 for agb allometry" ; - double fates_allom_agb_frac(fates_pft) ; - fates_allom_agb_frac:units = "fraction" ; - fates_allom_agb_frac:long_name = "Fraction of woody biomass that is above ground" ; - double fates_allom_amode(fates_pft) ; - fates_allom_amode:units = "index" ; - fates_allom_amode:long_name = "AGB allometry function index." ; - double fates_allom_blca_expnt_diff(fates_pft) ; - fates_allom_blca_expnt_diff:units = "unitless" ; - fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; - double fates_allom_cmode(fates_pft) ; - fates_allom_cmode:units = "index" ; - fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; - double fates_allom_crown_depth_frac(fates_pft) ; - fates_allom_crown_depth_frac:units = "fraction" ; - fates_allom_crown_depth_frac:long_name = "the depth of a cohort crown as a fraction of its height" ; - double fates_allom_d2bl1(fates_pft) ; - fates_allom_d2bl1:units = "variable" ; - fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; - double fates_allom_d2bl2(fates_pft) ; - fates_allom_d2bl2:units = "variable" ; - fates_allom_d2bl2:long_name = "Parameter 2 for d2bl allometry" ; - double fates_allom_d2bl3(fates_pft) ; - fates_allom_d2bl3:units = "unitless" ; - fates_allom_d2bl3:long_name = "Parameter 3 for d2bl allometry" ; - double fates_allom_d2ca_coefficient_max(fates_pft) ; - fates_allom_d2ca_coefficient_max:units = "m2 cm^(-1/beta)" ; - fates_allom_d2ca_coefficient_max:long_name = "max (savanna) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; - double fates_allom_d2ca_coefficient_min(fates_pft) ; - fates_allom_d2ca_coefficient_min:units = "m2 cm^(-1/beta)" ; - fates_allom_d2ca_coefficient_min:long_name = "min (forest) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; - double fates_allom_d2h1(fates_pft) ; - fates_allom_d2h1:units = "variable" ; - fates_allom_d2h1:long_name = "Parameter 1 for d2h allometry (intercept, or c)" ; - double fates_allom_d2h2(fates_pft) ; - fates_allom_d2h2:units = "variable" ; - fates_allom_d2h2:long_name = "Parameter 2 for d2h allometry (slope, or m)" ; - double fates_allom_d2h3(fates_pft) ; - fates_allom_d2h3:units = "variable" ; - fates_allom_d2h3:long_name = "Parameter 3 for d2h allometry (optional)" ; - double fates_allom_dbh_maxheight(fates_pft) ; - fates_allom_dbh_maxheight:units = "cm" ; - fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; - double fates_allom_fmode(fates_pft) ; - fates_allom_fmode:units = "index" ; - fates_allom_fmode:long_name = "fine root biomass allometry function index." ; - double fates_allom_fnrt_prof_a(fates_pft) ; - fates_allom_fnrt_prof_a:units = "unitless" ; - fates_allom_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; - double fates_allom_fnrt_prof_b(fates_pft) ; - fates_allom_fnrt_prof_b:units = "unitless" ; - fates_allom_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; - double fates_allom_fnrt_prof_mode(fates_pft) ; - fates_allom_fnrt_prof_mode:units = "index" ; - fates_allom_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; - double fates_allom_frbstor_repro(fates_pft) ; - fates_allom_frbstor_repro:units = "fraction" ; - fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; - double fates_allom_hmode(fates_pft) ; - fates_allom_hmode:units = "index" ; - fates_allom_hmode:long_name = "height allometry function index." ; - double fates_allom_l2fr(fates_pft) ; - fates_allom_l2fr:units = "gC/gC" ; - fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; - double fates_allom_la_per_sa_int(fates_pft) ; - fates_allom_la_per_sa_int:units = "m2/cm2" ; - fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; - double fates_allom_la_per_sa_slp(fates_pft) ; - fates_allom_la_per_sa_slp:units = "m2/cm2/m" ; - fates_allom_la_per_sa_slp:long_name = "Leaf area per sapwood area rate of change with height, slope (optional)" ; - double fates_allom_lmode(fates_pft) ; - fates_allom_lmode:units = "index" ; - fates_allom_lmode:long_name = "leaf biomass allometry function index." ; - double fates_allom_sai_scaler(fates_pft) ; - fates_allom_sai_scaler:units = "m2/m2" ; - fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; - double fates_allom_smode(fates_pft) ; - fates_allom_smode:units = "index" ; - fates_allom_smode:long_name = "sapwood allometry function index." ; - double fates_allom_stmode(fates_pft) ; - fates_allom_stmode:units = "index" ; - fates_allom_stmode:long_name = "storage allometry function index: 1) Storage proportional to leaf biomass (with trimming), 2) Storage proportional to maximum leaf biomass (not trimmed)" ; - double fates_allom_zroot_k(fates_pft) ; - fates_allom_zroot_k:units = "unitless" ; - fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; - double fates_allom_zroot_max_dbh(fates_pft) ; - fates_allom_zroot_max_dbh:units = "cm" ; - fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; - double fates_allom_zroot_max_z(fates_pft) ; - fates_allom_zroot_max_z:units = "m" ; - fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; - double fates_allom_zroot_min_dbh(fates_pft) ; - fates_allom_zroot_min_dbh:units = "cm" ; - fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; - double fates_allom_zroot_min_z(fates_pft) ; - fates_allom_zroot_min_z:units = "m" ; - fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; - double fates_c2b(fates_pft) ; - fates_c2b:units = "ratio" ; - fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; - double fates_cnp_eca_alpha_ptase(fates_pft) ; - fates_cnp_eca_alpha_ptase:units = "g/m3" ; - fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; - double fates_cnp_eca_decompmicc(fates_pft) ; - fates_cnp_eca_decompmicc:units = "gC/m3" ; - fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; - double fates_cnp_eca_km_nh4(fates_pft) ; - fates_cnp_eca_km_nh4:units = "gN/m3" ; - fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; - double fates_cnp_eca_km_no3(fates_pft) ; - fates_cnp_eca_km_no3:units = "gN/m3" ; - fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; - double fates_cnp_eca_km_p(fates_pft) ; - fates_cnp_eca_km_p:units = "gP/m3" ; - fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; - double fates_cnp_eca_km_ptase(fates_pft) ; - fates_cnp_eca_km_ptase:units = "gP/m3" ; - fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; - double fates_cnp_eca_lambda_ptase(fates_pft) ; - fates_cnp_eca_lambda_ptase:units = "g/m3" ; - fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; - double fates_cnp_eca_vmax_ptase(fates_pft) ; - fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; - fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; - double fates_cnp_nfix1(fates_pft) ; - fates_cnp_nfix1:units = "fraction" ; - fates_cnp_nfix1:long_name = "fractional surcharge added to maintenance respiration that drives symbiotic fixation" ; - double fates_cnp_nitr_store_ratio(fates_pft) ; - fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; - fates_cnp_nitr_store_ratio:long_name = "storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code)" ; - double fates_cnp_phos_store_ratio(fates_pft) ; - fates_cnp_phos_store_ratio:units = "(gP/gP)" ; - fates_cnp_phos_store_ratio:long_name = "storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code)" ; - double fates_cnp_pid_kd(fates_pft) ; - fates_cnp_pid_kd:units = "unknown" ; - fates_cnp_pid_kd:long_name = "derivative constant of the PID controller on adaptive fine-root biomass" ; - double fates_cnp_pid_ki(fates_pft) ; - fates_cnp_pid_ki:units = "unknown" ; - fates_cnp_pid_ki:long_name = "integral constant of the PID controller on adaptive fine-root biomass" ; - double fates_cnp_pid_kp(fates_pft) ; - fates_cnp_pid_kp:units = "unknown" ; - fates_cnp_pid_kp:long_name = "proportional constant of the PID controller on adaptive fine-root biomass" ; - double fates_cnp_prescribed_nuptake(fates_pft) ; - fates_cnp_prescribed_nuptake:units = "fraction" ; - fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; - double fates_cnp_prescribed_puptake(fates_pft) ; - fates_cnp_prescribed_puptake:units = "fraction" ; - fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; - double fates_cnp_store_ovrflw_frac(fates_pft) ; - fates_cnp_store_ovrflw_frac:units = "fraction" ; - fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; - double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; - fates_cnp_turnover_nitr_retrans:units = "fraction" ; - fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; - double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; - fates_cnp_turnover_phos_retrans:units = "fraction" ; - fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; - double fates_cnp_vmax_nh4(fates_pft) ; - fates_cnp_vmax_nh4:units = "gN/gC/s" ; - fates_cnp_vmax_nh4:long_name = "maximum (potential) uptake rate of NH4 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_nh4 for usage)" ; - double fates_cnp_vmax_no3(fates_pft) ; - fates_cnp_vmax_no3:units = "gN/gC/s" ; - fates_cnp_vmax_no3:long_name = "maximum (potential) uptake rate of NO3 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_no3 for usage)" ; - double fates_cnp_vmax_p(fates_pft) ; - fates_cnp_vmax_p:units = "gP/gC/s" ; - fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; - double fates_damage_frac(fates_pft) ; - fates_damage_frac:units = "fraction" ; - fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; - double fates_damage_mort_p1(fates_pft) ; - fates_damage_mort_p1:units = "fraction" ; - fates_damage_mort_p1:long_name = "inflection point of damage mortality function, a value of 0.8 means 50% mortality with 80% loss of crown, turn off with a large number" ; - double fates_damage_mort_p2(fates_pft) ; - fates_damage_mort_p2:units = "unitless" ; - fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; - 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_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" ; - double fates_fire_alpha_SH(fates_pft) ; - fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; - fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; - double fates_fire_bark_scaler(fates_pft) ; - fates_fire_bark_scaler:units = "fraction" ; - fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; - double fates_fire_crown_kill(fates_pft) ; - fates_fire_crown_kill:units = "NA" ; - fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; - double fates_frag_fnrt_fcel(fates_pft) ; - fates_frag_fnrt_fcel:units = "fraction" ; - fates_frag_fnrt_fcel:long_name = "Fine root litter cellulose fraction" ; - double fates_frag_fnrt_flab(fates_pft) ; - fates_frag_fnrt_flab:units = "fraction" ; - fates_frag_fnrt_flab:long_name = "Fine root litter labile fraction" ; - double fates_frag_fnrt_flig(fates_pft) ; - fates_frag_fnrt_flig:units = "fraction" ; - fates_frag_fnrt_flig:long_name = "Fine root litter lignin fraction" ; - double fates_frag_leaf_fcel(fates_pft) ; - fates_frag_leaf_fcel:units = "fraction" ; - fates_frag_leaf_fcel:long_name = "Leaf litter cellulose fraction" ; - double fates_frag_leaf_flab(fates_pft) ; - fates_frag_leaf_flab:units = "fraction" ; - fates_frag_leaf_flab:long_name = "Leaf litter labile fraction" ; - double fates_frag_leaf_flig(fates_pft) ; - fates_frag_leaf_flig:units = "fraction" ; - fates_frag_leaf_flig:long_name = "Leaf litter lignin fraction" ; - double fates_frag_seed_decay_rate(fates_pft) ; - fates_frag_seed_decay_rate:units = "yr-1" ; - fates_frag_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; - double fates_grperc(fates_pft) ; - fates_grperc:units = "unitless" ; - fates_grperc:long_name = "Growth respiration factor" ; - double fates_hydro_avuln_gs(fates_pft) ; - fates_hydro_avuln_gs:units = "unitless" ; - fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; - double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; - fates_hydro_avuln_node:units = "unitless" ; - fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; - double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; - fates_hydro_epsil_node:units = "MPa" ; - fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; - double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; - fates_hydro_fcap_node:units = "unitless" ; - fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; - double fates_hydro_k_lwp(fates_pft) ; - fates_hydro_k_lwp:units = "unitless" ; - fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; - double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; - fates_hydro_kmax_node:units = "kg/MPa/m/s" ; - fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; - double fates_hydro_p50_gs(fates_pft) ; - fates_hydro_p50_gs:units = "MPa" ; - fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; - double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; - fates_hydro_p50_node:units = "MPa" ; - fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; - double fates_hydro_p_taper(fates_pft) ; - fates_hydro_p_taper:units = "unitless" ; - fates_hydro_p_taper:long_name = "xylem taper exponent" ; - double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; - fates_hydro_pinot_node:units = "MPa" ; - fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; - double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; - fates_hydro_pitlp_node:units = "MPa" ; - fates_hydro_pitlp_node:long_name = "turgor loss point" ; - double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; - fates_hydro_resid_node:units = "cm3/cm3" ; - fates_hydro_resid_node:long_name = "residual water conent" ; - double fates_hydro_rfrac_stem(fates_pft) ; - fates_hydro_rfrac_stem:units = "fraction" ; - fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; - double fates_hydro_rs2(fates_pft) ; - fates_hydro_rs2:units = "m" ; - fates_hydro_rs2:long_name = "absorbing root radius" ; - double fates_hydro_srl(fates_pft) ; - fates_hydro_srl:units = "m g-1" ; - fates_hydro_srl:long_name = "specific root length" ; - double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; - fates_hydro_thetas_node:units = "cm3/cm3" ; - fates_hydro_thetas_node:long_name = "saturated water content" ; - double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; - fates_hydro_vg_alpha_node:units = "MPa-1" ; - fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; - double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; - fates_hydro_vg_m_node:units = "unitless" ; - fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; - 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_leaf_c3psn(fates_pft) ; - fates_leaf_c3psn:units = "flag" ; - fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; - double fates_leaf_jmaxha(fates_pft) ; - fates_leaf_jmaxha:units = "J/mol" ; - fates_leaf_jmaxha:long_name = "activation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; - double fates_leaf_jmaxhd(fates_pft) ; - fates_leaf_jmaxhd:units = "J/mol" ; - fates_leaf_jmaxhd:long_name = "deactivation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; - double fates_leaf_jmaxse(fates_pft) ; - fates_leaf_jmaxse:units = "J/mol/K" ; - fates_leaf_jmaxse:long_name = "entropy term for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; - double fates_leaf_slamax(fates_pft) ; - fates_leaf_slamax:units = "m^2/gC" ; - fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; - double fates_leaf_slatop(fates_pft) ; - fates_leaf_slatop:units = "m^2/gC" ; - fates_leaf_slatop:long_name = "Specific Leaf Area (SLA) at top of canopy, projected area basis" ; - double fates_leaf_stomatal_intercept(fates_pft) ; - fates_leaf_stomatal_intercept:units = "umol H2O/m**2/s" ; - fates_leaf_stomatal_intercept:long_name = "Minimum unstressed stomatal conductance for Ball-Berry model and Medlyn model" ; - double fates_leaf_stomatal_slope_ballberry(fates_pft) ; - fates_leaf_stomatal_slope_ballberry:units = "unitless" ; - fates_leaf_stomatal_slope_ballberry:long_name = "stomatal slope parameter, as per Ball-Berry" ; - double fates_leaf_stomatal_slope_medlyn(fates_pft) ; - fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; - fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; - double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; - fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; - fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; - double fates_leaf_vcmaxha(fates_pft) ; - fates_leaf_vcmaxha:units = "J/mol" ; - fates_leaf_vcmaxha:long_name = "activation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; - double fates_leaf_vcmaxhd(fates_pft) ; - fates_leaf_vcmaxhd:units = "J/mol" ; - fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; - double fates_leaf_vcmaxse(fates_pft) ; - fates_leaf_vcmaxse:units = "J/mol/K" ; - fates_leaf_vcmaxse:long_name = "entropy term for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; - double fates_maintresp_leaf_atkin2017_baserate(fates_pft) ; - fates_maintresp_leaf_atkin2017_baserate:units = "umol CO2/m^2/s" ; - fates_maintresp_leaf_atkin2017_baserate:long_name = "Leaf maintenance respiration base rate parameter (r0) per Atkin et al 2017" ; - double fates_maintresp_leaf_ryan1991_baserate(fates_pft) ; - fates_maintresp_leaf_ryan1991_baserate:units = "gC/gN/s" ; - fates_maintresp_leaf_ryan1991_baserate:long_name = "Leaf maintenance respiration base rate per Ryan et al 1991" ; - double fates_maintresp_reduction_curvature(fates_pft) ; - fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; - fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; - double fates_maintresp_reduction_intercept(fates_pft) ; - fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; - fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; - double fates_maintresp_reduction_upthresh(fates_pft) ; - fates_maintresp_reduction_upthresh:units = "unitless (0-1)" ; - fates_maintresp_reduction_upthresh:long_name = "upper threshold for storage biomass (relative to leaf biomass) above which MR is not reduced" ; - double fates_mort_bmort(fates_pft) ; - fates_mort_bmort:units = "1/yr" ; - fates_mort_bmort:long_name = "background mortality rate" ; - double fates_mort_freezetol(fates_pft) ; - fates_mort_freezetol:units = "degrees C" ; - fates_mort_freezetol:long_name = "minimum temperature tolerance" ; - double fates_mort_hf_flc_threshold(fates_pft) ; - fates_mort_hf_flc_threshold:units = "fraction" ; - fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; - double fates_mort_hf_sm_threshold(fates_pft) ; - fates_mort_hf_sm_threshold:units = "unitless" ; - fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; - double fates_mort_ip_age_senescence(fates_pft) ; - fates_mort_ip_age_senescence:units = "years" ; - fates_mort_ip_age_senescence:long_name = "Mortality cohort age senescence inflection point. If _ this mortality term is off. Setting this value turns on age dependent mortality. " ; - double fates_mort_ip_size_senescence(fates_pft) ; - fates_mort_ip_size_senescence:units = "dbh cm" ; - fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; - double fates_mort_prescribed_canopy(fates_pft) ; - fates_mort_prescribed_canopy:units = "1/yr" ; - fates_mort_prescribed_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; - double fates_mort_prescribed_understory(fates_pft) ; - fates_mort_prescribed_understory:units = "1/yr" ; - fates_mort_prescribed_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; - double fates_mort_r_age_senescence(fates_pft) ; - fates_mort_r_age_senescence:units = "mortality rate year^-1" ; - fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; - double fates_mort_r_size_senescence(fates_pft) ; - fates_mort_r_size_senescence:units = "mortality rate dbh^-1" ; - fates_mort_r_size_senescence:long_name = "Mortality dbh senescence rate of change. Sensible range is around 0.03-0.06. Larger values give steeper mortality curves." ; - double fates_mort_scalar_coldstress(fates_pft) ; - fates_mort_scalar_coldstress:units = "1/yr" ; - fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; - double fates_mort_scalar_cstarvation(fates_pft) ; - fates_mort_scalar_cstarvation:units = "1/yr" ; - fates_mort_scalar_cstarvation:long_name = "maximum mortality rate from carbon starvation" ; - double fates_mort_scalar_hydrfailure(fates_pft) ; - fates_mort_scalar_hydrfailure:units = "1/yr" ; - fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; - double fates_mort_upthresh_cstarvation(fates_pft) ; - fates_mort_upthresh_cstarvation:units = "unitless" ; - fates_mort_upthresh_cstarvation:long_name = "threshold for storage biomass (relative to target leaf biomass) above which carbon starvation is zero" ; - double fates_nonhydro_smpsc(fates_pft) ; - fates_nonhydro_smpsc:units = "mm" ; - fates_nonhydro_smpsc:long_name = "Soil water potential at full stomatal closure" ; - double fates_nonhydro_smpso(fates_pft) ; - fates_nonhydro_smpso:units = "mm" ; - fates_nonhydro_smpso:long_name = "Soil water potential at full stomatal opening" ; - double fates_phen_cold_size_threshold(fates_pft) ; - fates_phen_cold_size_threshold:units = "cm" ; - fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; - double fates_phen_drought_threshold(fates_pft) ; - fates_phen_drought_threshold:units = "m3/m3 or mm" ; - fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold for semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; - double fates_phen_evergreen(fates_pft) ; - fates_phen_evergreen:units = "logical flag" ; - fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; - double fates_phen_flush_fraction(fates_pft) ; - fates_phen_flush_fraction:units = "fraction" ; - fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; - double fates_phen_fnrt_drop_fraction(fates_pft) ; - fates_phen_fnrt_drop_fraction:units = "fraction" ; - fates_phen_fnrt_drop_fraction:long_name = "fraction of fine roots to drop during drought/cold" ; - double fates_phen_mindaysoff(fates_pft) ; - fates_phen_mindaysoff:units = "days" ; - fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves abscised (shed)" ; - double fates_phen_moist_threshold(fates_pft) ; - fates_phen_moist_threshold:units = "m3/m3 or mm" ; - fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for drought semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; - double fates_phen_season_decid(fates_pft) ; - fates_phen_season_decid:units = "logical flag" ; - fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; - double fates_phen_stem_drop_fraction(fates_pft) ; - fates_phen_stem_drop_fraction:units = "fraction" ; - fates_phen_stem_drop_fraction:long_name = "fraction of stems to drop for non-woody species during drought/cold" ; - double fates_phen_stress_decid(fates_pft) ; - fates_phen_stress_decid:units = "logical flag" ; - fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; - double fates_prescribed_npp_canopy(fates_pft) ; - fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; - fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; - double fates_prescribed_npp_understory(fates_pft) ; - fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; - fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; - double fates_rad_leaf_clumping_index(fates_pft) ; - fates_rad_leaf_clumping_index:units = "fraction (0-1)" ; - fates_rad_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; - double fates_rad_leaf_rhonir(fates_pft) ; - fates_rad_leaf_rhonir:units = "fraction" ; - fates_rad_leaf_rhonir:long_name = "Leaf reflectance: near-IR" ; - double fates_rad_leaf_rhovis(fates_pft) ; - fates_rad_leaf_rhovis:units = "fraction" ; - fates_rad_leaf_rhovis:long_name = "Leaf reflectance: visible" ; - double fates_rad_leaf_taunir(fates_pft) ; - fates_rad_leaf_taunir:units = "fraction" ; - fates_rad_leaf_taunir:long_name = "Leaf transmittance: near-IR" ; - double fates_rad_leaf_tauvis(fates_pft) ; - fates_rad_leaf_tauvis:units = "fraction" ; - fates_rad_leaf_tauvis:long_name = "Leaf transmittance: visible" ; - double fates_rad_leaf_xl(fates_pft) ; - fates_rad_leaf_xl:units = "unitless" ; - fates_rad_leaf_xl:long_name = "Leaf/stem orientation index" ; - double fates_rad_stem_rhonir(fates_pft) ; - fates_rad_stem_rhonir:units = "fraction" ; - fates_rad_stem_rhonir:long_name = "Stem reflectance: near-IR" ; - double fates_rad_stem_rhovis(fates_pft) ; - fates_rad_stem_rhovis:units = "fraction" ; - fates_rad_stem_rhovis:long_name = "Stem reflectance: visible" ; - double fates_rad_stem_taunir(fates_pft) ; - fates_rad_stem_taunir:units = "fraction" ; - fates_rad_stem_taunir:long_name = "Stem transmittance: near-IR" ; - double fates_rad_stem_tauvis(fates_pft) ; - fates_rad_stem_tauvis:units = "fraction" ; - fates_rad_stem_tauvis:long_name = "Stem transmittance: visible" ; - double fates_recruit_height_min(fates_pft) ; - fates_recruit_height_min:units = "m" ; - fates_recruit_height_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; - double fates_recruit_init_density(fates_pft) ; - fates_recruit_init_density:units = "stems/m2" ; - fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation. If negative sets initial tree dbh - only to be used in nocomp mode" ; - double fates_recruit_prescribed_rate(fates_pft) ; - fates_recruit_prescribed_rate:units = "n/yr" ; - fates_recruit_prescribed_rate:long_name = "recruitment rate for prescribed physiology mode" ; - double fates_recruit_seed_alloc(fates_pft) ; - fates_recruit_seed_alloc:units = "fraction" ; - fates_recruit_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; - double fates_recruit_seed_alloc_mature(fates_pft) ; - fates_recruit_seed_alloc_mature:units = "fraction" ; - fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; - double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; - fates_recruit_seed_dbh_repro_threshold:units = "cm" ; - fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter where the plant will increase allocation to the seed pool by fraction: fates_recruit_seed_alloc_mature" ; - double fates_recruit_seed_germination_rate(fates_pft) ; - fates_recruit_seed_germination_rate:units = "yr-1" ; - fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; - double fates_recruit_seed_supplement(fates_pft) ; - fates_recruit_seed_supplement:units = "KgC/m2/yr" ; - fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; - double fates_seed_dispersal_fraction(fates_pft) ; - fates_seed_dispersal_fraction:units = "fraction" ; - fates_seed_dispersal_fraction:long_name = "fraction of seed rain to be dispersed to other grid cells" ; - double fates_seed_dispersal_max_dist(fates_pft) ; - fates_seed_dispersal_max_dist:units = "m" ; - fates_seed_dispersal_max_dist:long_name = "maximum seed dispersal distance for a given pft" ; - double fates_seed_dispersal_pdf_scale(fates_pft) ; - fates_seed_dispersal_pdf_scale:units = "unitless" ; - fates_seed_dispersal_pdf_scale:long_name = "seed dispersal probability density function scale parameter, A, Table 1 Bullock et al 2016" ; - double fates_seed_dispersal_pdf_shape(fates_pft) ; - fates_seed_dispersal_pdf_shape:units = "unitless" ; - fates_seed_dispersal_pdf_shape:long_name = "seed dispersal probability density function shape parameter, B, Table 1 Bullock et al 2016" ; - double fates_stoich_nitr(fates_plant_organs, fates_pft) ; - fates_stoich_nitr:units = "gN/gC" ; - fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; - double fates_stoich_phos(fates_plant_organs, fates_pft) ; - fates_stoich_phos:units = "gP/gC" ; - fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; - double fates_trim_inc(fates_pft) ; - fates_trim_inc:units = "m2/m2" ; - fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; - double fates_trim_limit(fates_pft) ; - fates_trim_limit:units = "m2/m2" ; - fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; - double fates_trs_repro_alloc_a(fates_pft) ; - fates_trs_repro_alloc_a:units = "fraction" ; - fates_trs_repro_alloc_a:long_name = "shape parameter for sigmoidal function relating dbh to reproductive allocation" ; - double fates_trs_repro_alloc_b(fates_pft) ; - fates_trs_repro_alloc_b:units = "fraction" ; - fates_trs_repro_alloc_b:long_name = "intercept parameter for sigmoidal function relating dbh to reproductive allocation" ; - double fates_trs_repro_frac_seed(fates_pft) ; - fates_trs_repro_frac_seed:units = "fraction" ; - fates_trs_repro_frac_seed:long_name = "fraction of reproductive mass that is seed" ; - double fates_trs_seedling_a_emerg(fates_pft) ; - fates_trs_seedling_a_emerg:units = "day -1" ; - fates_trs_seedling_a_emerg:long_name = "mean fraction of seed bank emerging" ; - double fates_trs_seedling_b_emerg(fates_pft) ; - fates_trs_seedling_b_emerg:units = "day -1" ; - fates_trs_seedling_b_emerg:long_name = "seedling emergence sensitivity to soil moisture" ; - double fates_trs_seedling_background_mort(fates_pft) ; - fates_trs_seedling_background_mort:units = "yr-1" ; - fates_trs_seedling_background_mort:long_name = "background seedling mortality rate" ; - double fates_trs_seedling_h2o_mort_a(fates_pft) ; - fates_trs_seedling_h2o_mort_a:units = "-" ; - fates_trs_seedling_h2o_mort_a:long_name = "coefficient in moisture-based seedling mortality" ; - double fates_trs_seedling_h2o_mort_b(fates_pft) ; - fates_trs_seedling_h2o_mort_b:units = "-" ; - fates_trs_seedling_h2o_mort_b:long_name = "coefficient in moisture-based seedling mortality" ; - double fates_trs_seedling_h2o_mort_c(fates_pft) ; - fates_trs_seedling_h2o_mort_c:units = "-" ; - fates_trs_seedling_h2o_mort_c:long_name = "coefficient in moisture-based seedling mortality" ; - double fates_trs_seedling_light_mort_a(fates_pft) ; - fates_trs_seedling_light_mort_a:units = "-" ; - fates_trs_seedling_light_mort_a:long_name = "light-based seedling mortality coefficient" ; - double fates_trs_seedling_light_mort_b(fates_pft) ; - fates_trs_seedling_light_mort_b:units = "-" ; - fates_trs_seedling_light_mort_b:long_name = "light-based seedling mortality coefficient" ; - double fates_trs_seedling_light_rec_a(fates_pft) ; - fates_trs_seedling_light_rec_a:units = "-" ; - fates_trs_seedling_light_rec_a:long_name = "coefficient in light-based seedling to sapling transition" ; - double fates_trs_seedling_light_rec_b(fates_pft) ; - fates_trs_seedling_light_rec_b:units = "-" ; - fates_trs_seedling_light_rec_b:long_name = "coefficient in light-based seedling to sapling transition" ; - double fates_trs_seedling_mdd_crit(fates_pft) ; - fates_trs_seedling_mdd_crit:units = "mm H2O day" ; - fates_trs_seedling_mdd_crit:long_name = "critical moisture deficit (suction) day accumulation for seedling moisture-based seedling mortality to begin" ; - double fates_trs_seedling_par_crit_germ(fates_pft) ; - fates_trs_seedling_par_crit_germ:units = "MJ m-2 day-1" ; - fates_trs_seedling_par_crit_germ:long_name = "critical light level for germination" ; - double fates_trs_seedling_psi_crit(fates_pft) ; - fates_trs_seedling_psi_crit:units = "mm H2O" ; - fates_trs_seedling_psi_crit:long_name = "critical soil moisture (suction) for seedling stress" ; - double fates_trs_seedling_psi_emerg(fates_pft) ; - fates_trs_seedling_psi_emerg:units = "mm h20 suction" ; - fates_trs_seedling_psi_emerg:long_name = "critical soil moisture for seedling emergence" ; - double fates_trs_seedling_root_depth(fates_pft) ; - fates_trs_seedling_root_depth:units = "m" ; - fates_trs_seedling_root_depth:long_name = "rooting depth of seedlings" ; - double fates_turb_displar(fates_pft) ; - fates_turb_displar:units = "unitless" ; - fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; - double fates_turb_leaf_diameter(fates_pft) ; - fates_turb_leaf_diameter:units = "m" ; - fates_turb_leaf_diameter:long_name = "Characteristic leaf dimension" ; - double fates_turb_z0mr(fates_pft) ; - fates_turb_z0mr:units = "unitless" ; - fates_turb_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; - double fates_turnover_branch(fates_pft) ; - fates_turnover_branch:units = "yr" ; - fates_turnover_branch:long_name = "turnover time of branches" ; - double fates_turnover_fnrt(fates_pft) ; - fates_turnover_fnrt:units = "yr" ; - fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; - double fates_turnover_leaf(fates_leafage_class, fates_pft) ; - fates_turnover_leaf:units = "yr" ; - fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale). For drought-deciduous PFTs, this also indicates the maximum length of the growing (i.e., leaves on) season." ; - double fates_turnover_senleaf_fdrought(fates_pft) ; - fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; - fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; - double fates_wood_density(fates_pft) ; - fates_wood_density:units = "g/cm3" ; - fates_wood_density:long_name = "mean density of woody tissue in plant" ; - double fates_woody(fates_pft) ; - fates_woody:units = "logical flag" ; - fates_woody:long_name = "Binary woody lifeform flag" ; - double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; - fates_hlm_pft_map:units = "area fraction" ; - fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; - double fates_fire_FBD(fates_litterclass) ; - fates_fire_FBD:units = "kg Biomass/m3" ; - fates_fire_FBD:long_name = "fuel bulk density" ; - double fates_fire_low_moisture_Coeff(fates_litterclass) ; - fates_fire_low_moisture_Coeff:units = "NA" ; - fates_fire_low_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_low_moisture_Slope(fates_litterclass) ; - fates_fire_low_moisture_Slope:units = "NA" ; - fates_fire_low_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_mid_moisture(fates_litterclass) ; - fates_fire_mid_moisture:units = "NA" ; - fates_fire_mid_moisture:long_name = "spitfire litter moisture threshold to be considered medium dry" ; - double fates_fire_mid_moisture_Coeff(fates_litterclass) ; - fates_fire_mid_moisture_Coeff:units = "NA" ; - fates_fire_mid_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_mid_moisture_Slope(fates_litterclass) ; - fates_fire_mid_moisture_Slope:units = "NA" ; - fates_fire_mid_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_min_moisture(fates_litterclass) ; - fates_fire_min_moisture:units = "NA" ; - fates_fire_min_moisture:long_name = "spitfire litter moisture threshold to be considered very dry" ; - double fates_fire_SAV(fates_litterclass) ; - fates_fire_SAV:units = "cm-1" ; - fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; - double fates_frag_maxdecomp(fates_litterclass) ; - fates_frag_maxdecomp:units = "yr-1" ; - fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; - 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_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" ; - double fates_cnp_eca_plant_escalar ; - fates_cnp_eca_plant_escalar:units = "" ; - fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; - double fates_cohort_age_fusion_tol ; - fates_cohort_age_fusion_tol:units = "unitless" ; - fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; - double fates_cohort_size_fusion_tol ; - fates_cohort_size_fusion_tol:units = "unitless" ; - fates_cohort_size_fusion_tol:long_name = "minimum fraction in difference in dbh between cohorts" ; - double fates_comp_excln ; - fates_comp_excln:units = "none" ; - fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; - double fates_damage_canopy_layer_code ; - fates_damage_canopy_layer_code:units = "unitless" ; - fates_damage_canopy_layer_code:long_name = "Integer code that decides whether damage affects canopy trees (1), understory trees (2)" ; - double fates_damage_event_code ; - fates_damage_event_code:units = "unitless" ; - fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; - double fates_dev_arbitrary ; - fates_dev_arbitrary:units = "unknown" ; - fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; - double fates_fire_active_crown_fire ; - fates_fire_active_crown_fire:units = "0 or 1" ; - fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; - double fates_fire_cg_strikes ; - fates_fire_cg_strikes:units = "fraction (0-1)" ; - fates_fire_cg_strikes:long_name = "fraction of cloud to ground lightning strikes" ; - double fates_fire_drying_ratio ; - fates_fire_drying_ratio:units = "NA" ; - fates_fire_drying_ratio:long_name = "spitfire parameter, fire drying ratio for fuel moisture, alpha_FMC EQ 6 Thonicke et al 2010" ; - double fates_fire_durat_slope ; - fates_fire_durat_slope:units = "NA" ; - fates_fire_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; - double fates_fire_fdi_a ; - fates_fire_fdi_a:units = "NA" ; - fates_fire_fdi_a:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010" ; - double fates_fire_fdi_alpha ; - fates_fire_fdi_alpha:units = "NA" ; - fates_fire_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; - double fates_fire_fdi_b ; - fates_fire_fdi_b:units = "NA" ; - fates_fire_fdi_b:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010 " ; - double fates_fire_fuel_energy ; - fates_fire_fuel_energy:units = "kJ/kg" ; - fates_fire_fuel_energy:long_name = "spitfire parameter, heat content of fuel" ; - double fates_fire_max_durat ; - fates_fire_max_durat:units = "minutes" ; - fates_fire_max_durat:long_name = "spitfire parameter, fire maximum duration, Equation 14 Thonicke et al 2010" ; - double fates_fire_miner_damp ; - fates_fire_miner_damp:units = "NA" ; - fates_fire_miner_damp:long_name = "spitfire parameter, mineral-dampening coefficient EQ A1 Thonicke et al 2010 " ; - double fates_fire_miner_total ; - fates_fire_miner_total:units = "fraction" ; - fates_fire_miner_total:long_name = "spitfire parameter, total mineral content, Table A1 Thonicke et al 2010" ; - double fates_fire_nignitions ; - fates_fire_nignitions:units = "ignitions per year per km2" ; - fates_fire_nignitions:long_name = "number of annual ignitions per square km" ; - double fates_fire_part_dens ; - fates_fire_part_dens:units = "kg/m2" ; - fates_fire_part_dens:long_name = "spitfire parameter, oven dry particle density, Table A1 Thonicke et al 2010" ; - double fates_fire_threshold ; - fates_fire_threshold:units = "kW/m" ; - fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; - double fates_frag_cwd_fcel ; - fates_frag_cwd_fcel:units = "unitless" ; - fates_frag_cwd_fcel:long_name = "Cellulose fraction for CWD" ; - double fates_frag_cwd_flig ; - fates_frag_cwd_flig:units = "unitless" ; - fates_frag_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; - double fates_hydro_kmax_rsurf1 ; - fates_hydro_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; - fates_hydro_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; - double fates_hydro_kmax_rsurf2 ; - fates_hydro_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; - fates_hydro_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; - double fates_hydro_psi0 ; - fates_hydro_psi0:units = "MPa" ; - fates_hydro_psi0:long_name = "sapwood water potential at saturation" ; - double fates_hydro_psicap ; - fates_hydro_psicap:units = "MPa" ; - fates_hydro_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; - 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_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" ; - double fates_landuse_logging_collateral_frac ; - fates_landuse_logging_collateral_frac:units = "fraction" ; - fates_landuse_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; - double fates_landuse_logging_dbhmax ; - fates_landuse_logging_dbhmax:units = "cm" ; - fates_landuse_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; - double fates_landuse_logging_dbhmax_infra ; - fates_landuse_logging_dbhmax_infra:units = "cm" ; - fates_landuse_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; - double fates_landuse_logging_dbhmin ; - fates_landuse_logging_dbhmin:units = "cm" ; - fates_landuse_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; - double fates_landuse_logging_direct_frac ; - fates_landuse_logging_direct_frac:units = "fraction" ; - fates_landuse_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; - double fates_landuse_logging_event_code ; - fates_landuse_logging_event_code:units = "unitless" ; - fates_landuse_logging_event_code:long_name = "Integer code that options how logging events are structured" ; - double fates_landuse_logging_export_frac ; - fates_landuse_logging_export_frac:units = "fraction" ; - fates_landuse_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; - double fates_landuse_logging_mechanical_frac ; - fates_landuse_logging_mechanical_frac:units = "fraction" ; - fates_landuse_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; - double fates_landuse_pprodharv10_forest_mean ; - fates_landuse_pprodharv10_forest_mean:units = "fraction" ; - fates_landuse_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; - double fates_leaf_photo_temp_acclim_thome_time ; - fates_leaf_photo_temp_acclim_thome_time:units = "years" ; - fates_leaf_photo_temp_acclim_thome_time:long_name = "Length of the window for the long-term (i.e. T_home in Kumarathunge et al 2019) exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_leaf_photo_tempsens_model = 2)" ; - double fates_leaf_photo_temp_acclim_timescale ; - fates_leaf_photo_temp_acclim_timescale:units = "days" ; - fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_maintresp_leaf_model=2 or fates_leaf_photo_tempsens_model = 2)" ; - double fates_leaf_photo_tempsens_model ; - fates_leaf_photo_tempsens_model:units = "unitless" ; - fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating; 2=Kumarathunge et al 2019" ; - double fates_leaf_stomatal_assim_model ; - fates_leaf_stomatal_assim_model:units = "unitless" ; - fates_leaf_stomatal_assim_model:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; - double fates_leaf_stomatal_model ; - fates_leaf_stomatal_model:units = "unitless" ; - fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; - double fates_leaf_theta_cj_c3 ; - fates_leaf_theta_cj_c3:units = "unitless" ; - fates_leaf_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; - double fates_leaf_theta_cj_c4 ; - fates_leaf_theta_cj_c4:units = "unitless" ; - fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; - double fates_maintresp_leaf_model ; - fates_maintresp_leaf_model:units = "unitless" ; - fates_maintresp_leaf_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991), 2=Atkin et al., (2017)" ; - double fates_maintresp_nonleaf_baserate ; - fates_maintresp_nonleaf_baserate:units = "gC/gN/s" ; - fates_maintresp_nonleaf_baserate:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; - double fates_maxcohort ; - fates_maxcohort:units = "count" ; - fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; - double fates_maxpatch_primary ; - fates_maxpatch_primary:units = "count" ; - fates_maxpatch_primary:long_name = "maximum number of primary vegetation patches per site" ; - double fates_maxpatch_secondary ; - fates_maxpatch_secondary:units = "count" ; - fates_maxpatch_secondary:long_name = "maximum number of secondary vegetation patches per site" ; - double fates_mort_disturb_frac ; - fates_mort_disturb_frac:units = "fraction" ; - fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; - double fates_mort_understorey_death ; - fates_mort_understorey_death:units = "fraction" ; - fates_mort_understorey_death:long_name = "fraction of plants in understorey cohort impacted by overstorey tree-fall" ; - double fates_patch_fusion_tol ; - fates_patch_fusion_tol:units = "unitless" ; - fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; - double fates_phen_chilltemp ; - fates_phen_chilltemp:units = "degrees C" ; - fates_phen_chilltemp:long_name = "chilling day counting threshold for vegetation" ; - double fates_phen_coldtemp ; - fates_phen_coldtemp:units = "degrees C" ; - fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; - double fates_phen_gddthresh_a ; - fates_phen_gddthresh_a:units = "none" ; - fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_gddthresh_b ; - fates_phen_gddthresh_b:units = "none" ; - fates_phen_gddthresh_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_gddthresh_c ; - fates_phen_gddthresh_c:units = "none" ; - fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_mindayson ; - fates_phen_mindayson:units = "days" ; - fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; - double fates_phen_ncolddayslim ; - fates_phen_ncolddayslim:units = "days" ; - fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; - double fates_q10_froz ; - fates_q10_froz:units = "unitless" ; - fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; - double fates_q10_mr ; - fates_q10_mr:units = "unitless" ; - fates_q10_mr:long_name = "Q10 for maintenance respiration" ; - double fates_rad_model ; - fates_rad_model:units = "unitless" ; - fates_rad_model:long_name = "switch designating the model for canopy radiation, 1 = Norman, 2 = Two-stream (experimental)" ; - double fates_regeneration_model ; - fates_regeneration_model:units = "-" ; - fates_regeneration_model:long_name = "switch for choosing between FATES\'s: 1) default regeneration scheme , 2) the Tree Recruitment Scheme (Hanbury-Brown et al., 2022), or (3) the Tree Recruitment Scheme without seedling dynamics" ; - double fates_soil_salinity ; - fates_soil_salinity:units = "ppt" ; - fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; - double fates_trs_seedling2sap_par_timescale ; - fates_trs_seedling2sap_par_timescale:units = "days" ; - fates_trs_seedling2sap_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling to sapling transition rates" ; - double fates_trs_seedling_emerg_h2o_timescale ; - fates_trs_seedling_emerg_h2o_timescale:units = "days" ; - fates_trs_seedling_emerg_h2o_timescale:long_name = "Length of the window for the exponential moving average of smp used to calculate seedling emergence" ; - double fates_trs_seedling_mdd_timescale ; - fates_trs_seedling_mdd_timescale:units = "days" ; - fates_trs_seedling_mdd_timescale:long_name = "Length of the window for the exponential moving average of moisture deficit days used to calculate seedling mortality" ; - double fates_trs_seedling_mort_par_timescale ; - fates_trs_seedling_mort_par_timescale:units = "days" ; - fates_trs_seedling_mort_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling mortality" ; - double fates_vai_top_bin_width ; - fates_vai_top_bin_width:units = "m2/m2" ; - fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; - double fates_vai_width_increase_factor ; - fates_vai_width_increase_factor:units = "unitless" ; - fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; - -// global attributes: - :history = "This file was generated by BatchPatchParams.py:\nCDL Base File = archive/api24.1.0_101722_fates_params_default.cdl\nXML patch file = archive/api24.1.0_101722_patch_params.xml" ; -data: - - fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; - - fates_history_coageclass_bin_edges = 0, 5 ; - - fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; - - fates_history_damage_bin_edges = 0, 80 ; - - fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, - 80, 90, 100 ; - - fates_alloc_organ_id = 1, 2, 3, 6 ; - - fates_hydro_htftype_node = 1, 1, 1, 1 ; - - fates_pftname = - "broadleaf_evergreen_tropical_tree ", - "needleleaf_evergreen_extratrop_tree ", - "needleleaf_colddecid_extratrop_tree ", - "broadleaf_evergreen_extratrop_tree ", - "broadleaf_hydrodecid_tropical_tree ", - "broadleaf_colddecid_extratrop_tree ", - "broadleaf_evergreen_extratrop_shrub ", - "broadleaf_hydrodecid_extratrop_shrub ", - "broadleaf_colddecid_extratrop_shrub ", - "arctic_c3_grass ", - "cool_c3_grass ", - "c4_grass " ; - - fates_hydro_organ_name = - "leaf ", - "stem ", - "transporting root ", - "absorbing root " ; - - fates_alloc_organ_name = - "leaf", - "fine root", - "sapwood", - "structure" ; - - fates_litterclass_name = - "twig ", - "small branch ", - "large branch ", - "trunk ", - "dead leaves ", - "live grass " ; - - 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, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; - - fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 2.4, 1.2, 1.2, 2.4, 1.2, - 1.2, 1.2, 1.2 ; - - fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, - 0.8, 0.8, 0.8, 0.8 ; - - fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, - 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; - - fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, - 0.572, 0.572, 0.572, 0.572 ; - - fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, - 1.94, 1.94, 1.94 ; - - fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, - 0.931, 0.931, 0.931, 0.931 ; - - fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6 ; - - fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, - 0.95, 1, 1, 1 ; - - fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, - 0.07, 0.07, 0.07 ; - - fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, - 1.3 ; - - fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, - 0.55, 0.55, 0.55 ; - - fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464 ; - - fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119 ; - - fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, - 0.64, 0.64, 0.64 ; - - fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, - 0.37, 0.37, 0.37 ; - - fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, - -999.9, -999.9, -999.9, -999.9, -999.9 ; - - fates_allom_dbh_maxheight = 90, 80, 80, 80, 90, 80, 3, 3, 2, 0.35, 0.35, 0.35 ; - - fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; - - fates_allom_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; - - fates_allom_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - - fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, - 0.8, 0.8, 0.8 ; - - fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1, 0.1 ; - - fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_zroot_k = 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 ; - - fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; - - fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100 ; - - fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1 ; - - fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100 ; - - fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; - - fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5 ; - - fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, - 280, 280 ; - - fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, - 0.14, 0.14, 0.14 ; - - fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, - 0.27, 0.27, 0.27 ; - - fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1 ; - - fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, - 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - - fates_cnp_nfix1 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5, 1.5 ; - - fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5, 1.5 ; - - fates_cnp_pid_kd = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; - - fates_cnp_pid_ki = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_pid_kp = 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005 ; - - fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_turnover_nitr_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_turnover_phos_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_vmax_nh4 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, - 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; - - fates_cnp_vmax_no3 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, - 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; - - fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, - 5e-10, 5e-10, 5e-10, 5e-10 ; - - fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, - 0.01, 0.01, 0.01 ; - - fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; - - fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, - 5.5, 5.5 ; - - fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, - 0.2 ; - - fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, - 0.07, 0.07, 0.07, 0.07 ; - - fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, - 0.775, 0.775, 0.775, 0.775, 0.775 ; - - fates_frag_fnrt_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5 ; - - fates_frag_fnrt_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; - - fates_frag_fnrt_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; - - fates_frag_leaf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5 ; - - fates_frag_leaf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; - - fates_frag_leaf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; - - fates_frag_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, - 0.51, 0.51, 0.51, 0.51 ; - - fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, - 0.11, 0.11 ; - - fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, - 2.5, 2.5 ; - - fates_hydro_avuln_node = - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 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_hydro_epsil_node = - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - - fates_hydro_fcap_node = - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, - 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_hydro_kmax_node = - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; - - fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, - -1.5, -1.5, -1.5 ; - - fates_hydro_p50_node = - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25 ; - - fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, - 0.333, 0.333, 0.333, 0.333, 0.333 ; - - fates_hydro_pinot_node = - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; - - fates_hydro_pitlp_node = - -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, - -1.67, -1.67, - -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, - -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, - -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; - - fates_hydro_resid_node = - 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, - 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - - fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, - 0.625, 0.625, 0.625, 0.625, 0.625 ; - - fates_hydro_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, - 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; - - fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; - - fates_hydro_thetas_node = - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; - - fates_hydro_vg_alpha_node = - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005 ; - - fates_hydro_vg_m_node = - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_hydro_vg_n_node = - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 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_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, - 43540, 43540, 43540, 43540 ; - - fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, - 152040, 152040, 152040, 152040, 152040 ; - - fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, - 495 ; - - fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, - 0.03, 0.03, 0.03, 0.03, 0.03 ; - - fates_leaf_slatop = 0.012, 0.005, 0.024, 0.009, 0.03, 0.03, 0.012, 0.03, - 0.03, 0.03, 0.03, 0.03 ; - - fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, - 10000, 10000, 10000, 10000, 10000, 40000 ; - - fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - - fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, - 4.7, 2.2, 5.3, 1.6 ; - - fates_leaf_vcmax25top = - 50, 62, 39, 61, 58, 58, 62, 54, 54, 78, 78, 78 ; - - fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, - 65330, 65330, 65330, 65330 ; - - fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, - 149250, 149250, 149250, 149250, 149250 ; - - fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, - 485 ; - - fates_maintresp_leaf_atkin2017_baserate = 1.756, 1.4995, 1.4995, 1.756, - 1.756, 1.756, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956, 2.1956 ; - - fates_maintresp_leaf_ryan1991_baserate = 2.525e-06, 2.525e-06, 2.525e-06, - 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, - 2.525e-06, 2.525e-06, 2.525e-06 ; - - fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, - 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; - - fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_maintresp_reduction_upthresh = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, - 0.014, 0.014, 0.014, 0.014 ; - - fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -80, -60, -10, -80, -80, - -20, 2.5 ; - - fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5 ; - - fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, - 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; - - fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_prescribed_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, - 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; - - fates_mort_prescribed_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, - 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; - - fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - - fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6, 0.6 ; - - fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6, 0.6 ; - - fates_mort_upthresh_cstarvation = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_nonhydro_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, - -255000, -255000, -255000, -255000, -255000, -255000 ; - - fates_nonhydro_smpso = -66000, -66000, -66000, -66000, -66000, -66000, - -66000, -66000, -66000, -66000, -66000, -66000 ; - - fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_phen_drought_threshold = -152957.4, -152957.4, -152957.4, -152957.4, - -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, - -152957.4, -152957.4 ; - - fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; - - fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, - 0.5 ; - - fates_phen_fnrt_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_phen_mindaysoff = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100 ; - - fates_phen_moist_threshold = -122365.9, -122365.9, -122365.9, -122365.9, - -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, - -122365.9, -122365.9 ; - - fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; - - fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; - - fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, - 0.4, 0.4, 0.4 ; - - fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, - 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; - - fates_rad_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, - 0.9, 0.75, 0.75, 0.75 ; - - fates_rad_leaf_rhonir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, - 0.41, 0.28, 0.28, 0.28 ; - - fates_rad_leaf_rhovis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, - 0.08, 0.05, 0.05, 0.05 ; - - fates_rad_leaf_taunir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, - 0.43, 0.4, 0.4, 0.4 ; - - fates_rad_leaf_tauvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, - 0.06, 0.05, 0.05, 0.05 ; - - fates_rad_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, - -0.23, -0.23, -0.23 ; - - fates_rad_stem_rhonir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, - 0.49, 0.53, 0.53, 0.53 ; - - fates_rad_stem_rhovis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.21, 0.31, 0.31, 0.31 ; - - fates_rad_stem_taunir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, - 0.001, 0.001, 0.25, 0.25, 0.25 ; - - fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, - 0.001, 0.001, 0.12, 0.12, 0.12 ; - - fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.2, 0.2, 0.2, - 0.125, 0.125, 0.125 ; - - fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, - 0.2, 0.2, 0.2 ; - - fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, - 0.02, 0.02, 0.02, 0.02, 0.02 ; - - fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1, 0.1 ; - - fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, - 0.9 ; - - fates_recruit_seed_dbh_repro_threshold = 90, 80, 80, 80, 90, 80, 3, 3, 2, - 0.35, 0.35, 0.35 ; - - fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_seed_dispersal_fraction = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_seed_dispersal_max_dist = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_seed_dispersal_pdf_scale = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_seed_dispersal_pdf_shape = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_stoich_nitr = - 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, - 0.0047, 0.0047, 0.0047 ; - - fates_stoich_phos = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, - 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, - 0.00047, 0.00047, 0.00047, 0.00047 ; - - fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, - 0.03, 0.03 ; - - fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; - - fates_trs_repro_alloc_a = 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, - 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049 ; - - fates_trs_repro_alloc_b = -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, - -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171 ; - - fates_trs_repro_frac_seed = 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, - 0.24, 0.24, 0.24, 0.24 ; - - fates_trs_seedling_a_emerg = 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, - 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003 ; - - fates_trs_seedling_b_emerg = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, - 1.2, 1.2, 1.2 ; - - fates_trs_seedling_background_mort = 0.1085371, 0.1085371, 0.1085371, - 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, - 0.1085371, 0.1085371, 0.1085371 ; - - fates_trs_seedling_h2o_mort_a = 4.070565e-17, 4.070565e-17, 4.070565e-17, - 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, - 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17 ; - - fates_trs_seedling_h2o_mort_b = -6.390757e-11, -6.390757e-11, -6.390757e-11, - -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, - -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11 ; - - fates_trs_seedling_h2o_mort_c = 1.268992e-05, 1.268992e-05, 1.268992e-05, - 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, - 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05 ; - - fates_trs_seedling_light_mort_a = -0.009897694, -0.009897694, -0.009897694, - -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, - -0.009897694, -0.009897694, -0.009897694, -0.009897694 ; - - fates_trs_seedling_light_mort_b = -7.154063, -7.154063, -7.154063, - -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, - -7.154063, -7.154063, -7.154063 ; - - fates_trs_seedling_light_rec_a = 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, - 0.007, 0.007, 0.007, 0.007, 0.007, 0.007 ; - - fates_trs_seedling_light_rec_b = 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, - 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615 ; - - fates_trs_seedling_mdd_crit = 1400000, 1400000, 1400000, 1400000, 1400000, - 1400000, 1400000, 1400000, 1400000, 1400000, 1400000, 1400000 ; - - fates_trs_seedling_par_crit_germ = 0.656, 0.656, 0.656, 0.656, 0.656, 0.656, - 0.656, 0.656, 0.656, 0.656, 0.656, 0.656 ; - - fates_trs_seedling_psi_crit = -251995.7, -251995.7, -251995.7, -251995.7, - -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, - -251995.7, -251995.7 ; - - fates_trs_seedling_psi_emerg = -15744.65, -15744.65, -15744.65, -15744.65, - -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, - -15744.65, -15744.65 ; - - fates_trs_seedling_root_depth = 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, - 0.06, 0.06, 0.06, 0.06, 0.06 ; - - fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, - 0.67, 0.67, 0.67 ; - - fates_turb_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.04, 0.04, 0.04, 0.04 ; - - fates_turb_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, - 0.055, 0.055, 0.055, 0.055 ; - - fates_turnover_branch = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; - - fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - - fates_turnover_leaf = - 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - - fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_wood_density = 0.7, 0.4, 0.7, 0.53, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, - 0.7 ; - - fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; - - fates_hlm_pft_map = - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; - - fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; - - fates_fire_low_moisture_Coeff = 1.12, 1.09, 0.98, 0.8, 1.15, 1.15 ; - - fates_fire_low_moisture_Slope = 0.62, 0.72, 0.85, 0.8, 0.62, 0.62 ; - - fates_fire_mid_moisture = 0.72, 0.51, 0.38, 1, 0.8, 0.8 ; - - fates_fire_mid_moisture_Coeff = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; - - fates_fire_mid_moisture_Slope = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; - - fates_fire_min_moisture = 0.18, 0.12, 0, 0, 0.24, 0.24 ; - - fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; - - fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; - - fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; - - fates_canopy_closure_thresh = 0.8 ; - - fates_cnp_eca_plant_escalar = 1.25e-05 ; - - fates_cohort_age_fusion_tol = 0.08 ; - - fates_cohort_size_fusion_tol = 0.08 ; - - fates_comp_excln = 3 ; - - fates_damage_canopy_layer_code = 1 ; - - fates_damage_event_code = 1 ; - - fates_dev_arbitrary = _ ; - - fates_fire_active_crown_fire = 0 ; - - fates_fire_cg_strikes = 0.2 ; - - fates_fire_drying_ratio = 66000 ; - - fates_fire_durat_slope = -11.06 ; - - fates_fire_fdi_a = 17.62 ; - - fates_fire_fdi_alpha = 0.00037 ; - - fates_fire_fdi_b = 243.12 ; - - fates_fire_fuel_energy = 18000 ; - - fates_fire_max_durat = 240 ; - - fates_fire_miner_damp = 0.41739 ; - - fates_fire_miner_total = 0.055 ; - - fates_fire_nignitions = 15 ; - - fates_fire_part_dens = 513 ; - - fates_fire_threshold = 50 ; - - fates_frag_cwd_fcel = 0.76 ; - - fates_frag_cwd_flig = 0.24 ; - - fates_hydro_kmax_rsurf1 = 20 ; - - fates_hydro_kmax_rsurf2 = 0.0001 ; - - fates_hydro_psi0 = 0 ; - - fates_hydro_psicap = -0.6 ; - - fates_hydro_solver = 1 ; - - fates_landuse_logging_coll_under_frac = 0.55983 ; - - fates_landuse_logging_collateral_frac = 0.05 ; - - fates_landuse_logging_dbhmax = _ ; - - fates_landuse_logging_dbhmax_infra = 35 ; - - fates_landuse_logging_dbhmin = 50 ; - - fates_landuse_logging_direct_frac = 0.15 ; - - fates_landuse_logging_event_code = -30 ; - - fates_landuse_logging_export_frac = 0.8 ; - - fates_landuse_logging_mechanical_frac = 0.05 ; - - fates_landuse_pprodharv10_forest_mean = 0.8125 ; - - fates_leaf_photo_temp_acclim_thome_time = 30 ; - - fates_leaf_photo_temp_acclim_timescale = 30 ; - - fates_leaf_photo_tempsens_model = 1 ; - - fates_leaf_stomatal_assim_model = 1 ; - - fates_leaf_stomatal_model = 1 ; - - fates_leaf_theta_cj_c3 = 0.999 ; - - fates_leaf_theta_cj_c4 = 0.999 ; - - fates_maintresp_leaf_model = 1 ; - - fates_maintresp_nonleaf_baserate = 2.525e-06 ; - - fates_maxcohort = 100 ; - - fates_maxpatch_primary = 10 ; - - fates_maxpatch_secondary = 4 ; - - fates_mort_disturb_frac = 1 ; - - fates_mort_understorey_death = 0.55983 ; - - fates_patch_fusion_tol = 0.05 ; - - fates_phen_chilltemp = 5 ; - - fates_phen_coldtemp = 7.5 ; - - fates_phen_gddthresh_a = -68 ; - - fates_phen_gddthresh_b = 638 ; - - fates_phen_gddthresh_c = -0.01 ; - - fates_phen_mindayson = 90 ; - - fates_phen_ncolddayslim = 5 ; - - fates_q10_froz = 1.5 ; - - fates_q10_mr = 1.5 ; - - fates_rad_model = 1 ; - - fates_regeneration_model = 1 ; - - fates_soil_salinity = 0.4 ; - - fates_trs_seedling2sap_par_timescale = 32 ; - - fates_trs_seedling_emerg_h2o_timescale = 7 ; - - fates_trs_seedling_mdd_timescale = 126 ; - - fates_trs_seedling_mort_par_timescale = 32 ; - - fates_vai_top_bin_width = 1 ; - - fates_vai_width_increase_factor = 1 ; -} diff --git a/parameter_files/archive/api25.5.0_072423_pr1005.xml b/parameter_files/archive/api25.5.0_072423_pr1005.xml deleted file mode 100644 index 7dbc06d9ce..0000000000 --- a/parameter_files/archive/api25.5.0_072423_pr1005.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - archive/api25.5.0_072423_fates_params_default.cdl - fates_params_default.cdl - 1,2,3,4,5,6,7,8,9,10,11,12 - - - fates_seed_dispersal_max_dist - fates_pft - m - maximum seed dispersal distance for a given pft - - - - fates_seed_dispersal_fraction - fates_pft - fraction - fraction of seed rain to be dispersed to other grid cells - - - - fates_seed_dispersal_pdf_scale - fates_pft - unitless - seed dispersal probability density function scale parameter, A, Table 1 Bullock et al 2016 - - - - fates_seed_dispersal_pdf_shape - fates_pft - unitless - seed dispersal probability density function shape parameter, B, Table 1 Bullock et al 2016 - - - - From 436a95650751107b91cbc44af36bc38ecce36549 Mon Sep 17 00:00:00 2001 From: Marcos Longo <5891904+mpaiao@users.noreply.github.com> Date: Fri, 7 Jul 2023 08:57:27 -0700 Subject: [PATCH 790/852] Fix EDInitMod.F90 initialisation of drought deciduous variables Two local variables were not initialised before the first time being used (thanks @adrifoster for spotting it!). This PR fixes it. --- main/EDInitMod.F90 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 1b57ccfaeb..e32de0c895 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -847,9 +847,17 @@ subroutine init_cohorts(site_in, patch_in, bc_in) canopy_trim = 1.0_r8 crown_damage = 1 ! Assume no damage to begin with +<<<<<<< HEAD ! retrieve drop fraction of non-leaf tissues for phenology initialization fnrt_drop_fraction = prt_params%phen_fnrt_drop_fraction(pft) stem_drop_fraction = prt_params%phen_stem_drop_fraction(pft) +||||||| parent of 7c8a53cf (Fix EDInitMod.F90 initialisation of drought deciduous variables) +======= + ! Retrieve drop fraction of non-leaf tissues for phenology initialisation + fnrt_drop_fraction = prt_params%phen_fnrt_drop_fraction(pft) + stem_drop_fraction = prt_params%phen_stem_drop_fraction(pft) + +>>>>>>> 7c8a53cf (Fix EDInitMod.F90 initialisation of drought deciduous variables) ! initialize phenology variables if_spmode: if (hlm_use_sp == itrue) then From b6816f6c085c6170cb200a43a65e6c7d2e2f9ad1 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Wed, 26 Jul 2023 09:09:18 -0600 Subject: [PATCH 791/852] fix init error --- main/EDInitMod.F90 | 8 -------- 1 file changed, 8 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index e32de0c895..1b57ccfaeb 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -847,17 +847,9 @@ subroutine init_cohorts(site_in, patch_in, bc_in) canopy_trim = 1.0_r8 crown_damage = 1 ! Assume no damage to begin with -<<<<<<< HEAD ! retrieve drop fraction of non-leaf tissues for phenology initialization fnrt_drop_fraction = prt_params%phen_fnrt_drop_fraction(pft) stem_drop_fraction = prt_params%phen_stem_drop_fraction(pft) -||||||| parent of 7c8a53cf (Fix EDInitMod.F90 initialisation of drought deciduous variables) -======= - ! Retrieve drop fraction of non-leaf tissues for phenology initialisation - fnrt_drop_fraction = prt_params%phen_fnrt_drop_fraction(pft) - stem_drop_fraction = prt_params%phen_stem_drop_fraction(pft) - ->>>>>>> 7c8a53cf (Fix EDInitMod.F90 initialisation of drought deciduous variables) ! initialize phenology variables if_spmode: if (hlm_use_sp == itrue) then From f458ea73ed57f366667cdce72f1dacf23246ab8d Mon Sep 17 00:00:00 2001 From: Marcos Longo <5891904+mpaiao@users.noreply.github.com> Date: Fri, 7 Jul 2023 09:16:33 -0700 Subject: [PATCH 792/852] Remove duplicated init of the drought deciduous local variables I forgot to delete the assignment of the local variables when I moved it to the beginning of the `do` loop (thanks @glemieux). From 6a8898abd74351b1799a6d599cec3317c0e30f15 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 27 Jul 2023 11:59:33 -0600 Subject: [PATCH 793/852] removing conditional on ch4 bcs --- biogeochem/FatesSoilBGCFluxMod.F90 | 132 +++++++++++++++++------------ main/FatesInterfaceMod.F90 | 5 +- 2 files changed, 80 insertions(+), 57 deletions(-) diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index b32186c93f..564510bb49 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -268,8 +268,9 @@ subroutine PrepCH4BCs(csite,bc_in,bc_out) real(r8), parameter :: ema_npp_tscale = 10._r8 ! 10 day + ! Exit if we need not communicate with the hlm's ch4 module - if(.not.(hlm_use_ch4==itrue) .and. .not.(hlm_parteh_mode==prt_cnp_flex_allom_hyp) ) return + ! if(.not.(hlm_use_ch4==itrue) .and. .not.(hlm_parteh_mode==prt_cnp_flex_allom_hyp) ) return ! Initialize to zero bc_out%annavg_agnpp_pa(:) = 0._r8 @@ -279,12 +280,17 @@ subroutine PrepCH4BCs(csite,bc_in,bc_out) bc_out%frootc_pa(:) = 0._r8 bc_out%root_resp(:) = 0._r8 bc_out%woody_frac_aere_pa(:) = 0._r8 + bc_out%ema_npp = 0._r8 + site_npp = 0._r8 + + ! Process CH4 variables first + !if(.not.(hlm_use_ch4==itrue) .and. .not.(hlm_parteh_mode==prt_cnp_flex_allom_hyp) ) fp = 0 cpatch => csite%oldest_patch do while (associated(cpatch)) - + ! Patch ordering when passing boundary conditions ! always goes from oldest to youngest, following ! the convention of EDPatchDynamics::set_patchno() @@ -298,7 +304,7 @@ subroutine PrepCH4BCs(csite,bc_in,bc_out) ccohort => cpatch%tallest do while (associated(ccohort)) - + ! For consistency, only apply calculations to non-new ! cohorts. New cohorts will not have respiration rates ! at this point in the call sequence. @@ -306,23 +312,12 @@ subroutine PrepCH4BCs(csite,bc_in,bc_out) if(.not.ccohort%isnew) then pft = ccohort%pft - + call set_root_fraction(csite%rootfrac_scr, pft, csite%zi_soil, & bc_in%max_rooting_depth_index_col ) - + fnrt_c = ccohort%prt%GetState(fnrt_organ, carbon12_element) - - ! Fine root fraction over depth - - bc_out%rootfr_pa(fp,1:bc_in%nlevsoil) = & - bc_out%rootfr_pa(fp,1:bc_in%nlevsoil) + & - csite%rootfrac_scr(1:bc_in%nlevsoil) - - ! Fine root carbon, convert [kg/plant] -> [g/m2] - bc_out%frootc_pa(fp) = & - bc_out%frootc_pa(fp) + & - fnrt_c*ccohort%n/cpatch%area * g_per_kg - + ! [kgC/day] sapw_net_alloc = ccohort%prt%GetNetAlloc(sapw_organ, carbon12_element) * days_per_sec store_net_alloc = ccohort%prt%GetNetAlloc(store_organ, carbon12_element) * days_per_sec @@ -330,23 +325,37 @@ subroutine PrepCH4BCs(csite,bc_in,bc_out) fnrt_net_alloc = ccohort%prt%GetNetAlloc(fnrt_organ, carbon12_element) * days_per_sec struct_net_alloc = ccohort%prt%GetNetAlloc(struct_organ, carbon12_element) * days_per_sec repro_net_alloc = ccohort%prt%GetNetAlloc(repro_organ, carbon12_element) * days_per_sec - + ! [kgC/plant/day] -> [gC/m2/s] agnpp = agnpp + ccohort%n/cpatch%area * (leaf_net_alloc + repro_net_alloc + & prt_params%allom_agb_frac(pft)*(sapw_net_alloc+store_net_alloc+struct_net_alloc)) * g_per_kg - + ! [kgC/plant/day] -> [gC/m2/s] bgnpp = bgnpp + ccohort%n/cpatch%area * (fnrt_net_alloc + & (1._r8-prt_params%allom_agb_frac(pft))*(sapw_net_alloc+store_net_alloc+struct_net_alloc)) * g_per_kg - - ! (gC/m2/s) root respiration (fine root MR + total root GR) - ! RGK: We do not save root respiration and average over the day. Until we do - ! this is a best (bad) guess at fine root MR + total root GR - ! (kgC/indiv/yr) -> gC/m2/s - bc_out%root_resp(1:bc_in%nlevsoil) = bc_out%root_resp(1:bc_in%nlevsoil) + & - ccohort%resp_acc_hold*years_per_day*g_per_kg*days_per_sec* & - ccohort%n*area_inv*(1._r8-prt_params%allom_agb_frac(pft)) * csite%rootfrac_scr(1:bc_in%nlevsoil) - + + if(hlm_use_ch4==itrue)then + + ! Fine root fraction over depth + bc_out%rootfr_pa(fp,1:bc_in%nlevsoil) = & + bc_out%rootfr_pa(fp,1:bc_in%nlevsoil) + & + csite%rootfrac_scr(1:bc_in%nlevsoil) + + ! Fine root carbon, convert [kg/plant] -> [g/m2] + bc_out%frootc_pa(fp) = & + bc_out%frootc_pa(fp) + & + fnrt_c*ccohort%n/cpatch%area * g_per_kg + + ! (gC/m2/s) root respiration (fine root MR + total root GR) + ! RGK: We do not save root respiration and average over the day. Until we do + ! this is a best (bad) guess at fine root MR + total root GR + ! (kgC/indiv/yr) -> gC/m2/s + bc_out%root_resp(1:bc_in%nlevsoil) = bc_out%root_resp(1:bc_in%nlevsoil) + & + ccohort%resp_acc_hold*years_per_day*g_per_kg*days_per_sec* & + ccohort%n*area_inv*(1._r8-prt_params%allom_agb_frac(pft)) * csite%rootfrac_scr(1:bc_in%nlevsoil) + + end if + if( prt_params%woody(pft)==itrue ) then woody_area = woody_area + ccohort%c_area end if @@ -357,33 +366,38 @@ subroutine PrepCH4BCs(csite,bc_in,bc_out) ccohort => ccohort%shorter end do - - if( sum(bc_out%rootfr_pa(fp,1:bc_in%nlevsoil)) > nearzero) then - bc_out%rootfr_pa(fp,1:bc_in%nlevsoil) = & - bc_out%rootfr_pa(fp,1:bc_in%nlevsoil) / & - sum(bc_out%rootfr_pa(fp,1:bc_in%nlevsoil)) - end if - - ! RGK: These averages should switch to the new patch averaging methods - ! when available. Right now we are not doing any time averaging - ! because it would be mixing the memory of patches, which - ! would be arguably worse than just using the instantaneous value - ! gC/m2/s - bc_out%annavg_agnpp_pa(fp) = agnpp - bc_out%annavg_bgnpp_pa(fp) = bgnpp - ! gc/m2/yr - bc_out%annsum_npp_pa(fp) = (bgnpp+agnpp)*days_per_year*sec_per_day - - site_npp = site_npp + bc_out%annsum_npp_pa(fp)*cpatch%area*area_inv - - if(plant_area>nearzero) then - bc_out%woody_frac_aere_pa(fp) = woody_area/plant_area + if(hlm_use_ch4==itrue)then + if( sum(bc_out%rootfr_pa(fp,1:bc_in%nlevsoil)) > nearzero) then + bc_out%rootfr_pa(fp,1:bc_in%nlevsoil) = & + bc_out%rootfr_pa(fp,1:bc_in%nlevsoil) / & + sum(bc_out%rootfr_pa(fp,1:bc_in%nlevsoil)) + end if + + ! RGK: These averages should switch to the new patch averaging methods + ! when available. Right now we are not doing any time averaging + ! because it would be mixing the memory of patches, which + ! would be arguably worse than just using the instantaneous value + + ! gC/m2/s + bc_out%annavg_agnpp_pa(fp) = agnpp + bc_out%annavg_bgnpp_pa(fp) = bgnpp + ! gc/m2/yr + bc_out%annsum_npp_pa(fp) = (bgnpp+agnpp)*days_per_year*sec_per_day + + site_npp = site_npp + (bgnpp+agnpp)*days_per_year*sec_per_day*cpatch%area*area_inv + + if(plant_area>nearzero) then + bc_out%woody_frac_aere_pa(fp) = woody_area/plant_area + end if + end if + site_npp = site_npp + (bgnpp+agnpp)*days_per_year*sec_per_day*cpatch%area*area_inv + cpatch => cpatch%younger end do - + ! Smoothed [gc/m2/yr] if(csite%ema_npp<-9000._r8)then ! For cold starts, we initialize the ema_npp value at -9999, so that @@ -394,7 +408,7 @@ subroutine PrepCH4BCs(csite,bc_in,bc_out) end if bc_out%ema_npp = csite%ema_npp - + return end subroutine PrepCH4BCs @@ -701,6 +715,12 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) do id = 1,nlev_eff_decomp surface_prof(id) = surface_prof(id)/surface_prof_tot end do + + + !bc_out%litt_flux_cel_n_si(:) = 100._r8 + !bc_out%litt_flux_lab_n_si(:) = 100._r8 + !bc_out%litt_flux_lig_n_si(:) = 100._r8 + ! Loop over the different elements. do el = 1, num_elements @@ -711,9 +731,9 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) select case (element_list(el)) case (carbon12_element) - bc_out%litt_flux_cel_c_si(:) = 0._r8 - bc_out%litt_flux_lig_c_si(:) = 0._r8 - bc_out%litt_flux_lab_c_si(:) = 0._r8 + bc_out%litt_flux_cel_c_si(:) = 0.0_r8 + bc_out%litt_flux_lig_c_si(:) = 0.0_r8 + bc_out%litt_flux_lab_c_si(:) = 0.0_r8 flux_cel_si => bc_out%litt_flux_cel_c_si(:) flux_lab_si => bc_out%litt_flux_lab_c_si(:) flux_lig_si => bc_out%litt_flux_lig_c_si(:) @@ -733,6 +753,10 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) flux_lig_si => bc_out%litt_flux_lig_p_si(:) end select + !end do + !return + !do el = 1, num_elements + currentPatch => csite%oldest_patch do while (associated(currentPatch)) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index d39155ecfe..7c8aaba4ba 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -463,7 +463,6 @@ subroutine allocate_bcin(bc_in, nlevsoil_in, nlevdecomp_in, num_lu_harvest_cats, allocate(bc_in%plant_p_uptake_flux(1,1)) end if - allocate(bc_in%zi_sisl(0:nlevsoil_in)) allocate(bc_in%dz_sisl(nlevsoil_in)) allocate(bc_in%z_sisl(nlevsoil_in)) @@ -620,7 +619,7 @@ subroutine allocate_bcout(bc_out, nlevsoil_in, nlevdecomp_in) ! Include the bare-ground patch for these patch-level boundary conditions ! (it will always be zero for all of these) - if(hlm_use_ch4.eq.itrue) then + !if(hlm_use_ch4.eq.itrue) then allocate(bc_out%annavg_agnpp_pa(0:maxpatch_total));bc_out%annavg_agnpp_pa(:)=nan allocate(bc_out%annavg_bgnpp_pa(0:maxpatch_total));bc_out%annavg_bgnpp_pa(:)=nan allocate(bc_out%annsum_npp_pa(0:maxpatch_total));bc_out%annsum_npp_pa(:)=nan @@ -632,7 +631,7 @@ subroutine allocate_bcout(bc_out, nlevsoil_in, nlevdecomp_in) ! Give the bare-ground root fractions a nominal fraction of unity over depth bc_out%rootfr_pa(0,1:nlevsoil_in)=1._r8/real(nlevsoil_in,r8) - end if + !end if bc_out%ema_npp = -9999.9_r8 From 44668e2bf032d935da0f5fd9d9603385ce2b06ff Mon Sep 17 00:00:00 2001 From: adrifoster Date: Thu, 27 Jul 2023 12:04:34 -0600 Subject: [PATCH 794/852] remove default --- biogeochem/EDPhysiologyMod.F90 | 3 --- 1 file changed, 3 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index f202291352..91cd49bce7 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2537,9 +2537,6 @@ subroutine recruitment(currentSite, currentPatch, bc_in) else leaf_status = leaves_off end if - case default - write(fates_log(),*) 'Undefined stress deciduous type' - call endrun(msg=errMsg(sourcefile, __LINE__)) end select ! calculate live pools From 1054ce5ee94ed3264b03727e225d4e5a4348e1f9 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Thu, 27 Jul 2023 15:11:36 -0600 Subject: [PATCH 795/852] fix deallocate --- biogeochem/EDPatchDynamicsMod.F90 | 4 +++- biogeochem/FatesPatchMod.F90 | 23 +++++++++-------------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 1a84d7cddb..52a956f986 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -29,6 +29,8 @@ module EDPatchDynamicsMod use EDTypesMod , only : min_patch_area use EDTypesMod , only : min_patch_area_forced use EDParamsMod , only : nclmax + use EDParamsMod , only : regeneration_model + use FatesInterfaceTypesMod, only : numpft use EDTypesMod , only : dtype_ifall use EDTypesMod , only : dtype_ilog use EDTypesMod , only : dtype_ifire @@ -2569,7 +2571,7 @@ subroutine fuse_2_patches(csite, dp, rp) end if ! We have no need for the dp pointer anymore, we have passed on it's legacy - call dp%FreeMemory() + call dp%FreeMemory(regeneration_model, numpft) deallocate(dp, stat=istat, errmsg=smsg) if (istat/=0) then write(fates_log(),*) 'dealloc006: fail on deallocate(dp):'//trim(smsg) diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 index c75708e3c0..76d167c0f2 100644 --- a/biogeochem/FatesPatchMod.F90 +++ b/biogeochem/FatesPatchMod.F90 @@ -605,7 +605,7 @@ end subroutine Create !=========================================================================== - subroutine FreeMemory(this) + subroutine FreeMemory(this, regeneration_model, numpft) ! ! DESCRIPTION: ! deallocate the allocatable memory associated with this patch @@ -614,12 +614,13 @@ subroutine FreeMemory(this) ! ARGUMENTS: class(fates_patch_type), intent(inout) :: this + integer, intent(in) :: regeneration_model + integer, intent(in) :: numpft ! LOCALS: type(fates_cohort_type), pointer :: ccohort ! current cohort type(fates_cohort_type), pointer :: ncohort ! next cohort integer :: el ! loop counter for elements - integer :: numpft ! size of pft-indexed arrays integer :: pft ! loop counter for pfts integer :: istat ! return status code character(len=255) :: smsg ! message string for deallocation errors @@ -681,22 +682,16 @@ subroutine FreeMemory(this) call endrun(msg=errMsg(sourcefile, __LINE__)) endif - if (associated(this%seedling_layer_par24)) deallocate(this%seedling_layer_par24) - if (associated(this%sdlng_mort_par)) deallocate(this%sdlng_mort_par) - if (associated(this%sdlng2sap_par)) deallocate(this%sdlng2sap_par) - - if (associated(this%sdlng_mdd)) then - numpft = size(this%sdlng_mdd) + if (regeneration_model == TRS_regeneration) then + deallocate(this%seedling_layer_par24) + deallocate(this%sdlng_mort_par) + deallocate(this%sdlng2sap_par) do pft = 1, numpft - if (associated(this%sdlng_mdd(pft)%p)) deallocate(this%sdlng_mdd(pft)%p) + deallocate(this%sdlng_mdd(pft)%p) end do deallocate(this%sdlng_mdd) - end if - - if (associated(this%sdlng_emerg_smp)) then - numpft = size(this%sdlng_emerg_smp) do pft = 1, numpft - if (associated(this%sdlng_emerg_smp(pft)%p)) deallocate(this%sdlng_emerg_smp(pft)%p) + deallocate(this%sdlng_emerg_smp(pft)%p) end do deallocate(this%sdlng_emerg_smp) end if From 8bfb215ebbb47f5177b4eec16130a3d6e5a5aae8 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Fri, 28 Jul 2023 10:30:46 -0600 Subject: [PATCH 796/852] remove duplicate uses --- biogeochem/EDPhysiologyMod.F90 | 2 -- 1 file changed, 2 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 91cd49bce7..5fee6f3567 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -34,8 +34,6 @@ module EDPhysiologyMod use FatesConstantsMod, only : g_per_kg use FatesConstantsMod, only : ndays_per_year use FatesConstantsMod, only : nocomp_bareground - use FatesConstantsMod, only : g_per_kg - use FatesConstantsMod, only : ndays_per_year use EDPftvarcon , only : EDPftvarcon_inst use PRTParametersMod , only : prt_params use EDPftvarcon , only : GetDecompyFrac From ec19393b2169aee5ba786a033cd95ff090dbb847 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 28 Jul 2023 13:50:31 -0600 Subject: [PATCH 797/852] fix choice range and add shell script input options --- tools/luh2/luh2.py | 4 ++-- tools/luh2/luh2.sh | 16 ++++++++++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/tools/luh2/luh2.py b/tools/luh2/luh2.py index 5c4bf68858..13d516cefa 100644 --- a/tools/luh2/luh2.py +++ b/tools/luh2/luh2.py @@ -109,9 +109,9 @@ def CommandLineArgs(): # Optional input to subset the time range of the data # TODO: add support for parsing the input and checking against the allowable date range - parser.add_argument("-b","--begin", type=int, choices=range(850,2015), + parser.add_argument("-b","--begin", type=int, choices=range(850,2016), help="beginning of date range to slice (allowable range is 0850-2015)") - parser.add_argument("-e","--end", type=int, choices=range(850,2015), + parser.add_argument("-e","--end", type=int, choices=range(850,2016), help="ending of date range to slice (allowable range is 0850-2015)") # Optional output argument diff --git a/tools/luh2/luh2.sh b/tools/luh2/luh2.sh index 1e43dec9ef..3aa246907d 100755 --- a/tools/luh2/luh2.sh +++ b/tools/luh2/luh2.sh @@ -8,14 +8,18 @@ # LUH2 data names DATA_LOC=$1 -TARGET_LOC=$2 -OUTPUT_LOC=$3 +STATIC_LOC=$2 +TARGET_LOC=$3 +OUTPUT_LOC=$4 STATES_FILE=states.nc TRANSITIONS_FILE=transitions.nc MANAGE_FILE=management.nc STATIC_FILE=staticData_quarterdeg.nc REGRID_TARGET_FILE=surfdata_4x5_16pfts_Irrig_CMIP6_simyr2000_c170824.nc +START=1850 +END=2015 + # Save files REGRID_SAVE=regridder.nc OUTPUT_FILE=LUH2_historical_0850_2015_4x5.nc @@ -24,7 +28,7 @@ OUTPUT_FILE=LUH2_historical_0850_2015_4x5.nc STATES=${DATA_LOC}/${STATES_FILE} TRANSITIONS=${DATA_LOC}/${TRANSITIONS_FILE} MANAGE=${DATA_LOC}/${MANAGE_FILE} -STATIC=${DATA_LOC}/${STATIC_FILE} +STATIC=${STATIC_LOC}/${STATIC_FILE} REGRID_TARGET=${TARGET_LOC}/${REGRID_TARGET_FILE} REGRIDDER=${OUTPUT_LOC}/${REGRID_SAVE} @@ -33,19 +37,19 @@ REGRIDDER=${OUTPUT_LOC}/${REGRID_SAVE} # Regrid the luh2 data against a target surface data set and then remove the states_modified file echo "starting storage" du -h ${OUTPUT_LOC} -python luh2.py -l ${STATES} -s ${STATIC} -r ${REGRID_TARGET} -w ${REGRIDDER} -o ${OUTPUT_LOC}/states_regrid.nc +python luh2.py -b ${START} -e ${END} -l ${STATES} -s ${STATIC} -r ${REGRID_TARGET} -w ${REGRIDDER} -o ${OUTPUT_LOC}/states_regrid.nc echo -e"storage status:\n" du -h ${OUTPUT_LOC} # Regrid the luh2 transitions data using the saved regridder weights file and merge into previous regrid output -python luh2.py -l ${TRANSITIONS} -s ${STATIC} -r ${REGRID_TARGET} -w ${REGRIDDER} \ +python luh2.py -b ${START} -e ${END} -l ${TRANSITIONS} -s ${STATIC} -r ${REGRID_TARGET} -w ${REGRIDDER} \ -m ${OUTPUT_LOC}/states_regrid.nc -o ${OUTPUT_LOC}/states_trans_regrid.nc echo -e"storage status:\n" du -h ${OUTPUT_LOC} rm ${DATA_LOC}/states_regrid.nc # Regrid the luh2 management data using the saved regridder file and merge into previous regrid output -python luh2.py -l ${MANAGE} -s ${STATIC} -r ${REGRID_TARGET} -w ${REGRIDDER} \ +python luh2.py -b ${START} -e ${END} -l ${MANAGE} -s ${STATIC} -r ${REGRID_TARGET} -w ${REGRIDDER} \ -m ${OUTPUT_LOC}/states_trans_regrid.nc -o ${OUTPUT_LOC}/${OUTPUT_FILE} echo -e"storage status:\n" du -h ${OUTPUT_LOC} From 8f7f9b2e75cd5cb3d9fa7b721cd61f21ada98f71 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Fri, 28 Jul 2023 15:08:26 -0600 Subject: [PATCH 798/852] address comments --- biogeochem/EDCohortDynamicsMod.F90 | 1 - biogeochem/EDLoggingMortalityMod.F90 | 6 +++--- biogeochem/EDMortalityFunctionsMod.F90 | 2 +- biogeochem/EDPatchDynamicsMod.F90 | 9 +++++---- biogeochem/EDPhysiologyMod.F90 | 2 +- biogeochem/FatesPatchMod.F90 | 4 ++-- biogeophys/EDBtranMod.F90 | 2 +- biogeophys/EDSurfaceAlbedoMod.F90 | 15 +++------------ biogeophys/FatesBstressMod.F90 | 2 +- biogeophys/FatesPlantRespPhotosynthMod.F90 | 4 +--- main/EDParamsMod.F90 | 4 ++++ main/EDTypesMod.F90 | 9 ++------- main/FatesConstantsMod.F90 | 10 +++++++--- main/FatesHistoryInterfaceMod.F90 | 10 +++++----- main/FatesInterfaceMod.F90 | 2 +- main/FatesInventoryInitMod.F90 | 1 - main/FatesRestartInterfaceMod.F90 | 3 --- 17 files changed, 37 insertions(+), 49 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index cb4cdb0a1b..8e340ef33c 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -1393,7 +1393,6 @@ subroutine insert_cohort(currentPatch, pcc, ptall, pshort, tnull, snull, storebi storebigcohort => icohort end if currentPatch%tallest => icohort - !icohort%patchptr%tallest => icohort !new cohort is not tallest else !next shorter cohort to new cohort is the next shorter cohort diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 2a70c50d46..a4703ae840 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -25,9 +25,9 @@ module EDLoggingMortalityMod use FatesLitterMod , only : adjust_SF_CWD_frac use EDTypesMod , only : ed_site_type use EDTypesMod , only : ed_resources_management_type - use EDTypesMod , only : dtype_ilog - use EDTypesMod , only : dtype_ifall - use EDTypesMod , only : dtype_ifire + use FatesConstantsMod , only : dtype_ilog + use FatesConstantsMod , only : dtype_ifall + use FatesConstantsMod , only : dtype_ifire use EDPftvarcon , only : EDPftvarcon_inst use EDPftvarcon , only : GetDecompyFrac use PRTParametersMod , only : prt_params diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index ea7cc006c2..bf47a5cce3 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -11,7 +11,7 @@ module EDMortalityFunctionsMod use EDPftvarcon , only : EDPftvarcon_inst use FatesCohortMod , only : fates_cohort_type use EDTypesMod , only : ed_site_type - use FatesConstantsMod, only : maxpft + use EDParamsMod, only : maxpft use FatesConstantsMod , only : itrue,ifalse use FatesAllometryMod , only : bleaf use FatesAllometryMod , only : storage_fraction_of_target diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 52a956f986..6f022ccfbd 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -19,7 +19,8 @@ module EDPatchDynamicsMod use FatesConstantsMod , only : n_dbh_bins use FatesLitterMod , only : adjust_SF_CWD_frac use EDTypesMod , only : homogenize_seed_pfts - use EDTypesMod , only : area, patchfusion_dbhbin_loweredges + use EDTypesMod , only : area + use FatesConstantsMod , only : patchfusion_dbhbin_loweredges use EDtypesMod , only : force_patchfuse_min_biomass use EDTypesMod , only : ed_site_type use FatesPatchMod, only : fates_patch_type @@ -31,9 +32,9 @@ module EDPatchDynamicsMod use EDParamsMod , only : nclmax use EDParamsMod , only : regeneration_model use FatesInterfaceTypesMod, only : numpft - use EDTypesMod , only : dtype_ifall - use EDTypesMod , only : dtype_ilog - use EDTypesMod , only : dtype_ifire + use FatesConstantsMod , only : dtype_ifall + use FatesConstantsMod , only : dtype_ilog + use FatesConstantsMod , only : dtype_ifire use FatesConstantsMod , only : ican_upper use PRTGenericMod , only : num_elements use PRTGenericMod , only : element_list diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 5fee6f3567..9aaf9d3d80 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -66,7 +66,7 @@ module EDPhysiologyMod use FatesConstantsMod , only : isemi_stress_decid use EDParamsMod , only : nlevleaf use EDTypesMod , only : num_vegtemp_mem - use FatesConstantsMod , only : maxpft + use EDParamsMod , only : maxpft use EDTypesMod , only : ed_site_type use FatesPatchMod, only : fates_patch_type use FatesCohortMod, only : fates_cohort_type diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 index 76d167c0f2..8a38366217 100644 --- a/biogeochem/FatesPatchMod.F90 +++ b/biogeochem/FatesPatchMod.F90 @@ -15,8 +15,8 @@ module FatesPatchMod use FatesLitterMod, only : litter_type use PRTGenericMod, only : num_elements use PRTGenericMod, only : element_list - use EDParamsMod, only : maxSWb, nlevleaf, nclmax - use FatesConstantsMod, only : n_dbh_bins, maxpft, n_dist_types + use EDParamsMod, only : maxSWb, nlevleaf, nclmax, maxpft + use FatesConstantsMod, only : n_dbh_bins, n_dist_types use FatesConstantsMod, only : n_rad_stream_types use FatesConstantsMod, only : t_water_freeze_k_1atm use FatesRunningMeanMod, only : ema_24hr, fixed_24hr, ema_lpa, ema_longterm diff --git a/biogeophys/EDBtranMod.F90 b/biogeophys/EDBtranMod.F90 index ecdc1bb0c1..a785493d54 100644 --- a/biogeophys/EDBtranMod.F90 +++ b/biogeophys/EDBtranMod.F90 @@ -11,7 +11,7 @@ module EDBtranMod use FatesConstantsMod , only : nocomp_bareground use EDTypesMod , only : ed_site_type use FatesPatchMod, only : fates_patch_type - use FatesConstantsMod, only : maxpft + use EDParamsMod, only : maxpft use FatesCohortMod, only : fates_cohort_type use shr_kind_mod , only : r8 => shr_kind_r8 use FatesInterfaceTypesMod , only : bc_in_type, & diff --git a/biogeophys/EDSurfaceAlbedoMod.F90 b/biogeophys/EDSurfaceAlbedoMod.F90 index 8fe41194ba..18c7e7866e 100644 --- a/biogeophys/EDSurfaceAlbedoMod.F90 +++ b/biogeophys/EDSurfaceAlbedoMod.F90 @@ -12,7 +12,7 @@ module EDSurfaceRadiationMod use EDTypesMod , only : ed_site_type use FatesPatchMod, only : fates_patch_type - use FatesConstantsMod, only : maxpft + use EDParamsMod, only : maxpft use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : itrue use FatesConstantsMod , only : pi_const @@ -33,6 +33,7 @@ module EDSurfaceRadiationMod use EDCanopyStructureMod, only: calc_areaindex use FatesGlobals , only : fates_log use FatesGlobals, only : endrun => fates_endrun + use EDPftvarcon, only : EDPftvarcon_inst ! CIME globals use shr_log_mod , only : errMsg => shr_log_errMsg @@ -66,13 +67,8 @@ module EDSurfaceRadiationMod subroutine ED_Norman_Radiation (nsites, sites, bc_in, bc_out ) ! - ! - ! !USES: - use FatesPatchMod , only : fates_patch_type - use EDTypesMod , only : ed_site_type - - + ! !ARGUMENTS: integer, intent(in) :: nsites @@ -194,11 +190,6 @@ subroutine PatchNormanRadiation (currentPatch, & ! ! ----------------------------------------------------------------------------------- - ! - ! !USES: - use EDPftvarcon , only : EDPftvarcon_inst - use FatesPatchMod , only : fates_patch_type - ! ----------------------------------------------------------------------------------- ! !ARGUMENTS: ! ----------------------------------------------------------------------------------- diff --git a/biogeophys/FatesBstressMod.F90 b/biogeophys/FatesBstressMod.F90 index 825a886011..f37ab8ccb1 100644 --- a/biogeophys/FatesBstressMod.F90 +++ b/biogeophys/FatesBstressMod.F90 @@ -7,7 +7,7 @@ module FatesBstressMod ! use FatesConstantsMod , only : tfrz => t_water_freeze_k_1atm use FatesConstantsMod , only : itrue,ifalse - use FatesConstantsMod, only : maxpft + use EDParamsMod, only : maxpft use EDTypesMod , only : ed_site_type use FatesPatchMod, only : fates_patch_type use FatesCohortMod , only : fates_cohort_type diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 2c5c88c660..603e691067 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -38,7 +38,7 @@ module FATESPlantRespPhotosynthMod use FatesInterfaceTypesMod, only : hlm_parteh_mode use FatesInterfaceTypesMod, only : numpft use FatesInterfaceTypesMod, only : nleafage - use FatesConstantsMod, only : maxpft + use EDParamsMod, only : maxpft use EDParamsMod, only : nlevleaf use EDParamsMod, only : nclmax use PRTGenericMod, only : max_nleafage @@ -124,10 +124,8 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! a multi-layer canopy ! ----------------------------------------------------------------------------------- - ! !USES: use EDTypesMod , only : ed_site_type - use FatesConstantsMod , only : maxpft use EDParamsMod , only : dinc_vai use EDParamsMod , only : dlower_vai use FatesInterfaceTypesMod , only : bc_in_type diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 9620c9d433..438d387213 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -126,6 +126,10 @@ module EDParamsMod integer, parameter, public :: ipar = ivis ! The photosynthetically active band ! can be approximated to be equal to the visible band + + + +integer, parameter, public :: maxpft = 16 ! maximum number of PFTs allowed 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) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index f9a7f13717..c9b9a90161 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -28,8 +28,7 @@ module EDTypesMod use FatesInterfaceTypesMod,only : hlm_parteh_mode use FatesCohortMod, only : fates_cohort_type use FatesPatchMod, only : fates_patch_type - use EDParamsMod, only : maxSWb, nclmax, nlevleaf - use FatesConstantsMod, only : maxpft + use EDParamsMod, only : maxSWb, nclmax, nlevleaf, maxpft use FatesConstantsMod, only : n_dbh_bins, n_dist_types use shr_log_mod, only : errMsg => shr_log_errMsg @@ -87,9 +86,7 @@ module EDTypesMod ! BIOLOGY/BIOGEOCHEMISTRY integer , parameter, public :: num_vegtemp_mem = 10 ! Window of time over which we track temp for cold sensecence (days) - integer , parameter, public :: dtype_ifall = 1 ! index for naturally occuring tree-fall generated event - integer , parameter, public :: dtype_ifire = 2 ! index for fire generated disturbance event - integer , parameter, public :: dtype_ilog = 3 ! index for logging generated disturbance event + ! Phenology status flag definitions (cold type is cstat, dry type is dstat) @@ -106,8 +103,6 @@ module EDTypesMod ! PATCH FUSION real(r8), parameter, public :: force_patchfuse_min_biomass = 0.005_r8 ! min biomass (kg / m2 patch area) below which to force-fuse patches - real(r8), parameter, public :: patchfusion_dbhbin_loweredges(N_DBH_BINS) = & - (/0._r8, 5._r8, 20._r8, 50._r8, 100._r8, 150._r8/) ! array of bin lower edges for comparing patches real(r8), parameter, public :: patch_fusion_tolerance_relaxation_increment = 1.1_r8 ! amount by which to increment patch fusion threshold real(r8), parameter, public :: max_age_of_second_oldest_patch = 200._r8 ! age in years above which to combine all patches diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index 3a670e3e7c..08a8aaa3df 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -30,17 +30,21 @@ module FatesConstantsMod ! Integer equivalent of false (in case come compilers dont auto convert) integer, parameter, public :: ifalse = 0 - integer , parameter, public :: N_DBH_BINS = 6 ! no. of dbh bins used when comparing patches - - integer, parameter, public :: maxpft = 16 ! maximum number of PFTs allowed ! the parameter file may determine that fewer ! are used, but this helps allocate scratch ! space and output arrays. integer, parameter, public :: n_rad_stream_types = 2 ! The number of radiation streams used (direct/diffuse) + integer , parameter, public :: N_DBH_BINS = 6 ! no. of dbh bins used when comparing patches + real(fates_r8), parameter, public :: patchfusion_dbhbin_loweredges(N_DBH_BINS) = & + (/0._fates_r8, 5._fates_r8, 20._fates_r8, 50._fates_r8, 100._fates_r8, 150._fates_r8/) ! array of bin lower edges for comparing patches + integer , parameter, public :: N_DIST_TYPES = 3 ! Disturbance Modes 1) tree-fall, 2) fire, 3) logging + integer , parameter, public :: dtype_ifall = 1 ! index for naturally occuring tree-fall generated event + integer , parameter, public :: dtype_ifire = 2 ! index for fire generated disturbance event + integer , parameter, public :: dtype_ilog = 3 ! index for logging generated disturbance event ! Labels for patch disturbance history integer, parameter, public :: n_anthro_disturbance_categories = 2 diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 851d876c7a..779a1dbdda 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -12,7 +12,7 @@ module FatesHistoryInterfaceMod use FatesConstantsMod , only : t_water_freeze_k_1atm use FatesGlobals , only : fates_log use FatesGlobals , only : endrun => fates_endrun - use EDParamsMod , only : nclmax + use EDParamsMod , only : nclmax, maxpft use FatesConstantsMod , only : ican_upper use PRTGenericMod , only : element_pos use PRTGenericMod , only : num_elements @@ -27,10 +27,10 @@ module FatesHistoryInterfaceMod use EDTypesMod , only : num_vegtemp_mem use EDTypesMod , only : site_massbal_type use PRTGenericMod , only : element_list - use FatesConstantsMod , only : N_DIST_TYPES, maxpft - use EDTypesMod , only : dtype_ifall - use EDTypesMod , only : dtype_ifire - use EDTypesMod , only : dtype_ilog + use FatesConstantsMod , only : N_DIST_TYPES + use FatesConstantsMod , only : dtype_ifall + use FatesConstantsMod , only : dtype_ifire + use FatesConstantsMod , only : dtype_ilog use FatesIODimensionsMod , only : fates_io_dimension_type use FatesIOVariableKindMod , only : fates_io_variable_kind_type use FatesIOVariableKindMod , only : site_int diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index d5b489d528..be6c1bbd38 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -25,7 +25,7 @@ module FatesInterfaceMod use EDParamsMod , only : inir use EDParamsMod , only : nclmax use EDParamsMod , only : nlevleaf - use FatesConstantsMod , only : maxpft + use EDParamsMod , only : maxpft use EDTypesMod , only : do_fates_salinity use EDTypesMod , only : numWaterMem use EDTypesMod , only : numlevsoil_max diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index 76090fb844..0141c68fe5 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -555,7 +555,6 @@ subroutine initialize_sites_by_inventory(nsites,sites,bc_in) end if end do - !call canopy_summarization(nsites, sites, bc_in) deallocate(inv_format_list, inv_pss_list, inv_css_list, inv_lat_list, inv_lon_list) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 045f64408d..55016e9acb 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -1906,7 +1906,6 @@ subroutine set_restart_vectors(this,nc,nsites,sites) use EDParamsMod, only : nclmax use EDTypesMod, only : numWaterMem use EDTypesMod, only : num_vegtemp_mem - use FatesConstantsMod, only : maxpft use FatesInterfaceTypesMod, only : nlevdamage ! Arguments @@ -2646,7 +2645,6 @@ subroutine create_patchcohort_structure(this, nc, nsites, sites, bc_in, bc_out) use FatesInterfaceTypesMod, only : fates_maxElementsPerPatch use FatesInterfaceTypesMod, only : hlm_current_tod, hlm_numSWb, numpft - use FatesConstantsMod, only : maxpft use EDTypesMod, only : area use EDInitMod, only : zero_site use EDInitMod, only : init_site_vars @@ -2846,7 +2844,6 @@ subroutine get_restart_vectors(this, nc, nsites, sites) use FatesInterfaceTypesMod, only : numpft use FatesInterfaceTypesMod, only : fates_maxElementsPerPatch use EDTypesMod, only : numWaterMem - use FatesConstantsMod, only : maxpft use EDTypesMod, only : num_vegtemp_mem use FatesSizeAgeTypeIndicesMod, only : get_age_class_index From e0311ca5bceef300eb83746f92bf39ed6c5e387a Mon Sep 17 00:00:00 2001 From: Adrianna Foster Date: Fri, 28 Jul 2023 16:00:56 -0600 Subject: [PATCH 799/852] Update biogeochem/EDCohortDynamicsMod.F90 Co-authored-by: Gregory Lemieux <7565064+glemieux@users.noreply.github.com> --- biogeochem/EDCohortDynamicsMod.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 8e340ef33c..c4bfabdcf7 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -1413,7 +1413,6 @@ subroutine insert_cohort(currentPatch, pcc, ptall, pshort, tnull, snull, storebi storesmallcohort => icohort end if currentPatch%shortest => icohort - !icohort%patchptr%shortest => icohort else !new cohort is not shortest and becomes next taller cohort !to the cohort just below it as defined in the previous block From 97ae3548b341d968030b39c90d81a4fc1ae0aba6 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 31 Jul 2023 07:40:17 -0600 Subject: [PATCH 800/852] Updates to bgc coupling --- biogeochem/FatesSoilBGCFluxMod.F90 | 34 ++++++------------------------ main/FatesInterfaceMod.F90 | 32 +++++++++++++++++++++------- 2 files changed, 31 insertions(+), 35 deletions(-) diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index 564510bb49..5dafb6276c 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -255,7 +255,6 @@ subroutine PrepCH4BCs(csite,bc_in,bc_out) integer :: fp ! patch index of the site real(r8) :: agnpp ! Above ground daily npp real(r8) :: bgnpp ! Below ground daily npp - real(r8) :: site_npp ! Site level NPP gC/m2/year real(r8) :: plant_area ! crown area (m2) of all plants in patch real(r8) :: woody_area ! corwn area (m2) of woody plants in patch real(r8) :: fnrt_c ! Fine root carbon [kg/plant] @@ -282,8 +281,6 @@ subroutine PrepCH4BCs(csite,bc_in,bc_out) bc_out%woody_frac_aere_pa(:) = 0._r8 bc_out%ema_npp = 0._r8 - site_npp = 0._r8 - ! Process CH4 variables first !if(.not.(hlm_use_ch4==itrue) .and. .not.(hlm_parteh_mode==prt_cnp_flex_allom_hyp) ) @@ -384,29 +381,16 @@ subroutine PrepCH4BCs(csite,bc_in,bc_out) bc_out%annavg_bgnpp_pa(fp) = bgnpp ! gc/m2/yr bc_out%annsum_npp_pa(fp) = (bgnpp+agnpp)*days_per_year*sec_per_day - - site_npp = site_npp + (bgnpp+agnpp)*days_per_year*sec_per_day*cpatch%area*area_inv - + if(plant_area>nearzero) then bc_out%woody_frac_aere_pa(fp) = woody_area/plant_area end if end if - site_npp = site_npp + (bgnpp+agnpp)*days_per_year*sec_per_day*cpatch%area*area_inv - cpatch => cpatch%younger end do - ! Smoothed [gc/m2/yr] - if(csite%ema_npp<-9000._r8)then - ! For cold starts, we initialize the ema_npp value at -9999, so that - ! it becomes memoryless and uses the first calculated value - csite%ema_npp = site_npp - else - csite%ema_npp = (1._r8-1._r8/ema_npp_tscale)*csite%ema_npp + (1._r8/ema_npp_tscale)*site_npp - end if - bc_out%ema_npp = csite%ema_npp return @@ -716,12 +700,6 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) surface_prof(id) = surface_prof(id)/surface_prof_tot end do - - !bc_out%litt_flux_cel_n_si(:) = 100._r8 - !bc_out%litt_flux_lab_n_si(:) = 100._r8 - !bc_out%litt_flux_lig_n_si(:) = 100._r8 - - ! Loop over the different elements. do el = 1, num_elements @@ -753,10 +731,12 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) flux_lig_si => bc_out%litt_flux_lig_p_si(:) end select - !end do - !return - !do el = 1, num_elements - + ! These lines are for testing and should be removed + ! when the fates bgc pathway PR is integrated + !end do + !return + !do el = 1, num_elements + currentPatch => csite%oldest_patch do while (associated(currentPatch)) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 7c8aaba4ba..de4703017c 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -40,6 +40,7 @@ module FatesInterfaceMod use FatesConstantsMod , only : sec_per_day use FatesConstantsMod , only : days_per_year use FatesConstantsMod , only : TRS_regeneration + use FatesConstantsMod , only : g_per_kg use FatesGlobals , only : fates_global_verbose use FatesGlobals , only : fates_log use FatesGlobals , only : endrun => fates_endrun @@ -633,7 +634,7 @@ subroutine allocate_bcout(bc_out, nlevsoil_in, nlevdecomp_in) bc_out%rootfr_pa(0,1:nlevsoil_in)=1._r8/real(nlevsoil_in,r8) !end if - bc_out%ema_npp = -9999.9_r8 + bc_out%ema_npp = nan ! Fates -> BGC fragmentation mass fluxes select case(hlm_parteh_mode) @@ -1962,6 +1963,7 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) type(ed_patch_type), pointer :: cpatch type(ed_cohort_type), pointer :: ccohort integer :: s, ifp, io_si, pft + real(r8) :: site_npp ! Site level NPP gC/m2/year real(r8) :: new_seedling_layer_par ! seedling layer par in the current timestep real(r8) :: new_seedling_layer_smp ! seedling layer smp in the current timestep real(r8) :: new_seedling_mdd ! seedling layer moisture deficit days in the current timestep @@ -1971,10 +1973,12 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) real(r8) :: seedling_par_low ! lower intensity par for seedlings (par under the undergrowth) [W/m2] real(r8) :: par_low_frac ! fraction of ground where PAR is low integer,parameter :: ipar = 1 ! solar radiation in the shortwave band (i.e. par) + real(r8), parameter :: ema_npp_tscale = 480._r8 ! 10 day (10*48 steps) do s = 1,size(sites,dim=1) ifp=0 + site_npp = 0._r8 cpatch => sites(s)%oldest_patch do while(associated(cpatch)) if (cpatch%patchno .ne. 0) then @@ -1983,8 +1987,6 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) call cpatch%tveg_lpa%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) call cpatch%tveg_longterm%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) - - ! Update the seedling layer par running means if ( regeneration_model == TRS_regeneration ) then @@ -2030,15 +2032,29 @@ subroutine UpdateFatesRMeansTStep(sites,bc_in) end if - !ccohort => cpatch%tallest - !do while (associated(ccohort)) - ! call ccohort%tveg_lpa%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) - ! ccohort => ccohort%shorter - !end do + ccohort => cpatch%tallest + do while (associated(ccohort)) + ! call ccohort%tveg_lpa%UpdateRMean(bc_in(s)%t_veg_pa(ifp)) + + ! [kgC/plant/yr] -> [gC/m2/s] + site_npp = site_npp + ccohort%npp_acc_hold * ccohort%n*area_inv * & + g_per_kg * hlm_days_per_year / sec_per_day + + ccohort => ccohort%shorter + end do + end if cpatch => cpatch%younger enddo + + ! Smoothed [gc/m2/yr] + if(sites(s)%ema_npp<-9000._r8)then + sites(s)%ema_npp = site_npp + else + sites(s)%ema_npp = (1._r8-1._r8/ema_npp_tscale)*sites(s)%ema_npp + (1._r8/ema_npp_tscale)*site_npp + end if + end do return From cf41e0afe3396e849ca3e41d6fae99c125c436b4 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 31 Jul 2023 17:32:19 -0700 Subject: [PATCH 801/852] fix spmode cohort height initialization --- main/EDInitMod.F90 | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index daf502e1e7..8b76b604f4 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -801,6 +801,7 @@ subroutine init_cohorts(site_in, patch_in, bc_in) real(r8) :: canopy_trim ! fraction of the maximum leaf biomass that we are targeting [0-1] real(r8) :: cohort_n ! cohort density real(r8) :: dbh ! cohort dbh [cm] + real(r8) :: hite ! cohort height [m] real(r8) :: c_area ! cohort crown area [m2] real(r8) :: c_agw ! above ground (non-leaf) biomass [kgC] real(r8) :: c_bgw ! below ground (non-fineroot) biomss [kgC] @@ -922,19 +923,21 @@ subroutine init_cohorts(site_in, patch_in, bc_in) ! n.b. that this is the same as currentcohort%n = %initd(pft) &AREA cohort_n = cohort_n*sum(site_in%use_this_pft) endif + hite = EDPftvarcon_inst%hgt_min(pft) ! h, dbh, leafc, n from SP values or from small initial size if (hlm_use_sp .eq. itrue) then ! At this point, we do not know the bc_in values of tlai tsai and htop, ! so this is initializing to an arbitrary value for the very first timestep. ! Not sure if there's a way around this or not. - call calculate_SP_properties(0.5_r8, 0.2_r8, 0.1_r8, & + hite = 0.5_r8 + call calculate_SP_properties(hite, 0.2_r8, 0.1_r8, & patch_in%area, pft, crown_damage, 1, & EDPftvarcon_inst%vcmax25top(pft, 1), c_leaf, dbh, & cohort_n, c_area) else ! calculate the plant diameter from height - call h2d_allom(EDPftvarcon_inst%hgt_min(pft), pft, dbh) + call h2d_allom(hite, pft, dbh) ! Calculate the leaf biomass from allometry ! (calculates a maximum first, then applies canopy trim) @@ -1043,7 +1046,7 @@ subroutine init_cohorts(site_in, patch_in, bc_in) call prt%CheckInitialConditions() call create_cohort(site_in, patch_in, pft, cohort_n, & - EDPftvarcon_inst%hgt_min(pft), 0.0_r8, dbh, prt, efleaf_coh, & + hite, 0.0_r8, dbh, prt, efleaf_coh, & effnrt_coh, efstem_coh, leaf_status, recruitstatus, & canopy_trim, c_area, 1, crown_damage, site_in%spread, bc_in) From 65ed340b1f94a5de07f8a52769620939de0c105f Mon Sep 17 00:00:00 2001 From: "[Jennifer Kowalczyk]" <[jenniferkowalczyk@lbl.gov]> Date: Tue, 1 Aug 2023 11:58:14 -0700 Subject: [PATCH 802/852] swapped long names for MAINT_RESP* variables --- main/FatesHistoryInterfaceMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 0594c77506..605008e643 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -6475,7 +6475,7 @@ subroutine define_history_vars(this, initialize_variables) index = ih_growth_resp_secondary_si) call this%set_history_var(vname='FATES_MAINT_RESP', units='kg m-2 s-1', & - long='maintenance respiration in kg carbon per m2 land area per second, secondary patches', & + long='maintenance respiration in kg carbon per m2 land area per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=2, ivar=ivar, initialize=initialize_variables, & index = ih_maint_resp_si) @@ -6487,7 +6487,7 @@ subroutine define_history_vars(this, initialize_variables) index = ih_maint_resp_unreduced_si) call this%set_history_var(vname='FATES_MAINT_RESP_SECONDARY', units='kg m-2 s-1', & - long='maintenance respiration in kg carbon per m2 land area per second', & + long='maintenance respiration in kg carbon per m2 land area per second, secondary patches', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=2, ivar=ivar, initialize=initialize_variables, & index = ih_maint_resp_secondary_si) From 67b8d0191d28da19e13d9f84cec82c61ff3fe82e Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 1 Aug 2023 12:50:48 -0700 Subject: [PATCH 803/852] Add comments and remove unnecessary dependence to yaml file --- tools/luh2/conda-luh2.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/luh2/conda-luh2.yml b/tools/luh2/conda-luh2.yml index 4caf2e341b..12d4a35c65 100644 --- a/tools/luh2/conda-luh2.yml +++ b/tools/luh2/conda-luh2.yml @@ -1,3 +1,6 @@ +# This yaml file is intended for users who wish to utilize the luh2.py tool on their own machines. +# The file is not yet tested regularly to determine if the latest versions of the dependencies will +# always work. This regular testing is expected to be implemented in the future. name: luh2 channels: - conda-forge @@ -6,5 +9,3 @@ dependencies: - xesmf # xarray which is autodownloaded as xesmf dependency, uses scipy, which needs netcdf4 to open datasets - netcdf4 - - pynco -prefix: /home/glemieux/local/conda/miniconda3/envs/luh2 From 63124fd1ef0422595e09b46a2b3bf759166d509e Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 1 Aug 2023 15:20:33 -0700 Subject: [PATCH 804/852] add luh2 readme --- tools/luh2/README.md | 55 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 tools/luh2/README.md diff --git a/tools/luh2/README.md b/tools/luh2/README.md new file mode 100644 index 0000000000..60305c7ad1 --- /dev/null +++ b/tools/luh2/README.md @@ -0,0 +1,55 @@ +# FATES LUH2 data tool README + +## Purpose + +This tool takes the raw Land Use Harmonization (https://luh.umd.edu/), or LUH2, data files as +input and prepares them for use with FATES. The tool concatenates the various raw data sets into +a single file and provides the ability to regrid the source data resolution to a target +resolution that the user designates. The output data is then usable by FATES, mediated through +a host land model (currently either CTSM or E3SM). + +For more information on how FATES utilizes this information see https://github.com/NGEET/fates/pull/1040. + +## Installation + +This tool requires the usage of conda with python3. See https://docs.conda.io/en/latest/miniconda.html#installing +for information on installing conda on your system. To install the conda environment necessary to run the tool +execute the following commands: + +conda env create -f conda-luh2.yml + +This will create a conda environment named "luh2". To activate this environment run: + +conda activate luh2 + +For more information on creating conda environments see +https://conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html#creating-an-environment-from-an-environment-yml-file + +Note that it is planned that a subset of host land model (hlm) and hlm supported machines will incoporate this tool into the surface dataset workflow. +As such, if you are working on one of these machines, the output from this tool may be precomputed and available for the grid resolution of interest. + +## Usage + +After activating the "luh2" environment the tool can be run from the command line with the following minimum required inputs: + +python luh2.py -l -s -r -w -o + +The description of the minimum required input arguments is as follows: +- raw-luh2-datafile: this is one of three raw luh2 datafiles, either states, transitions, or management. This is the data to be regridded and used by FATES. +- luh2-static-datafile: supplementary 0.25 deg resolution static data used in the construction of the raw luh2 datafiles. This is utilized to help set the gridcell mask for the output file. +- regrid-targetfile: host land model surface data file intended to be used in conjunction with the fates run at a specific grid resolution. This is used as the regridder target resolution. +- regridder-output: the path and filename to write out the regridding weights file or to use an existing regridding weights file. +- outputfile: the path and filename to which the output is written + +The tool is intended to be run three times, sequentially, to concatenate the raw states, transitions, and management data into a single file. After the first run of +the tool, a merge option should also be included in the argument list pointing to the most recent output file. This will ensure that the previous regridding run +will be merged into the current run as well as reusing the previously output regridding weights file (to help reduce duplicate computation). +The luh2.sh file in this directory provides an example shell script in using the python tool in this sequential manner. The python tool itself provides additional +help by passing the `--help` option argument to the command line call. + +## Description of directory contents + +- luh2.py: main luh2 python script +- luh2mod.py: python module source file for the functions called in luh2.py +- luh2.sh: example bash shell script file demonstrating how to call luh2.py +- conda-luh2.yml: conda enviroment yaml file which defines the minimum set of package dependencies for luh2.py From e44bc90ffb895100051b7ed6305a4fa3625c5db9 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 1 Aug 2023 15:33:17 -0700 Subject: [PATCH 805/852] remove old comments --- tools/luh2/luh2mod.py | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/tools/luh2/luh2mod.py b/tools/luh2/luh2mod.py index 83ff10e40f..4a283382b8 100644 --- a/tools/luh2/luh2mod.py +++ b/tools/luh2/luh2mod.py @@ -93,8 +93,6 @@ def DimensionFixSurfData(input_dataset): input_dataset = input_dataset.rename_dims(dims_dict={'lsmlat':'lat','lsmlon':'lon'}) # Populate the new surface dataset with the actual lat/lon values - # input_dataset['longitude'] = input_dataset.LONGXY.isel(latitude=0) - # input_dataset['latitude'] = input_dataset.LATIXY.isel(longitude=0) input_dataset['lon'] = input_dataset.LONGXY.isel(lat=0) input_dataset['lat'] = input_dataset.LATIXY.isel(lon=0) @@ -102,20 +100,6 @@ def DimensionFixSurfData(input_dataset): return(input_dataset) -# def SetMask(input_dataset, masking_dataset): - -# # check what sort of inputdata is being provided; surface dataset or luh2 -# # LUH2 data will need to be masked based on the variable input to mask -# dsflag,dstype = CheckDataset(input_dataset) -# if (dsflag): -# if(dstype == "LUH2"): -# SetMaskLUH2(input_dataset) # temporary -# elif(dstype == "Surface"): -# SetMaskSurfData(input_dataset) -# print("mask added") -# -# return(input_dataset) - # LUH2 specific masking sub-function def SetMaskLUH2(input_dataset,static_data_set): @@ -244,15 +228,3 @@ def CorrectStateSum(input_dataset): input_dataset["stscf"] = 1.0 / state_sum return(input_dataset) - -# General functionality needed -# - collect data for specific user-defined time period -# - collect subset of the data variables (e.g. pasture, rangeland, etc) -# - write the subset to the necessary format to pass to regridding tools -# - This may need to be specific to the particular hlm tooling -# - call regridding tooling in hlm model -# - this will need to point at existing mapping data files, which are external to hlm -# - this may need a new mksurf_xxxx module if it can't conform to existing modules due -# to needing to use new fields -# future functionality: -# - importdata function for aforestation and other data to add to luh2 data From 4615b8a6a16462c6712d81939a2e9e3c89eff50c Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 1 Aug 2023 15:44:41 -0700 Subject: [PATCH 806/852] Add system exit if unrecognized file type provided as argument --- tools/luh2/luh2mod.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/luh2/luh2mod.py b/tools/luh2/luh2mod.py index 4a283382b8..29691bfbe2 100644 --- a/tools/luh2/luh2mod.py +++ b/tools/luh2/luh2mod.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -import re +import re, sys import numpy as np import xarray as xr import xesmf as xe @@ -138,7 +138,7 @@ def CheckDataset(input_dataset): dsflag = True else: dstype = 'Unknown' - print("Unrecognize data set") + sys.exit("CheckDataSetError: Unrecognize data set") return(dsflag,dstype) From 8cbb7ab204c2f2eb397d2cfec1da8f3471506da6 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 1 Aug 2023 17:22:16 -0700 Subject: [PATCH 807/852] update luh2 tool argparse options and time handling Adding 'default' and 'required' option as necessary to the argparse. This helps remove some of the luh2mod code that was previously handling default options. This also adds code to handle non-historical luh2 data file input arguments. Prior to this, it was assumed that only historical data files starting at 0850-01-01 were to be used. Now this can handle luh2 scenario files. It also adds time bounds error handling. --- tools/luh2/luh2.py | 45 +++++++++++++++++++------------- tools/luh2/luh2mod.py | 60 ++++++++++++++++++++++++++++--------------- 2 files changed, 66 insertions(+), 39 deletions(-) diff --git a/tools/luh2/luh2.py b/tools/luh2/luh2.py index 13d516cefa..3f31038565 100644 --- a/tools/luh2/luh2.py +++ b/tools/luh2/luh2.py @@ -79,14 +79,7 @@ def main(): # Write the files # TO DO: add check to handle if the user enters the full path - # TO DO: add check if user sets the output the same as the input - if (args.output == None): - output_filename = 'LUH2_timeseries.nc' - else: - output_filename = args.output - - - output_file = os.path.join(os.getcwd(),output_filename) + output_file = os.path.join(os.getcwd(),args.output) print("generating output: {}".format(output_file)) regrid_luh2.to_netcdf(output_file) @@ -96,29 +89,45 @@ def CommandLineArgs(): # Required input luh2 datafile # TO DO: using the checking function to report back if invalid file input - parser.add_argument("-l","--luh2_file", required=True) + parser.add_argument("-l","--luh2_file", + required=True, + help = "luh2 raw states, transitions, or management data file") # Required static luh2 data to get the ice/water fraction for masking - parser.add_argument("-s", "--luh2_static_file", required=True) + parser.add_argument("-s", "--luh2_static_file", + required=True, + help = "luh2 static data file") # File to use as regridder target (e.g. a surface dataset) - parser.add_argument("-r","--regridder_target_file", required=True) + parser.add_argument("-r","--regridder_target_file", + required=True, + help = "target file with desired resolution to regrid luh2 data to") # Filename to use or save for the regridder weights - parser.add_argument("-w", "--regridder_weights", required=True) + parser.add_argument("-w", "--regridder_weights", + default = 'regridder.nc', + help = "filename of regridder weights to write to or reuse (if -m option used)") # Optional input to subset the time range of the data # TODO: add support for parsing the input and checking against the allowable date range - parser.add_argument("-b","--begin", type=int, choices=range(850,2016), - help="beginning of date range to slice (allowable range is 0850-2015)") - parser.add_argument("-e","--end", type=int, choices=range(850,2016), - help="ending of date range to slice (allowable range is 0850-2015)") + parser.add_argument("-b","--begin", + type = int, + default = None, + help = "beginning of date range of interest") + parser.add_argument("-e","--end", + type = int, + default = None, + help = "ending of date range to slice") # Optional output argument - parser.add_argument("-o","--output") + parser.add_argument("-o","--output", + default = 'LUH2_timeseries.nc', + help = "output filename") # Optional merge argument to enable merging of other files - parser.add_argument("-m", "--luh2_merge_file") + parser.add_argument("-m", "--luh2_merge_file", + default = None, + help = "previous luh2 output filename to merge into current run output") args = parser.parse_args() diff --git a/tools/luh2/luh2mod.py b/tools/luh2/luh2mod.py index 29691bfbe2..c8534d42a9 100644 --- a/tools/luh2/luh2mod.py +++ b/tools/luh2/luh2mod.py @@ -22,28 +22,49 @@ def ImportData(input_file,start=None,stop=None,merge_flag=False): # Prepare the input_file to be used for regridding def PrepDataset(input_dataset,start=None,stop=None,merge_flag=False): - # Use the maximum span if start and stop are not present + # Check that the input dataset is a valid type dsflag, dstype = CheckDataset(input_dataset) - + + # Use the maximum span if start and stop are not present + # This assumes that the luh2 raw data will always use a + # 'years since' style format. if(not(dstype in ('static','regrid'))): - if (isinstance(start,type(None))): - start = input_dataset.time[0] - if (isinstance(stop,type(None))): - stop = input_dataset.time[-1] + if (dstype == 'LUH2'): + # Get the units to determine the file time + # It is expected that the units of time is 'years since ...' + time_since_array = input_dataset.time.units.split() + if (time_since_array[0] != 'years'): + sys.exit("FileTimeUnitsError: input file units of time is not 'years since ...'") + + # Note that datetime package is not used as the date range might + # be beyond the bounds of the packages applicable bounds + time_since = int(time_since_array[2].split('-')[0]) + + # Get the time bounds of the input file + start_bound = input_dataset.time.values[0] + stop_bound = input_dataset.time.values[-1] + + # If no input provided, simply get the bounds of the time + if (isinstance(start,type(None))): + start = start_bound + time_since + + if (isinstance(stop,type(None))): + stop = stop_bound + time_since + + # Convert the input dates to years since 0850 + years_since_start = start - time_since + years_since_stop = stop - time_since - # Convert the date to years since 0850 - years_since_start = start - 850 - years_since_stop = stop - 850 + # Abort if the times provided are outside the applicable range + if (years_since_start < start_bound or years_since_stop < start_bound or + years_since_start > stop_bound or years_since_stop > stop_bound): + sys.exit("StartStopBoundError: the input start or stop date is outside the applicable range of {} to {}".format(time_since+start_bound,time_since+stop_bound)) - # Truncate the data to the user defined range - # This might need some more error handling for when - # the start/stop is out of range - try: + # Truncate the data to the user defined range + # This might need some more error handling for when + # the start/stop is out of range input_dataset = input_dataset.sel(time=slice(years_since_start,years_since_stop)) - except TypeError as type_err: - print("Input must be a string\n") - raise TypeError(type_err) # Correct the necessary variables for both datasets # We don't need to Prep the incoming dataset if it's being opened to merge @@ -59,7 +80,7 @@ def PrepDataset_ESMF(input_dataset,dsflag,dstype): if(dstype == "LUH2"): print("PrepDataset: LUH2") input_dataset = BoundsVariableFixLUH2(input_dataset) - elif(dstype == "Surface"): + elif(dstype == "surface"): print("PrepDataset: SurfData") input_dataset = DimensionFixSurfData(input_dataset) print("data set updated for xESMF\n") @@ -89,7 +110,6 @@ def BoundsVariableFixLUH2(input_dataset): def DimensionFixSurfData(input_dataset): # Rename the surface dataset dimensions to something recognizable by xESMF. - # input_dataset = surfdataset.rename_dims(dims_dict={'lsmlat':'latitude','lsmlon':'longitude'}) input_dataset = input_dataset.rename_dims(dims_dict={'lsmlat':'lat','lsmlon':'lon'}) # Populate the new surface dataset with the actual lat/lon values @@ -105,14 +125,12 @@ def SetMaskLUH2(input_dataset,static_data_set): # Mask the luh2 data where the ice/water fraction is unity (i.e. fully ice covered gridcell) input_dataset["mask"] = (static_data_set.icwtr != 1) - # return(outputdataset) return(input_dataset) # Surface dataset specific masking sub-function def SetMaskSurfData(input_dataset): # Instead of passing the label_to_mask, loop through this for all labels? input_dataset["mask"] = input_dataset["PCT_NATVEG"] > 0 - # return(outputdataset) return(input_dataset) # Check which dataset we're working with @@ -127,7 +145,7 @@ def CheckDataset(input_dataset): dsflag = True print("LUH2") elif('natpft' in dsvars): - dstype = 'Surface' + dstype = 'surface' dsflag = True print("Surface") elif('icwtr' in dsvars): From 9cbfe4f0a10196e7805aec032205746b455eb92b Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 2 Aug 2023 14:42:46 -0700 Subject: [PATCH 808/852] update the usage description in luh2.py --- tools/luh2/luh2.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/luh2/luh2.py b/tools/luh2/luh2.py index 3f31038565..d0cd91afec 100644 --- a/tools/luh2/luh2.py +++ b/tools/luh2/luh2.py @@ -1,7 +1,8 @@ #!/usr/bin/env python3 # LUH2 python script -# Usage: python luh2.py -l -s +# Usage: python luh2.py -l -s \ +# -r -w -o import argparse, os, sys from luh2mod import ImportData, SetMaskLUH2, SetMaskSurfData From a6c3a74486fa4a1de574b4ec7e799d1299f1957d Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 7 Aug 2023 16:48:42 -0600 Subject: [PATCH 809/852] remove duplicate calculation of leaf_c --- biogeochem/EDPhysiologyMod.F90 | 3 --- 1 file changed, 3 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 9aaf9d3d80..b0dca899f7 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2013,9 +2013,6 @@ subroutine assign_cohort_SP_properties(currentCohort, htop, tlai, tsai, parea, i currentCohort%treelai = tlai currentCohort%treesai = tsai - leaf_c = leafc_from_treelai(tlai, currentCohort%pft, currentCohort%c_area, & - currentCohort%n, currentCohort%canopy_layer, currentCohort%vcmax25top) - if (init .eq. ifalse) then call SetState(currentCohort%prt, leaf_organ, carbon12_element, leaf_c, 1) endif From e12062f831e965e1439bbab7941d2299c49d72cb Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 10 Aug 2023 14:31:47 -0600 Subject: [PATCH 810/852] Small syntax updates and accomodations for moving litter flux bc outs --- biogeochem/FatesSoilBGCFluxMod.F90 | 6 ------ main/EDMainMod.F90 | 6 +++--- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index 5dafb6276c..6dd9300e51 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -731,12 +731,6 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) flux_lig_si => bc_out%litt_flux_lig_p_si(:) end select - ! These lines are for testing and should be removed - ! when the fates bgc pathway PR is integrated - !end do - !return - !do el = 1, num_elements - currentPatch => csite%oldest_patch do while (associated(currentPatch)) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 75f9c3e498..61691f4228 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -743,9 +743,9 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) enddo - ! Before we start messing with the patch areas, and before we start removing - ! trees, this is a good time to pass fragmentation litter fluxes and - ! plant-to-soil fluxes (such as efflux and fixation fluxes) + ! RGK: This call is unecessary for CLM coupling. I believe we + ! can remove it completely if/when this call is added in ELM to + ! subroutine UpdateLitterFluxes(this,bounds_clump) in elmfates_interfaceMod.F90 call FluxIntoLitterPools(currentsite, bc_in, bc_out) From 39b6a15c77781296c69575def7128ce89934d4b8 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Mon, 14 Aug 2023 15:08:41 -0600 Subject: [PATCH 811/852] put back error tolerance values --- biogeochem/EDCanopyStructureMod.F90 | 4 ++-- biogeochem/EDPhysiologyMod.F90 | 4 ++-- main/FatesConstantsMod.F90 | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 2232b74580..1f995e65e4 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -8,7 +8,7 @@ module EDCanopyStructureMod use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : itrue, ifalse use FatesConstantsMod , only : tinyr8 - use FatesConstantsMod , only : nearzero, area_error + use FatesConstantsMod , only : nearzero, area_error_1 use FatesConstantsMod , only : rsnbl_math_prec use FatesConstantsMod , only : nocomp_bareground use FatesGlobals , only : fates_log @@ -1389,7 +1389,7 @@ subroutine canopy_summarization( nsites, sites, bc_in ) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if (currentPatch%total_canopy_area - currentPatch%area > area_error) then + if (currentPatch%total_canopy_area - currentPatch%area > area_error_1) then write(fates_log(),*) 'too much canopy in summary', s, & currentPatch%nocomp_pft_label, currentPatch%total_canopy_area - currentPatch%area call endrun(msg=errMsg(sourcefile, __LINE__)) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 8fb6c30f55..01bb370594 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -33,7 +33,7 @@ module EDPhysiologyMod use FatesConstantsMod, only : g_per_kg use FatesConstantsMod, only : ndays_per_year use FatesConstantsMod, only : nocomp_bareground - use FatesConstantsMod, only : area_error + use FatesConstantsMod, only : area_error_2 use EDPftvarcon , only : EDPftvarcon_inst use PRTParametersMod , only : prt_params use EDPftvarcon , only : GetDecompyFrac @@ -1960,7 +1960,7 @@ subroutine assign_cohort_SP_properties(currentCohort,htop,tlai,tsai,parea,init,l currentCohort%n, currentCohort%canopy_layer, & canopylai,currentCohort%vcmax25top ) - if (abs(currentCohort%treelai - check_treelai) > area_error) then !this is not as precise as nearzero + if (abs(currentCohort%treelai - check_treelai) > area_error_2) then !this is not as precise as nearzero write(fates_log(),*) 'error in validate treelai',currentCohort%treelai,check_treelai,currentCohort%treelai-check_treelai write(fates_log(),*) 'tree_lai inputs: ', currentCohort%pft, currentCohort%c_area, currentCohort%n, & currentCohort%canopy_layer, currentCohort%vcmax25top diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index 2bada8ce1f..5d53b9b9a8 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -99,7 +99,8 @@ module FatesConstantsMod ! of carbon conservation in units of kgC/plant. This gives an effective ! error tolerance of 1 microgram. real(fates_r8), parameter, public :: calloc_abs_error = 1.0e-9_fates_r8 - real(fates_r8), parameter, public :: area_error = 1.0e-9_fates_r8 ! error tolerance for area checks (canopy, patch) + real(fates_r8), parameter, public :: area_error_1 = 1.0e-16_fates_r8 ! error tolerance for area checks (canopy, patch) + real(fates_r8), parameter, public :: area_error_2 = 1.0e-12_fates_r8 ! error tolerance for tree lai checks ! Rounding errors seem to hover around 1e-15 for the gnu compiler ! when not applying compiler directives for safe math. An example From 91aded9df5ee69038c4a7cc5c4676ff72e323bc4 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Mon, 14 Aug 2023 15:12:38 -0600 Subject: [PATCH 812/852] update to ensure b4b --- biogeochem/EDPhysiologyMod.F90 | 4 ++-- main/FatesConstantsMod.F90 | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 01bb370594..c13d11d3ef 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -96,7 +96,7 @@ module EDPhysiologyMod use EDParamsMod , only : sdlng_mort_par_timescale use FatesPlantHydraulicsMod , only : AccumulateMortalityWaterStorage use FatesConstantsMod , only : itrue,ifalse - use FatesConstantsMod , only : calloc_abs_error + use FatesConstantsMod , only : area_error_3 use FatesConstantsMod , only : years_per_day use FatesAllometryMod , only : h_allom use FatesAllometryMod , only : h2d_allom @@ -1973,7 +1973,7 @@ subroutine assign_cohort_SP_properties(currentCohort,htop,tlai,tsai,parea,init,l !! carea_allom in SP mode after this point. if (abs(currentCohort%c_area - parea) > nearzero) then ! there is an error - if (abs(currentCohort%c_area - parea) < calloc_abs_error) then !correct this if it's a very small error + if (abs(currentCohort%c_area - parea) < area_error_3) then !correct this if it's a very small error oldcarea = currentCohort%c_area ! generate new cohort area currentCohort%c_area = currentCohort%c_area - (currentCohort%c_area - parea) diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index 5d53b9b9a8..3956972cdd 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -101,6 +101,7 @@ module FatesConstantsMod real(fates_r8), parameter, public :: calloc_abs_error = 1.0e-9_fates_r8 real(fates_r8), parameter, public :: area_error_1 = 1.0e-16_fates_r8 ! error tolerance for area checks (canopy, patch) real(fates_r8), parameter, public :: area_error_2 = 1.0e-12_fates_r8 ! error tolerance for tree lai checks + real(fates_r8), parameter, public :: area_error_3 = 10.e-9_fates_r8 ! error tolerance for area checks (canopy, patch) ! Rounding errors seem to hover around 1e-15 for the gnu compiler ! when not applying compiler directives for safe math. An example From c831cbf08bd80ffbf24e22c3932e9bf20cc1f381 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Mon, 14 Aug 2023 15:22:42 -0600 Subject: [PATCH 813/852] fix merge conflict --- main/EDInitMod.F90 | 208 +-------------------------------------------- 1 file changed, 4 insertions(+), 204 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index bca2c5b263..e4ea4ae8aa 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -1054,212 +1054,12 @@ subroutine init_cohorts(site_in, patch_in, bc_in) endif if_use_this_pft enddo pft_loop - call fuse_cohorts(site_in, patch_in,bc_in) - call sort_cohorts(patch_in) + if (hlm_use_sp == ifalse) then + call fuse_cohorts(site_in, patch_in,bc_in) + call sort_cohorts(patch_in) + end if -<<<<<<< HEAD - ! -------------------------------------------------------------------------------- - ! Initialize the mass of every element in every organ of the organ - ! -------------------------------------------------------------------------------- - - prt_obj => null() - call InitPRTObject(prt_obj) - - element_loop: do el = 1,num_elements - - element_id = element_list(el) - - ! If this is carbon12, then the initialization is straight forward - ! otherwise, we use stoichiometric ratios - select case(element_id) - case(carbon12_element) - - m_struct = c_struct - m_leaf = c_leaf - m_fnrt = c_fnrt - m_sapw = c_sapw - m_store = c_store - m_repro = 0._r8 - - case(nitrogen_element) - - m_struct = c_struct*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(struct_organ)) - m_leaf = c_leaf*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(leaf_organ)) - m_fnrt = c_fnrt*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(fnrt_organ)) - m_sapw = c_sapw*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(sapw_organ)) - m_repro = 0._r8 - m_store = StorageNutrientTarget(pft,element_id,m_leaf,m_fnrt,m_sapw,m_struct) - - case(phosphorus_element) - - m_struct = c_struct*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(struct_organ)) - m_leaf = c_leaf*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(leaf_organ)) - m_fnrt = c_fnrt*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(fnrt_organ)) - m_sapw = c_sapw*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(sapw_organ)) - m_repro = 0._r8 - m_store = StorageNutrientTarget(pft,element_id,m_leaf,m_fnrt,m_sapw,m_struct) - - end select - - select case(hlm_parteh_mode) - case (prt_carbon_allom_hyp,prt_cnp_flex_allom_hyp ) - - ! Put all of the leaf mass into the first bin - call SetState(prt_obj,leaf_organ, element_id,m_leaf,1) - do iage = 2,nleafage - call SetState(prt_obj,leaf_organ, element_id,0._r8,iage) - end do - - call SetState(prt_obj,fnrt_organ, element_id, m_fnrt) - call SetState(prt_obj,sapw_organ, element_id, m_sapw) - call SetState(prt_obj,store_organ, element_id, m_store) - call SetState(prt_obj,struct_organ, element_id, m_struct) - call SetState(prt_obj,repro_organ, element_id, m_repro) - - case default - write(fates_log(),*) 'Unspecified PARTEH module during create_cohort' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end select - - end do element_loop - - call prt_obj%CheckInitialConditions() - - call create_cohort(site_in, patch_in, pft, temp_cohort%n, temp_cohort%hite, & - temp_cohort%coage, temp_cohort%dbh, prt_obj, temp_cohort%efleaf_coh, & - temp_cohort%effnrt_coh, temp_cohort%efstem_coh, temp_cohort%status_coh, & - rstatus, temp_cohort%canopy_trim, & - temp_cohort%c_area,1,temp_cohort%crowndamage, site_in%spread, bc_in) - - - deallocate(temp_cohort, stat=istat, errmsg=smsg) - if (istat/=0) then - write(fates_log(),*) 'dealloc014: fail on deallocate(temp_cohort):'//trim(smsg) - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - end if if_use_this_pft - end do pft_loop - - ! (Keeping as an example) - ! Pass patch level temperature to the new cohorts (this is a nominal 15C right now) - !temp_cohort => patch_in%tallest - !do while(associated(temp_cohort)) - !call temp_cohort%tveg_lpa%UpdateRmean(patch_in%tveg_lpa%GetMean()) - !temp_cohort => temp_cohort%shorter - !end do - - if (hlm_use_sp == ifalse) then - call fuse_cohorts(site_in, patch_in,bc_in) - call sort_cohorts(patch_in) - end if - - - end subroutine init_cohorts - - ! =============================================================================================== -||||||| 3fcc9fca - ! -------------------------------------------------------------------------------- - ! Initialize the mass of every element in every organ of the organ - ! -------------------------------------------------------------------------------- - - prt_obj => null() - call InitPRTObject(prt_obj) - - element_loop: do el = 1,num_elements - - element_id = element_list(el) - - ! If this is carbon12, then the initialization is straight forward - ! otherwise, we use stoichiometric ratios - select case(element_id) - case(carbon12_element) - - m_struct = c_struct - m_leaf = c_leaf - m_fnrt = c_fnrt - m_sapw = c_sapw - m_store = c_store - m_repro = 0._r8 - - case(nitrogen_element) - - m_struct = c_struct*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(struct_organ)) - m_leaf = c_leaf*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(leaf_organ)) - m_fnrt = c_fnrt*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(fnrt_organ)) - m_sapw = c_sapw*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(sapw_organ)) - m_repro = 0._r8 - m_store = StorageNutrientTarget(pft,element_id,m_leaf,m_fnrt,m_sapw,m_struct) - - case(phosphorus_element) - - m_struct = c_struct*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(struct_organ)) - m_leaf = c_leaf*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(leaf_organ)) - m_fnrt = c_fnrt*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(fnrt_organ)) - m_sapw = c_sapw*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(sapw_organ)) - m_repro = 0._r8 - m_store = StorageNutrientTarget(pft,element_id,m_leaf,m_fnrt,m_sapw,m_struct) - - end select - - select case(hlm_parteh_mode) - case (prt_carbon_allom_hyp,prt_cnp_flex_allom_hyp ) - - ! Put all of the leaf mass into the first bin - call SetState(prt_obj,leaf_organ, element_id,m_leaf,1) - do iage = 2,nleafage - call SetState(prt_obj,leaf_organ, element_id,0._r8,iage) - end do - - call SetState(prt_obj,fnrt_organ, element_id, m_fnrt) - call SetState(prt_obj,sapw_organ, element_id, m_sapw) - call SetState(prt_obj,store_organ, element_id, m_store) - call SetState(prt_obj,struct_organ, element_id, m_struct) - call SetState(prt_obj,repro_organ, element_id, m_repro) - - case default - write(fates_log(),*) 'Unspecified PARTEH module during create_cohort' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end select - - end do element_loop - - call prt_obj%CheckInitialConditions() - - call create_cohort(site_in, patch_in, pft, temp_cohort%n, temp_cohort%hite, & - temp_cohort%coage, temp_cohort%dbh, prt_obj, temp_cohort%efleaf_coh, & - temp_cohort%effnrt_coh, temp_cohort%efstem_coh, temp_cohort%status_coh, & - rstatus, temp_cohort%canopy_trim, & - temp_cohort%c_area,1,temp_cohort%crowndamage, site_in%spread, bc_in) - - - deallocate(temp_cohort, stat=istat, errmsg=smsg) - if (istat/=0) then - write(fates_log(),*) 'dealloc014: fail on deallocate(temp_cohort):'//trim(smsg) - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - end if if_use_this_pft - end do pft_loop - - ! (Keeping as an example) - ! Pass patch level temperature to the new cohorts (this is a nominal 15C right now) - !temp_cohort => patch_in%tallest - !do while(associated(temp_cohort)) - !call temp_cohort%tveg_lpa%UpdateRmean(patch_in%tveg_lpa%GetMean()) - !temp_cohort => temp_cohort%shorter - !end do - - call fuse_cohorts(site_in, patch_in,bc_in) - call sort_cohorts(patch_in) - - - end subroutine init_cohorts - - ! =============================================================================================== -======= end subroutine init_cohorts ->>>>>>> main ! ====================================================================================== From f5c75efb71b0692a2f0d80de264df0fd63e6ee36 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Mon, 14 Aug 2023 15:23:37 -0600 Subject: [PATCH 814/852] add fates_r8 --- main/FatesConstantsMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index 6f198b6dba..c73483fe67 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -150,7 +150,7 @@ module FatesConstantsMod real(fates_r8), parameter, public :: area_error_1 = 1.0e-16_fates_r8 ! error tolerance for area checks (canopy, patch) real(fates_r8), parameter, public :: area_error_2 = 1.0e-12_fates_r8 ! error tolerance for tree lai checks real(fates_r8), parameter, public :: area_error_3 = 10.e-9_fates_r8 ! error tolerance for area checks (canopy, patch) - real(fates_r8), parameter, public :: area_error_4 = 1.0e-10_r8 ! error tolerance for area checks + real(fates_r8), parameter, public :: area_error_4 = 1.0e-10_fates_r8 ! error tolerance for area checks ! Rounding errors seem to hover around 1e-15 for the gnu compiler ! when not applying compiler directives for safe math. An example From 5e7ed9d07d9fa279de4a1519a761a7df07538319 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Mon, 14 Aug 2023 16:33:54 -0600 Subject: [PATCH 815/852] add missing variable --- main/EDInitMod.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index e4ea4ae8aa..c6bf83baaf 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -546,6 +546,7 @@ subroutine init_patches( nsites, sites, bc_in) integer :: el real(r8) :: age !notional age of this patch integer :: ageclass + real(r8) :: area_diff ! dummy locals real(r8) :: biomass_stock From 9a27cd2f8497942f3ef383234f5480fa7ae73576 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 15 Aug 2023 08:11:01 -0600 Subject: [PATCH 816/852] relax tolerance a bit --- biogeochem/EDCanopyStructureMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 761f22bc29..960264c782 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1389,7 +1389,7 @@ subroutine canopy_summarization( nsites, sites, bc_in ) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if (currentPatch%total_canopy_area - currentPatch%area > area_error_1) then + if (currentPatch%total_canopy_area - currentPatch%area > area_error_2) then write(fates_log(),*) 'too much canopy in summary', s, & currentPatch%nocomp_pft_label, currentPatch%total_canopy_area - currentPatch%area call endrun(msg=errMsg(sourcefile, __LINE__)) From cd6299a1acc9da1a3a9a2e14fa894962a03b6e8f Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 15 Aug 2023 08:53:31 -0600 Subject: [PATCH 817/852] add error constant --- biogeochem/EDCanopyStructureMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 960264c782..59d512016f 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -8,7 +8,7 @@ module EDCanopyStructureMod use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : itrue, ifalse use FatesConstantsMod , only : tinyr8 - use FatesConstantsMod , only : nearzero, area_error_1 + use FatesConstantsMod , only : nearzero, area_error_2 use FatesConstantsMod , only : rsnbl_math_prec use FatesConstantsMod , only : nocomp_bareground use FatesGlobals , only : fates_log From 0630320a16b76d4cf804d2670eea971ea2d97eaa Mon Sep 17 00:00:00 2001 From: adrifoster Date: Fri, 18 Aug 2023 09:24:58 -0600 Subject: [PATCH 818/852] update error tolerance --- main/FatesConstantsMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index c73483fe67..8ac4c3b7f0 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -148,7 +148,7 @@ module FatesConstantsMod ! area tolerance checks real(fates_r8), parameter, public :: area_error_1 = 1.0e-16_fates_r8 ! error tolerance for area checks (canopy, patch) - real(fates_r8), parameter, public :: area_error_2 = 1.0e-12_fates_r8 ! error tolerance for tree lai checks + real(fates_r8), parameter, public :: area_error_2 = 1.0e-11_fates_r8 ! error tolerance for tree lai checks real(fates_r8), parameter, public :: area_error_3 = 10.e-9_fates_r8 ! error tolerance for area checks (canopy, patch) real(fates_r8), parameter, public :: area_error_4 = 1.0e-10_fates_r8 ! error tolerance for area checks From b1a2efbd2006d70ca9dd09a8fdad72c9c4d65714 Mon Sep 17 00:00:00 2001 From: Adrianna Foster Date: Fri, 18 Aug 2023 12:56:46 -0600 Subject: [PATCH 819/852] test new fix --- biogeochem/EDCanopyStructureMod.F90 | 4 ++-- main/EDInitMod.F90 | 21 ++++++++++++++++++++- main/FatesConstantsMod.F90 | 2 +- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 59d512016f..761f22bc29 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -8,7 +8,7 @@ module EDCanopyStructureMod use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : itrue, ifalse use FatesConstantsMod , only : tinyr8 - use FatesConstantsMod , only : nearzero, area_error_2 + use FatesConstantsMod , only : nearzero, area_error_1 use FatesConstantsMod , only : rsnbl_math_prec use FatesConstantsMod , only : nocomp_bareground use FatesGlobals , only : fates_log @@ -1389,7 +1389,7 @@ subroutine canopy_summarization( nsites, sites, bc_in ) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if (currentPatch%total_canopy_area - currentPatch%area > area_error_2) then + if (currentPatch%total_canopy_area - currentPatch%area > area_error_1) then write(fates_log(),*) 'too much canopy in summary', s, & currentPatch%nocomp_pft_label, currentPatch%total_canopy_area - currentPatch%area call endrun(msg=errMsg(sourcefile, __LINE__)) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index c6bf83baaf..d7ff088df4 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -10,7 +10,7 @@ module EDInitMod use FatesConstantsMod , only : fates_unset_int use FatesConstantsMod , only : fates_unset_r8 use FatesConstantsMod , only : primaryforest - use FatesConstantsMod , only : nearzero, area_error_4 + use FatesConstantsMod , only : nearzero, area_error_4, area_error_3 use FatesGlobals , only : endrun => fates_endrun use EDParamsMod , only : nclmax use EDParamsMod , only : regeneration_model @@ -559,11 +559,13 @@ subroutine init_patches( nsites, sites, bc_in) real(r8) :: newparea real(r8) :: total !check on area real(r8) :: litt_init + real(r8) :: old_carea integer :: is_first_patch type(ed_site_type), pointer :: sitep type(fates_patch_type), pointer :: newppft(:) type(fates_patch_type), pointer :: newp + type(fates_cohort_type), pointer :: cohort type(fates_patch_type), pointer :: currentPatch ! List out some nominal patch values that are used for Near Bear Ground initializations @@ -722,6 +724,23 @@ subroutine init_patches( nsites, sites, bc_in) call endrun(msg=errMsg(sourcefile, __LINE__)) end if ! big error end if ! too much patch area + + ! we might have messed up patch area now - need to correct if SP mode + if (hlm_use_sp .eq. itrue) then + newp => sites(s)%oldest_patch + do while (associated(newp)) + cohort => newp%tallest + do while (associated(cohort)) + if (abs(cohort%c_area - newp%area) < area_error_3) then ! correct if it's a very small error + old_carea = cohort%c_area + cohort%c_area = cohort%c_area - (cohort%c_area - newp%area) + cohort%n = cohort%n*(cohort%c_area/old_carea) + end if + cohort => cohort%shorter + end do + newp => newp%younger + end do + end if ! For carbon balance checks, we need to initialize the ! total carbon stock diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index 8ac4c3b7f0..c73483fe67 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -148,7 +148,7 @@ module FatesConstantsMod ! area tolerance checks real(fates_r8), parameter, public :: area_error_1 = 1.0e-16_fates_r8 ! error tolerance for area checks (canopy, patch) - real(fates_r8), parameter, public :: area_error_2 = 1.0e-11_fates_r8 ! error tolerance for tree lai checks + real(fates_r8), parameter, public :: area_error_2 = 1.0e-12_fates_r8 ! error tolerance for tree lai checks real(fates_r8), parameter, public :: area_error_3 = 10.e-9_fates_r8 ! error tolerance for area checks (canopy, patch) real(fates_r8), parameter, public :: area_error_4 = 1.0e-10_fates_r8 ! error tolerance for area checks From 5f72b2a6f1cb038be7341a68a7105fdcb7b2574e Mon Sep 17 00:00:00 2001 From: adrifoster Date: Fri, 18 Aug 2023 13:07:05 -0600 Subject: [PATCH 820/852] update indentation --- main/EDInitMod.F90 | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index d7ff088df4..6f7b649a4b 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -725,22 +725,22 @@ subroutine init_patches( nsites, sites, bc_in) end if ! big error end if ! too much patch area - ! we might have messed up patch area now - need to correct if SP mode - if (hlm_use_sp .eq. itrue) then - newp => sites(s)%oldest_patch - do while (associated(newp)) - cohort => newp%tallest - do while (associated(cohort)) - if (abs(cohort%c_area - newp%area) < area_error_3) then ! correct if it's a very small error - old_carea = cohort%c_area - cohort%c_area = cohort%c_area - (cohort%c_area - newp%area) - cohort%n = cohort%n*(cohort%c_area/old_carea) - end if - cohort => cohort%shorter - end do - newp => newp%younger - end do - end if + ! we might have messed up patch area now - need to correct if SP mode + if (hlm_use_sp .eq. itrue) then + newp => sites(s)%oldest_patch + do while (associated(newp)) + cohort => newp%tallest + do while (associated(cohort)) + if (abs(cohort%c_area - newp%area) < area_error_3) then ! correct if it's a very small error + old_carea = cohort%c_area + cohort%c_area = cohort%c_area - (cohort%c_area - newp%area) + cohort%n = cohort%n*(cohort%c_area/old_carea) + end if + cohort => cohort%shorter + end do + newp => newp%younger + end do + end if ! For carbon balance checks, we need to initialize the ! total carbon stock From 7750e5b90055b7eb4507ddbabb9a7c0bbc6ded49 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 21 Aug 2023 15:49:41 -0700 Subject: [PATCH 821/852] correct units per issue #1047 --- main/FatesHistoryInterfaceMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 605008e643..cfc33a2128 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -5481,7 +5481,7 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_gpp_sec_si_pft) - call this%set_history_var(vname='FATES_NPP_SE_PF', units='kg m-2 yr-1', & + call this%set_history_var(vname='FATES_NPP_SE_PF', units='kg m-2 s-1', & long='total PFT-level NPP in kg carbon per m2 land area per second, secondary patches', & use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & From 7b0cbf5d3e90cf85e2f4a4c0ce0bdd6cd55d36e2 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 23 Aug 2023 22:23:55 -0700 Subject: [PATCH 822/852] make global number of gridcells an input argument --- main/FatesInterfaceMod.F90 | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index d2f8162fb8..bdfb9a101f 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -2166,14 +2166,14 @@ end subroutine SeedlingParPatch ! ====================================================================================== -subroutine DetermineGridCellNeighbors(neighbors) +subroutine DetermineGridCellNeighbors(neighbors,numg) ! This subroutine utilizes information from the decomposition and domain types to determine ! the set of grid cell neighbors within some maximum distance. It records the distance for each ! neighbor for later use. This should be called after decompInit_lnd and surf_get_grid ! as it relies on ldecomp and ldomain information. - use decompMod , only : procinfo, get_proc_global + use decompMod , only : procinfo use domainMod , only : ldomain use spmdMod , only : MPI_REAL8, MPI_INTEGER, mpicom, npes, masterproc, iam use perf_mod , only : t_startf, t_stopf @@ -2183,17 +2183,14 @@ subroutine DetermineGridCellNeighbors(neighbors) use EDPftvarcon , only : EDPftvarcon_inst ! Arguments - type(neighborhood_type), intent(inout), pointer :: neighbors(:) + type(neighborhood_type), intent(inout), pointer :: neighbors(:) ! land gridcell neighbor data structure + integer , intent(in) :: numg ! number of land gridcells ! Local variables type (neighbor_type), pointer :: current_neighbor type (neighbor_type), pointer :: another_neighbor integer :: i, gi,gj ! indices - integer :: numg ! number of land gridcells - integer :: ngcheck ! number of land gridcells, globally - integer :: numproc ! number of processors, globally - integer :: ier,mpierr ! error code integer :: ipft ! pft index integer :: ldsize ! ldomain size @@ -2211,17 +2208,16 @@ subroutine DetermineGridCellNeighbors(neighbors) ! Allocate array neighbor type - call get_proc_global(ng=numg) allocate(neighbors(numg), stat=ier) neighbors(:)%neighbor_count = 0 - allocate(gclat(numg)) + allocate(gclat(numg), stat=ier) allocate(gclon(numg)) - gclon = nan - gclat = nan + gclon(:) = nan + gclat(:) = nan - allocate(ncells_array(0:npes-1)) - allocate(begg_array(0:npes-1)) + allocate(ncells_array(0:npes-1), stat=ier) + allocate(begg_array(0:npes-1), stat=ier) ncells_array(:) = fates_unset_int begg_array(:) = fates_unset_int From e067714c11c0d88aa3fc9c18ded4d9aa8209d882 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 23 Aug 2023 22:40:54 -0700 Subject: [PATCH 823/852] restore accidentally deleted error status variables --- main/FatesInterfaceMod.F90 | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index bdfb9a101f..e215bfd354 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -2190,10 +2190,9 @@ subroutine DetermineGridCellNeighbors(neighbors,numg) type (neighbor_type), pointer :: current_neighbor type (neighbor_type), pointer :: another_neighbor - integer :: i, gi,gj ! indices - integer :: ipft ! pft index - - integer :: ldsize ! ldomain size + integer :: i, gi,gj ! indices + integer :: ier, mpierr ! error status + integer :: ipft ! pft index integer, allocatable :: ncells_array(:), begg_array(:) real(r8), allocatable :: gclat(:), gclon(:) From ce241b6b30f0276b80a2832e633eb9d3f1406d7e Mon Sep 17 00:00:00 2001 From: Gregory Lemieux <7565064+glemieux@users.noreply.github.com> Date: Thu, 24 Aug 2023 15:18:37 -0700 Subject: [PATCH 824/852] Update PULL_REQUEST_TEMPLATE.md Updating the PR template to direct contributors to create an issue on the fates technical and/or user's guide as necessary so that we can track what needs updating. --- .github/PULL_REQUEST_TEMPLATE.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 8efa4c7b77..4b5f654602 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -18,25 +18,25 @@ ### Checklist: -- [ ] My change requires a change to the documentation. -- [ ] I have updated the in-code documentation .AND. (the [technical note](https://github.com/NGEET/fates-docs) .OR. the wiki) accordingly. -- [ ] I have read the [**CONTRIBUTING**](https://github.com/NGEET/fates/blob/master/CONTRIBUTING.md) document. +*If this is your first time contributing, please read the [**CONTRIBUTING**](https://github.com/NGEET/fates/blob/main/CONTRIBUTING.md) document.* + +All checklist items must be checked to enable merging this pull request: +- [ ] I have updated the in-code documentation with descriptive comments +- [ ] I have created an issue to update the [technical note](https://github.com/NGEET/fates-docs/issues/new/choose) / [user's guide](https://github.com/NGEET/fates-users-guide/issues/new/choose) as necessary - [ ] FATES PASS/FAIL regression tests were run - [ ] If answers were expected to change, evaluation was performed and provided + ### Test Results: -CTSM (or) E3SM (specify which) test hash-tag: - -CTSM (or) E3SM (specify which) baseline hash-tag: - -FATES baseline hash-tag: - -Test Output: +*CTSM (or) E3SM (specify which) test hash-tag:* +*CTSM (or) E3SM (specify which) baseline hash-tag:* +*FATES baseline hash-tag:* +*Test Output:* From 74228cad71eca0eff298fe8b52697429793413dc Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 24 Aug 2023 15:54:48 -0700 Subject: [PATCH 825/852] add site x pft restart variable for seed_in from dispersal --- main/FatesRestartInterfaceMod.F90 | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 55016e9acb..1fe71afa87 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -258,6 +258,9 @@ module FatesRestartInterfaceMod integer :: ir_woodprod_mbal integer :: ir_prt_base ! Base index for all PRT variables + ! site-level input seed from dispersal + integer :: ir_seed_in_sift + ! Damage x damage or damage x size integer :: ir_imortrate_sicdpf integer :: ir_termnindiv_cano_sicdpf @@ -703,7 +706,6 @@ subroutine define_restart_vars(this, initialize_variables) units='kgC/m2', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_trunk_product_si ) - ! ----------------------------------------------------------------------------------- ! Variables stored within cohort vectors ! Note: Some of these are multi-dimensional variables in the patch/site dimension @@ -1273,6 +1275,11 @@ subroutine define_restart_vars(this, initialize_variables) units='0/1', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_area_pft_sift) + call this%set_restart_var(vname='fates_seed_in_site', vtype=cohort_r8, & + long_name='Site-level seed mass input from neighboring gridcells per pft', & + units='kg', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_seed_in_sift ) + call this%set_restart_var(vname='fates_fmortrate_canopy', vtype=cohort_r8, & long_name='fates diagnostics on fire mortality canopy', & units='indiv/ha/year', flushval = flushzero, & @@ -2052,6 +2059,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_recrate_sift => this%rvars(ir_recrate_sift)%r81d, & rio_use_this_pft_sift => this%rvars(ir_use_this_pft_sift)%int1d, & rio_area_pft_sift => this%rvars(ir_area_pft_sift)%r81d, & + rio_seed_in_sift => this%rvars(ir_seed_in_sift)%r81d, & rio_fmortrate_cano_siscpf => this%rvars(ir_fmortrate_cano_siscpf)%r81d, & rio_fmortrate_usto_siscpf => this%rvars(ir_fmortrate_usto_siscpf)%r81d, & rio_imortrate_siscpf => this%rvars(ir_imortrate_siscpf)%r81d, & @@ -2170,6 +2178,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_dndaysleafon_sift(io_idx_si_pft) = sites(s)%dndaysleafon(i_pft) rio_dndaysleafoff_sift(io_idx_si_pft) = sites(s)%dndaysleafoff(i_pft) rio_elong_factor_sift(io_idx_si_pft) = sites(s)%elong_factor(i_pft) + rio_seed_in_sift(io_idx_si_pft) = sites(s)%seed_in(i_pft) io_idx_si_pft = io_idx_si_pft + 1 end do @@ -2990,6 +2999,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_recrate_sift => this%rvars(ir_recrate_sift)%r81d, & rio_use_this_pft_sift => this%rvars(ir_use_this_pft_sift)%int1d, & rio_area_pft_sift => this%rvars(ir_area_pft_sift)%r81d,& + rio_seed_in_sift => this%rvars(ir_seed_in_sift)%r81d, & rio_fmortrate_cano_siscpf => this%rvars(ir_fmortrate_cano_siscpf)%r81d, & rio_fmortrate_usto_siscpf => this%rvars(ir_fmortrate_usto_siscpf)%r81d, & rio_imortrate_siscpf => this%rvars(ir_imortrate_siscpf)%r81d, & @@ -3105,6 +3115,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%dndaysleafon(i_pft) = rio_dndaysleafon_sift(io_idx_si_pft) sites(s)%dndaysleafoff(i_pft) = rio_dndaysleafoff_sift(io_idx_si_pft) sites(s)%elong_factor(i_pft) = rio_elong_factor_sift(io_idx_si_pft) + sites(s)%seed_in(i_pft) = rio_seed_in_sift(io_idx_si_pft) io_idx_si_pft = io_idx_si_pft + 1 end do From 397d8227712509b1e3c029f1070190e3b24db131 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux <7565064+glemieux@users.noreply.github.com> Date: Fri, 25 Aug 2023 16:42:47 -0700 Subject: [PATCH 826/852] Update PULL_REQUEST_TEMPLATE.md Adding a subsection for documentation and changing the checklist language --- .github/PULL_REQUEST_TEMPLATE.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 4b5f654602..a34ed52795 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -14,19 +14,22 @@ - -### Checklist: +### Checklist *If this is your first time contributing, please read the [**CONTRIBUTING**](https://github.com/NGEET/fates/blob/main/CONTRIBUTING.md) document.* All checklist items must be checked to enable merging this pull request: -- [ ] I have updated the in-code documentation with descriptive comments -- [ ] I have created an issue to update the [technical note](https://github.com/NGEET/fates-docs/issues/new/choose) / [user's guide](https://github.com/NGEET/fates-users-guide/issues/new/choose) as necessary +- [ ] The in-code documentation has been updated with descriptive comments +- [ ] The documentation has been assessed to determine if updates are necessary - [ ] FATES PASS/FAIL regression tests were run -- [ ] If answers were expected to change, evaluation was performed and provided - +- [ ] Evaluation of test results for answer changes was performed and results provided +### Documentation + + +- [Technical Note](https://github.com/NGEET/fates-docs) update: +- [User's Guide](https://github.com/NGEET/fates-users-guide) update: ### Test Results: From eb250643ba354689eb9f8c6453a49dc25c3cf9ef Mon Sep 17 00:00:00 2001 From: jessica needham Date: Fri, 25 Aug 2023 19:01:57 -0700 Subject: [PATCH 827/852] fix error with large size initialisation in nocomp mode Add a call to h_allom so that trees can be demoted in canopy_structure --- main/EDInitMod.F90 | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 6f7b649a4b..384f0d8103 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -61,6 +61,7 @@ module EDInitMod use FatesInterfaceTypesMod , only : nlevage use FatesAllometryMod , only : h2d_allom + use FatesAllometryMod , only : h_allom use FatesAllometryMod , only : bagw_allom use FatesAllometryMod , only : bbgw_allom use FatesAllometryMod , only : bleaf @@ -851,6 +852,14 @@ subroutine init_cohorts(site_in, patch_in, bc_in) patch_in%tallest => null() patch_in%shortest => null() + ! if any pfts are starting with large size then the whole site needs a spread of 0 + do pft = 1, numpft + if (EDPftvarcon_inst%initd(pft) < 0.0_r8) then + site_in%spread = init_spread_inventory + end if + end do + + ! Manage interactions of fixed biogeog (site level filter) and nocomp (patch level filter) ! Need to cover all potential biogeog x nocomp combinations ! 1. biogeog = false. nocomp = false: all PFTs on (DEFAULT) @@ -980,8 +989,15 @@ subroutine init_cohorts(site_in, patch_in, bc_in) ! Calculate the leaf biomass from allometry ! (calculates a maximum first, then applies canopy trim) call bleaf(dbh, pft, crown_damage, canopy_trim, efleaf_coh, & - c_leaf) + c_leaf) + ! calculate crown area of the cohort + call carea_allom(dbh, cohort_n, init_spread_inventory, pft, crown_damage, & + c_area) + + ! calculate height from diameter + call h_allom(dbh, pft, hite) + else write(fates_log(),*) 'Negative fates_recruit_init_density can only be used in no comp mode' call endrun(msg=errMsg(sourcefile, __LINE__)) From e5cd151520967411b9a7a566602f0b59c9b7c727 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 30 Aug 2023 11:01:24 -0600 Subject: [PATCH 828/852] add seed_out to restart --- main/FatesDispersalMod.F90 | 4 +--- main/FatesRestartInterfaceMod.F90 | 10 ++++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index 806f710824..68a1e13536 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -222,10 +222,9 @@ logical function IsItDispersalTime(setdispersedflag) ! Check if set dispersal flag is provided. This should be provided during a check ! when the flag should be set to true after the global dispersal + setflag = .false. if (present(setdispersedflag)) then setflag = setdispersedflag - else - setflag = .false. end if ! If dispersal flag is true, regardless of the date, pass dispersed seeds to fates and reset flag @@ -243,7 +242,6 @@ logical function IsItDispersalTime(setdispersedflag) dispersal_date = GetCadenceDate() end if end if - end if end function IsItDispersalTime diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 1fe71afa87..02fa0bccbe 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -260,6 +260,7 @@ module FatesRestartInterfaceMod ! site-level input seed from dispersal integer :: ir_seed_in_sift + integer :: ir_seed_out_sift ! Damage x damage or damage x size integer :: ir_imortrate_sicdpf @@ -1280,6 +1281,11 @@ subroutine define_restart_vars(this, initialize_variables) units='kg', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_seed_in_sift ) + call this%set_restart_var(vname='fates_seed_out_site', vtype=cohort_r8, & + long_name='Site-level seed mass output to neighboring gridcells per pft', & + units='kg', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_seed_out_sift ) + call this%set_restart_var(vname='fates_fmortrate_canopy', vtype=cohort_r8, & long_name='fates diagnostics on fire mortality canopy', & units='indiv/ha/year', flushval = flushzero, & @@ -2060,6 +2066,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_use_this_pft_sift => this%rvars(ir_use_this_pft_sift)%int1d, & rio_area_pft_sift => this%rvars(ir_area_pft_sift)%r81d, & rio_seed_in_sift => this%rvars(ir_seed_in_sift)%r81d, & + rio_seed_out_sift => this%rvars(ir_seed_out_sift)%r81d, & rio_fmortrate_cano_siscpf => this%rvars(ir_fmortrate_cano_siscpf)%r81d, & rio_fmortrate_usto_siscpf => this%rvars(ir_fmortrate_usto_siscpf)%r81d, & rio_imortrate_siscpf => this%rvars(ir_imortrate_siscpf)%r81d, & @@ -2179,6 +2186,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_dndaysleafoff_sift(io_idx_si_pft) = sites(s)%dndaysleafoff(i_pft) rio_elong_factor_sift(io_idx_si_pft) = sites(s)%elong_factor(i_pft) rio_seed_in_sift(io_idx_si_pft) = sites(s)%seed_in(i_pft) + rio_seed_out_sift(io_idx_si_pft) = sites(s)%seed_out(i_pft) io_idx_si_pft = io_idx_si_pft + 1 end do @@ -3000,6 +3008,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_use_this_pft_sift => this%rvars(ir_use_this_pft_sift)%int1d, & rio_area_pft_sift => this%rvars(ir_area_pft_sift)%r81d,& rio_seed_in_sift => this%rvars(ir_seed_in_sift)%r81d, & + rio_seed_out_sift => this%rvars(ir_seed_out_sift)%r81d, & rio_fmortrate_cano_siscpf => this%rvars(ir_fmortrate_cano_siscpf)%r81d, & rio_fmortrate_usto_siscpf => this%rvars(ir_fmortrate_usto_siscpf)%r81d, & rio_imortrate_siscpf => this%rvars(ir_imortrate_siscpf)%r81d, & @@ -3116,6 +3125,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%dndaysleafoff(i_pft) = rio_dndaysleafoff_sift(io_idx_si_pft) sites(s)%elong_factor(i_pft) = rio_elong_factor_sift(io_idx_si_pft) sites(s)%seed_in(i_pft) = rio_seed_in_sift(io_idx_si_pft) + sites(s)%seed_out(i_pft) = rio_seed_out_sift(io_idx_si_pft) io_idx_si_pft = io_idx_si_pft + 1 end do From 98c36b390bbdd7376ac8a50219c28d350089db22 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux <7565064+glemieux@users.noreply.github.com> Date: Wed, 30 Aug 2023 16:07:21 -0700 Subject: [PATCH 829/852] Update checklist with contributor/integrator Note which checklist item is the responsibility of the contributor or the integrator --- .github/PULL_REQUEST_TEMPLATE.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index a34ed52795..aab00a15b9 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -20,8 +20,12 @@ *If this is your first time contributing, please read the [**CONTRIBUTING**](https://github.com/NGEET/fates/blob/main/CONTRIBUTING.md) document.* All checklist items must be checked to enable merging this pull request: + +*Contributor* - [ ] The in-code documentation has been updated with descriptive comments - [ ] The documentation has been assessed to determine if updates are necessary + +*Integrator* - [ ] FATES PASS/FAIL regression tests were run - [ ] Evaluation of test results for answer changes was performed and results provided From adb071188e505b0740f92f996fb2d1dc010355ec Mon Sep 17 00:00:00 2001 From: Gregory Lemieux <7565064+glemieux@users.noreply.github.com> Date: Thu, 31 Aug 2023 10:23:46 -0700 Subject: [PATCH 830/852] add missing newlines --- .github/PULL_REQUEST_TEMPLATE.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index aab00a15b9..87f6468203 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -41,8 +41,11 @@ All checklist items must be checked to enable merging this pull request: *CTSM (or) E3SM (specify which) test hash-tag:* + *CTSM (or) E3SM (specify which) baseline hash-tag:* + *FATES baseline hash-tag:* + *Test Output:* From efbb30298e83df1c5a2f3449940fe3247766bbcf Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 1 Sep 2023 15:30:46 -0600 Subject: [PATCH 831/852] refactoring code to accomodate use of mpi_allgatherv in place of a reduction --- main/FatesDispersalMod.F90 | 29 +++++++++++++++++++---------- main/FatesInterfaceMod.F90 | 28 +++++++++++++++------------- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index 68a1e13536..18fad12558 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -35,9 +35,11 @@ module FatesDispersalMod ! Dispersal type type, public :: dispersal_type - real(r8), allocatable :: outgoing_local(:,:) ! local gridcell array of outgoing seeds, gridcell x pft - real(r8), allocatable :: outgoing_global(:,:) ! global accumulation array of outgoing seeds, gridcell x pft - real(r8), allocatable :: incoming_global(:,:) ! + real(r8), allocatable :: outgoing_local(:,:) ! local buffer array of outgoing seeds, local gridcell x pft + real(r8), allocatable :: outgoing_global(:,:) ! global accumulation buffer array of outgoing seeds, global gridcell x pft + real(r8), allocatable :: incoming_global(:,:) ! local buffer array used to calculate incoming seeds based on nearest neighbors + real(r8), allocatable :: ncells_array(:) ! local array with the number of gridcells per process for each rank index + real(r8), allocatable :: begg_array(:) ! local array with the starting index of each gridcell for each rank index contains @@ -59,31 +61,38 @@ module FatesDispersalMod ! ==================================================================================== - subroutine init(this, numprocs, numpft) + subroutine init(this, numprocs, numgc_global, numgc_local, numpft) ! Use use EDPftvarcon , only : EDPftvarcon_inst - use FatesConstantsMod , only : fates_check_param_set + use FatesConstantsMod , only : fates_check_param_set, fates_unset_int use FatesInterfaceTypesMod, only : fates_dispersal_kernel_mode use FatesInterfaceTypesMod, only : fates_dispersal_kernel_none ! Arguments class(dispersal_type), intent(inout) :: this - integer, intent(in) :: numprocs - integer, intent(in) :: numpft + + integer, intent(in) :: numprocs ! number of processors (across all nodes) + integer, intent(in) :: numgc_global ! number of gridcells across all processors + integer, intent(in) :: numgc_local ! number of gridcells on this processor + integer, intent(in) :: numpft ! number of FATES pfts ! Check if seed dispersal mode is 'turned on' by checking the parameter values ! This assumes we consistency in the parameter file across all pfts, i.e. either ! all 'on' or all 'off' if (fates_dispersal_kernel_mode .eq. fates_dispersal_kernel_none) return - allocate(this%outgoing_local(numprocs,numpft)) - allocate(this%outgoing_global(numprocs,numpft)) - allocate(this%incoming_global(numprocs,numpft)) + allocate(this%outgoing_local(numgc_local,numpft)) + allocate(this%outgoing_global(numgc_global,numpft)) + allocate(this%incoming_global(numgc_global,numpft)) + allocate(this%ncells_array(0:numprocs-1)) + allocate(this%begg_array(0:numprocs-1)) this%outgoing_local(:,:) = 0._r8 this%outgoing_global(:,:) = 0._r8 this%incoming_global(:,:) = 0._r8 + this%ncells_array(:) = fates_unset_int + this%begg_array(:) = fates_unset_int ! Set the dispersal date to the current date. Dispersal will start at the end of ! current initial date diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index e215bfd354..6f411fe0d1 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -172,6 +172,8 @@ module FatesInterfaceMod public :: UpdateFatesRMeansTStep public :: InitTimeAveragingGlobals public :: DetermineGridCellNeighbors + + logical :: debug = .false. ! for debugging this module contains @@ -2166,7 +2168,7 @@ end subroutine SeedlingParPatch ! ====================================================================================== -subroutine DetermineGridCellNeighbors(neighbors,numg) +subroutine DetermineGridCellNeighbors(neighbors,seeds,numg) ! This subroutine utilizes information from the decomposition and domain types to determine ! the set of grid cell neighbors within some maximum distance. It records the distance for each @@ -2177,13 +2179,14 @@ subroutine DetermineGridCellNeighbors(neighbors,numg) use domainMod , only : ldomain use spmdMod , only : MPI_REAL8, MPI_INTEGER, mpicom, npes, masterproc, iam use perf_mod , only : t_startf, t_stopf - use FatesDispersalMod , only : neighborhood_type, neighbor_type, ProbabilityDensity + use FatesDispersalMod , only : neighborhood_type, neighbor_type, ProbabilityDensity, dispersal_type use FatesUtilsMod , only : GetNeighborDistance use FatesConstantsMod , only : fates_unset_int use EDPftvarcon , only : EDPftvarcon_inst ! Arguments type(neighborhood_type), intent(inout), pointer :: neighbors(:) ! land gridcell neighbor data structure + type(dispersal_type), intent(inout) :: seeds ! land gridcell neighbor data structure integer , intent(in) :: numg ! number of land gridcells ! Local variables @@ -2203,8 +2206,7 @@ subroutine DetermineGridCellNeighbors(neighbors,numg) ! Check if seed dispersal mode is 'turned on' by checking the parameter values if (fates_dispersal_kernel_mode .eq. fates_dispersal_kernel_none) return - if(hlm_is_restart .eq. itrue) write(fates_log(),*) 'gridcell initialization during restart' - + if(debug .and. hlm_is_restart .eq. itrue) write(fates_log(),*) 'gridcell initialization during restart' ! Allocate array neighbor type allocate(neighbors(numg), stat=ier) @@ -2215,25 +2217,25 @@ subroutine DetermineGridCellNeighbors(neighbors,numg) gclon(:) = nan gclat(:) = nan - allocate(ncells_array(0:npes-1), stat=ier) - allocate(begg_array(0:npes-1), stat=ier) - ncells_array(:) = fates_unset_int - begg_array(:) = fates_unset_int + !allocate(ncells_array(0:npes-1), stat=ier) + !allocate(begg_array(0:npes-1), stat=ier) + !ncells_array(:) = fates_unset_int + !begg_array(:) = fates_unset_int call t_startf('fates-seed-init-allgather') ! Gather the sizes of the ldomain that each mpi rank is passing - call MPI_Allgather(procinfo%ncells,1,MPI_INTEGER,ncells_array,1,MPI_INTEGER,mpicom,mpierr) + call MPI_Allgather(procinfo%ncells,1,MPI_INTEGER,seeds%ncells_array,1,MPI_INTEGER,mpicom,mpierr) ! Gather the starting index for each ldomain (reduce begging index by one for mpi rank conversion) - call MPI_Allgather(procinfo%begg-1,1,MPI_INTEGER,begg_array,1,MPI_INTEGER,mpicom,mpierr) + call MPI_Allgather(procinfo%begg-1,1,MPI_INTEGER,seeds%begg_array,1,MPI_INTEGER,mpicom,mpierr) ! Gather the domain information together into the neighbor type ! Note that MPI_Allgatherv is only gathering a subset of ldomain - call MPI_Allgatherv(ldomain%latc,procinfo%ncells,MPI_REAL8,gclat,ncells_array,begg_array,MPI_REAL8,mpicom,mpierr) - call MPI_Allgatherv(ldomain%lonc,procinfo%ncells,MPI_REAL8,gclon,ncells_array,begg_array,MPI_REAL8,mpicom,mpierr) + call MPI_Allgatherv(ldomain%latc,procinfo%ncells,MPI_REAL8,gclat,seeds%ncells_array,seeds%begg_array,MPI_REAL8,mpicom,mpierr) + call MPI_Allgatherv(ldomain%lonc,procinfo%ncells,MPI_REAL8,gclon,seeds%ncells_array,seeds%begg_array,MPI_REAL8,mpicom,mpierr) - if (iam==1) then + if (debug .and. iam .eq. 1) then write(fates_log(),*)'DGCN: ncells_array: ', ncells_array write(fates_log(),*)'DGCN: begg_array: ', begg_array write(fates_log(),*)'DGCN: sum(gclat):, sum(gclon): ', sum(gclat), sum(gclon) From 6a792e8755ef23e0e83a18a72ac54839bd7c3f90 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 5 Sep 2023 16:05:21 -0600 Subject: [PATCH 832/852] updates to pass bag compiler build --- main/FatesConstantsMod.F90 | 2 +- main/FatesHistoryInterfaceMod.F90 | 6 +++--- main/FatesInterfaceMod.F90 | 10 ++-------- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index 5d3b29ef8f..7ccb4e59a7 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -312,7 +312,7 @@ module FatesConstantsMod real(fates_r8), parameter, public :: fates_tiny = tiny(g_per_kg) ! Geodesy constants (WGS 84) - real(fates_r8), parameter, public :: earth_radius_eq = 6378137_fates_r8 ! equitorial radius, earth [m] + real(fates_r8), parameter, public :: earth_radius_eq = 6378137.0_fates_r8 ! equitorial radius, earth [m] real(fates_r8), parameter, public :: earth_flattening = 1.0_fates_r8 / 298.257223563_fates_r8 ! flattening [non-dimensional] diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 566873337f..548a7d50ec 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2479,9 +2479,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_cwd_bg_out_si_cwdsc => this%hvars(ih_cwd_bg_out_si_cwdsc)%r82d, & hio_crownarea_si_cnlf => this%hvars(ih_crownarea_si_cnlf)%r82d, & hio_crownarea_si_can => this%hvars(ih_crownarea_si_can)%r82d, & - hio_nplant_si_scag => this%hvars(ih_nplant_si_scag)%r82d, & - hio_nplant_canopy_si_scag => this%hvars(ih_nplant_canopy_si_scag)%r82d, & - hio_nplant_understory_si_scag => this%hvars(ih_nplant_understory_si_scag)%r82d, & hio_ddbh_canopy_si_scag => this%hvars(ih_ddbh_canopy_si_scag)%r82d, & hio_ddbh_understory_si_scag => this%hvars(ih_ddbh_understory_si_scag)%r82d, & hio_mortality_canopy_si_scag => this%hvars(ih_mortality_canopy_si_scag)%r82d, & @@ -2505,6 +2502,9 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_tgrowth => this%hvars(ih_tgrowth_si)%r81d, & hio_cbal_err_fates_si => this%hvars(ih_cbal_err_fates_si)%r81d, & hio_err_fates_si => this%hvars(ih_err_fates_si)%r82d, & + hio_nplant_si_scag => this%hvars(ih_nplant_si_scag)%r82d, & + hio_nplant_canopy_si_scag => this%hvars(ih_nplant_canopy_si_scag)%r82d, & + hio_nplant_understory_si_scag => this%hvars(ih_nplant_understory_si_scag)%r82d, & hio_lai_si => this%hvars(ih_lai_si)%r81d ) ! If we don't have dynamics turned on, we just abort these diagnostics diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 6f411fe0d1..7afcd87add 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -2196,7 +2196,6 @@ subroutine DetermineGridCellNeighbors(neighbors,seeds,numg) integer :: i, gi,gj ! indices integer :: ier, mpierr ! error status integer :: ipft ! pft index - integer, allocatable :: ncells_array(:), begg_array(:) real(r8), allocatable :: gclat(:), gclon(:) ! 5 deg = 785.8 km, 10 deg = 1569 km, 15deg = 2345 km assumes cartesian layout with diagonal distance @@ -2217,11 +2216,6 @@ subroutine DetermineGridCellNeighbors(neighbors,seeds,numg) gclon(:) = nan gclat(:) = nan - !allocate(ncells_array(0:npes-1), stat=ier) - !allocate(begg_array(0:npes-1), stat=ier) - !ncells_array(:) = fates_unset_int - !begg_array(:) = fates_unset_int - call t_startf('fates-seed-init-allgather') ! Gather the sizes of the ldomain that each mpi rank is passing @@ -2236,8 +2230,8 @@ subroutine DetermineGridCellNeighbors(neighbors,seeds,numg) call MPI_Allgatherv(ldomain%lonc,procinfo%ncells,MPI_REAL8,gclon,seeds%ncells_array,seeds%begg_array,MPI_REAL8,mpicom,mpierr) if (debug .and. iam .eq. 1) then - write(fates_log(),*)'DGCN: ncells_array: ', ncells_array - write(fates_log(),*)'DGCN: begg_array: ', begg_array + write(fates_log(),*)'DGCN: ncells_array: ', seeds%ncells_array + write(fates_log(),*)'DGCN: begg_array: ', seeds%begg_array write(fates_log(),*)'DGCN: sum(gclat):, sum(gclon): ', sum(gclat), sum(gclon) end if From e402f0cb16dfca2a23014f4b03b7b5e977eda0b4 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 11 Sep 2023 12:07:52 -0400 Subject: [PATCH 833/852] Small quality of life update to cohort age in create_cohort --- main/EDInitMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 384f0d8103..de80dd8920 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -846,7 +846,7 @@ subroutine init_cohorts(site_in, patch_in, bc_in) real(r8) :: stem_drop_fraction ! fraction of stem to absciss when leaves absciss real(r8) :: fnrt_drop_fraction ! fraction of fine roots to absciss when leaves absciss integer, parameter :: recruitstatus = 0 ! whether the newly created cohorts are recruited or initialized - + real(r8),parameter :: zero_co_age = 0._r8 ! The age of a newly recruited cohort is zero !------------------------------------------------------------------------------------- patch_in%tallest => null() @@ -1083,7 +1083,7 @@ subroutine init_cohorts(site_in, patch_in, bc_in) call prt%CheckInitialConditions() call create_cohort(site_in, patch_in, pft, cohort_n, & - hite, 0.0_r8, dbh, prt, efleaf_coh, & + hite, zero_co_age, dbh, prt, efleaf_coh, & effnrt_coh, efstem_coh, leaf_status, recruitstatus, & canopy_trim, c_area, 1, crown_damage, site_in%spread, bc_in) From dc8d222dd73f7667ce7dc62dc6ad3847ddd81fe7 Mon Sep 17 00:00:00 2001 From: jessica needham Date: Mon, 18 Sep 2023 18:06:52 -0700 Subject: [PATCH 834/852] cap atkin lmr at 0 to prevent negatives - add param warnings --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 10 +++++- main/EDPftvarcon.F90 | 41 +++++++++++++++++++++- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 603e691067..ffc5ddcd9b 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -2178,7 +2178,15 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & ! r_0 currently put into the EDPftvarcon_inst%dev_arbitrary_pft ! all figs in Atkin et al 2017 stop at zero Celsius so we will assume acclimation is fixed below that r_0 = EDPftvarcon_inst%maintresp_leaf_atkin2017_baserate(ft) - r_t_ref = nscaler * (r_0 + r_1 * lnc_top + r_2 * max(0._r8, (tgrowth - tfrz) )) + r_t_ref = max( 0._r8, nscaler * (r_0 + r_1 * lnc_top + r_2 * max(0._r8, (tgrowth - tfrz) )) ) + + if (r_t_ref .eq. 0._r8) then + write(fates_log(),*) 'Rdark has is negative at this temperature and has' + write(fates_log(),*) 'therefore been capped at 0.' + write(fates_log(),*) 'See LeafLayerMaintenanceRespiration_Atkin_etal_2017' + write(fates_log(),*) 'tgrowth : ', tgrowth + write(fates_log(),*) 'pft : ', ft + end if lmr = r_t_ref * exp(b * (veg_tempk - tfrz - TrefC) + c * ((veg_tempk-tfrz)**2 - TrefC**2)) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index bdd670b671..938c74a3a6 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1717,12 +1717,13 @@ subroutine FatesCheckParams(is_master) ! ----------------------------------------------------------------------------------- use FatesConstantsMod , only : fates_check_param_set use FatesConstantsMod , only : itrue, ifalse + use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm use EDParamsMod , only : logging_mechanical_frac, logging_collateral_frac use EDParamsMod , only : logging_direct_frac,logging_export_frac use EDParamsMod , only : radiation_model use FatesInterfaceTypesMod, only : hlm_use_fixed_biogeog,hlm_use_sp, hlm_name use FatesInterfaceTypesMod, only : hlm_use_inventory_init - + ! Argument logical, intent(in) :: is_master ! Only log if this is the master proc @@ -1738,6 +1739,17 @@ subroutine FatesCheckParams(is_master) real(r8) :: sumarea ! area of PFTs in nocomp mode. + + ! Parameters - used to check lmr base rate r_0 parameter + ! values from Atkin et al., 2017 https://doi.org/10.1007/978-3-319-68703-2_6 + ! and Heskel et al., 2016 https://doi.org/10.1073/pnas.1520282113 + real(r8), parameter :: r_1 = 0.2061_r8 ! (umol CO2/m**2/s / (gN/(m2 leaf))) + real(r8), parameter :: r_2 = -0.0402_r8 ! (umol CO2/m**2/s/degree C) + real(r8) :: neg_lmr_temp ! temperature at which lmr would got negative + real(r8) :: r_0 ! base respiartion rate, PFT-dependent + real(r8) :: lnc_top ! leaf nitrogen content at top of canopy + + npft = size(EDPftvarcon_inst%freezetol,1) if(.not.is_master) return @@ -2031,6 +2043,33 @@ subroutine FatesCheckParams(is_master) end do !ipft + ! Check the temperature at which Rdark would become negative for each PFT - + ! given their parameters + !------------------------------------------------------------------------------------ + do ipft = 1,npft + + + r_0 = EDPftvarcon_inst%maintresp_leaf_atkin2017_baserate(ipft) + + lnc_top = prt_params%nitr_stoich_p1(ipft, 1) / prt_params%slatop(ipft) + + ! From LeafLayerMaintenanceRespiration_Atkin_etal_2017 + ! r_t_ref = nscaler * (r_0 + r_1 * lnc_top + r_2 * max(0._r8, (tgrowth - tfrz) )) + + ! find temperature at which whole term is negative + neg_lmr_temp = ( -1._r8 * ( r_0 + r_1 * lnc_top ) ) / r_2 + + write(fates_log(),*) 'PFT ', ipft + write(fates_log(),*) 'will have negative Rdark at ', neg_lmr_temp, 'degrees C' + write(fates_log(),*) 'with these values of slatop, nitrogen stoichiometry and' + write(fates_log(),*) 'maintresp_leaf_atkin2017_baserate.' + write(fates_log(),*) 'See LeafLayerMaintenanceRespiration_Atkin_etal_2017 in ' + write(fates_log(),*) 'FatesPlantRespPhotosynthMod' + + end do ! ipft + + + !! ! Checks for HYDRO !! if( hlm_use_planthydro == itrue ) then !! From c722825ca47cd13c0176d295d73ad5789074da7c Mon Sep 17 00:00:00 2001 From: jessica needham Date: Mon, 18 Sep 2023 19:17:36 -0700 Subject: [PATCH 835/852] add note on place where code should maybe be updated --- main/EDPftvarcon.F90 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 938c74a3a6..867d0813fc 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -2050,7 +2050,9 @@ subroutine FatesCheckParams(is_master) r_0 = EDPftvarcon_inst%maintresp_leaf_atkin2017_baserate(ipft) - + + ! jfn - this should be prt_params%nitr_stoich_p1(ipft, prt_params%organ_param_id(leaf_organ)) + ! but that was giving errors during compile lnc_top = prt_params%nitr_stoich_p1(ipft, 1) / prt_params%slatop(ipft) ! From LeafLayerMaintenanceRespiration_Atkin_etal_2017 From f2d8c8aff70d743f12c695a231fd0783b7c70a87 Mon Sep 17 00:00:00 2001 From: jessica needham Date: Tue, 19 Sep 2023 10:36:49 -0700 Subject: [PATCH 836/852] wrap warning message in FatesWarn() construct --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index ffc5ddcd9b..cd6af830fe 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -22,7 +22,7 @@ module FATESPlantRespPhotosynthMod use FatesGlobals, only : endrun => fates_endrun use FatesGlobals, only : fates_log - use FatesGlobals, only : FatesWarn,N2S,A2S + use FatesGlobals, only : FatesWarn,N2S,A2S,I2S use FatesConstantsMod, only : r8 => fates_r8 use FatesConstantsMod, only : itrue use FatesConstantsMod, only : nearzero @@ -2181,11 +2181,8 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & r_t_ref = max( 0._r8, nscaler * (r_0 + r_1 * lnc_top + r_2 * max(0._r8, (tgrowth - tfrz) )) ) if (r_t_ref .eq. 0._r8) then - write(fates_log(),*) 'Rdark has is negative at this temperature and has' - write(fates_log(),*) 'therefore been capped at 0.' - write(fates_log(),*) 'See LeafLayerMaintenanceRespiration_Atkin_etal_2017' - write(fates_log(),*) 'tgrowth : ', tgrowth - write(fates_log(),*) 'pft : ', ft + warn_msg = 'Rdark is negative at this temperature and is capped at 0. tgrowth (C): '//trim(N2S(tgrowth-tfrz))//' pft: '//trim(I2S(ft)) + call FatesWarn(warn_msg,index=4) end if lmr = r_t_ref * exp(b * (veg_tempk - tfrz - TrefC) + c * ((veg_tempk-tfrz)**2 - TrefC**2)) From 56f3465a2637f72c91d55fb64a4f0a6fd1d71b96 Mon Sep 17 00:00:00 2001 From: jessica needham Date: Tue, 19 Sep 2023 11:22:49 -0700 Subject: [PATCH 837/852] move hard coded parameters to FatesConstantsMod --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 19 ++++++++----------- main/FatesConstantsMod.F90 | 13 +++++++++++++ 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index cd6af830fe..50bb0464bf 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -2140,6 +2140,11 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm use FatesConstantsMod, only : umolC_to_kgC use FatesConstantsMod, only : g_per_kg + use FatesConstantsMod, only : lmr_b + use FatesConstantsMod, only : lmr_c + use FatesConstantsMod, only : lmr_TrefC + use FatesConstantsMod, only : lmr_r_1 + use FatesConstantsMod, only : lmr_r_2 use EDPftvarcon , only : EDPftvarcon_inst ! Arguments @@ -2156,15 +2161,6 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & real(r8) :: r_t_ref ! acclimated ref respiration rate (umol CO2/m**2/s) real(r8) :: lmr25top ! canopy top leaf maint resp rate at 25C for this pft (umol CO2/m**2/s) - ! Parameters - ! values from Atkin et al., 2017 https://doi.org/10.1007/978-3-319-68703-2_6 - ! and Heskel et al., 2016 https://doi.org/10.1073/pnas.1520282113 - real(r8), parameter :: b = 0.1012_r8 ! (degrees C**-1) - real(r8), parameter :: c = -0.0005_r8 ! (degrees C**-2) - real(r8), parameter :: TrefC = 25._r8 ! (degrees C) - real(r8), parameter :: r_1 = 0.2061_r8 ! (umol CO2/m**2/s / (gN/(m2 leaf))) - real(r8), parameter :: r_2 = -0.0402_r8 ! (umol CO2/m**2/s/degree C) - ! parameter values of r_0 as listed in Atkin et al 2017: (umol CO2/m**2/s) ! Broad-leaved trees 1.7560 ! Needle-leaf trees 1.4995 @@ -2178,14 +2174,15 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & ! r_0 currently put into the EDPftvarcon_inst%dev_arbitrary_pft ! all figs in Atkin et al 2017 stop at zero Celsius so we will assume acclimation is fixed below that r_0 = EDPftvarcon_inst%maintresp_leaf_atkin2017_baserate(ft) - r_t_ref = max( 0._r8, nscaler * (r_0 + r_1 * lnc_top + r_2 * max(0._r8, (tgrowth - tfrz) )) ) + r_t_ref = max( 0._r8, nscaler * (r_0 + lmr_r_1 * lnc_top + lmr_r_2 * max(0._r8, (tgrowth - tfrz) )) ) if (r_t_ref .eq. 0._r8) then warn_msg = 'Rdark is negative at this temperature and is capped at 0. tgrowth (C): '//trim(N2S(tgrowth-tfrz))//' pft: '//trim(I2S(ft)) call FatesWarn(warn_msg,index=4) end if - lmr = r_t_ref * exp(b * (veg_tempk - tfrz - TrefC) + c * ((veg_tempk-tfrz)**2 - TrefC**2)) + lmr = r_t_ref * exp(lmr_b * (veg_tempk - tfrz - lmr_TrefC) + lmr_c * & + ((veg_tempk-tfrz)**2 - lmr_TrefC**2)) end subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017 diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index c73483fe67..dc89d06f4f 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -316,4 +316,17 @@ module FatesConstantsMod ! PI real(fates_r8), parameter, public :: pi_const = 3.14159265359_fates_r8 + ! Rdark constants from Atkin et al., 2017 https://doi.org/10.1007/978-3-319-68703-2_6 + ! and Heskel et al., 2016 https://doi.org/10.1073/pnas.1520282113 + real(fates_r8), parameter, public :: lmr_b = 0.1012_fates_r8 ! (degrees C**-1) + + real(fates_r8), parameter, public :: lmr_c = -0.0005_fates_r8 ! (degrees C**-2) + + real(fates_r8), parameter, public :: lmr_TrefC = 25._fates_r8 ! (degrees C) + + real(fates_r8), parameter, public :: lmr_r_1 = 0.2061_fates_r8 ! (umol CO2/m**2/s / (gN/(m2 leaf))) + + real(fates_r8), parameter, public :: lmr_r_2 = -0.0402_fates_r8 ! (umol CO2/m**2/s/degree C) + + end module FatesConstantsMod From 5921c15885011261f6579de9c013ad3b1f790d1a Mon Sep 17 00:00:00 2001 From: jessica needham Date: Tue, 19 Sep 2023 11:28:37 -0700 Subject: [PATCH 838/852] update parameter check to use FatesConstants --- main/EDPftvarcon.F90 | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 867d0813fc..969f890f9e 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1718,6 +1718,8 @@ subroutine FatesCheckParams(is_master) use FatesConstantsMod , only : fates_check_param_set use FatesConstantsMod , only : itrue, ifalse use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm + use FatesConstantsMod, only : lmr_r_1 + 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 @@ -1738,13 +1740,6 @@ subroutine FatesCheckParams(is_master) integer :: fates_pft ! used in fixed biogeog mode real(r8) :: sumarea ! area of PFTs in nocomp mode. - - - ! Parameters - used to check lmr base rate r_0 parameter - ! values from Atkin et al., 2017 https://doi.org/10.1007/978-3-319-68703-2_6 - ! and Heskel et al., 2016 https://doi.org/10.1073/pnas.1520282113 - real(r8), parameter :: r_1 = 0.2061_r8 ! (umol CO2/m**2/s / (gN/(m2 leaf))) - real(r8), parameter :: r_2 = -0.0402_r8 ! (umol CO2/m**2/s/degree C) real(r8) :: neg_lmr_temp ! temperature at which lmr would got negative real(r8) :: r_0 ! base respiartion rate, PFT-dependent real(r8) :: lnc_top ! leaf nitrogen content at top of canopy @@ -2059,7 +2054,7 @@ subroutine FatesCheckParams(is_master) ! r_t_ref = nscaler * (r_0 + r_1 * lnc_top + r_2 * max(0._r8, (tgrowth - tfrz) )) ! find temperature at which whole term is negative - neg_lmr_temp = ( -1._r8 * ( r_0 + r_1 * lnc_top ) ) / r_2 + neg_lmr_temp = ( -1._r8 * ( r_0 + lmr_r_1 * lnc_top ) ) / lmr_r_2 write(fates_log(),*) 'PFT ', ipft write(fates_log(),*) 'will have negative Rdark at ', neg_lmr_temp, 'degrees C' From ddff4c4407c26036062364758e08a655cc84f20f Mon Sep 17 00:00:00 2001 From: jessica needham Date: Tue, 19 Sep 2023 17:35:44 -0700 Subject: [PATCH 839/852] move call to PRTDerviedParams up This allows organ_param_id to be referenced in FatesCheckParams when we are calculating the temperature of negative Rdark for each pft. --- main/EDPftvarcon.F90 | 7 ++----- main/FatesInterfaceMod.F90 | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 969f890f9e..c6bec20651 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -2042,14 +2042,11 @@ subroutine FatesCheckParams(is_master) ! given their parameters !------------------------------------------------------------------------------------ do ipft = 1,npft - r_0 = EDPftvarcon_inst%maintresp_leaf_atkin2017_baserate(ipft) - ! jfn - this should be prt_params%nitr_stoich_p1(ipft, prt_params%organ_param_id(leaf_organ)) - ! but that was giving errors during compile - lnc_top = prt_params%nitr_stoich_p1(ipft, 1) / prt_params%slatop(ipft) - + lnc_top = prt_params%nitr_stoich_p1(ipft, prt_params%organ_param_id(leaf_organ)) + ! From LeafLayerMaintenanceRespiration_Atkin_etal_2017 ! r_t_ref = nscaler * (r_0 + r_1 * lnc_top + r_2 * max(0._r8, (tgrowth - tfrz) )) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 12491cc2ba..857c79336a 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1940,8 +1940,8 @@ subroutine FatesReportParameters(masterproc) call FatesReportPFTParams(masterproc) call FatesReportParams(masterproc) - call FatesCheckParams(masterproc) ! Check general fates parameters call PRTDerivedParams() ! Update PARTEH derived constants + call FatesCheckParams(masterproc) ! Check general fates parameters call PRTCheckParams(masterproc) ! Check PARTEH parameters call SpitFireCheckParams(masterproc) From d3c3f9866e411273a74f60edc36624cc018d2a1d Mon Sep 17 00:00:00 2001 From: jessica needham Date: Mon, 25 Sep 2023 14:45:47 -0700 Subject: [PATCH 840/852] Changge all 'hite' to 'height' --- biogeochem/EDCanopyStructureMod.F90 | 58 +++++++++++++------------- biogeochem/EDCohortDynamicsMod.F90 | 44 +++++++++---------- biogeochem/EDPhysiologyMod.F90 | 14 +++---- biogeochem/FatesAllometryMod.F90 | 2 +- biogeochem/FatesCohortMod.F90 | 16 +++---- biogeophys/FatesPlantHydraulicsMod.F90 | 14 +++---- fire/SFMainMod.F90 | 12 +++--- main/EDInitMod.F90 | 12 +++--- main/EDMainMod.F90 | 12 +++--- main/EDTypesMod.F90 | 6 +-- main/FatesHistoryInterfaceMod.F90 | 14 +++---- main/FatesInventoryInitMod.F90 | 8 ++-- main/FatesRestartInterfaceMod.F90 | 4 +- parteh/PRTAllometricCarbonMod.F90 | 2 +- 14 files changed, 109 insertions(+), 109 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 761f22bc29..a52be9a30e 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -317,7 +317,7 @@ subroutine canopy_structure( currentSite , bc_in ) if(currentCohort%canopy_layer .eq. 2)then if (associated(currentCohort%taller)) then if (currentCohort%taller%canopy_layer .eq. 1 ) then - currentPatch%zstar = currentCohort%taller%hite + currentPatch%zstar = currentCohort%taller%height endif endif endif @@ -407,7 +407,7 @@ subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr,bc_in) ! to the understory. ! ---------------------------------------------------------- - currentCohort%excl_weight = 1._r8 / (currentCohort%hite**ED_val_comp_excln) + currentCohort%excl_weight = 1._r8 / (currentCohort%height**ED_val_comp_excln) sumweights = sumweights + currentCohort%excl_weight else @@ -428,7 +428,7 @@ subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr,bc_in) tied_size_with_neighbors = .false. nextc => currentCohort%taller do while (associated(nextc)) - if ( abs(nextc%hite - currentCohort%hite) < similar_height_tol ) then + if ( abs(nextc%height - currentCohort%height) < similar_height_tol ) then if( nextc%canopy_layer .eq. currentCohort%canopy_layer ) then tied_size_with_neighbors = .true. total_crownarea_of_tied_cohorts = & @@ -451,7 +451,7 @@ subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr,bc_in) nextc => currentCohort%taller do while (associated(nextc)) - if ( abs(nextc%hite - currentCohort%hite) < similar_height_tol ) then + if ( abs(nextc%height - currentCohort%height) < similar_height_tol ) then if (nextc%canopy_layer .eq. currentCohort%canopy_layer ) then ! now we know the total crown area of all equal-sized, ! equal-canopy-layer cohorts @@ -891,7 +891,7 @@ subroutine PromoteIntoLayer(currentSite,currentPatch,i_lyr) ! Stochastic case, as above (in demotion portion of code) ! ------------------------------------------------------------------ - currentCohort%prom_weight = currentCohort%hite**ED_val_comp_excln + currentCohort%prom_weight = currentCohort%height**ED_val_comp_excln sumweights = sumweights + currentCohort%prom_weight else @@ -910,7 +910,7 @@ subroutine PromoteIntoLayer(currentSite,currentPatch,i_lyr) tied_size_with_neighbors = .false. nextc => currentCohort%shorter do while (associated(nextc)) - if ( abs(nextc%hite - currentCohort%hite) < similar_height_tol ) then + if ( abs(nextc%height - currentCohort%height) < similar_height_tol ) then if( nextc%canopy_layer .eq. currentCohort%canopy_layer ) then tied_size_with_neighbors = .true. total_crownarea_of_tied_cohorts = & @@ -932,7 +932,7 @@ subroutine PromoteIntoLayer(currentSite,currentPatch,i_lyr) nextc => currentCohort%shorter do while (associated(nextc)) - if ( abs(nextc%hite - currentCohort%hite) < similar_height_tol ) then + if ( abs(nextc%height - currentCohort%height) < similar_height_tol ) then if (nextc%canopy_layer .eq. currentCohort%canopy_layer ) then ! now we know the total crown area of all equal-sized, ! equal-canopy-layer cohorts @@ -1499,7 +1499,7 @@ subroutine leaf_area_profile( currentSite ) ! !USES: - use EDtypesMod , only : area, hitemax, n_hite_bins + use EDtypesMod , only : area, heightmax, n_height_bins use EDParamsMod, only : dinc_vai, dlower_vai ! @@ -1517,14 +1517,14 @@ subroutine leaf_area_profile( currentSite ) integer :: iv ! Vertical leaf layer index integer :: cl ! Canopy layer index real(r8) :: fraction_exposed ! how much of this layer is not covered by snow? - real(r8) :: layer_top_hite ! notional top height of this canopy layer (m) - real(r8) :: layer_bottom_hite ! notional bottom height of this canopy layer (m) - real(r8) :: frac_canopy(N_HITE_BINS) ! amount of canopy in each height class - real(r8) :: minh(N_HITE_BINS) ! minimum height in height class (m) - real(r8) :: maxh(N_HITE_BINS) ! maximum height in height class (m) + real(r8) :: layer_top_height ! notional top height of this canopy layer (m) + real(r8) :: layer_bottom_height ! notional bottom height of this canopy layer (m) + real(r8) :: frac_canopy(N_HEIGHT_BINS) ! amount of canopy in each height class + real(r8) :: minh(N_HEIGHT_BINS) ! minimum height in height class (m) + real(r8) :: maxh(N_HEIGHT_BINS) ! maximum height in height class (m) real(r8) :: dh ! vertical detph of height class (m) - real(r8) :: min_chite ! bottom of cohort canopy (m) - real(r8) :: max_chite ! top of cohort canopy (m) + real(r8) :: min_cheight ! bottom of cohort canopy (m) + real(r8) :: max_cheight ! top of cohort canopy (m) real(r8) :: lai ! leaf area per canopy area real(r8) :: sai ! stem area per canopy area @@ -1615,25 +1615,25 @@ subroutine leaf_area_profile( currentSite ) ! We calculate the absolute elevation of each layer to help determine if the layer ! is obscured by snow. - layer_top_hite = currentCohort%hite - & - ( real(iv-1,r8)/currentCohort%NV * currentCohort%hite * & + layer_top_height = currentCohort%height - & + ( real(iv-1,r8)/currentCohort%NV * currentCohort%height * & prt_params%crown_depth_frac(currentCohort%pft) ) - layer_bottom_hite = currentCohort%hite - & - ( real(iv,r8)/currentCohort%NV * currentCohort%hite * & + layer_bottom_height = currentCohort%height - & + ( real(iv,r8)/currentCohort%NV * currentCohort%height * & prt_params%crown_depth_frac(currentCohort%pft) ) fraction_exposed = 1.0_r8 - if(currentSite%snow_depth > layer_top_hite)then + if(currentSite%snow_depth > layer_top_height)then fraction_exposed = 0._r8 endif - if(currentSite%snow_depth < layer_bottom_hite)then + if(currentSite%snow_depth < layer_bottom_height)then fraction_exposed = 1._r8 endif - if(currentSite%snow_depth >= layer_bottom_hite .and. & - currentSite%snow_depth <= layer_top_hite) then !only partly hidden... - fraction_exposed = 1._r8 - max(0._r8,(min(1.0_r8,(currentSite%snow_depth -layer_bottom_hite)/ & - (layer_top_hite-layer_bottom_hite )))) + if(currentSite%snow_depth >= layer_bottom_height .and. & + currentSite%snow_depth <= layer_top_height) then !only partly hidden... + fraction_exposed = 1._r8 - max(0._r8,(min(1.0_r8,(currentSite%snow_depth -layer_bottom_height)/ & + (layer_top_height-layer_bottom_height )))) endif if(iv==currentCohort%NV) then @@ -1669,7 +1669,7 @@ subroutine leaf_area_profile( currentSite ) currentPatch%layer_height_profile(cl,ft,iv) = currentPatch%layer_height_profile(cl,ft,iv) + & (remainder * fleaf * currentCohort%c_area/currentPatch%total_canopy_area * & - (layer_top_hite+layer_bottom_hite)/2.0_r8) !average height of layer. + (layer_top_height+layer_bottom_height)/2.0_r8) !average height of layer. end do @@ -1850,7 +1850,7 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) endif if (associated(currentPatch%tallest)) then - bc_out(s)%htop_pa(ifp) = currentPatch%tallest%hite + bc_out(s)%htop_pa(ifp) = currentPatch%tallest%height else ! FIX(RF,040113) - should this be a parameter for the minimum possible vegetation height? bc_out(s)%htop_pa(ifp) = 0.1_r8 @@ -1870,9 +1870,9 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) if (currentCohort%canopy_layer .eq. 1) then weight = min(1.0_r8,currentCohort%c_area/currentPatch%total_canopy_area) bc_out(s)%z0m_pa(ifp) = bc_out(s)%z0m_pa(ifp) + & - EDPftvarcon_inst%z0mr(currentCohort%pft) * currentCohort%hite * weight + EDPftvarcon_inst%z0mr(currentCohort%pft) * currentCohort%height * weight bc_out(s)%displa_pa(ifp) = bc_out(s)%displa_pa(ifp) + & - EDPftvarcon_inst%displar(currentCohort%pft) * currentCohort%hite * weight + EDPftvarcon_inst%displar(currentCohort%pft) * currentCohort%height * weight endif currentCohort => currentCohort%taller end do diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index c4bfabdcf7..12385a8f9d 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -157,7 +157,7 @@ Module EDCohortDynamicsMod contains !-------------------------------------------------------------------------------------! -subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & +subroutine create_cohort(currentSite, patchptr, pft, nn, height, coage, dbh, & prt, elongf_leaf, elongf_fnrt, elongf_stem, status, recruitstatus, ctrim, & carea, clayer, crowndamage, spread, bc_in) @@ -182,7 +182,7 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & integer, intent(in) :: status ! growth status of plant [1=leaves off; 2=leaves on] integer, intent(in) :: recruitstatus ! recruit status of plant [1 = recruitment , 0 = other] real(r8), intent(in) :: nn ! number of individuals in cohort [/m2] -real(r8), intent(in) :: hite ! cohort height [m] +real(r8), intent(in) :: height ! cohort height [m] real(r8), intent(in) :: coage ! cohort age [m] real(r8), intent(in) :: dbh ! cohort diameter at breast height [cm] real(r8), intent(in) :: elongf_leaf ! leaf elongation factor [fraction] - 0: fully abscissed; 1: fully flushed @@ -206,7 +206,7 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & ! create new cohort allocate(newCohort) -call newCohort%Create(prt, pft, nn, hite, coage, dbh, status, ctrim, carea, & +call newCohort%Create(prt, pft, nn, height, coage, dbh, status, ctrim, carea, & clayer, crowndamage, spread, patchptr%canopy_layer_tlai, elongf_leaf, elongf_fnrt, & elongf_stem) @@ -247,7 +247,7 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & ! This calculates node heights call UpdatePlantHydrNodes(newCohort, newCohort%pft, & - newCohort%hite,currentSite%si_hydr) + newCohort%height,currentSite%si_hydr) ! This calculates volumes and lengths call UpdatePlantHydrLenVol(newCohort,currentSite%si_hydr) @@ -834,7 +834,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) write(fates_log(),*) 'Cohort I, Cohort II' write(fates_log(),*) 'n:',currentCohort%n,nextc%n write(fates_log(),*) 'isnew:',currentCohort%isnew,nextc%isnew - write(fates_log(),*) 'hite:',currentCohort%hite,nextc%hite + write(fates_log(),*) 'height:',currentCohort%height,nextc%height write(fates_log(),*) 'coage:',currentCohort%coage,nextc%coage write(fates_log(),*) 'dbh:',currentCohort%dbh,nextc%dbh write(fates_log(),*) 'pft:',currentCohort%pft,nextc%pft @@ -937,7 +937,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) call ForceDBH( currentCohort%pft, currentCohort%crowndamage, & currentCohort%canopy_trim, & currentCohort%efleaf_coh, currentCohort%efstem_coh, & - currentCohort%dbh, currentCohort%hite, & + currentCohort%dbh, currentCohort%height, & bdead = currentCohort%prt%GetState(struct_organ,carbon12_element)) end if @@ -950,7 +950,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) endif ! - call h_allom(currentCohort%dbh,currentCohort%pft,currentCohort%hite) + call h_allom(currentCohort%dbh,currentCohort%pft,currentCohort%height) ! case(conserve_dbh_and_number_not_crownarea) ! @@ -962,7 +962,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) currentCohort%dbh = (currentCohort%n*currentCohort%dbh & + nextc%n*nextc%dbh)/newn ! - call h_allom(currentCohort%dbh,currentCohort%pft,currentCohort%hite) + call h_allom(currentCohort%dbh,currentCohort%pft,currentCohort%height) ! ! ----------------------------------------------------------------- ! If fusion pushed structural biomass to be larger than @@ -976,7 +976,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) call ForceDBH( currentCohort%pft, currentCohort%crowndamage, & currentCohort%canopy_trim, & currentCohort%efleaf_coh, currentCohort%efstem_coh, & - currentCohort%dbh, currentCohort%hite, & + currentCohort%dbh, currentCohort%height, & bdead = currentCohort%prt%GetState(struct_organ,carbon12_element)) end if @@ -1163,7 +1163,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) endif ! At this point, nothing should be pointing to current Cohort - ! update hydraulics quantities that are functions of hite & biomasses + ! update hydraulics quantities that are functions of height & biomasses ! deallocate the hydro structure of nextc if (hlm_use_planthydro.eq.itrue) then call UpdateSizeDepPlantHydProps(currentSite,currentCohort, bc_in) @@ -1358,7 +1358,7 @@ subroutine insert_cohort(currentPatch, pcc, ptall, pshort, tnull, snull, storebi icohort => pcc ! assign address to icohort local name !place in the correct place in the linked list of heights !begin by finding cohort that is just taller than the new cohort - tsp = icohort%hite + tsp = icohort%height current => pshortest exitloop = 0 @@ -1366,7 +1366,7 @@ subroutine insert_cohort(currentPatch, pcc, ptall, pshort, tnull, snull, storebi !taller than tree being considered and return its pointer if (associated(current)) then do while (associated(current).and.exitloop == 0) - if (current%hite < tsp) then + if (current%height < tsp) then current => current%taller else exitloop = 1 @@ -1471,7 +1471,7 @@ end subroutine count_cohorts ! =================================================================================== - subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) + subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_height) ! ----------------------------------------------------------------------------------- ! If the current diameter of a plant is somehow less than what is allometrically @@ -1482,7 +1482,7 @@ subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) ! argument type(fates_cohort_type),intent(inout) :: currentCohort real(r8),intent(out) :: delta_dbh - real(r8),intent(out) :: delta_hite + real(r8),intent(out) :: delta_height ! locals real(r8) :: dbh @@ -1496,7 +1496,7 @@ subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) real(r8) :: target_struct_c real(r8) :: target_leaf_c real(r8) :: struct_c - real(r8) :: hite_out + real(r8) :: height_out real(r8) :: leaf_c real(r8) :: crown_reduction real(r8) :: elongf_leaf @@ -1510,7 +1510,7 @@ subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) elongf_stem = currentCohort%efstem_coh delta_dbh = 0._r8 - delta_hite = 0._r8 + delta_height = 0._r8 if( prt_params%woody(currentCohort%pft) == itrue) then @@ -1539,12 +1539,12 @@ subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) if( (struct_c - target_struct_c ) > calloc_abs_error ) then call ForceDBH( ipft,icrowndamage,canopy_trim, elongf_leaf, elongf_stem, & - dbh, hite_out, bdead=struct_c) + dbh, height_out, bdead=struct_c) delta_dbh = dbh - currentCohort%dbh - delta_hite = hite_out - currentCohort%hite + delta_height = height_out - currentCohort%height currentCohort%dbh = dbh - currentCohort%hite = hite_out + currentCohort%height = height_out end if else @@ -1557,11 +1557,11 @@ subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) if( ( leaf_c - target_leaf_c ) > calloc_abs_error ) then call ForceDBH( ipft, icrowndamage, canopy_trim, elongf_leaf, elongf_stem, & - dbh, hite_out, bl=leaf_c ) + dbh, height_out, bl=leaf_c ) delta_dbh = dbh - currentCohort%dbh - delta_hite = hite_out - currentCohort%hite + delta_height = height_out - currentCohort%height currentCohort%dbh = dbh - currentCohort%hite = hite_out + currentCohort%height = height_out end if end if diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index eb1872b02c..2d2531b9a6 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -829,13 +829,13 @@ subroutine trim_canopy( currentSite ) if (currentCohort%canopy_trim > EDPftvarcon_inst%trim_limit(ipft)) then ! keep trimming until none of the canopy is in negative carbon balance. - if (currentCohort%hite > EDPftvarcon_inst%hgt_min(ipft)) then + if (currentCohort%height > EDPftvarcon_inst%hgt_min(ipft)) then currentCohort%canopy_trim = currentCohort%canopy_trim - & EDPftvarcon_inst%trim_inc(ipft) trimmed = .true. - endif ! hite check + endif ! height check endif ! trim limit check endif ! net uptake check endif ! leaf activity check @@ -2008,7 +2008,7 @@ subroutine assign_cohort_SP_properties(currentCohort, htop, tlai, tsai, parea, i leaf_c, dbh, cohort_n, c_area) ! set allometric characteristics - currentCohort%hite = htop + currentCohort%height = htop currentCohort%dbh = dbh currentCohort%n = cohort_n currentCohort%c_area = c_area @@ -2444,7 +2444,7 @@ subroutine recruitment(currentSite, currentPatch, bc_in) integer :: element_id ! element index consistent with definitions in PRTGenericMod integer :: iage ! age loop counter for leaf age bins integer :: crowndamage ! crown damage class of the cohort [1 = undamaged, >1 = damaged] - real(r8) :: hite ! new cohort height [m] + real(r8) :: height ! new cohort height [m] real(r8) :: dbh ! new cohort DBH [cm] real(r8) :: cohort_n ! new cohort density real(r8) :: l2fr ! leaf to fineroot biomass ratio [0-1] @@ -2490,14 +2490,14 @@ subroutine recruitment(currentSite, currentPatch, bc_in) ((hlm_use_nocomp .eq. ifalse) .or. & (ft .eq. currentPatch%nocomp_pft_label))) then - hite = EDPftvarcon_inst%hgt_min(ft) + height = EDPftvarcon_inst%hgt_min(ft) stem_drop_fraction = prt_params%phen_stem_drop_fraction(ft) fnrt_drop_fraction = prt_params%phen_fnrt_drop_fraction(ft) l2fr = currentSite%rec_l2fr(ft, currentPatch%NCL_p) crowndamage = 1 ! new recruits are undamaged ! calculate DBH from initial height - call h2d_allom(hite, ft, dbh) + call h2d_allom(height, ft, dbh) ! default assumption is that leaves are on efleaf_coh = 1.0_r8 @@ -2721,7 +2721,7 @@ subroutine recruitment(currentSite, currentPatch, bc_in) call prt%CheckInitialConditions() call create_cohort(currentSite, currentPatch, ft, cohort_n, & - hite, 0.0_r8, dbh, prt, efleaf_coh, effnrt_coh, efstem_coh, & + height, 0.0_r8, dbh, prt, efleaf_coh, effnrt_coh, efstem_coh, & leaf_status, recruitstatus, init_recruit_trim, 0.0_r8, & currentPatch%NCL_p, crowndamage, currentSite%spread, bc_in) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index 1871f3fe0f..431219cfda 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -2096,7 +2096,7 @@ subroutine CrownDepth(height,ft,crown_depth) ! Alternative Hypothesis: ! crown depth from Poorter, Bongers & Bongers - ! crown_depth = exp(-1.169_r8)*cCohort%hite**1.098_r8 + ! crown_depth = exp(-1.169_r8)*cCohort%height**1.098_r8 ! Alternative Hypothesis: ! Original FATES crown depth heigh used for hydraulics diff --git a/biogeochem/FatesCohortMod.F90 b/biogeochem/FatesCohortMod.F90 index 71685a869e..7c1b586a71 100644 --- a/biogeochem/FatesCohortMod.F90 +++ b/biogeochem/FatesCohortMod.F90 @@ -83,7 +83,7 @@ module FatesCohortMod real(r8) :: n ! number of individuals in cohort per 'area' (10000m2 default) [/m2] real(r8) :: dbh ! diameter at breast height [cm] real(r8) :: coage ! age [years] - real(r8) :: hite ! height [m] + real(r8) :: height ! height [m] integer :: indexnumber ! unique number for each cohort (within clump?) integer :: canopy_layer ! canopy status of cohort [1 = canopy, 2 = understorey, etc.] real(r8) :: canopy_layer_yesterday ! recent canopy status of cohort [1 = canopy, 2 = understorey, etc.] @@ -345,7 +345,7 @@ subroutine NanValues(this) this%n = nan this%dbh = nan this%coage = nan - this%hite = nan + this%height = nan this%indexnumber = fates_unset_int this%canopy_layer = fates_unset_int this%canopy_layer_yesterday = nan @@ -532,7 +532,7 @@ end subroutine ZeroValues !=========================================================================== - subroutine Create(this, prt, pft, nn, hite, coage, dbh, status, & + subroutine Create(this, prt, pft, nn, height, coage, dbh, status, & ctrim, carea, clayer, crowndamage, spread, can_tlai, elongf_leaf, & elongf_fnrt, elongf_stem) ! @@ -547,7 +547,7 @@ subroutine Create(this, prt, pft, nn, hite, coage, dbh, status, & integer, intent(in) :: clayer ! canopy status of cohort [canopy/understory] integer, intent(in) :: status ! growth status of cohort [leaves on/off] real(r8), intent(in) :: nn ! number of individuals in cohort [/m2] - real(r8), intent(in) :: hite ! cohort height [m] + real(r8), intent(in) :: height ! cohort height [m] real(r8), intent(in) :: coage ! cohort age [yr] real(r8), intent(in) :: dbh ! cohort diameter at breat height [cm] real(r8), intent(in) :: ctrim ! fraction of the maximum leaf biomass @@ -572,7 +572,7 @@ subroutine Create(this, prt, pft, nn, hite, coage, dbh, status, & this%canopy_layer_yesterday = real(clayer, r8) this%status_coh = status this%n = nn - this%hite = hite + this%height = height this%dbh = dbh this%coage = coage this%canopy_trim = ctrim @@ -672,7 +672,7 @@ subroutine Copy(this, copyCohort) copyCohort%n = this%n copyCohort%dbh = this%dbh copyCohort%coage = this%coage - copyCohort%hite = this%hite + copyCohort%height = this%height copyCohort%canopy_layer = this%canopy_layer copyCohort%canopy_layer_yesterday = this%canopy_layer_yesterday copyCohort%crowndamage = this%crowndamage @@ -1010,7 +1010,7 @@ subroutine Dump(this) write(fates_log(),*) 'cohort%pft = ', this%pft write(fates_log(),*) 'cohort%n = ', this%n write(fates_log(),*) 'cohort%dbh = ', this%dbh - write(fates_log(),*) 'cohort%hite = ', this%hite + write(fates_log(),*) 'cohort%height = ', this%height write(fates_log(),*) 'cohort%crowndamage = ', this%crowndamage write(fates_log(),*) 'cohort%coage = ', this%coage write(fates_log(),*) 'cohort%l2fr = ', this%l2fr @@ -1087,4 +1087,4 @@ end subroutine Dump !=========================================================================== -end module FatesCohortMod \ No newline at end of file +end module FatesCohortMod diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index d3c4df6a38..e38e042252 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -365,7 +365,7 @@ subroutine RestartHydrStates(sites,nsites,bc_in,bc_out) ccohort_hydr => ccohort%co_hydr ! This calculates node heights - call UpdatePlantHydrNodes(ccohort,ccohort%pft,ccohort%hite, & + call UpdatePlantHydrNodes(ccohort,ccohort%pft,ccohort%height, & sites(s)%si_hydr) ! This calculates volumes and lengths @@ -862,7 +862,7 @@ subroutine UpdateSizeDepPlantHydProps(currentSite,ccohort,bc_in) call SavePreviousCompartmentVolumes(ccohort_hydr) ! This updates all of the z_node positions - call UpdatePlantHydrNodes(ccohort,ft,ccohort%hite,currentSite%si_hydr) + call UpdatePlantHydrNodes(ccohort,ft,ccohort%height,currentSite%si_hydr) ! This updates plant compartment volumes, lengths and ! maximum conductances. Make sure for already @@ -1004,11 +1004,11 @@ subroutine UpdatePlantHydrLenVol(ccohort,csite_hydr) a_sapwood = a_sapwood_target ! * sapw_c / sapw_c_target ! alternative cross section calculation - ! a_sapwood = a_leaf_tot / ( 0.001_r8 + 0.025_r8 * ccohort%hite ) * 1.e-4_r8 + ! a_sapwood = a_leaf_tot / ( 0.001_r8 + 0.025_r8 * ccohort%height ) * 1.e-4_r8 - !call CrownDepth(ccohort%hite,ft,crown_depth) - crown_depth = min(ccohort%hite,0.1_r8) - z_stem = ccohort%hite - crown_depth + !call CrownDepth(ccohort%height,ft,crown_depth) + crown_depth = min(ccohort%height,0.1_r8) + z_stem = ccohort%height - crown_depth v_sapwood = a_sapwood * z_stem ! + 0.333_r8*a_sapwood*crown_depth ! Junyan changed the following code to calculate the above ground node volume @@ -1228,7 +1228,7 @@ subroutine FuseCohortHydraulics(currentSite,currentCohort, nextCohort, bc_in, ne call SavePreviousCompartmentVolumes(ccohort_hydr) ! This updates all of the z_node positions - call UpdatePlantHydrNodes(currentCohort,ft,currentCohort%hite,csite_hydr) + call UpdatePlantHydrNodes(currentCohort,ft,currentCohort%height,csite_hydr) ! This updates plant compartment volumes, lengths and ! maximum conductances. Make sure for already diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index 797ca859b8..ef245b04f9 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -976,22 +976,22 @@ subroutine crown_damage ( currentSite ) currentCohort%fraction_crown_burned = 0.0_r8 if ( prt_params%woody(currentCohort%pft) == itrue) then !trees only ! Flames lower than bottom of canopy. - ! c%hite is height of cohort + ! c%height is height of cohort - call CrownDepth(currentCohort%hite,currentCohort%pft,crown_depth) + call CrownDepth(currentCohort%height,currentCohort%pft,crown_depth) if (currentPatch%Scorch_ht(currentCohort%pft) < & - (currentCohort%hite-crown_depth)) then + (currentCohort%height-crown_depth)) then currentCohort%fraction_crown_burned = 0.0_r8 else ! Flames part of way up canopy. ! Equation 17 in Thonicke et al. 2010. ! flames over bottom of canopy but not over top. - if ((currentCohort%hite > 0.0_r8).and.(currentPatch%Scorch_ht(currentCohort%pft) >= & - (currentCohort%hite-crown_depth))) then + if ((currentCohort%height > 0.0_r8).and.(currentPatch%Scorch_ht(currentCohort%pft) >= & + (currentCohort%height-crown_depth))) then currentCohort%fraction_crown_burned = (currentPatch%Scorch_ht(currentCohort%pft) - & - (currentCohort%hite - crown_depth))/crown_depth + (currentCohort%height - crown_depth))/crown_depth else ! Flames over top of canopy. diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 6f7b649a4b..ec37cabe5c 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -822,7 +822,7 @@ subroutine init_cohorts(site_in, patch_in, bc_in) real(r8) :: canopy_trim ! fraction of the maximum leaf biomass that we are targeting [0-1] real(r8) :: cohort_n ! cohort density real(r8) :: dbh ! cohort dbh [cm] - real(r8) :: hite ! cohort height [m] + real(r8) :: height ! cohort height [m] real(r8) :: c_area ! cohort crown area [m2] real(r8) :: c_agw ! above ground (non-leaf) biomass [kgC] real(r8) :: c_bgw ! below ground (non-fineroot) biomss [kgC] @@ -944,21 +944,21 @@ subroutine init_cohorts(site_in, patch_in, bc_in) ! n.b. that this is the same as currentcohort%n = %initd(pft) &AREA cohort_n = cohort_n*sum(site_in%use_this_pft) endif - hite = EDPftvarcon_inst%hgt_min(pft) + height = EDPftvarcon_inst%hgt_min(pft) ! h, dbh, leafc, n from SP values or from small initial size if (hlm_use_sp .eq. itrue) then ! At this point, we do not know the bc_in values of tlai tsai and htop, ! so this is initializing to an arbitrary value for the very first timestep. ! Not sure if there's a way around this or not. - hite = 0.5_r8 - call calculate_SP_properties(hite, 0.2_r8, 0.1_r8, & + height = 0.5_r8 + call calculate_SP_properties(height, 0.2_r8, 0.1_r8, & patch_in%area, pft, crown_damage, 1, & EDPftvarcon_inst%vcmax25top(pft, 1), c_leaf, dbh, & cohort_n, c_area) else ! calculate the plant diameter from height - call h2d_allom(hite, pft, dbh) + call h2d_allom(height, pft, dbh) ! Calculate the leaf biomass from allometry ! (calculates a maximum first, then applies canopy trim) @@ -1067,7 +1067,7 @@ subroutine init_cohorts(site_in, patch_in, bc_in) call prt%CheckInitialConditions() call create_cohort(site_in, patch_in, pft, cohort_n, & - hite, 0.0_r8, dbh, prt, efleaf_coh, & + height, 0.0_r8, dbh, prt, efleaf_coh, & effnrt_coh, efstem_coh, leaf_status, recruitstatus, & canopy_trim, c_area, 1, crown_damage, site_in%spread, bc_in) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 7bbe46cb99..42219fbabb 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -359,10 +359,10 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) integer :: el ! Counter for element type (c,n,p,etc) real(r8) :: cohort_biomass_store ! remembers the biomass in the cohort for balance checking real(r8) :: dbh_old ! dbh of plant before daily PRT [cm] - real(r8) :: hite_old ! height of plant before daily PRT [m] + real(r8) :: height_old ! height of plant before daily PRT [m] logical :: is_drought ! logical for if the plant (site) is in a drought state real(r8) :: delta_dbh ! correction for dbh - real(r8) :: delta_hite ! correction for hite + real(r8) :: delta_height ! correction for height real(r8) :: mean_temp logical :: newly_recovered ! If the current loop is dealing with a newly created cohort, which @@ -555,10 +555,10 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! If the current diameter of a plant is somehow less than what is consistent ! with what is allometrically consistent with the stuctural biomass, then ! correct the dbh to match. - call EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) + call EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_height) ! We want to save these values for the newly recovered cohort as well - hite_old = currentCohort%hite + height_old = currentCohort%height dbh_old = currentCohort%dbh ! ----------------------------------------------------------------------------- @@ -642,9 +642,9 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentCohort%isnew = .false. ! Update the plant height (if it has grown) - call h_allom(currentCohort%dbh,ft,currentCohort%hite) + call h_allom(currentCohort%dbh,ft,currentCohort%height) - currentCohort%dhdt = (currentCohort%hite-hite_old)/hlm_freq_day + currentCohort%dhdt = (currentCohort%height-height_old)/hlm_freq_day currentCohort%ddbhdt = (currentCohort%dbh-dbh_old)/hlm_freq_day ! Carbon assimilate has been spent at this point diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index c9b9a90161..020d26eafd 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -99,7 +99,7 @@ module EDTypesMod integer, parameter, public :: phen_dstat_moistoff = 1 ! Leaves off due to moisture avail (drought phenology) integer, parameter, public :: phen_dstat_moiston = 2 ! Leaves on due to moisture avail (drought phenology) integer, parameter, public :: phen_dstat_timeon = 3 ! Leaves on due to time exceedance (drought phenology) - integer, parameter, public :: phen_dstat_pshed = 4 ! Leaves partially abscissing (drought phenology) + integer, parameter, public :: phen_dstat_pshed = 4 ! Leaves partially abscissing (drought phenology) ! PATCH FUSION real(r8), parameter, public :: force_patchfuse_min_biomass = 0.005_r8 ! min biomass (kg / m2 patch area) below which to force-fuse patches @@ -107,8 +107,8 @@ module EDTypesMod real(r8), parameter, public :: max_age_of_second_oldest_patch = 200._r8 ! age in years above which to combine all patches ! COHORT FUSION - real(r8), parameter, public :: HITEMAX = 30.0_r8 ! max dbh value used in hgt profile comparison - integer , parameter, public :: N_HITE_BINS = 60 ! no. of hite bins used to distribute LAI + real(r8), parameter, public :: HEIGHTMAX = 30.0_r8 ! max dbh value used in hgt profile comparison + integer , parameter, public :: N_HEIGHT_BINS = 60 ! no. of height bins used to distribute LAI ! COHORT TERMINATION diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 0c6ff7c4e6..e76a3f5406 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2805,9 +2805,9 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) + ccohort%c_area * AREA_INV ! calculate leaf height distribution, assuming leaf area is evenly distributed thru crown depth - call CrownDepth(ccohort%hite,ft,crown_depth) - height_bin_max = get_height_index(ccohort%hite) - height_bin_min = get_height_index(ccohort%hite - crown_depth) + call CrownDepth(ccohort%height,ft,crown_depth) + height_bin_max = get_height_index(ccohort%height) + height_bin_min = get_height_index(ccohort%height - crown_depth) do i_heightbin = height_bin_min, height_bin_max binbottom = ED_val_history_height_bin_edges(i_heightbin) if (i_heightbin .eq. nlevheight) then @@ -2816,8 +2816,8 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) bintop = ED_val_history_height_bin_edges(i_heightbin+1) endif ! what fraction of a cohort's crown is in this height bin? - frac_canopy_in_bin = (min(bintop,ccohort%hite) - & - max(binbottom,ccohort%hite-crown_depth)) / & + frac_canopy_in_bin = (min(bintop,ccohort%height) - & + max(binbottom,ccohort%height-crown_depth)) / & (crown_depth) hio_leaf_height_dist_si_height(io_si,i_heightbin) = & @@ -3154,7 +3154,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) ccohort%ddbhdt*ccohort%n / m2_per_ha * m_per_cm hio_ba_weighted_height_si(io_si) = hio_ba_weighted_height_si(io_si) + & - ccohort%hite * & + ccohort%height * & 0.25_r8*pi_const*((dbh/100.0_r8)**2.0_r8)*ccohort%n / m2_per_ha end if @@ -3482,7 +3482,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) ccohort%canopy_layer_yesterday * ccohort%n / m2_per_ha hio_ca_weighted_height_si(io_si) = hio_ca_weighted_height_si(io_si) + & - ccohort%hite * ccohort%c_area / m2_per_ha + ccohort%height * ccohort%c_area / m2_per_ha else canlayer hio_nplant_understory_si_scag(io_si,iscag) = hio_nplant_understory_si_scag(io_si,iscag) + ccohort%n / m2_per_ha hio_mortality_understory_si_scag(io_si,iscag) = hio_mortality_understory_si_scag(io_si,iscag) + & diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index 0141c68fe5..ec099860f1 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -859,7 +859,7 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & ! patch (string) patch id string associated with this cohort ! index (integer) cohort index ! dbh (cm) diameter at breast height - ! height (m) height of the tree + ! height (m) height of the tree ! pft (integer) the plant functional type index (must be consistent with param file) ! n (/m2) The plant number density ! bdead (kgC/plant)The dead biomass per indiv of this cohort (NOT USED) @@ -1033,7 +1033,7 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & temp_cohort%dbh = c_dbh temp_cohort%crowndamage = 1 ! assume undamaged - call h_allom(c_dbh,temp_cohort%pft,temp_cohort%hite) + call h_allom(c_dbh,temp_cohort%pft,temp_cohort%height) temp_cohort%canopy_trim = 1.0_r8 ! Determine the phenology status and the elongation factors. @@ -1190,7 +1190,7 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & call prt_obj%CheckInitialConditions() - call create_cohort(csite, cpatch, temp_cohort%pft, temp_cohort%n, temp_cohort%hite, & + call create_cohort(csite, cpatch, temp_cohort%pft, temp_cohort%n, temp_cohort%height, & temp_cohort%coage, temp_cohort%dbh, & prt_obj, temp_cohort%efleaf_coh, temp_cohort%effnrt_coh, & temp_cohort%efstem_coh, temp_cohort%status_coh, rstatus, & @@ -1268,7 +1268,7 @@ subroutine write_inventory_type1(currentSite) open(unit=css_file_out,file=trim(css_name_out), status='UNKNOWN',action='WRITE',form='FORMATTED') write(pss_file_out,*) 'time patch trk age area water fsc stsc stsl ssc psc msn fsn' - write(css_file_out,*) 'time patch cohort dbh hite pft nplant bdead alive Avgrg' + write(css_file_out,*) 'time patch cohort dbh height pft nplant bdead alive Avgrg' ipatch=0 currentpatch => currentSite%youngest_patch diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 55016e9acb..2961e0900a 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -2298,7 +2298,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_size_class_lasttimestep(io_idx_co) = ccohort%size_class_lasttimestep rio_dbh_co(io_idx_co) = ccohort%dbh rio_coage_co(io_idx_co) = ccohort%coage - rio_height_co(io_idx_co) = ccohort%hite + rio_height_co(io_idx_co) = ccohort%height rio_g_sb_laweight_co(io_idx_co)= ccohort%g_sb_laweight rio_nplant_co(io_idx_co) = ccohort%n rio_gpp_acc_co(io_idx_co) = ccohort%gpp_acc @@ -3210,7 +3210,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ccohort%dbh = rio_dbh_co(io_idx_co) ccohort%coage = rio_coage_co(io_idx_co) ccohort%g_sb_laweight= rio_g_sb_laweight_co(io_idx_co) - ccohort%hite = rio_height_co(io_idx_co) + ccohort%height = rio_height_co(io_idx_co) ccohort%n = rio_nplant_co(io_idx_co) ccohort%gpp_acc = rio_gpp_acc_co(io_idx_co) ccohort%npp_acc = rio_npp_acc_co(io_idx_co) diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index c16d3541e6..8a732b24c7 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -378,7 +378,7 @@ subroutine DailyPRTAllometricCarbon(this,phase) integer :: nsteps ! number of sub-steps integer :: istep ! current substep index real(r8) :: totalC ! total carbon allocated over alometric growth step - real(r8) :: hite_out ! dummy height variable + real(r8) :: height_out ! dummy height variable integer :: i_var ! index for iterating state variables integer :: i_age ! index for iterating leaf ages From 90e1400f9c6cb2dbd3b46e0f0ccfb2049e4f65d3 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 25 Sep 2023 15:35:38 -0700 Subject: [PATCH 841/852] change the dispersal cadence to be a hlm defined switch --- main/FatesDispersalMod.F90 | 8 ++++---- main/FatesInterfaceMod.F90 | 26 +++++++++++++++++++------- main/FatesInterfaceTypesMod.F90 | 7 ++++--- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index 68a1e13536..8e460cbe47 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -250,17 +250,17 @@ end function IsItDispersalTime integer function GetCadenceDate() - use FatesInterfaceTypesMod, only : hlm_current_day, & + use FatesInterfaceTypesMod, only : hlm_current_day, & hlm_current_month, & hlm_current_year, & hlm_current_date, & - fates_dispersal_cadence, & + hlm_seeddisp_cadence, & fates_dispersal_cadence_daily, & fates_dispersal_cadence_monthly, & fates_dispersal_cadence_yearly ! Select the date type to check against based on the dispersal candence - select case(fates_dispersal_cadence) + select case(hlm_seeddisp_cadence) case (fates_dispersal_cadence_daily) GetCadenceDate = hlm_current_day case (fates_dispersal_cadence_monthly) @@ -268,7 +268,7 @@ integer function GetCadenceDate() case (fates_dispersal_cadence_yearly) GetCadenceDate = hlm_current_year case default - write(fates_log(),*) 'ERROR: An undefined dispersal cadence was specified: ', fates_dispersal_cadence + write(fates_log(),*) 'ERROR: An undefined dispersal cadence was specified: ', hlm_seeddisp_cadence call endrun(msg=errMsg(sourcefile, __LINE__)) end select diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index e215bfd354..b07f04a47d 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -959,13 +959,13 @@ subroutine SetFatesGlobalElements2(use_fates) ! Set the fates dispersal cadence if seed dispersal parameters are set. ! This could be a parameter value setting as well. Currently hardcoded - if(any(EDPftvarcon_inst%seed_dispersal_pdf_scale .lt. fates_check_param_set)) then - fates_dispersal_cadence = fates_dispersal_cadence_daily - !fates_dispersal_cadence = fates_dispersal_cadence_monthly - ! fates_dispersal_cadence = fates_dispersal_cadence_yearly - else - fates_dispersal_cadence = 0 - end if + ! if(any(EDPftvarcon_inst%seed_dispersal_pdf_scale .lt. fates_check_param_set)) then + ! fates_dispersal_cadence = fates_dispersal_cadence_daily + ! !fates_dispersal_cadence = fates_dispersal_cadence_monthly + ! ! fates_dispersal_cadence = fates_dispersal_cadence_yearly + ! else + ! fates_dispersal_cadence = 0 + ! end if ! Initialize Hydro globals ! (like water retention functions) @@ -1431,6 +1431,7 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) hlm_use_vertsoilc = unset_int hlm_parteh_mode = unset_int hlm_spitfire_mode = unset_int + hlm_seeddisp_cadence = unset_int hlm_sf_nofire_def = unset_int hlm_sf_scalar_lightning_def = unset_int hlm_sf_successful_ignitions_def = unset_int @@ -1633,6 +1634,11 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) call endrun(msg=errMsg(sourcefile, __LINE__)) end if + if(hlm_seeddisp_cadence .eq. unset_int) then + write(fates_log(), *) 'switch defining seed dispersal cadence is unset, hlm_seeddisp_cadence, exiting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + if(hlm_use_ch4 .eq. unset_int) then write(fates_log(), *) 'switch for the HLMs CH4 module unset: hlm_use_ch4, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) @@ -1793,6 +1799,12 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) write(fates_log(),*) 'Transfering hlm_parteh_mode= ',ival,' to FATES' end if + case('seeddisp_cadence') + hlm_seeddisp_cadence = ival + if (fates_global_verbose()) then + write(fates_log(),*) 'Transfering hlm_seeddisp_cadence= ',ival,' to FATES' + end if + case('spitfire_mode') hlm_spitfire_mode = ival if (fates_global_verbose()) then diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 3d405421c5..2a7509354d 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -94,6 +94,9 @@ module FatesInterfaceTypesMod integer, public :: hlm_parteh_mode ! This flag signals which Plant Allocation and Reactive ! Transport (exensible) Hypothesis (PARTEH) to use + integer, public :: hlm_seeddisp_cadence ! This flag signals at what cadence to disperse seeds across gridcells + ! 0 => no seed dispersal + ! 1, 2, 3 => daily, monthly, yearly dispersal integer, public :: hlm_use_ch4 ! This flag signals whether the methane model in ELM/CLM is ! active, and therefore whether or not boundary conditions @@ -234,9 +237,7 @@ module FatesInterfaceTypesMod integer, parameter, public :: fates_dispersal_kernel_exppower = 2 ! exponential power (ExP) dispersal kernel integer, parameter, public :: fates_dispersal_kernel_logsech = 3 ! logistic-sech (LogS) dispersal kernel - integer, public :: fates_dispersal_cadence ! Setting to denote how often seed dispersal should occur - - integer, parameter, public :: fates_dispersal_cadence_daily = 1 ! Disperse seeds daily + integer, parameter, public :: fates_dispersal_cadence_daily = 1 ! Disperse seeds daily integer, parameter, public :: fates_dispersal_cadence_monthly = 2 ! Disperse seeds monthly integer, parameter, public :: fates_dispersal_cadence_yearly = 3 ! Disperse seeds yearly From 540caa1a5982f2f5d685059bfc27a0a6b0958acf Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 25 Sep 2023 16:08:37 -0700 Subject: [PATCH 842/852] update kernel mode check to cadence check --- biogeochem/EDPhysiologyMod.F90 | 6 +++--- main/FatesDispersalMod.F90 | 14 +++++++------- main/FatesInterfaceMod.F90 | 7 +++---- main/FatesInterfaceTypesMod.F90 | 7 +++---- 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 67a5daa214..2d20c0aa6b 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2039,8 +2039,8 @@ subroutine SeedUpdate( currentSite ) ! !USES: use EDTypesMod, only : area use EDTypesMod, only : homogenize_seed_pfts - use FatesInterfaceTypesMod, only : fates_dispersal_kernel_mode - use FatesInterfaceTypesMod, only : fates_dispersal_kernel_none + use FatesInterfaceTypesMod, only : hlm_seeddisp_cadence + use FatesInterfaceTypesMod, only : fates_dispersal_cadence_none ! ! !ARGUMENTS type(ed_site_type), intent(inout), target :: currentSite @@ -2064,7 +2064,7 @@ subroutine SeedUpdate( currentSite ) ! If the dispersal kernel is not turned on, keep the dispersal fraction at zero site_disp_frac(:) = 0._r8 - if (fates_dispersal_kernel_mode .ne. fates_dispersal_kernel_none) then + if (hlm_seeddisp_cadence .ne. fates_dispersal_cadence_none) then site_disp_frac(:) = EDPftvarcon_inst%seed_dispersal_fraction(:) end if diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index 8e460cbe47..23202edfe0 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -64,8 +64,8 @@ subroutine init(this, numprocs, numpft) ! Use use EDPftvarcon , only : EDPftvarcon_inst use FatesConstantsMod , only : fates_check_param_set - use FatesInterfaceTypesMod, only : fates_dispersal_kernel_mode - use FatesInterfaceTypesMod, only : fates_dispersal_kernel_none + use FatesInterfaceTypesMod, only : hlm_seeddisp_cadence + use FatesInterfaceTypesMod, only : fates_dispersal_cadence_none ! Arguments class(dispersal_type), intent(inout) :: this @@ -75,7 +75,7 @@ subroutine init(this, numprocs, numpft) ! Check if seed dispersal mode is 'turned on' by checking the parameter values ! This assumes we consistency in the parameter file across all pfts, i.e. either ! all 'on' or all 'off' - if (fates_dispersal_kernel_mode .eq. fates_dispersal_kernel_none) return + if (hlm_seeddisp_cadence .eq. fates_dispersal_cadence_none) return allocate(this%outgoing_local(numprocs,numpft)) allocate(this%outgoing_global(numprocs,numpft)) @@ -109,7 +109,7 @@ subroutine ProbabilityDensity(pd, ipft, dist) real(r8), intent(in) :: dist ! distance ! Select the function to use based on the kernel mode - ! Note that fates_dispersal_kernel_none mode is checked prior to this call being made + ! Note that hlm_seeddisp_cadence is checked prior to this call being made select case(fates_dispersal_kernel_mode) case (fates_dispersal_kernel_exponential) @@ -204,8 +204,8 @@ logical function IsItDispersalTime(setdispersedflag) ! happen after WrapSeedGlobal, but can be threaded this takes place at the top of the ! dynamics_driv call. - use FatesInterfaceTypesMod, only : fates_dispersal_kernel_mode - use FatesInterfaceTypesMod, only : fates_dispersal_kernel_none + use FatesInterfaceTypesMod, only : hlm_seeddisp_cadence + use FatesInterfaceTypesMod, only : fates_dispersal_cadence_none ! Arguments logical, optional :: setdispersedflag ! Has the global dispersal been completed? @@ -218,7 +218,7 @@ logical function IsItDispersalTime(setdispersedflag) ! Check if seed dispersal mode is 'turned on' by checking the parameter values ! If it is off, return false by default - if (fates_dispersal_kernel_mode .eq. fates_dispersal_kernel_none) return + if (hlm_seeddisp_cadence .eq. fates_dispersal_cadence_none) return ! Check if set dispersal flag is provided. This should be provided during a check ! when the flag should be set to true after the global dispersal diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index b07f04a47d..3bfa8dc01f 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -948,13 +948,12 @@ subroutine SetFatesGlobalElements2(use_fates) ! Set the fates dispersal kernel mode if there are any seed dispersal parameters set. ! The validation of the parameter values is check in FatesCheckParams prior to this check. - ! This is currently hard coded. + ! This is currently hard coded, but could be added as a fates parameter file option, + ! particularly one that is pft dependent. if(any(EDPftvarcon_inst%seed_dispersal_pdf_scale .lt. fates_check_param_set)) then fates_dispersal_kernel_mode = fates_dispersal_kernel_exponential ! fates_dispersal_kernel_mode = fates_dispersal_kernel_exppower ! fates_dispersal_kernel_mode = fates_dispersal_kernel_logsech - else - fates_dispersal_kernel_mode = fates_dispersal_kernel_none end if ! Set the fates dispersal cadence if seed dispersal parameters are set. @@ -2213,7 +2212,7 @@ subroutine DetermineGridCellNeighbors(neighbors,numg) real(r8) :: pdf ! Check if seed dispersal mode is 'turned on' by checking the parameter values - if (fates_dispersal_kernel_mode .eq. fates_dispersal_kernel_none) return + if (hlm_seeddisp_cadence .eq. fates_dispersal_cadence_none) return if(hlm_is_restart .eq. itrue) write(fates_log(),*) 'gridcell initialization during restart' diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 2a7509354d..29a4ec2ba0 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -229,14 +229,13 @@ module FatesInterfaceTypesMod ! competitors that will be generated on each site - integer, public :: fates_dispersal_kernel_mode ! Flag to signal the use of grid cell seed dispersal - ! Setting this to greater than zero overrides seed rain - - integer, parameter, public :: fates_dispersal_kernel_none = 0 ! no dispersal (use seed rain only) + integer, public :: fates_dispersal_kernel_mode ! Flag to signal the type of kernel used for grid cell seed dispersal + integer, parameter, public :: fates_dispersal_kernel_exponential = 1 ! exponential dispersal kernel integer, parameter, public :: fates_dispersal_kernel_exppower = 2 ! exponential power (ExP) dispersal kernel integer, parameter, public :: fates_dispersal_kernel_logsech = 3 ! logistic-sech (LogS) dispersal kernel + integer, parameter, public :: fates_dispersal_cadence_none = 0 ! no dispersal (use seed rain only) integer, parameter, public :: fates_dispersal_cadence_daily = 1 ! Disperse seeds daily integer, parameter, public :: fates_dispersal_cadence_monthly = 2 ! Disperse seeds monthly integer, parameter, public :: fates_dispersal_cadence_yearly = 3 ! Disperse seeds yearly From 34fe68912e4aab197bcd038f5830e4e5f486d17d Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 11 Sep 2023 11:47:24 -0600 Subject: [PATCH 843/852] reverse dispersal type dimensions for memory continuity for mpi collective --- main/FatesDispersalMod.F90 | 12 +++++----- main/FatesInterfaceMod.F90 | 46 +++++++++++++++++++++++++++++++------- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index 18fad12558..2ea6746eaf 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -38,8 +38,8 @@ module FatesDispersalMod real(r8), allocatable :: outgoing_local(:,:) ! local buffer array of outgoing seeds, local gridcell x pft real(r8), allocatable :: outgoing_global(:,:) ! global accumulation buffer array of outgoing seeds, global gridcell x pft real(r8), allocatable :: incoming_global(:,:) ! local buffer array used to calculate incoming seeds based on nearest neighbors - real(r8), allocatable :: ncells_array(:) ! local array with the number of gridcells per process for each rank index - real(r8), allocatable :: begg_array(:) ! local array with the starting index of each gridcell for each rank index + integer, allocatable :: ncells_array(:) ! local array with the number of gridcells per process for each rank index + integer, allocatable :: begg_array(:) ! local array with the starting index of each gridcell for each rank index contains @@ -82,9 +82,9 @@ subroutine init(this, numprocs, numgc_global, numgc_local, numpft) ! all 'on' or all 'off' if (fates_dispersal_kernel_mode .eq. fates_dispersal_kernel_none) return - allocate(this%outgoing_local(numgc_local,numpft)) - allocate(this%outgoing_global(numgc_global,numpft)) - allocate(this%incoming_global(numgc_global,numpft)) + allocate(this%outgoing_local(numpft,numgc_local)) + allocate(this%outgoing_global(numpft,numgc_global)) + allocate(this%incoming_global(numpft,numgc_global)) allocate(this%ncells_array(0:numprocs-1)) allocate(this%begg_array(0:numprocs-1)) @@ -240,6 +240,7 @@ logical function IsItDispersalTime(setdispersedflag) ! If dispersal flag is false, check if it is time to disperse ! If it's time to disperse, check to see if the dispersal flag should be set true and last ! dispersal date updated + write(fates_log(),*) 'IIDTpre, dflag, sflag, cdate, ddate', IsItDispersalTime, dispersal_flag, setflag, GetCadenceDate(), dispersal_date if (dispersal_flag) then IsItDispersalTime = .true. dispersal_flag = .false. @@ -252,6 +253,7 @@ logical function IsItDispersalTime(setdispersedflag) end if end if end if + write(fates_log(),*) 'IIDTpst, dflag, sflag, cdate, ddate', IsItDispersalTime, dispersal_flag, setflag, GetCadenceDate(), dispersal_date end function IsItDispersalTime diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 7afcd87add..e3bcf0a5c6 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -173,7 +173,7 @@ module FatesInterfaceMod public :: InitTimeAveragingGlobals public :: DetermineGridCellNeighbors - logical :: debug = .false. ! for debugging this module + logical :: debug = .true. ! for debugging this module contains @@ -2212,29 +2212,59 @@ subroutine DetermineGridCellNeighbors(neighbors,seeds,numg) neighbors(:)%neighbor_count = 0 allocate(gclat(numg), stat=ier) - allocate(gclon(numg)) + write(fates_log(),*)'DGCN: gclat alloc: ', ier + allocate(gclon(numg), stat=ier) + write(fates_log(),*)'DGCN: gclon alloc: ', ier gclon(:) = nan gclat(:) = nan + allocate(ncells_array(0:npes-1), stat=ier) + write(fates_log(),*)'DGCN: ncells alloc: ', ier + allocate(begg_array(0:npes-1), stat=ier) + write(fates_log(),*)'DGCN: begg alloc: ', ier + ncells_array(:) = fates_unset_int + begg_array(:) = fates_unset_int + call t_startf('fates-seed-init-allgather') ! Gather the sizes of the ldomain that each mpi rank is passing - call MPI_Allgather(procinfo%ncells,1,MPI_INTEGER,seeds%ncells_array,1,MPI_INTEGER,mpicom,mpierr) + call MPI_Allgather(procinfo%ncells,1,MPI_INTEGER,ncells_array,1,MPI_INTEGER,mpicom,mpierr) + write(fates_log(),*)'DGCN: ncells mpierr: ', mpierr ! Gather the starting index for each ldomain (reduce begging index by one for mpi rank conversion) - call MPI_Allgather(procinfo%begg-1,1,MPI_INTEGER,seeds%begg_array,1,MPI_INTEGER,mpicom,mpierr) + call MPI_Allgather(procinfo%begg-1,1,MPI_INTEGER,begg_array,1,MPI_INTEGER,mpicom,mpierr) + write(fates_log(),*)'DGCN: begg mpierr: ', mpierr + + if (debug .and. iam .eq. 1) then + write(fates_log(),*)'DGCN: ncells_array: ', ncells_array + write(fates_log(),*)'DGCN: begg_array: ', begg_array + end if ! Gather the domain information together into the neighbor type ! Note that MPI_Allgatherv is only gathering a subset of ldomain - call MPI_Allgatherv(ldomain%latc,procinfo%ncells,MPI_REAL8,gclat,seeds%ncells_array,seeds%begg_array,MPI_REAL8,mpicom,mpierr) - call MPI_Allgatherv(ldomain%lonc,procinfo%ncells,MPI_REAL8,gclon,seeds%ncells_array,seeds%begg_array,MPI_REAL8,mpicom,mpierr) + write(fates_log(),*)'DGCN: gathering latc' + call MPI_Allgatherv(ldomain%latc,procinfo%ncells,MPI_REAL8,gclat,ncells_array,begg_array,MPI_REAL8,mpicom,mpierr) + write(fates_log(),*)'DGCN: gathering lonc' + call MPI_Allgatherv(ldomain%lonc,procinfo%ncells,MPI_REAL8,gclon,ncells_array,begg_array,MPI_REAL8,mpicom,mpierr) if (debug .and. iam .eq. 1) then - write(fates_log(),*)'DGCN: ncells_array: ', seeds%ncells_array - write(fates_log(),*)'DGCN: begg_array: ', seeds%begg_array + write(fates_log(),*)'DGCN: ncells_array: ', ncells_array + write(fates_log(),*)'DGCN: begg_array: ', begg_array write(fates_log(),*)'DGCN: sum(gclat):, sum(gclon): ', sum(gclat), sum(gclon) end if + ! Save number of cells and begging index arrays to dispersal type + write(fates_log(),*)'DGCN: save to seeds type' + write(fates_log(),*)'DGCN: seeds ncells alloc: ', allocated(seeds%ncells_array) + write(fates_log(),*)'DGCN: seeds begg alloc: ', allocated(seeds%begg_array) + seeds%ncells_array = ncells_array + seeds%begg_array = begg_array + + if (debug .and. iam .eq. 1) then + write(fates_log(),*)'DGCN: seeds%ncells_array: ', seeds%ncells_array + write(fates_log(),*)'DGCN: seeds%begg_array: ', seeds%begg_array + end if + call t_stopf('fates-seed-init-allgather') call t_startf('fates-seed-init-decomp') From 41731921fef9c359481493b411e02a9b90398560 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 26 Sep 2023 10:54:34 -0600 Subject: [PATCH 844/852] add neighbor array list to neighborhood data structure --- main/FatesDispersalMod.F90 | 9 +++-- main/FatesInterfaceMod.F90 | 75 +++++++++++++++++++++++++++++--------- 2 files changed, 63 insertions(+), 21 deletions(-) diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index 2ea6746eaf..f528df9eb0 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -28,7 +28,8 @@ module FatesDispersalMod type(neighbor_type), pointer :: first_neighbor => null() type(neighbor_type), pointer :: last_neighbor => null() - integer :: neighbor_count ! total neighbors near source + integer :: neighbor_count ! total neighbors near source + integer, allocatable :: neighbor_indices(:) ! list of gridcell indices end type neighborhood_type @@ -85,8 +86,10 @@ subroutine init(this, numprocs, numgc_global, numgc_local, numpft) allocate(this%outgoing_local(numpft,numgc_local)) allocate(this%outgoing_global(numpft,numgc_global)) allocate(this%incoming_global(numpft,numgc_global)) - allocate(this%ncells_array(0:numprocs-1)) - allocate(this%begg_array(0:numprocs-1)) + !allocate(this%ncells_array(0:numprocs-1)) + !allocate(this%begg_array(0:numprocs-1)) + allocate(this%begg_array(numprocs)) + allocate(this%ncells_array(numprocs)) this%outgoing_local(:,:) = 0._r8 this%outgoing_global(:,:) = 0._r8 diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index e3bcf0a5c6..f8722a7fd2 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -173,7 +173,7 @@ module FatesInterfaceMod public :: InitTimeAveragingGlobals public :: DetermineGridCellNeighbors - logical :: debug = .true. ! for debugging this module + logical :: debug = .false. ! for debugging this module contains @@ -2175,7 +2175,7 @@ subroutine DetermineGridCellNeighbors(neighbors,seeds,numg) ! neighbor for later use. This should be called after decompInit_lnd and surf_get_grid ! as it relies on ldecomp and ldomain information. - use decompMod , only : procinfo + use decompMod , only : procinfo, gindex_global, gindex_grc use domainMod , only : ldomain use spmdMod , only : MPI_REAL8, MPI_INTEGER, mpicom, npes, masterproc, iam use perf_mod , only : t_startf, t_stopf @@ -2193,7 +2193,7 @@ subroutine DetermineGridCellNeighbors(neighbors,seeds,numg) type (neighbor_type), pointer :: current_neighbor type (neighbor_type), pointer :: another_neighbor - integer :: i, gi,gj ! indices + integer :: i, gi, gj, ni ! indices integer :: ier, mpierr ! error status integer :: ipft ! pft index real(r8), allocatable :: gclat(:), gclon(:) @@ -2212,16 +2212,18 @@ subroutine DetermineGridCellNeighbors(neighbors,seeds,numg) neighbors(:)%neighbor_count = 0 allocate(gclat(numg), stat=ier) - write(fates_log(),*)'DGCN: gclat alloc: ', ier + !write(fates_log(),*)'DGCN: gclat alloc: ', ier allocate(gclon(numg), stat=ier) - write(fates_log(),*)'DGCN: gclon alloc: ', ier + !write(fates_log(),*)'DGCN: gclon alloc: ', ier gclon(:) = nan gclat(:) = nan - allocate(ncells_array(0:npes-1), stat=ier) - write(fates_log(),*)'DGCN: ncells alloc: ', ier - allocate(begg_array(0:npes-1), stat=ier) - write(fates_log(),*)'DGCN: begg alloc: ', ier + !allocate(ncells_array(0:npes-1), stat=ier) + allocate(ncells_array(npes), stat=ier) + !write(fates_log(),*)'DGCN: ncells alloc: ', ier + !allocate(begg_array(0:npes-1), stat=ier) + allocate(begg_array(npes), stat=ier) + !write(fates_log(),*)'DGCN: begg alloc: ', ier ncells_array(:) = fates_unset_int begg_array(:) = fates_unset_int @@ -2229,22 +2231,28 @@ subroutine DetermineGridCellNeighbors(neighbors,seeds,numg) ! Gather the sizes of the ldomain that each mpi rank is passing call MPI_Allgather(procinfo%ncells,1,MPI_INTEGER,ncells_array,1,MPI_INTEGER,mpicom,mpierr) - write(fates_log(),*)'DGCN: ncells mpierr: ', mpierr + !write(fates_log(),*)'DGCN: ncells mpierr: ', mpierr - ! Gather the starting index for each ldomain (reduce begging index by one for mpi rank conversion) - call MPI_Allgather(procinfo%begg-1,1,MPI_INTEGER,begg_array,1,MPI_INTEGER,mpicom,mpierr) - write(fates_log(),*)'DGCN: begg mpierr: ', mpierr + ! Gather the starting gridcell index for each ldomain + call MPI_Allgather(procinfo%begg,1,MPI_INTEGER,begg_array,1,MPI_INTEGER,mpicom,mpierr) + !write(fates_log(),*)'DGCN: begg mpierr: ', mpierr + + ! reduce the begg_array displacements by one as MPI collectives expect zero indexed arrays + begg_array = begg_array - 1 if (debug .and. iam .eq. 1) then write(fates_log(),*)'DGCN: ncells_array: ', ncells_array write(fates_log(),*)'DGCN: begg_array: ', begg_array + !write(fates_log(),*)'DGCN: size gindex: ', size(gindex_global), size(gindex_grc) + !write(fates_log(),*)'DGCN: gindex_global: ', gindex_global + !write(fates_log(),*)'DGCN: gindex_grc: ', gindex_grc end if ! Gather the domain information together into the neighbor type ! Note that MPI_Allgatherv is only gathering a subset of ldomain - write(fates_log(),*)'DGCN: gathering latc' + !write(fates_log(),*)'DGCN: gathering latc' call MPI_Allgatherv(ldomain%latc,procinfo%ncells,MPI_REAL8,gclat,ncells_array,begg_array,MPI_REAL8,mpicom,mpierr) - write(fates_log(),*)'DGCN: gathering lonc' + !write(fates_log(),*)'DGCN: gathering lonc' call MPI_Allgatherv(ldomain%lonc,procinfo%ncells,MPI_REAL8,gclon,ncells_array,begg_array,MPI_REAL8,mpicom,mpierr) if (debug .and. iam .eq. 1) then @@ -2254,9 +2262,9 @@ subroutine DetermineGridCellNeighbors(neighbors,seeds,numg) end if ! Save number of cells and begging index arrays to dispersal type - write(fates_log(),*)'DGCN: save to seeds type' - write(fates_log(),*)'DGCN: seeds ncells alloc: ', allocated(seeds%ncells_array) - write(fates_log(),*)'DGCN: seeds begg alloc: ', allocated(seeds%begg_array) + !write(fates_log(),*)'DGCN: save to seeds type' + !write(fates_log(),*)'DGCN: seeds ncells alloc: ', allocated(seeds%ncells_array) + !write(fates_log(),*)'DGCN: seeds begg alloc: ', allocated(seeds%begg_array) seeds%ncells_array = ncells_array seeds%begg_array = begg_array @@ -2269,6 +2277,8 @@ subroutine DetermineGridCellNeighbors(neighbors,seeds,numg) call t_startf('fates-seed-init-decomp') + write(fates_log(), *) 'DGCN: maxdist: ', EDPftvarcon_inst%seed_dispersal_max_dist + ! Iterate through the grid cell indices and determine if any neighboring cells are in range gc_loop: do gi = 1,numg-1 @@ -2278,6 +2288,9 @@ subroutine DetermineGridCellNeighbors(neighbors,seeds,numg) ! Determine distance to old grid cells to the current one g2g_dist = GetNeighborDistance(gi,gj,gclat,gclon) + write(fates_log(), *) 'DGCN: gi,gj,g2g_dist: ', gi,gj,g2g_dist + + ! dist_check: if (any(EDPftvarcon_inst%seed_dispersal_max_dist .gt. g2g_dist)) then ! Add neighbor index to current grid cell index list @@ -2331,6 +2344,32 @@ subroutine DetermineGridCellNeighbors(neighbors,seeds,numg) end do neighbor_search end do gc_loop + ! Loop through the list and populate the grid cell index array for each gridcell + do gi = 1,numg + + ! Start at the first neighbor of each neighborhood list + current_neighbor => neighbors(gi)%first_neighbor + + ! Allocate an array to hold the gridcell indices in each neighborhood + allocate(neighbors(gi)%neighbor_indices(neighbors(gi)%neighbor_count)) + + ! Walk through the neighborhood linked list and populate the array + ni = 1 + do while (associated(current_neighbor)) + neighbors(gi)%neighbor_indices(ni) = current_neighbor%gindex + ni = ni + 1 + current_neighbor => current_neighbor%next_neighbor + end do + + write(fates_log(), *) 'DGCN: g, lat, lon: ', gi, gclat(gi), gclon(gi) + write(fates_log(), *) 'DGCN: g, ncount: ', gi, neighbors(gi)%neighbor_count + do i = 1,neighbors(gi)%neighbor_count + write(fates_log(), *) 'DGCN: g, gilist: ', gi, neighbors(gi)%neighbor_indices(i) + end do + + end do + + call t_stopf('fates-seed-init-decomp') end subroutine DetermineGridCellNeighbors From c24643ba12a777d0a06d50fa6bbe34d489d1cfb0 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 26 Sep 2023 15:30:32 -0600 Subject: [PATCH 845/852] fix bad merge --- main/FatesInterfaceMod.F90 | 91 +++++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 40 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index f8722a7fd2..29557b192a 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -173,7 +173,7 @@ module FatesInterfaceMod public :: InitTimeAveragingGlobals public :: DetermineGridCellNeighbors - logical :: debug = .false. ! for debugging this module + logical :: debug = .true. ! for debugging this module contains @@ -2193,10 +2193,12 @@ subroutine DetermineGridCellNeighbors(neighbors,seeds,numg) type (neighbor_type), pointer :: current_neighbor type (neighbor_type), pointer :: another_neighbor - integer :: i, gi, gj, ni ! indices - integer :: ier, mpierr ! error status - integer :: ipft ! pft index - real(r8), allocatable :: gclat(:), gclon(:) + integer :: i, gi, gj, ni ! indices + integer :: ier, mpierr ! error status + integer :: ipft ! pft index + + integer, allocatable :: ncells_array(:), begg_array(:) ! number of cells and starting global grid cell index per process + real(r8), allocatable :: gclat(:), gclon(:) ! local array holding gridcell lat and lon ! 5 deg = 785.8 km, 10 deg = 1569 km, 15deg = 2345 km assumes cartesian layout with diagonal distance real(r8) :: g2g_dist ! grid cell distance (m) @@ -2207,68 +2209,75 @@ subroutine DetermineGridCellNeighbors(neighbors,seeds,numg) if(debug .and. hlm_is_restart .eq. itrue) write(fates_log(),*) 'gridcell initialization during restart' - ! Allocate array neighbor type + if(debug) write(fates_log(),*)'DGCN: npes, numg: ', npes, numg + + ! Allocate and initialize array neighbor type allocate(neighbors(numg), stat=ier) neighbors(:)%neighbor_count = 0 + ! Allocate and initialize local lat and lon arrays allocate(gclat(numg), stat=ier) - !write(fates_log(),*)'DGCN: gclat alloc: ', ier + if(debug) write(fates_log(),*)'DGCN: gclat alloc: ', ier + allocate(gclon(numg), stat=ier) - !write(fates_log(),*)'DGCN: gclon alloc: ', ier + if(debug) write(fates_log(),*)'DGCN: gclon alloc: ', ier + gclon(:) = nan gclat(:) = nan - !allocate(ncells_array(0:npes-1), stat=ier) - allocate(ncells_array(npes), stat=ier) - !write(fates_log(),*)'DGCN: ncells alloc: ', ier - !allocate(begg_array(0:npes-1), stat=ier) - allocate(begg_array(npes), stat=ier) - !write(fates_log(),*)'DGCN: begg alloc: ', ier + ! Allocate and initialize MPI count and displacement values + allocate(ncells_array(0:npes-1), stat=ier) + !allocate(ncells_array(npes), stat=ier) + if(debug) write(fates_log(),*)'DGCN: ncells alloc: ', ier + + allocate(begg_array(0:npes-1), stat=ier) + !allocate(begg_array(npes), stat=ier) + if(debug) write(fates_log(),*)'DGCN: begg alloc: ', ier + ncells_array(:) = fates_unset_int begg_array(:) = fates_unset_int call t_startf('fates-seed-init-allgather') + if(debug) write(fates_log(),*)'DGCN: procinfo%begg: ', procinfo%begg + if(debug) write(fates_log(),*)'DGCN: procinfo%ncells: ', procinfo%ncells + ! Gather the sizes of the ldomain that each mpi rank is passing call MPI_Allgather(procinfo%ncells,1,MPI_INTEGER,ncells_array,1,MPI_INTEGER,mpicom,mpierr) - !write(fates_log(),*)'DGCN: ncells mpierr: ', mpierr + if(debug) write(fates_log(),*)'DGCN: ncells mpierr: ', mpierr ! Gather the starting gridcell index for each ldomain call MPI_Allgather(procinfo%begg,1,MPI_INTEGER,begg_array,1,MPI_INTEGER,mpicom,mpierr) - !write(fates_log(),*)'DGCN: begg mpierr: ', mpierr + if(debug) write(fates_log(),*)'DGCN: begg mpierr: ', mpierr ! reduce the begg_array displacements by one as MPI collectives expect zero indexed arrays begg_array = begg_array - 1 - if (debug .and. iam .eq. 1) then - write(fates_log(),*)'DGCN: ncells_array: ', ncells_array - write(fates_log(),*)'DGCN: begg_array: ', begg_array - !write(fates_log(),*)'DGCN: size gindex: ', size(gindex_global), size(gindex_grc) - !write(fates_log(),*)'DGCN: gindex_global: ', gindex_global - !write(fates_log(),*)'DGCN: gindex_grc: ', gindex_grc - end if + if(debug) write(fates_log(),*)'DGCN: ncells_array: ' , ncells_array + if(debug) write(fates_log(),*)'DGCN: begg_array: ' , begg_array + if(debug) write(fates_log(),*)'DGCN: gindex_global: ', gindex_global + if(debug) write(fates_log(),*)'DGCN: gindex_grc: ' , gindex_grc ! Gather the domain information together into the neighbor type ! Note that MPI_Allgatherv is only gathering a subset of ldomain - !write(fates_log(),*)'DGCN: gathering latc' + if(debug) write(fates_log(),*)'DGCN: gathering latc' call MPI_Allgatherv(ldomain%latc,procinfo%ncells,MPI_REAL8,gclat,ncells_array,begg_array,MPI_REAL8,mpicom,mpierr) - !write(fates_log(),*)'DGCN: gathering lonc' + + if(debug) write(fates_log(),*)'DGCN: gathering lonc' call MPI_Allgatherv(ldomain%lonc,procinfo%ncells,MPI_REAL8,gclon,ncells_array,begg_array,MPI_REAL8,mpicom,mpierr) - if (debug .and. iam .eq. 1) then - write(fates_log(),*)'DGCN: ncells_array: ', ncells_array - write(fates_log(),*)'DGCN: begg_array: ', begg_array + !if (debug .and. iam .eq. 1) then write(fates_log(),*)'DGCN: sum(gclat):, sum(gclon): ', sum(gclat), sum(gclon) - end if + !end if ! Save number of cells and begging index arrays to dispersal type - !write(fates_log(),*)'DGCN: save to seeds type' - !write(fates_log(),*)'DGCN: seeds ncells alloc: ', allocated(seeds%ncells_array) - !write(fates_log(),*)'DGCN: seeds begg alloc: ', allocated(seeds%begg_array) + if(debug) write(fates_log(),*)'DGCN: save to seeds type' + if(debug) write(fates_log(),*)'DGCN: seeds ncells alloc: ', allocated(seeds%ncells_array) + if(debug) write(fates_log(),*)'DGCN: seeds begg alloc: ', allocated(seeds%begg_array) seeds%ncells_array = ncells_array seeds%begg_array = begg_array - if (debug .and. iam .eq. 1) then + if (debug .and. iam .eq. 0) then write(fates_log(),*)'DGCN: seeds%ncells_array: ', seeds%ncells_array write(fates_log(),*)'DGCN: seeds%begg_array: ', seeds%begg_array end if @@ -2277,7 +2286,7 @@ subroutine DetermineGridCellNeighbors(neighbors,seeds,numg) call t_startf('fates-seed-init-decomp') - write(fates_log(), *) 'DGCN: maxdist: ', EDPftvarcon_inst%seed_dispersal_max_dist + if(debug) write(fates_log(), *) 'DGCN: maxdist: ', EDPftvarcon_inst%seed_dispersal_max_dist ! Iterate through the grid cell indices and determine if any neighboring cells are in range gc_loop: do gi = 1,numg-1 @@ -2288,7 +2297,7 @@ subroutine DetermineGridCellNeighbors(neighbors,seeds,numg) ! Determine distance to old grid cells to the current one g2g_dist = GetNeighborDistance(gi,gj,gclat,gclon) - write(fates_log(), *) 'DGCN: gi,gj,g2g_dist: ', gi,gj,g2g_dist + if(debug) write(fates_log(), *) 'DGCN: gi,gj,g2g_dist: ', gi,gj,g2g_dist ! dist_check: if (any(EDPftvarcon_inst%seed_dispersal_max_dist .gt. g2g_dist)) then @@ -2361,11 +2370,13 @@ subroutine DetermineGridCellNeighbors(neighbors,seeds,numg) current_neighbor => current_neighbor%next_neighbor end do - write(fates_log(), *) 'DGCN: g, lat, lon: ', gi, gclat(gi), gclon(gi) - write(fates_log(), *) 'DGCN: g, ncount: ', gi, neighbors(gi)%neighbor_count - do i = 1,neighbors(gi)%neighbor_count - write(fates_log(), *) 'DGCN: g, gilist: ', gi, neighbors(gi)%neighbor_indices(i) - end do + if (debug .and. iam .eq. 0) then + write(fates_log(), *) 'DGCN: g, lat, lon: ', gi, gclat(gi), gclon(gi) + write(fates_log(), *) 'DGCN: g, ncount: ', gi, neighbors(gi)%neighbor_count + do i = 1,neighbors(gi)%neighbor_count + write(fates_log(), *) 'DGCN: g, gilist: ', gi, neighbors(gi)%neighbor_indices(i) + end do + end if end do From 3a00e8414341d267d09b31874699911f01a6ee81 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 26 Sep 2023 18:04:03 -0600 Subject: [PATCH 846/852] add missing unset --- main/FatesDispersalMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index ac24a0a838..d9070e0cdb 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -66,7 +66,7 @@ subroutine init(this, numprocs, numgc_global, numgc_local, numpft) ! Use use EDPftvarcon , only : EDPftvarcon_inst - use FatesConstantsMod , only : fates_check_param_set + use FatesConstantsMod , only : fates_check_param_set, fates_unset_int use FatesInterfaceTypesMod, only : hlm_seeddisp_cadence use FatesInterfaceTypesMod, only : fates_dispersal_cadence_none From a7e4ee0559d388cf21f149cfcb250acdb4b2ce94 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 27 Sep 2023 11:03:26 -0700 Subject: [PATCH 847/852] remove unnecessary dispersal cadence logic gates --- main/FatesDispersalMod.F90 | 18 +----------------- main/FatesInterfaceMod.F90 | 15 +-------------- 2 files changed, 2 insertions(+), 31 deletions(-) diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index d9070e0cdb..1ba14baa25 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -67,9 +67,7 @@ subroutine init(this, numprocs, numgc_global, numgc_local, numpft) ! Use use EDPftvarcon , only : EDPftvarcon_inst use FatesConstantsMod , only : fates_check_param_set, fates_unset_int - use FatesInterfaceTypesMod, only : hlm_seeddisp_cadence - use FatesInterfaceTypesMod, only : fates_dispersal_cadence_none - + ! Arguments class(dispersal_type), intent(inout) :: this @@ -78,16 +76,9 @@ subroutine init(this, numprocs, numgc_global, numgc_local, numpft) integer, intent(in) :: numgc_local ! number of gridcells on this processor integer, intent(in) :: numpft ! number of FATES pfts - ! Check if seed dispersal mode is 'turned on' by checking the parameter values - ! This assumes we consistency in the parameter file across all pfts, i.e. either - ! all 'on' or all 'off' - if (hlm_seeddisp_cadence .eq. fates_dispersal_cadence_none) return - allocate(this%outgoing_local(numpft,numgc_local)) allocate(this%outgoing_global(numpft,numgc_global)) allocate(this%incoming_global(numpft,numgc_global)) - !allocate(this%ncells_array(0:numprocs-1)) - !allocate(this%begg_array(0:numprocs-1)) allocate(this%begg_array(numprocs)) allocate(this%ncells_array(numprocs)) @@ -216,9 +207,6 @@ logical function IsItDispersalTime(setdispersedflag) ! happen after WrapSeedGlobal, but can be threaded this takes place at the top of the ! dynamics_driv call. - use FatesInterfaceTypesMod, only : hlm_seeddisp_cadence - use FatesInterfaceTypesMod, only : fates_dispersal_cadence_none - ! Arguments logical, optional :: setdispersedflag ! Has the global dispersal been completed? @@ -228,10 +216,6 @@ logical function IsItDispersalTime(setdispersedflag) ! The default return value is false IsItDispersalTime = .false. - ! Check if seed dispersal mode is 'turned on' by checking the parameter values - ! If it is off, return false by default - if (hlm_seeddisp_cadence .eq. fates_dispersal_cadence_none) return - ! Check if set dispersal flag is provided. This should be provided during a check ! when the flag should be set to true after the global dispersal setflag = .false. diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 094f054481..69843c684d 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -958,17 +958,7 @@ subroutine SetFatesGlobalElements2(use_fates) ! fates_dispersal_kernel_mode = fates_dispersal_kernel_logsech end if - ! Set the fates dispersal cadence if seed dispersal parameters are set. - ! This could be a parameter value setting as well. Currently hardcoded - ! if(any(EDPftvarcon_inst%seed_dispersal_pdf_scale .lt. fates_check_param_set)) then - ! fates_dispersal_cadence = fates_dispersal_cadence_daily - ! !fates_dispersal_cadence = fates_dispersal_cadence_monthly - ! ! fates_dispersal_cadence = fates_dispersal_cadence_yearly - ! else - ! fates_dispersal_cadence = 0 - ! end if - - ! Initialize Hydro globals + ! Initialize Hydro globals ! (like water retention functions) ! this needs to know the number of PFTs, which is ! determined in that call @@ -2215,9 +2205,6 @@ subroutine DetermineGridCellNeighbors(neighbors,seeds,numg) real(r8) :: g2g_dist ! grid cell distance (m) real(r8) :: pdf - ! Check if seed dispersal mode is 'turned on' by checking the parameter values - if (hlm_seeddisp_cadence .eq. fates_dispersal_cadence_none) return - if(debug .and. hlm_is_restart .eq. itrue) write(fates_log(),*) 'gridcell initialization during restart' if(debug) write(fates_log(),*)'DGCN: npes, numg: ', npes, numg From a92057d354b86fa83a03594fdc06191b3c55069f Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 27 Sep 2023 12:12:06 -0700 Subject: [PATCH 848/852] seed dispersal comment clean up --- main/FatesInterfaceMod.F90 | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 69843c684d..2f4f9c1fef 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -173,7 +173,7 @@ module FatesInterfaceMod public :: InitTimeAveragingGlobals public :: DetermineGridCellNeighbors - logical :: debug = .true. ! for debugging this module + logical :: debug = .false. ! for debugging this module contains @@ -2201,9 +2201,8 @@ subroutine DetermineGridCellNeighbors(neighbors,seeds,numg) integer, allocatable :: ncells_array(:), begg_array(:) ! number of cells and starting global grid cell index per process real(r8), allocatable :: gclat(:), gclon(:) ! local array holding gridcell lat and lon - ! 5 deg = 785.8 km, 10 deg = 1569 km, 15deg = 2345 km assumes cartesian layout with diagonal distance real(r8) :: g2g_dist ! grid cell distance (m) - real(r8) :: pdf + real(r8) :: pdf ! probability density function output if(debug .and. hlm_is_restart .eq. itrue) write(fates_log(),*) 'gridcell initialization during restart' @@ -2225,11 +2224,9 @@ subroutine DetermineGridCellNeighbors(neighbors,seeds,numg) ! Allocate and initialize MPI count and displacement values allocate(ncells_array(0:npes-1), stat=ier) - !allocate(ncells_array(npes), stat=ier) if(debug) write(fates_log(),*)'DGCN: ncells alloc: ', ier allocate(begg_array(0:npes-1), stat=ier) - !allocate(begg_array(npes), stat=ier) if(debug) write(fates_log(),*)'DGCN: begg alloc: ', ier ncells_array(:) = fates_unset_int @@ -2264,9 +2261,9 @@ subroutine DetermineGridCellNeighbors(neighbors,seeds,numg) if(debug) write(fates_log(),*)'DGCN: gathering lonc' call MPI_Allgatherv(ldomain%lonc,procinfo%ncells,MPI_REAL8,gclon,ncells_array,begg_array,MPI_REAL8,mpicom,mpierr) - !if (debug .and. iam .eq. 1) then + if (debug .and. iam .eq. 0) then write(fates_log(),*)'DGCN: sum(gclat):, sum(gclon): ', sum(gclat), sum(gclon) - !end if + end if ! Save number of cells and begging index arrays to dispersal type if(debug) write(fates_log(),*)'DGCN: save to seeds type' From 8733cafc38a03305282f4c89a07fb19f214cbc0c Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 9 Oct 2023 18:25:40 -0600 Subject: [PATCH 849/852] fix hite from merging in sci.1.67.4_api.27.0.0 --- main/EDInitMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index ecd8ab66bb..ee74f9b02b 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -996,7 +996,7 @@ subroutine init_cohorts(site_in, patch_in, bc_in) c_area) ! calculate height from diameter - call h_allom(dbh, pft, hite) + call h_allom(dbh, pft, height) else write(fates_log(),*) 'Negative fates_recruit_init_density can only be used in no comp mode' From df403b3e3bfc28829649d5524e6f9bb118c741f5 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 20 Oct 2023 13:24:08 -0700 Subject: [PATCH 850/852] remove elm incompatible gindex uses from fatesinterfacemod --- main/FatesInterfaceMod.F90 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index da451ede73..6ea4d21bf8 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -2176,7 +2176,7 @@ subroutine DetermineGridCellNeighbors(neighbors,seeds,numg) ! neighbor for later use. This should be called after decompInit_lnd and surf_get_grid ! as it relies on ldecomp and ldomain information. - use decompMod , only : procinfo, gindex_global, gindex_grc + use decompMod , only : procinfo use domainMod , only : ldomain use spmdMod , only : MPI_REAL8, MPI_INTEGER, mpicom, npes, masterproc, iam use perf_mod , only : t_startf, t_stopf @@ -2250,8 +2250,6 @@ subroutine DetermineGridCellNeighbors(neighbors,seeds,numg) if(debug) write(fates_log(),*)'DGCN: ncells_array: ' , ncells_array if(debug) write(fates_log(),*)'DGCN: begg_array: ' , begg_array - if(debug) write(fates_log(),*)'DGCN: gindex_global: ', gindex_global - if(debug) write(fates_log(),*)'DGCN: gindex_grc: ' , gindex_grc ! Gather the domain information together into the neighbor type ! Note that MPI_Allgatherv is only gathering a subset of ldomain From c4642a7fff8cf568157c6e790d0ce5d3b98828c4 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 20 Oct 2023 14:56:29 -0700 Subject: [PATCH 851/852] remove old diagnostic write statements --- main/FatesDispersalMod.F90 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/main/FatesDispersalMod.F90 b/main/FatesDispersalMod.F90 index 1ba14baa25..f030983a99 100644 --- a/main/FatesDispersalMod.F90 +++ b/main/FatesDispersalMod.F90 @@ -227,7 +227,6 @@ logical function IsItDispersalTime(setdispersedflag) ! If dispersal flag is false, check if it is time to disperse ! If it's time to disperse, check to see if the dispersal flag should be set true and last ! dispersal date updated - write(fates_log(),*) 'IIDTpre, dflag, sflag, cdate, ddate', IsItDispersalTime, dispersal_flag, setflag, GetCadenceDate(), dispersal_date if (dispersal_flag) then IsItDispersalTime = .true. dispersal_flag = .false. @@ -240,8 +239,7 @@ logical function IsItDispersalTime(setdispersedflag) end if end if end if - write(fates_log(),*) 'IIDTpst, dflag, sflag, cdate, ddate', IsItDispersalTime, dispersal_flag, setflag, GetCadenceDate(), dispersal_date - + end function IsItDispersalTime ! ==================================================================================== From 3090ea4dd8732d6e60d4e77eb11e39bc4c66e65e Mon Sep 17 00:00:00 2001 From: adrifoster Date: Thu, 26 Oct 2023 09:45:55 -0600 Subject: [PATCH 852/852] fix merge conflicts --- biogeochem/FatesPatchMod.F90 | 4 +- fire/SFMainMod.F90 | 200 ++++++++++++++++++----------------- main/EDParamsMod.F90 | 2 +- main/EDPftvarcon.F90 | 6 +- 4 files changed, 109 insertions(+), 103 deletions(-) diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 index ac9171dac6..d8ee395f62 100644 --- a/biogeochem/FatesPatchMod.F90 +++ b/biogeochem/FatesPatchMod.F90 @@ -196,7 +196,8 @@ module FatesPatchMod real(r8) :: fuel_eff_moist ! effective avearage fuel moisture content of the ground fuel ! (incl. live grasses. omits 1000hr fuels) real(r8) :: litter_moisture(nfsc) ! moisture of litter [m3/m3] - integer :: active_crown_fire_flg + real(r8) :: canopy_bulk_density + ! fire spread real(r8) :: ros_front ! rate of forward spread of fire [m/min] @@ -205,6 +206,7 @@ module FatesPatchMod real(r8) :: tau_l ! duration of lethal heating [min] real(r8) :: fi ! average fire intensity of flaming front [kJ/m/s] or [kW/m] integer :: fire ! is there a fire? [1=yes; 0=no] + integer :: active_crown_fire_flg real(r8) :: fd ! fire duration [min] ! fire effects diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index 87a978baec..b056fcc6b8 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -186,12 +186,11 @@ subroutine fire_danger_index ( currentSite, bc_in) end subroutine fire_danger_index - !***************************************************************** - subroutine characteristics_of_fuel ( currentSite) - !***************************************************************** + !***************************************************************** + subroutine characteristics_of_fuel ( currentSite) + !***************************************************************** - use SFParamsMod, only: SF_val_drying_ratio, SF_val_SAV, SF_val_FBD, & - SF_val_miner_total + use SFParamsMod, only: SF_val_drying_ratio, SF_val_SAV, SF_val_FBD, SF_val_miner_total type(ed_site_type), intent(in), target :: currentSite @@ -206,63 +205,65 @@ subroutine characteristics_of_fuel ( currentSite) fuel_moisture(:) = 0.0_r8 currentPatch => currentSite%oldest_patch; - do while(associated(currentPatch)) + + do while (associated(currentPatch)) - if(currentPatch%nocomp_pft_label .ne. nocomp_bareground)then + if (currentPatch%nocomp_pft_label .ne. nocomp_bareground) then - litt_c => currentPatch%litter(element_pos(carbon12_element)) - - ! How much live grass is there? - currentPatch%livegrass = 0.0_r8 - currentCohort => currentPatch%tallest - do while(associated(currentCohort)) - ! for grasses sum all aboveground tissues - if( prt_params%woody(currentCohort%pft) == ifalse)then - - currentPatch%livegrass = currentPatch%livegrass + & - ( currentCohort%prt%GetState(leaf_organ, carbon12_element) + & - currentCohort%prt%GetState(sapw_organ, carbon12_element) + & - currentCohort%prt%GetState(struct_organ, carbon12_element) ) * & - currentCohort%n/currentPatch%area + litt_c => currentPatch%litter(element_pos(carbon12_element)) + + ! How much live grass is there? + currentPatch%livegrass = 0.0_r8 + currentCohort => currentPatch%tallest + do while(associated(currentCohort)) + ! for grasses sum all aboveground tissues + if( prt_params%woody(currentCohort%pft) == ifalse)then + + currentPatch%livegrass = currentPatch%livegrass + & + ( currentCohort%prt%GetState(leaf_organ, carbon12_element) + & + currentCohort%prt%GetState(sapw_organ, carbon12_element) + & + currentCohort%prt%GetState(struct_organ, carbon12_element) ) * & + currentCohort%n/currentPatch%area endif currentCohort => currentCohort%shorter - enddo - - ! There are SIX fuel classes - ! 1:4) four CWD_AG pools (twig, s branch, l branch, trunk), 5) dead leaves and 6) live grass - ! NCWD =4 NFSC = 6 - ! tw_sf = 1, lb_sf = 3, tr_sf = 4, dl_sf = 5, lg_sf = 6, - + enddo - if(write_sf == itrue)then + ! There are SIX fuel classes + ! 1:4) four CWD_AG pools (twig, s branch, l branch, trunk), 5) dead leaves and 6) live grass + ! NCWD =4 NFSC = 6 + ! tw_sf = 1, lb_sf = 3, tr_sf = 4, dl_sf = 5, lg_sf = 6, + + + if(write_sf == itrue)then if ( hlm_masterproc == itrue ) write(fates_log(),*) ' leaf_litter1 ',sum(litt_c%leaf_fines(:)) if ( hlm_masterproc == itrue ) write(fates_log(),*) ' leaf_litter2 ',sum(litt_c%ag_cwd(:)) if ( hlm_masterproc == itrue ) write(fates_log(),*) ' leaf_litter3 ',currentPatch%livegrass - endif + endif - currentPatch%sum_fuel = sum(litt_c%leaf_fines(:)) + & - sum(litt_c%ag_cwd(:)) + & - currentPatch%livegrass - if(write_SF == itrue)then + currentPatch%sum_fuel = sum(litt_c%leaf_fines(:)) + & + sum(litt_c%ag_cwd(:)) + & + currentPatch%livegrass + if (write_SF == itrue) then if ( hlm_masterproc == itrue ) write(fates_log(),*) 'sum fuel', currentPatch%sum_fuel,currentPatch%area - endif - ! =============================================== - ! Average moisture, bulk density, surface area-volume and moisture extinction of fuel - ! ================================================ - - if (currentPatch%sum_fuel > 0.0) then + endif + + ! =============================================== + ! Average moisture, bulk density, surface area-volume and moisture extinction of fuel + ! ================================================ + + if (currentPatch%sum_fuel > 0.0) then ! Fraction of fuel in litter classes currentPatch%fuel_frac(dl_sf) = sum(litt_c%leaf_fines(:))/ currentPatch%sum_fuel currentPatch%fuel_frac(tw_sf:tr_sf) = litt_c%ag_cwd(:) / currentPatch%sum_fuel - if(write_sf == itrue)then - if ( hlm_masterproc == itrue ) write(fates_log(),*) 'ff2a ', & - lg_sf,currentPatch%livegrass,currentPatch%sum_fuel + if (write_sf == itrue) then + if ( hlm_masterproc == itrue ) write(fates_log(),*) 'ff2a ', & + lg_sf,currentPatch%livegrass,currentPatch%sum_fuel endif currentPatch%fuel_frac(lg_sf) = currentPatch%livegrass / currentPatch%sum_fuel - + ! MEF (moisure of extinction) depends on compactness of fuel, depth, particle size, wind, slope ! Eq here is Eq 27 from Peterson and Ryan (1986) "Modeling Postfire Conifer Mortality for Long-Range Planning" ! but lots of other approaches in use out there... @@ -278,28 +279,28 @@ subroutine characteristics_of_fuel ( currentSite) ! dead leaves and twigs included in 1hr pool per Thonicke (2010) ! Calculate fuel moisture for trunks to hold value for fuel consumption alpha_FMC(tw_sf:dl_sf) = SF_val_SAV(tw_sf:dl_sf)/SF_val_drying_ratio - + fuel_moisture(tw_sf:dl_sf) = exp(-1.0_r8 * alpha_FMC(tw_sf:dl_sf) * currentSite%acc_NI) - + if(write_SF == itrue)then - if ( hlm_masterproc == itrue ) write(fates_log(),*) 'ff3 ',currentPatch%fuel_frac - if ( hlm_masterproc == itrue ) write(fates_log(),*) 'fm ',fuel_moisture - if ( hlm_masterproc == itrue ) write(fates_log(),*) 'csa ',currentSite%acc_NI - if ( hlm_masterproc == itrue ) write(fates_log(),*) 'sfv ',alpha_FMC + if ( hlm_masterproc == itrue ) write(fates_log(),*) 'ff3 ',currentPatch%fuel_frac + if ( hlm_masterproc == itrue ) write(fates_log(),*) 'fm ',fuel_moisture + if ( hlm_masterproc == itrue ) write(fates_log(),*) 'csa ',currentSite%acc_NI + if ( hlm_masterproc == itrue ) write(fates_log(),*) 'sfv ',alpha_FMC endif - + ! live grass moisture is a function of SAV and changes via Nesterov Index ! along the same relationship as the 1 hour fuels (live grass has same SAV as dead grass, ! but retains more moisture with this calculation.) fuel_moisture(lg_sf) = exp(-1.0_r8 * ((SF_val_SAV(tw_sf)/SF_val_drying_ratio) * currentSite%acc_NI)) - + ! Average properties over the first three litter pools (twigs, s branches, l branches) currentPatch%fuel_bulkd = sum(currentPatch%fuel_frac(tw_sf:lb_sf) * SF_val_FBD(tw_sf:lb_sf)) currentPatch%fuel_sav = sum(currentPatch%fuel_frac(tw_sf:lb_sf) * SF_val_SAV(tw_sf:lb_sf)) currentPatch%fuel_mef = sum(currentPatch%fuel_frac(tw_sf:lb_sf) * MEF(tw_sf:lb_sf)) currentPatch%fuel_eff_moist = sum(currentPatch%fuel_frac(tw_sf:lb_sf) * fuel_moisture(tw_sf:lb_sf)) - if(write_sf == itrue)then - if ( hlm_masterproc == itrue ) write(fates_log(),*) 'ff4 ',currentPatch%fuel_eff_moist + if (write_sf == itrue) then + if ( hlm_masterproc == itrue ) write(fates_log(),*) 'ff4 ',currentPatch%fuel_eff_moist endif ! Add on properties of dead leaves and live grass pools (5 & 6) currentPatch%fuel_bulkd = currentPatch%fuel_bulkd + sum(currentPatch%fuel_frac(dl_sf:lg_sf) * SF_val_FBD(dl_sf:lg_sf)) @@ -313,28 +314,25 @@ subroutine characteristics_of_fuel ( currentSite) currentPatch%fuel_sav = currentPatch%fuel_sav * (1.0_r8/(1.0_r8-currentPatch%fuel_frac(tr_sf))) currentPatch%fuel_mef = currentPatch%fuel_mef * (1.0_r8/(1.0_r8-currentPatch%fuel_frac(tr_sf))) currentPatch%fuel_eff_moist = currentPatch%fuel_eff_moist * (1.0_r8/(1.0_r8-currentPatch%fuel_frac(tr_sf))) - + ! Pass litter moisture into the fuel burning routine (all fuels: twigs,s branch,l branch,trunk,dead leaves,live grass) ! (wo/me term in Thonicke et al. 2010) currentPatch%litter_moisture(tw_sf:lb_sf) = fuel_moisture(tw_sf:lb_sf)/MEF(tw_sf:lb_sf) currentPatch%litter_moisture(tr_sf) = fuel_moisture(tr_sf)/MEF(tr_sf) currentPatch%litter_moisture(dl_sf) = fuel_moisture(dl_sf)/MEF(dl_sf) currentPatch%litter_moisture(lg_sf) = fuel_moisture(lg_sf)/MEF(lg_sf) - - else - - if(write_SF == itrue)then - - if ( hlm_masterproc == itrue ) write(fates_log(),*) 'no litter fuel at all',currentPatch%patchno, & - currentPatch%sum_fuel,sum(litt_c%ag_cwd(:)),sum(litt_c%leaf_fines(:)) + else + if (write_SF == itrue) then + if ( hlm_masterproc == itrue ) write(fates_log(),*) 'no litter fuel at all',currentPatch%patchno, & + currentPatch%sum_fuel,sum(litt_c%ag_cwd(:)),sum(litt_c%leaf_fines(:)) endif currentPatch%fuel_sav = sum(SF_val_SAV(1:nfsc))/(nfsc) ! make average sav to avoid crashing code. - if ( hlm_masterproc == itrue .and. write_SF == itrue)then - write(fates_log(),*) 'problem with spitfire fuel averaging' + if ( hlm_masterproc == itrue .and. write_SF == itrue) then + write(fates_log(),*) 'problem with spitfire fuel averaging' end if - + ! FIX(SPM,032414) refactor...should not have 0 fuel unless everything is burnt ! off. currentPatch%fuel_eff_moist = 0.0000000001_r8 @@ -343,20 +341,22 @@ subroutine characteristics_of_fuel ( currentSite) currentPatch%fuel_mef = 0.0000000001_r8 currentPatch%sum_fuel = 0.0000000001_r8 - endif - ! check values. - ! FIX(SPM,032414) refactor... - if(write_SF == itrue.and.currentPatch%fuel_sav <= 0.0_r8.or.currentPatch%fuel_bulkd <= & - 0.0_r8.or.currentPatch%fuel_mef <= 0.0_r8.or.currentPatch%fuel_eff_moist <= 0.0_r8)then - if ( hlm_masterproc == itrue ) write(fates_log(),*) 'problem with spitfire fuel averaging' - endif - - ! remove mineral content from net fuel load per Thonicke 2010 - ! for ir calculation in subr. rate_of_spread - ! slevis moved here because rate_of_spread is now called twice/timestep - currentPatch%sum_fuel = currentPatch%sum_fuel * (1.0_r8 - SF_val_miner_total) !net of minerals + endif + ! check values. + ! FIX(SPM,032414) refactor... + if (write_SF == itrue.and.currentPatch%fuel_sav <= 0.0_r8.or.currentPatch%fuel_bulkd <= & + 0.0_r8.or.currentPatch%fuel_mef <= 0.0_r8.or.currentPatch%fuel_eff_moist <= 0.0_r8) then + if ( hlm_masterproc == itrue ) write(fates_log(),*) 'problem with spitfire fuel averaging' + endif - currentPatch => currentPatch%younger + ! remove mineral content from net fuel load per Thonicke 2010 + ! for ir calculation in subr. rate_of_spread + ! slevis moved here because rate_of_spread is now called twice/timestep + currentPatch%sum_fuel = currentPatch%sum_fuel * (1.0_r8 - SF_val_miner_total) !net of minerals + + currentPatch => currentPatch%younger + + end if enddo !end patch loop @@ -373,8 +373,8 @@ subroutine characteristics_of_crown ( currentSite, canopy_fuel_load, passive_cr type(ed_site_type), intent(in), target :: currentSite - type(ed_patch_type) , pointer :: currentPatch - type(ed_cohort_type), pointer :: currentCohort + type(fates_patch_type) , pointer :: currentPatch + type(fates_cohort_type), pointer :: currentCohort ! ARGUMENTS real(r8), intent(out) :: canopy_fuel_load ! available canopy fuel load in patch (kg biomass) @@ -436,17 +436,17 @@ subroutine characteristics_of_crown ( currentSite, canopy_fuel_load, passive_cr ! Calculate crown 1hr fuel biomass (leaf, twig sapwood, twig structural biomass) if ( int(prt_params%woody(currentCohort%pft)) == itrue) then !trees - call CrownDepth(currentCohort%hite,currentCohort%pft,crown_depth) - height_cbb = currentCohort%hite - crown_depth + call CrownDepth(currentCohort%height,currentCohort%pft,crown_depth) + height_cbb = currentCohort%height - crown_depth !find patch max height for stand canopy fuel - if (currentCohort%hite > max_height) then - max_height = currentCohort%hite + if (currentCohort%height > max_height) then + max_height = currentCohort%height endif - leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) - sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) - struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) + leaf_c = currentCohort%prt%GetState(leaf_organ, carbon12_element) + sapw_c = currentCohort%prt%GetState(sapw_organ, carbon12_element) + struct_c = currentCohort%prt%GetState(struct_organ, carbon12_element) tree_sapw_struct_c = currentCohort%n * & (prt_params%allom_agb_frac(currentCohort%pft)*(sapw_c + struct_c)) @@ -461,7 +461,7 @@ subroutine characteristics_of_crown ( currentSite, canopy_fuel_load, passive_cr !sort crown fuel into bins from bottom to top of crown !accumulate across cohorts to find density within canopy 1m sections - do ih = int(height_cbb), int(currentCohort%hite) + do ih = int(height_cbb), int(currentCohort%height) biom_matrix(ih) = biom_matrix(ih) + crown_fuel_per_m end do @@ -771,7 +771,7 @@ subroutine rate_of_spread ( currentSite, ROS_torch, passive_crown_FI, heat_per_a ! ROS for crown torch initation (m/min), Eq 18 Scott & Reinhardt 2001 ROS_torch = (1.0 / 54.683 * wind_reduce)* & ((((60.0*passive_crown_FI*currentPatch%fuel_bulkd*eps*q_ig)/heat_per_area*ir*xi)-1.0) & - / (c*beta_ratio)**-e)**1/b + / (c*beta_ratio)**(-1*e))**1/b endif ! Eq 10 in Thonicke et al. 2010 ! backward ROS from Can FBP System (1992) in m/min @@ -1097,8 +1097,8 @@ subroutine active_crown_fire ( currentSite, canopy_fuel_load, ROS_torch, & type(ed_site_type), intent(in), target :: currentSite - type(ed_patch_type) , pointer :: currentPatch - type(ed_cohort_type), pointer :: currentCohort + type(fates_patch_type) , pointer :: currentPatch + type(fates_cohort_type), pointer :: currentCohort ! ARGUMENTS real(r8), intent(in) :: ROS_torch ! ROS for crown torch initation (m/min) @@ -1127,6 +1127,10 @@ subroutine active_crown_fire ( currentSite, canopy_fuel_load, ROS_torch, & real(r8) fuel_moist10hr ! moisture 10 hour fuels real(r8) fuel_moist100hr ! moisture 100 hour fuels real(r8) fuel_moistlive ! moisture live fuels + real(r8) fuel_1hr + real(r8) fuel_10hr + real(r8) fuel_100hr + real(r8) fuel_live real(r8) SAV_1hr ! surface area to volume 1 hour fuels (twigs) real(r8) SAV_10hr ! surface area to volume 10 hour fuels (small branches) real(r8) SAV_100hr ! surface area to volume 100 hour fuels (large branches) @@ -1287,7 +1291,7 @@ subroutine active_crown_fire ( currentSite, canopy_fuel_load, ROS_torch, & ! calculate open wind speed critical to sustain active crown fire Eq 20 Scott & Reinhardt CI_temp = ((164.8_r8 * eps * q_ig)/(ir * currentPatch%canopy_bulk_density)) - 1.0_r8 - wind_active_min = 0.0457_r8 (CI_temp/0.001612_r8)**0.7_r8 + wind_active_min = 0.0457_r8*(CI_temp/0.001612_r8)**0.7_r8 ! use open wind speed "wind_active_min" for ROS surface fire where ROS_SA=ROS_active_min ROS_SA = (ir * xi * (1.0_r8 + wind_active_min)) / (fuel_bd * eps * q_ig) @@ -1430,8 +1434,8 @@ subroutine crown_damage ( currentSite ) type(ed_site_type), intent(in), target :: currentSite - type(ed_patch_type) , pointer :: currentPatch - type(ed_cohort_type), pointer :: currentCohort + type(fates_patch_type) , pointer :: currentPatch + type(fates_cohort_type), pointer :: currentCohort real(r8) :: crown_depth ! depth of crown (m) real(r8) :: height_cbb ! clear branch bole height or crown base height (m) for cohort @@ -1440,7 +1444,7 @@ subroutine crown_damage ( currentSite ) do while(associated(currentPatch)) !zero Patch level variables - + if(currentPatch%nocomp_pft_label .ne. nocomp_bareground)then if (currentPatch%fire == 1) then currentCohort=>currentPatch%tallest @@ -1451,13 +1455,13 @@ subroutine crown_damage ( currentSite ) ! height_cbb = clear branch bole height at base of crown (m) ! inst%crown = crown_depth_frac (PFT) - call CrownDepth(currentCohort%hite,currentCohort%pft,crown_depth) - height_cbb = currentCohort%hite - crown_depth + call CrownDepth(currentCohort%height,currentCohort%pft,crown_depth) + height_cbb = currentCohort%height - crown_depth ! Equation 17 in Thonicke et al. 2010 ! flames over bottom of canopy, and potentially over top of ! canopy - if (currentCohort%hite > 0.0_r8 .and. & + if (currentCohort%height > 0.0_r8 .and. & currentPatch%Scorch_ht(currentCohort%pft) >= height_cbb) then if (currentPatch%active_crown_fire_flg == 0) then currentCohort%fraction_crown_burned = min(1.0_r8, & diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index f2bc2b9285..413b2fadb7 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -812,7 +812,7 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetrieveParameter(name=name_dev_arbitrary, & data=dev_arbitrary) - call fates_params%RetreiveParameter(name=fates_name_cg_strikes, & + call fates_params%RetrieveParameter(name=fates_name_cg_strikes, & data=cg_strikes) call fates_params%RetrieveParameter(name=damage_name_event_code, & diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 950988a44d..f420894248 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -831,11 +831,11 @@ subroutine Receive_PFT(this, fates_params) data=this%crown_kill) name = 'fates_fire_active_crown_fire' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=this%active_crown_fire) name = 'fates_recruit_init_density' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=this%initd) name = 'fates_recruit_seed_supplement' @@ -1927,7 +1927,7 @@ subroutine FatesCheckParams(is_master) ! xl must be between -0.4 and 0.6 according to Bonan (2019) doi:10.1017/9781107339217 pg. 238 !----------------------------------------------------------------------------------- if (EDPftvarcon_inst%xl(ipft) < -0.4 .or. EDPftvarcon_inst%xl(ipft) > 0.6) then - write(fates_log(),*) 'fates_rad_leaf_xl for pft ', ipft, ' is outside the allowed range of -0.6 to 0.4' + write(fates_log(),*) 'fates_rad_leaf_xl for pft ', ipft, ' is outside the allowed range of -0.4 to 0.6' write(fates_log(),*) 'Aborting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if